diff --git a/Makefile b/Makefile index fd15adb..14088f7 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ .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 diff --git a/Makefile.gc b/Makefile.gc index f8da56a..942d2e2 100644 --- a/Makefile.gc +++ b/Makefile.gc @@ -21,7 +21,7 @@ BUILD := build_gc SOURCES := source source/images source/sounds source/fonts source/lang \ source/gui source/utils source/utils/sz \ 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 #--------------------------------------------------------------------------------- @@ -29,7 +29,8 @@ INCLUDES := source source/vba #--------------------------------------------------------------------------------- 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 \ -DSDL -DNO_PNG -DHAVE_ZUTIL_H \ -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ diff --git a/Makefile.wii b/Makefile.wii index 51ee648..68cfa7f 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -1,169 +1,170 @@ -#--------------------------------------------------------------------------------- -# Clear the implicit built in rules -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- -ifeq ($(strip $(DEVKITPPC)),) -$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") -endif - -include $(DEVKITPPC)/wii_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# INCLUDES is a list of directories containing extra header files -#--------------------------------------------------------------------------------- -TARGET := vbagx_wii -TARGETDIR := executables -BUILD := build_wii -SOURCES := source source/images source/sounds source/fonts source/lang \ - source/gui source/utils source/utils/sz source/utils/unzip \ - source/vba source/vba/apu source/vba/common \ - source/vba/gb source/vba/gba -INCLUDES := source source/vba - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- - -CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ - -DWORDS_BIGENDIAN \ - -DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \ - -DSDL -DNO_PNG -DHAVE_ZUTIL_H \ - -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ - -fomit-frame-pointer \ - -Wno-unused-parameter -Wno-strict-aliasing -Wno-parentheses -CXXFLAGS = $(CFLAGS) -LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map - -#--------------------------------------------------------------------------------- -# any extra libraries we wish to link with -#--------------------------------------------------------------------------------- -LIBS := -ldi -liso9660 -lpng -lmxml -lfat -lwiiuse -lz -lbte -lasnd -logc \ - -lvorbisidec -lfreetype -ltinysmb - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -#--------------------------------------------------------------------------------- -# automatically build a list of object files for our project -#--------------------------------------------------------------------------------- -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) -TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) -LANGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.lang))) -PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) -OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg))) -PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) - export LD := $(CC) -else - export LD := $(CXX) -endif - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ - $(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \ - $(PNGFILES:.png=.png.o) \ - $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) -#--------------------------------------------------------------------------------- -# build a list of include paths -#--------------------------------------------------------------------------------- -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) \ - -I$(LIBOGC_INC) -I$(PORTLIBS)/include/freetype2 - -#--------------------------------------------------------------------------------- -# build a list of library paths -#--------------------------------------------------------------------------------- -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ - -L$(LIBOGC_LIB) - -export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) -.PHONY: $(BUILD) clean - -#--------------------------------------------------------------------------------- -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol - -#--------------------------------------------------------------------------------- -run: - wiiload $(OUTPUT).dol - -#--------------------------------------------------------------------------------- -reload: - wiiload -r $(OUTPUT).dol - - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(OUTPUT).dol: $(OUTPUT).elf -$(OUTPUT).elf: $(OFILES) - -#--------------------------------------------------------------------------------- -# This rule links in binary data with these extensions: ttf lang png ogg pcm -#--------------------------------------------------------------------------------- -%.ttf.o : %.ttf - @echo $(notdir $<) - $(bin2o) - -%.lang.o : %.lang - @echo $(notdir $<) - $(bin2o) - -%.png.o : %.png - @echo $(notdir $<) - $(bin2o) - -%.ogg.o : %.ogg - @echo $(notdir $<) - $(bin2o) - -%.pcm.o : %.pcm - @echo $(notdir $<) - $(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := vbagx_wii +TARGETDIR := executables +BUILD := build_wii +SOURCES := source source/images source/sounds source/fonts source/lang \ + source/gui source/utils source/utils/sz source/utils/unzip \ + source/vba source/vba/apu source/vba/common \ + source/vba/gb source/vba/gba source/goomba source/goomba/minilzo-2.06 +INCLUDES := source source/vba + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ + -DWORDS_BIGENDIAN -DNO_LINK -DNO_FEX \ + -DTILED_RENDERING \ + -DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \ + -DSDL -DNO_PNG -DHAVE_ZUTIL_H \ + -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ + -fomit-frame-pointer \ + -Wno-unused-parameter -Wno-strict-aliasing -Wno-parentheses +CXXFLAGS = $(CFLAGS) +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,-wrap,wiiuse_register + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with +#--------------------------------------------------------------------------------- +LIBS := -ldi -liso9660 -lpng -lmxml -lfat -lwiiuse -lwupc -lz -lbte -lasnd -logc \ + -lvorbisidec -lfreetype -ltinysmb + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) +LANGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.lang))) +PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) +OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg))) +PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \ + $(PNGFILES:.png=.png.o) \ + $(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) -I$(PORTLIBS)/include/freetype2 + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + wiiload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +reload: + wiiload -r $(OUTPUT).dol + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with these extensions: ttf lang png ogg pcm +#--------------------------------------------------------------------------------- +%.ttf.o : %.ttf + @echo $(notdir $<) + $(bin2o) + +%.lang.o : %.lang + @echo $(notdir $<) + $(bin2o) + +%.png.o : %.png + @echo $(notdir $<) + $(bin2o) + +%.ogg.o : %.ogg + @echo $(notdir $<) + $(bin2o) + +%.pcm.o : %.pcm + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/readme.txt b/readme.txt index ce2dbaa..7ffe100 100644 --- a/readme.txt +++ b/readme.txt @@ -1,1014 +1,1153 @@ -¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - - - Visual Boy Advance GX - - http://code.google.com/p/vba-wii - (Under GPL License) - -¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - -Visual Boy Advance GX is a modified port of VBA-M. -With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube. - --=[ Features ]=- - -* Wiimote, Nunchuk, Classic, and Gamecube controller support -* Rotation sensors, Solar sensors, and Rumble support -* Optional special Wii controls built-in for some games -* SRAM and State saving -* IPS/UPS patch support -* Custom controller configurations -* SD, USB, DVD, SMB, Zip, and 7z support -* Compatibility based on VBA-M r927 -* MEM2 ROM Storage for fast access -* Auto frame skip for those core heavy games -* Turbo speed, video zooming, widescreen, and unfiltered video options - -×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ -|0O×øo· UPDATE HISTORY ·oø×O0| -`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' - -[2.2.8 - July 29, 2012] - -* Fixed lag with GameCube controllers - -[2.2.7 - July 7, 2012] - -* Fixed PAL support - -[2.2.6 - July 6, 2012] - -* Support for newer Wiimotes -* Fixed missing audio channel bug (eg: in Mario & Luigi: Superstar Saga) -* Improved controller behavior - allow two directions to be pressed simultaneously -* Compiled with devkitPPC r26 and libogc 1.8.11 - -[2.2.5 - May 15, 2011] - -* Added Turkish translation - -[2.2.4 - March 23, 2011] - -* Fixed browser regressions with stability and speed - -[2.2.3 - March 19, 2011] - -* Improved USB and controller compatibility (recompiled with latest libogc) -* Enabled SMB on GameCube (thanks Extrems!) -* Added Catalan translation -* Translation updates - -[2.2.2 - October 7, 2010] - -* Fixed "blank listing" issue for SMB -* Improved USB compatibility and speed -* Added Portuguese and Brazilian Portuguese translations -* Channel updated (improved USB compatibility) -* Other minor changes - -[2.2.1 - August 14, 2010] - -* IOS 202 support removed -* USB 2.0 support via IOS 58 added - requires that IOS58 be pre-installed -* DVD support via AHBPROT - requires latest HBC - -[2.2.0 - July 22, 2010] - -* Fixed broken auto-update - -[2.1.9 - July 20, 2010] - -* Reverted USB2 changes - -[2.1.8 - July 14, 2010] - -* Ability to use both USB ports (requires updated IOS 202 - WARNING: older - versions of IOS 202 are NO LONGER supported) -* Hide non-ROM files -* Other minor improvements - -[2.1.7 - June 20, 2010] - -* USB improvements -* GameCube improvements - audio, SD Gecko, show thumbnails for saves -* Other minor changes - -[2.1.6 - May 19, 2010] - -* DVD support fixed -* Fixed some potential hangs when returning to menu -* Video/audio code changes -* Fixed scrolling text bug -* Other minor changes - -[2.1.5 - April 9, 2010] - -* Fix auto-save bug - -[2.1.4 - April 9, 2010] - -* Fixed issue with saves (GBA) and snapshots (GB) -* Most 3rd party controllers should work now (you're welcome!) -* Translation updates (German and Dutch) -* Other minor changes - -[2.1.3 - March 30, 2010] - -* Fixed ROM allocation. Should solve some unexplained crashes -* Numerous performance optimizations (thanks dancinninja!) -* DVD / USB 2.0 support via IOS 202. DVDx support has been dropped. It is - highly recommended to install IOS 202 via the included installer -* Multi-language support (only French translation is fully complete) -* Thank you to everyone who submitted translations -* SMB improvements/bug fixes -* Minor video & input performance optimizations -* Disabling rumble now also disables in-game rumbling -* Fixed saving of GB screen position adjustment - -[2.1.2 - December 23, 2009] - -* Numerous core optimizations (thanks dancinninjac!) -* File browser now scrolls down to the last game when returning to browser -* Auto update for those using USB now works -* Fixed scrollbar up/down buttons -* Minor optimizations - -[2.1.1 - December 7, 2009] - -* Save state corruption issues fixed - -[2.1.0 - December 2, 2009] - -* Fixed SMB (for real this time!) - -[2.0.9 - November 30, 2009] - -* Fixed SMB -* Added separate horizontal/vertical zoom options, and separate GB/GBA ones -* Improved scrolling timing - the more you scroll, the fast it goes -* Fixed reset button on Wii console - now you can reset multiple times -* APU optimization (dancinninjac) -* Minor code optimizations -* Reduce memory fragmentation - fixes out of memory crashes - -[2.0.8 - October 7, 2009] - -* Revamped filebrowser and file I/O -* Fixed MBC2 saving/loading -* Fixed some GB-Z80 instructions -* DVD loading in GameCube should work now (untested and unsupported) -* Many, many other bug fixes - -[2.0.7 - September 16, 2009] - -* Text rendering corrections -* SMB improvements -* Built with latest libraries -* Video mode switching now works properly -* Other minor bugfixes and cleanup - -[2.0.6 - July 22, 2009] - -* Fixed "No game saves found." message when there are actually saves. -* Fixed shift key on keyboard -* Text scrolling works again -* Change default prompt window selection to "Cancel" button - -[2.0.5 - July 9, 2009] - -* Faster SMB/USB browsing -* Last browsed folder is now remembered -* Fixed controller mapping reset button -* Fixed no sound on GameCube version -* Directory names are no longer altered -* Preferences now only saved on exit -* Fixed on-screen keyboard glitches -* SRAM auto-saved on power-off from within a game -* Prevent 7z lockups, better 7z error messages - -[2.0.4 - June 30, 2009] - -* Fixed auto-update -* Increased file browser listing to 10 entries, decreased font size -* Added text scrolling on file browser -* Added reset button for controller mappings -* Settings are now loaded from USB when loading the app from USB on HBC -* Fixed menu crashes caused by ogg player bugs -* Fixed memory card saving verification bug -* Fixed game savebrowser bugs -* Miscellaneous code cleanup/corrections - -[2.0.3 - May 30, 2009] - -* Fixed SD/USB corruption bug -* SMB works again -* GUI bugs fixed, GUI behavioral improvements -* GB Palette editing -* More built-in palettes -* Palettes now fade to white correctly instead of getting brighter -* Can now turn off palette colorizing -* Workaround for palette issue on Mega Man I GB - palette disabled -* Star Wars, TMNT, Lord Of The Rings, Castlevania Wii Controls -* Fix for WarioWare startup - Nunchuk C button or Wii Remote B button will now - make calibration easy by locking the gyroscope. -* Fixed issues with constant rumbling - -[2.0.2 - May 26, 2009] - -* Improved stability -* Fixed broken SDHC from HBC 1.0.2 update -* Fixed issues with returning to menu from in-game -* Add option to disable rumble -* Auto-determines if HBC is present - returns to Wii menu otherwise -* Unfiltered mode fixed -* Miscellaneous bugfixes - -[2.0.1 - April 30, 2009] - -* Multiple state saves now working -* Built with more stable libogc/libfat -* Fixed settings saving glitches -* Fixed Mortal Kombat GameCube controller bug -* Fixed Zelda DX palette bug -* Fixed Harry Potter 1-3 keyboard bug - -[2.0.0 - April 27, 2009] - -* New GX-based menu, with a completely redesigned layout. Has Wiimote IR - support, sounds, graphics, animation effects, and more -* Thanks to the3seashells for designing some top-notch artwork, to - Peter de Man for composing the music, and a special thanks to shagkur for - fixing libogc bugs that would have otherwise prevented the release -* Onscreen keyboard for changing save/load folders and network settings -* Menu configuration options (configurable exit button, wiimote orientation, - volumes) -* New save manager, allowing multiple saves and save browsing. Shows - screenshots for Snapshot saves, and save dates/times -* Added video shifting option -* Added video mode selection (recommended to leave on Automatic) -* USB Mouse support (buttons only) -* Keyboard shift key bug fixed -* Built-in 14 colour palettes for some monochrome gameboy games (Magnetic - Soccer, Malibu Beach Volleyball, Marble Madness, Metroid 2, Mortal Kombat, - Mortal Kombat II, Mortal Kombat 3, Mr. Do!) -* Rumble works in GBC games designed for rumble cartridges but shipped - without rumble cartridges, such as Disney's Tarzan for GBC -* Improved Mortal Kombat Wii Controls -* Mortal Kombat games now have many extra characters to choose -* Wii Controls for more Teenage Mutant Ninja Turtles games -* Improved Lego Star Wars controls -* Boktai menu now tells you when there can't be sun because it is night -* Minor bug fixes - -[1.0.9 - April 7, 2009] - -* Gamecube controller should no longer rumble constantly - -[1.0.8 - April 4, 2009] - -* "Match Wii Game" controls option! Games that have a Wii equivalent can be - played using the controls for that Wii game. For example all Zelda games - can be played with Twilight Princess controls. See the Instructions section - below for important details. -* Rotation/Tilt sensor games all work -* Solar sensors (Boktai 1/2/3) -* Rumble (except for games that rely on Gameboy Player) -* Keyboard -* PAL support, finally! -* New scaling options, choose how much stretching you want -* Colourised games now partially work but still have distortion -* "Corvette" no longer has a screwed up palette (but still crashes) -* Triggers net reconnection on SMB failure -* Source code refactored, and project file added -* Instructions section added to this readme file - -[1.0.7 - January 27, 2009] - -* Updated to VBA-M r847 -* Corrected sound interpolation -* Faster SD/USB - new read-ahead cache -* Removed trigger of back to menu for Classic Controller right joystick -* Fixed a bug with reading files < 2048 bytes -* Fixed GBA games on GameCube -* Fixed homebrew GBA games on GameCube -* Fixed some memory leaks, buffer overflows, etc -* Code cleanup, other general bugfixes - -[1.0.6 - December 24, 2008] - -* Fixed save state saving bug -* Fixed unstable SD card access -* Proper SD/USB hotswap (Wii only) -* Auto-update feature (Wii only) -* Rewritten SMB access - speed boost, NTLM now supported (Wii only) -* Improved file access code -* Resetting preferences now resets controls -* Minor bug fixes - -[1.0.5 - November 19, 2008] - -* SDHC works now -* Frameskipping tweaks -* Fixed snapshot loading issue -* Full widescreen support -* Changed scaling -* Zooming fixed (thanks eke-eke!) -* PAL timing changes - EURGB60 mode forced -* Wii - Added console/remote power button support -* Wii - Added reset button support (resets game) -* Wii - Settings file is now named settings.xml and is stored in the same - folder as the DOL (eg: apps/vbagx/settings.xml) -* GameCube - Added DVD motor off option -* GameCube - Fixed GBA loading issue - -[1.0.4 - October 28, 2008] - -* Complete port of VBA-M - now uses blaarg's new audio core, latest GB core -* Frameskipping improvements -* Sound processing improved - L-R channel reversal corrected, skipping fixed -* Saving problems fixed, game compatibility improved -* IPS/UPS/PPF patch support -* SD/USB hot-swapping! -* SDHC support -* Zoom setting saved -* Widescreen correction option -* GameCube support is back, including Qoob support! - -[1.0.3 - October 15, 2008] - -* New timing / frameskip algorithm - should (hopefully) work 100% better! -* Performance improvements - video threading, PPC core partly activated -* Video zooming option -* Unfiltered video option -* 7z support -* Loading progress bars added - -[1.0.2 - October 6, 2008] - -* New core! The core is now a custom combination of VBA-M and VBA 1.72 -* Added DVD, SMB, ZIP, GameCube MC support -* Faster USB/SD speeds -* Screen alignment and flickering problems fixed -* 128K save support added -* Better emulation speeds. Should now be nearly full speed all the time - for most games. -* Turbo speed feature. Mapped to right C-stick (classic controller & - Gamecube controller), and A+B for wiimote -* Controller mapping preferences bug fixed. Your preferences will reset - automatically to correct any problems in your preferences file -* Many other tweaks behind the scenes - -[1.0.1 - September 18, 2008] - -* GBA games now run at full speed -* Menu improvements, with spiffy new background -* Fixed L/R buttons - they work now - -[1.0.0 - September 16, 2008] - -* Now compiles with devkitpro r15 -* One makefile to make all versions -* Complete rewrite based on code from SNES9x GX -* Now has a menu! ROM selector, preferences, controller mapping, etc -* Wiimote, Nunchuk, and Classic controller support -* Button mapping for all controller types -* Full support for SD and USB -* Load/save preference selector. ROMs, saves, and preferences are - saved/loaded according to these -* 'Auto' settings for save/load - attempts to automatically determine - your load/save device(s) - SD, USB -* Preferences are loaded and saved in XML format. You can open - VBAGX.xml edit all settings, including some not available within - the program - -×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ -|0O×øo· SETUP & INSTALLATION ·oø×O0| -`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' - -Unzip the archive. You will find the following folders inside: - -apps Contains Homebrew Channel ready files - (see Homebrew Channel instructions below) - -vbagx Contains the directory structure required for storing - roms and saves. By default, roms are loaded from - "vbagx/roms/" and saves / preferences are stored in - "vbagx/saves/". - --=[ Loading / Running the Emulator ]=- - -Wii - Via Homebrew Channel: --------------------------------- -The most popular method of running homebrew on the Wii is through the Homebrew -Channel. If you already have the channel installed, just copy over the apps folder -included in the archive into the root of your SD card. - -Remember to also create the vbagx directory structure required. See above. - -If you haven't installed the Homebrew Channel yet, read about how to here: -http://hbc.hackmii.com/ - -Gamecube: --------------------------------- -You can load VBAGX via sdload and an SD card in slot A, or by streaming -it to your Gamecube, or by booting a bootable DVD with VBAGX on it. -This document doesn't cover how to do any of that. - -×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ -|0O×øo· INSTRUCTIONS ·oø×O0| -`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' -If you have upgraded from a previous version, the emulator may start with a -message that your preferences have been reset. You will need to set your -preferences how you want them. - -Otherwise the emulator will start at the main menu, which is a list of game -ROMs. There is also a settings button to choose how and where to load or -save files, and to change menu settings. - -Navigate the menu with the D-Pad, or the Wiimote pointer, and select options -with the A button. Press the B button to swap between controlling a list box -and controlling the buttons. Pressing the Home button will exit from the -main menu. You can choose what exiting will do by using the settings menu. - -Click on the logo to see the credits. - -When choosing a file, use left and right to go up or down a page. - -Once you choose a game, the game will start. But you can get back to a menu -by pressing Home. This takes you to the in-game menu, where you can save, -load, reset, or change settings. The settings apply to all games, not just -the current one. These settings are different from the settings on the main -menu. If you are playing a Boktai game with a solar sensor, there will also -be a fifth button which lets you change the weather. The sunlight is based -on the weather, the time of day, and the angle of your Wiimote. - -Saving and loading let you choose two kinds of save files. SRAM is the -normal kind of saving and loading that you have on a real gameboy. It only -saves up to the last checkpoint or savepoint in the game. Or you can save -a better way by using the emulator's special "Snapshot" feature which -saves the state of everything, exactly where you are up to. Loading a -Snapshot may erase your "SRAM (Auto)" so be careful. - -From the game menu you can return to the game by pressing Home again, or by -clicking on the "Close" button in the top right. Or to quit that game and -choose a different game, click on the "Main Menu" button. - -If you don't want to load ROMs from the SD card, you can go to the -settings menu and choose where to load from. You can load from SD cards, -USB memory sticks/hard drives, DVD (if you installed DVDX), gamecube memory -cards, or from shared folders over the network (this is called SMB). - -ROMs can be in ZIP files, but the ROM must be the first file in the ZIP. If -not, you will get an error. ROMs can also be in .7z files, or ordinary rom -files. - -Patches can be used to colourise a monochrome gameboy game, or to translate -a game into your language, or to stop the game from needing special hardware. -Search the internet for patches. Many games have been translated by fans. -They can be in IPS or UPS format. You don't need to patch anything yourself. -Just put the IPS or UPS file in the vbagx/roms folder along with the rom -itself. The patch must have the same name as the rom. Patches can not be put -inside the ZIP file. If a rom is zipped, you might need to check inside the -zip for the actual rom filename. - -Colourised games still have some distortion in this version, but it is -improved from the previous version, and better than VBA-M. Some unpatched -monochrome gameboy games have built-in palettes in this emulator and will -appear in colour. - -You must not use patched versions of Boktai roms! (Except for the translation -patch for Boktai 3, which is highly recommended). The patches are for old -emulators that don't support the solar sensor. VBA GX and NO$GBA support the -solar sensor natively, and the patch will stop them from working. - -You must also not use patched versions of WarioWare Twisted, Kirby's Tilt n -Tumble, or Yoshi's Universal Gravitation (Topsy Turvy). The original roms -are fully supported, and the patch will stop them from working. - --=[ Controls ]=- - -See the website at http://www.wiibrew.org/wiki/VBA for better control -documentation, with illustrations and tables. - -The default controls are... - -+ = Gameboy Start Button -- = Gameboy Select Button -Home = Show emulator's game menu - -Wii Remote by itself: -Hold the Wii Remote sideways. -2 = Gameboy A Button -1 = Gameboy B Button -A = Gameboy R Button -B = Gameboy L Button - -Wii Remote + Nunchuk: -Hold the Nunchuk and ignore the Wii Remote. -Z = Gameboy A Button -C = Gameboy B Button - -Classic Controller: -Use the buttons as labelled. -A = Gameboy A Button -B = Gameboy B Button -R = Gameboy R Button -L = Gameboy L Button - -You can configure the controls how you want from the controls menu. Different -controls will be used depending on what you have plugged into the Wii Remote. -Nunchuk means Nunchuk + Wii Remote. Gamecube controllers can -be used at the same time as Wii Remotes and all control the same player. -When configuring controls, press HOME to cancel. - -But the controls you choose will be overridden for certain games if you -choose "Match Wii Game" (or "Match Gamecube Game" on a Gamecube) and you have -the appropriate expansion plugged in. If the game does not have special Wii -controls, then the controls you chose will be used. - -Gameboy and Gameboy colour games don't have L and R buttons. Those buttons -only work in Gameboy Advance games. - -In addition to the controls you can configure, these other controls apply: - -HOME, Escape: returns you to the emulator's game menu. Then press B to go -to the main menu and B again to return to the game. -A+B, Spacebar, or right analog stick: fast forward -Right analog stick: zoom (if enabled) - --=[ Match Wii Controls ]=- - -Special Wii controls exist for the following games: - -These Zelda games can be played with Twilight Princess controls: -The Legend Of Zelda, Zelda 2, A Link To The Past, Link's Awakening (DX), -Oracle of Ages, Oracle of Seasons, Minish Cap - -These Mario games can be played with Mario Galaxy controls: -Super Mario Bros., Super Mario Bros. DX, Super Mario 2, Super Mario (2) -Advance, Super Mario 3, Super Mario World, Yoshi's Island, -Yoshi's Universal Gravitation (Topsy Turvy) - -Mario Kart can be (sort of) played with Mario Kart wii controls, but it -doesn't work very well. - -These Metroid games can be played with Metroid Prime 3 controls: -Metroid Zero Mission, Metroid 1, Metroid 2, Metroid Fusion - -These Mortal Kombat games can be played with Mortal Kombat Armageddon controls: -Mortal Kombat, Mortal Kombat II, Mortal Kombat 3, Mortal Kombat 4, Mortal -Kombat Advance, Mortal Kombat Deadly Alliance, Mortal Kombat Tournament -Edition - -These Lego games can be played with Lego Star Wars the Complete Saga -controls: -Lego Star Wars The Video Game, Lego Star Wars The Original Trilogy - -These Teenage Mutant Ninja Turtles games can be played with TMNT Wii controls: -TMNT, Teenage Mutant Ninja Turtles, Fall of the Foot Clan, Back from the Sewers, -Radical Rescue - -These Harry Potter games can be played with Harry Potter and the Order of -the Phoenix Wii controls: -Harry Potter 1, Harry Potter 1 GBC, Harry Potter 2, Harry Potter 2 GBC, -Harry Potter 3, Harry Potter 4, Harry Potter 5 - -These Medal Of Honour games can be played with Medal Of Honour Wii controls: -Medal Of Honour Underground, Medal Of Honour Infiltrator - -One Piece can be played with One Piece Unlimited Adventure controls. - -Boktai 1, Boktai 2, Boktai 3, Kirby's Tilt n Tumble, and WarioWare Twisted -can be played with controls I designed for them. - --=[ Zelda, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Zelda games use the same controls as Twilight Princess on the Wii or -Gamecube. You can also connect a Classic Controller to use similar controls -to the Ocarina Of Time for the Virtual Console, but with the R trigger -acting as the B button and an inventory like Twilight Princess. With nothing -plugged in to the Wii Remote, your configured controls are used instead. - -The Wii Zelda controls are: -=========================== - -Swing your Wii Remote to draw or swing your sword. Press A to put your sword -away again. The 2 handed sword can't be drawn this way, and must be drawn -manually from the items menu, but you can swing it like normal. - -Shake your Nunchuk to do a spin attack. - -Use the Z Button to Z-Target and to draw and use your shield. While -Z-Targetting you will sidestep in some games. If you have a Gust Jar -equipped instead of a shield, it will be used for Z-Targetting. - -Use the A Button to perform an action, such as rolling, talking to people, -reading signs, picking things up, throwing things, shrinking or growing, -pulling things, etc. It will also put away your sword or shield. In Zelda 2, -it will jump. - -Use the C Button to fast forward. It was originally the camera button in -Twilight Princess. - -Press the B Button to use the currently selected item. 3 other items will be -mapped to Left, Down, and Right D-Pad buttons. Swap the currently selected -item with one of those items by pressing that D-Pad button. The three slots -correspond to the first 3 slots in your inventory. In Minish Cap, the D-Pad -buttons use the item directly instead of swapping it with the B Button, and -the B Button is the same as the down button. In Minish Cap the left item is -always the Kinstones and the down and right items correspond to the B and A -slots. - -Up on the D-Pad talks to Midna, or to your hat. It will take you to the save -screen in Link's Awakening, or to the secondary items screen in the Oracle -games. - -The 1 Button goes to the Map screen. -The - Button goes to the Items screen. -The + Button goes to the Quest Status screen - -On the Items screen, choose an item and then press either the B Button or the -D-Pad button to move it to that slot. The change may not be visible until you -go to another screen and back. In Link's Awakening you can toggle Bomb -Arrows by choosing the bombs and pressing Z. It will rumble for a short time -when bomb arrows are deactivated, and for a long time when bomb arrows are -activated. You still need to equip the bow to use bomb arrows. In Minish Cap -you should be able to use the IR pointer function to select items. - -The Gamecube controller Zelda controls are: -=========================================== - -B is the sword button. Use it to draw or swing your sword. Hold B for a spin -attack. Press A to put the sword away again. The 2 handed sword can't be -drawn this way, and must be selected manually from the items screen, but can -be swung with this (or any other) button. - -Use the L Trigger to L-Target and to draw and use your shield. While -L-Targetting you will sidestep in some games. If you have a Gust Jar -equipped instead of a shield, it will be used for L-Targetting. - -Use the A Button to perform an action, such as rolling, talking to people, -reading signs, picking things up, throwing things, shrinking or growing, -etc. It will also put away your sword or shield. In Zelda 2, it will jump. - -Use the R Trigger to pull on blocks or walls, or to lift things. You must -have a bracelet or gloves to lift some objects. The bracelet or gloves will -be equipped automatically. This feature is unique to the Gamecube controller. - -Use the right analog stick to fast forward. It was originally the camera -control in Twilight Princess. - -Press the X or Y buttons to use the two equipped items. These two items both -share the B slot, except in Minish Cap where one is in the A slot. The item -that was not used last will be in the first slot in your inventory. - -Right on the D-Pad takes you to the map. -Up on the D-Pad takes you to the items screen. -Start takes you to the quest status screen. - -The Z trigger talks to Midna, or to your hat. It will take you to the save -screen in Link's Awakening, or to the secondary items screen in the Oracle -games. - -The Classic controller Zelda controls are: -========================================== - -B is the sword button. Use it to draw or swing your sword. Hold B for a spin -attack. Press A to put the sword away again. The 2 handed sword can't be -drawn this way, and must be selected manually from the items screen, but can -be swung with this (or any other) button. - -Use the L Trigger to L-Target and to draw and use your shield. While -L-Targetting you will sidestep in some games. If you have a Gust Jar -equipped instead of a shield, it will be used for L-Targetting. - -Use the A Button to perform an action, such as rolling, talking to people, -reading signs, picking things up, throwing things, shrinking or growing, -pulling, etc. It will also put away your sword or shield. In Zelda 2, it -will jump. - -Use the ZL Button to fast forward. - -Press the R Button to use the currently selected item. 3 other items will be -mapped to Left, Down, and Right on the right analog stick. They are also -mapped to ZR, Y, and X. Swap the currently selected item with one of those -items by pressing that button or direction. The three slots correspond to -the first 3 slots in your inventory. In Minish Cap, the D-Pad buttons use the -item directly instead of swapping it with the B Button, and the B Button is -the same as the down button. In Minish Cap the left item is always the -Kinstones and the down and right items correspond to the B and A slots. - -+ (Start) takes you to the subscreens. -- (Select) takes you to the map or changes subscreens. - -Up on the analog stick talks to Midna, or to your hat. - - --=[ Mario, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Mario or Yoshi games use the same controls as Super Mario Galaxy on the -Wii. You can also connect a Classic Controller to use similar controls to -Super Mario World on the SNES. - -The Wii Mario controls are: -=========================== - -Shake the Wii Remote to do a spin attack, or to shoot fireballs when you are -fire Mario. In some games that have a spin attack, you will need to use the -B Button instead to shoot fireballs. You can also dismount Yoshi by shaking. - -Walk by moving the joystick a little, run by moving the joystick a lot. - -A = jump -B = shoot, run, hold on to things, yoshi's tongue, etc. -Z = crouch or lay egg. Press Z while in the air to butt stomp. -C = camera. Hold C to look around with the joystick. -D-Pad = look around, or walk in some games -+ = pause -1 = throw egg if you are Yoshi - -The Classic Controller Mario controls are: -========================================== - -Walk by moving the joystick a little, run by moving the joystick a lot. - -B = jump -A = spin attack -X/Y = shoot, run, hold on to things, yoshi's tongue, etc. -ZL or sometimes L = crouch or lay egg. Press in the air to butt stomp. -+ = pause -L/R sometimes look around - - --=[ Yoshi's Universal Gravitation (Topsy Turvy), Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -The controls are the same as all other Mario or Yoshi games, except that -tilting the Wii Remote tilts the world and the screen. This affects -everything in the world and also how you move. - - --=[ Metroid, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Metroid games use the same controls as Metroid Prime 3: Corruption on -the Wii. You aim up and down by pointing the Wii Remote up and down. - -The Wii Metroid controls are: -============================= -Aim up and down by pointing the Wii Remote up and down. - -Flick the Wii remote up while in Morph Ball to spring jump. - -A = shoot -B = jump -Down on D-Pad = fire missile -C = toggle Morph Ball -- = start -+ = toggle super missiles -1 = map -2 = hint - - --=[ TMNT, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -The TMNT games (except Battle Nexus) use the same controls as TMNT on Wii, -or GameCube. With a Classic Controller they use the same controls as on -the Playstation version. - -The Wii TMNT controls are: -========================== -Shake the Wii Remote to attack or to throw away a weapon if -in the air. Also shake to pick up a weapon. - -Shake the Nunchuk to do a spin kick. - -A = jump -B = swap turtle, or charge attack -B while pointing up = super family move -C = roll -Z = special move - --=[ Boktai, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -The 3 Boktai games use special controls that I created. They are not based on -anything, since the real game uses a solar sensor. - -The controls are the same with or without a Nunchuk. - -The Wii Boktai controls are: -============================ - -Point your Wii Remote at the sky to quickly charge your Gun Del Sol. Point -your Wii Remote at the ground to block the sunlight and prevent it from -charging or overheating. Or hold it like normal to use it like normal. - -Press Home to set the real life weather in the emulator's game menu. Note -that if it is night time in real life, there will not be any sun, regardless -of what you set the weather to. Please set the weather honestly or it spoils -the fun. Note that maximum sun is not actually the best, since it rots fruit, -and overheats your gun. The weather must be set each time you play, it is not -saved. - -Swing your Wii Remote to swing your sword or other weapon, if you have one. - -D-Pad or Nunchuk joystick walks. - -Press B to fire your Gun Del Sol. - -A = read signs, open chests, talk to people -C or 2 = look around, or change subscreen (R) -+ = start -- = select -Z or 1 = change element, or change subscreen (L) -1 (if Nunchuk plugged in) = fast forward - --=[ WarioWare Twisted, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -WarioWare Twisted uses similar controls to the Gameboy game. - -The Wii WarioWare Twisted controls are: -======================================= - -Rotate the Wii Remote to rotate. - -Hold Z to lock the current menu item. - -A = Select -B = Cancel -+ = Start - --=[ Kirby's Tilt n Tumble, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -Kirby's Tilt n Tumble uses similar controls to the Gameboy game. - -The Kirby Tilt n Tumble controls are: -===================================== - -Tilt the Wii Remote to tilt the world. Shake the Wii Remote to flick Kirby -and the monsters up into the air. - -A = shoot yourself out of holes in the ground, or jump from clouds. - --=[ Mortal Kombat, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All Mortal Kombat games use the same controls as Mortal Kombat Armaggedon -for the Wii, except that special moves gestures are not implemented yet. - -The Mortal Kombat Wii controls are: -=================================== - -Use the Nunchuk joystick to move and jump. - -D-Pad left = Low Punch -D-Pad up = High Punch -D-Pad down = Low Kick -D-Pad right = High Kick -Z = block -A = throw -C = change style, run, change costume or character -+ = pause -- = change costume or character - --=[ Lego Star Wars, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -Both Lego Star Wars games use the same controls as Lego Star Wars: The -Complete Saga for the Wii. - -The Lego Star Wars Wii controls are: -==================================== -Swing the Wii Remote to swing your lightsaber. -Flick the Wii Remote up to grapple. - -A = Jump -B = Shoot -Z = Use the force, build lego -C = Change characters, talk to people -- = force power, special ability -+ = start -1/2 = fast forward - --=[ Harry Potter, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All the Harry Potter games use the same controls as Harry Potter & The Order -Of The Phoenix on the Wii. Spell gestures are not supported yet. - -The Harry Potter Wii controls are: -================================== -Wave the Wii Remote to cast a spell. -Nunchuk joystick walks. -D-Pad changes subscreen in the map and navigates menu. -In Harry Potter and the Order of the Phoenix you must use the IR Pointer -to select where to cast a spell. - -A = Talk, open door, push button, interract, etc. / Jinx -B = Use your wand / charm / cancel -Z = run (fast forward) / sneak -C = show location name / flute / jump -- = Maurauders map / Tasks -+ = pause / menu -1/2 = change spells - --=[ Medal of Honour, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -All the Medal of Honour games use the same controls as various -Medal of Honour games and modes on the Wii. - -The Medal of Honour Wii controls are: -===================================== - -In Medal of Honour Underground you turn by aiming with the Wii Remote IR -pointer on the screen like any FPS game. In Medal of Honour Infiltrator, -you don't. - -Swing the Wiimote up to reload. -Move with the Nunchuk joystick. - -B = shoot -- = use -+ = pause, objectives, menu -2 / D-Pad Up = reload -D-Pad Left/Right = change weapons -D-Pad Down = toggle crouch -C = strafe -1 = run - --=[ One Piece, Match Wii Controls ]=- - -Turn "Match Wii Controls" ON to use these controls. - -One Piece uses the same controls as One Piece Unlimited Adventure on the Wii -or One Piece Grand Adventure (and others) on the Gamecube. - -The One Piece Wii controls are: -=============================== - -A = attack -B = jump -- = change character -+ = pause -C = dash (double click and hold) -Z = grab -2 = fast forward -1 = select (maybe does nothing) - -The One Piece Gamecube controls are: -=============================== - -A = attack -X = attack up -Y = jump -B = grab -R Trigger = change character -start = pause -L Trigger = dash (double click and hold) -Z = grab -right analog stick = fast forward -1 = select (maybe does nothing) - -¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - --=[ Credits ]=- - - Coding & menu design Tantric - Additional coding Carl Kenner, dancinninjac - Menu artwork the3seashells - Menu sound Peter de Man - - ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ - VBA GameCube/Wii SoftDev, emukidid - - Visual Boy Advance - M VBA-M Team - Visual Boy Advance Forgotten - libogc/devkitPPC shagkur & wintermute - FreeTypeGX Armin Tamzarian - - And many others who have contributed over the years! - -¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - - VBAGX Web Site - http://code.google.com/p/vba-wii - -¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ +¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ + + - Visual Boy Advance GX - + https://github.com/dborth/vba-wii + (Under GPL License) + +¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ + +Visual Boy Advance GX is a modified port of VBA-M. +With it you can play GBA/Game Boy Color/Game Boy games on your Wii/GameCube. + +-=[ Features ]=- + +* Wiimote, Nunchuk, Classic, and Gamecube controller support +* Rotation sensors, Solar sensors, and Rumble support +* Optional special Wii controls built-in for some games +* SRAM and State saving +* IPS/UPS patch support +* Custom controller configurations +* SD, USB, DVD, SMB, Zip, and 7z support +* Compatibility based on VBA-M r1231 +* MEM2 ROM Storage for fast access +* Auto frame skip (optional) for those core heavy games +* Turbo speed, video zooming, widescreen, and unfiltered video options +* Native loading/saving of ROMS and SRAM from Goomba (a GB emulator for GBA) +* Improved video rendering from RetroArch +* Screenshots can be displayed on the main menu +* Fixed pixel ratio mode (1x, 2x, and 3x) +* Borders (from Super Game Boy games or custom from .png) +* Wii U Pro Controller support +* 240p support + +×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0O×øo· UPDATE HISTORY ·oø×O0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' + +[2.3.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] + +* Fixed lag with GameCube controllers + +[2.2.7 - July 7, 2012] + +* Fixed PAL support + +[2.2.6 - July 6, 2012] + +* Support for newer Wiimotes +* Fixed missing audio channel bug (eg: in Mario & Luigi: Superstar Saga) +* Improved controller behavior - allow two directions to be pressed simultaneously +* Compiled with devkitPPC r26 and libogc 1.8.11 + +[2.2.5 - May 15, 2011] + +* Added Turkish translation + +[2.2.4 - March 23, 2011] + +* Fixed browser regressions with stability and speed + +[2.2.3 - March 19, 2011] + +* Improved USB and controller compatibility (recompiled with latest libogc) +* Enabled SMB on GameCube (thanks Extrems!) +* Added Catalan translation +* Translation updates + +[2.2.2 - October 7, 2010] + +* Fixed "blank listing" issue for SMB +* Improved USB compatibility and speed +* Added Portuguese and Brazilian Portuguese translations +* Channel updated (improved USB compatibility) +* Other minor changes + +[2.2.1 - August 14, 2010] + +* IOS 202 support removed +* USB 2.0 support via IOS 58 added - requires that IOS58 be pre-installed +* DVD support via AHBPROT - requires latest HBC + +[2.2.0 - July 22, 2010] + +* Fixed broken auto-update + +[2.1.9 - July 20, 2010] + +* Reverted USB2 changes + +[2.1.8 - July 14, 2010] + +* Ability to use both USB ports (requires updated IOS 202 - WARNING: older + versions of IOS 202 are NO LONGER supported) +* Hide non-ROM files +* Other minor improvements + +[2.1.7 - June 20, 2010] + +* USB improvements +* GameCube improvements - audio, SD Gecko, show thumbnails for saves +* Other minor changes + +[2.1.6 - May 19, 2010] + +* DVD support fixed +* Fixed some potential hangs when returning to menu +* Video/audio code changes +* Fixed scrolling text bug +* Other minor changes + +[2.1.5 - April 9, 2010] + +* Fix auto-save bug + +[2.1.4 - April 9, 2010] + +* Fixed issue with saves (GBA) and snapshots (GB) +* Most 3rd party controllers should work now (you're welcome!) +* Translation updates (German and Dutch) +* Other minor changes + +[2.1.3 - March 30, 2010] + +* Fixed ROM allocation. Should solve some unexplained crashes +* Numerous performance optimizations (thanks dancinninja!) +* DVD / USB 2.0 support via IOS 202. DVDx support has been dropped. It is + highly recommended to install IOS 202 via the included installer +* Multi-language support (only French translation is fully complete) +* Thank you to everyone who submitted translations +* SMB improvements/bug fixes +* Minor video & input performance optimizations +* Disabling rumble now also disables in-game rumbling +* Fixed saving of GB screen position adjustment + +[2.1.2 - December 23, 2009] + +* Numerous core optimizations (thanks dancinninjac!) +* File browser now scrolls down to the last game when returning to browser +* Auto update for those using USB now works +* Fixed scrollbar up/down buttons +* Minor optimizations + +[2.1.1 - December 7, 2009] + +* Save state corruption issues fixed + +[2.1.0 - December 2, 2009] + +* Fixed SMB (for real this time!) + +[2.0.9 - November 30, 2009] + +* Fixed SMB +* Added separate horizontal/vertical zoom options, and separate GB/GBA ones +* Improved scrolling timing - the more you scroll, the fast it goes +* Fixed reset button on Wii console - now you can reset multiple times +* APU optimization (dancinninjac) +* Minor code optimizations +* Reduce memory fragmentation - fixes out of memory crashes + +[2.0.8 - October 7, 2009] + +* Revamped filebrowser and file I/O +* Fixed MBC2 saving/loading +* Fixed some GB-Z80 instructions +* DVD loading in GameCube should work now (untested and unsupported) +* Many, many other bug fixes + +[2.0.7 - September 16, 2009] + +* Text rendering corrections +* SMB improvements +* Built with latest libraries +* Video mode switching now works properly +* Other minor bugfixes and cleanup + +[2.0.6 - July 22, 2009] + +* Fixed "No game saves found." message when there are actually saves. +* Fixed shift key on keyboard +* Text scrolling works again +* Change default prompt window selection to "Cancel" button + +[2.0.5 - July 9, 2009] + +* Faster SMB/USB browsing +* Last browsed folder is now remembered +* Fixed controller mapping reset button +* Fixed no sound on GameCube version +* Directory names are no longer altered +* Preferences now only saved on exit +* Fixed on-screen keyboard glitches +* SRAM auto-saved on power-off from within a game +* Prevent 7z lockups, better 7z error messages + +[2.0.4 - June 30, 2009] + +* Fixed auto-update +* Increased file browser listing to 10 entries, decreased font size +* Added text scrolling on file browser +* Added reset button for controller mappings +* Settings are now loaded from USB when loading the app from USB on HBC +* Fixed menu crashes caused by ogg player bugs +* Fixed memory card saving verification bug +* Fixed game savebrowser bugs +* Miscellaneous code cleanup/corrections + +[2.0.3 - May 30, 2009] + +* Fixed SD/USB corruption bug +* SMB works again +* GUI bugs fixed, GUI behavioral improvements +* GB Palette editing +* More built-in palettes +* Palettes now fade to white correctly instead of getting brighter +* Can now turn off palette colorizing +* Workaround for palette issue on Mega Man I GB - palette disabled +* Star Wars, TMNT, Lord Of The Rings, Castlevania Wii Controls +* Fix for WarioWare startup - Nunchuk C button or Wii Remote B button will now + make calibration easy by locking the gyroscope. +* Fixed issues with constant rumbling + +[2.0.2 - May 26, 2009] + +* Improved stability +* Fixed broken SDHC from HBC 1.0.2 update +* Fixed issues with returning to menu from in-game +* Add option to disable rumble +* Auto-determines if HBC is present - returns to Wii menu otherwise +* Unfiltered mode fixed +* Miscellaneous bugfixes + +[2.0.1 - April 30, 2009] + +* Multiple state saves now working +* Built with more stable libogc/libfat +* Fixed settings saving glitches +* Fixed Mortal Kombat GameCube controller bug +* Fixed Zelda DX palette bug +* Fixed Harry Potter 1-3 keyboard bug + +[2.0.0 - April 27, 2009] + +* New GX-based menu, with a completely redesigned layout. Has Wiimote IR + support, sounds, graphics, animation effects, and more +* Thanks to the3seashells for designing some top-notch artwork, to + Peter de Man for composing the music, and a special thanks to shagkur for + fixing libogc bugs that would have otherwise prevented the release +* Onscreen keyboard for changing save/load folders and network settings +* Menu configuration options (configurable exit button, wiimote orientation, + volumes) +* New save manager, allowing multiple saves and save browsing. Shows + screenshots for Snapshot saves, and save dates/times +* Added video shifting option +* Added video mode selection (recommended to leave on Automatic) +* USB Mouse support (buttons only) +* Keyboard shift key bug fixed +* Built-in 14 colour palettes for some monochrome gameboy games (Magnetic + Soccer, Malibu Beach Volleyball, Marble Madness, Metroid 2, Mortal Kombat, + Mortal Kombat II, Mortal Kombat 3, Mr. Do!) +* Rumble works in GBC games designed for rumble cartridges but shipped + without rumble cartridges, such as Disney's Tarzan for GBC +* Improved Mortal Kombat Wii Controls +* Mortal Kombat games now have many extra characters to choose +* Wii Controls for more Teenage Mutant Ninja Turtles games +* Improved Lego Star Wars controls +* Boktai menu now tells you when there can't be sun because it is night +* Minor bug fixes + +[1.0.9 - April 7, 2009] + +* Gamecube controller should no longer rumble constantly + +[1.0.8 - April 4, 2009] + +* "Match Wii Game" controls option! Games that have a Wii equivalent can be + played using the controls for that Wii game. For example all Zelda games + can be played with Twilight Princess controls. See the Instructions section + below for important details. +* Rotation/Tilt sensor games all work +* Solar sensors (Boktai 1/2/3) +* Rumble (except for games that rely on Gameboy Player) +* Keyboard +* PAL support, finally! +* New scaling options, choose how much stretching you want +* Colourised games now partially work but still have distortion +* "Corvette" no longer has a screwed up palette (but still crashes) +* Triggers net reconnection on SMB failure +* Source code refactored, and project file added +* Instructions section added to this readme file + +[1.0.7 - January 27, 2009] + +* Updated to VBA-M r847 +* Corrected sound interpolation +* Faster SD/USB - new read-ahead cache +* Removed trigger of back to menu for Classic Controller right joystick +* Fixed a bug with reading files < 2048 bytes +* Fixed GBA games on GameCube +* Fixed homebrew GBA games on GameCube +* Fixed some memory leaks, buffer overflows, etc +* Code cleanup, other general bugfixes + +[1.0.6 - December 24, 2008] + +* Fixed save state saving bug +* Fixed unstable SD card access +* Proper SD/USB hotswap (Wii only) +* Auto-update feature (Wii only) +* Rewritten SMB access - speed boost, NTLM now supported (Wii only) +* Improved file access code +* Resetting preferences now resets controls +* Minor bug fixes + +[1.0.5 - November 19, 2008] + +* SDHC works now +* Frameskipping tweaks +* Fixed snapshot loading issue +* Full widescreen support +* Changed scaling +* Zooming fixed (thanks eke-eke!) +* PAL timing changes - EURGB60 mode forced +* Wii - Added console/remote power button support +* Wii - Added reset button support (resets game) +* Wii - Settings file is now named settings.xml and is stored in the same + folder as the DOL (eg: apps/vbagx/settings.xml) +* GameCube - Added DVD motor off option +* GameCube - Fixed GBA loading issue + +[1.0.4 - October 28, 2008] + +* Complete port of VBA-M - now uses blaarg's new audio core, latest GB core +* Frameskipping improvements +* Sound processing improved - L-R channel reversal corrected, skipping fixed +* Saving problems fixed, game compatibility improved +* IPS/UPS/PPF patch support +* SD/USB hot-swapping! +* SDHC support +* Zoom setting saved +* Widescreen correction option +* GameCube support is back, including Qoob support! + +[1.0.3 - October 15, 2008] + +* New timing / frameskip algorithm - should (hopefully) work 100% better! +* Performance improvements - video threading, PPC core partly activated +* Video zooming option +* Unfiltered video option +* 7z support +* Loading progress bars added + +[1.0.2 - October 6, 2008] + +* New core! The core is now a custom combination of VBA-M and VBA 1.72 +* Added DVD, SMB, ZIP, GameCube MC support +* Faster USB/SD speeds +* Screen alignment and flickering problems fixed +* 128K save support added +* Better emulation speeds. Should now be nearly full speed all the time + for most games. +* Turbo speed feature. Mapped to right C-stick (classic controller & + Gamecube controller), and A+B for wiimote +* Controller mapping preferences bug fixed. Your preferences will reset + automatically to correct any problems in your preferences file +* Many other tweaks behind the scenes + +[1.0.1 - September 18, 2008] + +* GBA games now run at full speed +* Menu improvements, with spiffy new background +* Fixed L/R buttons - they work now + +[1.0.0 - September 16, 2008] + +* Now compiles with devkitpro r15 +* One makefile to make all versions +* Complete rewrite based on code from SNES9x GX +* Now has a menu! ROM selector, preferences, controller mapping, etc +* Wiimote, Nunchuk, and Classic controller support +* Button mapping for all controller types +* Full support for SD and USB +* Load/save preference selector. ROMs, saves, and preferences are + saved/loaded according to these +* 'Auto' settings for save/load - attempts to automatically determine + your load/save device(s) - SD, USB +* Preferences are loaded and saved in XML format. You can open + VBAGX.xml edit all settings, including some not available within + the program + +×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0O×øo· SETUP & INSTALLATION ·oø×O0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' + +Unzip the archive. You will find the following folders inside: + +apps Contains Homebrew Channel ready files + (see Homebrew Channel instructions below) + +vbagx Contains the directory structure required for storing + roms and saves. By default, roms are loaded from + "vbagx/roms/" and saves / preferences are stored in + "vbagx/saves/". + +-=[ Loading / Running the Emulator ]=- + +Wii - Via Homebrew Channel: +-------------------------------- +The most popular method of running homebrew on the Wii is through the Homebrew +Channel. If you already have the channel installed, just copy over the apps folder +included in the archive into the root of your SD card. + +Remember to also create the vbagx directory structure required. See above. + +If you haven't installed the Homebrew Channel yet, read about how to here: +http://hbc.hackmii.com/ + +Gamecube: +-------------------------------- +You can load VBAGX via sdload and an SD card in slot A, or by streaming +it to your Gamecube, or by booting a bootable DVD with VBAGX on it. +This document doesn't cover how to do any of that. + +×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0O×øo· INSTRUCTIONS ·oø×O0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' +If you have upgraded from a previous version, the emulator may start with a +message that your preferences have been reset. You will need to set your +preferences how you want them. + +Otherwise the emulator will start at the main menu, which is a list of game +ROMs. There is also a settings button to choose how and where to load or +save files, and to change menu settings. + +Navigate the menu with the D-Pad, or the Wiimote pointer, and select options +with the A button. Press the B button to swap between controlling a list box +and controlling the buttons. Pressing the Home button will exit from the +main menu. You can choose what exiting will do by using the settings menu. + +Click on the logo to see the credits. + +When choosing a file, use left and right to go up or down a page. + +Once you choose a game, the game will start. But you can get back to a menu +by pressing Home. This takes you to the in-game menu, where you can save, +load, reset, or change settings. The settings apply to all games, not just +the current one. These settings are different from the settings on the main +menu. If you are playing a Boktai game with a solar sensor, there will also +be a fifth button which lets you change the weather. The sunlight is based +on the weather, the time of day, and the angle of your Wiimote. + +Saving and loading let you choose two kinds of save files. SRAM is the +normal kind of saving and loading that you have on a real gameboy. It only +saves up to the last checkpoint or savepoint in the game. Or you can save +a better way by using the emulator's special "Snapshot" feature which +saves the state of everything, exactly where you are up to. Loading a +Snapshot may erase your "SRAM (Auto)" so be careful. + +From the game menu you can return to the game by pressing Home again, or by +clicking on the "Close" button in the top right. Or to quit that game and +choose a different game, click on the "Main Menu" button. + +If you don't want to load ROMs from the SD card, you can go to the +settings menu and choose where to load from. You can load from SD cards, +USB memory sticks/hard drives, DVD (if you installed DVDX), gamecube memory +cards, or from shared folders over the network (this is called SMB). + +ROMs can be in ZIP files, but the ROM must be the first file in the ZIP. If +not, you will get an error. ROMs can also be in .7z files, or ordinary rom +files. + +Patches can be used to colourise a monochrome gameboy game, or to translate +a game into your language, or to stop the game from needing special hardware. +Search the internet for patches. Many games have been translated by fans. +They can be in IPS or UPS format. You don't need to patch anything yourself. +Just put the IPS or UPS file in the vbagx/roms folder along with the rom +itself. The patch must have the same name as the rom. Patches can not be put +inside the ZIP file. If a rom is zipped, you might need to check inside the +zip for the actual rom filename. + +Colourised games still have some distortion in this version, but it is +improved from the previous version, and better than VBA-M. Some unpatched +monochrome gameboy games have built-in palettes in this emulator and will +appear in colour. + +You must not use patched versions of Boktai roms! (Except for the translation +patch for Boktai 3, which is highly recommended). The patches are for old +emulators that don't support the solar sensor. VBA GX and NO$GBA support the +solar sensor natively, and the patch will stop them from working. + +You must also not use patched versions of WarioWare Twisted, Kirby's Tilt n +Tumble, or Yoshi's Universal Gravitation (Topsy Turvy). The original roms +are fully supported, and the patch will stop them from working. + +-=[ Controls ]=- + +See the website at http://www.wiibrew.org/wiki/VBA for better control +documentation, with illustrations and tables. + +The default controls are... + ++ = Gameboy Start Button +- = Gameboy Select Button +Home = Show emulator's game menu + +Wii Remote by itself: +Hold the Wii Remote sideways. +2 = Gameboy A Button +1 = Gameboy B Button +A = Gameboy R Button +B = Gameboy L Button + +Wii Remote + Nunchuk: +Hold the Nunchuk and ignore the Wii Remote. +Z = Gameboy A Button +C = Gameboy B Button + +Classic Controller: +B = Gameboy A Button +Y = Gameboy B Button +R = Gameboy R Button +L = Gameboy L Button + +You can configure the controls how you want from the controls menu. Different +controls will be used depending on what you have plugged into the Wii Remote. +Nunchuk means Nunchuk + Wii Remote. Gamecube controllers can +be used at the same time as Wii Remotes and all control the same player. +When configuring controls, press HOME to cancel. + +But the controls you choose will be overridden for certain games if you +choose "Match Wii Game" (or "Match Gamecube Game" on a Gamecube) and you have +the appropriate expansion plugged in. If the game does not have special Wii +controls, then the controls you chose will be used. + +Gameboy and Gameboy colour games don't have L and R buttons. Those buttons +only work in Gameboy Advance games. + +In addition to the controls you can configure, these other controls apply: + +HOME, Escape: returns you to the emulator's game menu. Then press B to go +to the main menu and B again to return to the game. +A+B, Spacebar, or right analog stick: fast forward +Right analog stick: zoom (if enabled) + +-=[ Super Game Boy borders ]=- + +VBA-GX has supported Super Game Boy borders since 2.3.1. You can enable this +feature in the Emulation settings on the main menu. + +Borders can be loaded from two locations: +* PNG files in the borders folder (by default, /vbagx/borders) +* The game itself + +Borders will only be loaded from the game itself when the emulator is running +in Super Game Boy mode, and the border setting in Emulation settings is set to +"From game (SGB only)". (You can also use the Emulation settings menu to +force SGB mode even for Game Boy Color games.) If the borders folder exists, +but no border for the game is present, the loaded Super Game Boy border will +be written to a .png file, which can be loaded later in "From .png file" mode. + +In addition, if the borders folder exists but there is no border for the game, +the first border loaded from the game will be written to a PNG file so it can +be loaded in the future (even in Game Boy Color mode.) This means after you +run a game once in SGB mode, you can then use the same border in GBC mode. + +If the border setting is set to "From .png file", borders will be loaded +from the borders folder. Borders can be up to 640x480 and will work for both +Game Boy (Color) and Game Boy Advance games. + +For both loading and saving, the PNG filename is [TITLE].png, where [TITLE] +is the ROM title defined at 0x134 (for GB games) or 0xA0 (for GBA games). For +example, POKEMON_SFXAAXE.png will be loaded for Pokémon Silver. If no PNG file +by that name exists, VBA-GX will try loading default.png (for GB games) or +defaultgba.png (for GBA games) instead. + +Since the borders are rendered along with the video output of the game, the +pixels in the border will be the same size as game pixels. This means that +a Game Boy game will appear in the middle 160x144 pixels of the border, and a +Game Boy Advance game will appear in the middle 240x160 pixels, regardless of +the resolution of the border PNG image. + +-=[ Match Wii Controls ]=- + +Special Wii controls exist for the following games: + +These Zelda games can be played with Twilight Princess controls: +The Legend Of Zelda, Zelda 2, A Link To The Past, Link's Awakening (DX), +Oracle of Ages, Oracle of Seasons, Minish Cap + +These Mario games can be played with Mario Galaxy controls: +Super Mario Bros., Super Mario Bros. DX, Super Mario 2, Super Mario (2) +Advance, Super Mario 3, Super Mario World, Yoshi's Island, +Yoshi's Universal Gravitation (Topsy Turvy) + +Mario Kart can be (sort of) played with Mario Kart wii controls, but it +doesn't work very well. + +These Metroid games can be played with Metroid Prime 3 controls: +Metroid Zero Mission, Metroid 1, Metroid 2, Metroid Fusion + +These Mortal Kombat games can be played with Mortal Kombat Armageddon controls: +Mortal Kombat, Mortal Kombat II, Mortal Kombat 3, Mortal Kombat 4, Mortal +Kombat Advance, Mortal Kombat Deadly Alliance, Mortal Kombat Tournament +Edition + +These Lego games can be played with Lego Star Wars the Complete Saga +controls: +Lego Star Wars The Video Game, Lego Star Wars The Original Trilogy + +These Teenage Mutant Ninja Turtles games can be played with TMNT Wii controls: +TMNT, Teenage Mutant Ninja Turtles, Fall of the Foot Clan, Back from the Sewers, +Radical Rescue + +These Harry Potter games can be played with Harry Potter and the Order of +the Phoenix Wii controls: +Harry Potter 1, Harry Potter 1 GBC, Harry Potter 2, Harry Potter 2 GBC, +Harry Potter 3, Harry Potter 4, Harry Potter 5 + +These Medal Of Honour games can be played with Medal Of Honour Wii controls: +Medal Of Honour Underground, Medal Of Honour Infiltrator + +One Piece can be played with One Piece Unlimited Adventure controls. + +Boktai 1, Boktai 2, Boktai 3, and Kirby's Tilt n Tumble can be played with +controls designed for them. + +-=[ Zelda, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Zelda games use the same controls as Twilight Princess on the Wii or +Gamecube. You can also connect a Classic Controller to use similar controls +to the Ocarina Of Time for the Virtual Console, but with the R trigger +acting as the B button and an inventory like Twilight Princess. With nothing +plugged in to the Wii Remote, your configured controls are used instead. + +The Wii Zelda controls are: +=========================== + +Swing your Wii Remote to draw or swing your sword. Press A to put your sword +away again. The 2 handed sword can't be drawn this way, and must be drawn +manually from the items menu, but you can swing it like normal. + +Shake your Nunchuk to do a spin attack. + +Use the Z Button to Z-Target and to draw and use your shield. While +Z-Targetting you will sidestep in some games. If you have a Gust Jar +equipped instead of a shield, it will be used for Z-Targetting. + +Use the A Button to perform an action, such as rolling, talking to people, +reading signs, picking things up, throwing things, shrinking or growing, +pulling things, etc. It will also put away your sword or shield. In Zelda 2, +it will jump. + +Use the C Button to fast forward. It was originally the camera button in +Twilight Princess. + +Press the B Button to use the currently selected item. 3 other items will be +mapped to Left, Down, and Right D-Pad buttons. Swap the currently selected +item with one of those items by pressing that D-Pad button. The three slots +correspond to the first 3 slots in your inventory. In Minish Cap, the D-Pad +buttons use the item directly instead of swapping it with the B Button, and +the B Button is the same as the down button. In Minish Cap the left item is +always the Kinstones and the down and right items correspond to the B and A +slots. + +Up on the D-Pad talks to Midna, or to your hat. It will take you to the save +screen in Link's Awakening, or to the secondary items screen in the Oracle +games. + +The 1 Button goes to the Map screen. +The - Button goes to the Items screen. +The + Button goes to the Quest Status screen + +On the Items screen, choose an item and then press either the B Button or the +D-Pad button to move it to that slot. The change may not be visible until you +go to another screen and back. In Link's Awakening you can toggle Bomb +Arrows by choosing the bombs and pressing Z. It will rumble for a short time +when bomb arrows are deactivated, and for a long time when bomb arrows are +activated. You still need to equip the bow to use bomb arrows. In Minish Cap +you should be able to use the IR pointer function to select items. + +The Gamecube controller Zelda controls are: +=========================================== + +B is the sword button. Use it to draw or swing your sword. Hold B for a spin +attack. Press A to put the sword away again. The 2 handed sword can't be +drawn this way, and must be selected manually from the items screen, but can +be swung with this (or any other) button. + +Use the L Trigger to L-Target and to draw and use your shield. While +L-Targetting you will sidestep in some games. If you have a Gust Jar +equipped instead of a shield, it will be used for L-Targetting. + +Use the A Button to perform an action, such as rolling, talking to people, +reading signs, picking things up, throwing things, shrinking or growing, +etc. It will also put away your sword or shield. In Zelda 2, it will jump. + +Use the R Trigger to pull on blocks or walls, or to lift things. You must +have a bracelet or gloves to lift some objects. The bracelet or gloves will +be equipped automatically. This feature is unique to the Gamecube controller. + +Use the right analog stick to fast forward. It was originally the camera +control in Twilight Princess. + +Press the X or Y buttons to use the two equipped items. These two items both +share the B slot, except in Minish Cap where one is in the A slot. The item +that was not used last will be in the first slot in your inventory. + +Right on the D-Pad takes you to the map. +Up on the D-Pad takes you to the items screen. +Start takes you to the quest status screen. + +The Z trigger talks to Midna, or to your hat. It will take you to the save +screen in Link's Awakening, or to the secondary items screen in the Oracle +games. + +The Classic controller Zelda controls are: +========================================== + +B is the sword button. Use it to draw or swing your sword. Hold B for a spin +attack. Press A to put the sword away again. The 2 handed sword can't be +drawn this way, and must be selected manually from the items screen, but can +be swung with this (or any other) button. + +Use the L Trigger to L-Target and to draw and use your shield. While +L-Targetting you will sidestep in some games. If you have a Gust Jar +equipped instead of a shield, it will be used for L-Targetting. + +Use the A Button to perform an action, such as rolling, talking to people, +reading signs, picking things up, throwing things, shrinking or growing, +pulling, etc. It will also put away your sword or shield. In Zelda 2, it +will jump. + +Use the ZL Button to fast forward. + +Press the R Button to use the currently selected item. 3 other items will be +mapped to Left, Down, and Right on the right analog stick. They are also +mapped to ZR, Y, and X. Swap the currently selected item with one of those +items by pressing that button or direction. The three slots correspond to +the first 3 slots in your inventory. In Minish Cap, the D-Pad buttons use the +item directly instead of swapping it with the B Button, and the B Button is +the same as the down button. In Minish Cap the left item is always the +Kinstones and the down and right items correspond to the B and A slots. + ++ (Start) takes you to the subscreens. +- (Select) takes you to the map or changes subscreens. + +Up on the analog stick talks to Midna, or to your hat. + + +-=[ Mario, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Mario or Yoshi games use the same controls as Super Mario Galaxy on the +Wii. You can also connect a Classic Controller to use similar controls to +Super Mario World on the SNES. + +The Wii Mario controls are: +=========================== + +Shake the Wii Remote to do a spin attack, or to shoot fireballs when you are +fire Mario. In some games that have a spin attack, you will need to use the +B Button instead to shoot fireballs. You can also dismount Yoshi by shaking. + +Walk by moving the joystick a little, run by moving the joystick a lot. + +A = jump +B = shoot, run, hold on to things, yoshi's tongue, etc. +Z = crouch or lay egg. Press Z while in the air to butt stomp. +C = camera. Hold C to look around with the joystick. +D-Pad = look around, or walk in some games ++ = pause +1 = throw egg if you are Yoshi + +The Classic Controller Mario controls are: +========================================== + +Walk by moving the joystick a little, run by moving the joystick a lot. + +B = jump +A = spin attack +X/Y = shoot, run, hold on to things, yoshi's tongue, etc. +ZL or sometimes L = crouch or lay egg. Press in the air to butt stomp. ++ = pause +L/R = look around (if the game supports it) +ZR = fast forward (8-bit Game Boy only) + +In Super Mario World and Super Mario Land 2, you can use the A or R +buttons for a spin jump. + +-=[ Yoshi's Universal Gravitation (Topsy Turvy), Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +The controls are the same as all other Mario or Yoshi games, except that +tilting the Wii Remote tilts the world and the screen. This affects +everything in the world and also how you move. + + +-=[ Metroid, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Metroid games use the same controls as Metroid Prime 3: Corruption on +the Wii. You aim up and down by pointing the Wii Remote up and down. + +The Wii Metroid controls are: +============================= +Aim up and down by pointing the Wii Remote up and down. + +Flick the Wii remote up while in Morph Ball to spring jump. + +A = shoot +B = jump +Down on D-Pad = fire missile +C = toggle Morph Ball +- = start ++ = toggle super missiles +1 = map +2 = hint + + +-=[ TMNT, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +The TMNT games (except Battle Nexus) use the same controls as TMNT on Wii, +or GameCube. With a Classic Controller they use the same controls as on +the Playstation version. + +The Wii TMNT controls are: +========================== +Shake the Wii Remote to attack or to throw away a weapon if +in the air. Also shake to pick up a weapon. + +Shake the Nunchuk to do a spin kick. + +A = jump +B = swap turtle, or charge attack +B while pointing up = super family move +C = roll +Z = special move + +-=[ Boktai, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +The 3 Boktai games use special controls that I created. They are not based on +anything, since the real game uses a solar sensor. + +The controls are the same with or without a Nunchuk. + +The Wii Boktai controls are: +============================ + +Point your Wii Remote at the sky to quickly charge your Gun Del Sol. Point +your Wii Remote at the ground to block the sunlight and prevent it from +charging or overheating. Or hold it like normal to use it like normal. + +Press Home to set the real life weather in the emulator's game menu. Note +that if it is night time in real life, there will not be any sun, regardless +of what you set the weather to. Please set the weather honestly or it spoils +the fun. Note that maximum sun is not actually the best, since it rots fruit, +and overheats your gun. The weather must be set each time you play, it is not +saved. + +Swing your Wii Remote to swing your sword or other weapon, if you have one. + +D-Pad or Nunchuk joystick walks. + +Press B to fire your Gun Del Sol. + +A = read signs, open chests, talk to people +C or 2 = look around, or change subscreen (R) ++ = start +- = select +Z or 1 = change element, or change subscreen (L) +1 (if Nunchuk plugged in) = fast forward + +-=[ WarioWare Twisted, Match Wii Controls ]=- + +NOTE: For unknown reasons (but probably related to the update of the VBA-M +emulator code), WarioWare Twisted will no longer work on VBA-GX. For now, you +will need to go back to VBA-GX 2.2.8 to play it. + +-=[ Kirby's Tilt n Tumble, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +Kirby's Tilt n Tumble uses similar controls to the Gameboy game. + +The Kirby Tilt n Tumble controls are: +===================================== + +Tilt the Wii Remote to tilt the world. Shake the Wii Remote to flick Kirby +and the monsters up into the air. + +A = shoot yourself out of holes in the ground, or jump from clouds. + +-=[ Mortal Kombat, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All Mortal Kombat games use the same controls as Mortal Kombat Armaggedon +for the Wii, except that special moves gestures are not implemented yet. + +The Mortal Kombat Wii controls are: +=================================== + +Use the Nunchuk joystick to move and jump. + +D-Pad left = Low Punch +D-Pad up = High Punch +D-Pad down = Low Kick +D-Pad right = High Kick +Z = block +A = throw +C = change style, run, change costume or character ++ = pause +- = change costume or character + +-=[ Lego Star Wars, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +Both Lego Star Wars games use the same controls as Lego Star Wars: The +Complete Saga for the Wii. + +The Lego Star Wars Wii controls are: +==================================== +Swing the Wii Remote to swing your lightsaber. +Flick the Wii Remote up to grapple. + +A = Jump +B = Shoot +Z = Use the force, build lego +C = Change characters, talk to people +- = force power, special ability ++ = start +1/2 = fast forward + +-=[ Harry Potter, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All the Harry Potter games use the same controls as Harry Potter & The Order +Of The Phoenix on the Wii. Spell gestures are not supported yet. + +The Harry Potter Wii controls are: +================================== +Wave the Wii Remote to cast a spell. +Nunchuk joystick walks. +D-Pad changes subscreen in the map and navigates menu. +In Harry Potter and the Order of the Phoenix you must use the IR Pointer +to select where to cast a spell. + +A = Talk, open door, push button, interract, etc. / Jinx +B = Use your wand / charm / cancel +Z = run (fast forward) / sneak +C = show location name / flute / jump +- = Maurauders map / Tasks ++ = pause / menu +1/2 = change spells + +-=[ Medal of Honour, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +All the Medal of Honour games use the same controls as various +Medal of Honour games and modes on the Wii. + +The Medal of Honour Wii controls are: +===================================== + +In Medal of Honour Underground you turn by aiming with the Wii Remote IR +pointer on the screen like any FPS game. In Medal of Honour Infiltrator, +you don't. + +Swing the Wiimote up to reload. +Move with the Nunchuk joystick. + +B = shoot +- = use ++ = pause, objectives, menu +2 / D-Pad Up = reload +D-Pad Left/Right = change weapons +D-Pad Down = toggle crouch +C = strafe +1 = run + +-=[ One Piece, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +One Piece uses the same controls as One Piece Unlimited Adventure on the Wii +or One Piece Grand Adventure (and others) on the Gamecube. + +The One Piece Wii controls are: +=============================== + +A = attack +B = jump +- = change character ++ = pause +C = dash (double click and hold) +Z = grab +2 = fast forward +1 = select (maybe does nothing) + +The One Piece Gamecube controls are: +=============================== + +A = attack +X = attack up +Y = jump +B = grab +R Trigger = change character +start = pause +L Trigger = dash (double click and hold) +Z = grab +right analog stick = fast forward +1 = select (maybe does nothing) + +-=[ Kid Dracula, Match Wii Controls ]=- + +Turn "Match Wii Controls" ON to use these controls. + +(There's no Kid Dracula game for the Wii, but this is a good opportunity to +show off some fancy memory-swapping tricks. -libertyernie) + +The Kid Dracula Wii controls (remote + nunchuk) are: +==================================================== + +A = jump +B = use selected weapon +Z = use NOR weapon (fireball) +C = use BAT weapon (turn into bat for 5 sec) ++ = pause +- = switch item +1/2 = fast forward + +The Kid Dracula Classic Controller controls are: +================================================ + +A/B = jump +Y = use selected weapon +X = use NOR weapon (fireball) +R/ZR = use BAT weapon (turn into bat for 5 sec) ++ = pause +- = switch item +1/2 = fast forward + +In Kid Dracula, pressing the "fire" button will always shoot a small fireball, +but holding the button for a second or so to charge up the shoot lets you use +whichever item is selected. + +Pressing B (nunchuk) or Y (classic) will switch back to whatever item was +selected before you pressed Z/C (nunchuk) or X/R/ZR (classic), unless you have +switched items since then. + +¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ + +-=[ Credits ]=- + + Coding & menu design Tantric + Codebase update & Goomba libertyernie + Menu screenshots cebolleto + GBA tiled rendering bgK (for RetroArch) + Additional coding Carl Kenner, dancinninjac + Menu artwork the3seashells + Menu sound Peter de Man + + ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ + VBA GameCube/Wii SoftDev, emukidid + + Visual Boy Advance - M VBA-M Team + Visual Boy Advance Forgotten + libogc/devkitPPC shagkur & wintermute + FreeTypeGX Armin Tamzarian + + And many others who have contributed over the years! + +¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ + + VBAGX Web Site + https://github.com/dborth/vba-wii + +¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ diff --git a/source/filebrowser.cpp b/source/filebrowser.cpp index d3243ea..820fb3f 100644 --- a/source/filebrowser.cpp +++ b/source/filebrowser.cpp @@ -1,619 +1,656 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * filebrowser.cpp - * - * Generic file routines - reading, writing, browsing - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HW_RVL -#include -#endif - -#include "vbagx.h" -#include "vbasupport.h" -#include "vmmem.h" -#include "filebrowser.h" -#include "menu.h" -#include "video.h" -#include "networkop.h" -#include "fileop.h" -#include "input.h" -#include "gcunzip.h" - -BROWSERINFO browser; -BROWSERENTRY * browserList = NULL; // list of files/folders in browser - -char szpath[MAXPATHLEN]; -bool inSz = false; - -char ROMFilename[512]; -bool ROMLoaded = false; -bool loadingFile = false; - -/**************************************************************************** -* autoLoadMethod() -* Auto-determines and sets the load device -* Returns device set -****************************************************************************/ -int autoLoadMethod() -{ - ShowAction ("Attempting to determine load device..."); - - int device = DEVICE_AUTO; - - if(ChangeInterface(DEVICE_SD, SILENT)) - device = DEVICE_SD; - else if(ChangeInterface(DEVICE_USB, SILENT)) - device = DEVICE_USB; - else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT)) - device = DEVICE_SD_SLOTA; - else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT)) - device = DEVICE_SD_SLOTB; - else if(ChangeInterface(DEVICE_DVD, SILENT)) - device = DEVICE_DVD; - else if(ChangeInterface(DEVICE_SMB, SILENT)) - device = DEVICE_SMB; - else - ErrorPrompt("Unable to locate a load device!"); - - if(GCSettings.LoadMethod == DEVICE_AUTO) - GCSettings.LoadMethod = device; // save device found for later use - CancelAction(); - return device; -} - -/**************************************************************************** -* autoSaveMethod() -* Auto-determines and sets the save device -* Returns device set -****************************************************************************/ -int autoSaveMethod(bool silent) -{ - if(!silent) - ShowAction ("Attempting to determine save device..."); - - int device = DEVICE_AUTO; - - if(ChangeInterface(DEVICE_SD, SILENT)) - device = DEVICE_SD; - else if(ChangeInterface(DEVICE_USB, SILENT)) - device = DEVICE_USB; - else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT)) - device = DEVICE_SD_SLOTA; - else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT)) - device = DEVICE_SD_SLOTB; - else if(ChangeInterface(DEVICE_SMB, SILENT)) - device = DEVICE_SMB; - else if(!silent) - ErrorPrompt("Unable to locate a save device!"); - - if(GCSettings.SaveMethod == DEVICE_AUTO) - GCSettings.SaveMethod = device; // save device found for later use - - CancelAction(); - return device; -} - -/**************************************************************************** - * ResetBrowser() - * Clears the file browser memory, and allocates one initial entry - ***************************************************************************/ -void ResetBrowser() -{ - browser.numEntries = 0; - browser.selIndex = 0; - browser.pageIndex = 0; - browser.size = 0; -} - -bool AddBrowserEntry() -{ - if(browser.size >= MAX_BROWSER_SIZE) - { - ErrorPrompt("Out of memory: too many files!"); - return false; // out of space - } - - memset(&(browserList[browser.size]), 0, sizeof(BROWSERENTRY)); // clear the new entry - browser.size++; - return true; -} - -/**************************************************************************** - * CleanupPath() - * Cleans up the filepath, removing double // and replacing \ with / - ***************************************************************************/ -static void CleanupPath(char * path) -{ - if(!path || path[0] == 0) - return; - - int pathlen = strlen(path); - int j = 0; - for(int i=0; i < pathlen && i < MAXPATHLEN; i++) - { - if(path[i] == '\\') - path[i] = '/'; - - if(j == 0 || !(path[j-1] == '/' && path[i] == '/')) - path[j++] = path[i]; - } - path[j] = 0; -} - -bool IsDeviceRoot(char * path) -{ - if(path == NULL || path[0] == 0) - return false; - - if( strcmp(path, "sd:/") == 0 || - strcmp(path, "usb:/") == 0 || - strcmp(path, "dvd:/") == 0 || - strcmp(path, "smb:/") == 0 || - strcmp(path, "carda:/") == 0 || - strcmp(path, "cardb:/") == 0) - { - return true; - } - return false; -} - -/**************************************************************************** - * UpdateDirName() - * Update curent directory name for file browser - ***************************************************************************/ -int UpdateDirName() -{ - int size=0; - char * test; - char temp[1024]; - int device = 0; - - if(browser.numEntries == 0) - return 1; - - FindDevice(browser.dir, &device); - - /* current directory doesn't change */ - if (strcmp(browserList[browser.selIndex].filename,".") == 0) - { - return 0; - } - /* go up to parent directory */ - else if (strcmp(browserList[browser.selIndex].filename,"..") == 0) - { - // already at the top level - if(IsDeviceRoot(browser.dir)) - { - browser.dir[0] = 0; // remove device - we are going to the device listing screen - } - else - { - /* determine last subdirectory namelength */ - sprintf(temp,"%s",browser.dir); - test = strtok(temp,"/"); - while (test != NULL) - { - size = strlen(test); - test = strtok(NULL,"/"); - } - - /* remove last subdirectory name */ - size = strlen(browser.dir) - size - 1; - browser.dir[size] = 0; - } - - return 1; - } - /* Open a directory */ - else - { - /* test new directory namelength */ - if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) < MAXPATHLEN) - { - /* update current directory name */ - sprintf(browser.dir, "%s%s/",browser.dir, browserList[browser.selIndex].filename); - return 1; - } - else - { - ErrorPrompt("Directory name is too long!"); - return -1; - } - } -} - -bool MakeFilePath(char filepath[], int type, char * filename, int filenum) -{ - char file[512]; - char folder[1024]; - char ext[4]; - char temppath[MAXPATHLEN]; - - if(type == FILE_ROM) - { - // Check path length - if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN) - { - ErrorPrompt("Maximum filepath length reached!"); - filepath[0] = 0; - return false; - } - else - { - sprintf(temppath, "%s%s",browser.dir,browserList[browser.selIndex].filename); - } - } - else - { - if(GCSettings.SaveMethod == DEVICE_AUTO) - GCSettings.SaveMethod = autoSaveMethod(SILENT); - - if(GCSettings.SaveMethod == DEVICE_AUTO) - return false; - - switch(type) - { - case FILE_SRAM: - case FILE_SNAPSHOT: - sprintf(folder, GCSettings.SaveFolder); - - if(type == FILE_SRAM) sprintf(ext, "sav"); - else sprintf(ext, "sgm"); - - if(filenum >= -1) - { - if(filenum == -1) - sprintf(file, "%s.%s", filename, ext); - else if(filenum == 0) - sprintf(file, "%s Auto.%s", filename, ext); - else - sprintf(file, "%s %i.%s", filename, filenum, ext); - } - else - { - sprintf(file, "%s", filename); - } - break; - } - sprintf (temppath, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], folder, file); - } - CleanupPath(temppath); // cleanup path - snprintf(filepath, MAXPATHLEN, "%s", temppath); - return true; -} - -/**************************************************************************** - * FileSortCallback - * - * Quick sort callback to sort file entries with the following order: - * . - * .. - * - * - ***************************************************************************/ -int FileSortCallback(const void *f1, const void *f2) -{ - /* Special case for implicit directories */ - if(((BROWSERENTRY *)f1)->filename[0] == '.' || ((BROWSERENTRY *)f2)->filename[0] == '.') - { - if(strcmp(((BROWSERENTRY *)f1)->filename, ".") == 0) { return -1; } - if(strcmp(((BROWSERENTRY *)f2)->filename, ".") == 0) { return 1; } - if(strcmp(((BROWSERENTRY *)f1)->filename, "..") == 0) { return -1; } - if(strcmp(((BROWSERENTRY *)f2)->filename, "..") == 0) { return 1; } - } - - /* If one is a file and one is a directory the directory is first. */ - if(((BROWSERENTRY *)f1)->isdir && !(((BROWSERENTRY *)f2)->isdir)) return -1; - if(!(((BROWSERENTRY *)f1)->isdir) && ((BROWSERENTRY *)f2)->isdir) return 1; - - return stricmp(((BROWSERENTRY *)f1)->filename, ((BROWSERENTRY *)f2)->filename); -} - -/**************************************************************************** - * IsSz - * - * Checks if the specified file is a 7z - ***************************************************************************/ -bool IsSz() -{ - if (strlen(browserList[browser.selIndex].filename) > 4) - { - char * p = strrchr(browserList[browser.selIndex].filename, '.'); - - if (p != NULL) - if(stricmp(p, ".7z") == 0) - return true; - } - return false; -} - -/**************************************************************************** - * StripExt - * - * Strips an extension from a filename - ***************************************************************************/ -void StripExt(char* returnstring, char * inputstring) -{ - char* loc_dot; - - snprintf(returnstring, MAXJOLIET, "%s", inputstring); - - if(inputstring == NULL || strlen(inputstring) < 4) - return; - - loc_dot = strrchr(returnstring,'.'); - if (loc_dot != NULL) - *loc_dot = 0; // strip file extension -} - -// Shorten a ROM filename by removing the extension, URLs, id numbers and other rubbish -void ShortenFilename(char * returnstring, char * inputstring) -{ - if (!inputstring) { - returnstring[0] = '\0'; - return; - } - // skip URLs in brackets - char * dotcom = (char *) strstr(inputstring, ".com)"); - char * url = NULL; - if (dotcom) { - url = (char *) strchr(inputstring, '('); - if (url >= dotcom) { - url = NULL; - dotcom = NULL; - } else dotcom+= 5; // point to after ')' - } - // skip URLs not in brackets - if (!dotcom) { - dotcom = (char *) strstr(inputstring, ".com"); - url = NULL; - if (dotcom) { - url = (char *) strstr(inputstring, "www"); - if (url >= dotcom) { - url = NULL; - dotcom = NULL; - } else dotcom+= 4; // point to after ')' - } - } - // skip file extension - char * loc_dot = (char *)strrchr(inputstring,'.'); - char * s = (char *)inputstring; - char * r = (char *)returnstring; - // skip initial whitespace, numbers, - and _ ... - while ((*s!='\0' && *s<=' ') || *s=='-' || *s=='_' || *s=='+') s++; - // ... except those that SHOULD begin with numbers - if (strncmp(s,"3D",2)==0) for (int i=0; i<2; i++, r++, s++) *r=*s; - if (strncmp(s,"1st",3)==0 || strncmp(s,"2nd",3)==0 || strncmp(s,"3rd",3)==0 || strncmp(s,"4th",3)==0) for (int i=0; i<3; i++, r++, s++) *r=*s; - if (strncmp(s,"199",3)==0 || strncmp(s,"007",3)==0 || strncmp(s,"4x4",3)==0 || strncmp(s,"720",3)==0 || strncmp(s,"10 ",3)==0) for (int i=0; i<3; i++, r++, s++) *r=*s; - if (strncmp(s,"102 ",4)==0 || strncmp(s,"1942",4)==0 || strncmp(s,"3 Ch",4)==0) for (int i=0; i<4; i++, r++, s++) *r=*s; - if (strncmp(s,"2 in 1",6)==0 || strncmp(s,"3 in 1",6)==0 || strncmp(s,"4 in 1",6)==0) for (int i=0; i<6; i++, r++, s++) *r=*s; - if (strncmp(s,"2-in-1",6)==0 || strncmp(s,"3-in-1",6)==0 || strncmp(s,"4-in-1",6)==0) for (int i=0; i<6; i++, r++, s++) *r=*s; - while (*s>='0' && *s<='9') s++; - if (r==(char *)returnstring) while ((*s!='\0' && *s<=' ') || *s=='-' || *s=='_' || *s=='+') s++; - // now go through rest of string until we get to the end or the extension - while (*s!='\0' && (loc_dot==NULL || s'\0' && *s<=' ') || *s=='-' || *s=='_') s++; - while (*s>='0' && *s<='9') s++; - while ((*s>'\0' && *s<=' ') || *s=='-' || *s=='_') s++; - } - // skip all but 1 '-', '_' or space in a row - char c = s[0]; - if (c==s[1] && (c=='-' || c=='_' || c==' ')) s++; - // skip space before hyphen - if (*s==' ' && s[1]=='-') s++; - // copy character to result - if (*s=='_') *r=' '; - else *r = *s; - // skip spaces after hyphen - if (*s=='-') while (s[1]==' ') s++; - s++; r++; - } - *r = '\0'; - // if the result is too short, abandon what we did and just strip the ext instead - if (strlen(returnstring) <= 4) StripExt(returnstring, inputstring); -} - -/**************************************************************************** - * BrowserLoadSz - * - * Opens the selected 7z file, and parses a listing of the files within - ***************************************************************************/ -int BrowserLoadSz() -{ - char filepath[MAXPATHLEN]; - memset(filepath, 0, MAXPATHLEN); - - // we'll store the 7z filepath for extraction later - if(!MakeFilePath(szpath, FILE_ROM)) - return 0; - - int szfiles = SzParse(szpath); - if(szfiles) - { - browser.numEntries = szfiles; - inSz = true; - } - else - ErrorPrompt("Error opening archive!"); - - return szfiles; -} - -/**************************************************************************** - * BrowserLoadFile - * - * Loads the selected ROM - ***************************************************************************/ -int BrowserLoadFile() -{ - int device; - - if(!FindDevice(browser.dir, &device)) - return 0; - - // store the filename (w/o ext) - used for sram/freeze naming - StripExt(ROMFilename, browserList[browser.selIndex].filename); - strcpy(loadedFile, browserList[browser.selIndex].filename); - - loadingFile = true; - ROMLoaded = LoadVBAROM(); - loadingFile = false; - - if (!ROMLoaded) - { - if(inSz) - { - browser.selIndex = 0; - BrowserChangeFolder(); - } - ErrorPrompt("Error loading game!"); - } - else - { - if (GCSettings.AutoLoad == 1) - LoadBatteryOrStateAuto(FILE_SRAM, SILENT); - else if (GCSettings.AutoLoad == 2) - LoadBatteryOrStateAuto(FILE_SNAPSHOT, SILENT); - - ResetBrowser(); - } - CancelAction(); - return ROMLoaded; -} - -/**************************************************************************** - * BrowserChangeFolder - * - * Update current directory and set new entry list if directory has changed - ***************************************************************************/ -int BrowserChangeFolder() -{ - int device = 0; - FindDevice(browser.dir, &device); - - if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave - { - inSz = false; - SzClose(); - } - - if(!UpdateDirName()) - return -1; - - HaltParseThread(); // halt parsing - CleanupPath(browser.dir); - ResetBrowser(); // reset browser - - if(browser.dir[0] != 0) - ParseDirectory(); - - if(browser.numEntries == 0) - { - browser.dir[0] = 0; - int i=0; - -#ifdef HW_RVL - AddBrowserEntry(); - sprintf(browserList[i].filename, "sd:/"); - sprintf(browserList[i].displayname, "SD Card"); - browserList[i].length = 0; - browserList[i].isdir = 1; - browserList[i].icon = ICON_SD; - i++; - - AddBrowserEntry(); - sprintf(browserList[i].filename, "usb:/"); - sprintf(browserList[i].displayname, "USB Mass Storage"); - browserList[i].length = 0; - browserList[i].isdir = 1; - browserList[i].icon = ICON_USB; - i++; -#else - AddBrowserEntry(); - sprintf(browserList[i].filename, "carda:/"); - sprintf(browserList[i].displayname, "SD Gecko Slot A"); - browserList[i].length = 0; - browserList[i].isdir = 1; - browserList[i].icon = ICON_SD; - i++; - - AddBrowserEntry(); - sprintf(browserList[i].filename, "cardb:/"); - sprintf(browserList[i].displayname, "SD Gecko Slot B"); - browserList[i].length = 0; - browserList[i].isdir = 1; - browserList[i].icon = ICON_SD; - i++; -#endif - AddBrowserEntry(); - sprintf(browserList[i].filename, "smb:/"); - sprintf(browserList[i].displayname, "Network Share"); - browserList[i].length = 0; - browserList[i].isdir = 1; - browserList[i].icon = ICON_SMB; - i++; - - AddBrowserEntry(); - sprintf(browserList[i].filename, "dvd:/"); - sprintf(browserList[i].displayname, "Data DVD"); - browserList[i].length = 0; - browserList[i].isdir = 1; - browserList[i].icon = ICON_DVD; - i++; - - browser.numEntries += i; - } - - if(browser.dir[0] == 0) - { - GCSettings.LoadFolder[0] = 0; - GCSettings.LoadMethod = 0; - } - else - { - char * path = StripDevice(browser.dir); - if(path != NULL) - strcpy(GCSettings.LoadFolder, path); - FindDevice(browser.dir, &GCSettings.LoadMethod); - } - - return browser.numEntries; -} - -/**************************************************************************** - * OpenROM - * Displays a list of ROMS on load device - ***************************************************************************/ -int -OpenGameList () -{ - int device = GCSettings.LoadMethod; - - if(device == DEVICE_AUTO && strlen(GCSettings.LoadFolder) > 0) - device = autoLoadMethod(); - - // change current dir to roms directory - if(device > 0) - sprintf(browser.dir, "%s%s/", pathPrefix[device], GCSettings.LoadFolder); - else - browser.dir[0] = 0; - - BrowserChangeFolder(); - return browser.numEntries; -} +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * filebrowser.cpp + * + * Generic file routines - reading, writing, browsing + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HW_RVL +#include +#endif + +#include "vbagx.h" +#include "vbasupport.h" +#include "vmmem.h" +#include "filebrowser.h" +#include "menu.h" +#include "video.h" +#include "networkop.h" +#include "fileop.h" +#include "input.h" +#include "gcunzip.h" + +BROWSERINFO browser; +BROWSERENTRY * browserList = NULL; // list of files/folders in browser + +char szpath[MAXPATHLEN]; +char szname[MAXPATHLEN]; +bool inSz = false; + +char ROMFilename[512]; +bool ROMLoaded = false; +bool loadingFile = false; + +/**************************************************************************** +* autoLoadMethod() +* Auto-determines and sets the load device +* Returns device set +****************************************************************************/ +int autoLoadMethod() +{ + ShowAction ("Attempting to determine load device..."); + + int device = DEVICE_AUTO; + + if(ChangeInterface(DEVICE_SD, SILENT)) + device = DEVICE_SD; + else if(ChangeInterface(DEVICE_USB, SILENT)) + device = DEVICE_USB; + else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT)) + device = DEVICE_SD_SLOTA; + else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT)) + device = DEVICE_SD_SLOTB; + else if(ChangeInterface(DEVICE_DVD, SILENT)) + device = DEVICE_DVD; + else if(ChangeInterface(DEVICE_SMB, SILENT)) + device = DEVICE_SMB; + else + ErrorPrompt("Unable to locate a load device!"); + + if(GCSettings.LoadMethod == DEVICE_AUTO) + GCSettings.LoadMethod = device; // save device found for later use + CancelAction(); + return device; +} + +/**************************************************************************** +* autoSaveMethod() +* Auto-determines and sets the save device +* Returns device set +****************************************************************************/ +int autoSaveMethod(bool silent) +{ + if(!silent) + ShowAction ("Attempting to determine save device..."); + + int device = DEVICE_AUTO; + + if(ChangeInterface(DEVICE_SD, SILENT)) + device = DEVICE_SD; + else if(ChangeInterface(DEVICE_USB, SILENT)) + device = DEVICE_USB; + else if(ChangeInterface(DEVICE_SD_SLOTA, SILENT)) + device = DEVICE_SD_SLOTA; + else if(ChangeInterface(DEVICE_SD_SLOTB, SILENT)) + device = DEVICE_SD_SLOTB; + else if(ChangeInterface(DEVICE_SMB, SILENT)) + device = DEVICE_SMB; + else if(!silent) + ErrorPrompt("Unable to locate a save device!"); + + if(GCSettings.SaveMethod == DEVICE_AUTO) + GCSettings.SaveMethod = device; // save device found for later use + + CancelAction(); + return device; +} + +/**************************************************************************** + * ResetBrowser() + * Clears the file browser memory, and allocates one initial entry + ***************************************************************************/ +void ResetBrowser() +{ + browser.numEntries = 0; + browser.selIndex = 0; + browser.pageIndex = 0; + browser.size = 0; +} + +bool AddBrowserEntry() +{ + if(browser.size >= MAX_BROWSER_SIZE) + { + ErrorPrompt("Out of memory: too many files!"); + return false; // out of space + } + + memset(&(browserList[browser.size]), 0, sizeof(BROWSERENTRY)); // clear the new entry + browser.size++; + return true; +} + +/**************************************************************************** + * CleanupPath() + * Cleans up the filepath, removing double // and replacing \ with / + ***************************************************************************/ +static void CleanupPath(char * path) +{ + if(!path || path[0] == 0) + return; + + int pathlen = strlen(path); + int j = 0; + for(int i=0; i < pathlen && i < MAXPATHLEN; i++) + { + if(path[i] == '\\') + path[i] = '/'; + + if(j == 0 || !(path[j-1] == '/' && path[i] == '/')) + path[j++] = path[i]; + } + path[j] = 0; +} + +bool IsDeviceRoot(char * path) +{ + if(path == NULL || path[0] == 0) + return false; + + if( strcmp(path, "sd:/") == 0 || + strcmp(path, "usb:/") == 0 || + strcmp(path, "dvd:/") == 0 || + strcmp(path, "smb:/") == 0 || + strcmp(path, "carda:/") == 0 || + strcmp(path, "cardb:/") == 0) + { + return true; + } + return false; +} + +/**************************************************************************** + * UpdateDirName() + * Update curent directory name for file browser + ***************************************************************************/ +int UpdateDirName() +{ + int size=0; + char * test; + char temp[1024]; + int device = 0; + + if(browser.numEntries == 0) + return 1; + + FindDevice(browser.dir, &device); + + /* current directory doesn't change */ + if (strcmp(browserList[browser.selIndex].filename,".") == 0) + { + return 0; + } + /* go up to parent directory */ + else if (strcmp(browserList[browser.selIndex].filename,"..") == 0) + { + // already at the top level + if(IsDeviceRoot(browser.dir)) + { + browser.dir[0] = 0; // remove device - we are going to the device listing screen + } + else + { + /* determine last subdirectory namelength */ + sprintf(temp,"%s",browser.dir); + test = strtok(temp,"/"); + while (test != NULL) + { + size = strlen(test); + test = strtok(NULL,"/"); + } + + /* remove last subdirectory name */ + 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; + } + + return 1; + } + /* Open a directory */ + else + { + /* test new directory namelength */ + if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) < MAXPATHLEN) + { + /* update current directory name */ + sprintf(browser.dir, "%s%s/",browser.dir, browserList[browser.selIndex].filename); + return 1; + } + else + { + ErrorPrompt("Directory name is too long!"); + return -1; + } + } +} + +bool MakeFilePath(char filepath[], int type, char * filename, int filenum) +{ + char file[512]; + char folder[1024]; + char ext[4]; + char temppath[MAXPATHLEN]; + + if(type == FILE_ROM) + { + // Check path length + if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN) + { + ErrorPrompt("Maximum filepath length reached!"); + filepath[0] = 0; + return false; + } + else + { + 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 + { + if(GCSettings.SaveMethod == DEVICE_AUTO) + GCSettings.SaveMethod = autoSaveMethod(SILENT); + + if(GCSettings.SaveMethod == DEVICE_AUTO) + return false; + + switch(type) + { + case FILE_SRAM: + case FILE_SNAPSHOT: + sprintf(folder, GCSettings.SaveFolder); + + if(type == FILE_SRAM) sprintf(ext, "sav"); + else sprintf(ext, "sgm"); + + if(filenum >= -1) + { + if(filenum == -1) + sprintf(file, "%s.%s", filename, ext); + else if(filenum == 0) + if (GCSettings.AppendAuto <= 0) + { + sprintf(file, "%s.%s", filename, ext); + } + else + { + sprintf(file, "%s Auto.%s", filename, ext); + } + else + sprintf(file, "%s %i.%s", filename, filenum, ext); + } + else + { + sprintf(file, "%s", filename); + } + break; + } + sprintf (temppath, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], folder, file); + } + CleanupPath(temppath); // cleanup path + snprintf(filepath, MAXPATHLEN, "%s", temppath); + return true; +} + +/**************************************************************************** + * FileSortCallback + * + * Quick sort callback to sort file entries with the following order: + * . + * .. + * + * + ***************************************************************************/ +int FileSortCallback(const void *f1, const void *f2) +{ + /* Special case for implicit directories */ + if(((BROWSERENTRY *)f1)->filename[0] == '.' || ((BROWSERENTRY *)f2)->filename[0] == '.') + { + if(strcmp(((BROWSERENTRY *)f1)->filename, ".") == 0) { return -1; } + if(strcmp(((BROWSERENTRY *)f2)->filename, ".") == 0) { return 1; } + if(strcmp(((BROWSERENTRY *)f1)->filename, "..") == 0) { return -1; } + if(strcmp(((BROWSERENTRY *)f2)->filename, "..") == 0) { return 1; } + } + + /* If one is a file and one is a directory the directory is first. */ + if(((BROWSERENTRY *)f1)->isdir && !(((BROWSERENTRY *)f2)->isdir)) return -1; + if(!(((BROWSERENTRY *)f1)->isdir) && ((BROWSERENTRY *)f2)->isdir) return 1; + + return stricmp(((BROWSERENTRY *)f1)->filename, ((BROWSERENTRY *)f2)->filename); +} + +/**************************************************************************** + * IsSz + * + * Checks if the specified file is a 7z + ***************************************************************************/ +bool IsSz() +{ + if (strlen(browserList[browser.selIndex].filename) > 4) + { + char * p = strrchr(browserList[browser.selIndex].filename, '.'); + + if (p != NULL) + if(stricmp(p, ".7z") == 0) + return true; + } + return false; +} + +/**************************************************************************** + * StripExt + * + * Strips an extension from a filename + ***************************************************************************/ +void StripExt(char* returnstring, const char * inputstring) +{ + char* loc_dot; + + snprintf(returnstring, MAXJOLIET, "%s", inputstring); + + if(inputstring == NULL || strlen(inputstring) < 4) + return; + + loc_dot = strrchr(returnstring,'.'); + if (loc_dot != NULL) + *loc_dot = 0; // strip file extension +} + +// Shorten a ROM filename by removing the extension, URLs, id numbers and other rubbish +void ShortenFilename(char * returnstring, char * inputstring) +{ + if (!inputstring) { + returnstring[0] = '\0'; + return; + } + // skip URLs in brackets + char * dotcom = (char *) strstr(inputstring, ".com)"); + char * url = NULL; + if (dotcom) { + url = (char *) strchr(inputstring, '('); + if (url >= dotcom) { + url = NULL; + dotcom = NULL; + } else dotcom+= 5; // point to after ')' + } + // skip URLs not in brackets + if (!dotcom) { + dotcom = (char *) strstr(inputstring, ".com"); + url = NULL; + if (dotcom) { + url = (char *) strstr(inputstring, "www"); + if (url >= dotcom) { + url = NULL; + dotcom = NULL; + } else dotcom+= 4; // point to after ')' + } + } + // skip file extension + char * loc_dot = (char *)strrchr(inputstring,'.'); + char * s = (char *)inputstring; + char * r = (char *)returnstring; + // skip initial whitespace, numbers, - and _ ... + while ((*s!='\0' && *s<=' ') || *s=='-' || *s=='_' || *s=='+') s++; + // ... except those that SHOULD begin with numbers + if (strncmp(s,"3D",2)==0) for (int i=0; i<2; i++, r++, s++) *r=*s; + if (strncmp(s,"1st",3)==0 || strncmp(s,"2nd",3)==0 || strncmp(s,"3rd",3)==0 || strncmp(s,"4th",3)==0) for (int i=0; i<3; i++, r++, s++) *r=*s; + if (strncmp(s,"199",3)==0 || strncmp(s,"007",3)==0 || strncmp(s,"4x4",3)==0 || strncmp(s,"720",3)==0 || strncmp(s,"10 ",3)==0) for (int i=0; i<3; i++, r++, s++) *r=*s; + if (strncmp(s,"102 ",4)==0 || strncmp(s,"1942",4)==0 || strncmp(s,"3 Ch",4)==0) for (int i=0; i<4; i++, r++, s++) *r=*s; + if (strncmp(s,"2 in 1",6)==0 || strncmp(s,"3 in 1",6)==0 || strncmp(s,"4 in 1",6)==0) for (int i=0; i<6; i++, r++, s++) *r=*s; + if (strncmp(s,"2-in-1",6)==0 || strncmp(s,"3-in-1",6)==0 || strncmp(s,"4-in-1",6)==0) for (int i=0; i<6; i++, r++, s++) *r=*s; + while (*s>='0' && *s<='9') s++; + if (r==(char *)returnstring) while ((*s!='\0' && *s<=' ') || *s=='-' || *s=='_' || *s=='+') s++; + // now go through rest of string until we get to the end or the extension + while (*s!='\0' && (loc_dot==NULL || s'\0' && *s<=' ') || *s=='-' || *s=='_') s++; + while (*s>='0' && *s<='9') s++; + while ((*s>'\0' && *s<=' ') || *s=='-' || *s=='_') s++; + } + // skip all but 1 '-', '_' or space in a row + char c = s[0]; + if (c==s[1] && (c=='-' || c=='_' || c==' ')) s++; + // skip space before hyphen + if (*s==' ' && s[1]=='-') s++; + // copy character to result + if (*s=='_') *r=' '; + else *r = *s; + // skip spaces after hyphen + if (*s=='-') while (s[1]==' ') s++; + s++; r++; + } + *r = '\0'; + // if the result is too short, abandon what we did and just strip the ext instead + if (strlen(returnstring) <= 4) StripExt(returnstring, inputstring); +} + +/**************************************************************************** + * BrowserLoadSz + * + * Opens the selected 7z file, and parses a listing of the files within + ***************************************************************************/ +int BrowserLoadSz() +{ + memset(szpath, 0, MAXPATHLEN); + strncpy(szpath, browser.dir, strlen(browser.dir) - 1); + + strncpy(szname, strrchr(szpath, '/') + 1, strrchr(szpath, '.') - strrchr(szpath, '/')); + *strrchr(szname, '.') = '\0'; + + int szfiles = SzParse(szpath); + if(szfiles) + { + browser.numEntries = szfiles; + inSz = true; + } + else + ErrorPrompt("Error opening archive!"); + + return szfiles; +} + +/**************************************************************************** + * BrowserLoadFile + * + * Loads the selected ROM + ***************************************************************************/ +int BrowserLoadFile() +{ + int device; + + if(!FindDevice(browser.dir, &device)) + return 0; + + // store the filename (w/o ext) - used for sram/freeze naming + StripExt(ROMFilename, browserList[browser.selIndex].filename); + snprintf(GCSettings.LastFileLoaded, MAXPATHLEN, "%s", browserList[browser.selIndex].filename); + + loadingFile = true; + ROMLoaded = LoadVBAROM(); + loadingFile = false; + + if (!ROMLoaded) + { + if(inSz) + { + browser.selIndex = 0; + BrowserChangeFolder(); + } + ErrorPrompt("Error loading game!"); + } + else + { + if (GCSettings.AutoLoad == 1) + LoadBatteryOrStateAuto(FILE_SRAM, SILENT); + else if (GCSettings.AutoLoad == 2) + LoadBatteryOrStateAuto(FILE_SNAPSHOT, SILENT); + + ResetBrowser(); + } + CancelAction(); + return ROMLoaded; +} + +/**************************************************************************** + * BrowserChangeFolder + * + * Update current directory and set new entry list if directory has changed + ***************************************************************************/ +int BrowserChangeFolder() +{ + int device = 0; + FindDevice(browser.dir, &device); + + if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave + { + inSz = false; + SzClose(); + } + + if(!UpdateDirName()) + return -1; + + HaltParseThread(); + CleanupPath(browser.dir); + ResetBrowser(); + + if(browser.dir[0] != 0) + { + if(strstr(browser.dir, ".7z")) + { + BrowserLoadSz(); + } + else + { + ParseDirectory(true, true); + } + FindAndSelectLastLoadedFile(); + } + + if(browser.numEntries == 0) + { + browser.dir[0] = 0; + int i=0; + +#ifdef HW_RVL + AddBrowserEntry(); + sprintf(browserList[i].filename, "sd:/"); + sprintf(browserList[i].displayname, "SD Card"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SD; + i++; + + AddBrowserEntry(); + sprintf(browserList[i].filename, "usb:/"); + sprintf(browserList[i].displayname, "USB Mass Storage"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_USB; + i++; +#else + AddBrowserEntry(); + sprintf(browserList[i].filename, "carda:/"); + sprintf(browserList[i].displayname, "SD Gecko Slot A"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SD; + i++; + + AddBrowserEntry(); + sprintf(browserList[i].filename, "cardb:/"); + sprintf(browserList[i].displayname, "SD Gecko Slot B"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SD; + i++; +#endif + AddBrowserEntry(); + sprintf(browserList[i].filename, "smb:/"); + sprintf(browserList[i].displayname, "Network Share"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_SMB; + i++; + + AddBrowserEntry(); + sprintf(browserList[i].filename, "dvd:/"); + sprintf(browserList[i].displayname, "Data DVD"); + browserList[i].length = 0; + browserList[i].isdir = 1; + browserList[i].icon = ICON_DVD; + i++; + + browser.numEntries += i; + } + + if(browser.dir[0] == 0) + { + GCSettings.LoadFolder[0] = 0; + GCSettings.LoadMethod = 0; + } + else + { + char * path = StripDevice(browser.dir); + if(path != NULL) + strcpy(GCSettings.LoadFolder, path); + FindDevice(browser.dir, &GCSettings.LoadMethod); + } + + return browser.numEntries; +} + +/**************************************************************************** + * OpenROM + * Displays a list of ROMS on load device + ***************************************************************************/ +int +OpenGameList () +{ + int device = GCSettings.LoadMethod; + + if(device == DEVICE_AUTO && strlen(GCSettings.LoadFolder) > 0) + device = autoLoadMethod(); + + // change current dir to roms directory + if(device > 0) + sprintf(browser.dir, "%s%s/", pathPrefix[device], GCSettings.LoadFolder); + else + browser.dir[0] = 0; + + BrowserChangeFolder(); + return browser.numEntries; +} diff --git a/source/filebrowser.h b/source/filebrowser.h index 7d73b98..2b050f7 100644 --- a/source/filebrowser.h +++ b/source/filebrowser.h @@ -1,76 +1,77 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * filebrowser.h - * - * Generic file routines - reading, writing, browsing - ****************************************************************************/ - -#ifndef _FILEBROWSER_H_ -#define _FILEBROWSER_H_ - -#include -#include - -#define MAXJOLIET 255 -#ifdef HW_DOL -#define MAX_BROWSER_SIZE 1000 -#else -#define MAX_BROWSER_SIZE 3000 -#endif - -typedef struct -{ - char dir[MAXPATHLEN + 1]; // directory path of browserList - int numEntries; // # of entries in browserList - int selIndex; // currently selected index of browserList - int pageIndex; // starting index of browserList page display - int size; // # of entries browerList has space allocated to store -} BROWSERINFO; - -typedef struct -{ - size_t length; // file length - int isdir; // 0 - file, 1 - directory - char filename[MAXJOLIET + 1]; // full filename - char displayname[MAXJOLIET + 1]; // name for browser display - int filenum; // file # (for 7z support) - int icon; // icon to display -} BROWSERENTRY; - -extern BROWSERINFO browser; -extern BROWSERENTRY * browserList; -extern char ROMFilename[512]; -extern bool ROMLoaded; -extern bool loadingFile; -extern char szpath[MAXPATHLEN]; -extern bool inSz; - -enum -{ - ICON_NONE, - ICON_FOLDER, - ICON_SD, - ICON_USB, - ICON_DVD, - ICON_SMB -}; - -bool MakeFilePath(char filepath[], int type, char * filename = NULL, int filenum = -2); -int UpdateDirName(); -int OpenGameList(); -int autoLoadMethod(); -int autoSaveMethod(bool silent); -int FileSortCallback(const void *f1, const void *f2); -void StripExt(char* returnstring, char * inputstring); -bool IsSz(); -void ResetBrowser(); -bool AddBrowserEntry(); -bool IsDeviceRoot(char * path); -int BrowserLoadSz(); -int BrowserChangeFolder(); -int BrowserLoadFile(); - -#endif +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * filebrowser.h + * + * Generic file routines - reading, writing, browsing + ****************************************************************************/ + +#ifndef _FILEBROWSER_H_ +#define _FILEBROWSER_H_ + +#include +#include + +#define MAXJOLIET 255 +#ifdef HW_DOL +#define MAX_BROWSER_SIZE 1000 +#else +#define MAX_BROWSER_SIZE 3000 +#endif + +typedef struct +{ + char dir[MAXPATHLEN + 1]; // directory path of browserList + int numEntries; // # of entries in browserList + int selIndex; // currently selected index of browserList + int pageIndex; // starting index of browserList page display + int size; // # of entries browerList has space allocated to store +} BROWSERINFO; + +typedef struct +{ + size_t length; // file length + int isdir; // 0 - file, 1 - directory + char filename[MAXJOLIET + 1]; // full filename + char displayname[MAXJOLIET + 1]; // name for browser display + int filenum; // file # (for 7z support) + int icon; // icon to display +} BROWSERENTRY; + +extern BROWSERINFO browser; +extern BROWSERENTRY * browserList; +extern char ROMFilename[512]; +extern bool ROMLoaded; +extern bool loadingFile; +extern char szpath[MAXPATHLEN]; +extern bool inSz; +extern char szname[MAXPATHLEN]; + +enum +{ + ICON_NONE, + ICON_FOLDER, + ICON_SD, + ICON_USB, + ICON_DVD, + ICON_SMB +}; + +bool MakeFilePath(char filepath[], int type, char * filename = NULL, int filenum = -2); +int UpdateDirName(); +int OpenGameList(); +int autoLoadMethod(); +int autoSaveMethod(bool silent); +int FileSortCallback(const void *f1, const void *f2); +void StripExt(char* returnstring, const char* inputstring); +bool IsSz(); +void ResetBrowser(); +bool AddBrowserEntry(); +bool IsDeviceRoot(char * path); +int BrowserLoadSz(); +int BrowserChangeFolder(); +int BrowserLoadFile(); + +#endif diff --git a/source/filelist.h b/source/filelist.h index f431df5..9d31a83 100644 --- a/source/filelist.h +++ b/source/filelist.h @@ -104,6 +104,8 @@ extern const u8 icon_settings_gamecube_png[]; extern const u32 icon_settings_gamecube_png_size; extern const u8 icon_settings_nunchuk_png[]; 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 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 u8 icon_settings_video_png[]; 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 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 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 u32 scrollbar_png_size; diff --git a/source/fileop.cpp b/source/fileop.cpp index aa7a0b1..f38f685 100644 --- a/source/fileop.cpp +++ b/source/fileop.cpp @@ -1,927 +1,937 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric 2008-2009 - * - * fileop.cpp - * - * File operations - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vbagx.h" -#include "vbasupport.h" -#include "fileop.h" -#include "networkop.h" -#include "gcunzip.h" -#include "menu.h" -#include "filebrowser.h" -#include "gui/gui.h" - -#define THREAD_SLEEP 100 - -unsigned char *savebuffer; -static mutex_t bufferLock = LWP_MUTEX_NULL; -FILE * file; // file pointer - the only one we should ever use! -bool unmountRequired[7] = { false, false, false, false, false, false, false }; -bool isMounted[7] = { false, false, false, false, false, false, false }; - -#ifdef HW_RVL - const DISC_INTERFACE* sd = &__io_wiisd; - const DISC_INTERFACE* usb = &__io_usbstorage; - const DISC_INTERFACE* dvd = &__io_wiidvd; -#else - const DISC_INTERFACE* carda = &__io_gcsda; - const DISC_INTERFACE* cardb = &__io_gcsdb; - const DISC_INTERFACE* dvd = &__io_gcdvd; -#endif - -// folder parsing thread -static lwp_t parsethread = LWP_THREAD_NULL; -static DIR * dir = NULL; -static bool parseHalt = true; -static bool parseFilter = true; -static bool ParseDirEntries(); -int selectLoadedFile = 0; - -// device thread -static lwp_t devicethread = LWP_THREAD_NULL; -static bool deviceHalt = true; - -/**************************************************************************** - * ResumeDeviceThread - * - * Signals the device thread to start, and resumes the thread. - ***************************************************************************/ -void -ResumeDeviceThread() -{ - deviceHalt = false; - LWP_ResumeThread(devicethread); -} - -/**************************************************************************** - * HaltGui - * - * Signals the device thread to stop. - ***************************************************************************/ -void -HaltDeviceThread() -{ -#ifdef HW_RVL - deviceHalt = true; - - // wait for thread to finish - while(!LWP_ThreadIsSuspended(devicethread)) - usleep(THREAD_SLEEP); -#endif -} - -/**************************************************************************** - * HaltParseThread - * - * Signals the parse thread to stop. - ***************************************************************************/ -void -HaltParseThread() -{ - parseHalt = true; - - while(!LWP_ThreadIsSuspended(parsethread)) - usleep(THREAD_SLEEP); -} - - -/**************************************************************************** - * devicecallback - * - * This checks our devices for changes (SD/USB/DVD removed) - ***************************************************************************/ -#ifdef HW_RVL -static int devsleep; - -static void * -devicecallback (void *arg) -{ - while (1) - { - if(isMounted[DEVICE_SD]) - { - if(!sd->isInserted()) // check if the device was removed - { - unmountRequired[DEVICE_SD] = true; - isMounted[DEVICE_SD] = false; - } - } - - if(isMounted[DEVICE_USB]) - { - if(!usb->isInserted()) // check if the device was removed - { - unmountRequired[DEVICE_USB] = true; - isMounted[DEVICE_USB] = false; - } - } - - if(isMounted[DEVICE_DVD]) - { - if(!dvd->isInserted()) // check if the device was removed - { - unmountRequired[DEVICE_DVD] = true; - isMounted[DEVICE_DVD] = false; - } - } - - devsleep = 1000*1000; // 1 sec - - while(devsleep > 0) - { - if(deviceHalt) - LWP_SuspendThread(devicethread); - usleep(THREAD_SLEEP); - devsleep -= THREAD_SLEEP; - } - UpdateCheck(); - } - return NULL; -} -#endif - -static void * -parsecallback (void *arg) -{ - while(1) - { - while(ParseDirEntries()) - usleep(THREAD_SLEEP); - LWP_SuspendThread(parsethread); - } - return NULL; -} - -/**************************************************************************** - * InitDeviceThread - * - * libOGC provides a nice wrapper for LWP access. - * This function sets up a new local queue and attaches the thread to it. - ***************************************************************************/ -void -InitDeviceThread() -{ -#ifdef HW_RVL - LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40); -#endif - LWP_CreateThread (&parsethread, parsecallback, NULL, NULL, 0, 80); -} - -/**************************************************************************** - * UnmountAllFAT - * Unmounts all FAT devices - ***************************************************************************/ -void UnmountAllFAT() -{ -#ifdef HW_RVL - fatUnmount("sd:"); - fatUnmount("usb:"); -#else - fatUnmount("carda:"); - fatUnmount("cardb:"); -#endif -} - -/**************************************************************************** - * MountFAT - * Checks if the device needs to be (re)mounted - * If so, unmounts the device - * Attempts to mount the device specified - * Sets libfat to use the device by default - ***************************************************************************/ - -static bool MountFAT(int device, int silent) -{ - bool mounted = false; - int retry = 1; - char name[10], name2[10]; - const DISC_INTERFACE* disc = NULL; - - switch(device) - { -#ifdef HW_RVL - case DEVICE_SD: - sprintf(name, "sd"); - sprintf(name2, "sd:"); - disc = sd; - break; - case DEVICE_USB: - sprintf(name, "usb"); - sprintf(name2, "usb:"); - disc = usb; - break; -#else - case DEVICE_SD_SLOTA: - sprintf(name, "carda"); - sprintf(name2, "carda:"); - disc = carda; - break; - - case DEVICE_SD_SLOTB: - sprintf(name, "cardb"); - sprintf(name2, "cardb:"); - disc = cardb; - break; -#endif - default: - return false; // unknown device - } - - if(unmountRequired[device]) - { - unmountRequired[device] = false; - fatUnmount(name2); - disc->shutdown(); - isMounted[device] = false; - } - - while(retry) - { - if(disc->startup() && fatMountSimple(name, disc)) - mounted = true; - - if(mounted || silent) - break; - -#ifdef HW_RVL - if(device == DEVICE_SD) - retry = ErrorPromptRetry("SD card not found!"); - else - retry = ErrorPromptRetry("USB drive not found!"); -#else - retry = ErrorPromptRetry("SD card not found!"); -#endif - } - - isMounted[device] = mounted; - return mounted; -} - -void MountAllFAT() -{ -#ifdef HW_RVL - MountFAT(DEVICE_SD, SILENT); - MountFAT(DEVICE_USB, SILENT); -#else - MountFAT(DEVICE_SD_SLOTA, SILENT); - MountFAT(DEVICE_SD_SLOTB, SILENT); -#endif -} - -/**************************************************************************** - * MountDVD() - * - * Tests if a ISO9660 DVD is inserted and available, and mounts it - ***************************************************************************/ -bool MountDVD(bool silent) -{ - bool mounted = false; - int retry = 1; - - if(unmountRequired[DEVICE_DVD]) - { - unmountRequired[DEVICE_DVD] = false; - ISO9660_Unmount("dvd:"); - } - - while(retry) - { - ShowAction("Loading DVD..."); - - if(!dvd->isInserted()) - { - if(silent) - break; - - retry = ErrorPromptRetry("No disc inserted!"); - } - else if(!ISO9660_Mount("dvd", dvd)) - { - if(silent) - break; - - retry = ErrorPromptRetry("Unrecognized DVD format."); - } - else - { - mounted = true; - break; - } - } - CancelAction(); - isMounted[DEVICE_DVD] = mounted; - return mounted; -} - -bool FindDevice(char * filepath, int * device) -{ - if(!filepath || filepath[0] == 0) - return false; - - if(strncmp(filepath, "sd:", 3) == 0) - { - *device = DEVICE_SD; - return true; - } - else if(strncmp(filepath, "usb:", 4) == 0) - { - *device = DEVICE_USB; - return true; - } - else if(strncmp(filepath, "smb:", 4) == 0) - { - *device = DEVICE_SMB; - return true; - } - else if(strncmp(filepath, "carda:", 6) == 0) - { - *device = DEVICE_SD_SLOTA; - return true; - } - else if(strncmp(filepath, "cardb:", 6) == 0) - { - *device = DEVICE_SD_SLOTB; - return true; - } - else if(strncmp(filepath, "dvd:", 4) == 0) - { - *device = DEVICE_DVD; - return true; - } - return false; -} - -char * StripDevice(char * path) -{ - if(path == NULL) - return NULL; - - char * newpath = strchr(path,'/'); - - if(newpath != NULL) - newpath++; - - return newpath; -} - -/**************************************************************************** - * ChangeInterface - * Attempts to mount/configure the device specified - ***************************************************************************/ -bool ChangeInterface(int device, bool silent) -{ - if(isMounted[device]) - return true; - - bool mounted = false; - - switch(device) - { -#ifdef HW_RVL - case DEVICE_SD: - case DEVICE_USB: -#else - case DEVICE_SD_SLOTA: - case DEVICE_SD_SLOTB: -#endif - mounted = MountFAT(device, silent); - break; - case DEVICE_DVD: - mounted = MountDVD(silent); - break; - case DEVICE_SMB: - mounted = ConnectShare(silent); - break; - } - - return mounted; -} - -bool ChangeInterface(char * filepath, bool silent) -{ - int device = -1; - - if(!FindDevice(filepath, &device)) - return false; - - return ChangeInterface(device, silent); -} - -void CreateAppPath(char * origpath) -{ - if(!origpath || origpath[0] == 0) - return; - - char * path = strdup(origpath); // make a copy so we don't mess up original - - if(!path) - return; - - char * loc = strrchr(path,'/'); - if (loc != NULL) - *loc = 0; // strip file name - - int pos = 0; - - // replace fat:/ with sd:/ - if(strncmp(path, "fat:/", 5) == 0) - { - pos++; - path[1] = 's'; - path[2] = 'd'; - } - if(ChangeInterface(&path[pos], SILENT)) - snprintf(appPath, MAXPATHLEN-1, "%s", &path[pos]); - - free(path); -} - -static char *GetExt(char *file) -{ - if(!file) - return NULL; - - char *ext = strrchr(file,'.'); - if(ext != NULL) - { - ext++; - int extlen = strlen(ext); - if(extlen > 5) - return NULL; - } - return ext; -} - -bool GetFileSize(int i) -{ - if(browserList[i].length > 0) - return true; - - struct stat filestat; - char path[MAXPATHLEN+1]; - snprintf(path, MAXPATHLEN, "%s%s", browser.dir, browserList[i].filename); - - if(stat(path, &filestat) < 0) - return false; - - browserList[i].length = filestat.st_size; - return true; -} - -static bool ParseDirEntries() -{ - if(!dir) - return false; - - char *ext; - struct dirent *entry = NULL; - int isdir; - - int i = 0; - - while(i < 20 && !parseHalt) - { - entry = readdir(dir); - - if(entry == NULL) - break; - - if(entry->d_name[0] == '.' && entry->d_name[1] != '.') - continue; - - if(strcmp(entry->d_name, "..") == 0) - { - isdir = 1; - } - else - { - if(entry->d_type==DT_DIR) - isdir = 1; - else - isdir = 0; - - // don't show the file if it's not a valid ROM - if(parseFilter && !isdir) - { - ext = GetExt(entry->d_name); - - if(ext == NULL) - continue; - - if( stricmp(ext, "agb") != 0 && stricmp(ext, "gba") != 0 && - stricmp(ext, "bin") != 0 && stricmp(ext, "elf") != 0 && - stricmp(ext, "mb") != 0 && stricmp(ext, "dmg") != 0 && - stricmp(ext, "gb") != 0 && stricmp(ext, "gbc") != 0 && - stricmp(ext, "cgb") != 0 && stricmp(ext, "sgb") != 0 && - stricmp(ext, "zip") != 0 && stricmp(ext, "7z") != 0) - continue; - } - } - - if(!AddBrowserEntry()) - { - parseHalt = true; - break; - } - - snprintf(browserList[browser.numEntries+i].filename, MAXJOLIET, "%s", entry->d_name); - browserList[browser.numEntries+i].isdir = isdir; // flag this as a dir - - if(isdir) - { - if(strcmp(entry->d_name, "..") == 0) - sprintf(browserList[browser.numEntries+i].displayname, "Up One Level"); - else - snprintf(browserList[browser.numEntries+i].displayname, MAXJOLIET, "%s", browserList[browser.numEntries+i].filename); - browserList[browser.numEntries+i].icon = ICON_FOLDER; - } - else - { - StripExt(browserList[browser.numEntries+i].displayname, browserList[browser.numEntries+i].filename); // hide file extension - } - i++; - } - - if(!parseHalt) - { - // Sort the file list - if(i >= 0) - qsort(browserList, browser.numEntries+i, sizeof(BROWSERENTRY), FileSortCallback); - - browser.numEntries += i; - } - - if(entry == NULL || parseHalt) - { - closedir(dir); // close directory - 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 true; // more entries -} - -/*************************************************************************** - * Browse subdirectories - **************************************************************************/ -int -ParseDirectory(bool waitParse, bool filter) -{ - int retry = 1; - bool mounted = false; - parseFilter = filter; - - ResetBrowser(); // reset browser - - // add trailing slash - if(browser.dir[strlen(browser.dir)-1] != '/') - strcat(browser.dir, "/"); - - // open the directory - while(dir == NULL && retry == 1) - { - mounted = ChangeInterface(browser.dir, NOTSILENT); - - if(mounted) - dir = opendir(browser.dir); - else - return -1; - - if(dir == NULL) - retry = ErrorPromptRetry("Error opening directory!"); - } - - // if we can't open the dir, try higher levels - if (dir == NULL) - { - char * devEnd = strrchr(browser.dir, '/'); - - while(!IsDeviceRoot(browser.dir)) - { - devEnd[0] = 0; // strip slash - devEnd = strrchr(browser.dir, '/'); - - if(devEnd == NULL) - break; - - devEnd[1] = 0; // strip remaining file listing - dir = opendir(browser.dir); - if (dir) - break; - } - } - - if(dir == NULL) - return -1; - - if(IsDeviceRoot(browser.dir)) - { - AddBrowserEntry(); - sprintf(browserList[0].filename, ".."); - sprintf(browserList[0].displayname, "Up One Level"); - browserList[0].length = 0; - browserList[0].isdir = 1; // flag this as a dir - browserList[0].icon = ICON_FOLDER; - browser.numEntries++; - } - - parseHalt = false; - ParseDirEntries(); // index first 20 entries - - LWP_ResumeThread(parsethread); // index remaining entries - - if(waitParse) // wait for complete parsing - { - ShowAction("Loading..."); - - while(!LWP_ThreadIsSuspended(parsethread)) - usleep(THREAD_SLEEP); - - CancelAction(); - } - - return browser.numEntries; -} - -/**************************************************************************** - * AllocSaveBuffer () - * Clear and allocate the savebuffer - ***************************************************************************/ -void -AllocSaveBuffer () -{ - if(bufferLock == LWP_MUTEX_NULL) - LWP_MutexInit(&bufferLock, false); - - if(bufferLock != LWP_MUTEX_NULL) - LWP_MutexLock(bufferLock); - memset (savebuffer, 0, SAVEBUFFERSIZE); -} - -/**************************************************************************** - * FreeSaveBuffer () - * Free the savebuffer memory - ***************************************************************************/ -void -FreeSaveBuffer () -{ - if(bufferLock != LWP_MUTEX_NULL) - LWP_MutexUnlock(bufferLock); -} - -/**************************************************************************** - * LoadSzFile - * Loads the selected file # from the specified 7z into rbuffer - * Returns file size - ***************************************************************************/ -size_t -LoadSzFile(char * filepath, unsigned char * rbuffer) -{ - size_t size = 0; - - // stop checking if devices were removed/inserted - // since we're loading a file - HaltDeviceThread(); - - // halt parsing - HaltParseThread(); - - file = fopen (filepath, "rb"); - if (file > 0) - { - size = SzExtractFile(browserList[browser.selIndex].filenum, rbuffer); - fclose (file); - } - else - { - ErrorPrompt("Error opening file!"); - } - - // go back to checking if devices were inserted/removed - ResumeDeviceThread(); - - return size; -} - -/**************************************************************************** - * LoadFile - ***************************************************************************/ -size_t -LoadFile (char * rbuffer, char *filepath, size_t length, bool silent) -{ - char zipbuffer[2048]; - size_t size = 0, offset = 0, readsize = 0; - int retry = 1; - int device; - - if(!FindDevice(filepath, &device)) - return 0; - - // stop checking if devices were removed/inserted - // since we're loading a file - HaltDeviceThread(); - - // halt parsing - HaltParseThread(); - - // open the file - while(retry) - { - if(!ChangeInterface(device, silent)) - break; - - file = fopen (filepath, "rb"); - - if(!file) - { - if(silent) - break; - - retry = ErrorPromptRetry("Error opening file!"); - continue; - } - - if(length > 0 && length <= 2048) // do a partial read (eg: to check file header) - { - size = fread (rbuffer, 1, length, file); - } - else // load whole file - { - readsize = fread (zipbuffer, 1, 32, file); - - if(!readsize) - { - unmountRequired[device] = true; - retry = ErrorPromptRetry("Error reading file!"); - fclose (file); - continue; - } - - if (IsZipFile (zipbuffer)) - { - size = UnZipBuffer ((unsigned char *)rbuffer); // unzip - } - else - { - fseeko(file,0,SEEK_END); - size = ftello(file); - fseeko(file,0,SEEK_SET); - - while(!feof(file)) - { - ShowProgress ("Loading...", offset, size); - readsize = fread (rbuffer + offset, 1, 4096, file); // read in next chunk - - if(readsize <= 0) - break; // reading finished (or failed) - - offset += readsize; - } - size = offset; - CancelAction(); - } - } - retry = 0; - fclose (file); - } - - // go back to checking if devices were inserted/removed - ResumeDeviceThread(); - CancelAction(); - return size; -} - -size_t LoadFile(char * filepath, bool silent) -{ - return LoadFile((char *)savebuffer, filepath, 0, silent); -} - -/**************************************************************************** - * SaveFile - * Write buffer to file - ***************************************************************************/ -size_t -SaveFile (char * buffer, char *filepath, size_t datasize, bool silent) -{ - size_t written = 0; - size_t writesize, nextwrite; - int retry = 1; - int device; - - if(!FindDevice(filepath, &device)) - return 0; - - if(datasize == 0) - return 0; - - // stop checking if devices were removed/inserted - // since we're saving a file - HaltDeviceThread(); - - // halt parsing - HaltParseThread(); - - ShowAction("Saving..."); - - while(!written && retry == 1) - { - if(!ChangeInterface(device, silent)) - break; - - file = fopen (filepath, "wb"); - - if(!file) - { - if(silent) - break; - - retry = ErrorPromptRetry("Error creating file!"); - continue; - } - - while(written < datasize) - { - if(datasize - written > 4096) nextwrite=4096; - else nextwrite = datasize-written; - writesize = fwrite (buffer+written, 1, nextwrite, file); - if(writesize != nextwrite) break; // write failure - written += writesize; - } - fclose (file); - - if(written != datasize) written = 0; - - if(!written) - { - unmountRequired[device] = true; - if(silent) break; - retry = ErrorPromptRetry("Error saving file!"); - } - } - - // go back to checking if devices were inserted/removed - ResumeDeviceThread(); - - CancelAction(); - return written; -} - -size_t SaveFile(char * filepath, size_t datasize, bool silent) -{ - return SaveFile((char *)savebuffer, filepath, datasize, silent); -} +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric 2008-2009 + * + * fileop.cpp + * + * File operations + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vbagx.h" +#include "vbasupport.h" +#include "fileop.h" +#include "networkop.h" +#include "gcunzip.h" +#include "menu.h" +#include "filebrowser.h" +#include "gui/gui.h" + +#define THREAD_SLEEP 100 + +unsigned char *savebuffer; +static mutex_t bufferLock = LWP_MUTEX_NULL; +FILE * file; // file pointer - the only one we should ever use! +bool unmountRequired[7] = { false, false, false, false, false, false, false }; +bool isMounted[7] = { false, false, false, false, false, false, false }; + +#ifdef HW_RVL + const DISC_INTERFACE* sd = &__io_wiisd; + const DISC_INTERFACE* usb = &__io_usbstorage; + const DISC_INTERFACE* dvd = &__io_wiidvd; +#else + const DISC_INTERFACE* carda = &__io_gcsda; + const DISC_INTERFACE* cardb = &__io_gcsdb; + const DISC_INTERFACE* dvd = &__io_gcdvd; +#endif + +// folder parsing thread +static lwp_t parsethread = LWP_THREAD_NULL; +static DIR *dir = NULL; +static bool parseHalt = true; +static bool parseFilter = true; +static bool ParseDirEntries(); +int selectLoadedFile = 0; + +// device thread +static lwp_t devicethread = LWP_THREAD_NULL; +static bool deviceHalt = true; + +/**************************************************************************** + * ResumeDeviceThread + * + * Signals the device thread to start, and resumes the thread. + ***************************************************************************/ +void +ResumeDeviceThread() +{ + deviceHalt = false; + LWP_ResumeThread(devicethread); +} + +/**************************************************************************** + * HaltGui + * + * Signals the device thread to stop. + ***************************************************************************/ +void +HaltDeviceThread() +{ +#ifdef HW_RVL + deviceHalt = true; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(devicethread)) + usleep(THREAD_SLEEP); +#endif +} + +/**************************************************************************** + * HaltParseThread + * + * Signals the parse thread to stop. + ***************************************************************************/ +void +HaltParseThread() +{ + parseHalt = true; + + while(!LWP_ThreadIsSuspended(parsethread)) + usleep(THREAD_SLEEP); +} + + +/**************************************************************************** + * devicecallback + * + * This checks our devices for changes (SD/USB/DVD removed) + ***************************************************************************/ +#ifdef HW_RVL +static int devsleep; + +static void * +devicecallback (void *arg) +{ + while (1) + { + if(isMounted[DEVICE_SD]) + { + if(!sd->isInserted()) // check if the device was removed + { + unmountRequired[DEVICE_SD] = true; + isMounted[DEVICE_SD] = false; + } + } + + if(isMounted[DEVICE_USB]) + { + if(!usb->isInserted()) // check if the device was removed + { + unmountRequired[DEVICE_USB] = true; + isMounted[DEVICE_USB] = false; + } + } + + if(isMounted[DEVICE_DVD]) + { + if(!dvd->isInserted()) // check if the device was removed + { + unmountRequired[DEVICE_DVD] = true; + isMounted[DEVICE_DVD] = false; + } + } + + devsleep = 1000*1000; // 1 sec + + while(devsleep > 0) + { + if(deviceHalt) + LWP_SuspendThread(devicethread); + usleep(THREAD_SLEEP); + devsleep -= THREAD_SLEEP; + } + UpdateCheck(); + } + return NULL; +} +#endif + +static void * +parsecallback (void *arg) +{ + while(1) + { + while(ParseDirEntries()) + usleep(THREAD_SLEEP); + LWP_SuspendThread(parsethread); + } + return NULL; +} + +/**************************************************************************** + * InitDeviceThread + * + * libOGC provides a nice wrapper for LWP access. + * This function sets up a new local queue and attaches the thread to it. + ***************************************************************************/ +void +InitDeviceThread() +{ +#ifdef HW_RVL + LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40); +#endif + LWP_CreateThread (&parsethread, parsecallback, NULL, NULL, 0, 80); +} + +/**************************************************************************** + * UnmountAllFAT + * Unmounts all FAT devices + ***************************************************************************/ +void UnmountAllFAT() +{ +#ifdef HW_RVL + fatUnmount("sd:"); + fatUnmount("usb:"); +#else + fatUnmount("carda:"); + fatUnmount("cardb:"); +#endif +} + +/**************************************************************************** + * MountFAT + * Checks if the device needs to be (re)mounted + * If so, unmounts the device + * Attempts to mount the device specified + * Sets libfat to use the device by default + ***************************************************************************/ + +static bool MountFAT(int device, int silent) +{ + bool mounted = false; + int retry = 1; + char name[10], name2[10]; + const DISC_INTERFACE* disc = NULL; + + switch(device) + { +#ifdef HW_RVL + case DEVICE_SD: + sprintf(name, "sd"); + sprintf(name2, "sd:"); + disc = sd; + break; + case DEVICE_USB: + sprintf(name, "usb"); + sprintf(name2, "usb:"); + disc = usb; + break; +#else + case DEVICE_SD_SLOTA: + sprintf(name, "carda"); + sprintf(name2, "carda:"); + disc = carda; + break; + + case DEVICE_SD_SLOTB: + sprintf(name, "cardb"); + sprintf(name2, "cardb:"); + disc = cardb; + break; +#endif + default: + return false; // unknown device + } + + if(unmountRequired[device]) + { + unmountRequired[device] = false; + fatUnmount(name2); + disc->shutdown(); + isMounted[device] = false; + } + + while(retry) + { + if(disc->startup() && fatMountSimple(name, disc)) + mounted = true; + + if(mounted || silent) + break; + +#ifdef HW_RVL + if(device == DEVICE_SD) + retry = ErrorPromptRetry("SD card not found!"); + else + retry = ErrorPromptRetry("USB drive not found!"); +#else + retry = ErrorPromptRetry("SD card not found!"); +#endif + } + + isMounted[device] = mounted; + return mounted; +} + +void MountAllFAT() +{ +#ifdef HW_RVL + MountFAT(DEVICE_SD, SILENT); + MountFAT(DEVICE_USB, SILENT); +#else + MountFAT(DEVICE_SD_SLOTA, SILENT); + MountFAT(DEVICE_SD_SLOTB, SILENT); +#endif +} + +/**************************************************************************** + * MountDVD() + * + * Tests if a ISO9660 DVD is inserted and available, and mounts it + ***************************************************************************/ +bool MountDVD(bool silent) +{ + bool mounted = false; + int retry = 1; + + if(unmountRequired[DEVICE_DVD]) + { + unmountRequired[DEVICE_DVD] = false; + ISO9660_Unmount("dvd:"); + } + + while(retry) + { + ShowAction("Loading DVD..."); + + if(!dvd->isInserted()) + { + if(silent) + break; + + retry = ErrorPromptRetry("No disc inserted!"); + } + else if(!ISO9660_Mount("dvd", dvd)) + { + if(silent) + break; + + retry = ErrorPromptRetry("Unrecognized DVD format."); + } + else + { + mounted = true; + break; + } + } + CancelAction(); + isMounted[DEVICE_DVD] = mounted; + return mounted; +} + +bool FindDevice(char * filepath, int * device) +{ + if(!filepath || filepath[0] == 0) + return false; + + if(strncmp(filepath, "sd:", 3) == 0) + { + *device = DEVICE_SD; + return true; + } + else if(strncmp(filepath, "usb:", 4) == 0) + { + *device = DEVICE_USB; + return true; + } + else if(strncmp(filepath, "smb:", 4) == 0) + { + *device = DEVICE_SMB; + return true; + } + else if(strncmp(filepath, "carda:", 6) == 0) + { + *device = DEVICE_SD_SLOTA; + return true; + } + else if(strncmp(filepath, "cardb:", 6) == 0) + { + *device = DEVICE_SD_SLOTB; + return true; + } + else if(strncmp(filepath, "dvd:", 4) == 0) + { + *device = DEVICE_DVD; + return true; + } + return false; +} + +char * StripDevice(char * path) +{ + if(path == NULL) + return NULL; + + char * newpath = strchr(path,'/'); + + if(newpath != NULL) + newpath++; + + return newpath; +} + +/**************************************************************************** + * ChangeInterface + * Attempts to mount/configure the device specified + ***************************************************************************/ +bool ChangeInterface(int device, bool silent) +{ + if(isMounted[device]) + return true; + + bool mounted = false; + + switch(device) + { +#ifdef HW_RVL + case DEVICE_SD: + case DEVICE_USB: +#else + case DEVICE_SD_SLOTA: + case DEVICE_SD_SLOTB: +#endif + mounted = MountFAT(device, silent); + break; + case DEVICE_DVD: + mounted = MountDVD(silent); + break; + case DEVICE_SMB: + mounted = ConnectShare(silent); + break; + } + + return mounted; +} + +bool ChangeInterface(char * filepath, bool silent) +{ + int device = -1; + + if(!FindDevice(filepath, &device)) + return false; + + return ChangeInterface(device, silent); +} + +void CreateAppPath(char * origpath) +{ + if(!origpath || origpath[0] == 0) + return; + + char * path = strdup(origpath); // make a copy so we don't mess up original + + if(!path) + return; + + char * loc = strrchr(path,'/'); + if (loc != NULL) + *loc = 0; // strip file name + + int pos = 0; + + // replace fat:/ with sd:/ + if(strncmp(path, "fat:/", 5) == 0) + { + pos++; + path[1] = 's'; + path[2] = 'd'; + } + if(ChangeInterface(&path[pos], SILENT)) + snprintf(appPath, MAXPATHLEN-1, "%s", &path[pos]); + + free(path); +} + +static char *GetExt(char *file) +{ + if(!file) + return NULL; + + char *ext = strrchr(file,'.'); + if(ext != NULL) + { + ext++; + int extlen = strlen(ext); + if(extlen > 5) + return NULL; + } + return ext; +} + +bool GetFileSize(int i) +{ + if(browserList[i].length > 0) + return true; + + struct stat filestat; + char path[MAXPATHLEN+1]; + snprintf(path, MAXPATHLEN, "%s%s", browser.dir, browserList[i].filename); + + if(stat(path, &filestat) < 0) + return false; + + browserList[i].length = filestat.st_size; + 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() +{ + if(!dir) + return false; + + char *ext; + struct dirent *entry = NULL; + int isdir; + + int i = 0; + + while(i < 20 && !parseHalt) + { + entry = readdir(dir); + + if(entry == NULL) + break; + + if(entry->d_name[0] == '.' && entry->d_name[1] != '.') + continue; + + if(strcmp(entry->d_name, "..") == 0) + { + isdir = 1; + } + else + { + if(entry->d_type==DT_DIR) + isdir = 1; + else + isdir = 0; + + // don't show the file if it's not a valid ROM + if(parseFilter && !isdir) + { + ext = GetExt(entry->d_name); + + if(ext == NULL) + continue; + + if( stricmp(ext, "agb") != 0 && stricmp(ext, "gba") != 0 && + stricmp(ext, "bin") != 0 && stricmp(ext, "elf") != 0 && + stricmp(ext, "mb") != 0 && stricmp(ext, "dmg") != 0 && + stricmp(ext, "gb") != 0 && stricmp(ext, "gbc") != 0 && + stricmp(ext, "cgb") != 0 && stricmp(ext, "sgb") != 0 && + stricmp(ext, "zip") != 0 && stricmp(ext, "7z") != 0) + continue; + } + } + + if(!AddBrowserEntry()) + { + parseHalt = true; + break; + } + + snprintf(browserList[browser.numEntries+i].filename, MAXJOLIET, "%s", entry->d_name); + browserList[browser.numEntries+i].isdir = isdir; // flag this as a dir + + if(isdir) + { + if(strcmp(entry->d_name, "..") == 0) + sprintf(browserList[browser.numEntries+i].displayname, "Up One Level"); + else + snprintf(browserList[browser.numEntries+i].displayname, MAXJOLIET, "%s", browserList[browser.numEntries+i].filename); + browserList[browser.numEntries+i].icon = ICON_FOLDER; + } + else + { + StripExt(browserList[browser.numEntries+i].displayname, browserList[browser.numEntries+i].filename); // hide file extension + } + i++; + } + + if(!parseHalt) + { + // Sort the file list + if(i >= 0) + qsort(browserList, browser.numEntries+i, sizeof(BROWSERENTRY), FileSortCallback); + + browser.numEntries += i; + } + + if(entry == NULL || parseHalt) + { + closedir(dir); // close directory + dir = NULL; + + return false; // no more entries + } + return true; // more entries +} + +/*************************************************************************** + * Browse subdirectories + **************************************************************************/ +int +ParseDirectory(bool waitParse, bool filter) +{ + int retry = 1; + bool mounted = false; + parseFilter = filter; + + ResetBrowser(); // reset browser + + // add trailing slash + if(browser.dir[strlen(browser.dir)-1] != '/') + strcat(browser.dir, "/"); + + // open the directory + while(dir == NULL && retry == 1) + { + mounted = ChangeInterface(browser.dir, NOTSILENT); + + if(mounted) + dir = opendir(browser.dir); + else + return -1; + + if(dir == NULL) + retry = ErrorPromptRetry("Error opening directory!"); + } + + // if we can't open the dir, try higher levels + if (dir == NULL) + { + char * devEnd = strrchr(browser.dir, '/'); + + while(!IsDeviceRoot(browser.dir)) + { + devEnd[0] = 0; // strip slash + devEnd = strrchr(browser.dir, '/'); + + if(devEnd == NULL) + break; + + devEnd[1] = 0; // strip remaining file listing + dir = opendir(browser.dir); + if (dir) + break; + } + } + + if(dir == NULL) + return -1; + + if(IsDeviceRoot(browser.dir)) + { + AddBrowserEntry(); + sprintf(browserList[0].filename, ".."); + sprintf(browserList[0].displayname, "Up One Level"); + browserList[0].length = 0; + browserList[0].isdir = 1; // flag this as a dir + browserList[0].icon = ICON_FOLDER; + browser.numEntries++; + } + + parseHalt = false; + ParseDirEntries(); // index first 20 entries + + LWP_ResumeThread(parsethread); // index remaining entries + + if(waitParse) // wait for complete parsing + { + ShowAction("Loading..."); + + while(!LWP_ThreadIsSuspended(parsethread)) + usleep(THREAD_SLEEP); + + CancelAction(); + } + + return browser.numEntries; +} + +/**************************************************************************** + * AllocSaveBuffer () + * Clear and allocate the savebuffer + ***************************************************************************/ +void +AllocSaveBuffer () +{ + if(bufferLock == LWP_MUTEX_NULL) + LWP_MutexInit(&bufferLock, false); + + if(bufferLock != LWP_MUTEX_NULL) + LWP_MutexLock(bufferLock); + memset (savebuffer, 0, SAVEBUFFERSIZE); +} + +/**************************************************************************** + * FreeSaveBuffer () + * Free the savebuffer memory + ***************************************************************************/ +void +FreeSaveBuffer () +{ + if(bufferLock != LWP_MUTEX_NULL) + LWP_MutexUnlock(bufferLock); +} + +/**************************************************************************** + * LoadSzFile + * Loads the selected file # from the specified 7z into rbuffer + * Returns file size + ***************************************************************************/ +size_t +LoadSzFile(char * filepath, unsigned char * rbuffer) +{ + size_t size = 0; + + // stop checking if devices were removed/inserted + // since we're loading a file + HaltDeviceThread(); + + // halt parsing + HaltParseThread(); + + file = fopen (filepath, "rb"); + if (file > 0) + { + size = SzExtractFile(browserList[browser.selIndex].filenum, rbuffer); + fclose (file); + } + else + { + ErrorPrompt("Error opening file!"); + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + + return size; +} + +/**************************************************************************** + * LoadFile + ***************************************************************************/ +size_t +LoadFile (char * rbuffer, char *filepath, size_t length, bool silent) +{ + char zipbuffer[2048]; + size_t size = 0, offset = 0, readsize = 0; + int retry = 1; + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + // stop checking if devices were removed/inserted + // since we're loading a file + HaltDeviceThread(); + + // halt parsing + HaltParseThread(); + + // open the file + while(retry) + { + if(!ChangeInterface(device, silent)) + break; + + file = fopen (filepath, "rb"); + + if(!file) + { + if(silent) + break; + + retry = ErrorPromptRetry("Error opening file!"); + continue; + } + + if(length > 0 && length <= 2048) // do a partial read (eg: to check file header) + { + size = fread (rbuffer, 1, length, file); + } + else // load whole file + { + readsize = fread (zipbuffer, 1, 32, file); + + if(!readsize) + { + unmountRequired[device] = true; + retry = ErrorPromptRetry("Error reading file!"); + fclose (file); + continue; + } + + if (IsZipFile (zipbuffer)) + { + size = UnZipBuffer ((unsigned char *)rbuffer); // unzip + } + else + { + fseeko(file,0,SEEK_END); + size = ftello(file); + fseeko(file,0,SEEK_SET); + + 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); + readsize = fread (rbuffer + offset, 1, 4096, file); // read in next chunk + + if(readsize <= 0) + break; // reading finished (or failed) + + offset += readsize; + if (length > 0 && offset >= length) { + break; + } + } + size = offset; + CancelAction(); + } + } + retry = 0; + fclose (file); + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + CancelAction(); + return size; +} + +size_t LoadFile(char * filepath, bool silent) +{ + return LoadFile((char *)savebuffer, filepath, 0, silent); +} + +/**************************************************************************** + * SaveFile + * Write buffer to file + ***************************************************************************/ +size_t +SaveFile (char * buffer, char *filepath, size_t datasize, bool silent) +{ + size_t written = 0; + size_t writesize, nextwrite; + int retry = 1; + int device; + + if(!FindDevice(filepath, &device)) + return 0; + + if(datasize == 0) + return 0; + + // stop checking if devices were removed/inserted + // since we're saving a file + HaltDeviceThread(); + + // halt parsing + HaltParseThread(); + + ShowAction("Saving..."); + + while(!written && retry == 1) + { + if(!ChangeInterface(device, silent)) + break; + + file = fopen (filepath, "wb"); + + if(!file) + { + if(silent) + break; + + retry = ErrorPromptRetry("Error creating file!"); + continue; + } + + while(written < datasize) + { + if(datasize - written > 4096) nextwrite=4096; + else nextwrite = datasize-written; + writesize = fwrite (buffer+written, 1, nextwrite, file); + if(writesize != nextwrite) break; // write failure + written += writesize; + } + fclose (file); + + if(written != datasize) written = 0; + + if(!written) + { + unmountRequired[device] = true; + if(silent) break; + retry = ErrorPromptRetry("Error saving file!"); + } + } + + // go back to checking if devices were inserted/removed + ResumeDeviceThread(); + + CancelAction(); + return written; +} + +size_t SaveFile(char * filepath, size_t datasize, bool silent) +{ + return SaveFile((char *)savebuffer, filepath, datasize, silent); +} diff --git a/source/fileop.h b/source/fileop.h index 4a55cba..716f204 100644 --- a/source/fileop.h +++ b/source/fileop.h @@ -1,50 +1,51 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * fileop.h - * - * File operations - ****************************************************************************/ - -#ifndef _FILEOP_H_ -#define _FILEOP_H_ - -#include -#include -#include -#include -#include -#include - -#define SAVEBUFFERSIZE (1024 * 1024 * 2) - -void InitDeviceThread(); -void ResumeDeviceThread(); -void HaltDeviceThread(); -void HaltParseThread(); -void MountAllFAT(); -void UnmountAllFAT(); -bool FindDevice(char * filepath, int * device); -char * StripDevice(char * path); -bool ChangeInterface(int device, bool silent); -bool ChangeInterface(char * filepath, bool silent); -void CreateAppPath(char * origpath); -bool GetFileSize(int i); -int ParseDirectory(bool waitParse = false, bool filter = true); -void AllocSaveBuffer(); -void FreeSaveBuffer(); -size_t LoadFile(char * rbuffer, char *filepath, size_t length, bool silent); -size_t LoadFile(char * filepath, bool silent); -size_t LoadSzFile(char * filepath, unsigned char * rbuffer); -size_t SaveFile(char * buffer, char *filepath, size_t datasize, bool silent); -size_t SaveFile(char * filepath, size_t datasize, bool silent); - -extern unsigned char *savebuffer; -extern FILE * file; -extern bool unmountRequired[]; -extern bool isMounted[]; -extern int selectLoadedFile; - -#endif +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * fileop.h + * + * File operations + ****************************************************************************/ + +#ifndef _FILEOP_H_ +#define _FILEOP_H_ + +#include +#include +#include +#include +#include +#include + +#define SAVEBUFFERSIZE (1024 * 512) + +void InitDeviceThread(); +void ResumeDeviceThread(); +void HaltDeviceThread(); +void HaltParseThread(); +void MountAllFAT(); +void UnmountAllFAT(); +bool FindDevice(char * filepath, int * device); +char * StripDevice(char * path); +bool ChangeInterface(int device, bool silent); +bool ChangeInterface(char * filepath, bool silent); +void CreateAppPath(char * origpath); +bool GetFileSize(int i); +void FindAndSelectLastLoadedFile(); +int ParseDirectory(bool waitParse = false, bool filter = true); +void AllocSaveBuffer(); +void FreeSaveBuffer(); +size_t LoadFile(char * rbuffer, char *filepath, size_t length, bool silent); +size_t LoadFile(char * filepath, bool silent); +size_t LoadSzFile(char * filepath, unsigned char * rbuffer); +size_t SaveFile(char * buffer, char *filepath, size_t datasize, bool silent); +size_t SaveFile(char * filepath, size_t datasize, bool silent); + +extern unsigned char *savebuffer; +extern FILE * file; +extern bool unmountRequired[]; +extern bool isMounted[]; +extern int selectLoadedFile; + +#endif diff --git a/source/gameinput.cpp b/source/gameinput.cpp index ee29e01..a4484cd 100644 --- a/source/gameinput.cpp +++ b/source/gameinput.cpp @@ -1540,3 +1540,119 @@ u32 CastlevaniaCircleMoonInput(unsigned short pad) { 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; +} + diff --git a/source/gameinput.h b/source/gameinput.h index 1dfcc7d..cf3ed5b 100644 --- a/source/gameinput.h +++ b/source/gameinput.h @@ -115,7 +115,7 @@ #define CVCLASSIC gid('F','A','D') #define CVDOUBLE gid('B','X','K') - +#define KIDDRACULA 0xFF0014 #define MARBLEMADNESS 0xFF000A @@ -205,6 +205,7 @@ u32 CastlevaniaAdventureInput(unsigned short pad); u32 CastlevaniaBelmontInput(unsigned short pad); u32 CastlevaniaLegendsInput(unsigned short pad); u32 CastlevaniaCircleMoonInput(unsigned short pad); +u32 KidDraculaInput(unsigned short pad); #endif diff --git a/source/gcunzip.cpp b/source/gcunzip.cpp index 00e5e61..f9033a4 100644 --- a/source/gcunzip.cpp +++ b/source/gcunzip.cpp @@ -1,518 +1,526 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * gcunzip.cpp - * - * File unzip routines - ***************************************************************************/ - -#include -#include -#include -#include -#include - -#include "vbagx.h" -#include "fileop.h" -#include "filebrowser.h" -#include "menu.h" -#include "gcunzip.h" - -extern "C" { -#include "utils/sz/7zCrc.h" -#include "utils/sz/7zIn.h" -#include "utils/sz/7zExtract.h" -} - -#define ZIPCHUNK 2048 - -/* - * Zip file header definition - */ -typedef struct -{ - unsigned int zipid __attribute__ ((__packed__)); // 0x04034b50 - unsigned short zipversion __attribute__ ((__packed__)); - unsigned short zipflags __attribute__ ((__packed__)); - unsigned short compressionMethod __attribute__ ((__packed__)); - unsigned short lastmodtime __attribute__ ((__packed__)); - unsigned short lastmoddate __attribute__ ((__packed__)); - unsigned int crc32 __attribute__ ((__packed__)); - unsigned int compressedSize __attribute__ ((__packed__)); - unsigned int uncompressedSize __attribute__ ((__packed__)); - unsigned short filenameLength __attribute__ ((__packed__)); - unsigned short extraDataLength __attribute__ ((__packed__)); -} -PKZIPHEADER; - -/* - * Zip files are stored little endian - * Support functions for short and int types - */ -static u32 -FLIP32 (u32 b) -{ - unsigned int c; - - c = (b & 0xff000000) >> 24; - c |= (b & 0xff0000) >> 8; - c |= (b & 0xff00) << 8; - c |= (b & 0xff) << 24; - - return c; -} - -static u16 -FLIP16 (u16 b) -{ - u16 c; - - c = (b & 0xff00) >> 8; - c |= (b & 0xff) << 8; - - return c; -} - -/**************************************************************************** - * IsZipFile - * - * Returns TRUE when 0x504b0304 is first four characters of buffer - ***************************************************************************/ -int -IsZipFile (char *buffer) -{ - unsigned int *check = (unsigned int *) buffer; - - if (check[0] == 0x504b0304) - return 1; - - return 0; -} - -/***************************************************************************** -* UnZipBuffer -******************************************************************************/ - -size_t -UnZipBuffer (unsigned char *outbuffer) -{ - PKZIPHEADER pkzip; - size_t zipoffset = 0; - size_t zipchunk = 0; - char out[ZIPCHUNK]; - z_stream zs; - int res; - size_t bufferoffset = 0; - size_t have = 0; - char readbuffer[ZIPCHUNK]; - size_t sizeread = 0; - - // Read Zip Header - fseek(file, 0, SEEK_SET); - sizeread = fread (readbuffer, 1, ZIPCHUNK, file); - - if(sizeread <= 0) - return 0; - - /*** Copy PKZip header to local, used as info ***/ - memcpy (&pkzip, readbuffer, sizeof (PKZIPHEADER)); - - pkzip.uncompressedSize = FLIP32 (pkzip.uncompressedSize); - - ShowProgress ("Loading...", 0, pkzip.uncompressedSize); - - /*** Prepare the zip stream ***/ - memset (&zs, 0, sizeof (z_stream)); - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = 0; - zs.next_in = Z_NULL; - res = inflateInit2 (&zs, -MAX_WBITS); - - if (res != Z_OK) - goto done; - - /*** Set ZipChunk for first pass ***/ - zipoffset = - (sizeof (PKZIPHEADER) + FLIP16 (pkzip.filenameLength) + - FLIP16 (pkzip.extraDataLength)); - zipchunk = ZIPCHUNK - zipoffset; - - /*** Now do it! ***/ - do - { - zs.avail_in = zipchunk; - zs.next_in = (Bytef *) & readbuffer[zipoffset]; - - /*** Now inflate until input buffer is exhausted ***/ - do - { - zs.avail_out = ZIPCHUNK; - zs.next_out = (Bytef *) & out; - - res = inflate (&zs, Z_NO_FLUSH); - - if (res == Z_MEM_ERROR) - { - goto done; - } - - have = ZIPCHUNK - zs.avail_out; - if (have) - { - /*** Copy to normal block buffer ***/ - memcpy (&outbuffer[bufferoffset], &out, have); - bufferoffset += have; - } - } - while (zs.avail_out == 0); - - // Readup the next 2k block - zipoffset = 0; - zipchunk = ZIPCHUNK; - - sizeread = fread (readbuffer, 1, ZIPCHUNK, file); - if(sizeread <= 0) - goto done; // read failure - - ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize); - } - while (res != Z_STREAM_END); - -done: - inflateEnd (&zs); - CancelAction(); - - if (res == Z_STREAM_END) - return pkzip.uncompressedSize; - else - return 0; -} - -/**************************************************************************** -* GetFirstZipFilename -* -* Returns the filename of the first file in the zipped archive -* The idea here is to do the least amount of work required -***************************************************************************/ - -char * -GetFirstZipFilename () -{ - char * firstFilename = NULL; - char tempbuffer[ZIPCHUNK]; - char filepath[1024]; - - if(!MakeFilePath(filepath, FILE_ROM)) - return NULL; - - // read start of ZIP - if(LoadFile (tempbuffer, filepath, ZIPCHUNK, NOTSILENT) < 35) - return NULL; - - tempbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27) - int namelength = tempbuffer[26]; // filename length starts 26 bytes in - - if(namelength < 0 || namelength > 200) // filename is not a reasonable length - { - ErrorPrompt("Error - Invalid ZIP file!"); - return NULL; - } - - firstFilename = &tempbuffer[30]; // first filename of a ZIP starts 31 bytes in - firstFilename[namelength] = 0; // truncate at filename length - return strdup(firstFilename); -} - -/**************************************************************************** -* 7z functions -***************************************************************************/ - -typedef struct _SzFileInStream -{ - ISzInStream InStream; - u64 offset; // offset of the file - unsigned int len; // length of the file - u64 pos; // current position of the file pointer -} SzFileInStream; - -// 7zip error list -static char szerrormsg[][100] = { - "File is corrupt.", // 7z: Data error - "Archive contains too many files.", // 7z: Out of memory - "File is corrupt (CRC mismatch).", // 7z: CRC Error - "File uses unsupported compression settings.", // 7z: Not implemented - "File is corrupt.", // 7z: Fail - "Failed to read file data.", // 7z: Data read failure - "File is corrupt.", // 7z: Archive error - "File uses too high of compression settings (dictionary size is too large).", // 7z: Dictionary too large -}; - -static SZ_RESULT SzRes; -static SzFileInStream SzArchiveStream; -static CArchiveDatabaseEx SzDb; -static ISzAlloc SzAllocImp; -static ISzAlloc SzAllocTempImp; -static UInt32 SzBlockIndex = 0xFFFFFFFF; -static size_t SzBufferSize; -static size_t SzOffset; -static size_t SzOutSizeProcessed; -static CFileItem *SzF; - -static char sz_buffer[2048]; -static int szMethod = 0; - -/**************************************************************************** -* Is7ZipFile -* -* Returns 1 when 7z signature is found -****************************************************************************/ -int -Is7ZipFile (char *buffer) -{ - // 7z signature - static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; - - int i; - for(i = 0; i < 6; i++) - if(buffer[i] != Signature[i]) - return 0; - - return 1; // 7z archive found -} - -// display an error message -static void SzDisplayError(SZ_RESULT res) -{ - char msg[1024]; - sprintf(msg, "7z decompression failed: %s", szerrormsg[(res - 1)]); - ErrorPrompt(msg); -} - -// function used by the 7zip SDK to read data from SD/USB/DVD/SMB -static SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) -{ - size_t sizeread = 0; - - if(maxRequiredSize == 0) - return SZ_OK; - - // the void* object is a SzFileInStream - SzFileInStream *s = (SzFileInStream *) object; - - if (maxRequiredSize > 2048) - maxRequiredSize = 2048; - - // read data - sizeread = fread(sz_buffer, 1, maxRequiredSize, file); - - if(sizeread <= 0) - return SZE_FAILREAD; - - *buffer = sz_buffer; - *processedSize = sizeread; - s->pos += sizeread; - - if(sizeread > 1024) // only show progress for large reads - // this isn't quite right, but oh well - ShowProgress ("Loading...", s->pos, browserList[browser.selIndex].length); - - return SZ_OK; -} - -// function used by the 7zip SDK to change the filepointer -static SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) -{ - // the void* object is a SzFileInStream - SzFileInStream *s = (SzFileInStream *) object; - - // check if the 7z SDK wants to move the pointer to somewhere after the EOF - if (pos >= s->len) - return SZE_FAIL; - - // save new position and return - if(fseek(file, (long)pos, SEEK_SET) != 0) - return SZE_FAIL; - - s->pos = pos; - return SZ_OK; -} - -/**************************************************************************** -* SzClose -* -* Closes a 7z file -***************************************************************************/ - -void SzClose() -{ - if(SzDb.Database.NumFiles > 0) - SzArDbExFree(&SzDb, SzAllocImp.Free); -} - -/**************************************************************************** -* SzParse -* -* Opens a 7z file, and parses it -* It parses the entire 7z for full browsing capability -***************************************************************************/ - -int SzParse(char * filepath) -{ - if(!filepath) - return 0; - - int device; - - if(!FindDevice(browser.dir, &device) || !GetFileSize(browser.selIndex)) - return 0; - - int nbfiles = 0; - - // save the length/offset of this file - unsigned int filelen = browserList[browser.selIndex].length; - - // setup archive stream - SzArchiveStream.offset = 0; - SzArchiveStream.len = filelen; - SzArchiveStream.pos = 0; - - // open file - file = fopen (filepath, "rb"); - if(!file) - return 0; - - // set szMethod to current chosen load device - szMethod = device; - - // set handler functions for reading data from SD/USB/SMB/DVD - SzArchiveStream.InStream.Read = SzFileReadImp; - SzArchiveStream.InStream.Seek = SzFileSeekImp; - - // set default 7Zip SDK handlers for allocation and freeing memory - SzAllocImp.Alloc = SzAlloc; - SzAllocImp.Free = SzFree; - SzAllocTempImp.Alloc = SzAllocTemp; - SzAllocTempImp.Free = SzFreeTemp; - - // prepare CRC and 7Zip database structures - InitCrcTable(); - SzArDbExInit(&SzDb); - - // open the archive - SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp, - &SzAllocTempImp); - - if (SzRes != SZ_OK) - { - SzDisplayError(SzRes); - // free memory used by the 7z SDK - SzClose(); - } - else // archive opened successfully - { - if(SzDb.Database.NumFiles > 0) - { - // Parses the 7z into a full file listing - - HaltParseThread(); // halt parsing - ResetBrowser(); // reset browser - - // add '..' folder in case the user wants exit the 7z - AddBrowserEntry(); - - sprintf(browserList[0].displayname, "Up One Level"); - browserList[0].isdir = 1; - browserList[0].length = filelen; - browserList[0].icon = ICON_FOLDER; - - // get contents and parse them into file list structure - unsigned int SzI, SzJ; - SzJ = 1; - for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++) - { - SzF = SzDb.Database.Files + SzI; - - // skip directories - if (SzF->IsDirectory) - continue; - - if(!AddBrowserEntry()) - { - ResetBrowser(); - ErrorPrompt("Out of memory: too many files!"); - SzClose(); - SzJ = 0; - break; - } - - // parse information about this file to the file list structure - snprintf(browserList[SzJ].filename, MAXJOLIET, "%s", SzF->Name); - StripExt(browserList[SzJ].displayname, browserList[SzJ].filename); - browserList[SzJ].length = SzF->Size; // filesize - browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags) - browserList[SzJ].filenum = SzI; // the extraction function identifies the file with this number - SzJ++; - } - nbfiles = SzJ; - } - else - { - SzClose(); - } - } - - CancelAction(); - - // close file - fclose(file); - return nbfiles; -} - -/**************************************************************************** -* SzExtractFile -* -* Extracts the given file # into the buffer specified -* Must parse the 7z BEFORE running this function -***************************************************************************/ - -size_t SzExtractFile(int i, unsigned char *buffer) -{ - // prepare some variables - SzBlockIndex = 0xFFFFFFFF; - SzOffset = 0; - - // Unzip the file - - SzRes = SzExtract2( - &SzArchiveStream.InStream, - &SzDb, - i, // index of file - &SzBlockIndex, // index of solid block - &buffer, - &SzBufferSize, - &SzOffset, // offset of stream for required file in *outBuffer - &SzOutSizeProcessed, // size of file in *outBuffer - &SzAllocImp, - &SzAllocTempImp); - - // close 7Zip archive and free memory - SzClose(); - - CancelAction(); - - // check for errors - if(SzRes != SZ_OK) - { - // display error message - SzDisplayError(SzRes); - return 0; - } - else - { - return SzOutSizeProcessed; - } -} +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * gcunzip.cpp + * + * File unzip routines + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "vbagx.h" +#include "fileop.h" +#include "filebrowser.h" +#include "menu.h" +#include "gcunzip.h" + +extern "C" { +#include "utils/sz/7zCrc.h" +#include "utils/sz/7zIn.h" +#include "utils/sz/7zExtract.h" +} + +#define ZIPCHUNK 2048 + +/* + * Zip file header definition + */ +typedef struct +{ + unsigned int zipid __attribute__ ((__packed__)); // 0x04034b50 + unsigned short zipversion __attribute__ ((__packed__)); + unsigned short zipflags __attribute__ ((__packed__)); + unsigned short compressionMethod __attribute__ ((__packed__)); + unsigned short lastmodtime __attribute__ ((__packed__)); + unsigned short lastmoddate __attribute__ ((__packed__)); + unsigned int crc32 __attribute__ ((__packed__)); + unsigned int compressedSize __attribute__ ((__packed__)); + unsigned int uncompressedSize __attribute__ ((__packed__)); + unsigned short filenameLength __attribute__ ((__packed__)); + unsigned short extraDataLength __attribute__ ((__packed__)); +} +PKZIPHEADER; + +/* + * Zip files are stored little endian + * Support functions for short and int types + */ +static u32 +FLIP32 (u32 b) +{ + unsigned int c; + + c = (b & 0xff000000) >> 24; + c |= (b & 0xff0000) >> 8; + c |= (b & 0xff00) << 8; + c |= (b & 0xff) << 24; + + return c; +} + +static u16 +FLIP16 (u16 b) +{ + u16 c; + + c = (b & 0xff00) >> 8; + c |= (b & 0xff) << 8; + + return c; +} + +/**************************************************************************** + * IsZipFile + * + * Returns TRUE when 0x504b0304 is first four characters of buffer + ***************************************************************************/ +int +IsZipFile (char *buffer) +{ + unsigned int *check = (unsigned int *) buffer; + + if (check[0] == 0x504b0304) + return 1; + + return 0; +} + +/***************************************************************************** +* UnZipBuffer +******************************************************************************/ + +size_t +UnZipBuffer (unsigned char *outbuffer) +{ + PKZIPHEADER pkzip; + size_t zipoffset = 0; + size_t zipchunk = 0; + char out[ZIPCHUNK]; + z_stream zs; + int res; + size_t bufferoffset = 0; + size_t have = 0; + char readbuffer[ZIPCHUNK]; + size_t sizeread = 0; + + // Read Zip Header + fseek(file, 0, SEEK_SET); + sizeread = fread (readbuffer, 1, ZIPCHUNK, file); + + if(sizeread <= 0) + return 0; + + /*** Copy PKZip header to local, used as info ***/ + memcpy (&pkzip, readbuffer, sizeof (PKZIPHEADER)); + + pkzip.uncompressedSize = FLIP32 (pkzip.uncompressedSize); + + ShowProgress ("Loading...", 0, pkzip.uncompressedSize); + + /*** Prepare the zip stream ***/ + memset (&zs, 0, sizeof (z_stream)); + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = 0; + zs.next_in = Z_NULL; + res = inflateInit2 (&zs, -MAX_WBITS); + + if (res != Z_OK) + goto done; + + /*** Set ZipChunk for first pass ***/ + zipoffset = + (sizeof (PKZIPHEADER) + FLIP16 (pkzip.filenameLength) + + FLIP16 (pkzip.extraDataLength)); + zipchunk = ZIPCHUNK - zipoffset; + + /*** Now do it! ***/ + do + { + zs.avail_in = zipchunk; + zs.next_in = (Bytef *) & readbuffer[zipoffset]; + + /*** Now inflate until input buffer is exhausted ***/ + do + { + zs.avail_out = ZIPCHUNK; + zs.next_out = (Bytef *) & out; + + res = inflate (&zs, Z_NO_FLUSH); + + if (res == Z_MEM_ERROR) + { + goto done; + } + + have = ZIPCHUNK - zs.avail_out; + if (have) + { + /*** Copy to normal block buffer ***/ + memcpy (&outbuffer[bufferoffset], &out, have); + bufferoffset += have; + } + } + while (zs.avail_out == 0); + + // Readup the next 2k block + zipoffset = 0; + zipchunk = ZIPCHUNK; + + sizeread = fread (readbuffer, 1, ZIPCHUNK, file); + if(sizeread <= 0) + goto done; // read failure + + ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize); + } + while (res != Z_STREAM_END); + +done: + inflateEnd (&zs); + CancelAction(); + + if (res == Z_STREAM_END) + return pkzip.uncompressedSize; + else + return 0; +} + +/**************************************************************************** +* GetFirstZipFilename +* +* Returns the filename of the first file in the zipped archive +* The idea here is to do the least amount of work required +***************************************************************************/ + +char * +GetFirstZipFilename () +{ + char * firstFilename = NULL; + char tempbuffer[ZIPCHUNK]; + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_ROM)) + return NULL; + + // read start of ZIP + if(LoadFile (tempbuffer, filepath, ZIPCHUNK, NOTSILENT) < 35) + return NULL; + + tempbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27) + int namelength = tempbuffer[26]; // filename length starts 26 bytes in + + if(namelength < 0 || namelength > 200) // filename is not a reasonable length + { + ErrorPrompt("Error - Invalid ZIP file!"); + return NULL; + } + + firstFilename = &tempbuffer[30]; // first filename of a ZIP starts 31 bytes in + firstFilename[namelength] = 0; // truncate at filename length + return strdup(firstFilename); +} + +/**************************************************************************** +* 7z functions +***************************************************************************/ + +typedef struct _SzFileInStream +{ + ISzInStream InStream; + u64 offset; // offset of the file + unsigned int len; // length of the file + u64 pos; // current position of the file pointer +} SzFileInStream; + +// 7zip error list +static char szerrormsg[][100] = { + "File is corrupt.", // 7z: Data error + "Archive contains too many files.", // 7z: Out of memory + "File is corrupt (CRC mismatch).", // 7z: CRC Error + "File uses unsupported compression settings.", // 7z: Not implemented + "File is corrupt.", // 7z: Fail + "Failed to read file data.", // 7z: Data read failure + "File is corrupt.", // 7z: Archive error + "File uses too high of compression settings (dictionary size is too large).", // 7z: Dictionary too large +}; + +static SZ_RESULT SzRes; +static SzFileInStream SzArchiveStream; +static CArchiveDatabaseEx SzDb; +static ISzAlloc SzAllocImp; +static ISzAlloc SzAllocTempImp; +static UInt32 SzBlockIndex = 0xFFFFFFFF; +static size_t SzBufferSize; +static size_t SzOffset; +static size_t SzOutSizeProcessed; +static CFileItem *SzF; + +static char sz_buffer[2048]; +static int szMethod = 0; + +/**************************************************************************** +* Is7ZipFile +* +* Returns 1 when 7z signature is found +****************************************************************************/ +int +Is7ZipFile (char *buffer) +{ + // 7z signature + static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + + int i; + for(i = 0; i < 6; i++) + if(buffer[i] != Signature[i]) + return 0; + + return 1; // 7z archive found +} + +// display an error message +static void SzDisplayError(SZ_RESULT res) +{ + char msg[1024]; + sprintf(msg, "7z decompression failed: %s", szerrormsg[(res - 1)]); + ErrorPrompt(msg); +} + +// function used by the 7zip SDK to read data from SD/USB/DVD/SMB +static SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) +{ + size_t sizeread = 0; + + if(maxRequiredSize == 0) + return SZ_OK; + + // the void* object is a SzFileInStream + SzFileInStream *s = (SzFileInStream *) object; + + if (maxRequiredSize > 2048) + maxRequiredSize = 2048; + + // read data + sizeread = fread(sz_buffer, 1, maxRequiredSize, file); + + if(sizeread <= 0) + return SZE_FAILREAD; + + *buffer = sz_buffer; + *processedSize = sizeread; + s->pos += sizeread; + + if(sizeread > 1024) // only show progress for large reads + // this isn't quite right, but oh well + ShowProgress ("Loading...", s->pos, browserList[browser.selIndex].length); + + return SZ_OK; +} + +// function used by the 7zip SDK to change the filepointer +static SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) +{ + // the void* object is a SzFileInStream + SzFileInStream *s = (SzFileInStream *) object; + + // check if the 7z SDK wants to move the pointer to somewhere after the EOF + if (pos >= s->len) + return SZE_FAIL; + + // save new position and return + if(fseek(file, (long)pos, SEEK_SET) != 0) + return SZE_FAIL; + + s->pos = pos; + return SZ_OK; +} + +/**************************************************************************** +* SzClose +* +* Closes a 7z file +***************************************************************************/ + +void SzClose() +{ + if(SzDb.Database.NumFiles > 0) + SzArDbExFree(&SzDb, SzAllocImp.Free); +} + +/**************************************************************************** +* SzParse +* +* Opens a 7z file, and parses it +* It parses the entire 7z for full browsing capability +***************************************************************************/ + +int SzParse(char * filepath) +{ + if(!filepath) + return 0; + + int device; + + struct stat filestat; + if(stat(filepath, &filestat) < 0) + return 0; + unsigned int filelen = filestat.st_size; + + if(!FindDevice(filepath, &device) || !filelen) + return 0; + + int nbfiles = 0; + // setup archive stream + SzArchiveStream.offset = 0; + SzArchiveStream.len = filelen; + SzArchiveStream.pos = 0; + + // open file + file = fopen (filepath, "rb"); + if(!file) + return 0; + + // set szMethod to current chosen load device + szMethod = device; + + // set handler functions for reading data from SD/USB/SMB/DVD + SzArchiveStream.InStream.Read = SzFileReadImp; + SzArchiveStream.InStream.Seek = SzFileSeekImp; + + // set default 7Zip SDK handlers for allocation and freeing memory + SzAllocImp.Alloc = SzAlloc; + SzAllocImp.Free = SzFree; + SzAllocTempImp.Alloc = SzAllocTemp; + SzAllocTempImp.Free = SzFreeTemp; + + // prepare CRC and 7Zip database structures + InitCrcTable(); + SzArDbExInit(&SzDb); + + // open the archive + SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp, + &SzAllocTempImp); + + if (SzRes != SZ_OK) + { + SzDisplayError(SzRes); + // free memory used by the 7z SDK + SzClose(); + } + else // archive opened successfully + { + if(SzDb.Database.NumFiles > 0) + { + // Parses the 7z into a full file listing + + HaltParseThread(); // halt parsing + ResetBrowser(); // reset browser + + // add '..' folder in case the user wants exit the 7z + AddBrowserEntry(); + sprintf(browserList[0].filename, ".."); + sprintf(browserList[0].displayname, "Up One Level"); + browserList[0].isdir = 1; + browserList[0].length = filelen; + browserList[0].icon = ICON_FOLDER; + + // get contents and parse them into file list structure + unsigned int SzI, SzJ; + SzJ = 1; + for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++) + { + SzF = SzDb.Database.Files + SzI; + + // skip directories + if (SzF->IsDirectory) + continue; + + if(!AddBrowserEntry()) + { + ResetBrowser(); + ErrorPrompt("Out of memory: too many files!"); + SzClose(); + SzJ = 0; + break; + } + + // parse information about this file to the file list structure + snprintf(browserList[SzJ].filename, MAXJOLIET, "%s", SzF->Name); + 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].isdir = 0; // only files will be displayed (-> no flags) + browserList[SzJ].filenum = SzI; // the extraction function identifies the file with this number + SzJ++; + } + nbfiles = SzJ; + } + else + { + SzClose(); + } + } + + CancelAction(); + + // close file + fclose(file); + return nbfiles; +} + +/**************************************************************************** +* SzExtractFile +* +* Extracts the given file # into the buffer specified +* Must parse the 7z BEFORE running this function +***************************************************************************/ + +size_t SzExtractFile(int i, unsigned char *buffer) +{ + // prepare some variables + SzBlockIndex = 0xFFFFFFFF; + SzOffset = 0; + + // Unzip the file + + SzRes = SzExtract2( + &SzArchiveStream.InStream, + &SzDb, + i, // index of file + &SzBlockIndex, // index of solid block + &buffer, + &SzBufferSize, + &SzOffset, // offset of stream for required file in *outBuffer + &SzOutSizeProcessed, // size of file in *outBuffer + &SzAllocImp, + &SzAllocTempImp); + + // close 7Zip archive and free memory + SzClose(); + + CancelAction(); + + // check for errors + if(SzRes != SZ_OK) + { + // display error message + SzDisplayError(SzRes); + return 0; + } + else + { + return SzOutSizeProcessed; + } +} diff --git a/source/goomba/README.txt b/source/goomba/README.txt new file mode 100644 index 0000000..c44d4f7 --- /dev/null +++ b/source/goomba/README.txt @@ -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 diff --git a/source/goomba/goombarom.cpp b/source/goomba/goombarom.cpp new file mode 100644 index 0000000..22fc165 --- /dev/null +++ b/source/goomba/goombarom.cpp @@ -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 . + +When compiling in Visual Studio, set all goombarom files to compile +as C++ code (Properties -> C/C++ -> Advanced -> Compile As.) +*/ + +#include +#include +#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; +} diff --git a/source/goomba/goombarom.h b/source/goomba/goombarom.h new file mode 100644 index 0000000..cd7b7c5 --- /dev/null +++ b/source/goomba/goombarom.h @@ -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 . + +When compiling in Visual Studio, set all goombarom files to compile +as C++ code (Properties -> C/C++ -> Advanced -> Compile As.) +*/ + +#include + +/* 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); diff --git a/source/goomba/goombasav.cpp b/source/goomba/goombasav.cpp new file mode 100644 index 0000000..6bbb0bc --- /dev/null +++ b/source/goomba/goombasav.cpp @@ -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 . + +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 +#include +#include +#include +#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> 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; +} diff --git a/source/goomba/goombasav.h b/source/goomba/goombasav.h new file mode 100644 index 0000000..187b952 --- /dev/null +++ b/source/goomba/goombasav.h @@ -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 . + +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 +#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 diff --git a/source/goomba/minilzo-2.06/COPYING b/source/goomba/minilzo-2.06/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/source/goomba/minilzo-2.06/COPYING @@ -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. + + + Copyright (C) + + 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. + + , 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. diff --git a/source/goomba/minilzo-2.06/README.LZO b/source/goomba/minilzo-2.06/README.LZO new file mode 100644 index 0000000..058eace --- /dev/null +++ b/source/goomba/minilzo-2.06/README.LZO @@ -0,0 +1,124 @@ + + ============================================================================ + miniLZO -- mini subset of the LZO real-time data compression library + ============================================================================ + + Author : Markus Franz Xaver Johannes Oberhumer + + 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 . + + 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. + + diff --git a/source/goomba/minilzo-2.06/lzoconf.h b/source/goomba/minilzo-2.06/lzoconf.h new file mode 100644 index 0000000..af0aa23 --- /dev/null +++ b/source/goomba/minilzo-2.06/lzoconf.h @@ -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 + + 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 +#endif +#include +#include + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#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: */ diff --git a/source/goomba/minilzo-2.06/lzodefs.h b/source/goomba/minilzo-2.06/lzodefs.h new file mode 100644 index 0000000..946fdb8 --- /dev/null +++ b/source/goomba/minilzo-2.06/lzodefs.h @@ -0,0 +1,1852 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + 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 + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__) +# else +# define LZO_CC_CLANG_CLANG 0x010000L +# endif +# define LZO_CC_CLANG LZO_CC_CLANG_GNUC +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_inline __inline__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline /*empty*/ +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# if 0 && defined(__cplusplus) +# define LZO_UNCONST_CAST(t,e) (const_cast (e)) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e)))))) +# else +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if (LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif /* already included */ + +/* vim:set ts=4 et: */ diff --git a/source/goomba/minilzo-2.06/minilzo.cpp b/source/goomba/minilzo-2.06/minilzo.cpp new file mode 100644 index 0000000..1b912c4 --- /dev/null +++ b/source/goomba/minilzo-2.06/minilzo.cpp @@ -0,0 +1,4579 @@ +/* minilzo.c -- 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 + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO 1 + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__) +# else +# define LZO_CC_CLANG_CLANG 0x010000L +# endif +# define LZO_CC_CLANG LZO_CC_CLANG_GNUC +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_inline __inline__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline /*empty*/ +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# if 0 && defined(__cplusplus) +# define LZO_UNCONST_CAST(t,e) (const_cast (e)) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e)))))) +# else +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if (LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2060) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H 1 +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H 1 + +#if !defined(__LZO_IN_MINILZO) +#if (LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +# define ACC_LIBC_FREESTANDING 1 +# define ACC_OS_FREESTANDING 1 +#endif +#if (LZO_CFG_NO_UNALIGNED) +# define ACC_CFG_NO_UNALIGNED 1 +#endif +#if (LZO_ARCH_GENERIC) +# define ACC_ARCH_GENERIC 1 +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# define ACC_ABI_NEUTRAL_ENDIAN 1 +#endif +#if (LZO_HAVE_CONFIG_H) +# define ACC_CONFIG_NO_HEADER 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#include "lzo/lzoconf.h" +#endif + +#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) +# error "version mismatch" +#endif + +#if (LZO_CC_BORLANDC && LZO_ARCH_I086) +# pragma option -h +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +# pragma warning(disable: 4514 4710 4711) +#endif + +#if (LZO_CC_SUNPROC) +#if !defined(__cplusplus) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +# pragma error_messages(off,E_STATEMENT_NOT_REACHED) +#endif +#endif + +#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR) +# error "this should not happen - check defines for __huge" +#endif + +#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define ACC_WANT_ACC_INCD_H 1 +# define ACC_WANT_ACC_INCE_H 1 +# define ACC_WANT_ACC_INCI_H 1 +#elif 1 +# include +#else +# define ACC_WANT_ACC_INCD_H 1 +#endif + +#if (LZO_ARCH_I086) +# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT +# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) +# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) +# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) +# define __LZO_UINTPTR_T_IS_POINTER 1 + typedef char* lzo_uintptr_t; +# define lzo_uintptr_t lzo_uintptr_t +# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t size_t +# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long +# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned int +# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long long +# else +# define lzo_uintptr_t size_t +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include +#endif + +#if (LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memcmp +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memcpy +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memmove +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memset +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if (LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(__lzo_inline) +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +# define __lzo_forceinline /*empty*/ +#endif +#if !defined(__lzo_noinline) +# define __lzo_noinline /*empty*/ +#endif + +#if (LZO_CFG_PGO) +# undef __acc_likely +# undef __acc_unlikely +# undef __lzo_likely +# undef __lzo_unlikely +# define __acc_likely(e) (e) +# define __acc_unlikely(e) (e) +# define __lzo_likely(e) (e) +# define __lzo_unlikely(e) (e) +#endif + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC) +# if (LZO_SIZEOF_SHORT == 2) +# define LZO_UNALIGNED_OK_2 1 +# endif +# if (LZO_SIZEOF_INT == 4) +# define LZO_UNALIGNED_OK_4 1 +# endif +#endif +#if 1 && (LZO_ARCH_AMD64) +# if defined(LZO_UINT64_MAX) +# define LZO_UNALIGNED_OK_8 1 +# endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +# undef LZO_UNALIGNED_OK_8 +#endif + +#undef UA_GET16 +#undef UA_SET16 +#undef UA_COPY16 +#undef UA_GET32 +#undef UA_SET32 +#undef UA_COPY32 +#undef UA_GET64 +#undef UA_SET64 +#undef UA_COPY64 +#if defined(LZO_UNALIGNED_OK_2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(unsigned short) == 2) +# if 1 && defined(ACC_UA_COPY16) +# define UA_GET16 ACC_UA_GET16 +# define UA_SET16 ACC_UA_SET16 +# define UA_COPY16 ACC_UA_COPY16 +# else +# define UA_GET16(p) (* (__lzo_ua_volatile const lzo_ushortp) (__lzo_ua_volatile const lzo_voidp) (p)) +# define UA_SET16(p,v) ((* (__lzo_ua_volatile lzo_ushortp) (__lzo_ua_volatile lzo_voidp) (p)) = (unsigned short) (v)) +# define UA_COPY16(d,s) UA_SET16(d, UA_GET16(s)) +# endif +#endif +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +# if 1 && defined(ACC_UA_COPY32) +# define UA_GET32 ACC_UA_GET32 +# define UA_SET32 ACC_UA_SET32 +# define UA_COPY32 ACC_UA_COPY32 +# else +# define UA_GET32(p) (* (__lzo_ua_volatile const lzo_uint32p) (__lzo_ua_volatile const lzo_voidp) (p)) +# define UA_SET32(p,v) ((* (__lzo_ua_volatile lzo_uint32p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint32) (v)) +# define UA_COPY32(d,s) UA_SET32(d, UA_GET32(s)) +# endif +#endif +#if defined(LZO_UNALIGNED_OK_8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64) == 8) +# if 1 && defined(ACC_UA_COPY64) +# define UA_GET64 ACC_UA_GET64 +# define UA_SET64 ACC_UA_SET64 +# define UA_COPY64 ACC_UA_COPY64 +# else +# define UA_GET64(p) (* (__lzo_ua_volatile const lzo_uint64p) (__lzo_ua_volatile const lzo_voidp) (p)) +# define UA_SET64(p,v) ((* (__lzo_ua_volatile lzo_uint64p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint64) (v)) +# define UA_COPY64(d,s) UA_SET64(d, UA_GET64(s)) +# endif +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(lzo_uintptr_t) +# if (__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# else +# define lzo_uintptr_t acc_uintptr_t +# ifdef __ACC_INTPTR_T_IS_POINTER +# define __LZO_UINTPTR_T_IS_POINTER 1 +# endif +# endif +#endif + +#if (LZO_ARCH_I086) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) +#elif (LZO_MM_PVP) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0) +#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0) +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; +#if defined(LZO_UINT64_MAX) + lzo_int64 a_lzo_int64; + lzo_uint64 a_lzo_uint64; +#endif + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef LZO_DETERMINISTIC +#define LZO_DETERMINISTIC 1 +#endif + +#ifndef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 1 +#if 0 && (LZO_ARCH_I086) +# undef LZO_DICT_USE_PTR +# define LZO_DICT_USE_PTR 0 +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) + p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); +#elif (LZO_MM_PVP) + p = (lzo_uintptr_t) (ptr); + p = (p << 3) | (p >> 61); +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if defined(__LZO_UINTPTR_T_IS_POINTER) + size_t n = (size_t) ptr; + n = (((n + size - 1) / size) * size) - n; +#else + lzo_uintptr_t p, n; + p = __lzo_ptr_linear(ptr); + n = (((p + size - 1) / size) * size) - p; +#endif + + assert(size > 0); + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_UTIL) + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +static const char __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ +#if (LZO_OS_DOS16 && LZO_CC_TURBOC) + return (lzo_voidp) __lzo_copyright; +#else + return (const lzo_bytep) __lzo_copyright; +#endif +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) + const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) + lzo_hbyte_p p = (lzo_hbyte_p) s; + if __lzo_likely(len > 0) do + *p++ = (unsigned char) c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, c, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_INIT) + +#if !defined(__LZO_IN_MINILZO) + +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) + ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) +#if defined(LZO_UINT64_MAX) + ACCCHK_ASSERT(sizeof(lzo_uint64) == 8) + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int64) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint64) +#endif + +#if !defined(__LZO_UINTPTR_T_IS_POINTER) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) + ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) + +#endif +#undef ACCCHK_ASSERT + +#define WANT_lzo_bitops_clz32 1 +#define WANT_lzo_bitops_clz64 1 +#define WANT_lzo_bitops_ctz32 1 +#define WANT_lzo_bitops_ctz64 1 + +#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#include +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0 +#pragma intrinsic(_BitScanReverse) +static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanReverse(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz32 lzo_bitops_clz32 +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0 +#pragma intrinsic(_BitScanReverse64) +static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanReverse64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz64 lzo_bitops_clz64 +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#pragma intrinsic(_BitScanForward) +static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanForward(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz32 lzo_bitops_ctz32 +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#pragma intrinsic(_BitScanForward64) +static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanForward64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz64 lzo_bitops_ctz64 +#endif + +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) +#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v)) +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v)) +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v)) +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32) +#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v)) +#endif +#endif + +#if 0 +#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) +#else +static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) +{ + return (lzo_voidp) ((lzo_bytep) ptr + off); +} +#endif + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + union { + lzo_xint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_xint))]; +#if defined(LZO_UNALIGNED_OK_8) + lzo_uint64 c[2]; +#endif + unsigned short x[2]; lzo_uint32 y[2]; lzo_uint z[2]; + } u; + lzo_voidp p; + + u.a[0] = u.a[1] = 0; + p = u2p(&u, 0); + r &= ((* (lzo_bytep) p) == 0); +#if !defined(LZO_CFG_NO_CONFIG_CHECK) +#if defined(LZO_ABI_BIG_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if defined(LZO_ABI_LITTLE_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[0] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if defined(LZO_UNALIGNED_OK_2) + u.a[0] = u.a[1] = 0; + u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2; + p = u2p(&u, 1); + r &= ((* (lzo_ushortp) p) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_4) + u.a[0] = u.a[1] = 0; + u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4; + p = u2p(&u, 1); + r &= ((* (lzo_uint32p) p) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_8) + u.c[0] = u.c[1] = 0; + u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 6; + p = u2p(&u, 1); + r &= ((* (lzo_uint64p) p) == 0); +#endif +#if defined(lzo_bitops_clz32) + { unsigned i; lzo_uint32 v = 1; + for (i = 0; i < 32; i++, v <<= 1) + r &= lzo_bitops_clz32(v) == 31 - i; + } +#endif +#if defined(lzo_bitops_clz64) + { unsigned i; lzo_uint64 v = 1; + for (i = 0; i < 64; i++, v <<= 1) + r &= lzo_bitops_clz64(v) == 63 - i; + } +#endif +#if defined(lzo_bitops_ctz32) + { unsigned i; lzo_uint32 v = 1; + for (i = 0; i < 32; i++, v <<= 1) + r &= lzo_bitops_ctz32(v) == i; + } +#endif +#if defined(lzo_bitops_ctz64) + { unsigned i; lzo_uint64 v = 1; + for (i = 0; i < 64; i++, v <<= 1) + r &= lzo_bitops_ctz64(v) == i; + } +#endif +#endif + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT +#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef ACCCHK_ASSERT + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#endif + +#define LZO1X 1 +#define LZO_EOF_CODE 1 +#define M2_MAX_OFFSET 0x0800 + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#if 1 && defined(UA_GET32) +#undef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 0 +#undef lzo_dict_t +#define lzo_dict_t unsigned short +#endif + +#define LZO_NEED_DICT_H 1 +#ifndef D_BITS +#define D_BITS 14 +#endif +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) +#if 1 +#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) +#else +#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) +#endif + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H 1 + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X 1 +#endif + +#if !defined(__LZO_IN_MINILZO) +#include "lzo/lzo1x.h" +#endif + +#ifndef LZO_EOF_CODE +#define LZO_EOF_CODE 1 +#endif +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 6 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 6 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM) +static void __attribute__((__unused__)) +#else +static void +#endif +DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if (LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if (LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) + +#ifndef DO_COMPRESS +#define DO_COMPRESS lzo1x_1_compress +#endif + +#if 1 && defined(DO_COMPRESS) && !defined(do_compress) +# define do_compress LZO_CPP_ECONCAT2(DO_COMPRESS,_core) +#endif + +#if defined(UA_GET64) && (LZO_ABI_BIG_ENDIAN) +# define WANT_lzo_bitops_clz64 1 +#elif defined(UA_GET64) && (LZO_ABI_LITTLE_ENDIAN) +# define WANT_lzo_bitops_ctz64 1 +#elif defined(UA_GET32) && (LZO_ABI_BIG_ENDIAN) +# define WANT_lzo_bitops_clz32 1 +#elif defined(UA_GET32) && (LZO_ABI_LITTLE_ENDIAN) +# define WANT_lzo_bitops_ctz32 1 +#endif + +#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#include +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0 +#pragma intrinsic(_BitScanReverse) +static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanReverse(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz32 lzo_bitops_clz32 +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0 +#pragma intrinsic(_BitScanReverse64) +static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanReverse64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz64 lzo_bitops_clz64 +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#pragma intrinsic(_BitScanForward) +static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanForward(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz32 lzo_bitops_ctz32 +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#pragma intrinsic(_BitScanForward64) +static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanForward64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz64 lzo_bitops_ctz64 +#endif + +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) +#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v)) +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v)) +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v)) +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32) +#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v)) +#endif +#endif + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_uint ti, lzo_voidp wrkmem) +{ + register const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - 20; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += ti < 4 ? 4 - ti : 0; + for (;;) + { + const lzo_bytep m_pos; +#if !(LZO_DETERMINISTIC) + LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); + lzo_uint m_len; + lzo_uint dindex; +next: + if __lzo_unlikely(ip >= ip_end) + break; + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if defined(UA_GET32) + if (UA_GET32(m_pos) != UA_GET32(ip)) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) +#endif + { +literal: + UPDATE_I(dict,0,dindex,ip,in); + ip += 1 + ((ip - ii) >> 5); + continue; + } + UPDATE_I(dict,0,dindex,ip,in); +#else + lzo_uint m_off; + lzo_uint m_len; + { + lzo_uint32 dv; + lzo_uint dindex; +literal: + ip += 1 + ((ip - ii) >> 5); +next: + if __lzo_unlikely(ip >= ip_end) + break; + dv = UA_GET32(ip); + dindex = DINDEX(dv,ip); + GINDEX(m_off,m_pos,in+dict,dindex,in); + UPDATE_I(dict,0,dindex,ip,in); + if __lzo_unlikely(dv != UA_GET32(m_pos)) + goto literal; + } +#endif + + ii -= ti; ti = 0; + { + register lzo_uint t = pd(ip,ii); + if (t != 0) + { + if (t <= 3) + { + op[-2] |= LZO_BYTE(t); +#if defined(UA_COPY32) + UA_COPY32(op, ii); + op += t; +#else + { do *op++ = *ii++; while (--t > 0); } +#endif + } +#if defined(UA_COPY32) || defined(UA_COPY64) + else if (t <= 16) + { + *op++ = LZO_BYTE(t - 3); +#if defined(UA_COPY64) + UA_COPY64(op, ii); + UA_COPY64(op+8, ii+8); +#else + UA_COPY32(op, ii); + UA_COPY32(op+4, ii+4); + UA_COPY32(op+8, ii+8); + UA_COPY32(op+12, ii+12); +#endif + op += t; + } +#endif + else + { + if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + *op++ = 0; + while __lzo_unlikely(tt > 255) + { + tt -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } +#if defined(UA_COPY32) || defined(UA_COPY64) + do { +#if defined(UA_COPY64) + UA_COPY64(op, ii); + UA_COPY64(op+8, ii+8); +#else + UA_COPY32(op, ii); + UA_COPY32(op+4, ii+4); + UA_COPY32(op+8, ii+8); + UA_COPY32(op+12, ii+12); +#endif + op += 16; ii += 16; t -= 16; + } while (t >= 16); if (t > 0) +#endif + { do *op++ = *ii++; while (--t > 0); } + } + } + } + m_len = 4; + { +#if defined(UA_GET64) + lzo_uint64 v; + v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 8; + v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz64) + m_len += lzo_bitops_clz64(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (64 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (64 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64) + m_len += lzo_bitops_ctz64(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#elif defined(UA_GET32) + lzo_uint32 v; + v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 4; + v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz32) + m_len += lzo_bitops_clz32(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (32 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (32 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32) + m_len += lzo_bitops_ctz32(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#else + if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { + do { + m_len += 1; + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (ip[m_len] == m_pos[m_len]); + } +#endif + } +m_len_done: + m_off = pd(ip,m_pos); + ip += m_len; + ii = ip; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= M3_MAX_LEN) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= M3_MAX_LEN; + *op++ = M3_MARKER | 0; + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + else + { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + goto next; + } + + *out_len = pd(op, out); + return pd(in_end,ii-ti); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + const lzo_bytep ip = in; + lzo_bytep op = out; + lzo_uint l = in_len; + lzo_uint t = 0; + + while (l > 20) + { + lzo_uint ll = l; + lzo_uintptr_t ll_end; +#if 0 || (LZO_DETERMINISTIC) + ll = LZO_MIN(ll, 49152); +#endif + ll_end = (lzo_uintptr_t)ip + ll; + if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) + break; +#if (LZO_DETERMINISTIC) + lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); +#endif + t = do_compress(ip,ll,op,out_len,t,wrkmem); + ip += ll; + op += *out_len; + l -= ll; + } + t += l; + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + t += 3; + if (t >= 8) do + { + UA_COPY64(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY32(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY64(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN 1 +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + t += 3; + if (t >= 8) do + { + UA_COPY64(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY32(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY64(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ + diff --git a/source/goomba/minilzo-2.06/minilzo.h b/source/goomba/minilzo-2.06/minilzo.h new file mode 100644 index 0000000..cb6c556 --- /dev/null +++ b/source/goomba/minilzo-2.06/minilzo.h @@ -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 + + 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 */ + diff --git a/source/gui/gui.h b/source/gui/gui.h index bcab200..19593bc 100644 --- a/source/gui/gui.h +++ b/source/gui/gui.h @@ -123,6 +123,16 @@ typedef struct _paddata { u8 triggerR; } 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_BOTTOM 2 #define EFFECT_SLIDE_RIGHT 4 @@ -226,6 +236,7 @@ class GuiTrigger WPADData wpaddata; //!< Wii controller trigger data PADData pad; //!< GameCube controller trigger data + WUPCFullData wupcdata; //!< WiiU Pro controller trigger data WPADData * wpad; //!< Wii controller trigger 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) @@ -240,7 +251,7 @@ class GuiElement //!Constructor GuiElement(); //!Destructor - ~GuiElement(); + virtual ~GuiElement(); //!Set the element's parent //!\param e Pointer to parent element void SetParent(GuiElement * e); diff --git a/source/gui/gui_button.cpp b/source/gui/gui_button.cpp index a6941e5..2cd6f67 100644 --- a/source/gui/gui_button.cpp +++ b/source/gui/gui_button.cpp @@ -254,7 +254,7 @@ void GuiButton::Update(GuiTrigger * t) // button triggers 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++) { 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_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( (t->wpad->btns_d > 0 && (wm_btns == wm_btns_trig || (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) { @@ -303,7 +308,7 @@ void GuiButton::Update(GuiTrigger * t) if(this->IsHoldable()) { 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++) { @@ -319,11 +324,17 @@ void GuiButton::Update(GuiTrigger * t) cc_btns_h = t->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( (t->wpad->btns_d > 0 && (wm_btns == wm_btns_trig || (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 && (t->chan == stateChan || stateChan == -1)) @@ -334,7 +345,8 @@ void GuiButton::Update(GuiTrigger * t) (t->wpad->btns_h > 0 && (wm_btns_h == wm_btns_trig || (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) held = true; diff --git a/source/gui/gui_filebrowser.cpp b/source/gui/gui_filebrowser.cpp index c989fd2..f91fa83 100644 --- a/source/gui/gui_filebrowser.cpp +++ b/source/gui/gui_filebrowser.cpp @@ -39,7 +39,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h) bgFileSelectionImg = new GuiImage(bgFileSelection); bgFileSelectionImg->SetParent(this); bgFileSelectionImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - + bgFileSelectionEntry = new GuiImageData(bg_game_selection_entry_png); iconFolder = new GuiImageData(icon_folder_png); @@ -52,7 +52,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h) scrollbarImg = new GuiImage(scrollbar); scrollbarImg->SetParent(this); scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - scrollbarImg->SetPosition(0, 30); + scrollbarImg->SetPosition(0, 30); arrowDown = new GuiImageData(scrollbar_arrowdown_png); arrowDownImg = new GuiImage(arrowDown); @@ -108,12 +108,12 @@ GuiFileBrowser::GuiFileBrowser(int w, int h) fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); fileListText[i]->SetPosition(5,0); - fileListText[i]->SetMaxWidth(380); + fileListText[i]->SetMaxWidth(295); fileListBg[i] = new GuiImage(bgFileSelectionEntry); fileListIcon[i] = NULL; - fileList[i] = new GuiButton(380, 26); + fileList[i] = new GuiButton(295, 26); fileList[i]->SetParent(this); fileList[i]->SetLabel(fileListText[i]); fileList[i]->SetImageOver(fileListBg[i]); @@ -454,4 +454,4 @@ void GuiFileBrowser::Update(GuiTrigger * t) if(updateCB) updateCB(this); -} +} \ No newline at end of file diff --git a/source/gui/gui_keyboard.cpp b/source/gui/gui_keyboard.cpp index db4a964..d9476f2 100644 --- a/source/gui/gui_keyboard.cpp +++ b/source/gui/gui_keyboard.cpp @@ -22,7 +22,8 @@ static char * GetDisplayText(char * t) if(len < MAX_KEYBOARD_DISPLAY) 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]; } @@ -40,7 +41,8 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) focus = 0; // allow focus alignmentHor = ALIGN_CENTRE; alignmentVert = ALIGN_MIDDLE; - snprintf(kbtextstr, 255, "%s", t); + strncpy(kbtextstr, t, max); + kbtextstr[max] = 0; kbtextmaxlen = max; Key thekeys[4][11] = { @@ -106,7 +108,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyTextboxImg->SetPosition(0, 0); 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->SetPosition(0, 13); this->Append(kbText); @@ -128,7 +130,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyBackImg = new GuiImage(keyMedium); 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->SetImage(keyBackImg); keyBack->SetImageOver(keyBackOverImg); @@ -143,7 +145,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyCapsImg = new GuiImage(keyMedium); 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->SetImage(keyCapsImg); keyCaps->SetImageOver(keyCapsOverImg); @@ -158,7 +160,7 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) keyShiftImg = new GuiImage(keyMedium); 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->SetImage(keyShiftImg); keyShift->SetImageOver(keyShiftOverImg); @@ -196,9 +198,9 @@ GuiKeyboard::GuiKeyboard(char * t, u32 max) txt[0] = keys[i][j].ch; keyImg[i][j] = new GuiImage(key); 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]->SetPosition(0, -8); + keyTxt[i][j]->SetPosition(0, -10); keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight()); keyBtn[i][j]->SetImage(keyImg[i][j]); keyBtn[i][j]->SetImageOver(keyImgOver[i][j]); @@ -289,7 +291,7 @@ void GuiKeyboard::Update(GuiTrigger * t) else if(keyBack->GetState() == STATE_CLICKED) { if(strlen(kbtextstr) > 0) - { + { kbtextstr[strlen(kbtextstr)-1] = 0; kbText->SetText(GetDisplayText(kbtextstr)); } diff --git a/source/gui/gui_trigger.cpp b/source/gui/gui_trigger.cpp index 06a4165..fcf8072 100644 --- a/source/gui/gui_trigger.cpp +++ b/source/gui/gui_trigger.cpp @@ -22,6 +22,7 @@ static u32 delay[4]; GuiTrigger::GuiTrigger() { chan = -1; + memset(&wupcdata, 0, sizeof(WUPCFullData)); memset(&wpaddata, 0, sizeof(WPADData)); memset(&pad, 0, sizeof(PADData)); wpad = &wpaddata; @@ -43,6 +44,7 @@ void GuiTrigger::SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns) { type = TRIGGER_SIMPLE; chan = ch; + wupcdata.btns_d = wiibtns; wpaddata.btns_d = wiibtns; pad.btns_d = gcbtns; } @@ -56,6 +58,7 @@ void GuiTrigger::SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns) { type = TRIGGER_HELD; chan = ch; + wupcdata.btns_h = wiibtns; wpaddata.btns_h = wiibtns; pad.btns_h = gcbtns; } @@ -68,6 +71,7 @@ void GuiTrigger::SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns) { type = TRIGGER_BUTTON_ONLY; chan = ch; + wupcdata.btns_d = wiibtns; wpaddata.btns_d = wiibtns; pad.btns_d = gcbtns; } @@ -81,6 +85,7 @@ void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns) { type = TRIGGER_BUTTON_ONLY_IN_FOCUS; chan = ch; + wupcdata.btns_d = wiibtns; wpaddata.btns_d = wiibtns; pad.btns_d = gcbtns; } @@ -158,12 +163,15 @@ bool GuiTrigger::Left() u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_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.stickX < -PADCAL - || WPAD_StickX(0) < -PADCAL) + || WPAD_StickX(0) < -PADCAL + || wupcdata.stickX < -WUPCCAL) { - if(wpad->btns_d & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) - || pad.btns_d & PAD_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) { prev[chan] = gettime(); delay[chan] = SCROLL_DELAY_INITIAL; // reset scroll delay @@ -191,11 +199,14 @@ bool GuiTrigger::Right() u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_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.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) { prev[chan] = gettime(); @@ -223,12 +234,15 @@ bool GuiTrigger::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.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) { prev[chan] = gettime(); @@ -256,12 +270,15 @@ bool GuiTrigger::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.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) { prev[chan] = gettime(); diff --git a/source/gui/gui_window.cpp b/source/gui/gui_window.cpp index fd5e785..636d8ba 100644 --- a/source/gui/gui_window.cpp +++ b/source/gui/gui_window.cpp @@ -228,8 +228,8 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) } } // change focus - else if(t->wpad->btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B) - || t->pad.btns_d & PAD_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->wupcdata.btns_d & WPAD_CLASSIC_BUTTON_B)) { for (i = found; i < elemSize; ++i) { diff --git a/source/images/bg_preview.png b/source/images/bg_preview.png new file mode 100644 index 0000000..ea8a1fe Binary files /dev/null and b/source/images/bg_preview.png differ diff --git a/source/images/button_prompt.png b/source/images/button_prompt.png index be25c25..7e1f62e 100644 Binary files a/source/images/button_prompt.png and b/source/images/button_prompt.png differ diff --git a/source/images/button_prompt_over.png b/source/images/button_prompt_over.png index 8d839b1..a55dbd4 100644 Binary files a/source/images/button_prompt_over.png and b/source/images/button_prompt_over.png differ diff --git a/source/images/dialogue_box.png b/source/images/dialogue_box.png index a02328f..575b8c5 100644 Binary files a/source/images/dialogue_box.png and b/source/images/dialogue_box.png differ diff --git a/source/images/icon_settings_screenshot.png b/source/images/icon_settings_screenshot.png new file mode 100644 index 0000000..6cc3a45 Binary files /dev/null and b/source/images/icon_settings_screenshot.png differ diff --git a/source/images/icon_settings_wiiupro.png b/source/images/icon_settings_wiiupro.png new file mode 100644 index 0000000..69eeeed Binary files /dev/null and b/source/images/icon_settings_wiiupro.png differ diff --git a/source/input.cpp b/source/input.cpp index 142d0fd..027a3df 100644 --- a/source/input.cpp +++ b/source/input.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "vbagx.h" @@ -138,6 +139,7 @@ void UpdatePads() { #ifdef HW_RVL + WUPC_UpdateButtonStats(); WPAD_ScanPads(); #endif @@ -154,6 +156,15 @@ UpdatePads() userInput[i].pad.substickY = PAD_SubStickY(i); userInput[i].pad.triggerL = PAD_TriggerL(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; } while(i >= 0); } @@ -311,6 +322,9 @@ u32 StandardMovement(unsigned short chan) #ifdef HW_RVL s8 wm_ax = userInput[0].WPAD_StickX(0); s8 wm_ay = userInput[0].WPAD_StickY(0); + + s16 wupc_ax = userInput[chan].wupcdata.stickX; + s16 wupc_ay = userInput[chan].wupcdata.stickY; #endif /*** @@ -338,7 +352,19 @@ u32 StandardMovement(unsigned short chan) if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL) { 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) J |= VBA_RIGHT; else if(cos(angle) < -THRES) @@ -380,7 +406,19 @@ u32 StandardDPad(unsigned short pad) if (wp & WPAD_CLASSIC_BUTTON_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 + if (jp & PAD_BUTTON_UP) J |= VBA_UP; if (jp & PAD_BUTTON_DOWN) @@ -436,7 +474,8 @@ u32 StandardClassic(unsigned short pad) { u32 J = 0; #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) J |= VBA_RIGHT; @@ -535,6 +574,14 @@ u32 DecodeClassic(unsigned short pad) #ifdef HW_RVL WPADData * wp = WPAD_Data(pad); 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){ for (u32 i = 0; i < MAXJP; ++i){ @@ -811,13 +858,16 @@ static u32 DecodeJoy(unsigned short pad) case CVHARMONY: case CVARIA: 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 u32 J = StandardMovement(pad); // 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; // Report pressed buttons (gamepads) @@ -849,6 +899,7 @@ static u32 DecodeJoy(unsigned short pad) } } + else if(wpad_exp_type == WPAD_EXP_NUNCHUK) { // nunchuk + wiimote @@ -858,8 +909,8 @@ static u32 DecodeJoy(unsigned short pad) || ( (wpad_btns_h & btnmap[CTRLR_NUNCHUK][i]) )) J |= vbapadmap[i]; } - } + else // Check out this trickery! // If all else fails OR if HW_RVL is undefined, the result is the same @@ -871,31 +922,37 @@ static u32 DecodeJoy(unsigned short pad) 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; } bool MenuRequested() { - if( (userInput[0].pad.substickX < -70) || - (userInput[0].wpad->btns_h & WPAD_BUTTON_HOME) || - (userInput[0].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME) - || - (userInput[1].pad.substickX < -70) || - (userInput[1].wpad->btns_h & WPAD_BUTTON_HOME) || - (userInput[1].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME) - || - (userInput[2].pad.substickX < -70) || - (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) +for(int i=0; i<4; i++) + { + if ( + (userInput[i].pad.substickX < -70) + #ifdef HW_RVL + || (userInput[i].wpad->btns_h & WPAD_BUTTON_HOME) || + (userInput[i].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME) || + (userInput[i].wupcdata.btns_h & WPAD_CLASSIC_BUTTON_HOME) + #endif ) - { - return true; - } - return false; + { + return true; + } + return false; +} } u32 GetJoy(int pad) @@ -915,5 +972,6 @@ u32 GetJoy(int pad) if ((J & 192) == 192) J &= ~128; updateRumbleFrame(); + return J; } diff --git a/source/input.h b/source/input.h index 5fc20cd..f820d21 100644 --- a/source/input.h +++ b/source/input.h @@ -16,6 +16,7 @@ #define PI 3.14159265f #define PADCAL 50 +#define WUPCCAL 400 #define MAXJP 10 // # of mappable controller buttons #define VBA_BUTTON_A 1 diff --git a/source/inputmario.cpp b/source/inputmario.cpp index 0276fca..cb7f51e 100644 --- a/source/inputmario.cpp +++ b/source/inputmario.cpp @@ -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) J |= VBA_BUTTON_B; // 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; - // 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 if (wp->btns_h & WPAD_CLASSIC_BUTTON_ZL && (!(wp->btns_h & WPAD_CLASSIC_BUTTON_A))) { J |= VBA_DOWN; diff --git a/source/lang/es.lang b/source/lang/es.lang index ad7b51c..b1b943e 100644 --- a/source/lang/es.lang +++ b/source/lang/es.lang @@ -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." 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)" msgstr "Progresivo (480p)" diff --git a/source/menu.cpp b/source/menu.cpp index 9875297..3147eb1 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -1,4407 +1,4772 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric 2008-2009 - * - * menu.cpp - * - * Menu flow routines - handles all menu logic - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HW_RVL -#include -#endif - -#include "vbagx.h" -#include "vbasupport.h" -#include "video.h" -#include "filebrowser.h" -#include "gcunzip.h" -#include "networkop.h" -#include "fileop.h" -#include "preferences.h" -#include "button_mapping.h" -#include "input.h" -#include "filelist.h" -#include "menu.h" -#include "gamesettings.h" -#include "gui/gui.h" -#include "utils/gettext.h" - -#define THREAD_SLEEP 100 - -#ifdef HW_RVL -GuiImageData * pointer[4]; -#endif - -static GuiTrigger * trigA = NULL; -static GuiTrigger * trig2 = NULL; - -static GuiButton * btnLogo = NULL; -static GuiImageData * gameScreen = NULL; -static GuiImage * gameScreenImg = NULL; -static GuiImage * bgTopImg = NULL; -static GuiImage * bgBottomImg = NULL; -static GuiSound * bgMusic = NULL; -static GuiSound * enterSound = NULL; -static GuiSound * exitSound = NULL; -static GuiWindow * mainWindow = NULL; -static GuiText * settingText = NULL; -static GuiText * settingText2 = NULL; -static int lastMenu = MENU_NONE; -static int mapMenuCtrl = 0; - -static lwp_t guithread = LWP_THREAD_NULL; -static lwp_t progressthread = LWP_THREAD_NULL; -#ifdef HW_RVL -static lwp_t updatethread = LWP_THREAD_NULL; -#endif -static bool guiHalt = true; -static int showProgress = 0; - -static char progressTitle[101]; -static char progressMsg[201]; -static int progressDone = 0; -static int progressTotal = 0; - -/**************************************************************************** - * ResumeGui - * - * Signals the GUI thread to start, and resumes the thread. This is called - * after finishing the removal/insertion of new elements, and after initial - * GUI setup. - ***************************************************************************/ -static void -ResumeGui() -{ - guiHalt = false; - LWP_ResumeThread (guithread); -} - -/**************************************************************************** - * HaltGui - * - * Signals the GUI thread to stop, and waits for GUI thread to stop - * This is necessary whenever removing/inserting new elements into the GUI. - * This eliminates the possibility that the GUI is in the middle of accessing - * an element that is being changed. - ***************************************************************************/ -static void -HaltGui() -{ - guiHalt = true; - - // wait for thread to finish - while(!LWP_ThreadIsSuspended(guithread)) - usleep(THREAD_SLEEP); -} - -void ResetText() -{ - LoadLanguage(); - - if(mainWindow) - mainWindow->ResetText(); -} - -/**************************************************************************** - * WindowPrompt - * - * Displays a prompt window to user, with information, an error message, or - * presenting a user with a choice - ***************************************************************************/ -int -WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) -{ - if(!mainWindow || ExitRequested || ShutdownRequested) - return 0; - - int choice = -1; - - GuiWindow promptWindow(448,288); - promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - promptWindow.SetPosition(0, -10); - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_prompt_png); - GuiImageData btnOutlineOver(button_prompt_over_png); - - GuiImageData dialogBox(dialogue_box_png); - GuiImage dialogBoxImg(&dialogBox); - - GuiText titleTxt(title, 26, (GXColor){25, 100, 10, 255}); - titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - titleTxt.SetPosition(0,14); - GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); - msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - msgTxt.SetPosition(0,-20); - msgTxt.SetWrap(true, 430); - - GuiText btn1Txt(btn1Label, 22, (GXColor){0, 0, 0, 255}); - GuiImage btn1Img(&btnOutline); - GuiImage btn1ImgOver(&btnOutlineOver); - GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); - - if(btn2Label) - { - btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - btn1.SetPosition(20, -25); - } - else - { - btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); - btn1.SetPosition(0, -25); - } - - btn1.SetLabel(&btn1Txt); - btn1.SetImage(&btn1Img); - btn1.SetImageOver(&btn1ImgOver); - btn1.SetSoundOver(&btnSoundOver); - btn1.SetSoundClick(&btnSoundClick); - btn1.SetTrigger(trigA); - btn1.SetTrigger(trig2); - btn1.SetState(STATE_SELECTED); - btn1.SetEffectGrow(); - - GuiText btn2Txt(btn2Label, 22, (GXColor){0, 0, 0, 255}); - GuiImage btn2Img(&btnOutline); - GuiImage btn2ImgOver(&btnOutlineOver); - GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); - btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - btn2.SetPosition(-20, -25); - btn2.SetLabel(&btn2Txt); - btn2.SetImage(&btn2Img); - btn2.SetImageOver(&btn2ImgOver); - btn2.SetSoundOver(&btnSoundOver); - btn2.SetSoundClick(&btnSoundClick); - btn2.SetTrigger(trigA); - btn2.SetTrigger(trig2); - btn2.SetEffectGrow(); - - promptWindow.Append(&dialogBoxImg); - promptWindow.Append(&titleTxt); - promptWindow.Append(&msgTxt); - promptWindow.Append(&btn1); - - if(btn2Label) - promptWindow.Append(&btn2); - - promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); - CancelAction(); - HaltGui(); - mainWindow->SetState(STATE_DISABLED); - mainWindow->Append(&promptWindow); - mainWindow->ChangeFocus(&promptWindow); - if(btn2Label) - { - btn1.ResetState(); - btn2.SetState(STATE_SELECTED); - } - ResumeGui(); - - while(choice == -1) - { - usleep(THREAD_SLEEP); - - if(btn1.GetState() == STATE_CLICKED) - choice = 1; - else if(btn2.GetState() == STATE_CLICKED) - choice = 0; - } - - promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); - while(promptWindow.GetEffect() > 0) usleep(THREAD_SLEEP); - HaltGui(); - mainWindow->Remove(&promptWindow); - mainWindow->SetState(STATE_DEFAULT); - ResumeGui(); - return choice; -} - -#ifdef HW_RVL -/**************************************************************************** - * EmulatorUpdate - * - * Prompts for confirmation, and downloads/installs updates - ***************************************************************************/ -static void * -EmulatorUpdate (void *arg) -{ - bool installUpdate = WindowPrompt( - "Update Available", - "An update is available!", - "Update now", - "Update later"); - if(installUpdate) - if(DownloadUpdate()) - ExitRequested = 1; - return NULL; -} -#endif - -/**************************************************************************** - * UpdateGUI - * - * Primary thread to allow GUI to respond to state changes, and draws GUI - ***************************************************************************/ -static void * -UpdateGUI (void *arg) -{ - int i; - - while(1) - { - if(guiHalt) - LWP_SuspendThread(guithread); - - UpdatePads(); - mainWindow->Draw(); - - if (mainWindow->GetState() != STATE_DISABLED) - mainWindow->DrawTooltip(); - - #ifdef HW_RVL - i = 3; - do - { - if(userInput[i].wpad->ir.valid) - Menu_DrawImg(userInput[i].wpad->ir.x-48, userInput[i].wpad->ir.y-48, - 96, 96, pointer[i]->GetImage(), userInput[i].wpad->ir.angle, 1, 1, 255); - DoRumble(i); - --i; - } while(i>=0); - #endif - - Menu_Render(); - - mainWindow->Update(&userInput[3]); - mainWindow->Update(&userInput[2]); - mainWindow->Update(&userInput[1]); - mainWindow->Update(&userInput[0]); - - #ifdef HW_RVL - if(updateFound) - { - updateFound = false; - if(!loadingFile) - LWP_CreateThread (&updatethread, EmulatorUpdate, NULL, NULL, 0, 70); - } - #endif - - if(ExitRequested || ShutdownRequested) - { - for(i = 0; i <= 255; i += 15) - { - mainWindow->Draw(); - Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, i},1); - Menu_Render(); - } - ExitApp(); - } - usleep(THREAD_SLEEP); - } - return NULL; -} - -/**************************************************************************** - * ProgressWindow - * - * Opens a window, which displays progress to the user. Can either display a - * progress bar showing % completion, or a throbber that only shows that an - * action is in progress. - ***************************************************************************/ -static int progsleep = 0; - -static void -ProgressWindow(char *title, char *msg) -{ - GuiWindow promptWindow(448,288); - promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - promptWindow.SetPosition(0, -10); - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - - GuiImageData dialogBox(dialogue_box_png); - GuiImage dialogBoxImg(&dialogBox); - - GuiImageData progressbarOutline(progressbar_outline_png); - GuiImage progressbarOutlineImg(&progressbarOutline); - progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - progressbarOutlineImg.SetPosition(25, 40); - - GuiImageData progressbarEmpty(progressbar_empty_png); - GuiImage progressbarEmptyImg(&progressbarEmpty); - progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - progressbarEmptyImg.SetPosition(25, 40); - progressbarEmptyImg.SetTile(100); - - GuiImageData progressbar(progressbar_png); - GuiImage progressbarImg(&progressbar); - progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - progressbarImg.SetPosition(25, 40); - - GuiImageData throbber(throbber_png); - GuiImage throbberImg(&throbber); - throbberImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - throbberImg.SetPosition(0, 40); - - GuiText titleTxt(title, 26, (GXColor){25, 100, 10, 255}); - titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - titleTxt.SetPosition(0,14); - GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); - msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - msgTxt.SetPosition(0,80); - - promptWindow.Append(&dialogBoxImg); - promptWindow.Append(&titleTxt); - promptWindow.Append(&msgTxt); - - if(showProgress == 1) - { - promptWindow.Append(&progressbarEmptyImg); - promptWindow.Append(&progressbarImg); - promptWindow.Append(&progressbarOutlineImg); - } - else - { - promptWindow.Append(&throbberImg); - } - - // wait to see if progress flag changes soon - progsleep = 800000; - - while(progsleep > 0) - { - if(!showProgress) - break; - usleep(THREAD_SLEEP); - progsleep -= THREAD_SLEEP; - } - - if(!showProgress) - return; - - HaltGui(); - int oldState = mainWindow->GetState(); - mainWindow->SetState(STATE_DISABLED); - mainWindow->Append(&promptWindow); - mainWindow->ChangeFocus(&promptWindow); - ResumeGui(); - - float angle = 0; - u32 count = 0; - - while(showProgress) - { - progsleep = 20000; - - while(progsleep > 0) - { - if(!showProgress) - break; - usleep(THREAD_SLEEP); - progsleep -= THREAD_SLEEP; - } - - if(showProgress == 1) - { - progressbarImg.SetTile(100*progressDone/progressTotal); - } - else if(showProgress == 2) - { - if(count % 5 == 0) - { - angle+=45.0f; - if(angle >= 360.0f) - angle = 0; - throbberImg.SetAngle(angle); - } - ++count; - } - } - - HaltGui(); - mainWindow->Remove(&promptWindow); - mainWindow->SetState(oldState); - ResumeGui(); -} - -static void * ProgressThread (void *arg) -{ - while(1) - { - if(!showProgress) - LWP_SuspendThread (progressthread); - - ProgressWindow(progressTitle, progressMsg); - usleep(THREAD_SLEEP); - } - return NULL; -} - -/**************************************************************************** - * InitGUIThread - * - * Startup GUI threads - ***************************************************************************/ -void -InitGUIThreads() -{ - LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70); - LWP_CreateThread (&progressthread, ProgressThread, NULL, NULL, 0, 40); -} - -/**************************************************************************** - * CancelAction - * - * Signals the GUI progress window thread to halt, and waits for it to - * finish. Prevents multiple progress window events from interfering / - * overriding each other. - ***************************************************************************/ -void -CancelAction() -{ - showProgress = 0; - - // wait for thread to finish - while(!LWP_ThreadIsSuspended(progressthread)) - usleep(THREAD_SLEEP); -} - -/**************************************************************************** - * ShowProgress - * - * Updates the variables used by the progress window for drawing a progress - * bar. Also resumes the progress window thread if it is suspended. - ***************************************************************************/ -void -ShowProgress (const char *msg, int done, int total) -{ - if(!mainWindow || ExitRequested || ShutdownRequested) - return; - - if(total < (256*1024)) - return; - - if(done > total) // this shouldn't happen - done = total; - - if(showProgress != 1) - CancelAction(); // wait for previous progress window to finish - - snprintf(progressMsg, 200, "%s", msg); - sprintf(progressTitle, "Please Wait"); - showProgress = 1; - progressTotal = total; - progressDone = done; - LWP_ResumeThread (progressthread); -} - -/**************************************************************************** - * ShowAction - * - * Shows that an action is underway. Also resumes the progress window thread - * if it is suspended. - ***************************************************************************/ -void -ShowAction (const char *msg) -{ - if(!mainWindow || ExitRequested || ShutdownRequested) - return; - - if(showProgress != 0) - CancelAction(); // wait for previous progress window to finish - - snprintf(progressMsg, 200, "%s", msg); - sprintf(progressTitle, "Please Wait"); - showProgress = 2; - progressDone = 0; - progressTotal = 0; - LWP_ResumeThread (progressthread); -} - -void ErrorPrompt(const char *msg) -{ - WindowPrompt("Error", msg, "OK", NULL); -} - -int ErrorPromptRetry(const char *msg) -{ - return WindowPrompt("Error", msg, "Retry", "Cancel"); -} - -void InfoPrompt(const char *msg) -{ - WindowPrompt("Information", msg, "OK", NULL); -} - -/**************************************************************************** - * OnScreenKeyboard - * - * Opens an on-screen keyboard window, with the data entered being stored - * into the specified variable. - ***************************************************************************/ -static void OnScreenKeyboard(char * var, u32 maxlen) -{ - int save = -1; - - GuiKeyboard keyboard(var, maxlen); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - - GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); - GuiImage okBtnImg(&btnOutline); - GuiImage okBtnImgOver(&btnOutlineOver); - GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - - okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - okBtn.SetPosition(25, -25); - - okBtn.SetLabel(&okBtnTxt); - okBtn.SetImage(&okBtnImg); - okBtn.SetImageOver(&okBtnImgOver); - okBtn.SetSoundOver(&btnSoundOver); - okBtn.SetSoundClick(&btnSoundClick); - okBtn.SetTrigger(trigA); - okBtn.SetTrigger(trig2); - okBtn.SetEffectGrow(); - - GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); - GuiImage cancelBtnImg(&btnOutline); - GuiImage cancelBtnImgOver(&btnOutlineOver); - GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - cancelBtn.SetPosition(-25, -25); - cancelBtn.SetLabel(&cancelBtnTxt); - cancelBtn.SetImage(&cancelBtnImg); - cancelBtn.SetImageOver(&cancelBtnImgOver); - cancelBtn.SetSoundOver(&btnSoundOver); - cancelBtn.SetSoundClick(&btnSoundClick); - cancelBtn.SetTrigger(trigA); - cancelBtn.SetTrigger(trig2); - cancelBtn.SetEffectGrow(); - - keyboard.Append(&okBtn); - keyboard.Append(&cancelBtn); - - HaltGui(); - mainWindow->SetState(STATE_DISABLED); - mainWindow->Append(&keyboard); - mainWindow->ChangeFocus(&keyboard); - ResumeGui(); - - while(save == -1) - { - usleep(THREAD_SLEEP); - - if(okBtn.GetState() == STATE_CLICKED) - save = 1; - else if(cancelBtn.GetState() == STATE_CLICKED) - save = 0; - } - - if(save) - { - snprintf(var, maxlen, "%s", keyboard.kbtextstr); - } - - HaltGui(); - mainWindow->Remove(&keyboard); - mainWindow->SetState(STATE_DEFAULT); - ResumeGui(); -} - -/**************************************************************************** - * SettingWindow - * - * Opens a new window, with the specified window element appended. Allows - * for a customizable prompted setting. - ***************************************************************************/ -static int -SettingWindow(const char * title, GuiWindow * w) -{ - int save = -1; - - GuiWindow promptWindow(448,288); - promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - - GuiImageData dialogBox(dialogue_box_png); - GuiImage dialogBoxImg(&dialogBox); - - GuiText titleTxt(title, 26, (GXColor){25, 100, 10, 255}); - titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - titleTxt.SetPosition(0,14); - - GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); - GuiImage okBtnImg(&btnOutline); - GuiImage okBtnImgOver(&btnOutlineOver); - GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - - okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - okBtn.SetPosition(20, -25); - - okBtn.SetLabel(&okBtnTxt); - okBtn.SetImage(&okBtnImg); - okBtn.SetImageOver(&okBtnImgOver); - okBtn.SetSoundOver(&btnSoundOver); - okBtn.SetSoundClick(&btnSoundClick); - okBtn.SetTrigger(trigA); - okBtn.SetTrigger(trig2); - okBtn.SetEffectGrow(); - - GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); - GuiImage cancelBtnImg(&btnOutline); - GuiImage cancelBtnImgOver(&btnOutlineOver); - GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - cancelBtn.SetPosition(-20, -25); - cancelBtn.SetLabel(&cancelBtnTxt); - cancelBtn.SetImage(&cancelBtnImg); - cancelBtn.SetImageOver(&cancelBtnImgOver); - cancelBtn.SetSoundOver(&btnSoundOver); - cancelBtn.SetSoundClick(&btnSoundClick); - cancelBtn.SetTrigger(trigA); - cancelBtn.SetTrigger(trig2); - cancelBtn.SetEffectGrow(); - - promptWindow.Append(&dialogBoxImg); - promptWindow.Append(&titleTxt); - promptWindow.Append(&okBtn); - promptWindow.Append(&cancelBtn); - - HaltGui(); - mainWindow->SetState(STATE_DISABLED); - mainWindow->Append(&promptWindow); - mainWindow->Append(w); - mainWindow->ChangeFocus(w); - ResumeGui(); - - while(save == -1) - { - usleep(THREAD_SLEEP); - - if(okBtn.GetState() == STATE_CLICKED) - save = 1; - else if(cancelBtn.GetState() == STATE_CLICKED) - save = 0; - } - HaltGui(); - mainWindow->Remove(&promptWindow); - mainWindow->Remove(w); - mainWindow->SetState(STATE_DEFAULT); - ResumeGui(); - return save; -} - -/**************************************************************************** - * WindowCredits - * Display credits, legal copyright and licence - * - * THIS MUST NOT BE REMOVED OR DISABLED IN ANY DERIVATIVE WORK - ***************************************************************************/ -static void WindowCredits(void * ptr) -{ - if(btnLogo->GetState() != STATE_CLICKED) - return; - - btnLogo->ResetState(); - - bool exit = false; - int i = 0; - int y = 20; - - GuiWindow creditsWindow(screenwidth,screenheight); - GuiWindow creditsWindowBox(580,448); - creditsWindowBox.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - - GuiImageData creditsBox(credits_box_png); - GuiImage creditsBoxImg(&creditsBox); - creditsBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - creditsWindowBox.Append(&creditsBoxImg); - - int numEntries = 24; - GuiText * txt[numEntries]; - - txt[i] = new GuiText("Credits", 30, (GXColor){0, 0, 0, 255}); - txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=32; - - txt[i] = new GuiText("Official Site: http://code.google.com/p/vba-wii/", 20, (GXColor){0, 0, 0, 255}); - txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=40; - - txt[i]->SetPresets(20, (GXColor){0, 0, 0, 255}, 0, - FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP); - - txt[i] = new GuiText("Coding & menu design"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("Tantric"); - txt[i]->SetPosition(335,y); i++; y+=24; - txt[i] = new GuiText("Additional coding"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("Carl Kenner, dancinninjac"); - txt[i]->SetPosition(335,y); i++; y+=24; - txt[i] = new GuiText("Menu artwork"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("the3seashells"); - txt[i]->SetPosition(335,y); i++; y+=24; - txt[i] = new GuiText("Menu sound"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("Peter de Man"); - txt[i]->SetPosition(335,y); i++; y+=48; - - txt[i] = new GuiText("VBA GameCube"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("SoftDev, emukidid"); - txt[i]->SetPosition(335,y); i++; y+=24; - txt[i] = new GuiText("Visual Boy Advance - M"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("VBA-M Team"); - txt[i]->SetPosition(335,y); i++; y+=24; - txt[i] = new GuiText("Visual Boy Advance"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("Forgotten"); - txt[i]->SetPosition(335,y); i++; y+=24; - - txt[i] = new GuiText("libogc / devkitPPC"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("shagkur & wintermute"); - txt[i]->SetPosition(335,y); i++; y+=24; - txt[i] = new GuiText("FreeTypeGX"); - txt[i]->SetPosition(40,y); i++; - txt[i] = new GuiText("Armin Tamzarian"); - txt[i]->SetPosition(335,y); i++; y+=48; - - txt[i]->SetPresets(18, (GXColor){0, 0, 0, 255}, 0, - FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP, ALIGN_CENTRE, ALIGN_TOP); - - txt[i] = new GuiText("This software is open source and may be copied,"); - txt[i]->SetPosition(0,y); i++; y+=20; - txt[i] = new GuiText("distributed, or modified under the terms of the"); - txt[i]->SetPosition(0,y); i++; y+=20; - txt[i] = new GuiText("GNU General Public License (GPL) Version 2."); - txt[i]->SetPosition(0,y); i++; y+=20; - - char iosVersion[20]; - -#ifdef HW_RVL - sprintf(iosVersion, "IOS: %d", IOS_GetVersion()); -#endif - - txt[i] = new GuiText(iosVersion, 18, (GXColor){0, 0, 0, 255}); - txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - txt[i]->SetPosition(20,-20); - - for(i=0; i < numEntries; i++) - creditsWindowBox.Append(txt[i]); - - creditsWindow.Append(&creditsWindowBox); - - while(!exit) - { - UpdatePads(); - - gameScreenImg->Draw(); - bgBottomImg->Draw(); - bgTopImg->Draw(); - creditsWindow.Draw(); - - #ifdef HW_RVL - i = 3; - do { - if(userInput[i].wpad->ir.valid) - Menu_DrawImg(userInput[i].wpad->ir.x-48, userInput[i].wpad->ir.y-48, - 96, 96, pointer[i]->GetImage(), userInput[i].wpad->ir.angle, 1, 1, 255); - DoRumble(i); - --i; - } while(i >= 0); - #endif - - Menu_Render(); - - if((userInput[0].wpad->btns_d || userInput[0].pad.btns_d) || - (userInput[1].wpad->btns_d || userInput[1].pad.btns_d) || - (userInput[2].wpad->btns_d || userInput[2].pad.btns_d) || - (userInput[3].wpad->btns_d || userInput[3].pad.btns_d)){ - exit = true; - } - usleep(THREAD_SLEEP); - } - - // clear buttons pressed - for(i=0; i < 4; i++) - { - userInput[i].wpad->btns_d = 0; - userInput[i].pad.btns_d = 0; - } - - for(i=0; i < numEntries; i++) - delete txt[i]; -} - -/**************************************************************************** - * MenuGameSelection - * - * Displays a list of games on the specified load device, and allows the user - * to browse and select from this list. - ***************************************************************************/ -static int MenuGameSelection() -{ - int menu = MENU_NONE; - bool res; - int i; - - GuiText titleTxt("Choose Game", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData iconHome(icon_home_png); - GuiImageData iconSettings(icon_settings_png); - GuiImageData btnOutline(button_long_png); - GuiImageData btnOutlineOver(button_long_over_png); - - GuiTrigger trigHome; - trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); - - GuiText settingsBtnTxt("Settings", 22, (GXColor){0, 0, 0, 255}); - GuiImage settingsBtnIcon(&iconSettings); - settingsBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - settingsBtnIcon.SetPosition(14,0); - GuiImage settingsBtnImg(&btnOutline); - GuiImage settingsBtnImgOver(&btnOutlineOver); - GuiButton settingsBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - settingsBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - settingsBtn.SetPosition(90, -35); - settingsBtn.SetLabel(&settingsBtnTxt); - settingsBtn.SetIcon(&settingsBtnIcon); - settingsBtn.SetImage(&settingsBtnImg); - settingsBtn.SetImageOver(&settingsBtnImgOver); - settingsBtn.SetSoundOver(&btnSoundOver); - settingsBtn.SetSoundClick(&btnSoundClick); - settingsBtn.SetTrigger(trigA); - settingsBtn.SetTrigger(trig2); - settingsBtn.SetEffectGrow(); - - GuiText exitBtnTxt("Exit", 22, (GXColor){0, 0, 0, 255}); - GuiImage exitBtnIcon(&iconHome); - exitBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - exitBtnIcon.SetPosition(14,0); - GuiImage exitBtnImg(&btnOutline); - GuiImage exitBtnImgOver(&btnOutlineOver); - GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - exitBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - exitBtn.SetPosition(-90, -35); - exitBtn.SetLabel(&exitBtnTxt); - exitBtn.SetIcon(&exitBtnIcon); - exitBtn.SetImage(&exitBtnImg); - exitBtn.SetImageOver(&exitBtnImgOver); - exitBtn.SetSoundOver(&btnSoundOver); - exitBtn.SetSoundClick(&btnSoundClick); - exitBtn.SetTrigger(trigA); - exitBtn.SetTrigger(trig2); - exitBtn.SetTrigger(&trigHome); - exitBtn.SetEffectGrow(); - - GuiWindow buttonWindow(screenwidth, screenheight); - buttonWindow.Append(&settingsBtn); - buttonWindow.Append(&exitBtn); - - GuiFileBrowser gameBrowser(424, 268); - gameBrowser.SetPosition(50, 98); - ResetBrowser(); - - HaltGui(); - btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - btnLogo->SetPosition(-50, 24); - mainWindow->Append(&titleTxt); - mainWindow->Append(&gameBrowser); - mainWindow->Append(&buttonWindow); - ResumeGui(); - - #ifdef HW_RVL - ShutoffRumble(); - #endif - - // populate initial directory listing - selectLoadedFile = 1; - OpenGameList(); - - gameBrowser.ResetState(); - gameBrowser.fileList[0]->SetState(STATE_SELECTED); - gameBrowser.TriggerUpdate(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - if(selectLoadedFile == 2) - { - selectLoadedFile = 0; - mainWindow->ChangeFocus(&gameBrowser); - gameBrowser.TriggerUpdate(); - } - - // update gameWindow based on arrow buttons - // set MENU_EXIT if A button pressed on a game - for(i=0; i < FILE_PAGESIZE; ++i) - { - if(gameBrowser.fileList[i]->GetState() == STATE_CLICKED) - { - gameBrowser.fileList[i]->ResetState(); - // check corresponding browser entry - if(browserList[browser.selIndex].isdir || IsSz()) - { - if(IsSz()) - res = BrowserLoadSz(); - else - res = BrowserChangeFolder(); - - if(res) - { - gameBrowser.ResetState(); - gameBrowser.fileList[0]->SetState(STATE_SELECTED); - gameBrowser.TriggerUpdate(); - } - else - { - menu = MENU_GAMESELECTION; - break; - } - } - else - { - #ifdef HW_RVL - ShutoffRumble(); - #endif - mainWindow->SetState(STATE_DISABLED); - if(BrowserLoadFile()) - menu = MENU_EXIT; - else - mainWindow->SetState(STATE_DEFAULT); - } - } - } - - if(settingsBtn.GetState() == STATE_CLICKED) - menu = MENU_SETTINGS; - else if(exitBtn.GetState() == STATE_CLICKED) - ExitRequested = 1; - } - - HaltParseThread(); // halt parsing - HaltGui(); - ResetBrowser(); - mainWindow->Remove(&titleTxt); - mainWindow->Remove(&buttonWindow); - mainWindow->Remove(&gameBrowser); - return menu; -} - -extern char DebugStr[50]; - -/**************************************************************************** - * MenuGame - * - * Menu displayed when returning to the menu from in-game. - ***************************************************************************/ -static int MenuGame() -{ - int menu = MENU_NONE; - - // Weather menu if a game with Boktai solar sensor - bool isBoktai = ((RomIdCode & 0xFF)=='U'); - char s[64]; - - GuiText titleTxt(ROMFilename, 22, (GXColor){255, 255, 255, 255}); - if (DebugStr[0]) titleTxt.SetText(DebugStr); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - GuiImageData btnCloseOutline(button_small_png); - GuiImageData btnCloseOutlineOver(button_small_over_png); - GuiImageData btnLargeOutline(button_large_png); - GuiImageData btnLargeOutlineOver(button_large_over_png); - GuiImageData iconGameSettings(icon_game_settings_png); - GuiImageData iconLoad(icon_game_load_png); - GuiImageData iconSave(icon_game_save_png); - GuiImageData iconReset(icon_game_reset_png); - - GuiImageData battery(battery_png); - GuiImageData batteryRed(battery_red_png); - GuiImageData batteryBar(battery_bar_png); - - GuiTrigger trigHome; - trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); - - int xOffset=125, yOffset=65; - if (isBoktai) { - xOffset=170; yOffset=70; - } - - GuiText saveBtnTxt("Save", 22, (GXColor){0, 0, 0, 255}); - GuiImage saveBtnImg(&btnLargeOutline); - GuiImage saveBtnImgOver(&btnLargeOutlineOver); - GuiImage saveBtnIcon(&iconSave); - GuiButton saveBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - saveBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - saveBtn.SetPosition(-xOffset, 185-yOffset); - saveBtn.SetLabel(&saveBtnTxt); - saveBtn.SetImage(&saveBtnImg); - saveBtn.SetImageOver(&saveBtnImgOver); - saveBtn.SetIcon(&saveBtnIcon); - saveBtn.SetSoundOver(&btnSoundOver); - saveBtn.SetSoundClick(&btnSoundClick); - saveBtn.SetTrigger(trigA); - saveBtn.SetTrigger(trig2); - saveBtn.SetEffectGrow(); - - GuiText loadBtnTxt("Load", 22, (GXColor){0, 0, 0, 255}); - GuiImage loadBtnImg(&btnLargeOutline); - GuiImage loadBtnImgOver(&btnLargeOutlineOver); - GuiImage loadBtnIcon(&iconLoad); - GuiButton loadBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - loadBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - loadBtn.SetPosition(xOffset, 185-yOffset); - loadBtn.SetLabel(&loadBtnTxt); - loadBtn.SetImage(&loadBtnImg); - loadBtn.SetImageOver(&loadBtnImgOver); - loadBtn.SetIcon(&loadBtnIcon); - loadBtn.SetSoundOver(&btnSoundOver); - loadBtn.SetSoundClick(&btnSoundClick); - loadBtn.SetTrigger(trigA); - loadBtn.SetTrigger(trig2); - loadBtn.SetEffectGrow(); - - // Boktai adds an extra button for setting the sun. - GuiText *sunBtnTxt = NULL; - GuiImage *sunBtnImg = NULL; - GuiImage *sunBtnImgOver = NULL; - GuiButton *sunBtn = NULL; - if (isBoktai) { - struct tm *newtime; - time_t long_time; - - // regardless of the weather, there should be no sun at night time! - time(&long_time); // Get time as long integer. - newtime = localtime(&long_time); // Convert to local time. - if (newtime->tm_hour > 21 || newtime->tm_hour < 5) - { - sprintf(s, "Weather: Night Time"); - } else sprintf(s, "Weather: %d%% sun", SunBars*10); - sunBtnTxt = new GuiText(s, 22, (GXColor){0, 0, 0, 255}); - sunBtnTxt->SetWrap(true, btnLargeOutline.GetWidth()-30); - sunBtnImg = new GuiImage(&btnLargeOutline); - sunBtnImgOver = new GuiImage(&btnLargeOutlineOver); - sunBtn = new GuiButton(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - sunBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - sunBtn->SetPosition(0, 185); - sunBtn->SetLabel(sunBtnTxt); - sunBtn->SetImage(sunBtnImg); - sunBtn->SetImageOver(sunBtnImgOver); - sunBtn->SetSoundOver(&btnSoundOver); - sunBtn->SetSoundClick(&btnSoundClick); - sunBtn->SetTrigger(trigA); - sunBtn->SetTrigger(trig2); - sunBtn->SetEffectGrow(); - } - - GuiText resetBtnTxt("Reset", 22, (GXColor){0, 0, 0, 255}); - GuiImage resetBtnImg(&btnLargeOutline); - GuiImage resetBtnImgOver(&btnLargeOutlineOver); - GuiImage resetBtnIcon(&iconReset); - GuiButton resetBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - resetBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - resetBtn.SetPosition(xOffset, 185+yOffset); - resetBtn.SetLabel(&resetBtnTxt); - resetBtn.SetImage(&resetBtnImg); - resetBtn.SetImageOver(&resetBtnImgOver); - resetBtn.SetIcon(&resetBtnIcon); - resetBtn.SetSoundOver(&btnSoundOver); - resetBtn.SetSoundClick(&btnSoundClick); - resetBtn.SetTrigger(trigA); - resetBtn.SetTrigger(trig2); - resetBtn.SetEffectGrow(); - - GuiText gameSettingsBtnTxt("Game Settings", 22, (GXColor){0, 0, 0, 255}); - gameSettingsBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage gameSettingsBtnImg(&btnLargeOutline); - GuiImage gameSettingsBtnImgOver(&btnLargeOutlineOver); - GuiImage gameSettingsBtnIcon(&iconGameSettings); - GuiButton gameSettingsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - gameSettingsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - gameSettingsBtn.SetPosition(-xOffset, 185+yOffset); - gameSettingsBtn.SetLabel(&gameSettingsBtnTxt); - gameSettingsBtn.SetImage(&gameSettingsBtnImg); - gameSettingsBtn.SetImageOver(&gameSettingsBtnImgOver); - gameSettingsBtn.SetIcon(&gameSettingsBtnIcon); - gameSettingsBtn.SetSoundOver(&btnSoundOver); - gameSettingsBtn.SetSoundClick(&btnSoundClick); - gameSettingsBtn.SetTrigger(trigA); - gameSettingsBtn.SetTrigger(trig2); - gameSettingsBtn.SetEffectGrow(); - - GuiText mainmenuBtnTxt("Main Menu", 22, (GXColor){0, 0, 0, 255}); - GuiImage mainmenuBtnImg(&btnOutline); - GuiImage mainmenuBtnImgOver(&btnOutlineOver); - GuiButton mainmenuBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - mainmenuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); - mainmenuBtn.SetPosition(0, -35); - mainmenuBtn.SetLabel(&mainmenuBtnTxt); - mainmenuBtn.SetImage(&mainmenuBtnImg); - mainmenuBtn.SetImageOver(&mainmenuBtnImgOver); - mainmenuBtn.SetSoundOver(&btnSoundOver); - mainmenuBtn.SetSoundClick(&btnSoundClick); - mainmenuBtn.SetTrigger(trigA); - mainmenuBtn.SetTrigger(trig2); - mainmenuBtn.SetEffectGrow(); - - GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); - GuiImage closeBtnImg(&btnCloseOutline); - GuiImage closeBtnImgOver(&btnCloseOutlineOver); - GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-50, 35); - closeBtn.SetLabel(&closeBtnTxt); - closeBtn.SetImage(&closeBtnImg); - closeBtn.SetImageOver(&closeBtnImgOver); - closeBtn.SetSoundOver(&btnSoundOver); - closeBtn.SetSoundClick(&btnSoundClick); - closeBtn.SetTrigger(trigA); - closeBtn.SetTrigger(trig2); - closeBtn.SetTrigger(&trigHome); - closeBtn.SetEffectGrow(); - - #ifdef HW_RVL - int i; - char txt[3]; - bool status[4] = { false, false, false, false }; - int level[4] = { 0, 0, 0, 0 }; - bool newStatus; - int newLevel; - GuiText * batteryTxt[4]; - GuiImage * batteryImg[4]; - GuiImage * batteryBarImg[4]; - GuiButton * batteryBtn[4]; - - for(i=0; i < 4; ++i) - { - sprintf(txt, "P%d", i+1); - - batteryTxt[i] = new GuiText(txt, 20, (GXColor){255, 255, 255, 255}); - batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - batteryImg[i] = new GuiImage(&battery); - batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - batteryImg[i]->SetPosition(30, 0); - batteryBarImg[i] = new GuiImage(&batteryBar); - batteryBarImg[i]->SetTile(0); - batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - batteryBarImg[i]->SetPosition(34, 0); - - batteryBtn[i] = new GuiButton(70, 20); - batteryBtn[i]->SetLabel(batteryTxt[i]); - batteryBtn[i]->SetImage(batteryImg[i]); - batteryBtn[i]->SetIcon(batteryBarImg[i]); - batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - batteryBtn[i]->SetRumble(false); - batteryBtn[i]->SetSelectable(false); - batteryBtn[i]->SetAlpha(150); - } - - batteryBtn[0]->SetPosition(45, -65); - batteryBtn[1]->SetPosition(135, -65); - batteryBtn[2]->SetPosition(45, -40); - batteryBtn[3]->SetPosition(135, -40); - #endif - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&titleTxt); - w.Append(&saveBtn); - w.Append(&loadBtn); - w.Append(&resetBtn); - w.Append(&gameSettingsBtn); - if (isBoktai) - w.Append(sunBtn); - - #ifdef HW_RVL - w.Append(batteryBtn[0]); - w.Append(batteryBtn[1]); - w.Append(batteryBtn[2]); - w.Append(batteryBtn[3]); - #endif - - w.Append(&mainmenuBtn); - w.Append(&closeBtn); - - btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - btnLogo->SetPosition(-50, -40); - mainWindow->Append(&w); - - if(lastMenu == MENU_NONE) - { - enterSound->Play(); - bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); - closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); - titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); - mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - #ifdef HW_RVL - batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); - #endif - - w.SetEffect(EFFECT_FADE, 15); - } - - ResumeGui(); - - if(lastMenu == MENU_NONE) - { - if (GCSettings.AutoSave == 1) - { - SaveBatteryOrStateAuto(FILE_SRAM, SILENT); // save battery - } - else if (GCSettings.AutoSave == 2) - { - if (WindowPrompt("Save", "Save Snapshot?", "Save", "Don't Save") ) - SaveBatteryOrStateAuto(FILE_SNAPSHOT, NOTSILENT); // save state - } - else if (GCSettings.AutoSave == 3) - { - if (WindowPrompt("Save", "Save SRAM and Snapshot?", "Save", "Don't Save") ) - { - SaveBatteryOrStateAuto(FILE_SRAM, NOTSILENT); // save battery - SaveBatteryOrStateAuto(FILE_SNAPSHOT, NOTSILENT); // save state - } - } - } - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - #ifdef HW_RVL - for(i=0; i < 4; i++) - { - if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) - { - newStatus = true; - newLevel = (userInput[i].wpad->battery_level / 100.0) * 4; - if(newLevel > 4) newLevel = 4; - } - else - { - newStatus = false; - newLevel = 0; - } - - if(status[i] != newStatus || level[i] != newLevel) - { - if(newStatus == true) // controller connected - { - batteryBtn[i]->SetAlpha(255); - batteryBarImg[i]->SetTile(newLevel); - - if(newLevel == 0) - batteryImg[i]->SetImage(&batteryRed); - else - batteryImg[i]->SetImage(&battery); - } - else // controller not connected - { - batteryBtn[i]->SetAlpha(150); - batteryBarImg[i]->SetTile(0); - batteryImg[i]->SetImage(&battery); - } - status[i] = newStatus; - level[i] = newLevel; - } - } - #endif - - if (isBoktai) - { - if (sunBtn->GetState() == STATE_CLICKED) { - ++SunBars; - if (SunBars>10) SunBars=0; - menu = MENU_GAME; - } - } - - if(saveBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAME_SAVE; - } - else if(loadBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAME_LOAD; - } - else if(resetBtn.GetState() == STATE_CLICKED) - { - if (WindowPrompt("Reset Game", "Reset this game? Any unsaved progress will be lost.", "OK", "Cancel")) - { - emulator.emuReset(); - menu = MENU_EXIT; - } - } - else if(gameSettingsBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS; - } - else if(mainmenuBtn.GetState() == STATE_CLICKED) - { - if (WindowPrompt("Quit Game", "Quit this game? Any unsaved progress will be lost.", "OK", "Cancel")) - { - HaltGui(); - mainWindow->Remove(gameScreenImg); - delete gameScreenImg; - delete gameScreen; - gameScreen = NULL; - free(gameScreenPng); - gameScreenPng = NULL; - gameScreenImg = new GuiImage(screenwidth, screenheight, (GXColor){236, 226, 238, 255}); - gameScreenImg->ColorStripe(10); - mainWindow->Insert(gameScreenImg, 0); - ResumeGui(); - #ifndef NO_SOUND - bgMusic->Play(); // startup music - #endif - menu = MENU_GAMESELECTION; - } - } - else if(closeBtn.GetState() == STATE_CLICKED) - { - menu = MENU_EXIT; - - exitSound->Play(); - bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - #ifdef HW_RVL - batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - #endif - - w.SetEffect(EFFECT_FADE, -15); - usleep(350000); // wait for effects to finish - } - } - - HaltGui(); - - if (isBoktai) { - delete sunBtnTxt; - delete sunBtnImg; - delete sunBtnImgOver; - delete sunBtn; - } - - #ifdef HW_RVL - for(i=0; i < 4; ++i) - { - delete batteryTxt[i]; - delete batteryImg[i]; - delete batteryBarImg[i]; - delete batteryBtn[i]; - } - #endif - - mainWindow->Remove(&w); - return menu; -} - -/**************************************************************************** - * FindGameSaveNum - * - * Determines the save file number of the given file name - * Returns -1 if none is found - ***************************************************************************/ -static int FindGameSaveNum(char * savefile, int method) -{ - int n = -1; - int romlen = strlen(ROMFilename); - int savelen = strlen(savefile); - int diff = savelen-romlen; - - if(strncmp(savefile, ROMFilename, romlen) != 0) - return -1; - - if(savefile[romlen] == ' ') - { - if(diff == 5 && strncmp(&savefile[romlen+1], "Auto", 4) == 0) - n = 0; // found Auto save - else if(diff == 2 || diff == 3) - n = atoi(&savefile[romlen+1]); - } - - if(n >= 0 && n < MAX_SAVES) - return n; - else - return -1; -} - -/**************************************************************************** - * MenuGameSaves - * - * Allows the user to load or save progress. - ***************************************************************************/ -static int MenuGameSaves(int action) -{ - SaveList saves; - struct stat filestat; - struct tm * timeinfo; - - int menu = MENU_NONE; - int ret, result; - int i, n, type, len, len2; - int j = 0; - - char filepath[1024]; - char scrfile[1024]; - char tmp[MAXJOLIET+1]; - - int method = GCSettings.SaveMethod; - - if(method == DEVICE_AUTO) - autoSaveMethod(NOTSILENT); - - if(!ChangeInterface(method, NOTSILENT)) - return MENU_GAME; - - GuiText titleTxt(NULL, 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - if(action == 0) - titleTxt.SetText("Load Game"); - else - titleTxt.SetText("Save Game"); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - GuiImageData btnCloseOutline(button_small_png); - GuiImageData btnCloseOutlineOver(button_small_over_png); - - GuiTrigger trigHome; - trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(50, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); - GuiImage closeBtnImg(&btnCloseOutline); - GuiImage closeBtnImgOver(&btnCloseOutlineOver); - GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-50, 35); - closeBtn.SetLabel(&closeBtnTxt); - closeBtn.SetImage(&closeBtnImg); - closeBtn.SetImageOver(&closeBtnImgOver); - closeBtn.SetSoundOver(&btnSoundOver); - closeBtn.SetSoundClick(&btnSoundClick); - closeBtn.SetTrigger(trigA); - closeBtn.SetTrigger(trig2); - closeBtn.SetTrigger(&trigHome); - closeBtn.SetEffectGrow(); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&backBtn); - w.Append(&closeBtn); - mainWindow->Append(&w); - mainWindow->Append(&titleTxt); - ResumeGui(); - - memset(&saves, 0, sizeof(saves)); - - sprintf(browser.dir, "%s%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder); - ParseDirectory(true, false); - - len = strlen(ROMFilename); - - // find matching files - AllocSaveBuffer(); - - for(i=0; i < browser.numEntries; i++) - { - len2 = strlen(browserList[i].filename); - - if(len2 < 6 || len2-len < 5) - continue; - - if(strncmp(&browserList[i].filename[len2-4], ".sav", 4) == 0) - type = FILE_SRAM; - else if(strncmp(&browserList[i].filename[len2-4], ".sgm", 4) == 0) - type = FILE_SNAPSHOT; - else - continue; - - strcpy(tmp, browserList[i].filename); - tmp[len2-4] = 0; - n = FindGameSaveNum(tmp, method); - - if(n >= 0) - { - saves.type[j] = type; - saves.files[saves.type[j]][n] = 1; - strcpy(saves.filename[j], browserList[i].filename); - - if(saves.type[j] == FILE_SNAPSHOT) - { - sprintf(scrfile, "%s%s/%s.png", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, tmp); - - memset(savebuffer, 0, SAVEBUFFERSIZE); - if(LoadFile(scrfile, SILENT)) - saves.previewImg[j] = new GuiImageData(savebuffer, 64, 48); - } - snprintf(filepath, 1024, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, saves.filename[j]); - if (stat(filepath, &filestat) == 0) - { - timeinfo = localtime(&filestat.st_mtime); - strftime(saves.date[j], 20, "%a %b %d", timeinfo); - strftime(saves.time[j], 10, "%I:%M %p", timeinfo); - } - ++j; - } - } - - FreeSaveBuffer(); - saves.length = j; - - if(saves.length == 0 && action == 0) - { - InfoPrompt("No game saves found."); - menu = MENU_GAME; - } - - GuiSaveBrowser saveBrowser(552, 248, &saves, action); - saveBrowser.SetPosition(0, 108); - saveBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - - HaltGui(); - mainWindow->Append(&saveBrowser); - mainWindow->ChangeFocus(&saveBrowser); - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - ret = saveBrowser.GetClickedSave(); - - // load or save game - if(ret > -3) - { - result = 0; - - if(action == 0) // load - { - MakeFilePath(filepath, saves.type[ret], saves.filename[ret]); - switch(saves.type[ret]) - { - case FILE_SRAM: - result = LoadBatteryOrState(filepath, saves.type[ret], NOTSILENT); - emulator.emuReset(); - break; - case FILE_SNAPSHOT: - result = LoadBatteryOrState(filepath, saves.type[ret], NOTSILENT); - break; - } - if(result) - menu = MENU_EXIT; - } - else // save - { - if(ret == -2) // new SRAM - { - for(i=1; i < 100; i++) - if(saves.files[FILE_SRAM][i] == 0) - break; - - if(i < 100) - { - MakeFilePath(filepath, FILE_SRAM, ROMFilename, i); - SaveBatteryOrState(filepath, FILE_SRAM, NOTSILENT); - menu = MENU_GAME_SAVE; - } - } - else if(ret == -1) // new Snapshot - { - for(i=1; i < 100; i++) - if(saves.files[FILE_SNAPSHOT][i] == 0) - break; - - if(i < 100) - { - MakeFilePath(filepath, FILE_SNAPSHOT, ROMFilename, i); - SaveBatteryOrState(filepath, FILE_SNAPSHOT, NOTSILENT); - menu = MENU_GAME_SAVE; - } - } - else // overwrite SRAM/Snapshot - { - MakeFilePath(filepath, saves.type[ret], saves.filename[ret]); - switch(saves.type[ret]) - { - case FILE_SRAM: - SaveBatteryOrState(filepath, FILE_SRAM, NOTSILENT); - break; - case FILE_SNAPSHOT: - SaveBatteryOrState(filepath, FILE_SNAPSHOT, NOTSILENT); - break; - } - menu = MENU_GAME_SAVE; - } - } - } - - if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAME; - } - else if(closeBtn.GetState() == STATE_CLICKED) - { - menu = MENU_EXIT; - - exitSound->Play(); - bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - - w.SetEffect(EFFECT_FADE, -15); - - usleep(350000); // wait for effects to finish - } - } - - HaltGui(); - - for(i=0; i < saves.length; i++) - if(saves.previewImg[i]) - delete saves.previewImg[i]; - - mainWindow->Remove(&saveBrowser); - mainWindow->Remove(&w); - mainWindow->Remove(&titleTxt); - ResetBrowser(); - return menu; -} - - -/**************************************************************************** - * MenuGameSettings - ***************************************************************************/ -static int MenuGameSettings() -{ - int menu = MENU_NONE; - char s[4]; - - GuiText titleTxt("Game Settings", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - GuiImageData btnLargeOutline(button_large_png); - GuiImageData btnLargeOutlineOver(button_large_over_png); - GuiImageData iconMappings(icon_settings_mappings_png); - GuiImageData iconVideo(icon_settings_video_png); -#ifdef HW_RVL - GuiImageData iconWiiControls(icon_settings_nunchuk_png); -#else - GuiImageData iconWiiControls(icon_settings_gamecube_png); -#endif - //GuiImageData iconCheats(icon_game_cheats_png); - GuiImageData btnCloseOutline(button_small_png); - GuiImageData btnCloseOutlineOver(button_small_over_png); - - GuiTrigger trigHome; - trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); - - GuiText mappingBtnTxt("Button Mappings", 22, (GXColor){0, 0, 0, 255}); - mappingBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage mappingBtnImg(&btnLargeOutline); - GuiImage mappingBtnImgOver(&btnLargeOutlineOver); - GuiImage mappingBtnIcon(&iconMappings); - GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - mappingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - mappingBtn.SetPosition(-125, 120); - mappingBtn.SetLabel(&mappingBtnTxt); - mappingBtn.SetImage(&mappingBtnImg); - mappingBtn.SetImageOver(&mappingBtnImgOver); - mappingBtn.SetIcon(&mappingBtnIcon); - mappingBtn.SetSoundOver(&btnSoundOver); - mappingBtn.SetSoundClick(&btnSoundClick); - mappingBtn.SetTrigger(trigA); - mappingBtn.SetTrigger(trig2); - mappingBtn.SetEffectGrow(); - - GuiText videoBtnTxt("Video", 22, (GXColor){0, 0, 0, 255}); - videoBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage videoBtnImg(&btnLargeOutline); - GuiImage videoBtnImgOver(&btnLargeOutlineOver); - GuiImage videoBtnIcon(&iconVideo); - GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - videoBtn.SetPosition(125, 120); - videoBtn.SetLabel(&videoBtnTxt); - videoBtn.SetImage(&videoBtnImg); - videoBtn.SetImageOver(&videoBtnImgOver); - videoBtn.SetIcon(&videoBtnIcon); - videoBtn.SetSoundOver(&btnSoundOver); - videoBtn.SetSoundClick(&btnSoundClick); - videoBtn.SetTrigger(trigA); - videoBtn.SetTrigger(trig2); - videoBtn.SetEffectGrow(); - - #ifdef HW_RVL - GuiText wiiControlsBtnTxt1("Match Wii Controls", 22, (GXColor){0, 0, 0, 255}); - #else - GuiText wiiControlsBtnTxt1("Match GC Controls", 22, (GXColor){0, 0, 0, 255}); - #endif - if (GCSettings.WiiControls) sprintf(s, "ON"); - else sprintf(s, "OFF"); - GuiText wiiControlsBtnTxt2(s, 18, (GXColor){0, 0, 0, 255}); - wiiControlsBtnTxt1.SetPosition(0, -10); - wiiControlsBtnTxt1.SetWrap(true, btnLargeOutline.GetWidth()-30); - wiiControlsBtnTxt2.SetPosition(0, +30); - GuiImage wiiControlsBtnImg(&btnLargeOutline); - GuiImage wiiControlsBtnImgOver(&btnLargeOutlineOver); - GuiImage wiiControlsBtnIcon(&iconWiiControls); - GuiButton wiiControlsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - wiiControlsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - wiiControlsBtn.SetPosition(0, 250); - wiiControlsBtn.SetLabel(&wiiControlsBtnTxt1, 0); - wiiControlsBtn.SetLabel(&wiiControlsBtnTxt2, 1); - wiiControlsBtn.SetImage(&wiiControlsBtnImg); - wiiControlsBtn.SetImageOver(&wiiControlsBtnImgOver); - wiiControlsBtn.SetIcon(&wiiControlsBtnIcon); - wiiControlsBtn.SetSoundOver(&btnSoundOver); - wiiControlsBtn.SetSoundClick(&btnSoundClick); - wiiControlsBtn.SetTrigger(trigA); - wiiControlsBtn.SetTrigger(trig2); - wiiControlsBtn.SetEffectGrow(); - - /*GuiText cheatsBtnTxt("Cheats", 22, (GXColor){0, 0, 0, 255}); - GuiImage cheatsBtnImg(&btnLargeOutline); - GuiImage cheatsBtnImgOver(&btnLargeOutlineOver); - GuiImage cheatsBtnIcon(&iconCheats); - GuiButton cheatsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - cheatsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - cheatsBtn.SetPosition(125, 250); - cheatsBtn.SetLabel(&cheatsBtnTxt); - cheatsBtn.SetImage(&cheatsBtnImg); - cheatsBtn.SetImageOver(&cheatsBtnImgOver); - cheatsBtn.SetIcon(&cheatsBtnIcon); - cheatsBtn.SetSoundOver(&btnSoundOver); - cheatsBtn.SetSoundClick(&btnSoundClick); - cheatsBtn.SetTrigger(trigA); - cheatsBtn.SetEffectGrow();*/ - - GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); - GuiImage closeBtnImg(&btnCloseOutline); - GuiImage closeBtnImgOver(&btnCloseOutlineOver); - GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-50, 35); - closeBtn.SetLabel(&closeBtnTxt); - closeBtn.SetImage(&closeBtnImg); - closeBtn.SetImageOver(&closeBtnImgOver); - closeBtn.SetSoundOver(&btnSoundOver); - closeBtn.SetSoundClick(&btnSoundClick); - closeBtn.SetTrigger(trigA); - closeBtn.SetTrigger(trig2); - closeBtn.SetTrigger(&trigHome); - closeBtn.SetEffectGrow(); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(50, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&titleTxt); - w.Append(&mappingBtn); - w.Append(&videoBtn); - w.Append(&wiiControlsBtn); - //w.Append(&cheatsBtn); - w.Append(&closeBtn); - w.Append(&backBtn); - - mainWindow->Append(&w); - - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - if(mappingBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_MAPPINGS; - } - else if(videoBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_VIDEO; - } - else if(wiiControlsBtn.GetState() == STATE_CLICKED) - { - GCSettings.WiiControls ^= 1; - if (GCSettings.WiiControls) sprintf(s, "ON"); - else sprintf(s, "OFF"); - wiiControlsBtnTxt2.SetText(s); - wiiControlsBtn.ResetState(); - } - /*else if(cheatsBtn.GetState() == STATE_CLICKED) - { - cheatsBtn.ResetState(); - if(Cheat.num_cheats > 0) - menu = MENU_GAMESETTINGS_CHEATS; - else - InfoPrompt("Cheats file not found!"); - }*/ - else if(closeBtn.GetState() == STATE_CLICKED) - { - menu = MENU_EXIT; - - exitSound->Play(); - bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - - w.SetEffect(EFFECT_FADE, -15); - - usleep(350000); // wait for effects to finish - } - else if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAME; - } - } - - HaltGui(); - mainWindow->Remove(&w); - return menu; -} - -/**************************************************************************** - * MenuSettingsMappings - ***************************************************************************/ -static int MenuSettingsMappings() -{ - int menu = MENU_NONE; - - GuiText titleTxt("Game Settings - Button Mappings", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - GuiImageData btnLargeOutline(button_large_png); - GuiImageData btnLargeOutlineOver(button_large_over_png); - GuiImageData iconWiimote(icon_settings_wiimote_png); - GuiImageData iconClassic(icon_settings_classic_png); - GuiImageData iconGamecube(icon_settings_gamecube_png); - GuiImageData iconNunchuk(icon_settings_nunchuk_png); - - GuiText gamecubeBtnTxt("GameCube Controller", 22, (GXColor){0, 0, 0, 255}); - gamecubeBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage gamecubeBtnImg(&btnLargeOutline); - GuiImage gamecubeBtnImgOver(&btnLargeOutlineOver); - GuiImage gamecubeBtnIcon(&iconGamecube); - GuiButton gamecubeBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - gamecubeBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - gamecubeBtn.SetPosition(-125, 120); - gamecubeBtn.SetLabel(&gamecubeBtnTxt); - gamecubeBtn.SetImage(&gamecubeBtnImg); - gamecubeBtn.SetImageOver(&gamecubeBtnImgOver); - gamecubeBtn.SetIcon(&gamecubeBtnIcon); - gamecubeBtn.SetSoundOver(&btnSoundOver); - gamecubeBtn.SetSoundClick(&btnSoundClick); - gamecubeBtn.SetTrigger(trigA); - gamecubeBtn.SetTrigger(trig2); - gamecubeBtn.SetEffectGrow(); - - GuiText wiimoteBtnTxt("Wiimote", 22, (GXColor){0, 0, 0, 255}); - GuiImage wiimoteBtnImg(&btnLargeOutline); - GuiImage wiimoteBtnImgOver(&btnLargeOutlineOver); - GuiImage wiimoteBtnIcon(&iconWiimote); - GuiButton wiimoteBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - wiimoteBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - wiimoteBtn.SetPosition(125, 120); - wiimoteBtn.SetLabel(&wiimoteBtnTxt); - wiimoteBtn.SetImage(&wiimoteBtnImg); - wiimoteBtn.SetImageOver(&wiimoteBtnImgOver); - wiimoteBtn.SetIcon(&wiimoteBtnIcon); - wiimoteBtn.SetSoundOver(&btnSoundOver); - wiimoteBtn.SetSoundClick(&btnSoundClick); - wiimoteBtn.SetTrigger(trigA); - wiimoteBtn.SetTrigger(trig2); - wiimoteBtn.SetEffectGrow(); - - GuiText classicBtnTxt("Classic Controller", 22, (GXColor){0, 0, 0, 255}); - classicBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage classicBtnImg(&btnLargeOutline); - GuiImage classicBtnImgOver(&btnLargeOutlineOver); - GuiImage classicBtnIcon(&iconClassic); - GuiButton classicBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - classicBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - classicBtn.SetPosition(-125, 250); - classicBtn.SetLabel(&classicBtnTxt); - classicBtn.SetImage(&classicBtnImg); - classicBtn.SetImageOver(&classicBtnImgOver); - classicBtn.SetIcon(&classicBtnIcon); - classicBtn.SetSoundOver(&btnSoundOver); - classicBtn.SetSoundClick(&btnSoundClick); - classicBtn.SetTrigger(trigA); - classicBtn.SetTrigger(trig2); - classicBtn.SetEffectGrow(); - - GuiText nunchukBtnTxt1("Wiimote", 22, (GXColor){0, 0, 0, 255}); - GuiText nunchukBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); - GuiText nunchukBtnTxt3("Nunchuk", 22, (GXColor){0, 0, 0, 255}); - nunchukBtnTxt1.SetPosition(0, -20); - nunchukBtnTxt3.SetPosition(0, +20); - GuiImage nunchukBtnImg(&btnLargeOutline); - GuiImage nunchukBtnImgOver(&btnLargeOutlineOver); - GuiImage nunchukBtnIcon(&iconNunchuk); - GuiButton nunchukBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - nunchukBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - nunchukBtn.SetPosition(125, 250); - nunchukBtn.SetLabel(&nunchukBtnTxt1, 0); - nunchukBtn.SetLabel(&nunchukBtnTxt2, 1); - nunchukBtn.SetLabel(&nunchukBtnTxt3, 2); - nunchukBtn.SetImage(&nunchukBtnImg); - nunchukBtn.SetImageOver(&nunchukBtnImgOver); - nunchukBtn.SetIcon(&nunchukBtnIcon); - nunchukBtn.SetSoundOver(&btnSoundOver); - nunchukBtn.SetSoundClick(&btnSoundClick); - nunchukBtn.SetTrigger(trigA); - nunchukBtn.SetTrigger(trig2); - nunchukBtn.SetEffectGrow(); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(50, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&titleTxt); - - w.Append(&gamecubeBtn); -#ifdef HW_RVL - w.Append(&wiimoteBtn); - w.Append(&nunchukBtn); - w.Append(&classicBtn); -#endif - w.Append(&backBtn); - - mainWindow->Append(&w); - - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - if(wiimoteBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_MAPPINGS_MAP; - mapMenuCtrl = CTRLR_WIIMOTE; - } - else if(nunchukBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_MAPPINGS_MAP; - mapMenuCtrl = CTRLR_NUNCHUK; - } - else if(classicBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_MAPPINGS_MAP; - mapMenuCtrl = CTRLR_CLASSIC; - } - else if(gamecubeBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_MAPPINGS_MAP; - mapMenuCtrl = CTRLR_GCPAD; - } - else if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS; - } - } - HaltGui(); - mainWindow->Remove(&w); - return menu; -} - -/**************************************************************************** - * ButtonMappingWindow - ***************************************************************************/ -static u32 -ButtonMappingWindow() -{ - GuiWindow promptWindow(448,288); - promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - promptWindow.SetPosition(0, -10); - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - - GuiImageData dialogBox(dialogue_box_png); - GuiImage dialogBoxImg(&dialogBox); - - GuiText titleTxt("Button Mapping", 26, (GXColor){25, 100, 10, 255}); - titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - titleTxt.SetPosition(0,14); - - char msg[200]; - - switch(mapMenuCtrl) - { - case CTRLR_GCPAD: - #ifdef HW_RVL - sprintf(msg, "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping."); - #else - sprintf(msg, "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping."); - #endif - break; - case CTRLR_WIIMOTE: - sprintf(msg, "Press any button on the Wiimote now. Press Home to clear the existing mapping."); - break; - case CTRLR_CLASSIC: - sprintf(msg, "Press any button on the Classic Controller now. Press Home to clear the existing mapping."); - break; - case CTRLR_NUNCHUK: - sprintf(msg, "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping."); - break; - } - - GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); - msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - msgTxt.SetPosition(0,-20); - msgTxt.SetWrap(true, 430); - - promptWindow.Append(&dialogBoxImg); - promptWindow.Append(&titleTxt); - promptWindow.Append(&msgTxt); - - HaltGui(); - mainWindow->SetState(STATE_DISABLED); - mainWindow->Append(&promptWindow); - mainWindow->ChangeFocus(&promptWindow); - ResumeGui(); - - u32 pressed = 0; - - while(pressed == 0) - { - usleep(THREAD_SLEEP); - - if(mapMenuCtrl == CTRLR_GCPAD) - { - pressed = userInput[0].pad.btns_d; - - - if(userInput[0].pad.substickX < -70 || - userInput[0].pad.substickX > 70 || - userInput[0].pad.substickY < -70 || - userInput[0].pad.substickY > 70) - pressed = WPAD_BUTTON_HOME; - - if(userInput[0].wpad->btns_d == WPAD_BUTTON_HOME) - pressed = WPAD_BUTTON_HOME; - } - else - { - pressed = userInput[0].wpad->btns_d; - - // always allow Home button to be pressed to cancel - if(pressed != WPAD_BUTTON_HOME) - { - switch(mapMenuCtrl) - { - case CTRLR_WIIMOTE: - if(pressed > 0x1000) - pressed = 0; // not a valid input - break; - - case CTRLR_CLASSIC: - if(userInput[0].wpad->exp.type != WPAD_EXP_CLASSIC) - pressed = 0; // not a valid input - else if(pressed <= 0x1000) - pressed = 0; - break; - - case CTRLR_NUNCHUK: - if(userInput[0].wpad->exp.type != WPAD_EXP_NUNCHUK) - pressed = 0; // not a valid input - break; - } - } - } - } - - if(pressed == WPAD_BUTTON_HOME || pressed == WPAD_CLASSIC_BUTTON_HOME) - pressed = 0; - - HaltGui(); - mainWindow->Remove(&promptWindow); - mainWindow->SetState(STATE_DEFAULT); - ResumeGui(); - - return pressed; -} - -static int MenuSettingsMappingsMap() -{ - int menu = MENU_NONE; - int ret,i,j; - bool firstRun = true; - OptionList options; - - char menuTitle[100]; - char menuSubtitle[100]; - sprintf(menuTitle, "Game Settings - Button Mappings"); - - GuiText titleTxt(menuTitle, 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,30); - - sprintf(menuSubtitle, "%s", ctrlrName[mapMenuCtrl]); - GuiText subtitleTxt(menuSubtitle, 20, (GXColor){255, 255, 255, 255}); - subtitleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - subtitleTxt.SetPosition(50,60); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - GuiImageData btnShortOutline(button_short_png); - GuiImageData btnShortOutlineOver(button_short_over_png); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(50, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiText resetBtnTxt("Reset", 22, (GXColor){0, 0, 0, 255}); - GuiImage resetBtnImg(&btnShortOutline); - GuiImage resetBtnImgOver(&btnShortOutlineOver); - GuiButton resetBtn(btnShortOutline.GetWidth(), btnShortOutline.GetHeight()); - resetBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - resetBtn.SetPosition(260, -35); - resetBtn.SetLabel(&resetBtnTxt); - resetBtn.SetImage(&resetBtnImg); - resetBtn.SetImageOver(&resetBtnImgOver); - resetBtn.SetSoundOver(&btnSoundOver); - resetBtn.SetSoundClick(&btnSoundClick); - resetBtn.SetTrigger(trigA); - resetBtn.SetTrigger(trig2); - resetBtn.SetEffectGrow(); - - i=0; - sprintf(options.name[i++], "B"); - sprintf(options.name[i++], "A"); - sprintf(options.name[i++], "Select"); - sprintf(options.name[i++], "Start"); - sprintf(options.name[i++], "Up"); - sprintf(options.name[i++], "Down"); - sprintf(options.name[i++], "Left"); - sprintf(options.name[i++], "Right"); - sprintf(options.name[i++], "L"); - sprintf(options.name[i++], "R"); - options.length = i; - - for(i=0; i < options.length; i++) - options.value[i][0] = 0; - - GuiOptionBrowser optionBrowser(552, 248, &options); - optionBrowser.SetPosition(0, 108); - optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - optionBrowser.SetCol2Position(215); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&backBtn); - w.Append(&resetBtn); - mainWindow->Append(&optionBrowser); - mainWindow->Append(&w); - mainWindow->Append(&titleTxt); - mainWindow->Append(&subtitleTxt); - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS_MAPPINGS; - } - else if(resetBtn.GetState() == STATE_CLICKED) - { - resetBtn.ResetState(); - - int choice = WindowPrompt( - "Reset Mappings", - "Are you sure that you want to reset your mappings?", - "Yes", - "No"); - - if(choice == 1) - { - ResetControls(mapMenuCtrl); - firstRun = true; - } - } - - ret = optionBrowser.GetClickedOption(); - - if(ret >= 0) - { - // get a button selection from user - btnmap[mapMenuCtrl][ret] = ButtonMappingWindow(); - } - - if(ret >= 0 || firstRun) - { - firstRun = false; - - for(i=0; i < options.length; i++) - { - for(j=0; j < ctrlr_def[mapMenuCtrl].num_btns; j++) - { - if(btnmap[mapMenuCtrl][i] == 0) - { - options.value[i][0] = 0; - } - else if(btnmap[mapMenuCtrl][i] == - ctrlr_def[mapMenuCtrl].map[j].btn) - { - if(strcmp(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name) != 0) - sprintf(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name); - break; - } - } - } - optionBrowser.TriggerUpdate(); - } - } - HaltGui(); - mainWindow->Remove(&optionBrowser); - mainWindow->Remove(&w); - mainWindow->Remove(&titleTxt); - mainWindow->Remove(&subtitleTxt); - return menu; -} - -/**************************************************************************** - * MenuSettingsVideo - ***************************************************************************/ - -static void ScreenZoomWindowUpdate(void * ptr, float h, float v) -{ - GuiButton * b = (GuiButton *)ptr; - if(b->GetState() == STATE_CLICKED) - { - char zoom[10], zoom2[10]; - - if(IsGBAGame()) - { - GCSettings.gbaZoomHor += h; - GCSettings.gbaZoomVert += v; - sprintf(zoom, "%.2f%%", GCSettings.gbaZoomHor*100); - sprintf(zoom2, "%.2f%%", GCSettings.gbaZoomVert*100); - } - else - { - GCSettings.gbZoomHor += h; - GCSettings.gbZoomVert += v; - sprintf(zoom, "%.2f%%", GCSettings.gbZoomHor*100); - sprintf(zoom2, "%.2f%%", GCSettings.gbZoomVert*100); - } - - settingText->SetText(zoom); - settingText2->SetText(zoom2); - b->ResetState(); - } -} - -static void ScreenZoomWindowLeftClick(void * ptr) { ScreenZoomWindowUpdate(ptr, -0.01, 0); } -static void ScreenZoomWindowRightClick(void * ptr) { ScreenZoomWindowUpdate(ptr, +0.01, 0); } -static void ScreenZoomWindowUpClick(void * ptr) { ScreenZoomWindowUpdate(ptr, 0, +0.01); } -static void ScreenZoomWindowDownClick(void * ptr) { ScreenZoomWindowUpdate(ptr, 0, -0.01); } - -static void ScreenZoomWindow() -{ - GuiWindow * w = new GuiWindow(200,200); - w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - - GuiTrigger trigLeft; - trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); - - GuiTrigger trigRight; - trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); - - GuiTrigger trigUp; - trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); - - GuiTrigger trigDown; - trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); - - GuiImageData arrowLeft(button_arrow_left_png); - GuiImage arrowLeftImg(&arrowLeft); - GuiImageData arrowLeftOver(button_arrow_left_over_png); - GuiImage arrowLeftOverImg(&arrowLeftOver); - GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); - arrowLeftBtn.SetImage(&arrowLeftImg); - arrowLeftBtn.SetImageOver(&arrowLeftOverImg); - arrowLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - arrowLeftBtn.SetPosition(50, 0); - arrowLeftBtn.SetTrigger(trigA); - arrowLeftBtn.SetTrigger(trig2); - arrowLeftBtn.SetTrigger(&trigLeft); - arrowLeftBtn.SetSelectable(false); - arrowLeftBtn.SetUpdateCallback(ScreenZoomWindowLeftClick); - - GuiImageData arrowRight(button_arrow_right_png); - GuiImage arrowRightImg(&arrowRight); - GuiImageData arrowRightOver(button_arrow_right_over_png); - GuiImage arrowRightOverImg(&arrowRightOver); - GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); - arrowRightBtn.SetImage(&arrowRightImg); - arrowRightBtn.SetImageOver(&arrowRightOverImg); - arrowRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - arrowRightBtn.SetPosition(164, 0); - arrowRightBtn.SetTrigger(trigA); - arrowRightBtn.SetTrigger(trig2); - arrowRightBtn.SetTrigger(&trigRight); - arrowRightBtn.SetSelectable(false); - arrowRightBtn.SetUpdateCallback(ScreenZoomWindowRightClick); - - GuiImageData arrowUp(button_arrow_up_png); - GuiImage arrowUpImg(&arrowUp); - GuiImageData arrowUpOver(button_arrow_up_over_png); - GuiImage arrowUpOverImg(&arrowUpOver); - GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); - arrowUpBtn.SetImage(&arrowUpImg); - arrowUpBtn.SetImageOver(&arrowUpOverImg); - arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - arrowUpBtn.SetPosition(-76, -27); - arrowUpBtn.SetTrigger(trigA); - arrowUpBtn.SetTrigger(trig2); - arrowUpBtn.SetTrigger(&trigUp); - arrowUpBtn.SetSelectable(false); - arrowUpBtn.SetUpdateCallback(ScreenZoomWindowUpClick); - - GuiImageData arrowDown(button_arrow_down_png); - GuiImage arrowDownImg(&arrowDown); - GuiImageData arrowDownOver(button_arrow_down_over_png); - GuiImage arrowDownOverImg(&arrowDownOver); - GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); - arrowDownBtn.SetImage(&arrowDownImg); - arrowDownBtn.SetImageOver(&arrowDownOverImg); - arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - arrowDownBtn.SetPosition(-76, 27); - arrowDownBtn.SetTrigger(trigA); - arrowDownBtn.SetTrigger(trig2); - arrowDownBtn.SetTrigger(&trigDown); - arrowDownBtn.SetSelectable(false); - arrowDownBtn.SetUpdateCallback(ScreenZoomWindowDownClick); - - GuiImageData screenPosition(screen_position_png); - GuiImage screenPositionImg(&screenPosition); - screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - screenPositionImg.SetPosition(0, 0); - - settingText = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); - settingText2 = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); - char zoom[10], zoom2[10]; - float currentZoomHor, currentZoomVert; - - if(IsGBAGame()) - { - sprintf(zoom, "%.2f%%", GCSettings.gbaZoomHor*100); - sprintf(zoom2, "%.2f%%", GCSettings.gbaZoomVert*100); - currentZoomHor = GCSettings.gbaZoomHor; - currentZoomVert = GCSettings.gbaZoomVert; - } - else - { - sprintf(zoom, "%.2f%%", GCSettings.gbZoomHor*100); - sprintf(zoom2, "%.2f%%", GCSettings.gbZoomVert*100); - currentZoomHor = GCSettings.gbZoomHor; - currentZoomVert = GCSettings.gbZoomVert; - } - - settingText->SetText(zoom); - settingText->SetPosition(108, 0); - settingText2->SetText(zoom2); - settingText2->SetPosition(-76, 0); - - w->Append(&arrowLeftBtn); - w->Append(&arrowRightBtn); - w->Append(&arrowUpBtn); - w->Append(&arrowDownBtn); - w->Append(&screenPositionImg); - w->Append(settingText); - w->Append(settingText2); - - char windowName[20]; - if(IsGBAGame()) - sprintf(windowName, "GBA Screen Zoom"); - else - sprintf(windowName, "GB Screen Zoom"); - - if(!SettingWindow(windowName,w)) - { - // undo changes - if(IsGBAGame()) - { - GCSettings.gbaZoomHor = currentZoomHor; - GCSettings.gbaZoomVert = currentZoomVert; - } - else - { - GCSettings.gbZoomHor = currentZoomHor; - GCSettings.gbZoomVert = currentZoomVert; - } - } - - delete(w); - delete(settingText); - delete(settingText2); -} - -static void ScreenPositionWindowUpdate(void * ptr, int x, int y) -{ - GuiButton * b = (GuiButton *)ptr; - if(b->GetState() == STATE_CLICKED) - { - GCSettings.xshift += x; - GCSettings.yshift += y; - - char shift[10]; - sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); - settingText->SetText(shift); - b->ResetState(); - } -} - -static void ScreenPositionWindowLeftClick(void * ptr) { ScreenPositionWindowUpdate(ptr, -1, 0); } -static void ScreenPositionWindowRightClick(void * ptr) { ScreenPositionWindowUpdate(ptr, +1, 0); } -static void ScreenPositionWindowUpClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, -1); } -static void ScreenPositionWindowDownClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, +1); } - -static void ScreenPositionWindow() -{ - GuiWindow * w = new GuiWindow(150,150); - w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - w->SetPosition(0, -10); - - GuiTrigger trigLeft; - trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); - - GuiTrigger trigRight; - trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); - - GuiTrigger trigUp; - trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); - - GuiTrigger trigDown; - trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); - - GuiImageData arrowLeft(button_arrow_left_png); - GuiImage arrowLeftImg(&arrowLeft); - GuiImageData arrowLeftOver(button_arrow_left_over_png); - GuiImage arrowLeftOverImg(&arrowLeftOver); - GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); - arrowLeftBtn.SetImage(&arrowLeftImg); - arrowLeftBtn.SetImageOver(&arrowLeftOverImg); - arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); - arrowLeftBtn.SetTrigger(trigA); - arrowLeftBtn.SetTrigger(trig2); - arrowLeftBtn.SetTrigger(&trigLeft); - arrowLeftBtn.SetSelectable(false); - arrowLeftBtn.SetUpdateCallback(ScreenPositionWindowLeftClick); - - GuiImageData arrowRight(button_arrow_right_png); - GuiImage arrowRightImg(&arrowRight); - GuiImageData arrowRightOver(button_arrow_right_over_png); - GuiImage arrowRightOverImg(&arrowRightOver); - GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); - arrowRightBtn.SetImage(&arrowRightImg); - arrowRightBtn.SetImageOver(&arrowRightOverImg); - arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); - arrowRightBtn.SetTrigger(trigA); - arrowRightBtn.SetTrigger(trig2); - arrowRightBtn.SetTrigger(&trigRight); - arrowRightBtn.SetSelectable(false); - arrowRightBtn.SetUpdateCallback(ScreenPositionWindowRightClick); - - GuiImageData arrowUp(button_arrow_up_png); - GuiImage arrowUpImg(&arrowUp); - GuiImageData arrowUpOver(button_arrow_up_over_png); - GuiImage arrowUpOverImg(&arrowUpOver); - GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); - arrowUpBtn.SetImage(&arrowUpImg); - arrowUpBtn.SetImageOver(&arrowUpOverImg); - arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - arrowUpBtn.SetTrigger(trigA); - arrowUpBtn.SetTrigger(trig2); - arrowUpBtn.SetTrigger(&trigUp); - arrowUpBtn.SetSelectable(false); - arrowUpBtn.SetUpdateCallback(ScreenPositionWindowUpClick); - - GuiImageData arrowDown(button_arrow_down_png); - GuiImage arrowDownImg(&arrowDown); - GuiImageData arrowDownOver(button_arrow_down_over_png); - GuiImage arrowDownOverImg(&arrowDownOver); - GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); - arrowDownBtn.SetImage(&arrowDownImg); - arrowDownBtn.SetImageOver(&arrowDownOverImg); - arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); - arrowDownBtn.SetTrigger(trigA); - arrowDownBtn.SetTrigger(trig2); - arrowDownBtn.SetTrigger(&trigDown); - arrowDownBtn.SetSelectable(false); - arrowDownBtn.SetUpdateCallback(ScreenPositionWindowDownClick); - - GuiImageData screenPosition(screen_position_png); - GuiImage screenPositionImg(&screenPosition); - screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - - settingText = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); - char shift[10]; - sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); - settingText->SetText(shift); - - int currentX = GCSettings.xshift; - int currentY = GCSettings.yshift; - - w->Append(&arrowLeftBtn); - w->Append(&arrowRightBtn); - w->Append(&arrowUpBtn); - w->Append(&arrowDownBtn); - w->Append(&screenPositionImg); - w->Append(settingText); - - if(!SettingWindow("Screen Position",w)) - { - // undo changes - GCSettings.xshift = currentX; - GCSettings.yshift = currentY; - } - - delete(w); - delete(settingText); -} - -static int MenuSettingsVideo() -{ - int menu = MENU_NONE; - int ret; - int i = 0; - bool firstRun = true; - OptionList options; - - sprintf(options.name[i++], "Rendering"); - sprintf(options.name[i++], "Scaling"); - if(IsGBAGame()) - sprintf(options.name[i++], "GBA Screen Zoom"); - else - sprintf(options.name[i++], "GB Screen Zoom"); - sprintf(options.name[i++], "Screen Position"); - sprintf(options.name[i++], "Video Mode"); - sprintf(options.name[i++], "GB Mono Colorization"); - sprintf(options.name[i++], "GB Palette"); - options.length = i; - - for(i=0; i < options.length; i++) - options.value[i][0] = 0; - - if(IsGBAGame()) - options.name[5][0] = 0; - - if(!IsGameboyGame()) - options.name[6][0] = 0; // disable palette option for GBA/GBC - - GuiText titleTxt("Game Settings - Video", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(50, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiOptionBrowser optionBrowser(552, 248, &options); - optionBrowser.SetPosition(0, 108); - optionBrowser.SetCol2Position(240); - optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&backBtn); - mainWindow->Append(&optionBrowser); - mainWindow->Append(&w); - mainWindow->Append(&titleTxt); - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - ret = optionBrowser.GetClickedOption(); - - switch (ret) - { - case 0: - GCSettings.render++; - if (GCSettings.render > 2) - GCSettings.render = 1; - break; - - case 1: - GCSettings.scaling++; - if (GCSettings.scaling > 3) - GCSettings.scaling = 0; - // disable Widescreen correction in Wii mode - determined automatically - #ifdef HW_RVL - if(GCSettings.scaling == 3) - GCSettings.scaling = 0; - #endif - break; - - case 2: - ScreenZoomWindow(); - break; - - case 3: - ScreenPositionWindow(); - break; - - case 4: - GCSettings.videomode++; - if(GCSettings.videomode > 4) - GCSettings.videomode = 0; - break; - - case 5: - GCSettings.colorize ^= 1; - break; - - case 6: - menu = MENU_GAMESETTINGS_PALETTE; - break; - } - - if(ret >= 0 || firstRun) - { - firstRun = false; - - if (GCSettings.render == 0) - sprintf (options.value[0], "Original"); - else if (GCSettings.render == 1) - sprintf (options.value[0], "Filtered"); - else if (GCSettings.render == 2) - sprintf (options.value[0], "Unfiltered"); - - if (GCSettings.scaling == 0) - sprintf (options.value[1], "Maintain Aspect Ratio"); - else if (GCSettings.scaling == 1) - sprintf (options.value[1], "Partial Stretch"); - else if (GCSettings.scaling == 2) - sprintf (options.value[1], "Stretch to Fit"); - else if (GCSettings.scaling == 3) - sprintf (options.value[1], "16:9 Correction"); - - if(IsGBAGame()) - sprintf (options.value[2], "%.2f%%, %.2f%%", GCSettings.gbaZoomHor*100, GCSettings.gbaZoomVert*100); - else - sprintf (options.value[2], "%.2f%%, %.2f%%", GCSettings.gbZoomHor*100, GCSettings.gbZoomVert*100); - sprintf (options.value[3], "%d, %d", GCSettings.xshift, GCSettings.yshift); - - switch(GCSettings.videomode) - { - case 0: - sprintf (options.value[4], "Automatic (Recommended)"); break; - case 1: - sprintf (options.value[4], "NTSC (480i)"); break; - case 2: - sprintf (options.value[4], "Progressive (480p)"); break; - case 3: - sprintf (options.value[4], "PAL (50Hz)"); break; - case 4: - sprintf (options.value[4], "PAL (60Hz)"); break; - } - - if (GCSettings.colorize) - sprintf (options.value[5], "On"); - else - sprintf (options.value[5], "Off"); - - if(strcmp(CurrentPalette.gameName, "default")) - sprintf(options.value[6], "Custom"); - else - sprintf(options.value[6], "Default"); - - optionBrowser.TriggerUpdate(); - } - - if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESETTINGS; - } - } - HaltGui(); - mainWindow->Remove(&optionBrowser); - mainWindow->Remove(&w); - mainWindow->Remove(&titleTxt); - return menu; -} - -/**************************************************************************** - * MenuSettings - ***************************************************************************/ -static int MenuSettings() -{ - int menu = MENU_NONE; - - GuiText titleTxt("Settings", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_long_png); - GuiImageData btnOutlineOver(button_long_over_png); - GuiImageData btnLargeOutline(button_large_png); - GuiImageData btnLargeOutlineOver(button_large_over_png); - GuiImageData iconFile(icon_settings_file_png); - GuiImageData iconMenu(icon_settings_menu_png); - GuiImageData iconNetwork(icon_settings_network_png); - - GuiText savingBtnTxt1("Saving", 22, (GXColor){0, 0, 0, 255}); - GuiText savingBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); - GuiText savingBtnTxt3("Loading", 22, (GXColor){0, 0, 0, 255}); - savingBtnTxt1.SetPosition(0, -20); - savingBtnTxt3.SetPosition(0, +20); - GuiImage savingBtnImg(&btnLargeOutline); - GuiImage savingBtnImgOver(&btnLargeOutlineOver); - GuiImage fileBtnIcon(&iconFile); - GuiButton savingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - savingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - savingBtn.SetPosition(-125, 120); - savingBtn.SetLabel(&savingBtnTxt1, 0); - savingBtn.SetLabel(&savingBtnTxt2, 1); - savingBtn.SetLabel(&savingBtnTxt3, 2); - savingBtn.SetImage(&savingBtnImg); - savingBtn.SetImageOver(&savingBtnImgOver); - savingBtn.SetIcon(&fileBtnIcon); - savingBtn.SetSoundOver(&btnSoundOver); - savingBtn.SetSoundClick(&btnSoundClick); - savingBtn.SetTrigger(trigA); - savingBtn.SetTrigger(trig2); - savingBtn.SetEffectGrow(); - - GuiText menuBtnTxt("Menu", 22, (GXColor){0, 0, 0, 255}); - menuBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage menuBtnImg(&btnLargeOutline); - GuiImage menuBtnImgOver(&btnLargeOutlineOver); - GuiImage menuBtnIcon(&iconMenu); - GuiButton menuBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - menuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - menuBtn.SetPosition(125, 120); - menuBtn.SetLabel(&menuBtnTxt); - menuBtn.SetImage(&menuBtnImg); - menuBtn.SetImageOver(&menuBtnImgOver); - menuBtn.SetIcon(&menuBtnIcon); - menuBtn.SetSoundOver(&btnSoundOver); - menuBtn.SetSoundClick(&btnSoundClick); - menuBtn.SetTrigger(trigA); - menuBtn.SetTrigger(trig2); - menuBtn.SetEffectGrow(); - - GuiText networkBtnTxt("Network", 22, (GXColor){0, 0, 0, 255}); - networkBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); - GuiImage networkBtnImg(&btnLargeOutline); - GuiImage networkBtnImgOver(&btnLargeOutlineOver); - GuiImage networkBtnIcon(&iconNetwork); - GuiButton networkBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); - networkBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - networkBtn.SetPosition(0, 250); - networkBtn.SetLabel(&networkBtnTxt); - networkBtn.SetImage(&networkBtnImg); - networkBtn.SetImageOver(&networkBtnImgOver); - networkBtn.SetIcon(&networkBtnIcon); - networkBtn.SetSoundOver(&btnSoundOver); - networkBtn.SetSoundClick(&btnSoundClick); - networkBtn.SetTrigger(trigA); - networkBtn.SetTrigger(trig2); - networkBtn.SetEffectGrow(); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(90, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiText resetBtnTxt("Reset Settings", 22, (GXColor){0, 0, 0, 255}); - GuiImage resetBtnImg(&btnOutline); - GuiImage resetBtnImgOver(&btnOutlineOver); - GuiButton resetBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - resetBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); - resetBtn.SetPosition(-90, -35); - resetBtn.SetLabel(&resetBtnTxt); - resetBtn.SetImage(&resetBtnImg); - resetBtn.SetImageOver(&resetBtnImgOver); - resetBtn.SetSoundOver(&btnSoundOver); - resetBtn.SetSoundClick(&btnSoundClick); - resetBtn.SetTrigger(trigA); - resetBtn.SetTrigger(trig2); - resetBtn.SetEffectGrow(); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&titleTxt); - w.Append(&savingBtn); - w.Append(&menuBtn); - w.Append(&networkBtn); - w.Append(&backBtn); - w.Append(&resetBtn); - - mainWindow->Append(&w); - - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - if(savingBtn.GetState() == STATE_CLICKED) - { - menu = MENU_SETTINGS_FILE; - } - else if(menuBtn.GetState() == STATE_CLICKED) - { - menu = MENU_SETTINGS_MENU; - } - else if(networkBtn.GetState() == STATE_CLICKED) - { - menu = MENU_SETTINGS_NETWORK; - } - else if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_GAMESELECTION; - } - else if(resetBtn.GetState() == STATE_CLICKED) - { - resetBtn.ResetState(); - - int choice = WindowPrompt( - "Reset Settings", - "Are you sure that you want to reset your settings?", - "Yes", - "No"); - - if(choice == 1) - DefaultSettings(); - } - } - - HaltGui(); - mainWindow->Remove(&w); - return menu; -} - -/**************************************************************************** - * MenuSettingsFile - ***************************************************************************/ - -static int MenuSettingsFile() -{ - int menu = MENU_NONE; - int ret; - int i = 0; - bool firstRun = true; - OptionList options; - sprintf(options.name[i++], "Load Device"); - sprintf(options.name[i++], "Save Device"); - sprintf(options.name[i++], "Load Folder"); - sprintf(options.name[i++], "Save Folder"); - sprintf(options.name[i++], "Cheats Folder"); - sprintf(options.name[i++], "Auto Load"); - sprintf(options.name[i++], "Auto Save"); - options.length = i; - options.name[4][0] = 0; // hide cheats folder (not implemented) - - for(i=0; i < options.length; i++) - options.value[i][0] = 0; - - GuiText titleTxt("Settings - Saving & Loading", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_long_png); - GuiImageData btnOutlineOver(button_long_over_png); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(90, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiOptionBrowser optionBrowser(552, 248, &options); - optionBrowser.SetPosition(0, 108); - optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - optionBrowser.SetCol2Position(215); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&backBtn); - mainWindow->Append(&optionBrowser); - mainWindow->Append(&w); - mainWindow->Append(&titleTxt); - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - ret = optionBrowser.GetClickedOption(); - - switch (ret) - { - case 0: - GCSettings.LoadMethod++; - break; - - case 1: - GCSettings.SaveMethod++; - break; - - case 2: - OnScreenKeyboard(GCSettings.LoadFolder, MAXPATHLEN); - break; - - case 3: - OnScreenKeyboard(GCSettings.SaveFolder, MAXPATHLEN); - break; - - case 4: - OnScreenKeyboard(GCSettings.CheatFolder, MAXPATHLEN); - break; - - case 5: - GCSettings.AutoLoad++; - if (GCSettings.AutoLoad > 2) - GCSettings.AutoLoad = 0; - break; - - case 6: - GCSettings.AutoSave++; - if (GCSettings.AutoSave > 3) - GCSettings.AutoSave = 0; - break; - } - - if(ret >= 0 || firstRun) - { - firstRun = false; - - // some load/save methods are not implemented - here's where we skip them - // they need to be skipped in the order they were enumerated - - // no SD/USB ports on GameCube - #ifdef HW_DOL - if(GCSettings.LoadMethod == DEVICE_SD) - GCSettings.LoadMethod++; - if(GCSettings.SaveMethod == DEVICE_SD) - GCSettings.SaveMethod++; - if(GCSettings.LoadMethod == DEVICE_USB) - GCSettings.LoadMethod++; - if(GCSettings.SaveMethod == DEVICE_USB) - GCSettings.SaveMethod++; - #endif - - // saving to DVD is impossible - if(GCSettings.SaveMethod == DEVICE_DVD) - GCSettings.SaveMethod++; - - // don't allow SD Gecko on Wii - #ifdef HW_RVL - if(GCSettings.LoadMethod == DEVICE_SD_SLOTA) - GCSettings.LoadMethod++; - if(GCSettings.SaveMethod == DEVICE_SD_SLOTA) - GCSettings.SaveMethod++; - if(GCSettings.LoadMethod == DEVICE_SD_SLOTB) - GCSettings.LoadMethod++; - if(GCSettings.SaveMethod == DEVICE_SD_SLOTB) - GCSettings.SaveMethod++; - #endif - - // correct load/save methods out of bounds - if(GCSettings.LoadMethod > 6) - GCSettings.LoadMethod = 0; - if(GCSettings.SaveMethod > 6) - GCSettings.SaveMethod = 0; - - if (GCSettings.LoadMethod == DEVICE_AUTO) sprintf (options.value[0],"Auto Detect"); - else if (GCSettings.LoadMethod == DEVICE_SD) sprintf (options.value[0],"SD"); - else if (GCSettings.LoadMethod == DEVICE_USB) sprintf (options.value[0],"USB"); - else if (GCSettings.LoadMethod == DEVICE_DVD) sprintf (options.value[0],"DVD"); - else if (GCSettings.LoadMethod == DEVICE_SMB) sprintf (options.value[0],"Network"); - else if (GCSettings.LoadMethod == DEVICE_SD_SLOTA) sprintf (options.value[0],"SD Gecko Slot A"); - else if (GCSettings.LoadMethod == DEVICE_SD_SLOTB) sprintf (options.value[0],"SD Gecko Slot B"); - - if (GCSettings.SaveMethod == DEVICE_AUTO) sprintf (options.value[1],"Auto Detect"); - else if (GCSettings.SaveMethod == DEVICE_SD) sprintf (options.value[1],"SD"); - else if (GCSettings.SaveMethod == DEVICE_USB) sprintf (options.value[1],"USB"); - else if (GCSettings.SaveMethod == DEVICE_SMB) sprintf (options.value[1],"Network"); - else if (GCSettings.SaveMethod == DEVICE_SD_SLOTA) sprintf (options.value[1],"SD Gecko Slot A"); - else if (GCSettings.SaveMethod == DEVICE_SD_SLOTB) sprintf (options.value[1],"SD Gecko Slot B"); - - snprintf (options.value[2], 35, "%s", GCSettings.LoadFolder); - snprintf (options.value[3], 35, "%s", GCSettings.SaveFolder); - //snprintf (options.value[4], 30, "%s", GCSettings.CheatFolder); - - if (GCSettings.AutoLoad == 0) sprintf (options.value[5],"Off"); - else if (GCSettings.AutoLoad == 1) sprintf (options.value[5],"SRAM"); - else if (GCSettings.AutoLoad == 2) sprintf (options.value[5],"Snapshot"); - - if (GCSettings.AutoSave == 0) sprintf (options.value[6],"Off"); - else if (GCSettings.AutoSave == 1) sprintf (options.value[6],"SRAM"); - else if (GCSettings.AutoSave == 2) sprintf (options.value[6],"Snapshot"); - else if (GCSettings.AutoSave == 3) sprintf (options.value[6],"Both"); - - optionBrowser.TriggerUpdate(); - } - - if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_SETTINGS; - } - } - HaltGui(); - mainWindow->Remove(&optionBrowser); - mainWindow->Remove(&w); - mainWindow->Remove(&titleTxt); - return menu; -} - -/**************************************************************************** - * MenuSettingsMenu - ***************************************************************************/ -static int MenuSettingsMenu() -{ - int menu = MENU_NONE; - int ret; - int i = 0; - bool firstRun = true; - OptionList options; - - sprintf(options.name[i++], "Exit Action"); - sprintf(options.name[i++], "Wiimote Orientation"); - sprintf(options.name[i++], "Music Volume"); - sprintf(options.name[i++], "Sound Effects Volume"); - sprintf(options.name[i++], "Rumble"); - sprintf(options.name[i++], "Language"); - options.length = i; - - for(i=0; i < options.length; i++) - options.value[i][0] = 0; - - GuiText titleTxt("Settings - Menu", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_long_png); - GuiImageData btnOutlineOver(button_long_over_png); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(90, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiOptionBrowser optionBrowser(552, 248, &options); - optionBrowser.SetPosition(0, 108); - optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - optionBrowser.SetCol2Position(275); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&backBtn); - mainWindow->Append(&optionBrowser); - mainWindow->Append(&w); - mainWindow->Append(&titleTxt); - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - ret = optionBrowser.GetClickedOption(); - - switch (ret) - { - case 0: - GCSettings.ExitAction++; - if(GCSettings.ExitAction > 3) - GCSettings.ExitAction = 0; - break; - case 1: - GCSettings.WiimoteOrientation ^= 1; - break; - case 2: - GCSettings.MusicVolume += 10; - if(GCSettings.MusicVolume > 100) - GCSettings.MusicVolume = 0; - bgMusic->SetVolume(GCSettings.MusicVolume); - break; - case 3: - GCSettings.SFXVolume += 10; - if(GCSettings.SFXVolume > 100) - GCSettings.SFXVolume = 0; - break; - case 4: - GCSettings.Rumble ^= 1; - break; - case 5: - GCSettings.language++; - - if(GCSettings.language >= LANG_LENGTH) - GCSettings.language = LANG_JAPANESE; - - if(GCSettings.language == LANG_SIMP_CHINESE) - GCSettings.language = LANG_PORTUGUESE; - else if(GCSettings.language == LANG_JAPANESE) - GCSettings.language = LANG_ENGLISH; - break; - } - - if(ret >= 0 || firstRun) - { - firstRun = false; - - #ifdef HW_RVL - if (GCSettings.ExitAction == 1) - sprintf (options.value[0], "Return to Wii Menu"); - else if (GCSettings.ExitAction == 2) - sprintf (options.value[0], "Power off Wii"); - else if (GCSettings.ExitAction == 3) - sprintf (options.value[0], "Return to Loader"); - else - sprintf (options.value[0], "Auto"); - #else // GameCube - if(GCSettings.ExitAction > 1) - GCSettings.ExitAction = 0; - if (GCSettings.ExitAction == 0) - sprintf (options.value[0], "Return to Loader"); - else - sprintf (options.value[0], "Reboot"); - - options.name[1][0] = 0; // Wiimote - options.name[2][0] = 0; // Music - options.name[3][0] = 0; // Sound Effects - options.name[4][0] = 0; // Rumble - #endif - - if (GCSettings.WiimoteOrientation == 0) - sprintf (options.value[1], "Vertical"); - else if (GCSettings.WiimoteOrientation == 1) - sprintf (options.value[1], "Horizontal"); - - if(GCSettings.MusicVolume > 0) - sprintf(options.value[2], "%d%%", GCSettings.MusicVolume); - else - sprintf(options.value[2], "Mute"); - - if(GCSettings.SFXVolume > 0) - sprintf(options.value[3], "%d%%", GCSettings.SFXVolume); - else - sprintf(options.value[3], "Mute"); - - if (GCSettings.Rumble == 1) - sprintf (options.value[4], "Enabled"); - else - sprintf (options.value[4], "Disabled"); - - switch(GCSettings.language) - { - case LANG_JAPANESE: sprintf(options.value[5], "Japanese"); break; - case LANG_ENGLISH: sprintf(options.value[5], "English"); break; - case LANG_GERMAN: sprintf(options.value[5], "German"); break; - case LANG_FRENCH: sprintf(options.value[5], "French"); break; - case LANG_SPANISH: sprintf(options.value[5], "Spanish"); break; - case LANG_ITALIAN: sprintf(options.value[5], "Italian"); break; - case LANG_DUTCH: sprintf(options.value[5], "Dutch"); break; - case LANG_SIMP_CHINESE: sprintf(options.value[5], "Chinese (Simplified)"); break; - case LANG_TRAD_CHINESE: sprintf(options.value[5], "Chinese (Traditional)"); break; - case LANG_KOREAN: sprintf(options.value[5], "Korean"); break; - case LANG_PORTUGUESE: sprintf(options.value[5], "Portuguese"); break; - case LANG_BRAZILIAN_PORTUGUESE: sprintf(options.value[5], "Brazilian Portuguese"); break; - case LANG_CATALAN: sprintf(options.value[5], "Catalan"); break; - case LANG_TURKISH: sprintf(options.value[5], "Turkish"); break; - } - - optionBrowser.TriggerUpdate(); - } - - if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_SETTINGS; - } - } - HaltGui(); - mainWindow->Remove(&optionBrowser); - mainWindow->Remove(&w); - mainWindow->Remove(&titleTxt); - ResetText(); - return menu; -} - -/**************************************************************************** - * MenuSettingsNetwork - ***************************************************************************/ -static int MenuSettingsNetwork() -{ - int menu = MENU_NONE; - int ret; - int i = 0; - bool firstRun = true; - OptionList options; - sprintf(options.name[i++], "SMB Share IP"); - sprintf(options.name[i++], "SMB Share Name"); - sprintf(options.name[i++], "SMB Share Username"); - sprintf(options.name[i++], "SMB Share Password"); - options.length = i; - - for(i=0; i < options.length; i++) - options.value[i][0] = 0; - - GuiText titleTxt("Settings - Network", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_long_png); - GuiImageData btnOutlineOver(button_long_over_png); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(90, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - GuiOptionBrowser optionBrowser(552, 248, &options); - optionBrowser.SetPosition(0, 108); - optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - optionBrowser.SetCol2Position(290); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&backBtn); - mainWindow->Append(&optionBrowser); - mainWindow->Append(&w); - mainWindow->Append(&titleTxt); - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - ret = optionBrowser.GetClickedOption(); - - switch (ret) - { - case 0: - OnScreenKeyboard(GCSettings.smbip, 16); - break; - - case 1: - OnScreenKeyboard(GCSettings.smbshare, 20); - break; - - case 2: - OnScreenKeyboard(GCSettings.smbuser, 20); - break; - - case 3: - OnScreenKeyboard(GCSettings.smbpwd, 20); - break; - } - - if(ret >= 0 || firstRun) - { - firstRun = false; - snprintf (options.value[0], 25, "%s", GCSettings.smbip); - snprintf (options.value[1], 19, "%s", GCSettings.smbshare); - snprintf (options.value[2], 19, "%s", GCSettings.smbuser); - snprintf (options.value[3], 19, "%s", GCSettings.smbpwd); - optionBrowser.TriggerUpdate(); - } - - if(backBtn.GetState() == STATE_CLICKED) - { - menu = MENU_SETTINGS; - } - } - HaltGui(); - mainWindow->Remove(&optionBrowser); - mainWindow->Remove(&w); - mainWindow->Remove(&titleTxt); - CloseShare(); - return menu; -} - - -static int redAmount=128, greenAmount=128, blueAmount=128; -static GuiText *redText; -static GuiText *greenText; -static GuiText *blueText; -static GuiText *sampleText; - -static void RGBWindowUpdate(void * ptr, int red, int green, int blue) -{ - GuiButton * b = (GuiButton *)ptr; - if(b->GetState() == STATE_CLICKED) - { - redAmount += red; - if (redAmount>255) redAmount=255; - else if (redAmount<0) redAmount=0; - greenAmount += green; - if (greenAmount>255) greenAmount=255; - else if (greenAmount<0) greenAmount=0; - blueAmount += blue; - if (blueAmount>255) blueAmount=255; - else if (blueAmount<0) blueAmount=0; - - redText->SetColor((GXColor){redAmount, 0, 0, 255}); - greenText->SetColor((GXColor){0, greenAmount, 0, 255}); - blueText->SetColor((GXColor){0, 0, blueAmount, 255}); - sampleText->SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - - char shift[10]; - sprintf(shift, "%2x", redAmount); - redText->SetText(shift); - sprintf(shift, "%2x", greenAmount); - greenText->SetText(shift); - sprintf(shift, "%2x", blueAmount); - blueText->SetText(shift); - - b->ResetState(); - } -} - -static void LessRedClick(void * ptr) { RGBWindowUpdate(ptr, -8, 0, 0); } -static void LessGreenClick(void * ptr) { RGBWindowUpdate(ptr, 0, -8, 0); } -static void LessBlueClick(void * ptr) { RGBWindowUpdate(ptr, 0, 0, -8); } -static void MoreRedClick(void * ptr) { RGBWindowUpdate(ptr, +8, 0, 0); } -static void MoreGreenClick(void * ptr) { RGBWindowUpdate(ptr, 0, +8, 0); } -static void MoreBlueClick(void * ptr) { RGBWindowUpdate(ptr, 0, 0, +8); } - -static void PaletteWindow(const char *name) -{ - GuiWindow * w = new GuiWindow(500,480); - w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - w->SetPosition(0, -10); - - GuiImageData arrowUp(button_arrow_up_png); - GuiImageData arrowDown(button_arrow_down_png); - GuiImageData arrowUpOver(button_arrow_up_over_png); - GuiImageData arrowDownOver(button_arrow_down_over_png); - - GuiImage moreRedImg(&arrowUp); - GuiImage moreRedOverImg(&arrowUpOver); - GuiButton moreRedBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); - moreRedBtn.SetImage(&moreRedImg); - moreRedBtn.SetImageOver(&moreRedOverImg); - moreRedBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - moreRedBtn.SetPosition(-150,-60); - moreRedBtn.SetTrigger(trigA); - moreRedBtn.SetTrigger(trig2); - moreRedBtn.SetSelectable(true); - moreRedBtn.SetUpdateCallback(MoreRedClick); - - GuiImage lessRedImg(&arrowDown); - GuiImage lessRedOverImg(&arrowDownOver); - GuiButton lessRedBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); - lessRedBtn.SetImage(&lessRedImg); - lessRedBtn.SetImageOver(&lessRedOverImg); - lessRedBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - lessRedBtn.SetPosition(-150,+50); - lessRedBtn.SetTrigger(trigA); - lessRedBtn.SetTrigger(trig2); - lessRedBtn.SetSelectable(true); - lessRedBtn.SetUpdateCallback(LessRedClick); - - GuiImage moreGreenImg(&arrowUp); - GuiImage moreGreenOverImg(&arrowUpOver); - GuiButton moreGreenBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); - moreGreenBtn.SetImage(&moreGreenImg); - moreGreenBtn.SetImageOver(&moreGreenOverImg); - moreGreenBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - moreGreenBtn.SetPosition(-50,-60); - moreGreenBtn.SetTrigger(trigA); - moreGreenBtn.SetTrigger(trig2); - moreGreenBtn.SetSelectable(true); - moreGreenBtn.SetUpdateCallback(MoreGreenClick); - - GuiImage lessGreenImg(&arrowDown); - GuiImage lessGreenOverImg(&arrowDownOver); - GuiButton lessGreenBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); - lessGreenBtn.SetImage(&lessGreenImg); - lessGreenBtn.SetImageOver(&lessGreenOverImg); - lessGreenBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - lessGreenBtn.SetPosition(-50,+50); - lessGreenBtn.SetTrigger(trigA); - lessGreenBtn.SetTrigger(trig2); - lessGreenBtn.SetSelectable(true); - lessGreenBtn.SetUpdateCallback(LessGreenClick); - - GuiImage moreBlueImg(&arrowUp); - GuiImage moreBlueOverImg(&arrowUpOver); - GuiButton moreBlueBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); - moreBlueBtn.SetImage(&moreBlueImg); - moreBlueBtn.SetImageOver(&moreBlueOverImg); - moreBlueBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - moreBlueBtn.SetPosition(50,-60); - moreBlueBtn.SetTrigger(trigA); - moreBlueBtn.SetTrigger(trig2); - moreBlueBtn.SetSelectable(true); - moreBlueBtn.SetUpdateCallback(MoreBlueClick); - - GuiImage lessBlueImg(&arrowDown); - GuiImage lessBlueOverImg(&arrowDownOver); - GuiButton lessBlueBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); - lessBlueBtn.SetImage(&lessBlueImg); - lessBlueBtn.SetImageOver(&lessBlueOverImg); - lessBlueBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - lessBlueBtn.SetPosition(50,+50); - lessBlueBtn.SetTrigger(trigA); - lessBlueBtn.SetTrigger(trig2); - lessBlueBtn.SetSelectable(true); - lessBlueBtn.SetUpdateCallback(LessBlueClick); - - GuiImageData box(screen_position_png); - - GuiImage redBoxImg(&box); - redBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - redBoxImg.SetPosition(-150, 0); - - GuiImage greenBoxImg(&box); - greenBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - greenBoxImg.SetPosition(-50, 0); - - GuiImage blueBoxImg(&box); - blueBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); - blueBoxImg.SetPosition(+50, 0); - - char shift[10]; - redText = new GuiText(NULL, 20, (GXColor){128, 0, 0, 255}); - redText->SetPosition(-150,0); - sprintf(shift, "%2x", redAmount); - redText->SetText(shift); - - greenText = new GuiText(NULL, 20, (GXColor){0, 128, 0, 255}); - greenText->SetPosition(-50, 0); - sprintf(shift, "%2x", greenAmount); - greenText->SetText(shift); - - blueText = new GuiText(NULL, 20, (GXColor){0, 0, 128, 255}); - blueText->SetPosition(+50,0); - sprintf(shift, "%2x", blueAmount); - blueText->SetText(shift); - - sampleText = new GuiText(NULL, 20, (GXColor){redAmount, greenAmount, blueAmount, 255}); - sampleText->SetPosition(+150,0); - sampleText->SetText(name); - - int currentRed = redAmount; - int currentGreen = greenAmount; - int currentBlue = blueAmount; - - w->Append(&lessRedBtn); - w->Append(&moreRedBtn); - w->Append(&lessGreenBtn); - w->Append(&moreGreenBtn); - w->Append(&lessBlueBtn); - w->Append(&moreBlueBtn); - - w->Append(&redBoxImg); - w->Append(&greenBoxImg); - w->Append(&blueBoxImg); - - w->Append(sampleText); - w->Append(redText); - w->Append(greenText); - w->Append(blueText); - - if(!SettingWindow("Red Green Blue",w)) - { - redAmount = currentRed; // undo changes - greenAmount = currentGreen; - blueAmount = currentBlue; - } - - delete(w); - delete(redText); - delete(greenText); - delete(blueText); -} - -GXColor GetCol(int i) { - int c = 0; - u8 r=0, g=0, b=0; - if (unsigned(i) <= 13) - { - c = CurrentPalette.palette[i]; - r = (c >> 16) & 255; - g = (c >> 8) & 255; - b = (c) & 255; - - } - return (GXColor){r,g,b,255}; -} - -/**************************************************************************** - * MenuPalette - * - * Menu displayed when returning to the menu from in-game. - ***************************************************************************/ -static int MenuPalette() -{ - // We are now using a custom palette - strncpy(CurrentPalette.gameName, RomTitle, 17); - - int menu = MENU_NONE; - - GuiText titleTxt("Palette", 26, (GXColor){255, 255, 255, 255}); - titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); - titleTxt.SetPosition(50,50); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData btnOutline(button_png); - GuiImageData btnOutlineOver(button_over_png); - GuiImageData btnLargeOutline(button_large_png); - GuiImageData btnLargeOutlineOver(button_large_over_png); - GuiImageData btnCloseOutline(button_small_png); - GuiImageData btnCloseOutlineOver(button_small_over_png); - - GuiTrigger trigHome; - trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); - - GuiText bg0BtnTxt("BG 0", 24, GetCol(0)); - GuiImage bg0BtnImg(&btnCloseOutline); - GuiImage bg0BtnImgOver(&btnCloseOutlineOver); - GuiButton bg0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - bg0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - bg0Btn.SetPosition(-200, 120); - bg0Btn.SetLabel(&bg0BtnTxt); - bg0Btn.SetImage(&bg0BtnImg); - bg0Btn.SetImageOver(&bg0BtnImgOver); - bg0Btn.SetSoundOver(&btnSoundOver); - bg0Btn.SetSoundClick(&btnSoundClick); - bg0Btn.SetTrigger(trigA); - bg0Btn.SetTrigger(trig2); - bg0Btn.SetEffectGrow(); - - GuiText bg1BtnTxt("BG 1", 24, GetCol(1)); - GuiImage bg1BtnImg(&btnCloseOutline); - GuiImage bg1BtnImgOver(&btnCloseOutlineOver); - GuiButton bg1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - bg1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - bg1Btn.SetPosition(-200, 180); - bg1Btn.SetLabel(&bg1BtnTxt); - bg1Btn.SetImage(&bg1BtnImg); - bg1Btn.SetImageOver(&bg1BtnImgOver); - bg1Btn.SetSoundOver(&btnSoundOver); - bg1Btn.SetSoundClick(&btnSoundClick); - bg1Btn.SetTrigger(trigA); - bg1Btn.SetTrigger(trig2); - bg1Btn.SetEffectGrow(); - - GuiText bg2BtnTxt("BG 2", 24, GetCol(2)); - GuiImage bg2BtnImg(&btnCloseOutline); - GuiImage bg2BtnImgOver(&btnCloseOutlineOver); - GuiButton bg2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - bg2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - bg2Btn.SetPosition(-200, 240); - bg2Btn.SetLabel(&bg2BtnTxt); - bg2Btn.SetImage(&bg2BtnImg); - bg2Btn.SetImageOver(&bg2BtnImgOver); - bg2Btn.SetSoundOver(&btnSoundOver); - bg2Btn.SetSoundClick(&btnSoundClick); - bg2Btn.SetTrigger(trigA); - bg2Btn.SetTrigger(trig2); - bg2Btn.SetEffectGrow(); - - GuiText bg3BtnTxt("BG 3", 24, GetCol(3)); - GuiImage bg3BtnImg(&btnCloseOutline); - GuiImage bg3BtnImgOver(&btnCloseOutlineOver); - GuiButton bg3Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - bg3Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - bg3Btn.SetPosition(-200, 300); - bg3Btn.SetLabel(&bg3BtnTxt); - bg3Btn.SetImage(&bg3BtnImg); - bg3Btn.SetImageOver(&bg3BtnImgOver); - bg3Btn.SetSoundOver(&btnSoundOver); - bg3Btn.SetSoundClick(&btnSoundClick); - bg3Btn.SetTrigger(trigA); - bg3Btn.SetTrigger(trig2); - bg3Btn.SetEffectGrow(); - - GuiText win0BtnTxt("WIN 0", 24, GetCol(4)); - GuiImage win0BtnImg(&btnCloseOutline); - GuiImage win0BtnImgOver(&btnCloseOutlineOver); - GuiButton win0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - win0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - win0Btn.SetPosition(-70, 120); - win0Btn.SetLabel(&win0BtnTxt); - win0Btn.SetImage(&win0BtnImg); - win0Btn.SetImageOver(&win0BtnImgOver); - win0Btn.SetSoundOver(&btnSoundOver); - win0Btn.SetSoundClick(&btnSoundClick); - win0Btn.SetTrigger(trigA); - win0Btn.SetTrigger(trig2); - win0Btn.SetEffectGrow(); - - GuiText win1BtnTxt("WIN 1", 24, GetCol(5)); - GuiImage win1BtnImg(&btnCloseOutline); - GuiImage win1BtnImgOver(&btnCloseOutlineOver); - GuiButton win1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - win1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - win1Btn.SetPosition(-70, 180); - win1Btn.SetLabel(&win1BtnTxt); - win1Btn.SetImage(&win1BtnImg); - win1Btn.SetImageOver(&win1BtnImgOver); - win1Btn.SetSoundOver(&btnSoundOver); - win1Btn.SetSoundClick(&btnSoundClick); - win1Btn.SetTrigger(trigA); - win1Btn.SetTrigger(trig2); - win1Btn.SetEffectGrow(); - - GuiText win2BtnTxt("WIN 2", 24, GetCol(6)); - GuiImage win2BtnImg(&btnCloseOutline); - GuiImage win2BtnImgOver(&btnCloseOutlineOver); - GuiButton win2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - win2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - win2Btn.SetPosition(-70, 240); - win2Btn.SetLabel(&win2BtnTxt); - win2Btn.SetImage(&win2BtnImg); - win2Btn.SetImageOver(&win2BtnImgOver); - win2Btn.SetSoundOver(&btnSoundOver); - win2Btn.SetSoundClick(&btnSoundClick); - win2Btn.SetTrigger(trigA); - win2Btn.SetTrigger(trig2); - win2Btn.SetEffectGrow(); - - GuiText win3BtnTxt("WIN 3", 24, GetCol(7)); - GuiImage win3BtnImg(&btnCloseOutline); - GuiImage win3BtnImgOver(&btnCloseOutlineOver); - GuiButton win3Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - win3Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - win3Btn.SetPosition(-70, 300); - win3Btn.SetLabel(&win3BtnTxt); - win3Btn.SetImage(&win3BtnImg); - win3Btn.SetImageOver(&win3BtnImgOver); - win3Btn.SetSoundOver(&btnSoundOver); - win3Btn.SetSoundClick(&btnSoundClick); - win3Btn.SetTrigger(trigA); - win3Btn.SetTrigger(trig2); - win3Btn.SetEffectGrow(); - - GuiText obj0BtnTxt("OBJ 0", 24, GetCol(8)); - GuiImage obj0BtnImg(&btnCloseOutline); - GuiImage obj0BtnImgOver(&btnCloseOutlineOver); - GuiButton obj0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - obj0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - obj0Btn.SetPosition(+70, 120); - obj0Btn.SetLabel(&obj0BtnTxt); - obj0Btn.SetImage(&obj0BtnImg); - obj0Btn.SetImageOver(&obj0BtnImgOver); - obj0Btn.SetSoundOver(&btnSoundOver); - obj0Btn.SetSoundClick(&btnSoundClick); - obj0Btn.SetTrigger(trigA); - obj0Btn.SetTrigger(trig2); - obj0Btn.SetEffectGrow(); - - GuiText obj1BtnTxt("OBJ 1", 24, GetCol(9)); - GuiImage obj1BtnImg(&btnCloseOutline); - GuiImage obj1BtnImgOver(&btnCloseOutlineOver); - GuiButton obj1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - obj1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - obj1Btn.SetPosition(+70, 180); - obj1Btn.SetLabel(&obj1BtnTxt); - obj1Btn.SetImage(&obj1BtnImg); - obj1Btn.SetImageOver(&obj1BtnImgOver); - obj1Btn.SetSoundOver(&btnSoundOver); - obj1Btn.SetSoundClick(&btnSoundClick); - obj1Btn.SetTrigger(trigA); - obj1Btn.SetTrigger(trig2); - obj1Btn.SetEffectGrow(); - - GuiText obj2BtnTxt("OBJ 2", 24, GetCol(10)); - GuiImage obj2BtnImg(&btnCloseOutline); - GuiImage obj2BtnImgOver(&btnCloseOutlineOver); - GuiButton obj2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - obj2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - obj2Btn.SetPosition(+70, 240); - obj2Btn.SetLabel(&obj2BtnTxt); - obj2Btn.SetImage(&obj2BtnImg); - obj2Btn.SetImageOver(&obj2BtnImgOver); - obj2Btn.SetSoundOver(&btnSoundOver); - obj2Btn.SetSoundClick(&btnSoundClick); - obj2Btn.SetTrigger(trigA); - obj2Btn.SetTrigger(trig2); - obj2Btn.SetEffectGrow(); - - GuiText spr0BtnTxt("SPR 0", 24, GetCol(11)); - GuiImage spr0BtnImg(&btnCloseOutline); - GuiImage spr0BtnImgOver(&btnCloseOutlineOver); - GuiButton spr0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - spr0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - spr0Btn.SetPosition(+200, 120); - spr0Btn.SetLabel(&spr0BtnTxt); - spr0Btn.SetImage(&spr0BtnImg); - spr0Btn.SetImageOver(&spr0BtnImgOver); - spr0Btn.SetSoundOver(&btnSoundOver); - spr0Btn.SetSoundClick(&btnSoundClick); - spr0Btn.SetTrigger(trigA); - spr0Btn.SetTrigger(trig2); - spr0Btn.SetEffectGrow(); - - GuiText spr1BtnTxt("SPR 1", 24, GetCol(12)); - GuiImage spr1BtnImg(&btnCloseOutline); - GuiImage spr1BtnImgOver(&btnCloseOutlineOver); - GuiButton spr1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - spr1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - spr1Btn.SetPosition(+200, 180); - spr1Btn.SetLabel(&spr1BtnTxt); - spr1Btn.SetImage(&spr1BtnImg); - spr1Btn.SetImageOver(&spr1BtnImgOver); - spr1Btn.SetSoundOver(&btnSoundOver); - spr1Btn.SetSoundClick(&btnSoundClick); - spr1Btn.SetTrigger(trigA); - spr1Btn.SetTrigger(trig2); - spr1Btn.SetEffectGrow(); - - GuiText spr2BtnTxt("SPR 2", 24, GetCol(13)); - GuiImage spr2BtnImg(&btnCloseOutline); - GuiImage spr2BtnImgOver(&btnCloseOutlineOver); - GuiButton spr2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - spr2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - spr2Btn.SetPosition(+200, 240); - spr2Btn.SetLabel(&spr2BtnTxt); - spr2Btn.SetImage(&spr2BtnImg); - spr2Btn.SetImageOver(&spr2BtnImgOver); - spr2Btn.SetSoundOver(&btnSoundOver); - spr2Btn.SetSoundClick(&btnSoundClick); - spr2Btn.SetTrigger(trigA); - spr2Btn.SetTrigger(trig2); - spr2Btn.SetEffectGrow(); - - GuiText importBtnTxt("Load / Save", 22, (GXColor){0, 0, 0, 255}); - importBtnTxt.SetWrap(true, btnOutline.GetWidth()-30); - GuiImage importBtnImg(&btnOutline); - GuiImage importBtnImgOver(&btnOutlineOver); - GuiButton importBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - importBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - importBtn.SetPosition(140, 300); - importBtn.SetLabel(&importBtnTxt); - importBtn.SetImage(&importBtnImg); - importBtn.SetImageOver(&importBtnImgOver); - importBtn.SetSoundOver(&btnSoundOver); - importBtn.SetSoundClick(&btnSoundClick); - importBtn.SetTrigger(trigA); - importBtn.SetTrigger(trig2); - importBtn.SetEffectGrow(); - - GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); - GuiImage closeBtnImg(&btnCloseOutline); - GuiImage closeBtnImgOver(&btnCloseOutlineOver); - GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); - closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - closeBtn.SetPosition(-50, 35); - closeBtn.SetLabel(&closeBtnTxt); - closeBtn.SetImage(&closeBtnImg); - closeBtn.SetImageOver(&closeBtnImgOver); - closeBtn.SetSoundOver(&btnSoundOver); - closeBtn.SetSoundClick(&btnSoundClick); - closeBtn.SetTrigger(trigA); - closeBtn.SetTrigger(trig2); - closeBtn.SetTrigger(&trigHome); - closeBtn.SetEffectGrow(); - - GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); - GuiImage backBtnImg(&btnOutline); - GuiImage backBtnImgOver(&btnOutlineOver); - GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); - backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - backBtn.SetPosition(100, -35); - backBtn.SetLabel(&backBtnTxt); - backBtn.SetImage(&backBtnImg); - backBtn.SetImageOver(&backBtnImgOver); - backBtn.SetSoundOver(&btnSoundOver); - backBtn.SetSoundClick(&btnSoundClick); - backBtn.SetTrigger(trigA); - backBtn.SetTrigger(trig2); - backBtn.SetEffectGrow(); - - HaltGui(); - GuiWindow w(screenwidth, screenheight); - w.Append(&titleTxt); - w.Append(&bg0Btn); - w.Append(&bg1Btn); - w.Append(&bg2Btn); - w.Append(&bg3Btn); - w.Append(&win0Btn); - w.Append(&win1Btn); - w.Append(&win2Btn); - w.Append(&win3Btn); - w.Append(&obj0Btn); - w.Append(&obj1Btn); - w.Append(&obj2Btn); - w.Append(&spr0Btn); - w.Append(&spr1Btn); - w.Append(&spr2Btn); - w.Append(&importBtn); - w.Append(&closeBtn); - w.Append(&backBtn); - - mainWindow->Append(&w); - - ResumeGui(); - - while(menu == MENU_NONE) - { - usleep(THREAD_SLEEP); - - if(bg0Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[0] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[0] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[0] >> 0) & 0xFF; - PaletteWindow("BG 0"); - CurrentPalette.palette[0] = redAmount << 16 | greenAmount << 8 | blueAmount; - bg0BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - bg0Btn.ResetState(); - } - else if(bg1Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[1] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[1] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[1] >> 0) & 0xFF; - PaletteWindow("BG 1"); - CurrentPalette.palette[1] = redAmount << 16 | greenAmount << 8 | blueAmount; - bg1BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - bg1Btn.ResetState(); - } - else if(bg2Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[2] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[2] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[2] >> 0) & 0xFF; - PaletteWindow("BG 2"); - CurrentPalette.palette[2] = redAmount << 16 | greenAmount << 8 | blueAmount; - bg2BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - bg2Btn.ResetState(); - } - else if(bg3Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[3] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[3] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[3] >> 0) & 0xFF; - PaletteWindow("BG 3"); - CurrentPalette.palette[3] = redAmount << 16 | greenAmount << 8 | blueAmount; - bg3BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - bg3Btn.ResetState(); - } - else if(win0Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[4] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[4] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[4] >> 0) & 0xFF; - PaletteWindow("WIN 0"); - CurrentPalette.palette[4] = redAmount << 16 | greenAmount << 8 | blueAmount; - win0BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - win0Btn.ResetState(); - } - else if(win1Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[5] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[5] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[5] >> 0) & 0xFF; - PaletteWindow("WIN 1"); - CurrentPalette.palette[5] = redAmount << 16 | greenAmount << 8 | blueAmount; - win1BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - win1Btn.ResetState(); - } - else if(win2Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[6] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[6] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[6] >> 0) & 0xFF; - PaletteWindow("WIN 2"); - CurrentPalette.palette[6] = redAmount << 16 | greenAmount << 8 | blueAmount; - win2BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - win2Btn.ResetState(); - } - else if(win3Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[7] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[7] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[7] >> 0) & 0xFF; - PaletteWindow("WIN 3"); - CurrentPalette.palette[7] = redAmount << 16 | greenAmount << 8 | blueAmount; - win3BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - win3Btn.ResetState(); - } - else if(obj0Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[8] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[8] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[8] >> 0) & 0xFF; - PaletteWindow("OBJ 0"); - CurrentPalette.palette[8] = redAmount << 16 | greenAmount << 8 | blueAmount; - obj0BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - obj0Btn.ResetState(); - } - else if(obj1Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[9] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[9] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[9] >> 0) & 0xFF; - PaletteWindow("OBJ 1"); - CurrentPalette.palette[9] = redAmount << 16 | greenAmount << 8 | blueAmount; - obj1BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - obj1Btn.ResetState(); - } - else if(obj2Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[10] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[10] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[10] >> 0) & 0xFF; - PaletteWindow("OBJ 2"); - CurrentPalette.palette[10] = redAmount << 16 | greenAmount << 8 | blueAmount; - obj2BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - obj2Btn.ResetState(); - } - else if(spr0Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[11] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[11] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[11] >> 0) & 0xFF; - PaletteWindow("SPR 0"); - CurrentPalette.palette[11] = redAmount << 16 | greenAmount << 8 | blueAmount; - spr0BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - spr0Btn.ResetState(); - } - else if(spr1Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[12] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[12] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[12] >> 0) & 0xFF; - PaletteWindow("SPR 1"); - CurrentPalette.palette[12] = redAmount << 16 | greenAmount << 8 | blueAmount; - spr1BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - spr1Btn.ResetState(); - } - else if(spr2Btn.GetState() == STATE_CLICKED) - { - redAmount = (CurrentPalette.palette[13] >> 16) & 0xFF; - greenAmount = (CurrentPalette.palette[13] >> 8) & 0xFF; - blueAmount = (CurrentPalette.palette[13] >> 0) & 0xFF; - PaletteWindow("SPR 2"); - CurrentPalette.palette[13] = redAmount << 16 | greenAmount << 8 | blueAmount; - spr2BtnTxt.SetColor((GXColor){redAmount, greenAmount, blueAmount, 255}); - spr2Btn.ResetState(); - } - else if(importBtn.GetState() == STATE_CLICKED) - { - SavePaletteAs(NOTSILENT, RomTitle); - menu = MENU_GAMESETTINGS_PALETTE; - } - else if(closeBtn.GetState() == STATE_CLICKED) - { - menu = MENU_EXIT; - SavePaletteAs(SILENT, RomTitle); - - exitSound->Play(); - bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); - backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); - - w.SetEffect(EFFECT_FADE, -15); - - usleep(350000); // wait for effects to finish - } - else if(backBtn.GetState() == STATE_CLICKED) - { - SavePaletteAs(SILENT, RomTitle); - menu = MENU_GAMESETTINGS_VIDEO; - } - } - - HaltGui(); - mainWindow->Remove(&w); - return menu; -} - -/**************************************************************************** - * MainMenu - ***************************************************************************/ -void -MainMenu (int menu) -{ - static bool init = false; - int currentMenu = menu; - lastMenu = MENU_NONE; - - if(!init) - { - init = true; - #ifdef HW_RVL - pointer[0] = new GuiImageData(player1_point_png); - pointer[1] = new GuiImageData(player2_point_png); - pointer[2] = new GuiImageData(player3_point_png); - pointer[3] = new GuiImageData(player4_point_png); - #endif - - trigA = new GuiTrigger; - trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); - trig2 = new GuiTrigger; - trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); - } - - mainWindow = new GuiWindow(screenwidth, screenheight); - - if(menu == MENU_GAME) - { - gameScreen = new GuiImageData(gameScreenPng); - gameScreenImg = new GuiImage(gameScreen); - gameScreenImg->SetAlpha(192); - gameScreenImg->ColorStripe(30); - - gameScreenImg->SetScaleX(screenwidth/(float)vmode->fbWidth); - gameScreenImg->SetScaleY(screenheight/(float)vmode->efbHeight); - } - else - { - gameScreenImg = new GuiImage(screenwidth, screenheight, (GXColor){236, 226, 238, 255}); - gameScreenImg->ColorStripe(10); - } - - mainWindow->Append(gameScreenImg); - - GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); - GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); - GuiImageData bgTop(bg_top_png); - bgTopImg = new GuiImage(&bgTop); - GuiImageData bgBottom(bg_bottom_png); - bgBottomImg = new GuiImage(&bgBottom); - bgBottomImg->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); - GuiImageData logo(logo_png); - GuiImage logoImg(&logo); - GuiImageData logoOver(logo_over_png); - GuiImage logoImgOver(&logoOver); - GuiText logoTxt(APPVERSION, 18, (GXColor){255, 255, 255, 255}); - logoTxt.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - logoTxt.SetPosition(0, 4); - btnLogo = new GuiButton(logoImg.GetWidth(), logoImg.GetHeight()); - btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); - btnLogo->SetPosition(-50, 24); - btnLogo->SetImage(&logoImg); - btnLogo->SetImageOver(&logoImgOver); - btnLogo->SetLabel(&logoTxt); - btnLogo->SetSoundOver(&btnSoundOver); - btnLogo->SetSoundClick(&btnSoundClick); - btnLogo->SetTrigger(trigA); - btnLogo->SetTrigger(trig2); - btnLogo->SetUpdateCallback(WindowCredits); - - mainWindow->Append(bgTopImg); - mainWindow->Append(bgBottomImg); - mainWindow->Append(btnLogo); - - if(currentMenu == MENU_GAMESELECTION) - ResumeGui(); - - // Load preferences - if(!LoadPrefs()) - SavePrefs(SILENT); - -#ifdef HW_RVL - static bool checkIOS = true; - - if(checkIOS) - { - u32 ios = IOS_GetVersion(); - - if(!SupportedIOS(ios)) - ErrorPrompt("The current IOS is unsupported. Functionality and/or stability may be adversely affected."); - else if(!SaneIOS(ios)) - ErrorPrompt("The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected."); - } - - checkIOS = false; -#endif - - // Load palettes - LoadPalettes(); - - #ifndef NO_SOUND - bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, SOUND_OGG); - bgMusic->SetVolume(GCSettings.MusicVolume); - bgMusic->SetLoop(true); - enterSound = new GuiSound(enter_ogg, enter_ogg_size, SOUND_OGG); - enterSound->SetVolume(GCSettings.SFXVolume); - exitSound = new GuiSound(exit_ogg, exit_ogg_size, SOUND_OGG); - exitSound->SetVolume(GCSettings.SFXVolume); - if(currentMenu == MENU_GAMESELECTION) bgMusic->Play(); // startup music - #endif - - while(currentMenu != MENU_EXIT || !ROMLoaded) - { - switch (currentMenu) - { - case MENU_GAMESELECTION: - currentMenu = MenuGameSelection(); - break; - case MENU_GAME: - currentMenu = MenuGame(); - break; - case MENU_GAME_LOAD: - currentMenu = MenuGameSaves(0); - break; - case MENU_GAME_SAVE: - currentMenu = MenuGameSaves(1); - break; - case MENU_GAMESETTINGS: - currentMenu = MenuGameSettings(); - break; - case MENU_GAMESETTINGS_MAPPINGS: - currentMenu = MenuSettingsMappings(); - break; - case MENU_GAMESETTINGS_MAPPINGS_MAP: - currentMenu = MenuSettingsMappingsMap(); - break; - case MENU_GAMESETTINGS_VIDEO: - currentMenu = MenuSettingsVideo(); - break; - /*case MENU_GAMESETTINGS_CHEATS: - currentMenu = MenuGameCheats(); - break;*/ - case MENU_GAMESETTINGS_PALETTE: - currentMenu = MenuPalette(); - break; - case MENU_SETTINGS: - currentMenu = MenuSettings(); - break; - case MENU_SETTINGS_FILE: - currentMenu = MenuSettingsFile(); - break; - case MENU_SETTINGS_MENU: - currentMenu = MenuSettingsMenu(); - break; - case MENU_SETTINGS_NETWORK: - currentMenu = MenuSettingsNetwork(); - break; - default: // unrecognized menu - currentMenu = MenuGameSelection(); - break; - } - lastMenu = currentMenu; - usleep(THREAD_SLEEP); - } - - #ifdef HW_RVL - ShutoffRumble(); - #endif - - CancelAction(); - HaltGui(); - - #ifdef HW_RVL - if(updatethread != LWP_THREAD_NULL) - LWP_JoinThread(updatethread, NULL); - #endif - - #ifndef NO_SOUND - delete bgMusic; - delete enterSound; - delete exitSound; - #endif - - delete btnLogo; - delete gameScreenImg; - delete bgTopImg; - delete bgBottomImg; - delete mainWindow; - - mainWindow = NULL; - - if(gameScreen) - delete gameScreen; - - if(gameScreenPng) - { - free(gameScreenPng); - gameScreenPng = NULL; - } - - // wait for keys to be depressed - while(MenuRequested()) - { - UpdatePads(); - usleep(THREAD_SLEEP); - } -} +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric 2008-2009 + * + * menu.cpp + * + * Menu flow routines - handles all menu logic + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HW_RVL +#include +#endif + +#include "vbagx.h" +#include "vbasupport.h" +#include "video.h" +#include "filebrowser.h" +#include "gcunzip.h" +#include "networkop.h" +#include "fileop.h" +#include "preferences.h" +#include "button_mapping.h" +#include "input.h" +#include "filelist.h" +#include "menu.h" +#include "gamesettings.h" +#include "gui/gui.h" +#include "utils/gettext.h" + +#define THREAD_SLEEP 100 + +#ifdef HW_RVL +GuiImageData * pointer[4]; +#endif + +//#ifdef HW_RVL +// #include "mem2.h" +// +// #define MEM_ALLOC(A) (u8*)mem2_malloc(A) +// #define MEM_DEALLOC(A) mem2_free(A) +//#else + #define MEM_ALLOC(A) (u8*)memalign(32, A) + #define MEM_DEALLOC(A) free(A) +//#endif + +static GuiTrigger * trigA = NULL; +static GuiTrigger * trig2 = NULL; + +static GuiButton * btnLogo = NULL; +static GuiImageData * gameScreen = NULL; +static GuiImage * gameScreenImg = NULL; +static GuiImage * bgTopImg = NULL; +static GuiImage * bgBottomImg = NULL; +static GuiSound * bgMusic = NULL; +static GuiSound * enterSound = NULL; +static GuiSound * exitSound = NULL; +static GuiWindow * mainWindow = NULL; +static GuiText * settingText = NULL; +static GuiText * settingText2 = NULL; +//static int lastMenu = MENU_NONE; +static int mapMenuCtrl = 0; +static int wiiuproCtrl = 0; + +static lwp_t guithread = LWP_THREAD_NULL; +static lwp_t progressthread = LWP_THREAD_NULL; +#ifdef HW_RVL +static lwp_t updatethread = LWP_THREAD_NULL; +#endif +static bool guiHalt = true; +static int showProgress = 0; + +static char progressTitle[101]; +static char progressMsg[201]; +static int progressDone = 0; +static int progressTotal = 0; + +/**************************************************************************** + * ResumeGui + * + * Signals the GUI thread to start, and resumes the thread. This is called + * after finishing the removal/insertion of new elements, and after initial + * GUI setup. + ***************************************************************************/ +static void +ResumeGui() +{ + guiHalt = false; + LWP_ResumeThread (guithread); +} + +/**************************************************************************** + * HaltGui + * + * Signals the GUI thread to stop, and waits for GUI thread to stop + * This is necessary whenever removing/inserting new elements into the GUI. + * This eliminates the possibility that the GUI is in the middle of accessing + * an element that is being changed. + ***************************************************************************/ +static void +HaltGui() +{ + guiHalt = true; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(guithread)) + usleep(THREAD_SLEEP); +} + +void ResetText() +{ + LoadLanguage(); + + if(mainWindow) + mainWindow->ResetText(); +} + +/**************************************************************************** + * WindowPrompt + * + * Displays a prompt window to user, with information, an error message, or + * presenting a user with a choice + ***************************************************************************/ +int +WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label, bool btn1Default) +{ + if(!mainWindow || ExitRequested || ShutdownRequested) + return 0; + + int choice = -1; + + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_prompt_png); + GuiImageData btnOutlineOver(button_prompt_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-20); + msgTxt.SetWrap(true, 430); + + GuiText btn1Txt(btn1Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiImage btn1ImgOver(&btnOutlineOver); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + + if(btn2Label) + { + btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn1.SetPosition(20, -25); + } + else + { + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -25); + } + + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetImageOver(&btn1ImgOver); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetSoundClick(&btnSoundClick); + btn1.SetTrigger(trigA); + btn1.SetTrigger(trig2); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt(btn2Label, 22, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiImage btn2ImgOver(&btnOutlineOver); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn2.SetPosition(-20, -25); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetImageOver(&btn2ImgOver); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetSoundClick(&btnSoundClick); + btn2.SetTrigger(trigA); + btn2.SetTrigger(trig2); + btn2.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&btn1); + + if(btn2Label) + promptWindow.Append(&btn2); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + CancelAction(); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + if(btn2Label) + { + if (btn1Default) + { + btn2.ResetState(); + btn1.SetState(STATE_SELECTED); + } + else + { + btn1.ResetState(); + btn2.SetState(STATE_SELECTED); + } + } + ResumeGui(); + + while(choice == -1) + { + usleep(THREAD_SLEEP); + + if(btn1.GetState() == STATE_CLICKED) + choice = 1; + else if(btn2.GetState() == STATE_CLICKED) + choice = 0; + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(THREAD_SLEEP); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return choice; +} + +int +WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) +{ + return WindowPrompt(title, msg, btn1Label, btn2Label, false); +} + +#ifdef HW_RVL +/**************************************************************************** + * EmulatorUpdate + * + * Prompts for confirmation, and downloads/installs updates + ***************************************************************************/ +static void * +EmulatorUpdate (void *arg) +{ + bool installUpdate = WindowPrompt( + "Update Available", + "An update is available!", + "Update now", + "Update later"); + if(installUpdate) + if(DownloadUpdate()) + ExitRequested = 1; + return NULL; +} +#endif + +/**************************************************************************** + * UpdateGUI + * + * Primary thread to allow GUI to respond to state changes, and draws GUI + ***************************************************************************/ +static void * +UpdateGUI (void *arg) +{ + int i; + + while(1) + { + if(guiHalt) + LWP_SuspendThread(guithread); + + UpdatePads(); + mainWindow->Draw(); + + if (mainWindow->GetState() != STATE_DISABLED) + mainWindow->DrawTooltip(); + + #ifdef HW_RVL + i = 3; + do + { + if(userInput[i].wpad->ir.valid) + Menu_DrawImg(userInput[i].wpad->ir.x-48, userInput[i].wpad->ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad->ir.angle, 1, 1, 255); + DoRumble(i); + --i; + } while(i>=0); + #endif + + Menu_Render(); + + mainWindow->Update(&userInput[3]); + mainWindow->Update(&userInput[2]); + mainWindow->Update(&userInput[1]); + mainWindow->Update(&userInput[0]); + + #ifdef HW_RVL + if(updateFound) + { + updateFound = false; + if(!loadingFile) + LWP_CreateThread (&updatethread, EmulatorUpdate, NULL, NULL, 0, 70); + } + #endif + + if(ExitRequested || ShutdownRequested) + { + for(i = 0; i <= 255; i += 15) + { + mainWindow->Draw(); + Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, (u8)i},1); + Menu_Render(); + } + ExitApp(); + } + usleep(THREAD_SLEEP); + } + return NULL; +} + +/**************************************************************************** + * ProgressWindow + * + * Opens a window, which displays progress to the user. Can either display a + * progress bar showing % completion, or a throbber that only shows that an + * action is in progress. + ***************************************************************************/ +static int progsleep = 0; + +static void +ProgressWindow(char *title, char *msg) +{ + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiImageData progressbarOutline(progressbar_outline_png); + GuiImage progressbarOutlineImg(&progressbarOutline); + progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarOutlineImg.SetPosition(25, 40); + + GuiImageData progressbarEmpty(progressbar_empty_png); + GuiImage progressbarEmptyImg(&progressbarEmpty); + progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarEmptyImg.SetPosition(25, 40); + progressbarEmptyImg.SetTile(100); + + GuiImageData progressbar(progressbar_png); + GuiImage progressbarImg(&progressbar); + progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarImg.SetPosition(25, 40); + + GuiImageData throbber(throbber_png); + GuiImage throbberImg(&throbber); + throbberImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + throbberImg.SetPosition(0, 40); + + GuiText titleTxt(title, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + msgTxt.SetPosition(0,80); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + + if(showProgress == 1) + { + promptWindow.Append(&progressbarEmptyImg); + promptWindow.Append(&progressbarImg); + promptWindow.Append(&progressbarOutlineImg); + } + else + { + promptWindow.Append(&throbberImg); + } + + // wait to see if progress flag changes soon + progsleep = 800000; + + while(progsleep > 0) + { + if(!showProgress) + break; + usleep(THREAD_SLEEP); + progsleep -= THREAD_SLEEP; + } + + if(!showProgress) + return; + + HaltGui(); + int oldState = mainWindow->GetState(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + float angle = 0; + u32 count = 0; + + while(showProgress) + { + progsleep = 20000; + + while(progsleep > 0) + { + if(!showProgress) + break; + usleep(THREAD_SLEEP); + progsleep -= THREAD_SLEEP; + } + + if(showProgress == 1) + { + progressbarImg.SetTile(100*progressDone/progressTotal); + } + else if(showProgress == 2) + { + if(count % 5 == 0) + { + angle+=45.0f; + if(angle >= 360.0f) + angle = 0; + throbberImg.SetAngle(angle); + } + ++count; + } + } + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(oldState); + ResumeGui(); +} + +static void * ProgressThread (void *arg) +{ + while(1) + { + if(!showProgress) + LWP_SuspendThread (progressthread); + + ProgressWindow(progressTitle, progressMsg); + usleep(THREAD_SLEEP); + } + return NULL; +} + +/**************************************************************************** + * InitGUIThread + * + * Startup GUI threads + ***************************************************************************/ +void +InitGUIThreads() +{ + LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70); + LWP_CreateThread (&progressthread, ProgressThread, NULL, NULL, 0, 40); +} + +/**************************************************************************** + * CancelAction + * + * Signals the GUI progress window thread to halt, and waits for it to + * finish. Prevents multiple progress window events from interfering / + * overriding each other. + ***************************************************************************/ +void +CancelAction() +{ + showProgress = 0; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(progressthread)) + usleep(THREAD_SLEEP); +} + +/**************************************************************************** + * ShowProgress + * + * Updates the variables used by the progress window for drawing a progress + * bar. Also resumes the progress window thread if it is suspended. + ***************************************************************************/ +void +ShowProgress (const char *msg, int done, int total) +{ + if(!mainWindow || ExitRequested || ShutdownRequested) + return; + + if(total < (256*1024)) + return; + + if(done > total) // this shouldn't happen + done = total; + + if(showProgress != 1) + CancelAction(); // wait for previous progress window to finish + + snprintf(progressMsg, 200, "%s", msg); + sprintf(progressTitle, "Please Wait"); + showProgress = 1; + progressTotal = total; + progressDone = done; + LWP_ResumeThread (progressthread); +} + +/**************************************************************************** + * ShowAction + * + * Shows that an action is underway. Also resumes the progress window thread + * if it is suspended. + ***************************************************************************/ +void +ShowAction (const char *msg) +{ + if(!mainWindow || ExitRequested || ShutdownRequested) + return; + + if(showProgress != 0) + CancelAction(); // wait for previous progress window to finish + + snprintf(progressMsg, 200, "%s", msg); + sprintf(progressTitle, "Please Wait"); + showProgress = 2; + progressDone = 0; + progressTotal = 0; + LWP_ResumeThread (progressthread); +} + +void ErrorPrompt(const char *msg) +{ + WindowPrompt("Error", msg, "OK", NULL); +} + +int ErrorPromptRetry(const char *msg) +{ + return WindowPrompt("Error", msg, "Retry", "Cancel"); +} + +void InfoPrompt(const char *msg) +{ + WindowPrompt("Information", msg, "OK", NULL); +} + +int YesNoPrompt(const char *msg, bool yesDefault) +{ + return WindowPrompt("Goomba", msg, "Yes", "No", yesDefault); +} + +/**************************************************************************** + * OnScreenKeyboard + * + * Opens an on-screen keyboard window, with the data entered being stored + * into the specified variable. + ***************************************************************************/ +static void OnScreenKeyboard(char * var, u32 maxlen) +{ + int save = -1; + + GuiKeyboard keyboard(var, maxlen); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(25, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetSoundClick(&btnSoundClick); + okBtn.SetTrigger(trigA); + okBtn.SetTrigger(trig2); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiImage cancelBtnImgOver(&btnOutlineOver); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-25, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetImageOver(&cancelBtnImgOver); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetSoundClick(&btnSoundClick); + cancelBtn.SetTrigger(trigA); + cancelBtn.SetTrigger(trig2); + cancelBtn.SetEffectGrow(); + + keyboard.Append(&okBtn); + keyboard.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&keyboard); + mainWindow->ChangeFocus(&keyboard); + ResumeGui(); + + while(save == -1) + { + usleep(THREAD_SLEEP); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + + if(save) + { + snprintf(var, maxlen, "%s", keyboard.kbtextstr); + } + + HaltGui(); + mainWindow->Remove(&keyboard); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} + +/**************************************************************************** + * SettingWindow + * + * Opens a new window, with the specified window element appended. Allows + * for a customizable prompted setting. + ***************************************************************************/ +static int +SettingWindow(const char * title, GuiWindow * w) +{ + int save = -1; + + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + + GuiText okBtnTxt("OK", 22, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(20, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetSoundClick(&btnSoundClick); + okBtn.SetTrigger(trigA); + okBtn.SetTrigger(trig2); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 22, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiImage cancelBtnImgOver(&btnOutlineOver); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-20, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetImageOver(&cancelBtnImgOver); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetSoundClick(&btnSoundClick); + cancelBtn.SetTrigger(trigA); + cancelBtn.SetTrigger(trig2); + cancelBtn.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&okBtn); + promptWindow.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->Append(w); + mainWindow->ChangeFocus(w); + ResumeGui(); + + while(save == -1) + { + usleep(THREAD_SLEEP); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->Remove(w); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return save; +} + +/**************************************************************************** + * WindowCredits + * Display credits, legal copyright and licence + * + * THIS MUST NOT BE REMOVED OR DISABLED IN ANY DERIVATIVE WORK + ***************************************************************************/ +static void WindowCredits(void * ptr) +{ + if(btnLogo->GetState() != STATE_CLICKED) + return; + + btnLogo->ResetState(); + + bool exit = false; + int i = 0; + int y = 20; + + GuiWindow creditsWindow(screenwidth,screenheight); + GuiWindow creditsWindowBox(580,448); + creditsWindowBox.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiImageData creditsBox(credits_box_png); + GuiImage creditsBoxImg(&creditsBox); + creditsBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + creditsWindowBox.Append(&creditsBoxImg); + + int numEntries = 30; + GuiText * txt[numEntries]; + + txt[i] = new GuiText("Credits", 20, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=24; + + txt[i] = new GuiText("version 2.3.2 - github.com/libertyernie/vba-wii", 20, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=32; + + txt[i]->SetPresets(20, (GXColor){0, 0, 0, 255}, 0, + FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP); + + txt[i] = new GuiText("Coding (since 2014)"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("libertyernie & Glitch"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("Menu screenshot support"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("cebolleto"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("GBA tiled rendering"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("bgK (for RetroArch)"); + txt[i]->SetPosition(335,y); i++; y+=32; + + txt[i] = new GuiText("Coding & menu design"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("Tantric"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("Additional coding"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("Carl Kenner, dancinninjac"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("Menu artwork"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("the3seashells"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("Menu sound"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("Peter de Man"); + txt[i]->SetPosition(335,y); i++; y+=32; + + txt[i] = new GuiText("VBA GameCube"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("SoftDev, emukidid"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("Visual Boy Advance - M"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("VBA-M Team"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("Visual Boy Advance"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("Forgotten"); + txt[i]->SetPosition(335,y); i++; y+=24; + + txt[i] = new GuiText("libogc / devkitPPC"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("shagkur & wintermute"); + txt[i]->SetPosition(335,y); i++; y+=24; + txt[i] = new GuiText("FreeTypeGX"); + txt[i]->SetPosition(40,y); i++; + txt[i] = new GuiText("Armin Tamzarian"); + txt[i]->SetPosition(335,y); i++; y+=32; + + txt[i]->SetPresets(18, (GXColor){0, 0, 0, 255}, 0, + FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP, ALIGN_CENTRE, ALIGN_TOP); + + txt[i] = new GuiText("This software is open source and may be copied,"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("distributed, or modified under the terms of the"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("GNU General Public License (GPL) Version 2."); + txt[i]->SetPosition(0,y); i++; y+=20; + + char iosVersion[20]; + +#ifdef HW_RVL + sprintf(iosVersion, "IOS: %d", IOS_GetVersion()); +#endif + + txt[i] = new GuiText(iosVersion, 18, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + txt[i]->SetPosition(20,-20); + + for(i=0; i < numEntries; i++) + creditsWindowBox.Append(txt[i]); + + creditsWindow.Append(&creditsWindowBox); + + while(!exit) + { + UpdatePads(); + + gameScreenImg->Draw(); + bgBottomImg->Draw(); + bgTopImg->Draw(); + creditsWindow.Draw(); + + #ifdef HW_RVL + i = 3; + do { + if(userInput[i].wpad->ir.valid) + Menu_DrawImg(userInput[i].wpad->ir.x-48, userInput[i].wpad->ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad->ir.angle, 1, 1, 255); + DoRumble(i); + --i; + } while(i >= 0); + #endif + + Menu_Render(); + + if((userInput[0].wpad->btns_d || userInput[0].pad.btns_d || userInput[0].wupcdata.btns_d) || + (userInput[1].wpad->btns_d || userInput[1].pad.btns_d || userInput[1].wupcdata.btns_d) || + (userInput[2].wpad->btns_d || userInput[2].pad.btns_d || userInput[2].wupcdata.btns_d) || + (userInput[3].wpad->btns_d || userInput[3].pad.btns_d || userInput[3].wupcdata.btns_d)) + { + exit = true; + } + usleep(THREAD_SLEEP); + } + + // clear buttons pressed + for(i=0; i < 4; i++) + { + userInput[i].wupcdata.btns_d = 0; + userInput[i].wpad->btns_d = 0; + userInput[i].pad.btns_d = 0; + } + + for(i=0; i < numEntries; i++) + delete txt[i]; +} + +/**************************************************************************** + * MenuGameSelection + * + * Displays a list of games on the specified load device, and allows the user + * to browse and select from this list. + ***************************************************************************/ +static int MenuGameSelection() +{ + int menu = MENU_NONE; + bool res; + int i; + + GuiText titleTxt("Choose Game", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData iconHome(icon_home_png); + GuiImageData iconSettings(icon_settings_png); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + GuiImageData bgPreviewImg(bg_preview_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText settingsBtnTxt("Settings", 22, (GXColor){0, 0, 0, 255}); + GuiImage settingsBtnIcon(&iconSettings); + settingsBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + settingsBtnIcon.SetPosition(14,0); + GuiImage settingsBtnImg(&btnOutline); + GuiImage settingsBtnImgOver(&btnOutlineOver); + GuiButton settingsBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + settingsBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + settingsBtn.SetPosition(90, -35); + settingsBtn.SetLabel(&settingsBtnTxt); + settingsBtn.SetIcon(&settingsBtnIcon); + settingsBtn.SetImage(&settingsBtnImg); + settingsBtn.SetImageOver(&settingsBtnImgOver); + settingsBtn.SetSoundOver(&btnSoundOver); + settingsBtn.SetSoundClick(&btnSoundClick); + settingsBtn.SetTrigger(trigA); + settingsBtn.SetTrigger(trig2); + settingsBtn.SetEffectGrow(); + + GuiText exitBtnTxt("Exit", 22, (GXColor){0, 0, 0, 255}); + GuiImage exitBtnIcon(&iconHome); + exitBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + exitBtnIcon.SetPosition(14,0); + GuiImage exitBtnImg(&btnOutline); + GuiImage exitBtnImgOver(&btnOutlineOver); + GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + exitBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + exitBtn.SetPosition(-90, -35); + exitBtn.SetLabel(&exitBtnTxt); + exitBtn.SetIcon(&exitBtnIcon); + exitBtn.SetImage(&exitBtnImg); + exitBtn.SetImageOver(&exitBtnImgOver); + exitBtn.SetSoundOver(&btnSoundOver); + exitBtn.SetSoundClick(&btnSoundClick); + exitBtn.SetTrigger(trigA); + exitBtn.SetTrigger(trig2); + exitBtn.SetTrigger(&trigHome); + exitBtn.SetEffectGrow(); + + GuiWindow buttonWindow(screenwidth, screenheight); + buttonWindow.Append(&settingsBtn); + buttonWindow.Append(&exitBtn); + + GuiFileBrowser gameBrowser(330, 268); + gameBrowser.SetPosition(30, 98); + ResetBrowser(); + + GuiImage bgPreview(&bgPreviewImg); + bgPreview.SetPosition(365, 98); + + GuiImage preview; + preview.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + preview.SetPosition(174, -8); + u8* imgBuffer = MEM_ALLOC(512 * 512 * 4); + int previousBrowserIndex = -1; + char screenshotPath[MAXJOLIET + 1]; + + HaltGui(); + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo->SetPosition(-50, 24); + mainWindow->Append(&titleTxt); + mainWindow->Append(&gameBrowser); + mainWindow->Append(&buttonWindow); + mainWindow->Append(&bgPreview); + mainWindow->Append(&preview); + ResumeGui(); + + #ifdef HW_RVL + ShutoffRumble(); + #endif + + // populate initial directory listing + selectLoadedFile = 1; + OpenGameList(); + + gameBrowser.ResetState(); + gameBrowser.fileList[0]->SetState(STATE_SELECTED); + gameBrowser.TriggerUpdate(); + titleTxt.SetText(inSz ? szname : "Choose Game"); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(selectLoadedFile == 2) + { + selectLoadedFile = 0; + mainWindow->ChangeFocus(&gameBrowser); + gameBrowser.TriggerUpdate(); + } + + //update game screenshot + if(previousBrowserIndex != browser.selIndex) + { + previousBrowserIndex = browser.selIndex; + snprintf(screenshotPath, MAXJOLIET, "%s%s/%s.png", pathPrefix[GCSettings.LoadMethod], GCSettings.ScreenshotsFolder, browserList[browser.selIndex].displayname); + + AllocSaveBuffer(); + int width, height; + if(LoadFile(screenshotPath, SILENT)) + { + if(DecodePNG(savebuffer, &width, &height, imgBuffer, 512, 512)) + { + preview.SetImage(imgBuffer, width, height); + preview.SetScale( MIN(225.0f / width, 235.0f / height) ); + } + else + { + preview.SetImage(NULL, 0, 0); + } + } + else + { + preview.SetImage(NULL, 0, 0); + + } + FreeSaveBuffer(); + } + + // update gameWindow based on arrow buttons + // set MENU_EXIT if A button pressed on a game + for(i=0; i < FILE_PAGESIZE; i++) + { + if(gameBrowser.fileList[i]->GetState() == STATE_CLICKED) + { + gameBrowser.fileList[i]->ResetState(); + + // check corresponding browser entry + if(browserList[browser.selIndex].isdir || IsSz()) + { + HaltGui(); + res = BrowserChangeFolder(); + if(res) + { + gameBrowser.ResetState(); + gameBrowser.fileList[0]->SetState(STATE_SELECTED); + gameBrowser.TriggerUpdate(); + previousBrowserIndex = -1; + } + else + { + menu = MENU_GAMESELECTION; + break; + } + + + titleTxt.SetText(inSz ? szname : "Choose Game"); + + ResumeGui(); + } + else + { + #ifdef HW_RVL + ShutoffRumble(); + #endif + mainWindow->SetState(STATE_DISABLED); + SavePrefs(SILENT); + if(BrowserLoadFile()) + menu = MENU_EXIT; + else + mainWindow->SetState(STATE_DEFAULT); + } + } + } + + + + if(settingsBtn.GetState() == STATE_CLICKED) + menu = MENU_SETTINGS; + else if(exitBtn.GetState() == STATE_CLICKED) + ExitRequested = 1; + } + + HaltParseThread(); // halt parsing + HaltGui(); + ResetBrowser(); + mainWindow->Remove(&titleTxt); + mainWindow->Remove(&buttonWindow); + mainWindow->Remove(&gameBrowser); + mainWindow->Remove(&preview); + MEM_DEALLOC(imgBuffer); + return menu; +} + +extern char DebugStr[50]; + +/**************************************************************************** + * MenuGame + * + * Menu displayed when returning to the menu from in-game. + ***************************************************************************/ +static int MenuGame(int lastMenu) +{ + int menu = MENU_NONE; + + // Weather menu if a game with Boktai solar sensor + bool isBoktai = ((RomIdCode & 0xFF)=='U'); + char s[64]; + + GuiText titleTxt(ROMFilename, 22, (GXColor){255, 255, 255, 255}); + if (DebugStr[0]) titleTxt.SetText(DebugStr); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconGameSettings(icon_game_settings_png); + GuiImageData iconLoad(icon_game_load_png); + GuiImageData iconSave(icon_game_save_png); + GuiImageData iconReset(icon_game_reset_png); + + GuiImageData battery(battery_png); + GuiImageData batteryRed(battery_red_png); + GuiImageData batteryBar(battery_bar_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + int xOffset=125, yOffset=65; + if (isBoktai) { + xOffset=170; yOffset=70; + } + + GuiText saveBtnTxt("Save", 22, (GXColor){0, 0, 0, 255}); + GuiImage saveBtnImg(&btnLargeOutline); + GuiImage saveBtnImgOver(&btnLargeOutlineOver); + GuiImage saveBtnIcon(&iconSave); + GuiButton saveBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + saveBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + saveBtn.SetPosition(-xOffset, 185-yOffset); + saveBtn.SetLabel(&saveBtnTxt); + saveBtn.SetImage(&saveBtnImg); + saveBtn.SetImageOver(&saveBtnImgOver); + saveBtn.SetIcon(&saveBtnIcon); + saveBtn.SetSoundOver(&btnSoundOver); + saveBtn.SetSoundClick(&btnSoundClick); + saveBtn.SetTrigger(trigA); + saveBtn.SetTrigger(trig2); + saveBtn.SetEffectGrow(); + + GuiText loadBtnTxt("Load", 22, (GXColor){0, 0, 0, 255}); + GuiImage loadBtnImg(&btnLargeOutline); + GuiImage loadBtnImgOver(&btnLargeOutlineOver); + GuiImage loadBtnIcon(&iconLoad); + GuiButton loadBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + loadBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + loadBtn.SetPosition(xOffset, 185-yOffset); + loadBtn.SetLabel(&loadBtnTxt); + loadBtn.SetImage(&loadBtnImg); + loadBtn.SetImageOver(&loadBtnImgOver); + loadBtn.SetIcon(&loadBtnIcon); + loadBtn.SetSoundOver(&btnSoundOver); + loadBtn.SetSoundClick(&btnSoundClick); + loadBtn.SetTrigger(trigA); + loadBtn.SetTrigger(trig2); + loadBtn.SetEffectGrow(); + + // Boktai adds an extra button for setting the sun. + GuiText *sunBtnTxt = NULL; + GuiImage *sunBtnImg = NULL; + GuiImage *sunBtnImgOver = NULL; + GuiButton *sunBtn = NULL; + if (isBoktai) { + struct tm *newtime; + time_t long_time; + + // regardless of the weather, there should be no sun at night time! + time(&long_time); // Get time as long integer. + newtime = localtime(&long_time); // Convert to local time. + if (newtime->tm_hour > 21 || newtime->tm_hour < 5) + { + sprintf(s, "Weather: Night Time"); + } else sprintf(s, "Weather: %d%% sun", SunBars*10); + sunBtnTxt = new GuiText(s, 22, (GXColor){0, 0, 0, 255}); + sunBtnTxt->SetWrap(true, btnLargeOutline.GetWidth()-30); + sunBtnImg = new GuiImage(&btnLargeOutline); + sunBtnImgOver = new GuiImage(&btnLargeOutlineOver); + sunBtn = new GuiButton(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + sunBtn->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + sunBtn->SetPosition(0, 185); + sunBtn->SetLabel(sunBtnTxt); + sunBtn->SetImage(sunBtnImg); + sunBtn->SetImageOver(sunBtnImgOver); + sunBtn->SetSoundOver(&btnSoundOver); + sunBtn->SetSoundClick(&btnSoundClick); + sunBtn->SetTrigger(trigA); + sunBtn->SetTrigger(trig2); + sunBtn->SetEffectGrow(); + } + + GuiText resetBtnTxt("Reset", 22, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnLargeOutline); + GuiImage resetBtnImgOver(&btnLargeOutlineOver); + GuiImage resetBtnIcon(&iconReset); + GuiButton resetBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + resetBtn.SetPosition(xOffset, 185+yOffset); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetIcon(&resetBtnIcon); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetSoundClick(&btnSoundClick); + resetBtn.SetTrigger(trigA); + resetBtn.SetTrigger(trig2); + resetBtn.SetEffectGrow(); + + GuiText gameSettingsBtnTxt("Game Settings", 22, (GXColor){0, 0, 0, 255}); + gameSettingsBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage gameSettingsBtnImg(&btnLargeOutline); + GuiImage gameSettingsBtnImgOver(&btnLargeOutlineOver); + GuiImage gameSettingsBtnIcon(&iconGameSettings); + GuiButton gameSettingsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + gameSettingsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + gameSettingsBtn.SetPosition(-xOffset, 185+yOffset); + gameSettingsBtn.SetLabel(&gameSettingsBtnTxt); + gameSettingsBtn.SetImage(&gameSettingsBtnImg); + gameSettingsBtn.SetImageOver(&gameSettingsBtnImgOver); + gameSettingsBtn.SetIcon(&gameSettingsBtnIcon); + gameSettingsBtn.SetSoundOver(&btnSoundOver); + gameSettingsBtn.SetSoundClick(&btnSoundClick); + gameSettingsBtn.SetTrigger(trigA); + gameSettingsBtn.SetTrigger(trig2); + gameSettingsBtn.SetEffectGrow(); + + GuiText mainmenuBtnTxt("Main Menu", 22, (GXColor){0, 0, 0, 255}); + GuiImage mainmenuBtnImg(&btnOutline); + GuiImage mainmenuBtnImgOver(&btnOutlineOver); + GuiButton mainmenuBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + mainmenuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + mainmenuBtn.SetPosition(0, -35); + mainmenuBtn.SetLabel(&mainmenuBtnTxt); + mainmenuBtn.SetImage(&mainmenuBtnImg); + mainmenuBtn.SetImageOver(&mainmenuBtnImgOver); + mainmenuBtn.SetSoundOver(&btnSoundOver); + mainmenuBtn.SetSoundClick(&btnSoundClick); + mainmenuBtn.SetTrigger(trigA); + mainmenuBtn.SetTrigger(trig2); + mainmenuBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + #ifdef HW_RVL + int i; + char txt[3]; + bool status[4] = { false, false, false, false }; + int level[4] = { 0, 0, 0, 0 }; + bool newStatus; + int newLevel; + GuiText * batteryTxt[4]; + GuiImage * batteryImg[4]; + GuiImage * batteryBarImg[4]; + GuiButton * batteryBtn[4]; + + for(i=0; i < 4; ++i) + { + sprintf(txt, "P%d", i+1); + + batteryTxt[i] = new GuiText(txt, 20, (GXColor){255, 255, 255, 255}); + batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i] = new GuiImage(&battery); + batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i]->SetPosition(30, 0); + batteryBarImg[i] = new GuiImage(&batteryBar); + batteryBarImg[i]->SetTile(0); + batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryBarImg[i]->SetPosition(34, 0); + + batteryBtn[i] = new GuiButton(70, 20); + batteryBtn[i]->SetLabel(batteryTxt[i]); + batteryBtn[i]->SetImage(batteryImg[i]); + batteryBtn[i]->SetIcon(batteryBarImg[i]); + batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + batteryBtn[i]->SetRumble(false); + batteryBtn[i]->SetSelectable(false); + batteryBtn[i]->SetAlpha(150); + } + + batteryBtn[0]->SetPosition(45, -65); + batteryBtn[1]->SetPosition(135, -65); + batteryBtn[2]->SetPosition(45, -40); + batteryBtn[3]->SetPosition(135, -40); + #endif + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&saveBtn); + w.Append(&loadBtn); + w.Append(&resetBtn); + w.Append(&gameSettingsBtn); + if (isBoktai) + w.Append(sunBtn); + + #ifdef HW_RVL + w.Append(batteryBtn[0]); + w.Append(batteryBtn[1]); + w.Append(batteryBtn[2]); + w.Append(batteryBtn[3]); + #endif + + w.Append(&mainmenuBtn); + w.Append(&closeBtn); + + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btnLogo->SetPosition(-50, -40); + mainWindow->Append(&w); + + if(lastMenu == MENU_NONE) + { + enterSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + #ifdef HW_RVL + batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + #endif + + w.SetEffect(EFFECT_FADE, 15); + } + + ResumeGui(); + + if(lastMenu == MENU_NONE) + { + if (GCSettings.AutoSave == 1) + { + SaveBatteryOrStateAuto(FILE_SRAM, SILENT); // save battery + } + else if (GCSettings.AutoSave == 2) + { + if (WindowPrompt("Save", "Save Snapshot?", "Save", "Don't Save") ) + SaveBatteryOrStateAuto(FILE_SNAPSHOT, NOTSILENT); // save state + } + else if (GCSettings.AutoSave == 3) + { + if (WindowPrompt("Save", "Save SRAM and Snapshot?", "Save", "Don't Save") ) + { + SaveBatteryOrStateAuto(FILE_SRAM, NOTSILENT); // save battery + SaveBatteryOrStateAuto(FILE_SNAPSHOT, NOTSILENT); // save state + } + } + } + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) + { + newStatus = true; + newLevel = (userInput[i].wpad->battery_level / 100.0) * 4; + if(newLevel > 4) newLevel = 4; + } + else + { + struct WUPCData *data = WUPC_Data(i); + if(data != NULL) + { + newStatus = true; + newLevel = data->battery; + } + else + { + newStatus = false; + newLevel = 0; + } + } + + if(status[i] != newStatus || level[i] != newLevel) + { + if(newStatus == true) // controller connected + { + batteryBtn[i]->SetAlpha(255); + batteryBarImg[i]->SetTile(newLevel); + + if(newLevel == 0) + batteryImg[i]->SetImage(&batteryRed); + else + batteryImg[i]->SetImage(&battery); + } + else // controller not connected + { + batteryBtn[i]->SetAlpha(150); + batteryBarImg[i]->SetTile(0); + batteryImg[i]->SetImage(&battery); + } + status[i] = newStatus; + level[i] = newLevel; + } + } + #endif + + if (isBoktai) + { + if (sunBtn->GetState() == STATE_CLICKED) { + ++SunBars; + if (SunBars>10) SunBars=0; + menu = MENU_GAME; + } + } + + if(saveBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME_SAVE; + } + else if(loadBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME_LOAD; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + if (WindowPrompt("Reset Game", "Reset this game? Any unsaved progress will be lost.", "OK", "Cancel")) + { + emulator.emuReset(); + menu = MENU_EXIT; + } + } + else if(gameSettingsBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + else if(mainmenuBtn.GetState() == STATE_CLICKED) + { + if (WindowPrompt("Quit Game", "Quit this game? Any unsaved progress will be lost.", "OK", "Cancel")) + { + HaltGui(); + mainWindow->Remove(gameScreenImg); + delete gameScreenImg; + delete gameScreen; + gameScreen = NULL; + free(gameScreenPng); + gameScreenPng = NULL; + gameScreenImg = new GuiImage(screenwidth, screenheight, (GXColor){236, 226, 238, 255}); + gameScreenImg->ColorStripe(10); + mainWindow->Insert(gameScreenImg, 0); + ResumeGui(); + #ifndef NO_SOUND + bgMusic->Play(); // startup music + #endif + menu = MENU_GAMESELECTION; + } + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + #ifdef HW_RVL + batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + #endif + + w.SetEffect(EFFECT_FADE, -15); + usleep(350000); // wait for effects to finish + } + } + + HaltGui(); + + if (isBoktai) { + delete sunBtnTxt; + delete sunBtnImg; + delete sunBtnImgOver; + delete sunBtn; + } + + #ifdef HW_RVL + for(i=0; i < 4; ++i) + { + delete batteryTxt[i]; + delete batteryImg[i]; + delete batteryBarImg[i]; + delete batteryBtn[i]; + } + #endif + + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * FindGameSaveNum + * + * Determines the save file number of the given file name + * Returns -1 if none is found + ***************************************************************************/ +static int FindGameSaveNum(char * savefile, int method) +{ + int n = -1; + int romlen = strlen(ROMFilename); + int savelen = strlen(savefile); + int diff = savelen-romlen; + + if(strncmp(savefile, ROMFilename, romlen) != 0) + return -1; + + if(savefile[romlen] == ' ') + { + if(diff == 5 && strncmp(&savefile[romlen+1], "Auto", 4) == 0) + n = 0; // found Auto save + else if(diff == 2 || diff == 3) + n = atoi(&savefile[romlen+1]); + } + + if(n >= 0 && n < MAX_SAVES) + return n; + else + return -1; +} + +/**************************************************************************** + * MenuGameSaves + * + * Allows the user to load or save progress. + ***************************************************************************/ +static int MenuGameSaves(int action) +{ + SaveList saves; + struct stat filestat; + struct tm * timeinfo; + + int menu = MENU_NONE; + int ret, result; + int i, n, type, len, len2; + int j = 0; + + char filepath[1024]; + char scrfile[1024]; + char tmp[MAXJOLIET+1]; + + int method = GCSettings.SaveMethod; + + if(method == DEVICE_AUTO) + autoSaveMethod(NOTSILENT); + + if(!ChangeInterface(method, NOTSILENT)) + return MENU_GAME; + + GuiText titleTxt(NULL, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + if(action == 0) + titleTxt.SetText("Load Game"); + else + titleTxt.SetText("Save Game"); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + w.Append(&closeBtn); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + memset(&saves, 0, sizeof(saves)); + + sprintf(browser.dir, "%s%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder); + ParseDirectory(true, false); + + len = strlen(ROMFilename); + + // find matching files + AllocSaveBuffer(); + + for(i=0; i < browser.numEntries; i++) + { + len2 = strlen(browserList[i].filename); + + if(len2 < 6 || len2-len < 5) + continue; + + if(strncmp(&browserList[i].filename[len2-4], ".sav", 4) == 0) + type = FILE_SRAM; + else if(strncmp(&browserList[i].filename[len2-4], ".sgm", 4) == 0) + type = FILE_SNAPSHOT; + else + continue; + + strcpy(tmp, browserList[i].filename); + tmp[len2-4] = 0; + n = FindGameSaveNum(tmp, method); + + if(n >= 0) + { + saves.type[j] = type; + saves.files[saves.type[j]][n] = 1; + strcpy(saves.filename[j], browserList[i].filename); + + if(saves.type[j] == FILE_SNAPSHOT) + { + sprintf(scrfile, "%s%s/%s.png", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, tmp); + + memset(savebuffer, 0, SAVEBUFFERSIZE); + if(LoadFile(scrfile, SILENT)) + saves.previewImg[j] = new GuiImageData(savebuffer, 64, 48); + } + snprintf(filepath, 1024, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, saves.filename[j]); + if (stat(filepath, &filestat) == 0) + { + timeinfo = localtime(&filestat.st_mtime); + strftime(saves.date[j], 20, "%a %b %d", timeinfo); + strftime(saves.time[j], 10, "%I:%M %p", timeinfo); + } + ++j; + } + } + + FreeSaveBuffer(); + saves.length = j; + + if(saves.length == 0 && action == 0) + { + InfoPrompt("No game saves found."); + menu = MENU_GAME; + } + + GuiSaveBrowser saveBrowser(552, 248, &saves, action); + saveBrowser.SetPosition(0, 108); + saveBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + mainWindow->Append(&saveBrowser); + mainWindow->ChangeFocus(&saveBrowser); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = saveBrowser.GetClickedSave(); + + // load or save game + if(ret > -3) + { + result = 0; + + if(action == 0) // load + { + MakeFilePath(filepath, saves.type[ret], saves.filename[ret]); + switch(saves.type[ret]) + { + case FILE_SRAM: + result = LoadBatteryOrState(filepath, saves.type[ret], NOTSILENT); + emulator.emuReset(); + break; + case FILE_SNAPSHOT: + result = LoadBatteryOrState(filepath, saves.type[ret], NOTSILENT); + break; + } + if(result) + menu = MENU_EXIT; + } + else // save + { + if(ret == -2) // new SRAM + { + for(i=1; i < 100; i++) + if(saves.files[FILE_SRAM][i] == 0) + break; + + if(i < 100) + { + MakeFilePath(filepath, FILE_SRAM, ROMFilename, i); + SaveBatteryOrState(filepath, FILE_SRAM, NOTSILENT); + menu = MENU_GAME_SAVE; + } + } + else if(ret == -1) // new Snapshot + { + for(i=1; i < 100; i++) + if(saves.files[FILE_SNAPSHOT][i] == 0) + break; + + if(i < 100) + { + MakeFilePath(filepath, FILE_SNAPSHOT, ROMFilename, i); + SaveBatteryOrState(filepath, FILE_SNAPSHOT, NOTSILENT); + menu = MENU_GAME_SAVE; + } + } + else // overwrite SRAM/Snapshot + { + MakeFilePath(filepath, saves.type[ret], saves.filename[ret]); + switch(saves.type[ret]) + { + case FILE_SRAM: + SaveBatteryOrState(filepath, FILE_SRAM, NOTSILENT); + break; + case FILE_SNAPSHOT: + SaveBatteryOrState(filepath, FILE_SNAPSHOT, NOTSILENT); + break; + } + menu = MENU_GAME_SAVE; + } + } + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME; + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(350000); // wait for effects to finish + } + } + + HaltGui(); + + for(i=0; i < saves.length; i++) + if(saves.previewImg[i]) + delete saves.previewImg[i]; + + mainWindow->Remove(&saveBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + ResetBrowser(); + return menu; +} + + +/**************************************************************************** + * MenuGameSettings + ***************************************************************************/ +static int MenuGameSettings() +{ + int menu = MENU_NONE; + char s[4]; + char filepath[1024]; + + GuiText titleTxt("Game Settings", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconMappings(icon_settings_mappings_png); + GuiImageData iconVideo(icon_settings_video_png); +#ifdef HW_RVL + GuiImageData iconWiiControls(icon_settings_nunchuk_png); +#else + GuiImageData iconWiiControls(icon_settings_gamecube_png); +#endif + GuiImageData iconScreenshot(icon_settings_screenshot_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText mappingBtnTxt("Button Mappings", 22, (GXColor){0, 0, 0, 255}); + mappingBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage mappingBtnImg(&btnLargeOutline); + GuiImage mappingBtnImgOver(&btnLargeOutlineOver); + GuiImage mappingBtnIcon(&iconMappings); + GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + mappingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + mappingBtn.SetPosition(-125, 120); + mappingBtn.SetLabel(&mappingBtnTxt); + mappingBtn.SetImage(&mappingBtnImg); + mappingBtn.SetImageOver(&mappingBtnImgOver); + mappingBtn.SetIcon(&mappingBtnIcon); + mappingBtn.SetSoundOver(&btnSoundOver); + mappingBtn.SetSoundClick(&btnSoundClick); + mappingBtn.SetTrigger(trigA); + mappingBtn.SetTrigger(trig2); + mappingBtn.SetEffectGrow(); + + GuiText videoBtnTxt("Video", 22, (GXColor){0, 0, 0, 255}); + videoBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage videoBtnImg(&btnLargeOutline); + GuiImage videoBtnImgOver(&btnLargeOutlineOver); + GuiImage videoBtnIcon(&iconVideo); + GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + videoBtn.SetPosition(125, 120); + videoBtn.SetLabel(&videoBtnTxt); + videoBtn.SetImage(&videoBtnImg); + videoBtn.SetImageOver(&videoBtnImgOver); + videoBtn.SetIcon(&videoBtnIcon); + videoBtn.SetSoundOver(&btnSoundOver); + videoBtn.SetSoundClick(&btnSoundClick); + videoBtn.SetTrigger(trigA); + videoBtn.SetTrigger(trig2); + videoBtn.SetEffectGrow(); + + #ifdef HW_RVL + GuiText wiiControlsBtnTxt1("Match Wii Controls", 22, (GXColor){0, 0, 0, 255}); + #else + GuiText wiiControlsBtnTxt1("Match GC Controls", 22, (GXColor){0, 0, 0, 255}); + #endif + if (GCSettings.WiiControls) sprintf(s, "ON"); + else sprintf(s, "OFF"); + GuiText wiiControlsBtnTxt2(s, 18, (GXColor){0, 0, 0, 255}); + wiiControlsBtnTxt1.SetPosition(0, -10); + wiiControlsBtnTxt1.SetWrap(true, btnLargeOutline.GetWidth()-30); + wiiControlsBtnTxt2.SetPosition(0, +30); + GuiImage wiiControlsBtnImg(&btnLargeOutline); + GuiImage wiiControlsBtnImgOver(&btnLargeOutlineOver); + GuiImage wiiControlsBtnIcon(&iconWiiControls); + GuiButton wiiControlsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + wiiControlsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + wiiControlsBtn.SetPosition(-125, 250); + wiiControlsBtn.SetLabel(&wiiControlsBtnTxt1, 0); + wiiControlsBtn.SetLabel(&wiiControlsBtnTxt2, 1); + wiiControlsBtn.SetImage(&wiiControlsBtnImg); + wiiControlsBtn.SetImageOver(&wiiControlsBtnImgOver); + wiiControlsBtn.SetIcon(&wiiControlsBtnIcon); + wiiControlsBtn.SetSoundOver(&btnSoundOver); + wiiControlsBtn.SetSoundClick(&btnSoundClick); + wiiControlsBtn.SetTrigger(trigA); + wiiControlsBtn.SetTrigger(trig2); + wiiControlsBtn.SetEffectGrow(); + + GuiText screenshotBtnTxt("ScreenShot", 22, (GXColor){0, 0, 0, 255}); + GuiImage screenshotBtnImg(&btnLargeOutline); + GuiImage screenshotBtnImgOver(&btnLargeOutlineOver); + GuiImage screenshotBtnIcon(&iconScreenshot); + GuiButton screenshotBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + screenshotBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + screenshotBtn.SetPosition(125, 250); + screenshotBtn.SetLabel(&screenshotBtnTxt); + screenshotBtn.SetImage(&screenshotBtnImg); + screenshotBtn.SetImageOver(&screenshotBtnImgOver); + screenshotBtn.SetIcon(&screenshotBtnIcon); + screenshotBtn.SetSoundOver(&btnSoundOver); + screenshotBtn.SetSoundClick(&btnSoundClick); + screenshotBtn.SetTrigger(trigA); + screenshotBtn.SetTrigger(trig2); + screenshotBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&mappingBtn); + w.Append(&videoBtn); + w.Append(&wiiControlsBtn); + w.Append(&screenshotBtn); + w.Append(&closeBtn); + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(mappingBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS; + } + else if(videoBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_VIDEO; + } + else if(wiiControlsBtn.GetState() == STATE_CLICKED) + { + GCSettings.WiiControls ^= 1; + if (GCSettings.WiiControls) sprintf(s, "ON"); + else sprintf(s, "OFF"); + wiiControlsBtnTxt2.SetText(s); + wiiControlsBtn.ResetState(); + } + else if(screenshotBtn.GetState() == STATE_CLICKED) + { + if (WindowPrompt("Preview Screenshot", "Save a new Preview Screenshot? Current Screenshot image will be overwritten.", "OK", "Cancel")) + { + snprintf(filepath, 1024, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], GCSettings.ScreenshotsFolder, ROMFilename); + SavePreviewImg(filepath, NOTSILENT); + } + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(350000); // wait for effects to finish + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME; + } + } + + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MenuSettingsMappings + ***************************************************************************/ +static int MenuSettingsMappings() +{ + int menu = MENU_NONE; + + GuiText titleTxt("Game Settings - Button Mappings", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconWiimote(icon_settings_wiimote_png); + GuiImageData iconClassic(icon_settings_classic_png); + GuiImageData iconGamecube(icon_settings_gamecube_png); + GuiImageData iconNunchuk(icon_settings_nunchuk_png); + GuiImageData iconWiiupro(icon_settings_wiiupro_png); + + GuiText gamecubeBtnTxt("GameCube Controller", 22, (GXColor){0, 0, 0, 255}); + gamecubeBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage gamecubeBtnImg(&btnLargeOutline); + GuiImage gamecubeBtnImgOver(&btnLargeOutlineOver); + GuiImage gamecubeBtnIcon(&iconGamecube); + GuiButton gamecubeBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + gamecubeBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + gamecubeBtn.SetPosition(-125, 120); + gamecubeBtn.SetLabel(&gamecubeBtnTxt); + gamecubeBtn.SetImage(&gamecubeBtnImg); + gamecubeBtn.SetImageOver(&gamecubeBtnImgOver); + gamecubeBtn.SetIcon(&gamecubeBtnIcon); + gamecubeBtn.SetSoundOver(&btnSoundOver); + gamecubeBtn.SetSoundClick(&btnSoundClick); + gamecubeBtn.SetTrigger(trigA); + gamecubeBtn.SetTrigger(trig2); + gamecubeBtn.SetEffectGrow(); + + GuiText wiimoteBtnTxt("Wiimote", 22, (GXColor){0, 0, 0, 255}); + GuiImage wiimoteBtnImg(&btnLargeOutline); + GuiImage wiimoteBtnImgOver(&btnLargeOutlineOver); + GuiImage wiimoteBtnIcon(&iconWiimote); + GuiButton wiimoteBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + wiimoteBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + wiimoteBtn.SetPosition(125, 120); + wiimoteBtn.SetLabel(&wiimoteBtnTxt); + wiimoteBtn.SetImage(&wiimoteBtnImg); + wiimoteBtn.SetImageOver(&wiimoteBtnImgOver); + wiimoteBtn.SetIcon(&wiimoteBtnIcon); + wiimoteBtn.SetSoundOver(&btnSoundOver); + wiimoteBtn.SetSoundClick(&btnSoundClick); + wiimoteBtn.SetTrigger(trigA); + wiimoteBtn.SetTrigger(trig2); + wiimoteBtn.SetEffectGrow(); + + GuiText classicBtnTxt("Classic Controller", 22, (GXColor){0, 0, 0, 255}); + classicBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage classicBtnImg(&btnLargeOutline); + GuiImage classicBtnImgOver(&btnLargeOutlineOver); + GuiImage classicBtnIcon(&iconClassic); + GuiButton classicBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + classicBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + classicBtn.SetPosition(-200, 250); + classicBtn.SetLabel(&classicBtnTxt); + classicBtn.SetImage(&classicBtnImg); + classicBtn.SetImageOver(&classicBtnImgOver); + classicBtn.SetIcon(&classicBtnIcon); + classicBtn.SetSoundOver(&btnSoundOver); + classicBtn.SetSoundClick(&btnSoundClick); + classicBtn.SetTrigger(trigA); + classicBtn.SetTrigger(trig2); + classicBtn.SetEffectGrow(); + + GuiText wiiuproBtnTxt("Wii U Pro Controller", 22, (GXColor){0, 0, 0, 255}); + wiiuproBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20); + GuiImage wiiuproBtnImg(&btnLargeOutline); + GuiImage wiiuproBtnImgOver(&btnLargeOutlineOver); + GuiImage wiiuproBtnIcon(&iconWiiupro); + GuiButton wiiuproBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + wiiuproBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + wiiuproBtn.SetPosition(0, 250); + wiiuproBtn.SetLabel(&wiiuproBtnTxt); + wiiuproBtn.SetImage(&wiiuproBtnImg); + wiiuproBtn.SetImageOver(&wiiuproBtnImgOver); + wiiuproBtn.SetIcon(&wiiuproBtnIcon); + wiiuproBtn.SetSoundOver(&btnSoundOver); + wiiuproBtn.SetSoundClick(&btnSoundClick); + wiiuproBtn.SetTrigger(trigA); + wiiuproBtn.SetTrigger(trig2); + wiiuproBtn.SetEffectGrow(); + + GuiText nunchukBtnTxt1("Wiimote", 22, (GXColor){0, 0, 0, 255}); + GuiText nunchukBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); + GuiText nunchukBtnTxt3("Nunchuk", 22, (GXColor){0, 0, 0, 255}); + nunchukBtnTxt1.SetPosition(0, -20); + nunchukBtnTxt3.SetPosition(0, +20); + GuiImage nunchukBtnImg(&btnLargeOutline); + GuiImage nunchukBtnImgOver(&btnLargeOutlineOver); + GuiImage nunchukBtnIcon(&iconNunchuk); + GuiButton nunchukBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + nunchukBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + nunchukBtn.SetPosition(200, 250); + nunchukBtn.SetLabel(&nunchukBtnTxt1, 0); + nunchukBtn.SetLabel(&nunchukBtnTxt2, 1); + nunchukBtn.SetLabel(&nunchukBtnTxt3, 2); + nunchukBtn.SetImage(&nunchukBtnImg); + nunchukBtn.SetImageOver(&nunchukBtnImgOver); + nunchukBtn.SetIcon(&nunchukBtnIcon); + nunchukBtn.SetSoundOver(&btnSoundOver); + nunchukBtn.SetSoundClick(&btnSoundClick); + nunchukBtn.SetTrigger(trigA); + nunchukBtn.SetTrigger(trig2); + nunchukBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + + w.Append(&gamecubeBtn); +#ifdef HW_RVL + w.Append(&wiimoteBtn); + w.Append(&nunchukBtn); + w.Append(&classicBtn); + w.Append(&wiiuproBtn); +#endif + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(wiimoteBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_WIIMOTE; + } + else if(nunchukBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_NUNCHUK; + } + else if(classicBtn.GetState() == STATE_CLICKED) + { + wiiuproCtrl = 0; + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_CLASSIC; + } + else if(wiiuproBtn.GetState() == STATE_CLICKED) + { + wiiuproCtrl = 1; + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_CLASSIC; + } + else if(gamecubeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_GCPAD; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * ButtonMappingWindow + ***************************************************************************/ +static u32 +ButtonMappingWindow() +{ + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt("Button Mapping", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + + char msg[200]; + + switch(mapMenuCtrl) + { + case CTRLR_GCPAD: + #ifdef HW_RVL + sprintf(msg, "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to clear the existing mapping."); + #else + sprintf(msg, "Press any button on the GameCube Controller now. Press the C-Stick in any direction to clear the existing mapping."); + #endif + break; + case CTRLR_WIIMOTE: + sprintf(msg, "Press any button on the Wiimote now. Press Home to clear the existing mapping."); + break; + case CTRLR_CLASSIC: + if(wiiuproCtrl == 1) + { + sprintf(msg, "Press any button on the Wii U Pro Controller now. Press Home to clear the existing mapping."); + } + else + { + sprintf(msg, "Press any button on the Classic Controller now. Press Home to clear the existing mapping."); + } + break; + case CTRLR_NUNCHUK: + sprintf(msg, "Press any button on the Wiimote or Nunchuk now. Press Home to clear the existing mapping."); + break; + } + + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-20); + msgTxt.SetWrap(true, 430); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + u32 pressed = 0; + + while(pressed == 0) + { + usleep(THREAD_SLEEP); + + if(mapMenuCtrl == CTRLR_GCPAD) + { + pressed = userInput[0].pad.btns_d; + + + if(userInput[0].pad.substickX < -70 || + userInput[0].pad.substickX > 70 || + userInput[0].pad.substickY < -70 || + userInput[0].pad.substickY > 70) + pressed = WPAD_BUTTON_HOME; + + if(userInput[0].wpad->btns_d == WPAD_BUTTON_HOME) + pressed = WPAD_BUTTON_HOME; + } + else + { + pressed = userInput[0].wpad->btns_d; + + // always allow Home button to be pressed to cancel + if(pressed != WPAD_BUTTON_HOME) + { + switch(mapMenuCtrl) + { + case CTRLR_WIIMOTE: + if(pressed > 0x1000) + pressed = 0; // not a valid input + break; + + case CTRLR_CLASSIC: + if(userInput[0].wpad->exp.type != WPAD_EXP_CLASSIC) + pressed = 0; // not a valid input + else if(pressed <= 0x1000) + pressed = 0; + break; + + case CTRLR_NUNCHUK: + if(userInput[0].wpad->exp.type != WPAD_EXP_NUNCHUK) + pressed = 0; // not a valid input + break; + } + } + if(pressed == 0) + pressed = userInput[0].wupcdata.btns_d; + } + } + + if(pressed == WPAD_BUTTON_HOME || pressed == WPAD_CLASSIC_BUTTON_HOME) + pressed = 0; + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + + return pressed; +} + +static int MenuSettingsMappingsMap() +{ + int menu = MENU_NONE; + int ret,i,j; + bool firstRun = true; + OptionList options; + + char menuTitle[100]; + char menuSubtitle[100]; + sprintf(menuTitle, "Game Settings - Button Mappings"); + + GuiText titleTxt(menuTitle, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,30); + + if(wiiuproCtrl == 1) + { + sprintf(menuSubtitle, "%s", "Wii U Pro Controller"); + } + else + { + sprintf(menuSubtitle, "%s", ctrlrName[mapMenuCtrl]); + } + GuiText subtitleTxt(menuSubtitle, 20, (GXColor){255, 255, 255, 255}); + subtitleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + subtitleTxt.SetPosition(50,60); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnShortOutline(button_short_png); + GuiImageData btnShortOutlineOver(button_short_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset", 22, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnShortOutline); + GuiImage resetBtnImgOver(&btnShortOutlineOver); + GuiButton resetBtn(btnShortOutline.GetWidth(), btnShortOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + resetBtn.SetPosition(260, -35); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetSoundClick(&btnSoundClick); + resetBtn.SetTrigger(trigA); + resetBtn.SetTrigger(trig2); + resetBtn.SetEffectGrow(); + + i=0; + sprintf(options.name[i++], "B"); + sprintf(options.name[i++], "A"); + sprintf(options.name[i++], "Select"); + sprintf(options.name[i++], "Start"); + sprintf(options.name[i++], "Up"); + sprintf(options.name[i++], "Down"); + sprintf(options.name[i++], "Left"); + sprintf(options.name[i++], "Right"); + sprintf(options.name[i++], "L"); + sprintf(options.name[i++], "R"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(215); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + w.Append(&resetBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + mainWindow->Append(&subtitleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS_MAPPINGS; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + resetBtn.ResetState(); + + int choice = WindowPrompt( + "Reset Mappings", + "Are you sure that you want to reset your mappings?", + "Yes", + "No"); + + if(choice == 1) + { + ResetControls(mapMenuCtrl); + firstRun = true; + } + } + + ret = optionBrowser.GetClickedOption(); + + if(ret >= 0) + { + // get a button selection from user + btnmap[mapMenuCtrl][ret] = ButtonMappingWindow(); + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + for(i=0; i < options.length; i++) + { + for(j=0; j < ctrlr_def[mapMenuCtrl].num_btns; j++) + { + if(btnmap[mapMenuCtrl][i] == 0) + { + options.value[i][0] = 0; + } + else if(btnmap[mapMenuCtrl][i] == + ctrlr_def[mapMenuCtrl].map[j].btn) + { + if(strcmp(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name) != 0) + sprintf(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name); + break; + } + } + } + optionBrowser.TriggerUpdate(); + } + } + wiiuproCtrl = 0; + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + mainWindow->Remove(&subtitleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettingsVideo + ***************************************************************************/ + +static void ScreenZoomWindowUpdate(void * ptr, float h, float v) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + char zoom[10], zoom2[10]; + + if(IsGBAGame()) + { + GCSettings.gbaZoomHor += h; + GCSettings.gbaZoomVert += v; + sprintf(zoom, "%.2f%%", GCSettings.gbaZoomHor*100); + sprintf(zoom2, "%.2f%%", GCSettings.gbaZoomVert*100); + } + else + { + GCSettings.gbZoomHor += h; + GCSettings.gbZoomVert += v; + sprintf(zoom, "%.2f%%", GCSettings.gbZoomHor*100); + sprintf(zoom2, "%.2f%%", GCSettings.gbZoomVert*100); + } + + settingText->SetText(zoom); + settingText2->SetText(zoom2); + b->ResetState(); + } +} + +static void ScreenZoomWindowLeftClick(void * ptr) { ScreenZoomWindowUpdate(ptr, -0.01, 0); } +static void ScreenZoomWindowRightClick(void * ptr) { ScreenZoomWindowUpdate(ptr, +0.01, 0); } +static void ScreenZoomWindowUpClick(void * ptr) { ScreenZoomWindowUpdate(ptr, 0, +0.01); } +static void ScreenZoomWindowDownClick(void * ptr) { ScreenZoomWindowUpdate(ptr, 0, -0.01); } + +static void ScreenZoomWindow() +{ + GuiWindow * w = new GuiWindow(200,200); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiTrigger trigUp; + trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); + + GuiTrigger trigDown; + trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowLeftBtn.SetPosition(50, 0); + arrowLeftBtn.SetTrigger(trigA); + arrowLeftBtn.SetTrigger(trig2); + arrowLeftBtn.SetTrigger(&trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ScreenZoomWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowRightBtn.SetPosition(164, 0); + arrowRightBtn.SetTrigger(trigA); + arrowRightBtn.SetTrigger(trig2); + arrowRightBtn.SetTrigger(&trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ScreenZoomWindowRightClick); + + GuiImageData arrowUp(button_arrow_up_png); + GuiImage arrowUpImg(&arrowUp); + GuiImageData arrowUpOver(button_arrow_up_over_png); + GuiImage arrowUpOverImg(&arrowUpOver); + GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + arrowUpBtn.SetImage(&arrowUpImg); + arrowUpBtn.SetImageOver(&arrowUpOverImg); + arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowUpBtn.SetPosition(-76, -27); + arrowUpBtn.SetTrigger(trigA); + arrowUpBtn.SetTrigger(trig2); + arrowUpBtn.SetTrigger(&trigUp); + arrowUpBtn.SetSelectable(false); + arrowUpBtn.SetUpdateCallback(ScreenZoomWindowUpClick); + + GuiImageData arrowDown(button_arrow_down_png); + GuiImage arrowDownImg(&arrowDown); + GuiImageData arrowDownOver(button_arrow_down_over_png); + GuiImage arrowDownOverImg(&arrowDownOver); + GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + arrowDownBtn.SetImage(&arrowDownImg); + arrowDownBtn.SetImageOver(&arrowDownOverImg); + arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + arrowDownBtn.SetPosition(-76, 27); + arrowDownBtn.SetTrigger(trigA); + arrowDownBtn.SetTrigger(trig2); + arrowDownBtn.SetTrigger(&trigDown); + arrowDownBtn.SetSelectable(false); + arrowDownBtn.SetUpdateCallback(ScreenZoomWindowDownClick); + + GuiImageData screenPosition(screen_position_png); + GuiImage screenPositionImg(&screenPosition); + screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + screenPositionImg.SetPosition(0, 0); + + settingText = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); + settingText2 = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); + char zoom[10], zoom2[10]; + float currentZoomHor, currentZoomVert; + + if(IsGBAGame()) + { + sprintf(zoom, "%.2f%%", GCSettings.gbaZoomHor*100); + sprintf(zoom2, "%.2f%%", GCSettings.gbaZoomVert*100); + currentZoomHor = GCSettings.gbaZoomHor; + currentZoomVert = GCSettings.gbaZoomVert; + } + else + { + sprintf(zoom, "%.2f%%", GCSettings.gbZoomHor*100); + sprintf(zoom2, "%.2f%%", GCSettings.gbZoomVert*100); + currentZoomHor = GCSettings.gbZoomHor; + currentZoomVert = GCSettings.gbZoomVert; + } + + settingText->SetText(zoom); + settingText->SetPosition(108, 0); + settingText2->SetText(zoom2); + settingText2->SetPosition(-76, 0); + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(&arrowUpBtn); + w->Append(&arrowDownBtn); + w->Append(&screenPositionImg); + w->Append(settingText); + w->Append(settingText2); + + char windowName[20]; + if(IsGBAGame()) + sprintf(windowName, "GBA Screen Zoom"); + else + sprintf(windowName, "GB Screen Zoom"); + + if(!SettingWindow(windowName,w)) + { + // undo changes + if(IsGBAGame()) + { + GCSettings.gbaZoomHor = currentZoomHor; + GCSettings.gbaZoomVert = currentZoomVert; + } + else + { + GCSettings.gbZoomHor = currentZoomHor; + GCSettings.gbZoomVert = currentZoomVert; + } + } + + delete(w); + delete(settingText); + delete(settingText2); +} + +static void ScreenPositionWindowUpdate(void * ptr, int x, int y) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.xshift += x; + GCSettings.yshift += y; + + char shift[10]; + sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); + settingText->SetText(shift); + b->ResetState(); + } +} + +static void ScreenPositionWindowLeftClick(void * ptr) { ScreenPositionWindowUpdate(ptr, -1, 0); } +static void ScreenPositionWindowRightClick(void * ptr) { ScreenPositionWindowUpdate(ptr, +1, 0); } +static void ScreenPositionWindowUpClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, -1); } +static void ScreenPositionWindowDownClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, +1); } + +static void ScreenPositionWindow() +{ + GuiWindow * w = new GuiWindow(150,150); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + w->SetPosition(0, -10); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiTrigger trigUp; + trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); + + GuiTrigger trigDown; + trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + arrowLeftBtn.SetTrigger(trigA); + arrowLeftBtn.SetTrigger(trig2); + arrowLeftBtn.SetTrigger(&trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ScreenPositionWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + arrowRightBtn.SetTrigger(trigA); + arrowRightBtn.SetTrigger(trig2); + arrowRightBtn.SetTrigger(&trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ScreenPositionWindowRightClick); + + GuiImageData arrowUp(button_arrow_up_png); + GuiImage arrowUpImg(&arrowUp); + GuiImageData arrowUpOver(button_arrow_up_over_png); + GuiImage arrowUpOverImg(&arrowUpOver); + GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + arrowUpBtn.SetImage(&arrowUpImg); + arrowUpBtn.SetImageOver(&arrowUpOverImg); + arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn.SetTrigger(trigA); + arrowUpBtn.SetTrigger(trig2); + arrowUpBtn.SetTrigger(&trigUp); + arrowUpBtn.SetSelectable(false); + arrowUpBtn.SetUpdateCallback(ScreenPositionWindowUpClick); + + GuiImageData arrowDown(button_arrow_down_png); + GuiImage arrowDownImg(&arrowDown); + GuiImageData arrowDownOver(button_arrow_down_over_png); + GuiImage arrowDownOverImg(&arrowDownOver); + GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + arrowDownBtn.SetImage(&arrowDownImg); + arrowDownBtn.SetImageOver(&arrowDownOverImg); + arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn.SetTrigger(trigA); + arrowDownBtn.SetTrigger(trig2); + arrowDownBtn.SetTrigger(&trigDown); + arrowDownBtn.SetSelectable(false); + arrowDownBtn.SetUpdateCallback(ScreenPositionWindowDownClick); + + GuiImageData screenPosition(screen_position_png); + GuiImage screenPositionImg(&screenPosition); + screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + settingText = new GuiText(NULL, 20, (GXColor){0, 0, 0, 255}); + char shift[10]; + sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); + settingText->SetText(shift); + + int currentX = GCSettings.xshift; + int currentY = GCSettings.yshift; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(&arrowUpBtn); + w->Append(&arrowDownBtn); + w->Append(&screenPositionImg); + w->Append(settingText); + + if(!SettingWindow("Screen Position",w)) + { + // undo changes + GCSettings.xshift = currentX; + GCSettings.yshift = currentY; + } + + delete(w); + delete(settingText); +} + +static int MenuSettingsVideo() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + + sprintf(options.name[i++], "Rendering"); + sprintf(options.name[i++], "Scaling"); + if(IsGBAGame()) { + sprintf(options.name[i++], "GBA Screen Zoom"); + sprintf(options.name[i++], "GBA Fixed Pixel Ratio"); + } else { + sprintf(options.name[i++], "GB Screen Zoom"); + sprintf(options.name[i++], "GB Fixed Pixel Ratio"); + } + sprintf(options.name[i++], "Screen Position"); + sprintf(options.name[i++], "Video Mode"); + sprintf(options.name[i++], "GB Mono Colorization"); + sprintf(options.name[i++], "GB Palette"); + sprintf(options.name[i++], "GBA Frameskip"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + if(IsGBAGame()) + options.name[6][0] = 0; + + if(!IsGameboyGame()) + options.name[7][0] = 0; // disable palette option for GBA/GBC + + GuiText titleTxt("Game Settings - Video", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetCol2Position(240); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.render++; + if (GCSettings.render > 4) + GCSettings.render = 1; + break; + + case 1: + GCSettings.scaling++; + if (GCSettings.scaling > 3) + GCSettings.scaling = 0; + // disable Widescreen correction in Wii mode - determined automatically + #ifdef HW_RVL + if(GCSettings.scaling == 3) + GCSettings.scaling = 0; + #endif + break; + + case 2: + ScreenZoomWindow(); + break; + + case 3: + if(IsGBAGame()) { + GCSettings.gbaFixed++; + if(GCSettings.gbaFixed > 3) + GCSettings.gbaFixed = 0; + } else { + GCSettings.gbFixed++; + if(GCSettings.gbFixed > 3) + GCSettings.gbFixed = 0; + } + break; + + case 4: + ScreenPositionWindow(); + break; + + case 5: + GCSettings.videomode++; + if(GCSettings.videomode > 6) + GCSettings.videomode = 0; + break; + + case 6: + GCSettings.colorize ^= 1; + break; + + case 7: + menu = MENU_GAMESETTINGS_PALETTE; + break; + + case 8: + GCSettings.gbaFrameskip ^= 1; + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + if (GCSettings.render == 0) + sprintf (options.value[0], "Original"); + else if (GCSettings.render == 1) + sprintf (options.value[0], "Filtered (Auto)"); + else if (GCSettings.render == 2) + sprintf (options.value[0], "Unfiltered"); + else if (GCSettings.render == 3) + sprintf (options.value[0], "Filtered (Sharp)"); + else if (GCSettings.render == 4) + sprintf (options.value[0], "Filtered (Soft)"); + + if (GCSettings.scaling == 0) + sprintf (options.value[1], "Maintain Aspect Ratio"); + else if (GCSettings.scaling == 1) + sprintf (options.value[1], "Partial Stretch"); + else if (GCSettings.scaling == 2) + sprintf (options.value[1], "Stretch to Fit"); + else if (GCSettings.scaling == 3) + sprintf (options.value[1], "16:9 Correction"); + + int fixed; + if(IsGBAGame()) { + sprintf (options.value[2], "%.2f%%, %.2f%%", GCSettings.gbaZoomHor*100, GCSettings.gbaZoomVert*100); + fixed = GCSettings.gbaFixed; + } else { + sprintf (options.value[2], "%.2f%%, %.2f%%", GCSettings.gbZoomHor*100, GCSettings.gbZoomVert*100); + fixed = GCSettings.gbFixed; + } + + if (fixed) { + int w = fixed / 10; + int ratio = fixed % 10; + const char* widescreen = w + ? "(16:9 Correction)" + : ""; + + sprintf (options.value[3], "%dx %s", ratio, widescreen); + } else { + sprintf (options.value[3], "Disabled"); + } + + sprintf (options.value[4], "%d, %d", GCSettings.xshift, GCSettings.yshift); + + switch(GCSettings.videomode) + { + case 0: + sprintf (options.value[5], "Automatic (Recommended)"); break; + case 1: + sprintf (options.value[5], "NTSC (480i)"); break; + case 2: + sprintf (options.value[5], "NTSC (480p)"); break; + case 3: + sprintf (options.value[5], "PAL (576i)"); break; + case 4: + sprintf (options.value[5], "European RGB (240i)"); break; + case 5: + sprintf (options.value[5], "NTSC (240p)"); break; + case 6: + sprintf (options.value[5], "European RGB (240p)"); break; + } + + if (GCSettings.colorize) + sprintf (options.value[6], "On"); + else + sprintf (options.value[6], "Off"); + + if(strcmp(CurrentPalette.gameName, "default")) + sprintf(options.value[7], "Custom"); + else + sprintf(options.value[7], "Default"); + + if (GCSettings.gbaFrameskip) + sprintf (options.value[8], "On"); + else + sprintf (options.value[8], "Off"); + + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +static int MenuSettingsEmulation() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + + sprintf(options.name[i++], "Hardware (GB/GBC)"); + sprintf(options.name[i++], "Super Game Boy border"); + sprintf(options.name[i++], "Offset from UTC (hours)"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Game Settings - Emulation", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(50, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetCol2Position(240); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.GBHardware++; + if (GCSettings.GBHardware > 3) + GCSettings.GBHardware = 0; + break; + + case 1: + GCSettings.SGBBorder++; + if (GCSettings.SGBBorder > 2) + GCSettings.SGBBorder = 0; + break; + + case 2: + GCSettings.OffsetMinutesUTC += 15; + if (GCSettings.OffsetMinutesUTC > 60*14) { + GCSettings.OffsetMinutesUTC = -60*12; + } + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + if (GCSettings.GBHardware == 0) + sprintf (options.value[0], "Auto"); + else if (GCSettings.GBHardware == 1) + sprintf (options.value[0], "Game Boy Color"); + else if (GCSettings.GBHardware == 2) + sprintf (options.value[0], "Super Game Boy"); + else if (GCSettings.GBHardware == 3) + sprintf (options.value[0], "Game Boy"); + else if (GCSettings.GBHardware == 4) + sprintf (options.value[0], "Game Boy Advance"); + else if (GCSettings.GBHardware == 5) + sprintf (options.value[0], "Super Game Boy 2"); + + if (GCSettings.SGBBorder == 0) + sprintf (options.value[1], "Off"); + else if (GCSettings.SGBBorder == 1) + sprintf (options.value[1], "From game (SGB only)"); + else if (GCSettings.SGBBorder == 2) + sprintf (options.value[1], "From .png file"); + + sprintf (options.value[2], "%+.2f", GCSettings.OffsetMinutesUTC / 60.0); + + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettings + ***************************************************************************/ +static int MenuSettings(GuiTrigger *trigAptr,GuiTrigger *trig2ptr) +{ + int menu = MENU_NONE; + + GuiText titleTxt("Settings", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData iconFile(icon_settings_file_png); + GuiImageData iconMenu(icon_settings_menu_png); + GuiImageData iconNetwork(icon_settings_network_png); + GuiImageData iconEmulation(icon_game_settings_png); + + GuiText savingBtnTxt1("Saving", 22, (GXColor){0, 0, 0, 255}); + GuiText savingBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); + GuiText savingBtnTxt3("Loading", 22, (GXColor){0, 0, 0, 255}); + savingBtnTxt1.SetPosition(0, -20); + savingBtnTxt3.SetPosition(0, +20); + GuiImage savingBtnImg(&btnLargeOutline); + GuiImage savingBtnImgOver(&btnLargeOutlineOver); + GuiImage fileBtnIcon(&iconFile); + GuiButton savingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + savingBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + savingBtn.SetPosition(-125, 120); + savingBtn.SetLabel(&savingBtnTxt1, 0); + savingBtn.SetLabel(&savingBtnTxt2, 1); + savingBtn.SetLabel(&savingBtnTxt3, 2); + savingBtn.SetImage(&savingBtnImg); + savingBtn.SetImageOver(&savingBtnImgOver); + savingBtn.SetIcon(&fileBtnIcon); + savingBtn.SetSoundOver(&btnSoundOver); + savingBtn.SetSoundClick(&btnSoundClick); + savingBtn.SetTrigger(trigAptr); + savingBtn.SetTrigger(trig2ptr); + savingBtn.SetEffectGrow(); + + GuiText menuBtnTxt("Menu", 22, (GXColor){0, 0, 0, 255}); + menuBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage menuBtnImg(&btnLargeOutline); + GuiImage menuBtnImgOver(&btnLargeOutlineOver); + GuiImage menuBtnIcon(&iconMenu); + GuiButton menuBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + menuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + menuBtn.SetPosition(125, 120); + menuBtn.SetLabel(&menuBtnTxt); + menuBtn.SetImage(&menuBtnImg); + menuBtn.SetImageOver(&menuBtnImgOver); + menuBtn.SetIcon(&menuBtnIcon); + menuBtn.SetSoundOver(&btnSoundOver); + menuBtn.SetSoundClick(&btnSoundClick); + menuBtn.SetTrigger(trigAptr); + menuBtn.SetTrigger(trig2ptr); + menuBtn.SetEffectGrow(); + + GuiText networkBtnTxt("Network", 22, (GXColor){0, 0, 0, 255}); + networkBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30); + GuiImage networkBtnImg(&btnLargeOutline); + GuiImage networkBtnImgOver(&btnLargeOutlineOver); + GuiImage networkBtnIcon(&iconNetwork); + GuiButton networkBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + networkBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + networkBtn.SetPosition(-125, 250); + networkBtn.SetLabel(&networkBtnTxt); + networkBtn.SetImage(&networkBtnImg); + networkBtn.SetImageOver(&networkBtnImgOver); + networkBtn.SetIcon(&networkBtnIcon); + networkBtn.SetSoundOver(&btnSoundOver); + networkBtn.SetSoundClick(&btnSoundClick); + networkBtn.SetTrigger(trigAptr); + networkBtn.SetTrigger(trig2ptr); + networkBtn.SetEffectGrow(); + + GuiText emulationBtnTxt("Emulation", 22, (GXColor){0, 0, 0, 255}); + GuiImage emulationBtnImg(&btnLargeOutline); + GuiImage emulationBtnImgOver(&btnLargeOutlineOver); + GuiImage emulationBtnIcon(&iconEmulation); + GuiButton emulationBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + emulationBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + emulationBtn.SetPosition(125, 250); + emulationBtn.SetLabel(&emulationBtnTxt); + emulationBtn.SetImage(&emulationBtnImg); + emulationBtn.SetImageOver(&emulationBtnImgOver); + emulationBtn.SetIcon(&emulationBtnIcon); + emulationBtn.SetSoundOver(&btnSoundOver); + emulationBtn.SetSoundClick(&btnSoundClick); + emulationBtn.SetTrigger(trigA); + emulationBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigAptr); + backBtn.SetTrigger(trig2ptr);; + backBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset Settings", 22, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnOutline); + GuiImage resetBtnImgOver(&btnOutlineOver); + GuiButton resetBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + resetBtn.SetPosition(-90, -35); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetSoundClick(&btnSoundClick); + resetBtn.SetTrigger(trigAptr); + resetBtn.SetTrigger(trig2ptr); + resetBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&savingBtn); + w.Append(&menuBtn); + w.Append(&networkBtn); + w.Append(&emulationBtn); + w.Append(&backBtn); + w.Append(&resetBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(savingBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_FILE; + } + else if(menuBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MENU; + } + else if(networkBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_NETWORK; + } + else if(emulationBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_EMULATION; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESELECTION; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + resetBtn.ResetState(); + + int choice = WindowPrompt( + "Reset Settings", + "Are you sure that you want to reset your settings?", + "Yes", + "No"); + + if(choice == 1) + DefaultSettings(); + } + } + + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MenuSettingsFile + ***************************************************************************/ + +static int MenuSettingsFile() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + sprintf(options.name[i++], "Load Device"); + sprintf(options.name[i++], "Save Device"); + sprintf(options.name[i++], "Load Folder"); + sprintf(options.name[i++], "Save Folder"); + sprintf(options.name[i++], "Screenshots Folder"); + sprintf(options.name[i++], "Auto Load"); + sprintf(options.name[i++], "Auto Save"); + sprintf(options.name[i++], "Append Auto to .SAV Files"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Settings - Saving & Loading", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(215); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.LoadMethod++; + break; + + case 1: + GCSettings.SaveMethod++; + break; + + case 2: + OnScreenKeyboard(GCSettings.LoadFolder, MAXPATHLEN); + break; + + case 3: + OnScreenKeyboard(GCSettings.SaveFolder, MAXPATHLEN); + break; + + case 4: + OnScreenKeyboard(GCSettings.CheatFolder, MAXPATHLEN); + break; + + case 5: + OnScreenKeyboard(GCSettings.ScreenshotsFolder, MAXPATHLEN); + break; + + case 6: + GCSettings.AutoLoad++; + if (GCSettings.AutoLoad > 2) + GCSettings.AutoLoad = 0; + break; + + case 7: + GCSettings.AutoSave++; + if (GCSettings.AutoSave > 3) + GCSettings.AutoSave = 0; + break; + + case 8: + GCSettings.AppendAuto++; + if (GCSettings.AppendAuto > 1) + GCSettings.AppendAuto = 0; + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + // some load/save methods are not implemented - here's where we skip them + // they need to be skipped in the order they were enumerated + + // no SD/USB ports on GameCube + #ifdef HW_DOL + if(GCSettings.LoadMethod == DEVICE_SD) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_SD) + GCSettings.SaveMethod++; + if(GCSettings.LoadMethod == DEVICE_USB) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_USB) + GCSettings.SaveMethod++; + #endif + + // saving to DVD is impossible + if(GCSettings.SaveMethod == DEVICE_DVD) + GCSettings.SaveMethod++; + + // don't allow SD Gecko on Wii + #ifdef HW_RVL + if(GCSettings.LoadMethod == DEVICE_SD_SLOTA) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_SD_SLOTA) + GCSettings.SaveMethod++; + if(GCSettings.LoadMethod == DEVICE_SD_SLOTB) + GCSettings.LoadMethod++; + if(GCSettings.SaveMethod == DEVICE_SD_SLOTB) + GCSettings.SaveMethod++; + #endif + + // correct load/save methods out of bounds + if(GCSettings.LoadMethod > 6) + GCSettings.LoadMethod = 0; + if(GCSettings.SaveMethod > 6) + GCSettings.SaveMethod = 0; + + if (GCSettings.LoadMethod == DEVICE_AUTO) sprintf (options.value[0],"Auto Detect"); + else if (GCSettings.LoadMethod == DEVICE_SD) sprintf (options.value[0],"SD"); + else if (GCSettings.LoadMethod == DEVICE_USB) sprintf (options.value[0],"USB"); + else if (GCSettings.LoadMethod == DEVICE_DVD) sprintf (options.value[0],"DVD"); + else if (GCSettings.LoadMethod == DEVICE_SMB) sprintf (options.value[0],"Network"); + else if (GCSettings.LoadMethod == DEVICE_SD_SLOTA) sprintf (options.value[0],"SD Gecko Slot A"); + else if (GCSettings.LoadMethod == DEVICE_SD_SLOTB) sprintf (options.value[0],"SD Gecko Slot B"); + + if (GCSettings.SaveMethod == DEVICE_AUTO) sprintf (options.value[1],"Auto Detect"); + else if (GCSettings.SaveMethod == DEVICE_SD) sprintf (options.value[1],"SD"); + else if (GCSettings.SaveMethod == DEVICE_USB) sprintf (options.value[1],"USB"); + else if (GCSettings.SaveMethod == DEVICE_SMB) sprintf (options.value[1],"Network"); + else if (GCSettings.SaveMethod == DEVICE_SD_SLOTA) sprintf (options.value[1],"SD Gecko Slot A"); + else if (GCSettings.SaveMethod == DEVICE_SD_SLOTB) sprintf (options.value[1],"SD Gecko Slot B"); + + snprintf (options.value[2], 35, "%s", GCSettings.LoadFolder); + snprintf (options.value[3], 35, "%s", GCSettings.SaveFolder); + //snprintf (options.value[4], 30, "%s", GCSettings.CheatFolder); + snprintf (options.value[5], 35, "%s", GCSettings.ScreenshotsFolder); + + if (GCSettings.AutoLoad == 0) sprintf (options.value[6],"Off"); + else if (GCSettings.AutoLoad == 1) sprintf (options.value[6],"SRAM"); + else if (GCSettings.AutoLoad == 2) sprintf (options.value[6],"Snapshot"); + + if (GCSettings.AutoSave == 0) sprintf (options.value[7],"Off"); + else if (GCSettings.AutoSave == 1) sprintf (options.value[7],"SRAM"); + else if (GCSettings.AutoSave == 2) sprintf (options.value[7],"Snapshot"); + else if (GCSettings.AutoSave == 3) sprintf (options.value[7],"Both"); + + if (GCSettings.AppendAuto == 0) sprintf (options.value[8],"Off"); + else if (GCSettings.AppendAuto == 1) sprintf (options.value[8],"On"); + + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettingsMenu + ***************************************************************************/ +static int MenuSettingsMenu() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + + sprintf(options.name[i++], "Exit Action"); + sprintf(options.name[i++], "Wiimote Orientation"); + sprintf(options.name[i++], "Music Volume"); + sprintf(options.name[i++], "Sound Effects Volume"); + sprintf(options.name[i++], "Rumble"); + sprintf(options.name[i++], "Language"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Settings - Menu", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(275); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + GCSettings.ExitAction++; + if(GCSettings.ExitAction > 3) + GCSettings.ExitAction = 0; + break; + case 1: + GCSettings.WiimoteOrientation ^= 1; + break; + case 2: + GCSettings.MusicVolume += 10; + if(GCSettings.MusicVolume > 100) + GCSettings.MusicVolume = 0; + bgMusic->SetVolume(GCSettings.MusicVolume); + break; + case 3: + GCSettings.SFXVolume += 10; + if(GCSettings.SFXVolume > 100) + GCSettings.SFXVolume = 0; + break; + case 4: + GCSettings.Rumble ^= 1; + break; + case 5: + GCSettings.language++; + + if(GCSettings.language >= LANG_LENGTH) + GCSettings.language = LANG_JAPANESE; + + if(GCSettings.language == LANG_SIMP_CHINESE) + GCSettings.language = LANG_PORTUGUESE; + else if(GCSettings.language == LANG_JAPANESE) + GCSettings.language = LANG_ENGLISH; + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + + #ifdef HW_RVL + if (GCSettings.ExitAction == 1) + sprintf (options.value[0], "Return to Wii Menu"); + else if (GCSettings.ExitAction == 2) + sprintf (options.value[0], "Power off Wii"); + else if (GCSettings.ExitAction == 3) + sprintf (options.value[0], "Return to Loader"); + else + sprintf (options.value[0], "Auto"); + #else // GameCube + if(GCSettings.ExitAction > 1) + GCSettings.ExitAction = 0; + if (GCSettings.ExitAction == 0) + sprintf (options.value[0], "Return to Loader"); + else + sprintf (options.value[0], "Reboot"); + + options.name[1][0] = 0; // Wiimote + options.name[2][0] = 0; // Music + options.name[3][0] = 0; // Sound Effects + options.name[4][0] = 0; // Rumble + #endif + + if (GCSettings.WiimoteOrientation == 0) + sprintf (options.value[1], "Vertical"); + else if (GCSettings.WiimoteOrientation == 1) + sprintf (options.value[1], "Horizontal"); + + if(GCSettings.MusicVolume > 0) + sprintf(options.value[2], "%d%%", GCSettings.MusicVolume); + else + sprintf(options.value[2], "Mute"); + + if(GCSettings.SFXVolume > 0) + sprintf(options.value[3], "%d%%", GCSettings.SFXVolume); + else + sprintf(options.value[3], "Mute"); + + if (GCSettings.Rumble == 1) + sprintf (options.value[4], "Enabled"); + else + sprintf (options.value[4], "Disabled"); + + switch(GCSettings.language) + { + case LANG_JAPANESE: sprintf(options.value[5], "Japanese"); break; + case LANG_ENGLISH: sprintf(options.value[5], "English"); break; + case LANG_GERMAN: sprintf(options.value[5], "German"); break; + case LANG_FRENCH: sprintf(options.value[5], "French"); break; + case LANG_SPANISH: sprintf(options.value[5], "Spanish"); break; + case LANG_ITALIAN: sprintf(options.value[5], "Italian"); break; + case LANG_DUTCH: sprintf(options.value[5], "Dutch"); break; + case LANG_SIMP_CHINESE: sprintf(options.value[5], "Chinese (Simplified)"); break; + case LANG_TRAD_CHINESE: sprintf(options.value[5], "Chinese (Traditional)"); break; + case LANG_KOREAN: sprintf(options.value[5], "Korean"); break; + case LANG_PORTUGUESE: sprintf(options.value[5], "Portuguese"); break; + case LANG_BRAZILIAN_PORTUGUESE: sprintf(options.value[5], "Brazilian Portuguese"); break; + case LANG_CATALAN: sprintf(options.value[5], "Catalan"); break; + case LANG_TURKISH: sprintf(options.value[5], "Turkish"); break; + } + + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + ResetText(); + return menu; +} + +/**************************************************************************** + * MenuSettingsNetwork + ***************************************************************************/ +static int MenuSettingsNetwork() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + bool firstRun = true; + OptionList options; + sprintf(options.name[i++], "SMB Share IP"); + sprintf(options.name[i++], "SMB Share Name"); + sprintf(options.name[i++], "SMB Share Username"); + sprintf(options.name[i++], "SMB Share Password"); + options.length = i; + + for(i=0; i < options.length; i++) + options.value[i][0] = 0; + + GuiText titleTxt("Settings - Network", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_long_png); + GuiImageData btnOutlineOver(button_long_over_png); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(90, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(290); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + OnScreenKeyboard(GCSettings.smbip, 16); + break; + + case 1: + OnScreenKeyboard(GCSettings.smbshare, 20); + break; + + case 2: + OnScreenKeyboard(GCSettings.smbuser, 20); + break; + + case 3: + OnScreenKeyboard(GCSettings.smbpwd, 20); + break; + } + + if(ret >= 0 || firstRun) + { + firstRun = false; + snprintf (options.value[0], 25, "%s", GCSettings.smbip); + snprintf (options.value[1], 19, "%s", GCSettings.smbshare); + snprintf (options.value[2], 19, "%s", GCSettings.smbuser); + snprintf (options.value[3], 19, "%s", GCSettings.smbpwd); + optionBrowser.TriggerUpdate(); + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + CloseShare(); + return menu; +} + + +static int redAmount=128, greenAmount=128, blueAmount=128; +static GuiText *redText; +static GuiText *greenText; +static GuiText *blueText; +static GuiText *sampleText; + +static void RGBWindowUpdate(void * ptr, int red, int green, int blue) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + redAmount += red; + if (redAmount>255) redAmount=255; + else if (redAmount<0) redAmount=0; + greenAmount += green; + if (greenAmount>255) greenAmount=255; + else if (greenAmount<0) greenAmount=0; + blueAmount += blue; + if (blueAmount>255) blueAmount=255; + else if (blueAmount<0) blueAmount=0; + + redText->SetColor((GXColor){(u8)redAmount, 0, 0, 0xFF}); + greenText->SetColor((GXColor){0, (u8)greenAmount, 0, 0xFF}); + blueText->SetColor((GXColor){0, 0, (u8)blueAmount, 0xFF}); + sampleText->SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + + char shift[10]; + sprintf(shift, "%2x", redAmount); + redText->SetText(shift); + sprintf(shift, "%2x", greenAmount); + greenText->SetText(shift); + sprintf(shift, "%2x", blueAmount); + blueText->SetText(shift); + + b->ResetState(); + } +} + +static void LessRedClick(void * ptr) { RGBWindowUpdate(ptr, -8, 0, 0); } +static void LessGreenClick(void * ptr) { RGBWindowUpdate(ptr, 0, -8, 0); } +static void LessBlueClick(void * ptr) { RGBWindowUpdate(ptr, 0, 0, -8); } +static void MoreRedClick(void * ptr) { RGBWindowUpdate(ptr, +8, 0, 0); } +static void MoreGreenClick(void * ptr) { RGBWindowUpdate(ptr, 0, +8, 0); } +static void MoreBlueClick(void * ptr) { RGBWindowUpdate(ptr, 0, 0, +8); } + +static void PaletteWindow(const char *name) +{ + GuiWindow * w = new GuiWindow(500,480); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + w->SetPosition(0, -10); + + GuiImageData arrowUp(button_arrow_up_png); + GuiImageData arrowDown(button_arrow_down_png); + GuiImageData arrowUpOver(button_arrow_up_over_png); + GuiImageData arrowDownOver(button_arrow_down_over_png); + + GuiImage moreRedImg(&arrowUp); + GuiImage moreRedOverImg(&arrowUpOver); + GuiButton moreRedBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + moreRedBtn.SetImage(&moreRedImg); + moreRedBtn.SetImageOver(&moreRedOverImg); + moreRedBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + moreRedBtn.SetPosition(-150,-60); + moreRedBtn.SetTrigger(trigA); + moreRedBtn.SetTrigger(trig2); + moreRedBtn.SetSelectable(true); + moreRedBtn.SetUpdateCallback(MoreRedClick); + + GuiImage lessRedImg(&arrowDown); + GuiImage lessRedOverImg(&arrowDownOver); + GuiButton lessRedBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + lessRedBtn.SetImage(&lessRedImg); + lessRedBtn.SetImageOver(&lessRedOverImg); + lessRedBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + lessRedBtn.SetPosition(-150,+50); + lessRedBtn.SetTrigger(trigA); + lessRedBtn.SetTrigger(trig2); + lessRedBtn.SetSelectable(true); + lessRedBtn.SetUpdateCallback(LessRedClick); + + GuiImage moreGreenImg(&arrowUp); + GuiImage moreGreenOverImg(&arrowUpOver); + GuiButton moreGreenBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + moreGreenBtn.SetImage(&moreGreenImg); + moreGreenBtn.SetImageOver(&moreGreenOverImg); + moreGreenBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + moreGreenBtn.SetPosition(-50,-60); + moreGreenBtn.SetTrigger(trigA); + moreGreenBtn.SetTrigger(trig2); + moreGreenBtn.SetSelectable(true); + moreGreenBtn.SetUpdateCallback(MoreGreenClick); + + GuiImage lessGreenImg(&arrowDown); + GuiImage lessGreenOverImg(&arrowDownOver); + GuiButton lessGreenBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + lessGreenBtn.SetImage(&lessGreenImg); + lessGreenBtn.SetImageOver(&lessGreenOverImg); + lessGreenBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + lessGreenBtn.SetPosition(-50,+50); + lessGreenBtn.SetTrigger(trigA); + lessGreenBtn.SetTrigger(trig2); + lessGreenBtn.SetSelectable(true); + lessGreenBtn.SetUpdateCallback(LessGreenClick); + + GuiImage moreBlueImg(&arrowUp); + GuiImage moreBlueOverImg(&arrowUpOver); + GuiButton moreBlueBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + moreBlueBtn.SetImage(&moreBlueImg); + moreBlueBtn.SetImageOver(&moreBlueOverImg); + moreBlueBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + moreBlueBtn.SetPosition(50,-60); + moreBlueBtn.SetTrigger(trigA); + moreBlueBtn.SetTrigger(trig2); + moreBlueBtn.SetSelectable(true); + moreBlueBtn.SetUpdateCallback(MoreBlueClick); + + GuiImage lessBlueImg(&arrowDown); + GuiImage lessBlueOverImg(&arrowDownOver); + GuiButton lessBlueBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + lessBlueBtn.SetImage(&lessBlueImg); + lessBlueBtn.SetImageOver(&lessBlueOverImg); + lessBlueBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + lessBlueBtn.SetPosition(50,+50); + lessBlueBtn.SetTrigger(trigA); + lessBlueBtn.SetTrigger(trig2); + lessBlueBtn.SetSelectable(true); + lessBlueBtn.SetUpdateCallback(LessBlueClick); + + GuiImageData box(screen_position_png); + + GuiImage redBoxImg(&box); + redBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + redBoxImg.SetPosition(-150, 0); + + GuiImage greenBoxImg(&box); + greenBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + greenBoxImg.SetPosition(-50, 0); + + GuiImage blueBoxImg(&box); + blueBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + blueBoxImg.SetPosition(+50, 0); + + char shift[10]; + redText = new GuiText(NULL, 20, (GXColor){128, 0, 0, 255}); + redText->SetPosition(-150,0); + sprintf(shift, "%2x", redAmount); + redText->SetText(shift); + + greenText = new GuiText(NULL, 20, (GXColor){0, 128, 0, 255}); + greenText->SetPosition(-50, 0); + sprintf(shift, "%2x", greenAmount); + greenText->SetText(shift); + + blueText = new GuiText(NULL, 20, (GXColor){0, 0, 128, 255}); + blueText->SetPosition(+50,0); + sprintf(shift, "%2x", blueAmount); + blueText->SetText(shift); + + sampleText = new GuiText(NULL, 20, (GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + sampleText->SetPosition(+150,0); + sampleText->SetText(name); + + int currentRed = redAmount; + int currentGreen = greenAmount; + int currentBlue = blueAmount; + + w->Append(&lessRedBtn); + w->Append(&moreRedBtn); + w->Append(&lessGreenBtn); + w->Append(&moreGreenBtn); + w->Append(&lessBlueBtn); + w->Append(&moreBlueBtn); + + w->Append(&redBoxImg); + w->Append(&greenBoxImg); + w->Append(&blueBoxImg); + + w->Append(sampleText); + w->Append(redText); + w->Append(greenText); + w->Append(blueText); + + if(!SettingWindow("Red Green Blue",w)) + { + redAmount = currentRed; // undo changes + greenAmount = currentGreen; + blueAmount = currentBlue; + } + + delete(w); + delete(redText); + delete(greenText); + delete(blueText); +} + +GXColor GetCol(int i) { + int c = 0; + u8 r=0, g=0, b=0; + if (unsigned(i) <= 13) + { + c = CurrentPalette.palette[i]; + r = (c >> 16) & 255; + g = (c >> 8) & 255; + b = (c) & 255; + + } + return (GXColor){r,g,b,255}; +} + +/**************************************************************************** + * MenuPalette + * + * Menu displayed when returning to the menu from in-game. + ***************************************************************************/ +static int MenuPalette() +{ + // We are now using a custom palette + strncpy(CurrentPalette.gameName, RomTitle, 17); + + int menu = MENU_NONE; + + GuiText titleTxt("Palette", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData btnCloseOutline(button_small_png); + GuiImageData btnCloseOutlineOver(button_small_over_png); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText bg0BtnTxt("BG 0", 24, GetCol(0)); + GuiImage bg0BtnImg(&btnCloseOutline); + GuiImage bg0BtnImgOver(&btnCloseOutlineOver); + GuiButton bg0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + bg0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + bg0Btn.SetPosition(-200, 120); + bg0Btn.SetLabel(&bg0BtnTxt); + bg0Btn.SetImage(&bg0BtnImg); + bg0Btn.SetImageOver(&bg0BtnImgOver); + bg0Btn.SetSoundOver(&btnSoundOver); + bg0Btn.SetSoundClick(&btnSoundClick); + bg0Btn.SetTrigger(trigA); + bg0Btn.SetTrigger(trig2); + bg0Btn.SetEffectGrow(); + + GuiText bg1BtnTxt("BG 1", 24, GetCol(1)); + GuiImage bg1BtnImg(&btnCloseOutline); + GuiImage bg1BtnImgOver(&btnCloseOutlineOver); + GuiButton bg1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + bg1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + bg1Btn.SetPosition(-200, 180); + bg1Btn.SetLabel(&bg1BtnTxt); + bg1Btn.SetImage(&bg1BtnImg); + bg1Btn.SetImageOver(&bg1BtnImgOver); + bg1Btn.SetSoundOver(&btnSoundOver); + bg1Btn.SetSoundClick(&btnSoundClick); + bg1Btn.SetTrigger(trigA); + bg1Btn.SetTrigger(trig2); + bg1Btn.SetEffectGrow(); + + GuiText bg2BtnTxt("BG 2", 24, GetCol(2)); + GuiImage bg2BtnImg(&btnCloseOutline); + GuiImage bg2BtnImgOver(&btnCloseOutlineOver); + GuiButton bg2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + bg2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + bg2Btn.SetPosition(-200, 240); + bg2Btn.SetLabel(&bg2BtnTxt); + bg2Btn.SetImage(&bg2BtnImg); + bg2Btn.SetImageOver(&bg2BtnImgOver); + bg2Btn.SetSoundOver(&btnSoundOver); + bg2Btn.SetSoundClick(&btnSoundClick); + bg2Btn.SetTrigger(trigA); + bg2Btn.SetTrigger(trig2); + bg2Btn.SetEffectGrow(); + + GuiText bg3BtnTxt("BG 3", 24, GetCol(3)); + GuiImage bg3BtnImg(&btnCloseOutline); + GuiImage bg3BtnImgOver(&btnCloseOutlineOver); + GuiButton bg3Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + bg3Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + bg3Btn.SetPosition(-200, 300); + bg3Btn.SetLabel(&bg3BtnTxt); + bg3Btn.SetImage(&bg3BtnImg); + bg3Btn.SetImageOver(&bg3BtnImgOver); + bg3Btn.SetSoundOver(&btnSoundOver); + bg3Btn.SetSoundClick(&btnSoundClick); + bg3Btn.SetTrigger(trigA); + bg3Btn.SetTrigger(trig2); + bg3Btn.SetEffectGrow(); + + GuiText win0BtnTxt("WIN 0", 24, GetCol(4)); + GuiImage win0BtnImg(&btnCloseOutline); + GuiImage win0BtnImgOver(&btnCloseOutlineOver); + GuiButton win0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + win0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + win0Btn.SetPosition(-70, 120); + win0Btn.SetLabel(&win0BtnTxt); + win0Btn.SetImage(&win0BtnImg); + win0Btn.SetImageOver(&win0BtnImgOver); + win0Btn.SetSoundOver(&btnSoundOver); + win0Btn.SetSoundClick(&btnSoundClick); + win0Btn.SetTrigger(trigA); + win0Btn.SetTrigger(trig2); + win0Btn.SetEffectGrow(); + + GuiText win1BtnTxt("WIN 1", 24, GetCol(5)); + GuiImage win1BtnImg(&btnCloseOutline); + GuiImage win1BtnImgOver(&btnCloseOutlineOver); + GuiButton win1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + win1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + win1Btn.SetPosition(-70, 180); + win1Btn.SetLabel(&win1BtnTxt); + win1Btn.SetImage(&win1BtnImg); + win1Btn.SetImageOver(&win1BtnImgOver); + win1Btn.SetSoundOver(&btnSoundOver); + win1Btn.SetSoundClick(&btnSoundClick); + win1Btn.SetTrigger(trigA); + win1Btn.SetTrigger(trig2); + win1Btn.SetEffectGrow(); + + GuiText win2BtnTxt("WIN 2", 24, GetCol(6)); + GuiImage win2BtnImg(&btnCloseOutline); + GuiImage win2BtnImgOver(&btnCloseOutlineOver); + GuiButton win2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + win2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + win2Btn.SetPosition(-70, 240); + win2Btn.SetLabel(&win2BtnTxt); + win2Btn.SetImage(&win2BtnImg); + win2Btn.SetImageOver(&win2BtnImgOver); + win2Btn.SetSoundOver(&btnSoundOver); + win2Btn.SetSoundClick(&btnSoundClick); + win2Btn.SetTrigger(trigA); + win2Btn.SetTrigger(trig2); + win2Btn.SetEffectGrow(); + + GuiText win3BtnTxt("WIN 3", 24, GetCol(7)); + GuiImage win3BtnImg(&btnCloseOutline); + GuiImage win3BtnImgOver(&btnCloseOutlineOver); + GuiButton win3Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + win3Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + win3Btn.SetPosition(-70, 300); + win3Btn.SetLabel(&win3BtnTxt); + win3Btn.SetImage(&win3BtnImg); + win3Btn.SetImageOver(&win3BtnImgOver); + win3Btn.SetSoundOver(&btnSoundOver); + win3Btn.SetSoundClick(&btnSoundClick); + win3Btn.SetTrigger(trigA); + win3Btn.SetTrigger(trig2); + win3Btn.SetEffectGrow(); + + GuiText obj0BtnTxt("OBJ 0", 24, GetCol(8)); + GuiImage obj0BtnImg(&btnCloseOutline); + GuiImage obj0BtnImgOver(&btnCloseOutlineOver); + GuiButton obj0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + obj0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + obj0Btn.SetPosition(+70, 120); + obj0Btn.SetLabel(&obj0BtnTxt); + obj0Btn.SetImage(&obj0BtnImg); + obj0Btn.SetImageOver(&obj0BtnImgOver); + obj0Btn.SetSoundOver(&btnSoundOver); + obj0Btn.SetSoundClick(&btnSoundClick); + obj0Btn.SetTrigger(trigA); + obj0Btn.SetTrigger(trig2); + obj0Btn.SetEffectGrow(); + + GuiText obj1BtnTxt("OBJ 1", 24, GetCol(9)); + GuiImage obj1BtnImg(&btnCloseOutline); + GuiImage obj1BtnImgOver(&btnCloseOutlineOver); + GuiButton obj1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + obj1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + obj1Btn.SetPosition(+70, 180); + obj1Btn.SetLabel(&obj1BtnTxt); + obj1Btn.SetImage(&obj1BtnImg); + obj1Btn.SetImageOver(&obj1BtnImgOver); + obj1Btn.SetSoundOver(&btnSoundOver); + obj1Btn.SetSoundClick(&btnSoundClick); + obj1Btn.SetTrigger(trigA); + obj1Btn.SetTrigger(trig2); + obj1Btn.SetEffectGrow(); + + GuiText obj2BtnTxt("OBJ 2", 24, GetCol(10)); + GuiImage obj2BtnImg(&btnCloseOutline); + GuiImage obj2BtnImgOver(&btnCloseOutlineOver); + GuiButton obj2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + obj2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + obj2Btn.SetPosition(+70, 240); + obj2Btn.SetLabel(&obj2BtnTxt); + obj2Btn.SetImage(&obj2BtnImg); + obj2Btn.SetImageOver(&obj2BtnImgOver); + obj2Btn.SetSoundOver(&btnSoundOver); + obj2Btn.SetSoundClick(&btnSoundClick); + obj2Btn.SetTrigger(trigA); + obj2Btn.SetTrigger(trig2); + obj2Btn.SetEffectGrow(); + + GuiText spr0BtnTxt("SPR 0", 24, GetCol(11)); + GuiImage spr0BtnImg(&btnCloseOutline); + GuiImage spr0BtnImgOver(&btnCloseOutlineOver); + GuiButton spr0Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + spr0Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + spr0Btn.SetPosition(+200, 120); + spr0Btn.SetLabel(&spr0BtnTxt); + spr0Btn.SetImage(&spr0BtnImg); + spr0Btn.SetImageOver(&spr0BtnImgOver); + spr0Btn.SetSoundOver(&btnSoundOver); + spr0Btn.SetSoundClick(&btnSoundClick); + spr0Btn.SetTrigger(trigA); + spr0Btn.SetTrigger(trig2); + spr0Btn.SetEffectGrow(); + + GuiText spr1BtnTxt("SPR 1", 24, GetCol(12)); + GuiImage spr1BtnImg(&btnCloseOutline); + GuiImage spr1BtnImgOver(&btnCloseOutlineOver); + GuiButton spr1Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + spr1Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + spr1Btn.SetPosition(+200, 180); + spr1Btn.SetLabel(&spr1BtnTxt); + spr1Btn.SetImage(&spr1BtnImg); + spr1Btn.SetImageOver(&spr1BtnImgOver); + spr1Btn.SetSoundOver(&btnSoundOver); + spr1Btn.SetSoundClick(&btnSoundClick); + spr1Btn.SetTrigger(trigA); + spr1Btn.SetTrigger(trig2); + spr1Btn.SetEffectGrow(); + + GuiText spr2BtnTxt("SPR 2", 24, GetCol(13)); + GuiImage spr2BtnImg(&btnCloseOutline); + GuiImage spr2BtnImgOver(&btnCloseOutlineOver); + GuiButton spr2Btn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + spr2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + spr2Btn.SetPosition(+200, 240); + spr2Btn.SetLabel(&spr2BtnTxt); + spr2Btn.SetImage(&spr2BtnImg); + spr2Btn.SetImageOver(&spr2BtnImgOver); + spr2Btn.SetSoundOver(&btnSoundOver); + spr2Btn.SetSoundClick(&btnSoundClick); + spr2Btn.SetTrigger(trigA); + spr2Btn.SetTrigger(trig2); + spr2Btn.SetEffectGrow(); + + GuiText importBtnTxt("Load / Save", 22, (GXColor){0, 0, 0, 255}); + importBtnTxt.SetWrap(true, btnOutline.GetWidth()-30); + GuiImage importBtnImg(&btnOutline); + GuiImage importBtnImgOver(&btnOutlineOver); + GuiButton importBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + importBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + importBtn.SetPosition(140, 300); + importBtn.SetLabel(&importBtnTxt); + importBtn.SetImage(&importBtnImg); + importBtn.SetImageOver(&importBtnImgOver); + importBtn.SetSoundOver(&btnSoundOver); + importBtn.SetSoundClick(&btnSoundClick); + importBtn.SetTrigger(trigA); + importBtn.SetTrigger(trig2); + importBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 20, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-50, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetSoundClick(&btnSoundClick); + closeBtn.SetTrigger(trigA); + closeBtn.SetTrigger(trig2); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetSoundClick(&btnSoundClick); + backBtn.SetTrigger(trigA); + backBtn.SetTrigger(trig2); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&bg0Btn); + w.Append(&bg1Btn); + w.Append(&bg2Btn); + w.Append(&bg3Btn); + w.Append(&win0Btn); + w.Append(&win1Btn); + w.Append(&win2Btn); + w.Append(&win3Btn); + w.Append(&obj0Btn); + w.Append(&obj1Btn); + w.Append(&obj2Btn); + w.Append(&spr0Btn); + w.Append(&spr1Btn); + w.Append(&spr2Btn); + w.Append(&importBtn); + w.Append(&closeBtn); + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + usleep(THREAD_SLEEP); + + if(bg0Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[0] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[0] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[0] >> 0) & 0xFF; + PaletteWindow("BG 0"); + CurrentPalette.palette[0] = redAmount << 16 | greenAmount << 8 | blueAmount; + bg0BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + bg0Btn.ResetState(); + } + else if(bg1Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[1] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[1] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[1] >> 0) & 0xFF; + PaletteWindow("BG 1"); + CurrentPalette.palette[1] = redAmount << 16 | greenAmount << 8 | blueAmount; + bg1BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + bg1Btn.ResetState(); + } + else if(bg2Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[2] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[2] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[2] >> 0) & 0xFF; + PaletteWindow("BG 2"); + CurrentPalette.palette[2] = redAmount << 16 | greenAmount << 8 | blueAmount; + bg2BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + bg2Btn.ResetState(); + } + else if(bg3Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[3] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[3] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[3] >> 0) & 0xFF; + PaletteWindow("BG 3"); + CurrentPalette.palette[3] = redAmount << 16 | greenAmount << 8 | blueAmount; + bg3BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + bg3Btn.ResetState(); + } + else if(win0Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[4] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[4] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[4] >> 0) & 0xFF; + PaletteWindow("WIN 0"); + CurrentPalette.palette[4] = redAmount << 16 | greenAmount << 8 | blueAmount; + win0BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + win0Btn.ResetState(); + } + else if(win1Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[5] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[5] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[5] >> 0) & 0xFF; + PaletteWindow("WIN 1"); + CurrentPalette.palette[5] = redAmount << 16 | greenAmount << 8 | blueAmount; + win1BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + win1Btn.ResetState(); + } + else if(win2Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[6] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[6] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[6] >> 0) & 0xFF; + PaletteWindow("WIN 2"); + CurrentPalette.palette[6] = redAmount << 16 | greenAmount << 8 | blueAmount; + win2BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + win2Btn.ResetState(); + } + else if(win3Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[7] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[7] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[7] >> 0) & 0xFF; + PaletteWindow("WIN 3"); + CurrentPalette.palette[7] = redAmount << 16 | greenAmount << 8 | blueAmount; + win3BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + win3Btn.ResetState(); + } + else if(obj0Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[8] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[8] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[8] >> 0) & 0xFF; + PaletteWindow("OBJ 0"); + CurrentPalette.palette[8] = redAmount << 16 | greenAmount << 8 | blueAmount; + obj0BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + obj0Btn.ResetState(); + } + else if(obj1Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[9] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[9] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[9] >> 0) & 0xFF; + PaletteWindow("OBJ 1"); + CurrentPalette.palette[9] = redAmount << 16 | greenAmount << 8 | blueAmount; + obj1BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + obj1Btn.ResetState(); + } + else if(obj2Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[10] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[10] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[10] >> 0) & 0xFF; + PaletteWindow("OBJ 2"); + CurrentPalette.palette[10] = redAmount << 16 | greenAmount << 8 | blueAmount; + obj2BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + obj2Btn.ResetState(); + } + else if(spr0Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[11] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[11] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[11] >> 0) & 0xFF; + PaletteWindow("SPR 0"); + CurrentPalette.palette[11] = redAmount << 16 | greenAmount << 8 | blueAmount; + spr0BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + spr0Btn.ResetState(); + } + else if(spr1Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[12] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[12] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[12] >> 0) & 0xFF; + PaletteWindow("SPR 1"); + CurrentPalette.palette[12] = redAmount << 16 | greenAmount << 8 | blueAmount; + spr1BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + spr1Btn.ResetState(); + } + else if(spr2Btn.GetState() == STATE_CLICKED) + { + redAmount = (CurrentPalette.palette[13] >> 16) & 0xFF; + greenAmount = (CurrentPalette.palette[13] >> 8) & 0xFF; + blueAmount = (CurrentPalette.palette[13] >> 0) & 0xFF; + PaletteWindow("SPR 2"); + CurrentPalette.palette[13] = redAmount << 16 | greenAmount << 8 | blueAmount; + spr2BtnTxt.SetColor((GXColor){(u8)redAmount, (u8)greenAmount, (u8)blueAmount, 0xFF}); + spr2Btn.ResetState(); + } + else if(importBtn.GetState() == STATE_CLICKED) + { + SavePaletteAs(NOTSILENT, RomTitle); + menu = MENU_GAMESETTINGS_PALETTE; + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + SavePaletteAs(SILENT, RomTitle); + + exitSound->Play(); + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 15); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 15); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(350000); // wait for effects to finish + } + else if(backBtn.GetState() == STATE_CLICKED) + { + SavePaletteAs(SILENT, RomTitle); + menu = MENU_GAMESETTINGS_VIDEO; + } + } + + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MainMenu + ***************************************************************************/ +void +MainMenu (int menu) +{ + static bool init = false; + int currentMenu = menu; + //lastMenu = MENU_NONE; + + int lastMenu = MENU_NONE; /* local variable here fixes devkitppc r27 crash */ + GuiTrigger *trigAptr, *trig2ptr; /* local variable here fixes devkitppc r27 crash */ + if(!init) + { + init = true; + #ifdef HW_RVL + pointer[0] = new GuiImageData(player1_point_png); + pointer[1] = new GuiImageData(player2_point_png); + pointer[2] = new GuiImageData(player3_point_png); + pointer[3] = new GuiImageData(player4_point_png); + #endif + + trigA = new GuiTrigger; + trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + trig2 = new GuiTrigger; + trig2->SetSimpleTrigger(-1, WPAD_BUTTON_2, 0); + } + + mainWindow = new GuiWindow(screenwidth, screenheight); + + if(menu == MENU_GAME) + { + gameScreen = new GuiImageData(gameScreenPng); + gameScreenImg = new GuiImage(gameScreen); + gameScreenImg->SetAlpha(192); + gameScreenImg->ColorStripe(30); + + gameScreenImg->SetScaleX(screenwidth/(float)vmode->fbWidth); + gameScreenImg->SetScaleY(screenheight/(float)vmode->efbHeight); + } + else + { + gameScreenImg = new GuiImage(screenwidth, screenheight, (GXColor){236, 226, 238, 255}); + gameScreenImg->ColorStripe(10); + } + + mainWindow->Append(gameScreenImg); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiSound btnSoundClick(button_click_pcm, button_click_pcm_size, SOUND_PCM); + GuiImageData bgTop(bg_top_png); + bgTopImg = new GuiImage(&bgTop); + GuiImageData bgBottom(bg_bottom_png); + bgBottomImg = new GuiImage(&bgBottom); + bgBottomImg->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + GuiImageData logo(logo_png); + GuiImage logoImg(&logo); + GuiImageData logoOver(logo_over_png); + GuiImage logoImgOver(&logoOver); + GuiText logoTxt(APPVERSION, 18, (GXColor){255, 255, 255, 255}); + logoTxt.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + logoTxt.SetPosition(0, 4); + btnLogo = new GuiButton(logoImg.GetWidth(), logoImg.GetHeight()); + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo->SetPosition(-50, 24); + btnLogo->SetImage(&logoImg); + btnLogo->SetImageOver(&logoImgOver); + btnLogo->SetLabel(&logoTxt); + btnLogo->SetSoundOver(&btnSoundOver); + btnLogo->SetSoundClick(&btnSoundClick); + btnLogo->SetTrigger(trigA); + btnLogo->SetTrigger(trig2); + btnLogo->SetUpdateCallback(WindowCredits); + + mainWindow->Append(bgTopImg); + mainWindow->Append(bgBottomImg); + mainWindow->Append(btnLogo); + + trigAptr = trigA; + trig2ptr = trig2; + + if(currentMenu == MENU_GAMESELECTION) + ResumeGui(); + + // Load preferences + if(!LoadPrefs()) + SavePrefs(SILENT); + +#ifdef HW_RVL + static bool checkIOS = true; + + if(checkIOS) + { + u32 ios = IOS_GetVersion(); + + if(!SupportedIOS(ios)) + ErrorPrompt("The current IOS is unsupported. Functionality and/or stability may be adversely affected."); + else if(!SaneIOS(ios)) + ErrorPrompt("The current IOS has been altered (fake-signed). Functionality and/or stability may be adversely affected."); + } + + checkIOS = false; +#endif + + // Load palettes + LoadPalettes(); + + #ifndef NO_SOUND + bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, SOUND_OGG); + bgMusic->SetVolume(GCSettings.MusicVolume); + bgMusic->SetLoop(true); + enterSound = new GuiSound(enter_ogg, enter_ogg_size, SOUND_OGG); + enterSound->SetVolume(GCSettings.SFXVolume); + exitSound = new GuiSound(exit_ogg, exit_ogg_size, SOUND_OGG); + exitSound->SetVolume(GCSettings.SFXVolume); + if(currentMenu == MENU_GAMESELECTION) bgMusic->Play(); // startup music + #endif + + while(currentMenu != MENU_EXIT || !ROMLoaded) + { + switch (currentMenu) + { + case MENU_GAMESELECTION: + currentMenu = MenuGameSelection(); + break; + case MENU_GAME: + currentMenu = MenuGame(lastMenu); + break; + case MENU_GAME_LOAD: + currentMenu = MenuGameSaves(0); + break; + case MENU_GAME_SAVE: + currentMenu = MenuGameSaves(1); + break; + case MENU_GAMESETTINGS: + currentMenu = MenuGameSettings(); + break; + case MENU_GAMESETTINGS_MAPPINGS: + currentMenu = MenuSettingsMappings(); + break; + case MENU_GAMESETTINGS_MAPPINGS_MAP: + currentMenu = MenuSettingsMappingsMap(); + break; + case MENU_GAMESETTINGS_VIDEO: + currentMenu = MenuSettingsVideo(); + break; + case MENU_GAMESETTINGS_PALETTE: + currentMenu = MenuPalette(); + break; + case MENU_SETTINGS: + currentMenu = MenuSettings(trigAptr,trig2ptr); + break; + case MENU_SETTINGS_FILE: + currentMenu = MenuSettingsFile(); + break; + case MENU_SETTINGS_MENU: + currentMenu = MenuSettingsMenu(); + break; + case MENU_SETTINGS_NETWORK: + currentMenu = MenuSettingsNetwork(); + break; + case MENU_SETTINGS_EMULATION: + currentMenu = MenuSettingsEmulation(); + break; + default: // unrecognized menu + currentMenu = MenuGameSelection(); + break; + } + lastMenu = currentMenu; + usleep(THREAD_SLEEP); + } + + #ifdef HW_RVL + ShutoffRumble(); + #endif + + CancelAction(); + HaltGui(); + + #ifdef HW_RVL + if(updatethread != LWP_THREAD_NULL) + LWP_JoinThread(updatethread, NULL); + #endif + + #ifndef NO_SOUND + delete bgMusic; + delete enterSound; + delete exitSound; + #endif + + delete btnLogo; + delete gameScreenImg; + delete bgTopImg; + delete bgBottomImg; + delete mainWindow; + + mainWindow = NULL; + + if(gameScreen) + delete gameScreen; + + if(gameScreenPng) + { + free(gameScreenPng); + gameScreenPng = NULL; + } + + // wait for keys to be depressed + while(MenuRequested()) + { + UpdatePads(); + usleep(THREAD_SLEEP); + } +} diff --git a/source/menu.h b/source/menu.h index ad11904..5eeae28 100644 --- a/source/menu.h +++ b/source/menu.h @@ -1,49 +1,51 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * menu.h - * - * Menu flow routines - handles all menu logic - ***************************************************************************/ - -#ifndef _MENU_H -#define _MENU_H - -#include -#include "gui/gui.h" - -extern GuiImageData * pointer[4]; - -void InitGUIThreads(); -void MainMenu (int menuitem); -void ErrorPrompt(const char * msg); -int ErrorPromptRetry(const char * msg); -void InfoPrompt(const char * msg); -void ShowAction (const char *msg); -void CancelAction(); -void ShowProgress (const char *msg, int done, int total); -void ResetText(); - -enum -{ - MENU_EXIT = -1, - MENU_NONE, - MENU_SETTINGS, - MENU_SETTINGS_FILE, - MENU_SETTINGS_MENU, - MENU_SETTINGS_NETWORK, - MENU_GAMESELECTION, - MENU_GAME, - MENU_GAME_SAVE, - MENU_GAME_LOAD, - MENU_GAMESETTINGS, - MENU_GAMESETTINGS_MAPPINGS, - MENU_GAMESETTINGS_MAPPINGS_MAP, - MENU_GAMESETTINGS_VIDEO, - MENU_GAMESETTINGS_CHEATS, - MENU_GAMESETTINGS_PALETTE -}; - -#endif +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * menu.h + * + * Menu flow routines - handles all menu logic + ***************************************************************************/ + +#ifndef _MENU_H +#define _MENU_H + +#include +#include "gui/gui.h" + +extern GuiImageData * pointer[4]; + +void InitGUIThreads(); +void MainMenu (int menuitem); +void ErrorPrompt(const char * msg); +int ErrorPromptRetry(const char * msg); +void InfoPrompt(const char * msg); +int YesNoPrompt(const char *msg, bool yesDefault); +void ShowAction (const char *msg); +void CancelAction(); +void ShowProgress (const char *msg, int done, int total); +void ResetText(); + +enum +{ + MENU_EXIT = -1, + MENU_NONE, + MENU_SETTINGS, + MENU_SETTINGS_FILE, + MENU_SETTINGS_MENU, + MENU_SETTINGS_NETWORK, + MENU_GAMESELECTION, + MENU_GAME, + MENU_GAME_SAVE, + MENU_GAME_LOAD, + MENU_GAMESETTINGS, + MENU_GAMESETTINGS_MAPPINGS, + MENU_GAMESETTINGS_MAPPINGS_MAP, + MENU_GAMESETTINGS_VIDEO, + MENU_GAMESETTINGS_CHEATS, + MENU_GAMESETTINGS_PALETTE, + MENU_SETTINGS_EMULATION +}; + +#endif diff --git a/source/utils/pngu.c b/source/utils/pngu.c index 127017d..8f53831 100644 --- a/source/utils/pngu.c +++ b/source/utils/pngu.c @@ -1,751 +1,842 @@ -/**************************************************************************** - * - * PNGU - * - * Original author: frontier (http://frontier-dev.net) - * Modified by Tantric, 2009-2010 - * - ***************************************************************************/ - -#include -#include -#include "pngu.h" -#include - -// Constants -#define PNGU_SOURCE_BUFFER 1 -#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 -#define PNGU_COLOR_TYPE_GRAY 1 -#define PNGU_COLOR_TYPE_GRAY_ALPHA 2 -#define PNGU_COLOR_TYPE_PALETTE 3 -#define PNGU_COLOR_TYPE_RGB 4 -#define PNGU_COLOR_TYPE_RGB_ALPHA 5 -#define PNGU_COLOR_TYPE_UNKNOWN 6 - -// PNGU Image context struct -struct _IMGCTX -{ - int source; - void *buffer; - char *filename; - u32 cursor; - - u32 propRead; - PNGUPROP prop; - - u32 infoRead; - png_structp png_ptr; - png_infop info_ptr; - FILE *fd; - - png_bytep *row_pointers; - png_bytep img_data; -}; - -// PNGU Implementation - -static void pngu_free_info (IMGCTX ctx) -{ - if (ctx->infoRead) - { - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - - png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL); - - ctx->infoRead = 0; - } -} - -// Custom data provider function used for reading from memory buffers. -static void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length) -{ - IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); - memcpy (data, ctx->buffer + ctx->cursor, length); - ctx->cursor += length; -} - -// Custom data writer function used for writing to memory buffers. -static void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length) -{ - IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); - memcpy (ctx->buffer + ctx->cursor, data, length); - ctx->cursor += length; -} - -// Custom data flusher function used for writing to memory buffers. -static void pngu_flush_data_to_buffer (png_structp png_ptr) -{ - // Nothing to do here -} - -static int pngu_info (IMGCTX ctx) -{ - png_byte magic[8]; - png_uint_32 width; - png_uint_32 height; - png_color_16p background; - png_bytep trans; - png_color_16p trans_values; - int scale, i; - - // Check if there is a file selected and if it is a valid .png - if (ctx->source == PNGU_SOURCE_BUFFER) - memcpy (magic, ctx->buffer, 8); - - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Open file - if (!(ctx->fd = fopen (ctx->filename, "rb"))) - return PNGU_CANT_OPEN_FILE; - - // Load first 8 bytes into magic buffer - if (fread (magic, 1, 8, ctx->fd) != 8) - { - fclose (ctx->fd); - return PNGU_CANT_READ_FILE; - } - } - - else - return PNGU_NO_FILE_SELECTED;; - - if (png_sig_cmp(magic, 0, 8) != 0) - { - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_FILE_IS_NOT_PNG; - } - - // Allocation of libpng structs - ctx->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!(ctx->png_ptr)) - { - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - ctx->info_ptr = png_create_info_struct (ctx->png_ptr); - if (!(ctx->info_ptr)) - { - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - png_destroy_read_struct (&(ctx->png_ptr), (png_infopp)NULL, (png_infopp)NULL); - return PNGU_LIB_ERROR; - } - - if (ctx->source == PNGU_SOURCE_BUFFER) - { - // Installation of our custom data provider function - ctx->cursor = 0; - png_set_read_fn (ctx->png_ptr, ctx, pngu_read_data_from_buffer); - } - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Default data provider uses function fread, so it needs to use our FILE* - png_init_io (ctx->png_ptr, ctx->fd); - png_set_sig_bytes (ctx->png_ptr, 8); // We have read 8 bytes already to check PNG authenticity - } - - // Read png header - png_read_info (ctx->png_ptr, ctx->info_ptr); - - // Query image properties if they have not been queried before - if (!ctx->propRead) - { - int ctxNumTrans; - - png_get_IHDR(ctx->png_ptr, ctx->info_ptr, &width, &height, - (int *) &(ctx->prop.imgBitDepth), - (int *) &(ctx->prop.imgColorType), - NULL, NULL, NULL); - - ctx->prop.imgWidth = width; - ctx->prop.imgHeight = height; - switch (ctx->prop.imgColorType) - { - case PNG_COLOR_TYPE_GRAY: - ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY_ALPHA; - break; - case PNG_COLOR_TYPE_PALETTE: - ctx->prop.imgColorType = PNGU_COLOR_TYPE_PALETTE; - break; - case PNG_COLOR_TYPE_RGB: - ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB_ALPHA; - break; - default: - ctx->prop.imgColorType = PNGU_COLOR_TYPE_UNKNOWN; - break; - } - - // Constant used to scale 16 bit values to 8 bit values - scale = 0; - if (ctx->prop.imgBitDepth == 16) - scale = 8; - - // Query background color, if any. - ctx->prop.validBckgrnd = 0; - - switch(ctx->prop.imgColorType) - { - case PNGU_COLOR_TYPE_RGB: - case PNGU_COLOR_TYPE_RGB_ALPHA: - { - if(png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)){ - ctx->prop.validBckgrnd = 1; - ctx->prop.bckgrnd.r = background->red >> scale; - ctx->prop.bckgrnd.g = background->green >> scale; - ctx->prop.bckgrnd.b = background->blue >> scale; - } - - // Query list of transparent colors, if any. - ctx->prop.numTrans = 0; - ctx->prop.trans = NULL; - - if(png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)){ - ctxNumTrans = ctx->prop.numTrans; - if(ctxNumTrans){ - ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctxNumTrans); - if (ctx->prop.trans) - for (i = 0; i < ctxNumTrans; i++) - { - ctx->prop.trans[i].r = trans_values[i].red >> scale; - ctx->prop.trans[i].g = trans_values[i].green >> scale; - ctx->prop.trans[i].b = trans_values[i].blue >> scale; - } - else - ctx->prop.numTrans = 0; - } - } - - } - break; - - case PNGU_COLOR_TYPE_GRAY: - case PNGU_COLOR_TYPE_GRAY_ALPHA: - { - if(png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)){ - ctx->prop.validBckgrnd = 1; - ctx->prop.bckgrnd.r = - ctx->prop.bckgrnd.g = - ctx->prop.bckgrnd.b = background->gray >> scale; - } - - // Query list of transparent colors, if any. - ctx->prop.numTrans = 0; - ctx->prop.trans = NULL; - - if(png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)){ - ctxNumTrans = ctx->prop.numTrans; - if(ctxNumTrans){ - ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctxNumTrans); - if (ctx->prop.trans) - for (i = 0; i < ctxNumTrans; i++) - ctx->prop.trans[i].r = - ctx->prop.trans[i].g = - ctx->prop.trans[i].b = trans_values[i].gray >> scale; - else - ctx->prop.numTrans = 0; - } - } - - } - break; - - default: - - // It was none of those things, - { - // Query list of transparent colors, if any. - ctx->prop.numTrans = 0; - ctx->prop.trans = NULL; - } - break; - } - - ctx->propRead = 1; - } - - // Success - ctx->infoRead = 1; - - return PNGU_OK; -} - -static int pngu_decode (IMGCTX ctx, u32 width, u32 height, u32 stripAlpha) -{ - png_uint_32 rowbytes; - png_uint_32 i, propImgHeight; - - // Read info if it hasn't been read before - if (!ctx->infoRead) - { - int c = pngu_info (ctx); - if (c != PNGU_OK) - return c; - } - - // Check if the user has specified the real width and height of the image - if ( (ctx->prop.imgWidth != width) || (ctx->prop.imgHeight != height) ) - return PNGU_INVALID_WIDTH_OR_HEIGHT; - - // Check if color type is supported by PNGU - if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) ) - return PNGU_UNSUPPORTED_COLOR_TYPE; - - // Scale 16 bit samples to 8 bit - if (ctx->prop.imgBitDepth == 16) - png_set_strip_16 (ctx->png_ptr); - - // Remove alpha channel if we don't need it - if (stripAlpha && ((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA))) - png_set_strip_alpha (ctx->png_ptr); - - // Expand 1, 2 and 4 bit samples to 8 bit - if (ctx->prop.imgBitDepth < 8) - png_set_packing (ctx->png_ptr); - - // Transform grayscale images to RGB - if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) ) - png_set_gray_to_rgb (ctx->png_ptr); - - // Flush transformations - png_read_update_info (ctx->png_ptr, ctx->info_ptr); - - // Allocate memory to store the image - rowbytes = png_get_rowbytes (ctx->png_ptr, ctx->info_ptr); - - if (rowbytes & 3) - rowbytes = ((rowbytes >> 2) + 1) << 2; // Add extra padding so each row starts in a 4 byte boundary - - ctx->img_data = malloc (rowbytes * ctx->prop.imgHeight); - if (!ctx->img_data) - { - pngu_free_info (ctx); - return PNGU_LIB_ERROR; - } - - ctx->row_pointers = malloc (sizeof (png_bytep) * ctx->prop.imgHeight); - if (!ctx->row_pointers) - { - free (ctx->img_data); - pngu_free_info (ctx); - return PNGU_LIB_ERROR; - } - - propImgHeight = ctx->prop.imgHeight; - for (i = 0; i < propImgHeight; ++i) - ctx->row_pointers[i] = ctx->img_data + (i * rowbytes); - - // Transform the image and copy it to our allocated memory - png_read_image (ctx->png_ptr, ctx->row_pointers); - - // Free resources - pngu_free_info (ctx); - - // Success - return PNGU_OK; -} - -static inline u32 coordsRGBA8(u32 x, u32 y, u32 w) -{ - return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1; -} - -static u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, u32 width, u32 height, int * dstWidth, int * dstHeight, u8 *dstPtr, int maxWidth, int maxHeight) -{ - u8 default_alpha = 255; - u8 *dst; - int x, y, x2, y2, offset; - int xRatio = 0, yRatio = 0; - png_byte *pixel; - - if (pngu_decode (ctx, width, height, 0) != PNGU_OK) - return NULL; - - int newWidth = width; - int newHeight = height; - - if((maxWidth > 0 && width > maxWidth) || (maxHeight > 0 && height > maxHeight)) - { - float ratio = (float)width/(float)height; - - newWidth = maxWidth; - newHeight = maxWidth/ratio; - - if(newHeight > maxHeight) - { - newWidth = maxHeight*ratio; - newHeight = maxHeight; - } - xRatio = (int)((width<<16)/newWidth)+1; - yRatio = (int)((height<<16)/newHeight)+1; - } - - int padWidth = newWidth; - int padHeight = newHeight; - if(padWidth%4) padWidth += (4-padWidth%4); - if(padHeight%4) padHeight += (4-padHeight%4); - - int len = (padWidth * padHeight) << 2; - if(len%32) len += (32-len%32); - - if(dstPtr) - dst = dstPtr; // use existing allocation - else - dst = memalign (32, len); - - if(!dst) - return NULL; - - for (y = 0; y < padHeight; y++) - { - for (x = 0; x < padWidth; x++) - { - offset = coordsRGBA8(x, y, padWidth); - - if(y >= newHeight || x >= newWidth) - { - dst[offset] = 0; - dst[offset+1] = 255; - dst[offset+32] = 255; - dst[offset+33] = 255; - } - else - { - if(xRatio > 0) - { - x2 = ((x*xRatio)>>16); - y2 = ((y*yRatio)>>16); - } - - if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA || - ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) - { - if(xRatio > 0) - pixel = &(ctx->row_pointers[y2][x2*4]); - else - pixel = &(ctx->row_pointers[y][x*4]); - - dst[offset] = pixel[3]; // Alpha - dst[offset+1] = pixel[0]; // Red - dst[offset+32] = pixel[1]; // Green - dst[offset+33] = pixel[2]; // Blue - } - else - { - if(xRatio > 0) - pixel = &(ctx->row_pointers[y2][x2*3]); - else - pixel = &(ctx->row_pointers[y][x*3]); - - dst[offset] = default_alpha; // Alpha - dst[offset+1] = pixel[0]; // Red - dst[offset+32] = pixel[1]; // Green - dst[offset+33] = pixel[2]; // Blue - } - } - } - } - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - - *dstWidth = padWidth; - *dstHeight = padHeight; - DCFlushRange(dst, len); - return dst; -} - -IMGCTX PNGU_SelectImageFromBuffer (const void *buffer) -{ - IMGCTX ctx = NULL; - - if (!buffer) - return NULL; - - ctx = malloc (sizeof (struct _IMGCTX)); - if (!ctx) - return NULL; - - ctx->buffer = (void *) buffer; - ctx->source = PNGU_SOURCE_BUFFER; - ctx->cursor = 0; - ctx->filename = NULL; - ctx->propRead = 0; - ctx->infoRead = 0; - - return ctx; -} - -IMGCTX PNGU_SelectImageFromDevice (const char *filename) -{ - IMGCTX ctx = NULL; - - if (!filename) - return NULL; - - ctx = malloc (sizeof (struct _IMGCTX)); - if (!ctx) - return NULL; - - ctx->buffer = NULL; - ctx->source = PNGU_SOURCE_DEVICE; - ctx->cursor = 0; - - ctx->filename = malloc (strlen (filename) + 1); - if (!ctx->filename) - { - free (ctx); - return NULL; - } - strcpy(ctx->filename, filename); - - ctx->propRead = 0; - ctx->infoRead = 0; - - return ctx; -} - -void PNGU_ReleaseImageContext (IMGCTX ctx) -{ - if (!ctx) - return; - - if (ctx->filename) - free (ctx->filename); - - if ((ctx->propRead) && (ctx->prop.trans)) - free (ctx->prop.trans); - - pngu_free_info (ctx); - free (ctx); -} - -int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop) -{ - int res; - - if (!ctx->propRead) - { - res = pngu_info (ctx); - if (res != PNGU_OK) - return res; - } - - *imgprop = ctx->prop; - return PNGU_OK; -} - -u8 * DecodePNG(const u8 *src, int * width, int * height, u8 *dstPtr, int maxwidth, int maxheight) -{ - PNGUPROP imgProp; - IMGCTX ctx = PNGU_SelectImageFromBuffer(src); - u8 *dst = NULL; - - if(!ctx) - return NULL; - - if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK) - dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, width, height, dstPtr, maxwidth, maxheight); - - PNGU_ReleaseImageContext (ctx); - return dst; -} - -int PNGU_EncodeFromRGB (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride) -{ - png_uint_32 rowbytes; - u32 y; - - // Erase from the context any readed info - pngu_free_info (ctx); - ctx->propRead = 0; - - // Check if the user has selected a file to write the image - if (ctx->source == PNGU_SOURCE_BUFFER); - - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Open file - if (!(ctx->fd = fopen (ctx->filename, "wb"))) - return PNGU_CANT_OPEN_FILE; - } - - else - return PNGU_NO_FILE_SELECTED; - - // Allocation of libpng structs - ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!(ctx->png_ptr)) - { - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - ctx->info_ptr = png_create_info_struct (ctx->png_ptr); - if (!(ctx->info_ptr)) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - if (ctx->source == PNGU_SOURCE_BUFFER) - { - // Installation of our custom data writer function - ctx->cursor = 0; - png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer); - } - else if (ctx->source == PNGU_SOURCE_DEVICE) - { - // Default data writer uses function fwrite, so it needs to use our FILE* - png_init_io (ctx->png_ptr, ctx->fd); - } - - // Setup output file properties - png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - // Allocate memory to store the image in RGB format - rowbytes = width * 3; - if (rowbytes % 4) - rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary - - ctx->img_data = malloc(rowbytes * height); - - if (!ctx->img_data) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - memset(ctx->img_data, 0, rowbytes * height); - ctx->row_pointers = malloc (sizeof (png_bytep) * height); - - if (!ctx->row_pointers) - { - png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - return PNGU_LIB_ERROR; - } - - memset(ctx->row_pointers, 0, sizeof (png_bytep) * height); - - for (y = 0; y < height; ++y) - { - ctx->row_pointers[y] = buffer + (y * rowbytes); - } - - // Tell libpng where is our image data - png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers); - - // Write file header and image data - png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - // Tell libpng we have no more data to write - png_write_end (ctx->png_ptr, (png_infop) NULL); - - // Free resources - free (ctx->img_data); - free (ctx->row_pointers); - png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr)); - if (ctx->source == PNGU_SOURCE_DEVICE) - fclose (ctx->fd); - - // Success - return ctx->cursor; -} - -int PNGU_EncodeFromGXTexture (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride) -{ - int res; - u32 x, y, tmpy1, tmpy2, tmpyWid, tmpxy; - - unsigned char * ptr = (unsigned char*)buffer; - unsigned char * tmpbuffer = malloc(width*height*3); - - if(!tmpbuffer) - return PNGU_LIB_ERROR; - - memset(tmpbuffer, 0, width*height*3); - png_uint_32 offset; - - for(y=0; y < height; y++) - { - tmpy1 = y * 640*3; - tmpy2 = y%4 << 2; - tmpyWid = (((y >> 2)<<4)*width); - - for(x=0; x < width; x++) - { - offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1); - tmpxy = x * 3 + tmpy1; - - tmpbuffer[tmpxy ] = ptr[offset+1]; // R - tmpbuffer[tmpxy+1] = ptr[offset+32]; // G - tmpbuffer[tmpxy+2] = ptr[offset+33]; // B - } - } - - res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride); - free(tmpbuffer); - return res; -} - -int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height) -{ - int res; - u32 x, y, tmpy1, tmpxy; - GXColor color; - - 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; - GX_PeekARGB(x, y, &color); - tmpbuffer[tmpxy ] = color.r; // R - tmpbuffer[tmpxy+1] = color.g; // G - tmpbuffer[tmpxy+2] = color.b; // B - } - } - - res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, 0); - free(tmpbuffer); - return res; -} +/**************************************************************************** + * + * PNGU + * + * Original author: frontier (http://frontier-dev.net) + * This is Tantric's modified/condensed version + RGB565 decoder from original + * + ***************************************************************************/ + +#include +#include +#include "pngu.h" +#include + +// Constants +#define PNGU_SOURCE_BUFFER 1 +#define PNGU_SOURCE_DEVICE 2 + +// Color types +#define PNGU_COLOR_TYPE_GRAY 1 +#define PNGU_COLOR_TYPE_GRAY_ALPHA 2 +#define PNGU_COLOR_TYPE_PALETTE 3 +#define PNGU_COLOR_TYPE_RGB 4 +#define PNGU_COLOR_TYPE_RGB_ALPHA 5 +#define PNGU_COLOR_TYPE_UNKNOWN 6 + +// PNGU Image context struct +struct _IMGCTX +{ + int source; + void *buffer; + char *filename; + u32 cursor; + + u32 propRead; + PNGUPROP prop; + + u32 infoRead; + png_structp png_ptr; + png_infop info_ptr; + FILE *fd; + + png_bytep *row_pointers; + png_bytep img_data; +}; + +// PNGU Implementation + +static void pngu_free_info (IMGCTX ctx) +{ + if (ctx->infoRead) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + + png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL); + + ctx->infoRead = 0; + } +} + +// Custom data provider function used for reading from memory buffers. +static void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length) +{ + IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); + memcpy (data, ctx->buffer + ctx->cursor, length); + ctx->cursor += length; +} + +// Custom data writer function used for writing to memory buffers. +static void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length) +{ + IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr); + memcpy (ctx->buffer + ctx->cursor, data, length); + ctx->cursor += length; +} + +// Custom data flusher function used for writing to memory buffers. +static void pngu_flush_data_to_buffer (png_structp png_ptr) +{ + // Nothing to do here +} + +static int pngu_info (IMGCTX ctx) +{ + png_byte magic[8]; + png_uint_32 width; + png_uint_32 height; + png_color_16p background; + png_bytep trans; + png_color_16p trans_values; + int scale, i; + + // Check if there is a file selected and if it is a valid .png + if (ctx->source == PNGU_SOURCE_BUFFER) + memcpy (magic, ctx->buffer, 8); + + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Open file + if (!(ctx->fd = fopen (ctx->filename, "rb"))) + return PNGU_CANT_OPEN_FILE; + + // Load first 8 bytes into magic buffer + if (fread (magic, 1, 8, ctx->fd) != 8) + { + fclose (ctx->fd); + return PNGU_CANT_READ_FILE; + } + } + + else + return PNGU_NO_FILE_SELECTED;; + + if (png_sig_cmp(magic, 0, 8) != 0) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_FILE_IS_NOT_PNG; + } + + // Allocation of libpng structs + ctx->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!(ctx->png_ptr)) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + ctx->info_ptr = png_create_info_struct (ctx->png_ptr); + if (!(ctx->info_ptr)) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + png_destroy_read_struct (&(ctx->png_ptr), (png_infopp)NULL, (png_infopp)NULL); + return PNGU_LIB_ERROR; + } + + if (ctx->source == PNGU_SOURCE_BUFFER) + { + // Installation of our custom data provider function + ctx->cursor = 0; + png_set_read_fn (ctx->png_ptr, ctx, pngu_read_data_from_buffer); + } + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Default data provider uses function fread, so it needs to use our FILE* + png_init_io (ctx->png_ptr, ctx->fd); + png_set_sig_bytes (ctx->png_ptr, 8); // We have read 8 bytes already to check PNG authenticity + } + + // Read png header + png_read_info (ctx->png_ptr, ctx->info_ptr); + + // Query image properties if they have not been queried before + if (!ctx->propRead) + { + int ctxNumTrans; + + png_get_IHDR(ctx->png_ptr, ctx->info_ptr, &width, &height, + (int *) &(ctx->prop.imgBitDepth), + (int *) &(ctx->prop.imgColorType), + NULL, NULL, NULL); + + ctx->prop.imgWidth = width; + ctx->prop.imgHeight = height; + switch (ctx->prop.imgColorType) + { + case PNG_COLOR_TYPE_GRAY: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY_ALPHA; + break; + case PNG_COLOR_TYPE_PALETTE: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_PALETTE; + break; + case PNG_COLOR_TYPE_RGB: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB_ALPHA; + break; + default: + ctx->prop.imgColorType = PNGU_COLOR_TYPE_UNKNOWN; + break; + } + + // Constant used to scale 16 bit values to 8 bit values + scale = 0; + if (ctx->prop.imgBitDepth == 16) + scale = 8; + + // Query background color, if any. + ctx->prop.validBckgrnd = 0; + + switch(ctx->prop.imgColorType) + { + case PNGU_COLOR_TYPE_RGB: + case PNGU_COLOR_TYPE_RGB_ALPHA: + { + if(png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)){ + ctx->prop.validBckgrnd = 1; + ctx->prop.bckgrnd.r = background->red >> scale; + ctx->prop.bckgrnd.g = background->green >> scale; + ctx->prop.bckgrnd.b = background->blue >> scale; + } + + // Query list of transparent colors, if any. + ctx->prop.numTrans = 0; + ctx->prop.trans = NULL; + + if(png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)){ + ctxNumTrans = ctx->prop.numTrans; + if(ctxNumTrans){ + ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctxNumTrans); + if (ctx->prop.trans) + for (i = 0; i < ctxNumTrans; i++) + { + ctx->prop.trans[i].r = trans_values[i].red >> scale; + ctx->prop.trans[i].g = trans_values[i].green >> scale; + ctx->prop.trans[i].b = trans_values[i].blue >> scale; + } + else + ctx->prop.numTrans = 0; + } + } + + } + break; + + case PNGU_COLOR_TYPE_GRAY: + case PNGU_COLOR_TYPE_GRAY_ALPHA: + { + if(png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)){ + ctx->prop.validBckgrnd = 1; + ctx->prop.bckgrnd.r = + ctx->prop.bckgrnd.g = + ctx->prop.bckgrnd.b = background->gray >> scale; + } + + // Query list of transparent colors, if any. + ctx->prop.numTrans = 0; + ctx->prop.trans = NULL; + + if(png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)){ + ctxNumTrans = ctx->prop.numTrans; + if(ctxNumTrans){ + ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctxNumTrans); + if (ctx->prop.trans) + for (i = 0; i < ctxNumTrans; i++) + ctx->prop.trans[i].r = + ctx->prop.trans[i].g = + ctx->prop.trans[i].b = trans_values[i].gray >> scale; + else + ctx->prop.numTrans = 0; + } + } + + } + break; + + default: + + // It was none of those things, + { + // Query list of transparent colors, if any. + ctx->prop.numTrans = 0; + ctx->prop.trans = NULL; + } + break; + } + + ctx->propRead = 1; + } + + // Success + ctx->infoRead = 1; + + return PNGU_OK; +} + +static int pngu_decode (IMGCTX ctx, u32 width, u32 height, u32 stripAlpha) +{ + png_uint_32 rowbytes; + png_uint_32 i, propImgHeight; + + // Read info if it hasn't been read before + if (!ctx->infoRead) + { + int c = pngu_info (ctx); + if (c != PNGU_OK) + return c; + } + + // Check if the user has specified the real width and height of the image + if ( (ctx->prop.imgWidth != width) || (ctx->prop.imgHeight != height) ) + return PNGU_INVALID_WIDTH_OR_HEIGHT; + + // Check if color type is supported by PNGU + if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) + return PNGU_UNSUPPORTED_COLOR_TYPE; + + // Scale 16 bit samples to 8 bit + if (ctx->prop.imgBitDepth == 16) + png_set_strip_16 (ctx->png_ptr); + + // Remove alpha channel if we don't need it + if (stripAlpha && ((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA))) + png_set_strip_alpha (ctx->png_ptr); + + // Expand 1, 2 and 4 bit samples to 8 bit + if (ctx->prop.imgBitDepth < 8) + png_set_packing (ctx->png_ptr); + + // Transform grayscale images to RGB + if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) ) + 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 + png_read_update_info (ctx->png_ptr, ctx->info_ptr); + + // Allocate memory to store the image + rowbytes = png_get_rowbytes (ctx->png_ptr, ctx->info_ptr); + + if (rowbytes & 3) + rowbytes = ((rowbytes >> 2) + 1) << 2; // Add extra padding so each row starts in a 4 byte boundary + + ctx->img_data = malloc (rowbytes * ctx->prop.imgHeight); + if (!ctx->img_data) + { + pngu_free_info (ctx); + return PNGU_LIB_ERROR; + } + + ctx->row_pointers = malloc (sizeof (png_bytep) * ctx->prop.imgHeight); + if (!ctx->row_pointers) + { + free (ctx->img_data); + pngu_free_info (ctx); + return PNGU_LIB_ERROR; + } + + propImgHeight = ctx->prop.imgHeight; + for (i = 0; i < propImgHeight; ++i) + ctx->row_pointers[i] = ctx->img_data + (i * rowbytes); + + // Transform the image and copy it to our allocated memory + png_read_image (ctx->png_ptr, ctx->row_pointers); + + // Free resources + pngu_free_info (ctx); + + // Success + return PNGU_OK; +} + +static inline u32 coordsRGBA8(u32 x, u32 y, u32 w) +{ + return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1; +} + +static u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, u32 width, u32 height, int * dstWidth, int * dstHeight, u8 *dstPtr, int maxWidth, int maxHeight) +{ + u8 default_alpha = 255; + u8 *dst; + int x, y, x2, y2, offset; + int xRatio = 0, yRatio = 0; + png_byte *pixel; + + if (pngu_decode (ctx, width, height, 0) != PNGU_OK) + return NULL; + + int newWidth = width; + int newHeight = height; + + if((maxWidth > 0 && width > maxWidth) || (maxHeight > 0 && height > maxHeight)) + { + float ratio = (float)width/(float)height; + + newWidth = maxWidth; + newHeight = maxWidth/ratio; + + if(newHeight > maxHeight) + { + newWidth = maxHeight*ratio; + newHeight = maxHeight; + } + xRatio = (int)((width<<16)/newWidth)+1; + yRatio = (int)((height<<16)/newHeight)+1; + } + + int padWidth = newWidth; + int padHeight = newHeight; + if(padWidth%4) padWidth += (4-padWidth%4); + if(padHeight%4) padHeight += (4-padHeight%4); + + int len = (padWidth * padHeight) << 2; + if(len%32) len += (32-len%32); + + if(dstPtr) + dst = dstPtr; // use existing allocation + else + dst = memalign (32, len); + + if(!dst) + return NULL; + + for (y = 0; y < padHeight; y++) + { + for (x = 0; x < padWidth; x++) + { + offset = coordsRGBA8(x, y, padWidth); + + if(y >= newHeight || x >= newWidth) + { + dst[offset] = 0; + dst[offset+1] = 255; + dst[offset+32] = 255; + dst[offset+33] = 255; + } + else + { + if(xRatio > 0) + { + x2 = ((x*xRatio)>>16); + y2 = ((y*yRatio)>>16); + } + + if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA || + ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) + { + if(xRatio > 0) + pixel = &(ctx->row_pointers[y2][x2*4]); + else + pixel = &(ctx->row_pointers[y][x*4]); + + dst[offset] = pixel[3]; // Alpha + dst[offset+1] = pixel[0]; // Red + dst[offset+32] = pixel[1]; // Green + dst[offset+33] = pixel[2]; // Blue + } + else + { + if(xRatio > 0) + pixel = &(ctx->row_pointers[y2][x2*3]); + else + pixel = &(ctx->row_pointers[y][x*3]); + + dst[offset] = default_alpha; // Alpha + dst[offset+1] = pixel[0]; // Red + dst[offset+32] = pixel[1]; // Green + dst[offset+33] = pixel[2]; // Blue + } + } + } + } + + // Free resources + free (ctx->img_data); + free (ctx->row_pointers); + + *dstWidth = padWidth; + *dstHeight = padHeight; + DCFlushRange(dst, len); + 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 ctx = NULL; + + if (!buffer) + return NULL; + + ctx = malloc (sizeof (struct _IMGCTX)); + if (!ctx) + return NULL; + + ctx->buffer = (void *) buffer; + ctx->source = PNGU_SOURCE_BUFFER; + ctx->cursor = 0; + ctx->filename = NULL; + ctx->propRead = 0; + ctx->infoRead = 0; + + return ctx; +} + +IMGCTX PNGU_SelectImageFromDevice (const char *filename) +{ + IMGCTX ctx = NULL; + + if (!filename) + return NULL; + + ctx = malloc (sizeof (struct _IMGCTX)); + if (!ctx) + return NULL; + + ctx->buffer = NULL; + ctx->source = PNGU_SOURCE_DEVICE; + ctx->cursor = 0; + + ctx->filename = malloc (strlen (filename) + 1); + if (!ctx->filename) + { + free (ctx); + return NULL; + } + strcpy(ctx->filename, filename); + + ctx->propRead = 0; + ctx->infoRead = 0; + + return ctx; +} + +void PNGU_ReleaseImageContext (IMGCTX ctx) +{ + if (!ctx) + return; + + if (ctx->filename) + free (ctx->filename); + + if ((ctx->propRead) && (ctx->prop.trans)) + free (ctx->prop.trans); + + pngu_free_info (ctx); + free (ctx); +} + +int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop) +{ + int res; + + if (!ctx->propRead) + { + res = pngu_info (ctx); + if (res != PNGU_OK) + return res; + } + + *imgprop = ctx->prop; + return PNGU_OK; +} + +u8 * DecodePNG(const u8 *src, int * width, int * height, u8 *dstPtr, int maxwidth, int maxheight) +{ + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromBuffer(src); + u8 *dst = NULL; + + if(!ctx) + return NULL; + + if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK) + dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, width, height, dstPtr, maxwidth, maxheight); + + PNGU_ReleaseImageContext (ctx); + return dst; +} + +int PNGU_EncodeFromRGB (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride) +{ + png_uint_32 rowbytes; + u32 y; + + // Erase from the context any readed info + pngu_free_info (ctx); + ctx->propRead = 0; + + // Check if the user has selected a file to write the image + if (ctx->source == PNGU_SOURCE_BUFFER); + + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Open file + if (!(ctx->fd = fopen (ctx->filename, "wb"))) + return PNGU_CANT_OPEN_FILE; + } + + else + return PNGU_NO_FILE_SELECTED; + + // Allocation of libpng structs + ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!(ctx->png_ptr)) + { + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + ctx->info_ptr = png_create_info_struct (ctx->png_ptr); + if (!(ctx->info_ptr)) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + if (ctx->source == PNGU_SOURCE_BUFFER) + { + // Installation of our custom data writer function + ctx->cursor = 0; + png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer); + } + else if (ctx->source == PNGU_SOURCE_DEVICE) + { + // Default data writer uses function fwrite, so it needs to use our FILE* + png_init_io (ctx->png_ptr, ctx->fd); + } + + // Setup output file properties + png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // Allocate memory to store the image in RGB format + rowbytes = width * 3; + if (rowbytes % 4) + rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary + + ctx->img_data = malloc(rowbytes * height); + + if (!ctx->img_data) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + memset(ctx->img_data, 0, rowbytes * height); + ctx->row_pointers = malloc (sizeof (png_bytep) * height); + + if (!ctx->row_pointers) + { + png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + return PNGU_LIB_ERROR; + } + + memset(ctx->row_pointers, 0, sizeof (png_bytep) * height); + + for (y = 0; y < height; ++y) + { + ctx->row_pointers[y] = buffer + (y * rowbytes); + } + + // Tell libpng where is our image data + png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers); + + // Write file header and image data + png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + // Tell libpng we have no more data to write + png_write_end (ctx->png_ptr, (png_infop) NULL); + + // Free resources + free (ctx->img_data); + free (ctx->row_pointers); + png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr)); + if (ctx->source == PNGU_SOURCE_DEVICE) + fclose (ctx->fd); + + // Success + return ctx->cursor; +} + +int PNGU_EncodeFromGXTexture (IMGCTX ctx, u32 width, u32 height, void *buffer, u32 stride) +{ + int res; + u32 x, y, tmpy1, tmpy2, tmpyWid, tmpxy; + + unsigned char * ptr = (unsigned char*)buffer; + unsigned char * tmpbuffer = malloc(width*height*3); + + if(!tmpbuffer) + return PNGU_LIB_ERROR; + + memset(tmpbuffer, 0, width*height*3); + png_uint_32 offset; + + for(y=0; y < height; y++) + { + tmpy1 = y * 640*3; + tmpy2 = y%4 << 2; + tmpyWid = (((y >> 2)<<4)*width); + + for(x=0; x < width; x++) + { + offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1); + tmpxy = x * 3 + tmpy1; + + tmpbuffer[tmpxy ] = ptr[offset+1]; // R + tmpbuffer[tmpxy+1] = ptr[offset+32]; // G + tmpbuffer[tmpxy+2] = ptr[offset+33]; // B + } + } + + res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride); + free(tmpbuffer); + return res; +} + +int PNGU_EncodeFromEFB (IMGCTX ctx, u32 width, u32 height) +{ + int res; + u32 x, y, tmpy1, tmpxy; + GXColor color; + + 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; + GX_PeekARGB(x, y, &color); + tmpbuffer[tmpxy ] = color.r; // R + tmpbuffer[tmpxy+1] = color.g; // G + tmpbuffer[tmpxy+2] = color.b; // B + } + } + + res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, 0); + free(tmpbuffer); + 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; +} diff --git a/source/utils/pngu.h b/source/utils/pngu.h index fa89650..1ac91a7 100644 --- a/source/utils/pngu.h +++ b/source/utils/pngu.h @@ -3,7 +3,7 @@ * PNGU * * 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" { #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 { 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_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 } #endif diff --git a/source/vba/System.h b/source/vba/System.h index 733e3d0..87bf6e4 100644 --- a/source/vba/System.h +++ b/source/vba/System.h @@ -1,58 +1,57 @@ #ifndef SYSTEM_H #define SYSTEM_H - #include "common/Types.h" - #include class SoundDriver; struct EmulatedSystem { - // main emulation function - void (*emuMain)(int); - // reset emulator - void (*emuReset)(); - // clean up memory - void (*emuCleanUp)(); - // load battery file - bool (*emuReadBattery)(const char *); - // write battery file - bool (*emuWriteBattery)(const char *); - // load state - bool (*emuReadState)(const char *); - // save state - bool (*emuWriteState)(const char *); - // load memory state (rewind) - bool (*emuReadMemState)(char *, int); - // write memory state (rewind) - bool (*emuWriteMemState)(char *, int); - // write PNG file - bool (*emuWritePNG)(const char *); - // write BMP file - bool (*emuWriteBMP)(const char *); - // emulator update CPSR (ARM only) - void (*emuUpdateCPSR)(); - // emulator has debugger - bool emuHasDebugger; - // clock ticks to emulate - int emuCount; + // main emulation function + void (*emuMain)(int); + // reset emulator + void (*emuReset)(); + // clean up memory + void (*emuCleanUp)(); + // load battery file + bool (*emuReadBattery)(const char *); + // write battery file + bool (*emuWriteBattery)(const char *); +#ifdef __LIBRETRO__ + // load state + bool (*emuReadState)(const u8*, unsigned); + // load state + unsigned (*emuWriteState)(u8*, unsigned); +#else + // load state + bool (*emuReadState)(const char *); + // save state + bool (*emuWriteState)(const char *); +#endif + // load memory state (rewind) + bool (*emuReadMemState)(char *, int); + // write memory state (rewind) + bool (*emuWriteMemState)(char *, int); + // write PNG file + bool (*emuWritePNG)(const char *); + // write BMP file + bool (*emuWriteBMP)(const char *); + // emulator update CPSR (ARM only) + void (*emuUpdateCPSR)(); + // emulator has debugger + bool emuHasDebugger; + // clock ticks to emulate + int emuCount; }; extern void log(const char *,...); - 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 systemDrawScreen(); // updates the joystick data extern bool systemReadJoypads(); // return information about the given joystick, -1 for default joystick extern u32 systemReadJoypad(int); -// this function should turn on or off rumble on the gamepad -extern void systemCartridgeRumble(bool); -extern void systemPossibleCartridgeRumble(bool); -// This should be called once per frame -extern void updateRumbleFrame(); extern u32 systemGetClock(); extern void systemMessage(int, const char *, ...); extern void systemSetTitle(const char *); @@ -61,26 +60,26 @@ extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length); extern void systemOnSoundShutdown(); extern void systemScreenMessage(const char *); extern void systemUpdateMotionSensor(); -extern int systemGetSensorX(); -extern int systemGetSensorY(); +extern int systemGetSensorX(); +extern int systemGetSensorY(); extern bool systemCanChangeSoundQuality(); extern void systemShowSpeed(int); extern void system10Frames(int); extern void systemFrame(); extern void systemGbBorderOn(); - extern void Sm60FPS_Init(); extern bool Sm60FPS_CanSkipFrame(); extern void Sm60FPS_Sleep(); extern void DbgMsg(const char *msg, ...); +#ifdef SDL +#define winlog log +#else extern void winlog(const char *,...); - +#endif extern void (*dbgOutput)(const char *s, u32 addr); extern void (*dbgSignal)(int sig,int number); - extern u16 systemColorMap16[0x10000]; -//extern u32 systemColorMap32[0x10000]; -extern u32 *systemColorMap32; +extern u32 systemColorMap32[0x10000]; extern u16 systemGbPalette[24]; extern int systemRedShift; extern int systemGreenShift; @@ -91,8 +90,6 @@ extern int systemVerbose; extern int systemFrameSkip; extern int systemSaveUpdateCounter; extern int systemSpeed; - #define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_NOT_UPDATED 0 - -#endif // SYSTEM_H +#endif // SYSTEM_H diff --git a/source/vba/Util.cpp b/source/vba/Util.cpp index f139f8d..2f742ae 100644 --- a/source/vba/Util.cpp +++ b/source/vba/Util.cpp @@ -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 #include #include #include +#ifndef NO_PNG +extern "C" { +#include +} +#endif + #include "System.h" #include "NLS.h" #include "Util.h" @@ -29,12 +17,18 @@ #include "gba/Globals.h" #include "gba/RTC.h" #include "common/Port.h" -#include "../utils/unzip/unzip.h" + +#ifndef NO_FEX +#include "fex/fex.h" +#endif extern "C" { #include "common/memgzio.h" } +#include "gba/gbafilter.h" +#include "gb/gbGlobals.h" + #ifndef _MSC_VER #define _stricmp strcasecmp #endif // ! _MSC_VER @@ -45,13 +39,283 @@ extern int systemGreenShift; extern int systemBlueShift; extern u16 systemColorMap16[0x10000]; -//extern u32 systemColorMap32[0x10000]; -extern u32 *systemColorMap32; +extern u32 systemColorMap32[0x10000]; -static int (*utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL; -static int (*utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL; -static int (*utilGzCloseFunc)(gzFile) = NULL; -static z_off_t (*utilGzSeekFunc)(gzFile, z_off_t, int) = NULL; +static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL; +static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL; +static int (ZEXPORT *utilGzCloseFunc)(gzFile) = 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; @@ -95,34 +359,221 @@ bool utilIsGBImage(const char * file) return false; } -bool utilIsZipFile(const char *file) +bool utilIsGzipFile(const char *file) { - if(strlen(file) > 4) - { - char * p = strrchr(file,'.'); + if(strlen(file) > 3) { + const char * p = strrchr(file,'.'); - if(p != NULL) - { - if(_stricmp(p, ".zip") == 0) - return true; - } + if(p != NULL) { + if(_stricmp(p, ".gz") == 0) + return true; + if(_stricmp(p, ".z") == 0) + return true; } + } return false; } -void utilPutDword(u8 *p, u32 value) +// strip .gz or .z off end +void utilStripDoubleExtension(const char *file, char *buffer) { - *p++ = value & 255; - *p++ = (value >> 8) & 255; - *p++ = (value >> 16) & 255; - *p = (value >> 24) & 255; + if(buffer != file) // allows conversion in place + strcpy(buffer, file); + + 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; - *p = (value >> 8) & 255; + fex_t* fe; + 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 +#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) @@ -163,7 +614,7 @@ void utilWriteData(gzFile gzFile, variable_desc *data) 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; utilGzCloseFunc = gzclose; utilGzSeekFunc = gzseek; @@ -176,6 +627,7 @@ gzFile utilMemGzOpen(char *memory, int available, const char *mode) utilGzWriteFunc = memgzwrite; utilGzReadFunc = memgzread; utilGzCloseFunc = memgzclose; + utilGzSeekFunc = memgzseek; return memgzopen(memory, available, mode); } @@ -204,3 +656,90 @@ long utilGzMemTell(gzFile 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; + } +} diff --git a/source/vba/Util.h b/source/vba/Util.h index 2fe31f5..6c5148a 100644 --- a/source/vba/Util.h +++ b/source/vba/Util.h @@ -1,56 +1,56 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// 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" - -enum IMAGE_TYPE { - IMAGE_UNKNOWN = -1, - IMAGE_GBA = 0, - IMAGE_GB = 1 -}; - -// save game - -typedef struct { - void *address; - int size; -} variable_desc; - -extern bool utilIsGBAImage(const char *); -extern bool utilIsGBImage(const char *); -extern bool utilIsZipFile(const char *); - -extern void utilPutDword(u8 *, u32); -extern void utilPutWord(u8 *, u16); -extern void utilWriteData(gzFile, variable_desc *); -extern void utilReadData(gzFile, variable_desc *); -extern void utilReadDataSkip(gzFile, variable_desc *); -extern int utilReadInt(gzFile); -extern void utilWriteInt(gzFile, int); -extern gzFile utilGzOpen(const char *file, const char *mode); -extern gzFile utilMemGzOpen(char *memory, int available, const char *mode); -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 +#ifndef UTIL_H +#define UTIL_H + +#include "System.h" + +enum IMAGE_TYPE { + IMAGE_UNKNOWN = -1, + IMAGE_GBA = 0, + IMAGE_GB = 1 +}; + +// save game +typedef struct { + void *address; + int size; +} 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 &); + +void utilPutDword(uint8_t *, uint32_t); +void utilPutWord(uint8_t *, uint16_t); +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 ); + + +#ifdef __LIBRETRO__ +void utilWriteIntMem(uint8_t *& data, int); +void utilWriteMem(uint8_t *& data, const void *in_data, unsigned size); +void utilWriteDataMem(uint8_t *& data, variable_desc *); + +int utilReadIntMem(const uint8_t *& data); +void utilReadMem(void *buf, const uint8_t *& data, unsigned size); +void utilReadDataMem(const uint8_t *& data, variable_desc *); +#endif + +#endif // UTIL_H diff --git a/source/vba/apu/Blip_Buffer.cpp b/source/vba/apu/Blip_Buffer.cpp index bebb412..5eacc06 100644 --- a/source/vba/apu/Blip_Buffer.cpp +++ b/source/vba/apu/Blip_Buffer.cpp @@ -29,7 +29,7 @@ int const silent_buf_size = 1; // size used for Silent_Blip_Buffer Blip_Buffer::Blip_Buffer() { - factor_ = LONG_MAX; + factor_ = (blip_ulong)LONG_MAX; buffer_ = 0; buffer_size_ = 0; sample_rate_ = 0; @@ -126,7 +126,7 @@ Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const { - double ratio = (double)(sample_rate_) / double(rate); + double ratio = (double) sample_rate_ / rate; blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 ); assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large return (blip_resampled_time_t) factor; @@ -226,17 +226,15 @@ static void gen_sinc( float* out, int count, double oversample, double treble, d treble = 5.0; double const maxh = 4096.0; - double const rolloff = pow( 10.0, 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 to_angle = PI / (2.0 * maxh * oversample); + double const to_angle = PI / 2 / maxh / oversample; for ( int i = 0; i < count; i++ ) { - double angle = double(((i - count)<<1) + 1) * to_angle; - double maxhAngle = maxh * angle; - double c = rolloff * cos( maxhAngle - angle ) - cos( maxhAngle ); - double cos_nc_angle = cos( maxhAngle * cutoff ); - double cos_nc1_angle = cos( maxhAngle * cutoff - angle ); - + double angle = ((i - count) * 2 + 1) * to_angle; + double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle ); + double cos_nc_angle = cos( maxh * cutoff * angle ); + double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle ); double cos_angle = cos( 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 // (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; if ( 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 int const size = impulses_size(); - - int blipRes2 = blip_res >> 1; - for ( int p = blip_res; p-- >= blipRes2; ) + for ( int p = blip_res; p-- >= blip_res / 2; ) { int p2 = blip_res - 2 - p; long error = kernel_unit; @@ -294,11 +290,9 @@ void Blip_Synth_::adjust_impulse() 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 = blipRes2 * (width - 1); + int const half_size = blip_res / 2 * (width - 1); eq.generate( &fimpulse [blip_res], half_size ); 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]; // starts at 0 - for ( i = 0; i < blip_res; ++i ) + for ( i = 0; i < blip_res; i++ ) fimpulse [i] = 0.0f; // find rescale factor double total = 0.0; - for ( i = 0; i < half_size; ++i ) + for ( i = 0; i < half_size; i++ ) total += fimpulse [blip_res + i]; //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB //double const base_unit = 37888.0; // allows treble to +5 dB double const base_unit = 32768.0; // necessary for blip_unscaled to work - double rescale = base_unit / (2 * total); + double rescale = base_unit / 2 / total; kernel_unit = (long) base_unit; // integrate, first difference, rescale, convert to int double sum = 0.0; double next = 0.0; int const size = this->impulses_size(); - for ( i = 0; i < size; ++i ) + for ( i = 0; i < size; i++ ) { impulses [i] = (short) (int) floor( (next - sum) * rescale + 0.5 ); sum += fimpulse [i]; @@ -361,7 +355,7 @@ void Blip_Synth_::volume_unit( double new_unit ) // if unit is really small, might need to attenuate kernel while ( factor < 2.0 ) { - ++shift; + shift++; factor *= 2.0; } @@ -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_READER_NEXT_IDX_( reader, bass, offset ); BLIP_CLAMP( s, s ); - out [offset << 1] = (blip_sample_t) s; + out [offset * 2] = (blip_sample_t) s; } while ( ++offset ); } diff --git a/source/vba/apu/Effects_Buffer.cpp b/source/vba/apu/Effects_Buffer.cpp index deff3f0..b65d860 100644 --- a/source/vba/apu/Effects_Buffer.cpp +++ b/source/vba/apu/Effects_Buffer.cpp @@ -505,7 +505,7 @@ void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count ) int bufs_remain = bufs_size; do { - if ( buf->non_silent() && ( buf->echo == (bool)echo_phase ) ) + if ( buf->non_silent() && ( buf->echo == !!echo_phase ) ) { stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos]; int const bass = BLIP_READER_BASS( *buf ); diff --git a/source/vba/apu/Gb_Oscs.h b/source/vba/apu/Gb_Oscs.h index 260bb06..ba8daa8 100644 --- a/source/vba/apu/Gb_Oscs.h +++ b/source/vba/apu/Gb_Oscs.h @@ -50,6 +50,7 @@ public: class Gb_Env : public Gb_Osc { public: + Gb_Env() : env_enabled(false), env_delay(0) {} int env_delay; int volume; bool env_enabled; diff --git a/source/vba/common/Patch.cpp b/source/vba/common/Patch.cpp index c8db3aa..613ec93 100644 --- a/source/vba/common/Patch.cpp +++ b/source/vba/common/Patch.cpp @@ -1,471 +1,445 @@ -// 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 #include #include #include -#include "../System.h" -#include "memfile.h" +#include "Patch.h" -/* -#ifdef __GNUC__ -typedef off64_t __off64_t; -#endif -*/ #ifndef _MSC_VER #define _stricmp strcasecmp #endif // ! _MSC_VER -#ifdef _MSC_VER -#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 c = memfgetc(f); - if (c == MEOF) - return -1; - res = c; - c = memfgetc(f); - if (c == MEOF) - return -1; - return c + (res << 8); +static int readInt2(MFILE *f) +{ + int res = 0; + int c = memfgetc(f); + if(c == MEOF) + return -1; + res = c; + c = memfgetc(f); + if(c == MEOF) + return -1; + return c + (res<<8); } -static int readInt3(MFILE *f) { - int res = 0; - int c = memfgetc(f); - if (c == MEOF) - return -1; - res = c; - c = memfgetc(f); - if (c == MEOF) - return -1; - res = c + (res << 8); - c = memfgetc(f); - if (c == MEOF) - return -1; - return c + (res << 8); +static int readInt3(MFILE *f) +{ + int res = 0; + int c = memfgetc(f); + if(c == MEOF) + return -1; + res = c; + c = memfgetc(f); + if(c == MEOF) + return -1; + res = c + (res<<8); + c = memfgetc(f); + if(c == MEOF) + return -1; + return c + (res<<8); } -static s64 readInt4(MFILE *f) { - s64 tmp, res = 0; - int c; +static s64 readInt4(MFILE *f) +{ + s64 tmp, res = 0; + int c; - for (int i = 0; i < 4; i++) { - c = memfgetc(f); - if (c == MEOF) - return -1; - tmp = c; - res = res + (tmp << (i * 8)); - } + for (int i = 0; i < 4; i++) { + c = memfgetc(f); + if (c == MEOF) + return -1; + tmp = c; + res = res + (tmp << (i*8)); + } - return res; + return res; } -static s64 readInt8(MFILE *f) { - s64 tmp, res = 0; - int c; +static s64 readInt8(MFILE *f) +{ + s64 tmp, res = 0; + int c; - for (int i = 0; i < 8; i++) { - c = memfgetc(f); - if (c == MEOF) - return -1; - tmp = c; - res = res + (tmp << (i * 8)); - } + for (int i = 0; i < 8; i++) { + c = memfgetc(f); + if (c == MEOF) + return -1; + tmp = c; + res = res + (tmp << (i*8)); + } - return res; + return res; } -static s64 readVarPtr(MFILE *f) { - s64 offset = 0, shift = 1; - for (;;) { - int c = memfgetc(f); - if (c == MEOF) - return 0; - offset += (c & 0x7F) * shift; - if (c & 0x80) - break; - shift <<= 7; - offset += shift; - } - return offset; +static s64 readVarPtr(MFILE *f) +{ + s64 offset = 0, shift = 1; + for (;;) { + int c = memfgetc(f); + if (c == MEOF) return 0; + offset += (c & 0x7F) * shift; + if (c & 0x80) break; + shift <<= 7; + offset += shift; + } + return offset; } #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif -static uLong computePatchCRC(MFILE *f, unsigned int size) { - Bytef buf[4096]; - long readed; +static uLong computePatchCRC(MFILE *f, unsigned int size) +{ + Bytef buf[4096]; + long readed; - uLong crc = crc32(0L, Z_NULL, 0); - do { - readed = memfread(buf, 1, MIN(size, sizeof(buf)), f); - crc = crc32(crc, buf, readed); - size -= readed; - } while (readed > 0); - - return crc; + uLong crc = crc32(0L, Z_NULL, 0); + do { + readed = memfread(buf, 1, MIN(size, sizeof(buf)), f); + crc = crc32(crc, buf, readed); + size -= readed; + } while (readed > 0); + return crc; } -bool patchApplyIPS(MFILE * f, u8 **r, int *s) { - // from the IPS spec at http://zerosoft.zophar.net/ips.htm +bool patchApplyIPS(MFILE *f, u8 **r, int *s) +{ + // from the IPS spec at http://zerosoft.zophar.net/ips.htm - bool result = false; + bool result = false; - u8 *rom = *r; - int size = *s; - if (memfgetc(f) == 'P' && memfgetc(f) == 'A' && memfgetc(f) == 'T' - && memfgetc(f) == 'C' && memfgetc(f) == 'H') { - int b; - int offset; - int len; + u8 *rom = *r; + int size = *s; + if(memfgetc(f) == 'P' && + memfgetc(f) == 'A' && + memfgetc(f) == 'T' && + memfgetc(f) == 'C' && + memfgetc(f) == 'H') { + int b; + int offset; + int len; - result = true; + result = true; - for (;;) { - // read offset - offset = readInt3(f); - // if offset == MEOF, end of patch - if (offset == 0x454f46 || offset == -1) - break; - // read length - len = readInt2(f); - if (!len) { - // len == 0, RLE block - len = readInt2(f); - // byte to fill - int c = memfgetc(f); - if (c == -1) - break; - b = (u8) c; - } else - b = -1; - // check if we need to reallocate our ROM - if ((offset + len) >= size) { + for(;;) { + // read offset + offset = readInt3(f); + // if offset == MEOF, end of patch + if(offset == 0x454f46 || offset == -1) + break; + // read length + len = readInt2(f); + if(!len) { + // len == 0, RLE block + len = readInt2(f); + // byte to fill + int c = memfgetc(f); + if(c == -1) + break; + b = (u8)c; + } else + b= -1; + // check if we need to reallocate our ROM + if((offset + len) >= size) { #ifdef GEKKO - size = offset + len; + size = offset + len; #else - size *= 2; - rom = (u8 *) realloc(rom, size); + size *= 2; + rom = (u8 *)realloc(rom, size); #endif - *r = rom; - *s = size; - } - if (b == -1) { - // normal block, just read the data - if (memfread(&rom[offset], 1, len, f) != (size_t) len) - break; - } else { - // fill the region with the given byte - while (len--) { - rom[offset++] = b; - } - } - } - } - return result; + *r = rom; + *s = size; + } + if(b == -1) { + // normal block, just read the data + if(memfread(&rom[offset], 1, len, f) != (size_t)len) + break; + } else { + // fill the region with the given byte + while(len--) { + rom[offset++] = b; + } + } + } + } + + 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); + long int patchSize = memftell(f); + if (patchSize < 20) { + return false; + } - memfseek(f, 0, MSEEK_END); - long int patchSize = memftell(f); - if (patchSize < 20) { - return false; - } + memfseek(f, 0, MSEEK_SET); + if(memfgetc(f) != 'U' || memfgetc(f) != 'P' || memfgetc(f) != 'S' || memfgetc(f) != '1') { + return false; + } - memfseek(f, 0, MSEEK_SET); + memfseek(f, -12, MSEEK_END); + srcCRC = readInt4(f); + dstCRC = readInt4(f); + patchCRC = readInt4(f); + if (srcCRC == -1 || dstCRC == -1 || patchCRC == -1) { + return false; + } - if (memfgetc(f) != 'U' || memfgetc(f) != 'P' || memfgetc(f) != 'S' - || memfgetc(f) != '1') { - return false; - } + memfseek(f, 0, MSEEK_SET); + u32 crc = computePatchCRC(f, patchSize-4); - memfseek(f, -12, MSEEK_END); - srcCRC = readInt4(f); - dstCRC = readInt4(f); - patchCRC = readInt4(f); - if (srcCRC == -1 || dstCRC == -1 || patchCRC == -1) { - return false; - } + if (crc != patchCRC) { + return false; + } - memfseek(f, 0, MSEEK_SET); - u32 crc = computePatchCRC(f, patchSize - 4); + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, *rom, *size); - if (crc != patchCRC) { - return false; - } + memfseek(f, 4, MSEEK_SET); + s64 dataSize; + s64 srcSize = readVarPtr(f); + s64 dstSize = readVarPtr(f); - crc = crc32(0L, Z_NULL, 0); - crc = crc32(crc, *rom, *size); + if (crc == srcCRC) { + if (srcSize != *size) { + return false; + } + dataSize = dstSize; + } else if (crc == dstCRC) { + if (dstSize != *size) { + return false; + } + dataSize = srcSize; + } else { + return false; + } + if (dataSize > *size) { + *rom = (u8*)realloc(*rom, dataSize); + memset(*rom + *size, 0, dataSize - *size); + *size = dataSize; + } - memfseek(f, 4, MSEEK_SET); - s64 dataSize; - s64 srcSize = readVarPtr(f); - s64 dstSize = readVarPtr(f); + s64 relative = 0; + u8 *mem; + while(memftell(f) < patchSize - 12) { + relative += readVarPtr(f); + if (relative > dataSize) continue; + mem = *rom + relative; + for(s64 i = relative; i < dataSize; i++) { + int x = memfgetc(f); + relative++; + if (!x) break; + if (i < dataSize) { + *mem++ ^= x; + } + } + } - if (crc == srcCRC) { - dataSize = srcSize; - } else if (crc == dstCRC) { - dataSize = dstSize; - } else { - return false; - } - if (dataSize != *size) { - return false; - } - - s64 relative = 0; - u8 *mem; - while (memftell(f) < patchSize - 12) { - relative += readVarPtr(f); - if (relative > dataSize) - continue; - mem = *rom + relative; - for (s64 i = relative; i < dataSize; i++) { - int x = memfgetc(f); - relative++; - if (!x) - break; - if (i < dataSize) { - *mem++ ^= x; - } - } - } - return true; + return true; } -static int ppfVersion(MFILE *f) { - memfseek(f, 0, MSEEK_SET); - if (memfgetc(f) != 'P' || memfgetc(f) != 'P' || memfgetc(f) != 'F') - return 0; - switch (memfgetc(f)) { - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - default: - return 0; - } +static int ppfVersion(MFILE *f) +{ + memfseek(f, 0, MSEEK_SET); + 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; + } } -int ppfFileIdLen(MFILE *f, int version) { - if (version == 2) { - memfseek(f, -8, MSEEK_END); - } else { - memfseek(f, -6, MSEEK_END); - } +static int ppfFileIdLen(MFILE *f, int version) +{ + if (version == 2) { + memfseek(f, -8, MSEEK_END); + } else { + memfseek(f, -6, MSEEK_END); + } - if (memfgetc(f) != '.' || memfgetc(f) != 'D' || memfgetc(f) != 'I' - || memfgetc(f) != 'Z') - return 0; + if (memfgetc(f) != '.' || memfgetc(f) != 'D' || memfgetc(f) != 'I' || memfgetc(f) != 'Z') + 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) { - memfseek(f, 0, MSEEK_END); - int count = memftell(f); - if (count < 56) - return false; - count -= 56; +static bool patchApplyPPF1(MFILE *f, u8 **rom, int *size) +{ + memfseek(f, 0, MSEEK_END); + int count = memftell(f); + if (count < 56) + return false; + count -= 56; - memfseek(f, 56, MSEEK_SET); + memfseek(f, 56, MSEEK_SET); - u8 *mem = *rom; + u8 *mem = *rom; - while (count > 0) { - int offset = readInt4(f); - if (offset == -1) - break; - int len = memfgetc(f); - if (len == MEOF) - break; - if (offset + len > *size) - break; - if (memfread(&mem[offset], 1, len, f) != (size_t) len) - break; - count -= 4 + 1 + len; - } + while (count > 0) { + int offset = readInt4(f); + if (offset == -1) + break; + int len = memfgetc(f); + if (len == MEOF) + break; + if (offset+len > *size) + break; + if (memfread(&mem[offset], 1, len, f) != (size_t)len) + break; + count -= 4 + 1 + len; + } - return (count == 0); + return (count == 0); } -static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) { - memfseek(f, 0, MSEEK_END); - int count = memftell(f); - if (count < 56 + 4 + 1024) - return false; - count -= 56 + 4 + 1024; +static bool patchApplyPPF2(MFILE *f, u8 **rom, int *size) +{ + memfseek(f, 0, MSEEK_END); + int count = memftell(f); + if (count < 56+4+1024) + return false; + count -= 56+4+1024; - memfseek(f, 56, MSEEK_SET); + memfseek(f, 56, MSEEK_SET); - int datalen = readInt4(f); - if (datalen != *size) - return false; + int datalen = readInt4(f); + if (datalen != *size) + return false; - u8 *mem = *rom; + u8 *mem = *rom; - u8 block[1024]; - memfread(&block, 1, 1024, f); - if (memcmp(&mem[0x9320], &block, 1024) != 0) - return false; + u8 block[1024]; + memfread(&block, 1, 1024, f); + if (memcmp(&mem[0x9320], &block, 1024) != 0) + return false; - int idlen = ppfFileIdLen(f, 2); - if (idlen > 0) - count -= 16 + 16 + idlen; + int idlen = ppfFileIdLen(f, 2); + if (idlen > 0) + count -= 16 + 16 + idlen; - memfseek(f, 56 + 4 + 1024, MSEEK_SET); + memfseek(f, 56+4+1024, MSEEK_SET); - while (count > 0) { - int offset = readInt4(f); - if (offset == -1) - break; - int len = memfgetc(f); - if (len == MEOF) - break; - if (offset + len > *size) - break; - if (memfread(&mem[offset], 1, len, f) != (size_t) len) - break; - count -= 4 + 1 + len; - } + while (count > 0) { + int offset = readInt4(f); + if (offset == -1) + break; + int len = memfgetc(f); + if (len == MEOF) + break; + if (offset+len > *size) + break; + if (memfread(&mem[offset], 1, len, f) != (size_t)len) + break; + count -= 4 + 1 + len; + } - return (count == 0); + return (count == 0); } -static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size) { - memfseek(f, 0, MSEEK_END); - int count = memftell(f); - if (count < 56 + 4 + 1024) - return false; - count -= 56 + 4; +static bool patchApplyPPF3(MFILE *f, u8 **rom, int *size) +{ + memfseek(f, 0, MSEEK_END); + int count = memftell(f); + if (count < 56+4+1024) + return false; + count -= 56+4; - memfseek(f, 56, MSEEK_SET); + memfseek(f, 56, MSEEK_SET); - int imagetype = memfgetc(f); - int blockcheck = memfgetc(f); - int undo = memfgetc(f); - memfgetc(f); + int imagetype = memfgetc(f); + int blockcheck = memfgetc(f); + int undo = memfgetc(f); + memfgetc(f); - u8 *mem = *rom; + u8 *mem = *rom; - if (blockcheck) { - u8 block[1024]; - memfread(&block, 1, 1024, f); - if (memcmp(&mem[(imagetype == 0) ? 0x9320 : 0x80A0], &block, 1024) != 0) - return false; - count -= 1024; - } + if (blockcheck) { + u8 block[1024]; + memfread(&block, 1, 1024, f); + if (memcmp(&mem[(imagetype == 0) ? 0x9320 : 0x80A0], &block, 1024) != 0) + return false; + count -= 1024; + } - int idlen = ppfFileIdLen(f, 2); - if (idlen > 0) - count -= 16 + 16 + idlen; + int idlen = ppfFileIdLen(f, 2); + if (idlen > 0) + 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) { - s64 offset = readInt8(f); - if (offset == -1) - break; - int len = memfgetc(f); - if (len == MEOF) - break; - if (offset + len > *size) - break; - if (memfread(&mem[offset], 1, len, f) != (size_t) len) - break; - if (undo) - memfseek(f, len, MSEEK_CUR); - count -= 8 + 1 + len; - if (undo) - count -= len; - } + while (count > 0) { + s64 offset = readInt8(f); + if (offset == -1) + break; + int len = memfgetc(f); + if (len == MEOF) + break; + if (offset+len > *size) + break; + if (memfread(&mem[offset], 1, len, f) != (size_t)len) + break; + if (undo) memfseek(f, len, MSEEK_CUR); + count -= 8 + 1 + len; + if (undo) count -= len; + } - return (count == 0); + return (count == 0); } bool patchApplyPPF(MFILE *f, u8 **rom, int *size) { - bool res = false; + bool res = false; - int version = ppfVersion(f); - switch (version) - { - case 1: res = patchApplyPPF1(f, rom, size); break; - case 2: res = patchApplyPPF2(f, rom, size); break; - case 3: res = patchApplyPPF3(f, rom, size); break; - } + int version = ppfVersion(f); + switch (version) { + case 1: res = patchApplyPPF1(f, rom, size); break; + case 2: res = patchApplyPPF2(f, rom, size); break; + case 3: res = patchApplyPPF3(f, rom, size); break; + } - return res; + return res; } bool applyPatch(const char *patchname, u8 **rom, int *size) { - bool result = false; + bool result = false; - if (strlen(patchname) < 5) - return false; - const char * p = strrchr(patchname, '.'); - if (p == NULL) - return false; + if (strlen(patchname) < 5) + return false; + const char * p = strrchr(patchname, '.'); + if (p == NULL) + return false; - FILE *f = fopen(patchname, "rb"); - if (!f) - return false; + FILE *f = fopen(patchname, "rb"); + if (!f) + return false; - // read in file - fseek(f, 0, SEEK_END); // go to end of file - int filesize = ftell(f); // get filesize - fseek(f, 0, SEEK_SET); // go to start of file - char * pbuffer = (char *) malloc(filesize); - fread (pbuffer, 1, filesize, f); - fclose(f); + // read in file + fseek(f, 0, SEEK_END); // go to end of file + int filesize = ftell(f); // get filesize + fseek(f, 0, SEEK_SET); // go to start of file + char * pbuffer = (char *) malloc(filesize); + fread (pbuffer, 1, filesize, f); + fclose(f); - MFILE * mf = memfopen(pbuffer, filesize); // create memory file + MFILE * mf = memfopen(pbuffer, filesize); // create memory file - if (_stricmp(p, ".ips") == 0) - result = patchApplyIPS(mf, rom, size); - else if (_stricmp(p, ".ups") == 0) - result = patchApplyUPS(mf, rom, size); - else if (_stricmp(p, ".ppf") == 0) - result = patchApplyPPF(mf, rom, size); + if (_stricmp(p, ".ips") == 0) + result = patchApplyIPS(mf, rom, size); + else if (_stricmp(p, ".ups") == 0) + result = patchApplyUPS(mf, rom, size); + else if (_stricmp(p, ".ppf") == 0) + result = patchApplyPPF(mf, rom, size); - memfclose(mf); // close memory file - free(pbuffer); // free buffer + memfclose(mf); // close memory file + free(pbuffer); // free buffer - return result; + return result; } diff --git a/source/vba/common/Patch.h b/source/vba/common/Patch.h index fa7a0fe..7c86aaf 100644 --- a/source/vba/common/Patch.h +++ b/source/vba/common/Patch.h @@ -1,31 +1,12 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// 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 +#ifndef PATCH_H +#define PATCH_H #include "memfile.h" -#include "System.h" +#include "Types.h" bool applyPatch(const char *patchname, u8 **rom, int *size); bool patchApplyIPS(MFILE * f, u8 **r, int *s); bool patchApplyUPS(MFILE * f, u8 **rom, int *size); bool patchApplyPPF(MFILE *f, u8 **rom, int *size); -#endif +#endif // PATCH_H diff --git a/source/vba/common/Port.h b/source/vba/common/Port.h index db76d55..5f6947a 100644 --- a/source/vba/common/Port.h +++ b/source/vba/common/Port.h @@ -1,24 +1,17 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +#ifndef PORT_H +#define PORT_H -// 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. +#ifdef __CELLOS_LV2__ +/* PlayStation3 */ +#include +#endif -#ifndef VBA_PORT_H -#define VBA_PORT_H +#ifdef _XBOX360 +/* XBox 360 */ +#include +#endif + +#include "Types.h" // swaps a 16-bit value static inline u16 swap16(u16 v) @@ -72,4 +65,4 @@ static inline u32 swap32(u32 v) *((u32 *)x) = (v) #endif -#endif +#endif // PORT_H diff --git a/source/vba/common/SoundDriver.h b/source/vba/common/SoundDriver.h index 0b6ca7e..96672a5 100644 --- a/source/vba/common/SoundDriver.h +++ b/source/vba/common/SoundDriver.h @@ -13,7 +13,7 @@ // // 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. +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef __VBA_SOUND_DRIVER_H__ #define __VBA_SOUND_DRIVER_H__ diff --git a/source/vba/common/Types.h b/source/vba/common/Types.h index 6133849..3b3fe22 100644 --- a/source/vba/common/Types.h +++ b/source/vba/common/Types.h @@ -13,7 +13,7 @@ // // 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. +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef __VBA_TYPES_H__ #define __VBA_TYPES_H__ diff --git a/source/vba/common/memgzio.c b/source/vba/common/memgzio.c index cb38cb8..b526b1e 100644 --- a/source/vba/common/memgzio.c +++ b/source/vba/common/memgzio.c @@ -9,7 +9,7 @@ * 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 #include @@ -697,3 +697,23 @@ long ZEXPORT memtell(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); +} diff --git a/source/vba/common/memgzio.h b/source/vba/common/memgzio.h index e1f69b0..ab3be55 100644 --- a/source/vba/common/memgzio.h +++ b/source/vba/common/memgzio.h @@ -1,23 +1,24 @@ -#ifndef MEMGZIO_H -#define MEMGZIO_H - -/* gzio.c -- IO on .gz files - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Compile this file with -DNO_DEFLATE to avoid the compression code. - */ - -/* memgzio.c - IO on .gz files in memory - * Adapted from original gzio.c from zlib library by Forgotten - */ - -#include - -gzFile ZEXPORT memgzopen(char *memory, int available, const char *mode); -int ZEXPORT memgzread(gzFile file, voidp buf, unsigned len); -int ZEXPORT memgzwrite(gzFile file, const voidp buf, unsigned len); -int ZEXPORT memgzclose(gzFile file); -long ZEXPORT memtell(gzFile file); - -#endif // MEMGZIO_H +#ifndef MEMGZIO_H +#define MEMGZIO_H + +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. + */ + +/* memgzio.c - IO on .gz files in memory + * Adapted from original gzio.c from zlib library by Forgotten + */ + +#include + +gzFile ZEXPORT memgzopen(char *memory, int available, const char *mode); +int ZEXPORT memgzread(gzFile file, voidp buf, unsigned len); +int ZEXPORT memgzwrite(gzFile file, const voidp buf, unsigned len); +int ZEXPORT memgzclose(gzFile file); +long ZEXPORT memtell(gzFile file); +z_off_t ZEXPORT memgzseek(gzFile file, z_off_t off, int whence); + +#endif // MEMGZIO_H diff --git a/source/vba/gb/GB.cpp b/source/vba/gb/GB.cpp index cc43c32..01bea43 100644 --- a/source/vba/gb/GB.cpp +++ b/source/vba/gb/GB.cpp @@ -1,3 +1,4 @@ +//#include "../win32/stdafx.h" // would fix LNK2005 linker errors for MSVC #include #include #include @@ -24,7 +25,6 @@ void gbPaletteReset(); extern u8 *pix; extern bool speedup; - bool gbUpdateSizes(); bool inBios = false; @@ -283,260 +283,260 @@ int gbCyclesCB[] = { u16 DAATable[] = { 0x0080,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0800,0x0900,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520, + 0x0800,0x0900,0x1000,0x1100,0x1200,0x1300,0x1400,0x1500, 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1800,0x1900,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520, + 0x1800,0x1900,0x2000,0x2100,0x2200,0x2300,0x2400,0x2500, 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700, - 0x2800,0x2900,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520, + 0x2800,0x2900,0x3000,0x3100,0x3200,0x3300,0x3400,0x3500, 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x3600,0x3700, - 0x3800,0x3900,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520, + 0x3800,0x3900,0x4000,0x4100,0x4200,0x4300,0x4400,0x4500, 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4800,0x4900,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520, + 0x4800,0x4900,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500, 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5800,0x5900,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520, + 0x5800,0x5900,0x6000,0x6100,0x6200,0x6300,0x6400,0x6500, 0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700, - 0x6800,0x6900,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520, + 0x6800,0x6900,0x7000,0x7100,0x7200,0x7300,0x7400,0x7500, 0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x7600,0x7700, - 0x7800,0x7900,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520, + 0x7800,0x7900,0x8000,0x8100,0x8200,0x8300,0x8400,0x8500, 0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x8600,0x8700, - 0x8800,0x8900,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520, + 0x8800,0x8900,0x9000,0x9100,0x9200,0x9300,0x9400,0x9500, 0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x9600,0x9700, - 0x9800,0x9900,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, + 0x9800,0x9900,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510, 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710, - 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, + 0x0810,0x0910,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510, 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, + 0x1810,0x1910,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510, 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710, - 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, + 0x2810,0x2910,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510, 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710, - 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, + 0x3810,0x3910,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510, 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710, - 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, + 0x4810,0x4910,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510, 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, + 0x5810,0x5910,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510, 0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,0x6610,0x6710, - 0x6810,0x6910,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530, + 0x6810,0x6910,0x7010,0x7110,0x7210,0x7310,0x7410,0x7510, 0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,0x7610,0x7710, - 0x7810,0x7910,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530, + 0x7810,0x7910,0x8010,0x8110,0x8210,0x8310,0x8410,0x8510, 0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,0x8610,0x8710, - 0x8810,0x8910,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530, + 0x8810,0x8910,0x9010,0x9110,0x9210,0x9310,0x9410,0x9510, 0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,0x9610,0x9710, - 0x9810,0x9910,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530, + 0x9810,0x9910,0xA010,0xA110,0xA210,0xA310,0xA410,0xA510, 0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,0xA610,0xA710, - 0xA810,0xA910,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530, + 0xA810,0xA910,0xB010,0xB110,0xB210,0xB310,0xB410,0xB510, 0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,0xB610,0xB710, - 0xB810,0xB910,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530, + 0xB810,0xB910,0xC010,0xC110,0xC210,0xC310,0xC410,0xC510, 0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,0xC610,0xC710, - 0xC810,0xC910,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530, + 0xC810,0xC910,0xD010,0xD110,0xD210,0xD310,0xD410,0xD510, 0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,0xD610,0xD710, - 0xD810,0xD910,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530, + 0xD810,0xD910,0xE010,0xE110,0xE210,0xE310,0xE410,0xE510, 0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,0xE610,0xE710, - 0xE810,0xE910,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530, + 0xE810,0xE910,0xF010,0xF110,0xF210,0xF310,0xF410,0xF510, 0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,0xF610,0xF710, - 0xF810,0xF910,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, + 0xF810,0xF910,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510, 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710, - 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, + 0x0810,0x0910,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510, 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, + 0x1810,0x1910,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510, 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710, - 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, + 0x2810,0x2910,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510, 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710, - 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, + 0x3810,0x3910,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510, 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710, - 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, + 0x4810,0x4910,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510, 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, + 0x5810,0x5910,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510, 0x0600,0x0700,0x0800,0x0900,0x0A00,0x0B00,0x0C00,0x0D00, - 0x0E00,0x0F00,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520, + 0x0E00,0x0F00,0x1000,0x1100,0x1200,0x1300,0x1400,0x1500, 0x1600,0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00, - 0x1E00,0x1F00,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520, + 0x1E00,0x1F00,0x2000,0x2100,0x2200,0x2300,0x2400,0x2500, 0x2600,0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2C00,0x2D00, - 0x2E00,0x2F00,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520, + 0x2E00,0x2F00,0x3000,0x3100,0x3200,0x3300,0x3400,0x3500, 0x3600,0x3700,0x3800,0x3900,0x3A00,0x3B00,0x3C00,0x3D00, - 0x3E00,0x3F00,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520, + 0x3E00,0x3F00,0x4000,0x4100,0x4200,0x4300,0x4400,0x4500, 0x4600,0x4700,0x4800,0x4900,0x4A00,0x4B00,0x4C00,0x4D00, - 0x4E00,0x4F00,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520, + 0x4E00,0x4F00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500, 0x5600,0x5700,0x5800,0x5900,0x5A00,0x5B00,0x5C00,0x5D00, - 0x5E00,0x5F00,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520, + 0x5E00,0x5F00,0x6000,0x6100,0x6200,0x6300,0x6400,0x6500, 0x6600,0x6700,0x6800,0x6900,0x6A00,0x6B00,0x6C00,0x6D00, - 0x6E00,0x6F00,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520, + 0x6E00,0x6F00,0x7000,0x7100,0x7200,0x7300,0x7400,0x7500, 0x7600,0x7700,0x7800,0x7900,0x7A00,0x7B00,0x7C00,0x7D00, - 0x7E00,0x7F00,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520, + 0x7E00,0x7F00,0x8000,0x8100,0x8200,0x8300,0x8400,0x8500, 0x8600,0x8700,0x8800,0x8900,0x8A00,0x8B00,0x8C00,0x8D00, - 0x8E00,0x8F00,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520, + 0x8E00,0x8F00,0x9000,0x9100,0x9200,0x9300,0x9400,0x9500, 0x9600,0x9700,0x9800,0x9900,0x9A00,0x9B00,0x9C00,0x9D00, - 0x9E00,0x9F00,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, + 0x9E00,0x9F00,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510, 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10, - 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, + 0x0E10,0x0F10,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510, 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10, - 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, + 0x1E10,0x1F10,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510, 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10, - 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, + 0x2E10,0x2F10,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510, 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10, - 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, + 0x3E10,0x3F10,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510, 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10, - 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, + 0x4E10,0x4F10,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510, 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10, - 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, + 0x5E10,0x5F10,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510, 0x6610,0x6710,0x6810,0x6910,0x6A10,0x6B10,0x6C10,0x6D10, - 0x6E10,0x6F10,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530, + 0x6E10,0x6F10,0x7010,0x7110,0x7210,0x7310,0x7410,0x7510, 0x7610,0x7710,0x7810,0x7910,0x7A10,0x7B10,0x7C10,0x7D10, - 0x7E10,0x7F10,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530, + 0x7E10,0x7F10,0x8010,0x8110,0x8210,0x8310,0x8410,0x8510, 0x8610,0x8710,0x8810,0x8910,0x8A10,0x8B10,0x8C10,0x8D10, - 0x8E10,0x8F10,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530, + 0x8E10,0x8F10,0x9010,0x9110,0x9210,0x9310,0x9410,0x9510, 0x9610,0x9710,0x9810,0x9910,0x9A10,0x9B10,0x9C10,0x9D10, - 0x9E10,0x9F10,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530, + 0x9E10,0x9F10,0xA010,0xA110,0xA210,0xA310,0xA410,0xA510, 0xA610,0xA710,0xA810,0xA910,0xAA10,0xAB10,0xAC10,0xAD10, - 0xAE10,0xAF10,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530, + 0xAE10,0xAF10,0xB010,0xB110,0xB210,0xB310,0xB410,0xB510, 0xB610,0xB710,0xB810,0xB910,0xBA10,0xBB10,0xBC10,0xBD10, - 0xBE10,0xBF10,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530, + 0xBE10,0xBF10,0xC010,0xC110,0xC210,0xC310,0xC410,0xC510, 0xC610,0xC710,0xC810,0xC910,0xCA10,0xCB10,0xCC10,0xCD10, - 0xCE10,0xCF10,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530, + 0xCE10,0xCF10,0xD010,0xD110,0xD210,0xD310,0xD410,0xD510, 0xD610,0xD710,0xD810,0xD910,0xDA10,0xDB10,0xDC10,0xDD10, - 0xDE10,0xDF10,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530, + 0xDE10,0xDF10,0xE010,0xE110,0xE210,0xE310,0xE410,0xE510, 0xE610,0xE710,0xE810,0xE910,0xEA10,0xEB10,0xEC10,0xED10, - 0xEE10,0xEF10,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530, + 0xEE10,0xEF10,0xF010,0xF110,0xF210,0xF310,0xF410,0xF510, 0xF610,0xF710,0xF810,0xF910,0xFA10,0xFB10,0xFC10,0xFD10, - 0xFE10,0xFF10,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530, + 0xFE10,0xFF10,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510, 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10, - 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530, + 0x0E10,0x0F10,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510, 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10, - 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530, + 0x1E10,0x1F10,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510, 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10, - 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530, + 0x2E10,0x2F10,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510, 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10, - 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530, + 0x3E10,0x3F10,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510, 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10, - 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530, + 0x4E10,0x4F10,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510, 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10, - 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530, + 0x5E10,0x5F10,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510, 0x00C0,0x0140,0x0240,0x0340,0x0440,0x0540,0x0640,0x0740, - 0x0840,0x0940,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940, + 0x0840,0x0940,0x0A40,0x0B40,0x0C40,0x0D40,0x0E40,0x0F40, 0x1040,0x1140,0x1240,0x1340,0x1440,0x1540,0x1640,0x1740, - 0x1840,0x1940,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940, + 0x1840,0x1940,0x1A40,0x1B40,0x1C40,0x1D40,0x1E40,0x1F40, 0x2040,0x2140,0x2240,0x2340,0x2440,0x2540,0x2640,0x2740, - 0x2840,0x2940,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940, + 0x2840,0x2940,0x2A40,0x2B40,0x2C40,0x2D40,0x2E40,0x2F40, 0x3040,0x3140,0x3240,0x3340,0x3440,0x3540,0x3640,0x3740, - 0x3840,0x3940,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940, + 0x3840,0x3940,0x3A40,0x3B40,0x3C40,0x3D40,0x3E40,0x3F40, 0x4040,0x4140,0x4240,0x4340,0x4440,0x4540,0x4640,0x4740, - 0x4840,0x4940,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940, + 0x4840,0x4940,0x4A40,0x4B40,0x4C40,0x4D40,0x4E40,0x4F40, 0x5040,0x5140,0x5240,0x5340,0x5440,0x5540,0x5640,0x5740, - 0x5840,0x5940,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940, + 0x5840,0x5940,0x5A40,0x5B40,0x5C40,0x5D40,0x5E40,0x5F40, 0x6040,0x6140,0x6240,0x6340,0x6440,0x6540,0x6640,0x6740, - 0x6840,0x6940,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940, + 0x6840,0x6940,0x6A40,0x6B40,0x6C40,0x6D40,0x6E40,0x6F40, 0x7040,0x7140,0x7240,0x7340,0x7440,0x7540,0x7640,0x7740, - 0x7840,0x7940,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940, + 0x7840,0x7940,0x7A40,0x7B40,0x7C40,0x7D40,0x7E40,0x7F40, 0x8040,0x8140,0x8240,0x8340,0x8440,0x8540,0x8640,0x8740, - 0x8840,0x8940,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940, + 0x8840,0x8940,0x8A40,0x8B40,0x8C40,0x8D40,0x8E40,0x8F40, 0x9040,0x9140,0x9240,0x9340,0x9440,0x9540,0x9640,0x9740, - 0x9840,0x9940,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750, - 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750, - 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750, - 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750, - 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750, - 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750, - 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, + 0x9840,0x9940,0x9A40,0x9B40,0x9C40,0x9D40,0x9E40,0x9F40, + 0xA040,0xA140,0xA240,0xA340,0xA440,0xA540,0xA640,0xA740, + 0xA840,0xA940,0xAA40,0xAB40,0xAC40,0xAD40,0xAE40,0xAF40, + 0xB040,0xB140,0xB240,0xB340,0xB440,0xB540,0xB640,0xB740, + 0xB840,0xB940,0xBA40,0xBB40,0xBC40,0xBD40,0xBE40,0xBF40, + 0xC040,0xC140,0xC240,0xC340,0xC440,0xC540,0xC640,0xC740, + 0xC840,0xC940,0xCA40,0xCB40,0xCC40,0xCD40,0xCE40,0xCF40, + 0xD040,0xD140,0xD240,0xD340,0xD440,0xD540,0xD640,0xD740, + 0xD840,0xD940,0xDA40,0xDB40,0xDC40,0xDD40,0xDE40,0xDF40, + 0xE040,0xE140,0xE240,0xE340,0xE440,0xE540,0xE640,0xE740, + 0xE840,0xE940,0xEA40,0xEB40,0xEC40,0xED40,0xEE40,0xEF40, + 0xF040,0xF140,0xF240,0xF340,0xF440,0xF540,0xF640,0xF740, + 0xF840,0xF940,0xFA40,0xFB40,0xFC40,0xFD40,0xFE40,0xFF40, 0xA050,0xA150,0xA250,0xA350,0xA450,0xA550,0xA650,0xA750, - 0xA850,0xA950,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950, + 0xA850,0xA950,0xAA50,0xAB50,0xAC50,0xAD50,0xAE50,0xAF50, 0xB050,0xB150,0xB250,0xB350,0xB450,0xB550,0xB650,0xB750, - 0xB850,0xB950,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950, + 0xB850,0xB950,0xBA50,0xBB50,0xBC50,0xBD50,0xBE50,0xBF50, 0xC050,0xC150,0xC250,0xC350,0xC450,0xC550,0xC650,0xC750, - 0xC850,0xC950,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950, + 0xC850,0xC950,0xCA50,0xCB50,0xCC50,0xCD50,0xCE50,0xCF50, 0xD050,0xD150,0xD250,0xD350,0xD450,0xD550,0xD650,0xD750, - 0xD850,0xD950,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950, + 0xD850,0xD950,0xDA50,0xDB50,0xDC50,0xDD50,0xDE50,0xDF50, 0xE050,0xE150,0xE250,0xE350,0xE450,0xE550,0xE650,0xE750, - 0xE850,0xE950,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950, + 0xE850,0xE950,0xEA50,0xEB50,0xEC50,0xED50,0xEE50,0xEF50, 0xF050,0xF150,0xF250,0xF350,0xF450,0xF550,0xF650,0xF750, - 0xF850,0xF950,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950, + 0xF850,0xF950,0xFA50,0xFB50,0xFC50,0xFD50,0xFE50,0xFF50, 0x00D0,0x0150,0x0250,0x0350,0x0450,0x0550,0x0650,0x0750, - 0x0850,0x0950,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950, + 0x0850,0x0950,0x0A50,0x0B50,0x0C50,0x0D50,0x0E50,0x0F50, 0x1050,0x1150,0x1250,0x1350,0x1450,0x1550,0x1650,0x1750, - 0x1850,0x1950,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950, + 0x1850,0x1950,0x1A50,0x1B50,0x1C50,0x1D50,0x1E50,0x1F50, 0x2050,0x2150,0x2250,0x2350,0x2450,0x2550,0x2650,0x2750, - 0x2850,0x2950,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950, + 0x2850,0x2950,0x2A50,0x2B50,0x2C50,0x2D50,0x2E50,0x2F50, 0x3050,0x3150,0x3250,0x3350,0x3450,0x3550,0x3650,0x3750, - 0x3850,0x3950,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, + 0x3850,0x3950,0x3A50,0x3B50,0x3C50,0x3D50,0x3E50,0x3F50, 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750, - 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, + 0x4850,0x4950,0x4A50,0x4B50,0x4C50,0x4D50,0x4E50,0x4F50, 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750, - 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, + 0x5850,0x5950,0x5A50,0x5B50,0x5C50,0x5D50,0x5E50,0x5F50, 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750, - 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, + 0x6850,0x6950,0x6A50,0x6B50,0x6C50,0x6D50,0x6E50,0x6F50, 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750, - 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, + 0x7850,0x7950,0x7A50,0x7B50,0x7C50,0x7D50,0x7E50,0x7F50, 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750, - 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, + 0x8850,0x8950,0x8A50,0x8B50,0x8C50,0x8D50,0x8E50,0x8F50, 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750, - 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, - 0xFA60,0xFB60,0xFC60,0xFD60,0xFE60,0xFF60,0x00C0,0x0140, + 0x9850,0x9950,0x9A50,0x9B50,0x9C50,0x9D50,0x9E50,0x9F50, + 0xFA40,0xFB40,0xFC40,0xFD40,0xFE40,0xFF40,0x00C0,0x0140, 0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940, - 0x0A60,0x0B60,0x0C60,0x0D60,0x0E60,0x0F60,0x1040,0x1140, + 0x0A40,0x0B40,0x0C40,0x0D40,0x0E40,0x0F40,0x1040,0x1140, 0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940, - 0x1A60,0x1B60,0x1C60,0x1D60,0x1E60,0x1F60,0x2040,0x2140, + 0x1A40,0x1B40,0x1C40,0x1D40,0x1E40,0x1F40,0x2040,0x2140, 0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940, - 0x2A60,0x2B60,0x2C60,0x2D60,0x2E60,0x2F60,0x3040,0x3140, + 0x2A40,0x2B40,0x2C40,0x2D40,0x2E40,0x2F40,0x3040,0x3140, 0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940, - 0x3A60,0x3B60,0x3C60,0x3D60,0x3E60,0x3F60,0x4040,0x4140, + 0x3A40,0x3B40,0x3C40,0x3D40,0x3E40,0x3F40,0x4040,0x4140, 0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940, - 0x4A60,0x4B60,0x4C60,0x4D60,0x4E60,0x4F60,0x5040,0x5140, + 0x4A40,0x4B40,0x4C40,0x4D40,0x4E40,0x4F40,0x5040,0x5140, 0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940, - 0x5A60,0x5B60,0x5C60,0x5D60,0x5E60,0x5F60,0x6040,0x6140, + 0x5A40,0x5B40,0x5C40,0x5D40,0x5E40,0x5F40,0x6040,0x6140, 0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940, - 0x6A60,0x6B60,0x6C60,0x6D60,0x6E60,0x6F60,0x7040,0x7140, + 0x6A40,0x6B40,0x6C40,0x6D40,0x6E40,0x6F40,0x7040,0x7140, 0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940, - 0x7A60,0x7B60,0x7C60,0x7D60,0x7E60,0x7F60,0x8040,0x8140, + 0x7A40,0x7B40,0x7C40,0x7D40,0x7E40,0x7F40,0x8040,0x8140, 0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940, - 0x8A60,0x8B60,0x8C60,0x8D60,0x8E60,0x8F60,0x9040,0x9140, - 0x9240,0x9340,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150, - 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150, - 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150, - 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150, - 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150, - 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150, - 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, - 0x9A70,0x9B70,0x9C70,0x9D70,0x9E70,0x9F70,0xA050,0xA150, + 0x8A40,0x8B40,0x8C40,0x8D40,0x8E40,0x8F40,0x9040,0x9140, + 0x9240,0x9340,0x9440,0x9540,0x9640,0x9740,0x9840,0x9940, + 0x9A40,0x9B40,0x9C40,0x9D40,0x9E40,0x9F40,0xA040,0xA140, + 0xA240,0xA340,0xA440,0xA540,0xA640,0xA740,0xA840,0xA940, + 0xAA40,0xAB40,0xAC40,0xAD40,0xAE40,0xAF40,0xB040,0xB140, + 0xB240,0xB340,0xB440,0xB540,0xB640,0xB740,0xB840,0xB940, + 0xBA40,0xBB40,0xBC40,0xBD40,0xBE40,0xBF40,0xC040,0xC140, + 0xC240,0xC340,0xC440,0xC540,0xC640,0xC740,0xC840,0xC940, + 0xCA40,0xCB40,0xCC40,0xCD40,0xCE40,0xCF40,0xD040,0xD140, + 0xD240,0xD340,0xD440,0xD540,0xD640,0xD740,0xD840,0xD940, + 0xDA40,0xDB40,0xDC40,0xDD40,0xDE40,0xDF40,0xE040,0xE140, + 0xE240,0xE340,0xE440,0xE540,0xE640,0xE740,0xE840,0xE940, + 0xEA40,0xEB40,0xEC40,0xED40,0xEE40,0xEF40,0xF040,0xF140, + 0xF240,0xF340,0xF440,0xF540,0xF640,0xF740,0xF840,0xF940, + 0x9A50,0x9B50,0x9C50,0x9D50,0x9E50,0x9F50,0xA050,0xA150, 0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950, - 0xAA70,0xAB70,0xAC70,0xAD70,0xAE70,0xAF70,0xB050,0xB150, + 0xAA50,0xAB50,0xAC50,0xAD50,0xAE50,0xAF50,0xB050,0xB150, 0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950, - 0xBA70,0xBB70,0xBC70,0xBD70,0xBE70,0xBF70,0xC050,0xC150, + 0xBA50,0xBB50,0xBC50,0xBD50,0xBE50,0xBF50,0xC050,0xC150, 0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950, - 0xCA70,0xCB70,0xCC70,0xCD70,0xCE70,0xCF70,0xD050,0xD150, + 0xCA50,0xCB50,0xCC50,0xCD50,0xCE50,0xCF50,0xD050,0xD150, 0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950, - 0xDA70,0xDB70,0xDC70,0xDD70,0xDE70,0xDF70,0xE050,0xE150, + 0xDA50,0xDB50,0xDC50,0xDD50,0xDE50,0xDF50,0xE050,0xE150, 0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950, - 0xEA70,0xEB70,0xEC70,0xED70,0xEE70,0xEF70,0xF050,0xF150, + 0xEA50,0xEB50,0xEC50,0xED50,0xEE50,0xEF50,0xF050,0xF150, 0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950, - 0xFA70,0xFB70,0xFC70,0xFD70,0xFE70,0xFF70,0x00D0,0x0150, + 0xFA50,0xFB50,0xFC50,0xFD50,0xFE50,0xFF50,0x00D0,0x0150, 0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950, - 0x0A70,0x0B70,0x0C70,0x0D70,0x0E70,0x0F70,0x1050,0x1150, + 0x0A50,0x0B50,0x0C50,0x0D50,0x0E50,0x0F50,0x1050,0x1150, 0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950, - 0x1A70,0x1B70,0x1C70,0x1D70,0x1E70,0x1F70,0x2050,0x2150, + 0x1A50,0x1B50,0x1C50,0x1D50,0x1E50,0x1F50,0x2050,0x2150, 0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950, - 0x2A70,0x2B70,0x2C70,0x2D70,0x2E70,0x2F70,0x3050,0x3150, + 0x2A50,0x2B50,0x2C50,0x2D50,0x2E50,0x2F50,0x3050,0x3150, 0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950, - 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150, + 0x3A50,0x3B50,0x3C50,0x3D50,0x3E50,0x3F50,0x4050,0x4150, 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950, - 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150, + 0x4A50,0x4B50,0x4C50,0x4D50,0x4E50,0x4F50,0x5050,0x5150, 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950, - 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150, + 0x5A50,0x5B50,0x5C50,0x5D50,0x5E50,0x5F50,0x6050,0x6150, 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950, - 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150, + 0x6A50,0x6B50,0x6C50,0x6D50,0x6E50,0x6F50,0x7050,0x7150, 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950, - 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150, + 0x7A50,0x7B50,0x7C50,0x7D50,0x7E50,0x7F50,0x8050,0x8150, 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950, - 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150, + 0x8A50,0x8B50,0x8C50,0x8D50,0x8E50,0x8F50,0x9050,0x9150, 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, }; @@ -615,6 +615,8 @@ bool gbIsGameboyRom(char * file) if(p != NULL) { if(_stricmp(p, ".gb") == 0) return true; + if(_stricmp(p, ".dmg") == 0) + return true; if(_stricmp(p, ".gbc") == 0) return true; if(_stricmp(p, ".cgb") == 0) @@ -804,7 +806,7 @@ void gbWriteMemory(register u16 address, register u8 value) gbMemory[0xff02] = value; if(gbSerialOn) { gbSerialTicks = GBSERIAL_CLOCK_TICKS; -#ifdef LINK_EMULATION +#ifdef OLD_GB_LINK if(linkConnected) { if(value & 1) { linkSendByte(0x100|gbMemory[0xFF01]); @@ -1207,7 +1209,7 @@ void gbWriteMemory(register u16 address, register u8 value) else memset(gbBgpLine,value,sizeof(gbBgpLine)); - gbSetBGPalette(value); + gbSetBGPalette(value); break; } @@ -1230,7 +1232,7 @@ void gbWriteMemory(register u16 address, register u8 value) else memset(gbObp0Line,value,sizeof(gbObp0Line)); - gbSetObj0Palette(value); + gbSetObj0Palette(value); break; } @@ -1253,7 +1255,7 @@ void gbWriteMemory(register u16 address, register u8 value) else memset(gbObp1Line,value,sizeof(gbObp1Line)); - gbSetObj1Palette(value); + gbSetObj1Palette(value); break; } @@ -1431,12 +1433,10 @@ void gbWriteMemory(register u16 address, register u8 value) int paletteHiLo = (v & 0x01); // No access to gbPalette during mode 3 (Color Panel Demo) - // CAK - The following check has to be commented out for - // colourised roms like Metroid 2 DX - //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) { gbMemory[0xff69] = value; gbPalette[paletteIndex] = (paletteHiLo ? @@ -1487,12 +1487,10 @@ void gbWriteMemory(register u16 address, register u8 value) paletteIndex += 32; // No access to gbPalette during mode 3 (Color Panel Demo) - // CAK - The following check has to be commented out for - // colourised roms like Metroid 2 DX - //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) { gbMemory[0xff6b] = value; gbPalette[paletteIndex] = (paletteHiLo ? @@ -1569,17 +1567,33 @@ u8 gbReadOpcode(register u16 address) if(address < 0x8000) return gbMemoryMap[address>>12][address&0x0fff]; - if(address < 0xa000) + if (address < 0xa000) { // A lot of 'ugly' checks... But only way to emulate this particular behaviour... - if (((gbHardware & 0xa) && ((gbLcdModeDelayed !=3) || ((register_LY == 0) && - (gbScreenOn==false) && (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) || - ((gbHardware & 0x5) && (gbLcdModeDelayed !=3) && - ((gbLcdMode !=3) || ((register_LY == 0) && ((gbScreenOn==false) && - (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicks ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))))) - return gbMemoryMap[address>>12][address&0x0fff]; + if ( + ( + (gbHardware & 0xa) && + ( + (gbLcdModeDelayed != 3) || + ( + ((register_LY == 0) && (gbScreenOn == false) && (register_LCDC & 0x80)) && + (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)) + ) + ) + ) + || + ( + (gbHardware & 0x5) && + (gbLcdModeDelayed != 3) && + ( + (gbLcdMode != 3) || + ((register_LY == 0) && ((gbScreenOn == false) && (register_LCDC & 0x80)) && + (gbLcdLYIncrementTicks == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS))) + ) + ) + ) + return gbMemoryMap[address >> 12][address & 0x0fff]; + return 0xff; } @@ -1623,7 +1637,7 @@ u8 gbReadOpcode(register u16 address) case 0x41: // This is a GB/C only bug (ie. not GBA/SP). if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed)) - return (0x80 | gbMemory[0xff41] & 0xFC); + return (0x80 | (gbMemory[0xff41] & 0xFC)); else return (0x80 | gbMemory[0xff41]); case 0x42: @@ -1632,7 +1646,7 @@ u8 gbReadOpcode(register u16 address) return register_SCX; case 0x44: if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) || - (!(register_LCDC && 0x80))) + (!(register_LCDC & 0x80))) return 0; else return register_LY; @@ -1669,13 +1683,13 @@ u8 gbReadOpcode(register u16 address) if (gbCgbMode) { // No access to gbPalette during mode 3 (Color Panel Demo) - //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) return (gbMemory[address]); - //else - // return 0xff; + else + return 0xff; } else return 0xff; @@ -1719,17 +1733,34 @@ u8 gbReadMemory(register u16 address) if(address < 0x8000) return gbMemoryMap[address>>12][address&0x0fff]; - if(address < 0xa000) + + if (address < 0xa000) { // A lot of 'ugly' checks... But only way to emulate this particular behaviour... - if (((gbHardware & 0xa) && ((gbLcdModeDelayed !=3) || ((register_LY == 0) && - (gbScreenOn==false) && (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) || - ((gbHardware & 0x5) && (gbLcdModeDelayed !=3) && - ((gbLcdMode !=3) || ((register_LY == 0) && ((gbScreenOn==false) && - (register_LCDC & 0x80)) && - (gbLcdLYIncrementTicks ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))))) - return gbMemoryMap[address>>12][address&0x0fff]; + if ( + ( + (gbHardware & 0xa) && + ( + (gbLcdModeDelayed != 3) || + ( + ((register_LY == 0) && (gbScreenOn == false) && (register_LCDC & 0x80)) && + (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)) + ) + ) + ) + || + ( + (gbHardware & 0x5) && + (gbLcdModeDelayed != 3) && + ( + (gbLcdMode != 3) || + ((register_LY == 0) && ((gbScreenOn == false) && (register_LCDC & 0x80)) && + (gbLcdLYIncrementTicks == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS))) + ) + ) + ) + return gbMemoryMap[address >> 12][address & 0x0fff]; + return 0xff; } @@ -1886,7 +1917,7 @@ u8 gbReadMemory(register u16 address) case 0x41: // This is a GB/C only bug (ie. not GBA/SP). if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed)) - return (0x80 | gbMemory[0xff41] & 0xFC); + return (0x80 | (gbMemory[0xff41] & 0xFC)); else return (0x80 | gbMemory[0xff41]); case 0x42: @@ -1895,7 +1926,7 @@ u8 gbReadMemory(register u16 address) return register_SCX; case 0x44: if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) || - (!(register_LCDC && 0x80))) + (!(register_LCDC & 0x80))) return (0); else return register_LY; @@ -1930,13 +1961,13 @@ u8 gbReadMemory(register u16 address) if (gbCgbMode) { // No access to gbPalette during mode 3 (Color Panel Demo) - //if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || - // (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || - // ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || - // ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) return (gbMemory[address]); - //else - // return 0xff; + else + return 0xff; } else return 0xff; @@ -1951,10 +1982,10 @@ u8 gbReadMemory(register u16 address) } // OAM not accessible during mode 2 & 3. if(((address >= 0xfe00) && (address<0xfea0)) && - (((gbLcdMode | gbLcdModeDelayed) &2) && - (!(gbSpeed && (gbHardware & 0x2) && !(gbLcdModeDelayed & 2) && (gbLcdMode == 2))) || + ((((gbLcdMode | gbLcdModeDelayed) & 2) && + (!(gbSpeed && (gbHardware & 0x2) && !(gbLcdModeDelayed & 2) && (gbLcdMode == 2)))) || (gbSpeed && (gbHardware & 0x2) && (gbLcdModeDelayed == 0) && (gbLcdTicksDelayed == (GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]))))) - return 0xff; + return 0xff; if ((address >= 0xfea0) && (address < 0xff00)) { @@ -1982,6 +2013,7 @@ void gbVblank_interrupt() void gbLcd_interrupt() { + gbCheatWrite(false); // Emulates GS codes. gbMemory[0xff0f] = register_IF &= 0xfd; gbWriteMemory(--SP.W, PC.B.B1); gbWriteMemory(--SP.W, PC.B.B0); @@ -2092,7 +2124,7 @@ void gbCPUInit(const char *biosFileName, bool useBiosFile) useBios = false; if (useBiosFile) { -/* int size = 0x100; + int size = 0x100; if(utilLoad(biosFileName, CPUIsGBBios, bios, @@ -2101,7 +2133,7 @@ void gbCPUInit(const char *biosFileName, bool useBiosFile) useBios = true; else systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file size")); - }*/ + } } } @@ -2117,11 +2149,12 @@ void gbGetHardwareType() } } - if((gbCgbMode == 0 ) && (gbRom[0x146] == 0x03)) { + if((gbCgbMode == 0) && (gbRom[0x146] == 0x03)) { if(gbEmulatorType == 0 || gbEmulatorType == 2 || gbEmulatorType == 5) gbSgbMode = 1; + gbCgbMode = 0; } gbHardware = 1; // GB @@ -2139,9 +2172,7 @@ void gbGetHardwareType() void gbReset() { - systemCartridgeRumble(false); gbGetHardwareType(); - gbPaletteReset(); oldRegister_WY = 146; gbInterruptLaunched = 0; @@ -2173,11 +2204,6 @@ void gbReset() gbDmaTicks = 0; clockTicks = 0; - if(gbSpeed) { - gbSpeedSwitch(); - gbMemory[0xff4d] = 0; - } - // clean Wram // This kinda emulates the startup state of Wram on GB/C (not very accurate, // but way closer to the reality than filling it with 00es or FFes). @@ -2201,6 +2227,11 @@ void gbReset() gbMemory[temp] = 0xff; } + if(gbSpeed) { + gbSpeedSwitch(); + gbMemory[0xff4d] = 0; + } + // GB bios set this memory area to 0 // Fixes Pitman (J) title screen if (gbHardware & 0x1) { @@ -2209,10 +2240,10 @@ void gbReset() // clean LineBuffer if (gbLineBuffer != NULL) - memset(gbLineBuffer, 0, sizeof(gbLineBuffer)); + memset(gbLineBuffer, 0, sizeof(*gbLineBuffer)); // clean Pix if (pix != NULL) - memset(pix, 0, sizeof(pix)); + memset(pix, 0, sizeof(*pix)); // clean Vram if (gbVram != NULL) memset(gbVram, 0, 0x4000); @@ -2437,7 +2468,7 @@ void gbReset() gbTimerOn = false; if(gbCgbMode) { - for (int i = 0; i<0x20; i++) + for (i = 0; i<0x20; i++) gbPalette[i] = 0x7fff; // This is just to show that the starting values of the OBJ palettes are different @@ -2555,12 +2586,12 @@ void gbReset() } } else { if(gbSgbMode) { - for(int i = 0; i < 12; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*12+i]; + for(i = 0; i < 8; i++) + gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; } - for(int i = 0; i < 12; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*12+i]; + for(i = 0; i < 8; i++) + gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; } GBTIMER_MODE_0_CLOCK_TICKS = 256; @@ -2614,8 +2645,6 @@ void gbReset() memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); gbDataMBC5.mapperROMBank = 1; - if (gbRomType >= 0x1c && gbRomType<=0x1e) - gbDataMBC5.isRumbleCartridge = 1; memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); gbDataHuC1.mapperROMBank = 1; @@ -2717,7 +2746,7 @@ void gbWriteSaveMBC2(const char * name) return; } - fwrite(&gbMemoryMap[0x0a], + fwrite(gbMemoryMap[0x0a], 1, 512, file); @@ -2899,7 +2928,7 @@ bool gbReadSaveMBC2(const char * name) return false; } - size_t read = fread(&gbMemoryMap[0x0a], + size_t read = fread(gbMemoryMap[0x0a], 1, 512, file); @@ -3978,18 +4007,16 @@ bool gbReadSaveState(const char *name) bool gbWritePNGFile(const char *fileName) { -/* if(gbBorderOn) + if(gbBorderOn) return utilWritePNGFile(fileName, 256, 224, pix); - return utilWritePNGFile(fileName, 160, 144, pix);*/ - return false; + return utilWritePNGFile(fileName, 160, 144, pix); } bool gbWriteBMPFile(const char *fileName) { -/* if(gbBorderOn) + if(gbBorderOn) return utilWriteBMPFile(fileName, 256, 224, pix); - return utilWriteBMPFile(fileName, 160, 144, pix);*/ - return false; + return utilWriteBMPFile(fileName, 160, 144, pix); } void gbCleanUp() @@ -4054,10 +4081,10 @@ bool gbLoadRom(const char *szFile) systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; -/* gbRom = utilLoad(szFile, + gbRom = utilLoad(szFile, utilIsGBImage, NULL, - size);*/ + size); if(!gbRom) return false; @@ -4083,7 +4110,9 @@ bool gbUpdateSizes() } if(gbRomSize < gbRomSizes[gbRom[0x148]]) { - gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); + u8 *gbRomNew = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); + if( !gbRomNew ) { assert( false ); return false; }; + gbRom = gbRomNew; for (int i = gbRomSize; i 60) { + // Reset the clock + memset(&gbDataMBC3.mapperSeconds, 0, sizeof(int) * 10 + sizeof(time_t)); + } + } } return true; } @@ -5600,6 +5662,22 @@ bool MemgbReadSaveTAMA5(char * membuffer, int read) { memcpy(gbRam, membuffer, (gbRamSizeMask + 1)); int offset = (gbRamSizeMask + 1); memcpy(&gbDataTAMA5.mapperSeconds, membuffer+offset, sizeof(int) * 14 + sizeof(time_t)); + + swap_endian_32(&gbDataTAMA5.mapperSeconds, sizeof(int) * 14 + sizeof(time_t)); + + bool zero = gbDataTAMA5.mapperSeconds || gbDataTAMA5.mapperMinutes || gbDataTAMA5.mapperHours; + // If all values are zero, it's not possible to determine the byte order - assume little endian + if (!zero && gbDataTAMA5.mapperSeconds <= 60 && gbDataTAMA5.mapperMinutes <= 60 && gbDataTAMA5.mapperHours <= 24) { + // Big endian format (VBA-GX 2.3.0 and lower) + } else { + // Little endian format (VBA/VBA-M on x86) + swap_endian_32(&gbDataTAMA5.mapperSeconds, sizeof(int) * 14 + sizeof(time_t)); + if (gbDataTAMA5.mapperSeconds > 60) { + // Reset the clock + memset(&gbDataMBC3.mapperSeconds, 0, sizeof(int) * 14 + sizeof(time_t)); + } + } + return true; } return false; diff --git a/source/vba/gb/gb.h b/source/vba/gb/gb.h index 58712b3..463d152 100644 --- a/source/vba/gb/gb.h +++ b/source/vba/gb/gb.h @@ -17,7 +17,12 @@ typedef union { u16 W; } gbRegister; +extern gbRegister AF, BC, DE, HL, SP, PC; +extern u16 IFF; +int gbDis(char *, u16); + bool gbLoadRom(const char *); +bool gbUpdateSizes(); void gbEmulate(int); void gbWriteMemory(register u16, register u8); void gbDrawLine(); @@ -38,8 +43,11 @@ bool gbWritePNGFile(const char *); bool gbWriteBMPFile(const char *); bool gbReadGSASnapshot(const char *); +extern int gbHardware; + extern struct EmulatedSystem GBSystem; +// For VBA-GX bool MemgbReadBatteryFile(char * membuffer, int read); int MemgbWriteBatteryFile(char * membuffer); diff --git a/source/vba/gb/gbGlobals.cpp b/source/vba/gb/gbGlobals.cpp index f191dec..0076f1e 100644 --- a/source/vba/gb/gbGlobals.cpp +++ b/source/vba/gb/gbGlobals.cpp @@ -1,4 +1,4 @@ -#include +#include #include "../common/Types.h" u8 *gbMemoryMap[16]; @@ -30,7 +30,7 @@ u16 gbColorFilter[32768]; int gbColorOption = 0; int gbPaletteOption = 0; int gbEmulatorType = 0; -int gbBorderOn = 1; +int gbBorderOn = 0; int gbBorderAutomatic = 0; int gbBorderLineSkip = 160; int gbBorderRowSkip = 0; @@ -38,3 +38,4 @@ int gbBorderColumnSkip = 0; int gbDmaTicks = 0; u8 (*gbSerialFunction)(u8) = NULL; +void (*sgbBorderListener)(bool) = NULL; diff --git a/source/vba/gb/gbMemory.cpp b/source/vba/gb/gbMemory.cpp index 9a06954..12ce2b5 100644 --- a/source/vba/gb/gbMemory.cpp +++ b/source/vba/gb/gbMemory.cpp @@ -5,10 +5,12 @@ #include "gb.h" 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}; -extern int gbHardware; extern int gbGBCColorType; extern gbRegister PC; +// for UTC offset +#include "../../vbagx.h" + mapperMBC1 gbDataMBC1 = { 0, // RAM enable 1, // ROM bank @@ -327,7 +329,7 @@ mapperMBC3 gbDataMBC3 = { void memoryUpdateMBC3Clock() { - time_t now = time(NULL); + time_t now = time(NULL) - (GCSettings.OffsetMinutesUTC*60); time_t diff = now - gbDataMBC3.mapperLastTime; if(diff > 0) { // update the clock according to the last update time @@ -437,6 +439,7 @@ void mapperMBC3RAM(u16 address, u8 value) } } else { time(&gbDataMBC3.mapperLastTime); + gbDataMBC3.mapperLastTime -= (GCSettings.OffsetMinutesUTC*60); switch(gbDataMBC3.mapperClockRegister) { case 0x08: gbDataMBC3.mapperSeconds = value; @@ -540,7 +543,6 @@ mapperMBC5 gbDataMBC5 = { 0 // is rumble cartridge? }; -extern int ConfigRequested; // MBC5 ROM write registers void mapperMBC5ROM(u16 address, u8 value) { @@ -581,18 +583,10 @@ void mapperMBC5ROM(u16 address, u8 value) gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; } break; - case 0x4000: // RAM bank select, plus rumble - // Some games support rumble, such as Disney Tarzan, but aren't on a - // rumble cartridge. As long as the RAM is less than or equal to 256Kbit - // we know that the last address line is not used for real RAM addresses, - // so it must be a rumble signal instead. - if(gbDataMBC5.isRumbleCartridge) { - systemCartridgeRumble(value & 0x08); + case 0x4000: // RAM bank select + if(gbDataMBC5.isRumbleCartridge) value &= 0x07; - } else if (gbRamSizeMask <= 0x7FFF) { - systemPossibleCartridgeRumble(value & 0x08); - value &= 0x07; - } else + else value &= 0x0f; if(value == gbDataMBC5.mapperRAMBank) break; @@ -1231,7 +1225,7 @@ void memoryUpdateTAMA5Clock() else gbDaysinMonth[1] = 28; - time_t now = time(NULL); + time_t now = time(NULL) - (GCSettings.OffsetMinutesUTC*60); time_t diff = now - gbDataTAMA5.mapperLastTime; if(diff > 0) { // 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) ? time(&gbDataTAMA5.mapperLastTime); + gbDataMBC3.mapperLastTime -= (GCSettings.OffsetMinutesUTC*60); gbMemoryMap[0xa][0] = 1; } diff --git a/source/vba/gb/gbPrinter.cpp b/source/vba/gb/gbPrinter.cpp index d658697..8061394 100644 --- a/source/vba/gb/gbPrinter.cpp +++ b/source/vba/gb/gbPrinter.cpp @@ -38,6 +38,7 @@ void gbPrinterReset() void gbPrinterShowData() { systemGbPrint(gbPrinterData, + gbPrinterDataCount, gbPrinterPacket[6], gbPrinterPacket[7], gbPrinterPacket[8], @@ -87,6 +88,7 @@ void gbPrinterShowData() void gbPrinterReceiveData() { + int i = gbPrinterDataCount; if(gbPrinterPacket[3]) { // compressed u8 *data = &gbPrinterPacket[6]; u8 *dest = &gbPrinterData[gbPrinterDataCount]; @@ -97,16 +99,17 @@ void gbPrinterReceiveData() control &= 0x7f; control += 2; memset(dest, *data++, control); - len += control; + len += 2; dest += control; } else { // raw data control++; memcpy(dest, data, control); dest += control; data += control; - len += control; + len += control + 1; } } + gbPrinterDataCount = (int)(dest - gbPrinterData); } else { memcpy(&gbPrinterData[gbPrinterDataCount], &gbPrinterPacket[6], diff --git a/source/vba/gb/gbSGB.cpp b/source/vba/gb/gbSGB.cpp index c593526..8ed55aa 100644 --- a/source/vba/gb/gbSGB.cpp +++ b/source/vba/gb/gbSGB.cpp @@ -40,7 +40,7 @@ u8 gbSgbScreenBuffer[4160]; inline void gbSgbDraw24Bit(u8 *p, u16 v) { - *((u32*) p) = systemColorMap32[v]; + memcpy(p, &systemColorMap32[v], 3); } inline void gbSgbDraw32Bit(u32 *p, u16 v) @@ -188,9 +188,9 @@ void gbSgbRenderScreenToBuffer() 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; - u32 *dest32 = (u32*)pix + ((y+1)*257) + x; + u32 *dest32 = (u32*)pix + (y*257) + x; u8 *tileAddress = &gbSgbBorderChar[tile * 32]; u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16]; diff --git a/source/vba/gb/gbSound.cpp b/source/vba/gb/gbSound.cpp index fe1f011..7f9c13d 100644 --- a/source/vba/gb/gbSound.cpp +++ b/source/vba/gb/gbSound.cpp @@ -4,11 +4,11 @@ #include "../Util.h" #include "gbGlobals.h" #include "gbSound.h" +#include "gb.h" #include "../apu/Gb_Apu.h" #include "../apu/Effects_Buffer.h" -extern int gbHardware; extern long soundSampleRate; // current sound quality 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() { + // APU + if ( !gb_apu ) + { + gb_apu = new Gb_Apu; // TODO: handle errors + reset_apu(); + } + // Stereo_Buffer delete stereo_buffer; stereo_buffer = 0; @@ -128,20 +135,15 @@ static void remake_stereo_buffer() stereo_buffer = new Simple_Effects_Buffer; // 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 ); - - // APU + + // Multi_Buffer static int const chan_types [chan_count] = { Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2, Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1 }; if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors - if ( !gb_apu ) - { - gb_apu = new Gb_Apu; // TODO: handle errors - reset_apu(); - } - + // Volume Level apply_effects(); apply_volume(); } diff --git a/source/vba/gba/Cheats.cpp b/source/vba/gba/Cheats.cpp index ffd7b85..a4913f6 100644 --- a/source/vba/gba/Cheats.cpp +++ b/source/vba/gba/Cheats.cpp @@ -1,4 +1,4 @@ -#include +#ifndef __LIBRETRO__ #include #include #include @@ -910,24 +910,24 @@ int cheatsCheckKeys(u32 keys, u32 extended) } break; case GSA_8_BIT_POINTER : - if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) || - (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)) + if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) || + ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))) { CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8), cheatsList[i].value & 0xFF); } break; case GSA_16_BIT_POINTER : - if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) || - (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)) + if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) || + ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))) { CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15), cheatsList[i].value & 0xFFFF); } break; case GSA_32_BIT_POINTER : - if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) || - (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000)) + if (((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000)) || + ((CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))) { CPUWriteMemory(CPUReadMemory(cheatsList[i].address), cheatsList[i].value); @@ -935,15 +935,15 @@ int cheatsCheckKeys(u32 keys, u32 extended) break; case GSA_8_BIT_ADD : CPUWriteByte(cheatsList[i].address, - (cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address) & 0xFF); + ((cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address)) & 0xFF); break; case GSA_16_BIT_ADD : CPUWriteHalfWord(cheatsList[i].address, - (cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address) & 0xFFFF); + ((cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address)) & 0xFFFF); break; case GSA_32_BIT_ADD : CPUWriteMemory(cheatsList[i].address , - cheatsList[i].value + CPUReadMemory(cheatsList[i].address) & 0xFFFFFFFF); + (cheatsList[i].value + CPUReadMemory(cheatsList[i].address)) & 0xFFFFFFFF); break; case GSA_8_BIT_IF_LOWER_U: 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 ); } - bool firstCodeBreaker = true; - for( int i = 0; i < nCheats; i++ ) { if( version < 9 ) { utilGzSeek( file, ( 7 * sizeof(int) ) + ( 52 * sizeof(char) ), SEEK_CUR ); @@ -2898,3 +2896,4 @@ void cheatsWriteByte(u32, u8) #endif #endif } +#endif diff --git a/source/vba/gba/EEprom.cpp b/source/vba/gba/EEprom.cpp index bb14d00..524acd4 100644 --- a/source/vba/gba/EEprom.cpp +++ b/source/vba/gba/EEprom.cpp @@ -9,7 +9,15 @@ int eepromMode = EEPROM_IDLE; int eepromByte = 0; int eepromBits = 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]; +#endif + u8 eepromBuffer[16]; bool eepromInUse = false; int eepromSize = 512; @@ -27,7 +35,11 @@ variable_desc eepromSaveData[] = { void eepromInit() { - memset(eepromData, 255, sizeof(eepromData)); +#ifdef __LIBRETRO__ + memset(eepromData, 255, 0x2000); +#else + memset(eepromData, 255, sizeof(eepromData)); +#endif } void eepromReset() @@ -40,6 +52,26 @@ void eepromReset() 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) { utilWriteData(gzFile, eepromSaveData); @@ -68,6 +100,7 @@ void eepromReadGameSkip(gzFile gzFile, int version) utilGzSeek(gzFile, 0x2000, SEEK_CUR); } } +#endif int eepromRead(u32 /* address */) { diff --git a/source/vba/gba/EEprom.h b/source/vba/gba/EEprom.h index 63306f8..0320349 100644 --- a/source/vba/gba/EEprom.h +++ b/source/vba/gba/EEprom.h @@ -1,14 +1,23 @@ #ifndef 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 eepromReadGame(gzFile _gzFile, int version); +#endif extern void eepromReadGameSkip(gzFile _gzFile, int version); extern int eepromRead(u32 address); extern void eepromWrite(u32 address, u8 value); extern void eepromInit(); extern void eepromReset(); +#ifdef __LIBRETRO__ +extern u8 *eepromData; +#else extern u8 eepromData[0x2000]; +#endif extern bool eepromInUse; extern int eepromSize; diff --git a/source/vba/gba/Flash.cpp b/source/vba/gba/Flash.cpp index 1454791..d73a883 100644 --- a/source/vba/gba/Flash.cpp +++ b/source/vba/gba/Flash.cpp @@ -17,7 +17,13 @@ #define FLASH_PROGRAM 8 #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 flashReadState = FLASH_READ_ARRAY; int flashSize = 0x10000; @@ -51,7 +57,11 @@ static variable_desc flashSaveData3[] = { void flashInit() { - memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); +#ifdef __LIBRETRO__ + memset(flashSaveMemory, 0xff, 0x20000); +#else + memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); +#endif } void flashReset() @@ -61,6 +71,17 @@ void flashReset() 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) { utilWriteData(gzFile, flashSaveData3); @@ -90,6 +111,8 @@ void flashReadGameSkip(gzFile gzFile, int version) utilReadDataSkip(gzFile, flashSaveData3); } } +#endif + void flashSetSize(int size) { diff --git a/source/vba/gba/Flash.h b/source/vba/gba/Flash.h index 54ef19a..10861a0 100644 --- a/source/vba/gba/Flash.h +++ b/source/vba/gba/Flash.h @@ -1,13 +1,24 @@ #ifndef 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 flashReadGame(gzFile _gzFile, int version); +#endif extern void flashReadGameSkip(gzFile _gzFile, int version); extern u8 flashRead(u32 address); extern void flashWrite(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 flashReset(); extern void flashSetSize(int size); diff --git a/source/vba/gba/GBA-arm.cpp b/source/vba/gba/GBA-arm.cpp index 1118c31..5a97926 100644 --- a/source/vba/gba/GBA-arm.cpp +++ b/source/vba/gba/GBA-arm.cpp @@ -297,7 +297,7 @@ static void count(u32 opcode, int cond_res) #define EMIT0(op) #op"; " #define EMIT1(op,arg) #op" "arg"; " #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 ASMVAR2(prefix,cvar) STRING (prefix) cvar #define STRING(x) #x @@ -330,7 +330,7 @@ static void count(u32 opcode, int cond_res) #define EMIT0(op) __asm op #define EMIT1(op,arg) __asm op arg #define EMIT2(op,src,dest) __asm op dest, src - #define CONST(val) val + #define KONST(val) val #define VAR(var) var #define VARL(var) dword ptr var #define REGREF1(index) reg[index] @@ -349,15 +349,19 @@ static void count(u32 opcode, int cond_res) // Helper macros for loading value / shift count #define VALUE_LOAD_IMM \ - EMIT2(and, CONST(0x0F), eax) \ + EMIT2(and, KONST(0x0F), eax) \ EMIT2(mov, REGREF2(eax,4), eax) \ - EMIT2(shr, CONST(7), ecx) \ - EMIT2(and, CONST(0x1F), ecx) + EMIT2(shr, KONST(7), ecx) \ + EMIT2(and, KONST(0x1F), ecx) #define VALUE_LOAD_REG \ - EMIT2(and, CONST(0x0F), eax) \ - EMIT2(mov, REGREF2(eax,4), eax) \ + EMIT2(and, KONST(0x0F), eax) \ + EMIT2(cmp, KONST(0x0F), eax) \ + EMIT2(mov, REGREF2(eax,4), eax) \ + EMIT1(jne, LABELREF(3,f)) \ + EMIT2(add, KONST(4), eax) \ + LABEL(3) \ EMIT2(movzx, ch, ecx) \ - EMIT2(and, CONST(0x0F), ecx) \ + EMIT2(and, KONST(0x0F), ecx) \ EMIT2(mov, REGREF2(ecx,4), ecx) // Helper macros for setting flags @@ -381,13 +385,13 @@ static void count(u32 opcode, int cond_res) ALU_HEADER \ LOAD_C_FLAG \ EMIT2(mov, ecx, edx) \ - EMIT2(shr, CONST(14), edx) \ + EMIT2(shr, KONST(14), edx) \ EMIT2(mov, ecx, eax) \ EMIT2(mov, ecx, esi) \ - EMIT2(shr, CONST(10), esi) \ - EMIT2(and, CONST(0x3C), edx) \ + EMIT2(shr, KONST(10), esi) \ + EMIT2(and, KONST(0x3C), 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_NO /*nothing*/ @@ -415,14 +419,14 @@ static void count(u32 opcode, int cond_res) VALUE_LOAD_REG \ EMIT2(test, cl, cl) \ EMIT1(jz, LABELREF(0,f)) \ - EMIT2(cmp, CONST(0x20), cl) \ + EMIT2(cmp, KONST(0x20), cl) \ EMIT1(je, LABELREF(1,f)) \ EMIT1(ja, LABELREF(2,f)) \ EMIT2(shl, cl, eax) \ EMIT1(setc, bl) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(test, CONST(1), al) \ + EMIT2(test, KONST(1), al) \ EMIT1(setnz, bl) \ EMIT2(xor, eax, eax) \ EMIT1(jmp, LABELREF(0,f)) \ @@ -432,7 +436,7 @@ static void count(u32 opcode, int cond_res) LABEL(0) #define VALUE_LSL_REG_NC \ VALUE_LOAD_REG \ - EMIT2(cmp, CONST(0x20), cl) \ + EMIT2(cmp, KONST(0x20), cl) \ EMIT1(jae, LABELREF(1,f)) \ EMIT2(shl, cl, eax) \ EMIT1(jmp, LABELREF(0,f)) \ @@ -466,7 +470,7 @@ static void count(u32 opcode, int cond_res) VALUE_LOAD_REG \ EMIT2(test, cl, cl) \ EMIT1(jz, LABELREF(0,f)) \ - EMIT2(cmp, CONST(0x20), cl) \ + EMIT2(cmp, KONST(0x20), cl) \ EMIT1(je, LABELREF(1,f)) \ EMIT1(ja, LABELREF(2,f)) \ EMIT2(shr, cl, eax) \ @@ -483,7 +487,7 @@ static void count(u32 opcode, int cond_res) LABEL(0) #define VALUE_LSR_REG_NC \ VALUE_LOAD_REG \ - EMIT2(cmp, CONST(0x20), cl) \ + EMIT2(cmp, KONST(0x20), cl) \ EMIT1(jae, LABELREF(1,f)) \ EMIT2(shr, cl, eax) \ EMIT1(jmp, LABELREF(0,f)) \ @@ -499,7 +503,7 @@ static void count(u32 opcode, int cond_res) EMIT1(setc, bl) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ + EMIT2(sar, KONST(31), eax) \ EMIT1(sets, bl) \ LABEL(0) #define VALUE_ASR_IMM_NC \ @@ -508,7 +512,7 @@ static void count(u32 opcode, int cond_res) EMIT2(sar, cl, eax) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ + EMIT2(sar, KONST(31), eax) \ LABEL(0) // OP Rd,Rb,Rm ASR Rs @@ -516,23 +520,23 @@ static void count(u32 opcode, int cond_res) VALUE_LOAD_REG \ EMIT2(test, cl, cl) \ EMIT1(jz, LABELREF(0,f)) \ - EMIT2(cmp, CONST(0x20), cl) \ + EMIT2(cmp, KONST(0x20), cl) \ EMIT1(jae, LABELREF(1,f)) \ EMIT2(sar, cl, eax) \ EMIT1(setc, bl) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ + EMIT2(sar, KONST(31), eax) \ EMIT1(sets, bl) \ LABEL(0) #define VALUE_ASR_REG_NC \ VALUE_LOAD_REG \ - EMIT2(cmp, CONST(0x20), cl) \ + EMIT2(cmp, KONST(0x20), cl) \ EMIT1(jae, LABELREF(1,f)) \ EMIT2(sar, cl, eax) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(sar, CONST(31), eax) \ + EMIT2(sar, KONST(31), eax) \ LABEL(0) // OP Rd,Rb,Rm ROR # @@ -542,8 +546,8 @@ static void count(u32 opcode, int cond_res) EMIT2(ror, cl, eax) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(bt, CONST(0), ebx) \ - EMIT2(rcr, CONST(1), eax) \ + EMIT2(bt, KONST(0), ebx) \ + EMIT2(rcr, KONST(1), eax) \ LABEL(0) \ EMIT1(setc, bl) #define VALUE_ROR_IMM_NC \ @@ -552,14 +556,14 @@ static void count(u32 opcode, int cond_res) EMIT2(ror, cl, eax) \ EMIT1(jmp, LABELREF(0,f)) \ LABEL(1) \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ - EMIT2(rcr, CONST(1), eax) \ + EMIT2(bt, KONST(0), VARL(C_FLAG)) \ + EMIT2(rcr, KONST(1), eax) \ LABEL(0) // OP Rd,Rb,Rm ROR Rs #define VALUE_ROR_REG_C \ VALUE_LOAD_REG \ - EMIT2(bt, CONST(0), ebx) \ + EMIT2(bt, KONST(0), ebx) \ EMIT2(ror, cl, eax) \ EMIT1(setc, bl) #define VALUE_ROR_REG_NC \ @@ -571,7 +575,7 @@ static void count(u32 opcode, int cond_res) EMIT2(movzx, ch, ecx) \ EMIT2(add, ecx, ecx) \ EMIT2(movzx, al, eax) \ - EMIT2(bt, CONST(0), ebx) \ + EMIT2(bt, KONST(0), ebx) \ EMIT2(ror, cl, eax) \ EMIT1(setc, bl) #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) #define CHECK_PC(OP, SETCOND) \ - EMIT2(cmp, CONST(0x3C), esi) \ + EMIT2(cmp, KONST(0x3C), esi) \ EMIT1(je, LABELREF(8,f)) \ OP SETCOND \ EMIT1(jmp, LABELREF(9,f)) \ @@ -613,18 +617,18 @@ static void count(u32 opcode, int cond_res) EMIT2(mov, edx, REGREF1(esi)) #define OP_ADDS CHECK_PC(OP_ADD, SETCOND_ADD) #define OP_ADC \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ + EMIT2(bt, KONST(0), VARL(C_FLAG)) \ EMIT2(adc, eax, edx) \ EMIT2(mov, edx, REGREF1(esi)) #define OP_ADCS CHECK_PC(OP_ADC, SETCOND_ADD) #define OP_SBC \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ + EMIT2(bt, KONST(0), VARL(C_FLAG)) \ EMIT0(cmc) \ EMIT2(sbb, eax, edx) \ EMIT2(mov, edx, REGREF1(esi)) #define OP_SBCS CHECK_PC(OP_SBC, SETCOND_SUB) #define OP_RSC \ - EMIT2(bt, CONST(0), VARL(C_FLAG)) \ + EMIT2(bt, KONST(0), VARL(C_FLAG)) \ EMIT0(cmc) \ EMIT2(sbb, edx, eax) \ EMIT2(mov, eax, REGREF1(esi)) @@ -656,7 +660,7 @@ static void count(u32 opcode, int cond_res) #define OP_MVN \ EMIT1(not, eax) \ 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 #define ALU_FINISH ALU_TRAILER @@ -677,7 +681,7 @@ static void count(u32 opcode, int cond_res) : "0" (offset), "c" (shift)); #define RRX_OFFSET \ - asm(EMIT2(btl,CONST(0),VAR(C_FLAG)) \ + asm(EMIT2(btl,KONST(0),VAR(C_FLAG)) \ "rcr $1, %0" \ : "=r" (offset) \ : "0" (offset)); @@ -752,27 +756,31 @@ static void count(u32 opcode, int cond_res) // OP Rd,Rb,Rm LSL Rs #ifndef VALUE_LSL_REG_C #define VALUE_LSL_REG_C \ - unsigned int shift = reg[(opcode >> 8)&15].B.B0; \ - if (LIKELY(shift)) { \ - if (shift == 32) { \ - value = 0; \ - C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\ - } else if (LIKELY(shift < 32)) { \ - u32 v = reg[opcode & 0x0F].I; \ - C_OUT = (v >> (32 - shift)) & 1 ? true : false;\ - value = v << shift; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } else { \ - value = reg[opcode & 0x0F].I; \ + u32 shift = reg[(opcode >> 8)&15].B.B0; \ + u32 rm = reg[opcode & 0x0F].I; \ + if((opcode & 0x0F) == 15) { \ + rm += 4; \ + } \ + if (LIKELY(shift)) { \ + if (shift == 32) { \ + value = 0; \ + C_OUT = (rm & 1 ? true : false); \ + } else if (LIKELY(shift < 32)) { \ + u32 v = rm; \ + C_OUT = (v >> (32 - shift)) & 1 ? true : false; \ + value = v << shift; \ + } else { \ + value = 0; \ + C_OUT = false; \ + } \ + } else { \ + value = rm; \ } #endif // OP Rd,Rb,Rm LSR # #ifndef VALUE_LSR_IMM_C #define VALUE_LSR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ + u32 shift = (opcode >> 7) & 0x1F; \ if (LIKELY(shift)) { \ u32 v = reg[opcode & 0x0F].I; \ 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 #define VALUE_LSR_REG_C \ 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 (shift == 32) { \ value = 0; \ - C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\ + C_OUT = (rm & 0x80000000 ? true : false);\ } else if (LIKELY(shift < 32)) { \ - u32 v = reg[opcode & 0x0F].I; \ + u32 v = rm; \ C_OUT = (v >> (shift - 1)) & 1 ? true : false;\ value = v >> shift; \ } else { \ @@ -799,7 +811,7 @@ static void count(u32 opcode, int cond_res) C_OUT = false; \ } \ } else { \ - value = reg[opcode & 0x0F].I; \ + value = rm; \ } #endif // OP Rd,Rb,Rm ASR # @@ -825,13 +837,17 @@ static void count(u32 opcode, int cond_res) #ifndef VALUE_ASR_REG_C #define VALUE_ASR_REG_C \ 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)) { \ - s32 v = reg[opcode & 0x0F].I; \ + s32 v = rm; \ C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\ value = v >> (int)shift; \ } else { \ - value = reg[opcode & 0x0F].I; \ + value = rm; \ } \ } else { \ if (reg[opcode & 0x0F].I & 0x80000000) { \ @@ -863,13 +879,17 @@ static void count(u32 opcode, int cond_res) #ifndef VALUE_ROR_REG_C #define VALUE_ROR_REG_C \ 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)) { \ - u32 v = reg[opcode & 0x0F].I; \ + u32 v = rm; \ C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ value = ((v << (32 - shift)) | \ (v >> shift)); \ } else { \ - value = reg[opcode & 0x0F].I; \ + value = rm; \ if (shift) \ C_OUT = (value & 0x80000000 ? true : false);\ } @@ -950,9 +970,9 @@ static void count(u32 opcode, int cond_res) #endif #ifndef OP_RSB #define OP_RSB \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = rhs - lhs; \ + u32 lhs = value; \ + u32 rhs = reg[(opcode>>16)&15].I; \ + u32 res = lhs - rhs; \ reg[dest].I = res; #endif #ifndef OP_RSBS @@ -990,9 +1010,9 @@ static void count(u32 opcode, int cond_res) #endif #ifndef OP_RSC #define OP_RSC \ - u32 lhs = reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = rhs - lhs - !((u32)C_FLAG); \ + u32 lhs = value; \ + u32 rhs = reg[(opcode>>16)&15].I; \ + u32 res = lhs - rhs - !((u32)C_FLAG); \ reg[dest].I = res; #endif #ifndef OP_RSCS @@ -1516,7 +1536,7 @@ static INSN_REGPARM void arm121(u32 opcode) #define OP_LDR reg[dest].I = CPUReadMemory(address) #define OP_LDRH reg[dest].I = CPUReadHalfWord(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 WRITEBACK_NONE /*nothing*/ @@ -2591,8 +2611,7 @@ static INSN_REGPARM void armA00(u32 opcode) reg[15].I += 4; ARM_PREFETCH; clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); + clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1; busPrefetchCount = 0; } @@ -2608,8 +2627,7 @@ static INSN_REGPARM void armB00(u32 opcode) reg[15].I += 4; ARM_PREFETCH; clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); + clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1; busPrefetchCount = 0; } @@ -2627,9 +2645,8 @@ static INSN_REGPARM void armE01(u32 opcode) // SWI static INSN_REGPARM void armF00(u32 opcode) { - clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1; busPrefetchCount = 0; CPUSoftwareInterrupt(opcode & 0x00FFFFFF); } @@ -2681,9 +2698,9 @@ static insnfunc_t armInsnTable[4096] = { arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0 arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8 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,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 arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108 @@ -2946,4 +2963,4 @@ int armExecute() } while (cpuTotalTicks>3)&7)].I; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; +} + // MOV Rd, Hs static INSN_REGPARM void thumb46_1(u32 opcode) { reg[opcode&7].I = reg[((opcode>>3)&7)+8].I; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; } // MOV Hd, Rs @@ -1466,16 +1474,14 @@ static INSN_REGPARM void thumb47(u32 opcode) armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) - + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3; + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3; } else { armState = true; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; ARM_PREFETCH; - clockTicks = codeTicksAccessSeq32(armNextPC) - + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3; + clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3; } } @@ -1569,7 +1575,7 @@ static INSN_REGPARM void thumb5E(u32 opcode) if (busPrefetchCount == 0) busPrefetch = busPrefetchEnable; 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); } @@ -1662,6 +1668,7 @@ static INSN_REGPARM void thumbA0(u32 opcode) { u8 regist = (opcode >> 8) & 7; reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + clockTicks = 1 + codeTicksAccess16(armNextPC); } // ADD R0~R7, SP, Imm @@ -1669,6 +1676,7 @@ static INSN_REGPARM void thumbA8(u32 opcode) { u8 regist = (opcode >> 8) & 7; reg[regist].I = reg[13].I + ((opcode&255)<<2); + clockTicks = 1 + codeTicksAccess16(armNextPC); } // ADD SP, Imm @@ -1678,6 +1686,7 @@ static INSN_REGPARM void thumbB0(u32 opcode) if(opcode & 0x80) offset = -offset; reg[13].I += offset; + clockTicks = 1 + codeTicksAccess16(armNextPC); } // Push and pop /////////////////////////////////////////////////////////// @@ -1875,13 +1884,13 @@ static INSN_REGPARM void thumbC8(u32 opcode) static INSN_REGPARM void thumbD0(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1890,13 +1899,13 @@ static INSN_REGPARM void thumbD0(u32 opcode) static INSN_REGPARM void thumbD1(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1905,13 +1914,13 @@ static INSN_REGPARM void thumbD1(u32 opcode) static INSN_REGPARM void thumbD2(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(C_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1920,13 +1929,13 @@ static INSN_REGPARM void thumbD2(u32 opcode) static INSN_REGPARM void thumbD3(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!C_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1935,13 +1944,13 @@ static INSN_REGPARM void thumbD3(u32 opcode) static INSN_REGPARM void thumbD4(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(N_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1950,13 +1959,13 @@ static INSN_REGPARM void thumbD4(u32 opcode) static INSN_REGPARM void thumbD5(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!N_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1965,13 +1974,13 @@ static INSN_REGPARM void thumbD5(u32 opcode) static INSN_REGPARM void thumbD6(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1980,13 +1989,13 @@ static INSN_REGPARM void thumbD6(u32 opcode) static INSN_REGPARM void thumbD7(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1995,13 +2004,13 @@ static INSN_REGPARM void thumbD7(u32 opcode) static INSN_REGPARM void thumbD8(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(C_FLAG && !Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2010,13 +2019,13 @@ static INSN_REGPARM void thumbD8(u32 opcode) static INSN_REGPARM void thumbD9(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!C_FLAG || Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2025,13 +2034,13 @@ static INSN_REGPARM void thumbD9(u32 opcode) static INSN_REGPARM void thumbDA(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(N_FLAG == V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2040,13 +2049,13 @@ static INSN_REGPARM void thumbDA(u32 opcode) static INSN_REGPARM void thumbDB(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(N_FLAG != V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2055,13 +2064,13 @@ static INSN_REGPARM void thumbDB(u32 opcode) static INSN_REGPARM void thumbDC(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!Z_FLAG && (N_FLAG == V_FLAG)) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2070,13 +2079,13 @@ static INSN_REGPARM void thumbDC(u32 opcode) static INSN_REGPARM void thumbDD(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC); if(Z_FLAG || (N_FLAG != V_FLAG)) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2087,8 +2096,8 @@ static INSN_REGPARM void thumbDD(u32 opcode) static INSN_REGPARM void thumbDF(u32 opcode) { u32 address = 0; - clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) + - codeTicksAccess16(address)+3; + //clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3; + clockTicks = 3; busPrefetchCount=0; CPUSoftwareInterrupt(opcode & 0xFF); } @@ -2103,8 +2112,7 @@ static INSN_REGPARM void thumbE0(u32 opcode) armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC) + 3; + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3; busPrefetchCount=0; } @@ -2134,8 +2142,7 @@ static INSN_REGPARM void thumbF8(u32 opcode) reg[15].I += 2; reg[14].I = temp|1; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3; + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3; 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 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,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, thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48, diff --git a/source/vba/gba/GBA.cpp b/source/vba/gba/GBA.cpp index 7c25f5d..b728bfe 100644 --- a/source/vba/gba/GBA.cpp +++ b/source/vba/gba/GBA.cpp @@ -19,6 +19,8 @@ #include "../common/Port.h" #include "../System.h" #include "agbprint.h" +#include "GBALink.h" + #ifdef PROFILING #include "prof/prof.h" #endif @@ -27,17 +29,8 @@ #define _stricmp strcasecmp #endif - extern int emulating; -#ifdef LINK_EMULATION -extern int linktime; -extern void StartLink(u16); -extern void StartJOYLink(u16); -extern void StartGPLink(u16); -extern void LinkSSend(u16); -extern void LinkUpdate(int); -extern int linktime2; -#endif + int SWITicks = 0; int IRQTicks = 0; @@ -126,6 +119,9 @@ int capture = 0; int capturePrevious = 0; int captureNumber = 0; +int armOpcodeCount = 0; +int thumbOpcodeCount = 0; + const int TIMER_TICKS[4] = { 0, 6, @@ -525,11 +521,11 @@ void CPUUpdateWindow0() int x01 = WIN0H & 255; if(x00 <= x01) { - for(int i = 0; i < 240; ++i) { + for(int i = 0; i < 240; i++) { gfxInWin0[i] = (i >= x00 && i < x01); } } else { - for(int i = 0; i < 240; ++i) { + for(int i = 0; i < 240; i++) { gfxInWin0[i] = (i >= x00 || i < x01); } } @@ -541,11 +537,11 @@ void CPUUpdateWindow1() int x01 = WIN1H & 255; if(x00 <= x01) { - for(int i = 0; i < 240; ++i) { + for(int i = 0; i < 240; i++) { gfxInWin1[i] = (i >= x00 && i < x01); } } else { - for(int i = 0; i < 240; ++i) { + for(int i = 0; i < 240; i++) { gfxInWin1[i] = (i >= x00 || i < x01); } } @@ -580,6 +576,44 @@ void CPUUpdateRenderBuffers(bool force) } } +#ifdef __LIBRETRO__ +#include + +unsigned int CPUWriteState(u8* data, unsigned size) +{ + uint8_t *orig = data; + + utilWriteIntMem(data, SAVE_GAME_VERSION); + utilWriteMem(data, &rom[0xa0], 16); + utilWriteIntMem(data, useBios); + utilWriteMem(data, ®[0], sizeof(reg)); + + utilWriteDataMem(data, saveGameStruct); + + utilWriteIntMem(data, stopState); + utilWriteIntMem(data, IRQTicks); + + utilWriteMem(data, internalRAM, 0x8000); + utilWriteMem(data, paletteRAM, 0x400); + utilWriteMem(data, workRAM, 0x40000); + utilWriteMem(data, vram, 0x20000); + utilWriteMem(data, oam, 0x400); + utilWriteMem(data, pix, 4 * 241 * 162); + utilWriteMem(data, ioMem, 0x400); + + eepromSaveGame(data); + flashSaveGame(data); + soundSaveGame(data); + rtcSaveGame(data); + + return (ptrdiff_t)data - (ptrdiff_t)orig; +} + +bool CPUWriteMemState(char *memory, int available) +{ + return false; +} +#else static bool CPUWriteState(gzFile gzFile) { utilWriteInt(gzFile, SAVE_GAME_VERSION); @@ -633,6 +667,7 @@ bool CPUWriteState(const char *file) return res; } + bool CPUWriteMemState(char *memory, int available) { gzFile gzFile = utilMemGzOpen(memory, available, "w"); @@ -652,7 +687,108 @@ bool CPUWriteMemState(char *memory, int available) return res; } +#endif + +#ifdef __LIBRETRO__ +bool CPUReadState(const u8* data, unsigned size) +{ + // Don't really care about version. + int version = utilReadIntMem(data); + if (version != SAVE_GAME_VERSION) + return false; + + char romname[16]; + utilReadMem(romname, data, 16); + if (memcmp(&rom[0xa0], romname, 16) != 0) + return false; + + // Don't care about use bios ... + utilReadIntMem(data); + + utilReadMem(®[0], data, sizeof(reg)); + + utilReadDataMem(data, saveGameStruct); + + stopState = utilReadIntMem(data) ? true : false; + + IRQTicks = utilReadIntMem(data); + if (IRQTicks > 0) + intState = true; + else + { + intState = false; + IRQTicks = 0; + } + + utilReadMem(internalRAM, data, 0x8000); + utilReadMem(paletteRAM, data, 0x400); + utilReadMem(workRAM, data, 0x40000); + utilReadMem(vram, data, 0x20000); + utilReadMem(oam, data, 0x400); + utilReadMem(pix, data, 4*241*162); + utilReadMem(ioMem, data, 0x400); + + eepromReadGame(data, version); + flashReadGame(data, version); + soundReadGame(data, version); + rtcReadGame(data); + + //// Copypasta stuff ... + // set pointers! + layerEnable = layerSettings & DISPCNT; + + CPUUpdateRender(); + + // CPU Update Render Buffers set to true + CLEAR_ARRAY(line0); + CLEAR_ARRAY(line1); + CLEAR_ARRAY(line2); + CLEAR_ARRAY(line3); + // End of CPU Update Render Buffers set to true + + CPUUpdateWindow0(); + CPUUpdateWindow1(); + gbaSaveType = 0; + switch(saveType) { + case 0: + cpuSaveGameFunc = flashSaveDecide; + break; + case 1: + cpuSaveGameFunc = sramWrite; + gbaSaveType = 1; + break; + case 2: + cpuSaveGameFunc = flashWrite; + gbaSaveType = 2; + break; + case 3: + break; + case 5: + gbaSaveType = 5; + break; + default: +#ifdef CELL_VBA_DEBUG + systemMessage(MSG_UNSUPPORTED_SAVE_TYPE, + N_("Unsupported save type %d"), saveType); +#endif + break; + } + if(eepromInUse) + gbaSaveType = 3; + + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + if(armState) { + ARM_PREFETCH; + } else { + THUMB_PREFETCH; + } + + CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); + + return true; +} +#else static bool CPUReadState(gzFile gzFile) { int version = utilReadInt(gzFile); @@ -849,6 +985,7 @@ bool CPUReadState(const char * file) return res; } +#endif bool CPUExportEepromFile(const char *fileName) { @@ -940,7 +1077,7 @@ bool CPUReadGSASnapshot(const char *fileName) fseek(file, 0x0, SEEK_SET); fread(&i, 1, 4, file); fseek(file, i, SEEK_CUR); // Skip SharkPortSave - fseek(file, 4, SEEK_CUR); // skip some sort of flag +// fseek(file, 4, SEEK_CUR); // skip some sort of flag fread(&i, 1, 4, file); // name length fseek(file, i, SEEK_CUR); // skip name fread(&i, 1, 4, file); // desc length @@ -988,6 +1125,62 @@ bool CPUReadGSASnapshot(const char *fileName) return true; } +bool CPUReadGSASPSnapshot(const char *fileName) +{ + const char gsvfooter[] = "xV4\x12"; + const size_t namepos=0x0c, namesz=12; + const size_t footerpos=0x42c, footersz=4; + + char footer[footersz+1], romname[namesz+1], savename[namesz+1];; + FILE *file = fopen(fileName, "rb"); + + if(!file) { + systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); + return false; + } + + // read save name + fseek(file, namepos, SEEK_SET); + fread(savename, 1, namesz, file); + savename[namesz] = 0; + + memcpy(romname, &rom[0xa0], namesz); + romname[namesz] = 0; + + if(memcmp(romname, savename, namesz)) { + systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR, + N_("Cannot import snapshot for %s. Current game is %s"), + savename, + romname); + fclose(file); + return false; + } + + // read footer tag + fseek(file, footerpos, SEEK_SET); + fread(footer, 1, footersz, file); + footer[footersz] = 0; + + if(memcmp(footer, gsvfooter, footersz)) { + systemMessage(0, + N_("Unsupported snapshot file %s. Footer '%s' at %u should be '%s'"), + fileName, + footer, + footerpos, + gsvfooter); + fclose(file); + return false; + } + + // Read up to 128k save + fread(flashSaveMemory, 1, FLASH_128K_SZ, file); + + fclose(file); + CPUReset(); + return true; +} + + bool CPUWriteGSASnapshot(const char *fileName, const char *title, const char *desc, @@ -1084,8 +1277,10 @@ bool CPUImportEepromFile(const char *fileName) i++; i += 4; } - } else + } else { + fclose(file); return false; + } fclose(file); return true; } @@ -1130,12 +1325,12 @@ bool CPUReadBatteryFile(const char *fileName) bool CPUWritePNGFile(const char *fileName) { - return false; //utilWritePNGFile(fileName, 240, 160, pix); + return utilWritePNGFile(fileName, 240, 160, pix); } bool CPUWriteBMPFile(const char *fileName) { - return false; //utilWriteBMPFile(fileName, 240, 160, pix); + return utilWriteBMPFile(fileName, 240, 160, pix); } bool CPUIsZipFile(const char * file) @@ -1201,6 +1396,9 @@ bool CPUIsGBABios(const char * file) bool CPUIsELF(const char *file) { + if(file == NULL) + return false; + if(strlen(file) > 4) { const char * p = strrchr(file,'.'); @@ -1296,7 +1494,7 @@ int CPULoadRom(const char *szFile) return 0; } - //u8 *whereToLoad = cpuIsMultiBoot ? workRAM : rom; + u8 *whereToLoad = cpuIsMultiBoot ? workRAM : rom; #ifndef NO_DEBUGGER if(CPUIsELF(szFile)) { @@ -1321,15 +1519,18 @@ int CPULoadRom(const char *szFile) } } else #endif //NO_DEBUGGER -/* if(!utilLoad(szFile, - utilIsGBAImage, - whereToLoad, - romSize)) { - free(rom); - rom = NULL; - free(workRAM); - workRAM = NULL; - return 0; + if(szFile!=NULL) + { + if(!utilLoad(szFile, + utilIsGBAImage, + whereToLoad, + romSize)) { + free(rom); + rom = NULL; + free(workRAM); + workRAM = NULL; + return 0; + } } u16 *temp = (u16 *)(rom+((romSize+1)&~1)); @@ -1337,7 +1538,7 @@ int CPULoadRom(const char *szFile) for(i = (romSize+1)&~1; i < 0x2000000; i+=2) { WRITE16LE(temp, (i >> 1) & 0xFFFF); temp++; - }*/ + } bios = (u8 *)calloc(1,0x4000); if(bios == NULL) { @@ -1748,8 +1949,8 @@ void CPUSoftwareInterrupt(int comment) case 0x02: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_SWI) { - log("Halt: (VCOUNT = %2d)\n", - VCOUNT); + /*log("Halt: (VCOUNT = %2d)\n", + VCOUNT);*/ } #endif holdState = true; @@ -1759,8 +1960,8 @@ void CPUSoftwareInterrupt(int comment) case 0x03: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_SWI) { - log("Stop: (VCOUNT = %2d)\n", - VCOUNT); + /*log("Stop: (VCOUNT = %2d)\n", + VCOUNT);*/ } #endif holdState = true; @@ -2000,7 +2201,7 @@ void CPUCompareVCOUNT() } if (layerEnableDelay>0) { - --layerEnableDelay; + layerEnableDelay--; if (layerEnableDelay==1) layerEnable = layerSettings & DISPCNT; } @@ -2015,6 +2216,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) int dw = 0; int sc = c; + cpuDmaHack = true; cpuDmaCount = c; // This is done to get the correct waitstates. if (sm>15) @@ -2031,7 +2233,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) while(c != 0) { CPUWriteMemory(d, 0); d += di; - --c; + c--; } } else { while(c != 0) { @@ -2039,7 +2241,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) CPUWriteMemory(d, cpuDmaLast); d += di; s += si; - --c; + c--; } } } else { @@ -2050,7 +2252,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) while(c != 0) { CPUWriteHalfWord(d, 0); d += di; - --c; + c--; } } else { while(c != 0) { @@ -2059,7 +2261,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) cpuDmaLast |= (cpuDmaLast<<16); d += di; s += si; - --c; + c--; } } } @@ -2083,7 +2285,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) } cpuDmaTicksToUpdate += totalTicks; - + cpuDmaHack = false; } void CPUCheckDMA(int reason, int dmamask) @@ -2126,7 +2328,6 @@ void CPUCheckDMA(int reason, int dmamask) doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, DM0CNT_L ? DM0CNT_L : 0x4000, DM0CNT_H & 0x0400); - cpuDmaHack = true; if(DM0CNT_H & 0x4000) { IF |= 0x0100; @@ -2195,7 +2396,6 @@ void CPUCheckDMA(int reason, int dmamask) DM1CNT_L ? DM1CNT_L : 0x4000, DM1CNT_H & 0x0400); } - cpuDmaHack = true; if(DM1CNT_H & 0x4000) { IF |= 0x0200; @@ -2265,7 +2465,6 @@ void CPUCheckDMA(int reason, int dmamask) DM2CNT_L ? DM2CNT_L : 0x4000, DM2CNT_H & 0x0400); } - cpuDmaHack = true; if(DM2CNT_H & 0x4000) { IF |= 0x0400; @@ -2322,6 +2521,7 @@ void CPUCheckDMA(int reason, int dmamask) doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, DM3CNT_L ? DM3CNT_L : 0x10000, DM3CNT_H & 0x0400); + if(DM3CNT_H & 0x4000) { IF |= 0x0800; UPDATE_REG(0x202, IF); @@ -2368,7 +2568,7 @@ void CPUUpdateRegister(u32 address, u16 value) windowOn = (layerEnable & 0x6000) ? true : false; if(change && !((value & 0x80))) { if(!(DISPSTAT & 1)) { - lcdTicks = 1008; + //lcdTicks = 1008; // VCOUNT = 0; // UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFC; @@ -2763,61 +2963,65 @@ void CPUUpdateRegister(u32 address, u16 value) timerOnOffDelay|=8; cpuNextEvent = cpuTotalTicks; break; - case 0x128: -#ifdef LINK_EMULATION - if (linkenable) - { - StartLink(value); - } - else + + +#ifndef NO_LINK + case COMM_SIOCNT: + StartLink(value); + break; + + case COMM_SIODATA8: + UPDATE_REG(COMM_SIODATA8, value); + break; #endif - { - if(value & 0x80) { - value &= 0xff7f; - if(value & 1 && (value & 0x4000)) { - UPDATE_REG(0x12a, 0xFF); - IF |= 0x80; - UPDATE_REG(0x202, IF); - value &= 0x7f7f; - } - } - UPDATE_REG(0x128, value); - } - break; - case 0x12a: -#ifdef LINK_EMULATION - if(linkenable && lspeed) - LinkSSend(value); -#endif - { - UPDATE_REG(0x134, value); - } - break; + case 0x130: - P1 |= (value & 0x3FF); - UPDATE_REG(0x130, P1); - break; + P1 |= (value & 0x3FF); + UPDATE_REG(0x130, P1); + break; + case 0x132: - UPDATE_REG(0x132, value & 0xC3FF); - break; - case 0x134: -#ifdef LINK_EMULATION - if (linkenable) - StartGPLink(value); - else -#endif - UPDATE_REG(0x134, value); + UPDATE_REG(0x132, value & 0xC3FF); + break; - break; - case 0x140: -#ifdef LINK_EMULATION - if (linkenable) - StartJOYLink(value); - else -#endif - UPDATE_REG(0x140, value); +#ifndef NO_LINK + case COMM_RCNT: + StartGPLink(value); + break; + + case COMM_JOYCNT: + { + u16 cur = READ16LE(&ioMem[COMM_JOYCNT]); + + if (value & JOYCNT_RESET) cur &= ~JOYCNT_RESET; + if (value & JOYCNT_RECV_COMPLETE) cur &= ~JOYCNT_RECV_COMPLETE; + if (value & JOYCNT_SEND_COMPLETE) cur &= ~JOYCNT_SEND_COMPLETE; + if (value & JOYCNT_INT_ENABLE) cur |= JOYCNT_INT_ENABLE; + + UPDATE_REG(COMM_JOYCNT, cur); + } + break; + + case COMM_JOY_RECV_L: + UPDATE_REG(COMM_JOY_RECV_L, value); + break; + case COMM_JOY_RECV_H: + UPDATE_REG(COMM_JOY_RECV_H, value); + break; + + case COMM_JOY_TRANS_L: + UPDATE_REG(COMM_JOY_TRANS_L, value); + UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) | JOYSTAT_SEND); + break; + case COMM_JOY_TRANS_H: + UPDATE_REG(COMM_JOY_TRANS_H, value); + break; + + case COMM_JOYSTAT: + UPDATE_REG(COMM_JOYSTAT, (READ16LE(&ioMem[COMM_JOYSTAT]) & 0xf) | (value & 0xf0)); + break; +#endif - break; case 0x200: IE = value & 0x3FFF; UPDATE_REG(0x200, IE); @@ -2857,7 +3061,7 @@ void CPUUpdateRegister(u32 address, u16 value) for(int i = 8; i < 15; i++) { memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1; - memoryWaitSeq32[i] = (memoryWaitSeq[i]<<1) + 1; + memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1; } if((value & 0x4000) == 0x4000) { @@ -2969,7 +3173,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile) saveType = 0; useBios = false; -/* if(useBiosFile) { + if(useBiosFile) { int size = 0x4000; if(utilLoad(biosFileName, CPUIsGBABios, @@ -2980,7 +3184,7 @@ void CPUInit(const char *biosFileName, bool useBiosFile) else systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BIOS file size")); } - }*/ + } if(!useBios) { memcpy(bios, myROM, sizeof(myROM)); @@ -3052,7 +3256,6 @@ void CPUInit(const char *biosFileName, bool useBiosFile) void CPUReset() { - systemCartridgeRumble(false); if(gbaSaveType == 0) { if(eepromInUse) gbaSaveType = 3; @@ -3349,7 +3552,7 @@ void CPUReset() cpuDmaHack = false; - //lastTime = systemGetClock(); + lastTime = systemGetClock(); SWITicks = 0; } @@ -3383,10 +3586,13 @@ void CPULoop(int ticks) int timerOverflow = 0; // variable used by the CPU core cpuTotalTicks = 0; -#ifdef LINK_EMULATION - if(linkenable) + +#ifndef NO_LINK + // shuffle2: what's the purpose? + if(gba_link_enabled) cpuNextEvent = 1; #endif + cpuBreakLoop = false; cpuNextEvent = CPUUpdateTicks(); if(cpuNextEvent > ticks) @@ -3401,39 +3607,31 @@ void CPULoop(int ticks) #ifdef BKPT_SUPPORT if (debugger_last) { - sprintf(buffer, "R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n", + winlog("R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n", oldreg[0], oldreg[1], oldreg[2], oldreg[3], oldreg[4], oldreg[5], oldreg[6], oldreg[7], oldreg[8], oldreg[9], oldreg[10], oldreg[11], oldreg[12], oldreg[13], oldreg[14], oldreg[15], oldreg[16], oldreg[17]); } #endif - sprintf(buffer, "R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n", + winlog("R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n", reg[0].I, reg[1].I, reg[2].I, reg[3].I, reg[4].I, reg[5].I, reg[6].I, reg[7].I, reg[8].I, reg[9].I, reg[10].I, reg[11].I, reg[12].I, reg[13].I, reg[14].I, reg[15].I, reg[16].I, reg[17].I); -#ifdef SDL - log(buffer); -#else - winlog(buffer); -#endif } else if(!holdState) { - sprintf(buffer, "PC=%08x\n", armNextPC); -#ifdef SDL - log(buffer); -#else - winlog(buffer); -#endif + winlog("PC=%08x\n", armNextPC); } } #endif /* FINAL_VERSION */ if(!holdState && !SWITicks) { if(armState) { + armOpcodeCount++; if (!armExecute()) return; } else { + thumbOpcodeCount++; if (!thumbExecute()) return; } @@ -3456,7 +3654,6 @@ void CPULoop(int ticks) clockTicks = cpuNextEvent; cpuTotalTicks = 0; - cpuDmaHack = false; updateLoop: @@ -3475,7 +3672,7 @@ void CPULoop(int ticks) // if in V-Blank mode, keep computing... if(DISPSTAT & 2) { lcdTicks += 1008; - ++VCOUNT; + VCOUNT++; UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFD; UPDATE_REG(0x04, DISPSTAT); @@ -3490,7 +3687,7 @@ void CPULoop(int ticks) } } - if(VCOUNT >= 228) { //Reaching last line + if(VCOUNT > 227) { //Reaching last line DISPSTAT &= 0xFFFC; UPDATE_REG(0x04, DISPSTAT); VCOUNT = 0; @@ -3504,26 +3701,26 @@ void CPULoop(int ticks) if(DISPSTAT & 2) { // if in H-Blank, leave it and move to drawing mode - ++VCOUNT; + VCOUNT++; UPDATE_REG(0x06, VCOUNT); lcdTicks += 1008; DISPSTAT &= 0xFFFD; if(VCOUNT == 160) { - ++count; + count++; systemFrame(); if((count % 10) == 0) { system10Frames(60); } if(count == 60) { - /*u32 time = systemGetClock(); + u32 time = systemGetClock(); if(time != lastTime) { u32 t = 100000/(time - lastTime); systemShowSpeed(t); } else systemShowSpeed(0); - lastTime = time;*/ + lastTime = time; count = 0; } u32 joy = 0; @@ -3532,7 +3729,7 @@ void CPULoop(int ticks) // read default joystick joy = systemReadJoypad(-1); P1 = 0x03FF ^ (joy & 0x3FF); - //if(cpuEEPROMSensorEnabled) + if(cpuEEPROMSensorEnabled) systemUpdateMotionSensor(); UPDATE_REG(0x130, P1); u16 P1CNT = READ16LE(((u16 *)&ioMem[0x132])); @@ -3562,7 +3759,7 @@ void CPULoop(int ticks) capture = (ext & 2) ? true : false; if(capture && !capturePrevious) { - ++captureNumber; + captureNumber++; systemScreenCapture(captureNumber); } capturePrevious = capture; @@ -3579,7 +3776,7 @@ void CPULoop(int ticks) systemDrawScreen(); frameCount = 0; } else - ++frameCount; + frameCount++; if(systemPauseOnFrame()) ticks = 0; } @@ -3594,8 +3791,8 @@ void CPULoop(int ticks) switch(systemColorDepth) { case 16: { - u16 *dest = (u16 *)pix + 242 * (VCOUNT+1); - for(u32 x = 0; x < 240u;) { + u16 *dest = (u16 *)pix + 242 * VCOUNT; + for(int x = 0; x < 240;) { *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; *dest++ = systemColorMap16[lineMix[x++]&0xFFFF]; @@ -3622,8 +3819,8 @@ void CPULoop(int ticks) break; case 24: { - u8 *dest = (u8 *)pix + VCOUNT * 720; - for(u32 x = 0; x < 240u;) { + u8 *dest = (u8 *)pix + 240 * VCOUNT * 3; + for(int x = 0; x < 240;) { *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; dest += 3; *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF]; @@ -3664,8 +3861,8 @@ void CPULoop(int ticks) break; case 32: { - u32 *dest = (u32 *)pix + 241 * (VCOUNT+1); - for(u32 x = 0; x < 240u; ) { + u32 *dest = (u32 *)pix + 241 * VCOUNT; + for(int x = 0; x < 240; ) { *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; @@ -3731,7 +3928,7 @@ void CPULoop(int ticks) if(timer1On) { if(TM1CNT & 4) { if(timerOverflow & 1) { - ++TM1D; + TM1D++; if(TM1D == 0) { TM1D += timer1Reload; timerOverflow |= 2; @@ -3762,7 +3959,7 @@ void CPULoop(int ticks) if(timer2On) { if(TM2CNT & 4) { if(timerOverflow & 2) { - ++TM2D; + TM2D++; if(TM2D == 0) { TM2D += timer2Reload; timerOverflow |= 4; @@ -3791,7 +3988,7 @@ void CPULoop(int ticks) if(timer3On) { if(TM3CNT & 4) { if(timerOverflow & 4) { - ++TM3D; + TM3D++; if(TM3D == 0) { TM3D += timer3Reload; if(TM3CNT & 0x40) { @@ -3841,10 +4038,15 @@ void CPULoop(int ticks) #endif ticks -= clockTicks; -#ifdef LINK_EMULATION - if (linkenable) + + if (gba_joybus_enabled) + JoyBusUpdate(clockTicks); + +#ifndef NO_LINK + if (gba_link_enabled) LinkUpdate(clockTicks); #endif + cpuNextEvent = CPUUpdateTicks(); if(cpuDmaTicksToUpdate > 0) { @@ -3855,13 +4057,15 @@ void CPULoop(int ticks) cpuDmaTicksToUpdate -= clockTicks; if(cpuDmaTicksToUpdate < 0) cpuDmaTicksToUpdate = 0; - cpuDmaHack = true; goto updateLoop; } -#ifdef LINK_EMULATION - if(linkenable) + +#ifndef NO_LINK + // shuffle2: what's the purpose? + if(gba_link_enabled) cpuNextEvent = 1; #endif + if(IF && (IME & 1) && armIrqEnable) { int res = IF & IE; if(stopState) @@ -3927,6 +4131,272 @@ void CPULoop(int ticks) } } +#ifdef TILED_RENDERING +union u8h +{ + struct +#ifndef WORDS_BIGENDIAN + { + /* 0*/ unsigned char lo:4; + /* 4*/ unsigned char hi:4; +#else + { + /* 4*/ unsigned char hi:4; + /* 0*/ unsigned char lo:4; +#endif + } __attribute__ ((packed)); + u8 val; +}; + +union TileEntry +{ +#ifndef WORDS_BIGENDIAN + struct + { + /* 0*/ unsigned tileNum:10; + /*12*/ unsigned hFlip:1; + /*13*/ unsigned vFlip:1; + /*14*/ unsigned palette:4; + }; +#else + struct + { + /*14*/ unsigned palette:4; + /*13*/ unsigned vFlip:1; + /*12*/ unsigned hFlip:1; + /* 0*/ unsigned tileNum:10; + }; +#endif + u16 val; +}; + +struct TileLine +{ + u32 pixels[8]; +}; + +typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32); + +static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio) +{ + *dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000; +} + +inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio) +{ + TileEntry tile; + tile.val = READ16LE(screenSource); + + int tileY = yyy & 7; + if (tile.vFlip) tileY = 7 - tileY; + TileLine tileLine; + + const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8]; + + if (!tile.hFlip) + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio); + } + else + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio); + } + + return tileLine; +} + +inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio) +{ + TileEntry tile; + tile.val = READ16LE(screenSource); + + int tileY = yyy & 7; + if (tile.vFlip) tileY = 7 - tileY; + palette += tile.palette * 16; + TileLine tileLine; + + const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4]; + + if (!tile.hFlip) + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio); + } + else + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio); + } + + return tileLine; +} + +static inline void gfxDrawTile(const TileLine &tileLine, u32 *line) +{ + memcpy(line, tileLine.pixels, sizeof(tileLine.pixels)); +} + +static inline void gfxDrawTileClipped(const TileLine &tileLine, u32 *line, const int start, int w) +{ + memcpy(line, tileLine.pixels + start, w * sizeof(u32)); +} + +template +static void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, + u32 *line) +{ + u16 *palette = (u16 *)paletteRAM; + u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; + u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; + u32 prio = ((control & 3)<<25) + 0x1000000; + int sizeX = 256; + int sizeY = 256; + switch ((control >> 14) & 3) + { + case 0: + break; + case 1: + sizeX = 512; + break; + case 2: + sizeY = 512; + break; + case 3: + sizeX = 512; + sizeY = 512; + break; + } + + int maskX = sizeX-1; + int maskY = sizeY-1; + + bool mosaicOn = (control & 0x40) ? true : false; + + int xxx = hofs & maskX; + int yyy = (vofs + VCOUNT) & maskY; + int mosaicX = (MOSAIC & 0x000F)+1; + int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; + + if (mosaicOn) + { + if ((VCOUNT % mosaicY) != 0) + { + mosaicY = VCOUNT - (VCOUNT % mosaicY); + yyy = (vofs + mosaicY) & maskY; + } + } + + if (yyy > 255 && sizeY > 256) + { + yyy &= 255; + screenBase += 0x400; + if (sizeX > 256) + screenBase += 0x400; + } + + int yshift = ((yyy>>3)<<5); + + u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; + int x = 0; + const int firstTileX = xxx & 7; + + // First tile, if clipped + if (firstTileX) + { + gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], firstTileX, 8 - firstTileX); + screenSource++; + x += 8 - firstTileX; + xxx += 8 - firstTileX; + + if (xxx == 256 && sizeX > 256) + { + screenSource = screenBase + 0x400 + yshift; + } + else if (xxx >= sizeX) + { + xxx = 0; + screenSource = screenBase + yshift; + } + } + + // Middle tiles, full + while (x < 240 - firstTileX) + { + gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &line[x]); + screenSource++; + xxx += 8; + x += 8; + + if (xxx == 256 && sizeX > 256) + { + screenSource = screenBase + 0x400 + yshift; + } + else if (xxx >= sizeX) + { + xxx = 0; + screenSource = screenBase + yshift; + } + } + + // Last tile, if clipped + if (firstTileX) + { + gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], 0, firstTileX); + } + + if (mosaicOn) + { + if (mosaicX > 1) + { + int m = 1; + for (int i = 0; i < 239; i++) + { + line[i+1] = line[i]; + m++; + if (m == mosaicX) + { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line) +{ + if (control & 0x80) // 1 pal / 256 col + gfxDrawTextScreen(control, hofs, vofs, line); + else // 16 pal / 16 col + gfxDrawTextScreen(control, hofs, vofs, line); +} +#endif struct EmulatedSystem GBASystem = { @@ -3945,7 +4415,11 @@ struct EmulatedSystem GBASystem = { // emuWriteState CPUWriteState, // emuReadMemState +#ifdef __LIBRETRO__ + NULL, +#else CPUReadMemState, +#endif // emuWriteMemState CPUWriteMemState, // emuWritePNG diff --git a/source/vba/gba/GBA.h b/source/vba/gba/GBA.h index 33dee51..1aaab80 100644 --- a/source/vba/gba/GBA.h +++ b/source/vba/gba/GBA.h @@ -78,6 +78,7 @@ extern char oldbuffer[10]; #endif extern bool CPUReadGSASnapshot(const char *); +extern bool CPUReadGSASPSnapshot(const char *); extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *); extern bool CPUWriteBatteryFile(const char *); extern bool CPUReadBatteryFile(const char *); @@ -89,9 +90,14 @@ extern void CPUCleanUp(); extern void CPUUpdateRender(); extern void CPUUpdateRenderBuffers(bool); extern bool CPUReadMemState(char *, int); -extern bool CPUReadState(const char *); 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 *); +#endif extern int CPULoadRom(const char *); extern void doMirroring(bool); extern void CPUUpdateRegister(u32, u16); diff --git a/source/vba/gba/GBAGfx.h b/source/vba/gba/GBAGfx.h index 4e55ff2..33ee6bd 100644 --- a/source/vba/gba/GBAGfx.h +++ b/source/vba/gba/GBAGfx.h @@ -8,7 +8,11 @@ //#define SPRITE_DEBUG +#ifdef TILED_RENDERING +extern void gfxDrawTextScreen(u16, u16, u16, u32 *); +#else static void gfxDrawTextScreen(u16, u16, u16, u32 *); +#endif static void gfxDrawRotScreen(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, u32 *line) { @@ -238,6 +243,7 @@ static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, } } } +#endif static inline void gfxDrawRotScreen(u16 control, u16 x_l, u16 x_h, diff --git a/source/vba/gba/GBALink.h b/source/vba/gba/GBALink.h new file mode 100644 index 0000000..c2d7024 --- /dev/null +++ b/source/vba/gba/GBALink.h @@ -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 +#include + +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 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 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 */ diff --git a/source/vba/gba/GBAcpu.h b/source/vba/gba/GBAcpu.h index 5a080b4..53fa2d3 100644 --- a/source/vba/gba/GBAcpu.h +++ b/source/vba/gba/GBAcpu.h @@ -5,8 +5,11 @@ extern int armExecute(); extern int thumbExecute(); #ifdef __GNUC__ +#ifndef __APPLE__ +# define INSN_REGPARM __attribute__((regparm(1))) +#else # define INSN_REGPARM /*nothing*/ - //# define INSN_REGPARM __attribute__((regparm(1))) +#endif # define LIKELY(x) __builtin_expect(!!(x),1) # define UNLIKELY(x) __builtin_expect(!!(x),0) #else diff --git a/source/vba/gba/GBAinline.h b/source/vba/gba/GBAinline.h index 66b2951..fe53a88 100644 --- a/source/vba/gba/GBAinline.h +++ b/source/vba/gba/GBAinline.h @@ -6,7 +6,8 @@ #include "RTC.h" #include "Sound.h" #include "agbprint.h" -#include "vmmem.h" // Nintendo GC Virtual Memory +#include "GBAcpu.h" +#include "GBALink.h" extern const u32 objTilesAddress[3]; @@ -33,103 +34,33 @@ extern bool timer3On; extern int timer3Ticks; extern int timer3ClockReload; extern int cpuTotalTicks; -extern u32 RomIdCode; -#define gid(a,b,c) (a|(b<<8)|(c<<16)) -#define CORVETTE gid('A','V','C') - -/***************************************************************************** - * Nintendo GC Virtual Memory function override - * Tantric September 2008 - ****************************************************************************/ - -#define CPUReadByteQuickDef(addr) \ +#define CPUReadByteQuick(addr) \ 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])) -#define CPUReadMemoryQuickDef(addr) \ +#define CPUReadMemoryQuick(addr) \ READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) -u8 inline CPUReadByteQuick( u32 addr ) -{ - switch(addr >> 24 ) - { - case 0x08: - case 0x09: - case 0x0A: - case 0x0C: -#ifdef USE_VM - return VMRead8( addr & 0x1FFFFFF ); -#endif - default: - return CPUReadByteQuickDef(addr); - } - - return 0; -} - -u16 inline CPUReadHalfWordQuick( u32 addr ) -{ - switch(addr >> 24) - { - case 0x08: - case 0x09: - case 0x0A: - case 0x0C: -#ifdef USE_VM - return VMRead16( addr & 0x1FFFFFF ); -#endif - default: - return CPUReadHalfWordQuickDef(addr); - } - - return 0; -} - -u32 inline CPUReadMemoryQuick( u32 addr ) -{ - switch(addr >> 24) - { - case 0x08: - case 0x09: - case 0x0A: - case 0x0C: -#ifdef USE_VM - return VMRead32( addr & 0x1FFFFFF ); -#endif - default: - return CPUReadMemoryQuickDef(addr); - } - - return 0; -} - -/***************************************************************************** - * End of VM override - ****************************************************************************/ - static inline u32 CPUReadMemory(u32 address) { -#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 oldAddress = address; + + if(address & 3) { + address &= ~0x03; + } + switch(address >> 24) { - case 0x00: + case 0: if(reg[15].I >> 24) { if(address < 0x4000) { #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + log("Illegal word read from bios: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); } #endif @@ -139,117 +70,92 @@ static inline u32 CPUReadMemory(u32 address) } else value = READ32LE(((u32 *)&bios[address & 0x3FFC])); break; - case 0x02: + case 2: value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); break; - case 0x03: + case 3: value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); break; - case 0x04: - if((address < 0x4000400) && ioReadable[address & 0x3fc]) { - if(ioReadable[(address & 0x3fc) + 2]) + case 4: + if((address < 0x4000400) && ioReadable[address & 0x3fc]) { + if(ioReadable[(address & 0x3fc) + 2]) { 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])); - } else goto unreadable; - break; - case 0x05: + } + } + else + goto unreadable; + break; + case 5: value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); break; - case 0x06: + case 6: address = (address & 0x1fffc); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) { - value = 0; - break; + value = 0; + break; } if ((address & 0x18000) == 0x18000) address &= 0x17fff; value = READ32LE(((u32 *)&vram[address])); break; - case 0x07: + case 7: value = READ32LE(((u32 *)&oam[address & 0x3FC])); break; - case 0x08: - // Must be cartridge ROM, reading other sensors doesn't allow 32-bit access. - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: -#ifdef USE_VM // Nintendo GC Virtual Memory - value = VMRead32( address & 0x1FFFFFC ); -#else - value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); -#endif + case 8: + case 9: + case 10: + case 11: + case 12: + value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); break; - case 0x0D: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; - case 0x0E: - // Yoshi's Universal Gravitation (Topsy Turvy) - // Koro Koro - if(cpuEEPROMSensorEnabled) { - switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); + case 13: + value = eepromRead(address); + break; + case 14: + case 15: + value = flashRead(address) * 0x01010101; + break; // default default: - unreadable: +unreadable: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + armNextPC - 4 : armNextPC - 2); } #endif - - if(cpuDmaHack) { - value = cpuDmaLast; - } else { + if(cpuDmaHack) { + value = cpuDmaLast; + } else { if(armState) { -#ifdef USE_VM // Nintendo GC Virtual Memory - value = CPUReadMemoryQuick(reg[15].I); -#else - value = CPUReadMemoryQuickDef(reg[15].I); -#endif + return CPUReadMemoryQuick(reg[15].I); } else { -#ifdef USE_VM // Nintendo GC Virtual Memory - value = CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; -#else - value = CPUReadHalfWordQuickDef(reg[15].I) | - CPUReadHalfWordQuickDef(reg[15].I) << 16; -#endif + return CPUReadHalfWordQuick(reg[15].I) | + CPUReadHalfWordQuick(reg[15].I) << 16; } - } + } + break; } - if(address & 3) { + if(oldAddress & 3) { #ifdef C_CORE - int shift = (address & 3) << 3; + int shift = (oldAddress & 3) << 3; value = (value >> shift) | (value << (32 - shift)); #else #ifdef __GNUC__ asm("and $3, %%ecx;" - "shl $3 ,%%ecx;" - "ror %%cl, %0" - : "=r" (value) - : "r" (value), "c" (address)); + "shl $3 ,%%ecx;" + "ror %%cl, %0" + : "=r" (value) + : "r" (value), "c" (oldAddress)); #else __asm { - mov ecx, address; + mov ecx, oldAddress; and ecx, 3; shl ecx, 3; ror [dword ptr value], cl; @@ -257,6 +163,15 @@ static inline u32 CPUReadMemory(u32 address) #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; } @@ -264,25 +179,21 @@ extern u32 myROM[]; 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 oldAddress = address; + + if(address & 1) { + address &= ~0x01; + } switch(address >> 24) { - case 0x00: + case 0: if (reg[15].I >> 24) { if(address < 0x4000) { #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + log("Illegal halfword read from bios: %08x at %08x\n", oldAddress, armMode ? + armNextPC - 4 : armNextPC - 2); } #endif value = READ16LE(((u16 *)&biosProtected[address&2])); @@ -290,13 +201,13 @@ static inline u32 CPUReadHalfWord(u32 address) } else value = READ16LE(((u16 *)&bios[address & 0x3FFE])); break; - case 0x02: + case 2: value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); break; - case 0x03: + case 3: value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); break; - case 0x04: + case 4: if((address < 0x4000400) && ioReadable[address & 0x3fe]) { value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); @@ -305,216 +216,182 @@ static inline u32 CPUReadHalfWord(u32 address) if (((address & 0x3fe) == 0x100) && timer0On) value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload); else - if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) - value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); - else - if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) - value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); - else - if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) - value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); + if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) + value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); + else + if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) + value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); + else + if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) + value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); } } + else if((address < 0x4000400) && ioReadable[address & 0x3fc]) + { + value = 0; + } else goto unreadable; break; - case 0x05: + case 5: value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); break; - case 0x06: + case 6: address = (address & 0x1fffe); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) { - value = 0; - break; + value = 0; + break; } if ((address & 0x18000) == 0x18000) address &= 0x17fff; value = READ16LE(((u16 *)&vram[address])); break; - case 0x07: + case 7: value = READ16LE(((u16 *)&oam[address & 0x3fe])); break; - case 0x08: - // Use existing case statement and faster test for potential speed improvement - // This is possibly the GPIO port that controls the real time clock, - // WarioWare Twisted! tilt sensors, rumble, and solar sensors. - if(address >= 0x80000c4 && address <= 0x80000c8) { - // this function still works if there is no real time clock - // and does a normal memory read in that case. - value = rtcRead(address & 0xFFFFFFE); - break; - } - case 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])); -#endif + case 8: + case 9: + case 10: + case 11: + case 12: + if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) + value = rtcRead(address); + else + value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); break; - case 0x0D: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; - case 0x0E: - // Yoshi's Universal Gravitation (Topsy Turvy) - // Koro Koro - if(cpuEEPROMSensorEnabled) { - switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); + case 13: + value = eepromRead(address); + break; + case 14: + case 15: + value = flashRead(address) * 0x0101; + break; // default default: - unreadable: +unreadable: + if(cpuDmaHack) { + value = cpuDmaLast & 0xFFFF; + } else { + if(armState) { + value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); + } else { + value = CPUReadHalfWordQuick(reg[15].I); + } + } #ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal halfword read: %08x at %08x (%08x)\n", oldAddress, reg[15].I, value); + } #endif - if(cpuDmaHack) { - value = cpuDmaLast & 0xFFFF; - } else { - if(armState) { -#ifdef USE_VM // Nintendo GC Virtual Memory - value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); -#else - value = CPUReadHalfWordQuickDef(reg[15].I + (address & 2)); -#endif - } else { -#ifdef USE_VM // Nintendo GC Virtual Memory - value = CPUReadHalfWordQuick(reg[15].I); -#else - value = CPUReadHalfWordQuickDef(reg[15].I); -#endif - } - } - break; + return value; } - if(address & 1) { - value = (value >> 8) | (value << 24); + if(oldAddress & 1) { + 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; } -static inline u16 CPUReadHalfWordSigned(u32 address) +static inline s16 CPUReadHalfWordSigned(u32 address) { - u16 value = CPUReadHalfWord(address); + s32 value = (s32)CPUReadHalfWord(address); 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) { switch(address >> 24) { - case 0x00: + case 0: if (reg[15].I >> 24) { if(address < 0x4000) { #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + log("Illegal byte read from bios: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); } #endif return biosProtected[address & 3]; } else goto unreadable; } return bios[address & 0x3FFF]; - case 0x02: + case 2: return workRAM[address & 0x3FFFF]; - case 0x03: + case 3: return internalRAM[address & 0x7fff]; - case 0x04: + case 4: if((address < 0x4000400) && ioReadable[address & 0x3ff]) return ioMem[address & 0x3ff]; else goto unreadable; - case 0x05: + case 5: return paletteRAM[address & 0x3ff]; - case 0x06: + case 6: address = (address & 0x1ffff); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return 0; + return 0; if ((address & 0x18000) == 0x18000) address &= 0x17fff; return vram[address]; - case 0x07: + case 7: return oam[address & 0x3ff]; - case 0x08: - // the real time clock doesn't support byte reads, so don't bother checking for it. - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: -#ifdef USE_VM // Nintendo GC Virtual Memory - return VMRead8( address & 0x1FFFFFF ); -#else + case 8: + case 9: + case 10: + case 11: + case 12: return rom[address & 0x1FFFFFF]; -#endif - case 0x0D: - if(cpuEEPROMEnabled) - return eepromRead(address); - goto unreadable; - case 0x0E: - // Yoshi's Universal Gravitation (Topsy Turvy) - // Koro Koro - if(cpuEEPROMSensorEnabled) { - switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } - if(cpuSramEnabled | cpuFlashEnabled) - return flashRead(address); + case 13: + return eepromRead(address); + case 14: + case 15: + { + if (cpuEEPROMSensorEnabled) { + switch (address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8) | 0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } + return flashRead(address); + } // default default: - unreadable: +unreadable: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_READ) { log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); + armNextPC - 4 : armNextPC - 2); } #endif - if(cpuDmaHack) { - return cpuDmaLast & 0xFF; - } else { - if(armState) { -#ifdef USE_VM // Nintendo GC Virtual Memory - return CPUReadByteQuick(reg[15].I+(address & 3)); -#else - return CPUReadByteQuickDef(reg[15].I+(address & 3)); -#endif - } else { -#ifdef USE_VM // Nintendo GC Virtual Memory - return CPUReadByteQuick(reg[15].I+(address & 1)); -#else - return CPUReadByteQuickDef(reg[15].I+(address & 1)); -#endif - } - } - break; + if(cpuDmaHack) { + return cpuDmaLast & 0xFF; + } else { + if(armState) { + return CPUReadByteQuick(reg[15].I + (address & 3)); + } else { + return CPUReadByteQuick(reg[15].I + (address & 1)); + } + } } } @@ -525,19 +402,21 @@ static inline void CPUWriteMemory(u32 address, u32 value) if(address & 3) { if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { log("Unaligned word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); } } #endif + address &= 0xFFFFFFFC; + switch(address >> 24) { case 0x02: #ifdef BKPT_SUPPORT if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) cheatsWriteMemory(address & 0x203FFFC, - value); + value); else #endif WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); @@ -546,7 +425,7 @@ static inline void CPUWriteMemory(u32 address, u32 value) #ifdef BKPT_SUPPORT if(*((u32 *)&freezeInternalRAM[address & 0x7ffc])) cheatsWriteMemory(address & 0x3007FFC, - value); + value); else #endif WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); @@ -561,16 +440,15 @@ static inline void CPUWriteMemory(u32 address, u32 value) #ifdef BKPT_SUPPORT if(*((u32 *)&freezePRAM[address & 0x3fc])) cheatsWriteMemory(address & 0x70003FC, - value); + value); else #endif - if(address < 0x5000400 || (RomIdCode & 0xFFFFFF) != CORVETTE) - WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); + WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); break; case 0x06: address = (address & 0x1fffc); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; + return; if ((address & 0x18000) == 0x18000) address &= 0x17fff; @@ -580,16 +458,16 @@ static inline void CPUWriteMemory(u32 address, u32 value) else #endif - WRITE32LE(((u32 *)&vram[address]), value); + WRITE32LE(((u32 *)&vram[address]), value); break; case 0x07: #ifdef BKPT_SUPPORT if(*((u32 *)&freezeOAM[address & 0x3fc])) cheatsWriteMemory(address & 0x70003FC, - value); + value); else #endif - WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); + WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); break; case 0x0D: if(cpuEEPROMEnabled) { @@ -598,19 +476,20 @@ static inline void CPUWriteMemory(u32 address, u32 value) } goto unwritable; case 0x0E: - if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { + case 0x0F: + if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) { (*cpuSaveGameFunc)(address, (u8)value); break; } // default default: - unwritable: +unwritable: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { log("Illegal word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); } #endif break; @@ -623,19 +502,21 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) if(address & 1) { if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { log("Unaligned halfword write: %04x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); } } #endif + address &= 0xFFFFFFFE; + switch(address >> 24) { case 2: #ifdef BKPT_SUPPORT if(*((u16 *)&freezeWorkRAM[address & 0x3FFFE])) cheatsWriteHalfWord(address & 0x203FFFE, - value); + value); else #endif WRITE16LE(((u16 *)&workRAM[address & 0x3FFFE]),value); @@ -644,7 +525,7 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) #ifdef BKPT_SUPPORT if(*((u16 *)&freezeInternalRAM[address & 0x7ffe])) cheatsWriteHalfWord(address & 0x3007ffe, - value); + value); else #endif WRITE16LE(((u16 *)&internalRAM[address & 0x7ffe]), value); @@ -658,34 +539,33 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) #ifdef BKPT_SUPPORT if(*((u16 *)&freezePRAM[address & 0x03fe])) cheatsWriteHalfWord(address & 0x70003fe, - value); + value); else #endif - if(address < 0x5000400 || (RomIdCode & 0xFFFFFF) != CORVETTE) - WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value); + WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value); break; case 6: address = (address & 0x1fffe); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; + return; if ((address & 0x18000) == 0x18000) address &= 0x17fff; #ifdef BKPT_SUPPORT if(*((u16 *)&freezeVRAM[address])) cheatsWriteHalfWord(address + 0x06000000, - value); + value); else #endif - WRITE16LE(((u16 *)&vram[address]), value); + WRITE16LE(((u16 *)&vram[address]), value); break; case 7: #ifdef BKPT_SUPPORT if(*((u16 *)&freezeOAM[address & 0x03fe])) cheatsWriteHalfWord(address & 0x70003fe, - value); + value); else #endif - WRITE16LE(((u16 *)&oam[address & 0x3fe]), value); + WRITE16LE(((u16 *)&oam[address & 0x3fe]), value); break; case 8: case 9: @@ -701,19 +581,20 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) } goto unwritable; case 14: - if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { + case 15: + if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) { (*cpuSaveGameFunc)(address, (u8)value); break; } goto unwritable; default: - unwritable: +unwritable: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { log("Illegal halfword write: %04x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); } #endif break; @@ -837,7 +718,8 @@ static inline void CPUWriteByte(u32 address, u8 b) } goto unwritable; case 14: - if (!(saveType == 5) && (!eepromInUse | cpuSramEnabled | cpuFlashEnabled)) { + case 15: + if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) { //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) { diff --git a/source/vba/gba/Mode0.cpp b/source/vba/gba/Mode0.cpp index dfa6682..c0d5812 100644 --- a/source/vba/gba/Mode0.cpp +++ b/source/vba/gba/Mode0.cpp @@ -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 "Globals.h" #include "GBAGfx.h" @@ -15,18 +7,9 @@ void mode0RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } return; } @@ -55,55 +38,11 @@ void mode0RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(u32 x = 0; x < 240u; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; 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]; top = 0x01; } @@ -117,49 +56,41 @@ void mode0RenderLine() color = line2[x]; top = 0x04; } - if((u8)(line3[x]>>24) < (u8)(color >> 24)) { + + if((u8)(line3[x]>>24) < (u8)(color >> 24)) { color = line3[x]; top = 0x08; } + if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { color = lineOBJ[x]; top = 0x10; } - //*/ if((top & 0x10) && (color & 0x00010000)) { // semi-transparent OBJ u32 back = backdrop; u8 top2 = 0x20; - u8 li0 = (u8)(line0[x]>>24); - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - - u8 r = (li1 < li0) ? (li1) : (li0); - - if(li2 < r) { - r = (li3 < li2) ? (li3) : (li2); - }else if(li3 < r){ - r = (li3); - } - - if(r < (u8)(color >> 24)) { - if(r == li0){ - back = line0[x]; - top2 = 0x01; - }else if(r == li1){ - back = line1[x]; - top2 = 0x02; - }else if(r == li2){ - back = line2[x]; - top2 = 0x04; - }else if(r == li3){ - back = line3[x]; - top2 = 0x08; - } - } + if((u8)(line0[x]>>24) < (u8)(back >> 24)) { + back = line0[x]; + top2 = 0x01; + } + + if((u8)(line1[x]>>24) < (u8)(back >> 24)) { + back = line1[x]; + top2 = 0x02; + } + + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; + } + + if((u8)(line3[x]>>24) < (u8)(back >> 24)) { + back = line3[x]; + top2 = 0x08; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -188,20 +119,9 @@ void mode0RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } return; } @@ -234,41 +154,32 @@ void mode0RenderLineNoWindow() for(int x = 0; x < 240; x++) { u32 color = backdrop; - u8 top = 0x20; + u8 top = 0x20; - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - u8 li4 = (u8)(lineOBJ[x]>>24); - - u8 r = (li2 < li1) ? (li2) : (li1); - - if(li3 < r) { - r = (li4 < li3) ? (li4) : (li3); - }else if(li4 < r){ - r = (li4); - } - - if(line0[x] < backdrop) { - color = line0[x]; - top = 0x01; - } - - if(r < (u8)(color >> 24)) { - if(r == li1){ - color = line1[x]; - top = 0x02; - }else if(r == li2){ - color = line2[x]; - top = 0x04; - }else if(r == li3){ - color = line3[x]; - top = 0x08; - }else if(r == li4){ - color = lineOBJ[x]; - top = 0x10; - } - } + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if(line1[x] < (color & 0xFF000000)) { + color = line1[x]; + top = 0x02; + } + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(line3[x] < (color & 0xFF000000)) { + color = line3[x]; + top = 0x08; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } if(!(color & 0x00010000)) { switch(effect) { @@ -278,30 +189,40 @@ void mode0RenderLineNoWindow() { if(top & BLDMOD) { u32 back = backdrop; - u8 top2 = 0x20; - - if((top != 0x01) && line0[x] < back) { + u8 top2 = 0x20; + if(line0[x] < back) { + if(top != 0x01) { back = line0[x]; top2 = 0x01; + } } - if((top != 0x02) && line1[x] < (back & 0xFF000000)) { + + if(line1[x] < (back & 0xFF000000)) { + if(top != 0x02) { back = line1[x]; top2 = 0x02; + } } - if((top != 0x04) && line2[x] < (back & 0xFF000000)) { + if(line2[x] < (back & 0xFF000000)) { + if(top != 0x04) { back = line2[x]; top2 = 0x04; + } } - if((top != 0x08) && line3[x] < (back & 0xFF000000)) { + if(line3[x] < (back & 0xFF000000)) { + if(top != 0x08) { back = line3[x]; top2 = 0x08; + } } - if((top != 0x10) && lineOBJ[x] < (back & 0xFF000000)) { + if(lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { back = lineOBJ[x]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) @@ -324,45 +245,27 @@ void mode0RenderLineNoWindow() } else { // semi-transparent OBJ u32 back = backdrop; - u8 top2 = 0x20; + u8 top2 = 0x20; - //--DCN - // This is pretty much the exact same result: - // line1[x] < (back & 0xFF000000) - // - // (u8)(line0[x]>>24) < (u8)(back >> 24) - // - // The only difference is that the first is stored in a u32, - // and the second is stored in a u8 - //* - u8 li0 = (u8)(line0[x]>>24); - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - - u8 r = (li1 < li0) ? (li1) : (li0); - - if(li2 < r) { - r = (li3 < li2) ? (li3) : (li2); - }else if(li3 < r){ - r = (li3); - } - - if(r < (u8)(color >> 24)) { - if(r == li0){ - back = line0[x]; - top2 = 0x01; - }else if(r == li1){ - back = line1[x]; - top2 = 0x02; - }else if(r == li2){ - back = line2[x]; - top2 = 0x04; - }else if(r == li3){ - back = line3[x]; - top2 = 0x08; - } - } + if(line0[x] < back) { + back = line0[x]; + top2 = 0x01; + } + + if(line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -391,20 +294,9 @@ void mode0RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } return; } @@ -480,7 +372,7 @@ void mode0RenderLineAll() } } - if((mask & 1) && (line0[x] < color)) { + if((mask & 1) && (line0[x] < color)) { color = line0[x]; top = 0x01; } @@ -556,30 +448,39 @@ void mode0RenderLineAll() if(top & BLDMOD) { u32 back = backdrop; u8 top2 = 0x20; - - if((mask & 1) && (top != 0x01) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { + if((mask & 1) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { + if(top != 0x01) { back = line0[x]; 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]; 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]; 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]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/Mode1.cpp b/source/vba/gba/Mode1.cpp index 814b474..4cc3b07 100644 --- a/source/vba/gba/Mode1.cpp +++ b/source/vba/gba/Mode1.cpp @@ -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 "Globals.h" #include "GBAGfx.h" @@ -16,20 +7,9 @@ void mode1RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -60,64 +40,49 @@ void mode1RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(u32 x = 0; x < 240u; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - u8 li4 = (u8)(lineOBJ[x]>>24); - - u8 r = (li2 < li1) ? (li2) : (li1); - - if(li4 < r){ - r = (li4); - } - - if(line0[x] < backdrop) { - color = line0[x]; - top = 0x01; - } - - if(r < (u8)(color >> 24)) { - if(r == li1){ - color = line1[x]; - top = 0x02; - }else if(r == li2){ - color = line2[x]; - top = 0x04; - }else if(r == li4){ - color = lineOBJ[x]; - top = 0x10; - } - } + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if((u8)(line1[x]>>24) < (u8)(color >> 24)) { + color = line1[x]; + top = 0x02; + } + + if((u8)(line2[x]>>24) < (u8)(color >> 24)) { + color = line2[x]; + top = 0x04; + } + + if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { + color = lineOBJ[x]; + top = 0x10; + } if((top & 0x10) && (color & 0x00010000)) { // semi-transparent OBJ u32 back = backdrop; u8 top2 = 0x20; - u8 li0 = (u8)(line0[x]>>24); - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - u8 r = (li1 < li0) ? (li1) : (li0); - - if(li2 < r) { - r = (li2); - } - - if(r < (u8)(back >> 24)) { - if(r == li0){ - back = line0[x]; - top2 = 0x01; - }else if(r == li1){ - back = line1[x]; - top2 = 0x02; - }else if(r == li2){ - back = line2[x]; - top2 = 0x04; - } - } + if((u8)(line0[x]>>24) < (u8)(back >> 24)) { + back = line0[x]; + top2 = 0x01; + } + + if((u8)(line1[x]>>24) < (u8)(back >> 24)) { + back = line1[x]; + top2 = 0x02; + } + + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -148,20 +113,9 @@ void mode1RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -193,37 +147,29 @@ void mode1RenderLineNoWindow() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - u8 li4 = (u8)(lineOBJ[x]>>24); - - u8 r = (li2 < li1) ? (li2) : (li1); - - if(li4 < r){ - r = (li4); - } - - if(line0[x] < backdrop) { - color = line0[x]; - top = 0x01; - } - - if(r < (u8)(color >> 24)) { - if(r == li1){ - color = line1[x]; - top = 0x02; - }else if(r == li2){ - color = line2[x]; - top = 0x04; - }else if(r == li4){ - color = lineOBJ[x]; - top = 0x10; - } - } + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if((u8)(line1[x]>>24) < (u8)(color >> 24)) { + color = line1[x]; + top = 0x02; + } + + if((u8)(line2[x]>>24) < (u8)(color >> 24)) { + color = line2[x]; + top = 0x04; + } + + if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { + color = lineOBJ[x]; + top = 0x10; + } if(!(color & 0x00010000)) { switch((BLDMOD >> 6) & 3) { @@ -234,26 +180,33 @@ void mode1RenderLineNoWindow() if(top & BLDMOD) { u32 back = backdrop; u8 top2 = 0x20; + if((u8)(line0[x]>>24) < (u8)(back >> 24)) { + if(top != 0x01) { + back = line0[x]; + top2 = 0x01; + } + } - if((top != 0x01) && (u8)(line0[x]>>24) < (u8)(back >> 24)) { - back = line0[x]; - top2 = 0x01; - } + if((u8)(line1[x]>>24) < (u8)(back >> 24)) { + if(top != 0x02) { + back = line1[x]; + top2 = 0x02; + } + } - if((top != 0x02) && (u8)(line1[x]>>24) < (u8)(back >> 24)) { - back = line1[x]; - top2 = 0x02; - } + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } - if((top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; - } - - if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - back = lineOBJ[x]; - top2 = 0x10; - } + if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -272,32 +225,24 @@ void mode1RenderLineNoWindow() break; } } else { - // semi-transparent OBJ - u32 back = backdrop; - u8 top2 = 0x20; + // semi-transparent OBJ + u32 back = backdrop; + u8 top2 = 0x20; - u8 li0 = (u8)(line0[x]>>24); - u8 li1 = (u8)(line1[x]>>24); - u8 li2 = (u8)(line2[x]>>24); - - u8 r = (li1 < li0) ? (li1) : (li0); - - if(li2 < r) { - r = (li2); - } - - if(r < (u8)(back >> 24)) { - if(r == li0){ - back = line0[x]; - top2 = 0x01; - }else if(r == li1){ - back = line1[x]; - top2 = 0x02; - }else if(r == li2){ - back = line2[x]; - top2 = 0x04; - } - } + if((u8)(line0[x]>>24) < (u8)(back >> 24)) { + back = line0[x]; + top2 = 0x01; + } + + if((u8)(line1[x]>>24) < (u8)(back >> 24)) { + back = line1[x]; + top2 = 0x02; + } + + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -328,20 +273,9 @@ void mode1RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -399,7 +333,7 @@ void mode1RenderLineAll() u8 inWin1Mask = WININ >> 8; u8 outMask = WINOUT & 0xFF; - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; u8 mask = outMask; @@ -419,23 +353,22 @@ void mode1RenderLineAll() } } - // At the very least, move the inexpensive 'mask' operation up front - if((mask & 1) && line0[x] < backdrop) { + if(line0[x] < color && (mask & 1)) { color = line0[x]; 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]; 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]; 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]; top = 0x10; } @@ -445,7 +378,7 @@ void mode1RenderLineAll() u32 back = backdrop; 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]; top2 = 0x01; } @@ -487,24 +420,32 @@ void mode1RenderLineAll() u32 back = backdrop; 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]; 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]; 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]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/Mode2.cpp b/source/vba/gba/Mode2.cpp index d61b0c3..527a1ff 100644 --- a/source/vba/gba/Mode2.cpp +++ b/source/vba/gba/Mode2.cpp @@ -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 "Globals.h" #include "GBAGfx.h" @@ -15,20 +7,9 @@ void mode2RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -62,51 +43,40 @@ void mode2RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - u8 li4 = (u8)(lineOBJ[x]>>24); - - u8 r = (li3 < li2) ? (li3) : (li2); - - if(li4 < r){ - r = (li4); - } - - if(r < (u8)(color >> 24)) { - if(r == li2){ - color = line2[x]; - top = 0x04; - }else if(r == li3){ - color = line3[x]; - top = 0x08; - }else if(r == li4){ - color = lineOBJ[x]; - top = 0x10; - } - } + + if((u8)(line2[x]>>24) < (u8)(color >> 24)) { + color = line2[x]; + top = 0x04; + } + + if((u8)(line3[x]>>24) < (u8)(color >> 24)) { + color = line3[x]; + top = 0x08; + } + + if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { + color = lineOBJ[x]; + top = 0x10; + } if((top & 0x10) && (color & 0x00010000)) { // semi-transparent OBJ u32 back = backdrop; u8 top2 = 0x20; - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - u8 r = (li3 < li2) ? (li3) : (li2); - - if(r < (u8)(back >> 24)) { - if(r == li2){ - back = line2[x]; - top2 = 0x04; - }else if(r == li3){ - back = line3[x]; - top2 = 0x08; - } - } + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; + } + + if((u8)(line3[x]>>24) < (u8)(back >> 24)) { + back = line3[x]; + top2 = 0x08; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -138,20 +108,9 @@ void mode2RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -185,32 +144,25 @@ void mode2RenderLineNoWindow() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - u8 li4 = (u8)(lineOBJ[x]>>24); - - u8 r = (li3 < li2) ? (li3) : (li2); - - if(li4 < r){ - r = (li4); - } - - if(r < (u8)(color >> 24)) { - if(r == li2){ - color = line2[x]; - top = 0x04; - }else if(r == li3){ - color = line3[x]; - top = 0x08; - }else if(r == li4){ - color = lineOBJ[x]; - top = 0x10; - } - } + + if((u8)(line2[x]>>24) < (u8)(color >> 24)) { + color = line2[x]; + top = 0x04; + } + + if((u8)(line3[x]>>24) < (u8)(color >> 24)) { + color = line3[x]; + top = 0x08; + } + + if((u8)(lineOBJ[x]>>24) < (u8)(color >> 24)) { + color = lineOBJ[x]; + top = 0x10; + } if(!(color & 0x00010000)) { switch((BLDMOD >> 6) & 3) { @@ -222,20 +174,26 @@ void mode2RenderLineNoWindow() u32 back = backdrop; u8 top2 = 0x20; - if((top != 0x04) && (u8)(line2[x]>>24) < (u8)(back >> 24)) { - back = line2[x]; - top2 = 0x04; + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } } - if((top != 0x08) && (u8)(line3[x]>>24) < (u8)(back >> 24)) { - back = line3[x]; - top2 = 0x08; - } + if((u8)(line3[x]>>24) < (u8)(back >> 24)) { + if(top != 0x08) { + back = line3[x]; + top2 = 0x08; + } + } - if((top != 0x10) && (u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { - back = lineOBJ[x]; - top2 = 0x10; - } + if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -258,19 +216,15 @@ void mode2RenderLineNoWindow() u32 back = backdrop; u8 top2 = 0x20; - u8 li2 = (u8)(line2[x]>>24); - u8 li3 = (u8)(line3[x]>>24); - u8 r = (li3 < li2) ? (li3) : (li2); - - if(r < (u8)(back >> 24)) { - if(r == li2){ - back = line2[x]; - top2 = 0x04; - }else if(r == li3){ - back = line3[x]; - top2 = 0x08; - } - } + if((u8)(line2[x]>>24) < (u8)(back >> 24)) { + back = line2[x]; + top2 = 0x04; + } + + if((u8)(line3[x]>>24) < (u8)(back >> 24)) { + back = line3[x]; + top2 = 0x08; + } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, @@ -302,20 +256,9 @@ void mode2RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -396,17 +339,17 @@ void mode2RenderLineAll() } } - if((mask & 4) && line2[x] < color) { + if(line2[x] < color && (mask & 4)) { color = line2[x]; 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]; 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]; top = 0x10; } @@ -453,19 +396,25 @@ void mode2RenderLineAll() u32 back = backdrop; u8 top2 = 0x20; - if((mask & 4) && (top != 0x04) && line2[x] < back) { + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { back = line2[x]; 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]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/Mode3.cpp b/source/vba/gba/Mode3.cpp index 2d97265..1b1d0c6 100644 --- a/source/vba/gba/Mode3.cpp +++ b/source/vba/gba/Mode3.cpp @@ -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 "Globals.h" #include "GBAGfx.h" @@ -14,20 +7,9 @@ void mode3RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -54,7 +36,7 @@ void mode3RenderLine() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = background; u8 top = 0x20; @@ -73,7 +55,7 @@ void mode3RenderLine() u32 back = background; u8 top2 = 0x20; - if(line2[x] < background) { + if(line2[x] < back) { back = line2[x]; top2 = 0x04; } @@ -107,20 +89,9 @@ void mode3RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -147,11 +118,11 @@ void mode3RenderLineNoWindow() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = background; u8 top = 0x20; - if(line2[x] < background) { + if(line2[x] < color) { color = line2[x]; top = 0x04; } @@ -171,14 +142,18 @@ void mode3RenderLineNoWindow() u32 back = background; u8 top2 = 0x20; - if(top != 0x04 && (line2[x] < background) ) { - back = line2[x]; - top2 = 0x04; + if(line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } } - if(top != 0x10 && ((u8)(lineOBJ[x]>>24) < (u8)(back >> 24))) { - back = lineOBJ[x]; - top2 = 0x10; + if((u8)(lineOBJ[x]>>24) < (u8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) @@ -203,7 +178,7 @@ void mode3RenderLineNoWindow() u32 back = background; u8 top2 = 0x20; - if(line2[x] < background) { + if(line2[x] < back) { back = line2[x]; top2 = 0x04; } @@ -237,20 +212,9 @@ void mode3RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x80) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -304,7 +268,7 @@ void mode3RenderLineAll() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = background; u8 top = 0x20; u8 mask = outMask; @@ -324,7 +288,7 @@ void mode3RenderLineAll() } } - if((mask & 4) && line2[x] < background) { + if((mask & 4) && (line2[x] < color)) { color = line2[x]; top = 0x04; } @@ -339,7 +303,7 @@ void mode3RenderLineAll() u32 back = background; u8 top2 = 0x20; - if((mask & 4) && line2[x] < background) { + if((mask & 4) && line2[x] < back) { back = line2[x]; top2 = 0x04; } @@ -370,20 +334,25 @@ void mode3RenderLineAll() u32 back = background; u8 top2 = 0x20; - if((mask & 4) && (top != 0x04) && line2[x] < back) { + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { back = line2[x]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); + } } break; diff --git a/source/vba/gba/Mode4.cpp b/source/vba/gba/Mode4.cpp index 218f929..1907948 100644 --- a/source/vba/gba/Mode4.cpp +++ b/source/vba/gba/Mode4.cpp @@ -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 "GBAGfx.h" #include "Globals.h" @@ -14,20 +7,9 @@ void mode4RenderLine() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x0080) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -53,11 +35,11 @@ void mode4RenderLine() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; - if(line2[x] < backdrop) { + if(line2[x] < color) { color = line2[x]; top = 0x04; } @@ -72,7 +54,7 @@ void mode4RenderLine() u32 back = backdrop; u8 top2 = 0x20; - if(line2[x] < backdrop) { + if(line2[x] < back) { back = line2[x]; top2 = 0x04; } @@ -106,20 +88,9 @@ void mode4RenderLineNoWindow() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x0080) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -145,11 +116,11 @@ void mode4RenderLineNoWindow() backdrop = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; - if(line2[x] < backdrop) { + if(line2[x] < color) { color = line2[x]; top = 0x04; } @@ -169,14 +140,18 @@ void mode4RenderLineNoWindow() u32 back = backdrop; u8 top2 = 0x20; - if((top != 0x04) && line2[x] < backdrop) { + if(line2[x] < back) { + if(top != 0x04) { back = line2[x]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) @@ -235,20 +210,9 @@ void mode4RenderLineAll() u16 *palette = (u16 *)paletteRAM; if(DISPCNT & 0x0080) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -301,7 +265,7 @@ void mode4RenderLineAll() u8 inWin1Mask = WININ >> 8; u8 outMask = WINOUT & 0xFF; - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = backdrop; u8 top = 0x20; u8 mask = outMask; @@ -321,7 +285,7 @@ void mode4RenderLineAll() } } - if((mask & 4) && (line2[x] < backdrop)) { + if((mask & 4) && (line2[x] < color)) { color = line2[x]; top = 0x04; } @@ -367,20 +331,25 @@ void mode4RenderLineAll() u32 back = backdrop; u8 top2 = 0x20; - if((mask & 4) && (top != 0x04) && (line2[x] < backdrop)) { + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { back = line2[x]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) color = gfxAlphaBlend(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); + } } break; diff --git a/source/vba/gba/Mode5.cpp b/source/vba/gba/Mode5.cpp index 17ddf55..dc72427 100644 --- a/source/vba/gba/Mode5.cpp +++ b/source/vba/gba/Mode5.cpp @@ -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 "Globals.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() { if(DISPCNT & 0x0080) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -55,11 +36,11 @@ void mode5RenderLine() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = background; u8 top = 0x20; - if(line2[x] < background) { + if(line2[x] < color) { color = line2[x]; top = 0x04; } @@ -106,20 +87,9 @@ void mode5RenderLine() void mode5RenderLineNoWindow() { if(DISPCNT & 0x0080) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); - + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -148,11 +118,11 @@ void mode5RenderLineNoWindow() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = background; u8 top = 0x20; - if(line2[x] < background) { + if(line2[x] < color) { color = line2[x]; top = 0x04; } @@ -172,14 +142,18 @@ void mode5RenderLineNoWindow() u32 back = background; u8 top2 = 0x20; - if((top != 0x04) && line2[x] < background) { + if(line2[x] < back) { + if(top != 0x04) { back = line2[x]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) @@ -236,19 +210,9 @@ void mode5RenderLineNoWindow() void mode5RenderLineAll() { if(DISPCNT & 0x0080) { - - int x = 232; //240 - 8 - do{ - lineMix[x ] = - lineMix[x+1] = - lineMix[x+2] = - lineMix[x+3] = - lineMix[x+4] = - lineMix[x+5] = - lineMix[x+6] = - lineMix[x+7] = 0x7fff; - x-=8; - }while(x>=0); + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } gfxLastVCOUNT = VCOUNT; return; } @@ -304,7 +268,7 @@ void mode5RenderLineAll() background = ((customBackdropColor & 0x7FFF) | 0x30000000); } - for(int x = 0; x < 240; ++x) { + for(int x = 0; x < 240; x++) { u32 color = background; u8 top = 0x20; u8 mask = outMask; @@ -324,7 +288,7 @@ void mode5RenderLineAll() } } - if((mask & 4) && (line2[x] < background)) { + if((mask & 4) && (line2[x] < color)) { color = line2[x]; top = 0x04; } @@ -370,14 +334,18 @@ void mode5RenderLineAll() u32 back = background; u8 top2 = 0x20; - if((mask & 4) && (top != 0x04) && (line2[x] < background)) { + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { back = line2[x]; 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]; top2 = 0x10; + } } if(top2 & (BLDMOD>>8)) diff --git a/source/vba/gba/RTC.cpp b/source/vba/gba/RTC.cpp index 3d00003..511bb47 100644 --- a/source/vba/gba/RTC.cpp +++ b/source/vba/gba/RTC.cpp @@ -8,13 +8,21 @@ #include #include -#include + +// Defined in VGA-GX input.cpp +void systemCartridgeRumble(bool); + +enum RTCSTATE +{ + IDLE = 0, + COMMAND, + DATA, + READDATA +}; u8 systemGetSensorDarkness(); int systemGetSensorZ(); -enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; - typedef struct { u8 byte0; u8 byte1; @@ -271,6 +279,17 @@ void rtcReset() 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) { utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData)); @@ -280,3 +299,4 @@ void rtcReadGame(gzFile gzFile) { utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData)); } +#endif diff --git a/source/vba/gba/RTC.h b/source/vba/gba/RTC.h index dfcec65..7d50618 100644 --- a/source/vba/gba/RTC.h +++ b/source/vba/gba/RTC.h @@ -8,7 +8,12 @@ void rtcEnableWarioRumble(bool); bool rtcIsEnabled(); void rtcReset(); +#ifdef __LIBRETRO__ +void rtcReadGame(const u8 *&data); +void rtcSaveGame(u8 *&data); +#else void rtcReadGame(gzFile gzFile); void rtcSaveGame(gzFile gzFile); +#endif #endif // RTC_H diff --git a/source/vba/gba/Sound.cpp b/source/vba/gba/Sound.cpp index 96f90fc..3c630b0 100644 --- a/source/vba/gba/Sound.cpp +++ b/source/vba/gba/Sound.cpp @@ -50,8 +50,8 @@ int soundTicks = SOUND_CLOCK_TICKS_; static float soundVolume = 1.0f; static int soundEnableFlag = 0x3ff; // emulator channels enabled -static float soundFiltering_ = -1.0f; -static float soundVolume_ = -1.0f; +static float soundFiltering_ = -1; +static float soundVolume_ = -1; void interp_rate() { /* empty for now */ } @@ -82,8 +82,8 @@ public: int readIndex; int count; int writeIndex; - int dac; u8 fifo [32]; + int dac; private: int timer; @@ -115,7 +115,7 @@ void Gba_Pcm::apply_control( int idx ) int ch = 0; if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) ) - ch = ioMem [SGCNT0_H+1] >> (idx <<2) & 3; + ch = ioMem [SGCNT0_H+1] >> (idx * 4) & 3; Blip_Buffer* out = 0; switch ( ch ) @@ -162,10 +162,11 @@ void Gba_Pcm::update( int dac ) int filter = 0; if ( soundInterpolation ) { - unsigned period = unsigned(time - last_time); - unsigned idx = period >> 9; + // base filtering on how long since last sample was output + int period = time - last_time; - if ( idx > 3 ) + int idx = (unsigned) period / 512; + if ( idx >= 3 ) idx = 3; 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 ( count <= 16 ) + /* Mother 3 fix, refined to not break Metroid Fusion */ + if ( count == 16 || count == 0 ) { // Need to fill FIFO + int saved_count = count; 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 int reg = which ? FIFOB_L : FIFOA_L; - - // 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+2, (u16)0); + for ( int n = 8; n--; ) + { + soundEvent(reg , (u16)0); + soundEvent(reg+2, (u16)0); + } } } // Read next sample from FIFO - --count; + count--; dac = fifo [readIndex]; readIndex = (readIndex + 1) & 31; pcm.update( dac ); @@ -287,17 +284,14 @@ static void apply_volume( bool apu_only = false ) 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] ); } if ( !apu_only ) { - double tmpVol = 0.002578125 * soundVolume_; // 0.66 / 256 * soundVolume_ - - pcm_synth[0].volume( tmpVol ); - pcm_synth[1].volume( tmpVol ); - pcm_synth[2].volume( tmpVol ); + for ( int i = 0; i < 3; i++ ) + pcm_synth [i].volume( 0.66 / 256 * soundVolume_ ); } } @@ -358,14 +352,19 @@ static void end_frame( blip_time_t time ) void flush_samples(Multi_Buffer * buffer) { +#ifdef __LIBRETRO__ + int numSamples = buffer->read_samples( (blip_sample_t*) soundFinalWave, buffer->samples_avail() ); + soundDriver->write(soundFinalWave, numSamples); + systemOnWriteDataToSoundBuffer(soundFinalWave, numSamples); +#else // We want to write the data frame by frame to support legacy audio drivers // that don't use the length parameter of the write method. // TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the // samples at once to help reducing the audio delay on all platforms. - int soundBufferLen = ( soundSampleRate / 60 ) << 2; + int soundBufferLen = ( soundSampleRate / 60 ) * 4; // 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 int const out_buf_size = soundBufferLen / sizeof *soundFinalWave; @@ -380,16 +379,15 @@ void flush_samples(Multi_Buffer * buffer) soundDriver->write(soundFinalWave, soundBufferLen); systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen); } +#endif } static void apply_filtering() { soundFiltering_ = soundFiltering; - // Yes, I changed soundFiltering_ to soundFiltering, the reason is - // to eliminate a write-read dependency - int const base_freq = 32768 - (int) (soundFiltering * 16384.0f); - int const nyquist = stereo_buffer->sample_rate() >> 1; + int const base_freq = (int) (32768 - soundFiltering_ * 16384); + int const nyquist = stereo_buffer->sample_rate() / 2; for ( int i = 0; i < 3; i++ ) { @@ -458,6 +456,13 @@ static void remake_stereo_buffer() pcm [0].pcm.init(); pcm [1].pcm.init(); + // APU + if ( !gb_apu ) + { + gb_apu = new Gb_Apu; // TODO: handle out of memory + reset_apu(); + } + // Stereo_Buffer delete stereo_buffer; stereo_buffer = 0; @@ -471,13 +476,7 @@ static void remake_stereo_buffer() pcm [1].which = 1; apply_filtering(); - // APU - if ( !gb_apu ) - { - gb_apu = new Gb_Apu; // TODO: handle out of memory - reset_apu(); - } - + // Volume Level apply_muting(); apply_volume(); } @@ -596,8 +595,8 @@ static struct { gb_apu_state_t apu; // old state - int soundDSBValue; u8 soundDSAValue; + int soundDSBValue; } state; // 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 ) +#endif { gb_apu->save_state( &state.apu ); // Be sure areas for expansion get written as zero memset( dummy_state, 0, sizeof dummy_state ); +#ifdef __LIBRETRO__ + utilWriteDataMem( out, gba_state ); +#else utilWriteData( out, gba_state ); +#endif } +#ifndef __LIBRETRO__ static void soundReadGameOld( gzFile in, int version ) { // Read main data @@ -799,19 +807,28 @@ static void soundReadGameOld( gzFile in, int version ) (void) utilReadInt( in ); // ignore quality } +#endif #include +#ifdef __LIBRETRO__ +void soundReadGame(const u8*& in, int version ) +#else void soundReadGame( gzFile in, int version ) +#endif { // Prepare APU and default state reset_apu(); gb_apu->save_state( &state.apu ); if ( version > SAVE_GAME_VERSION_9 ) +#ifdef __LIBRETRO__ + utilReadDataMem( in, gba_state ); +#else utilReadData( in, gba_state ); else soundReadGameOld( in, version ); +#endif gb_apu->load_state( state.apu ); write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F ); diff --git a/source/vba/gba/Sound.h b/source/vba/gba/Sound.h index 3a48c00..4ccb0b8 100644 --- a/source/vba/gba/Sound.h +++ b/source/vba/gba/Sound.h @@ -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 // Saves/loads emulator state +#ifdef __LIBRETRO__ +void soundSaveGame( u8 *& ); +void soundReadGame(const u8*& in, int version ); +#else void soundSaveGame( gzFile ); void soundReadGame( gzFile, int version ); +#endif class Multi_Buffer; diff --git a/source/vba/gba/elf.cpp b/source/vba/gba/elf.cpp index 10bc19b..04b0690 100644 --- a/source/vba/gba/elf.cpp +++ b/source/vba/gba/elf.cpp @@ -1058,7 +1058,7 @@ void elfParseCFA(u8 *top) if(id == 0xffffffff) { // skip version - *data++; + (*data)++; ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie)); diff --git a/source/vba/gba/gbafilter.cpp b/source/vba/gba/gbafilter.cpp new file mode 100644 index 0000000..523ec82 --- /dev/null +++ b/source/vba/gba/gbafilter.cpp @@ -0,0 +1,227 @@ +#include "gbafilter.h" + +#include + +extern int systemColorDepth; +extern int systemRedShift; +extern int systemGreenShift; +extern int systemBlueShift; + +extern u16 systemColorMap16[0x10000]; +extern u32 systemColorMap32[0x10000]; + +static const unsigned char curve[32] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12, + 0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80, + 0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0}; + +// output R G B +static const unsigned char influence[3 * 3] = { 16, 4, 4, // red + 8, 16, 8, // green + 0, 8, 16};// blue + +inline void swap(short & a, short & b) +{ + short temp = a; + a = b; + b = temp; +} + +void gbafilter_pal(u16 * buf, int count) +{ + short temp[3 * 3], s; + unsigned pix; + u8 red, green, blue; + + while (count--) + { + pix = *buf; + + s = curve[(pix >> systemGreenShift) & 0x1f]; + temp[3] = s * influence[3]; + temp[4] = s * influence[4]; + temp[5] = s * influence[5]; + + s = curve[(pix >> systemRedShift) & 0x1f]; + temp[0] = s * influence[0]; + temp[1] = s * influence[1]; + temp[2] = s * influence[2]; + + s = curve[(pix >> systemBlueShift) & 0x1f]; + temp[6] = s * influence[6]; + temp[7] = s * influence[7]; + temp[8] = s * influence[8]; + + if (temp[0] < temp[3]) swap(temp[0], temp[3]); + if (temp[0] < temp[6]) swap(temp[0], temp[6]); + if (temp[3] < temp[6]) swap(temp[3], temp[6]); + temp[3] <<= 1; + temp[0] <<= 2; + temp[0] += temp[3] + temp[6]; + + red = ((int(temp[0]) * 160) >> 17) + 4; + if (red > 31) red = 31; + + if (temp[2] < temp[5]) swap(temp[2], temp[5]); + if (temp[2] < temp[8]) swap(temp[2], temp[8]); + if (temp[5] < temp[8]) swap(temp[5], temp[8]); + temp[5] <<= 1; + temp[2] <<= 2; + temp[2] += temp[5] + temp[8]; + + blue = ((int(temp[2]) * 160) >> 17) + 4; + if (blue > 31) blue = 31; + + if (temp[1] < temp[4]) swap(temp[1], temp[4]); + if (temp[1] < temp[7]) swap(temp[1], temp[7]); + if (temp[4] < temp[7]) swap(temp[4], temp[7]); + temp[4] <<= 1; + temp[1] <<= 2; + temp[1] += temp[4] + temp[7]; + + green = ((int(temp[1]) * 160) >> 17) + 4; + if (green > 31) green = 31; + + pix = red << systemRedShift; + pix += green << systemGreenShift; + pix += blue << systemBlueShift; + + *buf++ = pix; + } +} + +void gbafilter_pal32(u32 * buf, int count) +{ + short temp[3 * 3], s; + unsigned pix; + u8 red, green, blue; + + while (count--) + { + pix = *buf; + + s = curve[(pix >> systemGreenShift) & 0x1f]; + temp[3] = s * influence[3]; + temp[4] = s * influence[4]; + temp[5] = s * influence[5]; + + s = curve[(pix >> systemRedShift) & 0x1f]; + temp[0] = s * influence[0]; + temp[1] = s * influence[1]; + temp[2] = s * influence[2]; + + s = curve[(pix >> systemBlueShift) & 0x1f]; + temp[6] = s * influence[6]; + temp[7] = s * influence[7]; + temp[8] = s * influence[8]; + + if (temp[0] < temp[3]) swap(temp[0], temp[3]); + if (temp[0] < temp[6]) swap(temp[0], temp[6]); + if (temp[3] < temp[6]) swap(temp[3], temp[6]); + temp[3] <<= 1; + temp[0] <<= 2; + temp[0] += temp[3] + temp[6]; + + //red = ((int(temp[0]) * 160) >> 17) + 4; + red = ((int(temp[0]) * 160) >> 14) + 32; + + if (temp[2] < temp[5]) swap(temp[2], temp[5]); + if (temp[2] < temp[8]) swap(temp[2], temp[8]); + if (temp[5] < temp[8]) swap(temp[5], temp[8]); + temp[5] <<= 1; + temp[2] <<= 2; + temp[2] += temp[5] + temp[8]; + + //blue = ((int(temp[2]) * 160) >> 17) + 4; + blue = ((int(temp[2]) * 160) >> 14) + 32; + + if (temp[1] < temp[4]) swap(temp[1], temp[4]); + if (temp[1] < temp[7]) swap(temp[1], temp[7]); + if (temp[4] < temp[7]) swap(temp[4], temp[7]); + temp[4] <<= 1; + temp[1] <<= 2; + temp[1] += temp[4] + temp[7]; + + //green = ((int(temp[1]) * 160) >> 17) + 4; + green = ((int(temp[1]) * 160) >> 14) + 32; + + //pix = red << redshift; + //pix += green << greenshift; + //pix += blue << blueshift; + + pix = red << (systemRedShift - 3); + pix += green << (systemGreenShift - 3); + pix += blue << (systemBlueShift - 3); + + *buf++ = pix; + } +} + +// for palette mode to work with the three spoony filters in 32bpp depth + +void gbafilter_pad(u8 * buf, int count) +{ + union + { + struct + { + u8 r; + u8 g; + u8 b; + u8 a; + } part; + unsigned whole; + } + mask; + + mask.whole = 0x1f << systemRedShift; + mask.whole += 0x1f << systemGreenShift; + mask.whole += 0x1f << systemBlueShift; + + switch (systemColorDepth) + { + case 24: + while (count--) + { + *buf++ &= mask.part.r; + *buf++ &= mask.part.g; + *buf++ &= mask.part.b; + } + break; + case 32: + while (count--) + { + *((u32*)buf) &= mask.whole; + buf += 4; + } + } +} + +/* +void UpdateSystemColorMaps(int lcd) +{ + switch(systemColorDepth) { + case 16: + { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000); + } + break; + case 24: + case 32: + { + for(int i = 0; i < 0x10000; i++) { + systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000); + } + break; + } +} +*/ diff --git a/source/vba/gba/gbafilter.h b/source/vba/gba/gbafilter.h new file mode 100644 index 0000000..18ff53d --- /dev/null +++ b/source/vba/gba/gbafilter.h @@ -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); diff --git a/source/vbagx.cpp b/source/vbagx.cpp index 8f5d4a4..010828b 100644 --- a/source/vbagx.cpp +++ b/source/vbagx.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #ifdef HW_RVL @@ -51,7 +52,8 @@ int ShutdownRequested = 0; int ResetRequested = 0; int ExitRequested = 0; char appPath[1024] = { 0 }; -char loadedFile[1024] = { 0 }; + + /**************************************************************************** * Shutdown / Reboot / Exit @@ -341,6 +343,7 @@ int main(int argc, char *argv[]) SYS_SetPowerCallback(ShutdownCB); SYS_SetResetCallback(ResetCB); + WUPC_Init(); WPAD_Init(); WPAD_SetPowerButtonCallback((WPADShutdownCallback)ShutdownCB); DI_Init(); diff --git a/source/vbagx.h b/source/vbagx.h index 0e5c886..5e7d348 100644 --- a/source/vbagx.h +++ b/source/vbagx.h @@ -16,7 +16,7 @@ #include "utils/FreeTypeGX.h" #define APPNAME "Visual Boy Advance GX" -#define APPVERSION "2.2.8" +#define APPVERSION "2.3.3" #define APPFOLDER "vbagx" #define PREF_FILE_NAME "settings.xml" #define PAL_FILE_NAME "palettes.xml" @@ -40,7 +40,8 @@ enum { enum { FILE_SRAM, FILE_SNAPSHOT, - FILE_ROM + FILE_ROM, + FILE_BORDER_PNG }; enum { @@ -66,16 +67,20 @@ struct SGCSettings{ float gbaZoomVert; // GBA vertical zoom amount float gbZoomHor; // GB horizontal zoom amount float gbZoomVert; // GB vertical zoom amount + int gbFixed; + int gbaFixed; int AutoLoad; int AutoSave; int LoadMethod; // For ROMS: Auto, SD, DVD, USB, Network (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 scaling; // 0 - default, 1 - partial stretch, 2 - stretch to fit, 3 - widescreen correction int render; // 0 - original, 1 - filtered, 2 - unfiltered int xshift; // video output shift int yshift; int colorize; // colorize Mono Gameboy games + int gbaFrameskip; // turn on auto-frameskip for GBA games int WiiControls; // Match Wii Game int WiimoteOrientation; int ExitAction; @@ -83,15 +88,20 @@ struct SGCSettings{ int SFXVolume; int Rumble; 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 LastFileLoaded[MAXPATHLEN]; //Last file loaded filename char SaveFolder[MAXPATHLEN]; // Path to save 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 smbuser[20]; char smbpwd[20]; char smbshare[20]; }; - void ExitApp(); void ShutdownWii(); bool SupportedIOS(u32 ios); @@ -102,7 +112,7 @@ extern int ConfigRequested; extern int ShutdownRequested; extern int ExitRequested; extern char appPath[]; -extern char loadedFile[]; + extern FreeTypeGX *fontSystem[]; #endif diff --git a/source/vbasupport.cpp b/source/vbasupport.cpp index 5d7ae85..aa1e14d 100644 --- a/source/vbasupport.cpp +++ b/source/vbasupport.cpp @@ -16,6 +16,9 @@ #include #include +#include +#include + #include "vbagx.h" #include "fileop.h" #include "filebrowser.h" @@ -46,6 +49,9 @@ #include "vba/gb/gbCheats.h" #include "vba/gb/gbSound.h" +#include "goomba/goombarom.h" +#include "goomba/goombasav.h" + static u32 start; int cartridgeType = 0; u32 RomIdCode; @@ -72,7 +78,7 @@ int systemGreenShift = 0; int systemColorDepth = 0; u16 systemGbPalette[24]; u16 systemColorMap16[0x10000]; -u32 *systemColorMap32 = NULL; +u32 systemColorMap32[0x10000]; void gbSetPalette(u32 RRGGBB[]); bool StartColorizing(); @@ -141,29 +147,36 @@ void system10Frames(int rate) if (cartridgeType == 2) // GBA games require frameskipping { - // consider increasing skip - if(speed < 60) - systemFrameSkip += 4; - else if(speed < 70) - systemFrameSkip += 3; - else if(speed < 80) - systemFrameSkip += 2; - else if(speed < 98) - ++systemFrameSkip; - - // consider decreasing skip - else if(speed > 185) - systemFrameSkip -= 3; - else if(speed > 145) - systemFrameSkip -= 2; - else if(speed > 125) - systemFrameSkip -= 1; - - // correct invalid frame skip values - if(systemFrameSkip > 20) - systemFrameSkip = 20; - else if(systemFrameSkip < 0) + if (!GCSettings.gbaFrameskip) + { systemFrameSkip = 0; + } + else + { + // consider increasing skip + if(speed < 60) + systemFrameSkip += 4; + else if(speed < 70) + systemFrameSkip += 3; + else if(speed < 80) + systemFrameSkip += 2; + else if(speed < 98) + ++systemFrameSkip; + + // consider decreasing skip + else if(speed > 185) + systemFrameSkip -= 3; + else if(speed > 145) + systemFrameSkip -= 2; + else if(speed > 125) + systemFrameSkip -= 1; + + // correct invalid frame skip values + if(systemFrameSkip > 20) + systemFrameSkip = 20; + else if(systemFrameSkip < 0) + systemFrameSkip = 0; + } } lastTime = gettime(); } @@ -267,7 +280,35 @@ bool LoadBatteryOrState(char * filepath, int action, bool silent) // load the file into savebuffer 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 if (offset > 0) { @@ -319,6 +360,9 @@ bool LoadBatteryOrStateAuto(int action, bool silent) if (LoadBatteryOrState(filepath, action, SILENT)) return true; + if (!GCSettings.AppendAuto) + return false; + // look for file with no number or Auto appended if(!MakeFilePath(filepath2, action, ROMFilename, -1)) return false; @@ -372,6 +416,41 @@ bool SaveBatteryOrState(char * filepath, int action, bool silent) datasize = MemgbWriteBatteryFile((char *)savebuffer); else 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 { @@ -411,6 +490,30 @@ bool SaveBatteryOrStateAuto(int action, bool 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 @@ -614,11 +717,14 @@ void systemUpdateMotionSensor() ****************************************************************************/ static int srcWidth = 0; static int srcHeight = 0; -static int srcPitch = 0; void systemDrawScreen() { - GX_Render( srcWidth, srcHeight, pix, srcPitch ); + GX_Render( + srcWidth, + srcHeight, + pix + ); } static bool ValidGameId(u32 id) @@ -710,6 +816,8 @@ static void gbApplyPerImagePreferences() RomIdCode = SWEP5; else if (strcmp(RomTitle, "SRJ DMG") == 0) RomIdCode = SWEP6; + else if (strcmp(RomTitle, "KID DRACULA") == 0) + RomIdCode = KIDDRACULA; } // 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) @@ -825,11 +933,143 @@ void LoadPatch() 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(); 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); systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; @@ -847,6 +1087,27 @@ bool LoadGBROM() { 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) return false; @@ -854,10 +1115,24 @@ bool LoadGBROM() 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() { cartridgeType = 0; - bool loaded = false; + int loaded = 0; // image type (checks file extension) if(utilIsGBAImage(browserList[browser.selIndex].filename)) @@ -907,49 +1182,57 @@ bool LoadVBAROM() srcWidth = 0; srcHeight = 0; - srcPitch = 0; VMClose(); // cleanup GBA memory gbCleanUp(); // cleanup GB memory + + 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 - switch(cartridgeType) + if(cartridgeType == 2) { - case 2: - emulator = GBASystem; - srcWidth = 240; - srcHeight = 160; - loaded = VMCPULoadROM(); - srcPitch = 484; - soundSetSampleRate(22050); //44100 / 2 - cpuSaveType = 0; - break; + emulator = GBASystem; + srcWidth = 240; + srcHeight = 160; + loaded = VMCPULoadROM(); + soundSetSampleRate(22050); //44100 / 2 + cpuSaveType = 0; + if (loaded == 2) { + loaded = 0; + cartridgeType = 1; + } else if (loaded == 1 && GCSettings.SGBBorder == 2) { + LoadPNGBorder("defaultgba"); + } + } + + if (cartridgeType == 1) + { + emulator = GBSystem; + gbBorderOn = (GCSettings.SGBBorder == 1); - case 1: - emulator = GBSystem; + if(gbBorderOn) + { + srcWidth = 256; + srcHeight = 224; + gbBorderLineSkip = 256; + gbBorderColumnSkip = 48; + gbBorderRowSkip = 40; + SGBBorderLoadedFromGame = false; // try to load the border during rendering + } + else + { + srcWidth = 160; + srcHeight = 144; + gbBorderLineSkip = 160; + gbBorderColumnSkip = 0; + gbBorderRowSkip = 0; + } - gbBorderOn = 0; // GB borders always off - - if(gbBorderOn) - { - srcWidth = 256; - srcHeight = 224; - gbBorderLineSkip = 256; - gbBorderColumnSkip = 48; - gbBorderRowSkip = 40; - } - else - { - srcWidth = 160; - srcHeight = 144; - gbBorderLineSkip = 160; - gbBorderColumnSkip = 0; - gbBorderRowSkip = 0; - } - - loaded = LoadGBROM(); - srcPitch = 324; - soundSetSampleRate(44100); - break; + loaded = LoadGBROM(); + soundSetSampleRate(44100); } if(!loaded) @@ -960,7 +1243,11 @@ bool LoadVBAROM() else { // Setup GX - GX_Render_Init(srcWidth, srcHeight); + if (InitialBorder) { + GX_Render_Init(InitialBorderWidth, InitialBorderHeight); + } else { + GX_Render_Init(srcWidth, srcHeight); + } if (cartridgeType == 1) { @@ -1023,9 +1310,9 @@ void InitialisePalette() // Build GBPalette for( i = 0; i < 24; ) { - systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10); - systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10); - systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10); + systemGbPalette[i++] = (0x1c) | (0x1e << 5) | (0x1c << 10); + systemGbPalette[i++] = (0x10) | (0x17 << 5) | (0x0b << 10); + systemGbPalette[i++] = (0x27) | (0x0c << 5) | (0x0a << 10); systemGbPalette[i++] = 0; } // Set palette etc - Fixed to RGB565 diff --git a/source/vbasupport.h b/source/vbasupport.h index c9c55c4..5ca45f1 100644 --- a/source/vbasupport.h +++ b/source/vbasupport.h @@ -28,5 +28,6 @@ bool LoadBatteryOrState(char * filepath, int action, bool silent); bool LoadBatteryOrStateAuto(int action, bool silent); bool SaveBatteryOrState(char * filepath, int action, bool silent); bool SaveBatteryOrStateAuto(int action, bool silent); +bool SavePreviewImg (char * filepath, bool silent); #endif diff --git a/source/video.cpp b/source/video.cpp index e2f9318..97015eb 100644 --- a/source/video.cpp +++ b/source/video.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include "vbagx.h" #include "menu.h" #include "input.h" +#include "vbasupport.h" s32 CursorX, CursorY; bool CursorVisible; @@ -41,6 +43,11 @@ int gameScreenPngSize = 0; int screenheight = 480; int screenwidth = 640; +u16 *InitialBorder = NULL; +int InitialBorderWidth = 0; +int InitialBorderHeight = 0; +bool SGBBorderLoadedFromGame = false; + /*** 3D GX ***/ #define DEFAULT_FIFO_SIZE ( 256 * 1024 ) 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_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 } @@ -246,7 +253,7 @@ static inline void draw_cursor(Mtx v) GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, 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 } #endif @@ -290,6 +297,12 @@ static GXRModeObj * FindVideoMode() case 4: // PAL (60Hz) mode = &TVEurgb60Hz480IntDf; break; + case 5: // NTSC (240p) + mode = &TVNtsc240Ds; + break; + case 6: // PAL (60Hz 240p) + mode = &TVEurgb60Hz240Ds; + break; default: mode = VIDEO_GetPreferredMode(NULL); @@ -316,7 +329,7 @@ static GXRModeObj * FindVideoMode() if (mode == &TVPal576IntDfScale) pal = true; - if (CONF_GetAspectRatio() == CONF_ASPECT_16_9) + /*if (CONF_GetAspectRatio() == CONF_ASPECT_16_9 && mode->xfbHeight != 240) { if (pal) { @@ -334,9 +347,9 @@ static GXRModeObj * FindVideoMode() mode->efbHeight = 456; mode->viWidth = 686; } - else + else*/ { - mode->viWidth = 672; + mode->viWidth = 704; } if (pal) @@ -453,10 +466,7 @@ static inline void UpdateScaling() TvAspectRatio = 4.0f/3.0f; #endif - if (vwidth == 240) // GBA - 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 + GameboyAspectRatio = ((vwidth * 1.0) / vheight); if (TvAspectRatio>GameboyAspectRatio) { @@ -476,17 +486,37 @@ static inline void UpdateScaling() } // change zoom - if (vwidth == 240) // GBA + float zoomHor, zoomVert; + int fixed; + if (cartridgeType == 2) // GBA { - xscale *= GCSettings.gbaZoomHor; - yscale *= GCSettings.gbaZoomVert; + zoomHor = GCSettings.gbaZoomHor; + zoomVert = GCSettings.gbaZoomVert; + fixed = GCSettings.gbaFixed; } else { - xscale *= GCSettings.gbZoomHor; - yscale *= GCSettings.gbZoomVert; + zoomHor = GCSettings.gbZoomHor; + 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 square[0] = square[9] = -xscale + GCSettings.xshift; square[3] = square[6] = xscale + GCSettings.xshift; @@ -498,7 +528,23 @@ static inline void UpdateScaling() memset(&view, 0, sizeof(Mtx)); guLookAt(view, &cam.pos, &cam.up, &cam.view); - GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); + 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); + } updateScaling = 0; } @@ -523,7 +569,13 @@ ResetVideo_Emu () GX_SetDispCopySrc (0, 0, rmode->fbWidth, rmode->efbHeight); 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)); @@ -542,7 +594,7 @@ ResetVideo_Emu () // reinitialize texture 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 - 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_Flush(); @@ -569,26 +621,55 @@ void GX_Render_Init(int width, int 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 * * 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; - 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 *src2 = (long long int *) (buffer + pitch); - long long int *src3 = (long long int *) (buffer + (pitch << 1)); - long long int *src4 = (long long int *) (buffer + (pitch * 3)); - int rowpitch = (pitch >> 3) * 3; - int rowadjust = ( pitch % 8 ) << 2; + long long int *src2 = (long long int *) (buffer + gbPitch); + long long int *src3 = (long long int *) (buffer + (gbPitch << 1)); + long long int *src4 = (long long int *) (buffer + (gbPitch * 3)); + int srcrowpitch = (gbPitch >> 3) * 3; + int srcrowadjust = ( gbPitch % 8 ) << 2; + int dstrowpitch = borderWidth - gbWidth; - vwidth = width; - vheight = height; + vwidth = borderWidth; + vheight = borderHeight; - int vwid2 = (vwidth >> 2); + int vwid2 = (gbWidth >> 2); char *ra = NULL; // Ensure previous vb has complete @@ -605,8 +686,27 @@ void GX_Render(int width, int height, u8 * buffer, int pitch) GX_InvalidateTexAll(); GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL); 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) { @@ -616,24 +716,25 @@ void GX_Render(int width, int height, u8 * buffer, int pitch) *dst++ = *src4++; } - src1 += rowpitch; - src2 += rowpitch; - src3 += rowpitch; - src4 += rowpitch; + src1 += srcrowpitch; + src2 += srcrowpitch; + src3 += srcrowpitch; + src4 += srcrowpitch; + dst += dstrowpitch; - if ( rowadjust ) + if ( srcrowadjust ) { ra = (char *)src1; - src1 = (long long int *)(ra + rowadjust); + src1 = (long long int *)(ra + srcrowadjust); ra = (char *)src2; - src2 = (long long int *)(ra + rowadjust); + src2 = (long long int *)(ra + srcrowadjust); ra = (char *)src3; - src3 = (long long int *)(ra + rowadjust); + src3 = (long long int *)(ra + srcrowadjust); ra = (char *)src4; - src4 = (long long int *)(ra + rowadjust); + src4 = (long long int *)(ra + srcrowadjust); } } - + // load texture into GX DCFlushRange(texturemem, texturesize); @@ -690,6 +791,14 @@ void TakeScreenshot() void 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; f32 yscale; u32 xfbHeight; diff --git a/source/video.h b/source/video.h index 0da1991..4d950d8 100644 --- a/source/video.h +++ b/source/video.h @@ -1,41 +1,48 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * softdev 2007 - * - * video.h - * - * Video routines - ***************************************************************************/ - -#ifndef _GCVIDEOH_ -#define _GCVIDEOH_ - -#include - -void InitializeVideo (); -void GX_Render_Init(int width, int height); -void GX_Render(int width, int height, u8 * buffer, int pitch); -void StopGX(); -void ResetVideo_Emu(); -void ResetVideo_Menu(); -void TakeScreenshot(); -void Menu_Render(); -void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], f32 degrees, f32 scaleX, f32 scaleY, u8 alphaF ); -void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled); - -extern GXRModeObj *vmode; -extern int screenheight; -extern int screenwidth; -extern s32 CursorX, CursorY; -extern bool CursorVisible; -extern bool CursorValid; -extern bool TiltScreen; -extern float TiltAngle; -extern u8 * gameScreenTex; -extern u8 * gameScreenPng; -extern int gameScreenPngSize; -extern u32 FrameTimer; - -#endif +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * softdev 2007 + * + * video.h + * + * Video routines + ***************************************************************************/ + +#ifndef _GCVIDEOH_ +#define _GCVIDEOH_ + +#include + +void InitializeVideo (); +void GX_Render_Init(int width, int height); +void GX_Render(int gbWidth, int gbHeight, u8 * buffer); +void StopGX(); +void ResetVideo_Emu(); +void ResetVideo_Menu(); +void TakeScreenshot(); +void Menu_Render(); +void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], f32 degrees, f32 scaleX, f32 scaleY, u8 alphaF ); +void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled); + +extern GXRModeObj *vmode; +extern int screenheight; +extern int screenwidth; +extern s32 CursorX, CursorY; +extern bool CursorVisible; +extern bool CursorValid; +extern bool TiltScreen; +extern float TiltAngle; +extern u8 * gameScreenTex; +extern u8 * gameScreenPng; +extern int gameScreenPngSize; +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 diff --git a/source/vmmem.cpp b/source/vmmem.cpp index d162757..f14d573 100644 --- a/source/vmmem.cpp +++ b/source/vmmem.cpp @@ -1,442 +1,451 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * vmmem.cpp - * - * GameBoy Advance Virtual Memory Paging - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "vbagx.h" -#include "fileop.h" -#include "menu.h" -#include "filebrowser.h" -#include "gcunzip.h" - -#include "vba/gba/GBA.h" -#include "vba/gba/Globals.h" -#include "vba/Util.h" -#include "vba/common/Port.h" - -#define MEM_BAD 0xff -#define MEM_VM 0x01 -#define MEM_UN 0x80 - -int GBAROMSize = 0; - -#ifdef USE_VM - -/** Setup VM to use small 16kb windows **/ -#define VMSHIFTBITS 14 -#define VMSHIFTMASK 0x3FFF -#define MAXGBAROM ( 32 * 1024 * 1024 ) -#define MAXROM (4 * 1024 * 1024) -#define MAXVMPAGE ( MAXGBAROM >> VMSHIFTBITS ) -#define MAXVMMASK ( ( MAXROM >> VMSHIFTBITS ) - 1 ) - -typedef struct - { - char *pageptr; - int pagetype; - int pageno; - } -VMPAGE; - -static VMPAGE vmpage[MAXVMPAGE]; -static int vmpageno = 0; -static FILE* romfile = NULL; -static char *rombase = NULL; -#endif - -extern void CPUUpdateRenderBuffers(bool force); - -/**************************************************************************** -* VMClose -****************************************************************************/ -void VMClose() -{ - if(vram != NULL) - { - free(vram); - vram = NULL; - } - - if(paletteRAM != NULL) - { - free(paletteRAM); - paletteRAM = NULL; - } - - if(internalRAM != NULL) - { - free(internalRAM); - internalRAM = NULL; - } - - if(workRAM != NULL) - { - free(workRAM); - workRAM = NULL; - } - - if(bios != NULL) - { - free(bios); - bios = NULL; - } - - if(pix != NULL) - { - free(pix); - pix = NULL; - } - - if(oam != NULL) - { - free(oam); - oam = NULL; - } - - if(ioMem != NULL) - { - free(ioMem); - ioMem = NULL; - } - - #ifdef USE_VM - if (rombase != NULL) - { - free(rombase); - rombase = NULL; - } - #endif -} - -/**************************************************************************** -* VMAllocGBA -* -* Allocate the memory required for GBA. -****************************************************************************/ -static void VMAllocGBA( void ) -{ - workRAM = (u8 *)calloc(1, 0x40000); - bios = (u8 *)calloc(1,0x4000); - internalRAM = (u8 *)calloc(1,0x8000); - paletteRAM = (u8 *)calloc(1,0x400); - vram = (u8 *)calloc(1, 0x20000); - oam = (u8 *)calloc(1, 0x400); - pix = (u8 *)calloc(1, 4 * 241 * 162); - ioMem = (u8 *)calloc(1, 0x400); - - if(workRAM == NULL || bios == NULL || internalRAM == NULL || - paletteRAM == NULL || vram == NULL || oam == NULL || - pix == NULL || ioMem == NULL) - { - ErrorPrompt("Out of memory!"); - VMClose(); - } -} - -#ifndef USE_VM -/**************************************************************************** -* VMCPULoadROM -* -* MEM2 version of GBA CPULoadROM -****************************************************************************/ - -bool VMCPULoadROM() -{ - VMClose(); - VMAllocGBA(); - GBAROMSize = 0; - - if(!inSz) - { - char filepath[1024]; - - if(!MakeFilePath(filepath, FILE_ROM)) - return false; - - GBAROMSize = LoadFile ((char *)rom, filepath, browserList[browser.selIndex].length, NOTSILENT); - } - else - { - GBAROMSize = LoadSzFile(szpath, (unsigned char *)rom); - } - - if(GBAROMSize) - { - flashInit(); - eepromInit(); - CPUUpdateRenderBuffers( true ); - return true; - } - else - { - VMClose(); - return false; - } -} -#else - -/**************************************************************************** -* VMFindFree -* -* Look for a free page in the VM block. If none found, do a round-robin -****************************************************************************/ -static void VMFindFree( void ) -{ - ++vmpageno; - vmpageno &= MAXVMMASK; - if ( vmpageno == 0 ) ++vmpageno; - - for (unsigned i = 1; i < MAXVMPAGE; ++i ) - { - /** Remove any other pointer to this vmpage **/ - if ( vmpage[i].pageno == vmpageno ) - { - vmpage[i].pageptr = NULL; - vmpage[i].pagetype = MEM_UN; - vmpage[i].pageno = -1; - break; - } - } -} - -/**************************************************************************** -* VMAllocate -* -* Allocate a VM page -****************************************************************************/ -static void VMAllocate( int pageid ) -{ - VMFindFree(); - vmpage[pageid].pageptr = rombase + ( vmpageno << VMSHIFTBITS ); - vmpage[pageid].pagetype = MEM_VM; - vmpage[pageid].pageno = vmpageno; -} - -/**************************************************************************** -* VMInit -* -* Set everything to default -****************************************************************************/ -static void VMInit( void ) -{ - /** Clear down pointers **/ - memset(&vmpage, 0, sizeof(VMPAGE) * MAXVMPAGE); - - if(MAXVMPAGE % 4 == 0) - { - for (unsigned i =0 ; i < MAXVMPAGE; i+=4 ) - { - vmpage[i ].pageno = -1; - vmpage[i ].pagetype = MEM_UN; - vmpage[i+1].pageno = -1; - vmpage[i+1].pagetype = MEM_UN; - vmpage[i+2].pageno = -1; - vmpage[i+2].pagetype = MEM_UN; - vmpage[i+3].pageno = -1; - vmpage[i+3].pagetype = MEM_UN; - } - } - else - { - for (unsigned i =0 ; i < MAXVMPAGE; ++i ) - { - vmpage[i].pageno = -1; - vmpage[i].pagetype = MEM_UN; - } - } - - /** Allocate physical **/ - if ( rombase == NULL ) - rombase = (char *)memalign(32, MAXROM); - - vmpageno = 0; - rom = (u8 *)rombase; -} - -/**************************************************************************** -* VMCPULoadROM -* -* VM version of GBA CPULoadROM -****************************************************************************/ - -int VMCPULoadROM() -{ - int res; - char filepath[MAXPATHLEN]; - - if(!MakeFilePath(filepath, FILE_ROM)) - return 0; - - // loading compressed files via VM is not supported - if(!utilIsGBAImage(filepath)) - { - ErrorPrompt("Compressed GBA files are not supported!"); - return 0; - } - - if (romfile != NULL) - fclose(romfile); - - romfile = fopen(filepath, "rb"); - - if (romfile == NULL) - { - ErrorPrompt("Error opening file!"); - return 0; - } - - /** Fix VM **/ - VMClose(); - VMInit(); - VMAllocGBA(); - - GBAROMSize = 0; - - res = fread(rom, 1, (1 << VMSHIFTBITS), romfile); - if ( res != (1 << VMSHIFTBITS ) ) - { - ErrorPrompt("Error reading file!"); - VMClose(); - return 0; - } - - fseeko(romfile,0,SEEK_END); - GBAROMSize = ftello(romfile); - - vmpageno = 0; - vmpage[0].pageptr = rombase; - vmpage[0].pageno = 0; - vmpage[0].pagetype = MEM_VM; - - flashInit(); - eepromInit(); - CPUUpdateRenderBuffers( true ); - - return 1; -} - -/**************************************************************************** -* GBA Memory Read Routines -****************************************************************************/ -/**************************************************************************** -* VMNewPage -****************************************************************************/ -static void VMNewPage( int pageid ) -{ - int res = fseek( romfile, pageid << VMSHIFTBITS, SEEK_SET ); - - if (res) // fseek returns non-zero on a failure - { - ErrorPrompt("Seek error!"); - VMClose(); - ExitApp(); - } - - VMAllocate( pageid ); - - res = fread( vmpage[pageid].pageptr, 1, 1 << VMSHIFTBITS, romfile ); -} - -/**************************************************************************** - * VMRead32 - * - * Return a 32bit value - ****************************************************************************/ -u32 VMRead32( u32 address ) -{ - if ( address >= (u32)GBAROMSize ) - { - return u32(( ( ( address >> 1 ) & 0xffff ) << 16 ) | ( ( ( address + 2 ) >> 1 ) & 0xffff )); - } - - int pageid = address >> VMSHIFTBITS; - - switch( vmpage[pageid].pagetype ) - { - case MEM_UN: - VMNewPage(pageid); - - case MEM_VM: - return READ32LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) ); - - default: - ErrorPrompt("VM32: Unknown page type!"); - VMClose(); - ExitApp(); - return 0; - } -} - -/**************************************************************************** - * VMRead16 - * - * Return a 16bit value - ****************************************************************************/ -u16 VMRead16( u32 address ) -{ - if ( address >= (u32)GBAROMSize ) - { - return ( address >> 1 ) & 0xffff; - } - - int pageid = address >> VMSHIFTBITS; - - switch( vmpage[pageid].pagetype ) - { - case MEM_UN: - VMNewPage(pageid); - - case MEM_VM: - return READ16LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) ); - - default: - ErrorPrompt("VM16: Unknown page type!"); - VMClose(); - ExitApp(); - return 0; - } -} - -/**************************************************************************** - * VMRead8 - * - * Return 8bit value - ****************************************************************************/ -u8 VMRead8( u32 address ) -{ - if ( address >= (u32)GBAROMSize ) - { - return ( address >> 1 ) & 0xff; - } - - int pageid = address >> VMSHIFTBITS; - - switch( vmpage[pageid].pagetype ) - { - case MEM_UN: - VMNewPage(pageid); - - case MEM_VM: - return (u8)vmpage[pageid].pageptr[ (address & VMSHIFTMASK) ]; - - default: - ErrorPrompt("VM8: Unknown page type!"); - VMClose(); - ExitApp(); - return 0; - } -} - -#endif +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * vmmem.cpp + * + * GameBoy Advance Virtual Memory Paging + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "vbagx.h" +#include "fileop.h" +#include "menu.h" +#include "filebrowser.h" +#include "gcunzip.h" + +#include "vba/gba/GBA.h" +#include "vba/gba/Globals.h" +#include "vba/Util.h" +#include "vba/common/Port.h" +#include "goomba/goombarom.h" + +#define MEM_BAD 0xff +#define MEM_VM 0x01 +#define MEM_UN 0x80 + +int GBAROMSize = 0; + +#ifdef USE_VM + +/** Setup VM to use small 16kb windows **/ +#define VMSHIFTBITS 14 +#define VMSHIFTMASK 0x3FFF +#define MAXGBAROM ( 32 * 1024 * 1024 ) +#define MAXROM (4 * 1024 * 1024) +#define MAXVMPAGE ( MAXGBAROM >> VMSHIFTBITS ) +#define MAXVMMASK ( ( MAXROM >> VMSHIFTBITS ) - 1 ) + +typedef struct + { + char *pageptr; + int pagetype; + int pageno; + } +VMPAGE; + +static VMPAGE vmpage[MAXVMPAGE]; +static int vmpageno = 0; +static FILE* romfile = NULL; +static char *rombase = NULL; +#endif + +extern void CPUUpdateRenderBuffers(bool force); + +/**************************************************************************** +* VMClose +****************************************************************************/ +void VMClose() +{ + if(vram != NULL) + { + free(vram); + vram = NULL; + } + + if(paletteRAM != NULL) + { + free(paletteRAM); + paletteRAM = NULL; + } + + if(internalRAM != NULL) + { + free(internalRAM); + internalRAM = NULL; + } + + if(workRAM != NULL) + { + free(workRAM); + workRAM = NULL; + } + + if(bios != NULL) + { + free(bios); + bios = NULL; + } + + if(pix != NULL) + { + free(pix); + pix = NULL; + } + + if(oam != NULL) + { + free(oam); + oam = NULL; + } + + if(ioMem != NULL) + { + free(ioMem); + ioMem = NULL; + } + + #ifdef USE_VM + if (rombase != NULL) + { + free(rombase); + rombase = NULL; + } + #endif +} + +/**************************************************************************** +* VMAllocGBA +* +* Allocate the memory required for GBA. +****************************************************************************/ +static void VMAllocGBA( void ) +{ + workRAM = (u8 *)calloc(1, 0x40000); + bios = (u8 *)calloc(1,0x4000); + internalRAM = (u8 *)calloc(1,0x8000); + paletteRAM = (u8 *)calloc(1,0x400); + vram = (u8 *)calloc(1, 0x20000); + oam = (u8 *)calloc(1, 0x400); + pix = (u8 *)calloc(1, 4 * 241 * 162); + ioMem = (u8 *)calloc(1, 0x400); + + if(workRAM == NULL || bios == NULL || internalRAM == NULL || + paletteRAM == NULL || vram == NULL || oam == NULL || + pix == NULL || ioMem == NULL) + { + ErrorPrompt("Out of memory!"); + VMClose(); + } +} + +#ifndef USE_VM +/**************************************************************************** +* VMCPULoadROM +* +* MEM2 version of GBA CPULoadROM +****************************************************************************/ + +int VMCPULoadROM() +{ + VMClose(); + GBAROMSize = 0; + + if(!inSz) + { + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_ROM)) + return 0; + + GBAROMSize = LoadFile ((char *)rom, filepath, browserList[browser.selIndex].length, NOTSILENT); + } + else + { + 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) + { + flashInit(); + eepromInit(); + CPUUpdateRenderBuffers( true ); + return 1; + } + else + { + VMClose(); + return 0; + } +} +#else + +/**************************************************************************** +* VMFindFree +* +* Look for a free page in the VM block. If none found, do a round-robin +****************************************************************************/ +static void VMFindFree( void ) +{ + ++vmpageno; + vmpageno &= MAXVMMASK; + if ( vmpageno == 0 ) ++vmpageno; + + for (unsigned i = 1; i < MAXVMPAGE; ++i ) + { + /** Remove any other pointer to this vmpage **/ + if ( vmpage[i].pageno == vmpageno ) + { + vmpage[i].pageptr = NULL; + vmpage[i].pagetype = MEM_UN; + vmpage[i].pageno = -1; + break; + } + } +} + +/**************************************************************************** +* VMAllocate +* +* Allocate a VM page +****************************************************************************/ +static void VMAllocate( int pageid ) +{ + VMFindFree(); + vmpage[pageid].pageptr = rombase + ( vmpageno << VMSHIFTBITS ); + vmpage[pageid].pagetype = MEM_VM; + vmpage[pageid].pageno = vmpageno; +} + +/**************************************************************************** +* VMInit +* +* Set everything to default +****************************************************************************/ +static void VMInit( void ) +{ + /** Clear down pointers **/ + memset(&vmpage, 0, sizeof(VMPAGE) * MAXVMPAGE); + + if(MAXVMPAGE % 4 == 0) + { + for (unsigned i =0 ; i < MAXVMPAGE; i+=4 ) + { + vmpage[i ].pageno = -1; + vmpage[i ].pagetype = MEM_UN; + vmpage[i+1].pageno = -1; + vmpage[i+1].pagetype = MEM_UN; + vmpage[i+2].pageno = -1; + vmpage[i+2].pagetype = MEM_UN; + vmpage[i+3].pageno = -1; + vmpage[i+3].pagetype = MEM_UN; + } + } + else + { + for (unsigned i =0 ; i < MAXVMPAGE; ++i ) + { + vmpage[i].pageno = -1; + vmpage[i].pagetype = MEM_UN; + } + } + + /** Allocate physical **/ + if ( rombase == NULL ) + rombase = (char *)memalign(32, MAXROM); + + vmpageno = 0; + rom = (u8 *)rombase; +} + +/**************************************************************************** +* VMCPULoadROM +* +* VM version of GBA CPULoadROM +****************************************************************************/ + +int VMCPULoadROM() +{ + int res; + char filepath[MAXPATHLEN]; + + if(!MakeFilePath(filepath, FILE_ROM)) + return 0; + + // loading compressed files via VM is not supported + if(!utilIsGBAImage(filepath)) + { + ErrorPrompt("Compressed GBA files are not supported!"); + return 0; + } + + if (romfile != NULL) + fclose(romfile); + + romfile = fopen(filepath, "rb"); + + if (romfile == NULL) + { + ErrorPrompt("Error opening file!"); + return 0; + } + + /** Fix VM **/ + VMClose(); + VMInit(); + VMAllocGBA(); + + GBAROMSize = 0; + + res = fread(rom, 1, (1 << VMSHIFTBITS), romfile); + if ( res != (1 << VMSHIFTBITS ) ) + { + ErrorPrompt("Error reading file!"); + VMClose(); + return 0; + } + + fseeko(romfile,0,SEEK_END); + GBAROMSize = ftello(romfile); + + vmpageno = 0; + vmpage[0].pageptr = rombase; + vmpage[0].pageno = 0; + vmpage[0].pagetype = MEM_VM; + + flashInit(); + eepromInit(); + CPUUpdateRenderBuffers( true ); + + return 1; +} + +/**************************************************************************** +* GBA Memory Read Routines +****************************************************************************/ +/**************************************************************************** +* VMNewPage +****************************************************************************/ +static void VMNewPage( int pageid ) +{ + int res = fseek( romfile, pageid << VMSHIFTBITS, SEEK_SET ); + + if (res) // fseek returns non-zero on a failure + { + ErrorPrompt("Seek error!"); + VMClose(); + ExitApp(); + } + + VMAllocate( pageid ); + + res = fread( vmpage[pageid].pageptr, 1, 1 << VMSHIFTBITS, romfile ); +} + +/**************************************************************************** + * VMRead32 + * + * Return a 32bit value + ****************************************************************************/ +u32 VMRead32( u32 address ) +{ + if ( address >= (u32)GBAROMSize ) + { + return u32(( ( ( address >> 1 ) & 0xffff ) << 16 ) | ( ( ( address + 2 ) >> 1 ) & 0xffff )); + } + + int pageid = address >> VMSHIFTBITS; + + switch( vmpage[pageid].pagetype ) + { + case MEM_UN: + VMNewPage(pageid); + + case MEM_VM: + return READ32LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) ); + + default: + ErrorPrompt("VM32: Unknown page type!"); + VMClose(); + ExitApp(); + return 0; + } +} + +/**************************************************************************** + * VMRead16 + * + * Return a 16bit value + ****************************************************************************/ +u16 VMRead16( u32 address ) +{ + if ( address >= (u32)GBAROMSize ) + { + return ( address >> 1 ) & 0xffff; + } + + int pageid = address >> VMSHIFTBITS; + + switch( vmpage[pageid].pagetype ) + { + case MEM_UN: + VMNewPage(pageid); + + case MEM_VM: + return READ16LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) ); + + default: + ErrorPrompt("VM16: Unknown page type!"); + VMClose(); + ExitApp(); + return 0; + } +} + +/**************************************************************************** + * VMRead8 + * + * Return 8bit value + ****************************************************************************/ +u8 VMRead8( u32 address ) +{ + if ( address >= (u32)GBAROMSize ) + { + return ( address >> 1 ) & 0xff; + } + + int pageid = address >> VMSHIFTBITS; + + switch( vmpage[pageid].pagetype ) + { + case MEM_UN: + VMNewPage(pageid); + + case MEM_VM: + return (u8)vmpage[pageid].pageptr[ (address & VMSHIFTMASK) ]; + + default: + ErrorPrompt("VM8: Unknown page type!"); + VMClose(); + ExitApp(); + return 0; + } +} + +#endif diff --git a/source/vmmem.h b/source/vmmem.h index 887d281..d1835b1 100644 --- a/source/vmmem.h +++ b/source/vmmem.h @@ -1,26 +1,26 @@ -/**************************************************************************** - * Visual Boy Advance GX - * - * Tantric September 2008 - * - * vmmem.h - * - * GameBoy Advance Virtual Memory Paging - ***************************************************************************/ - -#ifndef __VBAVMHDR__ -#define __VBAVMHDR__ - -bool VMCPULoadROM(); -void VMClose(); - -#ifdef USE_VM -u32 VMRead32( u32 address ); -u16 VMRead16( u32 address ); -u8 VMRead8( u32 address ); -#endif - -extern int GBAROMSize; - -#endif - +/**************************************************************************** + * Visual Boy Advance GX + * + * Tantric September 2008 + * + * vmmem.h + * + * GameBoy Advance Virtual Memory Paging + ***************************************************************************/ + +#ifndef __VBAVMHDR__ +#define __VBAVMHDR__ + +int VMCPULoadROM(); +void VMClose(); + +#ifdef USE_VM +u32 VMRead32( u32 address ); +u16 VMRead16( u32 address ); +u8 VMRead8( u32 address ); +#endif + +extern int GBAROMSize; + +#endif + diff --git a/update.xml b/update.xml index dc37241..394bb13 100644 --- a/update.xml +++ b/update.xml @@ -1,4 +1,4 @@ - +