NOTE: The patches in this file are taken from the CVS repository for the VisualBoyAdvance project; they are distributed under the same license as VisualBoyAdvance itself (GPL version 2 or later). diff -urN ../VisualBoyAdvance-1.7.2/.cvsignore ./.cvsignore --- ../VisualBoyAdvance-1.7.2/.cvsignore 1970-01-01 09:00:00 +0900 +++ ./.cvsignore 2004-01-21 12:40:10 +0900 @@ -0,0 +1,2 @@ +autom4te.cache +.DS_Store diff -urN ../VisualBoyAdvance-1.7.2/AUTHORS ./AUTHORS --- ../VisualBoyAdvance-1.7.2/AUTHORS 2004-05-22 23:02:30 +0900 +++ ./AUTHORS 2006-04-30 04:06:28 +0900 @@ -12,3 +12,4 @@ - KVA: ARM/THUMB disassembler - kxu: GTK+ interface - Yann Parmentier aka kohai: new icons +- Spacy: Windows, Visual Studio 2005, DirectX \ No newline at end of file diff -urN ../VisualBoyAdvance-1.7.2/ChangeLog.1.5.1 ./ChangeLog.1.5.1 --- ../VisualBoyAdvance-1.7.2/ChangeLog.1.5.1 1970-01-01 09:00:00 +0900 +++ ./ChangeLog.1.5.1 2003-07-19 21:03:55 +0900 @@ -0,0 +1,323 @@ +2003-06-08 Forgotten + + * src/Sound.cpp (soundMix): fixed sound ratio problem with DS channels + +2003-06-04 Forgotten + + * src/Cheats.cpp (cheatsAdd): fixed bug that changed ROM with some codes + +2003-06-03 Forgotten + + * src/RTC.cpp (rtcWrite): fixed problem on last day of the month + +2003-06-02 Forgotten + + * src/SDL.cpp: changed pause when inactive default to false + +2003-05-28 Forgotten + + * src/arm-new.h: added PowerPC assembly code contributed by Jeffrey Lim + * src/thumb.h: added PowerPC assembly code contributed by Jeffrey Lim + +2003-05-26 Forgotten + + * src/win32/skin.cpp: make skin region optional + * src/Cheats.cpp (cheatsCheckKeys): extra AR support + * src/win32/Win32.cpp (systemReadJoypad): disallow L+R,U+D to be pressed together + * src/SDL.cpp (systemReadJoypad): disallow L+R,U+D to be pressed together + +2003-05-22 Forgotten + + * src/Cheats.cpp: add support for AR codes (thanks P.S.) + +2003-05-20 Forgotten + + * src/win32/skinButton.cpp (OnMouseLeave): try to detect when mouse is not over button better + +2003-05-14 Forgotten + + * src/win32/OpenGL.cpp: fix fullscreen problem + * src/win32/Win32.cpp: fix stretch to fit problem + * src/win32/Direct3D.cpp: fix stretch to fit problem + * src/win32/GDIDisplay.cpp: fix speed display + +2003-05-13 Forgotten + + * src/VisualBoyAdvance.cfg: changed separator to equal sign + * src/win32/Wnd.cpp: added default and create message support + * src/win32/Win32.cpp (WindowProc): update menu with accelerators when changing modes + * src/win32/Commands.cpp (winAccelGetID): added method to retrieve accelerator IDs and minimize function + * src/win32/skin.cpp: added button support and error messages + * src/win32/skinButton.cpp: created + +2003-04-24 Forgotten + + * src/win32/AcceleratorManager.cpp (Load): allow user to delete the default accelerators + * src/win32/WriteAVI.cpp (SetSoundFormat): added sound support + * src/Mode5.cpp: minor rendering optimization + * src/Mode4.cpp: minor rendering optimization + * src/Mode3.cpp: minor rendering optimization + * src/Mode2.cpp: minor rendering optimization + * src/Mode1.cpp: minor rendering optimization + * src/Mode0.cpp: minor rendering optimization + * src/GBA.cpp (CPUUpdateRenderBuffers): minor rendering improvement + +2003-04-19 Forgotten + + * src/win32/Win32.cpp (initApp): fixed Gameboy Printer initialization + * src/win32/Win32.cpp (WindowProc): fixed popup menu problem on Win 95/98/Me (unimplemented Unicode functions) + * src/win32/AcceleratorManager.cpp (UpdateMenu): take into account Win 95/98/Me + +2003-04-15 Forgotten + + * src/win32/skin.cpp (Hook): moved SetWindowRgn to after resizing and style change + +2003-04-07 Forgotten + + * VBA: too many changes to detail... + +2003-02-02 Forgotten + + * src/win32/Win32.cpp: added throttle support + * src/GBA.cpp (CPUUpdateRegister): fixed some wrong timer assumption (bad copy/paste) + +2003-01-29 Forgotten + + * src/win32/Win32.cpp: use registry or INI to store settings + * src/win32/Reg.cpp: use registry or INI to store settings + * src/win32/AcceleratorManager.cpp: use Reg.cpp to store settings + +2003-01-25 Forgotten + + * src/win32/Win32.cpp (WindowProc): minimize problem when minimizing emulator in fullscreen mode and filter is active + * src/win32/Win32.cpp (updateLayersMenu): added support to enable/disable GB/GBC layers + +2003-01-21 Forgotten + + * src/elf.cpp (elfReadProgram): added support for DW_FORM_strp + * src/interframe.cpp: added missing EMMS instructions to GCC inline assembly + * src/admame.cpp: added missing EMMS instructions to GCC inline assembly + +2003-01-20 Forgotten + + * src/win32/Win32.cpp (initApp): fixed disable SFX flag not being read + +2003-01-18 Forgotten + + * src/gb/GB.cpp (gbEmulate): changed interface with emulator for joypad + * src/GBA.cpp (CPULoop): changed interface with emulator for joypad + * src/win32/Win32.cpp: added support for multiple joypad configuration + +2003-01-14 Forgotten + + * src/win32/Win32.cpp (initApp): fixed problem when video mode was never selected + +2003-01-13 Forgotten + + * src/SDL.cpp: show detailed speed data + added auto frameskip support + CTRL+F to toggle fullscreen + +2003-01-12 Forgotten + + * src/win32/Win32.cpp: added some debugging for DDRAW and DINPUT + * src/win32/Win32.cpp: changed rendering when menu is active with triple buffering + +2003-01-11 Forgotten + + * src/GBA.cpp (CPULoop): set emulation speed value + * src/win32/Win32.cpp: added support for fullscreen speed display + * src/win32/Win32.cpp: support for triple buffering in fullscreen mode + * src/gb/GB.cpp (gbEmulate): set emulation speed value + * src/SDL.cpp: added support for fullscreen speed display + +2003-01-08 Forgotten + + * src/win32/Win32.cpp (systemMessage): fixed problem displaying error messages in fullscreen mode + * src/win32/Win32.cpp: added support to other resolutions for fullscreen mode + +2003-01-05 Forgotten + + * src/win32/Win32.cpp (detectMMX): added support for AMD CPUs + * src/win32/TileViewer.cpp: now shows all tiles in 256 mode + * src/elf.cpp (elfCleanUp): fixed crash when reloading an ELF file + * src/win32/Commands.cpp: added interframe blending commands + * src/win32/Win32.cpp: added interframe blending support + * src/SDL.cpp: added interframe blending support + +2003-01-03 Forgotten + + * src/win32/Win32.cpp: added bilinear filter support + * src/SDL.cpp: added bilinear filter support + +2002-12-11 Forgotten + + * src/Flash.cpp (flashSetSize): fixed reversed device ID and manufacturer ID + +2002-12-09 Forgotten + + * src/win32/Win32.cpp (fileExportGSASnapshot): change default title to internal name + * src/win32/Win32.cpp (WindowProc): added sound volume option + * src/win32/Win32.cpp (updateFileMenu): allow pausing even if not emulating yet + * src/win32/Win32.cpp: added AVI writing support + +2002-12-02 Forgotten + + * src/win32/Commands.cpp: added missing options + * src/win32/Win32.cpp (updateFilter): added 32-bit mode support for Kreed filters + * src/SDL.cpp (main): added 32-bit mode support for Kreed filters + * src/2xSaI.cpp (Scale_2xSaI): added 32-bit mode support + +2002-12-01 Forgotten + + * src/tvmode.cpp (TVMode32): 32-bit mode support + * src/simple2x.cpp (Simple2x32): 32-bit mode support + * src/pixel.cpp (Pixelate32): 32-bit mode support + * src/motionblur.cpp (MotionBlur32): 32-bit mode support + * src/admame.cpp (AdMame2x32): 32-bit mode support + * src/SDL.cpp (systemDrawScreen): added support for filters in 32-bit mode + * src/win32/Win32.cpp (updateFilter): added support for filters in 32-bit mode + +2002-11-29 Forgotten + + * src/Sound.cpp (soundMix): respect sound rations for CGB and DS + * src/GBA.cpp (CPULoadRom): fill memory to simulate no cartridge connected + +2002-11-28 Forgotten + + * src/GBA.cpp (CPULoop): renamed arm-new.cpp and thumb.cpp to .h + +2002-11-27 Forgotten + + * src/win32/Win32.cpp (fileOpen): add option for no IPS patching + * src/SDL.cpp (main): add option for no IPS patching + +2002-11-26 Forgotten + + * src/GBA.cpp (CPULoadRom): check for memory allocation error + * src/GBA.cpp (CPUWriteBatteryFile): fixed error message when failed to write battery file + +2002-11-25 Forgotten + + * src/SDL.cpp (systemSoundInit): correct sound type for big endian systems + * src/Gfx.h (gfxDrawSprites): fixed big endian problem with rotation sprites + * src/bios.cpp (BIOS_MidiKey2Freq): small clean up on logging + * src/win32/MemoryViewer.cpp (setCaretPos): show current edit address + * src/win32/MemoryViewer.cpp (OnLoad): added load/save memory support + * src/win32/RomInfo.cpp (OnInitDialog): fixed bug showing maker code/name in some old GB roms + +2002-11-24 Forgotten + + * src/SDL.cpp: added flag for help and configuration file + +2002-11-23 Forgotten + + * src/win32/GBACheats.cpp: cleaned up some unused stuff + * src/SDL.cpp: added support for long options + * src/Flash.cpp: added support for 128K Flash (thanks DesktopMan) + * src/GBA.cpp: added support for 128K Flash + +2002-11-21 Forgotten + + * src/gb/gbSGB.cpp: fixed big endian problems + * src/win32/Win32.cpp (updateVideoMenu): fixed missing check marks on layers menu + +2002-11-20 Forgotten + + * src/SDL.cpp (main): added profiling support + * src/GBA.cpp: added profiling support + * src/prof/prof.cpp: added profiling support + +2002-11-14 Forgotten + + * src/win32/Win32.cpp (systemWriteDataToSoundBuffer): remove test code that causes slowdown + +2002-11-13 Forgotten + + * src/SDL.cpp (sdlFindPreferences): improve search for configuration file + +2002-11-12 Forgotten + + * src/SDL.cpp (sdlReadPreferences): fixed incorrect variable being used for saveType + (main): removeIntros was not being used + (main): apply IPS patch automatically if it exists + * src/Util.cpp (utilApplyIPS): added IPS patching code + * src/win32/Win32.cpp (fileOpen): apply IPS patch automatically if it exists + +2002-11-07 Forgotten + + * src/SDL.cpp (main): fixed crash when trying load file that does not exist + * src/SDL.cpp (systemUpdateMotionSensor): implemented motion sensor for the SDL version + +2002-11-06 Forgotten + + * src/elf.cpp: fix wrong usage of CPUReadMemory + * src/admame.cpp: fixed incorrect #ifdef usage + * configure.in: added test for socklen_t type + * src/remote.cpp: fix problem compiling in some systems + * src/GBA.cpp (CPULoop): added support for movement sensor + * src/GBA.cpp (CPUReset): added support for selecting save type available + +2002-11-05 Forgotten + + * src/win32/DirectoriesDlg.cpp (browseForDir): fix bug when changing directory using the Browse button + +2002-11-04 Forgotten + + * src/GBA.cpp (CPUUpdateRegister): do not change timer data when writting to register TMxD. Only a restart or overflow will change the value + +2002-11-02 Forgotten + + * src/GBA.cpp (CPUWriteGSASnapshot): Compute CRC of save + +2002-10-31 Forgotten + + * src/GBA.cpp (CPUWriteGSASnapshot): fixed a few bytes in the snapshot + * src/Sound.cpp (soundEvent): fixed envelope reload bugs + * src/bios.cpp (BIOS_MidiKey2Freq): Added method (user contribution) + * src/Gfx.h: fixed problems in big endian machines + +2002-10-29 Forgotten + + * src/thumb.cpp: fixed bugs in C core + +2002-10-28 Forgotten + + * src/GBA.cpp (CPUSoftwareInterrupt): improved message about BIOS calls that are not emulated and need a BIOS file + * src/GBA.cpp (CPUInit): fix bug setting reable IO positions + +2002-10-27 Forgotten + + * src/SDL.cpp (sdlReadPreferences): Fixed warning if MMX not in use when reading the configuration file + * src/SDL.cpp (main): Fixed crash if BIOS file not specified correctly + * src/win32/Win32.cpp: Support for higher frameskip + * src/SDL.cpp: Support for higher frameskip + +2002-10-26 Forgotten + + * src/win32/Win32.cpp: Add 800x600 support + +2002-10-25 Forgotten + + * src/win32/Win32.cpp (fileExportGSASnapshot): added code + * src/win32/ExportGSASnapshot.cpp: Created dialog + * src/win32/Commands.cpp: Added new menu options + +2002-10-24 Forgotten + + * src/GBA.cpp (CPUReadGSASnapshot): Now skipping notes if they exist + +2002-10-23 Forgotten + + * src/win32/Win32.cpp (initApp): remember freeze recent list flag + +2002-10-22 Forgotten + + * win32/.cvsignore: added output directories and MSVC files to ignore + * src/win32/.cvsignore: Added vba.aps to ignore list + * src/TestEmu.cpp (systemPauseOnFrame): Added missing return statement + * INSTALL: Updated GCC requirements + * src/win32/Win32.cpp: added flag to freeze recent list + * src/win32/vba.rc: added flag to freeze recent list + * Initial Public Version + diff -urN ../VisualBoyAdvance-1.7.2/ChangeLog.1.7 ./ChangeLog.1.7 --- ../VisualBoyAdvance-1.7.2/ChangeLog.1.7 1970-01-01 09:00:00 +0900 +++ ./ChangeLog.1.7 2004-01-20 09:45:50 +0900 @@ -0,0 +1,157 @@ +2003-09-03 Forgotten + + * src/armdis.cpp: fixed thumb disassembly bug with ldsb and ldrh opcodes + +2003-08-23 Forgotten + + * src/win32/Win32.cpp (updateRenderMethod0): return true if render type did not change + * src/bios.cpp (BIOS_CpuSet): fixed bug introduced in previous fix + * src/GBA.cpp (CPULoop): fixed slowdown problem introduced in version 1.6 + +2003-08-09 Forgotten + + * src/GBA.cpp (CPUCheckDMA): fix minor DMA problem introduced with previous fixes + * src/GBA.cpp: fix DMA timings and add DMA hack fix + * src/Util.cpp (utilGBAFindSave): change search slightly + * src/agbprint.cpp (agbPrintWrite): return true to avoid warning message + * src/win32/TileViewer.cpp (OnMapInfo): fixed tile information when in 256 color mode + * src/win32/Win32.cpp (initApp): fix bug when initially switching to INI + +2003-08-02 Forgotten + + * src/win32/TileViewer.cpp (render): fixed TileViewer for 256 color display (incorrect tile and address) + +2003-08-01 Forgotten + + * src/win32/Win32.cpp (initApp): changed default rewind interval to 0 (disabled) + * src/bios.cpp (BIOS_CpuFastSet): fixed + * src/bios.cpp (BIOS_CpuSet): fixed + +2003-07-21 Forgotten + + * src/win32/Win32.cpp (fileMoviePlay): added message when playing movie + * src/Sound.cpp (soundTick): produce mute sound while in sleep state + * src/GBA.cpp (CPULoop): improve stop state/sleep support + +2003-07-19 Forgotten + + * src/win32/Win32.cpp (updateFileMenu): allow customize in fullscreen (not at 320x240 though) + +2003-07-18 Forgotten + + * src/win32/MapView.cpp (renderTextScreen): fixed rendering when 512x512 + * src/win32/MapView.cpp (GetTextClickAddress): fixed click address for text screens when size > 256 + +2003-07-16 Forgotten + + * src/Sound.cpp (soundEvent): fix sound envelope bug when set to 0 + +2003-07-15 Forgotten + + * src/TestEmu.cpp (systemGbBorderOn): fixed TestEmu compilation + * src/SDL.cpp: added save type NONE support + * src/win32/Win32.cpp (helpBugReport): fixed bug with bug report when emulating GB/GBC program + +2003-07-13 Forgotten + + * src/Util.cpp (utilGBAFindSave): added enhanced save type detection + +2003-07-09 Forgotten + * src/SDL.cpp: rewind default to disabled + * src/win32/Win32.cpp: rewind default to disabled + * src/win32/RewindInterval.cpp (OnOk): allow a rewind interval between 0 and 600 seconds - 0 to disable it + * src/win32/Win32.cpp (fileMoviePlay): put a warning when playing a movie + * src/GBA.cpp (CPUReadState): fix sound problem loading old save states + +2003-07-08 Forgotten + + * src/armdis.cpp: fixed thumb disassembly bug + * src/win32/Win32.cpp: fix rewind enable and reset when loading a game + * src/win32/Reg.cpp (regQueryBinaryValue): fix problem saving binary settings into INI + +2003-07-05 Forgotten + + * src/Mode0.cpp (mode0RenderLineAll): fixed priority between OBJ Win and Windows + * src/Mode1.cpp (mode0RenderLineAll): fixed priority between OBJ Win and Windows + * src/Mode2.cpp (mode0RenderLineAll): fixed priority between OBJ Win and Windows + * src/Mode3.cpp (mode0RenderLineAll): fixed priority between OBJ Win and Windows + * src/Mode4.cpp (mode0RenderLineAll): fixed priority between OBJ Win and Windows + * src/Mode5.cpp (mode0RenderLineAll): fixed priority between OBJ Win and Windows + +2003-07-04 Forgotten + + * src/win32/Win32.cpp: menu toggle can have a customizable accelerator + * src/win32/Commands.cpp: added file toggle menu + +2003-07-02 Forgotten + + * src/SDL.cpp: fixed type on pause-when-inactive option + +2003-06-29 Forgotten + + * src/win32/Reg.cpp (regExportSettingsToINI): also exporting settings for viewers + +2003-06-28 Forgotten + + * src/win32/Win32.cpp (WindowProc): added rewind interval configuration + * src/bios.cpp (BIOS_SndDriverJmpTableCopy): simple emulation of function 0x2a + +2003-06-26 Forgotten + + * src/win32/Win32.cpp: added movie version for future updates + +2003-06-25 Forgotten + + * src/win32/Win32.cpp (helpFAQ): added FAQ menu to take to website + +2003-06-24 Forgotten + + * src/win32/Win32.cpp (helpBugReport): added bug report option + * src/SDL.cpp: added rewind support + +2003-06-21 Forgotten + + * src/GBA.cpp (CPULoadRom): speed up loading + +2003-06-20 Forgotten + + * src/gb/GB.cpp: added rewind support + +2003-06-19 Forgotten + + * src/Cheats.cpp (cheatsCheckKeys): added support for slowdown codes + * src/elf.cpp (elfGetAddressSymbol): fix crash debugging the initialization code + +2003-06-17 Forgotten + + * src/GBA.cpp: added rewind support + * src/Win32.cpp: added rewind support + * src/Util.cpp: added memory gzip support for rewind + +2003-06-15 Forgotten + + * src/Gfx.h (gfxDrawSprites): emulate sprite priority bug + * src/GBA.cpp: fix for DMA emulation problems + +2003-06-13 Forgotten + + * src/SDL.cpp: support for automatic SGB border + * src/win32/Win32.cpp (systemGbBorderOn): support for automatic SGB border + * src/gb/gbSGB.cpp: added support for automatic SGB border + * src/GBA.cpp: fixed bug with enable/disable layers introduced in version 1.5.1 + +2003-06-12 Forgotten + + * src/SDL.cpp: added sound off/enable support + * src/VisualBoyAdvance.cfg: added sound off/enable flags + * src/win32/Win32.cpp: added auto hide menu support + * src/GBA.cpp, src/gb/GB.cpp: code cleanup + +2003-06-11 Forgotten + + * src/win32/Win32.cpp: added movie support + +2003-06-10 Forgotten + + * GBACheats.cpp: fixed bug with enable/disable cheats + diff -urN ../VisualBoyAdvance-1.7.2/ChangeLog.1.7.1 ./ChangeLog.1.7.1 --- ../VisualBoyAdvance-1.7.2/ChangeLog.1.7.1 1970-01-01 09:00:00 +0900 +++ ./ChangeLog.1.7.1 2004-03-20 09:18:32 +0900 @@ -0,0 +1,97 @@ +2004-02-07 Forgotten + + * src/SDL.cpp (main): disable remove intros option + * src/win32/MainWndOptions.cpp (OnUpdateOptionsEmulatorRemoveintrosgba): disable remove intros option + * src/win32/MainWnd.cpp: disable remove intros option + * src/win32/VBA.cpp: fix power management code + * src/win32/MainWnd.cpp (OnMySysCommand): fix power management code + * src/win32/MainWndFile.cpp: fix power management code + +2004-02-06 Forgotten + + * src/Sound.cpp (soundSetQuality): avoid turning sound on if sound off is checked + * src/gb/gbSound.cpp (gbSoundSetQuality): avoid turning sound on if sound off is checked + * src/GBA.cpp (CPUSoftwareInterrupt): added SWI call to exit emulator + +2004-02-05 Forgotten + + * src/win32/MainWnd.cpp (FileRun): update battery file more often + * src/win32/VBA.cpp (system10Frames): update battery file more often + * src/gb/gbMemory.cpp: update battery file more often + * src/gb/GB.cpp: update battery file more often + * src/System.h: update battery file more often + * src/Sram.cpp (sramWrite): update battery file more often + * src/SDL.cpp (main): update battery file more often + * src/GBA.cpp: update battery file more often + * src/Flash.cpp (flashWrite): update battery file more often + * src/EEprom.cpp (eepromWrite): update battery file more often + +2004-01-30 Forgotten + + * src/win32/OpenGL.cpp (render): fix memory leak in OpenGL rendering + +2004-01-29 Forgotten + + * src/gb/gbCodes.h: fix HALT when no matching in IE and IF + +2004-01-28 Forgotten + + * src/prof/prof.cpp: fix compile warnings + * src/win32/MainWndTools.cpp: switch to use structure functions + * src/win32/MainWndFile.cpp: switch to use structure functions + * src/win32/VBA.cpp (VBA): use structure instead of individual functions for emulation + * src/win32/VBA.h (class VBA): use structure instead of individual functions for emulation + * src/win32/MainWnd.cpp: switch to use structure functions + * src/System.h: structure for emulator functions + * src/win32/MainWnd.cpp (FileRun): save rom size for later use + * src/win32/BugReport.cpp (createReport): include cart save strings to bug report + +2004-01-25 Forgotten + + * src/win32/AboutDialog.cpp (OnInitDialog): fix problem with translator URLs not working correctly and force URL to new site + * src/win32/MainWndHelp.cpp (OnHelpFaq): update FAQ URL to new site + +2004-01-21 Forgotten + + * src/Util.cpp (utilLoad): fix possible memory corruption when loading files with a passed in memory location + +2004-01-20 Forgotten + + * src/Port.h (READ32LE): big endian updates from flea + * src/GBA.cpp: big endian updates from flea + * src/Cheats.cpp: big endian updates from flea + * src/win32/VBA.cpp (VBA): initialize default GB color palette + * src/win32/Direct3D.cpp (initialize): avoid resetting GB colors set by user + * src/win32/OpenGL.cpp (initialize): avoid resetting GB colors set by user + * src/win32/GDIDisplay.cpp (initialize): avoid resetting GB colors set by user + * src/win32/DirectDraw.cpp (initializeOffscreen): avoid resetting GB colors set by user + +2004-01-19 Forgotten + + * src/gb/GB.cpp (gbEmulate): reset the window line before starting a new frame + * src/elf.cpp (elfRead): fix memory leak + * src/GBA.cpp (CPULoadRom): avoid crash with invalid ELF file + +2004-01-18 Forgotten + + * src/win32/FileDlg.cpp (FileDlg): fix problem on 320x240 mode + * src/win32/ZoomControl.cpp (OnPaint): fix crash on map/oam/tile viewer + +2004-01-16 Forgotten + + * win32/GBMemoryViewerDlg.cpp (OnLoad): fixed bug loading memory dump + * win32/MemoryViewerDlg.cpp (OnLoad): fixed bug loading memory dump + +2004-01-15 Forgotten + + * win32/VBA.cpp: store throttle value + +2004-01-14 Forgotten + + * win32/VBA.cpp (adjustDestRect): fix multi-mon support + * win32/FileDlg.cpp (FileDlg): fix problem on VC 7.1 + * win32/MainWnd.cpp (OnActivateApp): fix compile errors on VC 7.1 + * win32/GBCheatsDlg.cpp: fix compile errors on VC 7.1 + * win32/GBACheats.cpp: fix compile errors on VC 7.1 + * bios.cpp: fix compile errors on VC 7.1 + diff -urN ../VisualBoyAdvance-1.7.2/INSTALL ./INSTALL --- ../VisualBoyAdvance-1.7.2/INSTALL 2004-05-22 23:06:32 +0900 +++ ./INSTALL 2006-08-25 21:28:38 +0900 @@ -65,6 +65,49 @@ 2. Windows ---------- +2.1 Visual C++ 2005 Express Edition +----------------------------------- + +If you want to use the free express edition of Visual C++ 2005, +you have to do the following steps prior to the normal setup procedure of Visual C++/Studio 2005: +!!! You will not be able to build the MFC (GUI) version of VBA, only the SDL build will succeed !!! +- First download and install VC++ 2005 Express from http://msdn.microsoft.com/vstudio/express/visualC/default.aspx +- Now follow the guide at http://msdn2.microsoft.com/en-us/library/ms235626.aspx +- Now continue with section [2.2] + +2.2 Visual C++ 2005 +------------------- + +Needed software: +- Microsoft Visual C++ 2005 (buy if not using Express Edition or if MFC build is required) + > http://msdn.microsoft.com/visualc/ + > You do not need the DLL runtimes and the .NET Framework +- Microsoft Platform SDK (free, optional, essential only for express edition) + > http://www.microsoft.com/downloads/details.aspx?FamilyId=E15438AC-60BE-41BD-AA14-7F1E0F19CA0D&displaylang=en +- Microsoft DirectX 9.0 SDK (free, essential) + > http://msdn.com/directx/sdk + (August 2006 version as I write these lines) +- Yasm (free, essential) + > http://www.tortall.net/projects/yasm/ + > Follow the install guide at http://www.tortall.net/projects/yasm/wiki/VisualStudio2005 +- AMD CodeAnalyst (optional, AMD CPU required) + > http://developer.amd.com/cawin.aspx?session_id=FB$37649@DJEBIGID + > Free and easy profiling for AMD CPUs (32bit and 64bit), Visual Studio 2005 plugin + + Those are all packages for now. The VBA source also includes the + sources and/or binaries of various free libraries for zip and image support. + Those can be accessed through the "dependencies" folder in the main + solution file. The main solution file includes references to all files + for all platforms. At the moment, only MFC and SDL build targets for + 32bit Windows are configured. GTK+ and 64bit Windows support are also possible, + but are not yet added for several reasons. + + You can now open the project file: "win32/vba_vs2005.sln". + Info: If you use the express edition of VC++ 2005, you will receive three neglectable warnings. + +2.3 Visual C++ 6.0 and Visual C++ 2002 +-------------------------------------- + Needed software: - nasm: see above for URL. Install it in the default directory - Microsoft Visual C++ 6.0 or greater: to compile diff -urN ../VisualBoyAdvance-1.7.2/Makefile.in ./Makefile.in --- ../VisualBoyAdvance-1.7.2/Makefile.in 2004-05-14 06:39:02 +0900 +++ ./Makefile.in 2004-09-30 07:23:13 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/NEWS ./NEWS --- ../VisualBoyAdvance-1.7.2/NEWS 2004-05-21 05:22:43 +0900 +++ ./NEWS 2004-12-21 00:02:43 +0900 @@ -1,3 +1,52 @@ +Version 1.8.0: +Core changes: +- added almost all AR V3 cheat codes (PokemonHacker) +- added prefetch emulation +- added full CBA support (verified for every CBA code type) +- added emulation for DMA interaction with reading from invalid address +- fixed CPU init for 256Mbit roms +- fixed HuffUnComp bug regarding tree size (SF #984608) +- fixed RTC support for day of the week (fixed at Sunday before) +- fixed loading of ELF multiboot files (thanks J.W.) +- fixed bug on CBA code type 5 +- fixed OBJWIN rendering bug when sprite wraps around (SF #1065447) +- fixed battery saving bug when save type equals to Flash or Sram +- fixed a compilation warning +- fixed BIOS ArcTan and ArcTan2 emulation (several bugs) +- fixed some instruction having incorrect cycles (caused SDL debugger to skip several instructions) +- fixed lq2x filter (was using hq2x code) +- fixed some bugs with IntrWait emulation +- fixed some timer bugs +- fixed memory timing when loading a save state (was using the timings before loading the state) +- fixed bug writing to IO register past 0x4000400 (no mirroring) +- initialize sram and flash memory to 0xff instead of 0x00 +- clean flash/sram on load/reload +- ignore 8-bit writes to OBJ and OAM memory +- major AR V1/2/3 support by PokemonHacker +- simplified GBA emulation loop (easier to understand and maintain) + +Windows: +- added dialog to edit game overrides +- added GPL link to Help menu +- fixed GB Disassemble crash when going to another address +- fixed a minor repaint bug when focus changed +- fixed problem displaying rom names that use & character +- fixed palette save name bug +- moved vsync code to where it should be +- moved common palette initialization and cleaned up rendering code to use it + +SDL versions: +- SDL debugger improvements adapted from VBA-H: + - break on change + - conditional breakpoints (ARM and THUMB) + - dump load and save (memory) + - edit register (exception of R15) + - disassemble to file + - save and load state from debugger + +Other: +- fixed some compilation issues (libpng, gtkmm) + Version 1.7.2: Core changes: - fixed bugs on ELF clean up diff -urN ../VisualBoyAdvance-1.7.2/README ./README --- ../VisualBoyAdvance-1.7.2/README 2004-05-22 23:05:38 +0900 +++ ./README 2004-12-21 00:02:43 +0900 @@ -1,4 +1,4 @@ -Welcome to version 1.7.2 of VisualBoyAdvance [SDL]. +Welcome to version 1.8.0 of VisualBoyAdvance [SDL]. This is a GB/GBC/GBA emulator for Windows, Linux, MacOS X and BeOS. Features diff -urN ../VisualBoyAdvance-1.7.2/README-win.txt ./README-win.txt --- ../VisualBoyAdvance-1.7.2/README-win.txt 2004-05-22 22:57:38 +0900 +++ ./README-win.txt 2006-08-24 07:11:54 +0900 @@ -1,4 +1,4 @@ -Welcome to VisualBoyAdvance version 1.7.2. +Welcome to VisualBoyAdvance version 1.8.0. Compiling the sources --------------------- @@ -40,11 +40,13 @@ The 1 thorugh 4 joypads allow you to have different settings which can be easily switched. -System requirements -------------------- +Recommended System Requirements +------------------------------- -Fast computer (Pentium III 500 Mhz recommended) and Microsoft DirectX 7 or -greater. +CPU: 800MHz with MMX & SSE +RAM: 64MB free +GPU: Graphics card with drivers supporting DirectX9 +OS: Windows 2000 with DirectX9 runtime Translations ------------ @@ -147,6 +149,7 @@ can defined the following settings on a per game basis by using an INI file called vba-over.ini in the same directory as the emulator: +comment=You can add any text you like here, for example the full name of the game, but not exceeding 255 characters rtcEnabled=<0 for false, anything else for true> flashSize=<65536 or 131072> saveType=<0 for automatic, 1 for EEPROM, 2 for SRAM, 3 for Flash or 4 for @@ -164,6 +167,9 @@ flashSize=131072 saveType=0 +An easier way to change the per game settings is to use the Game overrides dialog in the MFC version of VBA. +Select Menu>Options>Emulator>Game Overrides... to open the dialog. Just make your changes and click OK. + FAQ --- diff -urN ../VisualBoyAdvance-1.7.2/VERSION ./VERSION --- ../VisualBoyAdvance-1.7.2/VERSION 2004-03-24 02:21:53 +0900 +++ ./VERSION 2004-12-21 00:02:43 +0900 @@ -1 +1 @@ -VisualBoyAdvance 1.7.2 +VisualBoyAdvance 1.8.0 diff -urN ../VisualBoyAdvance-1.7.2/aclocal.m4 ./aclocal.m4 --- ../VisualBoyAdvance-1.7.2/aclocal.m4 2004-05-14 06:38:53 +0900 +++ ./aclocal.m4 2004-09-30 07:10:53 +0900 @@ -1647,6 +1647,64 @@ LEX=${am_missing_run}flex fi]) + +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN(PKG_CHECK_MODULES, [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + + # gettext.m4 serial 28 (gettext-0.13) dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU @@ -4277,61 +4335,3 @@ fi ]) - -dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) -dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page -dnl also defines GSTUFF_PKG_ERRORS on error -AC_DEFUN(PKG_CHECK_MODULES, [ - succeeded=no - - if test -z "$PKG_CONFIG"; then - AC_PATH_PROG(PKG_CONFIG, pkg-config, no) - fi - - if test "$PKG_CONFIG" = "no" ; then - echo "*** The pkg-config script could not be found. Make sure it is" - echo "*** in your path, or set the PKG_CONFIG environment variable" - echo "*** to the full path to pkg-config." - echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." - else - PKG_CONFIG_MIN_VERSION=0.9.0 - if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then - AC_MSG_CHECKING(for $2) - - if $PKG_CONFIG --exists "$2" ; then - AC_MSG_RESULT(yes) - succeeded=yes - - AC_MSG_CHECKING($1_CFLAGS) - $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` - AC_MSG_RESULT($$1_CFLAGS) - - AC_MSG_CHECKING($1_LIBS) - $1_LIBS=`$PKG_CONFIG --libs "$2"` - AC_MSG_RESULT($$1_LIBS) - else - $1_CFLAGS="" - $1_LIBS="" - ## If we have a custom action on failure, don't print errors, but - ## do set a variable so people can do so. - $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` - ifelse([$4], ,echo $$1_PKG_ERRORS,) - fi - - AC_SUBST($1_CFLAGS) - AC_SUBST($1_LIBS) - else - echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." - echo "*** See http://www.freedesktop.org/software/pkgconfig" - fi - fi - - if test $succeeded = yes; then - ifelse([$3], , :, [$3]) - else - ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) - fi -]) - - - diff -urN ../VisualBoyAdvance-1.7.2/configure ./configure --- ../VisualBoyAdvance-1.7.2/configure 2004-05-14 06:39:06 +0900 +++ ./configure 2006-09-04 06:52:24 +0900 @@ -309,7 +309,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE am__leading_dot CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE YACC LEX LEXLIB LEX_OUTPUT_ROOT CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE RANLIB ac_ct_RANLIB NASM CPP EGREP SDL_CONFIG SDL_CFLAGS SDL_LIBS MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE LIBICONV LTLIBICONV INTLLIBS LIBINTL LTLIBINTL POSUB GETTEXT_PACKAGE PKG_CONFIG GTKMM_CFLAGS GTKMM_LIBS GTKMM_CPPFLAGS VBA_EXTRA VBA_SRC_EXTRA VBA_LIBS LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE am__leading_dot CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE YACC LEX LEXLIB LEX_OUTPUT_ROOT CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE RANLIB ac_ct_RANLIB NASM PKG_CONFIG LIBPNG_CFLAGS LIBPNG_LIBS CPP EGREP SDL_CONFIG SDL_CFLAGS SDL_LIBS MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE LIBICONV LTLIBICONV INTLLIBS LIBINTL LTLIBINTL POSUB GETTEXT_PACKAGE GTKMM_CFLAGS GTKMM_LIBS GTKMM_CPPFLAGS VBA_EXTRA VBA_SRC_EXTRA VBA_LIBS LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -1705,7 +1705,7 @@ # Define the identity of the package. PACKAGE=VisualBoyAdvance - VERSION=1.7.2 + VERSION=1.8.0 cat >>confdefs.h <<_ACEOF @@ -3950,83 +3950,6 @@ fi -echo "$as_me:$LINENO: checking for png_create_write_struct in -lpng" >&5 -echo $ECHO_N "checking for png_create_write_struct in -lpng... $ECHO_C" >&6 -if test "${ac_cv_lib_png_png_create_write_struct+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpng -lz $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char png_create_write_struct (); -int -main () -{ -png_create_write_struct (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_png_png_create_write_struct=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_png_png_create_write_struct=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_create_write_struct" >&5 -echo "${ECHO_T}$ac_cv_lib_png_png_create_write_struct" >&6 -if test $ac_cv_lib_png_png_create_write_struct = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPNG 1 -_ACEOF - - LIBS="-lpng $LIBS" - -else - { { echo "$as_me:$LINENO: error: *** Cannot compile without libpng." >&5 -echo "$as_me: error: *** Cannot compile without libpng." >&2;} - { (exit 1); exit 1; }; } -fi - - echo "$as_me:$LINENO: checking for pthread_yield in -lpthread" >&5 echo $ECHO_N "checking for pthread_yield in -lpthread... $ECHO_C" >&6 if test "${ac_cv_lib_pthread_pthread_yield+set}" = set; then @@ -4100,6 +4023,107 @@ fi + + succeeded=no + + if test -z "$PKG_CONFIG"; then + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 +echo "${ECHO_T}$PKG_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + echo "$as_me:$LINENO: checking for libpng" >&5 +echo $ECHO_N "checking for libpng... $ECHO_C" >&6 + + if $PKG_CONFIG --exists "libpng" ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + succeeded=yes + + echo "$as_me:$LINENO: checking LIBPNG_CFLAGS" >&5 +echo $ECHO_N "checking LIBPNG_CFLAGS... $ECHO_C" >&6 + LIBPNG_CFLAGS=`$PKG_CONFIG --cflags "libpng"` + echo "$as_me:$LINENO: result: $LIBPNG_CFLAGS" >&5 +echo "${ECHO_T}$LIBPNG_CFLAGS" >&6 + + echo "$as_me:$LINENO: checking LIBPNG_LIBS" >&5 +echo $ECHO_N "checking LIBPNG_LIBS... $ECHO_C" >&6 + LIBPNG_LIBS=`$PKG_CONFIG --libs "libpng"` + echo "$as_me:$LINENO: result: $LIBPNG_LIBS" >&5 +echo "${ECHO_T}$LIBPNG_LIBS" >&6 + else + LIBPNG_CFLAGS="" + LIBPNG_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + LIBPNG_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libpng"` + echo $LIBPNG_PKG_ERRORS + fi + + + + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + : + else + { { echo "$as_me:$LINENO: error: Library requirements (libpng) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&5 +echo "$as_me: error: Library requirements (libpng) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&2;} + { (exit 1); exit 1; }; } + fi + +CPPFLAGS="$CPPFLAGS $LIBPNG_CFLAGS" +LIBS="$LIBS $LIBPNG_LIBS" + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -4338,6 +4362,7 @@ echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6 +ac_path_x_has_been_run=yes # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -4430,7 +4455,7 @@ /usr/openwin/share/include' if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for Intrinsic.h. + # Guess where to find include files, by looking for a specified header file. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -4438,7 +4463,7 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include +#include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -4465,7 +4490,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Intrinsic.h"; then + if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi @@ -4479,18 +4504,18 @@ # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS - LIBS="-lXt $LIBS" + LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include +#include int main () { -XtMalloc (0) +XrmInitialize () ; return 0; } @@ -4528,7 +4553,7 @@ do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl; do - if test -r $ac_dir/libXt.$ac_extension; then + if test -r $ac_dir/libX11.$ac_extension; then ac_x_libraries=$ac_dir break 2 fi @@ -4564,8 +4589,12 @@ # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes \ ac_x_includes=$x_includes ac_x_libraries=$x_libraries" - echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 -echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 + # It might be that x_includes is empty (headers are found in the + # standard search path. Then output the corresponding message + ac_out_x_includes=$x_includes + test "x$x_includes" = x && ac_out_x_includes="in standard search path" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $ac_out_x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $ac_out_x_includes" >&6 fi echo "$as_me:$LINENO: checking for egrep" >&5 @@ -5624,6 +5653,8 @@ VBA_LIBS="../gb/libgb.a" +CXXFLAGS="$CXXFLAGS -DBKPT_SUPPORT" + if test "x$enable_c_core" = xyes; then CXXFLAGS="$CXXFLAGS -DC_CORE" fi @@ -7819,7 +7850,7 @@ done - GETTEXT_PACKAGE=vba-1.7.2 + GETTEXT_PACKAGE=vba-1.8.0 @@ -8691,6 +8722,9 @@ s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@NASM@,$NASM,;t t +s,@PKG_CONFIG@,$PKG_CONFIG,;t t +s,@LIBPNG_CFLAGS@,$LIBPNG_CFLAGS,;t t +s,@LIBPNG_LIBS@,$LIBPNG_LIBS,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@SDL_CONFIG@,$SDL_CONFIG,;t t @@ -8709,7 +8743,6 @@ s,@LTLIBINTL@,$LTLIBINTL,;t t s,@POSUB@,$POSUB,;t t s,@GETTEXT_PACKAGE@,$GETTEXT_PACKAGE,;t t -s,@PKG_CONFIG@,$PKG_CONFIG,;t t s,@GTKMM_CFLAGS@,$GTKMM_CFLAGS,;t t s,@GTKMM_LIBS@,$GTKMM_LIBS,;t t s,@GTKMM_CPPFLAGS@,$GTKMM_CPPFLAGS,;t t diff -urN ../VisualBoyAdvance-1.7.2/configure.in ./configure.in --- ../VisualBoyAdvance-1.7.2/configure.in 2004-05-14 06:38:35 +0900 +++ ./configure.in 2006-09-04 06:52:24 +0900 @@ -16,7 +16,7 @@ ;; esac -AM_INIT_AUTOMAKE(VisualBoyAdvance, 1.7.2) +AM_INIT_AUTOMAKE(VisualBoyAdvance, 1.8.0) AC_ARG_ENABLE(c-core, AC_HELP_STRING([--enable-c-core],[enable C core (default is no on x86 targets)]), @@ -63,10 +63,12 @@ dnl Checks for libraries. AC_CHECK_LIB(z, gzopen, , AC_MSG_ERROR([*** Cannot compile without zlib.])) -AC_CHECK_LIB(png, png_create_write_struct, - , AC_MSG_ERROR([*** Cannot compile without libpng.]), [-lz]) AC_CHECK_LIB(pthread, pthread_yield) +PKG_CHECK_MODULES(LIBPNG, libpng) +CPPFLAGS="$CPPFLAGS $LIBPNG_CFLAGS" +LIBS="$LIBS $LIBPNG_LIBS" + dnl Checks for header files. AC_PATH_X AC_HEADER_STDC @@ -102,6 +104,8 @@ VBA_LIBS="../gb/libgb.a" +CXXFLAGS="$CXXFLAGS -DBKPT_SUPPORT" + if test "x$enable_c_core" = xyes; then CXXFLAGS="$CXXFLAGS -DC_CORE" fi @@ -138,7 +142,7 @@ ALL_LINGUAS="fr" AM_GNU_GETTEXT(external) AC_CHECK_HEADERS(libintl.h) - GETTEXT_PACKAGE=vba-1.7.2 + GETTEXT_PACKAGE=vba-1.8.0 AC_SUBST(GETTEXT_PACKAGE) PKG_CHECK_MODULES(GTKMM, gtkmm-$gtk_version >= 2.0.0 libglademm-$gtk_version >= 2.1.0) diff -urN ../VisualBoyAdvance-1.7.2/fix-timestamps ./fix-timestamps --- ../VisualBoyAdvance-1.7.2/fix-timestamps 1970-01-01 09:00:00 +0900 +++ ./fix-timestamps 2004-01-18 08:09:27 +0900 @@ -0,0 +1,4 @@ +#! /bin/sh +touch acinclude.m4 aclocal.m4 +touch configure +touch `find . -name Makefile.in` diff -urN ../VisualBoyAdvance-1.7.2/m4/Makefile.in ./m4/Makefile.in --- ../VisualBoyAdvance-1.7.2/m4/Makefile.in 2004-05-14 06:39:37 +0900 +++ ./m4/Makefile.in 2004-09-30 07:23:40 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ Binary files ../VisualBoyAdvance-1.7.2/po/fr.gmo and ./po/fr.gmo differ diff -urN ../VisualBoyAdvance-1.7.2/po/fr.po ./po/fr.po --- ../VisualBoyAdvance-1.7.2/po/fr.po 2004-05-22 01:03:26 +0900 +++ ./po/fr.po 2006-09-04 06:52:24 +0900 @@ -9,29 +9,30 @@ msgstr "" "Project-Id-Version: VisualBoyAdvance 1.7.2\n" "Report-Msgid-Bugs-To: undefined\n" -"POT-Creation-Date: 2004-05-21 18:02+0200\n" -"PO-Revision-Date: 2004-05-21 18:03+0200\n" +"POT-Creation-Date: 2006-09-03 22:57+0200\n" +"PO-Revision-Date: 2006-09-03 23:45+0200\n" "Last-Translator: Sébastien Guignot \n" "Language-Team: French <@>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: src/Cheats.cpp:653 src/Cheats.cpp:658 src/Cheats.cpp:667 src/Cheats.cpp:675 +#: src/Cheats.cpp:1473 src/Cheats.cpp:1478 src/Cheats.cpp:1487 +#: src/Cheats.cpp:1495 #, c-format msgid "Invalid cheat code '%s'" msgstr "Cheat code incorrect '%s'" -#: src/Cheats.cpp:694 +#: src/Cheats.cpp:1524 #, c-format msgid "Invalid cheat code address: %08x" msgstr "Adresse de cheat code incorrecte : %08x" -#: src/Cheats.cpp:738 src/Cheats.cpp:747 +#: src/Cheats.cpp:1603 src/Cheats.cpp:1612 msgid "Invalid GSA code. Format is XXXXXXXXYYYYYYYY" msgstr "Code GSA incorrect. Le format est XXXXXXXXYYYYYYYY" -#: src/Cheats.cpp:773 +#: src/Cheats.cpp:1638 #, c-format msgid "" "Warning: cheats are for game %s. Current game is %s.\n" @@ -40,12 +41,12 @@ "Avertissement : les cheats sont pour le jeu %s. Le jeu courant est %s.\n" "Les codes peuvent ne pas fonctionner correctement." -#: src/Cheats.cpp:1307 src/Cheats.cpp:1316 src/Cheats.cpp:1323 -#: src/Cheats.cpp:1331 +#: src/Cheats.cpp:2458 src/Cheats.cpp:2467 src/Cheats.cpp:2474 +#: src/Cheats.cpp:2482 msgid "Invalid CBA code. Format is XXXXXXXX YYYY." msgstr "Code CBA incorrect. Le format est XXXXXXXX YYYY." -#: src/Cheats.cpp:1385 +#: src/Cheats.cpp:2538 msgid "" "Warning: Codes seem to be for a different game.\n" "Codes may not work correctly." @@ -53,86 +54,86 @@ "Avertissement : les codes semblent être faits pour un autre jeu.\n" "Ils peuvent ne pas fonctionner correctement." -#: src/Cheats.cpp:1545 src/gb/gbCheats.cpp:130 +#: src/Cheats.cpp:2723 src/gb/gbCheats.cpp:132 #, c-format msgid "Unsupported cheat list version %d" msgstr "Version de liste de cheats %d non supportée" -#: src/Cheats.cpp:1558 src/gb/gbCheats.cpp:143 +#: src/Cheats.cpp:2737 src/gb/gbCheats.cpp:145 #, c-format msgid "Unsupported cheat list type %d" msgstr "Type de liste de cheats %d non supporté" -#: src/elf.cpp:2814 +#: src/elf.cpp:2811 #, c-format msgid "Not a valid ELF file %s" msgstr "%s n'est pas un fichier ELF correct" -#: src/GBA.cpp:664 src/GBA.cpp:849 src/GBA.cpp:887 src/Util.cpp:61 -#: src/Util.cpp:270 src/gb/GB.cpp:1662 src/gb/GB.cpp:1679 src/gb/GB.cpp:1696 -#: src/gb/GB.cpp:1719 src/gb/GB.cpp:1736 +#: src/GBA.cpp:863 src/GBA.cpp:1084 src/GBA.cpp:1122 src/Util.cpp:69 +#: src/Util.cpp:278 src/gb/GB.cpp:2708 src/gb/GB.cpp:2728 src/gb/GB.cpp:2750 +#: src/gb/GB.cpp:2777 src/gb/GB.cpp:2797 src/gb/GB.cpp:2815 src/gb/GB.cpp:2845 #, c-format msgid "Error creating file %s" msgstr "Erreur lors de la création du fichier %s" -#: src/GBA.cpp:701 +#: src/GBA.cpp:900 #, c-format msgid "Unsupported VisualBoyAdvance save game version %d" msgstr "Version de sauvegarde VisualBoyAdvance %d non supportée" -#: src/GBA.cpp:715 +#: src/GBA.cpp:914 #, c-format msgid "Cannot load save game for %s" msgstr "Impossible de charger la sauvegarde pour %s" -#: src/GBA.cpp:724 +#: src/GBA.cpp:923 src/gb/GB.cpp:3628 msgid "Save game is not using the BIOS files" msgstr "La sauvegarde n'utilise pas de fichier BIOS" -#: src/GBA.cpp:727 +#: src/GBA.cpp:926 src/gb/GB.cpp:3631 msgid "Save game is using the BIOS file" msgstr "La sauvegarde utilise le fichier BIOS" -#: src/GBA.cpp:807 +#: src/GBA.cpp:1035 #, c-format msgid "Unsupported save type %d" msgstr "Type de sauvegarde %d non supporté" -#: src/GBA.cpp:922 src/GBA.cpp:989 src/Util.cpp:588 src/Util.cpp:700 -#: src/gb/gbCheats.cpp:400 src/gb/GB.cpp:1977 +#: src/GBA.cpp:1157 src/GBA.cpp:1224 src/Util.cpp:596 src/Util.cpp:708 +#: src/gb/gbCheats.cpp:409 src/gb/GB.cpp:3368 #, c-format msgid "Cannot open file %s" msgstr "Impossible d'ouvrir le fichier %s" -#: src/GBA.cpp:957 src/gb/GB.cpp:1991 +#: src/GBA.cpp:1192 src/gb/GB.cpp:3381 #, c-format msgid "Cannot import snapshot for %s. Current game is %s" msgstr "Impossible d'importer le snapshot pour %s. Le jeu courant est %s" -#: src/GBA.cpp:971 src/gb/GB.cpp:2018 +#: src/GBA.cpp:1206 src/gb/GB.cpp:3408 #, c-format msgid "Unsupported snapshot file %s" msgstr "Fichier snapshot %s non supporté" -#: src/GBA.cpp:1274 src/GBA.cpp:1280 src/GBA.cpp:1329 src/GBA.cpp:1336 -#: src/GBA.cpp:1343 src/GBA.cpp:1350 src/GBA.cpp:1357 src/GBA.cpp:1364 -#: src/GBA.cpp:1371 src/Util.cpp:767 src/Util.cpp:825 src/Util.cpp:933 +#: src/GBA.cpp:1508 src/GBA.cpp:1514 src/GBA.cpp:1563 src/GBA.cpp:1570 +#: src/GBA.cpp:1577 src/GBA.cpp:1584 src/GBA.cpp:1591 src/GBA.cpp:1598 +#: src/GBA.cpp:1605 src/Util.cpp:775 src/Util.cpp:833 src/Util.cpp:941 #, c-format msgid "Failed to allocate memory for %s" msgstr "Échec de l'allocation de mémoire pour : %s" -#: src/GBA.cpp:1292 src/Util.cpp:756 src/Util.cpp:802 src/Util.cpp:816 -#: src/Util.cpp:920 +#: src/GBA.cpp:1526 src/Util.cpp:764 src/Util.cpp:810 src/Util.cpp:824 +#: src/Util.cpp:928 #, c-format msgid "Error opening image %s" msgstr "Erreur lors de l'ouverture de l'image %s" -#: src/GBA.cpp:1606 +#: src/GBA.cpp:1859 #, c-format msgid "Unsupported ARM mode %02x" msgstr "Mode ARM %02x non supporté" -#: src/GBA.cpp:1839 +#: src/GBA.cpp:2198 #, c-format msgid "" "Unsupported BIOS function %02x called from %08x. A BIOS file is needed in " @@ -141,93 +142,111 @@ "Fonction du BIOS %02x non supportée appelée depuis %08x. Un fichier BIOS est " "nécessaire pour obtenir un comportement correct." -#: src/GBA.cpp:2947 +#: src/GBA.cpp:3400 msgid "Invalid BIOS file size" msgstr "Taille de fichier BIOS incorrecte" -#: src/RTC.cpp:157 +#: src/RTC.cpp:159 #, c-format msgid "Unknown RTC command %02x" msgstr "Commande RTC %02x inconnue" -#: src/Util.cpp:596 src/Util.cpp:616 src/Util.cpp:707 src/Util.cpp:727 +#: src/Util.cpp:604 src/Util.cpp:624 src/Util.cpp:715 src/Util.cpp:735 #, c-format msgid "Bad ZIP file %s" msgstr "Fichier ZIP incorrect : %s" -#: src/Util.cpp:639 src/Util.cpp:745 +#: src/Util.cpp:647 src/Util.cpp:753 #, c-format msgid "No image found on ZIP file %s" msgstr "Pas d'image trouvée dans le fichier ZIP %s" -#: src/Util.cpp:783 src/Util.cpp:838 src/Util.cpp:877 src/Util.cpp:946 +#: src/Util.cpp:791 src/Util.cpp:846 src/Util.cpp:885 src/Util.cpp:954 #, c-format msgid "Error reading image %s" msgstr "Erreur lors de la lecture de l'image %s" -#: src/Util.cpp:889 +#: src/Util.cpp:897 #, c-format msgid "No image found on RAR file %s" msgstr "Pas d'image trouvée dans le fichier RAR %s" -#: src/gb/gbCheats.cpp:194 src/gb/gbCheats.cpp:304 +#: src/gb/gbCheats.cpp:192 src/gb/gbCheats.cpp:310 msgid "Maximum number of cheats reached." msgstr "Le nombre maximum de cheats a été atteint." -#: src/gb/gbCheats.cpp:200 +#: src/gb/gbCheats.cpp:198 #, c-format msgid "Invalid GameShark code: %s" msgstr "Code GameShark incorrect : %s" -#: src/gb/gbCheats.cpp:310 +#: src/gb/gbCheats.cpp:227 +#, c-format +msgid "Wrong GameShark code type : %s" +msgstr "Code GameShark incorrect : %s" + +#: src/gb/gbCheats.cpp:230 +#, c-format +msgid "Unsupported GameShark code type : %s" +msgstr "Code GameShark %s non supporté" + +#: src/gb/gbCheats.cpp:316 #, c-format msgid "Invalid GameGenie code: %s" msgstr "Code GameGenie incorrect : %s" -#: src/gb/gbCheats.cpp:355 +#: src/gb/gbCheats.cpp:364 #, c-format msgid "Invalid cheat to remove %d" msgstr "Cheat à supprimer %d incorrect" -#: src/gb/gbCodesCB.h:1285 src/gb/gbCodes.h:1404 +#: src/gb/gbCodesCB.h:1287 src/gb/gbCodes.h:1456 #, c-format msgid "Unknown opcode %02x at %04x" msgstr "Opcode %02x inconnu à %04x" -#: src/gb/GB.cpp:1761 src/gb/GB.cpp:1785 src/gb/GB.cpp:1810 src/gb/GB.cpp:1842 -#: src/gb/GB.cpp:1866 +#: src/gb/GB.cpp:2123 +msgid "Invalid BOOTROM file size" +msgstr "Taille de fichier BIOS incorrecte" + +#: src/gb/GB.cpp:2875 src/gb/GB.cpp:2890 src/gb/GB.cpp:2921 src/gb/GB.cpp:2937 +#: src/gb/GB.cpp:2972 src/gb/GB.cpp:3002 src/gb/GB.cpp:3029 src/gb/GB.cpp:3045 +#: src/gb/GB.cpp:3075 src/gb/GB.cpp:3091 src/gb/GB.cpp:3129 src/gb/GB.cpp:3159 +#: src/gb/GB.cpp:3187 src/gb/GB.cpp:3202 #, c-format -msgid "Failed to read complete save game %s (%d)" -msgstr "La lecture de la sauvegarde %s complète a échouée (%d)" +msgid "" +"Battery file's size incompatible with the rom settings %s (%d).\n" +"Warning : save of the battery file is now disabled !" +msgstr "" -#: src/gb/GB.cpp:1818 +#: src/gb/GB.cpp:2981 src/gb/GB.cpp:2987 src/gb/GB.cpp:3138 src/gb/GB.cpp:3144 #, c-format msgid "Failed to read RTC from save game %s (continuing)" msgstr "" "La lecture de la RTC de la sauvegarde %s a échoué (le chargement se poursuit)" -#: src/gb/GB.cpp:2195 +#: src/gb/GB.cpp:3601 #, c-format msgid "Unsupported VisualBoy save game version %d" msgstr "Version de sauvegarde VisualBoy %d non supportée" -#: src/gb/GB.cpp:2205 +#: src/gb/GB.cpp:3611 #, c-format msgid "Cannot load save game for %s. Playing %s" msgstr "" "Impossible de charger la sauvegarde pour le jeu %s. Le jeu %s est en cours." -#: src/gb/GB.cpp:2464 +#: src/gb/GB.cpp:4061 #, c-format msgid "Unsupported rom size %02x" msgstr "Taille de rom %02x non supportée" -#: src/gb/GB.cpp:2476 +#: src/gb/GB.cpp:4116 #, c-format msgid "Unsupported ram size %02x" msgstr "Taille de ram %02x non supportée" -#: src/gb/GB.cpp:2552 +#: src/gb/GB.cpp:4258 #, c-format msgid "Unknown cartridge type %02x" msgstr "Type de cartouche %02x inconnu" @@ -1072,43 +1091,46 @@ msgid "Only GBA images are supported." msgstr "Seules les images GBA sont supportées." -#: src/gtk/window.cpp:1427 +#: src/gtk/window.cpp:1421 #, c-format msgid "Unknown file type %s" msgstr "Type de fichier inconnu %s" -#: src/gtk/window.cpp:1708 src/gtk/window.cpp:1722 +#: src/gtk/window.cpp:1702 src/gtk/window.cpp:1716 msgid "Open" msgstr "Ouvrir" -#: src/gtk/window.cpp:1749 +#: src/gtk/window.cpp:1743 msgid "All Gameboy Advance files" msgstr "Tous les fichiers Gameboy Advance" -#: src/gtk/window.cpp:1756 +#: src/gtk/window.cpp:1750 msgid "Gameboy Advance files" msgstr "Fichiers Gameboy Advance" -#: src/gtk/window.cpp:1763 +#: src/gtk/window.cpp:1757 msgid "Gameboy files" msgstr "Fichiers Gameboy" -#: src/gtk/window.cpp:1793 +#: src/gtk/window.cpp:1787 msgid "Loaded battery" msgstr "Batterie chargée" -#: src/gtk/window.cpp:1812 +#: src/gtk/window.cpp:1806 msgid "Saved battery" msgstr "Batterie enregistrée" -#: src/gtk/window.cpp:1870 src/gtk/window.cpp:1917 +#: src/gtk/window.cpp:1864 src/gtk/window.cpp:1911 msgid "----/--/-- --:--:--" msgstr "--/--/---- --:--:--" -#: src/gtk/window.cpp:1902 +#: src/gtk/window.cpp:1896 msgid "%Y/%m/%d %H:%M:%S" msgstr "%d/%m/%Y %H:%M:%S" -#: src/prof/prof.cpp:143 +#: src/prof/prof.cpp:137 msgid "No space for profiling buffer(s)\n" msgstr "Pas de place pour le(s) tampon(s) de profil\n" + +#~ msgid "Failed to read complete save game %s (%d)" +#~ msgstr "La lecture de la sauvegarde %s complète a échouée (%d)" diff -urN ../VisualBoyAdvance-1.7.2/po/stamp-po ./po/stamp-po --- ../VisualBoyAdvance-1.7.2/po/stamp-po 2004-05-22 01:03:36 +0900 +++ ./po/stamp-po 1970-01-01 09:00:00 +0900 @@ -1 +0,0 @@ -timestamp diff -urN ../VisualBoyAdvance-1.7.2/po/vba-1.8.0.pot ./po/vba-1.8.0.pot --- ../VisualBoyAdvance-1.7.2/po/vba-1.8.0.pot 1970-01-01 09:00:00 +0900 +++ ./po/vba-1.8.0.pot 2006-09-04 06:52:24 +0900 @@ -0,0 +1,1115 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR VBA development team +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: undefined\n" +"POT-Creation-Date: 2006-09-03 22:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/Cheats.cpp:1473 src/Cheats.cpp:1478 src/Cheats.cpp:1487 +#: src/Cheats.cpp:1495 +#, c-format +msgid "Invalid cheat code '%s'" +msgstr "" + +#: src/Cheats.cpp:1524 +#, c-format +msgid "Invalid cheat code address: %08x" +msgstr "" + +#: src/Cheats.cpp:1603 src/Cheats.cpp:1612 +msgid "Invalid GSA code. Format is XXXXXXXXYYYYYYYY" +msgstr "" + +#: src/Cheats.cpp:1638 +#, c-format +msgid "" +"Warning: cheats are for game %s. Current game is %s.\n" +"Codes may not work correctly." +msgstr "" + +#: src/Cheats.cpp:2458 src/Cheats.cpp:2467 src/Cheats.cpp:2474 +#: src/Cheats.cpp:2482 +msgid "Invalid CBA code. Format is XXXXXXXX YYYY." +msgstr "" + +#: src/Cheats.cpp:2538 +msgid "" +"Warning: Codes seem to be for a different game.\n" +"Codes may not work correctly." +msgstr "" + +#: src/Cheats.cpp:2723 src/gb/gbCheats.cpp:132 +#, c-format +msgid "Unsupported cheat list version %d" +msgstr "" + +#: src/Cheats.cpp:2737 src/gb/gbCheats.cpp:145 +#, c-format +msgid "Unsupported cheat list type %d" +msgstr "" + +#: src/elf.cpp:2811 +#, c-format +msgid "Not a valid ELF file %s" +msgstr "" + +#: src/GBA.cpp:863 src/GBA.cpp:1084 src/GBA.cpp:1122 src/Util.cpp:69 +#: src/Util.cpp:278 src/gb/GB.cpp:2708 src/gb/GB.cpp:2728 src/gb/GB.cpp:2750 +#: src/gb/GB.cpp:2777 src/gb/GB.cpp:2797 src/gb/GB.cpp:2815 src/gb/GB.cpp:2845 +#, c-format +msgid "Error creating file %s" +msgstr "" + +#: src/GBA.cpp:900 +#, c-format +msgid "Unsupported VisualBoyAdvance save game version %d" +msgstr "" + +#: src/GBA.cpp:914 +#, c-format +msgid "Cannot load save game for %s" +msgstr "" + +#: src/GBA.cpp:923 src/gb/GB.cpp:3628 +msgid "Save game is not using the BIOS files" +msgstr "" + +#: src/GBA.cpp:926 src/gb/GB.cpp:3631 +msgid "Save game is using the BIOS file" +msgstr "" + +#: src/GBA.cpp:1035 +#, c-format +msgid "Unsupported save type %d" +msgstr "" + +#: src/GBA.cpp:1157 src/GBA.cpp:1224 src/Util.cpp:596 src/Util.cpp:708 +#: src/gb/gbCheats.cpp:409 src/gb/GB.cpp:3368 +#, c-format +msgid "Cannot open file %s" +msgstr "" + +#: src/GBA.cpp:1192 src/gb/GB.cpp:3381 +#, c-format +msgid "Cannot import snapshot for %s. Current game is %s" +msgstr "" + +#: src/GBA.cpp:1206 src/gb/GB.cpp:3408 +#, c-format +msgid "Unsupported snapshot file %s" +msgstr "" + +#: src/GBA.cpp:1508 src/GBA.cpp:1514 src/GBA.cpp:1563 src/GBA.cpp:1570 +#: src/GBA.cpp:1577 src/GBA.cpp:1584 src/GBA.cpp:1591 src/GBA.cpp:1598 +#: src/GBA.cpp:1605 src/Util.cpp:775 src/Util.cpp:833 src/Util.cpp:941 +#, c-format +msgid "Failed to allocate memory for %s" +msgstr "" + +#: src/GBA.cpp:1526 src/Util.cpp:764 src/Util.cpp:810 src/Util.cpp:824 +#: src/Util.cpp:928 +#, c-format +msgid "Error opening image %s" +msgstr "" + +#: src/GBA.cpp:1859 +#, c-format +msgid "Unsupported ARM mode %02x" +msgstr "" + +#: src/GBA.cpp:2198 +#, c-format +msgid "" +"Unsupported BIOS function %02x called from %08x. A BIOS file is needed in " +"order to get correct behaviour." +msgstr "" + +#: src/GBA.cpp:3400 +msgid "Invalid BIOS file size" +msgstr "" + +#: src/RTC.cpp:159 +#, c-format +msgid "Unknown RTC command %02x" +msgstr "" + +#: src/Util.cpp:604 src/Util.cpp:624 src/Util.cpp:715 src/Util.cpp:735 +#, c-format +msgid "Bad ZIP file %s" +msgstr "" + +#: src/Util.cpp:647 src/Util.cpp:753 +#, c-format +msgid "No image found on ZIP file %s" +msgstr "" + +#: src/Util.cpp:791 src/Util.cpp:846 src/Util.cpp:885 src/Util.cpp:954 +#, c-format +msgid "Error reading image %s" +msgstr "" + +#: src/Util.cpp:897 +#, c-format +msgid "No image found on RAR file %s" +msgstr "" + +#: src/gb/gbCheats.cpp:192 src/gb/gbCheats.cpp:310 +msgid "Maximum number of cheats reached." +msgstr "" + +#: src/gb/gbCheats.cpp:198 +#, c-format +msgid "Invalid GameShark code: %s" +msgstr "" + +#: src/gb/gbCheats.cpp:227 +#, c-format +msgid "Wrong GameShark code type : %s" +msgstr "" + +#: src/gb/gbCheats.cpp:230 +#, c-format +msgid "Unsupported GameShark code type : %s" +msgstr "" + +#: src/gb/gbCheats.cpp:316 +#, c-format +msgid "Invalid GameGenie code: %s" +msgstr "" + +#: src/gb/gbCheats.cpp:364 +#, c-format +msgid "Invalid cheat to remove %d" +msgstr "" + +#: src/gb/gbCodesCB.h:1287 src/gb/gbCodes.h:1456 +#, c-format +msgid "Unknown opcode %02x at %04x" +msgstr "" + +#: src/gb/GB.cpp:2123 +msgid "Invalid BOOTROM file size" +msgstr "" + +#: src/gb/GB.cpp:2875 src/gb/GB.cpp:2890 src/gb/GB.cpp:2921 src/gb/GB.cpp:2937 +#: src/gb/GB.cpp:2972 src/gb/GB.cpp:3002 src/gb/GB.cpp:3029 src/gb/GB.cpp:3045 +#: src/gb/GB.cpp:3075 src/gb/GB.cpp:3091 src/gb/GB.cpp:3129 src/gb/GB.cpp:3159 +#: src/gb/GB.cpp:3187 src/gb/GB.cpp:3202 +#, c-format +msgid "" +"Battery file's size incompatible with the rom settings %s (%d).\n" +"Warning : save of the battery file is now disabled !" +msgstr "" + +#: src/gb/GB.cpp:2981 src/gb/GB.cpp:2987 src/gb/GB.cpp:3138 src/gb/GB.cpp:3144 +#, c-format +msgid "Failed to read RTC from save game %s (continuing)" +msgstr "" + +#: src/gb/GB.cpp:3601 +#, c-format +msgid "Unsupported VisualBoy save game version %d" +msgstr "" + +#: src/gb/GB.cpp:3611 +#, c-format +msgid "Cannot load save game for %s. Playing %s" +msgstr "" + +#: src/gb/GB.cpp:4061 +#, c-format +msgid "Unsupported rom size %02x" +msgstr "" + +#: src/gb/GB.cpp:4116 +#, c-format +msgid "Unsupported ram size %02x" +msgstr "" + +#: src/gb/GB.cpp:4258 +#, c-format +msgid "Unknown cartridge type %02x" +msgstr "" + +#: src/gtk/joypadconfig.cpp:202 src/gtk/joypadconfig.cpp:239 +#: src/gtk/joypadconfig.cpp:257 +msgid "" +msgstr "" + +#: src/gtk/main.cpp:61 +#, c-format +msgid "Try `%s --help' for more information.\n" +msgstr "" + +#: src/gtk/main.cpp:65 +#, c-format +msgid "Usage: %s [option ...] [file]\n" +msgstr "" + +#: src/gtk/main.cpp:66 +msgid "" +"\n" +"Options:\n" +" --help Output this help.\n" +" -V, --version Output version information.\n" +msgstr "" + +#: src/gtk/main.cpp:130 +#, c-format +msgid "VisualBoyAdvance version %s [GTK+]\n" +msgstr "" + +#: src/gtk/vba.glade:7 +msgid "VBA" +msgstr "" + +#: src/gtk/vba.glade:37 +msgid "_File" +msgstr "" + +#: src/gtk/vba.glade:46 +msgid "_Open..." +msgstr "" + +#: src/gtk/vba.glade:73 +msgid "_Load..." +msgstr "" + +#: src/gtk/vba.glade:82 +msgid "_Save..." +msgstr "" + +#: src/gtk/vba.glade:91 +msgid "Loa_d game" +msgstr "" + +#: src/gtk/vba.glade:100 +msgid "Most recent" +msgstr "" + +#: src/gtk/vba.glade:108 +msgid "Auto load most recent" +msgstr "" + +#: src/gtk/vba.glade:123 src/gtk/vba.glade:240 +msgid "Slot1" +msgstr "" + +#: src/gtk/vba.glade:132 src/gtk/vba.glade:249 +msgid "Slot2" +msgstr "" + +#: src/gtk/vba.glade:141 src/gtk/vba.glade:258 +msgid "Slot3" +msgstr "" + +#: src/gtk/vba.glade:150 src/gtk/vba.glade:267 +msgid "Slot4" +msgstr "" + +#: src/gtk/vba.glade:159 src/gtk/vba.glade:276 +msgid "Slot5" +msgstr "" + +#: src/gtk/vba.glade:168 src/gtk/vba.glade:285 +msgid "Slot6" +msgstr "" + +#: src/gtk/vba.glade:177 src/gtk/vba.glade:294 +msgid "Slot7" +msgstr "" + +#: src/gtk/vba.glade:186 src/gtk/vba.glade:303 +msgid "Slot8" +msgstr "" + +#: src/gtk/vba.glade:195 src/gtk/vba.glade:312 +msgid "Slot9" +msgstr "" + +#: src/gtk/vba.glade:204 src/gtk/vba.glade:321 +msgid "Slot10" +msgstr "" + +#: src/gtk/vba.glade:217 +msgid "S_ave game" +msgstr "" + +#: src/gtk/vba.glade:226 +msgid "Oldest slot" +msgstr "" + +#: src/gtk/vba.glade:340 +msgid "_Pause" +msgstr "" + +#: src/gtk/vba.glade:350 src/gtk/vba.glade:374 +msgid "_Reset" +msgstr "" + +#: src/gtk/vba.glade:365 +msgid "Rece_nt" +msgstr "" + +#: src/gtk/vba.glade:382 +msgid "_Freeze" +msgstr "" + +#: src/gtk/vba.glade:407 +msgid "_Import" +msgstr "" + +#: src/gtk/vba.glade:416 src/gtk/vba.glade:437 +msgid "_Battery file..." +msgstr "" + +#: src/gtk/vba.glade:428 +msgid "E_xport" +msgstr "" + +#: src/gtk/vba.glade:455 +msgid "Screen capt_ure..." +msgstr "" + +#: src/gtk/vba.glade:469 +msgid "_Close" +msgstr "" + +#: src/gtk/vba.glade:489 +msgid "_Exit" +msgstr "" + +#: src/gtk/vba.glade:514 +msgid "_Options" +msgstr "" + +#: src/gtk/vba.glade:523 +msgid "_Frameskip" +msgstr "" + +#: src/gtk/vba.glade:532 +msgid "_Throttle" +msgstr "" + +#: src/gtk/vba.glade:541 +msgid "_No throttle" +msgstr "" + +#: src/gtk/vba.glade:550 src/gtk/vba.glade:1315 +msgid "25%" +msgstr "" + +#: src/gtk/vba.glade:560 src/gtk/vba.glade:1324 +msgid "50%" +msgstr "" + +#: src/gtk/vba.glade:570 src/gtk/vba.glade:1334 +msgid "100%" +msgstr "" + +#: src/gtk/vba.glade:580 +msgid "150%" +msgstr "" + +#: src/gtk/vba.glade:590 src/gtk/vba.glade:1344 +msgid "200%" +msgstr "" + +#: src/gtk/vba.glade:600 +msgid "_Other..." +msgstr "" + +#: src/gtk/vba.glade:620 src/gtk/vba.glade:981 src/gtk/vba.glade:1415 +msgid "_Automatic" +msgstr "" + +#: src/gtk/vba.glade:629 +msgid "_0" +msgstr "" + +#: src/gtk/vba.glade:639 src/gtk/vba.glade:1753 +msgid "_1" +msgstr "" + +#: src/gtk/vba.glade:649 src/gtk/vba.glade:1762 +msgid "_2" +msgstr "" + +#: src/gtk/vba.glade:659 src/gtk/vba.glade:1772 +msgid "_3" +msgstr "" + +#: src/gtk/vba.glade:669 src/gtk/vba.glade:1782 +msgid "_4" +msgstr "" + +#: src/gtk/vba.glade:679 +msgid "_5" +msgstr "" + +#: src/gtk/vba.glade:689 +msgid "_6" +msgstr "" + +#: src/gtk/vba.glade:699 +msgid "_7" +msgstr "" + +#: src/gtk/vba.glade:709 +msgid "_8" +msgstr "" + +#: src/gtk/vba.glade:719 +msgid "_9" +msgstr "" + +#: src/gtk/vba.glade:733 +msgid "_Video" +msgstr "" + +#: src/gtk/vba.glade:742 +msgid "_1x" +msgstr "" + +#: src/gtk/vba.glade:751 +msgid "_2x" +msgstr "" + +#: src/gtk/vba.glade:761 +msgid "_3x" +msgstr "" + +#: src/gtk/vba.glade:771 +msgid "_4x" +msgstr "" + +#: src/gtk/vba.glade:781 +msgid "_5x" +msgstr "" + +#: src/gtk/vba.glade:791 +msgid "_6x" +msgstr "" + +#: src/gtk/vba.glade:807 +msgid "_Layers" +msgstr "" + +#: src/gtk/vba.glade:816 +msgid "BG0" +msgstr "" + +#: src/gtk/vba.glade:826 +msgid "BG1" +msgstr "" + +#: src/gtk/vba.glade:836 +msgid "BG2" +msgstr "" + +#: src/gtk/vba.glade:846 +msgid "BG3" +msgstr "" + +#: src/gtk/vba.glade:856 +msgid "OBJ" +msgstr "" + +#: src/gtk/vba.glade:866 +msgid "WIN0" +msgstr "" + +#: src/gtk/vba.glade:876 +msgid "WIN1" +msgstr "" + +#: src/gtk/vba.glade:886 +msgid "OBJWIN" +msgstr "" + +#: src/gtk/vba.glade:904 +msgid "_Emulator" +msgstr "" + +#: src/gtk/vba.glade:913 +msgid "Directories..." +msgstr "" + +#: src/gtk/vba.glade:921 +msgid "Pause when inactive window" +msgstr "" + +#: src/gtk/vba.glade:930 +msgid "Show speed" +msgstr "" + +#: src/gtk/vba.glade:939 src/gtk/vba.glade:1030 +msgid "None" +msgstr "" + +#: src/gtk/vba.glade:948 +msgid "Percentage" +msgstr "" + +#: src/gtk/vba.glade:958 +msgid "Detailed" +msgstr "" + +#: src/gtk/vba.glade:972 +msgid "Save type" +msgstr "" + +#: src/gtk/vba.glade:990 +msgid "EEPROM" +msgstr "" + +#: src/gtk/vba.glade:1000 +msgid "SRAM" +msgstr "" + +#: src/gtk/vba.glade:1010 +msgid "Flash" +msgstr "" + +#: src/gtk/vba.glade:1020 +msgid "EEPROM+Sensor" +msgstr "" + +#: src/gtk/vba.glade:1046 +msgid "Flash 64K" +msgstr "" + +#: src/gtk/vba.glade:1055 +msgid "Flash 128K" +msgstr "" + +#: src/gtk/vba.glade:1075 +msgid "_Select BIOS file..." +msgstr "" + +#: src/gtk/vba.glade:1083 +msgid "_Use BIOS file" +msgstr "" + +#: src/gtk/vba.glade:1098 +msgid "Screenshot format" +msgstr "" + +#: src/gtk/vba.glade:1107 +msgid "_PNG" +msgstr "" + +#: src/gtk/vba.glade:1116 +msgid "_BMP" +msgstr "" + +#: src/gtk/vba.glade:1134 +msgid "_Sound" +msgstr "" + +#: src/gtk/vba.glade:1143 +msgid "O_ff" +msgstr "" + +#: src/gtk/vba.glade:1152 +msgid "_Mute" +msgstr "" + +#: src/gtk/vba.glade:1162 +msgid "_On" +msgstr "" + +#: src/gtk/vba.glade:1178 +msgid "Echo" +msgstr "" + +#: src/gtk/vba.glade:1187 +msgid "Low pass filter" +msgstr "" + +#: src/gtk/vba.glade:1196 +msgid "Reverse stereo" +msgstr "" + +#: src/gtk/vba.glade:1211 +msgid "Channel _1" +msgstr "" + +#: src/gtk/vba.glade:1220 +msgid "Channel _2" +msgstr "" + +#: src/gtk/vba.glade:1229 +msgid "Channel _3" +msgstr "" + +#: src/gtk/vba.glade:1238 +msgid "Channel _4" +msgstr "" + +#: src/gtk/vba.glade:1247 +msgid "Channel _A" +msgstr "" + +#: src/gtk/vba.glade:1256 +msgid "Channel _B" +msgstr "" + +#: src/gtk/vba.glade:1271 +msgid "11 _Khz" +msgstr "" + +#: src/gtk/vba.glade:1280 +msgid "22 K_hz" +msgstr "" + +#: src/gtk/vba.glade:1290 +msgid "44 Kh_z" +msgstr "" + +#: src/gtk/vba.glade:1306 +msgid "_Volume" +msgstr "" + +#: src/gtk/vba.glade:1354 +msgid "300%" +msgstr "" + +#: src/gtk/vba.glade:1364 +msgid "400%" +msgstr "" + +#: src/gtk/vba.glade:1382 +msgid "_Gameboy" +msgstr "" + +#: src/gtk/vba.glade:1391 +msgid "_Border" +msgstr "" + +#: src/gtk/vba.glade:1400 +msgid "_Printer" +msgstr "" + +#: src/gtk/vba.glade:1424 +msgid "_GBA" +msgstr "" + +#: src/gtk/vba.glade:1434 +msgid "_CGB/GBC" +msgstr "" + +#: src/gtk/vba.glade:1444 +msgid "_SGB" +msgstr "" + +#: src/gtk/vba.glade:1454 +msgid "SGB_2" +msgstr "" + +#: src/gtk/vba.glade:1464 +msgid "G_B" +msgstr "" + +#: src/gtk/vba.glade:1478 +msgid "F_ilter" +msgstr "" + +#: src/gtk/vba.glade:1487 +msgid "Interframe _blending" +msgstr "" + +#: src/gtk/vba.glade:1496 src/gtk/vba.glade:1535 +msgid "_None" +msgstr "" + +#: src/gtk/vba.glade:1505 +msgid "_Smart" +msgstr "" + +#: src/gtk/vba.glade:1515 src/gtk/vba.glade:1594 +msgid "_Motion Blur" +msgstr "" + +#: src/gtk/vba.glade:1544 +msgid "_TV Mode" +msgstr "" + +#: src/gtk/vba.glade:1554 +msgid "_2xSaI" +msgstr "" + +#: src/gtk/vba.glade:1564 +msgid "_Super 2xSaI" +msgstr "" + +#: src/gtk/vba.glade:1574 +msgid "Super _Eagle" +msgstr "" + +#: src/gtk/vba.glade:1584 +msgid "_Pixelate" +msgstr "" + +#: src/gtk/vba.glade:1604 +msgid "_AdvanceMAME 2x" +msgstr "" + +#: src/gtk/vba.glade:1614 +msgid "S_imple 2x" +msgstr "" + +#: src/gtk/vba.glade:1624 +msgid "Bilinea_r" +msgstr "" + +#: src/gtk/vba.glade:1634 +msgid "Bilinear Pl_us" +msgstr "" + +#: src/gtk/vba.glade:1644 +msgid "S_canlines" +msgstr "" + +#: src/gtk/vba.glade:1654 +msgid "h_q2x" +msgstr "" + +#: src/gtk/vba.glade:1664 +msgid "_lq2x" +msgstr "" + +#: src/gtk/vba.glade:1680 +msgid "_Disable MMX" +msgstr "" + +#: src/gtk/vba.glade:1693 +msgid "_Joypad" +msgstr "" + +#: src/gtk/vba.glade:1702 +msgid "_Configure" +msgstr "" + +#: src/gtk/vba.glade:1711 +msgid "_1..." +msgstr "" + +#: src/gtk/vba.glade:1719 +msgid "_2..." +msgstr "" + +#: src/gtk/vba.glade:1727 +msgid "_3..." +msgstr "" + +#: src/gtk/vba.glade:1735 +msgid "_4..." +msgstr "" + +#: src/gtk/vba.glade:1798 +msgid "_Autofire" +msgstr "" + +#: src/gtk/vba.glade:1807 +msgid "_A" +msgstr "" + +#: src/gtk/vba.glade:1817 +msgid "_B" +msgstr "" + +#: src/gtk/vba.glade:1827 +msgid "_L" +msgstr "" + +#: src/gtk/vba.glade:1837 +msgid "_R" +msgstr "" + +#: src/gtk/vba.glade:1859 +msgid "_Tools" +msgstr "" + +#: src/gtk/vba.glade:1868 +msgid "_GDB" +msgstr "" + +#: src/gtk/vba.glade:1877 +msgid "_Wait connection..." +msgstr "" + +#: src/gtk/vba.glade:1885 +msgid "_Load and wait..." +msgstr "" + +#: src/gtk/vba.glade:1893 +msgid "_Break" +msgstr "" + +#: src/gtk/vba.glade:1901 +msgid "_Disconnect" +msgstr "" + +#: src/gtk/vba.glade:1917 +msgid "_Help" +msgstr "" + +#: src/gtk/vba.glade:1926 +msgid "_About" +msgstr "" + +#: src/gtk/vba.glade:1967 +msgid "About VBA" +msgstr "" + +#: src/gtk/vba.glade:2054 +msgid "An emulator for Gameboy(TM) and GameboyAdvance(TM)." +msgstr "" + +#: src/gtk/vba.glade:2076 +msgid "Special thanks to Yann Parmentier aka \"kohai\" for the icons." +msgstr "" + +#: src/gtk/vba.glade:2098 +msgid "" +"Copyright (C) 2004 Forgotten and the VBA development team" +msgstr "" + +#: src/gtk/vba.glade:2120 +msgid "Throttle" +msgstr "" + +#: src/gtk/vba.glade:2191 +msgid "Throttle : " +msgstr "" + +#: src/gtk/vba.glade:2231 +msgid " %" +msgstr "" + +#: src/gtk/vba.glade:2262 +msgid "Directories" +msgstr "" + +#: src/gtk/vba.glade:2328 +msgid "GBA roms : " +msgstr "" + +#: src/gtk/vba.glade:2358 src/gtk/vba.glade:2511 src/gtk/vba.glade:2612 +#: src/gtk/vba.glade:2713 src/gtk/vba.glade:2790 src/gtk/vba.glade:2921 +#: src/gtk/vba.glade:3207 src/gtk/vba.glade:3229 src/gtk/vba.glade:3251 +#: src/gtk/vba.glade:3273 src/gtk/vba.glade:3295 src/gtk/vba.glade:3317 +#: src/gtk/vba.glade:3339 src/gtk/vba.glade:3361 src/gtk/vba.glade:3383 +#: src/gtk/vba.glade:3405 src/gtk/vba.glade:3427 +msgid "*" +msgstr "" + +#: src/gtk/vba.glade:2429 +msgid "GB roms : " +msgstr "" + +#: src/gtk/vba.glade:2481 +msgid "Batteries : " +msgstr "" + +#: src/gtk/vba.glade:2582 +msgid "Saves : " +msgstr "" + +#: src/gtk/vba.glade:2683 +msgid "Captures : " +msgstr "" + +#: src/gtk/vba.glade:2841 +msgid "Joypad config" +msgstr "" + +#: src/gtk/vba.glade:2937 +msgid "Down : " +msgstr "" + +#: src/gtk/vba.glade:2961 +msgid "Left : " +msgstr "" + +#: src/gtk/vba.glade:2985 +msgid "Right : " +msgstr "" + +#: src/gtk/vba.glade:3009 +msgid "Button A : " +msgstr "" + +#: src/gtk/vba.glade:3033 +msgid "Button B : " +msgstr "" + +#: src/gtk/vba.glade:3057 +msgid "Button L : " +msgstr "" + +#: src/gtk/vba.glade:3081 +msgid "Button R : " +msgstr "" + +#: src/gtk/vba.glade:3105 +msgid "Select : " +msgstr "" + +#: src/gtk/vba.glade:3129 +msgid "Start : " +msgstr "" + +#: src/gtk/vba.glade:3153 +msgid "Speed : " +msgstr "" + +#: src/gtk/vba.glade:3177 +msgid "Capture : " +msgstr "" + +#: src/gtk/vba.glade:3443 +msgid "Up : " +msgstr "" + +#: src/gtk/vba.glade:3477 +msgid "TCP port" +msgstr "" + +#: src/gtk/vba.glade:3548 +msgid "Port : " +msgstr "" + +#: src/gtk/windowcallbacks.cpp:80 src/gtk/windowcallbacks.cpp:94 +msgid "Load game" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:109 src/gtk/windowcallbacks.cpp:163 +msgid "VisualBoyAdvance save game" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:131 src/gtk/windowcallbacks.cpp:146 +msgid "Save game" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:181 src/gtk/windowcallbacks.cpp:466 +#: src/gtk/windowcallbacks.cpp:585 +msgid "File already exists. Overwrite it?" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:318 src/gtk/windowcallbacks.cpp:332 +msgid "Import battery file" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:347 src/gtk/windowcallbacks.cpp:424 +msgid "Battery file" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:351 src/gtk/windowcallbacks.cpp:428 +msgid "Flash save" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:362 +msgid "" +"Importing a battery file will erase any saved games and reset the emulator. " +"Do you want to continue?" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:380 +#, c-format +msgid "Failed to import battery file %s." +msgstr "" + +#: src/gtk/windowcallbacks.cpp:392 src/gtk/windowcallbacks.cpp:407 +msgid "Export battery file" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:494 +#, c-format +msgid "Failed to export battery file %s." +msgstr "" + +#: src/gtk/windowcallbacks.cpp:506 src/gtk/windowcallbacks.cpp:521 +msgid "Save screenshot" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:538 +msgid "PNG image" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:542 +msgid "BMP image" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:824 src/gtk/windowcallbacks.cpp:844 +msgid "Select directory" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:872 src/gtk/windowcallbacks.cpp:882 +msgid "Select BIOS file" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:898 +msgid "All files" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:902 +msgid "Gameboy Advance BIOS" +msgstr "" + +#: src/gtk/windowcallbacks.cpp:1336 +msgid "Only GBA images are supported." +msgstr "" + +#: src/gtk/window.cpp:1421 +#, c-format +msgid "Unknown file type %s" +msgstr "" + +#: src/gtk/window.cpp:1702 src/gtk/window.cpp:1716 +msgid "Open" +msgstr "" + +#: src/gtk/window.cpp:1743 +msgid "All Gameboy Advance files" +msgstr "" + +#: src/gtk/window.cpp:1750 +msgid "Gameboy Advance files" +msgstr "" + +#: src/gtk/window.cpp:1757 +msgid "Gameboy files" +msgstr "" + +#: src/gtk/window.cpp:1787 +msgid "Loaded battery" +msgstr "" + +#: src/gtk/window.cpp:1806 +msgid "Saved battery" +msgstr "" + +#: src/gtk/window.cpp:1864 src/gtk/window.cpp:1911 +msgid "----/--/-- --:--:--" +msgstr "" + +#: src/gtk/window.cpp:1896 +msgid "%Y/%m/%d %H:%M:%S" +msgstr "" + +#: src/prof/prof.cpp:137 +msgid "No space for profiling buffer(s)\n" +msgstr "" diff -urN ../VisualBoyAdvance-1.7.2/src/2xSaI.cpp ./src/2xSaI.cpp --- ../VisualBoyAdvance-1.7.2/src/2xSaI.cpp 2004-01-26 11:12:15 +0900 +++ ./src/2xSaI.cpp 2004-09-16 07:12:51 +0900 @@ -1,6 +1,8 @@ #include "System.h" #include "Port.h" +extern int RGB_LOW_BITS_MASK; + extern "C" { @@ -48,6 +50,7 @@ greenMask = 0x7E0; qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0xF7DEF7DE; hq2x_init(16); + RGB_LOW_BITS_MASK = 0x0821; } else if (BitFormat == 555) { colorMask = 0x7BDE7BDE; lowPixelMask = 0x04210421; @@ -57,6 +60,7 @@ greenMask = 0x3E0; qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0x7BDE7BDE; hq2x_init(15); + RGB_LOW_BITS_MASK = 0x0421; } else { return 0; } @@ -67,6 +71,7 @@ qlowpixelMask = 0x030303; qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0xfefefe; hq2x_init(32); + RGB_LOW_BITS_MASK = 0x010101; } else return 0; diff -urN ../VisualBoyAdvance-1.7.2/src/AutoBuild.h ./src/AutoBuild.h --- ../VisualBoyAdvance-1.7.2/src/AutoBuild.h 2004-05-16 06:36:44 +0900 +++ ./src/AutoBuild.h 2004-12-19 08:09:56 +0900 @@ -20,12 +20,12 @@ #ifndef __AUTOBUILD_H__ #define __AUTOBUILD_H__ #ifndef VERSION -#define VERSION "1.7.2" +#define VERSION "1.8.0" #endif //change the FALSE to TRUE for autoincrement of build number #define INCREMENT_VERSION FALSE -#define FILEVER 1,7,2,560 -#define PRODUCTVER 1,7,2,560 -#define STRFILEVER "1, 7, 2, 560\0" -#define STRPRODUCTVER "1, 7, 2, 560\0" +#define FILEVER 1,8,0,600 +#define PRODUCTVER 1,8,0,600 +#define STRFILEVER "1, 8, 0, 600\0" +#define STRPRODUCTVER "1, 8, 0, 600\0" #endif //__AUTOBUILD_H__ diff -urN ../VisualBoyAdvance-1.7.2/src/Cheats.cpp ./src/Cheats.cpp --- ../VisualBoyAdvance-1.7.2/src/Cheats.cpp 2004-05-13 23:38:33 +0900 +++ ./src/Cheats.cpp 2006-06-25 05:21:47 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -29,25 +29,34 @@ #include "Util.h" /** - * Gameshark code types: + * Gameshark code types: (based on AR v1.0) * * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM - * DEADFACE XXXXXXXX - changes decryption seeds + * DEADFACE XXXXXXXX - changes decryption seeds // Not supported by VBA. * 0AAAAAAA 000000YY - 8-bit constant write * 1AAAAAAA 0000YYYY - 16-bit constant write * 2AAAAAAA YYYYYYYY - 32-bit constant write - * 3AAAAAAA YYYYYYYY - ?? - * 6AAAAAAA 0000YYYY - 16-bit ROM Patch (address >> 1) - * 6AAAAAAA 1000YYYY - 16-bit ROM Patch ? (address >> 1) - * 6AAAAAAA 2000YYYY - 16-bit ROM Patch ? (address >> 1) + * 30XXAAAA YYYYYYYY - 32bit Group Write, 8/16/32bit Sub/Add (depending on the XX value). + * 6AAAAAAA Z000YYYY - 16-bit ROM Patch (address >> 1). Z selects the Rom Patching register. + * - AR v1/2 hardware only supports Z=0. + * - AR v3 hardware should support Z=0,1,2 or 3. * 8A1AAAAA 000000YY - 8-bit button write * 8A2AAAAA 0000YYYY - 16-bit button write - * 8A3AAAAA YYYYYYYY - 32-bit button write + * 8A4AAAAA YYYYYYYY - 32-bit button write // BUGGY ! Only writes 00000000 on the AR v1.0. * 80F00000 0000YYYY - button slow motion - * DAAAAAAA 0000YYYY - if address contains 16-bit value enable next code + * DAAAAAAA 00Z0YYYY - Z = 0 : if 16-bit value at address != YYYY skip next line + * - Z = 1 : if 16-bit value at address == YYYY skip next line + * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip next line + * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip next line + * E0CCYYYY ZAAAAAAA - Z = 0 : if 16-bit value at address != YYYY skip CC lines + * - Z = 1 : if 16-bit value at address == YYYY skip CC lines + * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip CC lines + * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip CC lines * FAAAAAAA 0000YYYY - Master code function * - * CodeBreaker codes types: + * + * + * CodeBreaker codes types: (based on the CBA clone "Cheatcode S" v1.1) * * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI) * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16) @@ -56,65 +65,150 @@ * 3AAAAAAA YYYY - 8-bit constant write * 4AAAAAAA YYYY - Slide code * XXXXCCCC IIII (C is count and I is address increment, X is value incr.) - * 5AAAAAAA CCCC - Super code (Write bytes to address, CCCC is count) + * 5AAAAAAA CCCC - Super code (Write bytes to address, 2*CCCC is count) * BBBBBBBB BBBB * 6AAAAAAA YYYY - 16-bit and * 7AAAAAAA YYYY - if address contains 16-bit value enable next code * 8AAAAAAA YYYY - 16-bit constant write * 9AAAAAAA YYYY - change decryption (when first code only?) * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code - * BAAAAAAA YYYY - if 16-bit < YYYY - * CAAAAAAA YYYY - if 16-bit > YYYY - * D0000020 YYYY - if button keys equal value enable next code - * EAAAAAAA YYYY - increase value stored in address - */ -#define UNKNOWN_CODE -1 -#define INT_8_BIT_WRITE 0 -#define INT_16_BIT_WRITE 1 -#define INT_32_BIT_WRITE 2 -#define GSA_16_BIT_ROM_PATCH 3 -#define GSA_8_BIT_GS_WRITE 4 -#define GSA_16_BIT_GS_WRITE 5 -#define GSA_32_BIT_GS_WRITE 6 -#define CBA_IF_KEYS_PRESSED 7 -#define CBA_IF_TRUE 8 -#define CBA_SLIDE_CODE 9 -#define CBA_IF_FALSE 10 -#define CBA_AND 11 -#define GSA_8_BIT_GS_WRITE2 12 -#define GSA_16_BIT_GS_WRITE2 13 -#define GSA_32_BIT_GS_WRITE2 14 -#define GSA_16_BIT_ROM_PATCH2 15 -#define GSA_8_BIT_SLIDE 16 -#define GSA_16_BIT_SLIDE 17 -#define GSA_32_BIT_SLIDE 18 -#define GSA_8_BIT_IF_TRUE 19 -#define GSA_32_BIT_IF_TRUE 20 -#define GSA_8_BIT_IF_FALSE 21 -#define GSA_32_BIT_IF_FALSE 22 -#define GSA_8_BIT_FILL 23 -#define GSA_16_BIT_FILL 24 -#define GSA_8_BIT_IF_TRUE2 25 -#define GSA_16_BIT_IF_TRUE2 26 -#define GSA_32_BIT_IF_TRUE2 27 -#define GSA_8_BIT_IF_FALSE2 28 -#define GSA_16_BIT_IF_FALSE2 29 -#define GSA_32_BIT_IF_FALSE2 30 -#define GSA_SLOWDOWN 31 -#define CBA_ADD 32 -#define CBA_OR 33 -#define CBA_LT 34 -#define CBA_GT 35 -#define CBA_SUPER 36 + * BAAAAAAA YYYY - if 16-bit value at address <= YYYY skip next code + * CAAAAAAA YYYY - if 16-bit value at address >= YYYY skip next code + * D00000X0 YYYY - if button keys ... enable next code (else skip next code) + * EAAAAAAA YYYY - increase 16/32bit value stored in address + * FAAAAAAA YYYY - if 16-bit value at address AND YYYY = 0 then skip next code + **/ + +#define UNKNOWN_CODE -1 +#define INT_8_BIT_WRITE 0 +#define INT_16_BIT_WRITE 1 +#define INT_32_BIT_WRITE 2 +#define GSA_16_BIT_ROM_PATCH 3 +#define GSA_8_BIT_GS_WRITE 4 +#define GSA_16_BIT_GS_WRITE 5 +#define GSA_32_BIT_GS_WRITE 6 +#define CBA_IF_KEYS_PRESSED 7 +#define CBA_IF_TRUE 8 +#define CBA_SLIDE_CODE 9 +#define CBA_IF_FALSE 10 +#define CBA_AND 11 +#define GSA_8_BIT_GS_WRITE2 12 +#define GSA_16_BIT_GS_WRITE2 13 +#define GSA_32_BIT_GS_WRITE2 14 +#define GSA_16_BIT_ROM_PATCH2C 15 +#define GSA_8_BIT_SLIDE 16 +#define GSA_16_BIT_SLIDE 17 +#define GSA_32_BIT_SLIDE 18 +#define GSA_8_BIT_IF_TRUE 19 +#define GSA_32_BIT_IF_TRUE 20 +#define GSA_8_BIT_IF_FALSE 21 +#define GSA_32_BIT_IF_FALSE 22 +#define GSA_8_BIT_FILL 23 +#define GSA_16_BIT_FILL 24 +#define GSA_8_BIT_IF_TRUE2 25 +#define GSA_16_BIT_IF_TRUE2 26 +#define GSA_32_BIT_IF_TRUE2 27 +#define GSA_8_BIT_IF_FALSE2 28 +#define GSA_16_BIT_IF_FALSE2 29 +#define GSA_32_BIT_IF_FALSE2 30 +#define GSA_SLOWDOWN 31 +#define CBA_ADD 32 +#define CBA_OR 33 +#define CBA_LT 34 +#define CBA_GT 35 +#define CBA_SUPER 36 +#define GSA_8_BIT_POINTER 37 +#define GSA_16_BIT_POINTER 38 +#define GSA_32_BIT_POINTER 39 +#define GSA_8_BIT_ADD 40 +#define GSA_16_BIT_ADD 41 +#define GSA_32_BIT_ADD 42 +#define GSA_8_BIT_IF_LOWER_U 43 +#define GSA_16_BIT_IF_LOWER_U 44 +#define GSA_32_BIT_IF_LOWER_U 45 +#define GSA_8_BIT_IF_HIGHER_U 46 +#define GSA_16_BIT_IF_HIGHER_U 47 +#define GSA_32_BIT_IF_HIGHER_U 48 +#define GSA_8_BIT_IF_AND 49 +#define GSA_16_BIT_IF_AND 50 +#define GSA_32_BIT_IF_AND 51 +#define GSA_8_BIT_IF_LOWER_U2 52 +#define GSA_16_BIT_IF_LOWER_U2 53 +#define GSA_32_BIT_IF_LOWER_U2 54 +#define GSA_8_BIT_IF_HIGHER_U2 55 +#define GSA_16_BIT_IF_HIGHER_U2 56 +#define GSA_32_BIT_IF_HIGHER_U2 57 +#define GSA_8_BIT_IF_AND2 58 +#define GSA_16_BIT_IF_AND2 59 +#define GSA_32_BIT_IF_AND2 60 +#define GSA_ALWAYS 61 +#define GSA_ALWAYS2 62 +#define GSA_8_BIT_IF_LOWER_S 63 +#define GSA_16_BIT_IF_LOWER_S 64 +#define GSA_32_BIT_IF_LOWER_S 65 +#define GSA_8_BIT_IF_HIGHER_S 66 +#define GSA_16_BIT_IF_HIGHER_S 67 +#define GSA_32_BIT_IF_HIGHER_S 68 +#define GSA_8_BIT_IF_LOWER_S2 69 +#define GSA_16_BIT_IF_LOWER_S2 70 +#define GSA_32_BIT_IF_LOWER_S2 71 +#define GSA_8_BIT_IF_HIGHER_S2 72 +#define GSA_16_BIT_IF_HIGHER_S2 73 +#define GSA_32_BIT_IF_HIGHER_S2 74 +#define GSA_16_BIT_WRITE_IOREGS 75 +#define GSA_32_BIT_WRITE_IOREGS 76 +#define GSA_CODES_ON 77 +#define GSA_8_BIT_IF_TRUE3 78 +#define GSA_16_BIT_IF_TRUE3 79 +#define GSA_32_BIT_IF_TRUE3 80 +#define GSA_8_BIT_IF_FALSE3 81 +#define GSA_16_BIT_IF_FALSE3 82 +#define GSA_32_BIT_IF_FALSE3 83 +#define GSA_8_BIT_IF_LOWER_S3 84 +#define GSA_16_BIT_IF_LOWER_S3 85 +#define GSA_32_BIT_IF_LOWER_S3 86 +#define GSA_8_BIT_IF_HIGHER_S3 87 +#define GSA_16_BIT_IF_HIGHER_S3 88 +#define GSA_32_BIT_IF_HIGHER_S3 89 +#define GSA_8_BIT_IF_LOWER_U3 90 +#define GSA_16_BIT_IF_LOWER_U3 91 +#define GSA_32_BIT_IF_LOWER_U3 92 +#define GSA_8_BIT_IF_HIGHER_U3 93 +#define GSA_16_BIT_IF_HIGHER_U3 94 +#define GSA_32_BIT_IF_HIGHER_U3 95 +#define GSA_8_BIT_IF_AND3 96 +#define GSA_16_BIT_IF_AND3 97 +#define GSA_32_BIT_IF_AND3 98 +#define GSA_ALWAYS3 99 +#define GSA_16_BIT_ROM_PATCH2D 100 +#define GSA_16_BIT_ROM_PATCH2E 101 +#define GSA_16_BIT_ROM_PATCH2F 102 +#define GSA_GROUP_WRITE 103 +#define GSA_32_BIT_ADD2 104 +#define GSA_32_BIT_SUB2 105 +#define GSA_16_BIT_IF_LOWER_OR_EQ_U 106 +#define GSA_16_BIT_IF_HIGHER_OR_EQ_U 107 +#define GSA_16_BIT_MIF_TRUE 108 +#define GSA_16_BIT_MIF_FALSE 109 +#define GSA_16_BIT_MIF_LOWER_OR_EQ_U 110 +#define GSA_16_BIT_MIF_HIGHER_OR_EQ_U 111 +#define MASTER_CODE 112 +#define CHEATS_16_BIT_WRITE 114 +#define CHEATS_32_BIT_WRITE 115 CheatsData cheatsList[100]; int cheatsNumber = 0; +u32 rompatch2addr [4]; +u16 rompatch2val [4]; +u16 rompatch2oldval [4]; u8 cheatsCBASeedBuffer[0x30]; u32 cheatsCBASeed[4]; u32 cheatsCBATemporaryValue = 0; u16 cheatsCBATable[256]; bool cheatsCBATableGenerated = false; +u16 super = 0; +extern u32 mastercode; u8 cheatsCBACurrentSeed[12] = { 0x00, 0x00, 0x00, 0x00, @@ -122,15 +216,119 @@ 0x00, 0x00, 0x00, 0x00 }; +u32 seeds_v1[4]; +u32 seeds_v3[4]; + +u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2); + +//seed tables for AR v1 +u8 v1_deadtable1[256] = { + 0x31, 0x1C, 0x23, 0xE5, 0x89, 0x8E, 0xA1, 0x37, 0x74, 0x6D, 0x67, 0xFC, 0x1F, 0xC0, 0xB1, 0x94, + 0x3B, 0x05, 0x56, 0x86, 0x00, 0x24, 0xF0, 0x17, 0x72, 0xA2, 0x3D, 0x1B, 0xE3, 0x17, 0xC5, 0x0B, + 0xB9, 0xE2, 0xBD, 0x58, 0x71, 0x1B, 0x2C, 0xFF, 0xE4, 0xC9, 0x4C, 0x5E, 0xC9, 0x55, 0x33, 0x45, + 0x7C, 0x3F, 0xB2, 0x51, 0xFE, 0x10, 0x7E, 0x75, 0x3C, 0x90, 0x8D, 0xDA, 0x94, 0x38, 0xC3, 0xE9, + 0x95, 0xEA, 0xCE, 0xA6, 0x06, 0xE0, 0x4F, 0x3F, 0x2A, 0xE3, 0x3A, 0xE4, 0x43, 0xBD, 0x7F, 0xDA, + 0x55, 0xF0, 0xEA, 0xCB, 0x2C, 0xA8, 0x47, 0x61, 0xA0, 0xEF, 0xCB, 0x13, 0x18, 0x20, 0xAF, 0x3E, + 0x4D, 0x9E, 0x1E, 0x77, 0x51, 0xC5, 0x51, 0x20, 0xCF, 0x21, 0xF9, 0x39, 0x94, 0xDE, 0xDD, 0x79, + 0x4E, 0x80, 0xC4, 0x9D, 0x94, 0xD5, 0x95, 0x01, 0x27, 0x27, 0xBD, 0x6D, 0x78, 0xB5, 0xD1, 0x31, + 0x6A, 0x65, 0x74, 0x74, 0x58, 0xB3, 0x7C, 0xC9, 0x5A, 0xED, 0x50, 0x03, 0xC4, 0xA2, 0x94, 0x4B, + 0xF0, 0x58, 0x09, 0x6F, 0x3E, 0x7D, 0xAE, 0x7D, 0x58, 0xA0, 0x2C, 0x91, 0xBB, 0xE1, 0x70, 0xEB, + 0x73, 0xA6, 0x9A, 0x44, 0x25, 0x90, 0x16, 0x62, 0x53, 0xAE, 0x08, 0xEB, 0xDC, 0xF0, 0xEE, 0x77, + 0xC2, 0xDE, 0x81, 0xE8, 0x30, 0x89, 0xDB, 0xFE, 0xBC, 0xC2, 0xDF, 0x26, 0xE9, 0x8B, 0xD6, 0x93, + 0xF0, 0xCB, 0x56, 0x90, 0xC0, 0x46, 0x68, 0x15, 0x43, 0xCB, 0xE9, 0x98, 0xE3, 0xAF, 0x31, 0x25, + 0x4D, 0x7B, 0xF3, 0xB1, 0x74, 0xE2, 0x64, 0xAC, 0xD9, 0xF6, 0xA0, 0xD5, 0x0B, 0x9B, 0x49, 0x52, + 0x69, 0x3B, 0x71, 0x00, 0x2F, 0xBB, 0xBA, 0x08, 0xB1, 0xAE, 0xBB, 0xB3, 0xE1, 0xC9, 0xA6, 0x7F, + 0x17, 0x97, 0x28, 0x72, 0x12, 0x6E, 0x91, 0xAE, 0x3A, 0xA2, 0x35, 0x46, 0x27, 0xF8, 0x12, 0x50 +}; +u8 v1_deadtable2[256] = { + 0xD8, 0x65, 0x04, 0xC2, 0x65, 0xD5, 0xB0, 0x0C, 0xDF, 0x9D, 0xF0, 0xC3, 0x9A, 0x17, 0xC9, 0xA6, + 0xE1, 0xAC, 0x0D, 0x14, 0x2F, 0x3C, 0x2C, 0x87, 0xA2, 0xBF, 0x4D, 0x5F, 0xAC, 0x2D, 0x9D, 0xE1, + 0x0C, 0x9C, 0xE7, 0x7F, 0xFC, 0xA8, 0x66, 0x59, 0xAC, 0x18, 0xD7, 0x05, 0xF0, 0xBF, 0xD1, 0x8B, + 0x35, 0x9F, 0x59, 0xB4, 0xBA, 0x55, 0xB2, 0x85, 0xFD, 0xB1, 0x72, 0x06, 0x73, 0xA4, 0xDB, 0x48, + 0x7B, 0x5F, 0x67, 0xA5, 0x95, 0xB9, 0xA5, 0x4A, 0xCF, 0xD1, 0x44, 0xF3, 0x81, 0xF5, 0x6D, 0xF6, + 0x3A, 0xC3, 0x57, 0x83, 0xFA, 0x8E, 0x15, 0x2A, 0xA2, 0x04, 0xB2, 0x9D, 0xA8, 0x0D, 0x7F, 0xB8, + 0x0F, 0xF6, 0xAC, 0xBE, 0x97, 0xCE, 0x16, 0xE6, 0x31, 0x10, 0x60, 0x16, 0xB5, 0x83, 0x45, 0xEE, + 0xD7, 0x5F, 0x2C, 0x08, 0x58, 0xB1, 0xFD, 0x7E, 0x79, 0x00, 0x34, 0xAD, 0xB5, 0x31, 0x34, 0x39, + 0xAF, 0xA8, 0xDD, 0x52, 0x6A, 0xB0, 0x60, 0x35, 0xB8, 0x1D, 0x52, 0xF5, 0xF5, 0x30, 0x00, 0x7B, + 0xF4, 0xBA, 0x03, 0xCB, 0x3A, 0x84, 0x14, 0x8A, 0x6A, 0xEF, 0x21, 0xBD, 0x01, 0xD8, 0xA0, 0xD4, + 0x43, 0xBE, 0x23, 0xE7, 0x76, 0x27, 0x2C, 0x3F, 0x4D, 0x3F, 0x43, 0x18, 0xA7, 0xC3, 0x47, 0xA5, + 0x7A, 0x1D, 0x02, 0x55, 0x09, 0xD1, 0xFF, 0x55, 0x5E, 0x17, 0xA0, 0x56, 0xF4, 0xC9, 0x6B, 0x90, + 0xB4, 0x80, 0xA5, 0x07, 0x22, 0xFB, 0x22, 0x0D, 0xD9, 0xC0, 0x5B, 0x08, 0x35, 0x05, 0xC1, 0x75, + 0x4F, 0xD0, 0x51, 0x2D, 0x2E, 0x5E, 0x69, 0xE7, 0x3B, 0xC2, 0xDA, 0xFF, 0xF6, 0xCE, 0x3E, 0x76, + 0xE8, 0x36, 0x8C, 0x39, 0xD8, 0xF3, 0xE9, 0xA6, 0x42, 0xE6, 0xC1, 0x4C, 0x05, 0xBE, 0x17, 0xF2, + 0x5C, 0x1B, 0x19, 0xDB, 0x0F, 0xF3, 0xF8, 0x49, 0xEB, 0x36, 0xF6, 0x40, 0x6F, 0xAD, 0xC1, 0x8C +}; + +//seed tables for AR v3 +u8 v3_deadtable1[256] = { + 0xD0, 0xFF, 0xBA, 0xE5, 0xC1, 0xC7, 0xDB, 0x5B, 0x16, 0xE3, 0x6E, 0x26, 0x62, 0x31, 0x2E, 0x2A, + 0xD1, 0xBB, 0x4A, 0xE6, 0xAE, 0x2F, 0x0A, 0x90, 0x29, 0x90, 0xB6, 0x67, 0x58, 0x2A, 0xB4, 0x45, + 0x7B, 0xCB, 0xF0, 0x73, 0x84, 0x30, 0x81, 0xC2, 0xD7, 0xBE, 0x89, 0xD7, 0x4E, 0x73, 0x5C, 0xC7, + 0x80, 0x1B, 0xE5, 0xE4, 0x43, 0xC7, 0x46, 0xD6, 0x6F, 0x7B, 0xBF, 0xED, 0xE5, 0x27, 0xD1, 0xB5, + 0xD0, 0xD8, 0xA3, 0xCB, 0x2B, 0x30, 0xA4, 0xF0, 0x84, 0x14, 0x72, 0x5C, 0xFF, 0xA4, 0xFB, 0x54, + 0x9D, 0x70, 0xE2, 0xFF, 0xBE, 0xE8, 0x24, 0x76, 0xE5, 0x15, 0xFB, 0x1A, 0xBC, 0x87, 0x02, 0x2A, + 0x58, 0x8F, 0x9A, 0x95, 0xBD, 0xAE, 0x8D, 0x0C, 0xA5, 0x4C, 0xF2, 0x5C, 0x7D, 0xAD, 0x51, 0xFB, + 0xB1, 0x22, 0x07, 0xE0, 0x29, 0x7C, 0xEB, 0x98, 0x14, 0xC6, 0x31, 0x97, 0xE4, 0x34, 0x8F, 0xCC, + 0x99, 0x56, 0x9F, 0x78, 0x43, 0x91, 0x85, 0x3F, 0xC2, 0xD0, 0xD1, 0x80, 0xD1, 0x77, 0xA7, 0xE2, + 0x43, 0x99, 0x1D, 0x2F, 0x8B, 0x6A, 0xE4, 0x66, 0x82, 0xF7, 0x2B, 0x0B, 0x65, 0x14, 0xC0, 0xC2, + 0x1D, 0x96, 0x78, 0x1C, 0xC4, 0xC3, 0xD2, 0xB1, 0x64, 0x07, 0xD7, 0x6F, 0x02, 0xE9, 0x44, 0x31, + 0xDB, 0x3C, 0xEB, 0x93, 0xED, 0x9A, 0x57, 0x05, 0xB9, 0x0E, 0xAF, 0x1F, 0x48, 0x11, 0xDC, 0x35, + 0x6C, 0xB8, 0xEE, 0x2A, 0x48, 0x2B, 0xBC, 0x89, 0x12, 0x59, 0xCB, 0xD1, 0x18, 0xEA, 0x72, 0x11, + 0x01, 0x75, 0x3B, 0xB5, 0x56, 0xF4, 0x8B, 0xA0, 0x41, 0x75, 0x86, 0x7B, 0x94, 0x12, 0x2D, 0x4C, + 0x0C, 0x22, 0xC9, 0x4A, 0xD8, 0xB1, 0x8D, 0xF0, 0x55, 0x2E, 0x77, 0x50, 0x1C, 0x64, 0x77, 0xAA, + 0x3E, 0xAC, 0xD3, 0x3D, 0xCE, 0x60, 0xCA, 0x5D, 0xA0, 0x92, 0x78, 0xC6, 0x51, 0xFE, 0xF9, 0x30 +}; +u8 v3_deadtable2[256] = { + 0xAA, 0xAF, 0xF0, 0x72, 0x90, 0xF7, 0x71, 0x27, 0x06, 0x11, 0xEB, 0x9C, 0x37, 0x12, 0x72, 0xAA, + 0x65, 0xBC, 0x0D, 0x4A, 0x76, 0xF6, 0x5C, 0xAA, 0xB0, 0x7A, 0x7D, 0x81, 0xC1, 0xCE, 0x2F, 0x9F, + 0x02, 0x75, 0x38, 0xC8, 0xFC, 0x66, 0x05, 0xC2, 0x2C, 0xBD, 0x91, 0xAD, 0x03, 0xB1, 0x88, 0x93, + 0x31, 0xC6, 0xAB, 0x40, 0x23, 0x43, 0x76, 0x54, 0xCA, 0xE7, 0x00, 0x96, 0x9F, 0xD8, 0x24, 0x8B, + 0xE4, 0xDC, 0xDE, 0x48, 0x2C, 0xCB, 0xF7, 0x84, 0x1D, 0x45, 0xE5, 0xF1, 0x75, 0xA0, 0xED, 0xCD, + 0x4B, 0x24, 0x8A, 0xB3, 0x98, 0x7B, 0x12, 0xB8, 0xF5, 0x63, 0x97, 0xB3, 0xA6, 0xA6, 0x0B, 0xDC, + 0xD8, 0x4C, 0xA8, 0x99, 0x27, 0x0F, 0x8F, 0x94, 0x63, 0x0F, 0xB0, 0x11, 0x94, 0xC7, 0xE9, 0x7F, + 0x3B, 0x40, 0x72, 0x4C, 0xDB, 0x84, 0x78, 0xFE, 0xB8, 0x56, 0x08, 0x80, 0xDF, 0x20, 0x2F, 0xB9, + 0x66, 0x2D, 0x60, 0x63, 0xF5, 0x18, 0x15, 0x1B, 0x86, 0x85, 0xB9, 0xB4, 0x68, 0x0E, 0xC6, 0xD1, + 0x8A, 0x81, 0x2B, 0xB3, 0xF6, 0x48, 0xF0, 0x4F, 0x9C, 0x28, 0x1C, 0xA4, 0x51, 0x2F, 0xD7, 0x4B, + 0x17, 0xE7, 0xCC, 0x50, 0x9F, 0xD0, 0xD1, 0x40, 0x0C, 0x0D, 0xCA, 0x83, 0xFA, 0x5E, 0xCA, 0xEC, + 0xBF, 0x4E, 0x7C, 0x8F, 0xF0, 0xAE, 0xC2, 0xD3, 0x28, 0x41, 0x9B, 0xC8, 0x04, 0xB9, 0x4A, 0xBA, + 0x72, 0xE2, 0xB5, 0x06, 0x2C, 0x1E, 0x0B, 0x2C, 0x7F, 0x11, 0xA9, 0x26, 0x51, 0x9D, 0x3F, 0xF8, + 0x62, 0x11, 0x2E, 0x89, 0xD2, 0x9D, 0x35, 0xB1, 0xE4, 0x0A, 0x4D, 0x93, 0x01, 0xA7, 0xD1, 0x2D, + 0x00, 0x87, 0xE2, 0x2D, 0xA4, 0xE9, 0x0A, 0x06, 0x66, 0xF8, 0x1F, 0x44, 0x75, 0xB5, 0x6B, 0x1C, + 0xFC, 0x31, 0x09, 0x48, 0xA3, 0xFF, 0x92, 0x12, 0x58, 0xE9, 0xFA, 0xAE, 0x4F, 0xE2, 0xB4, 0xCC +}; + +#define debuggerReadMemory(addr) \ + READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +#define debuggerReadHalfWord(addr) \ + READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +#define debuggerReadByte(addr) \ + map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] + +#define debuggerWriteMemory(addr, value) \ + WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value) + +#define debuggerWriteHalfWord(addr, value) \ + WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value) + +#define debuggerWriteByte(addr, value) \ + map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value) + + #define CHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9')) #define CHEAT_PATCH_ROM_16BIT(a,v) \ - WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v); + WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v); + +#define CHEAT_PATCH_ROM_32BIT(a,v) \ + WRITE32LE(((u32 *)&rom[(a) & 0x1ffffff]), v); static bool isMultilineWithData(int i) { // we consider it a multiline code if it has more than one line of data // otherwise, it can still be considered a single code + // (Only CBA codes can be true multilines !!!) if(i < cheatsNumber && i >= 0) switch(cheatsList[i].size) { case INT_8_BIT_WRITE: @@ -159,18 +357,96 @@ case GSA_SLOWDOWN: case CBA_ADD: case CBA_OR: - return false; - // the codes below have two lines of data - case CBA_SLIDE_CODE: + case CBA_LT: + case CBA_GT: + case GSA_8_BIT_POINTER: + case GSA_16_BIT_POINTER: + case GSA_32_BIT_POINTER: + case GSA_8_BIT_ADD: + case GSA_16_BIT_ADD: + case GSA_32_BIT_ADD: + case GSA_8_BIT_IF_LOWER_U: + case GSA_16_BIT_IF_LOWER_U: + case GSA_32_BIT_IF_LOWER_U: + case GSA_8_BIT_IF_HIGHER_U: + case GSA_16_BIT_IF_HIGHER_U: + case GSA_32_BIT_IF_HIGHER_U: + case GSA_8_BIT_IF_AND: + case GSA_16_BIT_IF_AND: + case GSA_32_BIT_IF_AND: + case GSA_8_BIT_IF_LOWER_U2: + case GSA_16_BIT_IF_LOWER_U2: + case GSA_32_BIT_IF_LOWER_U2: + case GSA_8_BIT_IF_HIGHER_U2: + case GSA_16_BIT_IF_HIGHER_U2: + case GSA_32_BIT_IF_HIGHER_U2: + case GSA_8_BIT_IF_AND2: + case GSA_16_BIT_IF_AND2: + case GSA_32_BIT_IF_AND2: + case GSA_ALWAYS: + case GSA_ALWAYS2: + case GSA_8_BIT_IF_LOWER_S: + case GSA_16_BIT_IF_LOWER_S: + case GSA_32_BIT_IF_LOWER_S: + case GSA_8_BIT_IF_HIGHER_S: + case GSA_16_BIT_IF_HIGHER_S: + case GSA_32_BIT_IF_HIGHER_S: + case GSA_8_BIT_IF_LOWER_S2: + case GSA_16_BIT_IF_LOWER_S2: + case GSA_32_BIT_IF_LOWER_S2: + case GSA_8_BIT_IF_HIGHER_S2: + case GSA_16_BIT_IF_HIGHER_S2: + case GSA_32_BIT_IF_HIGHER_S2: + case GSA_16_BIT_WRITE_IOREGS: + case GSA_32_BIT_WRITE_IOREGS: + case GSA_CODES_ON: + case GSA_8_BIT_IF_TRUE3: + case GSA_16_BIT_IF_TRUE3: + case GSA_32_BIT_IF_TRUE3: + case GSA_8_BIT_IF_FALSE3: + case GSA_16_BIT_IF_FALSE3: + case GSA_32_BIT_IF_FALSE3: + case GSA_8_BIT_IF_LOWER_S3: + case GSA_16_BIT_IF_LOWER_S3: + case GSA_32_BIT_IF_LOWER_S3: + case GSA_8_BIT_IF_HIGHER_S3: + case GSA_16_BIT_IF_HIGHER_S3: + case GSA_32_BIT_IF_HIGHER_S3: + case GSA_8_BIT_IF_LOWER_U3: + case GSA_16_BIT_IF_LOWER_U3: + case GSA_32_BIT_IF_LOWER_U3: + case GSA_8_BIT_IF_HIGHER_U3: + case GSA_16_BIT_IF_HIGHER_U3: + case GSA_32_BIT_IF_HIGHER_U3: + case GSA_8_BIT_IF_AND3: + case GSA_16_BIT_IF_AND3: + case GSA_32_BIT_IF_AND3: + case GSA_ALWAYS3: case GSA_8_BIT_GS_WRITE2: case GSA_16_BIT_GS_WRITE2: case GSA_32_BIT_GS_WRITE2: - case GSA_16_BIT_ROM_PATCH2: + case GSA_16_BIT_ROM_PATCH2C: + case GSA_16_BIT_ROM_PATCH2D: + case GSA_16_BIT_ROM_PATCH2E: + case GSA_16_BIT_ROM_PATCH2F: case GSA_8_BIT_SLIDE: case GSA_16_BIT_SLIDE: case GSA_32_BIT_SLIDE: - case CBA_LT: - case CBA_GT: + case GSA_GROUP_WRITE: + case GSA_32_BIT_ADD2: + case GSA_32_BIT_SUB2: + case GSA_16_BIT_IF_LOWER_OR_EQ_U: + case GSA_16_BIT_IF_HIGHER_OR_EQ_U: + case GSA_16_BIT_MIF_TRUE: + case GSA_16_BIT_MIF_FALSE: + case GSA_16_BIT_MIF_LOWER_OR_EQ_U: + case GSA_16_BIT_MIF_HIGHER_OR_EQ_U: + case MASTER_CODE: + case CHEATS_16_BIT_WRITE: + case CHEATS_32_BIT_WRITE: + return false; + // the codes below have two lines of data + case CBA_SLIDE_CODE: case CBA_SUPER: return true; } @@ -197,15 +473,59 @@ case GSA_SLOWDOWN: case CBA_ADD: case CBA_OR: - return 1; - case CBA_IF_KEYS_PRESSED: - case CBA_IF_TRUE: - case CBA_IF_FALSE: - case CBA_SLIDE_CODE: + case GSA_8_BIT_POINTER: + case GSA_16_BIT_POINTER: + case GSA_32_BIT_POINTER: + case GSA_8_BIT_ADD: + case GSA_16_BIT_ADD: + case GSA_32_BIT_ADD: + case GSA_CODES_ON: + case GSA_8_BIT_IF_TRUE3: + case GSA_16_BIT_IF_TRUE3: + case GSA_32_BIT_IF_TRUE3: + case GSA_8_BIT_IF_FALSE3: + case GSA_16_BIT_IF_FALSE3: + case GSA_32_BIT_IF_FALSE3: + case GSA_8_BIT_IF_LOWER_S3: + case GSA_16_BIT_IF_LOWER_S3: + case GSA_32_BIT_IF_LOWER_S3: + case GSA_8_BIT_IF_HIGHER_S3: + case GSA_16_BIT_IF_HIGHER_S3: + case GSA_32_BIT_IF_HIGHER_S3: + case GSA_8_BIT_IF_LOWER_U3: + case GSA_16_BIT_IF_LOWER_U3: + case GSA_32_BIT_IF_LOWER_U3: + case GSA_8_BIT_IF_HIGHER_U3: + case GSA_16_BIT_IF_HIGHER_U3: + case GSA_32_BIT_IF_HIGHER_U3: + case GSA_8_BIT_IF_AND3: + case GSA_16_BIT_IF_AND3: + case GSA_32_BIT_IF_AND3: + case GSA_8_BIT_IF_LOWER_U: + case GSA_16_BIT_IF_LOWER_U: + case GSA_32_BIT_IF_LOWER_U: + case GSA_8_BIT_IF_HIGHER_U: + case GSA_16_BIT_IF_HIGHER_U: + case GSA_32_BIT_IF_HIGHER_U: + case GSA_8_BIT_IF_AND: + case GSA_16_BIT_IF_AND: + case GSA_32_BIT_IF_AND: + case GSA_ALWAYS: + case GSA_8_BIT_IF_LOWER_S: + case GSA_16_BIT_IF_LOWER_S: + case GSA_32_BIT_IF_LOWER_S: + case GSA_8_BIT_IF_HIGHER_S: + case GSA_16_BIT_IF_HIGHER_S: + case GSA_32_BIT_IF_HIGHER_S: + case GSA_16_BIT_WRITE_IOREGS: + case GSA_32_BIT_WRITE_IOREGS: case GSA_8_BIT_GS_WRITE2: case GSA_16_BIT_GS_WRITE2: case GSA_32_BIT_GS_WRITE2: - case GSA_16_BIT_ROM_PATCH2: + case GSA_16_BIT_ROM_PATCH2C: + case GSA_16_BIT_ROM_PATCH2D: + case GSA_16_BIT_ROM_PATCH2E: + case GSA_16_BIT_ROM_PATCH2F: case GSA_8_BIT_SLIDE: case GSA_16_BIT_SLIDE: case GSA_32_BIT_SLIDE: @@ -215,111 +535,136 @@ case GSA_32_BIT_IF_FALSE: case CBA_LT: case CBA_GT: - return 2; + case CBA_IF_TRUE: + case CBA_IF_FALSE: case GSA_8_BIT_IF_TRUE2: case GSA_16_BIT_IF_TRUE2: case GSA_32_BIT_IF_TRUE2: case GSA_8_BIT_IF_FALSE2: case GSA_16_BIT_IF_FALSE2: case GSA_32_BIT_IF_FALSE2: - return 3; + case GSA_8_BIT_IF_LOWER_U2: + case GSA_16_BIT_IF_LOWER_U2: + case GSA_32_BIT_IF_LOWER_U2: + case GSA_8_BIT_IF_HIGHER_U2: + case GSA_16_BIT_IF_HIGHER_U2: + case GSA_32_BIT_IF_HIGHER_U2: + case GSA_8_BIT_IF_AND2: + case GSA_16_BIT_IF_AND2: + case GSA_32_BIT_IF_AND2: + case GSA_ALWAYS2: + case GSA_8_BIT_IF_LOWER_S2: + case GSA_16_BIT_IF_LOWER_S2: + case GSA_32_BIT_IF_LOWER_S2: + case GSA_8_BIT_IF_HIGHER_S2: + case GSA_16_BIT_IF_HIGHER_S2: + case GSA_32_BIT_IF_HIGHER_S2: + case GSA_GROUP_WRITE: + case GSA_32_BIT_ADD2: + case GSA_32_BIT_SUB2: + case GSA_16_BIT_IF_LOWER_OR_EQ_U: + case GSA_16_BIT_IF_HIGHER_OR_EQ_U: + case GSA_16_BIT_MIF_TRUE: + case GSA_16_BIT_MIF_FALSE: + case GSA_16_BIT_MIF_LOWER_OR_EQ_U: + case GSA_16_BIT_MIF_HIGHER_OR_EQ_U: + case MASTER_CODE: + case CHEATS_16_BIT_WRITE: + case CHEATS_32_BIT_WRITE: + case UNKNOWN_CODE: + return 1; + case CBA_IF_KEYS_PRESSED: + case CBA_SLIDE_CODE: + return 2; case CBA_SUPER: - return (cheatsList[num].value+5)/6; + return ((((cheatsList[num].value-1) & 0xFFFF)/3) + 1); } return 1; } int cheatsCheckKeys(u32 keys, u32 extended) { + bool onoff = true; int ticks = 0; - for(int i = 0; i < cheatsNumber; i++) { + int i; + mastercode = 0; + + for (i = 0; i<4; i++) + if (rompatch2addr [i] != 0) { + CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2oldval [i]); + rompatch2addr [i] = 0; + } + + for (i = 0; i < cheatsNumber; i++) { if(!cheatsList[i].enabled) { // make sure we skip other lines in this code i += getCodeLength(i)-1; continue; } switch(cheatsList[i].size) { - case INT_8_BIT_WRITE: - CPUWriteByte(cheatsList[i].address, cheatsList[i].value); + case GSA_CODES_ON: + onoff = true; break; - case INT_16_BIT_WRITE: - CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); - break; - case INT_32_BIT_WRITE: - CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); + case GSA_SLOWDOWN: + // check if button was pressed and released, if so toggle our state + if((cheatsList[i].status & 4) && !(extended & 4)) + cheatsList[i].status ^= 1; + if(extended & 4) + cheatsList[i].status |= 4; + else + cheatsList[i].status &= ~4; + + if(cheatsList[i].status & 1) + ticks += ((cheatsList[i].value & 0xFFFF) * 7); break; - case GSA_16_BIT_ROM_PATCH: - if((cheatsList[i].status & 1) == 0) { - if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { - cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address); - cheatsList[i].status |= 1; - CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value); + case GSA_8_BIT_SLIDE: + i++; + if(i < cheatsNumber) { + u32 addr = cheatsList[i-1].value; + u8 value = cheatsList[i].rawaddress; + int vinc = (cheatsList[i].value >> 24) & 255; + int count = (cheatsList[i].value >> 16) & 255; + int ainc = (cheatsList[i].value & 0xffff); + while(count > 0) { + CPUWriteByte(addr, value); + value += vinc; + addr += ainc; + count--; } } break; - case GSA_8_BIT_GS_WRITE: - if(extended & 4) { - CPUWriteByte(cheatsList[i].address, cheatsList[i].value); - } - break; - case GSA_16_BIT_GS_WRITE: - if(extended & 4) { - CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); - } - break; - case GSA_32_BIT_GS_WRITE: - if(extended & 4) { - CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); - } - break; - case CBA_IF_KEYS_PRESSED: - { - u16 value = cheatsList[i].value; - u32 addr = cheatsList[i].address; - if((addr & 0x30) == 0x20) { - if((keys & value) != value) { - i++; - } - } else if((addr & 0x30) == 0x10) { - if((keys & value) == value) { - i++; - } + case GSA_16_BIT_SLIDE: + i++; + if(i < cheatsNumber) { + u32 addr = cheatsList[i-1].value; + u16 value = cheatsList[i].rawaddress; + int vinc = (cheatsList[i].value >> 24) & 255; + int count = (cheatsList[i].value >> 16) & 255; + int ainc = (cheatsList[i].value & 0xffff)*2; + while(count > 0) { + CPUWriteHalfWord(addr, value); + value += vinc; + addr += ainc; + count--; } } break; - case CBA_IF_TRUE: - if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { - i++; - } - break; - case CBA_SLIDE_CODE: - { - u32 address = cheatsList[i].address; - u16 value = cheatsList[i].value; - i++; - if(i < cheatsNumber) { - int count = (cheatsList[i].address & 0xFFFF); - u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF; - int inc = cheatsList[i].value; - - for(int x = 0; x < count; x++) { - CPUWriteHalfWord(address, value); - address += inc; - value += vinc; - } + case GSA_32_BIT_SLIDE: + i++; + if(i < cheatsNumber) { + u32 addr = cheatsList[i-1].value; + u32 value = cheatsList[i].rawaddress; + int vinc = (cheatsList[i].value >> 24) & 255; + int count = (cheatsList[i].value >> 16) & 255; + int ainc = (cheatsList[i].value & 0xffff)*4; + while(count > 0) { + CPUWriteMemory(addr, value); + value += vinc; + addr += ainc; + count--; } } break; - case CBA_IF_FALSE: - if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) { - i++; - } - break; - case CBA_AND: - CPUWriteHalfWord(cheatsList[i].address, - CPUReadHalfWord(cheatsList[i].address) & - cheatsList[i].value); - break; case GSA_8_BIT_GS_WRITE2: i++; if(i < cheatsNumber) { @@ -344,196 +689,644 @@ } } break; - case GSA_16_BIT_ROM_PATCH2: - i++; - if(i < cheatsNumber) { - if((cheatsList[i-1].status & 1) == 0) { - u32 addr = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000; - if(CPUReadHalfWord(addr) != (cheatsList[i].address & 0xFFFF)) { - cheatsList[i-1].oldValue = CPUReadHalfWord(addr); - cheatsList[i-1].status |= 1; - CHEAT_PATCH_ROM_16BIT(addr,cheatsList[i].address & 0xFFFF); + case GSA_16_BIT_ROM_PATCH: + if((cheatsList[i].status & 1) == 0) { + if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { + cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address); + cheatsList[i].status |= 1; + CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value); } } + break; + case GSA_16_BIT_ROM_PATCH2C: + i++; + if(i < cheatsNumber) { + rompatch2addr [0] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000; + rompatch2oldval [0] = CPUReadHalfWord(rompatch2addr [0]); + rompatch2val [0] = cheatsList[i].rawaddress & 0xFFFF; } break; - case GSA_8_BIT_SLIDE: + case GSA_16_BIT_ROM_PATCH2D: i++; if(i < cheatsNumber) { - u32 addr = cheatsList[i-1].value; - u8 value = cheatsList[i].address; - int vinc = (cheatsList[i].value >> 24) & 255; - int count = (cheatsList[i].value >> 16) & 255; - int ainc = (cheatsList[i].value & 0xffff); - while(count > 0) { - CPUWriteByte(addr, value); - value += vinc; - addr += ainc; - count--; - } + rompatch2addr [1] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000; + rompatch2oldval [1] = CPUReadHalfWord(rompatch2addr [1]); + rompatch2val [1] = cheatsList[i].rawaddress & 0xFFFF; } break; - case GSA_16_BIT_SLIDE: + case GSA_16_BIT_ROM_PATCH2E: i++; if(i < cheatsNumber) { - u32 addr = cheatsList[i-1].value; - u16 value = cheatsList[i].address; - int vinc = (cheatsList[i].value >> 24) & 255; - int count = (cheatsList[i].value >> 16) & 255; - int ainc = (cheatsList[i].value & 0xffff)*2; - while(count > 0) { - CPUWriteHalfWord(addr, value); - value += vinc; - addr += ainc; - count--; - } + rompatch2addr [2] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000; + rompatch2oldval [2] = CPUReadHalfWord(rompatch2addr [2]); + rompatch2val [2] = cheatsList[i].rawaddress & 0xFFFF; } break; - case GSA_32_BIT_SLIDE: + case GSA_16_BIT_ROM_PATCH2F: i++; if(i < cheatsNumber) { - u32 addr = cheatsList[i-1].value; - u32 value = cheatsList[i].address; - int vinc = (cheatsList[i].value >> 24) & 255; - int count = (cheatsList[i].value >> 16) & 255; - int ainc = (cheatsList[i].value & 0xffff)*4; - while(count > 0) { - CPUWriteMemory(addr, value); - value += vinc; - addr += ainc; - count--; + rompatch2addr [3] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000; + rompatch2oldval [3] = CPUReadHalfWord(rompatch2addr [3]); + rompatch2val [3] = cheatsList[i].rawaddress & 0xFFFF; + } + break; + case MASTER_CODE: + mastercode = cheatsList[i].address; + break; + } + if (onoff) { + switch(cheatsList[i].size) { + case INT_8_BIT_WRITE: + CPUWriteByte(cheatsList[i].address, cheatsList[i].value); + break; + case INT_16_BIT_WRITE: + CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); + break; + case INT_32_BIT_WRITE: + CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); + break; + case GSA_8_BIT_GS_WRITE: + if(extended & 4) { + CPUWriteByte(cheatsList[i].address, cheatsList[i].value); + } + break; + case GSA_16_BIT_GS_WRITE: + if(extended & 4) { + CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); + } + break; + case GSA_32_BIT_GS_WRITE: + if(extended & 4) { + CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); + } + break; + case CBA_IF_KEYS_PRESSED: + { + u16 value = cheatsList[i].value; + u32 addr = cheatsList[i].address; + if((addr & 0xF0) == 0x20) { + if((keys & value) == 0) { + i++; + } + } else if((addr & 0xF0) == 0x10) { + if((keys & value) == value) { + i++; + } + } else if((addr & 0xF0) == 0x00) { + if(((~keys) & 0x3FF) == value) { + i++; + } + } + } + break; + case CBA_IF_TRUE: + if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { + i++; + } + break; + case CBA_SLIDE_CODE: + { + u32 address = cheatsList[i].address; + u16 value = cheatsList[i].value; + i++; + if(i < cheatsNumber) { + int count = ((cheatsList[i].address - 1) & 0xFFFF); + u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF; + int inc = cheatsList[i].value; + for(int x = 0; x <= count ; x++) { + CPUWriteHalfWord(address, value); + address += inc; + value += vinc; + } + } + } + break; + case CBA_IF_FALSE: + if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value){ + i++; + } + break; + case CBA_AND: + CPUWriteHalfWord(cheatsList[i].address, + CPUReadHalfWord(cheatsList[i].address) & + cheatsList[i].value); + break; + case GSA_8_BIT_IF_TRUE: + if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) { + i++; + } + break; + case GSA_32_BIT_IF_TRUE: + if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) { + i++; + } + break; + case GSA_8_BIT_IF_FALSE: + if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) { + i++; + } + break; + case GSA_32_BIT_IF_FALSE: + if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) { + i++; + } + break; + case GSA_8_BIT_FILL: + { + u32 addr = cheatsList[i].address; + u8 v = cheatsList[i].value & 0xff; + u32 end = addr + (cheatsList[i].value >> 8); + do { + CPUWriteByte(addr, v); + addr++; + } while (addr <= end); + } + break; + case GSA_16_BIT_FILL: + { + u32 addr = cheatsList[i].address; + u16 v = cheatsList[i].value & 0xffff; + u32 end = addr + ((cheatsList[i].value >> 16) << 1); + do { + CPUWriteHalfWord(addr, v); + addr+=2; + } while (addr <= end); + } + break; + case GSA_8_BIT_IF_TRUE2: + if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) { + i+=2; + } + break; + case GSA_16_BIT_IF_TRUE2: + if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { + i+=2; + } + break; + case GSA_32_BIT_IF_TRUE2: + if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) { + i+=2; + } + break; + case GSA_8_BIT_IF_FALSE2: + if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) { + i+=2; + } + break; + case GSA_16_BIT_IF_FALSE2: + if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) { + i+=2; + } + break; + case GSA_32_BIT_IF_FALSE2: + if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) { + i+=2; + } + break; + case CBA_ADD: + if ((cheatsList[i].address & 1) == 0) { + CPUWriteHalfWord(cheatsList[i].address, + CPUReadHalfWord(cheatsList[i].address) + + cheatsList[i].value); + } else { + CPUWriteMemory(cheatsList[i].address & 0x0FFFFFFE, + CPUReadMemory(cheatsList[i].address & 0x0FFFFFFE) + + cheatsList[i].value); + } + break; + case CBA_OR: + CPUWriteHalfWord(cheatsList[i].address, + CPUReadHalfWord(cheatsList[i].address) | + cheatsList[i].value); + break; + case CBA_GT: + if (!(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value)){ + i++; + } + break; + case CBA_LT: + if (!(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value)){ + i++; + } + break; + case CBA_SUPER: + { + int count = 2*((cheatsList[i].value -1) & 0xFFFF)+1; + u32 address = cheatsList[i].address; + for(int x = 0; x <= count; x++) { + u8 b; + int res = x % 6; + if (res==0) + i++; + if(res < 4) + b = (cheatsList[i].address >> (24-8*res)) & 0xFF; + else + b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0xFF; + CPUWriteByte(address, b); + address++; + } + } + 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)) + { + 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)) + { + 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)) + { + CPUWriteMemory(CPUReadMemory(cheatsList[i].address), + cheatsList[i].value); + } + break; + case GSA_8_BIT_ADD : + CPUWriteByte(cheatsList[i].address, + (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); + break; + case GSA_32_BIT_ADD : + CPUWriteMemory(cheatsList[i].address , + 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))) { + i++; + } + break; + case GSA_16_BIT_IF_LOWER_U: + if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) { + i++; + } + break; + case GSA_32_BIT_IF_LOWER_U: + if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) { + i++; + } + break; + case GSA_8_BIT_IF_HIGHER_U: + if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) { + i++; + } + break; + case GSA_16_BIT_IF_HIGHER_U: + if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) { + i++; + } + break; + case GSA_32_BIT_IF_HIGHER_U: + if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) { + i++; + } + break; + case GSA_8_BIT_IF_AND: + if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) { + i++; + } + break; + case GSA_16_BIT_IF_AND: + if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) { + i++; + } + break; + case GSA_32_BIT_IF_AND: + if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) { + i++; + } + break; + case GSA_8_BIT_IF_LOWER_U2: + if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) { + i+=2; + } + break; + case GSA_16_BIT_IF_LOWER_U2: + if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) { + i+=2; + } + break; + case GSA_32_BIT_IF_LOWER_U2: + if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) { + i+=2; + } + break; + case GSA_8_BIT_IF_HIGHER_U2: + if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) { + i+=2; + } + break; + case GSA_16_BIT_IF_HIGHER_U2: + if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) { + i+=2; + } + break; + case GSA_32_BIT_IF_HIGHER_U2: + if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) { + i+=2; + } + break; + case GSA_8_BIT_IF_AND2: + if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) { + i+=2; + } + break; + case GSA_16_BIT_IF_AND2: + if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) { + i+=2; + } + break; + case GSA_32_BIT_IF_AND2: + if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) { + i+=2; + } + break; + case GSA_ALWAYS: + i++; + break; + case GSA_ALWAYS2: + i+=2; + break; + case GSA_8_BIT_IF_LOWER_S: + if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) { + i++; + } + break; + case GSA_16_BIT_IF_LOWER_S: + if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) { + i++; + } + break; + case GSA_32_BIT_IF_LOWER_S: + if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) { + i++; + } + break; + case GSA_8_BIT_IF_HIGHER_S: + if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) { + i++; + } + break; + case GSA_16_BIT_IF_HIGHER_S: + if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) { + i++; + } + break; + case GSA_32_BIT_IF_HIGHER_S: + if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) { + i++; + } + break; + case GSA_8_BIT_IF_LOWER_S2: + if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) { + i+=2; + } + break; + case GSA_16_BIT_IF_LOWER_S2: + if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) { + i+=2; + } + break; + case GSA_32_BIT_IF_LOWER_S2: + if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) { + i+=2; + } + break; + case GSA_8_BIT_IF_HIGHER_S2: + if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) { + i+=2; + } + break; + case GSA_16_BIT_IF_HIGHER_S2: + if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) { + i+=2; + } + break; + case GSA_32_BIT_IF_HIGHER_S2: + if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) { + i+=2; + } + break; + case GSA_16_BIT_WRITE_IOREGS: + if ((cheatsList[i].address <= 0x3FF) && (cheatsList[i].address != 0x6) && + (cheatsList[i].address != 0x130)) + ioMem[cheatsList[i].address & 0x3FE]=cheatsList[i].value & 0xFFFF; + break; + case GSA_32_BIT_WRITE_IOREGS: + if (cheatsList[i].address<=0x3FF) + { + if (((cheatsList[i].address & 0x3FC) != 0x6) && ((cheatsList[i].address & 0x3FC) != 0x130)) + ioMem[cheatsList[i].address & 0x3FC]= (cheatsList[i].value & 0xFFFF); + if ((((cheatsList[i].address & 0x3FC)+2) != 0x6) && ((cheatsList[i].address & 0x3FC) +2) != 0x130) + ioMem[(cheatsList[i].address & 0x3FC) + 2 ]= ((cheatsList[i].value>>16 ) & 0xFFFF); + } + break; + case GSA_8_BIT_IF_TRUE3: + if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) { + onoff=false; + } + break; + case GSA_16_BIT_IF_TRUE3: + if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { + onoff=false; + } + break; + case GSA_32_BIT_IF_TRUE3: + if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) { + onoff=false; + } + break; + case GSA_8_BIT_IF_FALSE3: + if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) { + onoff=false; + } + break; + case GSA_16_BIT_IF_FALSE3: + if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) { + onoff=false; + } + break; + case GSA_32_BIT_IF_FALSE3: + if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) { + onoff=false; + } + break; + case GSA_8_BIT_IF_LOWER_S3: + if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) { + onoff=false; + } + break; + case GSA_16_BIT_IF_LOWER_S3: + if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) { + onoff=false; + } + break; + case GSA_32_BIT_IF_LOWER_S3: + if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) { + onoff=false; + } + break; + case GSA_8_BIT_IF_HIGHER_S3: + if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) { + onoff=false; + } + break; + case GSA_16_BIT_IF_HIGHER_S3: + if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) { + onoff=false; + } + break; + case GSA_32_BIT_IF_HIGHER_S3: + if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) { + onoff=false; + } + break; + case GSA_8_BIT_IF_LOWER_U3: + if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) { + onoff=false; + } + break; + case GSA_16_BIT_IF_LOWER_U3: + if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) { + onoff=false; + } + break; + case GSA_32_BIT_IF_LOWER_U3: + if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) { + onoff=false; + } + break; + case GSA_8_BIT_IF_HIGHER_U3: + if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) { + onoff=false; + } + break; + case GSA_16_BIT_IF_HIGHER_U3: + if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) { + onoff=false; + } + break; + case GSA_32_BIT_IF_HIGHER_U3: + if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) { + onoff=false; } - } - break; - case GSA_8_BIT_IF_TRUE: - if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) { - i++; - } - break; - case GSA_32_BIT_IF_TRUE: - if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) { - i++; - } - break; - case GSA_8_BIT_IF_FALSE: - if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) { - i++; - } - break; - case GSA_32_BIT_IF_FALSE: - if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) { - i++; - } - break; - case GSA_8_BIT_FILL: - { - u32 addr = cheatsList[i].address; - u8 v = cheatsList[i].value & 0xff; - u32 end = addr + (cheatsList[i].value >> 8); - do { - CPUWriteByte(addr, v); - addr++; - } while (addr <= end); - } - break; - case GSA_16_BIT_FILL: - { - u32 addr = cheatsList[i].address; - u16 v = cheatsList[i].value & 0xffff; - u32 end = addr + ((cheatsList[i].value >> 16) << 1); - do { - CPUWriteHalfWord(addr, v); - addr+=2; - } while (addr <= end); - } - break; - case GSA_8_BIT_IF_TRUE2: - if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) { - i+=2; - } - break; - case GSA_16_BIT_IF_TRUE2: - if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { - i+=2; - } - break; - case GSA_32_BIT_IF_TRUE2: - if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) { - i+=2; - } - break; - case GSA_8_BIT_IF_FALSE2: - if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) { - i+=2; - } - break; - case GSA_16_BIT_IF_FALSE2: - if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) { - i+=2; - } - break; - case GSA_32_BIT_IF_FALSE2: - if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) { - i+=2; - } - break; - case GSA_SLOWDOWN: - // check if button was pressed and released, if so toggle our state - if((cheatsList[i].status & 4) && !(extended & 4)) - cheatsList[i].status ^= 1; - if(extended & 4) - cheatsList[i].status |= 4; - else - cheatsList[i].status &= ~4; - - if(cheatsList[i].status & 1) - ticks += 2*256*((cheatsList[i].value >> 8) & 255); - break; - case CBA_ADD: - CPUWriteHalfWord(cheatsList[i].address, - CPUReadHalfWord(cheatsList[i].address) + - (u16)cheatsList[i].value); - break; - case CBA_OR: - CPUWriteHalfWord(cheatsList[i].address, - CPUReadHalfWord(cheatsList[i].address) | - cheatsList[i].value); - break; - case CBA_LT: - if(CPUReadHalfWord(cheatsList[i].address) >= cheatsList[i].value) + break; + case GSA_8_BIT_IF_AND3: + if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) { + onoff=false; + } + break; + case GSA_16_BIT_IF_AND3: + if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) { + onoff=false; + } + break; + case GSA_32_BIT_IF_AND3: + if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) { + onoff=false; + } + break; + case GSA_ALWAYS3: + if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) { + onoff=false; + } + break; + case GSA_GROUP_WRITE: + { + int count = ((cheatsList[i].address) & 0xFFFE) +1; + u32 value = cheatsList[i].value; + if (count==0) + i++; + else + for (int x = 1; x <= count; x++) { + if ((x % 2) ==0){ + if (x> (24-8*res)) & 0xFF; - else - b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0x0FF; - CPUWriteByte(address, b); - address++; - if(x && !res) - i++; + break; + case GSA_16_BIT_IF_LOWER_OR_EQ_U: + if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) { + i++; } - if(count % 6) + break; + case GSA_16_BIT_IF_HIGHER_OR_EQ_U: + if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) { i++; + } + break; + case GSA_16_BIT_MIF_TRUE: + if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) { + i+=((cheatsList[i].rawaddress >> 0x10) & 0xFF); + } + break; + case GSA_16_BIT_MIF_FALSE: + if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) { + i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF; + } + break; + case GSA_16_BIT_MIF_LOWER_OR_EQ_U: + if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) { + i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF; + } + break; + case GSA_16_BIT_MIF_HIGHER_OR_EQ_U: + if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) { + i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF; + } + break; + case CHEATS_16_BIT_WRITE: + if ((cheatsList[i].address>>24)>=0x08) { + CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value); + } else { + CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value); + } + break; + case CHEATS_32_BIT_WRITE: + if ((cheatsList[i].address>>24)>=0x08) { + CHEAT_PATCH_ROM_32BIT(cheatsList[i].address, cheatsList[i].value); + } else { + CPUWriteMemory(cheatsList[i].address, cheatsList[i].value); + } + break; } - break; } } + for (i = 0; i<4; i++) + if (rompatch2addr [i] != 0) + CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2val [i]); return ticks; } void cheatsAdd(const char *codeStr, const char *desc, + u32 rawaddress, u32 address, u32 value, int code, @@ -543,6 +1336,7 @@ int x = cheatsNumber; cheatsList[x].code = code; cheatsList[x].size = size; + cheatsList[x].rawaddress = rawaddress; cheatsList[x].address = address; cheatsList[x].value = value; strcpy(cheatsList[x].codestring, codeStr); @@ -562,6 +1356,12 @@ case INT_32_BIT_WRITE: cheatsList[x].oldValue = CPUReadMemory(address); break; + case CHEATS_16_BIT_WRITE: + cheatsList[x].oldValue = CPUReadHalfWord(address); + break; + case CHEATS_32_BIT_WRITE: + cheatsList[x].oldValue = CPUReadMemory(address); + break; } cheatsNumber++; } @@ -583,6 +1383,19 @@ case INT_32_BIT_WRITE: CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue); break; + case CHEATS_16_BIT_WRITE: + if ((cheatsList[x].address>>24)>=0x08) { + CHEAT_PATCH_ROM_16BIT(cheatsList[x].address, cheatsList[x].oldValue); + } else { + CPUWriteHalfWord(cheatsList[x].address, cheatsList[x].oldValue); + } + break; + case CHEATS_32_BIT_WRITE: + if ((cheatsList[x].address>>24)>=0x08) { + CHEAT_PATCH_ROM_32BIT(cheatsList[x].address, cheatsList[x].oldValue); + } else { + CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue); + } case GSA_16_BIT_ROM_PATCH: if(cheatsList[x].status & 1) { cheatsList[x].status &= ~1; @@ -590,14 +1403,17 @@ cheatsList[x].oldValue); } break; - case GSA_16_BIT_ROM_PATCH2: + case GSA_16_BIT_ROM_PATCH2C: + case GSA_16_BIT_ROM_PATCH2D: + case GSA_16_BIT_ROM_PATCH2E: + case GSA_16_BIT_ROM_PATCH2F: if(cheatsList[x].status & 1) { cheatsList[x].status &= ~1; - CHEAT_PATCH_ROM_16BIT(((cheatsList[x].value & 0x00FFFFFF) << 1)+ - 0x8000000, - cheatsList[x].oldValue); } break; + case MASTER_CODE: + mastercode=0; + break; } } if((x+1) < cheatsNumber) { @@ -619,6 +1435,7 @@ { if(i >= 0 && i < cheatsNumber) { cheatsList[i].enabled = true; + mastercode = 0; } } @@ -633,14 +1450,17 @@ cheatsList[i].oldValue); } break; - case GSA_16_BIT_ROM_PATCH2: + case GSA_16_BIT_ROM_PATCH2C: + case GSA_16_BIT_ROM_PATCH2D: + case GSA_16_BIT_ROM_PATCH2E: + case GSA_16_BIT_ROM_PATCH2F: if(cheatsList[i].status & 1) { cheatsList[i].status &= ~1; - CHEAT_PATCH_ROM_16BIT(((cheatsList[i].value & 0x00FFFFFF) << 1)+ - 0x8000000, - cheatsList[i].oldValue); } break; + case MASTER_CODE: + mastercode=0; + break; } cheatsList[i].enabled = false; } @@ -648,7 +1468,7 @@ bool cheatsVerifyCheatCode(const char *code, const char *desc) { - int len = strlen(code); + size_t len = strlen(code); if(len != 11 && len != 13 && len != 17) { systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code); return false; @@ -659,7 +1479,7 @@ return false; } - int i; + size_t i; for(i = 0; i < 8; i++) { if(!CHEAT_IS_HEX(code[i])) { // wrong cheat @@ -686,8 +1506,18 @@ sscanf(buffer, "%x", &address); switch(address >> 24) { - case 2: - case 3: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: break; default: systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS, @@ -700,10 +1530,10 @@ sscanf(buffer, "%x", &value); int type = 0; if(len == 13) - type = 1; + type = 114; if(len == 17) - type = 2; - cheatsAdd(code, desc, address, value, type, type); + type = 115; + cheatsAdd(code, desc, address, address, value, type, type); return true; } @@ -712,11 +1542,46 @@ cheatsVerifyCheatCode(code, desc); } -void cheatsDecryptGSACode(u32& address, u32& value, bool v3) +u16 cheatsGSAGetDeadface(bool v3) +{ + for(int i = cheatsNumber-1; i >= 0; i--) + if ((cheatsList[i].address == 0xDEADFACE) && (cheatsList[i].code == (v3 ? 257 : 256))) + return cheatsList[i].value & 0xFFFF; + return 0; +} + +void cheatsGSAChangeEncryption(u16 value, bool v3) { + int i; + u8 *deadtable1, *deadtable2; + + if (v3) { + deadtable1 = (u8*)(&v3_deadtable1); + deadtable2 = (u8*)(&v3_deadtable2); + for (i = 0; i < 4; i++) + seeds_v3[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2); + } + else { + deadtable1 = (u8*)(&v1_deadtable1); + deadtable2 = (u8*)(&v1_deadtable2); + for (i = 0; i < 4; i++){ + seeds_v1[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2); + } + } +} + +u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2) { + int i; + u32 newseed = 0; + + for (i = 0; i < 4; i++) + newseed = ((newseed << 8) | ((deadtable1[(i + upper) & 0xFF] + deadtable2[seed]) & 0xFF)); + + return newseed; +} + +void cheatsDecryptGSACode(u32& address, u32& value, bool v3) { u32 rollingseed = 0xC6EF3720; - u32 seeds_v1[] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 }; - u32 seeds_v3[] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 }; u32 *seeds = v3 ? seeds_v3 : seeds_v1; int bitsleft = 32; @@ -758,7 +1623,7 @@ buffer[8] = 0; u32 value; sscanf(buffer, "%x", &value); - + cheatsGSAChangeEncryption(cheatsGSAGetDeadface (v3), v3); cheatsDecryptGSACode(address, value, v3); if(value == 0x1DC0DE) { @@ -773,17 +1638,26 @@ systemMessage(MSG_GBA_CODE_WARNING, N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."), buffer, buffer2); } - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, v3 ? 257 : 256, + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, v3 ? 257 : 256, UNKNOWN_CODE); return; } if(isMultilineWithData(cheatsNumber-1)) { - cheatsAdd(code, desc, address, value, v3 ? 257 : 256, UNKNOWN_CODE); + cheatsAdd(code, desc, address, address, value, v3 ? 257 : 256, UNKNOWN_CODE); return; } if(v3) { - int type = (address >> 25) & 127; + int type = ((address >> 25) & 127) | ((address >> 17) & 0x80); u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF); + u16 mcode = (address>>24 & 0xFF); + + if ((mcode & 0xFE) == 0xC4) + { + cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | (0x08000000), + value, 257, MASTER_CODE); + mastercode = (address & 0x1FFFFFF) | (0x08000000); + } + else switch(type) { case 0x00: if(address == 0) { @@ -791,83 +1665,278 @@ addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF); switch(type) { case 0x04: - cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN); + cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN); break; case 0x08: - cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_GS_WRITE2); + cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_GS_WRITE2); break; case 0x09: - cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_GS_WRITE2); + cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_GS_WRITE2); break; case 0x0a: - cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_GS_WRITE2); + cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_GS_WRITE2); break; case 0x0c: + cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2C); + break; case 0x0d: + cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2D); + break; case 0x0e: + cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2E); + break; case 0x0f: - cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2); + cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2F); + break; + case 0x20: + cheatsAdd(code, desc, address, 0, addr, 257, GSA_CODES_ON); break; case 0x40: - cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_SLIDE); + cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_SLIDE); break; case 0x41: - cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_SLIDE); + cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_SLIDE); break; case 0x42: - cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_SLIDE); + cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_SLIDE); break; default: - cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE); + cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE); break; } } else - cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_FILL); + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_FILL); break; case 0x01: - cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_FILL); + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_FILL); break; case 0x02: - cheatsAdd(code, desc, addr, value, 257, INT_32_BIT_WRITE); + cheatsAdd(code, desc, address, addr, value, 257, INT_32_BIT_WRITE); break; case 0x04: - cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE); + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE); break; case 0x05: - cheatsAdd(code, desc, addr, value, 257, CBA_IF_TRUE); + cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_TRUE); break; case 0x06: - cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE); + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE); + break; + case 0x07: + cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS); break; case 0x08: - cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE); + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE); break; case 0x09: - cheatsAdd(code, desc, addr, value, 257, CBA_IF_FALSE); + cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_FALSE); break; case 0x0a: - cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE); + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE); + break; + case 0xc: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S); + break; + case 0xd: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S); + break; + case 0xe: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S); + break; + case 0x10: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S); + break; + case 0x11: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S); + break; + case 0x12: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S); + break; + case 0x14: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U); + break; + case 0x15: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U); + break; + case 0x16: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U); + break; + case 0x18: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U); + break; + case 0x19: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U); + break; + case 0x1A: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U); + break; + case 0x1C: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND); + break; + case 0x1D: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND); + break; + case 0x1E: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND); + break; + case 0x20: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_POINTER); + break; + case 0x21: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_POINTER); + break; + case 0x22: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_POINTER); break; case 0x24: - cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE2); + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE2); break; case 0x25: - cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_TRUE2); + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE2); break; case 0x26: - cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE2); + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE2); + break; + case 0x27: + cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS2); break; case 0x28: - cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE2); + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE2); break; case 0x29: - cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_FALSE2); + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE2); break; case 0x2a: - cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE2); + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE2); + break; + case 0x2c: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S2); + break; + case 0x2d: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S2); + break; + case 0x2e: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S2); + break; + case 0x30: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S2); + break; + case 0x31: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S2); + break; + case 0x32: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S2); + break; + case 0x34: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U2); + break; + case 0x35: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U2); + break; + case 0x36: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U2); + break; + case 0x38: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U2); + break; + case 0x39: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U2); + break; + case 0x3A: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U2); + break; + case 0x3C: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND2); + break; + case 0x3D: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND2); + break; + case 0x3E: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND2); + break; + case 0x40: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_ADD); + break; + case 0x41: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_ADD); + break; + case 0x42: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_ADD); + break; + case 0x44: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE3); + break; + case 0x45: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE3); + break; + case 0x46: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE3); + break; + case 0x47: + cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS3); + break; + case 0x48: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE3); + break; + case 0x49: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE3); + break; + case 0x4a: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE3); + break; + case 0x4c: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S3); + break; + case 0x4d: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S3); + break; + case 0x4e: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S3); + break; + case 0x50: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S3); + break; + case 0x51: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S3); + break; + case 0x52: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S3); + break; + case 0x54: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U3); + break; + case 0x55: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U3); + break; + case 0x56: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U3); + break; + case 0x58: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U3); + break; + case 0x59: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U3); + break; + case 0x5a: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U3); + break; + case 0x5c: + cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND3); + break; + case 0x5d: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND3); + break; + case 0x5e: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND3); + break; + case 0x63: + cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_WRITE_IOREGS); + break; + case 0xE3: + cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_WRITE_IOREGS); break; default: - cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE); + cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE); break; } } else { @@ -876,54 +1945,136 @@ case 0: case 1: case 2: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, type); + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, type); + break; + case 3: + switch ((address >> 0x10) & 0xFF){ + case 0x00: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_GROUP_WRITE); + break; + case 0x10: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFF, 256, GSA_32_BIT_ADD ); + break; + case 0x20: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFF)+1), 256, GSA_32_BIT_ADD ); + break; + case 0x30: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, GSA_32_BIT_ADD ); + break; + case 0x40: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFFFF)+1), 256, GSA_32_BIT_ADD ); + break; + case 0x50: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_ADD2); + break; + case 0x60: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_SUB2); + break; + default: + // unsupported code + cheatsAdd(code, desc, address, address, value, 256, + UNKNOWN_CODE); + break; + } break; case 6: address <<= 1; - type = (address >> 28) & 15; - if(type == 0x0c) { - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, + type = (value >> 24) & 0xFF; + if(type == 0x00) { + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256, GSA_16_BIT_ROM_PATCH); break; } // unsupported code - cheatsAdd(code, desc, address, value, 256, + cheatsAdd(code, desc, address, address, value, 256, UNKNOWN_CODE); break; case 8: switch((address >> 20) & 15) { case 1: - cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, + cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256, GSA_8_BIT_GS_WRITE); break; case 2: - cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, + cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256, GSA_16_BIT_GS_WRITE); break; - case 3: - cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256, + case 4: + // This code is buggy : the value is always set to 0 ! + cheatsAdd(code, desc, address, address & 0x0F0FFFFF, 0, 256, GSA_32_BIT_GS_WRITE); + break; case 15: - cheatsAdd(code, desc, 0, value & 0xFF00, 256, GSA_SLOWDOWN); + cheatsAdd(code, desc, address, 0, value & 0xFFFF, 256, GSA_SLOWDOWN); break; default: // unsupported code - cheatsAdd(code, desc, address, value, 256, + cheatsAdd(code, desc, address, address, value, 256, UNKNOWN_CODE); break; } break; case 0x0d: if(address != 0xDEADFACE) { - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, + switch((value >> 20) & 0xF) { + case 0: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256, CBA_IF_TRUE); + break; + case 1: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256, + CBA_IF_FALSE); + break; + case 2: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256, + GSA_16_BIT_IF_LOWER_OR_EQ_U); + break; + case 3: + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256, + GSA_16_BIT_IF_HIGHER_OR_EQ_U); + break; + default: + // unsupported code + cheatsAdd(code, desc, address, address, value, 256, + UNKNOWN_CODE); + break; + } } else - cheatsAdd(code, desc, address, value, 256, + cheatsAdd(code, desc, address, address, value, 256, UNKNOWN_CODE); break; - default: + case 0x0e: + switch((value >> 28) & 0xF) { + case 0: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, + GSA_16_BIT_MIF_TRUE); + break; + case 1: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, + GSA_16_BIT_MIF_FALSE); + break; + case 2: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, + GSA_16_BIT_MIF_LOWER_OR_EQ_U); + break; + case 3: + cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, + GSA_16_BIT_MIF_HIGHER_OR_EQ_U); + break; + default: + // unsupported code + cheatsAdd(code, desc, address, address, value, 256, + UNKNOWN_CODE); + break; + } + break; + case 0x0f: + cheatsAdd(code, desc, address, (address & 0xFFFFFFF), value, 256, MASTER_CODE); + mastercode = (address & 0xFFFFFFF); + break; + default: // unsupported code - cheatsAdd(code, desc, address, value, 256, + cheatsAdd(code, desc, address, address, value, 256, UNKNOWN_CODE); break; } @@ -1359,7 +2510,7 @@ u32 seed[8]; cheatsCBAParseSeedCode(address, value, seed); cheatsCBAChangeEncryption(seed); - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE); + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE); } else { if(cheatsCBAShouldDecrypt()) cheatsCBADecrypt(array); @@ -1369,8 +2520,10 @@ int type = (address >> 28) & 15; - if(isMultilineWithData(cheatsNumber-1)) { - cheatsAdd(code, desc, address, value, 512, UNKNOWN_CODE); + if(isMultilineWithData(cheatsNumber-1) || (super>0)) { + cheatsAdd(code, desc, address, address, value, 512, UNKNOWN_CODE); + if (super>0) + super-= 1; return; } @@ -1384,61 +2537,71 @@ systemMessage(MSG_CBA_CODE_WARNING, N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly.")); } - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE); } break; + case 0x01: + cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | 0x08000000, value, 512, MASTER_CODE); + mastercode = (address & 0x1FFFFFF) | 0x08000000; + break; case 0x02: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, CBA_OR); break; case 0x03: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, INT_8_BIT_WRITE); break; case 0x04: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, CBA_SLIDE_CODE); break; case 0x05: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, - CBA_SUPER); + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, + CBA_SUPER); + super = getCodeLength(cheatsNumber-1); break; case 0x06: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, CBA_AND); break; case 0x07: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, CBA_IF_TRUE); break; case 0x08: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, INT_16_BIT_WRITE); break; case 0x0a: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, CBA_IF_FALSE); break; case 0x0b: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, - CBA_LT); + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, + CBA_GT); break; case 0x0c: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, - CBA_GT); + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, + CBA_LT); break; case 0x0d: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + if ((address & 0xF0)<0x30) + cheatsAdd(code, desc, address, address & 0xF0, value, 512, CBA_IF_KEYS_PRESSED); break; case 0x0e: - cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0x8000 ? value | 0xFFFF0000 : value, 512, CBA_ADD); break; + case 0x0f: + cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512, + GSA_16_BIT_IF_AND); + break; default: // unsupported code - cheatsAdd(code, desc, address & 0xFFFFFFFF, value, 512, + cheatsAdd(code, desc, address, address & 0xFFFFFFFF, value, 512, UNKNOWN_CODE); break; } @@ -1452,17 +2615,33 @@ utilGzWrite(file, cheatsList, sizeof(cheatsList)); } -void cheatsReadGame(gzFile file) +void cheatsReadGame(gzFile file, int version) { cheatsNumber = 0; cheatsNumber = utilReadInt(file); - utilGzRead(file, cheatsList, sizeof(cheatsList)); + if (version > 8) + utilGzRead(file, cheatsList, sizeof(cheatsList)); + bool firstCodeBreaker = true; for(int i = 0; i < cheatsNumber; i++) { + if (version <9) + { + cheatsList[i].code = utilReadInt(file); + cheatsList[i].size = utilReadInt(file); + cheatsList[i].status = utilReadInt(file); + cheatsList[i].enabled = utilReadInt(file) ? true : false; + utilGzRead(file, &cheatsList[i].address, sizeof(u32)); + cheatsList[i].rawaddress = cheatsList[i].address; + utilGzRead(file, &cheatsList[i].value, sizeof(u32)); + utilGzRead(file, &cheatsList[i].oldValue, sizeof(u32)); + utilGzRead(file, &cheatsList[i].codestring, 20*sizeof(char)); + utilGzRead(file, &cheatsList[i].desc, 32*sizeof(char)); + } + cheatsList[i].status = 0; if(!cheatsList[i].codestring[0]) { switch(cheatsList[i].size) { @@ -1515,7 +2694,7 @@ return; int version = 1; fwrite(&version, 1, sizeof(version), f); - int type = 0; + int type = 1; fwrite(&type, 1, sizeof(type), f); fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f); fwrite(cheatsList, 1, sizeof(cheatsList), f); @@ -1524,7 +2703,6 @@ bool cheatsLoadCheatList(const char *file) { - cheatsNumber = 0; int count = 0; @@ -1553,7 +2731,8 @@ return false; } - if(type != 0) { + + if((type != 0) && (type != 1)) { systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, N_("Unsupported cheat list type %d"), type); fclose(f); @@ -1564,10 +2743,31 @@ fclose(f); return false; } - - if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) { - fclose(f); - return false; + if (type == 1) + { + if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) { + fclose(f); + return false; + } + } + else if (type == 0) + { + for(int i = 0; i < count; i++) { + fread(&cheatsList[i].code, 1, sizeof(int),f); + fread(&cheatsList[i].size, 1, sizeof(int),f); + fread(&cheatsList[i].status, 1, sizeof(int),f); + fread(&cheatsList[i].enabled, 1, sizeof(int),f); + cheatsList[i].enabled = cheatsList[i].enabled ? true : false; + fread(&cheatsList[i].address, 1, sizeof(u32),f); + cheatsList[i].rawaddress = cheatsList[i].address; + fread(&cheatsList[i].value, 1, sizeof(u32),f); + fread(&cheatsList[i].oldValue, 1, sizeof(u32),f); + fread(&cheatsList[i].codestring, 1, 20*sizeof(char),f); + if(fread(&cheatsList[i].desc, 1, 32*sizeof(char),f) != 32*sizeof(char)) { + fclose(f); + return false; + } + } } bool firstCodeBreaker = true; @@ -1615,59 +2815,80 @@ return true; } -extern int *extCpuLoopTicks; -extern int *extClockTicks; -extern int *extTicks; -extern int cpuSavedTicks; - -extern void debuggerBreakOnWrite(u32 *, u32, u32, int); - -#define CPU_BREAK_LOOP \ - cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks;\ - *extCpuLoopTicks = *extClockTicks;\ - *extTicks = *extClockTicks; +extern int cpuNextEvent; + +extern void debuggerBreakOnWrite(u32 , u32, u32, int, int); + +static u8 cheatsGetType(u32 address) +{ + switch(address >> 24) { + case 2: + return freezeWorkRAM[address & 0x3FFFF]; + case 3: + return freezeInternalRAM[address & 0x7FFF]; + case 5: + return freezePRAM[address & 0x3FC]; + case 6: + if (address > 0x06010000) + return freezeVRAM[address & 0x17FFF]; + else + return freezeVRAM[address & 0x1FFFF]; + case 7: + return freezeOAM[address & 0x3FC]; + } + return 0; +} -void cheatsWriteMemory(u32 *address, u32 value, u32 mask) +void cheatsWriteMemory(u32 address, u32 value) { #ifdef BKPT_SUPPORT #ifdef SDL if(cheatsNumber == 0) { - debuggerBreakOnWrite(address, *address, value, 2); - CPU_BREAK_LOOP; - *address = value; - return; + int type = cheatsGetType(address); + u32 oldValue = debuggerReadMemory(address); + if(type == 1 || (type == 2 && oldValue != value)) { + debuggerBreakOnWrite(address, oldValue, value, 2, type); + cpuNextEvent = 0; + } + debuggerWriteMemory(address, value); } #endif #endif } -void cheatsWriteHalfWord(u16 *address, u16 value, u16 mask) +void cheatsWriteHalfWord(u32 address, u16 value) { #ifdef BKPT_SUPPORT #ifdef SDL if(cheatsNumber == 0) { - debuggerBreakOnWrite((u32 *)address, *address, value, 1); - CPU_BREAK_LOOP; - *address = value; - return; + int type = cheatsGetType(address); + u16 oldValue = debuggerReadHalfWord(address); + if(type == 1 || (type == 2 && oldValue != value)) { + debuggerBreakOnWrite(address, oldValue, value, 1, type); + cpuNextEvent = 0; + } + debuggerWriteHalfWord(address, value); } #endif #endif } #if defined BKPT_SUPPORT && defined SDL -void cheatsWriteByte(u8 *address, u8 value) +void cheatsWriteByte(u32 address, u8 value) #else -void cheatsWriteByte(u8 *, u8) +void cheatsWriteByte(u32, u8) #endif { #ifdef BKPT_SUPPORT #ifdef SDL if(cheatsNumber == 0) { - debuggerBreakOnWrite((u32 *)address, *address, value, 0); - CPU_BREAK_LOOP; - *address = value; - return; + int type = cheatsGetType(address); + u8 oldValue = debuggerReadByte(address); + if(type == 1 || (type == 2 && oldValue != value)) { + debuggerBreakOnWrite(address, oldValue, value, 0, type); + cpuNextEvent = 0; + } + debuggerWriteByte(address, value); } #endif #endif diff -urN ../VisualBoyAdvance-1.7.2/src/Cheats.h ./src/Cheats.h --- ../VisualBoyAdvance-1.7.2/src/Cheats.h 2004-05-13 23:06:42 +0900 +++ ./src/Cheats.h 2006-04-30 23:35:35 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -25,6 +25,7 @@ int size; int status; bool enabled; + u32 rawaddress; u32 address; u32 value; u32 oldValue; @@ -32,7 +33,7 @@ char desc[32]; }; -extern void cheatsAdd(const char *,const char *,u32,u32,int,int); +extern void cheatsAdd(const char *,const char *,u32, u32,u32,int,int); extern void cheatsAddCheatCode(const char *code, const char *desc); extern void cheatsAddGSACode(const char *code, const char *desc, bool v3); extern void cheatsAddCBACode(const char *code, const char *desc); @@ -42,12 +43,12 @@ extern void cheatsEnable(int number); extern void cheatsDisable(int number); extern void cheatsSaveGame(gzFile file); -extern void cheatsReadGame(gzFile file); +extern void cheatsReadGame(gzFile file, int version); extern void cheatsSaveCheatList(const char *file); extern bool cheatsLoadCheatList(const char *file); -extern void cheatsWriteMemory(u32 *, u32, u32); -extern void cheatsWriteHalfWord(u16 *, u16, u16); -extern void cheatsWriteByte(u8 *, u8); +extern void cheatsWriteMemory(u32, u32); +extern void cheatsWriteHalfWord(u32, u16); +extern void cheatsWriteByte(u32, u8); extern int cheatsCheckKeys(u32,u32); extern int cheatsNumber; extern CheatsData cheatsList[100]; diff -urN ../VisualBoyAdvance-1.7.2/src/EEprom.cpp ./src/EEprom.cpp --- ../VisualBoyAdvance-1.7.2/src/EEprom.cpp 2004-05-13 23:38:22 +0900 +++ ./src/EEprom.cpp 2005-06-25 15:15:34 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -16,6 +16,7 @@ // 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 "GBA.h" #include "EEprom.h" #include "Util.h" @@ -42,6 +43,11 @@ { NULL, 0 } }; +void eepromInit() +{ + memset(eepromData, 255, sizeof(eepromData)); +} + void eepromReset() { eepromMode = EEPROM_IDLE; diff -urN ../VisualBoyAdvance-1.7.2/src/EEprom.h ./src/EEprom.h --- ../VisualBoyAdvance-1.7.2/src/EEprom.h 2004-05-13 23:06:31 +0900 +++ ./src/EEprom.h 2006-06-07 06:04:20 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -20,10 +20,11 @@ #ifndef VBA_EEPROM_H #define VBA_EEPROM_H -extern void eepromSaveGame(gzFile gzFile); -extern void eepromReadGame(gzFile gzFile, int version); +extern void eepromSaveGame(gzFile _gzFile); +extern void eepromReadGame(gzFile _gzFile, int version); extern int eepromRead(u32 address); extern void eepromWrite(u32 address, u8 value); +extern void eepromInit(); extern void eepromReset(); extern u8 eepromData[0x2000]; extern bool eepromInUse; diff -urN ../VisualBoyAdvance-1.7.2/src/Flash.cpp ./src/Flash.cpp --- ../VisualBoyAdvance-1.7.2/src/Flash.cpp 2004-05-13 23:38:11 +0900 +++ ./src/Flash.cpp 2006-04-30 23:36:24 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -67,6 +67,11 @@ { NULL, 0 } }; +void flashInit() +{ + memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); +} + void flashReset() { flashState = FLASH_READ_ARRAY; @@ -95,7 +100,6 @@ void flashSetSize(int size) { // log("Setting flash size to %d\n", size); - flashSize = size; if(size == 0x10000) { flashDeviceID = 0x1b; flashManufacturerID = 0x32; @@ -103,6 +107,11 @@ flashDeviceID = 0x13; //0x09; flashManufacturerID = 0x62; //0xc2; } + // Added to make 64k saves compatible with 128k ones + // (allow wrongfuly set 64k saves to work for Pokemon games) + if ((size == 0x20000) && (flashSize == 0x10000)) + memcpy((u8 *)(flashSaveMemory+0x10000), (u8 *)(flashSaveMemory), 0x10000); + flashSize = size; } u8 flashRead(u32 address) @@ -146,6 +155,13 @@ (*cpuSaveGameFunc)(address, byte); } +void flashDelayedWrite(u32 address, u8 byte) +{ + saveType = 2; + cpuSaveGameFunc = flashWrite; + flashWrite(address, byte); +} + void flashWrite(u32 address, u8 byte) { // log("Writing %02x at %08x\n", byte, address); diff -urN ../VisualBoyAdvance-1.7.2/src/Flash.h ./src/Flash.h --- ../VisualBoyAdvance-1.7.2/src/Flash.h 2004-05-13 23:05:20 +0900 +++ ./src/Flash.h 2006-06-07 06:04:20 +0900 @@ -20,14 +20,16 @@ #ifndef VBA_FLASH_H #define VBA_FLASH_H -extern void flashSaveGame(gzFile gzFile); -extern void flashReadGame(gzFile gzFile, int version); +extern void flashSaveGame(gzFile _gzFile); +extern void flashReadGame(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]; extern void flashSaveDecide(u32 address, u8 byte); extern void flashReset(); extern void flashSetSize(int size); +extern void flashInit(); extern int flashSize; #endif // VBA_FLASH_H diff -urN ../VisualBoyAdvance-1.7.2/src/GBA.cpp ./src/GBA.cpp --- ../VisualBoyAdvance-1.7.2/src/GBA.cpp 2004-05-13 23:37:59 +0900 +++ ./src/GBA.cpp 2006-08-25 23:13:38 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -42,32 +42,51 @@ #include "prof/prof.h" #endif -#define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value) +#define UPDATE_REG(address, value)\ + {\ + WRITE16LE(((u16 *)&ioMem[address]),value);\ + }\ + +#define ARM_PREFETCH \ + {\ + cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);\ + cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);\ + } + +#define THUMB_PREFETCH \ + {\ + cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);\ + cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);\ + } + +#define ARM_PREFETCH_NEXT \ + cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4); + +#define THUMB_PREFETCH_NEXT\ + cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2); #ifdef __GNUC__ #define _stricmp strcasecmp #endif -#define CPU_BREAK_LOOP \ - cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks;\ - *extCpuLoopTicks = *extClockTicks; - -#define CPU_BREAK_LOOP_2 \ - cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks;\ - *extCpuLoopTicks = *extClockTicks;\ - *extTicks = *extClockTicks; extern int emulating; +int SWITicks = 0; +int IRQTicks = 0; +u32 mastercode = 0; +int layerEnableDelay = 0; +bool busPrefetch = false; +bool busPrefetchEnable = false; +u32 busPrefetchCount = 0; int cpuDmaTicksToUpdate = 0; int cpuDmaCount = 0; -bool cpuDmaHack = 0; +bool cpuDmaHack = false; u32 cpuDmaLast = 0; int dummyAddress = 0; -int *extCpuLoopTicks = NULL; -int *extClockTicks = NULL; -int *extTicks = NULL; +bool cpuBreakLoop = false; +int cpuNextEvent = 0; int gbaSaveType = 0; // used to remember the save type on reset bool intState = false; @@ -79,29 +98,42 @@ bool cpuEEPROMEnabled = true; bool cpuEEPROMSensorEnabled = false; +u32 cpuPrefetch[2]; + +int cpuTotalTicks = 0; #ifdef PROFILING int profilingTicks = 0; int profilingTicksReload = 0; -static char *profilBuffer = NULL; -static int profilSize = 0; -static u32 profilLowPC = 0; -static int profilScale = 0; -#endif -bool freezeWorkRAM[0x40000]; -bool freezeInternalRAM[0x8000]; -int lcdTicks = 960; +static profile_segment *profilSegment = NULL; +#endif + +#ifdef BKPT_SUPPORT +u8 freezeWorkRAM[0x40000]; +u8 freezeInternalRAM[0x8000]; +u8 freezeVRAM[0x18000]; +u8 freezePRAM[0x400]; +u8 freezeOAM[0x400]; +bool debugger_last; +#endif + +int lcdTicks = (useBios && !skipBios) ? 1008 : 208; +u8 timerOnOffDelay = 0; +u16 timer0Value = 0; bool timer0On = false; int timer0Ticks = 0; int timer0Reload = 0; int timer0ClockReload = 0; +u16 timer1Value = 0; bool timer1On = false; int timer1Ticks = 0; int timer1Reload = 0; int timer1ClockReload = 0; +u16 timer2Value = 0; bool timer2On = false; int timer2Ticks = 0; int timer2Reload = 0; int timer2ClockReload = 0; +u16 timer3Value = 0; bool timer3On = false; int timer3Ticks = 0; int timer3Reload = 0; @@ -129,62 +161,38 @@ int captureNumber = 0; const int TIMER_TICKS[4] = { - 1, - 64, - 256, - 1024 -}; - -const int thumbCycles[] = { -// 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 4 - 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 5 - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 6 - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 7 - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 8 - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 9 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // a - 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, // b - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, // d - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // e - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // f + 0, + 6, + 8, + 10 }; -const int gamepakRamWaitState[4] = { 4, 3, 2, 8 }; -const int gamepakWaitState[8] = { 4, 3, 2, 8, 4, 3, 2, 8 }; -const int gamepakWaitState0[8] = { 2, 2, 2, 2, 1, 1, 1, 1 }; -const int gamepakWaitState1[8] = { 4, 4, 4, 4, 1, 1, 1, 1 }; -const int gamepakWaitState2[8] = { 8, 8, 8, 8, 1, 1, 1, 1 }; +const u32 objTilesAddress [3] = {0x010000, 0x014000, 0x014000}; +const u8 gamepakRamWaitState[4] = { 4, 3, 2, 8 }; +const u8 gamepakWaitState[4] = { 4, 3, 2, 8 }; +const u8 gamepakWaitState0[2] = { 2, 1 }; +const u8 gamepakWaitState1[2] = { 4, 1 }; +const u8 gamepakWaitState2[2] = { 8, 1 }; +const bool isInRom [16]= + { false, false, false, false, false, false, false, false, + true, true, true, true, true, true, false, false }; -int memoryWait[16] = +u8 memoryWait[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 }; -int memoryWait32[16] = - { 0, 0, 9, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 0 }; -int memoryWaitSeq[16] = +u8 memoryWait32[16] = + { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 }; +u8 memoryWaitSeq[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 }; -int memoryWaitSeq32[16] = - { 2, 0, 3, 0, 0, 2, 2, 0, 4, 4, 8, 8, 16, 16, 8, 0 }; -int memoryWaitFetch[16] = - { 3, 0, 3, 0, 0, 1, 1, 0, 4, 4, 4, 4, 4, 4, 4, 0 }; -int memoryWaitFetch32[16] = - { 6, 0, 6, 0, 0, 2, 2, 0, 8, 8, 8, 8, 8, 8, 8, 0 }; - -const int cpuMemoryWait[16] = { - 0, 0, 2, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 0, 0 -}; -const int cpuMemoryWait32[16] = { - 0, 0, 3, 0, 0, 0, 0, 0, - 3, 3, 3, 3, 3, 3, 0, 0 -}; - -const bool memory32[16] = - { true, false, false, true, true, false, false, true, false, false, false, false, false, false, true, false}; +u8 memoryWaitSeq32[16] = + { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 }; + +// The videoMemoryWait constants are used to add some waitstates +// if the opcode access video memory data outside of vblank/hblank +// It seems to happen on only one ticks for each pixel. +// Not used for now (too problematic with current code). +//const u8 videoMemoryWait[16] = +// {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + u8 biosProtected[4]; @@ -320,7 +328,6 @@ 0xE3A00001, 0xE3A01001, 0xE92D4010, -0xE3A0C301, 0xE3A03000, 0xE3A04001, 0xE3500000, @@ -330,11 +337,12 @@ 0x0AFFFFFC, 0xE8BD4010, 0xE12FFF1E, +0xE3A0C301, 0xE5CC3208, 0xE15C20B8, 0xE0110002, -0x10200002, -0x114C00B8, +0x10222000, +0x114C20B8, 0xE5CC4208, 0xE12FFF1E, 0xE92D500F, @@ -487,16 +495,12 @@ { NULL, 0 } }; -//int cpuLoopTicks = 0; -int cpuSavedTicks = 0; +static int romSize = 0x2000000; #ifdef PROFILING -void cpuProfil(char *buf, int size, u32 lowPC, int scale) +void cpuProfil(profile_segment *seg) { - profilBuffer = buf; - profilSize = size; - profilLowPC = lowPC; - profilScale = scale; + profilSegment = seg; } void cpuEnableProfiling(int hz) @@ -508,26 +512,211 @@ } #endif -inline int CPUUpdateTicksAccess32(u32 address) + +// Waitstates when accessing data +inline int dataTicksAccess16(u32 address) // DATA 8/16bits NON SEQ { - return memoryWait32[(address>>24)&15]; + int addr = (address>>24)&15; + int value = memoryWait[addr]; + + if ((addr>=0x08) || (addr < 0x02)) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (!waitState) + waitState = 1; + busPrefetchCount = ((++busPrefetchCount)<>24)&15]; + int addr = (address>>24)&15; + int value = memoryWait32[addr]; + + if ((addr>=0x08) || (addr < 0x02)) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (!waitState) + waitState = 1; + busPrefetchCount = ((++busPrefetchCount)<>24)&15]; + int addr = (address>>24)&15; + int value = memoryWaitSeq[addr]; + + if ((addr>=0x08) || (addr < 0x02)) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (!waitState) + waitState = 1; + busPrefetchCount = ((++busPrefetchCount)<>24)&15; + int value = memoryWaitSeq32[addr]; + + if ((addr>=0x08) || (addr < 0x02)) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (!waitState) + waitState = 1; + busPrefetchCount = ((++busPrefetchCount)<>24)&15]; + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + if (busPrefetchCount&0x2) + { + busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return memoryWaitSeq[addr]-1; + } + else + { + busPrefetchCount=0; + return memoryWait[addr]; + } + } + else + { + busPrefetchCount = 0; + return memoryWait[addr]; + } +} + +inline int codeTicksAccess32(u32 address) // ARM NON SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + if (busPrefetchCount&0x2) + { + busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return memoryWaitSeq[addr] - 1; + } + else + { + busPrefetchCount = 0; + return memoryWait32[addr]; + } + } + else + { + busPrefetchCount = 0; + return memoryWait32[addr]; + } +} + +inline int codeTicksAccessSeq16(u32 address) // THUMB SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + else + if (busPrefetchCount>0xFF) + { + busPrefetchCount=0; + return memoryWait[addr]; + } + else + return memoryWaitSeq[addr]; + } + else + { + busPrefetchCount = 0; + return memoryWaitSeq[addr]; + } +} + +inline int codeTicksAccessSeq32(u32 address) // ARM SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + if (busPrefetchCount&0x2) + { + busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return memoryWaitSeq[addr]; + } + else + if (busPrefetchCount>0xFF) + { + busPrefetchCount=0; + return memoryWait32[addr]; + } + else + return memoryWaitSeq32[addr]; + } + else + { + return memoryWaitSeq32[addr]; + } } + inline int CPUUpdateTicks() { int cpuLoopTicks = lcdTicks; @@ -535,7 +724,7 @@ if(soundTicks < cpuLoopTicks) cpuLoopTicks = soundTicks; - if(timer0On && !(TM0CNT & 4) && (timer0Ticks < cpuLoopTicks)) { + if(timer0On && (timer0Ticks < cpuLoopTicks)) { cpuLoopTicks = timer0Ticks; } if(timer1On && !(TM1CNT & 4) && (timer1Ticks < cpuLoopTicks)) { @@ -554,7 +743,17 @@ } } #endif - cpuSavedTicks = cpuLoopTicks; + + if (SWITicks) { + if (SWITicks < cpuLoopTicks) + cpuLoopTicks = SWITicks; + } + + if (IRQTicks) { + if (IRQTicks < cpuLoopTicks) + cpuLoopTicks = IRQTicks; + } + return cpuLoopTicks; } @@ -634,7 +833,7 @@ // new to version 0.7.1 utilWriteInt(gzFile, stopState); // new to version 0.8 - utilWriteInt(gzFile, intState); + utilWriteInt(gzFile, IRQTicks); utilGzWrite(gzFile, internalRAM, 0x8000); utilGzWrite(gzFile, paletteRAM, 0x400); @@ -738,9 +937,21 @@ stopState = utilReadInt(gzFile) ? true : false; if(version < SAVE_GAME_VERSION_4) + { + IRQTicks = 0; intState = false; + } else - intState = utilReadInt(gzFile) ? true : false; + { + IRQTicks = utilReadInt(gzFile); + if (IRQTicks>0) + intState = true; + else + { + intState = false; + IRQTicks = 0; + } + } utilGzRead(gzFile, internalRAM, 0x8000); utilGzRead(gzFile, paletteRAM, 0x400); @@ -758,7 +969,7 @@ soundReadGame(gzFile, version); if(version > SAVE_GAME_VERSION_1) { - cheatsReadGame(gzFile); + cheatsReadGame(gzFile, version); } if(version > SAVE_GAME_VERSION_6) { rtcReadGame(gzFile); @@ -782,6 +993,18 @@ SWAP(dma3Dest, DM3DAD_H, DM3DAD_L); } + if(version <= SAVE_GAME_VERSION_8) { + timer0ClockReload = TIMER_TICKS[TM0CNT & 3]; + timer1ClockReload = TIMER_TICKS[TM1CNT & 3]; + timer2ClockReload = TIMER_TICKS[TM2CNT & 3]; + timer3ClockReload = TIMER_TICKS[TM3CNT & 3]; + + timer0Ticks = ((0x10000 - TM0D) << timer0ClockReload) - timer0Ticks; + timer1Ticks = ((0x10000 - TM1D) << timer1ClockReload) - timer1Ticks; + timer2Ticks = ((0x10000 - TM2D) << timer2ClockReload) - timer2Ticks; + timer3Ticks = ((0x10000 - TM3D) << timer3ClockReload) - timer3Ticks; + } + // set pointers! layerEnable = layerSettings & DISPCNT; @@ -802,6 +1025,11 @@ cpuSaveGameFunc = flashWrite; gbaSaveType = 2; break; + case 3: + break; + case 5: + gbaSaveType = 5; + break; default: systemMessage(MSG_UNSUPPORTED_SAVE_TYPE, N_("Unsupported save type %d"), saveType); @@ -811,6 +1039,13 @@ gbaSaveType = 3; systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + if(armState) { + ARM_PREFETCH; + } else { + THUMB_PREFETCH; + } + + CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); return true; } @@ -880,7 +1115,7 @@ } } - if(gbaSaveType) { + if((gbaSaveType) && (gbaSaveType!=5)) { FILE *file = fopen(fileName, "wb"); if(!file) { @@ -997,13 +1232,13 @@ fwrite("SharkPortSave", 1, 0x0d, file); utilPutDword(buffer, 0x000f0000); fwrite(buffer, 1, 4, file); // save type 0x000f0000 = GBA save - utilPutDword(buffer, strlen(title)); + utilPutDword(buffer, (u32)strlen(title)); fwrite(buffer, 1, 4, file); // title length fwrite(title, 1, strlen(title), file); - utilPutDword(buffer, strlen(desc)); + utilPutDword(buffer, (u32)strlen(desc)); fwrite(buffer, 1, 4, file); // desc length fwrite(desc, 1, strlen(desc), file); - utilPutDword(buffer, strlen(notes)); + utilPutDword(buffer, (u32)strlen(notes)); fwrite(buffer, 1, 4, file); // notes length fwrite(notes, 1, strlen(notes), file); int saveSize = 0x10000; @@ -1130,7 +1365,7 @@ bool CPUIsZipFile(const char * file) { if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".zip") == 0) @@ -1145,7 +1380,7 @@ { cpuIsMultiBoot = false; if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".gba") == 0) @@ -1169,7 +1404,7 @@ bool CPUIsGBABios(const char * file) { if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".gba") == 0) @@ -1189,7 +1424,7 @@ bool CPUIsELF(const char *file) { if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".elf") == 0) @@ -1261,8 +1496,7 @@ int CPULoadRom(const char *szFile) { - int size = 0x2000000; - + romSize = 0x2000000; if(rom != NULL) { CPUCleanUp(); } @@ -1297,8 +1531,8 @@ workRAM = NULL; return 0; } - bool res = elfRead(szFile, size, f); - if(!res || size == 0) { + bool res = elfRead(szFile, romSize, f); + if(!res || romSize == 0) { free(rom); rom = NULL; free(workRAM); @@ -1309,7 +1543,7 @@ } else if(!utilLoad(szFile, utilIsGBAImage, whereToLoad, - size)) { + romSize)) { free(rom); rom = NULL; free(workRAM); @@ -1317,9 +1551,9 @@ return 0; } - u16 *temp = (u16 *)(rom+((size+1)&~1)); + u16 *temp = (u16 *)(rom+((romSize+1)&~1)); int i; - for(i = (size+1)&~1; i < 0x2000000; i+=2) { + for(i = (romSize+1)&~1; i < 0x2000000; i+=2) { WRITE16LE(temp, (i >> 1) & 0xFFFF); temp++; } @@ -1374,9 +1608,29 @@ return 0; } + flashInit(); + eepromInit(); + CPUUpdateRenderBuffers(true); - return size; + return romSize; +} + +void doMirroring (bool b) +{ + u32 mirroredRomSize = (((romSize)>>20) & 0x3F)<<20; + u32 mirroredRomAddress = romSize; + if ((mirroredRomSize <=0x800000) && (b)) + { + mirroredRomAddress = mirroredRomSize; + if (mirroredRomSize==0) + mirroredRomSize=0x100000; + while (mirroredRomAddress<0x01000000) + { + memcpy ((u16 *)(rom+mirroredRomAddress), (u16 *)(rom), mirroredRomSize); + mirroredRomAddress+=mirroredRomSize; + } + } } void CPUUpdateRender() @@ -1470,9 +1724,8 @@ armState = (CPSR & 0x20) ? false : true; armIrqEnable = (CPSR & 0x80) ? false : true; if(breakLoop) { - if(armIrqEnable && (IF & IE) && (IME & 1)) { - CPU_BREAK_LOOP_2; - } + if (armIrqEnable && (IF & IE) && (IME & 1)) + cpuNextEvent = cpuTotalTicks; } } @@ -1626,6 +1879,7 @@ armState = true; armIrqEnable = false; armNextPC = 0x04; + ARM_PREFETCH; reg[15].I += 4; } @@ -1639,6 +1893,7 @@ armState = true; armIrqEnable = false; armNextPC = 0x08; + ARM_PREFETCH; reg[15].I += 4; } @@ -1678,7 +1933,8 @@ #ifdef SDL if(comment == 0xf9) { emulating = 0; - CPU_BREAK_LOOP_2; + cpuNextEvent = cpuTotalTicks; + cpuBreakLoop = true; return; } #endif @@ -1704,6 +1960,7 @@ switch(comment) { case 0x00: BIOS_SoftReset(); + ARM_PREFETCH; break; case 0x01: BIOS_RegisterRamReset(); @@ -1717,6 +1974,7 @@ #endif holdState = true; holdType = -1; + cpuNextEvent = cpuTotalTicks; break; case 0x03: #ifdef DEV_VERSION @@ -1728,6 +1986,7 @@ holdState = true; holdType = -1; stopState = true; + cpuNextEvent = cpuTotalTicks; break; case 0x04: #ifdef DEV_VERSION @@ -1765,11 +2024,52 @@ BIOS_ArcTan2(); break; case 0x0B: + { + int len = (reg[2].I & 0x1FFFFF) >>1; + if (!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + len) & 0xe000000) == 0)) + { + if ((reg[2].I >> 24) & 1) + { + if ((reg[2].I >> 26) & 1) + SWITicks = (7 + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1); + else + SWITicks = (8 + memoryWait[(reg[1].I>>24) & 0xF]) * (len); + } + else + { + if ((reg[2].I >> 26) & 1) + SWITicks = (10 + memoryWait32[(reg[0].I>>24) & 0xF] + + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1); + else + SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + } + } BIOS_CpuSet(); break; case 0x0C: + { + int len = (reg[2].I & 0x1FFFFF) >>5; + if (!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + len) & 0xe000000) == 0)) + { + if ((reg[2].I >> 24) & 1) + SWITicks = (6 + memoryWait32[(reg[1].I>>24) & 0xF] + + 7 * (memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 1)) * len; + else + SWITicks = (9 + memoryWait32[(reg[0].I>>24) & 0xF] + + memoryWait32[(reg[1].I>>24) & 0xF] + + 7 * (memoryWaitSeq32[(reg[0].I>>24) & 0xF] + + memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 2)) * len; + } + } BIOS_CpuFastSet(); break; + case 0x0D: + BIOS_GetBiosChecksum(); + break; case 0x0E: BIOS_BgAffineSet(); break; @@ -1777,30 +2077,89 @@ BIOS_ObjAffineSet(); break; case 0x10: + { + int len = CPUReadHalfWord(reg[2].I); + if (!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + len) & 0xe000000) == 0)) + SWITicks = (32 + memoryWait[(reg[0].I>>24) & 0xF]) * len; + } BIOS_BitUnPack(); break; case 0x11: + { + u32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (9 + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_LZ77UnCompWram(); break; case 0x12: + { + u32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (19 + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_LZ77UnCompVram(); break; case 0x13: + { + u32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (29 + (memoryWait[(reg[0].I>>24) & 0xF]<<1)) * len; + } BIOS_HuffUnComp(); break; case 0x14: + { + u32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_RLUnCompWram(); break; case 0x15: + { + u32 len = CPUReadMemory(reg[0].I) >> 9; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (34 + (memoryWait[(reg[0].I>>24) & 0xF] << 1) + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_RLUnCompVram(); break; case 0x16: + { + u32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_Diff8bitUnFilterWram(); break; case 0x17: + { + u32 len = CPUReadMemory(reg[0].I) >> 9; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (39 + (memoryWait[(reg[0].I>>24) & 0xF]<<1) + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_Diff8bitUnFilterVram(); break; case 0x18: + { + u32 len = CPUReadMemory(reg[0].I) >> 9; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } BIOS_Diff16bitUnFilter(); break; case 0x19: @@ -1859,17 +2218,33 @@ DISPSTAT &= 0xFFFB; UPDATE_REG(0x4, DISPSTAT); } + if (layerEnableDelay>0) + { + layerEnableDelay--; + if (layerEnableDelay==1) + layerEnable = layerSettings & DISPCNT; + } + } void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) { int sm = s >> 24; int dm = d >> 24; - + int sw = 0; + int dw = 0; int sc = c; cpuDmaCount = c; + // This is done to get the correct waitstates. + if (sm>15) + sm=15; + if (dm>15) + dm=15; + //if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07)) + // blank = (((DISPSTAT | ((DISPSTAT>>1)&1))==1) ? true : false); + if(transfer32) { s &= 0xFFFFFFFC; if(s < 0x02000000 && (reg[15].I >> 24)) { @@ -1880,7 +2255,8 @@ } } else { while(c != 0) { - CPUWriteMemory(d, CPUReadMemory(s)); + cpuDmaLast = CPUReadMemory(s); + CPUWriteMemory(d, cpuDmaLast); d += di; s += si; c--; @@ -1900,6 +2276,7 @@ while(c != 0) { cpuDmaLast = CPUReadHalfWord(s); CPUWriteHalfWord(d, cpuDmaLast); + cpuDmaLast |= (cpuDmaLast<<16); d += di; s += si; c--; @@ -1909,30 +2286,28 @@ cpuDmaCount = 0; - int sw = 1+memoryWaitSeq[sm & 15]; - int dw = 1+memoryWaitSeq[dm & 15]; - int totalTicks = 0; if(transfer32) { - if(!memory32[sm & 15]) - sw <<= 1; - if(!memory32[dm & 15]) - dw <<= 1; + sw =1+memoryWaitSeq32[sm & 15]; + dw =1+memoryWaitSeq32[dm & 15]; + totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] + + memoryWaitSeq32[dm & 15]; + } + else + { + sw = 1+memoryWaitSeq[sm & 15]; + dw = 1+memoryWaitSeq[dm & 15]; + totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] + + memoryWaitSeq[dm & 15]; } - - totalTicks = (sw+dw)*sc; cpuDmaTicksToUpdate += totalTicks; - if(*extCpuLoopTicks >= 0) { - CPU_BREAK_LOOP; - } } void CPUCheckDMA(int reason, int dmamask) { - cpuDmaHack = 0; // DMA 0 if((DM0CNT_H & 0x8000) && (dmamask & 1)) { if(((DM0CNT_H >> 12) & 3) == reason) { @@ -1971,10 +2346,12 @@ doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, DM0CNT_L ? DM0CNT_L : 0x4000, DM0CNT_H & 0x0400); - cpuDmaHack = 1; + cpuDmaHack = true; + if(DM0CNT_H & 0x4000) { IF |= 0x0100; UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; } if(((DM0CNT_H >> 5) & 3) == 3) { @@ -2038,11 +2415,12 @@ DM1CNT_L ? DM1CNT_L : 0x4000, DM1CNT_H & 0x0400); } - cpuDmaHack = 1; - + cpuDmaHack = true; + if(DM1CNT_H & 0x4000) { IF |= 0x0200; UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; } if(((DM1CNT_H >> 5) & 3) == 3) { @@ -2107,10 +2485,12 @@ DM2CNT_L ? DM2CNT_L : 0x4000, DM2CNT_H & 0x0400); } - cpuDmaHack = 1; + cpuDmaHack = true; + if(DM2CNT_H & 0x4000) { IF |= 0x0400; UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; } if(((DM2CNT_H >> 5) & 3) == 3) { @@ -2165,6 +2545,7 @@ if(DM3CNT_H & 0x4000) { IF |= 0x0800; UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; } if(((DM3CNT_H >> 5) & 3) == 3) { @@ -2177,7 +2558,6 @@ } } } - cpuDmaHack = 0; } void CPUUpdateRegister(u32 address, u16 value) @@ -2185,15 +2565,27 @@ switch(address) { case 0x00: { + if ((value & 7) >5) + DISPCNT = (value &7); bool change = ((DISPCNT ^ value) & 0x80) ? true : false; bool changeBG = ((DISPCNT ^ value) & 0x0F00) ? true : false; + u16 changeBGon = (((~DISPCNT) & value) & 0x0F00); DISPCNT = (value & 0xFFF7); UPDATE_REG(0x00, DISPCNT); - layerEnable = layerSettings & value; + + if (changeBGon) + { + layerEnableDelay=4; + layerEnable = layerSettings & value & (~changeBGon); + } + else + layerEnable = layerSettings & value; + // CPUUpdateTicks(); + windowOn = (layerEnable & 0x6000) ? true : false; if(change && !((value & 0x80))) { if(!(DISPSTAT & 1)) { - lcdTicks = 960; + lcdTicks = 1008; // VCOUNT = 0; // UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFC; @@ -2206,7 +2598,6 @@ // we only care about changes in BG0-BG3 if(changeBG) CPUUpdateRenderBuffers(false); - // CPUUpdateTicks(); } break; case 0x04: @@ -2554,70 +2945,37 @@ } } break; - case 0x100: + case 0x100: timer0Reload = value; break; case 0x102: - timer0Ticks = timer0ClockReload = TIMER_TICKS[value & 3]; - if(!timer0On && (value & 0x80)) { - // reload the counter - TM0D = timer0Reload; - if(timer0ClockReload == 1) - timer0Ticks = 0x10000 - TM0D; - UPDATE_REG(0x100, TM0D); - } - timer0On = value & 0x80 ? true : false; - TM0CNT = value & 0xC7; - UPDATE_REG(0x102, TM0CNT); - // CPUUpdateTicks(); + timer0Value = value; + timerOnOffDelay|=1; + cpuNextEvent = cpuTotalTicks; break; case 0x104: timer1Reload = value; break; case 0x106: - timer1Ticks = timer1ClockReload = TIMER_TICKS[value & 3]; - if(!timer1On && (value & 0x80)) { - // reload the counter - TM1D = timer1Reload; - if(timer1ClockReload == 1) - timer1Ticks = 0x10000 - TM1D; - UPDATE_REG(0x104, TM1D); - } - timer1On = value & 0x80 ? true : false; - TM1CNT = value & 0xC7; - UPDATE_REG(0x106, TM1CNT); + timer1Value = value; + timerOnOffDelay|=2; + cpuNextEvent = cpuTotalTicks; break; case 0x108: timer2Reload = value; break; case 0x10A: - timer2Ticks = timer2ClockReload = TIMER_TICKS[value & 3]; - if(!timer2On && (value & 0x80)) { - // reload the counter - TM2D = timer2Reload; - if(timer2ClockReload == 1) - timer2Ticks = 0x10000 - TM2D; - UPDATE_REG(0x108, TM2D); - } - timer2On = value & 0x80 ? true : false; - TM2CNT = value & 0xC7; - UPDATE_REG(0x10A, TM2CNT); + timer2Value = value; + timerOnOffDelay|=4; + cpuNextEvent = cpuTotalTicks; break; case 0x10C: timer3Reload = value; break; case 0x10E: - timer3Ticks = timer3ClockReload = TIMER_TICKS[value & 3]; - if(!timer3On && (value & 0x80)) { - // reload the counter - TM3D = timer3Reload; - if(timer3ClockReload == 1) - timer3Ticks = 0x10000 - TM3D; - UPDATE_REG(0x10C, TM3D); - } - timer3On = value & 0x80 ? true : false; - TM3CNT = value & 0xC7; - UPDATE_REG(0x10E, TM3CNT); + timer3Value = value; + timerOnOffDelay|=8; + cpuNextEvent = cpuTotalTicks; break; case 0x128: if(value & 0x80) { @@ -2641,9 +2999,8 @@ case 0x200: IE = value & 0x3FFF; UPDATE_REG(0x200, IE); - if((IME & 1) && (IF & IE) && armIrqEnable) { - CPU_BREAK_LOOP_2; - } + if ((IME & 1) && (IF & IE) && armIrqEnable) + cpuNextEvent = cpuTotalTicks; break; case 0x202: IF ^= (value & IF); @@ -2651,54 +3008,54 @@ break; case 0x204: { - int i; memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3]; if(!speedHack) { - memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 7]; + memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3]; memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = - gamepakWaitState0[(value >> 2) & 7]; + gamepakWaitState0[(value >> 4) & 1]; - memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 7]; + memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3]; memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = - gamepakWaitState1[(value >> 5) & 7]; + gamepakWaitState1[(value >> 7) & 1]; - memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 7]; + memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3]; memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = - gamepakWaitState2[(value >> 8) & 7]; + gamepakWaitState2[(value >> 10) & 1]; } else { - memoryWait[0x08] = memoryWait[0x09] = 4; - memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 2; + memoryWait[0x08] = memoryWait[0x09] = 3; + memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1; - memoryWait[0x0a] = memoryWait[0x0b] = 4; - memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 4; + memoryWait[0x0a] = memoryWait[0x0b] = 3; + memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1; - memoryWait[0x0c] = memoryWait[0x0d] = 4; - memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 8; + memoryWait[0x0c] = memoryWait[0x0d] = 3; + memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1; } - for(i = 0; i < 16; i++) { - memoryWaitFetch32[i] = memoryWait32[i] = memoryWait[i] * - (memory32[i] ? 1 : 2); - memoryWaitFetch[i] = memoryWait[i]; + + for(int i = 8; i < 15; i++) { + memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1; + memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1; } - memoryWaitFetch32[3] += 1; - memoryWaitFetch32[2] += 3; - - if(value & 0x4000) { - for(i = 8; i < 16; i++) { - memoryWaitFetch32[i] = 2*cpuMemoryWait[i]; - memoryWaitFetch[i] = cpuMemoryWait[i]; - } + + if((value & 0x4000) == 0x4000) { + busPrefetchEnable = true; + busPrefetch = false; + busPrefetchCount = 0; + } else { + busPrefetchEnable = false; + busPrefetch = false; + busPrefetchCount = 0; } - UPDATE_REG(0x204, value); + UPDATE_REG(0x204, value & 0x7FFF); + } break; case 0x208: IME = value & 1; UPDATE_REG(0x208, IME); - if((IME & 1) && (IF & IE) && armIrqEnable) { - CPU_BREAK_LOOP_2; - } + if ((IME & 1) && (IF & IE) && armIrqEnable) + cpuNextEvent = cpuTotalTicks; break; case 0x300: if(value != 0) @@ -2711,6 +3068,65 @@ } } +void applyTimer () +{ + if (timerOnOffDelay & 1) + { + timer0ClockReload = TIMER_TICKS[timer0Value & 3]; + if(!timer0On && (timer0Value & 0x80)) { + // reload the counter + TM0D = timer0Reload; + timer0Ticks = (0x10000 - TM0D) << timer0ClockReload; + UPDATE_REG(0x100, TM0D); + } + timer0On = timer0Value & 0x80 ? true : false; + TM0CNT = timer0Value & 0xC7; + UPDATE_REG(0x102, TM0CNT); + // CPUUpdateTicks(); + } + if (timerOnOffDelay & 2) + { + timer1ClockReload = TIMER_TICKS[timer1Value & 3]; + if(!timer1On && (timer1Value & 0x80)) { + // reload the counter + TM1D = timer1Reload; + timer1Ticks = (0x10000 - TM1D) << timer1ClockReload; + UPDATE_REG(0x104, TM1D); + } + timer1On = timer1Value & 0x80 ? true : false; + TM1CNT = timer1Value & 0xC7; + UPDATE_REG(0x106, TM1CNT); + } + if (timerOnOffDelay & 4) + { + timer2ClockReload = TIMER_TICKS[timer2Value & 3]; + if(!timer2On && (timer2Value & 0x80)) { + // reload the counter + TM2D = timer2Reload; + timer2Ticks = (0x10000 - TM2D) << timer2ClockReload; + UPDATE_REG(0x108, TM2D); + } + timer2On = timer2Value & 0x80 ? true : false; + TM2CNT = timer2Value & 0xC7; + UPDATE_REG(0x10A, TM2CNT); + } + if (timerOnOffDelay & 8) + { + timer3ClockReload = TIMER_TICKS[timer3Value & 3]; + if(!timer3On && (timer3Value & 0x80)) { + // reload the counter + TM3D = timer3Reload; + timer3Ticks = (0x10000 - TM3D) << timer3ClockReload; + UPDATE_REG(0x10C, TM3D); + } + timer3On = timer3Value & 0x80 ? true : false; + TM3CNT = timer3Value & 0xC7; + UPDATE_REG(0x10E, TM3CNT); + } + cpuNextEvent = CPUUpdateTicks(); + timerOnOffDelay = 0; +} + void CPUWriteHalfWord(u32 address, u16 value) { #ifdef DEV_VERSION @@ -2726,38 +3142,58 @@ switch(address >> 24) { case 2: -#ifdef SDL +#ifdef BKPT_SUPPORT if(*((u16 *)&freezeWorkRAM[address & 0x3FFFE])) - cheatsWriteHalfWord((u16 *)&workRAM[address & 0x3FFFE], - value, - *((u16 *)&freezeWorkRAM[address & 0x3FFFE])); + cheatsWriteHalfWord(address & 0x203FFFE, + value); else #endif WRITE16LE(((u16 *)&workRAM[address & 0x3FFFE]),value); break; case 3: -#ifdef SDL +#ifdef BKPT_SUPPORT if(*((u16 *)&freezeInternalRAM[address & 0x7ffe])) - cheatsWriteHalfWord((u16 *)&internalRAM[address & 0x7ffe], - value, - *((u16 *)&freezeInternalRAM[address & 0x7ffe])); + cheatsWriteHalfWord(address & 0x3007ffe, + value); else #endif WRITE16LE(((u16 *)&internalRAM[address & 0x7ffe]), value); break; case 4: - CPUUpdateRegister(address & 0x3fe, value); + if(address < 0x4000400) + CPUUpdateRegister(address & 0x3fe, value); + else goto unwritable; break; case 5: +#ifdef BKPT_SUPPORT + if(*((u16 *)&freezePRAM[address & 0x03fe])) + cheatsWriteHalfWord(address & 0x70003fe, + value); + else +#endif WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value); break; case 6: - if(address & 0x10000) - WRITE16LE(((u16 *)&vram[address & 0x17ffe]), value); + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; +#ifdef BKPT_SUPPORT + if(*((u16 *)&freezeVRAM[address])) + cheatsWriteHalfWord(address + 0x06000000, + value); else - WRITE16LE(((u16 *)&vram[address & 0x1fffe]), value); +#endif + WRITE16LE(((u16 *)&vram[address]), value); break; case 7: +#ifdef BKPT_SUPPORT + if(*((u16 *)&freezeOAM[address & 0x03fe])) + cheatsWriteHalfWord(address & 0x70003fe, + value); + else +#endif WRITE16LE(((u16 *)&oam[address & 0x3fe]), value); break; case 8: @@ -2797,99 +3233,113 @@ { switch(address >> 24) { case 2: -#ifdef SDL +#ifdef BKPT_SUPPORT if(freezeWorkRAM[address & 0x3FFFF]) - cheatsWriteByte(&workRAM[address & 0x3FFFF], b); + cheatsWriteByte(address & 0x203FFFF, b); else #endif workRAM[address & 0x3FFFF] = b; break; case 3: -#ifdef SDL +#ifdef BKPT_SUPPORT if(freezeInternalRAM[address & 0x7fff]) - cheatsWriteByte(&internalRAM[address & 0x7fff], b); + cheatsWriteByte(address & 0x3007fff, b); else #endif internalRAM[address & 0x7fff] = b; break; case 4: - switch(address & 0x3FF) { - case 0x301: - if(b == 0x80) - stopState = true; - holdState = 1; - holdType = -1; - break; - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x68: - case 0x69: - case 0x6c: - case 0x6d: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x78: - case 0x79: - case 0x7c: - case 0x7d: - case 0x80: - case 0x81: - case 0x84: - case 0x85: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9a: - case 0x9b: - case 0x9c: - case 0x9d: - case 0x9e: - case 0x9f: - soundEvent(address&0xFF, b); + if(address < 0x4000400) { + switch(address & 0x3FF) { + case 0x301: + if(b == 0x80) + stopState = true; + holdState = 1; + holdType = -1; + cpuNextEvent = cpuTotalTicks; + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x68: + case 0x69: + case 0x6c: + case 0x6d: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x78: + case 0x79: + case 0x7c: + case 0x7d: + case 0x80: + case 0x81: + case 0x84: + case 0x85: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + soundEvent(address&0xFF, b); + break; + default: + if(address & 1) + CPUUpdateRegister(address & 0x3fe, + ((READ16LE(((u16 *)&ioMem[address & 0x3fe]))) + & 0x00FF) | + b<<8); + else + CPUUpdateRegister(address & 0x3fe, + ((READ16LE(((u16 *)&ioMem[address & 0x3fe])) & 0xFF00) | b)); + } break; - default: - // if(address & 1) { - // CPUWriteHalfWord(address-1, (CPUReadHalfWord(address-1)&0x00FF)|((int)b<<8)); - // } else - if(address & 1) - CPUUpdateRegister(address & 0x3fe, - ((READ16LE(((u16 *)&ioMem[address & 0x3fe]))) - & 0x00FF) | - b<<8); - else - CPUUpdateRegister(address & 0x3fe, - ((READ16LE(((u16 *)&ioMem[address & 0x3fe])) & 0xFF00) | b)); - } + } else goto unwritable; break; case 5: // no need to switch *((u16 *)&paletteRAM[address & 0x3FE]) = (b << 8) | b; break; case 6: - // no need to switch - if(address & 0x10000) - *((u16 *)&vram[address & 0x17FFE]) = (b << 8) | b; - else - *((u16 *)&vram[address & 0x1FFFE]) = (b << 8) | b; + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + + // no need to switch + // byte writes to OBJ VRAM are ignored + if ((address) < objTilesAddress[((DISPCNT&7)+1)>>2]) + { +#ifdef BKPT_SUPPORT + if(freezeVRAM[address]) + cheatsWriteByte(address + 0x06000000, b); + else +#endif + *((u16 *)&vram[address]) = (b << 8) | b; + } break; case 7: // no need to switch - *((u16 *)&oam[address & 0x3FE]) = (b << 8) | b; + // byte writes to OAM are ignored + // *((u16 *)&oam[address & 0x3FE]) = (b << 8) | b; break; case 13: if(cpuEEPROMEnabled) { @@ -2898,8 +3348,11 @@ } goto unwritable; case 14: - if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { - (*cpuSaveGameFunc)(address, b); + if (!(saveType == 5) && (!eepromInUse | cpuSramEnabled | cpuFlashEnabled)) { + + //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) { + + (*cpuSaveGameFunc)(address, b); break; } // default @@ -3008,8 +3461,12 @@ for(i = 0x304; i < 0x400; i++) ioReadable[i] = false; - *((u16 *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA - *((u16 *)&rom[0x1fe209e]) = 0x4770; // BX LR + if(romSize < 0x1fe2000) { + *((u16 *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA + *((u16 *)&rom[0x1fe209e]) = 0x4770; // BX LR + } else { + agbPrintEnable(false); + } } void CPUReset() @@ -3028,7 +3485,7 @@ } } rtcReset(); - // clen registers + // clean registers memset(®[0], 0, sizeof(reg)); // clean OAM memset(oam, 0, 0x400); @@ -3043,7 +3500,7 @@ DISPCNT = 0x0080; DISPSTAT = 0x0000; - VCOUNT = 0x0000; + VCOUNT = (useBios && !skipBios) ? 0 :0x007E; BG0CNT = 0x0000; BG1CNT = 0x0000; BG2CNT = 0x0000; @@ -3132,7 +3589,7 @@ if(useBios && !skipBios) { reg[15].I = 0x00000000; armMode = 0x13; - armIrqEnable = false; + armIrqEnable = false; } else { reg[13].I = 0x03007F00; reg[15].I = 0x08000000; @@ -3145,6 +3602,7 @@ armState = true; C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false; UPDATE_REG(0x00, DISPCNT); + UPDATE_REG(0x06, VCOUNT); UPDATE_REG(0x20, BG2PA); UPDATE_REG(0x26, BG2PD); UPDATE_REG(0x30, BG3PA); @@ -3169,7 +3627,7 @@ biosProtected[2] = 0x29; biosProtected[3] = 0xe1; - lcdTicks = 960; + lcdTicks = (useBios && !skipBios) ? 1008 : 208; timer0On = false; timer0Ticks = 0; timer0Reload = 0; @@ -3259,44 +3717,59 @@ cpuFlashEnabled = true; cpuEEPROMEnabled = true; cpuEEPROMSensorEnabled = false; + saveType = gbaSaveType = 0; break; case 1: // EEPROM cpuSramEnabled = false; cpuFlashEnabled = false; cpuEEPROMEnabled = true; cpuEEPROMSensorEnabled = false; + saveType = gbaSaveType = 3; + // EEPROM usage is automatically detected break; case 2: // SRAM cpuSramEnabled = true; cpuFlashEnabled = false; cpuEEPROMEnabled = false; cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = sramWrite; + cpuSaveGameFunc = sramDelayedWrite; // to insure we detect the write + saveType = gbaSaveType = 1; break; case 3: // FLASH cpuSramEnabled = false; cpuFlashEnabled = true; cpuEEPROMEnabled = false; cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = flashWrite; + cpuSaveGameFunc = flashDelayedWrite; // to insure we detect the write + saveType = gbaSaveType = 2; break; case 4: // EEPROM+Sensor cpuSramEnabled = false; cpuFlashEnabled = false; cpuEEPROMEnabled = true; cpuEEPROMSensorEnabled = true; + // EEPROM usage is automatically detected + saveType = gbaSaveType = 3; break; case 5: // NONE cpuSramEnabled = false; cpuFlashEnabled = false; cpuEEPROMEnabled = false; cpuEEPROMSensorEnabled = false; + // no save at all + saveType = gbaSaveType = 5; break; } + ARM_PREFETCH; + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - + + cpuDmaHack = false; + lastTime = systemGetClock(); + + SWITicks = 0; } void CPUInterrupt() @@ -3313,6 +3786,7 @@ armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; // if(!holdState) biosProtected[0] = 0x02; @@ -3345,30 +3819,30 @@ void CPULoop(int ticks) { int clockTicks; - int cpuLoopTicks = 0; int timerOverflow = 0; - // variables used by the CPU core + // variable used by the CPU core + cpuTotalTicks = 0; + cpuBreakLoop = false; + cpuNextEvent = CPUUpdateTicks(); + if(cpuNextEvent > ticks) + cpuNextEvent = ticks; - extCpuLoopTicks = &cpuLoopTicks; - extClockTicks = &clockTicks; - extTicks = &ticks; - cpuLoopTicks = CPUUpdateTicks(); - if(cpuLoopTicks > ticks) { - cpuLoopTicks = ticks; - cpuSavedTicks = ticks; - } - - if(intState) { - cpuLoopTicks = 5; - cpuSavedTicks = 5; - } - for(;;) { #ifndef FINAL_VERSION if(systemDebug) { if(systemDebug >= 10 && !holdState) { CPUUpdateCPSR(); +#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", + 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", 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, @@ -3388,63 +3862,72 @@ #endif } } -#endif +#endif /* FINAL_VERSION */ + + if(!holdState && !SWITicks) { + + // Emulates the Cheat System (m) code + if((cheatsEnabled) && (mastercode) && (mastercode == armNextPC)) + { + u32 joy = 0; + if(systemReadJoypads()) + joy = systemReadJoypad(-1); + u32 ext = (joy >> 10); + cpuTotalTicks += cheatsCheckKeys(P1^0x3FF, ext); + } + + if ((armNextPC & 0x0803FFFF) == 0x08020000) + busPrefetchCount=0x100; - if(!holdState) { if(armState) { #include "arm-new.h" } else { #include "thumb.h" } - } else { - clockTicks = lcdTicks; + } else + clockTicks = CPUUpdateTicks(); - if(soundTicks < clockTicks) - clockTicks = soundTicks; - - if(timer0On && (timer0Ticks < clockTicks)) { - clockTicks = timer0Ticks; - } - if(timer1On && (timer1Ticks < clockTicks)) { - clockTicks = timer1Ticks; - } - if(timer2On && (timer2Ticks < clockTicks)) { - clockTicks = timer2Ticks; - } - if(timer3On && (timer3Ticks < clockTicks)) { - clockTicks = timer3Ticks; - } -#ifdef PROFILING - if(profilingTicksReload != 0) { - if(profilingTicks < clockTicks) { - clockTicks = profilingTicks; - } + cpuTotalTicks += clockTicks; + + + if(cpuTotalTicks >= cpuNextEvent) { + int remainingTicks = cpuTotalTicks - cpuNextEvent; + + if (SWITicks) + { + SWITicks-=clockTicks; + if (SWITicks<0) + SWITicks = 0; } -#endif - } + + clockTicks = cpuNextEvent; + cpuTotalTicks = 0; + cpuDmaHack = false; - cpuLoopTicks -= clockTicks; - if((cpuLoopTicks <= 0)) { - if(cpuSavedTicks) { - clockTicks = cpuSavedTicks;// + cpuLoopTicks; + updateLoop: + + if (IRQTicks) + { + IRQTicks -= clockTicks; + if (IRQTicks<0) + IRQTicks = 0; } - cpuDmaTicksToUpdate = -cpuLoopTicks; - updateLoop: lcdTicks -= clockTicks; + if(lcdTicks <= 0) { if(DISPSTAT & 1) { // V-BLANK // if in V-Blank mode, keep computing... if(DISPSTAT & 2) { - lcdTicks += 960; + lcdTicks += 1008; VCOUNT++; UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFD; UPDATE_REG(0x04, DISPSTAT); CPUCompareVCOUNT(); } else { - lcdTicks += 272; + lcdTicks += 224; DISPSTAT |= 2; UPDATE_REG(0x04, DISPSTAT); if(DISPSTAT & 16) { @@ -3453,7 +3936,7 @@ } } - if(VCOUNT >= 228) { + if(VCOUNT >= 228) { //Reaching last line DISPSTAT &= 0xFFFC; UPDATE_REG(0x04, DISPSTAT); VCOUNT = 0; @@ -3469,8 +3952,8 @@ // if in H-Blank, leave it and move to drawing mode VCOUNT++; UPDATE_REG(0x06, VCOUNT); - - lcdTicks += (960); + + lcdTicks += 1008; DISPSTAT &= 0xFFFD; if(VCOUNT == 160) { count++; @@ -3518,10 +4001,9 @@ } u32 ext = (joy >> 10); - int cheatTicks = 0; - if(cheatsEnabled) - cheatsCheckKeys(P1^0x3FF, ext); - cpuDmaTicksToUpdate += cheatTicks; + // If no (m) code is enabled, apply the cheats at each LCDline + if((cheatsEnabled) && (mastercode==0)) + remainingTicks += cheatsCheckKeys(P1^0x3FF, ext); speedup = (ext & 1) ? true : false; capture = (ext & 2) ? true : false; @@ -3530,7 +4012,7 @@ systemScreenCapture(captureNumber); } capturePrevious = capture; - + DISPSTAT |= 1; DISPSTAT &= 0xFFFD; UPDATE_REG(0x04, DISPSTAT); @@ -3549,14 +4031,14 @@ } UPDATE_REG(0x04, DISPSTAT); - - CPUCompareVCOUNT(); + CPUCompareVCOUNT(); + } else { - if(frameCount >= framesToSkip) { - (*renderLine)(); - + if(frameCount >= framesToSkip) + { + (*renderLine)(); switch(systemColorDepth) { - case 16: + case 16: { u16 *dest = (u16 *)pix + 242 * (VCOUNT+1); for(int x = 0; x < 240;) { @@ -3584,7 +4066,7 @@ *dest++ = 0; } break; - case 24: + case 24: { u8 *dest = (u8 *)pix + 240 * VCOUNT * 3; for(int x = 0; x < 240;) { @@ -3626,7 +4108,7 @@ } } break; - case 32: + case 32: { u32 *dest = (u32 *)pix + 241 * (VCOUNT+1); for(int x = 0; x < 240; ) { @@ -3634,7 +4116,7 @@ *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; - + *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF]; @@ -3657,7 +4139,7 @@ // entering H-Blank DISPSTAT |= 2; UPDATE_REG(0x04, DISPSTAT); - lcdTicks += 272; + lcdTicks += 224; CPUCheckDMA(2, 0x0f); if(DISPSTAT & 16) { IF |= 2; @@ -3669,37 +4151,18 @@ if(!stopState) { if(timer0On) { - if(timer0ClockReload == 1) { - u32 tm0d = TM0D + clockTicks; - if(tm0d > 0xffff) { - tm0d += timer0Reload; - timerOverflow |= 1; - soundTimerOverflow(0); - if(TM0CNT & 0x40) { - IF |= 0x08; - UPDATE_REG(0x202, IF); - } - } - TM0D = tm0d; - timer0Ticks = 0x10000 - TM0D; - UPDATE_REG(0x100, TM0D); - } else { - timer0Ticks -= clockTicks; - if(timer0Ticks <= 0) { - timer0Ticks += timer0ClockReload; - TM0D++; - if(TM0D == 0) { - TM0D = timer0Reload; - timerOverflow |= 1; - soundTimerOverflow(0); - if(TM0CNT & 0x40) { - IF |= 0x08; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x100, TM0D); + timer0Ticks -= clockTicks; + if(timer0Ticks <= 0) { + timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload; + timerOverflow |= 1; + soundTimerOverflow(0); + if(TM0CNT & 0x40) { + IF |= 0x08; + UPDATE_REG(0x202, IF); } } + TM0D = 0xFFFF - (timer0Ticks >> timer0ClockReload); + UPDATE_REG(0x100, TM0D); } if(timer1On) { @@ -3718,38 +4181,18 @@ UPDATE_REG(0x104, TM1D); } } else { - if(timer1ClockReload == 1) { - u32 tm1d = TM1D + clockTicks; - if(tm1d > 0xffff) { - tm1d += timer1Reload; - timerOverflow |= 2; - soundTimerOverflow(1); - if(TM1CNT & 0x40) { - IF |= 0x10; - UPDATE_REG(0x202, IF); - } - } - TM1D = tm1d; - timer1Ticks = 0x10000 - TM1D; - UPDATE_REG(0x104, TM1D); - } else { - timer1Ticks -= clockTicks; - if(timer1Ticks <= 0) { - timer1Ticks += timer1ClockReload; - TM1D++; - - if(TM1D == 0) { - TM1D = timer1Reload; - timerOverflow |= 2; - soundTimerOverflow(1); - if(TM1CNT & 0x40) { - IF |= 0x10; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x104, TM1D); + timer1Ticks -= clockTicks; + if(timer1Ticks <= 0) { + timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload; + timerOverflow |= 2; + soundTimerOverflow(1); + if(TM1CNT & 0x40) { + IF |= 0x10; + UPDATE_REG(0x202, IF); } } + TM1D = 0xFFFF - (timer1Ticks >> timer1ClockReload); + UPDATE_REG(0x104, TM1D); } } @@ -3768,36 +4211,17 @@ UPDATE_REG(0x108, TM2D); } } else { - if(timer2ClockReload == 1) { - u32 tm2d = TM2D + clockTicks; - if(tm2d > 0xffff) { - tm2d += timer2Reload; - timerOverflow |= 4; - if(TM2CNT & 0x40) { - IF |= 0x20; - UPDATE_REG(0x202, IF); - } - } - TM2D = tm2d; - timer2Ticks = 0x10000 - TM2D; - UPDATE_REG(0x108, TM2D); - } else { - timer2Ticks -= clockTicks; - if(timer2Ticks <= 0) { - timer2Ticks += timer2ClockReload; - TM2D++; - - if(TM2D == 0) { - TM2D = timer2Reload; - timerOverflow |= 4; - if(TM2CNT & 0x40) { - IF |= 0x20; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x108, TM2D); + timer2Ticks -= clockTicks; + if(timer2Ticks <= 0) { + timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload; + timerOverflow |= 4; + if(TM2CNT & 0x40) { + IF |= 0x20; + UPDATE_REG(0x202, IF); } } + TM2D = 0xFFFF - (timer2Ticks >> timer2ClockReload); + UPDATE_REG(0x108, TM2D); } } @@ -3812,41 +4236,26 @@ UPDATE_REG(0x202, IF); } } - UPDATE_REG(0x10c, TM3D); + UPDATE_REG(0x10C, TM3D); } } else { - if(timer3ClockReload == 1) { - u32 tm3d = TM3D + clockTicks; - if(tm3d > 0xffff) { - tm3d += timer3Reload; - if(TM3CNT & 0x40) { - IF |= 0x40; - UPDATE_REG(0x202, IF); - } - } - TM3D = tm3d; - timer3Ticks = 0x10000 - TM3D; - UPDATE_REG(0x10C, TM3D); - } else { - timer3Ticks -= clockTicks; - if(timer3Ticks <= 0) { - timer3Ticks += timer3ClockReload; - TM3D++; - - if(TM3D == 0) { - TM3D = timer3Reload; - if(TM3CNT & 0x40) { - IF |= 0x40; - UPDATE_REG(0x202, IF); - } - } - UPDATE_REG(0x10C, TM3D); + timer3Ticks -= clockTicks; + if(timer3Ticks <= 0) { + timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload; + if(TM3CNT & 0x40) { + IF |= 0x40; + UPDATE_REG(0x202, IF); } } + TM3D = 0xFFFF - (timer3Ticks >> timer3ClockReload); + UPDATE_REG(0x10C, TM3D); } } } - // we shouldn't be doing sound in stop state, but we lose synchronization + + timerOverflow = 0; + + // we shouldn't be doing sound in stop state, but we loose synchronization // if sound is disabled, so in stop state, soundTick will just produce // mute sound soundTicks -= clockTicks; @@ -3854,33 +4263,40 @@ soundTick(); soundTicks += SOUND_CLOCK_TICKS; } - timerOverflow = 0; #ifdef PROFILING profilingTicks -= clockTicks; if(profilingTicks <= 0) { profilingTicks += profilingTicksReload; - if(profilBuffer && profilSize) { - u16 *b = (u16 *)profilBuffer; - int pc = ((reg[15].I - profilLowPC) * profilScale)/0x10000; - if(pc >= 0 && pc < profilSize) { + if(profilSegment) { + profile_segment *seg = profilSegment; + do { + u16 *b = (u16 *)seg->sbuf; + int pc = ((reg[15].I - seg->s_lowpc) * seg->s_scale)/0x10000; + if(pc >= 0 && pc < seg->ssiz) { b[pc]++; + break; } + + seg = seg->next; + } while(seg); } } #endif ticks -= clockTicks; - cpuLoopTicks = CPUUpdateTicks(); + cpuNextEvent = CPUUpdateTicks(); if(cpuDmaTicksToUpdate > 0) { - clockTicks = cpuSavedTicks; - if(clockTicks > cpuDmaTicksToUpdate) + if(cpuDmaTicksToUpdate > cpuNextEvent) + clockTicks = cpuNextEvent; + else clockTicks = cpuDmaTicksToUpdate; cpuDmaTicksToUpdate -= clockTicks; if(cpuDmaTicksToUpdate < 0) cpuDmaTicksToUpdate = 0; + cpuDmaHack = true; goto updateLoop; } @@ -3889,35 +4305,68 @@ if(stopState) res &= 0x3080; if(res) { - if(intState) { - CPUInterrupt(); - intState = false; - if(holdState) { + if (intState) + { + if (!IRQTicks) + { + CPUInterrupt(); + intState = false; holdState = false; stopState = false; - } - } else { - if(!holdState) { + holdType = 0; + } + } + else + { + if (!holdState) + { intState = true; - cpuLoopTicks = 5; - cpuSavedTicks = 5; - } else { - CPUInterrupt(); - if(holdState) { - holdState = false; - stopState = false; - } + IRQTicks=7; + if (cpuNextEvent> IRQTicks) + cpuNextEvent = IRQTicks; + } + else + { + CPUInterrupt(); + holdState = false; + stopState = false; + holdType = 0; } } + + // Stops the SWI Ticks emulation if an IRQ is executed + //(to avoid problems with nested IRQ/SWI) + if (SWITicks) + SWITicks = 0; } } - - if(ticks <= 0) + + if(remainingTicks > 0) { + if(remainingTicks > cpuNextEvent) + clockTicks = cpuNextEvent; + else + clockTicks = remainingTicks; + remainingTicks -= clockTicks; + if(remainingTicks < 0) + remainingTicks = 0; + goto updateLoop; + } + + if (timerOnOffDelay) + applyTimer(); + + if(cpuNextEvent > ticks) + cpuNextEvent = ticks; + + if(ticks <= 0 || cpuBreakLoop) break; + } } } + + struct EmulatedSystem GBASystem = { // emuMain CPULoop, @@ -3931,7 +4380,7 @@ CPUWriteBatteryFile, // emuReadState CPUReadState, - // emuWriteState + // emuWriteState CPUWriteState, // emuReadMemState CPUReadMemState, diff -urN ../VisualBoyAdvance-1.7.2/src/GBA.h ./src/GBA.h --- ../VisualBoyAdvance-1.7.2/src/GBA.h 2004-05-13 23:04:58 +0900 +++ ./src/GBA.h 2006-08-25 23:13:38 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -30,7 +30,8 @@ #define SAVE_GAME_VERSION_6 6 #define SAVE_GAME_VERSION_7 7 #define SAVE_GAME_VERSION_8 8 -#define SAVE_GAME_VERSION SAVE_GAME_VERSION_8 +#define SAVE_GAME_VERSION_9 9 +#define SAVE_GAME_VERSION SAVE_GAME_VERSION_9 typedef struct { u8 *address; @@ -83,8 +84,17 @@ extern int armMode; extern void (*cpuSaveGameFunc)(u32,u8); -extern bool freezeWorkRAM[0x40000]; -extern bool freezeInternalRAM[0x8000]; +#ifdef BKPT_SUPPORT +extern u8 freezeWorkRAM[0x40000]; +extern u8 freezeInternalRAM[0x8000]; +extern u8 freezeVRAM[0x18000]; +extern u8 freezeOAM[0x400]; +extern u8 freezePRAM[0x400]; +extern bool debugger_last; +extern int oldreg[17]; +extern char oldbuffer[10]; +#endif + extern bool CPUReadGSASnapshot(const char *); extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *); extern bool CPUWriteBatteryFile(const char *); @@ -100,7 +110,9 @@ extern bool CPUWriteMemState(char *, int); extern bool CPUWriteState(const char *); extern int CPULoadRom(const char *); +extern void doMirroring(bool); extern void CPUUpdateRegister(u32, u16); +extern void applyTimer (); extern void CPUWriteHalfWord(u32, u16); extern void CPUWriteByte(u32, u8); extern void CPUInit(const char *,bool); @@ -110,7 +122,8 @@ extern bool CPUIsGBAImage(const char *); extern bool CPUIsZipFile(const char *); #ifdef PROFILING -extern void cpuProfil(char *buffer, int, u32, int); +#include "prof/prof.h" +extern void cpuProfil(profile_segment *seg); extern void cpuEnableProfiling(int hz); #endif diff -urN ../VisualBoyAdvance-1.7.2/src/GBAinline.h ./src/GBAinline.h --- ../VisualBoyAdvance-1.7.2/src/GBAinline.h 2004-05-13 23:04:44 +0900 +++ ./src/GBAinline.h 2006-09-04 06:52:25 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -28,6 +28,21 @@ extern bool cpuFlashEnabled; extern bool cpuEEPROMEnabled; extern bool cpuEEPROMSensorEnabled; +extern bool cpuDmaHack; +extern u32 cpuDmaLast; +extern bool timer0On; +extern int timer0Ticks; +extern int timer0ClockReload; +extern bool timer1On; +extern int timer1Ticks; +extern int timer1ClockReload; +extern bool timer2On; +extern int timer2Ticks; +extern int timer2ClockReload; +extern bool timer3On; +extern int timer3Ticks; +extern int timer3ClockReload; +extern int cpuTotalTicks; #define CPUReadByteQuick(addr) \ map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] @@ -38,7 +53,7 @@ #define CPUReadMemoryQuick(addr) \ READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) -inline u32 CPUReadMemory(u32 address) +static inline u32 CPUReadMemory(u32 address) { #ifdef DEV_VERSION @@ -86,7 +101,15 @@ value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); break; case 6: - value = READ32LE(((u32 *)&vram[address & 0x1fffc])); + address = (address & 0x1fffc); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + { + value = 0; + break; + } + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + value = READ32LE(((u32 *)&vram[address])); break; case 7: value = READ32LE(((u32 *)&oam[address & 0x3FC])); @@ -116,18 +139,17 @@ armNextPC - 4 : armNextPC - 2); } #endif - - // if(ioMem[0x205] & 0x40) { + + if(cpuDmaHack) { + value = cpuDmaLast; + } else { if(armState) { value = CPUReadMemoryQuick(reg[15].I); } else { value = CPUReadHalfWordQuick(reg[15].I) | CPUReadHalfWordQuick(reg[15].I) << 16; } - // } else { - // value = *((u32 *)&bios[address & 0x3ffc]); - // } - // return 0xFFFFFFFF; + } } if(address & 3) { @@ -156,7 +178,7 @@ extern u32 myROM[]; -inline u32 CPUReadHalfWord(u32 address) +static inline u32 CPUReadHalfWord(u32 address) { #ifdef DEV_VERSION if(address & 1) { @@ -192,14 +214,38 @@ break; case 4: if((address < 0x4000400) && ioReadable[address & 0x3fe]) + { value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); + if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E)) + { + 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); + } + } else goto unreadable; break; case 5: value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); break; case 6: - value = READ16LE(((u16 *)&vram[address & 0x1fffe])); + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + { + value = 0; + break; + } + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + value = READ16LE(((u16 *)&vram[address])); break; case 7: value = READ16LE(((u16 *)&oam[address & 0x3fe])); @@ -232,11 +278,8 @@ armNextPC - 4 : armNextPC - 2); } #endif - extern bool cpuDmaHack; - extern u32 cpuDmaLast; - extern int cpuDmaCount; - if(cpuDmaHack && cpuDmaCount) { - value = (u16)cpuDmaLast; + if(cpuDmaHack) { + value = cpuDmaLast & 0xFFFF; } else { if(armState) { value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); @@ -244,10 +287,6 @@ value = CPUReadHalfWordQuick(reg[15].I); } } - // return value; - // if(address & 1) - // value = (value >> 8) | ((value & 0xFF) << 24); - // return 0xFFFF; break; } @@ -258,7 +297,7 @@ return value; } -inline u16 CPUReadHalfWordSigned(u32 address) +static inline u16 CPUReadHalfWordSigned(u32 address) { u16 value = CPUReadHalfWord(address); if((address & 1)) @@ -266,7 +305,7 @@ return value; } -inline u8 CPUReadByte(u32 address) +static inline u8 CPUReadByte(u32 address) { switch(address >> 24) { case 0: @@ -293,7 +332,12 @@ case 5: return paletteRAM[address & 0x3ff]; case 6: - return vram[address & 0x1ffff]; + address = (address & 0x1ffff); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return 0; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + return vram[address]; case 7: return oam[address & 0x3ff]; case 8: @@ -325,28 +369,31 @@ default: unreadable: #ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal byte read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } #endif - - if(armState) { - return CPUReadByteQuick(reg[15].I+(address & 3)); + if(cpuDmaHack) { + return cpuDmaLast & 0xFF; } else { - return CPUReadByteQuick(reg[15].I+(address & 1)); + if(armState) { + return CPUReadByteQuick(reg[15].I+(address & 3)); + } else { + return CPUReadByteQuick(reg[15].I+(address & 1)); + } } - // return 0xFF; break; } } -inline void CPUWriteMemory(u32 address, u32 value) +static inline void CPUWriteMemory(u32 address, u32 value) { + #ifdef DEV_VERSION if(address & 3) { if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaliagned word write: %08x to %08x from %08x\n", + log("Unaligned word write: %08x to %08x from %08x\n", value, address, armMode ? armNextPC - 4 : armNextPC - 2); @@ -356,39 +403,60 @@ switch(address >> 24) { case 0x02: -#ifdef SDL +#ifdef BKPT_SUPPORT if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) - cheatsWriteMemory((u32 *)&workRAM[address & 0x3FFFC], - value, - *((u32 *)&freezeWorkRAM[address & 0x3FFFC])); + cheatsWriteMemory(address & 0x203FFFC, + value); else #endif WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); break; case 0x03: -#ifdef SDL +#ifdef BKPT_SUPPORT if(*((u32 *)&freezeInternalRAM[address & 0x7ffc])) - cheatsWriteMemory((u32 *)&internalRAM[address & 0x7FFC], - value, - *((u32 *)&freezeInternalRAM[address & 0x7ffc])); + cheatsWriteMemory(address & 0x3007FFC, + value); else #endif WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); break; case 0x04: - CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); - CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); + if(address < 0x4000400) { + CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); + CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); + } else goto unwritable; break; case 0x05: +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezePRAM[address & 0x3fc])) + cheatsWriteMemory(address & 0x70003FC, + value); + else +#endif WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); break; case 0x06: - if(address & 0x10000) - WRITE32LE(((u32 *)&vram[address & 0x17ffc]), value); + address = (address & 0x1fffc); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezeVRAM[address])) + cheatsWriteMemory(address + 0x06000000, value); else - WRITE32LE(((u32 *)&vram[address & 0x1fffc]), value); +#endif + + WRITE32LE(((u32 *)&vram[address]), value); break; case 0x07: +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezeOAM[address & 0x3fc])) + cheatsWriteMemory(address & 0x70003FC, + value); + else +#endif WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); break; case 0x0D: diff -urN ../VisualBoyAdvance-1.7.2/src/Gfx.cpp ./src/Gfx.cpp --- ../VisualBoyAdvance-1.7.2/src/Gfx.cpp 2004-05-13 23:37:47 +0900 +++ ./src/Gfx.cpp 2005-09-03 21:28:23 +0900 @@ -22,7 +22,6 @@ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; - u32 line0[240]; u32 line1[240]; u32 line2[240]; @@ -32,6 +31,7 @@ u32 lineMix[240]; bool gfxInWin0[240]; bool gfxInWin1[240]; +int lineOBJpixleft[128]; int gfxBG2Changed = 0; int gfxBG3Changed = 0; diff -urN ../VisualBoyAdvance-1.7.2/src/Gfx.h ./src/Gfx.h --- ../VisualBoyAdvance-1.7.2/src/Gfx.h 2004-05-13 23:04:18 +0900 +++ ./src/Gfx.h 2006-08-25 23:50:53 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -100,6 +100,7 @@ extern u32 lineMix[240]; extern bool gfxInWin0[240]; extern bool gfxInWin1[240]; +extern int lineOBJpixleft[128]; extern int gfxBG2Changed; extern int gfxBG3Changed; @@ -305,7 +306,7 @@ int dy = pc & 0x7FFF; if(pc & 0x8000) dy |= 0xFFFF8000; - int dmy = pd & 0x7FFFF; + int dmy = pd & 0x7FFF; if(pd & 0x8000) dmy |= 0xFFFF8000; @@ -462,7 +463,7 @@ int dy = pc & 0x7FFF; if(pc & 0x8000) dy |= 0xFFFF8000; - int dmy = pd & 0x7FFFF; + int dmy = pd & 0x7FFF; if(pd & 0x8000) dmy |= 0xFFFF8000; @@ -560,7 +561,7 @@ int dy = pc & 0x7FFF; if(pc & 0x8000) dy |= 0xFFFF8000; - int dmy = pd & 0x7FFFF; + int dmy = pd & 0x7FFF; if(pd & 0x8000) dmy |= 0xFFFF8000; @@ -661,7 +662,7 @@ int dy = pc & 0x7FFF; if(pc & 0x8000) dy |= 0xFFFF8000; - int dmy = pd & 0x7FFFF; + int dmy = pd & 0x7FFF; if(pd & 0x8000) dmy |= 0xFFFF8000; @@ -731,6 +732,10 @@ inline void gfxDrawSprites(u32 *lineOBJ) { + // lineOBJpix is used to keep track of the drawn OBJs + // and to stop drawing them if the 'maximum number of OBJ per line' + // has been reached. + int lineOBJpix = (DISPCNT & 0x20) ? 954 : 1226; int m=0; gfxClearArray(lineOBJ); if(layerEnable & 0x1000) { @@ -744,55 +749,37 @@ u16 a2 = READ16LE(sprites++); sprites++; - // ignore OBJ-WIN - if((a0 & 0x0c00) == 0x0800) - continue; - - int sizeY = 8; - int sizeX = 8; - - switch(((a0 >>12) & 0x0c)|(a1>>14)) { - case 0: - break; - case 1: - sizeX = sizeY = 16; - break; - case 2: - sizeX = sizeY = 32; - break; - case 3: - sizeX = sizeY = 64; - break; - case 4: - sizeX = 16; - break; - case 5: - sizeX = 32; - break; - case 6: - sizeX = 32; - sizeY = 16; - break; - case 7: - sizeX = 64; - sizeY = 32; - break; - case 8: - sizeY = 16; - break; - case 9: - sizeY = 32; - break; - case 10: - sizeX = 16; - sizeY = 32; - break; - case 11: - sizeX = 32; - sizeY = 64; - break; - default: + lineOBJpixleft[x]=lineOBJpix; + + lineOBJpix-=2; + if (lineOBJpix<=0) continue; + + if ((a0 & 0x0c00) == 0x0c00) + a0 &=0xF3FF; + + if ((a0>>14) == 3) + { + a0 &= 0x3FFF; + a1 &= 0x3FFF; + } + + int sizeX = 8<<(a1>>14); + int sizeY = sizeX; + + if ((a0>>14) & 1) + { + if (sizeX<32) + sizeX<<=1; + if (sizeY>8) + sizeY>>=1; + } + else if ((a0>>14) & 2) + { + if (sizeX>8) + sizeX>>=1; + if (sizeY<32) + sizeY<<=1; } #ifdef SPRITE_DEBUG @@ -801,9 +788,45 @@ #endif int sy = (a0 & 255); + int sx = (a1 & 0x1FF); + + // computes ticks used by OBJ-WIN if OBJWIN is enabled + if (((a0 & 0x0c00) == 0x0800) && (layerEnable & 0x8000)) + { + if ((a0 & 0x0300) == 0x0300) + { + sizeX<<=1; + sizeY<<=1; + } + if((sy+sizeY) > 256) + sy -= 256; + if ((sx+sizeX)> 512) + sx-=512; + if (sx<0) + { + sizeX+=sx; + sx = 0; + } + else if ((sx+sizeX)>240) + sizeX=240-sx; + if ((VCOUNT>=sy) && (VCOUNT 160) - sy -= 256; if(a0 & 0x0100) { int fieldX = sizeX; @@ -812,11 +835,18 @@ fieldX <<= 1; fieldY <<= 1; } - + if((sy+fieldY) > 256) + sy -= 256; int t = VCOUNT - sy; if((t >= 0) && (t < fieldY)) { - int sx = (a1 & 0x1FF); - if((sx < 240) || (((sx + fieldX) & 511) < 240)) { + int startpix = 0; + if ((sx+fieldX)> 512) + { + startpix=512-sx; + } + if (lineOBJpix>0) + if((sx < 240) || startpix) { + lineOBJpix-=8; // int t2 = t - (fieldY >> 1); int rot = (a1 >> 9) & 0x1F; u16 *OAM = (u16 *)oam; @@ -854,6 +884,10 @@ else c &= 0x3FE; for(int x = 0; x < fieldX; x++) { + if (x >= startpix) + lineOBJpix-=2; + if (lineOBJpix<0) + continue; int xxx = realX >> 8; int yyy = realY >> 8; @@ -885,7 +919,7 @@ lineOBJ[sx] = 0x001F; #endif } - sx = (sx+1)&511;; + sx = (sx+1)&511; realX += dx; realY += dy; } @@ -897,8 +931,12 @@ int inc = 32; if(DISPCNT & 0x40) inc = sizeX >> 3; - int palette = (a2 >> 8) & 0xF0; + int palette = (a2 >> 8) & 0xF0; for(int x = 0; x < fieldX; x++) { + if (x >= startpix) + lineOBJpix-=2; + if (lineOBJpix<0) + continue; int xxx = realX >> 8; int yyy = realY >> 8; if(xxx < 0 || xxx >= sizeX || @@ -934,7 +972,7 @@ if(t == 0 || t == maskY || x == 0 || x == maskX) lineOBJ[sx] = 0x001F; #endif - sx = (sx+1)&511;; + sx = (sx+1)&511; realX += dx; realY += dy; @@ -943,10 +981,17 @@ } } } else { + if(sy+sizeY > 256) + sy -= 256; int t = VCOUNT - sy; if((t >= 0) && (t < sizeY)) { - int sx = (a1 & 0x1FF); - if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) { + int startpix = 0; + if ((sx+sizeX)> 512) + { + startpix=512-sx; + } + if((sx < 240) || startpix) { + lineOBJpix+=2; if(a0 & 0x2000) { if(a1 & 0x2000) t = sizeY - t - 1; @@ -976,6 +1021,10 @@ u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); for(int xx = 0; xx < sizeX; xx++) { + if (xx >= startpix) + lineOBJpix--; + if (lineOBJpix<0) + continue; if(sx < 240) { u8 color = vram[address]; if ((color==0) && (((prio >> 25)&3) < @@ -1048,6 +1097,10 @@ if(a1 & 0x1000) { xxx = 7; for(int xx = sizeX - 1; xx >= 0; xx--) { + if (xx >= startpix) + lineOBJpix--; + if (lineOBJpix<0) + continue; if(sx < 240) { u8 color = vram[address]; if(xx & 1) { @@ -1088,6 +1141,10 @@ } } else { for(int xx = 0; xx < sizeX; xx++) { + if (xx >= startpix) + lineOBJpix--; + if (lineOBJpix<0) + continue; if(sx < 240) { u8 color = vram[address]; if(xx & 1) { @@ -1139,70 +1196,51 @@ inline void gfxDrawOBJWin(u32 *lineOBJWin) { gfxClearArray(lineOBJWin); - if(layerEnable & 0x8000) { + if((layerEnable & 0x9000) == 0x9000) { u16 *sprites = (u16 *)oam; // u16 *spritePalette = &((u16 *)paletteRAM)[256]; for(int x = 0; x < 128 ; x++) { + int lineOBJpix = lineOBJpixleft[x]; u16 a0 = READ16LE(sprites++); u16 a1 = READ16LE(sprites++); u16 a2 = READ16LE(sprites++); sprites++; - // ignore non OBJ-WIN - if((a0 & 0x0c00) != 0x0800) + if (lineOBJpix<=0) continue; + + // ignores non OBJ-WIN and disabled OBJ-WIN + if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200)) + continue; + + if ((a0 & 0x0c00) == 0x0c00) + a0 &=0xF3FF; - int sizeY = 8; - int sizeX = 8; + if ((a0>>14) == 3) + { + a0 &= 0x3FFF; + a1 &= 0x3FFF; + } - switch(((a0 >>12) & 0x0c)|(a1>>14)) { - case 0: - break; - case 1: - sizeX = sizeY = 16; - break; - case 2: - sizeX = sizeY = 32; - break; - case 3: - sizeX = sizeY = 64; - break; - case 4: - sizeX = 16; - break; - case 5: - sizeX = 32; - break; - case 6: - sizeX = 32; - sizeY = 16; - break; - case 7: - sizeX = 64; - sizeY = 32; - break; - case 8: - sizeY = 16; - break; - case 9: - sizeY = 32; - break; - case 10: - sizeX = 16; - sizeY = 32; - break; - case 11: - sizeX = 32; - sizeY = 64; - break; - default: - continue; + int sizeX = 8<<(a1>>14); + int sizeY = sizeX; + + if ((a0>>14) & 1) + { + if (sizeX<32) + sizeX<<=1; + if (sizeY>8) + sizeY>>=1; + } + else if ((a0>>14) & 2) + { + if (sizeX>8) + sizeX>>=1; + if (sizeY<32) + sizeY<<=1; } int sy = (a0 & 255); - - if(sy > 160) - sy -= 256; if(a0 & 0x0100) { int fieldX = sizeX; @@ -1211,11 +1249,18 @@ fieldX <<= 1; fieldY <<= 1; } - + if((sy+fieldY) > 256) + sy -= 256; int t = VCOUNT - sy; if((t >= 0) && (t < fieldY)) { int sx = (a1 & 0x1FF); - if((sx < 240) || (((sx + fieldX) & 511) < 240)) { + int startpix = 0; + if ((sx+fieldX)> 512) + { + startpix=512-sx; + } + if((sx < 240) || startpix) { + lineOBJpix-=8; // int t2 = t - (fieldY >> 1); int rot = (a1 >> 9) & 0x1F; u16 *OAM = (u16 *)oam; @@ -1249,11 +1294,16 @@ else c &= 0x3FE; for(int x = 0; x < fieldX; x++) { + if (x >= startpix) + lineOBJpix-=2; + if (lineOBJpix<0) + continue; int xxx = realX >> 8; int yyy = realY >> 8; if(xxx < 0 || xxx >= sizeX || - yyy < 0 || yyy >= sizeY) { + yyy < 0 || yyy >= sizeY || + sx >= 240) { } else { u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + @@ -1262,7 +1312,7 @@ lineOBJWin[sx] = 1; } } - sx = (sx+1)&511;; + sx = (sx+1)&511; realX += dx; realY += dy; } @@ -1276,6 +1326,10 @@ inc = sizeX >> 3; // int palette = (a2 >> 8) & 0xF0; for(int x = 0; x < fieldX; x++) { + if (x >= startpix) + lineOBJpix-=2; + if (lineOBJpix<0) + continue; int xxx = realX >> 8; int yyy = realY >> 8; @@ -1284,7 +1338,8 @@ // lineOBJ[sx] = 0x001F | prio; // } else { if(xxx < 0 || xxx >= sizeX || - yyy < 0 || yyy >= sizeY){ + yyy < 0 || yyy >= sizeY || + sx >= 240) { } else { u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + @@ -1299,7 +1354,7 @@ } } // } - sx = (sx+1)&511;; + sx = (sx+1)&511; realX += dx; realY += dy; } @@ -1307,10 +1362,18 @@ } } } else { + if((sy+sizeY) > 256) + sy -= 256; int t = VCOUNT - sy; if((t >= 0) && (t < sizeY)) { int sx = (a1 & 0x1FF); - if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) { + int startpix = 0; + if ((sx+sizeX)> 512) + { + startpix=512-sx; + } + if((sx < 240) || startpix) { + lineOBJpix+=2; if(a0 & 0x2000) { if(a1 & 0x2000) t = sizeY - t - 1; @@ -1333,6 +1396,10 @@ xxx = 7; // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); for(int xx = 0; xx < sizeX; xx++) { + if (xx >= startpix) + lineOBJpix--; + if (lineOBJpix<0) + continue; if(sx < 240) { u8 color = vram[address]; if(color) { @@ -1382,6 +1449,10 @@ if(a1 & 0x1000) { xxx = 7; for(int xx = sizeX - 1; xx >= 0; xx--) { + if (xx >= startpix) + lineOBJpix--; + if (lineOBJpix<0) + continue; if(sx < 240) { u8 color = vram[address]; if(xx & 1) { @@ -1406,6 +1477,10 @@ } } else { for(int xx = 0; xx < sizeX; xx++) { + if (xx >= startpix) + lineOBJpix--; + if (lineOBJpix<0) + continue; if(sx < 240) { u8 color = vram[address]; if(xx & 1) { @@ -1528,10 +1603,10 @@ int g0 = ((color2 >> 5) & 0x1F); int b0 = ((color2 >> 10) & 0x1F); - r = ((r * ca) >> 4) + ((r0 * cb) >> 4); - g = ((g * ca) >> 4) + ((g0 * cb) >> 4); - b = ((b * ca) >> 4) + ((b0 * cb) >> 4); - + r = ((r * ca) + (r0 * cb)) >> 4; + g = ((g * ca) + (g0 * cb)) >> 4; + b = ((b * ca) + (b0 * cb)) >> 4; + if(r > 31) r = 31; if(g > 31) @@ -1557,9 +1632,9 @@ int g0 = ((color2 >> 5) & 0x1F); int b0 = ((color2 >> 10) & 0x1F); - r = ((r * ca) >> 4) + ((r0 * cb) >> 4); - g = ((g * ca) >> 4) + ((g0 * cb) >> 4); - b = ((b * ca) >> 4) + ((b0 * cb) >> 4); + r = ((r * ca) + (r0 * cb)) >> 4; + g = ((g * ca) + (g0 * cb)) >> 4; + b = ((b * ca) + (b0 * cb)) >> 4; if(r > 31) r = 31; diff -urN ../VisualBoyAdvance-1.7.2/src/Globals.cpp ./src/Globals.cpp --- ../VisualBoyAdvance-1.7.2/src/Globals.cpp 2004-05-13 23:37:29 +0900 +++ ./src/Globals.cpp 2006-08-01 00:51:01 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -18,6 +18,11 @@ #include "GBA.h" +#ifdef BKPT_SUPPORT +int oldreg[17]; +char oldbuffer[10]; +#endif + reg_pair reg[45]; memoryMap map[256]; bool ioReadable[0x400]; @@ -43,8 +48,8 @@ int layerEnable = 0xff00; bool speedHack = false; int cpuSaveType = 0; -bool cpuEnhancedDetection = true; bool cheatsEnabled = true; +bool mirroringEnable = false; u8 *bios = NULL; u8 *rom = NULL; diff -urN ../VisualBoyAdvance-1.7.2/src/Globals.h ./src/Globals.h --- ../VisualBoyAdvance-1.7.2/src/Globals.h 2004-05-13 23:04:03 +0900 +++ ./src/Globals.h 2006-08-01 00:51:01 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -20,6 +20,8 @@ #ifndef VBA_GLOBALS_H #define VBA_GLOBALS_H +#include "GBA.h" + #define VERBOSE_SWI 1 #define VERBOSE_UNALIGNED_MEMORY 2 #define VERBOSE_ILLEGAL_WRITE 4 @@ -55,8 +57,8 @@ extern int layerEnable; extern bool speedHack; extern int cpuSaveType; -extern bool cpuEnhancedDetection; extern bool cheatsEnabled; +extern bool mirroringEnable; extern u8 *bios; extern u8 *rom; diff -urN ../VisualBoyAdvance-1.7.2/src/Makefile.in ./src/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/Makefile.in 2004-05-21 03:17:48 +0900 +++ ./src/Makefile.in 2004-09-30 07:23:29 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/NLS.h ./src/NLS.h --- ../VisualBoyAdvance-1.7.2/src/NLS.h 2004-05-13 23:03:44 +0900 +++ ./src/NLS.h 2006-06-07 00:19:25 +0900 @@ -60,3 +60,5 @@ #define MSG_INVALID_CBA_CODE 39 #define MSG_CBA_CODE_WARNING 40 #define MSG_OUT_OF_MEMORY 41 +#define MSG_WRONG_GAMESHARK_CODE 42 +#define MSG_UNSUPPORTED_GAMESHARK_CODE 43 diff -urN ../VisualBoyAdvance-1.7.2/src/RTC.cpp ./src/RTC.cpp --- ../VisualBoyAdvance-1.7.2/src/RTC.cpp 2004-05-13 23:36:17 +0900 +++ ./src/RTC.cpp 2006-01-04 22:42:59 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -119,6 +119,8 @@ rtcClockData.data[0] = 0x40; rtcClockData.state = DATA; break; + case 0x64: + break; case 0x65: { struct tm *newtime; @@ -131,7 +133,7 @@ rtcClockData.data[0] = toBCD(newtime->tm_year); rtcClockData.data[1] = toBCD(newtime->tm_mon+1); rtcClockData.data[2] = toBCD(newtime->tm_mday); - rtcClockData.data[3] = 0; + rtcClockData.data[3] = toBCD(newtime->tm_wday); rtcClockData.data[4] = toBCD(newtime->tm_hour); rtcClockData.data[5] = toBCD(newtime->tm_min); rtcClockData.data[6] = toBCD(newtime->tm_sec); diff -urN ../VisualBoyAdvance-1.7.2/src/Sound.cpp ./src/Sound.cpp --- ../VisualBoyAdvance-1.7.2/src/Sound.cpp 2004-05-13 23:36:07 +0900 +++ ./src/Sound.cpp 2006-08-25 22:30:08 +0900 @@ -1,6 +1,7 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -18,15 +19,16 @@ #include +#include "Sound.h" + #include "GBA.h" #include "Globals.h" -#include "Sound.h" #include "Util.h" #define USE_TICKS_AS 380 #define SOUND_MAGIC 0x60000000 #define SOUND_MAGIC_2 0x30000000 -#define NOISE_MAGIC 5 +#define NOISE_MAGIC 5 extern bool stopState; @@ -387,8 +389,8 @@ sound2Index = 0; sound2On = 1; } - break; - ioMem[address] = data; + ioMem[address] = data; + break; case NR30: data &= 0xe0; if(!(data & 0x80)) { @@ -541,7 +543,7 @@ switch(address) { case SGCNT0_H: data &= 0xFF0F; - soundControl = data & 0x770F;; + soundControl = data & 0x770F; if(data & 0x0800) { soundDSFifoAWriteIndex = 0; soundDSFifoAIndex = 0; @@ -560,7 +562,7 @@ } soundDSBEnabled = (data & 0x3000) ? true : false; soundDSBTimer = (data & 0x4000) ? 1 : 0; - *((u16 *)&ioMem[address]) = data; + *((u16 *)&ioMem[address]) = soundControl; break; case FIFOA_L: case FIFOA_H: @@ -865,7 +867,7 @@ } soundDSAValue = (soundDSFifoA[soundDSFifoAIndex]); - soundDSFifoAIndex = (++soundDSFifoAIndex) & 31; + soundDSFifoAIndex = (soundDSFifoAIndex + 1) & 31; soundDSFifoACount--; } else soundDSAValue = 0; @@ -894,7 +896,7 @@ } soundDSBValue = (soundDSFifoB[soundDSFifoBIndex]); - soundDSFifoBIndex = (++soundDSFifoBIndex) & 31; + soundDSFifoBIndex = (soundDSFifoBIndex + 1) & 31; soundDSFifoBCount--; } else { soundDSBValue = 0; diff -urN ../VisualBoyAdvance-1.7.2/src/Sound.h ./src/Sound.h --- ../VisualBoyAdvance-1.7.2/src/Sound.h 2004-05-13 23:03:07 +0900 +++ ./src/Sound.h 2006-06-07 06:04:20 +0900 @@ -2,6 +2,7 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -20,6 +21,8 @@ #ifndef VBA_SOUND_H #define VBA_SOUND_H +#include "System.h" + #define NR10 0x60 #define NR11 0x62 #define NR12 0x63 @@ -47,23 +50,22 @@ #define FIFOB_L 0xa4 #define FIFOB_H 0xa6 -extern void soundTick(); -extern void soundShutdown(); -extern bool soundInit(); -extern void soundPause(); -extern void soundResume(); -extern void soundEnable(int); -extern void soundDisable(int); -extern int soundGetEnable(); -extern void soundReset(); -extern void soundSaveGame(gzFile); -extern void soundReadGame(gzFile, int); -extern void soundEvent(u32, u8); -extern void soundEvent(u32, u16); -extern void soundTimerOverflow(int); -extern void soundSetQuality(int); +void soundTick(); +void soundShutdown(); +bool soundInit(); +void soundPause(); +void soundResume(); +void soundEnable(int); +void soundDisable(int); +int soundGetEnable(); +void soundReset(); +void soundSaveGame(gzFile); +void soundReadGame(gzFile, int); +void soundEvent(u32, u8); +void soundEvent(u32, u16); +void soundTimerOverflow(int); +void soundSetQuality(int); -//extern int SOUND_TICKS; extern int SOUND_CLOCK_TICKS; extern int soundTicks; extern int soundPaused; diff -urN ../VisualBoyAdvance-1.7.2/src/Sram.cpp ./src/Sram.cpp --- ../VisualBoyAdvance-1.7.2/src/Sram.cpp 2004-05-13 23:35:57 +0900 +++ ./src/Sram.cpp 2004-11-15 03:54:14 +0900 @@ -17,6 +17,7 @@ // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "GBA.h" +#include "Globals.h" #include "Flash.h" #include "Sram.h" @@ -24,6 +25,12 @@ { return flashSaveMemory[address & 0xFFFF]; } +void sramDelayedWrite(u32 address, u8 byte) +{ + saveType = 1; + cpuSaveGameFunc = sramWrite; + sramWrite(address, byte); +} void sramWrite(u32 address, u8 byte) { diff -urN ../VisualBoyAdvance-1.7.2/src/Sram.h ./src/Sram.h --- ../VisualBoyAdvance-1.7.2/src/Sram.h 2004-05-13 23:02:56 +0900 +++ ./src/Sram.h 2004-11-15 03:54:14 +0900 @@ -22,5 +22,6 @@ extern u8 sramRead(u32 address); extern void sramWrite(u32 address, u8 byte); +extern void sramDelayedWrite(u32 address, u8 byte); #endif // VBA_SRAM_H diff -urN ../VisualBoyAdvance-1.7.2/src/System.h ./src/System.h --- ../VisualBoyAdvance-1.7.2/src/System.h 2004-05-13 23:02:43 +0900 +++ ./src/System.h 2006-06-22 01:58:15 +0900 @@ -106,6 +106,12 @@ extern void systemFrame(); extern void systemGbBorderOn(); +extern void Sm60FPS_Init(); +extern bool Sm60FPS_CanSkipFrame(); +extern void Sm60FPS_Sleep(); +extern void DbgMsg(const char *msg, ...); +extern void winlog(const char *,...); + extern bool systemSoundOn; extern u16 systemColorMap16[0x10000]; extern u32 systemColorMap32[0x10000]; @@ -118,6 +124,7 @@ extern int systemVerbose; extern int systemFrameSkip; extern int systemSaveUpdateCounter; +extern int systemSpeed; #define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_NOT_UPDATED 0 diff -urN ../VisualBoyAdvance-1.7.2/src/Util.cpp ./src/Util.cpp --- ../VisualBoyAdvance-1.7.2/src/Util.cpp 2004-05-21 02:42:37 +0900 +++ ./src/Util.cpp 2006-05-27 23:47:32 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -47,9 +47,17 @@ #define _stricmp strcasecmp #endif // ! _MSC_VER -static int (*utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL; -static int (*utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL; -static int (*utilGzCloseFunc)(gzFile) = NULL; +extern int systemColorDepth; +extern int systemRedShift; +extern int systemGreenShift; +extern int systemBlueShift; + +extern u16 systemColorMap16[0x10000]; +extern u32 systemColorMap32[0x10000]; + +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; bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix) { @@ -478,7 +486,7 @@ { cpuIsMultiBoot = false; if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".gba") == 0) @@ -502,7 +510,7 @@ bool utilIsGBImage(const char * file) { if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".gb") == 0) @@ -522,7 +530,7 @@ bool utilIsZipFile(const char *file) { if(strlen(file) > 4) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".zip") == 0) @@ -552,7 +560,7 @@ bool utilIsGzipFile(const char *file) { if(strlen(file) > 3) { - char * p = strrchr(file,'.'); + const char * p = strrchr(file,'.'); if(p != NULL) { if(_stricmp(p, ".gz") == 0) @@ -937,11 +945,11 @@ } size = fileSize; } - int read = fileSize <= size ? fileSize : size; - int r = fread(image, 1, read, f); + size_t read = fileSize <= size ? fileSize : size; + size_t r = fread(image, 1, read, f); fclose(f); - if(r != (int)read) { + if(r != read) { systemMessage(MSG_ERROR_READING_IMAGE, N_("Error reading image %s"), file); if(data == NULL) @@ -984,7 +992,7 @@ gzFile utilGzOpen(const char *file, const char *mode) { - utilGzWriteFunc = (int (*)(void *,void * const, unsigned int))gzwrite; + utilGzWriteFunc = (int (ZEXPORT *)(void *,void * const, unsigned int))gzwrite; utilGzReadFunc = gzread; utilGzCloseFunc = gzclose; @@ -1034,22 +1042,22 @@ if(d == 0x52504545) { if(memcmp(p, "EEPROM_", 7) == 0) { if(saveType == 0) - saveType = 1; + saveType = 3; } } else if (d == 0x4D415253) { if(memcmp(p, "SRAM_", 5) == 0) { if(saveType == 0) - saveType = 2; + saveType = 1; } } else if (d == 0x53414C46) { if(memcmp(p, "FLASH1M_", 8) == 0) { if(saveType == 0) { - saveType = 3; + saveType = 2; flashSize = 0x20000; } } else if(memcmp(p, "FLASH", 5) == 0) { if(saveType == 0) { - saveType = 3; + saveType = 2; flashSize = 0x10000; } } @@ -1067,3 +1075,28 @@ cpuSaveType = saveType; flashSetSize(flashSize); } + +void utilUpdateSystemColorMaps() +{ + switch(systemColorDepth) { + case 16: + { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + } + 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); + } + } + break; + } +} diff -urN ../VisualBoyAdvance-1.7.2/src/Util.h ./src/Util.h --- ../VisualBoyAdvance-1.7.2/src/Util.h 2004-05-13 23:02:08 +0900 +++ ./src/Util.h 2004-09-16 07:12:52 +0900 @@ -61,4 +61,5 @@ extern int utilGzClose(gzFile file); extern long utilGzMemTell(gzFile file); extern void utilGBAFindSave(const u8 *, const int); +extern void utilUpdateSystemColorMaps(); #endif diff -urN ../VisualBoyAdvance-1.7.2/src/arm-new.h ./src/arm-new.h --- ../VisualBoyAdvance-1.7.2/src/arm-new.h 2004-05-13 22:57:11 +0900 +++ ./src/arm-new.h 2006-08-25 22:30:08 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -1113,26 +1113,34 @@ bool C_OUT = C_FLAG;\ u32 value;\ \ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_LSL_REG\ } else {\ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1148,6 +1156,12 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_LSR_REG\ } else {\ @@ -1156,20 +1170,22 @@ }\ \ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1185,6 +1201,12 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_ASR_REG\ } else {\ @@ -1198,20 +1220,22 @@ }\ \ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1227,26 +1251,34 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_ROR_REG\ } else {\ LOGICAL_RRX_REG\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1256,12 +1288,17 @@ case BASE+1:\ {\ /* OP Rd,Rb,Rm LSL Rs */\ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ if(shift == 32) {\ value = 0;\ @@ -1276,20 +1313,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1299,12 +1338,17 @@ case BASE+3:\ {\ /* OP Rd,Rb,Rm LSR Rs */ \ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ if(shift == 32) {\ value = 0;\ @@ -1319,20 +1363,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1342,12 +1388,17 @@ case BASE+5:\ {\ /* OP Rd,Rb,Rm ASR Rs */ \ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift < 32) {\ if(shift) {\ LOGICAL_ASR_REG\ @@ -1364,20 +1415,22 @@ }\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1387,12 +1440,17 @@ case BASE+7:\ {\ /* OP Rd,Rb,Rm ROR Rs */\ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ shift &= 0x1f;\ if(shift) {\ @@ -1406,20 +1464,22 @@ C_OUT = (value & 0x80000000 ? true : false);\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1448,26 +1508,34 @@ int dest = (opcode >> 12) & 0x0F;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_ROR_IMM\ } else {\ value = opcode & 0xff;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1484,6 +1552,12 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ \ if(shift) {\ LOGICAL_LSL_REG\ @@ -1491,20 +1565,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1519,6 +1595,12 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_LSR_REG\ } else {\ @@ -1527,20 +1609,22 @@ }\ \ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1555,6 +1639,12 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_ASR_REG\ } else {\ @@ -1568,20 +1658,22 @@ }\ \ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1596,26 +1688,34 @@ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_ROR_REG\ } else {\ LOGICAL_RRX_REG\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1625,11 +1725,16 @@ case BASE+1:\ {\ /* OP Rd,Rb,Rm LSL Rs */\ - clockTicks++;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ if(shift == 32) {\ value = 0;\ @@ -1644,20 +1749,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1667,11 +1774,16 @@ case BASE+3:\ {\ /* OP Rd,Rb,Rm LSR Rs */ \ - clockTicks++;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ if(shift == 32) {\ value = 0;\ @@ -1686,20 +1798,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1709,11 +1823,16 @@ case BASE+5:\ {\ /* OP Rd,Rb,Rm ASR Rs */ \ - clockTicks++;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift < 32) {\ if(shift) {\ LOGICAL_ASR_REG\ @@ -1730,20 +1849,22 @@ }\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1753,11 +1874,16 @@ case BASE+7:\ {\ /* OP Rd,Rb,Rm ROR Rs */\ - clockTicks++;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ shift &= 0x1f;\ if(shift) {\ @@ -1771,20 +1897,22 @@ C_OUT = (value & 0x80000000 ? true : false);\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1812,26 +1940,34 @@ int dest = (opcode >> 12) & 0x0F;\ bool C_OUT = C_FLAG;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ LOGICAL_ROR_IMM\ } else {\ value = opcode & 0xff;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1848,26 +1984,34 @@ int shift = (opcode >> 7) & 0x1F;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ ARITHMETIC_LSL_REG\ } else {\ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1882,26 +2026,34 @@ int shift = (opcode >> 7) & 0x1F;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ ARITHMETIC_LSR_REG\ } else {\ value = 0;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1916,6 +2068,12 @@ int shift = (opcode >> 7) & 0x1F;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ ARITHMETIC_ASR_REG\ } else {\ @@ -1924,20 +2082,22 @@ } else value = 0;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1952,26 +2112,34 @@ int shift = (opcode >> 7) & 0x1F;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ ARITHMETIC_ROR_REG\ } else {\ ARITHMETIC_RRX_REG\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -1981,11 +2149,16 @@ case BASE+1:\ {\ /* OP Rd,Rb,Rm LSL Rs */\ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ if(shift == 32) {\ value = 0;\ @@ -1996,20 +2169,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -2019,11 +2194,16 @@ case BASE+3:\ {\ /* OP Rd,Rb,Rm LSR Rs */\ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ if(shift == 32) {\ value = 0;\ @@ -2034,20 +2214,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -2057,11 +2239,16 @@ case BASE+5:\ {\ /* OP Rd,Rb,Rm ASR Rs */\ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift < 32) {\ if(shift) {\ ARITHMETIC_ASR_REG\ @@ -2074,20 +2261,22 @@ } else value = 0;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -2097,11 +2286,16 @@ case BASE+7:\ {\ /* OP Rd,Rb,Rm ROR Rs */\ - clockTicks++;\ int base = (opcode >> 16) & 0x0F;\ int shift = reg[(opcode >> 8)&15].B.B0;\ int dest = (opcode>>12) & 15;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ if(shift) {\ shift &= 0x1f;\ if(shift) {\ @@ -2113,20 +2307,22 @@ value = reg[opcode & 0x0F].I;\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -2154,24 +2350,32 @@ int base = (opcode >> 16) & 0x0F;\ int dest = (opcode >> 12) & 0x0F;\ u32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccess32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ {\ ARITHMETIC_ROR_IMM\ }\ if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ OPCODE2\ /* todo */\ if(opcode & 0x00100000) {\ - clockTicks++;\ CPUSwitchMode(reg[17].I & 0x1f, false);\ }\ if(armState) {\ reg[15].I &= 0xFFFFFFFC;\ armNextPC = reg[15].I;\ reg[15].I += 4;\ + ARM_PREFETCH;\ } else {\ reg[15].I &= 0xFFFFFFFE;\ armNextPC = reg[15].I;\ reg[15].I += 2;\ + THUMB_PREFETCH;\ }\ } else {\ OPCODE \ @@ -2179,9 +2383,16 @@ }\ break; - u32 opcode = CPUReadMemoryQuick(armNextPC); + u32 opcode = cpuPrefetch[0]; + cpuPrefetch[0] = cpuPrefetch[1]; + + busPrefetch = false; + if (busPrefetchCount & 0xFFFFFE00) + busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF); - clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15]; + + clockTicks = 0;//codeTicksAccessSeq32(armNextPC)+1; + int oldArmNextPC = armNextPC; #ifndef FINAL_VERSION if(armNextPC == stop) { @@ -2191,6 +2402,8 @@ armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH_NEXT; + int cond = opcode >> 28; // suggested optimization for frequent cases bool cond_res; @@ -2260,18 +2473,23 @@ // MUL Rd, Rm, Rs int dest = (opcode >> 16) & 0x0F; int mult = (opcode & 0x0F); + clockTicks = 1; u32 rs = reg[(opcode >> 8) & 0x0F].I; reg[dest].I = reg[mult].I * rs; if(((s32)rs)<0) - rs = ~rs; + rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 2; + clockTicks += 0; else if ((rs & 0xFFFF0000) == 0) - clockTicks += 3; + clockTicks += 1; else if ((rs & 0xFF000000) == 0) - clockTicks += 4; + clockTicks += 2; else - clockTicks += 5; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 16) & 0x0F; int mult = (opcode & 0x0F); + clockTicks = 1; u32 rs = reg[(opcode >> 8) & 0x0F].I; reg[dest].I = reg[mult].I * rs; N_FLAG = (reg[dest].I & 0x80000000) ? true : false; @@ -2286,24 +2505,30 @@ if(((s32)rs)<0) rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 2; + clockTicks += 0; else if ((rs & 0xFFFF0000) == 0) - clockTicks += 3; + clockTicks += 1; else if ((rs & 0xFF000000) == 0) - clockTicks += 4; + clockTicks += 2; else - clockTicks += 5; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); address -= offset; reg[base].I = address; @@ -2313,11 +2538,14 @@ case 0x06b: { // STRH Rd, [Rn], #-offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); address -= offset; reg[base].I = address; @@ -2327,11 +2555,14 @@ case 0x0ab: { // STRH Rd, [Rn], Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); address += offset; reg[base].I = address; @@ -2341,11 +2572,14 @@ case 0x0eb: { // STRH Rd, [Rn], #offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); address += offset; reg[base].I = address; @@ -2354,20 +2588,26 @@ case 0x10b: { // STRH Rd, [Rn, -Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); } break; case 0x12b: { // STRH Rd, [Rn, -Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); reg[base].I = address; } @@ -2375,20 +2615,26 @@ case 0x14b: { // STRH Rd, [Rn, -#offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); } break; case 0x16b: { // STRH Rd, [Rn, -#offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); reg[base].I = address; } @@ -2396,20 +2642,26 @@ case 0x18b: { // STRH Rd, [Rn, Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); } break; case 0x1ab: { // STRH Rd, [Rn, Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); reg[base].I = address; } @@ -2417,20 +2669,26 @@ case 0x1cb: { // STRH Rd, [Rn, #offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); } break; case 0x1eb: { // STRH Rd, [Rn, #offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 4 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); CPUWriteHalfWord(address, reg[dest].W.W0); reg[base].I = address; } @@ -2439,456 +2697,852 @@ case 0x03b: { // LDRH Rd, [Rn], -Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) { address -= offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x05b: case 0x07b: { // LDRH Rd, [Rn], #-offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) { address -= offset; reg[base].I = address; } + clockTicks=0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x09b: case 0x0bb: { // LDRH Rd, [Rn], Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) { address += offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x0db: case 0x0fb: { // LDRH Rd, [Rn], #offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) { address += offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x11b: { // LDRH Rd, [Rn, -Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x13b: { // LDRH Rd, [Rn, -Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x15b: { // LDRH Rd, [Rn, -#offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x17b: { // LDRH Rd, [Rn, -#offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x19b: { // LDRH Rd, [Rn, Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1bb: { // LDRH Rd, [Rn, Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1db: { // LDRH Rd, [Rn, #offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1fb: { // LDRH Rd, [Rn, #offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = CPUReadHalfWord(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x01d: case 0x03d: { // LDRSB Rd, [Rn], -Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) { address -= offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x05d: case 0x07d: { // LDRSB Rd, [Rn], #-offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) { address -= offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x09d: case 0x0bd: { // LDRSB Rd, [Rn], Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) { address += offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x0dd: case 0x0fd: { // LDRSB Rd, [Rn], #offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) { address += offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x11d: { // LDRSB Rd, [Rn, -Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x13d: { // LDRSB Rd, [Rn, -Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x15d: { // LDRSB Rd, [Rn, -#offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x17d: { // LDRSB Rd, [Rn, -#offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x19d: { // LDRSB Rd, [Rn, Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1bd: { // LDRSB Rd, [Rn, Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1dd: { // LDRSB Rd, [Rn, #offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1fd: { // LDRSB Rd, [Rn, #offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s8)CPUReadByte(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x01f: case 0x03f: { // LDRSH Rd, [Rn], -Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) { address -= offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x05f: case 0x07f: { // LDRSH Rd, [Rn], #-offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) { address -= offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x09f: case 0x0bf: { // LDRSH Rd, [Rn], Rm + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) { address += offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x0df: case 0x0ff: { // LDRSH Rd, [Rn], #offset + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I; int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) { address += offset; reg[base].I = address; } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x11f: { // LDRSH Rd, [Rn, -Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x13f: { // LDRSH Rd, [Rn, -Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x15f: { // LDRSH Rd, [Rn, -#offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x17f: { // LDRSH Rd, [Rn, -#offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x19f: { // LDRSH Rd, [Rn, Rm] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1bf: { // LDRSH Rd, [Rn, Rm]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + reg[opcode & 0x0F].I; - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1df: { // LDRSH Rd, [Rn, #offset] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x1ff: { // LDRSH Rd, [Rn, #offset]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode >> 16) & 0x0F; int dest = (opcode >> 12) & 0x0F; u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); - clockTicks += 3 + CPUUpdateTicksAccess16(address); reg[dest].I = (s16)CPUReadHalfWordSigned(address); if(dest != base) reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020); @@ -2896,25 +3550,28 @@ case 0x029: { // MLA Rd, Rm, Rs, Rn + clockTicks = 2; int dest = (opcode >> 16) & 0x0F; int mult = (opcode & 0x0F); u32 rs = reg[(opcode >> 8) & 0x0F].I; reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I; - if(((s32)rs)<0) - rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 3; + clockTicks += 0; else if ((rs & 0xFFFF0000) == 0) - clockTicks += 4; + clockTicks += 1; else if ((rs & 0xFF000000) == 0) - clockTicks += 5; + clockTicks += 2; else - clockTicks += 6; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 16) & 0x0F; int mult = (opcode & 0x0F); u32 rs = reg[(opcode >> 8) & 0x0F].I; @@ -2924,13 +3581,16 @@ if(((s32)rs)<0) rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 3; + clockTicks += 0; else if ((rs & 0xFFFF0000) == 0) - clockTicks += 4; + clockTicks += 1; else if ((rs & 0xFF000000) == 0) - clockTicks += 5; + clockTicks += 2; else - clockTicks += 6; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I; int destLo = (opcode >> 12) & 0x0F; @@ -2950,18 +3611,22 @@ reg[destLo].I = (u32)uTemp; reg[destHi].I = (u32)(uTemp >> 32); if ((usource & 0xFFFFFF00) == 0) - clockTicks += 2; + clockTicks += 0; else if ((usource & 0xFFFF0000) == 0) - clockTicks += 3; + clockTicks += 1; else if ((usource & 0xFF000000) == 0) - clockTicks += 4; + clockTicks += 2; else - clockTicks += 5; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I; int destLo = (opcode >> 12) & 0x0F; @@ -2972,13 +3637,16 @@ Z_FLAG = (uTemp) ? false : true; N_FLAG = (reg[destHi].I & 0x80000000) ? true : false; if ((usource & 0xFFFFFF00) == 0) - clockTicks += 2; + clockTicks += 0; else if ((usource & 0xFFFF0000) == 0) - clockTicks += 3; + clockTicks += 1; else if ((usource & 0xFF000000) == 0) - clockTicks += 4; + clockTicks += 2; else - clockTicks += 5; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I; int destLo = (opcode >> 12) & 0x0F; @@ -2997,18 +3666,22 @@ reg[destLo].I = (u32)uTemp; reg[destHi].I = (u32)(uTemp >> 32); if ((usource & 0xFFFFFF00) == 0) - clockTicks += 3; + clockTicks += 0; else if ((usource & 0xFFFF0000) == 0) - clockTicks += 4; + clockTicks += 1; else if ((usource & 0xFF000000) == 0) - clockTicks += 5; + clockTicks += 2; else - clockTicks += 6; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I; int destLo = (opcode >> 12) & 0x0F; @@ -3022,13 +3695,16 @@ Z_FLAG = (uTemp) ? false : true; N_FLAG = (reg[destHi].I & 0x80000000) ? true : false; if ((usource & 0xFFFFFF00) == 0) - clockTicks += 3; + clockTicks += 0; else if ((usource & 0xFFFF0000) == 0) - clockTicks += 4; + clockTicks += 1; else if ((usource & 0xFF000000) == 0) - clockTicks += 5; + clockTicks += 2; else - clockTicks += 6; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F; int destHi = (opcode >> 16) & 0x0F; u32 rs = reg[(opcode >> 8) & 0x0F].I; @@ -3047,18 +3724,22 @@ if(((s32)rs) < 0) rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 2; + clockTicks += 0; else if((rs & 0xFFFF0000) == 0) - clockTicks += 3; + clockTicks += 1; else if((rs & 0xFF000000) == 0) - clockTicks += 4; + clockTicks += 2; else - clockTicks += 5; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F; int destHi = (opcode >> 16) & 0x0F; u32 rs = reg[(opcode >> 8) & 0x0F].I; @@ -3072,13 +3753,16 @@ if(((s32)rs) < 0) rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 2; + clockTicks += 0; else if((rs & 0xFFFF0000) == 0) - clockTicks += 3; + clockTicks += 1; else if((rs & 0xFF000000) == 0) - clockTicks += 4; + clockTicks += 2; else - clockTicks += 5; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F; int destHi = (opcode >> 16) & 0x0F; u32 rs = reg[(opcode >> 8) & 0x0F].I; @@ -3100,18 +3785,21 @@ if(((s32)rs) < 0) rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 3; + clockTicks += 0; else if((rs & 0xFFFF0000) == 0) - clockTicks += 4; + clockTicks += 1; else if((rs & 0xFF000000) == 0) - clockTicks += 5; + clockTicks += 2; else - clockTicks += 6; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F; int destHi = (opcode >> 16) & 0x0F; u32 rs = reg[(opcode >> 8) & 0x0F].I; @@ -3128,13 +3816,15 @@ if(((s32)rs) < 0) rs = ~rs; if((rs & 0xFFFFFF00) == 0) - clockTicks += 3; + clockTicks += 0; else if((rs & 0xFFFF0000) == 0) - clockTicks += 4; + clockTicks += 1; else if((rs & 0xFF000000) == 0) - clockTicks += 5; + clockTicks += 2; else - clockTicks += 6; + clockTicks += 3; + if (!busPrefetchCount) + busPrefetchCount = ((++busPrefetchCount)<> 12) & 15].I = temp; + clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130); @@ -3174,23 +3866,33 @@ CPUSwitchMode(newValue & 0x1f, false); reg[16].I = newValue; CPUUpdateFlags(); + if(!armState) { // this should not be allowed, but it seems to work + THUMB_PREFETCH; + reg[15].I = armNextPC + 2; + } } break; case 0x121: { // BX Rm // TODO: check if right instruction... - clockTicks += 3; int base = opcode & 0x0F; + busPrefetchCount=0; armState = reg[base].I & 1 ? false : true; if(armState) { reg[15].I = reg[base].I & 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks = codeTicksAccessSeq32(armNextPC) + + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3; } else { reg[15].I = reg[base].I & 0xFFFFFFFE; armNextPC = reg[15].I; reg[15].I += 2; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC) + + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3; } } break; @@ -3207,6 +3909,8 @@ u32 temp = CPUReadByte(address); CPUWriteByte(address, reg[opcode&15].B.B0); reg[(opcode>>12)&15].I = temp; + clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170); @@ -3284,6 +3988,10 @@ CPUSwitchMode(newValue & 0x1f, false); reg[16].I = newValue; CPUUpdateFlags(); + if(!armState) { // this should not be allowed, but it seems to work + THUMB_PREFETCH; + reg[15].I = armNextPC + 2; + } } break; case 0x360: @@ -3326,13 +4034,16 @@ CASE_16(0x420) { // STR Rd, [Rn], -# + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x480) @@ -3340,64 +4051,81 @@ CASE_16(0x4a0) { // STR Rd, [Rn], # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x500) { // STR Rd, [Rn, -#] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x520) { // STR Rd, [Rn, -#]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x580) { // STR Rd, [Rn, #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x5a0) { // STR Rd, [Rn, #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x410) { // LDR Rd, [Rn], -# + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3405,18 +4133,23 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I -= offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x430) { // LDRT Rd, [Rn], -# + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3424,12 +4157,23 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I -= offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x490) { // LDR Rd, [Rn], # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3437,18 +4181,23 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I += offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x4b0) { // LDRT Rd, [Rn], # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3456,29 +4205,45 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I += offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x510) { // LDR Rd, [Rn, -#] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x530) { // LDR Rd, [Rn, -#]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3486,35 +4251,45 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } - } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); + } break; CASE_16(0x590) { // LDR Rd, [Rn, #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x5b0) { // LDR Rd, [Rn, #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3522,13 +4297,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x440) @@ -3536,73 +4314,91 @@ CASE_16(0x460) { // STRB Rd, [Rn], -# + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x4c0) // T versions shouldn't be different on GBA CASE_16(0x4e0) - // STRB Rd, [Rn], # { + // STRB Rd, [Rn], # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x540) { // STRB Rd, [Rn, -#] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x560) { // STRB Rd, [Rn, -#]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x5c0) { // STRB Rd, [Rn, #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x5e0) { // STRB Rd, [Rn, #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteByte(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x450) @@ -3610,6 +4406,8 @@ CASE_16(0x470) { // LDRB Rd, [Rn], -# + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3617,13 +4415,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I -= offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x4d0) CASE_16(0x4f0) // T versions should not be different { // LDRB Rd, [Rn], # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3631,23 +4440,45 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I += offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x550) { // LDRB Rd, [Rn, -#] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x570) { // LDRB Rd, [Rn, -#]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3655,23 +4486,45 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x5d0) { // LDRB Rd, [Rn, #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; CASE_16(0x5f0) { // LDRB Rd, [Rn, #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = opcode & 0xFFF; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -3679,7 +4532,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x600: @@ -3689,13 +4551,16 @@ case 0x628: { // STR Rd, [Rn], -Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x602: @@ -3705,6 +4570,8 @@ case 0x62a: { // STR Rd, [Rn], -Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -3712,7 +4579,8 @@ u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x604: @@ -3722,6 +4590,8 @@ case 0x62c: { // STR Rd, [Rn], -Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -3735,7 +4605,8 @@ u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x606: @@ -3745,6 +4616,8 @@ case 0x62e: { // STR Rd, [Rn], -Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -3757,7 +4630,8 @@ u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address - value; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x680: @@ -3767,13 +4641,16 @@ case 0x6a8: { // STR Rd, [Rn], Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x682: @@ -3783,6 +4660,8 @@ case 0x6aa: { // STR Rd, [Rn], Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -3790,7 +4669,8 @@ u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x684: @@ -3800,6 +4680,8 @@ case 0x6ac: { // STR Rd, [Rn], Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -3813,7 +4695,8 @@ u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x686: @@ -3823,6 +4706,8 @@ case 0x6ae: { // STR Rd, [Rn], Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -3835,38 +4720,47 @@ u32 address = reg[base].I; CPUWriteMemory(address, reg[dest].I); reg[base].I = address + value; - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x700: case 0x708: { // STR Rd, [Rn, -Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x702: case 0x70a: { // STR Rd, [Rn, -Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x704: case 0x70c: { // STR Rd, [Rn, -Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -3879,13 +4773,16 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x706: case 0x70e: { // STR Rd, [Rn, -Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -3897,26 +4794,32 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - value; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x720: case 0x728: { // STR Rd, [Rn, -Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x722: case 0x72a: { // STR Rd, [Rn, -Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -3924,13 +4827,16 @@ u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x724: case 0x72c: { // STR Rd, [Rn, -Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -3944,13 +4850,16 @@ u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x726: case 0x72e: { // STR Rd, [Rn, -Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -3963,38 +4872,47 @@ u32 address = reg[base].I - value; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x780: case 0x788: { // STR Rd, [Rn, Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x782: case 0x78a: { // STR Rd, [Rn, Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x784: case 0x78c: { // STR Rd, [Rn, Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4007,13 +4925,16 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x786: case 0x78e: { // STR Rd, [Rn, Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4025,26 +4946,32 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + value; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7a0: case 0x7a8: { // STR Rd, [Rn, Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7a2: case 0x7aa: { // STR Rd, [Rn, Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4052,13 +4979,16 @@ u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7a4: case 0x7ac: { // STR Rd, [Rn, Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4072,13 +5002,16 @@ u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7a6: case 0x7ae: { // STR Rd, [Rn, Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4091,7 +5024,8 @@ u32 address = reg[base].I + value; reg[base].I = address; CPUWriteMemory(address, reg[dest].I); - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks = 2 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x610: @@ -4101,6 +5035,8 @@ case 0x638: { // LDR Rd, [Rn], -Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -4108,13 +5044,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address - offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x612: @@ -4124,6 +5063,8 @@ case 0x63a: { // LDR Rd, [Rn], -Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4132,13 +5073,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address - offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x614: @@ -4148,6 +5092,8 @@ case 0x63c: { // LDR Rd, [Rn], -Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4162,13 +5108,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address - offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x616: @@ -4178,6 +5127,8 @@ case 0x63e: { // LDR Rd, [Rn], -Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4191,13 +5142,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address - value; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x690: @@ -4207,6 +5161,8 @@ case 0x6b8: { // LDR Rd, [Rn], Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -4214,13 +5170,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address + offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x692: @@ -4230,6 +5189,8 @@ case 0x6ba: { // LDR Rd, [Rn], Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4238,13 +5199,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address + offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x694: @@ -4254,6 +5218,8 @@ case 0x6bc: { // LDR Rd, [Rn], Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4268,13 +5234,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address + offset; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x696: @@ -4284,6 +5253,8 @@ case 0x6be: { // LDR Rd, [Rn], Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4297,56 +5268,71 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address + value; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x710: case 0x718: { // LDR Rd, [Rn, -Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x712: case 0x71a: { // LDR Rd, [Rn, -Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x714: case 0x71c: { // LDR Rd, [Rn, -Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4359,19 +5345,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x716: case 0x71e: { // LDR Rd, [Rn, -Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4383,19 +5374,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - value; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x730: case 0x738: { // LDR Rd, [Rn, -Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -4403,19 +5399,24 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x732: case 0x73a: { // LDR Rd, [Rn, -Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4424,19 +5425,24 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x734: case 0x73c: { // LDR Rd, [Rn, -Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4451,19 +5457,24 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x736: case 0x73e: { // LDR Rd, [Rn, -Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4477,56 +5488,71 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x790: case 0x798: { // LDR Rd, [Rn, Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x792: case 0x79a: { // LDR Rd, [Rn, Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x794: case 0x79c: { // LDR Rd, [Rn, Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4539,19 +5565,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x796: case 0x79e: { // LDR Rd, [Rn, Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4563,19 +5594,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + value; reg[dest].I = CPUReadMemory(address); - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7b0: case 0x7b8: { // LDR Rd, [Rn, Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -4583,19 +5619,24 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7b2: case 0x7ba: { // LDR Rd, [Rn, Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4604,19 +5645,24 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7b4: case 0x7bc: { // LDR Rd, [Rn, Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4631,19 +5677,24 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x7b6: case 0x7be: { // LDR Rd, [Rn, Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4657,13 +5708,16 @@ reg[dest].I = CPUReadMemory(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess32(address); + clockTicks = 0; if(dest == 15) { - clockTicks += 2; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); } + clockTicks += 3 + dataTicksAccess32(address) + + codeTicksAccess32(armNextPC); } break; case 0x640: @@ -4673,13 +5727,16 @@ case 0x668: { // STRB Rd, [Rn], -Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x642: @@ -4689,6 +5746,8 @@ case 0x66a: { // STRB Rd, [Rn], -Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4696,7 +5755,8 @@ u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x644: @@ -4706,6 +5766,8 @@ case 0x66c: { // STRB Rd, [Rn], -Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4719,7 +5781,8 @@ u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address - offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x646: @@ -4729,6 +5792,8 @@ case 0x66e: { // STRB Rd, [Rn], -Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4741,7 +5806,8 @@ u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address - value; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6c0: @@ -4751,13 +5817,16 @@ case 0x6e8: { // STRB Rd, [Rn], Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6c2: @@ -4767,6 +5836,8 @@ case 0x6ea: { // STRB Rd, [Rn], Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4774,7 +5845,8 @@ u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6c4: @@ -4783,7 +5855,9 @@ case 0x6e4: case 0x6ec: { - // STR Rd, [Rn], Rm, ASR # + // STRB Rd, [Rn], Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4797,7 +5871,8 @@ u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address + offset; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6c6: @@ -4807,6 +5882,8 @@ case 0x6ee: { // STRB Rd, [Rn], Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4819,38 +5896,47 @@ u32 address = reg[base].I; CPUWriteByte(address, reg[dest].B.B0); reg[base].I = address + value; - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x740: case 0x748: { // STRB Rd, [Rn, -Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x742: case 0x74a: { // STRB Rd, [Rn, -Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x744: case 0x74c: { // STRB Rd, [Rn, -Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4863,13 +5949,16 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x746: case 0x74e: { // STRB Rd, [Rn, -Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4881,26 +5970,32 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - value; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x760: case 0x768: { // STRB Rd, [Rn, -Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x762: case 0x76a: { // STRB Rd, [Rn, -Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -4908,13 +6003,16 @@ u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x764: case 0x76c: { // STRB Rd, [Rn, -Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4928,13 +6026,16 @@ u32 address = reg[base].I - offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x766: case 0x76e: { // STRB Rd, [Rn, -Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -4947,38 +6048,47 @@ u32 address = reg[base].I - value; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7c0: case 0x7c8: { // STRB Rd, [Rn, Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7c2: case 0x7ca: { // STRB Rd, [Rn, Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7c4: case 0x7cc: { // STRB Rd, [Rn, Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -4991,13 +6101,16 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7c6: case 0x7ce: { // STRB Rd, [Rn, Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5009,26 +6122,32 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + value; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7e0: case 0x7e8: { // STRB Rd, [Rn, Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7e2: case 0x7ea: { // STRB Rd, [Rn, Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -5036,13 +6155,16 @@ u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7e4: case 0x7ec: { // STRB Rd, [Rn, Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5056,13 +6178,16 @@ u32 address = reg[base].I + offset; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7e6: case 0x7ee: { // STRB Rd, [Rn, Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5075,7 +6200,8 @@ u32 address = reg[base].I + value; reg[base].I = address; CPUWriteByte(address, reg[dest].B.B0); - clockTicks += 2 + CPUUpdateTicksAccess16(address); + clockTicks = 2 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x650: @@ -5085,6 +6211,8 @@ case 0x678: { // LDRB Rd, [Rn], -Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -5092,7 +6220,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address - offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x652: @@ -5102,6 +6239,8 @@ case 0x67a: { // LDRB Rd, [Rn], -Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -5110,7 +6249,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address - offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x654: @@ -5120,6 +6268,8 @@ case 0x67c: { // LDRB Rd, [Rn], -Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5134,7 +6284,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address - offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x656: @@ -5144,6 +6303,8 @@ case 0x67e: { // LDRB Rd, [Rn], -Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5157,7 +6318,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address - value; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6d0: @@ -5167,6 +6337,8 @@ case 0x6f8: { // LDRB Rd, [Rn], Rm, LSL # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -5174,7 +6346,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address + offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6d2: @@ -5184,6 +6365,8 @@ case 0x6fa: { // LDRB Rd, [Rn], Rm, LSR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -5192,7 +6375,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address + offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6d4: @@ -5202,6 +6394,8 @@ case 0x6fc: { // LDRB Rd, [Rn], Rm, ASR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5216,7 +6410,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address + offset; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x6d6: @@ -5226,6 +6429,8 @@ case 0x6fe: { // LDRB Rd, [Rn], Rm, ROR # + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5239,38 +6444,71 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address + value; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x750: case 0x758: { // LDRB Rd, [Rn, -Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x752: case 0x75a: { // LDRB Rd, [Rn, -Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x754: case 0x75c: { // LDRB Rd, [Rn, -Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5283,13 +6521,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x756: case 0x75e: { // LDRB Rd, [Rn, -Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5301,13 +6550,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I - value; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x770: case 0x778: { // LDRB Rd, [Rn, -Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -5315,13 +6575,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x772: case 0x77a: { // LDRB Rd, [Rn, -Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -5330,13 +6601,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x774: case 0x77c: { // LDRB Rd, [Rn, -Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5351,13 +6633,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x776: case 0x77e: { // LDRB Rd, [Rn, -Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5371,38 +6664,71 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7d0: case 0x7d8: { // LDRB Rd, [Rn, Rm, LSL #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7d2: case 0x7da: { // LDRB Rd, [Rn, Rm, LSR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7d4: case 0x7dc: { // LDRB Rd, [Rn, Rm, ASR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5415,13 +6741,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + offset; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7d6: case 0x7de: { // LDRB Rd, [Rn, Rm, ROR #] + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5433,13 +6770,24 @@ int base = (opcode >> 16) & 15; u32 address = reg[base].I + value; reg[dest].I = CPUReadByte(address); - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7f0: case 0x7f8: { // LDRB Rd, [Rn, Rm, LSL #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = reg[opcode & 15].I << ((opcode>>7)& 31); int dest = (opcode >> 12) & 15; int base = (opcode >> 16) & 15; @@ -5447,13 +6795,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7f2: case 0x7fa: { // LDRB Rd, [Rn, Rm, LSR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset = shift ? reg[opcode & 15].I >> shift : 0; int dest = (opcode >> 12) & 15; @@ -5462,13 +6821,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7f4: case 0x7fc: { // LDRB Rd, [Rn, Rm, ASR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; int offset; if(shift) @@ -5483,13 +6853,24 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; case 0x7f6: case 0x7fe: { // LDRB Rd, [Rn, Rm, ROR #]! + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int shift = (opcode >> 7) & 31; u32 value = reg[opcode & 15].I; if(shift) { @@ -5503,7 +6884,16 @@ reg[dest].I = CPUReadByte(address); if(dest != base) reg[base].I = address; - clockTicks += 3 + CPUUpdateTicksAccess16(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccess16(address) + + codeTicksAccess32(armNextPC); } break; #define STMW_REG(val,num) \ @@ -5511,10 +6901,10 @@ CPUWriteMemory(address, reg[(num)].I);\ if(!offset) {\ reg[base].I = temp;\ - clockTicks += 1 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccess32(address);\ offset = 1;\ } else {\ - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ }\ address += 4;\ } @@ -5522,22 +6912,23 @@ if(opcode & (val)) {\ CPUWriteMemory(address, reg[(num)].I);\ if(!offset) {\ - clockTicks += 1 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccess32(address);\ offset = 1;\ } else {\ - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ }\ address += 4;\ } CASE_16(0x800) - // STMDA Rn, {Rlist} { + // STMDA Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp + 4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); STM_REG(2, 1); @@ -5557,20 +6948,22 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x820) { // STMDA Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STMW_REG(1, 0); @@ -5591,21 +6984,23 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); reg[base].I = temp; } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x840) { // STMDA Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); @@ -5642,20 +7037,22 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x860) { // STMDA Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STMW_REG(1, 0); @@ -5692,20 +7089,22 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); reg[base].I = temp; } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x880) { // STMIA Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); STM_REG(2, 1); @@ -5725,18 +7124,20 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x8a0) { // STMIA Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); @@ -5759,18 +7160,20 @@ CPUWriteMemory(address, reg[15].I+4); if(!offset) { reg[base].I = temp; - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); } else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x8c0) { // STMIA Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); STM_REG(2, 1); @@ -5803,18 +7206,20 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x8e0) { // STMIA Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); @@ -5850,21 +7255,23 @@ CPUWriteMemory(address, reg[15].I+4); if(!offset) { reg[base].I = temp; - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); } else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x900) { // STMDB Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); STM_REG(2, 1); @@ -5884,20 +7291,22 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x920) { // STMDB Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STMW_REG(1, 0); @@ -5918,21 +7327,23 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); reg[base].I = temp; } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x940) { // STMDB Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); @@ -5969,20 +7380,22 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x960) { // STMDB Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STMW_REG(1, 0); @@ -6019,20 +7432,22 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); reg[base].I = temp; } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x980) - // STMIB Rn, {Rlist} { + // STMIB Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); STM_REG(2, 1); @@ -6052,18 +7467,20 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x9a0) { // STMIB Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); @@ -6086,18 +7503,20 @@ CPUWriteMemory(address, reg[15].I+4); if(!offset) { reg[base].I = temp; - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); } else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x9c0) { // STMIB Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; STM_REG(1, 0); STM_REG(2, 1); @@ -6130,18 +7549,20 @@ if(opcode & 32768) { CPUWriteMemory(address, reg[15].I+4); if(!offset) - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; CASE_16(0x9e0) { // STMIB Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; int offset = 0; u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); @@ -6177,10 +7598,11 @@ CPUWriteMemory(address, reg[15].I+4); if(!offset) { reg[base].I = temp; - clockTicks += 1 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); } else - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); } + clockTicks += 1 + codeTicksAccess32(armNextPC); } break; @@ -6188,9 +7610,9 @@ if(opcode & (val)) {\ reg[(num)].I = CPUReadMemory(address);\ if(offset)\ - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ else {\ - clockTicks += 1 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccess32(address);\ offset = 1;\ }\ address += 4;\ @@ -6199,11 +7621,13 @@ CASE_16(0x810) { // LDMDA Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp + 4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6222,23 +7646,28 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x830) { // LDMDA Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp + 4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6257,13 +7686,17 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); if(!(opcode & (1 << base))) reg[base].I = temp; } @@ -6271,11 +7704,13 @@ CASE_16(0x850) { // LDMDA Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp + 4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6295,18 +7730,16 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); CPUSwitchMode(reg[17].I & 0x1f, false); if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -6339,17 +7772,25 @@ LDM_REG(8192, 13); LDM_REG(16384, 14); } + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x870) { // LDMDA Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (temp + 4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6369,10 +7810,6 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if(!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); if(!(opcode & (1 << base))) reg[base].I = temp; @@ -6381,9 +7818,11 @@ if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -6419,16 +7858,24 @@ if(!(opcode & (1 << base))) reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x890) { // LDMIA Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6447,23 +7894,29 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x8b0) { // LDMIA Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6482,13 +7935,17 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); if(!(opcode & (1 << base))) reg[base].I = temp; } @@ -6496,9 +7953,11 @@ CASE_16(0x8d0) { // LDMIA Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6518,18 +7977,16 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); CPUSwitchMode(reg[17].I & 0x1f, false); if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -6562,17 +8019,25 @@ LDM_REG(8192, 13); LDM_REG(16384, 14); } + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x8f0) { // LDMIA Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = reg[base].I & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6592,10 +8057,6 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if(!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); if(!(opcode & (1 << base))) reg[base].I = temp; @@ -6604,9 +8065,11 @@ if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -6642,18 +8105,26 @@ if(!(opcode & (1 << base))) reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x910) { // LDMDB Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6672,23 +8143,29 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x930) { // LDMDB Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6707,13 +8184,17 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); if(!(opcode & (1 << base))) reg[base].I = temp; } @@ -6721,11 +8202,13 @@ CASE_16(0x950) { // LDMDB Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6745,18 +8228,16 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); CPUSwitchMode(reg[17].I & 0x1f, false); if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -6789,17 +8270,25 @@ LDM_REG(8192, 13); LDM_REG(16384, 14); } + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x970) { // LDMDB Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = temp & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6819,10 +8308,6 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if(!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); if(!(opcode & (1 << base))) reg[base].I = temp; @@ -6831,9 +8316,11 @@ if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -6869,16 +8356,24 @@ if(!(opcode & (1 << base))) reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x990) { // LDMIB Rn, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6897,23 +8392,29 @@ LDM_REG(16384, 14); if(opcode & 32768) { reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x9b0) { // LDMIB Rn!, {Rlist} + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; LDM_REG(1, 0); LDM_REG(2, 1); @@ -6933,12 +8434,21 @@ if(opcode & 32768) { reg[15].I = CPUReadMemory(address); if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); + armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); if(!(opcode & (1 << base))) reg[base].I = temp; } @@ -6946,9 +8456,11 @@ CASE_16(0x9d0) { // LDMIB Rn, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -6968,18 +8480,16 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if (!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); CPUSwitchMode(reg[17].I & 0x1f, false); if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -7012,17 +8522,25 @@ LDM_REG(8192, 13); LDM_REG(16384, 14); } + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_16(0x9f0) { // LDMIB Rn!, {Rlist}^ + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int base = (opcode & 0x000F0000) >> 16; u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); u32 address = (reg[base].I+4) & 0xFFFFFFFC; - clockTicks += 2; + clockTicks = 0; int offset = 0; if(opcode & 0x8000) { LDM_REG(1, 0); @@ -7042,10 +8560,6 @@ LDM_REG(16384, 14); reg[15].I = CPUReadMemory(address); - if(!offset) - clockTicks += 2 + CPUUpdateTicksAccess32(address); - else - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); if(!(opcode & (1 << base))) reg[base].I = temp; @@ -7054,9 +8568,11 @@ if(armState) { armNextPC = reg[15].I & 0xFFFFFFFC; reg[15].I = armNextPC + 4; + ARM_PREFETCH; } else { armNextPC = reg[15].I & 0xFFFFFFFE; reg[15].I = armNextPC + 2; + THUMB_PREFETCH; } } else { LDM_REG(1, 0); @@ -7092,13 +8608,18 @@ if(!(opcode & (1 << base))) reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccess32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); } + clockTicks += 2 + codeTicksAccess32(armNextPC); } break; CASE_256(0xa00) { // B - clockTicks += 3; int offset = opcode & 0x00FFFFFF; if(offset & 0x00800000) { offset |= 0xFF000000; @@ -7107,12 +8628,16 @@ reg[15].I += offset; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks += 2 + codeTicksAccess32(armNextPC) + + codeTicksAccessSeq32(armNextPC); + busPrefetchCount=0; } break; CASE_256(0xb00) { // BL - clockTicks += 3; int offset = opcode & 0x00FFFFFF; if(offset & 0x00800000) { offset |= 0xFF000000; @@ -7122,12 +8647,21 @@ reg[15].I += offset; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks += 2 + codeTicksAccess32(armNextPC) + + codeTicksAccessSeq32(armNextPC); + busPrefetchCount=0; } break; CASE_256(0xf00) // SWI - clockTicks += 3; - CPUSoftwareInterrupt(opcode & 0x00FFFFFF); + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks += 2 + codeTicksAccess32(armNextPC) + + codeTicksAccessSeq32(armNextPC); + busPrefetchCount=0; + CPUSoftwareInterrupt(opcode & 0x00FFFFFF); + break; #ifdef GP_SUPPORT case 0xe11: @@ -7162,3 +8696,6 @@ // END } } + +if (clockTicks == 0) + clockTicks = codeTicksAccessSeq32(oldArmNextPC) + 1; diff -urN ../VisualBoyAdvance-1.7.2/src/armdis.cpp ./src/armdis.cpp --- ../VisualBoyAdvance-1.7.2/src/armdis.cpp 2004-05-13 23:34:51 +0900 +++ ./src/armdis.cpp 2006-01-07 04:40:08 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -117,8 +117,8 @@ {0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]"}, // Format 8 {0xfe00, 0x5200, "strh %r0, [%r3, %r6]"}, - {0xfe00, 0x5600, "ldrh %r0, [%r3, %r6]"}, - {0xfe00, 0x5a00, "ldsb %r0, [%r3, %r6]"}, + {0xfe00, 0x5600, "ldsb %r0, [%r3, %r6]"}, + {0xfe00, 0x5a00, "ldrh %r0, [%r3, %r6]"}, {0xfe00, 0x5e00, "ldsh %r0, [%r3, %r6]"}, // Format 9 {0xe800, 0x6000, "str%B %r0, [%r3, %p]"}, diff -urN ../VisualBoyAdvance-1.7.2/src/bios.cpp ./src/bios.cpp --- ../VisualBoyAdvance-1.7.2/src/bios.cpp 2004-05-13 23:34:20 +0900 +++ ./src/bios.cpp 2006-04-30 23:35:05 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -70,7 +70,7 @@ } #endif - s32 a = -((s32)(reg[0].I * reg[0].I)) >> 14; + s32 a = -(((s32)(reg[0].I*reg[0].I)) >> 14); s32 b = ((0xA9 * a) >> 14) + 0x390; b = ((b * a) >> 14) + 0x91C; b = ((b * a) >> 14) + 0xFB6; @@ -78,7 +78,8 @@ b = ((b * a) >> 14) + 0x2081; b = ((b * a) >> 14) + 0x3651; b = ((b * a) >> 14) + 0xA2F9; - reg[0].I = (reg[0].I * b) >> 16; + a = ((s32)reg[0].I * b) >> 16; + reg[0].I = a; #ifdef DEV_VERSION if(systemVerbose & VERBOSE_SWI) { @@ -99,36 +100,33 @@ } #endif - s16 x = reg[0].I; - s16 y = reg[1].I; - + s32 x = reg[0].I; + s32 y = reg[1].I; + u32 res = 0; if (y == 0) { - reg[0].I = 0x8000 & x; - reg[3].I = 0x170; + res = ((x>>16) & 0x8000); } else { if (x == 0) { - reg[0].I = (0x8000 & y) + 0x4000; - reg[3].I = 0x170; + res = ((y>>16) & 0x8000) + 0x4000; } else { - if (abs(x) > abs(y)) { + if ((abs(x) > abs(y)) || ((abs(x) == abs(y)) && (!((x<0) && (y<0))))) { reg[1].I = x; reg[0].I = y << 14; BIOS_Div(); BIOS_ArcTan(); if (x < 0) - reg[0].I = 0x8000 + reg[0].I; + res = 0x8000 + reg[0].I; else - reg[0].I = ((y & 0x8000) << 1 ) + reg[0].I; - reg[3].I = 0x170; + res = (((y>>16) & 0x8000)<<1) + reg[0].I; } else { reg[0].I = x << 14; BIOS_Div(); BIOS_ArcTan(); - reg[0].I = (0x4000 + (y & 0x8000)) - reg[0].I; - reg[3].I = 0x170; + res = (0x4000 + ((y>>16) & 0x8000)) - reg[0].I; } } } + reg[0].I = res; #ifdef DEV_VERSION if(systemVerbose & VERBOSE_SWI) { @@ -136,7 +134,7 @@ reg[0].I); } #endif -} +} void BIOS_BitUnPack() { @@ -155,7 +153,11 @@ u32 header = reg[2].I; int len = CPUReadHalfWord(header); - // check address + // check address + if(((source & 0xe000000) == 0) || + ((source + len) & 0xe000000) == 0) + return; + int bits = CPUReadByte(header+2); int revbits = 8 - bits; // u32 value = 0; @@ -179,7 +181,7 @@ break; u32 d = b & mask; u32 temp = d >> bitcount; - if(!temp && addBase) { + if(d || addBase) { temp += base; } data |= temp << bitwritecount; @@ -196,6 +198,11 @@ } } +void BIOS_GetBiosChecksum() +{ + reg[0].I=0xBAAE187F; +} + void BIOS_BgAffineSet() { #ifdef DEV_VERSION @@ -280,7 +287,7 @@ dest &= 0xFFFFFFFC; // fill ? if((cnt >> 24) & 1) { - u32 value = CPUReadMemory(source); + u32 value = (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source)); while(count) { CPUWriteMemory(dest, value); dest += 4; @@ -289,7 +296,7 @@ } else { // copy while(count) { - CPUWriteMemory(dest, CPUReadMemory(source)); + CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source))); source += 4; dest += 4; count--; @@ -298,7 +305,7 @@ } else { // 16-bit fill? if((cnt >> 24) & 1) { - u16 value = CPUReadHalfWord(source); + u16 value = (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source)); while(count) { CPUWriteHalfWord(dest, value); dest += 2; @@ -307,7 +314,7 @@ } else { // copy while(count) { - CPUWriteHalfWord(dest, CPUReadHalfWord(source)); + CPUWriteHalfWord(dest, (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source))); source += 2; dest += 2; count--; @@ -343,7 +350,7 @@ if((cnt >> 24) & 1) { while(count > 0) { // BIOS always transfers 32 bytes at a time - u32 value = CPUReadMemory(source); + u32 value = (source>0x0EFFFFFF ? 0xBAFFFFFB : CPUReadMemory(source)); for(int i = 0; i < 8; i++) { CPUWriteMemory(dest, value); dest += 4; @@ -355,7 +362,7 @@ while(count > 0) { // BIOS always transfers 32 bytes at a time for(int i = 0; i < 8; i++) { - CPUWriteMemory(dest, CPUReadMemory(source)); + CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0xBAFFFFFB :CPUReadMemory(source))); source += 4; dest += 4; } @@ -548,7 +555,7 @@ u32 treeStart = source; - source += (treeSize<<1) + 1; + source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte int len = header >> 8; @@ -866,6 +873,8 @@ { // no need to trace here. this is only called directly from GBA.cpp // to emulate bios initialization + + CPUUpdateRegister(0x0, 0x80); if(flags) { if(flags & 0x01) { @@ -891,18 +900,16 @@ if(flags & 0x80) { int i; - for(i = 0; i < 8; i++) + for(i = 0; i < 0x10; i++) CPUUpdateRegister(0x200+i*2, 0); - CPUUpdateRegister(0x202, 0xFFFF); - - for(i = 0; i < 8; i++) + for(i = 0; i < 0xF; i++) CPUUpdateRegister(0x4+i*2, 0); - for(i = 0; i < 16; i++) + for(i = 0; i < 0x20; i++) CPUUpdateRegister(0x20+i*2, 0); - for(i = 0; i < 24; i++) + for(i = 0; i < 0x18; i++) CPUUpdateRegister(0xb0+i*2, 0); CPUUpdateRegister(0x130, 0); @@ -965,7 +972,7 @@ u32 source = reg[0].I; u32 dest = reg[1].I; - u32 header = CPUReadMemory(source); + u32 header = CPUReadMemory(source & 0xFFFFFFFC); source += 4; if(((source & 0xe000000) == 0) || @@ -1034,7 +1041,7 @@ u32 source = reg[0].I; u32 dest = reg[1].I; - u32 header = CPUReadMemory(source); + u32 header = CPUReadMemory(source & 0xFFFFFFFC); source += 4; if(((source & 0xe000000) == 0) || diff -urN ../VisualBoyAdvance-1.7.2/src/bios.h ./src/bios.h --- ../VisualBoyAdvance-1.7.2/src/bios.h 2004-05-13 22:56:47 +0900 +++ ./src/bios.h 2006-04-30 23:35:05 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -23,6 +23,7 @@ extern void BIOS_ArcTan(); extern void BIOS_ArcTan2(); extern void BIOS_BitUnPack(); +extern void BIOS_GetBiosChecksum(); extern void BIOS_BgAffineSet(); extern void BIOS_CpuSet(); extern void BIOS_CpuFastSet(); diff -urN ../VisualBoyAdvance-1.7.2/src/elf.cpp ./src/elf.cpp --- ../VisualBoyAdvance-1.7.2/src/elf.cpp 2004-05-13 23:34:08 +0900 +++ ./src/elf.cpp 2006-06-08 23:12:18 +0900 @@ -820,7 +820,7 @@ *bytesRead = 1; return NULL; } - *bytesRead = strlen((char *)data) + 1; + *bytesRead = (int)strlen((char *)data) + 1; return (char *)data; } @@ -961,8 +961,7 @@ data += bytes; break; case DW_FORM_ref_addr: - attr->value = (elfDebugInfo->infodata + elfRead4Bytes(data)) - - elfGetCompileUnitForData(data)->top; + attr->value = (u32)((elfDebugInfo->infodata + elfRead4Bytes(data)) - elfGetCompileUnitForData(data)->top); data += 4; break; case DW_FORM_ref4: @@ -970,11 +969,7 @@ data += 4; break; case DW_FORM_ref_udata: - attr->value = (elfDebugInfo->infodata + - (elfGetCompileUnitForData(data)->top - - elfDebugInfo->infodata) + - elfReadLEB128(data, &bytes)) - - elfCurrentUnit->top; + attr->value = (u32)((elfDebugInfo->infodata + (elfGetCompileUnitForData(data)->top - elfDebugInfo->infodata) + elfReadLEB128(data, &bytes)) - elfCurrentUnit->top); data += bytes; break; case DW_FORM_indirect: @@ -1070,7 +1065,7 @@ ELFcie *cies = NULL; while(data < end) { - u32 offset = data - topOffset; + u32 offset = (u32)(data - topOffset); u32 len = elfRead4Bytes(data); data += 4; @@ -1110,7 +1105,7 @@ cie->returnAddress = *data++; cie->data = data; - cie->dataLen = dataEnd - data; + cie->dataLen = (u32)(dataEnd - data); } else { ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde)); @@ -1136,7 +1131,7 @@ data += 4; fde->data = data; - fde->dataLen = dataEnd - data; + fde->dataLen = (u32)(dataEnd - data); if((elfFdeCount %10) == 0) { elfFdes = (ELFfde **)realloc(elfFdes, (elfFdeCount+10) * @@ -2659,6 +2654,7 @@ memcpy(&workRAM[READ32LE(&ph->paddr) & 0x3ffff], data + READ32LE(&ph->offset), READ32LE(&ph->filesz)); + size += READ32LE(&ph->filesz); } } else { if(READ32LE(&ph->paddr) >= 0x8000000 && @@ -2708,6 +2704,7 @@ memcpy(&workRAM[READ32LE(&sh[i]->addr) & 0x3ffff], data + READ32LE(&sh[i]->offset), READ32LE(&sh[i]->size)); + size += READ32LE(&sh[i]->size); } } else { if(READ32LE(&sh[i]->addr) >= 0x8000000 && @@ -2760,7 +2757,7 @@ while(ddata < end) { unit = elfParseCompUnit(ddata, abbrevdata); - unit->offset = ddata-debugdata; + unit->offset = (u32)(ddata-debugdata); elfParseLineInfo(unit, data); if(last == NULL) elfCompileUnits = unit; diff -urN ../VisualBoyAdvance-1.7.2/src/expr-lex.cpp ./src/expr-lex.cpp --- ../VisualBoyAdvance-1.7.2/src/expr-lex.cpp 2003-06-06 23:17:21 +0900 +++ ./src/expr-lex.cpp 2006-09-04 06:52:25 +0900 @@ -2,7 +2,7 @@ /* A lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header: /cvsroot/vba/VisualBoyAdvance/src/expr-lex.cpp,v 1.2 2003/06/06 14:17:21 forgotten Exp $ + * $Header: /cvsroot/vba/VisualBoyAdvance/src/expr-lex.cpp,v 1.4 2006/09/03 21:52:25 kxu Exp $ */ #define FLEX_SCANNER @@ -386,6 +386,7 @@ #ifndef __GNUC__ #include #define isatty _isatty +#define fileno _fileno #endif char *exprString; diff -urN ../VisualBoyAdvance-1.7.2/src/expr.l ./src/expr.l --- ../VisualBoyAdvance-1.7.2/src/expr.l 2002-10-20 22:03:12 +0900 +++ ./src/expr.l 2006-09-04 06:52:25 +0900 @@ -4,6 +4,7 @@ #ifndef __GNUC__ #include #define isatty _isatty +#define fileno _fileno #endif char *exprString; diff -urN ../VisualBoyAdvance-1.7.2/src/exprNode.cpp ./src/exprNode.cpp --- ../VisualBoyAdvance-1.7.2/src/exprNode.cpp 2004-05-13 23:33:47 +0900 +++ ./src/exprNode.cpp 2006-09-04 06:52:25 +0900 @@ -25,6 +25,10 @@ #include "elf.h" #include "exprNode.h" +#ifndef __GNUC__ +#define strdup _strdup +#endif + extern char *yytext; #define debuggerReadMemory(addr) \ diff -urN ../VisualBoyAdvance-1.7.2/src/gb/GB.cpp ./src/gb/GB.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/GB.cpp 2004-05-14 04:35:26 +0900 +++ ./src/gb/GB.cpp 2006-08-25 22:30:09 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -40,6 +40,7 @@ extern bool speedup; bool gbUpdateSizes(); +bool inBios = false; // debugging bool memorydebug = false; @@ -51,6 +52,7 @@ void (*mapper)(u16,u8) = NULL; void (*mapperRAM)(u16,u8) = NULL; u8 (*mapperReadRAM)(u16) = NULL; +void (*mapperUpdateClock)() = NULL; // registers gbRegister PC; @@ -59,7 +61,7 @@ gbRegister BC; gbRegister DE; gbRegister HL; -u16 IFF; +u16 IFF = 0; // 0xff04 u8 register_DIV = 0; // 0xff05 @@ -121,29 +123,79 @@ // state variables +// general +int clockTicks = 0; +bool gbSystemMessage = false; +int gbGBCColorType = 0; +int gbHardware = 0; +int gbRomType = 0; +int gbRemainingClockTicks = 0; +int gbOldClockTicks = 0; +int gbIntBreak = 0; +int gbInterruptLaunched = 0; +u8 gbCheatingDevice = 0; // 1 = GS, 2 = GG +// breakpoint +bool breakpoint = false; // interrupt -int gbInterrupt = 0; +int gbInt48Signal = 0; int gbInterruptWait = 0; // serial int gbSerialOn = 0; int gbSerialTicks = 0; int gbSerialBits = 0; // timer -int gbTimerOn = 0; -int gbTimerTicks = 0; -int gbTimerClockTicks = 0; +bool gbTimerOn = false; +int gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; +int gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS; int gbTimerMode = 0; +bool gbIncreased = false; +// The internal timer is always active, and it is +// not reset by writing to register_TIMA/TMA, but by +// writing to register_DIV... +int gbInternalTimer = 0x55; +const u8 gbTimerMask [4] = {0xff, 0x3, 0xf, 0x3f}; +const u8 gbTimerBug [8] = {0x80, 0x80, 0x02, 0x02, 0x0, 0xff, 0x0, 0xff}; +bool gbTimerModeChange = false; +bool gbTimerOnChange = false; // lcd +bool gbScreenOn = true; int gbLcdMode = 2; -int gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; -int gbLcdLYIncrementTicks = 0; +int gbLcdModeDelayed = 2; +int gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS-1; +int gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS; +int gbLcdLYIncrementTicks = 114; +int gbLcdLYIncrementTicksDelayed = 115; +int gbScreenTicks = 0; +u8 gbSCYLine[300]; +u8 gbSCXLine[300]; +u8 gbBgpLine[300]; +u8 gbObp0Line [300]; +u8 gbObp1Line [300]; +u8 gbSpritesTicks [300]; +u8 oldRegister_WY; +bool gbLYChangeHappened = false; +bool gbLCDChangeHappened = false; +int gbLine99Ticks = 1; +int gbRegisterLYLCDCOffOn = 0; +int inUseRegister_WY = 0; + +// Used to keep track of the line that ellapse +// when screen is off +int gbWhiteScreen = 0; +bool gbBlackScreen = false; +int register_LCDCBusy = 0; + // div int gbDivTicks = GBDIV_CLOCK_TICKS; // cgb int gbVramBank = 0; int gbWramBank = 1; -int gbHdmaSource = 0x0000; -int gbHdmaDestination = 0x8000; +//sgb +bool gbSgbResetFlag = false; +// gbHdmaDestination is 0x99d0 on startup (tested on HW) +// but I'm not sure what gbHdmaSource is... +int gbHdmaSource = 0x99d0; +int gbHdmaDestination = 0x99d0; int gbHdmaBytes = 0x0000; int gbHdmaOn = 0; int gbSpeed = 0; @@ -158,6 +210,7 @@ int gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; // emulator features int gbBattery = 0; +bool gbBatteryError = false; int gbCaptureNumber = 0; bool gbCapture = false; bool gbCapturePrevious = false; @@ -185,7 +238,7 @@ }; int gbRamSizes[6] = { 0x00000000, // 0K - 0x00000800, // 2K + 0x00002000, // 2K // Changed to 2000 to avoid problems with gbMemoryMap... 0x00002000, // 8K 0x00008000, // 32K 0x00020000, // 128K @@ -215,9 +268,9 @@ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c - 2, 3, 3, 0, 3, 4, 2, 4, 2, 4, 3, 0, 3, 0, 2, 4, // d - 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4, // e - 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4 // f + 2, 3, 3, 1, 3, 4, 2, 4, 2, 4, 3, 1, 3, 1, 2, 4, // d + 3, 3, 2, 1, 1, 4, 2, 4, 4, 1, 4, 1, 1, 1, 2, 4, // e + 3, 3, 2, 1, 1, 4, 2, 4, 3, 2, 4, 1, 0, 1, 2, 4 // f }; int gbCyclesCB[] = { @@ -230,14 +283,14 @@ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 8 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 9 - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // a - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // b - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // c - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // d - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // e - 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2 // f + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 8 + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 9 + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // a + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // b + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // c + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // d + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // e + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2 // f }; u16 DAATable[] = { @@ -499,7 +552,7 @@ 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950, }; -u8 ZeroTable[] = { +u8 ZeroTable[256] = { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -536,7 +589,8 @@ #define GBSAVE_GAME_VERSION_8 8 #define GBSAVE_GAME_VERSION_9 9 #define GBSAVE_GAME_VERSION_10 10 -#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_10 +#define GBSAVE_GAME_VERSION_11 11 +#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_11 int inline gbGetValue(int min,int max,int v) { @@ -596,45 +650,72 @@ void gbDoHdma() { - gbCopyMemory(gbHdmaDestination, - gbHdmaSource, + + gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000, + gbHdmaSource & 0xfff0, 0x10); - + gbHdmaDestination += 0x10; + if (gbHdmaDestination == 0xa000) + gbHdmaDestination = 0x8000; + gbHdmaSource += 0x10; + if (gbHdmaSource == 0x8000) + gbHdmaSource = 0xa000; - register_HDMA2 += 0x10; - if(register_HDMA2 == 0x00) - register_HDMA1++; - - register_HDMA4 += 0x10; - if(register_HDMA4 == 0x00) - register_HDMA3++; + register_HDMA2 = gbHdmaSource & 0xff; + register_HDMA1 = gbHdmaSource>>8; + + register_HDMA4 = gbHdmaDestination & 0xff; + register_HDMA3 = gbHdmaDestination>>8; - if(gbHdmaDestination == 0x96b0) - gbHdmaBytes = gbHdmaBytes; gbHdmaBytes -= 0x10; - register_HDMA5--; + gbMemory[0xff55] = --register_HDMA5; if(register_HDMA5 == 0xff) gbHdmaOn = 0; + +// We need to add the dmaClockticks for HDMA ! + if(gbSpeed) + gbDmaTicks = 17; + else + gbDmaTicks = 9; + + if (IFF & 0x80) + gbDmaTicks++; + } // fix for Harley and Lego Racers void gbCompareLYToLYC() { - if(register_LY == register_LYC) { - // mark that we have a match - register_STAT |= 4; + if(register_LCDC & 0x80) { + if(register_LY == register_LYC) { + + // mark that we have a match + register_STAT |= 4; - // check if we need an interrupt - if((register_STAT & 0x40) && (register_IE & 2)) - gbInterrupt |= 2; - } else // no match - register_STAT &= 0xfb; + // check if we need an interrupt + if (register_STAT & 0x40) + { + // send LCD interrupt only if no interrupt 48h signal... + if (!gbInt48Signal) + { + register_IF |=2; + } + gbInt48Signal |= 8; + } + } + else // no match + { + register_STAT &= 0xfb; + gbInt48Signal &=~8; + } + } } void gbWriteMemory(register u16 address, register u8 value) { + if(address < 0x8000) { #ifndef FINAL_VERSION if(memorydebug && (address>0x3fff || address < 0x2000)) { @@ -643,17 +724,31 @@ value, PC.W); } + #endif if(mapper) (*mapper)(address, value); return; + } - + if(address < 0xa000) { - gbMemoryMap[address>>12][address&0x0fff] = value; + // No access to Vram during mode 3 + // (used to emulate the gfx differences between GB & GBC-GBA/SP in Stunt Racer) + if ((gbLcdModeDelayed !=3) || + // This part is used to emulate a small difference between hardwares + // (check 8-in-1's arrow on GBA/GBC to verify it) + ((register_LY == 0) && ((gbHardware & 0xa) && (gbScreenOn==false) && + (register_LCDC & 0x80)) && + (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) + gbMemoryMap[address>>12][address&0x0fff] = value; return; } - + + // Used for the mirroring of 0xC000 in 0xE000 + if ((address >= 0xe000) && (address < 0xfe00)) + address &= ~0x2000; + if(address < 0xc000) { #ifndef FINAL_VERSION if(memorydebug) { @@ -663,474 +758,831 @@ PC.W); } #endif - - if(mapper) - (*mapperRAM)(address, value); + + // Is that a correct fix ??? (it used to be 'if (mapper)')... + if(mapperRAM) + (*mapperRAM)(address, value); return; } - + + if(address < 0xfe00) { gbMemoryMap[address>>12][address & 0x0fff] = value; return; } - - if(address < 0xff00) { + + // OAM not accessible during mode 2 & 3. + if(address < 0xfea0) + { + if (((gbHardware & 0xa) && ((gbLcdMode | gbLcdModeDelayed) &2)) || + ((gbHardware & 5) && (((gbLcdModeDelayed == 2) && + (gbLcdTicksDelayed<=GBLCD_MODE_2_CLOCK_TICKS)) || + (gbLcdModeDelayed == 3)))) + return; + else + { + gbMemory[address] = value; + return; + } + } + + + + if((address > 0xfea0) && (address < 0xff00)){ // GBC allows reading/writing to that area gbMemory[address] = value; return; - } - + } + switch(address & 0x00ff) { - case 0x00: { - gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) | - (value & 0x30)); - if(gbSgbMode) { - gbSgbDoBitTransfer(value); + + case 0x00: { + gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) | + (value & 0x30) | 0xc0); + if(gbSgbMode) { + gbSgbDoBitTransfer(value); + } + return; } - - return; - } - case 0x01: { - gbMemory[0xff01] = value; - return; - } + case 0x01: { + gbMemory[0xff01] = value; + return; + } - // serial control - case 0x02: { - gbSerialOn = (value & 0x80); - gbMemory[0xff02] = value; - if(gbSerialOn) { - gbSerialTicks = GBSERIAL_CLOCK_TICKS; + // serial control + case 0x02: { + gbSerialOn = (value & 0x80); + gbMemory[0xff02] = value; + if(gbSerialOn) { + gbSerialTicks = GBSERIAL_CLOCK_TICKS; #ifdef LINK_EMULATION - if(linkConnected) { - if(value & 1) { - linkSendByte(0x100|gbMemory[0xFF01]); - Sleep(5); + if(linkConnected) { + if(value & 1) { + linkSendByte(0x100|gbMemory[0xFF01]); + Sleep(5); + } } - } #endif - } + } - gbSerialBits = 0; - return; - } + gbSerialBits = 0; + return; + } - // DIV register resets on any write - case 0x04: { - register_DIV = 0; - return; - } - case 0x05: - register_TIMA = value; - return; + case 0x04: { + // DIV register resets on any write + // (not totally perfect, but better than nothing) + gbMemory[0xff04] = register_DIV = 0; + gbDivTicks = GBDIV_CLOCK_TICKS; + // Another weird timer 'bug' : + // Writing to DIV register resets the internal timer, + // and can also increase TIMA/trigger an interrupt + // in some cases... + if (gbTimerOn && !(gbInternalTimer & (gbTimerClockTicks>>1))) + { + gbMemory[0xff05] = ++register_TIMA; + if(register_TIMA == 0) { + // timer overflow! + + // reload timer modulo + gbMemory[0xff05] = register_TIMA = register_TMA; + + // flag interrupt + gbMemory[0xff0f] = register_IF |= 4; + } + } + gbInternalTimer = 0xff; + return; + } + case 0x05: + gbMemory[0xff05] = register_TIMA = value; + return; - case 0x06: - register_TMA = value; - return; - - // TIMER control - case 0x07: { - register_TAC = value; + case 0x06: + gbMemory[0xff06] = register_TMA = value; + return; - gbTimerOn = (value & 4); - gbTimerMode = value & 3; - // register_TIMA = register_TMA; - switch(gbTimerMode) { - case 0: - gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; - break; - case 1: - gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_1_CLOCK_TICKS; - break; - case 2: - gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_2_CLOCK_TICKS; - break; - case 3: - gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_3_CLOCK_TICKS; - break; - } - return; - } + // TIMER control + case 0x07: { - case 0x0f: { - register_IF = value; - gbInterrupt = value; - return; - } - - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: { - SOUND_EVENT(address,value); - return; - } - case 0x40: { - int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80); + gbTimerModeChange = (((value & 3) != (register_TAC&3)) && (value & register_TAC & 4)) ? true : false; + gbTimerOnChange = (((value ^ register_TAC) & 4) == 4) ? true : false; + + gbTimerOn = (value & 4) ? true : false; - if(lcdChange) { - if(value & 0x80) { - gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS; - gbLcdMode = 0; - register_STAT &= 0xfc; - register_LY = 0x00; - } else { - gbLcdTicks = 0; - gbLcdMode = 0; - register_STAT &= 0xfc; - register_LY = 0x00; - } - // compareLYToLYC(); - } - // don't draw the window if it was not enabled and not being drawn before - if(!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 && - register_LY > register_WY) - gbWindowLine = 144; + if (gbTimerOnChange || gbTimerModeChange) + { + gbTimerMode = value & 3; - register_LCDC = value; + switch(gbTimerMode) { + case 0: + gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS; + break; + case 1: + gbTimerClockTicks = GBTIMER_MODE_1_CLOCK_TICKS; + break; + case 2: + gbTimerClockTicks = GBTIMER_MODE_2_CLOCK_TICKS; + break; + case 3: + gbTimerClockTicks = GBTIMER_MODE_3_CLOCK_TICKS; + break; + } + } - return; - } - // STAT - case 0x41: { - //register_STAT = (register_STAT & 0x87) | - // (value & 0x7c); - register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? - // GB bug from Devrs FAQ - if(!gbCgbMode && (register_LCDC & 0x80) && gbLcdMode < 2) - gbInterrupt |= 2; - return; - } + // This looks weird, but this emulates a bug in which register_TIMA + // is increased when writing to register_TAC + // (This fixes Korodice's long-delay between menus bug). + + if (gbTimerOnChange || gbTimerModeChange) + { + bool temp = false; - // SCY - case 0x42: { - register_SCY = value; - return; - } - - // SCX - case 0x43: { - register_SCX = value; - return; - } - - // LY - case 0x44: { - // read only - return; - } + if ((gbTimerOn && !gbTimerModeChange) && (gbTimerMode & 2) && + !(gbInternalTimer & 0x80) && (gbInternalTimer & (gbTimerClockTicks>>1)) && + !(gbInternalTimer & (gbTimerClockTicks>>5))) + temp = true; + else if ((!gbTimerOn && !gbTimerModeChange && gbTimerOnChange ) && ((gbTimerTicks-1) < (gbTimerClockTicks>>1))) + temp = true; + else if (gbTimerOn && gbTimerModeChange && !gbTimerOnChange) + { + switch(gbTimerMode & 3) + { + case 0x00: + temp = false; + break; + case 0x01: + if (((gbInternalTimer & 0x82) == 2) && (gbTimerTicks>(clockTicks+1))) + temp = true; + break; + case 0x02: + if (((gbInternalTimer & 0x88) == 0x8) && (gbTimerTicks>(clockTicks+1))) + temp = true; + break; + case 0x03: + if (((gbInternalTimer & 0xA0) == 0x20) && (gbTimerTicks>(clockTicks+1))) + temp = true; + break; + } + } - // LYC - case 0x45: { - register_LYC = value; - if((register_LCDC & 0x80)) { - gbCompareLYToLYC(); + if (temp) + { + gbMemory[0xff05] = ++register_TIMA; + if((register_TIMA & 0xff) == 0) { + // timer overflow! + + // reload timer modulo + gbMemory[0xff05] = register_TIMA = register_TMA; + + // flag interrupt + gbMemory[0xff0f] = register_IF |= 4; + } + } + } + gbMemory[0xff07] = register_TAC = value; + return; } - return; - } - - // DMA! - case 0x46: { - int source = value * 0x0100; - - gbCopyMemory(0xfe00, - source, - 0xa0); - register_DMA = value; - return; - } - - // BGP - case 0x47: { - gbBgp[0] = value & 0x03; - gbBgp[1] = (value & 0x0c)>>2; - gbBgp[2] = (value & 0x30)>>4; - gbBgp[3] = (value & 0xc0)>>6; - break; - } - - // OBP0 - case 0x48: { - gbObp0[0] = value & 0x03; - gbObp0[1] = (value & 0x0c)>>2; - gbObp0[2] = (value & 0x30)>>4; - gbObp0[3] = (value & 0xc0)>>6; - break; - } - - // OBP1 - case 0x49: { - gbObp1[0] = value & 0x03; - gbObp1[1] = (value & 0x0c)>>2; - gbObp1[2] = (value & 0x30)>>4; - gbObp1[3] = (value & 0xc0)>>6; - break; - } - case 0x4a: - register_WY = value; - return; - - case 0x4b: - register_WX = value; - return; - - // KEY1 - case 0x4d: { - if(gbCgbMode) { - gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1); + case 0x0f: { + gbMemory[0xff0f] = register_IF = value; + //gbMemory[0xff0f] = register_IE |= value; return; } - } - break; - - // VBK - case 0x4f: { - if(gbCgbMode) { - value = value & 1; - if(value == gbVramBank) + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: { + if (gbMemory[NR52] & 0x80) { + SOUND_EVENT(address,value); return; - - int vramAddress = value * 0x2000; - gbMemoryMap[0x08] = &gbVram[vramAddress]; - gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000]; - - gbVramBank = value; - register_VBK = value; + } } - return; - } - break; - // HDMA1 - case 0x51: { - if(gbCgbMode) { - if(value > 0x7f && value < 0xa0) - value = 0; - - gbHdmaSource = (value << 8) | (register_HDMA2 & 0xf0); - - register_HDMA1 = value; - return; - } - } - break; - - // HDMA2 - case 0x52: { - if(gbCgbMode) { - value = value & 0xf0; - - gbHdmaSource = (register_HDMA1 << 8) | (value); - - register_HDMA2 = value; + case 0x26: { + SOUND_EVENT(address,value); return; } - } - break; - // HDMA3 - case 0x53: { - if(gbCgbMode) { - value = value & 0x1f; - gbHdmaDestination = (value << 8) | (register_HDMA4 & 0xf0); - gbHdmaDestination += 0x8000; - register_HDMA3 = value; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: { + gbMemory[address] = value; return; } - } - break; + + case 0x40: { + int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80); + + // don't draw the window if it was not enabled and not being drawn before + if(!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 && + register_LY > register_WY) + gbWindowLine = 146; + // 007 fix : don't draw the first window's 1st line if it's enable 'too late' + // (ie. if register_LY == register_WY when enabling it) + // and move it to the next line + else if (!(register_LCDC & 0x20) && (value & 0x20) && (register_LY == register_WY)) + gbWindowLine = -2; + + + gbMemory[0xff40] = register_LCDC = value; + + + if(lcdChange) { + if((value & 0x80) && (!register_LCDCBusy)) { + + // if (!gbWhiteScreen && !gbSgbMask) + + // systemDrawScreen(); + + + + gbRegisterLYLCDCOffOn = (register_LY + 144) % 154; + + gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 2 : 1); + gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 1 : 0); + gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 2 : 1); + gbLcdLYIncrementTicksDelayed = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 1 : 0); + gbLcdMode = 2; + gbLcdModeDelayed = 2; + gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | 2; + gbMemory[0xff44] = register_LY = 0x00; + gbInt48Signal = 0; + gbLYChangeHappened = false; + gbLCDChangeHappened = false; + gbWindowLine = 146; + oldRegister_WY = 146; + + // Fix for Namco Gallery Vol.2 + // (along with updating register_LCDC at the start of 'case 0x40') : + if(register_STAT & 0x20) + { + // send LCD interrupt only if no interrupt 48h signal... + if (!gbInt48Signal) + { + gbMemory[0xff0f] = register_IF |= 2; + } + gbInt48Signal |= 4; + } + gbCompareLYToLYC(); + + } else { - // HDMA4 - case 0x54: { - if(gbCgbMode) { - value = value & 0xf0; - gbHdmaDestination = ((register_HDMA3 & 0x1f) << 8) | value; - gbHdmaDestination += 0x8000; - register_HDMA4 = value; + register_LCDCBusy = clockTicks+6; + + //used to update the screen with white lines when it's off. + //(it looks strange, but it's pretty accurate) + + gbWhiteScreen = 0; + + gbScreenTicks = ((150-register_LY)*GBLY_INCREMENT_CLOCK_TICKS + + (49<<(gbSpeed ? 1 : 0))); + + // disable the screen rendering + gbScreenOn = false; + gbLcdTicks = 0; + gbLcdMode = 0; + gbLcdModeDelayed = 0; + gbMemory[0xff41] = register_STAT &= 0xfc; + gbInt48Signal = 0; + } + } return; } - } - break; - - // HDMA5 - case 0x55: { - if(gbCgbMode) { - gbHdmaBytes = 16 + (value & 0x7f) * 16; - if(gbHdmaOn) { - if(value & 0x80) { - register_HDMA5 = (value & 0x7f); - } else { - register_HDMA5 = 0xff; - gbHdmaOn = 0; + + // STAT + case 0x41: { + //register_STAT = (register_STAT & 0x87) | + // (value & 0x7c); + gbMemory[0xff41] = register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? + // GB bug from Devrs FAQ + // Corrected : it happens if Lcd Mode<2, but also if LY == LYC whatever + // Lcd Mode is, and if !gbInt48Signal in all cases. The screen being off + // doesn't matter (the bug will still happen). + // That fixes 'Satoru Nakajima - F-1 Hero' crash bug. + + if((gbHardware & 5) && (((!gbInt48Signal) && (gbLcdMode<2) && (register_LCDC & 0x80)) || + (register_LY == register_LYC))) + { + gbMemory[0xff0f] = register_IF |=2; + } + + gbInt48Signal &= ((register_STAT>>3) & 0xF); + + if((register_LCDC & 0x80)) { + if ((register_STAT & 0x08) && (gbLcdMode == 0)) + { + if (!gbInt48Signal) + { + gbMemory[0xff0f] = register_IF |=2; + } + gbInt48Signal |= 1; } - } else { - if(value & 0x80) { - gbHdmaOn = 1; - register_HDMA5 = value & 0x7f; - if(gbLcdMode == 0) - gbDoHdma(); - } else { - // we need to take the time it takes to complete the transfer into - // account... according to GB DEV FAQs, the setup time is the same - // for single and double speed, but the actual transfer takes the - // same time - if(gbSpeed) - gbDmaTicks = 231 + 16 * (value & 0x7f); - else - gbDmaTicks = 231 + 8 * (value & 0x7f); - gbCopyMemory(gbHdmaDestination, - gbHdmaSource, - gbHdmaBytes); - gbHdmaDestination += gbHdmaBytes; - gbHdmaSource += gbHdmaBytes; - - register_HDMA3 = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f; - register_HDMA4 = gbHdmaDestination & 0xf0; - register_HDMA1 = (gbHdmaSource >> 8) & 0xff; - register_HDMA2 = gbHdmaSource & 0xf0; + if ((register_STAT & 0x10) && (gbLcdMode == 1)) + { + if (!gbInt48Signal) + { + gbMemory[0xff0f] = register_IF |=2; + } + gbInt48Signal |= 2; + } + if ((register_STAT & 0x20) && (gbLcdMode == 2)) + { + if (!gbInt48Signal) + { + gbMemory[0xff0f] = register_IF |=2; + } + gbInt48Signal |= 4; } + gbCompareLYToLYC(); + + gbMemory[0xff0f] = register_IF; + gbMemory[0xff41] = register_STAT; + } return; } - } - break; - - // BCPS - case 0x68: { - if(gbCgbMode) { - int paletteIndex = (value & 0x3f) >> 1; - int paletteHiLo = (value & 0x01); - - gbMemory[0xff68] = value; - gbMemory[0xff69] = (paletteHiLo ? - (gbPalette[paletteIndex] >> 8) : - (gbPalette[paletteIndex] & 0x00ff)); - return; - } - } - break; - - // BCPD - case 0x69: { - if(gbCgbMode) { - int v = gbMemory[0xff68]; - int paletteIndex = (v & 0x3f) >> 1; - int paletteHiLo = (v & 0x01); - gbMemory[0xff69] = value; - gbPalette[paletteIndex] = (paletteHiLo ? - ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : - ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; - - if(gbMemory[0xff68] & 0x80) { - int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f; - - gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index; - - gbMemory[0xff69] = (index & 1 ? - (gbPalette[index>>1] >> 8) : - (gbPalette[index>>1] & 0x00ff)); - + + // SCY + case 0x42: { + int temp = -1; + + if ((gbLcdMode == 3) || (gbLcdModeDelayed == 3)) + temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - + gbLcdLYIncrementTicks); + + if (temp >=0) + { + for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) + if (temp < 300) + gbSCYLine[i] = value; } + + else + memset(gbSCYLine, value, sizeof(gbSCYLine)); + + gbMemory[0xff42] = register_SCY = value; return; } - } - break; - // OCPS - case 0x6a: { - if(gbCgbMode) { - int paletteIndex = (value & 0x3f) >> 1; - int paletteHiLo = (value & 0x01); - - paletteIndex += 32; + // SCX + case 0x43: { + int temp = -1; + + if (gbLcdModeDelayed == 3) + temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - + gbLcdLYIncrementTicksDelayed); + + if (temp >=0) + { + for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) + if (temp < 300) + gbSCXLine[i] = value; + } - gbMemory[0xff6a] = value; - gbMemory[0xff6b] = (paletteHiLo ? - (gbPalette[paletteIndex] >> 8) : - (gbPalette[paletteIndex] & 0x00ff)); + else + memset(gbSCXLine, value, sizeof(gbSCXLine)); + + gbMemory[0xff43] = register_SCX = value; return; } - } - break; - // OCPD - case 0x6b: { - if(gbCgbMode) { - int v = gbMemory[0xff6a]; - int paletteIndex = (v & 0x3f) >> 1; - int paletteHiLo = (v & 0x01); - - paletteIndex += 32; - - gbMemory[0xff6b] = value; - gbPalette[paletteIndex] = (paletteHiLo ? - ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : - ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; - if(gbMemory[0xff6a] & 0x80) { - int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f; - - gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index; - - gbMemory[0xff6b] = (index & 1 ? - (gbPalette[(index>>1) + 32] >> 8) : - (gbPalette[(index>>1) + 32] & 0x00ff)); - - } + // LY + case 0x44: { + // read only return; } - } - break; - - // SVBK - case 0x70: { - if(gbCgbMode) { - value = value & 7; - - int bank = value; - if(value == 0) - bank = 1; - if(bank == gbWramBank) + // LYC + case 0x45: { + if (register_LYC != value) + { + gbMemory[0xff45] = register_LYC = value; + if(register_LCDC & 0x80) { + gbCompareLYToLYC(); + } + } + return; + } + + // DMA! + case 0x46: { + int source = value * 0x0100; + + gbCopyMemory(0xfe00, + source, + 0xa0); + gbMemory[0xff46] = register_DMA = value; + return; + } + + // BGP + case 0x47: { + + int temp = -1; + + gbMemory[0xff47] = value; + + if (gbLcdModeDelayed == 3) + temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - + gbLcdLYIncrementTicksDelayed); + + if (temp >=0) + { + for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) + if (temp < 300) + gbBgpLine[i] = value; + } + else + memset(gbBgpLine,value,sizeof(gbBgpLine)); + + gbBgp[0] = value & 0x03; + gbBgp[1] = (value & 0x0c)>>2; + gbBgp[2] = (value & 0x30)>>4; + gbBgp[3] = (value & 0xc0)>>6; + break; + } + + // OBP0 + case 0x48: { + int temp = -1; + + gbMemory[0xff48] = value; + + if (gbLcdModeDelayed == 3) + temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - + gbLcdLYIncrementTicksDelayed); + + if (temp >=0) + { + for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) + if (temp < 300) + gbObp0Line[i] = value; + } + else + memset(gbObp0Line,value,sizeof(gbObp0Line)); + + gbObp0[0] = value & 0x03; + gbObp0[1] = (value & 0x0c)>>2; + gbObp0[2] = (value & 0x30)>>4; + gbObp0[3] = (value & 0xc0)>>6; + break; + } + + // OBP1 + case 0x49: { + int temp = -1; + + gbMemory[0xff49] = value; + + if (gbLcdModeDelayed == 3) + temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) - + gbLcdLYIncrementTicksDelayed); + + if (temp >=0) + { + for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++) + if (temp < 300) + gbObp1Line[i] = value; + } + else + memset(gbObp1Line,value,sizeof(gbObp1Line)); + + gbObp1[0] = value & 0x03; + gbObp1[1] = (value & 0x0c)>>2; + gbObp1[2] = (value & 0x30)>>4; + gbObp1[3] = (value & 0xc0)>>6; + break; + } + + // WY + case 0x4a: + gbMemory[0xff4a] = register_WY = value; + if ((register_LY <= register_WY) && ((gbWindowLine < 0) || (gbWindowLine>=144))) + { + gbWindowLine = -1; + oldRegister_WY = register_WY; + } + return; + + // WX + case 0x4b: + gbMemory[0xff4b] = register_WX = value; + return; + + // KEY1 + case 0x4d: { + if(gbCgbMode) { + gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1) | 0x7e; return; + } + } + break; + + // VBK + case 0x4f: { + if(gbCgbMode) { + value = value & 1; + if(value == gbVramBank) + return; - int wramAddress = bank * 0x1000; - gbMemoryMap[0x0d] = &gbWram[wramAddress]; + int vramAddress = value * 0x2000; + gbMemoryMap[0x08] = &gbVram[vramAddress]; + gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000]; - gbWramBank = bank; - register_SVBK = value; + gbVramBank = value; + register_VBK = value; + } return; } - } - break; + break; + + // BOOTROM disable register (also gbCgbMode enabler if value & 0x10 ?) + case 0x50 : + { + if (useBios && inBios && !skipBios && (value & 1)) + { + gbMemoryMap[0x00] = &gbRom[0x0000]; + memcpy ((u8 *)(gbRom+0x100), (u8 *)(gbMemory + 0x100), 0xF00); + inBios = false; + } + } + + // HDMA1 + case 0x51: { + if(gbCgbMode) { + if(value > 0x7f && value < 0xa0) + value = 0; + + gbHdmaSource = (value << 8) | (gbHdmaSource & 0xf0); + + register_HDMA1 = value; + return; + } + } + break; - case 0xff: { - register_IE = value; - register_IF &= value; - return; + // HDMA2 + case 0x52: { + if(gbCgbMode) { + value = value & 0xf0; + + gbHdmaSource = (gbHdmaSource & 0xff00) | (value); + + register_HDMA2 = value; + return; + } + } + break; + + // HDMA3 + case 0x53: { + if(gbCgbMode) { + value = value & 0x1f; + gbHdmaDestination = (value << 8) | (gbHdmaDestination & 0xf0); + gbHdmaDestination |= 0x8000; + register_HDMA3 = value; + return; + } + } + break; + + // HDMA4 + case 0x54: { + if(gbCgbMode) { + value = value & 0xf0; + gbHdmaDestination = (gbHdmaDestination & 0x1f00) | value; + gbHdmaDestination |= 0x8000; + register_HDMA4 = value; + return; + } + } + break; + + // HDMA5 + case 0x55: { + + if(gbCgbMode) { + gbHdmaBytes = 16 + (value & 0x7f) * 16; + if(gbHdmaOn) { + if(value & 0x80) { + gbMemory[0xff55] = register_HDMA5 = (value & 0x7f); + } else { + register_HDMA5 = 0xff; + gbHdmaOn = 0; + } + } else { + if(value & 0x80) { + gbHdmaOn = 1; + gbMemory[0xff55] = register_HDMA5 = value & 0x7f; + if(gbLcdModeDelayed == 0) + gbDoHdma(); + } else { + // we need to take the time it takes to complete the transfer into + // account... according to GB DEV FAQs, the setup time is the same + // for single and double speed, but the actual transfer takes the + // same time + if(gbSpeed) + gbDmaTicks = 2+16 * ((value & 0x7f) +1); + else + gbDmaTicks = 1+8 * ((value & 0x7f)+1); + + gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000, + gbHdmaSource & 0xfff0, + gbHdmaBytes); + gbHdmaDestination += gbHdmaBytes; + gbHdmaSource += gbHdmaBytes; + + gbMemory[0xff51] = register_HDMA1 = 0xff;// = (gbHdmaSource >> 8) & 0xff; + gbMemory[0xff52] = register_HDMA2 = 0xff;// = gbHdmaSource & 0xf0; + gbMemory[0xff53] = register_HDMA3 = 0xff;// = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f; + gbMemory[0xff54] = register_HDMA4 = 0xff;// = gbHdmaDestination & 0xf0; + gbMemory[0xff55] = register_HDMA5 = 0xff; + } + } + return; + } + } + break; + + // BCPS + case 0x68: { + if(gbCgbMode) { + int paletteIndex = (value & 0x3f) >> 1; + int paletteHiLo = (value & 0x01); + + gbMemory[0xff68] = value; + + gbMemory[0xff69] = (paletteHiLo ? + (gbPalette[paletteIndex] >> 8) : + (gbPalette[paletteIndex] & 0x00ff)); + return; + } + } + break; + + // BCPD + case 0x69: { + if(gbCgbMode) { + int v = gbMemory[0xff68]; + int paletteIndex = (v & 0x3f) >> 1; + int paletteHiLo = (v & 0x01); + + // No access to gbPalette during mode 3 (Color Panel Demo) + if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + { + gbMemory[0xff69] = value; + gbPalette[paletteIndex] = (paletteHiLo ? + ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : + ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; + } + + + if(gbMemory[0xff68] & 0x80) { + int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f; + + gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index; + gbMemory[0xff69] = (index & 1 ? + (gbPalette[index>>1] >> 8) : + (gbPalette[index>>1] & 0x00ff)); + } + return; + } + } + break; + + // OCPS + case 0x6a: { + if(gbCgbMode) { + int paletteIndex = (value & 0x3f) >> 1; + int paletteHiLo = (value & 0x01); + + paletteIndex += 32; + + gbMemory[0xff6a] = value; + + gbMemory[0xff6b] = (paletteHiLo ? + (gbPalette[paletteIndex] >> 8) : + (gbPalette[paletteIndex] & 0x00ff)); + return; + } + } + break; + + // OCPD + case 0x6b: { + + if(gbCgbMode) { + int v = gbMemory[0xff6a]; + int paletteIndex = (v & 0x3f) >> 1; + int paletteHiLo = (v & 0x01); + + paletteIndex += 32; + + // No access to gbPalette during mode 3 (Color Panel Demo) + if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || + ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) || + ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2)))))) + { + gbMemory[0xff6b] = value; + gbPalette[paletteIndex] = (paletteHiLo ? + ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : + ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; + } + + if(gbMemory[0xff6a] & 0x80) { + int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f; + + gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index; + + gbMemory[0xff6b] = (index & 1 ? + (gbPalette[(index>>1) + 32] >> 8) : + (gbPalette[(index>>1) + 32] & 0x00ff)); + } + return; + } + } + break; + + case 0x6c: { + gbMemory[0xff6c] = 0xfe | value; + return; + } + + + // SVBK + case 0x70: { + if(gbCgbMode) { + value = value & 7; + + int bank = value; + if(value == 0) + bank = 1; + + if(bank == gbWramBank) + return; + + int wramAddress = bank * 0x1000; + gbMemoryMap[0x0d] = &gbWram[wramAddress]; + + gbWramBank = bank; + gbMemory[0xff70] = register_SVBK = value; + return; + } + } + + case 0x75:{ + gbMemory[0xff75] = 0x8f | value; + return; + } + + case 0xff: { + gbMemory[0xffff] = register_IE = value; + return; + } } + + if(address < 0xff80) + { + gbMemory[address] = value; + return; } - + gbMemory[address] = value; } @@ -1139,6 +1591,27 @@ if(gbCheatMap[address]) return gbCheatRead(address); + if(address < 0x8000) + return gbMemoryMap[address>>12][address&0x0fff]; + + 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]; + return 0xff; + } + + // Used for the mirroring of 0xC000 in 0xE000 + if ((address >= 0xe000) && (address < 0xfe00)) + address &= ~0x2000; + switch(address & 0xf000) { case 0x0a: case 0x0b: @@ -1148,6 +1621,10 @@ case 0x0f: if(address > 0xff00) { switch(address & 0x00ff) { + case 0x02: + return (gbMemory[0xff02]); + case 0x03: + return (0xff); case 0x04: return register_DIV; case 0x05: @@ -1156,17 +1633,33 @@ return register_TMA; case 0x07: return (0xf8 | register_TAC); + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + return (0xff); case 0x0f: - return (0xe0 | register_IF); + return (0xe0 | gbMemory[0xff0f]); case 0x40: return register_LCDC; case 0x41: - return (0x80 | register_STAT); + // This is a GB/C only bug (ie. not GBA/SP). + if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed)) + return (0x80 | gbMemory[0xff41] & 0xFC); + else + return (0x80 | gbMemory[0xff41]); case 0x42: return register_SCY; case 0x43: return register_SCX; case 0x44: + if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) || + (!(register_LCDC && 0x80))) + return 0; + else return register_LY; case 0x45: return register_LYC; @@ -1176,6 +1669,8 @@ return register_WY; case 0x4b: return register_WX; + case 0x4c: + return 0xff; case 0x4f: return (0xfe | register_VBK); case 0x51: @@ -1188,14 +1683,55 @@ return register_HDMA4; case 0x55: return register_HDMA5; + case 0x68: + case 0x6a: + if (gbCgbMode) + return (0x40 | gbMemory[address]); + else + return 0xc0; + case 0x69: + case 0x6b: + 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)))))) + return (gbMemory[address]); + else + return 0xff; + } + else + return 0xff; case 0x70: - return (0xf8 | register_SVBK); + if (gbCgbMode) + return (0xf8 | register_SVBK); + else + return 0xff; case 0xff: return register_IE; } } + // OAM not accessible during mode 2 & 3. + if(((address >= 0xfe00) && (address<0xfea0)) && + ((gbLcdMode | gbLcdModeDelayed) &2)) + return 0xff; break; } + + if ((address >= 0xfea0) && (address < 0xff00)) + { + if (gbHardware & 1) + return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff ); + else if (gbHardware & 2) + return gbMemoryMap[address>>12][address & 0x0fff]; + else if (gbHardware & 4) + return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 ); + else if (gbHardware & 8) + return ((address & 0xf0) |((address & 0xf0)>>4)); + } + return gbMemoryMap[address>>12][address & 0x0fff]; } @@ -1203,10 +1739,28 @@ { if(gbCheatMap[address]) return gbCheatRead(address); - - if(address < 0xa000) + + + if(address < 0x8000) return gbMemoryMap[address>>12][address&0x0fff]; + 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]; + return 0xff; + } + + if ((address >= 0xe000) && (address < 0xfe00)) + address &= ~0x2000; + if(address < 0xc000) { #ifndef FINAL_VERSION if(memorydebug) { @@ -1215,11 +1769,18 @@ PC.W); } #endif - + + // for the 2kb ram limit (fixes crash in shawu's story + // but now its sram test fails, as the it expects 8kb and not 2kb... + // So use the 'genericflashcard' option to fix it). + if (address<=(0xa000+gbRamSizeMask)) + { if(mapperReadRAM) return mapperReadRAM(address); return gbMemoryMap[address>>12][address & 0x0fff]; } + return 0xff; + } if(address >= 0xff00) { switch(address & 0x00ff) { @@ -1310,8 +1871,10 @@ break; case 0x01: return gbMemory[0xff01]; + case 0x02: + return (gbMemory[0xff02]); case 0x04: - return register_DIV; + return register_DIV; case 0x05: return register_TIMA; case 0x06: @@ -1319,17 +1882,45 @@ case 0x07: return (0xf8 | register_TAC); case 0x0f: - return (0xe0 | register_IF); - case 0x40: + return (0xe0 | gbMemory[0xff0f]); + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + if ((gbMemory[NR30] & 0x80) && (gbMemory[NR34] & 0x80)) + return 0xFF; + else + return gbMemoryMap[address>>12][address & 0x0fff]; + case 0x40: return register_LCDC; case 0x41: - return (0x80 | register_STAT); + // This is a GB/C only bug (ie. not GBA/SP). + if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed)) + return (0x80 | gbMemory[0xff41] & 0xFC); + else + return (0x80 | gbMemory[0xff41]); case 0x42: return register_SCY; case 0x43: return register_SCX; case 0x44: - return register_LY; + if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) || + (!(register_LCDC && 0x80))) + return (0); + else + return register_LY; case 0x45: return register_LYC; case 0x46: @@ -1350,27 +1941,62 @@ return register_HDMA4; case 0x55: return register_HDMA5; + case 0x68: + case 0x6a: + if (gbCgbMode) + return (0x40 | gbMemory[address]); + else + return 0xc0; + case 0x69: + case 0x6b: + 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)))))) + return (gbMemory[address]); + else + return 0xff; + } + else + return 0xff; case 0x70: - return (0xf8 | register_SVBK); + if (gbCgbMode) + return (0xf8 | register_SVBK); + else + return 0xff; case 0xff: return register_IE; } } - + // OAM not accessible during mode 2 & 3. + if(((address >= 0xfe00) && (address<0xfea0)) && + (((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; + + if ((address >= 0xfea0) && (address < 0xff00)) + { + if (gbHardware & 1) + return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff ); + else if (gbHardware & 2) + return gbMemoryMap[address>>12][address & 0x0fff]; + else if (gbHardware & 4) + return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 ); + else if (gbHardware & 8) + return ((address & 0xf0) |((address & 0xf0)>>4)); + } + return gbMemoryMap[address>>12][address & 0x0fff]; } void gbVblank_interrupt() { - if(IFF & 0x80) { - PC.W++; - IFF &= 0x7f; - } - gbInterrupt &= 0xfe; - - IFF &= 0x7e; - register_IF &= 0xfe; - + gbCheatWrite(false); // Emulates GS codes. + gbMemory[0xff0f] = register_IF &= 0xfe; gbWriteMemory(--SP.W, PC.B.B1); gbWriteMemory(--SP.W, PC.B.B0); PC.W = 0x40; @@ -1378,221 +2004,617 @@ void gbLcd_interrupt() { - if(IFF & 0x80) { - PC.W++; - IFF &= 0x7f; - } - gbInterrupt &= 0xfd; - IFF &= 0x7e; - register_IF &= 0xfd; - + gbMemory[0xff0f] = register_IF &= 0xfd; gbWriteMemory(--SP.W, PC.B.B1); gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x48; } void gbTimer_interrupt() { - if(IFF & 0x80) { - PC.W++; - IFF &= 0x7f; - } - IFF &= 0x7e; - gbInterrupt &= 0xfb; - register_IF &= 0xfb; - + gbMemory[0xff0f] = register_IF &= 0xfb; gbWriteMemory(--SP.W, PC.B.B1); gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x50; } void gbSerial_interrupt() { - if(IFF & 0x80) { - PC.W++; - IFF &= 0x7f; - } - IFF &= 0x7e; - gbInterrupt &= 0xf7; - register_IF &= 0xf7; - + gbMemory[0xff0f] = register_IF &= 0xf7; gbWriteMemory(--SP.W, PC.B.B1); gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x58; } void gbJoypad_interrupt() { - if(IFF & 0x80) { - PC.W++; - IFF &= 0x7f; - } - IFF &= 0x7e; - gbInterrupt &= 0xef; - register_IF &= 0xef; - + gbMemory[0xff0f] = register_IF &= 0xef; gbWriteMemory(--SP.W, PC.B.B1); gbWriteMemory(--SP.W, PC.B.B0); - PC.W = 0x60; } void gbSpeedSwitch() { + gbBlackScreen = true; if(gbSpeed == 0) { gbSpeed = 1; - GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; //127; //51 * 2; + GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2; - GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; //52; //20 * 2; - GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; //99; //43 * 2; - GBDIV_CLOCK_TICKS = 64 * 2; + GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; + GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; GBLY_INCREMENT_CLOCK_TICKS = 114 * 2; - GBTIMER_MODE_0_CLOCK_TICKS = 256; //256*2; - GBTIMER_MODE_1_CLOCK_TICKS = 4; //4*2; - GBTIMER_MODE_2_CLOCK_TICKS = 16; //16*2; - GBTIMER_MODE_3_CLOCK_TICKS = 64; //64*2; + GBDIV_CLOCK_TICKS = 64; + GBTIMER_MODE_0_CLOCK_TICKS = 256; + GBTIMER_MODE_1_CLOCK_TICKS = 4; + GBTIMER_MODE_2_CLOCK_TICKS = 16; + GBTIMER_MODE_3_CLOCK_TICKS = 64; GBSERIAL_CLOCK_TICKS = 128 * 2; - gbDivTicks *= 2; gbLcdTicks *= 2; + gbLcdTicksDelayed *=2; + gbLcdTicksDelayed--; gbLcdLYIncrementTicks *= 2; - // timerTicks *= 2; - // timerClockTicks *= 2; + gbLcdLYIncrementTicksDelayed *= 2; + gbLcdLYIncrementTicksDelayed--; gbSerialTicks *= 2; SOUND_CLOCK_TICKS = soundQuality * 24 * 2; soundTicks *= 2; - // synchronizeTicks *= 2; - // SYNCHRONIZE_CLOCK_TICKS *= 2; + gbLine99Ticks = 3; } else { gbSpeed = 0; GBLCD_MODE_0_CLOCK_TICKS = 51; GBLCD_MODE_1_CLOCK_TICKS = 1140; GBLCD_MODE_2_CLOCK_TICKS = 20; GBLCD_MODE_3_CLOCK_TICKS = 43; - GBDIV_CLOCK_TICKS = 64; GBLY_INCREMENT_CLOCK_TICKS = 114; + GBDIV_CLOCK_TICKS = 64; GBTIMER_MODE_0_CLOCK_TICKS = 256; GBTIMER_MODE_1_CLOCK_TICKS = 4; GBTIMER_MODE_2_CLOCK_TICKS = 16; GBTIMER_MODE_3_CLOCK_TICKS = 64; GBSERIAL_CLOCK_TICKS = 128; - gbDivTicks /= 2; - gbLcdTicks /= 2; - gbLcdLYIncrementTicks /= 2; - // timerTicks /= 2; - // timerClockTicks /= 2; + gbLcdTicks >>= 1; + gbLcdTicksDelayed++; + gbLcdTicksDelayed >>=1; + gbLcdLYIncrementTicks >>= 1; + gbLcdLYIncrementTicksDelayed++; + gbLcdLYIncrementTicksDelayed >>= 1; gbSerialTicks /= 2; SOUND_CLOCK_TICKS = soundQuality * 24; - soundTicks /= 2; - // synchronizeTicks /= 2; - // SYNCHRONIZE_CLOCK_TICKS /= 2; + soundTicks /= 2; + gbLine99Ticks = 1; + if (gbHardware & 8) + gbLine99Ticks++; } + gbDmaTicks += (134)*GBLY_INCREMENT_CLOCK_TICKS + (37<<(gbSpeed ? 1 : 0)); } -void gbReset() +bool CPUIsGBBios(const char * file) { - SP.W = 0xfffe; - AF.W = 0x01b0; - BC.W = 0x0013; - DE.W = 0x00d8; - HL.W = 0x014d; - PC.W = 0x0100; - IFF = 0; - gbInterrupt = 1; - gbInterruptWait = 0; + if(strlen(file) > 4) { + const char * p = strrchr(file,'.'); + + if(p != NULL) { + if(_stricmp(p, ".gb") == 0) + return true; + if(_stricmp(p, ".bin") == 0) + return true; + if(_stricmp(p, ".bios") == 0) + return true; + } + } - register_DIV = 0; - register_TIMA = 0; - register_TMA = 0; - register_TAC = 0; - register_IF = 1; - register_LCDC = 0x91; - register_STAT = 0; - register_SCY = 0; - register_SCX = 0; - register_LY = 0; - register_LYC = 0; - register_DMA = 0; - register_WY = 0; - register_WX = 0; - register_VBK = 0; - register_HDMA1 = 0; - register_HDMA2 = 0; - register_HDMA3 = 0; - register_HDMA4 = 0; - register_HDMA5 = 0; - register_SVBK = 0; - register_IE = 0; + return false; +} - if(gbCgbMode) { - if(gbSgbMode) { - if(gbEmulatorType == 5) - AF.W = 0xffb0; +void gbCPUInit(const char *biosFileName, bool useBiosFile) +{ + useBios = false; + if (useBiosFile) + { + int size = 0x100; + if(utilLoad(biosFileName, + CPUIsGBBios, + bios, + size)) { + if(size == 0x100) + useBios = true; else - AF.W = 0x01b0; - BC.W = 0x0013; - DE.W = 0x00d8; - HL.W = 0x014d; - for(int i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; - } else { - AF.W = 0x11b0; - BC.W = 0x0000; - DE.W = 0xff56; - HL.W = 0x000d; + systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file size")); } - if(gbEmulatorType == 4) - BC.B.B1 |= 0x01; - - register_HDMA5 = 0xff; - gbMemory[0xff68] = 0xc0; - gbMemory[0xff6a] = 0xc0; - } else { - for(int i = 0; i < 8; i++) - gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; + } +} + +void gbGetHardwareType() +{ + gbCgbMode = 0; + gbSgbMode = 0; + if(gbRom[0x143] & 0x80) { + if((gbEmulatorType == 0) || + gbEmulatorType == 1 || + gbEmulatorType == 4) { + gbCgbMode = 1; + } + } + + if((gbCgbMode == 0 ) && (gbRom[0x146] == 0x03)) { + if(gbEmulatorType == 0 || + gbEmulatorType == 2 || + gbEmulatorType == 5) + gbSgbMode = 1; } + gbHardware = 1; // GB + if (((gbCgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 1)) + gbHardware = 2; // GBC + else if (((gbSgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 2) || (gbEmulatorType == 5)) + gbHardware = 4; // SGB(2) + else if (gbEmulatorType == 4) + gbHardware = 8; // GBA + + gbGBCColorType = 0; + if (gbHardware & 8) // If GBA is selected, choose the GBA default settings. + gbGBCColorType = 2; // (0 = GBC, 1 = GBA, 2 = GBASP) +} + +void gbReset() +{ + gbGetHardwareType(); + + oldRegister_WY = 146; + gbInterruptLaunched = 0; + + if(gbCgbMode == 1) { + if (gbVram == NULL) + gbVram = (u8 *)malloc(0x4000); + if (gbWram == NULL) + gbWram = (u8 *)malloc(0x8000); + memset(gbVram,0,0x4000); + memset(gbPalette,0, 2*128); + } + else + { + if(gbVram != NULL) { + free(gbVram); + gbVram = NULL; + } + if(gbWram != NULL) { + free(gbWram); + gbWram = NULL; + } + } + + gbLYChangeHappened = false; + gbLCDChangeHappened = false; + gbBlackScreen = false; + gbInterruptWait = 0; + 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). + // On GBA/GBASP, it's kinda filled with random data. + // In all cases, most of the 2nd bank is filled with 00s. + // The starting data are important for some 'buggy' games, like Buster Brothers or + // Karamuchou ha Oosawagi!. + if (gbMemory != NULL) + { + memset(gbMemory,0xff, 65536); + for (int temp = 0xC000; temp < 0xE000; temp++) + if ((temp & 0x8) ^((temp & 0x800)>>8)) + { + if ((gbHardware & 0x02) && (gbGBCColorType == 0)) + gbMemory[temp] = 0x0; + else + gbMemory[temp] = 0x0f; + } + + else + gbMemory[temp] = 0xff; + } + + + + // clean LineBuffer + if (gbLineBuffer != NULL) + memset(gbLineBuffer, 0, sizeof(gbLineBuffer)); + // clean Pix + if (pix != NULL) + memset(pix, 0, sizeof(pix)); + // clean Vram + if (gbVram != NULL) + memset(gbVram, 0, 0x4000); + // clean Wram 2 + // This kinda emulates the startup state of Wram on GBC (not very accurate, + // but way closer to the reality than filling it with 00es or FFes). + // On GBA/GBASP, it's kinda filled with random data. + // In all cases, most of the 2nd bank is filled with 00s. + // The starting data are important for some 'buggy' games, like Buster Brothers or + // Karamuchou ha Oosawagi! + if (gbWram != NULL) + { + for (int i = 0; i<8; i++) + if (i != 2) + memcpy ((u16 *)(gbWram+i*0x1000), (u16 *)(gbMemory+0xC000), 0x1000); + } + + memset(gbSCYLine,0,sizeof(gbSCYLine)); + memset(gbSCXLine,0,sizeof(gbSCXLine)); + memset(gbBgpLine,0xfc,sizeof(gbBgpLine)); + if (gbHardware & 5) + { + memset(gbObp0Line,0xff,sizeof(gbObp0Line)); + memset(gbObp1Line,0xff,sizeof(gbObp1Line)); + } + else + { + memset(gbObp0Line,0x0,sizeof(gbObp0Line)); + memset(gbObp1Line,0x0,sizeof(gbObp1Line)); + } + memset(gbSpritesTicks,0x0,sizeof(gbSpritesTicks)); + + SP.W = 0xfffe; + AF.W = 0x01b0; + BC.W = 0x0013; + DE.W = 0x00d8; + HL.W = 0x014d; + PC.W = 0x0100; + IFF = 0; + gbInt48Signal = 0; - gbDivTicks = GBDIV_CLOCK_TICKS; - gbLcdMode = 2; - gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; - gbLcdLYIncrementTicks = 0; - gbTimerTicks = 0; - gbTimerClockTicks = 0; + register_TIMA = 0; + register_TMA = 0; + register_TAC = 0; + gbMemory[0xff0f] = register_IF = 1; + gbMemory[0xff40] = register_LCDC = 0x91; + gbMemory[0xff47] = 0xfc; + + if (gbCgbMode) + gbMemory[0xff4d] = 0x7e; + else + gbMemory[0xff4d] = 0xff; + + if (!gbCgbMode) + gbMemory[0xff70] = gbMemory[0xff74] = 0xff; + + if (gbCgbMode) + gbMemory[0xff56] = 0x3e; + else + gbMemory[0xff56] = 0xff; + + register_SCY = 0; + register_SCX = 0; + register_LYC = 0; + register_DMA = 0xff; + register_WY = 0; + register_WX = 0; + register_VBK = 0; + register_HDMA1 = 0xff; + register_HDMA2 = 0xff; + register_HDMA3 = 0xff; + register_HDMA4 = 0xff; + register_HDMA5 = 0xff; + register_SVBK = 0; + register_IE = 0; + + if (gbCgbMode) + gbMemory[0xff02] = 0x7c; + else + gbMemory[0xff02] = 0x7e; + + gbMemory[0xff03] = 0xff; + int i; + for (i = 0x8; i<0xf; i++) + gbMemory[0xff00+i] = 0xff; + + gbMemory[0xff13] = 0xff; + gbMemory[0xff15] = 0xff; + gbMemory[0xff18] = 0xff; + gbMemory[0xff1d] = 0xff; + gbMemory[0xff1f] = 0xff; + + for (i = 0x27; i<0x30; i++) + gbMemory[0xff00+i] = 0xff; + + gbMemory[0xff4c] = 0xff; + gbMemory[0xff4e] = 0xff; + gbMemory[0xff50] = 0xff; + + for (i = 0x57; i<0x68; i++) + gbMemory[0xff00+i] = 0xff; + + for (i = 0x5d; i<0x70; i++) + gbMemory[0xff00+i] = 0xff; + + gbMemory[0xff71] = 0xff; + + for (i = 0x78; i<0x80; i++) + gbMemory[0xff00+i] = 0xff; + + if (gbHardware & 0xa) + { + + if (gbHardware & 2) + { + AF.W = 0x1180; + BC.W = 0x0000; + } + else + { + AF.W = 0x1100; + BC.W = 0x0100; // GBA/SP have B = 0x01 (which means GBC & GBA/SP bootrom are different !) + } + + gbMemory[0xff26] = 0xf1; + if (gbCgbMode) + { + + gbMemory[0xff31] = 0xff; + gbMemory[0xff33] = 0xff; + gbMemory[0xff35] = 0xff; + gbMemory[0xff37] = 0xff; + gbMemory[0xff39] = 0xff; + gbMemory[0xff3b] = 0xff; + gbMemory[0xff3d] = 0xff; + + gbMemory[0xff44] = register_LY = 0x90; + gbDivTicks = 0x19 + ((gbHardware & 2) >> 1); + gbInternalTimer = 0x58 + ((gbHardware & 2) >> 1); + gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS - + (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 72 + ((gbHardware & 2) >> 1); + gbLcdLYIncrementTicks = 72 + ((gbHardware & 2) >> 1); + gbMemory[0xff04] = register_DIV = 0x1E; + } + else + { + gbMemory[0xff44] = register_LY = 0x94; + gbDivTicks = 0x22 + ((gbHardware & 2) >> 1); + gbInternalTimer = 0x61 + ((gbHardware & 2) >> 1); + gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS - + (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 25 + ((gbHardware & 2) >> 1); + gbLcdLYIncrementTicks = 25 + ((gbHardware & 2) >> 1); + gbMemory[0xff04] = register_DIV = 0x26; + } + + + DE.W = 0xff56; + HL.W = 0x000d; + + register_HDMA5 = 0xff; + gbMemory[0xff68] = 0xc0; + gbMemory[0xff6a] = 0xc0; + + + gbMemory[0xff41] = register_STAT = 0x81; + gbLcdMode = 1; + } + else + { + if (gbHardware & 4) + { + if(gbEmulatorType == 5) + AF.W = 0xffb0; + else + AF.W = 0x01b0; + BC.W = 0x0013; + DE.W = 0x00d8; + HL.W = 0x014d; + } + gbDivTicks = 14; + gbInternalTimer = gbDivTicks--; + gbMemory[0xff04] = register_DIV = 0xAB; + gbMemory[0xff41] = register_STAT = 0x85; + gbMemory[0xff44] = register_LY = 0x00; + gbLcdTicks = 15; + gbLcdLYIncrementTicks = 114+gbLcdTicks; + gbLcdMode = 1; + + // used for the handling of the gb Boot Rom + if ((gbHardware & 5) && (bios != NULL) && useBios && !skipBios) + { + memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000); + memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100); + gbWhiteScreen = 0; + + gbInternalTimer = 0x3e; + gbDivTicks = 0x3f; + gbMemory[0xff04] = register_DIV = 0x00; + PC.W = 0x0000; + register_LCDC = 0x11; + gbScreenOn = false; + gbLcdTicks = 0; + gbLcdMode = 0; + gbLcdModeDelayed = 0; + gbMemory[0xff41] = register_STAT &= 0xfc; + gbInt48Signal = 0; + gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS; + } + } + + gbLine99Ticks = 1; + if (gbHardware & 8) + gbLine99Ticks++; + + gbLcdModeDelayed = gbLcdMode; + gbLcdTicksDelayed = gbLcdTicks+1; + gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks+1; + + + gbTimerModeChange = false; + gbTimerOnChange = false; + gbTimerOn = false; + + if(gbCgbMode) { + for (int i = 0; i<0x20; i++) + gbPalette[i] = 0x7fff; + + // This is just to show that the starting values of the OBJ palettes are different + // between the 3 consoles, and that they 'kinda' stay the same at each reset + // (they can slightly change, somehow (randomly?)). + // You can check the effects of gbGBCColorType on the "Vila Caldan Color" gbc demo. + // Note that you could also check the Div register to check on which system the game + // is running (GB,GBC and GBA(SP) have different startup values). + // Unfortunatly, I don't have any SGB system, so I can't get their starting values. + + if (gbGBCColorType == 0) // GBC Hardware + { + gbPalette[0x20] = 0x0600; + gbPalette[0x21] = 0xfdf3; + gbPalette[0x22] = 0x041c; + gbPalette[0x23] = 0xf5db; + gbPalette[0x24] = 0x4419; + gbPalette[0x25] = 0x57ea; + gbPalette[0x26] = 0x2808; + gbPalette[0x27] = 0x9b75; + gbPalette[0x28] = 0x129b; + gbPalette[0x29] = 0xfce0; + gbPalette[0x2a] = 0x22da; + gbPalette[0x2b] = 0x4ac5; + gbPalette[0x2c] = 0x2d71; + gbPalette[0x2d] = 0xf0c2; + gbPalette[0x2e] = 0x5137; + gbPalette[0x2f] = 0x2d41; + gbPalette[0x30] = 0x6b2d; + gbPalette[0x31] = 0x2215; + gbPalette[0x32] = 0xbe0a; + gbPalette[0x33] = 0xc053; + gbPalette[0x34] = 0xfe5f; + gbPalette[0x35] = 0xe000; + gbPalette[0x36] = 0xbe10; + gbPalette[0x37] = 0x914d; + gbPalette[0x38] = 0x7f91; + gbPalette[0x39] = 0x02b5; + gbPalette[0x3a] = 0x77ac; + gbPalette[0x3b] = 0x14e5; + gbPalette[0x3c] = 0xcf89; + gbPalette[0x3d] = 0xa03d; + gbPalette[0x3e] = 0xfd50; + gbPalette[0x3f] = 0x91ff; + } + else if (gbGBCColorType == 1) // GBA Hardware + { + gbPalette[0x20] = 0xbe00; + gbPalette[0x21] = 0xfdfd; + gbPalette[0x22] = 0xbd69; + gbPalette[0x23] = 0x7baf; + gbPalette[0x24] = 0xf5ff; + gbPalette[0x25] = 0x3f8f; + gbPalette[0x26] = 0xcee5; + gbPalette[0x27] = 0x5bf7; + gbPalette[0x28] = 0xb35b; + gbPalette[0x29] = 0xef97; + gbPalette[0x2a] = 0xef9f; + gbPalette[0x2b] = 0x97f7; + gbPalette[0x2c] = 0x82bf; + gbPalette[0x2d] = 0x9f3d; + gbPalette[0x2e] = 0xddde; + gbPalette[0x2f] = 0xbad5; + gbPalette[0x30] = 0x3cba; + gbPalette[0x31] = 0xdfd7; + gbPalette[0x32] = 0xedea; + gbPalette[0x33] = 0xfeda; + gbPalette[0x34] = 0xf7f9; + gbPalette[0x35] = 0xfdee; + gbPalette[0x36] = 0x6d2f; + gbPalette[0x37] = 0xf0e6; + gbPalette[0x38] = 0xf7f0; + gbPalette[0x39] = 0xf296; + gbPalette[0x3a] = 0x3bf1; + gbPalette[0x3b] = 0xe211; + gbPalette[0x3c] = 0x69ba; + gbPalette[0x3d] = 0x3d0d; + gbPalette[0x3e] = 0xdfd3; + gbPalette[0x3f] = 0xa6ba; + } + else if (gbGBCColorType == 2) // GBASP Hardware + { + gbPalette[0x20] = 0x9c00; + gbPalette[0x21] = 0x6340; + gbPalette[0x22] = 0x10c6; + gbPalette[0x23] = 0xdb97; + gbPalette[0x24] = 0x7622; + gbPalette[0x25] = 0x3e57; + gbPalette[0x26] = 0x2e12; + gbPalette[0x27] = 0x95c3; + gbPalette[0x28] = 0x1095; + gbPalette[0x29] = 0x488c; + gbPalette[0x2a] = 0x8241; + gbPalette[0x2b] = 0xde8c; + gbPalette[0x2c] = 0xfabc; + gbPalette[0x2d] = 0x0e81; + gbPalette[0x2e] = 0x7675; + gbPalette[0x2f] = 0xfdec; + gbPalette[0x30] = 0xddfd; + gbPalette[0x31] = 0x5995; + gbPalette[0x32] = 0x066a; + gbPalette[0x33] = 0xed1e; + gbPalette[0x34] = 0x1e84; + gbPalette[0x35] = 0x1d14; + gbPalette[0x36] = 0x11c3; + gbPalette[0x37] = 0x2749; + gbPalette[0x38] = 0xa727; + gbPalette[0x39] = 0x6266; + gbPalette[0x3a] = 0xe27b; + gbPalette[0x3b] = 0xe3fc; + gbPalette[0x3c] = 0x1f76; + gbPalette[0x3d] = 0xf158; + gbPalette[0x3e] = 0x468e; + gbPalette[0x3f] = 0xa540; + } + } else { + if(gbSgbMode) { + for(int i = 0; i < 8; i++) + gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; + + } + for(int i = 0; i < 8; i++) + gbPalette[i] = systemGbPalette[gbPaletteOption*8+i]; + } + + GBTIMER_MODE_0_CLOCK_TICKS = 256; + GBTIMER_MODE_1_CLOCK_TICKS = 4; + GBTIMER_MODE_2_CLOCK_TICKS = 16; + GBTIMER_MODE_3_CLOCK_TICKS = 64; + + GBLY_INCREMENT_CLOCK_TICKS = 114; + gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; + gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS; gbSerialTicks = 0; gbSerialBits = 0; gbSerialOn = 0; gbWindowLine = -1; - gbTimerOn = 0; + gbTimerOn = false; gbTimerMode = 0; - // gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; gbSpeed = 0; gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; if(gbCgbMode) { gbSpeed = 0; gbHdmaOn = 0; - gbHdmaSource = 0x0000; - gbHdmaDestination = 0x8000; + gbHdmaSource = 0x99d0; + gbHdmaDestination = 0x99d0; gbVramBank = 0; gbWramBank = 1; - register_LY = 0x90; - gbLcdMode = 1; - for(int i = 0; i < 64; i++) - gbPalette[i] = 0x7fff; + } - if(gbSgbMode) { + // used to clean the borders + if (gbSgbMode) + { + gbSgbResetFlag = true; gbSgbReset(); + if (gbBorderOn) + gbSgbRenderBorder(); + gbSgbResetFlag = false; } - for(int i =0; i < 4; i++) + for(i = 0; i < 4; i++) gbBgp[i] = gbObp0[i] = gbObp1[i] = i; memset(&gbDataMBC1,0, sizeof(gbDataMBC1)); @@ -1613,7 +2635,23 @@ memset(&gbDataHuC3, 0, sizeof(gbDataHuC3)); gbDataHuC3.mapperROMBank = 1; - gbMemoryMap[0x00] = &gbRom[0x0000]; + memset(&gbDataTAMA5,0, 26*sizeof(int)); + gbDataTAMA5.mapperROMBank = 1; + + memset(&gbDataMMM01,0, sizeof(gbDataMMM01)); + gbDataMMM01.mapperROMBank = 1; + + if (useBios && !skipBios && (gbHardware & 5)) + { + gbMemoryMap[0x00] = &gbMemory[0x0000]; + inBios = true; + } + else + { + gbMemoryMap[0x00] = &gbRom[0x0000]; + inBios = false; + } + gbMemoryMap[0x01] = &gbRom[0x1000]; gbMemoryMap[0x02] = &gbRom[0x2000]; gbMemoryMap[0x03] = &gbRom[0x3000]; @@ -1638,7 +2676,7 @@ gbMemoryMap[0x0c] = &gbMemory[0xc000]; gbMemoryMap[0x0d] = &gbMemory[0xd000]; gbMemoryMap[0x0e] = &gbMemory[0xe000]; - gbMemoryMap[0x0f] = &gbMemory[0xf000]; + gbMemoryMap[0x0f] = &gbMemory[0xf000]; } if(gbRam) { @@ -1652,146 +2690,418 @@ gbLastTime = systemGetClock(); gbFrameCount = 0; + + gbScreenOn = true; + gbSystemMessage = false; + + gbCheatWrite(true); // Emulates GS codes. + } void gbWriteSaveMBC1(const char * name) { - FILE *gzFile = fopen(name,"wb"); + if (gbRam) + { + FILE *gzFile = fopen(name,"wb"); - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } + if(gzFile == NULL) { + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); + return; + } - fwrite(gbRam, - 1, - gbRamSize, - gzFile); + fwrite(gbRam, + 1, + (gbRamSizeMask+1), + gzFile); - fclose(gzFile); + fclose(gzFile); + } } void gbWriteSaveMBC2(const char * name) { - FILE *file = fopen(name, "wb"); + if (gbRam) + { + FILE *file = fopen(name, "wb"); - if(file == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } + if(file == NULL) { + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); + return; + } - fwrite(&gbMemory[0xa000], - 1, - 256, - file); + fwrite(&gbMemory[0xa000], + 1, + 256, + file); - fclose(file); + fclose(file); + } } void gbWriteSaveMBC3(const char * name, bool extendedSave) { + if (gbRam || extendedSave) + { + FILE *gzFile = fopen(name,"wb"); + if (gbRam) + { + + if(gzFile == NULL) { + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); + return; + } + + fwrite(gbRam, + 1, + (gbRamSizeMask+1), + gzFile); + } + + if(extendedSave) + fwrite(&gbDataMBC3.mapperSeconds, + 1, + 10*sizeof(int) + sizeof(time_t), + gzFile); + + fclose(gzFile); + } +} + +void gbWriteSaveMBC5(const char * name) +{ + if (gbRam) + { + FILE *gzFile = fopen(name,"wb"); + + if(gzFile == NULL) { + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); + return; + } + + fwrite(gbRam, + 1, + (gbRamSizeMask+1), + gzFile); + + fclose(gzFile); + } +} + +void gbWriteSaveMBC7(const char * name) +{ + if (gbRam) + { + FILE *file = fopen(name, "wb"); + + if(file == NULL) { + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); + return; + } + + fwrite(&gbMemory[0xa000], + 1, + 256, + file); + + fclose(file); + } +} + +void gbWriteSaveTAMA5(const char * name, bool extendedSave) +{ FILE *gzFile = fopen(name,"wb"); if(gzFile == NULL) { systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); return; } - - fwrite(gbRam, + if (gbRam) + fwrite(gbRam, + 1, + (gbRamSizeMask+1), + gzFile); + + fwrite(gbTAMA5ram, 1, - gbRamSize, + (gbTAMA5ramSize), gzFile); if(extendedSave) - fwrite(&gbDataMBC3.mapperSeconds, + fwrite(&gbDataTAMA5.mapperSeconds, 1, - 10*sizeof(int) + sizeof(time_t), + 14*sizeof(int) + sizeof(time_t), gzFile); fclose(gzFile); } -void gbWriteSaveMBC5(const char * name) +void gbWriteSaveMMM01(const char * name) { - FILE *gzFile = fopen(name,"wb"); + if (gbRam) + { + FILE *gzFile = fopen(name,"wb"); - if(gzFile == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; - } + if(gzFile == NULL) { + systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); + return; + } - fwrite(gbRam, - 1, - gbRamSize, - gzFile); - - fclose(gzFile); + fwrite(gbRam, + 1, + (gbRamSizeMask+1), + gzFile); + + fclose(gzFile); + } } -void gbWriteSaveMBC7(const char * name) + +bool gbReadSaveMBC1(const char * name) { - FILE *file = fopen(name, "wb"); + if (gbRam) + { + gzFile gzFile = gzopen(name, "rb"); - if(file == NULL) { - systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); - return; + if(gzFile == NULL) { + return false; + } + + int read = gzread(gzFile, + gbRam, + (gbRamSizeMask+1)); + + if(read != (gbRamSizeMask+1)) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gzclose(gzFile); + gbBatteryError = true; + return false; + } + + // Also checks if the battery file it bigger than gbRamSizeMask+1 ! + u8 data[1]; + data[0] = 0; + + read = gzread(gzFile, + data, + 1); + if(read >0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gzclose(gzFile); + gbBatteryError = true; + return false; + } + + gzclose(gzFile); + return true; } + else + return false; +} - fwrite(&gbMemory[0xa000], - 1, - 256, - file); - fclose(file); +bool gbReadSaveMBC2(const char * name) +{ + if (gbRam) + { + FILE *file = fopen(name, "rb"); + + if(file == NULL) { + return false; + } + + size_t read = fread(&gbMemory[0xa000], + 1, + 256, + file); + + if(read != 256) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + fclose(file); + gbBatteryError = true; + return false; + } + + // Also checks if the battery file it bigger than gbRamSizeMask+1 ! + u8 data[1]; + data[0] = 0; + + read = fread(&data[0], + 1, + 1, + file); + if(read > 0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + fclose(file); + gbBatteryError = true; + return false; + } + + fclose(file); + return true; + } + else + return false; } -bool gbReadSaveMBC1(const char * name) +bool gbReadSaveMBC3(const char * name) { gzFile gzFile = gzopen(name, "rb"); if(gzFile == NULL) { return false; } + + int read = 0; + + if (gbRam) + read = gzread(gzFile, + gbRam, + (gbRamSizeMask+1)); + else + read = (gbRamSizeMask+1); + + + bool res = true; - int read = gzread(gzFile, - gbRam, - gbRamSize); - - if(read != gbRamSize) { - systemMessage(MSG_FAILED_TO_READ_SGM, N_("Failed to read complete save game %s (%d)"), name, read); - gzclose(gzFile); - return false; + if(read != (gbRamSizeMask+1)) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gbBatteryError = true; + res = false; + } else if ((gbRomType == 0xf) || (gbRomType == 0x10)){ + read = gzread(gzFile, + &gbDataMBC3.mapperSeconds, + sizeof(int)*10 + sizeof(time_t)); + + if(read != (sizeof(int)*10 + sizeof(time_t)) && read != 0) { + systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), + name); + res = false; + } + else if (read == 0) + { + systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), + name); + res = false; + } + else + { + // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC ! + u8 data[1]; + data[0] = 0; + + read = gzread(gzFile, + data, + 1); + if(read >0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gbBatteryError = true; + res = false; + } + } } gzclose(gzFile); - return true; + return res; } -bool gbReadSaveMBC2(const char * name) +bool gbReadSaveMBC5(const char * name) { - FILE *file = fopen(name, "rb"); + if (gbRam) + { + gzFile gzFile = gzopen(name, "rb"); - if(file == NULL) { - return false; + if(gzFile == NULL) { + return false; + } + + int read = gzread(gzFile, + gbRam, + (gbRamSizeMask+1)); + + if(read != (gbRamSizeMask+1)) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gzclose(gzFile); + gbBatteryError = true; + return false; + } + + + // Also checks if the battery file it bigger than gbRamSizeMask+1 ! + u8 data[1]; + data[0] = 0; + + read = gzread(gzFile, + data, + 1); + if(read >0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gzclose(gzFile); + gbBatteryError = true; + return false; + } + + gzclose(gzFile); + return true; } + else + return false; +} - int read = fread(&gbMemory[0xa000], - 1, - 256, - file); +bool gbReadSaveMBC7(const char * name) +{ + if (gbRam) + { + FILE *file = fopen(name, "rb"); + + if(file == NULL) { + return false; + } + + size_t read = fread(&gbMemory[0xa000], + 1, + 256, + file); + + if(read != 256) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + fclose(file); + gbBatteryError = true; + return false; + } + + // Also checks if the battery file it bigger than gbRamSizeMask+1 ! + u8 data[1]; + data[0] = 0; + + read = fread(&data[0], + 1, + 1, + file); + if(read > 0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + fclose(file); + gbBatteryError = true; + return false; + } - if(read != 256) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Failed to read complete save game %s (%d)"), name, read); fclose(file); - return false; + return true; } - - fclose(file); - return true; + else + return false; } -bool gbReadSaveMBC3(const char * name) +bool gbReadSaveTAMA5(const char * name) { gzFile gzFile = gzopen(name, "rb"); @@ -1799,25 +3109,57 @@ return false; } - int read = gzread(gzFile, - gbRam, - gbRamSize); + int read = 0; + + if (gbRam) + read = gzread(gzFile, + gbRam, + (gbRamSizeMask+1)); + else + read = gbRamSizeMask; + + read += gzread(gzFile, + gbTAMA5ram, + gbTAMA5ramSize); bool res = true; - if(read != gbRamSize) { + if(read != (gbRamSizeMask+gbTAMA5ramSize+1)) { systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Failed to read complete save game %s (%d)"), name, read); + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gbBatteryError = true; + res = false; } else { read = gzread(gzFile, - &gbDataMBC3.mapperSeconds, - sizeof(int)*10 + sizeof(time_t)); + &gbDataTAMA5.mapperSeconds, + sizeof(int)*14 + sizeof(time_t)); - if(read != (sizeof(int)*10 + sizeof(time_t)) && read != 0) { - systemMessage(MSG_FAILED_TO_READ_RTC, - N_("Failed to read RTC from save game %s (continuing)"), - name); - res = false; + if(read != (sizeof(int)*14 + sizeof(time_t)) && read != 0) { + systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), + name); + res = false; + } + else if (read == 0) + { + systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"), + name); + res = false; + } + else + { + // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC ! + u8 data[1]; + data[0] = 0; + + read = gzread(gzFile, + data, + 1); + if(read >0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gbBatteryError = true; + res = false; + } } } @@ -1825,51 +3167,49 @@ return res; } -bool gbReadSaveMBC5(const char * name) -{ - gzFile gzFile = gzopen(name, "rb"); - if(gzFile == NULL) { - return false; - } +bool gbReadSaveMMM01(const char * name) +{ + if (gbRam) + { + gzFile gzFile = gzopen(name, "rb"); + + if(gzFile == NULL) { + return false; + } + + int read = gzread(gzFile, + gbRam, + (gbRamSizeMask+1)); + + if(read != (gbRamSizeMask+1)) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gzclose(gzFile); + gbBatteryError = true; + return false; + } + + // Also checks if the battery file it bigger than gbRamSizeMask+1 ! + u8 data[1]; + data[0] = 0; - int read = gzread(gzFile, - gbRam, - gbRamSize); + read = gzread(gzFile, + data, + 1); + if(read >0) { + systemMessage(MSG_FAILED_TO_READ_SGM, + N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read); + gzclose(gzFile); + gbBatteryError = true; + return false; + } - if(read != gbRamSize) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Failed to read complete save game %s (%d)"), name, read); gzclose(gzFile); - return false; - } - - gzclose(gzFile); - return true; -} - -bool gbReadSaveMBC7(const char * name) -{ - FILE *file = fopen(name, "rb"); - - if(file == NULL) { - return false; + return true; } - - int read = fread(&gbMemory[0xa000], - 1, - 256, - file); - - if(read != 256) { - systemMessage(MSG_FAILED_TO_READ_SGM, - N_("Failed to read complete save game %s (%d)"), name, read); - fclose(file); + else return false; - } - - fclose(file); - return true; } void gbInit() @@ -1878,7 +3218,6 @@ gbSgbInit(); gbMemory = (u8 *)malloc(65536); - memset(gbMemory,0, 65536); pix = (u8 *)calloc(1,4*257*226); @@ -1888,20 +3227,23 @@ bool gbWriteBatteryFile(const char *file, bool extendedSave) { if(gbBattery) { - int type = gbRom[0x147]; - - switch(type) { + switch(gbRomType) { case 0x03: gbWriteSaveMBC1(file); break; case 0x06: gbWriteSaveMBC2(file); break; + case 0x0d: + gbWriteSaveMMM01(file); + break; case 0x0f: case 0x10: - case 0x13: gbWriteSaveMBC3(file, extendedSave); break; + case 0x13: + case 0xfc: + gbWriteSaveMBC3(file, false); case 0x1b: case 0x1e: gbWriteSaveMBC5(file); @@ -1909,6 +3251,9 @@ case 0x22: gbWriteSaveMBC7(file); break; + case 0xfd: + gbWriteSaveTAMA5(file, extendedSave); + break; case 0xff: gbWriteSaveMBC1(file); break; @@ -1919,26 +3264,30 @@ bool gbWriteBatteryFile(const char *file) { - gbWriteBatteryFile(file, true); - return true; + if (!gbBatteryError) + { + gbWriteBatteryFile(file, true); + return true; + } + else return false; } bool gbReadBatteryFile(const char *file) { bool res = false; if(gbBattery) { - int type = gbRom[0x147]; - - switch(type) { + switch(gbRomType) { case 0x03: res = gbReadSaveMBC1(file); break; case 0x06: res = gbReadSaveMBC2(file); break; + case 0x0d: + res = gbReadSaveMMM01(file); + break; case 0x0f: case 0x10: - case 0x13: if(!gbReadSaveMBC3(file)) { time(&gbDataMBC3.mapperLastTime); struct tm *lt; @@ -1954,12 +3303,54 @@ } res = true; break; + case 0x13: + case 0xfc: + res = gbReadSaveMBC3(file); case 0x1b: case 0x1e: res = gbReadSaveMBC5(file); break; case 0x22: res = gbReadSaveMBC7(file); + case 0xfd: + if(!gbReadSaveTAMA5(file)) { + u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + time(&gbDataTAMA5.mapperLastTime); + struct tm *lt; + lt = localtime(&gbDataTAMA5.mapperLastTime); + gbDataTAMA5.mapperSeconds = lt->tm_sec; + gbDataTAMA5.mapperMinutes = lt->tm_min; + gbDataTAMA5.mapperHours = lt->tm_hour; + gbDataTAMA5.mapperDays = 1; + gbDataTAMA5.mapperMonths = 1; + gbDataTAMA5.mapperYears = 1970; + int days = lt->tm_yday+365*3; + while (days) + { + gbDataTAMA5.mapperDays++; + days--; + if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1]) + { + gbDataTAMA5.mapperDays = 1; + gbDataTAMA5.mapperMonths++; + if (gbDataTAMA5.mapperMonths>12) + { + gbDataTAMA5.mapperMonths = 1; + gbDataTAMA5.mapperYears++; + if ((gbDataTAMA5.mapperYears & 3) == 0) + gbDaysinMonth[1] = 29; + else + gbDaysinMonth[1] = 28; + } + } + } + gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) | + (lt->tm_yday > 255 ? 1: 0); + res = false; + break; + } + res = true; + break; case 0xff: res = gbReadSaveMBC1(file); break; @@ -1978,7 +3369,6 @@ return false; } - // long size = ftell(file); fseek(file, 0x4, SEEK_SET); char buffer[16]; char buffer2[16]; @@ -1995,9 +3385,9 @@ return false; } fseek(file, 0x13, SEEK_SET); - int read = 0; + size_t read = 0; int toRead = 0; - switch(gbRom[0x147]) { + switch(gbRomType) { case 0x03: case 0x0f: case 0x10: @@ -2005,8 +3395,8 @@ case 0x1b: case 0x1e: case 0xff: - read = fread(gbRam, 1, gbRamSize, file); - toRead = gbRamSize; + read = fread(gbRam, 1, (gbRamSizeMask+1), file); + toRead = (gbRamSizeMask+1); break; case 0x06: case 0x22: @@ -2053,7 +3443,7 @@ { &gbTimerClockTicks, sizeof(int) }, { &gbSerialTicks, sizeof(int) }, { &gbSerialBits, sizeof(int) }, - { &gbInterrupt, sizeof(int) }, + { &gbInt48Signal, sizeof(int) }, { &gbInterruptWait, sizeof(int) }, { &gbSynchronizeTicks, sizeof(int) }, { &gbTimerOn, sizeof(int) }, @@ -2109,9 +3499,13 @@ static bool gbWriteSaveState(gzFile gzFile) { + utilWriteInt(gzFile, GBSAVE_GAME_VERSION); utilGzWrite(gzFile, &gbRom[0x134], 15); + + utilWriteInt(gzFile, useBios); + utilWriteInt(gzFile, inBios); utilWriteData(gzFile, gbSaveGameStruct); @@ -2120,24 +3514,24 @@ if(gbSgbMode) { gbSgbSaveGame(gzFile); } - + utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); - - // not saved anymore - // gzwrite(gzFile, pix, 256*224*sizeof(u16)); + utilGzWrite(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5)); + if (gbTAMA5ram != NULL) + utilGzWrite(gzFile, gbTAMA5ram, gbTAMA5ramSize); + utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01)); utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); - // todo: remove - utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); if(gbRamSize && gbRam) { + utilWriteInt(gzFile, gbRamSize); utilGzWrite(gzFile, gbRam, gbRamSize); } @@ -2149,7 +3543,19 @@ gbSoundSaveGame(gzFile); gbCheatsSaveGame(gzFile); - + + utilWriteInt(gzFile, gbLcdModeDelayed); + utilWriteInt(gzFile, gbLcdTicksDelayed); + utilWriteInt(gzFile, gbLcdLYIncrementTicksDelayed); + utilWriteInt(gzFile, gbSpritesTicks[299]); + utilWriteInt(gzFile, gbTimerModeChange); + utilWriteInt(gzFile, gbTimerOnChange); + utilWriteInt(gzFile, gbHardware); + utilWriteInt(gzFile, gbBlackScreen); + utilWriteInt(gzFile, oldRegister_WY); + utilWriteInt(gzFile, gbWindowLine); + utilWriteInt(gzFile, inUseRegister_WY); + utilWriteInt(gzFile, gbScreenOn); return true; } @@ -2206,9 +3612,58 @@ romname, &gbRom[0x134]); return false; } + + + bool ub = false; + bool ib = false; + + if (version >= 11) + { + ub = utilReadInt(gzFile) ? true : false; + ib = utilReadInt(gzFile) ? true : false; + + if((ub != useBios) && (ib)) { + if(useBios) + systemMessage(MSG_SAVE_GAME_NOT_USING_BIOS, + N_("Save game is not using the BIOS files")); + else + systemMessage(MSG_SAVE_GAME_USING_BIOS, + N_("Save game is using the BIOS file")); + return false; + } + } + + gbReset(); + + inBios = ib; utilReadData(gzFile, gbSaveGameStruct); + + // Correct crash when loading color gameboy save in regular gameboy type. + if (!gbCgbMode) + { + if(gbVram != NULL) { + free(gbVram); + gbVram = NULL; + } + if(gbWram != NULL) { + free(gbWram); + gbWram = NULL; + } + } + else + { + if(gbVram == NULL) + gbVram = (u8 *)malloc(0x4000); + if(gbWram == NULL) + gbWram = (u8 *)malloc(0x8000); + memset(gbVram,0,0x4000); + memset(gbPalette,0, 2*128); + } + + + if(version >= GBSAVE_GAME_VERSION_7) { utilGzRead(gzFile, &IFF, 2); } @@ -2218,8 +3673,10 @@ } else { gbSgbMask = 0; // loading a game at the wrong time causes no display } - - utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); + if (version<11) + utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1) - sizeof(int)); + else + utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); if(version < GBSAVE_GAME_VERSION_4) // prior to version 4, there was no adjustment for the time the game @@ -2231,6 +3688,13 @@ utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); + if (version>=11) + { + utilGzRead(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5)); + if (gbTAMA5ram != NULL) + utilGzRead(gzFile, gbTAMA5ram, gbTAMA5ramSize); + utilGzRead(gzFile, &gbDataMMM01, sizeof(gbDataMMM01)); + } if(version < GBSAVE_GAME_VERSION_5) { utilGzRead(gzFile, pix, 256*224*sizeof(u16)); @@ -2242,8 +3706,8 @@ } else utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); - // todo: remove - utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); + if (version < 11) + utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); if(version < GBSAVE_GAME_VERSION_10) { if(!gbCgbMode && !gbSgbMode) { @@ -2255,10 +3719,35 @@ utilGzRead(gzFile, &gbMemory[0x8000], 0x8000); if(gbRamSize && gbRam) { - utilGzRead(gzFile, gbRam, gbRamSize); + if (version < 11) + utilGzRead(gzFile, gbRam, gbRamSize); + else + { + int ramSize = utilReadInt(gzFile); + utilGzRead(gzFile, gbRam, (gbRamSize>ramSize) ? ramSize : gbRamSize); + if (ramSize>gbRamSize) + gzseek(gzFile,ramSize-gbRamSize,SEEK_CUR); + } } - - gbMemoryMap[0x00] = &gbRom[0x0000]; + + memset(gbSCYLine, register_SCY, sizeof(gbSCYLine)); + memset(gbSCXLine, register_SCX, sizeof(gbSCXLine)); + memset(gbBgpLine, (gbBgp[0] | (gbBgp[1]<<2) | (gbBgp[2]<<4) | + (gbBgp[3]<<6)), sizeof(gbBgpLine)); + memset(gbObp0Line, (gbObp0[0] | (gbObp0[1]<<2) | (gbObp0[2]<<4) | + (gbObp0[3]<<6)), sizeof(gbObp0Line)); + memset(gbObp1Line, (gbObp1[0] | (gbObp1[1]<<2) | (gbObp1[2]<<4) | + (gbObp1[3]<<6)), sizeof(gbObp1Line)); + memset(gbSpritesTicks, 0x0, sizeof(gbSpritesTicks)); + + if (inBios) + { + gbMemoryMap[0x00] = &gbMemory[0x0000]; + memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000); + memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100); + } + else + gbMemoryMap[0x00] = &gbRom[0x0000]; gbMemoryMap[0x01] = &gbRom[0x1000]; gbMemoryMap[0x02] = &gbRom[0x2000]; gbMemoryMap[0x03] = &gbRom[0x3000]; @@ -2275,9 +3764,7 @@ gbMemoryMap[0x0e] = &gbMemory[0xe000]; gbMemoryMap[0x0f] = &gbMemory[0xf000]; - int type = gbRom[0x147]; - - switch(type) { + switch(gbRomType) { case 0x00: case 0x01: case 0x02: @@ -2290,6 +3777,12 @@ // MBC2 memoryUpdateMapMBC2(); break; + case 0x0b: + case 0x0c: + case 0x0d: + // MMM01 + memoryUpdateMapMMM01(); + break; case 0x0f: case 0x10: case 0x11: @@ -2314,6 +3807,14 @@ // MBC 7 memoryUpdateMapMBC7(); break; + case 0x56: + // GS3 + memoryUpdateMapGS3(); + break; + case 0xfd: + // TAMA5 + memoryUpdateMapTAMA5(); + break; case 0xfe: // HuC3 memoryUpdateMapHuC3(); @@ -2339,7 +3840,11 @@ gbSoundReadGame(version, gzFile); - if(gbBorderOn) { + if (gbCgbMode && gbSgbMode) { + gbSgbMode = 0; + } + + if(gbBorderOn && !gbSgbMask) { gbSgbRenderBorder(); } @@ -2348,6 +3853,85 @@ if(version > GBSAVE_GAME_VERSION_1) gbCheatsReadGame(gzFile, version); + if (version<11) + { + gbWriteMemory(0xff00, 0); + gbMemory[0xff04] = register_DIV; + gbMemory[0xff05] = register_TIMA; + gbMemory[0xff06] = register_TMA; + gbMemory[0xff07] = register_TAC; + gbMemory[0xff40] = register_LCDC; + gbMemory[0xff42] = register_SCY; + gbMemory[0xff43] = register_SCX; + gbMemory[0xff44] = register_LY; + gbMemory[0xff45] = register_LYC; + gbMemory[0xff46] = register_DMA; + gbMemory[0xff4a] = register_WY; + gbMemory[0xff4b] = register_WX; + gbMemory[0xff4f] = register_VBK; + gbMemory[0xff51] = register_HDMA1; + gbMemory[0xff52] = register_HDMA2; + gbMemory[0xff53] = register_HDMA3; + gbMemory[0xff54] = register_HDMA4; + gbMemory[0xff55] = register_HDMA5; + gbMemory[0xff70] = register_SVBK; + gbMemory[0xffff] = register_IE; + GBDIV_CLOCK_TICKS = 64; + + if (gbSpeed) + gbDivTicks /=2; + + if ((gbLcdMode == 0) && (register_STAT & 8)) + gbInt48Signal |= 1; + if ((gbLcdMode == 1) && (register_STAT & 0x10)) + gbInt48Signal |= 2; + if ((gbLcdMode == 2) && (register_STAT & 0x20)) + gbInt48Signal |= 4; + if ((register_LY==register_LYC) && (register_STAT & 0x40)) + gbInt48Signal |= 8; + + gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS; + + if (gbLcdMode == 2) + gbLcdLYIncrementTicks-=GBLCD_MODE_2_CLOCK_TICKS-gbLcdTicks; + else if (gbLcdMode == 3) + gbLcdLYIncrementTicks -=GBLCD_MODE_2_CLOCK_TICKS+GBLCD_MODE_3_CLOCK_TICKS-gbLcdTicks; + else if (gbLcdMode == 0) + gbLcdLYIncrementTicks =gbLcdTicks; + else if (gbLcdMode == 1) + { + gbLcdLYIncrementTicks = gbLcdTicks % GBLY_INCREMENT_CLOCK_TICKS; + if (register_LY == 0x99) + gbLcdLYIncrementTicks =gbLine99Ticks; + else if (register_LY == 0) + gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; + } + + gbLcdModeDelayed = gbLcdMode; + gbLcdTicksDelayed = gbLcdTicks--; + gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks--; + gbInterruptWait = 0; + memset(gbSpritesTicks,0,sizeof(gbSpritesTicks)); + } + else + { + gbLcdModeDelayed = utilReadInt(gzFile); + gbLcdTicksDelayed = utilReadInt(gzFile); + gbLcdLYIncrementTicksDelayed = utilReadInt(gzFile); + gbSpritesTicks[299] = utilReadInt(gzFile) & 0xff; + gbTimerModeChange = (utilReadInt(gzFile) ? true : false); + gbTimerOnChange = (utilReadInt(gzFile) ? true : false); + gbHardware = utilReadInt(gzFile); + gbBlackScreen = (utilReadInt(gzFile) ? true : false); + oldRegister_WY = utilReadInt(gzFile); + gbWindowLine = utilReadInt(gzFile); + inUseRegister_WY = utilReadInt(gzFile); + gbScreenOn = (utilReadInt(gzFile) ? true : false); + } + + if (gbSpeed) + gbLine99Ticks *= 2; + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; return true; @@ -2432,13 +4016,18 @@ gbWram = NULL; } + if(gbTAMA5ram != NULL) { + free(gbTAMA5ram); + gbTAMA5ram = NULL; + } + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; } bool gbLoadRom(const char *szFile) { int size = 0; - + if(gbRom != NULL) { gbCleanUp(); } @@ -2453,6 +4042,14 @@ return false; gbRomSize = size; + + gbBatteryError = false; + + if(bios != NULL) { + free(bios); + bios = NULL; + } + bios = (u8 *)calloc(1,0x100); return gbUpdateSizes(); } @@ -2467,36 +4064,103 @@ if(gbRomSize < gbRomSizes[gbRom[0x148]]) { gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); + for (int i = gbRomSize; igbRomSizes[gbRom[0x148]]) && (genericflashcardEnable)) + { + gbRomSize = gbRomSize>>16; + gbRom[0x148] = 0; + if (gbRomSize) + { + while (!((gbRomSize & 1) || (gbRom[0x148] == 7))) + { + gbRom[0x148]++; + gbRomSize>>=1; + } + gbRom[0x148]++; + } + gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); } gbRomSize = gbRomSizes[gbRom[0x148]]; gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]]; - if(gbRom[0x149] > 5) { + + // The 'genericflashcard' option allows some PD to work. + // However, the setting is dangerous (if you let in enabled + // and play a normal game, it might just break everything). + // That's why it is not saved in the emulator options. + // Also I added some checks in VBA to make sure your saves will not be + // overwritten if you wrongly enable this option for a game + // you already played (and vice-versa, ie. if you forgot to + // enable the option for a game you played with it enabled, like Shawu Story). + u8 ramsize = genericflashcardEnable ? 5 : gbRom[0x149]; + gbRom[0x149] = ramsize; + + if ((gbRom[2] == 0x6D) && (gbRom[5] == 0x47) && (gbRom[6] == 0x65) && (gbRom[7] == 0x6E) && + (gbRom[8] == 0x69) && (gbRom[9] == 0x65) && (gbRom[0xA] == 0x28) && (gbRom[0xB] == 0x54)) + { + gbCheatingDevice = 1; // GameGenie + for (int i = 0; i < 0x20; i++) // Cleans GG hardware registers + gbRom[0x4000+i] = 0; + } + else if (((gbRom[0x104] == 0x44) && (gbRom[0x156] == 0xEA) && (gbRom[0x158] == 0x7F) && + (gbRom[0x159] == 0xEA) && (gbRom[0x15B] == 0x7F)) || ((gbRom[0x165] == 0x3E) && + (gbRom[0x166] == 0xD9) && (gbRom[0x16D] == 0xE1) && (gbRom[0x16E] == 0x7F))) + gbCheatingDevice = 2; // GameShark + else gbCheatingDevice = 0; + + if(ramsize > 5) { systemMessage(MSG_UNSUPPORTED_RAM_SIZE, N_("Unsupported ram size %02x"), gbRom[0x149]); return false; } - gbRamSize = gbRamSizes[gbRom[0x149]]; - gbRamSizeMask = gbRamSizesMasks[gbRom[0x149]]; + gbRamSize = gbRamSizes[ramsize]; + gbRamSizeMask = gbRamSizesMasks[ramsize]; if(gbRamSize) { gbRam = (u8 *)malloc(gbRamSize); - memset(gbRam, 0xFF, gbRamSize); + memset(gbRam, 0xff, gbRamSize); } - int type = gbRom[0x147]; + + gbRomType = gbRom[0x147]; + if (genericflashcardEnable) + { + /*if (gbRomType<2) + gbRomType =3; + else if ((gbRomType == 0xc) || (gbRomType == 0xf) || (gbRomType == 0x12) || + (gbRomType == 0x16) || (gbRomType == 0x1a) || (gbRomType == 0x1d)) + gbRomType++; + else if ((gbRomType == 0xb) || (gbRomType == 0x11) || (gbRomType == 0x15) || + (gbRomType == 0x19) || (gbRomType == 0x1c)) + gbRomType+=2; + else if ((gbRomType == 0x5) || (gbRomType == 0x6)) + gbRomType = 0x1a;*/ + gbRomType = 0x1b; + } + else if (gbCheatingDevice == 1) + gbRomType = 0x55; + else if (gbCheatingDevice == 2) + gbRomType = 0x56; + + gbRom[0x147] = gbRomType; mapperReadRAM = NULL; - switch(type) { + switch(gbRomType) { case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: + case 0x09: // MBC 1 mapper = mapperMBC1ROM; mapperRAM = mapperMBC1RAM; + mapperReadRAM = mapperMBC1ReadRAM; break; case 0x05: case 0x06: @@ -2506,11 +4170,19 @@ gbRamSize = 0x200; gbRamSizeMask = 0x1ff; break; + case 0x0b: + case 0x0c: + case 0x0d: + // MMM01 + mapper = mapperMMM01ROM; + mapperRAM = mapperMMM01RAM; + break; case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: + case 0xfc: // MBC 3 mapper = mapperMBC3ROM; mapperRAM = mapperMBC3RAM; @@ -2522,6 +4194,7 @@ // MBC5 mapper = mapperMBC5ROM; mapperRAM = mapperMBC5RAM; + mapperReadRAM = mapperMBC5ReadRAM; break; case 0x1c: case 0x1d: @@ -2529,6 +4202,7 @@ // MBC 5 Rumble mapper = mapperMBC5ROM; mapperRAM = mapperMBC5RAM; + mapperReadRAM = mapperMBC5ReadRAM; break; case 0x22: // MBC 7 @@ -2536,6 +4210,38 @@ mapperRAM = mapperMBC7RAM; mapperReadRAM = mapperMBC7ReadRAM; break; + // GG (GameGenie) + case 0x55: + mapper = mapperGGROM; + break; + case 0x56: + // GS (GameShark) + mapper = mapperGS3ROM; + break; + case 0xfd: + // TAMA5 + if (gbRam!= NULL) + { + free(gbRam); + gbRam = NULL; + } + + ramsize = 3; + gbRamSize = gbRamSizes[3]; + gbRamSizeMask = gbRamSizesMasks[3]; + gbRam = (u8 *)malloc(gbRamSize); + memset(gbRam, 0x0, gbRamSize); + + gbTAMA5ramSize = 0x100; + + if (gbTAMA5ram == NULL) + gbTAMA5ram = (u8 *)malloc(gbTAMA5ramSize); + memset(gbTAMA5ram, 0x0, gbTAMA5ramSize); + + mapperRAM = mapperTAMA5RAM; + mapperReadRAM = mapperTAMA5ReadRAM; + mapperUpdateClock = memoryUpdateTAMA5Clock; + break; case 0xfe: // HuC3 mapper = mapperHuC3ROM; @@ -2549,11 +4255,11 @@ break; default: systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE, - N_("Unknown cartridge type %02x"), type); + N_("Unknown cartridge type %02x"), gbRomType); return false; } - switch(type) { + switch(gbRomType) { case 0x03: case 0x06: case 0x0f: @@ -2563,42 +4269,17 @@ case 0x1d: case 0x1e: case 0x22: + case 0xfd: case 0xff: gbBattery = 1; break; } - if(gbRom[0x146] == 0x03) { - if(gbEmulatorType == 0 || - gbEmulatorType == 2 || - gbEmulatorType == 5) - gbSgbMode = 1; - else - gbSgbMode = 0; - } else - gbSgbMode = 0; - - if(gbRom[0x143] & 0x80) { - if(gbEmulatorType == 0 || - gbEmulatorType == 1 || - gbEmulatorType == 4 || - gbEmulatorType == 5) { - gbCgbMode = 1; - gbVram = (u8 *)malloc(0x4000); - gbWram = (u8 *)malloc(0x8000); - memset(gbVram,0,0x4000); - memset(gbWram,0,0x8000); - memset(gbPalette,0, 2*128); - } else { - gbCgbMode = 0; - } - } else - gbCgbMode = 0; - gbInit(); - gbReset(); - switch(type) { + //gbReset(); + + switch(gbRomType) { case 0x1c: case 0x1d: case 0x1e: @@ -2608,16 +4289,163 @@ return true; } +int gbGetNextEvent (int clockTicks) +{ + if (register_LCDC & 0x80) + { + if(gbLcdTicks < clockTicks) + clockTicks = gbLcdTicks; + + if(gbLcdTicksDelayed < clockTicks) + clockTicks = gbLcdTicksDelayed; + + if(gbLcdLYIncrementTicksDelayed < clockTicks) + clockTicks = gbLcdLYIncrementTicksDelayed; + } + + if(gbLcdLYIncrementTicks < clockTicks) + clockTicks = gbLcdLYIncrementTicks; + + if(gbSerialOn && (gbSerialTicks < clockTicks)) + clockTicks = gbSerialTicks; + + if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks)) + clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1; + + if(soundTicks && (soundTicks < clockTicks)) + clockTicks = soundTicks; + + if ((clockTicks<=0) || (gbInterruptWait)) + clockTicks = 1; + + return clockTicks; +} + +void gbDrawLine() +{ + switch(systemColorDepth) { + case 16: + { + u16 * dest = (u16 *)pix + + (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1) + + gbBorderColumnSkip; + for(int x = 0; x < 160; ) { + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + *dest++ = systemColorMap16[gbLineMix[x++]]; + } + if(gbBorderOn) + dest += gbBorderColumnSkip; + *dest++ = 0; // for filters that read one pixel more + } + break; + + case 24: + { + u8 *dest = (u8 *)pix + + 3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) + + gbBorderColumnSkip); + for(int x = 0; x < 160;) { + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; + dest+= 3; + } + } + break; + + case 32: + { + u32 * dest = (u32 *)pix + + (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1) + + gbBorderColumnSkip; + for(int x = 0; x < 160;) { + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + *dest++ = systemColorMap32[gbLineMix[x++]]; + } + } + break; + } +} + void gbEmulate(int ticksToStop) { gbRegister tempRegister; u8 tempValue; s8 offset; - int clockTicks = 0; + clockTicks = 0; gbDmaTicks = 0; register int opcode = 0; + + int opcode1 = 0; + int opcode2 = 0; + bool execute = false; while(1) { #ifndef FINAL_VERSION @@ -2633,29 +4461,53 @@ } } #endif + + u16 oldPCW = PC.W; + if(IFF & 0x80) { if(register_LCDC & 0x80) { - clockTicks = gbLcdTicks; + clockTicks = gbLcdTicks; } else - clockTicks = 100; + clockTicks = 1000; + + clockTicks = gbGetNextEvent(clockTicks); + + /*if(gbLcdTicksDelayed < clockTicks) + clockTicks = gbLcdTicksDelayed; + + if(gbLcdLYIncrementTicksDelayed < clockTicks) + clockTicks = gbLcdLYIncrementTicksDelayed; - if(gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks)) + if(gbLcdLYIncrementTicks < clockTicks) clockTicks = gbLcdLYIncrementTicks; if(gbSerialOn && (gbSerialTicks < clockTicks)) clockTicks = gbSerialTicks; - if(gbTimerOn && (gbTimerTicks < clockTicks)) - clockTicks = gbTimerTicks; + if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks)) + clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1; if(soundTicks && (soundTicks < clockTicks)) clockTicks = soundTicks; - } else { - opcode = gbReadOpcode(PC.W++); + + if ((clockTicks<=0) || (gbInterruptWait)) + clockTicks = 1;*/ - if(IFF & 0x100) { - IFF &= 0xff; + } else { + + // First we apply the clockTicks, then we execute the opcodes. + opcode1 = 0; + opcode2 = 0; + execute = true; + + opcode2 = opcode1 = opcode = gbReadOpcode(PC.W++); + + // If HALT state was launched while IME = 0 and (register_IF & register_IE & 0x1F), + // PC.W is not incremented for the first byte of the next instruction. + if (IFF & 2) + { PC.W--; + IFF &= ~2; } clockTicks = gbCycles[opcode]; @@ -2663,24 +4515,66 @@ switch(opcode) { case 0xCB: // extended opcode - opcode = gbReadOpcode(PC.W++); + opcode2 = opcode = gbReadOpcode(PC.W++); clockTicks = gbCyclesCB[opcode]; - switch(opcode) { -#include "gbCodesCB.h" - } - break; -#include "gbCodes.h" + break; } + gbOldClockTicks = clockTicks-1; + gbIntBreak = 1; + } + + + if(!emulating) + return; + + // For 'breakpoint' support (opcode 0xFC is considered as a breakpoint) + if ((clockTicks==0) && execute) + { + PC.W = oldPCW; + return; + } + + + if (!(IFF & 0x80)) + clockTicks = 1; + + gbRedoLoop: + + + + if (gbInterruptWait) + gbInterruptWait = 0; + else + gbInterruptLaunched = 0; + + + // Used for the EI/DI instruction's delay. + if (IFF & 0x38) + { + int tempIFF = (IFF >> 4) & 3; + + if (tempIFF <=clockTicks) + { + tempIFF = 0; + IFF |=1; + } + else + tempIFF -= clockTicks; + IFF = (IFF & 0xCF) | (tempIFF <<4); + + if (IFF & 0x08) + IFF &= 0x82; } - if(!emulating) - return; - if(gbDmaTicks) { - clockTicks += gbDmaTicks; - gbDmaTicks = 0; + if (register_LCDCBusy) + { + register_LCDCBusy-=clockTicks; + if (register_LCDCBusy<0) + register_LCDCBusy = 0; } + if(gbSgbMode) { if(gbSgbPacketTimeout) { gbSgbPacketTimeout -= clockTicks; @@ -2695,79 +4589,528 @@ // DIV register emulation gbDivTicks -= clockTicks; while(gbDivTicks <= 0) { - register_DIV++; + gbMemory[0xff04] = ++register_DIV; gbDivTicks += GBDIV_CLOCK_TICKS; } if(register_LCDC & 0x80) { // LCD stuff + gbLcdTicks -= clockTicks; - if(gbLcdMode == 1) { - // during V-BLANK,we need to increment LY at the same rate! - gbLcdLYIncrementTicks -= clockTicks; - while(gbLcdLYIncrementTicks <= 0) { + gbLcdTicksDelayed -= clockTicks; + gbLcdLYIncrementTicks -= clockTicks; + gbLcdLYIncrementTicksDelayed -= clockTicks; + + + // our counters are off, see what we need to do + + // This looks (and kinda is) complicated, however this + // is the only way I found to emulate properly the way + // the real hardware operates... + while(((gbLcdTicks <= 0) && (gbLCDChangeHappened == false)) || + ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened == true)) || + ((gbLcdLYIncrementTicks <= 0) && (gbLYChangeHappened == false)) || + ((gbLcdLYIncrementTicksDelayed<=0) && (gbLYChangeHappened == true))) + { + + if ((gbLcdLYIncrementTicks <= 0) && (!gbLYChangeHappened)) + { + gbLYChangeHappened = true; + gbMemory[0xff44] = register_LY = (register_LY + 1) % 154; + + if (register_LY == 0x91) + { + /* if (IFF & 0x80) + gbScreenOn = !gbScreenOn; + else*/ if (register_LCDC & 0x80) + gbScreenOn = true; + } + gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; - if(register_LY < 153) { - register_LY++; - - gbCompareLYToLYC(); - - if(register_LY >= 153) - gbLcdLYIncrementTicks = 6; - } else { - register_LY = 0x00; - // reset the window line - gbWindowLine = -1; - gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2; - gbCompareLYToLYC(); + if (gbLcdMode == 1) + { + + if(register_LY == 153) + gbLcdLYIncrementTicks -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; + else if(register_LY == 0) + gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; + } + + // GB only 'bug' : Halt state is broken one tick before LY==LYC interrupt + // is reflected in the registers. + if ((gbHardware & 5) && (IFF & 0x80) && (register_LY == register_LYC) + && (register_STAT & 0x40) && (register_LY != 0)) + { + if (!((gbLcdModeDelayed != 1) && (register_LY==0))) + { + gbInt48Signal &= ~9; + gbCompareLYToLYC(); + gbLYChangeHappened = false; + gbMemory[0xff41] = register_STAT; + gbMemory[0xff0f] = register_IF; + } + + gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks+1; } } - } + + + if ((gbLcdTicks <= 0) && (!gbLCDChangeHappened)) + { + gbLCDChangeHappened = true; + + switch(gbLcdMode) + { + case 0: + { + // H-Blank + // check if we reached the V-Blank period + if(register_LY == 144) { + // Yes, V-Blank + // set the LY increment counter + if (gbHardware & 0x5) + { + register_IF |= 1; // V-Blank interrupt + } + + gbInt48Signal &= ~6; + if(register_STAT & 0x10) + { + // send LCD interrupt only if no interrupt 48h signal... + if ((!(gbInt48Signal & 1)) && ((!(gbInt48Signal & 8)) || (gbHardware & 0x0a))) + { + register_IF |=2; + gbInterruptLaunched |= 2; + if (gbHardware & 0xa) + gbInterruptWait = 1; + } + gbInt48Signal |= 2; + } + gbInt48Signal &= ~1; + + gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS; + gbLcdMode = 1; + + } else { + // go the the OAM being accessed mode + gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; + gbLcdMode = 2; + + gbInt48Signal &= ~6; + if(register_STAT & 0x20) + { + // send LCD interrupt only if no interrupt 48h signal... + if (!gbInt48Signal) + { + register_IF |= 2; + gbInterruptLaunched |= 2; + } + gbInt48Signal |= 4; + } + gbInt48Signal &= ~1; + } + } + break; + case 1: + { + // V-Blank + // next mode is OAM being accessed mode + gbInt48Signal &= ~5; + if(register_STAT & 0x20) + { + // send LCD interrupt only if no interrupt 48h signal... + if (!gbInt48Signal) + { + register_IF |= 2; + gbInterruptLaunched |= 2; + if ((gbHardware & 0xa) && (IFF & 0x80)) + gbInterruptWait = 1; + } + gbInt48Signal |= 4; + } + gbInt48Signal &= ~2; + + gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; + + gbLcdMode = 2; + register_LY = 0x00; + + } + break; + case 2: + { + + // OAM being accessed mode + // next mode is OAM and VRAM in use + if ((gbScreenOn) && (register_LCDC & 0x80)) + { + gbDrawSprites(false); + // Used to add a one tick delay when a window line is drawn. + //(fixes a part of Carmaggedon problem) + if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) && + (gbWindowLine != -2)) { + + int inUseRegister_WY = 0; + int tempgbWindowLine = gbWindowLine; + + if ((tempgbWindowLine == -1) || (tempgbWindowLine>144)) + { + inUseRegister_WY = oldRegister_WY; + if (register_LY>oldRegister_WY) + tempgbWindowLine = 146; + } + + int wy = inUseRegister_WY; - // our counter is off, see what we need to do - while(gbLcdTicks <= 0) { - int framesToSkip = systemFrameSkip; - if(speedup) - framesToSkip = 9; // try 6 FPS during speedup - switch(gbLcdMode) { - case 0: - // H-Blank - register_LY++; + if(register_LY >= inUseRegister_WY) { - gbCompareLYToLYC(); + if (tempgbWindowLine == -1) + tempgbWindowLine = 0; + + int wx = register_WX; + wx -= 7; + if (wx<0) + wx = 0; + + if((wx <= 159) && (tempgbWindowLine <= 143)) + for (int i = wx; i<300; i++) + if (gbSpeed) + gbSpritesTicks[i]+=3; + else + gbSpritesTicks[i]+=1; + } + } + } + + gbInt48Signal &= ~7; + + gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299]; + gbLcdMode = 3; + } + break; + case 3: + { + // OAM and VRAM in use + // next mode is H-Blank + + + gbInt48Signal &= ~7; + if(register_STAT & 0x08) + { + // send LCD interrupt only if no interrupt 48h signal... + if (!(gbInt48Signal & 8)) + { + register_IF |= 2; + if ((gbHardware & 0xa) && (IFF & 0x80)) + gbInterruptWait = 1; + } + gbInt48Signal |= 1; + } + + gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]; + + gbLcdMode = 0; + + // No HDMA during HALT ! + if(gbHdmaOn && (!(IFF & 0x80) || (register_IE & register_IF & 0x1f))) { + gbDoHdma(); + } + + } + break; + } + } + + + if ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened)) { + int framesToSkip = systemFrameSkip; + if(speedup) + framesToSkip = 9; // try 6 FPS during speedup + //gbLcdTicksDelayed = gbLcdTicks+1; + gbLCDChangeHappened = false; + switch(gbLcdModeDelayed) { + case 0: + { + // H-Blank - // check if we reached the V-Blank period - if(register_LY == 144) { - // Yes, V-Blank - // set the LY increment counter - gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS; - gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS; - gbLcdMode = 1; - if(register_LCDC & 0x80) { - gbInterrupt |= 1; // V-Blank interrupt - gbInterruptWait = 6; - if(register_STAT & 0x10) - gbInterrupt |= 2; + memset(gbSCYLine,gbSCYLine[299],sizeof(gbSCYLine)); + memset(gbSCXLine,gbSCXLine[299],sizeof(gbSCXLine)); + memset(gbBgpLine,gbBgpLine[299],sizeof(gbBgpLine)); + memset(gbObp0Line,gbObp0Line[299],sizeof(gbObp0Line)); + memset(gbObp1Line,gbObp1Line[299],sizeof(gbObp1Line)); + memset(gbSpritesTicks,gbSpritesTicks[299],sizeof(gbSpritesTicks)); + + if (gbWindowLine <0) + oldRegister_WY = register_WY; + // check if we reached the V-Blank period + if(register_LY == 144) { + // Yes, V-Blank + // set the LY increment counter + + if(register_LCDC & 0x80) { + if (gbHardware & 0xa) + { + + register_IF |= 1; // V-Blank interrupt + gbInterruptLaunched |=1; + } + + + } + + gbLcdTicksDelayed += GBLCD_MODE_1_CLOCK_TICKS; + gbLcdModeDelayed = 1; + + gbFrameCount++; + systemFrame(); + + if((gbFrameCount % 10) == 0) + system10Frames(60); + + if(gbFrameCount >= 60) { + u32 currentTime = systemGetClock(); + if(currentTime != gbLastTime) + systemShowSpeed(100000/(currentTime - gbLastTime)); + else + systemShowSpeed(0); + gbLastTime = currentTime; + gbFrameCount = 0; + } + + if(systemReadJoypads()) { + // read joystick + if(gbSgbMode && gbSgbMultiplayer) { + if(gbSgbFourPlayers) { + gbJoymask[0] = systemReadJoypad(0); + gbJoymask[1] = systemReadJoypad(1); + gbJoymask[2] = systemReadJoypad(2); + gbJoymask[3] = systemReadJoypad(3); + } else { + gbJoymask[0] = systemReadJoypad(0); + gbJoymask[1] = systemReadJoypad(1); + } + } else { + gbJoymask[0] = systemReadJoypad(-1); + } + } + int newmask = gbJoymask[0] & 255; + + if(gbRomType == 0x22) { + systemUpdateMotionSensor(); + } + + if(newmask) + { + gbMemory[0xff0f] |= 16; + } + + + newmask = (gbJoymask[0] >> 10); + + speedup = (newmask & 1) ? true : false; + gbCapture = (newmask & 2) ? true : false; + + if(gbCapture && !gbCapturePrevious) { + gbCaptureNumber++; + systemScreenCapture(gbCaptureNumber); + } + gbCapturePrevious = gbCapture; + + if(gbFrameSkipCount >= framesToSkip) { + + if(!gbSgbMask) + { + if (gbBorderOn) + gbSgbRenderBorder(); + //if (gbScreenOn) + systemDrawScreen(); } + gbFrameSkipCount = 0; + } else + gbFrameSkipCount++; - gbFrameCount++; + } else { + // go the the OAM being accessed mode + gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS; + gbLcdModeDelayed = 2; + gbInt48Signal &= ~3; + } + } + break; + case 1: + { + // V-Blank + // next mode is OAM being accessed mode - systemFrame(); + // gbScreenOn = true; - if((gbFrameCount % 10) == 0) - system10Frames(60); + oldRegister_WY = register_WY; - if(gbFrameCount >= 60) { - u32 currentTime = systemGetClock(); - if(currentTime != gbLastTime) - systemShowSpeed(100000/(currentTime - gbLastTime)); - else - systemShowSpeed(0); - gbLastTime = currentTime; - gbFrameCount = 0; + gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS; + gbLcdModeDelayed = 2; + + // reset the window line + gbWindowLine = -1; + } + break; + case 2: + { + // OAM being accessed mode + // next mode is OAM and VRAM in use + gbLcdTicksDelayed += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299]; + gbLcdModeDelayed = 3; + } + break; + case 3: + { + + // OAM and VRAM in use + // next mode is H-Blank + if((register_LY < 144) && (register_LCDC & 0x80) && gbScreenOn) { + if(!gbSgbMask) { + if(gbFrameSkipCount >= framesToSkip) { + if (!gbBlackScreen) + { + gbRenderLine(); + gbDrawSprites(true); + } + else if (gbBlackScreen) + { + u16 color = gbColorOption ? gbColorFilter[0] : 0; + if (!gbCgbMode) + color = gbColorOption ? gbColorFilter[gbPalette[3] & 0x7FFF] : + gbPalette[3] & 0x7FFF; + for(int i = 0; i < 160; i++) + { + gbLineMix[i] = color; + gbLineBuffer[i] = 0; + } + } + gbDrawLine(); + } + } + } + gbLcdTicksDelayed += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]; + gbLcdModeDelayed = 0; + } + break; + } + } + + if ((gbLcdLYIncrementTicksDelayed <= 0) && (gbLYChangeHappened == true)) + { + + gbLYChangeHappened = false; + + if (!((gbLcdMode != 1) && (register_LY==0))) + { + { + gbInt48Signal &= ~8; + gbCompareLYToLYC(); + if ((gbInt48Signal == 8) && (!((register_LY == 0) && (gbHardware & 1)))) + gbInterruptLaunched |= 2; + if ((gbHardware & (gbSpeed ? 8 : 2)) && (register_LY==0) && ((register_STAT & 0x44) == 0x44) && (gbLcdLYIncrementTicksDelayed==0)) + { + gbInterruptWait = 1; + + } + } + } + gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS; + + if (gbLcdModeDelayed == 1) + { + + if(register_LY == 153) + gbLcdLYIncrementTicksDelayed -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; + else if(register_LY == 0) + gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks; + } + gbMemory[0xff0f] = register_IF; + gbMemory[0xff41] = register_STAT; + } + } + gbMemory[0xff0f] = register_IF; + gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | gbLcdModeDelayed; + } + else + { + + // Used to update the screen with white lines when it's off. + // (it looks strange, but it's kinda accurate :p) + // You can try the Mario Demo Vx.x for exemple + // (check the bottom 2 lines while moving) + if (!gbWhiteScreen) + { + gbScreenTicks -= clockTicks; + gbLcdLYIncrementTicks -= clockTicks; + while (gbLcdLYIncrementTicks <=0) + { + register_LY = ((register_LY+1)%154); + gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS; + } + if (gbScreenTicks <= 0) + { + gbWhiteScreen = 1; + u8 register_LYLcdOff = ((register_LY+154)%154); + for (register_LY=0;register_LY <= 0x90;register_LY++) + { + u16 color = gbColorOption ? gbColorFilter[0x7FFF] : + 0x7FFF; + if (!gbCgbMode) + color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : + gbPalette[0] & 0x7FFF; + for(int i = 0; i < 160; i++) + { + gbLineMix[i] = color; + gbLineBuffer[i] = 0; } + gbDrawLine(); + } + register_LY = register_LYLcdOff; + } + } + + if (gbWhiteScreen) + { + gbLcdLYIncrementTicks -= clockTicks; + while (gbLcdLYIncrementTicks <=0) + { + register_LY = ((register_LY+1)%154); + gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS; + if (register_LY<144) + { + + u16 color = gbColorOption ? gbColorFilter[0x7FFF] : + 0x7FFF; + if (!gbCgbMode) + color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : + gbPalette[0] & 0x7FFF; + for(int i = 0; i < 160; i++) + { + gbLineMix[i] = color; + gbLineBuffer[i] = 0; + } + gbDrawLine(); + } + else if ((register_LY==144) && (!systemFrameSkip)) + { + int framesToSkip = systemFrameSkip; + if(speedup) + framesToSkip = 9; // try 6 FPS during speedup + if((gbFrameSkipCount >= framesToSkip) || (gbWhiteScreen == 1)) { + gbWhiteScreen = 2; + + if(!gbSgbMask) + { + if (gbBorderOn) + gbSgbRenderBorder(); + //if (gbScreenOn) + systemDrawScreen(); + } + } if(systemReadJoypads()) { // read joystick if(gbSgbMode && gbSgbMultiplayer) { @@ -2784,198 +5127,29 @@ gbJoymask[0] = systemReadJoypad(-1); } } - int newmask = gbJoymask[0] & 255; + gbFrameCount++; - if(gbRom[0x147] == 0x22) { - systemUpdateMotionSensor(); - } - - if(newmask) { - gbInterrupt |= 16; - } + systemFrame(); - newmask = (gbJoymask[0] >> 10); - - speedup = (newmask & 1) ? true : false; - gbCapture = (newmask & 2) ? true : false; + if((gbFrameCount % 10) == 0) + system10Frames(60); - if(gbCapture && !gbCapturePrevious) { - gbCaptureNumber++; - systemScreenCapture(gbCaptureNumber); - } - gbCapturePrevious = gbCapture; - - if(gbFrameSkipCount >= framesToSkip) { - systemDrawScreen(); - gbFrameSkipCount = 0; - } else - gbFrameSkipCount++; - } else { - // go the the OAM being accessed mode - gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; - gbLcdMode = 2; - - // only one LCD interrupt per line. may need to generalize... - if(!(register_STAT & 0x40) || - (register_LY != register_LYC)) { - if((register_STAT & 0x28) == 0x20) - gbInterrupt |= 2; - } - } - break; - case 1: - // V-Blank - // next mode is OAM being accessed mode - gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; - gbLcdMode = 2; - if(!(register_STAT & 0x40) || - (register_LY != register_LYC)) { - if((register_STAT & 0x28) == 0x20) - gbInterrupt |= 2; - } - break; - case 2: - // OAM being accessed mode - - // next mode is OAM and VRAM in use - gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS; - gbLcdMode = 3; - break; - case 3: - // OAM and VRAM in use - // next mode is H-Blank - if(register_LY < 144) { - if(!gbSgbMask) { - if(gbFrameSkipCount >= framesToSkip) { - gbRenderLine(); - gbDrawSprites(); - - switch(systemColorDepth) { - case 16: - { - u16 * dest = (u16 *)pix + - (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1) - + gbBorderColumnSkip; - for(int x = 0; x < 160; ) { - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - *dest++ = systemColorMap16[gbLineMix[x++]]; - } - if(gbBorderOn) - dest += gbBorderColumnSkip; - *dest++ = 0; // for filters that read one pixel more - } - break; - case 24: - { - u8 *dest = (u8 *)pix + - 3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) + - gbBorderColumnSkip); - for(int x = 0; x < 160;) { - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; - dest+= 3; - } - } - break; - case 32: - { - u32 * dest = (u32 *)pix + - (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1) - + gbBorderColumnSkip; - for(int x = 0; x < 160;) { - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - *dest++ = systemColorMap32[gbLineMix[x++]]; - } - } - break; - } - } + if(gbFrameCount >= 60) { + u32 currentTime = systemGetClock(); + if(currentTime != gbLastTime) + systemShowSpeed(100000/(currentTime - gbLastTime)); + else + systemShowSpeed(0); + gbLastTime = currentTime; + gbFrameCount = 0; } } - gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS; - gbLcdMode = 0; - // only one LCD interrupt per line. may need to generalize... - if(!(register_STAT & 0x40) || - (register_LY != register_LYC)) { - if(register_STAT & 0x08) - gbInterrupt |= 2; - } - if(gbHdmaOn) { - gbDoHdma(); - } - break; } - // mark the correct lcd mode on STAT register - register_STAT = (register_STAT & 0xfc) | gbLcdMode; } } + gbMemory[0xff41] = register_STAT; + // serial emulation if(gbSerialOn) { #ifdef LINK_EMULATION @@ -2992,7 +5166,7 @@ gbMemory[0xff01] = 0xff; gbMemory[0xff02] &= 0x7f; gbSerialOn = 0; - gbInterrupt |= 8; + gbMemory[0xff0f] = register_IF |= 8; gbSerialTicks = 0; } } @@ -3018,7 +5192,7 @@ gbSerialTicks = 0; gbMemory[0xff02] &= 0x7f; gbSerialOn = 0; - gbInterrupt |= 8; + gbMemory[0xff0f] = register_IF |= 8; gbSerialBits = 0; } else gbSerialTicks += GBSERIAL_CLOCK_TICKS; @@ -3029,27 +5203,43 @@ #endif } + + soundTicks -= clockTicks; + + while(soundTicks < 0) { + soundTicks += SOUND_CLOCK_TICKS; + + gbSoundTick(); + } + + // timer emulation + if(gbTimerOn) { - gbTimerTicks -= clockTicks; - + gbTimerTicks= ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1-clockTicks; + while(gbTimerTicks <= 0) { register_TIMA++; - - if(register_TIMA == 0) { - // timer overflow! - + // timer overflow! + if((register_TIMA & 0xff) == 0) { // reload timer modulo register_TIMA = register_TMA; - // flag interrupt - gbInterrupt |= 4; + gbMemory[0xff0f] = register_IF |= 4; } - gbTimerTicks += gbTimerClockTicks; } + gbTimerOnChange = false; + gbTimerModeChange = false; + + gbMemory[0xff05] = register_TIMA; + } + gbInternalTimer -= clockTicks; + while (gbInternalTimer<0) + gbInternalTimer+=0x100; + /* if(soundOffFlag) { if(synchronize && !speedup) { @@ -3077,58 +5267,122 @@ } */ - soundTicks -= clockTicks; + clockTicks = 0; - while(soundTicks < 0) { - soundTicks += SOUND_CLOCK_TICKS; + if (gbIntBreak == 1) + { + gbIntBreak = 0; + if ((register_IE & register_IF & gbInterruptLaunched & 0x3) && + ((IFF & 0x81) == 1) && (!gbInterruptWait) && (execute)) + { + gbIntBreak = 2; + PC.W = oldPCW; + execute = false; + gbOldClockTicks = 0; + } + if (gbOldClockTicks) + { + clockTicks = gbOldClockTicks; + gbOldClockTicks = 0; + goto gbRedoLoop; + } + } - gbSoundTick(); + // Executes the opcode(s), and apply the instruction's remaining clockTicks (if any). + if (execute) + { + switch(opcode1) { + case 0xCB: + // extended opcode + switch(opcode2) { +#include "gbCodesCB.h" + } + break; +#include "gbCodes.h" + } + execute = false; + + if (clockTicks) + { + gbDmaTicks += clockTicks; + clockTicks = 0; + } } - - register_IF = gbInterrupt; - if(IFF & 0x20) { - IFF &= 0xdf; - IFF |= 0x01; - gbInterruptWait = 0; - } else if(gbInterrupt) { - if(gbInterruptWait == 0) { - // gbInterruptWait = 0; - - if(IFF & 0x01) { - if((gbInterrupt & 1) && (register_IE & 1)) { - gbVblank_interrupt(); - continue; - } - - if((gbInterrupt & 2) && (register_IE & 2)) { - gbLcd_interrupt(); - continue; - } - - if((gbInterrupt & 4) && (register_IE & 4)) { - gbTimer_interrupt(); - continue; - } - - if((gbInterrupt & 8) && (register_IE & 8)) { - gbSerial_interrupt(); - continue; - } + if (gbDmaTicks) + { + clockTicks = gbGetNextEvent(gbDmaTicks); - if((gbInterrupt & 16) && (register_IE & 16)) { - gbJoypad_interrupt(); - continue; - } + if (clockTicks<=gbDmaTicks) + gbDmaTicks -= clockTicks; + else + { + clockTicks = gbDmaTicks; + gbDmaTicks = 0; + } + + goto gbRedoLoop; + } + + + // Remove the 'if an IE is pending' flag if IE has finished being executed. + if ((IFF & 0x40) && !(IFF & 0x30)) + IFF &= 0x81; + + + + if ((register_IE & register_IF & 0x1f) && (IFF & 0x81) && (!gbInterruptWait)) + { + + if (IFF & 1) + { + // Add 5 ticks for the interrupt execution time + gbDmaTicks += 5; + + if (gbIntBreak == 2) + { + gbDmaTicks--; + gbIntBreak = 0; } - } else { - gbInterruptWait -= clockTicks; - if(gbInterruptWait < 0) - gbInterruptWait = 0; + + + if(register_IF & register_IE & 1) + gbVblank_interrupt(); + else if(register_IF & register_IE & 2) + gbLcd_interrupt(); + else if(register_IF & register_IE & 4) + gbTimer_interrupt(); + else if(register_IF & register_IE & 8) + gbSerial_interrupt(); + else if(register_IF & register_IE & 16) + gbJoypad_interrupt(); + } + + IFF &= ~0x81; + } + + if (IFF & 0x08) + IFF &=~0x79; + + // Used to apply the interrupt's execution time. + if (gbDmaTicks) + { + clockTicks = gbGetNextEvent(gbDmaTicks); + + if (clockTicks<=gbDmaTicks) + gbDmaTicks -= clockTicks; + else + { + clockTicks = gbDmaTicks; + gbDmaTicks = 0; } + goto gbRedoLoop; } - if(ticksToStop <= 0) { + + gbBlackScreen = false; + + if((ticksToStop <= 0)) { if(!(register_LCDC & 0x80)) { if(systemReadJoypads()) { // read joystick diff -urN ../VisualBoyAdvance-1.7.2/src/gb/GB.h ./src/gb/GB.h --- ../VisualBoyAdvance-1.7.2/src/gb/GB.h 2004-05-13 23:11:09 +0900 +++ ./src/gb/GB.h 2006-06-06 23:25:43 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -38,11 +38,15 @@ extern bool gbLoadRom(const char *); extern void gbEmulate(int); +extern void gbWriteMemory(register u16, register u8); +extern void gbDrawLine(); extern bool gbIsGameboyRom(const char *); extern void gbSoundReset(); extern void gbSoundSetQuality(int); +extern void gbGetHardwareType(); extern void gbReset(); extern void gbCleanUp(); +extern void gbCPUInit(const char *,bool); extern bool gbWriteBatteryFile(const char *); extern bool gbWriteBatteryFile(const char *, bool); extern bool gbReadBatteryFile(const char *); diff -urN ../VisualBoyAdvance-1.7.2/src/gb/Makefile.in ./src/gb/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/gb/Makefile.in 2004-05-14 06:39:48 +0900 +++ ./src/gb/Makefile.in 2004-09-30 07:23:29 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbCheats.cpp ./src/gb/gbCheats.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/gbCheats.cpp 2004-05-13 23:40:33 +0900 +++ ./src/gb/gbCheats.cpp 2006-06-06 23:25:43 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -27,9 +27,11 @@ #include "gbCheats.h" #include "gbGlobals.h" +#include "GB.h" gbCheat gbCheatList[100]; int gbCheatNumber = 0; +int gbNextCheat = 0; bool gbCheatMap[0x10000]; extern bool cheatsEnabled; @@ -50,7 +52,7 @@ void gbCheatsSaveGame(gzFile gzFile) { utilWriteInt(gzFile, gbCheatNumber); - if(gbCheatNumber) + if(gbCheatNumber>0) utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); } @@ -81,7 +83,7 @@ } else { gbCheatNumber = utilReadInt(gzFile); - if(gbCheatNumber) { + if(gbCheatNumber>0) { utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); } } @@ -163,7 +165,7 @@ bool gbVerifyGsCode(const char *code) { - int len = strlen(code); + size_t len = strlen(code); if(len == 0) return true; @@ -180,10 +182,6 @@ GBCHEAT_HEX_VALUE(code[4]) << 4 | GBCHEAT_HEX_VALUE(code[5]); - if(address < 0xa000 || - address > 0xdfff) - return false; - return true; } @@ -220,15 +218,23 @@ gbCheatList[i].compare = 0; gbCheatList[i].enabled = true; - - gbCheatMap[gbCheatList[i].address] = true; - + + int gsCode = gbCheatList[i].code; + + if ((gsCode !=1) && ((gsCode & 0xF0) !=0x80) && ((gsCode & 0xF0) !=0x90) && + ((gsCode & 0xF0) !=0xA0) && ((gsCode) !=0xF0) && ((gsCode) !=0xF1)) + systemMessage(MSG_WRONG_GAMESHARK_CODE, + N_("Wrong GameShark code type : %s"), code); + else if (((gsCode & 0xF0) ==0xA0) || ((gsCode) ==0xF0) || ((gsCode) ==0xF1)) + systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE, + N_("Unsupported GameShark code type : %s"), code); + gbCheatNumber++; } bool gbVerifyGgCode(const char *code) { - int len = strlen(code); + size_t len = strlen(code); if(len != 11 && len != 7 && @@ -313,12 +319,12 @@ int i = gbCheatNumber; - int len = strlen(code); + size_t len = strlen(code); strcpy(gbCheatList[i].cheatCode, code); strcpy(gbCheatList[i].cheatDesc, desc); - gbCheatList[i].code = 1; + gbCheatList[i].code = 0x101; gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + GBCHEAT_HEX_VALUE(code[1]); @@ -338,9 +344,12 @@ compare ^= 0x45; gbCheatList[i].compare = compare; - gbCheatList[i].code = 0; + //gbCheatList[i].code = 0; + gbCheatList[i].code = 0x100; // fix for compare value + } + gbCheatList[i].enabled = true; gbCheatMap[gbCheatList[i].address] = true; @@ -425,6 +434,7 @@ return true; } +// Used to emulated GG codes u8 gbCheatRead(u16 address) { if(!cheatsEnabled) @@ -437,26 +447,72 @@ if(gbMemoryMap[address>>12][address&0xFFF] == gbCheatList[i].compare) return gbCheatList[i].value; break; - case 0x00: - case 0x01: - case 0x80: - return gbCheatList[i].value; - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - if(address >= 0xd000 && address < 0xe000) { - if(((gbMemoryMap[0x0d] - gbWram)/0x1000) == - (gbCheatList[i].code - 0x90)) - return gbCheatList[i].value; - } else + case 0x101: // GameGenie 6 digits code support return gbCheatList[i].value; + break; } } } return gbMemoryMap[address>>12][address&0xFFF]; } + + +// Used to emulate GS codes. +void gbCheatWrite(bool reboot) +{ + if(cheatsEnabled) + { + u16 address = 0; + + if (gbNextCheat >= gbCheatNumber) + gbNextCheat = 0; + + for(int i = gbNextCheat; i < gbCheatNumber; i++) { + if(gbCheatList[i].enabled) { + address = gbCheatList[i].address; + if ((!reboot) && (address >= 0x8000) && !((address>=0xA000) && (address<0xC000))) + { // These codes are executed one per one, at each Vblank + switch(gbCheatList[i].code) { + case 0x01: + gbWriteMemory(address, gbCheatList[i].value); + gbNextCheat = i+1; + return; + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + int oldbank = gbMemory[0xff70]; + gbWriteMemory(0xff70, gbCheatList[i].code & 0xf); + gbWriteMemory(address, gbCheatList[i].value); + gbWriteMemory(0xff70, oldbank); + gbNextCheat = i+1; + return; + } + } + else // These codes are only executed when the game is booted + { + switch(gbCheatList[i].code & 0xF0) { + case 0x80: + gbWriteMemory(0x0000, 0x0A); + gbWriteMemory(0x4000, gbCheatList[i].value & 0xF); + gbWriteMemory(address, gbCheatList[i].value); + gbNextCheat = i+1; + return; + } + } + } + } + } +} \ No newline at end of file diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbCheats.h ./src/gb/gbCheats.h --- ../VisualBoyAdvance-1.7.2/src/gb/gbCheats.h 2004-05-13 23:10:49 +0900 +++ ./src/gb/gbCheats.h 2006-06-06 23:25:43 +0900 @@ -50,6 +50,7 @@ extern void gbCheatEnable(int); extern void gbCheatDisable(int); extern u8 gbCheatRead(u16); +extern void gbCheatWrite(bool); extern int gbCheatNumber; extern gbCheat gbCheatList[100]; diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbCodes.h ./src/gb/gbCodes.h --- ../VisualBoyAdvance-1.7.2/src/gb/gbCodes.h 2004-05-13 23:10:32 +0900 +++ ./src/gb/gbCodes.h 2006-04-30 23:41:32 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -22,8 +22,8 @@ break; case 0x01: // LD BC, NNNN - BC.B.B0=gbReadMemory(PC.W++); - BC.B.B1=gbReadMemory(PC.W++); + BC.B.B0=gbReadOpcode(PC.W++); + BC.B.B1=gbReadOpcode(PC.W++); break; case 0x02: // LD (BC),A @@ -102,7 +102,9 @@ opcode = gbReadOpcode(PC.W++); if(gbCgbMode) { if(gbMemory[0xff4d] & 1) { + gbSpeedSwitch(); + //clockTicks += 228*144-(gbSpeed ? 62 : 63); if(gbSpeed == 0) gbMemory[0xff4d] = 0x00; @@ -113,8 +115,8 @@ break; case 0x11: // LD DE, NNNN - DE.B.B0=gbReadMemory(PC.W++); - DE.B.B1=gbReadMemory(PC.W++); + DE.B.B0=gbReadOpcode(PC.W++); + DE.B.B1=gbReadOpcode(PC.W++); break; case 0x12: // LD (DE),A @@ -147,7 +149,7 @@ break; case 0x18: // JR NN - PC.W+=(s8)gbReadMemory(PC.W)+1; + PC.W+=(s8)gbReadOpcode(PC.W)+1; break; case 0x19: // ADD HL,DE @@ -190,14 +192,14 @@ if(AF.B.B0&Z_FLAG) PC.W++; else { - PC.W+=(s8)gbReadMemory(PC.W)+1; + PC.W+=(s8)gbReadOpcode(PC.W)+1; clockTicks++; } break; case 0x21: // LD HL,NNNN - HL.B.B0=gbReadMemory(PC.W++); - HL.B.B1=gbReadMemory(PC.W++); + HL.B.B0=gbReadOpcode(PC.W++); + HL.B.B1=gbReadOpcode(PC.W++); break; case 0x22: // LDI (HL),A @@ -233,7 +235,7 @@ case 0x28: // JR Z,NN if(AF.B.B0&Z_FLAG) { - PC.W+=(s8)gbReadMemory(PC.W)+1; + PC.W+=(s8)gbReadOpcode(PC.W)+1; clockTicks++; } else PC.W++; @@ -278,14 +280,14 @@ if(AF.B.B0&C_FLAG) PC.W++; else { - PC.W+=(s8)gbReadMemory(PC.W)+1; + PC.W+=(s8)gbReadOpcode(PC.W)+1; clockTicks++; } break; case 0x31: // LD SP,NNNN - SP.B.B0=gbReadMemory(PC.W++); - SP.B.B1=gbReadMemory(PC.W++); + SP.B.B0=gbReadOpcode(PC.W++); + SP.B.B1=gbReadOpcode(PC.W++); break; case 0x32: // LDD (HL),A @@ -318,7 +320,7 @@ case 0x38: // JR C,NN if(AF.B.B0&C_FLAG) { - PC.W+=(s8)gbReadMemory(PC.W)+1; + PC.W+=(s8)gbReadOpcode(PC.W)+1; clockTicks ++; } else PC.W++; @@ -575,16 +577,24 @@ break; case 0x76: // HALT - if(IFF & 1) { + // If an EI is pending, the interrupts are triggered before Halt state !! + // Fix Torpedo Range's intro. + if (IFF & 0x40) + { + IFF &= ~0x70; + IFF |=1; PC.W--; - IFF |= 0x80; - } else { - if((register_IE & register_IF) > 0) - IFF |= 0x100; - else { - PC.W--; - IFF |= 0x81; + } + else + { + // if (IE & IF) and interrupts are disabeld, + // Halt is cancelled. + if ((register_IE & register_IF & 0x1f) && !(IFF & 1)) + { + IFF|=2; } + else + IFF |= 0x80; } break; case 0x77: @@ -1036,16 +1046,16 @@ if(AF.B.B0&Z_FLAG) PC.W+=2; else { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W); PC.W=tempRegister.W; clockTicks++; } break; case 0xc3: // JP NNNN - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W); PC.W=tempRegister.W; break; case 0xc4: @@ -1053,8 +1063,8 @@ if(AF.B.B0&Z_FLAG) PC.W+=2; else { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W++); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W++); gbWriteMemory(--SP.W,PC.B.B1); gbWriteMemory(--SP.W,PC.B.B0); PC.W=tempRegister.W; @@ -1096,8 +1106,8 @@ case 0xca: // JP Z,NNNN if(AF.B.B0&Z_FLAG) { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W); PC.W=tempRegister.W; clockTicks++; } else @@ -1107,8 +1117,8 @@ case 0xcc: // CALL Z,NNNN if(AF.B.B0&Z_FLAG) { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W++); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W++); gbWriteMemory(--SP.W,PC.B.B1); gbWriteMemory(--SP.W,PC.B.B0); PC.W=tempRegister.W; @@ -1118,8 +1128,8 @@ break; case 0xcd: // CALL NNNN - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W++); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W++); gbWriteMemory(--SP.W,PC.B.B1); gbWriteMemory(--SP.W,PC.B.B0); PC.W=tempRegister.W; @@ -1156,20 +1166,24 @@ if(AF.B.B0&C_FLAG) PC.W+=2; else { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W); PC.W=tempRegister.W; clockTicks++; } break; // D3 illegal + case 0xd3: + PC.W--; + IFF = 0; + break; case 0xd4: // CALL NC,NNNN if(AF.B.B0&C_FLAG) PC.W+=2; else { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W++); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W++); gbWriteMemory(--SP.W,PC.B.B1); gbWriteMemory(--SP.W,PC.B.B0); PC.W=tempRegister.W; @@ -1200,7 +1214,7 @@ if(AF.B.B0&C_FLAG) { PC.B.B0=gbReadMemory(SP.W++); PC.B.B1=gbReadMemory(SP.W++); - clockTicks += 4; + clockTicks += 3; } break; case 0xd9: @@ -1212,19 +1226,23 @@ case 0xda: // JP C,NNNN if(AF.B.B0&C_FLAG) { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W); PC.W=tempRegister.W; clockTicks++; } else PC.W+=2; break; // DB illegal + case 0xdb: + PC.W--; + IFF = 0; + break; case 0xdc: // CALL C,NNNN if(AF.B.B0&C_FLAG) { - tempRegister.B.B0=gbReadMemory(PC.W++); - tempRegister.B.B1=gbReadMemory(PC.W++); + tempRegister.B.B0=gbReadOpcode(PC.W++); + tempRegister.B.B1=gbReadOpcode(PC.W++); gbWriteMemory(--SP.W,PC.B.B1); gbWriteMemory(--SP.W,PC.B.B0); PC.W=tempRegister.W; @@ -1233,6 +1251,10 @@ PC.W+=2; break; // DD illegal + case 0xdd: + PC.W--; + IFF = 0; + break; case 0xde: // SBC NN tempValue=gbReadOpcode(PC.W++); @@ -1262,6 +1284,11 @@ break; // E3 illegal // E4 illegal + case 0xe3: + case 0xe4: + PC.W--; + IFF = 0; + break; case 0xe5: // PUSH HL gbWriteMemory(--SP.W,HL.B.B1); @@ -1308,6 +1335,12 @@ // EB illegal // EC illegal // ED illegal + case 0xeb: + case 0xec: + case 0xed: + PC.W--; + IFF = 0; + break; case 0xee: // XOR NN tempValue=gbReadOpcode(PC.W++); @@ -1336,9 +1369,13 @@ case 0xf3: // DI // IFF&=0xFE; - IFF&=(~0x21); + IFF|=0x08; break; // F4 illegal + case 0xf4: + PC.W--; + IFF = 0; + break; case 0xf5: // PUSH AF gbWriteMemory(--SP.W,AF.B.B1); @@ -1383,10 +1420,23 @@ break; case 0xfb: // EI - IFF|=0x20; - break; - // FC illegal + if (!(IFF & 0x30)) + // If an EI is executed right before HALT, + // the interrupts are triggered before the Halt state !! + // Fix Torpedo Range Intro. + // IFF |= 0x10 : 1 ticks before the EI enables the interrupts + // IFF |= 0x40 : marks that an EI is being executed. + IFF|=0x50; + break; + // FC illegal (FC = breakpoint) + case 0xfc: + breakpoint = true; + break; // FD illegal + case 0xfd: + PC.W--; + IFF = 0; + break; case 0xfe: // CP NN tempValue=gbReadOpcode(PC.W++); @@ -1401,7 +1451,10 @@ PC.W=0x0038; break; default: - systemMessage(0, N_("Unknown opcode %02x at %04x"), - gbReadOpcode(PC.W-1),PC.W-1); - emulating = false; + if (gbSystemMessage == false) + { + systemMessage(0, N_("Unknown opcode %02x at %04x"), + gbReadOpcode(PC.W-1),PC.W-1); + gbSystemMessage =true; + } return; diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbCodesCB.h ./src/gb/gbCodesCB.h --- ../VisualBoyAdvance-1.7.2/src/gb/gbCodesCB.h 2004-05-13 23:10:17 +0900 +++ ./src/gb/gbCodesCB.h 2006-01-04 22:38:47 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -1282,7 +1282,10 @@ AF.B.B1|=1<<7; break; default: - systemMessage(0, N_("Unknown opcode %02x at %04x"), - gbReadOpcode(PC.W-1),PC.W-1); - emulating = false; + if (gbSystemMessage == false) + { + systemMessage(0, N_("Unknown opcode %02x at %04x"), + gbReadOpcode(PC.W-1),PC.W-1); + gbSystemMessage =true; + } return; diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbGfx.cpp ./src/gb/gbGfx.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/gbGfx.cpp 2004-05-13 23:40:13 +0900 +++ ./src/gb/gbGfx.cpp 2006-04-30 23:42:18 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -58,9 +58,12 @@ }; u16 gbLineMix[160]; +u16 gbWindowColor[160]; +extern int inUseRegister_WY; void gbRenderLine() { + memset(gbLineMix, 0, sizeof(gbLineMix)); u8 * bank0; u8 * bank1; if(gbCgbMode) { @@ -86,10 +89,9 @@ if(y >= 144) return; - // int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip; - - int sx = register_SCX; - int sy = register_SCY; + int SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4); + int sx = gbSCXLine[(gbSpeed ? 0 : 4)+SpritesTicks]; + int sy = gbSCYLine[(gbSpeed ? 11 : 5)+SpritesTicks]; sy+=y; @@ -113,16 +115,17 @@ tile_map_address++; - if((register_LCDC & 16) == 0) { - if(tile < 128) tile += 128; - else tile -= 128; - } + if(!(register_LCDC & 0x10)) + tile ^= 0x80; int tile_pattern_address = tile_pattern + tile * 16 + by*2; if(register_LCDC & 0x80) { if((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) { while(x < 160) { + + + u8 tile_a = 0; u8 tile_b = 0; @@ -155,7 +158,7 @@ if(gbCgbMode) { c = c + (attrs & 7)*4; } else { - c = gbBgp[c]; + c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+SpritesTicks]>>(c<<1)) &3; if(gbSgbMode && !gbCgbMode) { int dx = x >> 3; int dy = y >> 3; @@ -168,42 +171,92 @@ c = c + 4*palette; } } - gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] : - gbPalette[c]; + gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : + gbPalette[c] & 0x7FFF; x++; if(x >= 160) break; bx >>= 1; } - tx++; - if(tx == 32) - tx = 0; + bx = 128; - + + SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4); + + sx = gbSCXLine[x+(gbSpeed ? 0 : 4)+SpritesTicks]; + + sy = gbSCYLine[x+(gbSpeed ? 11 : 5)+SpritesTicks]; + + + tx = ((sx+x)>>3) & 0x1f; + + sy+=y; + + sy &= 255; + + ty = sy >> 3; + + by = sy & 7; + + tile_pattern_address = tile_pattern + tile * 16 + by * 2; + + tile_map_line_y = tile_map + ty * 32; + + tile_map_address = tile_map_line_y + tx; + if(bank1) attrs = bank1[tile_map_line_y + tx]; tile = bank0[tile_map_line_y + tx]; - - if((register_LCDC & 16) == 0) { - if(tile < 128) tile += 128; - else tile -= 128; - } + + if(!(register_LCDC & 0x10)) + tile ^= 0x80; + tile_pattern_address = tile_pattern + tile * 16 + by * 2; } } else { - for(int i = 0; i < 160; i++) { - gbLineMix[i] = gbPalette[0]; + // Use gbBgp[0] instead of 0 (?) + // (this fixes white flashes on Last Bible II) + // Also added the gbColorOption (fixes Dracula Densetsu II color problems) + for(int i = 0; i < 160; i++) + { + u16 color = gbColorOption ? gbColorFilter[0x7FFF] : + 0x7FFF; + if (!gbCgbMode) + color = gbColorOption ? gbColorFilter[gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF] : + gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF; + gbLineMix[i] = color; gbLineBuffer[i] = 0; } } // do the window display - if((register_LCDC & 0x20) && (layerSettings & 0x2000)) { - int wy = register_WY; + // LCDC.0 also enables/disables the window in !gbCgbMode ?!?! + // (tested on real hardware) + // This fixes Last Bible II & Zankurou Musouken + if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) && + (layerSettings & 0x2000) && (gbWindowLine != -2)) { + int i = 0; + // Fix (accurate emulation) for most of the window display problems + // (ie. Zen - Intergalactic Ninja, Urusei Yatsura...). + if ((gbWindowLine == -1) || (gbWindowLine>144)) + { + inUseRegister_WY = oldRegister_WY; + if (register_LY>oldRegister_WY) + gbWindowLine = 146; + // for (i = 0; i<160; i++) + // gbWindowColor[i] = gbLineMix[i]; + } + + int wy = inUseRegister_WY; - if(y >= wy) { + if(y >= inUseRegister_WY) { + + if (gbWindowLine == -1) + gbWindowLine = 0; + int wx = register_WX; + int swx = 0; wx -= 7; if( wx <= 159 && gbWindowLine <= 143) { @@ -212,10 +265,7 @@ if((register_LCDC & 0x40) != 0) tile_map = 0x1c00; - - if(gbWindowLine == -1) { - gbWindowLine = 0; - } + tx = 0; ty = gbWindowLine >> 3; @@ -223,6 +273,25 @@ bx = 128; by = gbWindowLine & 7; + // Tries to emulate the 'window scrolling bug' when wx == 0 (ie. wx-7 == -7). + // Nothing close to perfect, but good enought for now... + if (wx == -7) + { + swx = 7-((gbSCXLine[0]-1) & 7); + bx >>= ((gbSCXLine[0]+((swx != 1) ? 1 : 0)) & 7); + if (swx == 1) + swx = 2; + + //bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7); + + if ((swx == 7)) + { + //wx = 0; + if ((gbWindowLine>0) || (wy == 0)) + swx = 0; + } + } + else if(wx < 0) { bx >>= (-wx); wx = 0; @@ -247,6 +316,10 @@ tile_pattern_address = tile_pattern + tile * 16 + by*2; + if (wx) + for (i = 0; i=0) + { if(attrs & 0x80) gbLineBuffer[x] = 0x300 + c; else @@ -280,8 +355,8 @@ if(gbCgbMode) { c = c + (attrs & 7) * 4; } else { - c = gbBgp[c]; - if(gbSgbMode && ! gbCgbMode) { + c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(c<<1)) &3; + if(gbSgbMode && !gbCgbMode) { int dx = x >> 3; int dy = y >> 3; @@ -293,8 +368,9 @@ c = c + 4*palette; } } - gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] : - gbPalette[c]; + gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : + gbPalette[c] & 0x7FFF; + } x++; if(x >= 160) break; @@ -314,13 +390,30 @@ } tile_pattern_address = tile_pattern + tile * 16 + by * 2; } + + //for (i = swx; i<160; i++) + // gbLineMix[i] = gbWindowColor[i]; gbWindowLine++; } } } + else if (gbWindowLine == -2) + { + inUseRegister_WY = oldRegister_WY; + if (register_LY>oldRegister_WY) + gbWindowLine = 146; + else + gbWindowLine = 0; + } } else { - for(int i = 0; i < 160; i++) { - gbLineMix[i] = gbPalette[0]; + u16 color = gbColorOption ? gbColorFilter[0x7FFF] : + 0x7FFF; + if (!gbCgbMode) + color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : + gbPalette[0] & 0x7FFF; + for(int i = 0; i < 160; i++) + { + gbLineMix[i] = color; gbLineBuffer[i] = 0; } } @@ -346,8 +439,11 @@ int init = 0x0000; - // int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip; - + for (int i = 0; i<4; i++) + { + gbObp0[i] = (gbObp0Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3; + gbObp1[i] = (gbObp1Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3; + } u8 *pal = gbObp0; int flipx = (flags & 0x20); @@ -366,7 +462,7 @@ int a = 0; int b = 0; - if(gbCgbMode && flags & 0x08) { + if(gbCgbMode && (flags & 0x08)) { a = bank1[address++]; b = bank1[address++]; } else { @@ -392,12 +488,14 @@ continue; u16 color = gbLineBuffer[xxx]; - - if(prio) { + + // Fixes OAM-BG priority + if(prio && (register_LCDC & 1)) { if(color < 0x200 && ((color & 0xFF) != 0)) continue; } - if(color >= 0x300 && color != 0x300) + // Fixes OAM-BG priority for Moorhuhn 2 + if(color >= 0x300 && color != 0x300 && (register_LCDC & 1)) continue; else if(color >= 0x200 && color < 0x300) { int sprite = color & 0xff; @@ -412,7 +510,9 @@ if(sprite < spriteNumber) continue; } else { - if(spriteX < x+8) + // Fixes GB sprites priorities (was '< x + 8' before) + // ('A boy and his blob...' sprites' emulation is now correct) + if(spriteX < x) continue; } } @@ -442,12 +542,12 @@ } } - gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] : - gbPalette[c]; + gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : + gbPalette[c] & 0x7FFF; } } -void gbDrawSprites() +void gbDrawSprites(bool draw) { int x = 0; int y = 0; @@ -455,6 +555,9 @@ int size = (register_LCDC & 4); + if (!draw) + memset (gbSpritesTicks, 0, sizeof(gbSpritesTicks)); + if(!(register_LCDC & 0x80)) return; @@ -473,11 +576,19 @@ if(x > 0 && y > 0 && x < 168 && y < 160) { // check if sprite intersects current line int t = yc -y + 16; - if(size && t >=0 && t < 16) { - gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i); - count++; - } else if(!size && t >= 0 && t < 8) { - gbDrawSpriteTile(tile, x-8, yc, t, flags,size,i); + if((size && t >=0 && t < 16) || (!size && t >= 0 && t < 8)) { + if (draw) + gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i); + else + { + for (int j = x-8; j<300; j++) + if (j>=0) + if (gbSpeed) + gbSpritesTicks[j] += 5; + else + gbSpritesTicks[j] += 2+(count&1); + + } count++; } } @@ -486,5 +597,5 @@ break; } } -} - + return; +} \ No newline at end of file diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbGlobals.cpp ./src/gb/gbGlobals.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/gbGlobals.cpp 2004-05-13 23:40:02 +0900 +++ ./src/gb/gbGlobals.cpp 2006-04-30 23:43:06 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -24,6 +24,7 @@ int gbRomSize = 0; int gbRamSizeMask = 0; int gbRamSize = 0; +int gbTAMA5ramSize = 0; u8 *gbMemory = NULL; u8 *gbVram = NULL; @@ -31,6 +32,7 @@ u8 *gbRam = NULL; u8 *gbWram = NULL; u16 *gbLineBuffer = NULL; +u8 *gbTAMA5ram = NULL; u16 gbPalette[128]; u8 gbBgp[4] = { 0, 1, 2, 3}; @@ -38,6 +40,7 @@ u8 gbObp1[4] = { 0, 1, 2, 3}; int gbWindowLine = -1; +bool genericflashcardEnable = false; int gbCgbMode = 0; u16 gbColorFilter[32768]; diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbGlobals.h ./src/gb/gbGlobals.h --- ../VisualBoyAdvance-1.7.2/src/gb/gbGlobals.h 2004-05-13 23:10:07 +0900 +++ ./src/gb/gbGlobals.h 2006-04-30 23:43:06 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -21,6 +21,11 @@ extern int gbRomSize; extern int gbRamSize; extern int gbRamSizeMask; +extern int gbTAMA5ramSize; + +extern bool useBios; +extern bool skipBios; +extern u8 *bios; extern u8 *gbRom; extern u8 *gbRam; @@ -28,6 +33,7 @@ extern u8 *gbWram; extern u8 *gbMemory; extern u16 *gbLineBuffer; +extern u8 *gbTAMA5ram; extern u8 *gbMemoryMap[16]; @@ -46,6 +52,19 @@ extern u8 gbObp0[4]; extern u8 gbObp1[4]; extern u16 gbPalette[128]; +extern bool gbScreenOn; +extern bool gbDrawWindow; +extern u8 gbSCYLine[300]; +// gbSCXLine is used for the emulation (bug) of the SX change +// found in the Artic Zone game. +extern u8 gbSCXLine[300]; +// gbBgpLine is used for the emulation of the +// Prehistorik Man's title screen scroller. +extern u8 gbBgpLine[300]; +extern u8 gbObp0Line [300]; +extern u8 gbObp1Line [300]; +// gbSpritesTicks is used for the emulation of Parodius' Laser Beam. +extern u8 gbSpritesTicks[300]; extern u8 register_LCDC; extern u8 register_LY; @@ -54,8 +73,10 @@ extern u8 register_WY; extern u8 register_WX; extern u8 register_VBK; +extern u8 oldRegister_WY; extern int emulating; +extern bool genericflashcardEnable; extern int gbBorderLineSkip; extern int gbBorderRowSkip; @@ -63,6 +84,6 @@ extern int gbDmaTicks; extern void gbRenderLine(); -extern void gbDrawSprites(); +extern void gbDrawSprites(bool); extern u8 (*gbSerialFunction)(u8); diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbMemory.cpp ./src/gb/gbMemory.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/gbMemory.cpp 2004-05-13 23:39:52 +0900 +++ ./src/gb/gbMemory.cpp 2006-06-06 23:25:43 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -20,6 +20,12 @@ #include "../Port.h" #include "gbGlobals.h" #include "gbMemory.h" +#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; mapperMBC1 gbDataMBC1 = { 0, // RAM enable @@ -27,7 +33,8 @@ 0, // RAM bank 0, // memory model 0, // ROM high address - 0 // RAM address + 0, // RAM address + 0 // Rom Bank 0 remapping }; // MBC1 ROM write registers @@ -41,17 +48,25 @@ break; case 0x2000: // ROM bank select // value = value & 0x1f; - if(value == 0) - value = 1; + if ((value == 1) && (address == 0x2100)) + gbDataMBC1.mapperRomBank0Remapping = 1; + + if((value & 0x1f) == 0) + value += 1; if(value == gbDataMBC1.mapperROMBank) break; tmpAddress = value << 14; // check current model + if (gbDataMBC1.mapperRomBank0Remapping == 3) { + tmpAddress = (value & 0xf) << 14; + tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 18; + } + else if(gbDataMBC1.mapperMemoryModel == 0) { // model is 16/8, so we have a high address in use - tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; + tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 19; } tmpAddress &= gbRomSizeMask; @@ -63,16 +78,39 @@ break; case 0x4000: // RAM bank select if(gbDataMBC1.mapperMemoryModel == 1) { + if (!gbRamSize) + { + if (gbDataMBC1.mapperRomBank0Remapping == 3) + { + gbDataMBC1.mapperROMHighAddress = value & 0x03; + tmpAddress = (gbDataMBC1.mapperROMHighAddress) << 18; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x00] = &gbRom[tmpAddress]; + gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; + gbMemoryMap[0x04] = &gbRom[tmpAddress + 0x4000]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x5000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x6000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x7000]; + } + else gbDataMBC1.mapperRomBank0Remapping = 0; + } // 4/32 model, RAM bank switching provided value = value & 0x03; if(value == gbDataMBC1.mapperRAMBank) break; tmpAddress = value << 13; tmpAddress &= gbRamSizeMask; - gbMemoryMap[0x0a] = &gbRam[tmpAddress]; - gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; + if(gbRamSize) { + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; + } gbDataMBC1.mapperRAMBank = value; gbDataMBC1.mapperRAMAddress = tmpAddress; + + if (gbDataMBC1.mapperRomBank0Remapping != 3) + gbDataMBC1.mapperROMHighAddress = 0; } else { // 16/8, set the high address gbDataMBC1.mapperROMHighAddress = value & 0x03; @@ -83,10 +121,57 @@ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + if(gbRamSize) { + gbMemoryMap[0x0a] = &gbRam[0]; + gbMemoryMap[0x0b] = &gbRam[0x1000]; + } + + gbDataMBC1.mapperRAMBank = 0; } break; case 0x6000: // memory model select gbDataMBC1.mapperMemoryModel = value & 1; + + if(gbDataMBC1.mapperMemoryModel == 1) { + // 4/32 model, RAM bank switching provided + + value = gbDataMBC1.mapperRAMBank & 0x03; + tmpAddress = value << 13; + tmpAddress &= gbRamSizeMask; + if(gbRamSize) { + gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress]; + gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000]; + gbDataMBC1.mapperRomBank0Remapping = 0; + } + else gbDataMBC1.mapperRomBank0Remapping |=2; + + gbDataMBC1.mapperRAMBank = value; + gbDataMBC1.mapperRAMAddress = tmpAddress; + + tmpAddress = gbDataMBC1.mapperROMBank << 14; + + + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + + } else { + // 16/8, set the high address + + tmpAddress = gbDataMBC1.mapperROMBank << 14; + tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + if(gbRamSize) { + gbMemoryMap[0x0a] = &gbRam[0]; + gbMemoryMap[0x0b] = &gbRam[0x1000]; + } + } break; } } @@ -102,23 +187,72 @@ } } +// MBC1 read RAM +u8 mapperMBC1ReadRAM(u16 address) +{ + + if(gbDataMBC1.mapperRAMEnable) + return gbMemoryMap[address>>12][address & 0x0fff]; + + if (!genericflashcardEnable) + return 0xff; + else + if ((address & 0x1000) >= 0x1000) + { + // The value returned when reading RAM while it's disabled + // is constant, exept for the GBASP hardware. + // (actually, is the address that read is out of the ROM, the returned value if 0xff...) + if (PC.W>=0xff80) + return 0xff; + else + if ((gbHardware & 0x08) && (gbGBCColorType == 2)) + { + if (address & 1) + return 0xfb; + else + return 0x7a; + } + else + return 0x0a; + } + else + return gbDisabledRam[address & 7]; +} + void memoryUpdateMapMBC1() { int tmpAddress = gbDataMBC1.mapperROMBank << 14; // check current model - if(gbDataMBC1.mapperMemoryModel == 1) { - // model is 16/8, so we have a high address in use - tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19; + if (gbDataMBC1.mapperRomBank0Remapping == 3) { + tmpAddress = (gbDataMBC1.mapperROMHighAddress & 3) << 18; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x00] = &gbRom[tmpAddress]; + gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; + + tmpAddress |= (gbDataMBC1.mapperROMBank & 0xf) << 14; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; } + else + { + if(gbDataMBC1.mapperMemoryModel == 0) { + // model is 16/8, so we have a high address in use + tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 19; + } - tmpAddress &= gbRomSizeMask; - gbMemoryMap[0x04] = &gbRom[tmpAddress]; - gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; - gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; - gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + } - if(gbRamSize) { + if((gbRamSize) && (gbDataMBC1.mapperMemoryModel == 1)){ gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress]; gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000]; } @@ -210,7 +344,7 @@ time_t diff = now - gbDataMBC3.mapperLastTime; if(diff > 0) { // update the clock according to the last update time - gbDataMBC3.mapperSeconds += diff % 60; + gbDataMBC3.mapperSeconds += (int)(diff % 60); if(gbDataMBC3.mapperSeconds > 59) { gbDataMBC3.mapperSeconds -= 60; gbDataMBC3.mapperMinutes++; @@ -218,22 +352,22 @@ diff /= 60; - gbDataMBC3.mapperMinutes += diff % 60; - if(gbDataMBC3.mapperMinutes > 60) { + gbDataMBC3.mapperMinutes += (int)(diff % 60); + if(gbDataMBC3.mapperMinutes > 59) { gbDataMBC3.mapperMinutes -= 60; gbDataMBC3.mapperHours++; } diff /= 60; - gbDataMBC3.mapperHours += diff % 24; - if(gbDataMBC3.mapperHours > 24) { + gbDataMBC3.mapperHours += (int)(diff % 24); + if(gbDataMBC3.mapperHours > 23) { gbDataMBC3.mapperHours -= 24; gbDataMBC3.mapperDays++; } diff /= 24; - gbDataMBC3.mapperDays += diff; + gbDataMBC3.mapperDays += (int)(diff & 0xffffffff); if(gbDataMBC3.mapperDays > 255) { if(gbDataMBC3.mapperDays > 511) { gbDataMBC3.mapperDays %= 512; @@ -365,7 +499,30 @@ return gbDataMBC3.mapperLControl; } } - return 0; + + if (!genericflashcardEnable) + return 0xff; + else + if ((address & 0x1000) >= 0x1000) + { + // The value returned when reading RAM while it's disabled + // is constant, exept for the GBASP hardware. + // (actually, is the address that read is out of the ROM, the returned value if 0xff...) + if (PC.W>=0xff80) + return 0xff; + else + if ((gbHardware & 0x08) && (gbGBCColorType == 2)) + { + if (address & 1) + return 0xfb; + else + return 0x7a; + } + else + return 0x0a; + } + else + return gbDisabledRam[address & 7]; } void memoryUpdateMapMBC3() @@ -406,6 +563,7 @@ gbDataMBC5.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); break; case 0x2000: // ROM bank select + if(address < 0x3000) { value = value & 0xff; if(value == gbDataMBC5.mapperROMBank) @@ -466,6 +624,38 @@ } } +// MBC5 read RAM +u8 mapperMBC5ReadRAM(u16 address) +{ + + if(gbDataMBC5.mapperRAMEnable) + return gbMemoryMap[address>>12][address & 0x0fff]; + + if (!genericflashcardEnable) + return 0xff; + else + if ((address & 0x1000) >= 0x1000) + { + // The value returned when reading RAM while it's disabled + // is constant, exept for the GBASP hardware. + // (actually, is the address that read is out of the ROM, the returned value if 0xff...) + if (PC.W>=0xff80) + return 0xff; + else + if ((gbHardware & 0x08) && (gbGBCColorType == 2)) + { + if (address & 1) + return 0xfb; + else + return 0x7a; + } + else + return 0x0a; + } + else + return gbDisabledRam[address & 7]; +} + void memoryUpdateMapMBC5() { int tmpAddress = (gbDataMBC5.mapperROMBank << 14) | @@ -568,7 +758,30 @@ case 0xa080: return gbDataMBC7.value; } - return 0xff; + + if (!genericflashcardEnable) + return 0xff; + else + if ((address & 0x1000) >= 0x1000) + { + // The value returned when reading RAM while it's disabled + // is constant, exept for the GBASP hardware. + // (actually, is the address that read is out of the ROM, the returned value if 0xff...) + if (PC.W>=0xff80) + return 0xff; + else + if ((gbHardware & 0x08) && (gbGBCColorType == 2)) + { + if (address & 1) + return 0xfb; + else + return 0x7a; + } + else + return 0x0a; + } + else + return gbDisabledRam[address & 7]; } // MBC7 RAM write @@ -717,7 +930,7 @@ void memoryUpdateMapMBC7() { - int tmpAddress = (gbDataMBC5.mapperROMBank << 14); + int tmpAddress = (gbDataMBC7.mapperROMBank << 14); tmpAddress &= gbRomSizeMask; gbMemoryMap[0x04] = &gbRom[tmpAddress]; @@ -965,3 +1178,540 @@ gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; } } + +// TAMA5 (for Tamagotchi 3 (gb)). +// Very basic (and ugly :p) support, only rom bank switching is actually working... +mapperTAMA5 gbDataTAMA5 = { + 1, // RAM enable + 1, // ROM bank + 0, // RAM bank + 0, // RAM address + 0, // RAM Byte select + 0, // mapper command number + 0, // mapper last command; + 0, // commands 0x0 + 0, // commands 0x1 + 0, // commands 0x2 + 0, // commands 0x3 + 0, // commands 0x4 + 0, // commands 0x5 + 0, // commands 0x6 + 0, // commands 0x7 + 0, // commands 0x8 + 0, // commands 0x9 + 0, // commands 0xa + 0, // commands 0xb + 0, // commands 0xc + 0, // commands 0xd + 0, // commands 0xe + 0, // commands 0xf + 0, // register + 0, // timer clock latch + 0, // timer clock register + 0, // timer seconds + 0, // timer minutes + 0, // timer hours + 0, // timer days + 0, // timer months + 0, // timer years + 0, // timer control + 0, // timer latched seconds + 0, // timer latched minutes + 0, // timer latched hours + 0, // timer latched days + 0, // timer latched months + 0, // timer latched years + 0, // timer latched control + (time_t)-1 // last time +}; + + +void memoryUpdateTAMA5Clock() +{ + if ((gbDataTAMA5.mapperYears & 3) == 0) + gbDaysinMonth[1] = 29; + else + gbDaysinMonth[1] = 28; + + time_t now = time(NULL); + time_t diff = now - gbDataTAMA5.mapperLastTime; + if(diff > 0) { + // update the clock according to the last update time + gbDataTAMA5.mapperSeconds += (int)(diff % 60); + if(gbDataTAMA5.mapperSeconds > 59) { + gbDataTAMA5.mapperSeconds -= 60; + gbDataTAMA5.mapperMinutes++; + } + + diff /= 60; + + gbDataTAMA5.mapperMinutes += (int)(diff % 60); + if(gbDataTAMA5.mapperMinutes > 59) { + gbDataTAMA5.mapperMinutes -= 60; + gbDataTAMA5.mapperHours++; + } + + diff /= 60; + + gbDataTAMA5.mapperHours += (int)(diff % 24); + diff /= 24; + if(gbDataTAMA5.mapperHours > 23) { + gbDataTAMA5.mapperHours -= 24; + diff++; + + } + + time_t days = diff; + while (days) + { + gbDataTAMA5.mapperDays++; + days--; + if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1]) + { + gbDataTAMA5.mapperDays = 1; + gbDataTAMA5.mapperMonths++; + if (gbDataTAMA5.mapperMonths>12) + { + gbDataTAMA5.mapperMonths = 1; + gbDataTAMA5.mapperYears++; + if ((gbDataTAMA5.mapperYears & 3) == 0) + gbDaysinMonth[1] = 29; + else + gbDaysinMonth[1] = 28; + } + } + } + } + gbDataTAMA5.mapperLastTime = now; + +} + + + +// TAMA5 RAM write +void mapperTAMA5RAM(u16 address, u8 value) +{ + if ((address & 0xffff) <= 0xa001) + { + switch (address & 1) + { + case 0: // 'Values' Register + { + value &= 0xf; + gbDataTAMA5.mapperCommands[gbDataTAMA5.mapperCommandNumber] = value; + gbMemoryMap[0xa][0] = value; + + int test = gbDataTAMA5.mapperCommands[gbDataTAMA5.mapperCommandNumber & 0x0e] | + (gbDataTAMA5.mapperCommands[(gbDataTAMA5.mapperCommandNumber & 0x0e) +1]<<4); + + if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 0) // Read Command !!! + { + gbDataTAMA5.mapperROMBank = gbDataTAMA5.mapperCommands[0] | + (gbDataTAMA5.mapperCommands[1]<<4); + + int tmpAddress = (gbDataTAMA5.mapperROMBank << 14); + + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + + gbDataTAMA5.mapperCommands[0x0f] = 0; + } + else if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 4) + { + gbDataTAMA5.mapperCommands[0x0f] = 1; + if (gbDataTAMA5.mapperCommandNumber == 4) + gbDataTAMA5.mapperCommands[5] =0; // correct ? + } + else if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 6) + { + gbDataTAMA5.mapperRamByteSelect = (gbDataTAMA5.mapperCommands[7]<<4) | + (gbDataTAMA5.mapperCommands[6]&0x0f); + + // Write Commands !!! + if (gbDataTAMA5.mapperCommands[0x0f] && (gbDataTAMA5.mapperCommandNumber == 7)) + { + int data = gbDataTAMA5.mapperCommands[0x04] & 0x0f | + (gbDataTAMA5.mapperCommands[0x05] <<4); + + // Not sure when the write command should reset... + // but it doesn't seem to matter. + // gbDataTAMA5.mapperCommands[0x0f] = 0; + + if (gbDataTAMA5.mapperRamByteSelect == 0x8) // Timer stuff + { + switch (data & 0xf) + { + case 0x7: + gbDataTAMA5.mapperDays = ((gbDataTAMA5.mapperDays)/10)*10 + (data >> 4); + break; + case 0x8: + gbDataTAMA5.mapperDays = (gbDataTAMA5.mapperDays%10) + (data >>4)*10; + break; + case 0x9: + gbDataTAMA5.mapperMonths = ((gbDataTAMA5.mapperMonths)/10)*10 + (data >> 4); + break; + case 0xa: + gbDataTAMA5.mapperMonths = (gbDataTAMA5.mapperMonths%10) + (data >>4)*10; + break; + case 0xb: + gbDataTAMA5.mapperYears = ((gbDataTAMA5.mapperYears)%1000) + (data >> 4)*1000; + break; + case 0xc: + gbDataTAMA5.mapperYears = (gbDataTAMA5.mapperYears%100) + (gbDataTAMA5.mapperYears/1000)*1000 + + (data >>4)*100; + break; + default : + break; + } + } + else if (gbDataTAMA5.mapperRamByteSelect == 0x18) // Timer stuff again + { + memoryUpdateTAMA5Clock(); + gbDataTAMA5.mapperLSeconds = gbDataTAMA5.mapperSeconds; + gbDataTAMA5.mapperLMinutes = gbDataTAMA5.mapperMinutes; + gbDataTAMA5.mapperLHours = gbDataTAMA5.mapperHours; + gbDataTAMA5.mapperLDays = gbDataTAMA5.mapperDays; + gbDataTAMA5.mapperLMonths = gbDataTAMA5.mapperMonths; + gbDataTAMA5.mapperLYears = gbDataTAMA5.mapperYears; + gbDataTAMA5.mapperLControl = gbDataTAMA5.mapperControl; + + int seconds = (gbDataTAMA5.mapperLSeconds / 10)*16 + gbDataTAMA5.mapperLSeconds %10; + int secondsL = (gbDataTAMA5.mapperLSeconds % 10); + int secondsH = (gbDataTAMA5.mapperLSeconds / 10); + int minutes = (gbDataTAMA5.mapperLMinutes / 10)*16 + gbDataTAMA5.mapperLMinutes %10; + int hours = (gbDataTAMA5.mapperLHours / 10)*16 + gbDataTAMA5.mapperLHours %10; + int DaysL = gbDataTAMA5.mapperLDays % 10; + int DaysH = gbDataTAMA5.mapperLDays /10; + int MonthsL = gbDataTAMA5.mapperLMonths % 10; + int MonthsH = gbDataTAMA5.mapperLMonths / 10; + int Years3 = (gbDataTAMA5.mapperLYears / 100) % 10; + int Years4 = (gbDataTAMA5.mapperLYears / 1000); + + switch (data & 0x0f) + { + // I guess cases 0 and 1 are used for secondsL and secondsH + // so the game would update the timer values on screen when + // the seconds reset to 0... ? + case 0x0: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = secondsL; + break; + case 0x1: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = secondsH; + break; + case 0x7: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = DaysL; // days low + break; + case 0x8: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = DaysH; // days high + break; + case 0x9: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = MonthsL; // month low + break; + case 0xa: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = MonthsH; // month high + break; + case 0xb: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = Years4; // years 4th digit + break; + case 0xc: + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = Years3; // years 3rd digit + break; + default : + break; + } + + gbTAMA5ram[0x54] = seconds; // incorrect ? (not used by the game) ? + gbTAMA5ram[0x64] = minutes; + gbTAMA5ram[0x74] = hours; + gbTAMA5ram[0x84] = DaysH*16+DaysL; // incorrect ? (not used by the game) ? + gbTAMA5ram[0x94] = MonthsH*16+MonthsL; // incorrect ? (not used by the game) ? + + time(&gbDataTAMA5.mapperLastTime); + + gbMemoryMap[0xa][0] = 1; + } + else if (gbDataTAMA5.mapperRamByteSelect == 0x28) // Timer stuff again + { + if ((data & 0xf) == 0xb) + gbDataTAMA5.mapperYears = ((gbDataTAMA5.mapperYears>>2)<<2) + (data & 3); + } + else if (gbDataTAMA5.mapperRamByteSelect == 0x44) + { + gbDataTAMA5.mapperMinutes = (data/16)*10 + data%16; + } + else if (gbDataTAMA5.mapperRamByteSelect == 0x54) + { + gbDataTAMA5.mapperHours = (data/16)*10 + data%16; + } + else + { + gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = data; + } + } + } + } + break; + case 1: // 'Commands' Register + { + gbMemoryMap[0xa][1] = gbDataTAMA5.mapperCommandNumber = value; + + // This should be only a 'is the flashrom ready ?' command. + // However as I couldn't find any 'copy' command + // (that seems to be needed for the saving system to work) + // I put it there... + if (value == 0x0a) + { + for (int i = 0; i<0x10; i++) + for (int j = 0; j<0x10; j++) + if (!(j&2)) + gbTAMA5ram[(i*0x10)+j | 2] = gbTAMA5ram[(i*0x10)+j]; + // Enable this to see the content of the flashrom in 0xe000 + /*for (int k = 0; k<0x100; k++) + gbMemoryMap[0xe][k] = gbTAMA5ram[k];*/ + + gbMemoryMap[0xa][0] = gbDataTAMA5.mapperRAMEnable = 1; + } + else + { + if ((value & 0x0e) == 0x0c) + { + gbDataTAMA5.mapperRamByteSelect = gbDataTAMA5.mapperCommands[6] | + (gbDataTAMA5.mapperCommands[7]<<4); + + u8 byte = gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect]; + + gbMemoryMap[0xa][0] = (value & 1) ? byte >> 4 : byte & 0x0f; + + gbDataTAMA5.mapperCommands[0x0f] = 0; + } + } + break; + } + } + } + else + { + if(gbDataTAMA5.mapperRAMEnable) { + if(gbDataTAMA5.mapperRAMBank != -1) { + if(gbRamSize) { + gbMemoryMap[address>>12][address & 0x0fff] = value; + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; + } + } + } + } +} + + +// TAMA5 read RAM +u8 mapperTAMA5ReadRAM(u16 address) +{ + return gbMemoryMap[address>>12][address & 0xfff]; +} + + +void memoryUpdateMapTAMA5() +{ + int tmpAddress = (gbDataTAMA5.mapperROMBank << 14); + + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + + if(gbRamSize) { + tmpAddress = 0 << 13; + tmpAddress &= gbRamSizeMask; + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; + } +} + +// MMM01 Used in Momotarou collection (however the rom is corrupted) +mapperMMM01 gbDataMMM01 ={ + 0, // RAM enable + 1, // ROM bank + 0, // RAM bank + 0, // memory model + 0, // ROM high address + 0, // RAM address + 0 // Rom Bank 0 remapping +}; + +// MMM01 ROM write registers +void mapperMMM01ROM(u16 address, u8 value) +{ + int tmpAddress = 0; + + switch(address & 0x6000) { + case 0x0000: // RAM enable register + gbDataMMM01.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0); + break; + case 0x2000: // ROM bank select + // value = value & 0x1f; + if(value == 0) + value = 1; + if(value == gbDataMMM01.mapperROMBank) + break; + + tmpAddress = value << 14; + + // check current model + if(gbDataMMM01.mapperMemoryModel == 0) { + // model is 16/8, so we have a high address in use + tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19; + } + else + tmpAddress |= gbDataMMM01.mapperRomBank0Remapping << 18; + + tmpAddress &= gbRomSizeMask; + gbDataMMM01.mapperROMBank = value; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + break; + case 0x4000: // RAM bank select + if(gbDataMMM01.mapperMemoryModel == 1) { + // 4/32 model, RAM bank switching provided + value = value & 0x03; + if(value == gbDataMBC1.mapperRAMBank) + break; + tmpAddress = value << 13; + tmpAddress &= gbRamSizeMask; + gbMemoryMap[0x0a] = &gbRam[tmpAddress]; + gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000]; + gbDataMMM01.mapperRAMBank = value; + gbDataMMM01.mapperRAMAddress = tmpAddress; + } else { + // 16/8, set the high address + gbDataMMM01.mapperROMHighAddress = value & 0x03; + tmpAddress = gbDataMMM01.mapperROMBank << 14; + tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + + gbDataMMM01.mapperRomBank0Remapping = ((value<<1) | (value & 0x40 ? 1 : 0)) & 0xff; + tmpAddress = gbDataMMM01.mapperRomBank0Remapping << 18; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x00] = &gbRom[tmpAddress]; + gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; + } + break; + case 0x6000: // memory model select + gbDataMMM01.mapperMemoryModel = value & 1; + break; + } +} + +// MMM01 RAM write +void mapperMMM01RAM(u16 address, u8 value) +{ + if(gbDataMMM01.mapperRAMEnable) { + if(gbRamSize) { + gbMemoryMap[address >> 12][address & 0x0fff] = value; + systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED; + } + } +} + +void memoryUpdateMapMMM01() +{ + int tmpAddress = gbDataMMM01.mapperROMBank << 14; + + // check current model + if(gbDataMMM01.mapperMemoryModel == 1) { + // model is 16/8, so we have a high address in use + tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19; + } + + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000]; + + tmpAddress = gbDataMMM01.mapperRomBank0Remapping << 18; + tmpAddress &= gbRomSizeMask; + gbMemoryMap[0x00] = &gbRom[tmpAddress]; + gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000]; + gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000]; + gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000]; + + if(gbRamSize) { + gbMemoryMap[0x0a] = &gbRam[gbDataMMM01.mapperRAMAddress]; + gbMemoryMap[0x0b] = &gbRam[gbDataMMM01.mapperRAMAddress + 0x1000]; + } +} + +// GameGenie ROM write registers +void mapperGGROM(u16 address, u8 value) +{ + int tmpAddress = 0; + + switch(address & 0x6000) { + case 0x0000: // RAM enable register + break; + case 0x2000: // GameGenie has only a half bank + break; + case 0x4000: // GameGenie has no RAM + if ((address >=0x4001) && (address <= 0x4020)) // GG Hardware Registers + gbMemoryMap[address >> 12][address & 0x0fff] = value; + break; + case 0x6000: // GameGenie has only a half bank + break; + } +} + + +// GS3 Used to emulate the GS V3.0 rom bank switching +mapperGS3 gbDataGS3 = { 1 }; // ROM bank + +void mapperGS3ROM(u16 address, u8 value) +{ + int tmpAddress = 0; + + switch(address & 0x6000) { + case 0x0000: // GS has no ram + break; + case 0x2000: // GS has no 'classic' ROM bank select + break; + case 0x4000: // GS has no ram + break; + case 0x6000: // 0x6000 area is RW, and used for GS hardware registers + + if (address == 0x7FE1) // This is the (half) ROM bank select register + { + if(value == gbDataGS3.mapperROMBank) + break; + tmpAddress = value << 13; + + tmpAddress &= gbRomSizeMask; + gbDataGS3.mapperROMBank = value; + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; + } + else + gbMemoryMap[address>>12][address & 0x0fff] = value; + break; + } +} + +void memoryUpdateMapGS3() +{ + int tmpAddress = gbDataGS3.mapperROMBank << 13; + + tmpAddress &= gbRomSizeMask; + // GS can only change a half ROM bank + gbMemoryMap[0x04] = &gbRom[tmpAddress]; + gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000]; +} \ No newline at end of file diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbMemory.h ./src/gb/gbMemory.h --- ../VisualBoyAdvance-1.7.2/src/gb/gbMemory.h 2004-05-13 23:09:24 +0900 +++ ./src/gb/gbMemory.h 2006-06-06 23:25:43 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -26,6 +26,7 @@ int mapperMemoryModel; int mapperROMHighAddress; int mapperRAMAddress; + int mapperRomBank0Remapping; }; struct mapperMBC2 { @@ -106,15 +107,62 @@ int mapperRegister8; }; +struct mapperTAMA5 { + int mapperRAMEnable; + int mapperROMBank; + int mapperRAMBank; + int mapperRAMAddress; + int mapperRamByteSelect; + int mapperCommandNumber; + int mapperLastCommandNumber; + int mapperCommands[0x10]; + int mapperRegister; + int mapperClockLatch; + int mapperClockRegister; + int mapperSeconds; + int mapperMinutes; + int mapperHours; + int mapperDays; + int mapperMonths; + int mapperYears; + int mapperControl; + int mapperLSeconds; + int mapperLMinutes; + int mapperLHours; + int mapperLDays; + int mapperLMonths; + int mapperLYears; + int mapperLControl; + time_t mapperLastTime; +}; + +struct mapperMMM01 { + int mapperRAMEnable; + int mapperROMBank; + int mapperRAMBank; + int mapperMemoryModel; + int mapperROMHighAddress; + int mapperRAMAddress; + int mapperRomBank0Remapping; +}; + +struct mapperGS3 { + int mapperROMBank; +}; + extern mapperMBC1 gbDataMBC1; extern mapperMBC2 gbDataMBC2; extern mapperMBC3 gbDataMBC3; extern mapperMBC5 gbDataMBC5; extern mapperHuC1 gbDataHuC1; extern mapperHuC3 gbDataHuC3; +extern mapperTAMA5 gbDataTAMA5; +extern mapperMMM01 gbDataMMM01; +extern mapperGS3 gbDataGS3; void mapperMBC1ROM(u16,u8); void mapperMBC1RAM(u16,u8); +u8 mapperMBC1ReadRAM(u16); void mapperMBC2ROM(u16,u8); void mapperMBC2RAM(u16,u8); void mapperMBC3ROM(u16,u8); @@ -122,6 +170,7 @@ u8 mapperMBC3ReadRAM(u16); void mapperMBC5ROM(u16,u8); void mapperMBC5RAM(u16,u8); +u8 mapperMBC5ReadRAM(u16); void mapperMBC7ROM(u16,u8); void mapperMBC7RAM(u16,u8); u8 mapperMBC7ReadRAM(u16); @@ -130,7 +179,13 @@ void mapperHuC3ROM(u16,u8); void mapperHuC3RAM(u16,u8); u8 mapperHuC3ReadRAM(u16); - +void mapperTAMA5RAM(u16,u8); +u8 mapperTAMA5ReadRAM(u16); +void memoryUpdateTAMA5Clock(); +void mapperMMM01ROM(u16,u8); +void mapperMMM01RAM(u16,u8); +void mapperGGROM(u16,u8); +void mapperGS3ROM(u16,u8); //extern void (*mapper)(u16,u8); //extern void (*mapperRAM)(u16,u8); //extern u8 (*mapperReadRAM)(u16); @@ -142,7 +197,9 @@ extern void memoryUpdateMapMBC7(); extern void memoryUpdateMapHuC1(); extern void memoryUpdateMapHuC3(); - +extern void memoryUpdateMapTAMA5(); +extern void memoryUpdateMapMMM01(); +extern void memoryUpdateMapGS3(); diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbSGB.cpp ./src/gb/gbSGB.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/gbSGB.cpp 2004-05-14 07:27:47 +0900 +++ ./src/gb/gbSGB.cpp 2006-04-30 23:44:31 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -27,6 +27,7 @@ extern u8 *pix; extern bool speedup; +extern bool gbSgbResetFlag; #define GBSGB_NONE 0 #define GBSGB_RESET 1 @@ -96,7 +97,7 @@ gbSgbBorder[i] = 1 << 2; } - for(i = 0; i < 4; i++) { + for(i = 0; i < 32; i++) { gbPalette[i*4] = (0x1f) | (0x1f << 5) | (0x1f << 10); gbPalette[i*4+1] = (0x15) | (0x15 << 5) | (0x15 << 10); gbPalette[i*4+2] = (0x0c) | (0x0c << 5) | (0x0c << 10); @@ -255,9 +256,12 @@ yyy = 7 - yy; u16 c = gbPalette[palette + color]; - if(!color) - c = gbPalette[0]; - if((yy < 40 || yy >= 184) || (xx < 48 || xx >= 208)) { + + // Fix for Super Snaky ??? + // (it allows SGB borders to not redraw on the GB screen) + //if(!color) + // c = gbPalette[0]; + if(((yy < 40 || yy >= 184) || (xx < 48 || xx >= 208)) && (color || (gbSgbResetFlag == true))) { switch(systemColorDepth) { case 16: gbSgbDraw16Bit(dest + yyy*(256+2) + xxx, c); diff -urN ../VisualBoyAdvance-1.7.2/src/gb/gbSound.cpp ./src/gb/gbSound.cpp --- ../VisualBoyAdvance-1.7.2/src/gb/gbSound.cpp 2004-05-13 23:39:20 +0900 +++ ./src/gb/gbSound.cpp 2006-04-30 23:44:44 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -32,6 +32,7 @@ #define NOISE_MAGIC 5 extern int speed; +extern int gbHardware; extern void soundResume(); @@ -57,6 +58,9 @@ extern int sound1On; extern int sound1ATL; +int sound1ATLreload; +int freq1low; +int freq1high; extern int sound1Skip; extern int sound1Index; extern int sound1Continue; @@ -73,6 +77,9 @@ extern int sound2On; extern int sound2ATL; +int sound2ATLreload; +int freq2low; +int freq2high; extern int sound2Skip; extern int sound2Index; extern int sound2Continue; @@ -84,6 +91,9 @@ extern int sound3On; extern int sound3ATL; +int sound3ATLreload; +int freq3low; +int freq3high; extern int sound3Skip; extern int sound3Index; extern int sound3Continue; @@ -93,6 +103,8 @@ extern int sound4On; extern int sound4Clock; extern int sound4ATL; +int sound4ATLreload; +int freq4; extern int sound4Skip; extern int sound4Index; extern int sound4ShiftRight; @@ -136,14 +148,16 @@ #endif switch(address) { case NR10: + gbMemory[address] = data | 0x80; sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7); sound1SweepSteps = data & 7; sound1SweepUpDown = data & 0x08; sound1SweepStep = 0; break; case NR11: + gbMemory[address] = data | 0x3f; sound1Wave = soundWavePattern[data >> 6]; - sound1ATL = 172 * (64 - (data & 0x3f)); + sound1ATL = sound1ATLreload = 172 * (64 - (data & 0x3f)); break; case NR12: sound1EnvelopeVolume = data >> 4; @@ -151,8 +165,10 @@ sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7); break; case NR13: - freq = (((int)(gbMemory[NR14] & 7)) << 8) | data; - sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); + gbMemory[address] = 0xff; + freq1low = data; + freq = ((((int)(freq1high & 7)) << 8) | freq1low); + sound1ATL = sound1ATLreload; freq = 2048 - freq; if(freq) { sound1Skip = SOUND_MAGIC / freq; @@ -160,9 +176,11 @@ sound1Skip = 0; break; case NR14: - freq = (((int)(data&7) << 8) | gbMemory[NR13]); + gbMemory[address] = data | 0xbf; + freq1high = data; + freq = ((((int)(freq1high & 7)) << 8) | freq1low); freq = 2048 - freq; - sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); + sound1ATL = sound1ATLreload; sound1Continue = data & 0x40; if(freq) { sound1Skip = SOUND_MAGIC / freq; @@ -172,7 +190,6 @@ gbMemory[NR52] |= 1; sound1EnvelopeVolume = gbMemory[NR12] >> 4; sound1EnvelopeUpDown = gbMemory[NR12] & 0x08; - sound1ATL = 172 * (64 - (gbMemory[NR11] & 0x3f)); sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7); sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7); sound1SweepSteps = gbMemory[NR10] & 7; @@ -184,8 +201,9 @@ } break; case NR21: + gbMemory[address] = data | 0x3f; sound2Wave = soundWavePattern[data >> 6]; - sound2ATL = 172 * (64 - (data & 0x3f)); + sound2ATL = sound2ATLreload = 172 * (64 - (data & 0x3f)); break; case NR22: sound2EnvelopeVolume = data >> 4; @@ -193,8 +211,10 @@ sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7); break; case NR23: - freq = (((int)(gbMemory[NR24] & 7)) << 8) | data; - sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); + gbMemory[address] = 0xff; + freq2low = data; + freq = (((int)(freq2high & 7)) << 8) | freq2low; + sound2ATL = sound2ATLreload; freq = 2048 - freq; if(freq) { sound2Skip = SOUND_MAGIC / freq; @@ -202,9 +222,11 @@ sound2Skip = 0; break; case NR24: - freq = (((int)(data&7) << 8) | gbMemory[NR23]); + gbMemory[address] = data | 0xbf; + freq2high = data; + freq = (((int)(freq2high & 7)) << 8) | freq2low; freq = 2048 - freq; - sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); + sound2ATL = sound2ATLreload; sound2Continue = data & 0x40; if(freq) { sound2Skip = SOUND_MAGIC / freq; @@ -214,7 +236,7 @@ gbMemory[NR52] |= 2; sound2EnvelopeVolume = gbMemory[NR22] >> 4; sound2EnvelopeUpDown = gbMemory[NR22] & 0x08; - sound2ATL = 172 * (64 - (gbMemory[NR21] & 0x3f)); + sound2ATL = sound2ATLreload; sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7); sound2Index = 0; @@ -222,26 +244,33 @@ } break; case NR30: + gbMemory[address] = data | 0x7f; if(!(data & 0x80)) { gbMemory[NR52] &= 0xfb; sound3On = 0; } break; case NR31: - sound3ATL = 172 * (256-data); + gbMemory[address] = 0xff; + sound3ATL = sound3ATLreload = 172 * (256-data); break; case NR32: + gbMemory[address] = data | 0x9f; sound3OutputLevel = (data >> 5) & 3; break; case NR33: - freq = 2048 - (((int)(gbMemory[NR34]&7) << 8) | data); + gbMemory[address] = 0xff; + freq3low = data; + freq = 2048 - (((int)(freq3high&7) << 8) | freq3low); if(freq) { sound3Skip = SOUND_MAGIC_2 / freq; } else sound3Skip = 0; break; case NR34: - freq = 2048 - (((data &7) << 8) | (int)gbMemory[NR33]); + gbMemory[address] = data | 0xbf; + freq3high = data; + freq = 2048 - (((int)(freq3high&7) << 8) | freq3low); if(freq) { sound3Skip = SOUND_MAGIC_2 / freq; } else { @@ -250,13 +279,13 @@ sound3Continue = data & 0x40; if((data & 0x80) && (gbMemory[NR30] & 0x80)) { gbMemory[NR52] |= 4; - sound3ATL = 172 * (256 - gbMemory[NR31]); + sound3ATL = sound3ATLreload; sound3Index = 0; sound3On = 1; } break; case NR41: - sound4ATL = 172 * (64 - (data & 0x3f)); + sound4ATL = sound4ATLreload = 172 * (64 - (data & 0x3f)); break; case NR42: sound4EnvelopeVolume = data >> 4; @@ -264,7 +293,7 @@ sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7); break; case NR43: - freq = soundFreqRatio[data & 7]; + freq = freq4 = soundFreqRatio[data & 7]; sound4NSteps = data & 0x08; sound4Skip = (freq << 8) / NOISE_MAGIC; @@ -277,12 +306,13 @@ break; case NR44: + gbMemory[address] = data | 0xbf; sound4Continue = data & 0x40; if(data & 0x80) { gbMemory[NR52] |= 8; sound4EnvelopeVolume = gbMemory[NR42] >> 4; sound4EnvelopeUpDown = gbMemory[NR42] & 0x08; - sound4ATL = 172 * (64 - (gbMemory[NR41] & 0x3f)); + sound4ATL = sound4ATLreload; sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7); sound4On = 1; @@ -290,15 +320,6 @@ sound4Index = 0; sound4ShiftIndex = 0; - freq = soundFreqRatio[gbMemory[NR43] & 7]; - - sound4Skip = (freq << 8) / NOISE_MAGIC; - - sound4NSteps = gbMemory[NR43] & 0x08; - - freq = freq / soundShiftClock[gbMemory[NR43] >> 4]; - - sound4ShiftSkip = (freq << 8) / NOISE_MAGIC; if(sound4NSteps) sound4ShiftRight = 0x7fff; else @@ -320,7 +341,9 @@ sound2On = 0; sound3On = 0; sound4On = 0; + gbMemory[address] &= 0xf0; } + gbMemory[address] = data & 0x80 | 0x70 | (gbMemory[address] & 0xf); break; } @@ -384,7 +407,7 @@ sound1SweepATL-=soundQuality; if(sound1SweepATL<=0) { - freq = (((int)(gbMemory[NR14]&7) << 8) | gbMemory[NR13]); + freq = (((int)(freq1high & 7)) << 8) | freq1low; int updown = 1; @@ -409,8 +432,8 @@ sound1SweepATL += sound1SweepATLReload; sound1Skip = SOUND_MAGIC/(2048 - newfreq); - gbMemory[NR13] = newfreq & 0xff; - gbMemory[NR14] = (gbMemory[NR14] & 0xf8) |((newfreq >> 8) & 7); + freq1low = newfreq & 0xff; + freq1high = (freq1high & 0xf8) |((newfreq >> 8) & 7); } } } @@ -462,9 +485,12 @@ void gbSoundChannel3() { - int value = sound3Last; + int value = 0; if(sound3On && (sound3ATL || !sound3Continue)) { + + value = sound3Last; + sound3Index += soundQuality*sound3Skip; sound3Index &= 0x1fffffff; @@ -552,7 +578,7 @@ sound4ATL-=soundQuality; if(sound4ATL <= 0 && sound4Continue) { - gbMemory[NR52] &= 0xfd; + gbMemory[NR52] &= 0xf7; sound4On = 0; } } @@ -592,7 +618,7 @@ } if(gbDigitalSound) - res = soundLevel1*256; + res *= soundLevel1*256; else res *= soundLevel1*60; @@ -654,7 +680,7 @@ } if(gbDigitalSound) - res = soundLevel2*256; + res *= soundLevel2*256; else res *= soundLevel2*60; @@ -822,7 +848,10 @@ gbSoundEvent(0xff24, 0x77); gbSoundEvent(0xff25, 0xf3); - gbSoundEvent(0xff26, 0xf0); + if (gbHardware & 0x4) + gbSoundEvent(0xff26, 0xf0); + else + gbSoundEvent(0xff26, 0xf1); // don't translate if(soundDebug) { @@ -934,6 +963,18 @@ { utilWriteData(gzFile, gbSoundSaveStruct); + utilWriteInt(gzFile, sound1ATLreload); + utilWriteInt(gzFile, freq1low); + utilWriteInt(gzFile, freq1high); + utilWriteInt(gzFile, sound2ATLreload); + utilWriteInt(gzFile, freq2low); + utilWriteInt(gzFile, freq2high); + utilWriteInt(gzFile, sound3ATLreload); + utilWriteInt(gzFile, freq3low); + utilWriteInt(gzFile, freq3high); + utilWriteInt(gzFile, sound4ATLreload); + utilWriteInt(gzFile, freq4); + utilGzWrite(gzFile, soundBuffer, 4*735); utilGzWrite(gzFile, soundFinalWave, 2*735); utilGzWrite(gzFile, &soundQuality, sizeof(int)); @@ -943,6 +984,35 @@ { utilReadData(gzFile, gbSoundSaveStruct); + if (version<11) + { + sound1ATLreload = 172 * (64 - (gbMemory[NR11] & 0x3f)); + freq1low = gbMemory[NR13]; + freq1high = gbMemory[NR14] & 7; + sound2ATLreload = 172 * (64 - (gbMemory[NR21] & 0x3f)); + freq2low = gbMemory[NR23]; + freq2high = gbMemory[NR24] & 7; + sound3ATLreload = 172 * (256 - gbMemory[NR31]); + freq3low = gbMemory[NR33]; + freq3high = gbMemory[NR34] & 7; + sound4ATLreload = 172 * (64 - (gbMemory[NR41] & 0x3f)); + freq4 = soundFreqRatio[gbMemory[NR43] & 7]; + } + else + { + sound1ATLreload = utilReadInt(gzFile); + freq1low = utilReadInt(gzFile); + freq1high = utilReadInt(gzFile); + sound2ATLreload = utilReadInt(gzFile); + freq2low = utilReadInt(gzFile); + freq2high = utilReadInt(gzFile); + sound3ATLreload = utilReadInt(gzFile); + freq3low = utilReadInt(gzFile); + freq3high = utilReadInt(gzFile); + sound4ATLreload = utilReadInt(gzFile); + freq4 = utilReadInt(gzFile); + } + soundBufferIndex = soundIndex * 2; utilGzRead(gzFile, soundBuffer, 4*735); diff -urN ../VisualBoyAdvance-1.7.2/src/gtk/Makefile.in ./src/gtk/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/gtk/Makefile.in 2004-05-14 06:44:28 +0900 +++ ./src/gtk/Makefile.in 2004-09-30 07:23:40 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/gtk/images/Makefile.in ./src/gtk/images/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/gtk/images/Makefile.in 2004-05-14 06:40:58 +0900 +++ ./src/gtk/images/Makefile.in 2004-09-30 07:23:39 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/gtk/main.cpp ./src/gtk/main.cpp --- ../VisualBoyAdvance-1.7.2/src/gtk/main.cpp 2004-05-22 01:02:35 +0900 +++ ./src/gtk/main.cpp 2004-09-30 05:34:18 +0900 @@ -22,10 +22,10 @@ #include -#include #include #include #include +#include #include "images/vba-wm-pixbufs.h" diff -urN ../VisualBoyAdvance-1.7.2/src/gtk/system.cpp ./src/gtk/system.cpp --- ../VisualBoyAdvance-1.7.2/src/gtk/system.cpp 2004-05-06 17:26:00 +0900 +++ ./src/gtk/system.cpp 2006-09-04 06:52:25 +0900 @@ -338,6 +338,10 @@ { } +void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value, int size, int t) +{ +} + void (*dbgMain)() = debuggerMain; void (*dbgSignal)(int, int) = debuggerSignal; void (*dbgOutput)(char *, u32) = debuggerOutput; diff -urN ../VisualBoyAdvance-1.7.2/src/gtk/window.cpp ./src/gtk/window.cpp --- ../VisualBoyAdvance-1.7.2/src/gtk/window.cpp 2004-05-21 22:27:07 +0900 +++ ./src/gtk/window.cpp 2004-09-16 07:12:53 +0900 @@ -909,15 +909,9 @@ for (int i = 0; i < 0x10000; i++) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN systemColorMap32[i] = (((i & 0x1f) << systemRedShift) | (((i & 0x3e0) >> 5) << systemGreenShift) | (((i & 0x7c00) >> 10) << systemBlueShift)); -#else - systemColorMap32[i] = (((i & 0x1f) << systemRedShift) - | (((i & 0x3e0) >> 5) << systemGreenShift) - | (((i & 0x7c00) >> 10) << systemBlueShift)); -#endif } gbFrameSkip = 0; diff -urN ../VisualBoyAdvance-1.7.2/src/gtk/window.h ./src/gtk/window.h --- ../VisualBoyAdvance-1.7.2/src/gtk/window.h 2004-05-21 22:25:41 +0900 +++ ./src/gtk/window.h 2004-09-30 05:34:18 +0900 @@ -23,8 +23,8 @@ #include #include -#include #include +#include #ifndef GTKMM20 # include "sigccompat.h" diff -urN ../VisualBoyAdvance-1.7.2/src/hq2x.cpp ./src/hq2x.cpp --- ../VisualBoyAdvance-1.7.2/src/hq2x.cpp 2004-01-21 07:02:03 +0900 +++ ./src/hq2x.cpp 2004-12-19 08:09:56 +0900 @@ -559,7 +559,7 @@ while(count) { dst0 += dstPitch; dst1 += dstPitch; - hq2x_16_def(dst0, dst1, src0, src1, src2, width); + lq2x_16_def(dst0, dst1, src0, src1, src2, width); src0 = src1; src1 = src2; src2 += srcPitch >> 1; @@ -587,7 +587,7 @@ while(count) { dst0 += dstPitch >> 1; dst1 += dstPitch >> 1; - hq2x_32_def(dst0, dst1, src0, src1, src2, width); + lq2x_32_def(dst0, dst1, src0, src1, src2, width); src0 = src1; src1 = src2; src2 += srcPitch >> 2; diff -urN ../VisualBoyAdvance-1.7.2/src/i386/2xSaImmx.asm ./src/i386/2xSaImmx.asm --- ../VisualBoyAdvance-1.7.2/src/i386/2xSaImmx.asm 2003-11-04 23:08:22 +0900 +++ ./src/i386/2xSaImmx.asm 2006-06-20 20:35:21 +0900 @@ -1,40 +1,38 @@ ;/*---------------------------------------------------------------------* ; * The following (piece of) code, (part of) the 2xSaI engine, * -; * copyright (c) 1999 - 2001 by Derek Liauw Kie Fa. * -; * Non-Commercial use of this software is allowed and is encouraged, * -; * provided that appropriate credit be given. * +; * copyright (c) 2001 by Derek Liauw Kie Fa. * +; * Non-Commercial use of the engine is allowed and is encouraged, * +; * provided that appropriate credit be given and that this copyright * +; * notice will not be removed under any circumstance. * ; * You may freely modify this code, but I request * ; * that any improvements to the engine be submitted to me, so * ; * that I can implement these improvements in newer versions of * -; * the software. * +; * the engine. * ; * If you need more information, have any comments or suggestions, * -; * you can e-mail me. My e-mail: derek-liauw@usa.net. * +; * you can e-mail me. My e-mail: DerekL666@yahoo.com * ; *---------------------------------------------------------------------*/ +; modified by Spacy to compile with yasm [2006-06-20] ;---------------------- -; 2xSaI version 0.59 WIP, soon to become version 0.60 +; 2xSaI, Super2xSaI, SuperEagle .. FINAL. no versioning anymore.. ;---------------------- -;%define FAR_POINTER - - - - BITS 32 + BITS 32 %ifdef __DJGPP__ GLOBAL __2xSaILine GLOBAL __2xSaISuperEagleLine - GLOBAL __2xSaISuper2xSaILine + GLOBAL __2xSaISuper2xSaILine GLOBAL _Init_2xSaIMMX %else GLOBAL _2xSaILine GLOBAL _2xSaISuperEagleLine - GLOBAL _2xSaISuper2xSaILine + GLOBAL _2xSaISuper2xSaILine GLOBAL Init_2xSaIMMX %endif - SECTION .text ALIGN = 32 + SECTION .text ALIGN = 32 -%ifdef FAR_POINTER -;EXTERN_C void _2xSaILine (uint8 *srcPtr, uint32 srcPitch, uint32 width, +%ifdef __DJGPP__ +;EXTERN_C void __2xSaILine (uint8 *srcPtr, uint32 srcPitch, uint32 width, ; uint8 *dstPtr, uint32 dstPitch, uint16 dstSegment); %else ;EXTERN_C void _2xSaILine (uint8 *srcPtr, uint32 srcPitch, uint32 width, @@ -50,8 +48,6 @@ dstSegment equ 32 - - colorB0 equ -2 colorB1 equ 0 colorB2 equ 2 @@ -79,18 +75,23 @@ + + + + + %ifdef __DJGPP__ __2xSaISuper2xSaILine: %else -_2xSaISuper2xSaILine: +NEWSYM _2xSaISuper2xSaILine %endif ; Store some stuff - push ebp - mov ebp, esp + push ebp + mov ebp, esp pushad ; Prepare the destination -%ifdef FAR_POINTER +%ifdef __DJGPP__ ; Set the selector mov eax, [ebp+dstSegment] mov fs, ax @@ -98,11 +99,11 @@ mov edx, [ebp+dstOffset] ; edx points to the screen ; Prepare the source ; eax points to colorA - mov eax, [ebp+srcPtr] ;eax points to colorA - mov ebx, [ebp+srcPitch] ;ebx contains the source pitch - mov ecx, [ebp+width] ;ecx contains the number of pixels to process + mov eax, [ebp+srcPtr] ;eax points to colorA + mov ebx, [ebp+srcPitch] ;ebx contains the source pitch + mov ecx, [ebp+width] ;ecx contains the number of pixels to process ; eax now points to colorB1 - sub eax, ebx ;eax points to B1 which is the base + sub eax, ebx ;eax points to B1 which is the base ; Main Loop .Loop: push ecx @@ -111,7 +112,7 @@ mov ecx, [ebp+deltaPtr] - ;load source img + ;load source img movq mm0, [eax+colorB0] movq mm1, [eax+colorB3] movq mm2, [eax+ebx+color4] @@ -124,7 +125,7 @@ movq mm7, [eax+ebx+ebx+colorA3] pop eax - ;compare to delta + ;compare to delta pcmpeqw mm0, [ecx+2+colorB0] pcmpeqw mm1, [ecx+2+colorB3] pcmpeqw mm2, [ecx+ebx+2+color4] @@ -137,7 +138,7 @@ sub ecx, ebx - ;compose results + ;compose results pand mm0, mm1 pand mm2, mm3 pand mm4, mm5 @@ -147,14 +148,14 @@ pxor mm7, mm7 pand mm0, mm4 movq mm6, [eax+colorB0] - pcmpeqw mm7, mm0 ;did any compare give us a zero ? + pcmpeqw mm7, mm0 ;did any compare give us a zero ? movq [ecx+2+colorB0], mm6 packsswb mm7, mm7 movd ecx, mm7 - test ecx, ecx - jz near .SKIP_PROCESS ;no, so we can skip + test ecx, ecx + jz near .SKIP_PROCESS ;no, so we can skip ;End Delta @@ -432,15 +433,15 @@ pcmpgtw mm0, mm1 por mm7, [Mask35] - por mm0, [Mask26] + por mm0, [Mask26] movq [Mask35], mm7 movq [Mask26], mm0 .SKIP_GUESS: - ;Start the ASSEMBLY !!! eh... compose all the results together to form the final image... + ;Start the ASSEMBLY !!! eh... compose all the results together to form the final image... - + movq mm0, [eax+ebx+color5] movq mm1, [eax+ebx+ebx+color2] movq mm2, mm0 @@ -459,7 +460,7 @@ pand mm3, mm2 paddw mm0, mm3 ;mm0 contains the interpolated values - ;--------------------------- + ;--------------------------- @@ -484,102 +485,102 @@ %endif - movq mm7, [Mask26] - movq mm6, [eax+colorB2] - movq mm5, [eax+ebx+ebx+color2] - movq mm4, [eax+ebx+ebx+color1] - pcmpeqw mm4, mm5 - pcmpeqw mm6, mm5 - pxor mm5, mm5 - pand mm7, mm4 - pcmpeqw mm6, mm5 - pand mm7, mm6 - - - - movq mm6, [eax+ebx+ebx+color3] - movq mm5, [eax+ebx+ebx+color2] - movq mm4, [eax+ebx+ebx+color1] - movq mm2, [eax+ebx+color5] - movq mm1, [eax+ebx+color4] - movq mm3, [eax+colorB0] - - pcmpeqw mm2, mm4 - pcmpeqw mm6, mm5 - pcmpeqw mm1, mm5 - pcmpeqw mm3, mm5 - pxor mm5, mm5 - pcmpeqw mm2, mm5 - pcmpeqw mm3, mm5 - pand mm6, mm1 - pand mm2, mm3 - pand mm6, mm2 - por mm7, mm6 - - - movq mm6, mm7 - pcmpeqw mm6, mm5 - pand mm7, mm0 - - movq mm1, [eax+ebx+color5] - pand mm6, mm1 - por mm7, mm6 - movq [final1a], mm7 ;finished 1a - - - - ;-------------------------------- - - movq mm7, [Mask35] - push eax - add eax, ebx - movq mm6, [eax+ebx+ebx+colorA2] - pop eax - movq mm5, [eax+ebx+color5] - movq mm4, [eax+ebx+color4] - pcmpeqw mm4, mm5 - pcmpeqw mm6, mm5 - pxor mm5, mm5 - pand mm7, mm4 - pcmpeqw mm6, mm5 - pand mm7, mm6 - - - - movq mm6, [eax+ebx+color6] - movq mm5, [eax+ebx+color5] - movq mm4, [eax+ebx+color4] - movq mm2, [eax+ebx+ebx+color2] - movq mm1, [eax+ebx+ebx+color1] - push eax - add eax, ebx - movq mm3, [eax+ebx+ebx+colorA0] - pop eax - - pcmpeqw mm2, mm4 - pcmpeqw mm6, mm5 - pcmpeqw mm1, mm5 - pcmpeqw mm3, mm5 - pxor mm5, mm5 - pcmpeqw mm2, mm5 - pcmpeqw mm3, mm5 - pand mm6, mm1 - pand mm2, mm3 - pand mm6, mm2 - por mm7, mm6 - - - movq mm6, mm7 - pcmpeqw mm6, mm5 - pand mm7, mm0 - - movq mm1, [eax+ebx+ebx+color2] - pand mm6, mm1 - por mm7, mm6 - movq [final2a], mm7 ;finished 2a + movq mm7, [Mask26] + movq mm6, [eax+colorB2] + movq mm5, [eax+ebx+ebx+color2] + movq mm4, [eax+ebx+ebx+color1] + pcmpeqw mm4, mm5 + pcmpeqw mm6, mm5 + pxor mm5, mm5 + pand mm7, mm4 + pcmpeqw mm6, mm5 + pand mm7, mm6 + + + + movq mm6, [eax+ebx+ebx+color3] + movq mm5, [eax+ebx+ebx+color2] + movq mm4, [eax+ebx+ebx+color1] + movq mm2, [eax+ebx+color5] + movq mm1, [eax+ebx+color4] + movq mm3, [eax+colorB0] + + pcmpeqw mm2, mm4 + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm3, mm5 + pxor mm5, mm5 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm6, mm1 + pand mm2, mm3 + pand mm6, mm2 + por mm7, mm6 + + + movq mm6, mm7 + pcmpeqw mm6, mm5 + pand mm7, mm0 + + movq mm1, [eax+ebx+color5] + pand mm6, mm1 + por mm7, mm6 + movq [final1a], mm7 ;finished 1a + + + + ;-------------------------------- + + movq mm7, [Mask35] + push eax + add eax, ebx + movq mm6, [eax+ebx+ebx+colorA2] + pop eax + movq mm5, [eax+ebx+color5] + movq mm4, [eax+ebx+color4] + pcmpeqw mm4, mm5 + pcmpeqw mm6, mm5 + pxor mm5, mm5 + pand mm7, mm4 + pcmpeqw mm6, mm5 + pand mm7, mm6 + + + + movq mm6, [eax+ebx+color6] + movq mm5, [eax+ebx+color5] + movq mm4, [eax+ebx+color4] + movq mm2, [eax+ebx+ebx+color2] + movq mm1, [eax+ebx+ebx+color1] + push eax + add eax, ebx + movq mm3, [eax+ebx+ebx+colorA0] + pop eax + + pcmpeqw mm2, mm4 + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm3, mm5 + pxor mm5, mm5 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm6, mm1 + pand mm2, mm3 + pand mm6, mm2 + por mm7, mm6 + + + movq mm6, mm7 + pcmpeqw mm6, mm5 + pand mm7, mm0 + + movq mm1, [eax+ebx+ebx+color2] + pand mm6, mm1 + por mm7, mm6 + movq [final2a], mm7 ;finished 2a - ;-------------------------------------------- + ;-------------------------------------------- %ifdef dfhsdfhsdahdsfhdsfh @@ -600,168 +601,133 @@ product1b = INTERPOLATE (color5, color6); %endif - push eax - add eax, ebx - pxor mm7, mm7 - movq mm0, [eax+ebx+ebx+colorA0] - movq mm1, [eax+ebx+ebx+colorA1] - movq mm2, [eax+ebx+ebx+colorA2] - movq mm3, [eax+ebx+ebx+colorA3] - pop eax - movq mm4, [eax+ebx+ebx+color2] - movq mm5, [eax+ebx+ebx+color3] - movq mm6, [eax+ebx+color6] - - pcmpeqw mm6, mm5 - pcmpeqw mm1, mm5 - pcmpeqw mm4, mm2 - pcmpeqw mm0, mm5 - pcmpeqw mm4, mm7 - pcmpeqw mm0, mm7 - pand mm0, mm4 - pand mm6, mm1 - pand mm0, mm6 - - - push eax - add eax, ebx - movq mm1, [eax+ebx+ebx+colorA1] - pop eax - movq mm4, [eax+ebx+ebx+color2] - movq mm5, [eax+ebx+color5] - movq mm6, [eax+ebx+ebx+color3] - - pcmpeqw mm5, mm4 - pcmpeqw mm2, mm4 - pcmpeqw mm1, mm6 - pcmpeqw mm3, mm4 - pcmpeqw mm1, mm7 - pcmpeqw mm3, mm7 - pand mm2, mm5 - pand mm1, mm3 - pand mm1, mm2 - - - movq mm7, mm0 - por mm7, mm1 - - movq mm4, [Mask35] - movq mm3, [Mask26] - - movq mm6, mm4 - pand mm6, mm7 - pxor mm4, mm6 - - movq mm6, mm3 - pand mm6, mm7 - pxor mm3, mm6 - - movq mm2, mm0 - movq mm7, [I2333Pixel] - movq mm6, [I2223Pixel] - movq mm5, [I23Pixel] - - - por mm2, mm4 - pand mm4, [eax+ebx+ebx+color3] - por mm2, mm3 - pand mm3, [eax+ebx+ebx+color2] - por mm2, mm1 - pand mm0, mm7 - pand mm1, mm6 - pxor mm7, mm7 - pcmpeqw mm2, mm7 - por mm0, mm1 - por mm3, mm4 - pand mm2, mm5 - por mm0, mm3 - por mm0, mm2 - movq [final2b], mm0 - - ;----------------------------------- - - - pxor mm7, mm7 - movq mm0, [eax+colorB0] - movq mm1, [eax+colorB1] - movq mm2, [eax+colorB2] - movq mm3, [eax+colorB3] - movq mm4, [eax+ebx+color5] - movq mm5, [eax+ebx+color6] - movq mm6, [eax+ebx+ebx+color3] - - pcmpeqw mm6, mm5 - pcmpeqw mm1, mm5 - pcmpeqw mm4, mm2 - pcmpeqw mm0, mm5 - pcmpeqw mm4, mm7 - pcmpeqw mm0, mm7 - pand mm0, mm4 - pand mm6, mm1 - pand mm0, mm6 - - movq mm1, [eax+colorB1] - movq mm4, [eax+ebx+color5] - movq mm5, [eax+ebx+ebx+color2] - movq mm6, [eax+ebx+color6] - - pcmpeqw mm5, mm4 - pcmpeqw mm2, mm4 - pcmpeqw mm1, mm6 - pcmpeqw mm3, mm4 - pcmpeqw mm1, mm7 - pcmpeqw mm3, mm7 - pand mm2, mm5 - pand mm1, mm3 - pand mm1, mm2 - - - movq mm7, mm0 - por mm7, mm1 - - movq mm4, [Mask35] - movq mm3, [Mask26] - - movq mm6, mm4 - pand mm6, mm7 - pxor mm4, mm6 - - movq mm6, mm3 - pand mm6, mm7 - pxor mm3, mm6 - - movq mm2, mm0 - movq mm7, [I5666Pixel] - movq mm6, [I5556Pixel] - movq mm5, [I56Pixel] - - - por mm2, mm4 - pand mm4, [eax+ebx+color5] - por mm2, mm3 - pand mm3, [eax+ebx+color6] - por mm2, mm1 - pand mm0, mm7 - pand mm1, mm6 - pxor mm7, mm7 - pcmpeqw mm2, mm7 - por mm0, mm1 - por mm3, mm4 - pand mm2, mm5 - por mm0, mm3 - por mm0, mm2 - movq [final1b], mm0 - - ;--------- - - movq mm0, [final1a] - movq mm4, [final2a] - movq mm2, [final1b] - movq mm6, [final2b] - + push eax + add eax, ebx + pxor mm7, mm7 + movq mm0, [eax+ebx+ebx+colorA0] + movq mm1, [eax+ebx+ebx+colorA1] + movq mm2, [eax+ebx+ebx+colorA2] + movq mm3, [eax+ebx+ebx+colorA3] + pop eax + movq mm4, [eax+ebx+ebx+color2] + movq mm5, [eax+ebx+ebx+color3] + movq mm6, [eax+ebx+color6] + + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm4, mm2 + pcmpeqw mm0, mm5 + pcmpeqw mm4, mm7 + pcmpeqw mm0, mm7 + pand mm0, mm4 + pand mm6, mm1 + pand mm0, mm6 + + movq mm4, [eax+ebx+color2] + movq mm5, [eax+ebx+ebx+color5] + movq mm6, [eax+ebx+ebx+color3] + + pcmpeqw mm5, mm4 + pcmpeqw mm2, mm4 + pcmpeqw mm1, mm6 + pcmpeqw mm3, mm4 + pcmpeqw mm1, mm7 + pcmpeqw mm3, mm7 + pand mm2, mm5 + pand mm1, mm3 + pand mm1, mm2 + + movq mm2, mm0 + movq mm7, [I2333Pixel] + movq mm6, [I2223Pixel] + movq mm5, [I23Pixel] + movq mm4, [Mask35] + movq mm3, [Mask26] + + por mm2, mm4 + pand mm4, [eax+ebx+ebx+color3] + por mm2, mm3 + pand mm3, [eax+ebx+ebx+color2] + por mm2, mm1 + pand mm0, mm7 + pand mm1, mm6 + pxor mm7, mm7 + pcmpeqw mm2, mm7 + por mm0, mm1 + por mm3, mm4 + pand mm2, mm5 + por mm0, mm3 + por mm0, mm2 + movq [final2b], mm0 + + ;----------------------------------- + + + pxor mm7, mm7 + movq mm0, [eax+colorB0] + movq mm1, [eax+colorB1] + movq mm2, [eax+colorB2] + movq mm3, [eax+colorB3] + movq mm4, [eax+ebx+color5] + movq mm5, [eax+ebx+color6] + movq mm6, [eax+ebx+ebx+color3] + + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm4, mm2 + pcmpeqw mm0, mm5 + pcmpeqw mm4, mm7 + pcmpeqw mm0, mm7 + pand mm0, mm4 + pand mm6, mm1 + pand mm0, mm6 + + movq mm4, [eax+ebx+color5] + movq mm5, [eax+ebx+ebx+color2] + movq mm6, [eax+ebx+color6] + + pcmpeqw mm5, mm4 + pcmpeqw mm2, mm4 + pcmpeqw mm1, mm6 + pcmpeqw mm3, mm4 + pcmpeqw mm1, mm7 + pcmpeqw mm3, mm7 + pand mm2, mm5 + pand mm1, mm3 + pand mm1, mm2 + + movq mm2, mm0 + movq mm7, [I5666Pixel] + movq mm6, [I5556Pixel] + movq mm5, [I56Pixel] + movq mm4, [Mask35] + movq mm3, [Mask26] + + por mm2, mm4 + pand mm4, [eax+ebx+color5] + por mm2, mm3 + pand mm3, [eax+ebx+color6] + por mm2, mm1 + pand mm0, mm7 + pand mm1, mm6 + pxor mm7, mm7 + pcmpeqw mm2, mm7 + por mm0, mm1 + por mm3, mm4 + pand mm2, mm5 + por mm0, mm3 + por mm0, mm2 + movq [final1b], mm0 + + ;--------- + + movq mm0, [final1a] + movq mm4, [final2a] + movq mm2, [final1b] + movq mm6, [final2b] - movq mm1, mm0 - movq mm5, mm4 + movq mm1, mm0 + movq mm5, mm4 punpcklwd mm0, mm2 @@ -780,12 +746,12 @@ movq [fs:edx+8], mm5 pop edx %else - movq [edx], mm0 - movq [edx+8], mm1 + movq [es:edx], mm0 + movq [es:edx+8], mm1 push edx add edx, [ebp+dstPitch] - movq [edx], mm4 - movq [edx+8], mm5 + movq [es:edx], mm4 + movq [es:edx+8], mm5 pop edx %endif .SKIP_PROCESS: @@ -818,18 +784,22 @@ + + + + %ifdef __DJGPP__ __2xSaISuperEagleLine: %else -_2xSaISuperEagleLine: +NEWSYM _2xSaISuperEagleLine %endif ; Store some stuff - push ebp - mov ebp, esp + push ebp + mov ebp, esp pushad ; Prepare the destination -%ifdef FAR_POINTER +%ifdef __DJGPP__ ; Set the selector mov eax, [ebp+dstSegment] mov fs, ax @@ -1217,9 +1187,9 @@ pcmpgtw mm0, mm1 por mm7, [Mask35] - por mm0, [Mask26] + por mm1, [Mask26] movq [Mask35], mm7 - movq [Mask26], mm0 + movq [Mask26], mm1 .SKIP_GUESS: ;Start the ASSEMBLY !!! @@ -1331,7 +1301,7 @@ -%ifdef FAR_POINTER +%ifdef __DJGPP__ movq [fs:edx], mm0 movq [fs:edx+8], mm1 push edx @@ -1340,12 +1310,12 @@ movq [fs:edx+8], mm5 pop edx %else - movq [edx], mm0 - movq [edx+8], mm1 + movq [es:edx], mm0 + movq [es:edx+8], mm1 push edx add edx, [ebp+dstPitch] - movq [edx], mm4 - movq [edx+8], mm5 + movq [es:edx], mm4 + movq [es:edx+8], mm5 pop edx %endif .SKIP_PROCESS: @@ -1377,7 +1347,7 @@ ;------------------------------------------------------------------------- -;This is version 0.50 +;This is 2xSaI colorI equ -2 colorE equ 0 colorF equ 2 @@ -1401,15 +1371,15 @@ %ifdef __DJGPP__ __2xSaILine: %else -_2xSaILine: +NEWSYM _2xSaILine %endif ; Store some stuff - push ebp - mov ebp, esp + push ebp + mov ebp, esp pushad ; Prepare the destination -%ifdef FAR_POINTER +%ifdef __DJGPP__ ; Set the selector mov eax, [ebp+dstSegment] mov fs, ax @@ -1599,12 +1569,12 @@ punpcklwd mm5, mm0 punpckhwd mm6, mm0 -%ifdef FAR_POINTER +%ifdef __DJGPP__ movq [fs:edx], mm5 movq [fs:edx+8], mm6 %else - movq [edx], mm5 - movq [edx+8], mm6 + movq [es:edx], mm5 + movq [es:edx+8], mm6 %endif ;------------------------------------------------ @@ -1766,7 +1736,6 @@ movd ecx, mm7 test ecx, ecx jz near .SKIP_GUESS - ;--------------------------------------------- ; Map of the pixels: I|E F|J ; G|A B|K @@ -1887,9 +1856,9 @@ pcmpgtw mm0, mm1 por mm7, [Mask1] - por mm0, [Mask2] + por mm1, [Mask2] movq [Mask1], mm7 - movq [Mask2], mm0 + movq [Mask2], mm1 .SKIP_GUESS: ;---------------------------- @@ -1953,12 +1922,12 @@ push edx add edx, [ebp+dstPitch] -%ifdef FAR_POINTER +%ifdef __DJGPP__ movq [fs:edx], mm0 movq [fs:edx+8], mm1 %else - movq [edx], mm0 - movq [edx+8], mm1 + movq [es:edx], mm0 + movq [es:edx+8], mm1 %endif pop edx @@ -1992,28 +1961,28 @@ %ifdef __DJGPP__ _Init_2xSaIMMX: %else -Init_2xSaIMMX: +NEWSYM Init_2xSaIMMX %endif ; Store some stuff - push ebp - mov ebp, esp + push ebp + mov ebp, esp push edx ;Damn thing doesn't work -; mov eax,1 -; cpuid -; test edx, 0x00800000 ;test bit 23 -; jz end2 ;bit not set => no MMX detected - - mov eax, [ebp+8] ;PixelFormat - cmp eax, 555 - jz Bits555 - cmp eax, 565 - jz Bits565 +; mov eax,1 +; cpuid +; test edx, 0x00800000 ;test bit 23 +; jz end2 ;bit not set => no MMX detected + + mov eax, [ebp+8] ;PixelFormat + cmp eax, 555 + jz Bits555 + cmp eax, 565 + jz Bits565 end2: - mov eax, 1 - jmp end3 + mov eax, 1 + jmp end Bits555: mov edx, 0x7BDE7BDE mov eax, colorMask @@ -2032,7 +2001,7 @@ mov [eax], edx mov [eax+4], edx mov eax, 0 - jmp end3 + jmp end Bits565: mov edx, 0xF7DEF7DE mov eax, colorMask @@ -2051,12 +2020,12 @@ mov [eax], edx mov [eax+4], edx mov eax, 0 - jmp end3 -end3: + jmp end +end: pop edx - mov esp, ebp - pop ebp - ret + mov esp, ebp + pop ebp + ret ;------------------------------------------------------------------------- @@ -2067,21 +2036,17 @@ ;------------------------------------------------------------------------- ;------------------------------------------------------------------------- - SECTION .data ALIGN = 32 + SECTION .data ALIGN = 32 ;Some constants -colorMask dd 0xF7DEF7DE,0xF7DEF7DE -lowPixelMask dd 0x08210821,0x08210821 +colorMask dd 0xF7DEF7DE, 0xF7DEF7DE +lowPixelMask dd 0x08210821, 0x08210821 -qcolorMask dd 0xE79CE79C,0xE79CE79C -qlowpixelMask dd 0x18631863,0x18631863 +qcolorMask dd 0xE79CE79C, 0xE79CE79C +qlowpixelMask dd 0x18631863, 0x18631863 -darkenMask dd 0xC718C718,0xC718C718 -GreenMask dd 0x07E007E0,0x07E007E0 -RedBlueMask dd 0xF81FF81F,0xF81FF81F - -FALSE dd 0x00000000,0x00000000 -TRUE dd 0xffffffff,0xffffffff -ONE dd 0x00010001,0x00010001 +FALSE dd 0x00000000, 0x00000000 +TRUE dd 0xffffffff, 0xffffffff +ONE dd 0x00010001, 0x00010001 SECTION .bss ALIGN = 32 diff -urN ../VisualBoyAdvance-1.7.2/src/i386/Makefile.in ./src/i386/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/i386/Makefile.in 2004-05-14 06:40:00 +0900 +++ ./src/i386/Makefile.in 2004-09-30 07:23:30 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/interframe.cpp ./src/interframe.cpp --- ../VisualBoyAdvance-1.7.2/src/interframe.cpp 2004-05-13 23:33:32 +0900 +++ ./src/interframe.cpp 2006-08-24 11:13:39 +0900 @@ -579,42 +579,3 @@ pos++; } } - -static int count = 0; - -void InterlaceIB(u8 *srcPtr, u32 srcPitch, int width, int height) -{ - if(frm1 == NULL) { - Init(); - } - - u16 colorMask = ~RGB_LOW_BITS_MASK; - - u16 *src0 = (u16 *)srcPtr; - u16 *src1 = (u16 *)frm1; - - int sPitch = srcPitch >> 1; - - int pos = 0; - for (int j = 0; j < height; j++) { - bool render = count ? (j & 1) != 0 : (j & 1) == 0; - if(render) { - for (int i = 0; i < sPitch; i++) { - u16 color = src0[pos]; - src0[pos] = - (((color & colorMask) >> 1) + ((((src1[pos] & colorMask) >> 1) & colorMask) >> 1)); - src1[pos] = color; - pos++; - } - } else { - for (int i = 0; i < sPitch; i++) { - u16 color = src0[pos]; - src0[pos] = - (((((color & colorMask) >> 1) & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)); - src1[pos] = color; - pos++; - } - } - } - count = count ^ 1; -} diff -urN ../VisualBoyAdvance-1.7.2/src/memgzio.c ./src/memgzio.c --- ../VisualBoyAdvance-1.7.2/src/memgzio.c 2004-01-18 08:07:32 +0900 +++ ./src/memgzio.c 2006-06-07 06:04:20 +0900 @@ -9,7 +9,7 @@ * Adapted from original gzio.c from zlib library by Forgotten */ -/* @(#) $Id: memgzio.c,v 1.3 2004/01/17 23:07:32 kxu Exp $ */ +/* @(#) $Id: memgzio.c,v 1.5 2006/06/06 21:04:20 spacy51 Exp $ */ #include #include @@ -125,7 +125,7 @@ total = file->available; } memcpy(file->next, buffer, total); - file->available -= total; + file->available -= (int)total; file->next += total; return total; } @@ -147,7 +147,7 @@ total = file->available; } memcpy(buffer, file->next, total); - file->available -= total; + file->available -= (int)total; file->next += total; return total; } @@ -170,7 +170,7 @@ local long memTell(MEMFILE *f) { - return (f->next - f->memory) - 8; + return (long)(f->next - f->memory) - 8; } local int memError(MEMFILE *f) @@ -197,7 +197,7 @@ len = vsprintf(buffer, format, list); va_end(list); - return memWrite(buffer, 1, len, f); + return (int)memWrite(buffer, 1, len, f); } /* =========================================================================== @@ -331,7 +331,7 @@ if (s->z_eof) return EOF; if (s->stream.avail_in == 0) { errno = 0; - s->stream.avail_in = memRead(s->inbuf, 1, Z_BUFSIZE, s->file); + s->stream.avail_in = (uInt)memRead(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (memError(s->file)) s->z_err = Z_ERRNO; @@ -476,8 +476,7 @@ s->stream.avail_in -= n; } if (s->stream.avail_out > 0) { - s->stream.avail_out -= memRead(next_out, 1, s->stream.avail_out, - s->file); + s->stream.avail_out -= (uInt)memRead(next_out, 1, s->stream.avail_out, s->file); } len -= s->stream.avail_out; s->stream.total_in += (uLong)len; @@ -488,7 +487,7 @@ if (s->stream.avail_in == 0 && !s->z_eof) { errno = 0; - s->stream.avail_in = memRead(s->inbuf, 1, Z_BUFSIZE, s->file); + s->stream.avail_in = (uInt)memRead(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (memError(s->file)) { diff -urN ../VisualBoyAdvance-1.7.2/src/memgzio.h ./src/memgzio.h --- ../VisualBoyAdvance-1.7.2/src/memgzio.h 2003-07-24 22:21:52 +0900 +++ ./src/memgzio.h 2006-09-04 06:52:25 +0900 @@ -8,10 +8,11 @@ /* memgzio.c - IO on .gz files in memory * Adapted from original gzio.c from zlib library by Forgotten */ -#ifndef HAVE_ZUTIL_H -#include "../win32/include/zlib/zutil.h" + +#if defined(HAVE_ZUTIL_H) || defined(_WIN32) +# include #else -#include +# include "../win32/dependencies/zlib/zutil.h" #endif gzFile ZEXPORT memgzopen(char *memory, int, const char *); diff -urN ../VisualBoyAdvance-1.7.2/src/prof/Makefile.in ./src/prof/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/prof/Makefile.in 2004-05-14 06:39:54 +0900 +++ ./src/prof/Makefile.in 2004-09-30 07:23:30 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/prof/prof.cpp ./src/prof/prof.cpp --- ../VisualBoyAdvance-1.7.2/src/prof/prof.cpp 2004-05-13 23:31:58 +0900 +++ ./src/prof/prof.cpp 2006-08-25 23:13:38 +0900 @@ -57,20 +57,14 @@ #include "../GBA.h" #include "../NLS.h" +#include "prof.h" /* for struct profile_segment */ + /* * froms is actually a bunch of unsigned shorts indexing tos */ static int profiling = 3; -static unsigned short *froms; -static struct tostruct *tos = 0; -static long tolimit = 0; -static u32 s_lowpc = 0; -static u32 s_highpc = 0; -static unsigned long s_textsize = 0; - -static int ssiz; -static char *sbuf; -static int s_scale; + +static profile_segment *first_segment = NULL; static int hz = 0; static int hist_num_bins = 0; @@ -127,13 +121,13 @@ if (mode) { /* start */ #ifdef PROFILING - cpuProfil(sbuf, ssiz, (u32)s_lowpc, s_scale); + cpuProfil(first_segment); #endif profiling = 0; } else { /* stop */ #ifdef PROFILING - cpuProfil(NULL, 0, 0, 0); + cpuProfil(NULL); #endif profiling = 3; } @@ -147,57 +141,65 @@ int monsize; char *buffer; int o; + profile_segment *newseg = (profile_segment*)calloc(1,sizeof(profile_segment)); + if (newseg) { + newseg->next = first_segment; + first_segment = newseg; + } else { + systemMessage(0, MSG); + return; + } /* * round lowpc and highpc to multiples of the density we're using * so the rest of the scaling (here and in gprof) stays in ints. */ lowpc = ROUNDDOWN(lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); - s_lowpc = lowpc; + newseg->s_lowpc = lowpc; highpc = ROUNDUP(highpc, HISTFRACTION*sizeof(HISTCOUNTER)); - s_highpc = highpc; - s_textsize = highpc - lowpc; - monsize = (s_textsize / HISTFRACTION); + newseg->s_highpc = highpc; + newseg->s_textsize = highpc - lowpc; + monsize = (newseg->s_textsize / HISTFRACTION); buffer = (char *)calloc(1, 2*monsize ); if ( buffer == NULL ) { systemMessage(0, MSG); return; } - froms = (unsigned short *) calloc(1, 4*s_textsize / HASHFRACTION ); - if ( froms == NULL ) { + newseg->froms = (unsigned short *) calloc(1, 4*newseg->s_textsize / HASHFRACTION ); + if ( newseg->froms == NULL ) { systemMessage(0, MSG); free(buffer); buffer = NULL; return; } - tolimit = s_textsize * ARCDENSITY / 100; - if ( tolimit < MINARCS ) { - tolimit = MINARCS; - } else if ( tolimit > 65534 ) { - tolimit = 65534; + newseg->tolimit = newseg->s_textsize * ARCDENSITY / 100; + if ( newseg->tolimit < MINARCS ) { + newseg->tolimit = MINARCS; + } else if ( newseg->tolimit > 65534 ) { + newseg->tolimit = 65534; } - tos = (struct tostruct *) calloc(1, tolimit * sizeof( struct tostruct ) ); - if ( tos == NULL ) { + newseg->tos = (struct tostruct *) calloc(1, newseg->tolimit * sizeof( struct tostruct ) ); + if ( newseg->tos == NULL ) { systemMessage(0, MSG); free(buffer); buffer = NULL; - free(froms); - froms = NULL; + free(newseg->froms); + newseg->froms = NULL; return; } - tos[0].link = 0; - sbuf = buffer; - ssiz = monsize; + newseg->tos[0].link = 0; + newseg->sbuf = buffer; + newseg->ssiz = monsize; if ( monsize <= 0 ) return; o = highpc - lowpc; if( monsize < o ) - s_scale = (int)(( (float) monsize / o ) * SCALE_1_TO_1); + newseg->s_scale = (int)(( (float) monsize / o ) * SCALE_1_TO_1); else - s_scale = SCALE_1_TO_1; + newseg->s_scale = SCALE_1_TO_1; profControl(1); } @@ -209,6 +211,7 @@ u32 frompc; int toindex; struct gmon_hdr ghdr; + profile_segment *seg = first_segment; profControl(0); fd = fopen( "gmon.out" , "wb" ); @@ -229,11 +232,13 @@ if(hz == 0) hz = 100; - hist_num_bins = ssiz; + while(seg) { + + hist_num_bins = seg->ssiz; if(profWrite8(fd, GMON_TAG_TIME_HIST) || - profWrite32(fd, (u32)s_lowpc) || - profWrite32(fd, (u32)s_highpc) || + profWrite32(fd, (u32)seg->s_lowpc) || + profWrite32(fd, (u32)seg->s_highpc) || profWrite32(fd, hist_num_bins) || profWrite32(fd, hz) || profWrite(fd, hist_dimension, 15) || @@ -242,7 +247,7 @@ fclose(fd); return; } - u16 *hist_sample = (u16 *)sbuf; + u16 *hist_sample = (u16 *)seg->sbuf; u16 count; int i; @@ -257,23 +262,25 @@ } } - endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); + endfrom = seg->s_textsize / (HASHFRACTION * sizeof(*seg->froms)); for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { - if ( froms[fromindex] == 0 ) { + if ( seg->froms[fromindex] == 0 ) { continue; } - frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); - for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { + frompc = seg->s_lowpc + (fromindex * HASHFRACTION * sizeof(*seg->froms)); + for (toindex=seg->froms[fromindex]; toindex!=0; toindex=seg->tos[toindex].link) { if(profWrite8(fd, GMON_TAG_CG_ARC) || profWrite32(fd, (u32)frompc) || - profWrite32(fd, (u32)tos[toindex].selfpc) || - profWrite32(fd, tos[toindex].count)) { + profWrite32(fd, (u32)seg->tos[toindex].selfpc) || + profWrite32(fd, seg->tos[toindex].count)) { systemMessage(0, "mcount: arc"); fclose(fd); return; } } } + seg = seg->next; + } fclose(fd); } @@ -284,6 +291,7 @@ register struct tostruct *top; register struct tostruct *prevtop; register long toindex; + profile_segment *seg = first_segment; /* * find the return address for mcount, @@ -309,29 +317,36 @@ * for example: signal catchers get called from the stack, * not from text space. too bad. */ - frompcindex = (unsigned short *) ((long) frompcindex - (long) s_lowpc); - if ((unsigned long) frompcindex > s_textsize) { + while(seg) { + u32 index = (long)frompcindex - (long)seg->s_lowpc; + if (index <= seg->s_textsize) { + frompcindex = (unsigned short *) index; + break; + } + seg = seg->next; + } + if ((unsigned long) frompcindex > seg->s_textsize) { goto done; } frompcindex = - &froms[((long) frompcindex) / (HASHFRACTION * sizeof(*froms))]; + &(seg->froms[((long) frompcindex) / (HASHFRACTION * sizeof(*seg->froms))]); toindex = *frompcindex; if (toindex == 0) { /* * first time traversing this arc */ - toindex = ++tos[0].link; - if (toindex >= tolimit) { + toindex = ++seg->tos[0].link; + if (toindex >= seg->tolimit) { goto overflow; } *frompcindex = (unsigned short)toindex; - top = &tos[toindex]; + top = &seg->tos[toindex]; top->selfpc = selfpc; top->count = 1; top->link = 0; goto done; } - top = &tos[toindex]; + top = &seg->tos[toindex]; if (top->selfpc == selfpc) { /* * arc at front of chain; usual case. @@ -353,11 +368,11 @@ * so we allocate a new tostruct * and link it to the head of the chain. */ - toindex = ++tos[0].link; - if (toindex >= tolimit) { + toindex = ++seg->tos[0].link; + if (toindex >= seg->tolimit) { goto overflow; } - top = &tos[toindex]; + top = &seg->tos[toindex]; top->selfpc = selfpc; top->count = 1; top->link = *frompcindex; @@ -368,7 +383,7 @@ * otherwise, check the next arc on the chain. */ prevtop = top; - top = &tos[top->link]; + top = &seg->tos[top->link]; if (top->selfpc == selfpc) { /* * there it is. diff -urN ../VisualBoyAdvance-1.7.2/src/prof/prof.h ./src/prof/prof.h --- ../VisualBoyAdvance-1.7.2/src/prof/prof.h 2004-05-13 22:49:00 +0900 +++ ./src/prof/prof.h 2006-08-25 23:13:38 +0900 @@ -24,6 +24,24 @@ profiling is what mcount checks to see if all the data structures are ready. */ + +typedef struct profile_segment { + unsigned short *froms; + struct tostruct *tos; + long tolimit; + + u32 s_lowpc; + u32 s_highpc; + unsigned long s_textsize; + + int ssiz; + char *sbuf; + int s_scale; + + struct profile_segment *next; + +} profile_segment; + extern void profControl(int mode); extern void profStartup(u32 lowpc, u32 highpc); extern void profCleanup(); diff -urN ../VisualBoyAdvance-1.7.2/src/remote.cpp ./src/remote.cpp --- ../VisualBoyAdvance-1.7.2/src/remote.cpp 2004-05-21 02:24:47 +0900 +++ ./src/remote.cpp 2006-09-04 06:52:25 +0900 @@ -20,7 +20,7 @@ #include #include -#ifndef WIN32 +#ifndef _WIN32 # include # include # include @@ -32,14 +32,15 @@ # else // ! HAVE_ARPA_INET_H # define socklen_t int # endif // ! HAVE_ARPA_INET_H -#else // WIN32 +# define SOCKET int +#else // _WIN32 # include # include # define socklen_t int # define close closesocket # define read _read # define write _write -#endif // WIN32 +#endif // _WIN32 #include "GBA.h" @@ -54,8 +55,8 @@ int remotePort = 55555; int remoteSignal = 5; -int remoteSocket = -1; -int remoteListenSocket = -1; +SOCKET remoteSocket = -1; +SOCKET remoteListenSocket = -1; bool remoteConnected = false; bool remoteResumed = false; @@ -85,11 +86,11 @@ bool remoteTcpInit() { if(remoteSocket == -1) { -#ifdef WIN32 +#ifdef _WIN32 WSADATA wsaData; int error = WSAStartup(MAKEWORD(1,1),&wsaData); -#endif // WIN32 - int s = socket(PF_INET, SOCK_STREAM, 0); +#endif // _WIN32 + SOCKET s = socket(PF_INET, SOCK_STREAM, 0); remoteListenSocket = s; @@ -131,19 +132,19 @@ } socklen_t len = sizeof(addr); -#ifdef WIN32 +#ifdef _WIN32 int flag = 0; ioctlsocket(s, FIONBIO, (unsigned long *)&flag); -#endif // WIN32 - int s2 = accept(s, (sockaddr *)&addr, &len); +#endif // _WIN32 + SOCKET s2 = accept(s, (sockaddr *)&addr, &len); if(s2 > 0) { fprintf(stderr, "Got a connection from %s %d\n", inet_ntoa((in_addr)addr.sin_addr), ntohs(addr.sin_port)); } else { -#ifdef WIN32 +#ifdef _WIN32 int error = WSAGetLastError(); -#endif // WIN32 +#endif // _WIN32 } char dummy; recv(s2, &dummy, 1, 0); @@ -230,14 +231,14 @@ char *hex = "0123456789abcdef"; char buffer[1024]; - int count = strlen(packet); + size_t count = strlen(packet); unsigned char csum = 0; char *p = buffer; *p++ = '$'; - for(int i = 0 ;i < count; i++) { + for(size_t i = 0 ;i < count; i++) { csum += packet[i]; *p++ = packet[i]; } @@ -246,7 +247,7 @@ *p++ = hex[csum & 15]; *p++ = 0; // printf("Sending %s\n", buffer); - remoteSendFnc(buffer, count + 4); + remoteSendFnc(buffer, (int)count + 4); char c = 0; remoteRecvFnc(&c, 1); diff -urN ../VisualBoyAdvance-1.7.2/src/sdl/Makefile.in ./src/sdl/Makefile.in --- ../VisualBoyAdvance-1.7.2/src/sdl/Makefile.in 2004-05-21 03:30:10 +0900 +++ ./src/sdl/Makefile.in 2004-09-30 07:23:39 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/src/sdl/SDL.cpp ./src/sdl/SDL.cpp --- ../VisualBoyAdvance-1.7.2/src/sdl/SDL.cpp 2004-05-22 05:16:58 +0900 +++ ./src/sdl/SDL.cpp 2006-08-25 23:06:01 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -23,34 +23,34 @@ #include #include -#include "AutoBuild.h" +#include "../AutoBuild.h" #include "SDL.h" -#include "GBA.h" -#include "agbprint.h" -#include "Flash.h" -#include "Port.h" +#include "../GBA.h" +#include "../agbprint.h" +#include "../Flash.h" +#include "../Port.h" #include "debugger.h" -#include "RTC.h" -#include "Sound.h" -#include "Text.h" -#include "unzip.h" -#include "Util.h" -#include "gb/GB.h" -#include "gb/gbGlobals.h" +#include "../RTC.h" +#include "../Sound.h" +#include "../Text.h" +#include "../unzip.h" +#include "../Util.h" +#include "../gb/GB.h" +#include "../gb/gbGlobals.h" -#ifndef WIN32 +#ifndef _WIN32 # include # define GETCWD getcwd -#else // WIN32 +#else // _WIN32 # include # define GETCWD _getcwd -#endif // WIN32 +#endif // _WIN32 #ifndef __GNUC__ # define HAVE_DECL_GETOPT 0 # define __STDC__ 1 -# include "getopt.h" +# include "../getopt.h" #else // ! __GNUC__ # define HAVE_DECL_GETOPT 1 # include "getopt.h" @@ -109,6 +109,7 @@ extern void debuggerOutput(char *, u32); extern void CPUUpdateRenderBuffers(bool); +extern int gbHardware; struct EmulatedSystem emulator = { NULL, @@ -186,6 +187,7 @@ static int rewindTimer = 0; #define REWIND_SIZE 400000 +#define SYSMSG_BUFFER_SIZE 1024 #define _stricmp strcasecmp @@ -231,6 +233,7 @@ int sdlAutoIPS = 1; int sdlRtcEnable = 0; int sdlAgbPrint = 0; +int sdlMirroringEnable = 0; int sdlDefaultJoypad = 0; @@ -248,8 +251,10 @@ char screenMessageBuffer[21]; u32 screenMessageTime = 0; -SDL_cond *cond = NULL; -SDL_mutex *mutex = NULL; +// Patch #1382692 by deathpudding. +SDL_sem *sdlBufferLock = NULL; +SDL_sem *sdlBufferFull = NULL; +SDL_sem *sdlBufferEmpty = NULL; u8 sdlBuffer[4096]; int sdlSoundLen = 0; @@ -862,15 +867,15 @@ char buffer[4096]; char path[2048]; -#ifdef WIN32 +#ifdef _WIN32 #define PATH_SEP ";" #define FILE_SEP '\\' #define EXE_NAME "VisualBoyAdvance-SDL.exe" -#else // ! WIN32 +#else // ! _WIN32 #define PATH_SEP ":" #define FILE_SEP '/' #define EXE_NAME "VisualBoyAdvance" -#endif // ! WIN32 +#endif // ! _WIN32 fprintf(stderr, "Searching for file %s\n", name); @@ -893,7 +898,7 @@ return f; } -#ifdef WIN32 +#ifdef _WIN32 home = getenv("USERPROFILE"); if(home != NULL) { fprintf(stderr, "Searching user profile directory: %s\n", home); @@ -902,13 +907,13 @@ if(f != NULL) return f; } -#else // ! WIN32 +#else // ! _WIN32 fprintf(stderr, "Searching system config directory: %s\n", SYSCONFDIR); sprintf(path, "%s%c%s", SYSCONFDIR, FILE_SEP, name); f = fopen(path, "r"); if(f != NULL) return f; -#endif // ! WIN32 +#endif // ! _WIN32 if(!strchr(arg0, '/') && !strchr(arg0, '\\')) { @@ -1204,8 +1209,6 @@ if(rewindTimer < 0 || rewindTimer > 600) rewindTimer = 0; rewindTimer *= 6; // convert value to 10 frames multiple - } else if(!strcmp(key, "enhancedDetection")) { - cpuEnhancedDetection = sdlFromHex(value) ? true : false; } else { fprintf(stderr, "Unknown configuration key %s\n", key); } @@ -1306,6 +1309,8 @@ int save = atoi(value); if(save >= 0 && save <= 5) cpuSaveType = save; + } else if(!strcmp(token, "mirroringEnabled")) { + mirroringEnable = (atoi(value) == 0 ? false : true); } } } @@ -1353,10 +1358,14 @@ num+1); else sprintf(stateName,"%s%d.sgm", filename, num+1); + if(emulator.emuWriteState) emulator.emuWriteState(stateName); + sprintf(stateName, "Wrote state %d", num+1); systemScreenMessage(stateName); + + systemDrawScreen(); } void sdlReadState(int num) @@ -1374,6 +1383,8 @@ sprintf(stateName, "Loaded state %d", num+1); systemScreenMessage(stateName); + + systemDrawScreen(); } void sdlWriteBattery() @@ -1720,7 +1731,7 @@ (event.key.keysym.mod & KMOD_CTRL)) { if(emulating && emulator.emuReadMemState && rewindMemory && rewindCount) { - rewindPos = --rewindPos & 7; + rewindPos = (rewindPos - 1) & 7; emulator.emuReadMemState(&rewindMemory[REWIND_SIZE*rewindPos], REWIND_SIZE); rewindCount--; @@ -2182,6 +2193,12 @@ if(optind < argc) { char *szFile = argv[optind]; + u32 len = strlen(szFile); + if (len > SYSMSG_BUFFER_SIZE) + { + fprintf(stderr,"%s :%s: File name too long\n",argv[0],szFile); + exit(-1); + } utilGetBaseName(szFile, filename); char *p = strrchr(filename, '.'); @@ -2205,7 +2222,23 @@ if(type == IMAGE_GB) { failed = !gbLoadRom(szFile); if(!failed) { - cartridgeType = 1; + gbGetHardwareType(); + + // used for the handling of the gb Boot Rom + if (gbHardware & 5) + { + char tempName[0x800]; + strcpy(tempName, arg0); + char *p = strrchr(tempName, '\\'); + if(p) { *p = 0x00; } + strcat(tempName, "\\DMG_ROM.bin"); + fprintf(stderr, "%s\n", tempName); + gbCPUInit(tempName, useBios); + } + else useBios = false; + + gbReset(); + cartridgeType = IMAGE_GB; emulator = GBSystem; if(sdlAutoIPS) { int size = gbRomSize; @@ -2221,11 +2254,9 @@ int size = CPULoadRom(szFile); failed = (size == 0); if(!failed) { - // if(cpuEnhancedDetection && cpuSaveType == 0) { - // utilGBAFindSave(rom, size); - // } - sdlApplyPerImagePreferences(); + + doMirroring(mirroringEnable); cartridgeType = 0; emulator = GBASystem; @@ -2262,7 +2293,7 @@ paletteRAM = (u8 *)calloc(1,0x400); vram = (u8 *)calloc(1, 0x20000); oam = (u8 *)calloc(1, 0x400); - pix = (u8 *)calloc(1, 4 * 240 * 160); + pix = (u8 *)calloc(1, 4 * 241 * 162); ioMem = (u8 *)calloc(1, 0x400); emulator = GBASystem; @@ -2376,43 +2407,22 @@ if(systemColorDepth == 16) { if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) { Init_2xSaI(565); - RGB_LOW_BITS_MASK = 0x821; } else { Init_2xSaI(555); - RGB_LOW_BITS_MASK = 0x421; - } - if(cartridgeType == 2) { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) | - (((i & 0x7c0) >> 6) << systemGreenShift) | - (((i & 0xf800) >> 11) << systemRedShift); - } - } else { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } } srcPitch = srcWidth * 2+4; } else { if(systemColorDepth != 32) filterFunction = NULL; - RGB_LOW_BITS_MASK = 0x010101; - if(systemColorDepth == 32) { - Init_2xSaI(32); - } - for(int i = 0; i < 0x10000; i++) { - systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } + Init_2xSaI(32); if(systemColorDepth == 32) srcPitch = srcWidth*4 + 4; else srcPitch = srcWidth*3; } + utilUpdateSystemColorMaps(); + if(systemColorDepth != 32) { switch(filter) { case 0: @@ -2568,9 +2578,9 @@ if(emulator.emuWriteMemState && emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE], REWIND_SIZE)) { - rewindPos = ++rewindPos & 7; + rewindPos = (rewindPos + 1) & 7; if(rewindCount == 8) - rewindTopPos = ++rewindTopPos & 7; + rewindTopPos = (rewindTopPos + 1) & 7; } } @@ -2608,7 +2618,7 @@ void systemMessage(int num, const char *msg, ...) { - char buffer[2048]; + char buffer[SYSMSG_BUFFER_SIZE*2]; va_list valist; va_start(valist, msg); @@ -2914,67 +2924,69 @@ void soundCallback(void *,u8 *stream,int len) { - if(!emulating) + if (!emulating) return; - SDL_mutexP(mutex); - // printf("Locked mutex\n"); - if(!speedup && !throttle) { - while(sdlSoundLen < 2048*2) { - if(emulating) - SDL_CondWait(cond, mutex); - else - break; - } - } - if(emulating) { - // printf("Copying data\n"); - memcpy(stream, sdlBuffer, len); - } + + // Patch #1382692 by deathpudding. + /* since this is running in a different thread, speedup and + * throttle can change at any time; save the value so locks + * stay in sync */ + bool lock = (!speedup && !throttle) ? true : false; + + if (lock) + SDL_SemWait (sdlBufferFull); + + SDL_SemWait (sdlBufferLock); + memcpy (stream, sdlBuffer, len); sdlSoundLen = 0; - if(mutex) - SDL_mutexV(mutex); + SDL_SemPost (sdlBufferLock); + + if (lock) + SDL_SemPost (sdlBufferEmpty); } void systemWriteDataToSoundBuffer() { - if(SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) - SDL_PauseAudio(0); - bool cont = true; - while(cont && !speedup && !throttle) { - SDL_mutexP(mutex); - // printf("Waiting for len < 2048 (speed up %d)\n", speedup); - if(sdlSoundLen < 2048*2) - cont = false; - SDL_mutexV(mutex); - } - - int len = soundBufferLen; - int copied = 0; - if((sdlSoundLen+len) >= 2048*2) { - // printf("Case 1\n"); - memcpy(&sdlBuffer[sdlSoundLen],soundFinalWave, 2048*2-sdlSoundLen); - copied = 2048*2 - sdlSoundLen; + // Patch #1382692 by deathpudding. + if (SDL_GetAudioStatus () != SDL_AUDIO_PLAYING) + SDL_PauseAudio (0); + + if ((sdlSoundLen + soundBufferLen) >= 2048*2) { + bool lock = (!speedup && !throttle) ? true : false; + + if (lock) + SDL_SemWait (sdlBufferEmpty); + + SDL_SemWait (sdlBufferLock); + int copied = 2048*2 - sdlSoundLen; + memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, copied); sdlSoundLen = 2048*2; - SDL_CondSignal(cond); - cont = true; - if(!speedup && !throttle) { - while(cont) { - SDL_mutexP(mutex); - if(sdlSoundLen < 2048*2) - cont = false; - SDL_mutexV(mutex); - } - memcpy(&sdlBuffer[0],&(((u8 *)soundFinalWave)[copied]), - soundBufferLen-copied); - sdlSoundLen = soundBufferLen-copied; - } else { - memcpy(&sdlBuffer[0], &(((u8 *)soundFinalWave)[copied]), -soundBufferLen); - } - } else { - // printf("case 2\n"); - memcpy(&sdlBuffer[sdlSoundLen], soundFinalWave, soundBufferLen); - sdlSoundLen += soundBufferLen; + SDL_SemPost (sdlBufferLock); + + if (lock) { + SDL_SemPost (sdlBufferFull); + + /* wait for buffer to be dumped by soundCallback() */ + SDL_SemWait (sdlBufferEmpty); + SDL_SemPost (sdlBufferEmpty); + + SDL_SemWait (sdlBufferLock); + memcpy (sdlBuffer, ((u8 *)soundFinalWave) + copied, + soundBufferLen - copied); + sdlSoundLen = soundBufferLen - copied; + SDL_SemPost (sdlBufferLock); + } + else { + SDL_SemWait (sdlBufferLock); + memcpy (sdlBuffer, ((u8 *) soundFinalWave) + copied, soundBufferLen); + SDL_SemPost (sdlBufferLock); + } + } + else { + SDL_SemWait (sdlBufferLock); + memcpy (sdlBuffer + sdlSoundLen, soundFinalWave, soundBufferLen); + sdlSoundLen += soundBufferLen; + SDL_SemPost (sdlBufferLock); } } @@ -3006,8 +3018,10 @@ return false; } soundBufferTotalLen = soundBufferLen*10; - cond = SDL_CreateCond(); - mutex = SDL_CreateMutex(); + // Patch #1382692 by deathpudding. + sdlBufferLock = SDL_CreateSemaphore (1); + sdlBufferFull = SDL_CreateSemaphore (0); + sdlBufferEmpty = SDL_CreateSemaphore (1); sdlSoundLen = 0; systemSoundOn = true; return true; @@ -3015,14 +3029,14 @@ void systemSoundShutdown() { - SDL_mutexP(mutex); - SDL_CondSignal(cond); - SDL_mutexV(mutex); - SDL_DestroyCond(cond); - cond = NULL; - SDL_DestroyMutex(mutex); - mutex = NULL; - SDL_CloseAudio(); + // Patch #1382692 by deathpudding. + SDL_CloseAudio (); //TODO: fix freeze + SDL_DestroySemaphore (sdlBufferLock); + SDL_DestroySemaphore (sdlBufferFull); + SDL_DestroySemaphore (sdlBufferEmpty); + sdlBufferLock = NULL; + sdlBufferFull = NULL; + sdlBufferEmpty = NULL; } void systemSoundPause() diff -urN ../VisualBoyAdvance-1.7.2/src/sdl/TestEmu.cpp ./src/sdl/TestEmu.cpp --- ../VisualBoyAdvance-1.7.2/src/sdl/TestEmu.cpp 2004-05-21 03:13:15 +0900 +++ ./src/sdl/TestEmu.cpp 2006-08-25 22:09:04 +0900 @@ -23,17 +23,18 @@ #include #include -#include "AutoBuild.h" +#include "../AutoBuild.h" -#include "GBA.h" +#include "../GBA.h" #include "debugger.h" -#include "Sound.h" -#include "unzip.h" -#include "Util.h" -#include "gb/GB.h" -#include "gb/gbGlobals.h" +#include "../Sound.h" +#include "../unzip.h" +#include "../Util.h" +#include "../gb/GB.h" +#include "../gb/gbGlobals.h" +#include "../getopt.h" -#ifndef WIN32 +#ifndef _WIN32 # include # define GETCWD getcwd #else // WIN32 @@ -255,7 +256,7 @@ paletteRAM = (u8 *)calloc(1,0x400); vram = (u8 *)calloc(1, 0x20000); oam = (u8 *)calloc(1, 0x400); - pix = (u8 *)calloc(1, 4 * 240 * 160); + pix = (u8 *)calloc(1, 4 * 241 * 162); ioMem = (u8 *)calloc(1, 0x400); emulator = GBASystem; @@ -352,6 +353,38 @@ { } +void sdlWriteState(int num) +{ + char stateName[2048]; + + if(saveDir[0]) + sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), + num+1); + else + sprintf(stateName,"%s%d.sgm", filename, num+1); + if(emulator.emuWriteState) + emulator.emuWriteState(stateName); + sprintf(stateName, "Wrote state %d", num+1); + systemScreenMessage(stateName); +} + +void sdlReadState(int num) +{ + char stateName[2048]; + + if(saveDir[0]) + sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), + num+1); + else + sprintf(stateName,"%s%d.sgm", filename, num+1); + + if(emulator.emuReadState) + emulator.emuReadState(stateName); + + sprintf(stateName, "Loaded state %d", num+1); + systemScreenMessage(stateName); +} + void systemScreenCapture(int a) { char buffer[2048]; diff -urN ../VisualBoyAdvance-1.7.2/src/sdl/debugger.cpp ./src/sdl/debugger.cpp --- ../VisualBoyAdvance-1.7.2/src/sdl/debugger.cpp 2004-05-13 23:13:14 +0900 +++ ./src/sdl/debugger.cpp 2006-08-25 23:00:49 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -16,18 +16,23 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// Parts adapted from VBA-H (VBA for Hackers) by LabMaster + #include #include #include +#include -#include "GBA.h" -#include "Port.h" -#include "armdis.h" -#include "elf.h" -#include "exprNode.h" +#include "../GBA.h" +#include "../Port.h" +#include "../armdis.h" +#include "../elf.h" +#include "../exprNode.h" extern bool debugger; extern int emulating; +extern void sdlWriteState(int num); +extern void sdlReadState(int num); extern struct EmulatedSystem emulator; @@ -53,6 +58,13 @@ u32 address; u32 value; int size; + + u32 cond_address; + char cond_rel; + u32 cond_value; + int cond_size; + bool ia1; + bool ia2; }; struct DebuggerCommand { @@ -62,73 +74,116 @@ char *syntax; }; -void debuggerContinueAfterBreakpoint(); - -void debuggerHelp(int,char **); -void debuggerNext(int,char **); -void debuggerContinue(int, char **); -void debuggerRegisters(int, char **); -void debuggerBreak(int, char **); -void debuggerBreakDelete(int, char **); -void debuggerBreakList(int, char **); -void debuggerBreakArm(int, char **); -void debuggerBreakWriteClear(int, char **); -void debuggerBreakThumb(int, char **); -void debuggerBreakWrite(int, char **); -void debuggerDebug(int, char **); -void debuggerDisassemble(int, char **); -void debuggerDisassembleArm(int, char **); -void debuggerDisassembleThumb(int, char **); -void debuggerEditByte(int, char **); -void debuggerEditHalfWord(int, char **); -void debuggerEdit(int, char **); -void debuggerIo(int, char **); -void debuggerLocals(int, char **); -void debuggerMemoryByte(int, char **); -void debuggerMemoryHalfWord(int, char **); -void debuggerMemory(int, char **); -void debuggerPrint(int, char **); -void debuggerQuit(int, char **); -void debuggerSetRadix(int, char **); -void debuggerSymbols(int, char **); -void debuggerVerbose(int, char **); -void debuggerWhere(int, char **); - -DebuggerCommand debuggerCommands[] = { - { "?", debuggerHelp, "Shows this help information. Type ? for command help", "[]" }, - { "ba", debuggerBreakArm, "Adds an ARM breakpoint", "
" }, - { "bd", debuggerBreakDelete,"Deletes a breakpoint", "" }, - { "bl", debuggerBreakList, "Lists breakpoints" }, +unsigned int SearchStart = 0xFFFFFFFF; +unsigned int SearchMaxMatches = 5; +u8 SearchData [64]; // It doesn't make much sense to search for more than 64 bytes +unsigned int SearchLength = 0; +unsigned int SearchResults; + +static void debuggerContinueAfterBreakpoint(); +void debuggerDoSearch(); +unsigned int AddressToGBA(u8* mem); + +static void debuggerHelp(int,char **); +static void debuggerNext(int,char **); +static void debuggerContinue(int, char **); +static void debuggerRegisters(int, char **); +static void debuggerBreak(int, char **); +static void debuggerBreakDelete(int, char **); +static void debuggerBreakList(int, char **); +static void debuggerBreakArm(int, char **); +static void debuggerBreakThumb(int, char **); +static void debuggerBreakChange(int, char **); +static void debuggerBreakChangeClear(int, char **); +static void debuggerBreakWriteClear(int, char **); +static void debuggerBreakWrite(int, char **); +static void debuggerDebug(int, char **); +static void debuggerDisassemble(int, char **); +static void debuggerDisassembleArm(int, char **); +static void debuggerDisassembleThumb(int, char **); +static void debuggerEditByte(int, char **); +static void debuggerEditHalfWord(int, char **); +static void debuggerEditRegister(int, char **); +static void debuggerEdit(int, char **); +static void debuggerFileDisassemble(int, char **); +static void debuggerFileDisassembleArm(int, char **); +static void debuggerFileDisassembleThumb(int, char **); +static void debuggerFindText(int, char **); +static void debuggerFindHex(int, char **); +static void debuggerFindResume(int, char **); +static void debuggerIo(int, char **); +static void debuggerLast(int, char **); +static void debuggerLocals(int, char **); +static void debuggerMemoryByte(int, char **); +static void debuggerMemoryHalfWord(int, char **); +static void debuggerMemory(int, char **); +static void debuggerPrint(int, char **); +static void debuggerQuit(int, char **); +static void debuggerSetRadix(int, char **); +static void debuggerSymbols(int, char **); +static void debuggerVerbose(int, char **); +static void debuggerWhere(int, char **); + +static void debuggerReadState(int, char **); +static void debuggerWriteState(int, char **); +static void debuggerDumpLoad(int, char**); +static void debuggerDumpSave(int, char**); +static void debuggerCondValidate(int n, char **args, int start); +static bool debuggerCondEvaluate(int num); +static void debuggerCondBreakThumb(int, char **); +static void debuggerCondBreakArm(int, char **); + +static DebuggerCommand debuggerCommands[] = { + { "?", debuggerHelp, "Show this help information. Type ? for command help", "[]" }, + { "ba", debuggerBreakArm, "Add an ARM breakpoint", "
" }, + { "bd", debuggerBreakDelete,"Delete a breakpoint", "" }, + { "bl", debuggerBreakList, "List breakpoints" }, + { "bpc", debuggerBreakChange, "Break on change", "
" }, + { "bpcc", debuggerBreakChangeClear, "Clear break on change", "[
]" }, { "bpw", debuggerBreakWrite, "Break on write", "
" }, - { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL }, - { "break", debuggerBreak, "Adds a breakpoint on the given function", "||" }, - { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "
" }, - { "c", debuggerContinue, "Continues execution" , NULL }, - { "d", debuggerDisassemble, "Disassembles instructions", "[
[]]" }, - { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[
[]]" }, - { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[
[]]" }, + { "bpwc", debuggerBreakWriteClear, "Clear break on write", "[
]" }, + { "break", debuggerBreak, "Add a breakpoint on the given function", "||" }, + { "bt", debuggerBreakThumb, "Add a THUMB breakpoint", "
" }, + { "c", debuggerContinue, "Continue execution" , NULL }, + { "cba", debuggerCondBreakArm, "Add a conditional ARM breakpoint", "
$
|R []\n either ==, !=, <, >, <=, >=\n either b, h, w" }, + { "cbt", debuggerCondBreakThumb, "Add a conditional THUMB breakpoint", "
$
|R []\n either ==, !=, <, >, <=, >=\n either b, h, w" }, + { "d", debuggerDisassemble, "Disassemble instructions", "[
[]]" }, + { "da", debuggerDisassembleArm, "Disassemble ARM instructions", "[
[]]" }, + { "dload",debuggerDumpLoad, "Load raw data dump from file","
"}, + { "dsave",debuggerDumpSave, "Dump raw data to file","
"}, + { "dt", debuggerDisassembleThumb, "Disassemble THUMB instructions", "[
[]]" }, { "eb", debuggerEditByte, "Modify memory location (byte)", "
" }, { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","
" }, - { "ew", debuggerEdit, "Modify memory location (word)", "
for command help", "[]" }, + { "er", debuggerEditRegister, "Modify register", " " }, + { "ew", debuggerEdit, "Modify memory location (word)", "
" }, + { "fd", debuggerFileDisassemble, "Disassemble instructions to file", " [
[]]" }, + { "fda", debuggerFileDisassembleArm, "Disassemble ARM instructions to file", " [
[]]" }, + { "fdt", debuggerFileDisassembleThumb, "Disassemble THUMB instructions to file", " [
[]]" }, + { "ft", debuggerFindText, "Search memory for ASCII-string.", " [] " }, + { "fh", debuggerFindHex, "Search memory for hex-string.", " [] " }, + { "fr", debuggerFindResume, "Resume current search.", "[]" }, + { "h", debuggerHelp, "Show this help information. Type h for command help", "[]" }, { "io", debuggerIo, "Show I/O registers status", "[video|video2|dma|timer|misc]" }, - { "locals", debuggerLocals, "Shows local variables", NULL }, - { "mb", debuggerMemoryByte, "Shows memory contents (bytes)", "
" }, - { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "
"}, - { "mw", debuggerMemory, "Shows memory contents (words)", "
" }, - { "n", debuggerNext, "Executes the next instruction", "[]" }, + { "last", debuggerLast, "Trigger the display of the last registers states", NULL }, + { "load", debuggerReadState, "Load a savegame", "" }, + { "locals", debuggerLocals, "Show local variables", NULL }, + { "mb", debuggerMemoryByte, "Show memory contents (bytes)", "
" }, + { "mh", debuggerMemoryHalfWord, "Show memory contents (half-words)", "
"}, + { "mw", debuggerMemory, "Show memory contents (words)", "
" }, + { "n", debuggerNext, "Execute the next instruction", "[]" }, { "print", debuggerPrint, "Print the value of a expression (if known)", "[/x|/o|/d] " }, - { "q", debuggerQuit, "Quits the emulator", NULL }, - { "r", debuggerRegisters, "Shows ARM registers", NULL }, - { "radix", debuggerSetRadix, "Sets the print radix", "" }, + { "q", debuggerQuit, "Quit the emulator", NULL }, + { "r", debuggerRegisters, "Show ARM registers", NULL }, + { "radix", debuggerSetRadix, "Set the print radix", "" }, + { "save", debuggerWriteState, "Create a savegame", "" }, { "symbols", debuggerSymbols, "List symbols", "[]" }, #ifndef FINAL_VERSION - { "trace", debuggerDebug, "Sets the trace level", "" }, + { "trace", debuggerDebug, "Set the trace level", "" }, #endif #ifdef DEV_VERSION { "verbose", debuggerVerbose, "Change verbose setting", "" }, #endif - { "where", debuggerWhere, "Shows call chain", NULL }, + { "where", debuggerWhere, "Show the call chain (if available)", NULL }, { NULL, NULL, NULL, NULL} // end marker }; @@ -139,7 +194,30 @@ int debuggerBreakpointNumber = 0; int debuggerRadix = 0; -void debuggerApplyBreakpoint(u32 address, int num, int size) +extern u32 cpuPrefetch[2]; + +#define ARM_PREFETCH \ + {\ + cpuPrefetch[0] = debuggerReadMemory(armNextPC);\ + cpuPrefetch[1] = debuggerReadMemory(armNextPC+4);\ + } + +#define THUMB_PREFETCH \ + {\ + cpuPrefetch[0] = debuggerReadHalfWord(armNextPC);\ + cpuPrefetch[1] = debuggerReadHalfWord(armNextPC+2);\ + } + +static void debuggerPrefetch() +{ + if(armState) { + ARM_PREFETCH; + } else { + THUMB_PREFETCH; + } +} + +static void debuggerApplyBreakpoint(u32 address, int num, int size) { if(size) debuggerWriteMemory(address, (u32)(0xe1200070 | @@ -150,7 +228,7 @@ (u16)(0xbe00 | num)); } -void debuggerDisableBreakpoints() +static void debuggerDisableBreakpoints() { for(int i = 0; i < debuggerNumOfBreakpoints; i++) { if(debuggerBreakpointList[i].size) @@ -162,7 +240,7 @@ } } -void debuggerEnableBreakpoints(bool skipPC) +static void debuggerEnableBreakpoints(bool skipPC) { for(int i = 0; i < debuggerNumOfBreakpoints; i++) { if(debuggerBreakpointList[i].address == armNextPC && skipPC) @@ -174,12 +252,12 @@ } } -void debuggerUsage(char *cmd) +static void debuggerUsage(char *cmd) { for(int i = 0; ; i++) { if(debuggerCommands[i].name) { if(!strcmp(debuggerCommands[i].name, cmd)) { - printf("%s %s\t%s\n", + printf("%s %s\n\n%s\n", debuggerCommands[i].name, debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "", debuggerCommands[i].help); @@ -192,9 +270,9 @@ } } -void debuggerPrintBaseType(Type *t, u32 value, u32 location, - LocationType type, - int bitSize, int bitOffset) +static void debuggerPrintBaseType(Type *t, u32 value, u32 location, + LocationType type, + int bitSize, int bitOffset) { if(bitSize) { if(bitOffset) @@ -287,7 +365,7 @@ } } -char *debuggerPrintType(Type *t) +static char *debuggerPrintType(Type *t) { char buffer[1024]; static char buffer2[1024]; @@ -307,12 +385,12 @@ return t->name; } -void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32); -void debuggerPrintValueInternal(Function *f, Type *t, - int bitSize, int bitOffset, - u32 objLocation, LocationType type); +static void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32); +static void debuggerPrintValueInternal(Function *f, Type *t, + int bitSize, int bitOffset, + u32 objLocation, LocationType type); -u32 debuggerGetValue(u32 location, LocationType type) +static u32 debuggerGetValue(u32 location, LocationType type) { switch(type) { case LOCATION_memory: @@ -325,31 +403,31 @@ return 0; } -void debuggerPrintPointer(Type *t, u32 value) +static void debuggerPrintPointer(Type *t, u32 value) { printf("(%s)0x%08x", debuggerPrintType(t), value); } -void debuggerPrintReference(Type *t, u32 value) +static void debuggerPrintReference(Type *t, u32 value) { printf("(%s)0x%08x", debuggerPrintType(t), value); } -void debuggerPrintFunction(Type *t, u32 value) +static void debuggerPrintFunction(Type *t, u32 value) { printf("(%s)0x%08x", debuggerPrintType(t), value); } -void debuggerPrintArray(Type *t, u32 value) +static void debuggerPrintArray(Type *t, u32 value) { // todo printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value); } -void debuggerPrintMember(Function *f, - Member *m, - u32 objLocation, - u32 location) +static void debuggerPrintMember(Function *f, + Member *m, + u32 objLocation, + u32 location) { int bitSize = m->bitSize; if(bitSize) { @@ -392,7 +470,7 @@ } } -void debuggerPrintStructure(Function *f, Type *t, u32 objLocation) +static void debuggerPrintStructure(Function *f, Type *t, u32 objLocation) { printf("{"); int count = t->structure->memberCount; @@ -410,7 +488,7 @@ printf("}"); } -void debuggerPrintUnion(Function *f, Type *t, u32 objLocation) +static void debuggerPrintUnion(Function *f, Type *t, u32 objLocation) { // todo printf("{"); @@ -427,7 +505,7 @@ printf("}"); } -void debuggerPrintEnum(Type *t, u32 value) +static void debuggerPrintEnum(Type *t, u32 value) { int i; for(i = 0; i < t->enumeration->count; i++) { @@ -440,9 +518,9 @@ printf("(UNKNOWN VALUE) %d", value); } -void debuggerPrintValueInternal(Function *f, Type *t, - int bitSize, int bitOffset, - u32 objLocation, LocationType type) +static void debuggerPrintValueInternal(Function *f, Type *t, + int bitSize, int bitOffset, + u32 objLocation, LocationType type) { u32 value = debuggerGetValue(objLocation, type); if(!t) { @@ -480,8 +558,9 @@ } } -void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc, - int bitSize, int bitOffset, u32 objLocation) +static void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc, + int bitSize, int bitOffset, + u32 objLocation) { LocationType type; u32 location; @@ -498,14 +577,14 @@ debuggerPrintValueInternal(f, t, bitSize, bitOffset, location, type); } -void debuggerPrintValue(Function *f, Object *o) +static void debuggerPrintValue(Function *f, Object *o) { debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0); printf("\n"); } -void debuggerSymbols(int argc, char **argv) +static void debuggerSymbols(int argc, char **argv) { int i = 0; u32 value; @@ -550,7 +629,7 @@ } } -void debuggerSetRadix(int argc, char **argv) +static void debuggerSetRadix(int argc, char **argv) { if(argc != 2) debuggerUsage(argv[0]); @@ -578,7 +657,7 @@ } } -void debuggerPrint(int argc, char **argv) +static void debuggerPrint(int argc, char **argv) { if(argc != 2 && argc != 3) { debuggerUsage(argv[0]); @@ -647,7 +726,7 @@ } } -void debuggerHelp(int n, char **args) +static void debuggerHelp(int n, char **args) { if(n == 2) { debuggerUsage(args[1]); @@ -661,7 +740,7 @@ } } -void debuggerDebug(int n, char **args) +static void debuggerDebug(int n, char **args) { if(n == 2) { int v = 0; @@ -672,7 +751,7 @@ debuggerUsage("trace"); } -void debuggerVerbose(int n, char **args) +static void debuggerVerbose(int n, char **args) { if(n == 2) { int v = 0; @@ -683,13 +762,13 @@ debuggerUsage("verbose"); } -void debuggerWhere(int n, char **args) +static void debuggerWhere(int n, char **args) { void elfPrintCallChain(u32); elfPrintCallChain(armNextPC); } -void debuggerLocals(int n, char **args) +static void debuggerLocals(int n, char **args) { Function *f = NULL; CompileUnit *u = NULL; @@ -719,7 +798,7 @@ } } -void debuggerNext(int n, char **args) +static void debuggerNext(int n, char **args) { int count = 1; if(n == 2) { @@ -729,8 +808,10 @@ if(debuggerAtBreakpoint) { debuggerContinueAfterBreakpoint(); debuggerEnableBreakpoints(false); - } else + } else { + debuggerPrefetch(); emulator.emuMain(1); + } } debuggerDisableBreakpoints(); Function *f = NULL; @@ -746,15 +827,16 @@ debuggerRegisters(0, NULL); } -void debuggerContinue(int n, char **args) +static void debuggerContinue(int n, char **args) { if(debuggerAtBreakpoint) debuggerContinueAfterBreakpoint(); debuggerEnableBreakpoints(false); debugger = false; + debuggerPrefetch(); } -void debuggerSignal(int sig,int number) +/*extern*/ void debuggerSignal(int sig,int number) { switch(sig) { case 4: @@ -765,12 +847,21 @@ break; case 5: { - printf("Breakpoint %d reached\n", number); - debugger = true; + bool cond = debuggerCondEvaluate(number & 255); + if(cond) { + printf("Breakpoint %d reached\n", number); + debugger = true; + } else { + debuggerDisableBreakpoints(); + debuggerPrefetch(); + emulator.emuMain(1); + debuggerEnableBreakpoints(false); + return; + } debuggerAtBreakpoint = true; debuggerBreakpointNumber = number; debuggerDisableBreakpoints(); - + Function *f = NULL; CompileUnit *u = NULL; @@ -788,7 +879,7 @@ } } -void debuggerBreakList(int, char **) +static void debuggerBreakList(int, char **) { printf("Num Address Type Symbol\n"); printf("--- -------- ----- ------\n"); @@ -799,13 +890,13 @@ } } -void debuggerBreakDelete(int n, char **args) +static void debuggerBreakDelete(int n, char **args) { if(n == 2) { int n = 0; sscanf(args[1], "%d", &n); - printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints); if(n >= 0 && n < debuggerNumOfBreakpoints) { + printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints); n++; if(n < debuggerNumOfBreakpoints) { for(int i = n; i < debuggerNumOfBreakpoints; i++) { @@ -819,11 +910,13 @@ } debuggerNumOfBreakpoints--; } + else + printf("No breakpoints are set\n"); } else debuggerUsage("bd"); } -void debuggerBreak(int n, char **args) +static void debuggerBreak(int n, char **args) { if(n == 2) { u32 address = 0; @@ -914,7 +1007,7 @@ debuggerUsage("break"); } -void debuggerBreakThumb(int n, char **args) +static void debuggerBreakThumb(int n, char **args) { if(n == 2) { u32 address = 0; @@ -930,7 +1023,7 @@ debuggerUsage("bt"); } -void debuggerBreakArm(int n, char **args) +static void debuggerBreakArm(int n, char **args) { if(n == 2) { u32 address = 0; @@ -946,34 +1039,130 @@ debuggerUsage("ba"); } -void debuggerBreakOnWrite(u32 *mem, u32 oldvalue, u32 value, int size) +/*extern*/ void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value, + int size, int t) { - u32 address = 0; - if(mem >= (u32*)&workRAM[0] && mem <= (u32*)&workRAM[0x3ffff]) - address = 0x2000000 + ((u32)mem - (u32)&workRAM[0]); - else - address = 0x3000000 + ((u32)mem - (u32)&internalRAM[0]); + const char *type = "write"; + if(t == 2) + type = "change"; if(size == 2) - printf("Breakpoint (on write) address %08x old:%08x new:%08x\n", - address, oldvalue, value); + printf("Breakpoint (on %s) address %08x old:%08x new:%08x\n", + type, address, oldvalue, value); else if(size == 1) - printf("Breakpoint (on write) address %08x old:%04x new:%04x\n", - address, (u16)oldvalue,(u16)value); + printf("Breakpoint (on %s) address %08x old:%04x new:%04x\n", + type, address, (u16)oldvalue,(u16)value); else - printf("Breakpoint (on write) address %08x old:%02x new:%02x\n", - address, (u8)oldvalue, (u8)value); + printf("Breakpoint (on %s) address %08x old:%02x new:%02x\n", + type, address, (u8)oldvalue, (u8)value); debugger = true; } -void debuggerBreakWriteClear(int n, char **args) +static void debuggerBreakWriteClear(int n, char **args) { - memset(freezeWorkRAM, false, 0x40000); - memset(freezeInternalRAM, false, 0x8000); - printf("Cleared all break on write\n"); + if(n == 3) { + u32 address = 0; + sscanf(args[1], "%x", &address); + int n = 0; + sscanf(args[2], "%d", &n); + + if (! ((address >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + printf("Invalid address: %08x\n", address); + return; + } + + u32 final = address + n; + switch(address >> 24) { + case 2: + { + address &= 0x3ffff; + final &= 0x3ffff; + for(u32 i = address; i < final; i++) + if(freezeWorkRAM[i] == 1) + freezeWorkRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x2000000+address, 0x2000000+final); + } + break; + case 3: + { + address &= 0x7fff; + final &= 0x7fff; + for(u32 i = address; i < final; i++) + if(freezeInternalRAM[i] == 1) + freezeInternalRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x3000000+address, 0x3000000+final); + } + break; + case 5: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezePRAM[i] == 1) + freezePRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x5000000+address, 0x5000000+final); + } + break; + case 6: + { + if (address > 0x6010000) { + address &= 0x17fff; + final &= 0x17fff; + } else { + address &= 0xffff; + final &= 0xffff; + } + + for (u32 i = address; i < final; i++) + if(freezeVRAM[i] == 1) + freezeVRAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x06000000+address, 0x06000000+final); + } + break; + case 7: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezeOAM[i] == 1) + freezeOAM[i] = 0; + printf("Cleared break on write from %08x to %08x\n", + 0x7000000+address, 0x7000000+final); + } + break; + } + } else if(n == 1) { + int i; + for(i = 0; i < 0x40000; i++) + if(freezeWorkRAM[i] == 1) + freezeWorkRAM[i] = 0; + for(i = 0; i < 0x8000; i++) + if(freezeInternalRAM[i] == 1) + freezeInternalRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezePRAM[i] == 1) + freezePRAM[i] = 0; + for(i = 0; i< 0x18000; i++) + if(freezeVRAM[i] == 1) + freezeVRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezeOAM[i] == 1) + freezeOAM[i] = 0; + + printf("Cleared all break on write\n"); + } else + debuggerUsage("bpwc"); } -void debuggerBreakWrite(int n, char **args) +static void debuggerBreakWrite(int n, char **args) { if(n == 3) { if(cheatsNumber != 0) { @@ -985,15 +1174,187 @@ int n = 0; sscanf(args[2], "%d", &n); - if(address < 0x2000000 || address > 0x3007fff) { - printf("Invalid address: %08x\n", address); + if (! ((address >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + printf("Invalid address: %08x\n", address); + return; + } + + u32 final = address + n; + + if(address < 0x2040000 && final > 0x2040000) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x3008000 && final > 0x3008000) { + printf("Invalid byte count: %d\n", n); return; + } else if(address < 0x05000400 && final > 0x05000400) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x06018000 && final > 0x06018000) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x07000400 && final > 0x07000400) { + printf("Invalid byte count: %d\n", n); + return; + } + + printf("Added break on write at %08x for %d bytes\n", address, n); + + switch(address >> 24) { + case 2: + for (int i = 0; i < n; i++) + freezeWorkRAM[(address + i) & 0x3ffff] = 1; + break; + case 3: + for (int i = 0; i < n; i++) + freezeInternalRAM[(address + i) & 0x7fff] = 1; + break; + case 5: + for (int i = 0; i < n; i++) + freezePRAM[(address + i) & 0x3ff] = 1; + break; + case 6: + // address/range must be valid, so we can use a lazy mask + for (int i = 0; i < n; i++) + freezeVRAM[(address + i) & 0x1ffff] = 1; + break; + case 7: + for (int i = 0; i < n; i++) + freezeOAM[(address + i) & 0x3ff] = 1; + break; + } + + } else + debuggerUsage("bpw"); +} + +static void debuggerBreakChangeClear(int n, char **args) +{ + if(n == 3) { + u32 address = 0; + sscanf(args[1], "%x", &address); + int n = 0; + sscanf(args[2], "%d", &n); + + if (! ((address >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + printf("Invalid address: %08x\n", address); + return; + } + + u32 final = address + n; + switch(address >> 24) { + case 2: + { + address &= 0x3ffff; + final &= 0x3ffff; + for(u32 i = address; i < final; i++) + if(freezeWorkRAM[i] == 2) + freezeWorkRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x2000000+address, 0x2000000+final); + } + break; + case 3: + { + address &= 0x7fff; + final &= 0x7fff; + for(u32 i = address; i < final; i++) + if(freezeInternalRAM[i] == 2) + freezeInternalRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x3000000+address, 0x3000000+final); + } + break; + case 5: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezePRAM[i] == 2) + freezePRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x5000000+address, 0x5000000+final); + } + break; + case 6: + { + if (address > 0x6010000) { + address &= 0x17fff; + final &= 0x17fff; + } else { + address &= 0xffff; + final &= 0xffff; + } + for(u32 i = address; i < final; i++) + if(freezeVRAM[i] == 2) + freezeVRAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x3000000+address, 0x3000000+final); + } + break; + case 7: + { + address &= 0x3ff; + final &= 0x3ff; + for(u32 i = address; i < final; i++) + if(freezeOAM[i] == 2) + freezeOAM[i] = 0; + printf("Cleared break on change from %08x to %08x\n", + 0x7000000+address, 0x7000000+final); + } + break; } + } else if(n == 1) { + int i; + for(i = 0; i < 0x40000; i++) + if(freezeWorkRAM[i] == 2) + freezeWorkRAM[i] = 0; + for(i = 0; i < 0x8000; i++) + if(freezeInternalRAM[i] == 2) + freezeInternalRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezePRAM[i] == 2) + freezePRAM[i] = 0; + for(i = 0; i < 0x18000; i++) + if(freezeVRAM[i] == 2) + freezeVRAM[i] = 0; + for(i = 0; i < 0x400; i++) + if(freezeOAM[i] == 2) + freezeOAM[i] = 0; - if(address > 0x203ffff && address < 0x3000000) { - printf("Invalid address: %08x\n", address); + printf("Cleared all break on change\n"); + } else + debuggerUsage("bpcc"); +} + +static void debuggerBreakChange(int n, char **args) +{ + if(n == 3) { + if(cheatsNumber != 0) { + printf("Cheats are enabled. Cannot continue.\n"); return; } + u32 address = 0; + sscanf(args[1], "%x", &address); + int n = 0; + sscanf(args[2], "%d", &n); + + if (! ((address >= 0x02000000 && address < 0x02040000) || + (address >= 0x03000000 && address < 0x03008000) || + (address >= 0x05000000 && address < 0x05000400) || + (address >= 0x06000000 && address < 0x06018000) || + (address >= 0x07000000 && address < 0x07000400))) { + printf("Invalid address: %08x\n", address); + return; + } u32 final = address + n; @@ -1003,22 +1364,84 @@ } else if(address < 0x3008000 && final > 0x3008000) { printf("Invalid byte count: %d\n", n); return; + } else if(address < 0x6018000 && final > 0x6018000) { + printf("Invalid byte count: %d\n", n); + return; + } else if(address < 0x7000400 && final > 0x7000400) { + printf("Invalid byte count: %d\n", n); + return; } - printf("Added break on write at %08x for %d bytes\n", address, n); - for(int i = 0; i < n; i++) { - if((address >> 24) == 2) - freezeWorkRAM[address & 0x3ffff] = true; - else - freezeInternalRAM[address & 0x7fff] = true; - address++; + printf("Added break on change at %08x for %d bytes\n", address, n); + + switch(address >> 24) { + case 2: + for (int i = 0; i < n; i++) + freezeWorkRAM[(address + i) & 0x3ffff] = 2; + break; + case 3: + for (int i = 0; i < n; i++) + freezeInternalRAM[(address + i) & 0x7fff] = 2; + break; + case 5: + for (int i = 0; i < n; i++) + freezePRAM[(address + i) & 0x3ff] = 2; + break; + case 6: + // address/range must be valid, so we can use a lazy mask + for (int i = 0; i < n; i++) + freezeVRAM[(address + i) & 0x1ffff] = 2; + break; + case 7: + for (int i = 0; i < n; i++) + freezeOAM[(address + i) & 0x3ff] = 2; + break; } + } else - debuggerUsage("bpw"); + debuggerUsage("bpc"); +} + +static void debuggerDisassembleArm(FILE *f, u32 pc, int count) +{ + char buffer[80]; + int i = 0; + u32 len = 0; + char format[30]; + for(i = 0; i < count; i++) { + size_t l = strlen(elfGetAddressSymbol(pc+4*i)); + if(l > len) + len = l; + } + sprintf(format, "%%08x %%-%ds %%s\n", len); + for(i = 0; i < count; i++) { + u32 addr = pc; + pc += disArm(pc, buffer, 2); + fprintf(f, format, addr, elfGetAddressSymbol(addr), buffer); + } } -void debuggerDisassembleArm(int n, char **args) +static void debuggerDisassembleThumb(FILE *f, u32 pc, int count) { char buffer[80]; + int i = 0; + u32 len = 0; + char format[30]; + for(i = 0; i < count; i++) { + size_t l = strlen(elfGetAddressSymbol(pc+2*i)); + if(l > len) + len = l; + } + sprintf(format, "%%08x %%-%ds %%s\n", len); + + for(i = 0; i < count; i++) { + u32 addr = pc; + pc += disThumb(pc, buffer, 2); + fprintf(f, format, addr, elfGetAddressSymbol(addr), buffer); + } +} + +static void debuggerDisassembleArm(int n, char **args) +{ u32 pc = reg[15].I; pc -= 4; int count = 20; @@ -1032,25 +1455,11 @@ if(n >= 3) { sscanf(args[2], "%d", &count); } - int i = 0; - int len = 0; - char format[30]; - for(i = 0; i < count; i++) { - int l = strlen(elfGetAddressSymbol(pc+4*i)); - if(l > len) - len = l; - } - sprintf(format, "%%08x %%-%ds %%s\n", len); - for(i = 0; i < count; i++) { - u32 addr = pc; - pc += disArm(pc, buffer, 2); - printf(format, addr, elfGetAddressSymbol(addr), buffer); - } + debuggerDisassembleArm(stdout, pc, count); } -void debuggerDisassembleThumb(int n, char **args) +static void debuggerDisassembleThumb(int n, char **args) { - char buffer[80]; u32 pc = reg[15].I; pc -= 2; int count = 20; @@ -1064,25 +1473,10 @@ if(n >= 3) { sscanf(args[2], "%d", &count); } - - int i = 0; - int len = 0; - char format[30]; - for(i = 0; i < count; i++) { - int l = strlen(elfGetAddressSymbol(pc+2*i)); - if(l > len) - len = l; - } - sprintf(format, "%%08x %%-%ds %%s\n", len); - - for(i = 0; i < count; i++) { - u32 addr = pc; - pc += disThumb(pc, buffer, 2); - printf(format, addr, elfGetAddressSymbol(addr), buffer); - } + debuggerDisassembleThumb(stdout, pc, count); } -void debuggerDisassemble(int n, char **args) +static void debuggerDisassemble(int n, char **args) { if(armState) debuggerDisassembleArm(n, args); @@ -1090,19 +1484,306 @@ debuggerDisassembleThumb(n, args); } -void debuggerContinueAfterBreakpoint() +static void debuggerFileDisassembleArm(int n, char **args) +{ + u32 pc = reg[15].I; + pc -= 4; + int count = 20; + if(n < 2) { + debuggerUsage("fda"); + return; + } + FILE *f = fopen(args[1], "w+"); + if(!f) { + printf("Error: cannot open file %s\n", args[1]); + return; + } + if(n >= 3) { + sscanf(args[2], "%x", &pc); + } + if(pc & 3) { + printf("Misaligned address %08x\n", pc); + pc &= 0xfffffffc; + } + if(n >= 4) { + sscanf(args[3], "%d", &count); + } + debuggerDisassembleArm(f, pc, count); + fclose(f); +} + +static void debuggerFileDisassembleThumb(int n, char **args) +{ + u32 pc = reg[15].I; + pc -= 2; + int count = 20; + if(n < 2) { + debuggerUsage("fdt"); + return; + } + FILE *f = fopen(args[1], "w+"); + if(!f) { + printf("Error: cannot open file %s\n", args[1]); + return; + } + + if(n >= 3) { + sscanf(args[2], "%x", &pc); + } + if(pc & 1) { + printf("Misaligned address %08x\n", pc); + pc &= 0xfffffffe; + } + if(n >= 4) { + sscanf(args[3], "%d", &count); + } + debuggerDisassembleThumb(f, pc, count); + fclose(f); +} + +void debuggerFindText(int n, char **args) +{ + if ((n == 4) || (n == 3)) + { + SearchResults = 0; + sscanf(args[1], "%x", &SearchStart); + + if (n == 4) + { + sscanf(args[2], "%u", &SearchMaxMatches); + strncpy((char*) SearchData, args[3], 64); + SearchLength = strlen(args[3]); + } + else if (n == 3) + { + strncpy((char*) SearchData, args[2], 64); + SearchLength = strlen(args[2]); + }; + + if (SearchLength > 64) + { + printf ("Entered string (length: %d) is longer than 64 bytes and was cut.\n", SearchLength); + SearchLength = 64; + }; + + debuggerDoSearch (); + + } else + debuggerUsage("ft"); +}; + +void debuggerFindHex(int n, char **args) +{ + if ((n == 4) || (n == 3)) + { + SearchResults = 0; + sscanf(args[1], "%x", &SearchStart); + + char SearchHex [128]; + if (n == 4) + { + sscanf(args[2], "%u", &SearchMaxMatches); + strncpy(SearchHex, args[3], 128); + SearchLength = strlen(args[3]); + } + else if (n == 3) + { + strncpy(SearchHex, args[2], 128); + SearchLength = strlen(args[2]); + }; + + if (SearchLength & 1) + printf ("Unaligned bytecount: %d,5. Last digit (%c) cut.\n", SearchLength / 2, SearchHex [SearchLength - 1]); + + SearchLength /= 2; + + if (SearchLength > 64) + { + printf ("Entered string (length: %d) is longer than 64 bytes and was cut.\n", SearchLength); + SearchLength = 64; + }; + + for (unsigned int i = 0; i < SearchLength; i++) + { + unsigned int cbuf = 0; + sscanf (&SearchHex [i << 1], "%02x", &cbuf); + SearchData [i] = cbuf; + }; + + debuggerDoSearch (); + + } else + debuggerUsage("fh"); +}; + +void debuggerFindResume(int n, char **args) +{ + if ((n == 1) || (n == 2)) + { + if (SearchLength == 0) + { + printf("Error: No search in progress. Start a search with ft or fh.\n"); + debuggerUsage("fr"); + return; + }; + + if (n == 2) + sscanf(args[1], "%u", &SearchMaxMatches); + + debuggerDoSearch(); + + } else + debuggerUsage("fr"); +}; + +void debuggerDoSearch() +{ + int count = 0; + + while (true) + { + unsigned int final = SearchStart + SearchLength - 1; + u8* end; + u8* start; + + switch (SearchStart >> 24) + { + case 0: + if (final > 0x00003FFF) { SearchStart = 0x02000000; continue; } + else { start = bios + (SearchStart & 0x3FFF); end = bios + 0x3FFF; break; }; + case 2: + if (final > 0x0203FFFF) { SearchStart = 0x03000000; continue; } + else { start = workRAM + (SearchStart & 0x3FFFF); end = workRAM + 0x3FFFF; break; }; + case 3: + if (final > 0x03007FFF) { SearchStart = 0x04000000; continue; } + else { start = internalRAM + (SearchStart & 0x7FFF); end = internalRAM + 0x7FFF; break; }; + case 4: + if (final > 0x040003FF) { SearchStart = 0x05000000; continue; } + else { start = ioMem + (SearchStart & 0x3FF); end = ioMem + 0x3FF; break; }; + case 5: + if (final > 0x050003FF) { SearchStart = 0x06000000; continue; } + else { start = paletteRAM + (SearchStart & 0x3FF); end = paletteRAM + 0x3FF; break; }; + case 6: + if (final > 0x0601FFFF) { SearchStart = 0x07000000; continue; } + else { start = vram + (SearchStart & 0x1FFFF); end = vram + 0x1FFFF; break; }; + case 7: + if (final > 0x070003FF) { SearchStart = 0x08000000; continue; } + else { start = oam + (SearchStart & 0x3FF); end = oam + 0x3FF; break; }; + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + if (final <= 0x09FFFFFF) + { start = rom + (SearchStart & 0x01FFFFFF); end = rom + 0x01FFFFFF; break; }; + default: + printf ("Search completed.\n"); + SearchLength = 0; + return; + }; + + end -= SearchLength - 1; + u8 firstbyte = SearchData [0]; + while (start <= end) + { + while ((start <= end) && (*start != firstbyte)) + start++; + + if (start > end) + break; + + unsigned int p = 1; + while ((start [p] == SearchData [p]) && (p < SearchLength)) + p++; + + if (p == SearchLength) + { + printf ("Search result (%d): %08x\n", count + SearchResults, AddressToGBA (start)); + count++; + if (count == SearchMaxMatches) + { + SearchStart = AddressToGBA (start + p); + SearchResults += count; + return; + }; + + start += p; // assume areas don't overlap; alternative: start++; + } else + start++; + }; + + SearchStart = AddressToGBA (end + SearchLength - 1) + 1; + }; +}; + +unsigned int AddressToGBA(u8* mem) +{ + if(mem >= &bios[0] && mem <= &bios[0x3fff]) + return 0x00000000 + (mem - &bios[0]); + else if(mem >= &workRAM[0] && mem <= &workRAM[0x3ffff]) + return 0x02000000 + (mem - &workRAM[0]); + else if(mem >= &internalRAM[0] && mem <= &internalRAM[0x7fff]) + return 0x03000000 + (mem - &internalRAM[0]); + else if(mem >= &ioMem[0] && mem <= &ioMem[0x3ff]) + return 0x04000000 + (mem - &ioMem[0]); + else if(mem >= &paletteRAM[0] && mem <= &paletteRAM[0x3ff]) + return 0x05000000 + (mem - &paletteRAM[0]); + else if(mem >= &vram[0] && mem <= &vram[0x1ffff]) + return 0x06000000 + (mem - &vram[0]); + else if(mem >= &oam[0] && mem <= &oam[0x3ff]) + return 0x07000000 + (mem - &oam[0]); + else if(mem >= &rom[0] && mem <= &rom[0x1ffffff]) + return 0x08000000 + (mem - &rom[0]); + else + return 0xFFFFFFFF; +}; + +static void debuggerFileDisassemble(int n, char **args) +{ + if(n < 2) { + debuggerUsage("fd"); + } else { + if(armState) + debuggerFileDisassembleArm(n, args); + else + debuggerFileDisassembleThumb(n, args); + } +} + +static void debuggerContinueAfterBreakpoint() { printf("Continuing after breakpoint\n"); debuggerEnableBreakpoints(true); + debuggerPrefetch(); emulator.emuMain(1); debuggerAtBreakpoint = false; } -void debuggerRegisters(int, char **) +static void debuggerRegisters(int, char **) { char *command[3]; char buffer[10]; +#ifdef BKPT_SUPPORT + if (debugger_last) + { + printf("R00=%08x R04=%08x R08=%08x R12=%08x\n", + oldreg[0], oldreg[4], oldreg[8], oldreg[12]); + printf("R01=%08x R05=%08x R09=%08x R13=%08x\n", + oldreg[1], oldreg[5], oldreg[9], oldreg[13]); + printf("R02=%08x R06=%08x R10=%08x R14=%08x\n", + oldreg[2], oldreg[6], oldreg[10], oldreg[14]); + printf("R03=%08x R07=%08x R11=%08x R15=%08x\n", + oldreg[3], oldreg[7], oldreg[11], oldreg[15]); + command[0]="m"; + command[1]=oldbuffer; + command[2]="1"; + debuggerDisassemble(3, command); + printf("\n"); + } +#endif + printf("R00=%08x R04=%08x R08=%08x R12=%08x\n", reg[0].I, reg[4].I, reg[8].I, reg[12].I); printf("R01=%08x R05=%08x R09=%08x R13=%08x\n", @@ -1128,7 +1809,7 @@ debuggerDisassemble(3, command); } -void debuggerIoVideo() +static void debuggerIoVideo() { printf("DISPCNT = %04x\n", DISPCNT); printf("DISPSTAT = %04x\n", DISPSTAT); @@ -1149,7 +1830,7 @@ printf("COLY = %04x\n", COLY); } -void debuggerIoVideo2() +static void debuggerIoVideo2() { printf("BG0HOFS = %04x\n", BG0HOFS); printf("BG0VOFS = %04x\n", BG0VOFS); @@ -1173,7 +1854,7 @@ printf("BG3Y = %08x\n", (BG3Y_H<<16)|BG3Y_L); } -void debuggerIoDMA() +static void debuggerIoDMA() { printf("DM0SAD = %08x\n", (DM0SAD_H<<16)|DM0SAD_L); printf("DM0DAD = %08x\n", (DM0DAD_H<<16)|DM0DAD_L); @@ -1189,7 +1870,7 @@ printf("DM3CNT = %08x\n", (DM3CNT_H<<16)|DM3CNT_L); } -void debuggerIoTimer() +static void debuggerIoTimer() { printf("TM0D = %04x\n", TM0D); printf("TM0CNT = %04x\n", TM0CNT); @@ -1201,7 +1882,7 @@ printf("TM3CNT = %04x\n", TM3CNT); } -void debuggerIoMisc() +static void debuggerIoMisc() { printf("P1 = %04x\n", P1); printf("IE = %04x\n", IE); @@ -1209,7 +1890,7 @@ printf("IME = %04x\n", IME); } -void debuggerIo(int n, char **args) +static void debuggerIo(int n, char **args) { if(n == 1) { debuggerIoVideo(); @@ -1228,11 +1909,11 @@ else printf("Unrecognized option %s\n", args[1]); } -void debuggerEditByte(int n, char **args) +static void debuggerEditByte(int n, char **args) { if(n == 3) { - u32 address; - u32 byte; + u32 address = 0x10000; + u32 byte = 0; sscanf(args[1], "%x", &address); sscanf(args[2], "%x", &byte); debuggerWriteByte(address, (u8)byte); @@ -1240,23 +1921,41 @@ debuggerUsage("eb"); } -void debuggerEditHalfWord(int n, char **args) +static void debuggerEditHalfWord(int n, char **args) { if(n == 3) { - u32 address; - u32 byte; + u32 address = 0x10000; + u32 HalfWord = 0; sscanf(args[1], "%x", &address); if(address & 1) { printf("Error: address must be half-word aligned\n"); return; } - sscanf(args[2], "%x", &byte); - debuggerWriteHalfWord(address, (u16)byte); + sscanf(args[2], "%x", &HalfWord); + debuggerWriteHalfWord(address, (u16)HalfWord); } else debuggerUsage("eh"); } -void debuggerEdit(int n, char **args) +static void debuggerEditRegister(int n, char **args) +{ + if(n == 3) { + int r = 15; + u32 val; + sscanf(args[1], "%d", &r); + if(r > 16 || r == 15) { + // don't allow PC to change + printf("Error: Register must be valid (0-14,16)\n"); + return; + } + sscanf(args[2], "%x", &val); + reg[r].I=val; + printf("Register changed.\n"); + } else + debuggerUsage("er"); +} + +static void debuggerEdit(int n, char **args) { if(n == 3) { u32 address; @@ -1275,12 +1974,12 @@ #define ASCII(c) (c) < 32 ? '.' : (c) > 127 ? '.' : (c) -void debuggerMemoryByte(int n, char **args) +static void debuggerMemoryByte(int n, char **args) { if(n == 2) { u32 addr = 0; sscanf(args[1], "%x", &addr); - for(int i = 0; i < 16; i++) { + for(int _i = 0; _i < 16; _i++) { int a = debuggerReadByte(addr); int b = debuggerReadByte(addr+1); int c = debuggerReadByte(addr+2); @@ -1310,13 +2009,13 @@ debuggerUsage("mb"); } -void debuggerMemoryHalfWord(int n, char **args) +static void debuggerMemoryHalfWord(int n, char **args) { if(n == 2) { u32 addr = 0; sscanf(args[1], "%x", &addr); addr = addr & 0xfffffffe; - for(int i = 0; i < 16; i++) { + for(int _i = 0; _i < 16; _i++) { int a = debuggerReadByte(addr); int b = debuggerReadByte(addr+1); int c = debuggerReadByte(addr+2); @@ -1346,13 +2045,13 @@ debuggerUsage("mh"); } -void debuggerMemory(int n, char **args) +static void debuggerMemory(int n, char **args) { if(n == 2) { u32 addr = 0; sscanf(args[1], "%x", &addr); addr = addr & 0xfffffffc; - for(int i = 0; i < 16; i++) { + for(int _i = 0; _i < 16; _i++) { int a = debuggerReadByte(addr); int b = debuggerReadByte(addr+1); int c = debuggerReadByte(addr+2); @@ -1385,7 +2084,7 @@ debuggerUsage("mw"); } -void debuggerQuit(int, char **) +static void debuggerQuit(int, char **) { char buffer[10]; printf("Are you sure you want to quit (y/n)? "); @@ -1397,7 +2096,450 @@ } } -void debuggerOutput(char *s, u32 addr) +static void debuggerWriteState(int n, char **args) +{ + int num = 12; + + if(n == 2) { + sscanf(args[1],"%d",&num); + if(num > 0 && num < 11) + sdlWriteState(num-1); + else + printf("Savestate number must be in the 1-10 range"); + } + else + debuggerUsage("save"); +} + +static void debuggerReadState(int n, char **args) +{ + int num = 12; + + if(n == 2) { + sscanf(args[1],"%d",&num); + if(num > 0 && num < 11) + sdlReadState(num-1); + else + printf("Savestate number must be in the 1-10 range"); + } + else + debuggerUsage("load"); +} + +static void debuggerDumpLoad(int n, char** args) +{ + u32 address = 0; + char *file; + FILE *f; + int c; + + if(n==3) { + file=args[1]; + + sscanf(args[2],"%x",&address); + + f=fopen(file,"rb"); + if(!f) { + printf("Error opening file.\n"); + return; + } + + fseek(f,0,SEEK_END); + int size=ftell(f); + fseek(f,0,SEEK_SET); + + for(int i=0;i 4) { //conditional args handled separately + int i = debuggerNumOfBreakpoints; + + u32 address = 0; + sscanf(args[1],"%x", &address); + + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = debuggerReadHalfWord(address); + debuggerBreakpointList[i].size = 0; + + debuggerCondValidate(n, args,2); + } else + debuggerUsage("cbt"); + +} + +static void debuggerCondBreakArm(int n, char **args) +{ + if(n > 4) { //conditional args handled separately + + int i = debuggerNumOfBreakpoints; + u32 address = 0; + + sscanf(args[1],"%x", &address); + debuggerBreakpointList[i].address = address; + debuggerBreakpointList[i].value = debuggerReadMemory(address); + debuggerBreakpointList[i].size = 1; + debuggerCondValidate(n, args,2); + } else + debuggerUsage("cba"); +} + +static void debuggerCondValidate(int n,char **args,int start) +{ + /* + 0: address/register + 1: op + 2: value + 3: size + */ + + int i=debuggerNumOfBreakpoints; + + char *address=args[start]; + char *op=args[start+1]; + char *value=args[start+2]; + char *tsize,*taddress,*tvalue; + + int rel=0; + + u32 value1=0; + u32 value2=0; + + char size=0; + int j=1; + + if(n==6) { + size = args[start+3][0]; + if(size != 'b' && size != 'h' && size != 'w') { + printf("Invalid size.\n"); + return; + } + + switch(size) { + case 'b': + debuggerBreakpointList[i].cond_size=1; + tsize="byte"; + break; + case 'h': + debuggerBreakpointList[i].cond_size=2; + tsize="halfword"; + break; + case 'w': + debuggerBreakpointList[i].cond_size=4; + tsize="word"; + break; + } + } + + switch(toupper(address[0])) { + case '$': //is address + while (address[j]) { + address[j-1]=address[j]; + j++; + } + address[j-1]=0; + + sscanf(address,"%x",&value1); + switch(size) { + case 'h': + if(value1 & 1) { + printf("Misaligned Conditional Address.\n"); + return; + } + break; + case 'w': + if(value1 & 3) { + printf("Misaligned Conditional Address.\n"); + return; + } + case 'b': + break; + default: + printf("Erroneous Condition\n"); + debuggerUsage((char *)((toupper(args[0][2])=='T') ? "cbt" : "cba")); + return; + } + debuggerBreakpointList[i].ia1=true; + taddress="$"; + break; + case 'R': //is register + while(address[j]) { + address[j-1]=address[j]; + j++; + } + address[j-1]=0; + sscanf(address,"%d",&value1); + + if(value1 > 16) { + printf("Invalid Register.\n"); + return; + } + if(size) + size=0; + debuggerBreakpointList[i].ia1=true; + taddress="r"; + break; + default: //immediate; + printf("First Comparison Parameter should not be Immediate\n"); + return; + } + + debuggerBreakpointList[i].cond_address = value1; + + // Check op + switch(op[0]) { + case '=': // 1 + if (op[1] == '=' && op[2]==0) + rel=1; + else + goto error; + break; + case '!': //2 + if (op[1]=='=' && op[2]==0) + rel=2; + else + goto error; + break; + case '<': //3 + if(op[1]=='=') + rel=5; + else if (op[1]==0) + rel=3; + else + goto error; + break; + case '>': //4 + if (op[1]=='=') + rel=6; + else if (op[1]==0) + rel=4; + else + goto error; + break; + default: + error: + printf("Invalid comparison operator.\n"); + return; + } + + if(op==0) { + printf("Invalid comparison operator.\n"); + return; + } + debuggerBreakpointList[i].cond_rel=rel; + + switch(toupper(value[0])) { + case '$': //is address + while(value[j]) { + value[j-1]=value[j]; + j++; + } + value[j-1]=0; + + sscanf(value,"%x",&value2); + debuggerBreakpointList[i].ia2=true; + tvalue="$"; + switch(size) { + case 'h': + if(value2 & 1) { + printf("Misaligned Conditional Address.\n"); + return; + } + break; + case 'w': + if(value2 & 3) { + printf("Misaligned Conditional Address.\n"); + return; + } + case 'b': + break; + default: + printf("Erroneous Condition\n"); + debuggerUsage((char *)((toupper(args[0][2])=='T') ? "cbt" : "cba")); + return; + } + break; + case 'R': //is register + while(value[j]) { + value[j-1]=value[j]; + j++; + } + value[j-1]=0; + sscanf(value,"%d",&value2); + + if(value2 > 16) { + printf("Invalid Register.\n"); + return; + } + debuggerBreakpointList[i].ia2=true; + tvalue="r"; + break; + default: //immediate; + sscanf(value, "%x",&value2); + debuggerBreakpointList[i].ia2=false; + tvalue="0x"; + + switch(size) { + case 'b': + value2 &=0xFF; + break; + case 'h': + value2 &=0xFFFF; + break; + default: + case 'w': + value2 &=0xFFFFFFFF; + break; + } + break; + } + + debuggerBreakpointList[i].cond_value = value2; + debuggerNumOfBreakpoints++; + + // At here, everything's set. Display message. + switch(size) { + case 0: + printf("Added breakpoint on %08X if R%02d %s %08X\n", + debuggerBreakpointList[i].address, + debuggerBreakpointList[i].cond_address, + op, + debuggerBreakpointList[i].cond_value); + break; + case 'b': + printf("Added breakpoint on %08X if %s%08X %s %s%02X\n", + debuggerBreakpointList[i].address, + taddress, + debuggerBreakpointList[i].cond_address, + op,tvalue, + debuggerBreakpointList[i].cond_value); + break; + case 'h': + printf("Added breakpoint on %08X if %s%08X %s %s%04X\n", + debuggerBreakpointList[i].address, + taddress, + debuggerBreakpointList[i].cond_address, + op, + tvalue, + debuggerBreakpointList[i].cond_value); + break; + case 'w': + printf("Added breakpoint on %08X if %s%08X %s %s%08X\n", + debuggerBreakpointList[i].address, + taddress, + debuggerBreakpointList[i].cond_address, + op,tvalue, + debuggerBreakpointList[i].cond_value); + break; + } +} + +static bool debuggerCondEvaluate(int num) +{ + // check if there is a condition + if(debuggerBreakpointList[num].cond_rel == 0) + return true; + + u32 address=debuggerBreakpointList[num].cond_address; + char size=debuggerBreakpointList[num].cond_size; + u32 value=debuggerBreakpointList[num].cond_value; + u32 value1=0; + u32 value2=0; + + if(address<17) + value1=reg[address].I; + else { + switch(size) { + case 1: + value1=debuggerReadByte(address); + break; + case 2: + value1=debuggerReadHalfWord(address); + break; + default: + value1=debuggerReadMemory(address); + break; + } + } + + //value2 + if(debuggerBreakpointList[num].ia2) { //is address or register + if(value<17) + value2=reg[address].I; + else { + switch(size) { + case 'b': + value2=debuggerReadByte(value); + break; + case 'h': + value2=debuggerReadHalfWord(value); + break; + default: + value2=debuggerReadMemory(value); + break; + } + } + } else + value2=value; + + switch(debuggerBreakpointList[num].cond_rel) { + case 1: // == + return (value1 == value2); + case 2: // != + return (value1 != value2); + case 3: // < + return (value1 < value2); + case 4: // > + return (value1 > value2); + case 5: // <= + return (value1 <= value2); + case 6: // >= + return (value1 >= value2); + default: + return false; //should never happen + } +} + +/*extern*/ void debuggerOutput(char *s, u32 addr) { if(s) printf(s); @@ -1414,7 +2556,65 @@ } } -void debuggerMain() +char* strqtok (char* string, const char* ctrl) +{ // quoted tokens + static char* nexttoken = NULL; + char* str; + + if (string != NULL) + str = string; + else { + if (nexttoken == NULL) + return NULL; + str = nexttoken; + }; + + char deli [32]; + memset (deli, 0, 32 * sizeof (char)); + while (*ctrl) + { + deli [*ctrl >> 3] |= (1 << (*ctrl & 7)); + ctrl++; + }; + // can't allow to be set + deli ['"' >> 3] &= ~(1 << ('"' & 7)); + + // jump over leading delimiters + while ((deli [*str >> 3] & (1 << (*str & 7))) && *str) + str++; + + if (*str == '"') + { + string = ++str; + + // only break if another quote or end of string is found + while ((*str != '"') && *str) + str++; + } else { + string = str; + + // break on delimiter + while (!(deli [*str >> 3] & (1 << (*str & 7))) && *str) + str++; + }; + + if (string == str) + { + nexttoken = NULL; + return NULL; + } else { + if (*str) + { + *str = 0; + nexttoken = str + 1; + } else + nexttoken = NULL; + + return string; + }; +}; + +/*extern*/ void debuggerMain() { char buffer[1024]; char *commands[10]; @@ -1426,15 +2626,16 @@ while(debugger) { systemSoundPause(); + debuggerDisableBreakpoints(); printf("debugger> "); commandCount = 0; char *s = fgets(buffer, 1024, stdin); - commands[0] = strtok(s, " \t\n"); + commands[0] = strqtok(s, " \t\n"); if(commands[0] == NULL) continue; commandCount++; - while((s = strtok(NULL, " \t\n"))) { + while((s = strqtok(NULL, " \t\n"))) { commands[commandCount++] = s; if(commandCount == 10) break; @@ -1452,3 +2653,12 @@ } } } + +void debuggerLast(int n, char **args) +{ +debugger_last =!debugger_last; +if (debugger_last == true) +printf ("Last registers will be shown\n"); +else +printf ("Last registers wont be shown\n"); +} diff -urN ../VisualBoyAdvance-1.7.2/src/thumb.h ./src/thumb.h --- ../VisualBoyAdvance-1.7.2/src/thumb.h 2004-05-13 22:50:06 +0900 +++ ./src/thumb.h 2006-06-25 05:21:47 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -17,6 +17,17 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// The following define updates oldreg when debugger_last is activated + +#define UPDATE_OLD_REG \ + if (debugger_last) { \ + sprintf(oldbuffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 4); \ + for (xxx=0; xxx<18; xxx++){ \ + oldreg[xxx]=reg[xxx].I; \ + } \ + } + + #ifdef C_CORE #define NEG(i) ((i) >> 31) #define POS(i) ((~(i)) >> 31) @@ -763,16 +774,29 @@ #endif #endif -u32 opcode = CPUReadHalfWordQuick(armNextPC); -clockTicks = thumbCycles[opcode >> 8] + memoryWaitFetch[(armNextPC >> 24) & 15]; + +#ifdef BKPT_SUPPORT +u8 xxx; +#endif + +u32 opcode = cpuPrefetch[0]; +cpuPrefetch[0] = cpuPrefetch[1]; + +busPrefetch = false; + if (busPrefetchCount & 0xFFFFFF00) + busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF); + +clockTicks = 0; +u32 oldArmNextPC = armNextPC; #ifndef FINAL_VERSION if(armNextPC == stop) { - armNextPC = armNextPC++; + armNextPC++; } #endif armNextPC = reg[15].I; reg[15].I += 2; +THUMB_PREFETCH_NEXT; switch(opcode >> 8) { case 0x00: @@ -901,54 +925,22 @@ } break; case 0x20: - // MOV R0, #Offset8 - reg[0].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[0].I ? false : true); - break; case 0x21: - // MOV R1, #Offset8 - reg[1].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[1].I ? false : true); - break; case 0x22: - // MOV R2, #Offset8 - reg[2].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[2].I ? false : true); - break; case 0x23: - // MOV R3, #Offset8 - reg[3].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[3].I ? false : true); - break; case 0x24: - // MOV R4, #Offset8 - reg[4].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[4].I ? false : true); - break; case 0x25: - // MOV R5, #Offset8 - reg[5].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[5].I ? false : true); - break; case 0x26: - // MOV R6, #Offset8 - reg[6].I = opcode & 255; - N_FLAG = false; - Z_FLAG = (reg[6].I ? false : true); - break; case 0x27: - // MOV R7, #Offset8 - reg[7].I = opcode & 255; + { + u8 regist = (opcode >> 8) & 7; + // MOV R0~R7, #Offset8 + reg[regist].I = opcode & 255; N_FLAG = false; - Z_FLAG = (reg[7].I ? false : true); + Z_FLAG = (reg[regist].I ? false : true); + } break; - case 0x28: +case 0x28: // CMP R0, #Offset8 CMP_RN_O8(0); break; @@ -1044,6 +1036,7 @@ // SUB R7,#Offset8 SUB_RN_O8(7); break; + case 0x40: switch((opcode >> 6) & 3) { case 0x00: @@ -1093,7 +1086,7 @@ } N_FLAG = reg[dest].I & 0x80000000 ? true : false; Z_FLAG = reg[dest].I ? false : true; - clockTicks++; + clockTicks = codeTicksAccess16(armNextPC)+2; } break; case 0x03: @@ -1115,7 +1108,7 @@ } N_FLAG = reg[dest].I & 0x80000000 ? true : false; Z_FLAG = reg[dest].I ? false : true; - clockTicks++; + clockTicks = codeTicksAccess16(armNextPC)+2; } break; } @@ -1144,7 +1137,7 @@ } N_FLAG = reg[dest].I & 0x80000000 ? true : false; Z_FLAG = reg[dest].I ? false : true; - clockTicks++; + clockTicks = codeTicksAccess16(armNextPC)+2; } break; case 0x01: @@ -1181,7 +1174,7 @@ reg[dest].I = value; } } - clockTicks++; + clockTicks = codeTicksAccess16(armNextPC)+2; N_FLAG = reg[dest].I & 0x80000000 ? true : false; Z_FLAG = reg[dest].I ? false : true; } @@ -1239,19 +1232,22 @@ case 0x01: { // MUL Rd, Rs + clockTicks = 1; int dest = opcode & 7; - u32 rm = reg[(opcode >> 3) & 7].I; - reg[dest].I = reg[dest].I * rm; + u32 rm = reg[dest].I; + reg[dest].I = reg[(opcode >> 3) & 7].I * rm; if (((s32)rm) < 0) rm = ~rm; if ((rm & 0xFFFFFF00) == 0) - clockTicks += 1; + clockTicks += 0; else if ((rm & 0xFFFF0000) == 0) - clockTicks += 2; + clockTicks += 1; else if ((rm & 0xFF000000) == 0) - clockTicks += 3; + clockTicks += 2; else - clockTicks += 4; + clockTicks += 3; + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccess16(armNextPC) + 1; Z_FLAG = reg[dest].I ? false : true; N_FLAG = reg[dest].I & 0x80000000 ? true : false; } @@ -1294,7 +1290,9 @@ reg[15].I &= 0xFFFFFFFE; armNextPC = reg[15].I; reg[15].I += 2; - clockTicks++; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC)+1; + clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1; } break; case 3: @@ -1304,7 +1302,9 @@ reg[15].I &= 0xFFFFFFFE; armNextPC = reg[15].I; reg[15].I += 2; - clockTicks++; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC)+1; + clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1; } break; } @@ -1359,20 +1359,33 @@ // MOV Hd, Rs reg[dest+8].I = reg[base].I; if(dest == 7) { +#ifdef BKPT_SUPPORT + UPDATE_OLD_REG +#endif + reg[15].I &= 0xFFFFFFFE; armNextPC = reg[15].I; reg[15].I += 2; - clockTicks++; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC)+1; + clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1; } break; case 3: // MOV Hd, Hs reg[dest+8].I = reg[base+8].I; if(dest == 7) { + +#ifdef BKPT_SUPPORT + UPDATE_OLD_REG +#endif + reg[15].I &= 0xFFFFFFFE; armNextPC = reg[15].I; reg[15].I += 2; - clockTicks++; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC)+1; + clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1; } break; } @@ -1381,33 +1394,54 @@ case 0x47: { int base = (opcode >> 3) & 7; + busPrefetchCount=0; switch((opcode >>6) & 3) { case 0: // BX Rs +#ifdef BKPT_SUPPORT + UPDATE_OLD_REG +#endif reg[15].I = (reg[base].I) & 0xFFFFFFFE; if(reg[base].I & 1) { armState = false; armNextPC = reg[15].I; reg[15].I += 2; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC) + + codeTicksAccessSeq16(armNextPC) + 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; } break; case 1: // BX Hs + +#ifdef BKPT_SUPPORT + UPDATE_OLD_REG +#endif + reg[15].I = (reg[8+base].I) & 0xFFFFFFFE; if(reg[8+base].I & 1) { armState = false; armNextPC = reg[15].I; reg[15].I += 2; + THUMB_PREFETCH; + clockTicks = dataTicksAccess16(armNextPC) + dataTicksAccess16(armNextPC) + + codeTicksAccess16(armNextPC) + 3; } else { armState = true; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; + ARM_PREFETCH; + clockTicks = dataTicksAccess32(armNextPC) + dataTicksAccess32(armNextPC) + + codeTicksAccess32(armNextPC) + 3; } break; default: @@ -1416,143 +1450,119 @@ } break; case 0x48: - // LDR R0,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[0].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x49: - // LDR R1,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[1].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x4a: - // LDR R2,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[2].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x4b: - // LDR R3,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[3].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x4c: - // LDR R4,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[4].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x4d: - // LDR R5,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[5].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x4e: - // LDR R6,[PC, #Imm] - { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[6].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x4f: - // LDR R7,[PC, #Imm] + // LDR R0~R7,[PC, #Imm] { - u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - reg[7].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); + u8 regist = (opcode >> 8) & 7; + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; + u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[regist].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccess32(address) + + codeTicksAccess16(armNextPC); } break; case 0x50: case 0x51: // STR Rd, [Rs, Rn] { - u32 - address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; + u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; CPUWriteMemory(address, reg[opcode & 7].I); - clockTicks += CPUUpdateTicksAccess32(address); + clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2; } break; case 0x52: case 0x53: // STRH Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; CPUWriteHalfWord(address, reg[opcode&7].W.W0); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; } break; case 0x54: case 0x55: // STRB Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I; CPUWriteByte(address, reg[opcode & 7].B.B0); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; } break; case 0x56: case 0x57: // LDSB Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; reg[opcode&7].I = (s8)CPUReadByte(address); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = 3 + dataTicksAccess16(address) + + codeTicksAccess16(armNextPC); } break; case 0x58: case 0x59: // LDR Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; reg[opcode&7].I = CPUReadMemory(address); - clockTicks += CPUUpdateTicksAccess32(address); + clockTicks = 3 + dataTicksAccess32(address) + + codeTicksAccess16(armNextPC); } break; case 0x5a: case 0x5b: // LDRH Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; reg[opcode&7].I = CPUReadHalfWord(address); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = 3 + dataTicksAccess32(address) + + codeTicksAccess16(armNextPC); } break; case 0x5c: case 0x5d: // LDRB Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; reg[opcode&7].I = CPUReadByte(address); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = 3 + dataTicksAccess16(address) + + codeTicksAccess16(armNextPC); } break; case 0x5e: case 0x5f: // LDSH Rd, [Rs, Rn] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = 3 + dataTicksAccess16(address) + + codeTicksAccess16(armNextPC); } break; case 0x60: @@ -1565,10 +1575,12 @@ case 0x67: // STR Rd, [Rs, #Imm] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); CPUWriteMemory(address, reg[opcode&7].I); - clockTicks += CPUUpdateTicksAccess32(address); + clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2; } break; case 0x68: @@ -1581,9 +1593,12 @@ case 0x6f: // LDR Rd, [Rs, #Imm] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); reg[opcode&7].I = CPUReadMemory(address); - clockTicks += CPUUpdateTicksAccess32(address); + clockTicks = 3 + dataTicksAccess32(address) + + codeTicksAccess16(armNextPC); } break; case 0x70: @@ -1596,10 +1611,12 @@ case 0x77: // STRB Rd, [Rs, #Imm] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)); CPUWriteByte(address, reg[opcode&7].B.B0); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; } break; case 0x78: @@ -1612,9 +1629,12 @@ case 0x7f: // LDRB Rd, [Rs, #Imm] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)); reg[opcode&7].I = CPUReadByte(address); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = 3 + dataTicksAccess16(address) + + codeTicksAccess16(armNextPC); } break; case 0x80: @@ -1627,10 +1647,12 @@ case 0x87: // STRH Rd, [Rs, #Imm] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); CPUWriteHalfWord(address, reg[opcode&7].W.W0); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2; } break; case 0x88: @@ -1643,203 +1665,79 @@ case 0x8f: // LDRH Rd, [Rs, #Imm] { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); reg[opcode&7].I = CPUReadHalfWord(address); - clockTicks += CPUUpdateTicksAccess16(address); + clockTicks = 3 + dataTicksAccess16(address) + + codeTicksAccess16(armNextPC); } break; case 0x90: - // STR R0, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[0].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x91: - // STR R1, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[1].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x92: - // STR R2, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[2].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x93: - // STR R3, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[3].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x94: - // STR R4, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[4].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x95: - // STR R5, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[5].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x96: - // STR R6, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[6].I); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x97: - // STR R7, [SP, #Imm] + // STR R0~R7, [SP, #Imm] { - u32 address = reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, reg[7].I); - clockTicks += CPUUpdateTicksAccess32(address); + u8 regist = (opcode >> 8) & 7; + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; + u32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[regist].I); + clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2; } - break; + break; case 0x98: - // LDR R0, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[0].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x99: - // LDR R1, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[1].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x9a: - // LDR R2, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[2].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x9b: - // LDR R3, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[3].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x9c: - // LDR R4, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[4].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x9d: - // LDR R5, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[5].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x9e: - // LDR R6, [SP, #Imm] - { - u32 address = reg[13].I + ((opcode&255)<<2); - reg[6].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); - } - break; case 0x9f: - // LDR R7, [SP, #Imm] + // LDR R0~R7, [SP, #Imm] { + u8 regist = (opcode >> 8) & 7; + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; u32 address = reg[13].I + ((opcode&255)<<2); - reg[7].I = CPUReadMemoryQuick(address); - clockTicks += CPUUpdateTicksAccess32(address); + reg[regist].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccess32(address) + + codeTicksAccess16(armNextPC); } break; case 0xa0: - // ADD R0, PC, Imm - reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa1: - // ADD R1, PC, Imm - reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa2: - // ADD R2, PC, Imm - reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa3: - // ADD R3, PC, Imm - reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa4: - // ADD R4, PC, Imm - reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa5: - // ADD R5, PC, Imm - reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa6: - // ADD R6, PC, Imm - reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); - break; case 0xa7: - // ADD R7, PC, Imm - reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + { + // ADD R0~R7, PC, Imm + u8 regist = (opcode >> 8) & 7; + reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + } break; case 0xa8: - // ADD R0, SP, Imm - reg[0].I = reg[13].I + ((opcode&255)<<2); - break; case 0xa9: - // ADD R1, SP, Imm - reg[1].I = reg[13].I + ((opcode&255)<<2); - break; case 0xaa: - // ADD R2, SP, Imm - reg[2].I = reg[13].I + ((opcode&255)<<2); - break; case 0xab: - // ADD R3, SP, Imm - reg[3].I = reg[13].I + ((opcode&255)<<2); - break; case 0xac: - // ADD R4, SP, Imm - reg[4].I = reg[13].I + ((opcode&255)<<2); - break; case 0xad: - // ADD R5, SP, Imm - reg[5].I = reg[13].I + ((opcode&255)<<2); - break; case 0xae: - // ADD R6, SP, Imm - reg[6].I = reg[13].I + ((opcode&255)<<2); - break; case 0xaf: - // ADD R7, SP, Imm - reg[7].I = reg[13].I + ((opcode&255)<<2); - break; + { + // ADD R0~R7, SP, Imm + u8 regist = (opcode >> 8) & 7; + reg[regist].I = reg[13].I + ((opcode&255)<<2); + } + break; case 0xb0: { // ADD SP, Imm @@ -1853,15 +1751,17 @@ if(opcode & (val)) {\ CPUWriteMemory(address, reg[(r)].I);\ if(offset)\ - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ else\ - clockTicks += 1 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccess32(address);\ offset = 1;\ address += 4;\ } case 0xb4: // PUSH {Rlist} { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = 0; u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff]; u32 address = temp & 0xFFFFFFFC; @@ -1873,12 +1773,15 @@ PUSH_REG(32, 5); PUSH_REG(64, 6); PUSH_REG(128, 7); + clockTicks += codeTicksAccess16(armNextPC)+1; reg[13].I = temp; } break; case 0xb5: // PUSH {Rlist, LR} { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = 0; u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff]; u32 address = temp & 0xFFFFFFFC; @@ -1891,6 +1794,7 @@ PUSH_REG(64, 6); PUSH_REG(128, 7); PUSH_REG(256, 14); + clockTicks += codeTicksAccess16(armNextPC)+1; reg[13].I = temp; } break; @@ -1898,18 +1802,21 @@ if(opcode & (val)) {\ reg[(r)].I = CPUReadMemory(address);\ if(offset)\ - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ else\ - clockTicks += 2 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccess32(address);\ offset = 1;\ address += 4;\ } case 0xbc: // POP {Rlist} { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = 0; u32 address = reg[13].I & 0xFFFFFFFC; u32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF]; + clockTicks = 0; POP_REG(1, 0); POP_REG(2, 1); POP_REG(4, 2); @@ -1919,14 +1826,18 @@ POP_REG(64, 6); POP_REG(128, 7); reg[13].I = temp; + clockTicks += codeTicksAccess16(armNextPC)+2; } break; case 0xbd: // POP {Rlist, PC} { + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; int offset = 0; u32 address = reg[13].I & 0xFFFFFFFC; u32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF]; + clockTicks = 0; POP_REG(1, 0); POP_REG(2, 1); POP_REG(4, 2); @@ -1937,12 +1848,15 @@ POP_REG(128, 7); reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE); if(offset) - clockTicks += CPUUpdateTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); else - clockTicks += CPUUpdateTicksAccess32(address); + clockTicks += 1 + dataTicksAccess32(address); armNextPC = reg[15].I; reg[15].I += 2; reg[13].I = temp; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks += codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC) + 3; } break; #define THUMB_STM_REG(val,r,b) \ @@ -1950,297 +1864,67 @@ CPUWriteMemory(address, reg[(r)].I);\ if(!offset) {\ reg[(b)].I = temp;\ - clockTicks += 1 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccess32(address);\ } else \ - clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ offset = 1;\ address += 4;\ } case 0xc0: - { - // STM R0!, {Rlist} - u32 address = reg[0].I & 0xFFFFFFFC; - u32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 0); - THUMB_STM_REG(2, 1, 0); - THUMB_STM_REG(4, 2, 0); - THUMB_STM_REG(8, 3, 0); - THUMB_STM_REG(16, 4, 0); - THUMB_STM_REG(32, 5, 0); - THUMB_STM_REG(64, 6, 0); - THUMB_STM_REG(128, 7, 0); - } - break; case 0xc1: - { - // STM R1!, {Rlist} - u32 address = reg[1].I & 0xFFFFFFFC; - u32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 1); - THUMB_STM_REG(2, 1, 1); - THUMB_STM_REG(4, 2, 1); - THUMB_STM_REG(8, 3, 1); - THUMB_STM_REG(16, 4, 1); - THUMB_STM_REG(32, 5, 1); - THUMB_STM_REG(64, 6, 1); - THUMB_STM_REG(128, 7, 1); - } - break; case 0xc2: - { - // STM R2!, {Rlist} - u32 address = reg[2].I & 0xFFFFFFFC; - u32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 2); - THUMB_STM_REG(2, 1, 2); - THUMB_STM_REG(4, 2, 2); - THUMB_STM_REG(8, 3, 2); - THUMB_STM_REG(16, 4, 2); - THUMB_STM_REG(32, 5, 2); - THUMB_STM_REG(64, 6, 2); - THUMB_STM_REG(128, 7, 2); - } - break; case 0xc3: - { - // STM R3!, {Rlist} - u32 address = reg[3].I & 0xFFFFFFFC; - u32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 3); - THUMB_STM_REG(2, 1, 3); - THUMB_STM_REG(4, 2, 3); - THUMB_STM_REG(8, 3, 3); - THUMB_STM_REG(16, 4, 3); - THUMB_STM_REG(32, 5, 3); - THUMB_STM_REG(64, 6, 3); - THUMB_STM_REG(128, 7, 3); - } - break; case 0xc4: - { - // STM R4!, {Rlist} - u32 address = reg[4].I & 0xFFFFFFFC; - u32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 4); - THUMB_STM_REG(2, 1, 4); - THUMB_STM_REG(4, 2, 4); - THUMB_STM_REG(8, 3, 4); - THUMB_STM_REG(16, 4, 4); - THUMB_STM_REG(32, 5, 4); - THUMB_STM_REG(64, 6, 4); - THUMB_STM_REG(128, 7, 4); - } - break; case 0xc5: - { - // STM R5!, {Rlist} - u32 address = reg[5].I & 0xFFFFFFFC; - u32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 5); - THUMB_STM_REG(2, 1, 5); - THUMB_STM_REG(4, 2, 5); - THUMB_STM_REG(8, 3, 5); - THUMB_STM_REG(16, 4, 5); - THUMB_STM_REG(32, 5, 5); - THUMB_STM_REG(64, 6, 5); - THUMB_STM_REG(128, 7, 5); - } - break; case 0xc6: - { - // STM R6!, {Rlist} - u32 address = reg[6].I & 0xFFFFFFFC; - u32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xff]; - int offset = 0; - // store - THUMB_STM_REG(1, 0, 6); - THUMB_STM_REG(2, 1, 6); - THUMB_STM_REG(4, 2, 6); - THUMB_STM_REG(8, 3, 6); - THUMB_STM_REG(16, 4, 6); - THUMB_STM_REG(32, 5, 6); - THUMB_STM_REG(64, 6, 6); - THUMB_STM_REG(128, 7, 6); - } - break; case 0xc7: { - // STM R7!, {Rlist} - u32 address = reg[7].I & 0xFFFFFFFC; - u32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xff]; + // STM R0~7!, {Rlist} + u8 regist = (opcode >> 8) & 7; + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; + u32 address = reg[regist].I & 0xFFFFFFFC; + u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff]; int offset = 0; // store - THUMB_STM_REG(1, 0, 7); - THUMB_STM_REG(2, 1, 7); - THUMB_STM_REG(4, 2, 7); - THUMB_STM_REG(8, 3, 7); - THUMB_STM_REG(16, 4, 7); - THUMB_STM_REG(32, 5, 7); - THUMB_STM_REG(64, 6, 7); - THUMB_STM_REG(128, 7, 7); + THUMB_STM_REG(1, 0, regist); + THUMB_STM_REG(2, 1, regist); + THUMB_STM_REG(4, 2, regist); + THUMB_STM_REG(8, 3, regist); + THUMB_STM_REG(16, 4, regist); + THUMB_STM_REG(32, 5, regist); + THUMB_STM_REG(64, 6, regist); + THUMB_STM_REG(128, 7, regist); + clockTicks = codeTicksAccess16(armNextPC)+1; } - break; + break; #define THUMB_LDM_REG(val,r) \ if(opcode & (val)) {\ reg[(r)].I = CPUReadMemory(address);\ if(offset)\ - clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);\ - else\ - clockTicks += 2 + CPUUpdateTicksAccess32(address);\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + else \ + clockTicks += 1 + dataTicksAccess32(address);\ offset = 1;\ address += 4;\ } case 0xc8: - { - // LDM R0!, {Rlist} - u32 address = reg[0].I & 0xFFFFFFFC; - u32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 1)) - reg[0].I = temp; - } - break; case 0xc9: - { - // LDM R1!, {Rlist} - u32 address = reg[1].I & 0xFFFFFFFC; - u32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 2)) - reg[1].I = temp; - } - break; case 0xca: - { - // LDM R2!, {Rlist} - u32 address = reg[2].I & 0xFFFFFFFC; - u32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 4)) - reg[2].I = temp; - } - break; case 0xcb: - { - // LDM R3!, {Rlist} - u32 address = reg[3].I & 0xFFFFFFFC; - u32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 8)) - reg[3].I = temp; - } - break; case 0xcc: - { - // LDM R4!, {Rlist} - u32 address = reg[4].I & 0xFFFFFFFC; - u32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 16)) - reg[4].I = temp; - } - break; case 0xcd: - { - // LDM R5!, {Rlist} - u32 address = reg[5].I & 0xFFFFFFFC; - u32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 32)) - reg[5].I = temp; - } - break; case 0xce: - { - // LDM R6!, {Rlist} - u32 address = reg[6].I & 0xFFFFFFFC; - u32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xFF]; - int offset = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 64)) - reg[6].I = temp; - } - break; case 0xcf: { - // LDM R7!, {Rlist} - u32 address = reg[7].I & 0xFFFFFFFC; - u32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xFF]; + // LDM R0~R7!, {Rlist} + u8 regist = (opcode >> 8) & 7; + if (!busPrefetchCount) + busPrefetch = busPrefetchEnable; + u32 address = reg[regist].I & 0xFFFFFFFC; + u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF]; int offset = 0; + clockTicks = 0; // load THUMB_LDM_REG(1, 0); THUMB_LDM_REG(2, 1); @@ -2249,141 +1933,232 @@ THUMB_LDM_REG(16, 4); THUMB_LDM_REG(32, 5); THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - if(!(opcode & 128)) - reg[7].I = temp; + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccess16(armNextPC)+2; + if(!(opcode & (1<GetString(szBuffer); index = m_currents.AddString(szBuffer); // and a pointer to the accel object. - m_currents.SetItemData(index, (DWORD)pAccel); + m_currents.SetItemData(index, (DWORD_PTR)pAccel); } } // Init the key editor @@ -185,7 +185,8 @@ return; // no valid key, abort int count = m_commands.GetCount(); - for (int index = 0; index < count; index++) { + int index; + for (index = 0; index < count; index++) { wIDCommand = LOWORD(m_commands.GetItemData(index)); mgr.m_mapAccelTable.Lookup(wIDCommand, pCmdAccel); @@ -234,7 +235,7 @@ pAccel->GetString(szBuffer); index = m_currents.AddString(szBuffer); - m_currents.SetItemData(index, (DWORD)pAccel); + m_currents.SetItemData(index, (DWORD_PTR)pAccel); // Reset the key editor. m_key.ResetKey(); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/AcceleratorManager.cpp ./src/win32/AcceleratorManager.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/AcceleratorManager.cpp 2003-11-04 23:09:51 +0900 +++ ./src/win32/AcceleratorManager.cpp 2006-06-07 06:04:20 +0900 @@ -247,7 +247,7 @@ } } - int nAccel = arrayACCEL.GetSize(); + INT_PTR nAccel = arrayACCEL.GetSize(); LPACCEL lpAccel = (LPACCEL)LocalAlloc(LPTR, nAccel * sizeof(ACCEL)); if (!lpAccel) { for (iLoop = 0; iLoop < nAccel; iLoop++) @@ -268,7 +268,7 @@ } arrayACCEL.RemoveAll(); - HACCEL hNewTable = CreateAcceleratorTable(lpAccel, nAccel); + HACCEL hNewTable = CreateAcceleratorTable(lpAccel, (int)nAccel); if (!hNewTable) { ::LocalFree(lpAccel); return false; @@ -709,14 +709,14 @@ } // AccelsDatasArray.InsertAt(0, MAKELONG(65535, iCount)); - int count = AccelsDatasArray.GetSize(); + INT_PTR count = AccelsDatasArray.GetSize(); DWORD *data = (DWORD *)malloc(count * sizeof(DWORD)); ASSERT(data != NULL); for(int index = 0; index < count; index++) data[index] = AccelsDatasArray[index]; - regSetBinaryValue("keyboard", (char *)data, count*sizeof(DWORD)); + regSetBinaryValue("keyboard", (char *)data, (int)(count*sizeof(DWORD))); AccelsDatasArray.RemoveAll(); CmdDatasArray.RemoveAll(); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/BitmapControl.h ./src/win32/BitmapControl.h --- ../VisualBoyAdvance-1.7.2/src/win32/BitmapControl.h 2004-05-13 22:47:15 +0900 +++ ./src/win32/BitmapControl.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_BITMAPCONTROL_H__2434AADB_B6A5_4E43_AA16_7B65B6F7FA26__INCLUDED_) #define AFX_BITMAPCONTROL_H__2434AADB_B6A5_4E43_AA16_7B65B6F7FA26__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/BugReport.cpp ./src/win32/BugReport.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/BugReport.cpp 2004-05-13 23:29:11 +0900 +++ ./src/win32/BugReport.cpp 2006-08-02 04:21:16 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -216,7 +216,6 @@ AppendFormat(report, "Using BIOS : %d\r\n", theApp.useBiosFile); AppendFormat(report, "Skip BIOS : %d\r\n", theApp.skipBiosFile); AppendFormat(report, "Disable SFX : %d\r\n", cpuDisableSfx); - AppendFormat(report, "Skip intro : %d\r\n", theApp.removeIntros); AppendFormat(report, "Throttle : %d\r\n", theApp.throttle); AppendFormat(report, "Rewind : %d\r\n", theApp.rewindTimer); AppendFormat(report, "Auto frame : %d\r\n", theApp.autoFrameSkip); @@ -227,6 +226,7 @@ AppendFormat(report, "Green shift : %08x\r\n", systemGreenShift); AppendFormat(report, "Blue shift : %08x\r\n", systemBlueShift); AppendFormat(report, "Layer setting: %04X\r\n", layerSettings); + AppendFormat(report, "Mirroring : %d\r\n", mirroringEnable); AppendFormat(report, "Save type : %d (%d)\r\n", theApp.winSaveType, cpuSaveType); AppendFormat(report, "Flash size : %08X (%08x)\r\n", diff -urN ../VisualBoyAdvance-1.7.2/src/win32/CmdAccelOb.cpp ./src/win32/CmdAccelOb.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/CmdAccelOb.cpp 2003-11-04 23:09:52 +0900 +++ ./src/win32/CmdAccelOb.cpp 2006-05-14 01:32:16 +0900 @@ -264,7 +264,8 @@ return; // modifiers part - for (int i = 0; i < sizetable(mapVirtSysKeys); i++) { + int i; + for (i = 0; i < sizetable(mapVirtSysKeys); i++) { if (m_cVirt & mapVirtSysKeys[i].wKey) { szBuffer += mapVirtSysKeys[i].szKey; szBuffer += "+"; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/ColorButton.h ./src/win32/ColorButton.h --- ../VisualBoyAdvance-1.7.2/src/win32/ColorButton.h 2004-05-13 22:46:40 +0900 +++ ./src/win32/ColorButton.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_COLORBUTTON_H__DF02109B_B91C_49FD_954F_74A48B83C314__INCLUDED_) #define AFX_COLORBUTTON_H__DF02109B_B91C_49FD_954F_74A48B83C314__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/ColorControl.h ./src/win32/ColorControl.h --- ../VisualBoyAdvance-1.7.2/src/win32/ColorControl.h 2004-05-13 22:46:30 +0900 +++ ./src/win32/ColorControl.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_COLORCONTROL_H__747E1E47_DDFA_4D67_B337_A473F2BACB86__INCLUDED_) #define AFX_COLORCONTROL_H__747E1E47_DDFA_4D67_B337_A473F2BACB86__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Commands.cpp ./src/win32/Commands.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Commands.cpp 2004-05-13 23:28:36 +0900 +++ ./src/win32/Commands.cpp 2006-08-04 00:20:17 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -129,13 +129,13 @@ { "OptionsEmulatorDirectories", ID_OPTIONS_EMULATOR_DIRECTORIES }, { "OptionsEmulatorSelectBIOS", ID_OPTIONS_EMULATOR_SELECTBIOSFILE }, { "OptionsEmulatorUseBIOS", ID_OPTIONS_EMULATOR_USEBIOSFILE }, + { "OptionsEmulatorGameOverrides", ID_OPTIONS_EMULATOR_GAMEOVERRIDES }, { "OptionsEmulatorSkipBIOS", ID_OPTIONS_EMULATOR_SKIPBIOS }, { "OptionsEmulatorShowSpeedNone", ID_OPTIONS_EMULATOR_SHOWSPEED_NONE }, { "OptionsEmulatorShowSpeedPercentage", ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE }, { "OptionsEmulatorShowSpeedDetailed", ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED }, { "OptionsEmulatorShowSpeedTransparent", ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT }, { "OptionsEmulatorSpeedupToggle", ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE }, - { "OptionsEmulatorRemoveIntros", ID_OPTIONS_EMULATOR_REMOVEINTROSGBA }, { "OptionsEmulatorAutoHideMenu", ID_OPTIONS_EMULATOR_AUTOHIDEMENU }, { "OptionsEmulatorSaveAuto", ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC }, { "OptionsEmulatorSaveEEPROM", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM }, @@ -147,6 +147,7 @@ { "OptionsEmulatorAutoIPSPatch", ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH }, { "OptionsEmulatorAGBPrint", ID_OPTIONS_EMULATOR_AGBPRINT }, { "OptionsEmulatorRTC", ID_OPTIONS_EMULATOR_REALTIMECLOCK }, + { "OptionsEmulatorGenericflashcard", ID_OPTIONS_EMULATOR_GENERICFLASHCARD }, { "OptionsEmulatorRewindInterval", ID_OPTIONS_EMULATOR_REWINDINTERVAL }, { "OptionsSoundOff", ID_OPTIONS_SOUND_OFF }, { "OptionsSoundMute", ID_OPTIONS_SOUND_MUTE }, diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Direct3D.cpp ./src/win32/Direct3D.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Direct3D.cpp 2004-05-13 23:28:26 +0900 +++ ./src/win32/Direct3D.cpp 2006-08-11 19:58:39 +0900 @@ -1,6 +1,7 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -17,11 +18,8 @@ // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" -#include "vba.h" -#define DIRECT3D_VERSION 0x0800 -#include -#include +#include "Display.h" #include "MainWnd.h" @@ -29,10 +27,17 @@ #include "../GBA.h" #include "../Globals.h" #include "../Text.h" +#include "../Util.h" #include "../gb/gbGlobals.h" -#include "Reg.h" -#include "resource.h" +// Direct3D +#define DIRECT3D_VERSION 0x0900 +#include // main include file +#include // required for font rednering +#include // contains debug functions + +extern int Init_2xSaI(u32); // initializes all pixel filters +extern int systemSpeed; #ifdef _DEBUG #define new DEBUG_NEW @@ -42,720 +47,588 @@ #ifdef MMX extern "C" bool cpu_mmx; - extern bool detectMMX(); #endif -extern int Init_2xSaI(u32); -extern void winlog(const char *,...); -extern int systemSpeed; - -typedef struct _D3DTLVERTEX { - float sx; /* Screen coordinates */ - float sy; - float sz; - float rhw; /* Reciprocal of homogeneous w */ - D3DCOLOR color; /* Vertex color */ - float tu; /* Texture coordinates */ - float tv; - _D3DTLVERTEX() { } - _D3DTLVERTEX(const D3DVECTOR& v, float _rhw, - D3DCOLOR _color, - float _tu, float _tv) - { sx = v.x; sy = v.y; sz = v.z; rhw = _rhw; - color = _color; - tu = _tu; tv = _tv; - } -} D3DTLVERTEX, *LPD3DTLVERTEX; - -#define D3DFVF_TLVERTEX D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1 class Direct3DDisplay : public IDisplay { private: - HINSTANCE d3dDLL; - LPDIRECT3D8 pD3D; - LPDIRECT3DDEVICE8 pDevice; - LPDIRECT3DTEXTURE8 pTexture; - D3DSURFACE_DESC dsdBackBuffer; - D3DPRESENT_PARAMETERS dpp; - D3DFORMAT screenFormat; - int width; - int height; - bool filterDisabled; - ID3DXFont *pFont; - bool failed; - - void restoreDeviceObjects(); - void invalidateDeviceObjects(); - bool initializeOffscreen(int w, int h); - void updateFiltering(int); -public: - Direct3DDisplay(); - virtual ~Direct3DDisplay(); + LPDIRECT3D9 pD3D; + LPDIRECT3DDEVICE9 pDevice; + D3DPRESENT_PARAMETERS dpp; + D3DFORMAT screenFormat; + LPDIRECT3DSURFACE9 emulatedImage; + D3DTEXTUREFILTERTYPE filter; + int width; + int height; + RECT destRect; + bool failed; + ID3DXFont *pFont; + + void createFont(); + void destroyFont(); + void createSurface(); + void destroySurface(); + void calculateDestRect(); + bool resetDevice(); - virtual bool initialize(); - virtual void cleanup(); - virtual void render(); - virtual void checkFullScreen(); - virtual void renderMenu(); - virtual void clear(); - virtual bool changeRenderSize(int w, int h); - virtual void resize(int w, int h); - virtual DISPLAY_TYPE getType() { return DIRECT_3D; }; - virtual void setOption(const char *, int); - virtual int selectFullScreenMode(GUID **); +public: + Direct3DDisplay(); + virtual ~Direct3DDisplay(); + virtual DISPLAY_TYPE getType() { return DIRECT_3D; }; + + virtual bool initialize(); + virtual void cleanup(); + virtual void clear(); + virtual void render(); + + virtual void renderMenu(); + virtual bool changeRenderSize( int w, int h ); + virtual void resize( int w, int h ); + virtual void setOption( const char *option, int value ); + virtual int selectFullScreenMode( GUID ** ); }; + Direct3DDisplay::Direct3DDisplay() { - d3dDLL = NULL; - pD3D = NULL; - pDevice = NULL; - pTexture = NULL; - pFont = NULL; - screenFormat = D3DFMT_R5G6B5; - width = 0; - height = 0; - filterDisabled = false; - failed = false; + pD3D = NULL; + pDevice = NULL; + screenFormat = D3DFMT_X8R8G8B8; + width = 0; + height = 0; + failed = false; + pFont = NULL; + emulatedImage = NULL; + filter = D3DTEXF_POINT; } + Direct3DDisplay::~Direct3DDisplay() { - cleanup(); + cleanup(); } + void Direct3DDisplay::cleanup() { - if(pD3D != NULL) { - if(pFont) { - pFont->Release(); - pFont = NULL; - } - - if(pTexture) { - pTexture->Release(); - pTexture = NULL; - } - - if(pDevice) { - pDevice->Release(); - pDevice = NULL; - } - - pD3D->Release(); - pD3D = NULL; - - if(d3dDLL != NULL) { - FreeLibrary(d3dDLL); - d3dDLL = NULL; - } - } + destroyFont(); + destroySurface(); + + if( pDevice ) { + pDevice->Release(); + pDevice = NULL; + } + + if( pD3D ) { + pD3D->Release(); + pD3D = NULL; + } } + bool Direct3DDisplay::initialize() { - theApp.sizeX = 240; - theApp.sizeY = 160; + switch(theApp.cartridgeType) + { + case IMAGE_GBA: + theApp.sizeX = 240; + theApp.sizeY = 160; + break; + case IMAGE_GB: + if (gbBorderOn) + { + theApp.sizeX = 256; + theApp.sizeY = 224; + } + else + { + theApp.sizeX = 160; + theApp.sizeY = 144; + } + break; + } + + + switch(theApp.videoOption) + { + case VIDEO_1X: + theApp.surfaceSizeX = theApp.sizeX; + theApp.surfaceSizeY = theApp.sizeY; + break; + case VIDEO_2X: + theApp.surfaceSizeX = theApp.sizeX * 2; + theApp.surfaceSizeY = theApp.sizeY * 2; + break; + case VIDEO_3X: + theApp.surfaceSizeX = theApp.sizeX * 3; + theApp.surfaceSizeY = theApp.sizeY * 3; + break; + case VIDEO_4X: + theApp.surfaceSizeX = theApp.sizeX * 4; + theApp.surfaceSizeY = theApp.sizeY * 4; + break; + case VIDEO_320x240: + case VIDEO_640x480: + case VIDEO_800x600: + case VIDEO_OTHER: + float scaleX = ((float)theApp.fsWidth / theApp.sizeX); + float scaleY = ((float)theApp.fsHeight / theApp.sizeY); + float min = (scaleX < scaleY) ? scaleX : scaleY; + if(theApp.fullScreenStretch) { + theApp.surfaceSizeX = theApp.fsWidth; + theApp.surfaceSizeY = theApp.fsHeight; + } else { + theApp.surfaceSizeX = (int)(theApp.sizeX * min); + theApp.surfaceSizeY = (int)(theApp.sizeY * min); + } + break; + } + + theApp.rect.left = 0; + theApp.rect.top = 0; + theApp.rect.right = theApp.sizeX; + theApp.rect.bottom = theApp.sizeY; + + theApp.dest.left = 0; + theApp.dest.top = 0; + theApp.dest.right = theApp.surfaceSizeX; + theApp.dest.bottom = theApp.surfaceSizeY; + + + DWORD style = WS_POPUP | WS_VISIBLE; + DWORD styleEx = 0; + + if(theApp.videoOption <= VIDEO_4X) { + style |= WS_OVERLAPPEDWINDOW; + } else { + styleEx = 0; + } + + if(theApp.videoOption <= VIDEO_4X) { + AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx); + } else { + AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx); + } + + int winSizeX = theApp.dest.right-theApp.dest.left; + int winSizeY = theApp.dest.bottom-theApp.dest.top; + + if(theApp.videoOption > VIDEO_4X) { + winSizeX = theApp.fsWidth; + winSizeY = theApp.fsHeight; + } + + int x = 0, y = 0; + + if(theApp.videoOption <= VIDEO_4X) { + x = theApp.windowPositionX; + y = theApp.windowPositionY; + } + + + // Create a window + MainWnd *pWnd = new MainWnd; + theApp.m_pMainWnd = pWnd; + + pWnd->CreateEx(styleEx, + theApp.wndClass, + _T("VisualBoyAdvance"), + style, + x,y,winSizeX,winSizeY, + NULL, + 0); + + if (!(HWND)*pWnd) { + DXTRACE_ERR_MSGBOX( _T("Error creating window"), 0 ); + return FALSE; + } + pWnd->DragAcceptFiles(TRUE); + theApp.updateMenuBar(); + theApp.adjustDestRect(); + + + // load Direct3D v9 + pD3D = Direct3DCreate9( D3D_SDK_VERSION ); + + if(pD3D == NULL) { + DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D object"), 0 ); + return FALSE; + } + + theApp.mode320Available = FALSE; + theApp.mode640Available = FALSE; + theApp.mode800Available = FALSE; + + D3DDISPLAYMODE mode; + pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode); + screenFormat = mode.Format; - switch(theApp.videoOption) { - case VIDEO_1X: - theApp.surfaceSizeX = theApp.sizeX; - theApp.surfaceSizeY = theApp.sizeY; - break; - case VIDEO_2X: - theApp.surfaceSizeX = theApp.sizeX * 2; - theApp.surfaceSizeY = theApp.sizeY * 2; - break; - case VIDEO_3X: - theApp.surfaceSizeX = theApp.sizeX * 3; - theApp.surfaceSizeY = theApp.sizeY * 3; - break; - case VIDEO_4X: - theApp.surfaceSizeX = theApp.sizeX * 4; - theApp.surfaceSizeY = theApp.sizeY * 4; - break; - case VIDEO_320x240: - case VIDEO_640x480: - case VIDEO_800x600: - case VIDEO_OTHER: - { - RECT r; - ::GetWindowRect(GetDesktopWindow(), &r); - theApp.fsWidth = r.right - r.left; - theApp.fsHeight = r.bottom - r.top; - - /* Need to fix this code later. For now, Fullscreen takes the whole - screen. - int scaleX = (fsWidth / sizeX); - int scaleY = (fsHeight / sizeY); - int min = scaleX < scaleY ? scaleX : scaleY; - surfaceSizeX = sizeX * min; - surfaceSizeY = sizeY * min; - if(fullScreenStretch) { - */ - theApp.surfaceSizeX = theApp.fsWidth; - theApp.surfaceSizeY = theApp.fsHeight; - // } - } - break; - } - - theApp.rect.left = 0; - theApp.rect.top = 0; - theApp.rect.right = theApp.sizeX; - theApp.rect.bottom = theApp.sizeY; - - theApp.dest.left = 0; - theApp.dest.top = 0; - theApp.dest.right = theApp.surfaceSizeX; - theApp.dest.bottom = theApp.surfaceSizeY; - - DWORD style = WS_POPUP | WS_VISIBLE; - DWORD styleEx = 0; - - if(theApp.videoOption <= VIDEO_4X) - style |= WS_OVERLAPPEDWINDOW; - else - styleEx = 0; - - if(theApp.videoOption <= VIDEO_4X) - AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx); - else - AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx); - - int winSizeX = theApp.dest.right-theApp.dest.left; - int winSizeY = theApp.dest.bottom-theApp.dest.top; - - if(theApp.videoOption > VIDEO_4X) { - winSizeX = theApp.fsWidth; - winSizeY = theApp.fsHeight; - } - - int x = 0; - int y = 0; - - if(theApp.videoOption <= VIDEO_4X) { - x = theApp.windowPositionX; - y = theApp.windowPositionY; - } - - // Create a window - MainWnd *pWnd = new MainWnd; - theApp.m_pMainWnd = pWnd; - - pWnd->CreateEx(styleEx, - theApp.wndClass, - "VisualBoyAdvance", - style, - x,y,winSizeX,winSizeY, - NULL, - 0); - - if (!(HWND)*pWnd) { - winlog("Error creating Window %08x\n", GetLastError()); - return FALSE; - } - - theApp.updateMenuBar(); - - theApp.adjustDestRect(); - - d3dDLL = LoadLibrary("D3D8.DLL"); - LPDIRECT3D8 (WINAPI *D3DCreate)(UINT); - if(d3dDLL != NULL) { - D3DCreate = (LPDIRECT3D8 (WINAPI *)(UINT)) - GetProcAddress(d3dDLL, "Direct3DCreate8"); - - if(D3DCreate == NULL) { - theApp.directXMessage("Direct3DCreate8"); - return FALSE; - } - } else { - theApp.directXMessage("D3D8.DLL"); - return FALSE; - } - - pD3D = D3DCreate(120); - - if(pD3D == NULL) { - winlog("Error creating Direct3D object\n"); - return FALSE; - } - - theApp.mode320Available = FALSE; - theApp.mode640Available = FALSE; - theApp.mode800Available = FALSE; - - D3DDISPLAYMODE mode; - pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode); - - switch(mode.Format) { + switch(mode.Format) { case D3DFMT_R8G8B8: - systemColorDepth = 24; - systemRedShift = 19; - systemGreenShift = 11; - systemBlueShift = 3; - break; + systemColorDepth = 24; + systemRedShift = 19; + systemGreenShift = 11; + systemBlueShift = 3; + break; case D3DFMT_X8R8G8B8: - systemColorDepth = 32; - systemRedShift = 19; - systemGreenShift = 11; - systemBlueShift = 3; - Init_2xSaI(32); - break; + systemColorDepth = 32; + systemRedShift = 19; + systemGreenShift = 11; + systemBlueShift = 3; + Init_2xSaI(32); + break; case D3DFMT_R5G6B5: - systemColorDepth = 16; - systemRedShift = 11; - systemGreenShift = 6; - systemBlueShift = 0; - Init_2xSaI(565); - break; + systemColorDepth = 16; + systemRedShift = 11; + systemGreenShift = 6; + systemBlueShift = 0; + Init_2xSaI(565); + break; case D3DFMT_X1R5G5B5: - systemColorDepth = 16; - systemRedShift = 10; - systemGreenShift = 5; - systemBlueShift = 0; - Init_2xSaI(555); - break; + systemColorDepth = 16; + systemRedShift = 10; + systemGreenShift = 5; + systemBlueShift = 0; + Init_2xSaI(555); + break; default: - systemMessage(0,"Unsupport D3D format %d", mode.Format); - return false; - } - theApp.fsColorDepth = systemColorDepth; + DXTRACE_ERR_MSGBOX( _T("Unsupport D3D format"), 0 ); + return false; + } + theApp.fsColorDepth = systemColorDepth; + utilUpdateSystemColorMaps(); + #ifdef MMX - if(!theApp.disableMMX) - cpu_mmx = theApp.detectMMX(); - else - cpu_mmx = 0; + if(!theApp.disableMMX) { + cpu_mmx = theApp.detectMMX(); + } else { + cpu_mmx = 0; + } #endif - - screenFormat = mode.Format; - - // check for available fullscreen modes - ZeroMemory(&dpp, sizeof(dpp)); - dpp.Windowed = TRUE; - dpp.BackBufferFormat = mode.Format; - dpp.BackBufferCount = 1; - dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - dpp.BackBufferWidth = theApp.surfaceSizeX; - dpp.BackBufferHeight = theApp.surfaceSizeY; - - HRESULT hret = pD3D->CreateDevice(D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - pWnd->GetSafeHwnd(), - D3DCREATE_SOFTWARE_VERTEXPROCESSING, - &dpp, - &pDevice); - if(!SUCCEEDED(hret)) { - winlog("Error creating Direct3DDevice %08x\n", hret); - return false; - } - - restoreDeviceObjects(); - - switch(systemColorDepth) { - case 16: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - } - 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); - } - } - break; - } - - theApp.updateFilter(); - theApp.updateIFB(); - - if(failed) - return false; - - pWnd->DragAcceptFiles(TRUE); - - return TRUE; -} - -bool Direct3DDisplay::initializeOffscreen(int w, int h) -{ - int size = 256; - if(w > 256 || h > 256) - size = 512; - - UINT ww = size; - UINT hh = size; - D3DFORMAT format = screenFormat; - - if(SUCCEEDED(D3DXCheckTextureRequirements(pDevice, - &ww, - &hh, - NULL, - 0, - &format, - D3DPOOL_MANAGED))) { - if((int)ww < w || (int)hh < h) { - if(theApp.filterFunction) { - filterDisabled = true; - theApp.filterFunction = NULL; - systemMessage(0, "3D card cannot support needed texture size for filter function. Disabling it"); - } - } else - filterDisabled = false; - if(SUCCEEDED(D3DXCreateTexture(pDevice, - ww, - hh, - 0, - 0, - format, - D3DPOOL_MANAGED, - &pTexture))) { - width = w; - height = h; - return true; - } - } - return false; -} - -void Direct3DDisplay::updateFiltering(int filter) -{ - switch(filter) { - default: - case 0: - // point filtering - pDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT ); - pDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT ); - pDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT ); - break; - case 1: - // bilinear - pDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); - pDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); - pDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_POINT ); - break; - } -} - -void Direct3DDisplay::restoreDeviceObjects() -{ - // Store render target surface desc - LPDIRECT3DSURFACE8 pBackBuffer; - HRESULT hr; - if(SUCCEEDED(hr = pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ))) { - pBackBuffer->GetDesc( &dsdBackBuffer ); - pBackBuffer->Release(); - } else - systemMessage(0, "Failed GetBackBuffer %08x", hr); - - // Set up the texture - pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); - pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); - pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); - - int filter = regQueryDwordValue("d3dFilter", 0); - if(filter < 0 || filter > 3) - filter = 0; - updateFiltering(filter); - - // Set miscellaneous render states - pDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE ); - pDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); - - // Set the projection matrix - D3DXMATRIX matProj; - FLOAT fAspect = ((FLOAT)dsdBackBuffer.Width) / dsdBackBuffer.Height; - D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f ); - pDevice->SetTransform( D3DTS_PROJECTION, &matProj ); - - // turn off lighting - pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); - - if(pFont) { - pFont->Release(); - pFont = NULL; - } - // Create a D3D font using D3DX - HFONT hFont = CreateFont( 14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, - ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, - ANTIALIASED_QUALITY, FF_DONTCARE, "Arial" ); - D3DXCreateFont( pDevice, hFont, &pFont ); -} - -void Direct3DDisplay::clear() -{ -} - -void Direct3DDisplay::renderMenu() -{ - checkFullScreen(); - if(theApp.m_pMainWnd) - theApp.m_pMainWnd->DrawMenuBar(); -} -void Direct3DDisplay::checkFullScreen() -{ - // if(tripleBuffering) - // pDirect3D->FlipToGDISurface(); -} -static void BlitRect(LPDIRECT3DDEVICE8 lpDevice, - LPDIRECT3DTEXTURE8 lpSrc, - float left, float top, - float right, float bottom, - D3DCOLOR col,float z) -{ - // calculate rhw + theApp.updateFilter(); + theApp.updateIFB(); - float rhw=1.0f/(z*990.0f+10.0f); - // set up rectangle + // create device + ZeroMemory(&dpp, sizeof(dpp)); + dpp.Windowed = TRUE; + dpp.BackBufferFormat = mode.Format; + dpp.BackBufferCount = theApp.tripleBuffering ? 2 : 1; + dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + dpp.BackBufferWidth = 0; // use width of hDeviceWindow + dpp.BackBufferHeight = 0; // use height of hDeviceWindow + dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + dpp.PresentationInterval = theApp.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + + HRESULT hret = pD3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + pWnd->GetSafeHwnd(), + D3DCREATE_SOFTWARE_VERTEXPROCESSING, + &dpp, + &pDevice); + if( FAILED( hret ) ) { + DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D device"), hret ); + return false; + } + + createFont(); + createSurface(); + calculateDestRect(); - D3DTLVERTEX verts[4]; - verts[0]=D3DTLVERTEX(D3DXVECTOR3(left-0.5f, top-0.5f, z),rhw,col,0.0f,0.0f); - verts[1]=D3DTLVERTEX(D3DXVECTOR3(right-0.5f, top-0.5f, z),rhw,col,1.0f,0.0f); - verts[2]=D3DTLVERTEX(D3DXVECTOR3(right-0.5f, bottom-0.5f, z),rhw,col,1.0f,1.0f); - verts[3]=D3DTLVERTEX(D3DXVECTOR3(left-0.5f, bottom-0.5f, z),rhw,col,0.0f,1.0f); + setOption( _T("d3dFilter"), theApp.d3dFilter ); - // set the texture + if(failed) return false; - lpDevice->SetTexture(0,lpSrc); + return TRUE; +} - // configure shader for vertex type - lpDevice->SetVertexShader(D3DFVF_TLVERTEX); +void Direct3DDisplay::renderMenu() +{ + checkFullScreen(); + if(theApp.m_pMainWnd) { + theApp.m_pMainWnd->DrawMenuBar(); + } +} - // draw the rectangle - lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,verts,sizeof(D3DTLVERTEX)); +void Direct3DDisplay::clear() +{ + if( pDevice ) { + pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00,0x00,0x00), 0.0f, 0 ); + } } + void Direct3DDisplay::render() { - if(!pDevice) - return; - - // Test the cooperative level to see if it's okay to render - if( FAILED( pDevice->TestCooperativeLevel() ) ) - { - return; - } - pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0L ); - - if(SUCCEEDED(pDevice->BeginScene())) { - D3DLOCKED_RECT locked; - if(pTexture && SUCCEEDED(pTexture->LockRect(0, &locked, NULL, 0))) { - if(theApp.filterFunction) { - if(systemColorDepth == 16) - theApp.filterFunction(pix+theApp.filterWidth*2+4, - theApp.filterWidth*2+4, - (u8*)theApp.delta, - (u8*)locked.pBits, - locked.Pitch, - theApp.filterWidth, - theApp.filterHeight); - else - theApp.filterFunction(pix+theApp.filterWidth*4+4, - theApp.filterWidth*4+4, - (u8*)theApp.delta, - (u8*)locked.pBits, - locked.Pitch, - theApp.filterWidth, - theApp.filterHeight); - } else { - int copyX = 240; - int copyY = 160; - - if(theApp.cartridgeType == 1) { - if(gbBorderOn) { - copyX = 256; - copyY = 224; - } else { - copyX = 160; - copyY = 144; - } - } - // MMX doesn't seem to be faster to copy the data - __asm { - mov eax, copyX; - mov ebx, copyY; - - mov esi, pix; - mov edi, locked.pBits; - mov edx, locked.Pitch; - cmp systemColorDepth, 16; - jnz gbaOtherColor; - sub edx, eax; - sub edx, eax; - lea esi,[esi+2*eax+4]; - shr eax, 1; - gbaLoop16bit: - mov ecx, eax; - repz movsd; - inc esi; - inc esi; - inc esi; - inc esi; - add edi, edx; - dec ebx; - jnz gbaLoop16bit; - jmp gbaLoopEnd; - gbaOtherColor: - cmp systemColorDepth, 32; - jnz gbaOtherColor2; - - sub edx, eax; - sub edx, eax; - sub edx, eax; - sub edx, eax; - lea esi, [esi+4*eax+4]; - gbaLoop32bit: - mov ecx, eax; - repz movsd; - add esi, 4; - add edi, edx; - dec ebx; - jnz gbaLoop32bit; - jmp gbaLoopEnd; - gbaOtherColor2: - lea eax, [eax+2*eax]; - sub edx, eax; - gbaLoop24bit: - mov ecx, eax; - shr ecx, 2; - repz movsd; - add edi, edx; - dec ebx; - jnz gbaLoop24bit; - gbaLoopEnd: - } - } - - if(theApp.videoOption > VIDEO_4X && theApp.showSpeed) { - char buffer[30]; - if(theApp.showSpeed == 1) - sprintf(buffer, "%3d%%", systemSpeed); - else - sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed, - systemFrameSkip, - theApp.showRenderedFrames); - if(theApp.showSpeedTransparent) - drawTextTransp((u8*)locked.pBits, - locked.Pitch, - theApp.rect.left+10, - theApp.rect.bottom-10, - buffer); - else - drawText((u8*)locked.pBits, - locked.Pitch, - theApp.rect.left+10, - theApp.rect.bottom-10, - buffer); - } - - pTexture->UnlockRect(0); - - float scaleX = (float)theApp.surfaceSizeX / theApp.sizeX; - float scaleY = (float)theApp.surfaceSizeY / theApp.sizeY; - BlitRect(pDevice, pTexture, 0, 0, scaleX*256, scaleY*256, 0xffffff, 0.1f); - } - - if(theApp.screenMessage) { - if(((GetTickCount() - theApp.screenMessageTime) < 3000) && - !theApp.disableStatusMessage && pFont) { - D3DCOLOR color = D3DCOLOR_ARGB(255, 255, 0, 0); - pFont->Begin(); - RECT r; - r.left = 10; - r.top = dpp.BackBufferHeight - 20; - r.right = dpp.BackBufferWidth - 10; - r.bottom = r.top + 20; - - pFont->DrawText(theApp.screenMessageBuffer, -1, &r, 0, color); - pFont->End(); - } else { - theApp.screenMessage = false; - } - } - - pDevice->EndScene(); - - pDevice->Present( NULL, NULL, NULL, NULL ); - } -} - -void Direct3DDisplay::invalidateDeviceObjects() -{ - if(pFont) - pFont->Release(); - pFont = NULL; -} - -void Direct3DDisplay::resize(int w, int h) -{ - if(pDevice) { - dpp.BackBufferWidth = w; - dpp.BackBufferHeight = h; - HRESULT hr; - invalidateDeviceObjects(); - if(SUCCEEDED(hr = pDevice->Reset(&dpp))) { - restoreDeviceObjects(); - } else - systemMessage(0, "Failed device reset %08x", hr); - } -} - -bool Direct3DDisplay::changeRenderSize(int w, int h) -{ - if(w != width || h != height) { - if(pTexture) { - pTexture->Release(); - pTexture = NULL; - } - if(!initializeOffscreen(w, h)) { - failed = true; - return false; - } - } - if(filterDisabled && theApp.filterFunction) - theApp.filterFunction = NULL; - - return true; -} - -void Direct3DDisplay::setOption(const char *option, int value) -{ - if(!strcmp(option, "d3dFilter")) - updateFiltering(value); -} - -int Direct3DDisplay::selectFullScreenMode(GUID **) -{ - HWND wnd = GetDesktopWindow(); - RECT r; - GetWindowRect(wnd, &r); - int w = (r.right - r.left) & 4095; - int h = (r.bottom - r.top) & 4095; - HDC dc = GetDC(wnd); - int c = GetDeviceCaps(dc, BITSPIXEL); - ReleaseDC(wnd, dc); - - return (c << 24) | (w << 12) | h; + if( failed ) return; + if(!pDevice) return; + if( FAILED( pDevice->TestCooperativeLevel() ) ) return; + + clear(); + + pDevice->BeginScene(); + + // copy pix to emulatedImage and apply pixel filter if selected + HRESULT hr; + D3DLOCKED_RECT lr; + if( FAILED( hr = emulatedImage->LockRect( &lr, NULL, D3DLOCK_DISCARD ) ) ) { + DXTRACE_ERR_MSGBOX( _T("Can not lock back buffer"), hr ); + return; + } else { + if( !theApp.filterFunction ) { + copyImage( pix, lr.pBits, theApp.sizeX, theApp.sizeY, lr.Pitch, systemColorDepth ); + } else { + u32 pitch = theApp.filterWidth * (systemColorDepth>>3) + 4; + theApp.filterFunction( pix + pitch, + pitch, + (u8*)theApp.delta, + (u8*)lr.pBits, + lr.Pitch, + theApp.filterWidth, + theApp.filterHeight); + } + emulatedImage->UnlockRect(); + } + + // copy emulatedImage to pBackBuffer and scale with or without aspect ratio + LPDIRECT3DSURFACE9 pBackBuffer; + pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); + if( theApp.fullScreenStretch ) { + pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, NULL, filter ); + } else { + pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, &destRect, filter ); + } + pBackBuffer->Release(); + pBackBuffer = NULL; + + D3DCOLOR color; + RECT r; + r.left = 4; + r.right = dpp.BackBufferWidth - 4; + + if( theApp.screenMessage ) { + color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0xFF, 0x00, 0x00) : D3DCOLOR_ARGB(0xFF, 0xFF, 0x00, 0x00); + if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage && pFont ) { + r.top = dpp.BackBufferHeight - 20; + r.bottom = dpp.BackBufferHeight - 4; + pFont->DrawText( NULL, theApp.screenMessageBuffer, -1, &r, 0, color ); + } else { + theApp.screenMessage = false; + } + } + + if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) { + color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0x00, 0x00, 0xFF) : D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0xFF); + char buffer[30]; + if( theApp.showSpeed == 1 ) { + sprintf( buffer, "%3d%%", systemSpeed ); + } else { + sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames ); + } + + r.top = 4; + r.bottom = 20; + pFont->DrawText( NULL, buffer, -1, &r, 0, color ); + } + + pDevice->EndScene(); + + pDevice->Present( NULL, NULL, NULL, NULL ); + + return; +} + + +bool Direct3DDisplay::changeRenderSize( int w, int h ) +{ + if( (w != width) || (h != height) ) { + width = w; height = h; + if( pDevice ) { + destroySurface(); + createSurface(); + calculateDestRect(); + } + } + return true; +} + + +void Direct3DDisplay::resize( int w, int h ) +{ + if( (w != dpp.BackBufferWidth) || (h != dpp.BackBufferHeight) ) { + dpp.BackBufferWidth = (UINT)w; + dpp.BackBufferHeight = (UINT)h; + resetDevice(); + calculateDestRect(); + } +} + + +int Direct3DDisplay::selectFullScreenMode( GUID ** ) +{ + HRESULT hr; + D3DDISPLAYMODE dm; + if( FAILED( hr = pDevice->GetDisplayMode( 0, &dm ) ) ) { + DXTRACE_ERR_MSGBOX( _T("pDevice->GetDisplayMode failed"), hr ); + return false; + } + + UINT bitsPerPixel; + switch( dm.Format ) + { + case D3DFMT_A2R10G10B10: + case D3DFMT_X8R8G8B8: + bitsPerPixel = 32; + break; + case D3DFMT_X1R5G5B5: + case D3DFMT_R5G6B5: + bitsPerPixel = 16; + break; + } + + return (bitsPerPixel << 24) | (dm.Width << 12) | dm.Height; +} + + +void Direct3DDisplay::createFont() +{ + if( !pFont ) { + HRESULT hr = D3DXCreateFont( + pDevice, + 14, + 0, + FW_BOLD, + 1, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + DEFAULT_QUALITY, + DEFAULT_PITCH || FF_DONTCARE, + _T("Arial"), + &pFont ); + if( FAILED( hr ) ) { + DXTRACE_ERR_MSGBOX( _T("createFont failed"), hr ); + } + } +} + + +void Direct3DDisplay::destroyFont() +{ + if( pFont ) { + pFont->Release(); + pFont = NULL; + } +} + + +void Direct3DDisplay::createSurface() +{ + if( !emulatedImage ) { + HRESULT hr = pDevice->CreateOffscreenPlainSurface( + width, height, + dpp.BackBufferFormat, + D3DPOOL_DEFAULT, + &emulatedImage, + NULL ); + if( FAILED( hr ) ) { + DXTRACE_ERR_MSGBOX( _T("createSurface failed"), hr ); + } + } +} + + +void Direct3DDisplay::destroySurface() +{ + if( emulatedImage ) { + emulatedImage->Release(); + emulatedImage = NULL; + } +} + + +void Direct3DDisplay::calculateDestRect() +{ + float scaleX = (float)dpp.BackBufferWidth / (float)width; + float scaleY = (float)dpp.BackBufferHeight / (float)height; + float min = (scaleX < scaleY) ? scaleX : scaleY; + if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) { + min = (float)theApp.fsMaxScale; + } + destRect.left = 0; + destRect.top = 0; + destRect.right = (LONG)(width * min); + destRect.bottom = (LONG)(height * min); + if( destRect.right != dpp.BackBufferWidth ) { + LONG diff = (dpp.BackBufferWidth - destRect.right) / 2; + destRect.left += diff; + destRect.right += diff; + } + if( destRect.bottom != dpp.BackBufferHeight ) { + LONG diff = (dpp.BackBufferHeight - destRect.bottom) / 2; + destRect.top += diff; + destRect.bottom += diff; + } +} + + +void Direct3DDisplay::setOption( const char *option, int value ) +{ + if( !_tcscmp( option, _T("vsync") ) ) { + dpp.PresentationInterval = value ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + resetDevice(); + } + + if( !_tcscmp( option, _T("tripleBuffering") ) ) { + dpp.BackBufferCount = value ? 2 : 1; + resetDevice(); + } + + if( !_tcscmp( option, _T("d3dFilter") ) ) { + switch( value ) + { + case 0: //point + filter = D3DTEXF_POINT; + break; + case 1: //linear + filter = D3DTEXF_LINEAR; + break; + } + } + + if( !_tcscmp( option, _T("maxScale") ) ) { + calculateDestRect(); + } +} + + +bool Direct3DDisplay::resetDevice() +{ + if( !pDevice ) return false; + + HRESULT hr; + destroyFont(); + destroySurface(); + if( FAILED( hr = pDevice->Reset( &dpp ) ) ) { + //DXTRACE_ERR_MSGBOX( _T("pDevice->Reset failed"), hr ); + failed = true; + return false; + } + createFont(); + createSurface(); + failed = false; + return true; } + IDisplay *newDirect3DDisplay() { - return new Direct3DDisplay(); + return new Direct3DDisplay(); } - diff -urN ../VisualBoyAdvance-1.7.2/src/win32/DirectDraw.cpp ./src/win32/DirectDraw.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/DirectDraw.cpp 2004-05-13 23:28:16 +0900 +++ ./src/win32/DirectDraw.cpp 2006-06-07 06:04:21 +0900 @@ -26,12 +26,15 @@ #include "../GBA.h" #include "../Globals.h" #include "../Text.h" +#include "../Util.h" #include "VBA.h" #include "MainWnd.h" #include "Reg.h" #include "resource.h" +#include "Display.h" + #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE @@ -39,7 +42,6 @@ #endif extern int Init_2xSaI(u32); -extern int RGB_LOW_BITS_MASK; extern void winlog(const char *,...); extern int systemSpeed; extern int winVideoModeSelect(CWnd *, GUID **); @@ -153,7 +155,11 @@ } if(ddrawDLL != NULL) { - AfxFreeLibrary(ddrawDLL); +#ifdef _AFXDLL + AfxFreeLibrary( ddrawDLL ); +#else + FreeLibrary( ddrawDLL ); +#endif ddrawDLL = NULL; } width = 0; @@ -265,7 +271,12 @@ if(theApp.pVideoDriverGUID) guid = theApp.pVideoDriverGUID; - ddrawDLL = AfxLoadLibrary("DDRAW.DLL"); +#ifdef _AFXDLL + ddrawDLL = AfxLoadLibrary("ddraw.dll"); +#else + ddrawDLL = LoadLibrary( _T("ddraw.dll") ); +#endif + HRESULT (WINAPI *DDrawCreateEx)(GUID *,LPVOID *,REFIID,IUnknown *); if(ddrawDLL != NULL) { DDrawCreateEx = (HRESULT (WINAPI *)(GUID *,LPVOID *,REFIID,IUnknown *)) @@ -551,26 +562,22 @@ px.dwBBitMask == 0x001F) { systemGreenShift++; Init_2xSaI(565); - RGB_LOW_BITS_MASK=0x821; } else if((px.dwFlags&DDPF_RGB) != 0 && px.dwRBitMask == 0x7C00 && px.dwGBitMask == 0x03E0 && px.dwBBitMask == 0x001F) { Init_2xSaI(555); - RGB_LOW_BITS_MASK=0x421; } else if((px.dwFlags&DDPF_RGB) != 0 && px.dwRBitMask == 0x001F && px.dwGBitMask == 0x07E0 && px.dwBBitMask == 0xF800) { systemGreenShift++; Init_2xSaI(565); - RGB_LOW_BITS_MASK=0x821; } else if((px.dwFlags&DDPF_RGB) != 0 && px.dwRBitMask == 0x001F && px.dwGBitMask == 0x03E0 && px.dwBBitMask == 0x7C00) { Init_2xSaI(555); - RGB_LOW_BITS_MASK=0x421; } else { // 32-bit or 24-bit if(systemColorDepth == 32 || systemColorDepth == 24) { @@ -588,27 +595,7 @@ winlog("B shift: %d\n", systemBlueShift); } - switch(systemColorDepth) { - case 16: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - } - 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); - } - } - break; - } + utilUpdateSystemColorMaps(); width = w; height = h; return true; @@ -646,16 +633,13 @@ void DirectDrawDisplay::render() { HRESULT hret; + unsigned int nBytesPerPixel = systemColorDepth>>3; if(pDirectDraw == NULL || ddsOffscreen == NULL || ddsPrimary == NULL) return; - if(theApp.vsync && !speedup) { - hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); - } - DDSURFACEDESC2 ddsDesc; ZeroMemory(&ddsDesc, sizeof(ddsDesc)); @@ -722,60 +706,7 @@ copyY = 144; } } - // MMX doesn't seem to be faster to copy the data - __asm { - mov eax, copyX; - mov ebx, copyY; - - mov esi, pix; - mov edi, ddsDesc.lpSurface; - mov edx, ddsDesc.lPitch; - cmp systemColorDepth, 16; - jnz gbaOtherColor; - sub edx, eax; - sub edx, eax; - lea esi,[esi+2*eax+4]; - shr eax, 1; - gbaLoop16bit: - mov ecx, eax; - repz movsd; - inc esi; - inc esi; - inc esi; - inc esi; - add edi, edx; - dec ebx; - jnz gbaLoop16bit; - jmp gbaLoopEnd; - gbaOtherColor: - cmp systemColorDepth, 32; - jnz gbaOtherColor2; - - sub edx, eax; - sub edx, eax; - sub edx, eax; - sub edx, eax; - lea esi, [esi+4*eax+4]; - gbaLoop32bit: - mov ecx, eax; - repz movsd; - add esi, 4; - add edi, edx; - dec ebx; - jnz gbaLoop32bit; - jmp gbaLoopEnd; - gbaOtherColor2: - lea eax, [eax+2*eax]; - sub edx, eax; - gbaLoop24bit: - mov ecx, eax; - shr ecx, 2; - repz movsd; - add edi, edx; - dec ebx; - jnz gbaLoop24bit; - gbaLoopEnd: - } + copyImage( pix, ddsDesc.lpSurface, copyX, copyY, ddsDesc.lPitch, systemColorDepth ); } if(theApp.showSpeed && (theApp.videoOption > VIDEO_4X || theApp.skin != NULL)) { char buffer[30]; @@ -804,6 +735,9 @@ hret = ddsOffscreen->Unlock(NULL); if(hret == DD_OK) { + if(theApp.vsync && !(theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) && !speedup) { // isn't the Flip() call synced unless a certain flag is passed to it? + hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); + } ddsOffscreen->PageLock(0); if(theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) { hret = ddsFlip->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_WAIT, NULL); @@ -844,7 +778,7 @@ SetTextColor(hdc, RGB(255,0,0)); SetBkMode(hdc,TRANSPARENT); TextOut(hdc, theApp.dest.left+10, theApp.dest.bottom - 20, theApp.screenMessageBuffer, - strlen(theApp.screenMessageBuffer)); + (int)_tcslen(theApp.screenMessageBuffer)); ddsPrimary->ReleaseDC(hdc); } else { theApp.screenMessage = false; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/DirectInput.cpp ./src/win32/DirectInput.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/DirectInput.cpp 2004-05-13 23:28:05 +0900 +++ ./src/win32/DirectInput.cpp 2006-08-24 11:08:26 +0900 @@ -1,27 +1,36 @@ -// 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. +/* + VisualBoyAdvance S - GB & GBA emulator + Copyright (C) 2006 Spacy + + Original VBA Credits: + Copyright (C) 1999-2003 Forgotten + Copyright (C) 2004-2006 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 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. +*/ #include "stdafx.h" +#include "VBA.h" +#include "Input.h" #include "Reg.h" #include "WinResUtil.h" -#define DIRECTINPUT_VERSION 0x0500 -#include +#define DIRECTINPUT_VERSION 0x0800 +#include +#pragma comment(lib, "Dinput8") + #ifdef _DEBUG #define new DEBUG_NEW @@ -38,1020 +47,979 @@ #define POV_LEFT 8 class DirectInput : public Input { -private: - HINSTANCE dinputDLL; - public: - virtual void checkDevices(); - DirectInput(); - virtual ~DirectInput(); - - virtual bool initialize(); - virtual bool readDevices(); - virtual u32 readDevice(int which); - virtual CString getKeyName(int key); - virtual void checkKeys(); - virtual void checkMotionKeys(); - virtual void activate(); - virtual void loadSettings(); - virtual void saveSettings(); + virtual void checkDevices(); + DirectInput(); + virtual ~DirectInput(); + + virtual bool initialize(); + virtual bool readDevices(); + virtual u32 readDevice(int which); + virtual CString getKeyName(LONG_PTR key); + virtual void checkKeys(); + virtual void checkMotionKeys(); + virtual void activate(); + virtual void loadSettings(); + virtual void saveSettings(); }; struct deviceInfo { - LPDIRECTINPUTDEVICE device; - BOOL isPolled; - int nButtons; - int nAxes; - int nPovs; - BOOL first; - struct { - DWORD offset; - LONG center; - LONG negative; - LONG positive; - } axis[8]; - int needed; - union { - UCHAR data[256]; - DIJOYSTATE state; - }; + LPDIRECTINPUTDEVICE8 device; + BOOL isPolled; + int nButtons; + int nAxes; + int nPovs; + BOOL first; + struct { + DWORD offset; + LONG center; + LONG negative; + LONG positive; + } axis[8]; + int needed; + union { + UCHAR data[256]; + DIJOYSTATE state; + }; }; static deviceInfo *currentDevice = NULL; static int numDevices = 1; static deviceInfo *pDevices = NULL; -static LPDIRECTINPUT pDirectInput = NULL; -static int joyDebug = 0; +static LPDIRECTINPUT8 pDirectInput = NULL; static int axisNumber = 0; -USHORT joypad[4][13] = { - { - DIK_LEFT, DIK_RIGHT, - DIK_UP, DIK_DOWN, - DIK_Z, DIK_X, - DIK_RETURN,DIK_BACK, - DIK_A, DIK_S, - DIK_SPACE, DIK_F12, - DIK_C - }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -}; - -USHORT motion[4] = { - DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2 -}; +LONG_PTR joypad[4][13] = { + { + DIK_LEFT, DIK_RIGHT, + DIK_UP, DIK_DOWN, + DIK_Z, DIK_X, + DIK_RETURN,DIK_BACK, + DIK_A, DIK_S, + DIK_SPACE, DIK_F12, + DIK_C + }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + }; + +LONG_PTR motion[4] = { + DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2 + }; static int winReadKey(char *name, int num) { - char buffer[80]; + char buffer[80]; - sprintf(buffer, "Joy%d_%s", num, name); + sprintf(buffer, "Joy%d_%s", num, name); - return regQueryDwordValue(buffer, (DWORD)-1); + return regQueryDwordValue(buffer, (DWORD)-1); } void winReadKeys() { - int key = -1; + int key = -1; - for(int i = 0; i < 4; i++) { - key = winReadKey("Left", i); - if(key != -1) - joypad[i][KEY_LEFT] = key; - key = winReadKey("Right", i); - if(key != -1) - joypad[i][KEY_RIGHT] = key; - key = winReadKey("Up", i); - if(key != -1) - joypad[i][KEY_UP] = key; - key = winReadKey("Down", i); - if(key != -1) - joypad[i][KEY_DOWN] = key; - key = winReadKey("A", i); - if(key != -1) - joypad[i][KEY_BUTTON_A] = key; - key = winReadKey("B", i); - if(key != -1) - joypad[i][KEY_BUTTON_B] = key; - key = winReadKey("L", i); - if(key != -1) - joypad[i][KEY_BUTTON_L] = key; - key = winReadKey("R", i); - if(key != -1) - joypad[i][KEY_BUTTON_R] = key; - key = winReadKey("Start", i); - if(key != -1) - joypad[i][KEY_BUTTON_START] = key; - key = winReadKey("Select", i); - if(key != -1) - joypad[i][KEY_BUTTON_SELECT] = key; - key = winReadKey("Speed", i); - if(key != -1) - joypad[i][KEY_BUTTON_SPEED] = key; - key = winReadKey("Capture", i); - if(key != -1) - joypad[i][KEY_BUTTON_CAPTURE] = key; - key = winReadKey("GS", i); - if(key != -1) - joypad[i][KEY_BUTTON_GS] = key; - } - key = regQueryDwordValue("Motion_Left", (DWORD)-1); - if(key != -1) - motion[KEY_LEFT] = key; - key = regQueryDwordValue("Motion_Right", (DWORD)-1); - if(key != -1) - motion[KEY_RIGHT] = key; - key = regQueryDwordValue("Motion_Up", (DWORD)-1); - if(key != -1) - motion[KEY_UP] = key; - key = regQueryDwordValue("Motion_Down", (DWORD)-1); - if(key != -1) - motion[KEY_DOWN] = key; + for (int i = 0; i < 4; i++) { + key = winReadKey("Left", i); + if (key != -1) + joypad[i][KEY_LEFT] = key; + key = winReadKey("Right", i); + if (key != -1) + joypad[i][KEY_RIGHT] = key; + key = winReadKey("Up", i); + if (key != -1) + joypad[i][KEY_UP] = key; + key = winReadKey("Down", i); + if (key != -1) + joypad[i][KEY_DOWN] = key; + key = winReadKey("A", i); + if (key != -1) + joypad[i][KEY_BUTTON_A] = key; + key = winReadKey("B", i); + if (key != -1) + joypad[i][KEY_BUTTON_B] = key; + key = winReadKey("L", i); + if (key != -1) + joypad[i][KEY_BUTTON_L] = key; + key = winReadKey("R", i); + if (key != -1) + joypad[i][KEY_BUTTON_R] = key; + key = winReadKey("Start", i); + if (key != -1) + joypad[i][KEY_BUTTON_START] = key; + key = winReadKey("Select", i); + if (key != -1) + joypad[i][KEY_BUTTON_SELECT] = key; + key = winReadKey("Speed", i); + if (key != -1) + joypad[i][KEY_BUTTON_SPEED] = key; + key = winReadKey("Capture", i); + if (key != -1) + joypad[i][KEY_BUTTON_CAPTURE] = key; + key = winReadKey("GS", i); + if (key != -1) + joypad[i][KEY_BUTTON_GS] = key; + } + key = regQueryDwordValue("Motion_Left", (DWORD)-1); + if (key != -1) + motion[KEY_LEFT] = key; + key = regQueryDwordValue("Motion_Right", (DWORD)-1); + if (key != -1) + motion[KEY_RIGHT] = key; + key = regQueryDwordValue("Motion_Up", (DWORD)-1); + if (key != -1) + motion[KEY_UP] = key; + key = regQueryDwordValue("Motion_Down", (DWORD)-1); + if (key != -1) + motion[KEY_DOWN] = key; } -static void winSaveKey(char *name, int num, USHORT value) +static void winSaveKey(char *name, int num, LONG_PTR value) { - char buffer[80]; + char buffer[80]; - sprintf(buffer, "Joy%d_%s", num, name); + sprintf(buffer, "Joy%d_%s", num, name); - regSetDwordValue(buffer, value); + regSetDwordValue(buffer, (DWORD)value); } void winSaveKeys() { - for(int i = 0; i < 4; i++) { - winSaveKey("Left", i, joypad[i][KEY_LEFT]); - winSaveKey("Right", i, joypad[i][KEY_RIGHT]); - winSaveKey("Up", i, joypad[i][KEY_UP]); - winSaveKey("Speed", i, joypad[i][KEY_BUTTON_SPEED]); - winSaveKey("Capture", i, joypad[i][KEY_BUTTON_CAPTURE]); - winSaveKey("GS", i, joypad[i][KEY_BUTTON_GS]); - winSaveKey("Down", i, joypad[i][KEY_DOWN]); - winSaveKey("A", i, joypad[i][KEY_BUTTON_A]); - winSaveKey("B", i, joypad[i][KEY_BUTTON_B]); - winSaveKey("L", i, joypad[i][KEY_BUTTON_L]); - winSaveKey("R", i, joypad[i][KEY_BUTTON_R]); - winSaveKey("Start", i, joypad[i][KEY_BUTTON_START]); - winSaveKey("Select", i, joypad[i][KEY_BUTTON_SELECT]); - } - regSetDwordValue("joyVersion", 1); - - regSetDwordValue("Motion_Left", - motion[KEY_LEFT]); - regSetDwordValue("Motion_Right", - motion[KEY_RIGHT]); - regSetDwordValue("Motion_Up", - motion[KEY_UP]); - regSetDwordValue("Motion_Down", - motion[KEY_DOWN]); + for (int i = 0; i < 4; i++) { + winSaveKey("Left", i, joypad[i][KEY_LEFT]); + winSaveKey("Right", i, joypad[i][KEY_RIGHT]); + winSaveKey("Up", i, joypad[i][KEY_UP]); + winSaveKey("Speed", i, joypad[i][KEY_BUTTON_SPEED]); + winSaveKey("Capture", i, joypad[i][KEY_BUTTON_CAPTURE]); + winSaveKey("GS", i, joypad[i][KEY_BUTTON_GS]); + winSaveKey("Down", i, joypad[i][KEY_DOWN]); + winSaveKey("A", i, joypad[i][KEY_BUTTON_A]); + winSaveKey("B", i, joypad[i][KEY_BUTTON_B]); + winSaveKey("L", i, joypad[i][KEY_BUTTON_L]); + winSaveKey("R", i, joypad[i][KEY_BUTTON_R]); + winSaveKey("Start", i, joypad[i][KEY_BUTTON_START]); + winSaveKey("Select", i, joypad[i][KEY_BUTTON_SELECT]); + } + regSetDwordValue("joyVersion", 1); + + regSetDwordValue("Motion_Left", (DWORD)motion[KEY_LEFT]); + regSetDwordValue("Motion_Right", (DWORD)motion[KEY_RIGHT]); + regSetDwordValue("Motion_Up", (DWORD)motion[KEY_UP]); + regSetDwordValue("Motion_Down", (DWORD)motion[KEY_DOWN]); } static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext ) { - DIPROPRANGE diprg; - diprg.diph.dwSize = sizeof(DIPROPRANGE); - diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); - diprg.diph.dwHow = DIPH_BYOFFSET; - diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis - - diprg.lMin = -32768; - diprg.lMax = 32767; - // try to set the range - if(FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) { - // Get the range for the axis - if( FAILED(currentDevice->device-> - GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) { - return DIENUM_STOP; - } - } - - DIPROPDWORD didz; - - didz.diph.dwSize = sizeof(didz); - didz.diph.dwHeaderSize = sizeof(DIPROPHEADER); - didz.diph.dwHow = DIPH_BYOFFSET; - didz.diph.dwObj = pdidoi->dwOfs; - - didz.dwData = 5000; - - currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph); - - LONG center = (diprg.lMin + diprg.lMax)/2; - LONG threshold = (diprg.lMax - center)/2; - - // only 8 axis supported - if(axisNumber < 8) { - currentDevice->axis[axisNumber].center = center; - currentDevice->axis[axisNumber].negative = center - threshold; - currentDevice->axis[axisNumber].positive = center + threshold; - currentDevice->axis[axisNumber].offset = pdidoi->dwOfs; - } - axisNumber++; - return DIENUM_CONTINUE; + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYOFFSET; + diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis + + diprg.lMin = -32768; + diprg.lMax = 32767; + // try to set the range + if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) { + // Get the range for the axis + if ( FAILED(currentDevice->device-> + GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) { + return DIENUM_STOP; + } + } + + DIPROPDWORD didz; + + didz.diph.dwSize = sizeof(didz); + didz.diph.dwHeaderSize = sizeof(DIPROPHEADER); + didz.diph.dwHow = DIPH_BYOFFSET; + didz.diph.dwObj = pdidoi->dwOfs; + + didz.dwData = 5000; + + currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph); + + LONG center = (diprg.lMin + diprg.lMax)/2; + LONG threshold = (diprg.lMax - center)/2; + + // only 8 axis supported + if (axisNumber < 8) { + currentDevice->axis[axisNumber].center = center; + currentDevice->axis[axisNumber].negative = center - threshold; + currentDevice->axis[axisNumber].positive = center + threshold; + currentDevice->axis[axisNumber].offset = pdidoi->dwOfs; + } + axisNumber++; + return DIENUM_CONTINUE; } static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext ) { - return DIENUM_CONTINUE; + return DIENUM_CONTINUE; } static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst, - LPVOID lpvContext) + LPVOID lpvContext) { - ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo)); - - HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance, - &pDevices[numDevices].device, - NULL); - - if(hRet != DI_OK) - return DIENUM_STOP; - - DIDEVCAPS caps; - caps.dwSize=sizeof(DIDEVCAPS); - - hRet = pDevices[numDevices].device->GetCapabilities(&caps); - - if(hRet == DI_OK) { - if(caps.dwFlags & DIDC_POLLEDDATAFORMAT || - caps.dwFlags & DIDC_POLLEDDEVICE) - pDevices[numDevices].isPolled = TRUE; - - pDevices[numDevices].nButtons = caps.dwButtons; - pDevices[numDevices].nAxes = caps.dwAxes; - pDevices[numDevices].nPovs = caps.dwPOVs; - - for(int i = 0; i < 6; i++) { - pDevices[numDevices].axis[i].center = 0x8000; - pDevices[numDevices].axis[i].negative = 0x4000; - pDevices[numDevices].axis[i].positive = 0xc000; - } - } else if(joyDebug) - winlog("Failed to get device capabilities %08x\n", hRet); - - if(joyDebug) { - // don't translate. debug only - winlog("******************************\n"); - winlog("Joystick %2d name : %s\n", numDevices, pInst->tszProductName); - } - - numDevices++; + ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo)); + + HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance, + &pDevices[numDevices].device, + NULL); + + if (hRet != DI_OK) + return DIENUM_STOP; + + DIDEVCAPS caps; + caps.dwSize=sizeof(DIDEVCAPS); + + hRet = pDevices[numDevices].device->GetCapabilities(&caps); + + if (hRet == DI_OK) { + if (caps.dwFlags & DIDC_POLLEDDATAFORMAT || + caps.dwFlags & DIDC_POLLEDDEVICE) + pDevices[numDevices].isPolled = TRUE; + + pDevices[numDevices].nButtons = caps.dwButtons; + pDevices[numDevices].nAxes = caps.dwAxes; + pDevices[numDevices].nPovs = caps.dwPOVs; + + for (int i = 0; i < 6; i++) { + pDevices[numDevices].axis[i].center = 0x8000; + pDevices[numDevices].axis[i].negative = 0x4000; + pDevices[numDevices].axis[i].positive = 0xc000; + } + } + + + numDevices++; + - - return DIENUM_CONTINUE; + return DIENUM_CONTINUE; } BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst, LPVOID lpvContext) { - numDevices++; - - return DIENUM_CONTINUE; + numDevices++; + + return DIENUM_CONTINUE; } static int getPovState(DWORD value) { - int state = 0; - if(LOWORD(value) != 0xFFFF) { - if(value < 9000 || value > 27000) - state |= POV_UP; - if(value > 0 && value < 18000) - state |= POV_RIGHT; - if(value > 9000 && value < 27000) - state |= POV_DOWN; - if(value > 18000) - state |= POV_LEFT; - } - return state; + int state = 0; + if (LOWORD(value) != 0xFFFF) { + if (value < 9000 || value > 27000) + state |= POV_UP; + if (value > 0 && value < 18000) + state |= POV_RIGHT; + if (value > 9000 && value < 27000) + state |= POV_DOWN; + if (value > 18000) + state |= POV_LEFT; + } + return state; } static void checkKeys() { - int dev = 0; - int i; + LONG_PTR dev = 0; + int i; - for(i = 0; i < numDevices; i++) - pDevices[i].needed = 0; + for (i = 0; i < numDevices; i++) + pDevices[i].needed = 0; - for(i = 0; i < 4; i++) { - dev = joypad[i][KEY_LEFT] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_LEFT] = DIK_LEFT; - - dev = joypad[i][KEY_RIGHT] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_RIGHT] = DIK_RIGHT; - - dev = joypad[i][KEY_UP] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_UP] = DIK_UP; - - dev = joypad[i][KEY_DOWN] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_DOWN] = DIK_DOWN; - - dev = joypad[i][KEY_BUTTON_A] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_BUTTON_A] = DIK_Z; - - dev = joypad[i][KEY_BUTTON_B] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_BUTTON_B] = DIK_X; - - dev = joypad[i][KEY_BUTTON_L] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_BUTTON_L] = DIK_A; - - dev = joypad[i][KEY_BUTTON_R] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_BUTTON_R] = DIK_S; - - dev = joypad[i][KEY_BUTTON_START] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - joypad[i][KEY_BUTTON_START] = DIK_RETURN; - - dev = joypad[i][KEY_BUTTON_SELECT] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; + for (i = 0; i < 4; i++) { + dev = joypad[i][KEY_LEFT] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_LEFT] = DIK_LEFT; + + dev = joypad[i][KEY_RIGHT] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_RIGHT] = DIK_RIGHT; + + dev = joypad[i][KEY_UP] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_UP] = DIK_UP; + + dev = joypad[i][KEY_DOWN] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_DOWN] = DIK_DOWN; + + dev = joypad[i][KEY_BUTTON_A] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_A] = DIK_Z; + + dev = joypad[i][KEY_BUTTON_B] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_B] = DIK_X; + + dev = joypad[i][KEY_BUTTON_L] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_L] = DIK_A; + + dev = joypad[i][KEY_BUTTON_R] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_R] = DIK_S; + + dev = joypad[i][KEY_BUTTON_START] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_START] = DIK_RETURN; + + dev = joypad[i][KEY_BUTTON_SELECT] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_SELECT] = DIK_BACK; + + dev = joypad[i][KEY_BUTTON_SPEED] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_SPEED] = DIK_SPACE; + + dev = joypad[i][KEY_BUTTON_CAPTURE] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_CAPTURE] = DIK_F12; + + dev = joypad[i][KEY_BUTTON_GS] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; + else + joypad[i][KEY_BUTTON_GS] = DIK_C; + } + + dev = motion[KEY_UP] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; else - joypad[i][KEY_BUTTON_SELECT] = DIK_BACK; - - dev = joypad[i][KEY_BUTTON_SPEED] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; + motion[KEY_UP] = DIK_NUMPAD8; + + dev = motion[KEY_DOWN] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; else - joypad[i][KEY_BUTTON_SPEED] = DIK_SPACE; - - dev = joypad[i][KEY_BUTTON_CAPTURE] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; + motion[KEY_DOWN] = DIK_NUMPAD2; + + dev = motion[KEY_LEFT] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; else - joypad[i][KEY_BUTTON_CAPTURE] = DIK_F12; - - dev = joypad[i][KEY_BUTTON_GS] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; + motion[KEY_LEFT] = DIK_NUMPAD4; + + dev = motion[KEY_RIGHT] >> 8; + if (dev < numDevices && dev >= 0) + pDevices[dev].needed = 1; else - joypad[i][KEY_BUTTON_GS] = DIK_C; - } - - dev = motion[KEY_UP] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - motion[KEY_UP] = DIK_NUMPAD8; - - dev = motion[KEY_DOWN] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - motion[KEY_DOWN] = DIK_NUMPAD2; - - dev = motion[KEY_LEFT] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - motion[KEY_LEFT] = DIK_NUMPAD4; - - dev = motion[KEY_RIGHT] >> 8; - if(dev < numDevices && dev >= 0) - pDevices[dev].needed = 1; - else - motion[KEY_RIGHT] = DIK_NUMPAD6; + motion[KEY_RIGHT] = DIK_NUMPAD6; } #define KEYDOWN(buffer,key) (buffer[key] & 0x80) static bool readKeyboard() { - if(pDevices[0].needed) { - HRESULT hret = pDevices[0].device-> - GetDeviceState(256, - (LPVOID)pDevices[0].data); - - if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { - hret = pDevices[0].device->Acquire(); - if(hret != DI_OK) - return false; - hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data); + if (pDevices[0].needed) { + HRESULT hret = pDevices[0].device-> + GetDeviceState(256, + (LPVOID)pDevices[0].data); + + if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { + hret = pDevices[0].device->Acquire(); + if (hret != DI_OK) + return false; + hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data); + } + + return hret == DI_OK; } - - return hret == DI_OK; - } - return true; + return true; } static bool readJoystick(int joy) { - if(pDevices[joy].needed) { - if(pDevices[joy].isPolled) - ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); - - HRESULT hret = pDevices[joy].device-> - GetDeviceState(sizeof(DIJOYSTATE), - (LPVOID)&pDevices[joy].state); - - if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { - hret = pDevices[joy].device->Acquire(); - - if(hret == DI_OK) { - - if(pDevices[joy].isPolled) - ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); - - hret = pDevices[joy].device-> - GetDeviceState(sizeof(DIJOYSTATE), - (LPVOID)&pDevices[joy].state); - } - } + if (pDevices[joy].needed) { + if (pDevices[joy].isPolled) + ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); + + HRESULT hret = pDevices[joy].device-> + GetDeviceState(sizeof(DIJOYSTATE), + (LPVOID)&pDevices[joy].state); + + if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { + hret = pDevices[joy].device->Acquire(); + + if (hret == DI_OK) { + + if (pDevices[joy].isPolled) + ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); + + hret = pDevices[joy].device-> + GetDeviceState(sizeof(DIJOYSTATE), + (LPVOID)&pDevices[joy].state); + } + } - return hret == DI_OK; - } + return hret == DI_OK; + } - return true; + return true; } static void checkKeyboard() { - HRESULT hret = pDevices[0].device->Acquire(); - hret = pDevices[0].device-> - GetDeviceState(256, - (LPVOID)pDevices[0].data); - - if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { - return; - } - - if(hret == DI_OK) { - for(int i = 0; i < 256; i++) { - if(KEYDOWN(pDevices[0].data, i)) { - SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i); - break; - } + // mham fix. Patch #1378104 + UCHAR keystate[256]; + HRESULT hret = pDevices[0].device->Acquire(); + + if (pDevices[0].first) { + pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data); + pDevices[0].first = FALSE; + return; + } + + hret = pDevices[0].device-> + GetDeviceState(256, (LPVOID)keystate); + + if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) { + return; } - } + + if (hret == DI_OK) { + for (int i = 0; i < 256; i++) { + if (keystate[i] == pDevices[0].data[i]) continue; + if (KEYDOWN(keystate, i)) { + SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i); + break; + } + } + } + memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256); } static void checkJoypads() { - DIDEVICEOBJECTINSTANCE di; + DIDEVICEOBJECTINSTANCE di; - ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); + ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); - di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); + di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); - int i =0; + int i =0; - DIJOYSTATE joystick; - - for(i = 1; i < numDevices; i++) { - HRESULT hret = pDevices[i].device->Acquire(); - - - if(pDevices[i].isPolled) - ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll(); - - hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick); - - int j; - - if(pDevices[i].first) { - memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); - pDevices[i].first = FALSE; - continue; - } - - for(j = 0; j < pDevices[i].nButtons; j++) { - if(((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) - & joystick.rgbButtons[j]) & 0x80) { - HWND focus = GetFocus(); - - SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128); - } - } - - for(j = 0; j < pDevices[i].nAxes && j < 8; j++) { - LONG value = pDevices[i].axis[j].center; - LONG old = 0; - switch(pDevices[i].axis[j].offset) { - case DIJOFS_X: - value = joystick.lX; - old = pDevices[i].state.lX; - break; - case DIJOFS_Y: - value = joystick.lY; - old = pDevices[i].state.lY; - break; - case DIJOFS_Z: - value = joystick.lZ; - old = pDevices[i].state.lZ; - break; - case DIJOFS_RX: - value = joystick.lRx; - old = pDevices[i].state.lRx; - break; - case DIJOFS_RY: - value = joystick.lRy; - old = pDevices[i].state.lRy; - break; - case DIJOFS_RZ: - value = joystick.lRz; - old = pDevices[i].state.lRz; - break; - case DIJOFS_SLIDER(0): - value = joystick.rglSlider[0]; - old = pDevices[i].state.rglSlider[0]; - break; - case DIJOFS_SLIDER(1): - value = joystick.rglSlider[1]; - old = pDevices[i].state.rglSlider[1]; - break; - } - if(value != old) { - if(value < pDevices[i].axis[j].negative) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)); - else if (value > pDevices[i].axis[j].positive) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1); - } - } - - for(j = 0;j < 4 && j < pDevices[i].nPovs; j++) { - if(LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) { - int state = getPovState(joystick.rgdwPOV[j]); - - if(state & POV_UP) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20); - else if(state & POV_DOWN) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21); - else if(state & POV_RIGHT) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22); - else if(state & POV_LEFT) - SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23); - } - } - - memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); - } -} - -BOOL checkKey(int key) -{ - int dev = (key >> 8); - - int k = (key & 255); - - if(dev == 0) { - return KEYDOWN(pDevices[0].data,k); - } else { - if(k < 16) { - int axis = k >> 1; - LONG value = pDevices[dev].axis[axis].center; - switch(pDevices[dev].axis[axis].offset) { - case DIJOFS_X: - value = pDevices[dev].state.lX; - break; - case DIJOFS_Y: - value = pDevices[dev].state.lY; - break; - case DIJOFS_Z: - value = pDevices[dev].state.lZ; - break; - case DIJOFS_RX: - value = pDevices[dev].state.lRx; - break; - case DIJOFS_RY: - value = pDevices[dev].state.lRy; - break; - case DIJOFS_RZ: - value = pDevices[dev].state.lRz; - break; - case DIJOFS_SLIDER(0): - value = pDevices[dev].state.rglSlider[0]; - break; - case DIJOFS_SLIDER(1): - value = pDevices[dev].state.rglSlider[1]; - break; - } - - if(k & 1) - return value > pDevices[dev].axis[axis].positive; - return value < pDevices[dev].axis[axis].negative; - } else if(k < 48) { - int hat = (k >> 2) & 3; - int state = getPovState(pDevices[dev].state.rgdwPOV[hat]); - BOOL res = FALSE; - switch(k & 3) { - case 0: - res = state & POV_UP; - break; - case 1: - res = state & POV_DOWN; - break; - case 2: - res = state & POV_RIGHT; - break; - case 3: - res = state & POV_LEFT; - break; - } - return res; - } else if(k >= 128) { - return pDevices[dev].state.rgbButtons[k-128] & 0x80; - } - } + DIJOYSTATE joystick; - return FALSE; + for (i = 1; i < numDevices; i++) { + HRESULT hret = pDevices[i].device->Acquire(); + + + if (pDevices[i].isPolled) + ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll(); + + hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick); + + int j; + + if (pDevices[i].first) { + memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); + pDevices[i].first = FALSE; + continue; + } + + for (j = 0; j < pDevices[i].nButtons; j++) { + if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) + & joystick.rgbButtons[j]) & 0x80) { + HWND focus = GetFocus(); + + SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128); + } + } + + for (j = 0; j < pDevices[i].nAxes && j < 8; j++) { + LONG value = pDevices[i].axis[j].center; + LONG old = 0; + switch (pDevices[i].axis[j].offset) { + case DIJOFS_X: + value = joystick.lX; + old = pDevices[i].state.lX; + break; + case DIJOFS_Y: + value = joystick.lY; + old = pDevices[i].state.lY; + break; + case DIJOFS_Z: + value = joystick.lZ; + old = pDevices[i].state.lZ; + break; + case DIJOFS_RX: + value = joystick.lRx; + old = pDevices[i].state.lRx; + break; + case DIJOFS_RY: + value = joystick.lRy; + old = pDevices[i].state.lRy; + break; + case DIJOFS_RZ: + value = joystick.lRz; + old = pDevices[i].state.lRz; + break; + case DIJOFS_SLIDER(0): + value = joystick.rglSlider[0]; + old = pDevices[i].state.rglSlider[0]; + break; + case DIJOFS_SLIDER(1): + value = joystick.rglSlider[1]; + old = pDevices[i].state.rglSlider[1]; + break; + } + if (value != old) { + if (value < pDevices[i].axis[j].negative) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)); + else if (value > pDevices[i].axis[j].positive) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1); + } + } + + for (j = 0;j < 4 && j < pDevices[i].nPovs; j++) { + if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) { + int state = getPovState(joystick.rgdwPOV[j]); + + if (state & POV_UP) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20); + else if (state & POV_DOWN) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21); + else if (state & POV_RIGHT) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22); + else if (state & POV_LEFT) + SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23); + } + } + + memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); + } } -DirectInput::DirectInput() +BOOL checkKey(LONG_PTR key) { - dinputDLL = NULL; + LONG_PTR dev = (key >> 8); + + LONG_PTR k = (key & 255); + + if (dev == 0) { + return KEYDOWN(pDevices[0].data,k); + } else { + if (k < 16) { + LONG_PTR axis = k >> 1; + LONG value = pDevices[dev].axis[axis].center; + switch (pDevices[dev].axis[axis].offset) { + case DIJOFS_X: + value = pDevices[dev].state.lX; + break; + case DIJOFS_Y: + value = pDevices[dev].state.lY; + break; + case DIJOFS_Z: + value = pDevices[dev].state.lZ; + break; + case DIJOFS_RX: + value = pDevices[dev].state.lRx; + break; + case DIJOFS_RY: + value = pDevices[dev].state.lRy; + break; + case DIJOFS_RZ: + value = pDevices[dev].state.lRz; + break; + case DIJOFS_SLIDER(0): + value = pDevices[dev].state.rglSlider[0]; + break; + case DIJOFS_SLIDER(1): + value = pDevices[dev].state.rglSlider[1]; + break; + } + + if (k & 1) + return value > pDevices[dev].axis[axis].positive; + return value < pDevices[dev].axis[axis].negative; + } else if (k < 48) { + LONG_PTR hat = (k >> 2) & 3; + int state = getPovState(pDevices[dev].state.rgdwPOV[hat]); + BOOL res = FALSE; + switch (k & 3) { + case 0: + res = state & POV_UP; + break; + case 1: + res = state & POV_DOWN; + break; + case 2: + res = state & POV_RIGHT; + break; + case 3: + res = state & POV_LEFT; + break; + } + return res; + } else if (k >= 128) { + return pDevices[dev].state.rgbButtons[k-128] & 0x80; + } + } + + return FALSE; } +DirectInput::DirectInput() +{} + DirectInput::~DirectInput() { - saveSettings(); - if(pDirectInput != NULL) { - if(pDevices) { - for(int i = 0; i < numDevices ; i++) { - if(pDevices[i].device) { - pDevices[i].device->Unacquire(); - pDevices[i].device->Release(); - pDevices[i].device = NULL; + saveSettings(); + if (pDirectInput != NULL) { + if (pDevices) { + for (int i = 0; i < numDevices ; i++) { + if (pDevices[i].device) { + pDevices[i].device->Unacquire(); + pDevices[i].device->Release(); + pDevices[i].device = NULL; + } + } + free(pDevices); + pDevices = NULL; } - } - free(pDevices); - pDevices = NULL; - } - - pDirectInput->Release(); - pDirectInput = NULL; - } - - if(dinputDLL) { - AfxFreeLibrary(dinputDLL); - dinputDLL = NULL; - } + + pDirectInput->Release(); + pDirectInput = NULL; + } } + bool DirectInput::initialize() { - joyDebug = GetPrivateProfileInt("config", - "joyDebug", - 0, - "VBA.ini"); - dinputDLL = AfxLoadLibrary("DINPUT.DLL"); - HRESULT (WINAPI *DInputCreate)(HINSTANCE,DWORD,LPDIRECTINPUT *,IUnknown *); - if(dinputDLL != NULL) { - DInputCreate = (HRESULT (WINAPI *)(HINSTANCE,DWORD,LPDIRECTINPUT *,IUnknown *)) - GetProcAddress(dinputDLL, "DirectInputCreateA"); - - if(DInputCreate == NULL) { - directXMessage("DirectInputCreateA"); - return false; - } - } else { - directXMessage("DINPUT.DLL"); - return false; - } - - HRESULT hret = DInputCreate(AfxGetInstanceHandle(), - DIRECTINPUT_VERSION, - &pDirectInput, - NULL); - if(hret != DI_OK) { - // errorMessage(myLoadString(IDS_ERROR_DISP_CREATE), hret); - return false; - } - hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK, + HRESULT hr; + + hr = DirectInput8Create( + AfxGetInstanceHandle(), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (LPVOID*)&pDirectInput, + NULL ); + + if ( hr != DI_OK ) { + return false; + } + + + + + hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback2, NULL, DIEDFL_ATTACHEDONLY); - - - pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo)); - - hret = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL); - pDevices[0].isPolled = false; - pDevices[0].needed = true; - - if(hret != DI_OK) { - // errorMessage(myLoadString(IDS_ERROR_DISP_CREATEDEVICE), hret); - return false; - } - - numDevices = 1; - hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK, + pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo)); + + hr = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL); + pDevices[0].isPolled = false; + pDevices[0].needed = true; + pDevices[0].first = true; + + if (hr != DI_OK) { + return false; + } + + + numDevices = 1; + + hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, NULL, - DIEDFL_ATTACHEDONLY); + DIEDFL_ATTACHEDONLY); + + + if (hr != DI_OK) { + return false; + } + + hr = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard); + + if (hr != DI_OK) { + return false; + } + + int i; + for (i = 1; i < numDevices; i++) { + pDevices[i].device->SetDataFormat(&c_dfDIJoystick); + pDevices[i].needed = false; + pDevices[i].first = true; + currentDevice = &pDevices[i]; + axisNumber = 0; + currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS); + currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV); + + + currentDevice = NULL; + } - // hret = pDevices[0].device->SetCooperativeLevel(hWindow, - // DISCL_FOREGROUND| - // DISCL_NONEXCLUSIVE); - - if(hret != DI_OK) { - // errorMessage(myLoadString(IDS_ERROR_DISP_LEVEL), hret); - return false; - } - - hret = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard); - - if(hret != DI_OK) { - // errorMessage(myLoadString(IDS_ERROR_DISP_DATAFORMAT), hret); - return false; - } - - for(int i = 1; i < numDevices; i++) { - pDevices[i].device->SetDataFormat(&c_dfDIJoystick); - pDevices[i].needed = false; - currentDevice = &pDevices[i]; - axisNumber = 0; - currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS); - currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV); - if(joyDebug) { - // don't translate. debug only - winlog("Joystick %2d polled : %d\n", i, currentDevice->isPolled); - winlog("Joystick %2d buttons : %d\n", i, currentDevice->nButtons); - winlog("Joystick %2d povs : %d\n", i, currentDevice->nPovs); - winlog("Joystick %2d axes : %d\n", i, currentDevice->nAxes); - for(int j = 0; j < currentDevice->nAxes; j++) { - winlog("Axis %2d offset : %08lx\n", j, currentDevice->axis[j]. - offset); - winlog("Axis %2d center : %08lx\n", j, currentDevice->axis[j]. - center); - winlog("Axis %2d negative : %08lx\n", j, currentDevice->axis[j]. - negative); - winlog("Axis %2d positive : %08lx\n", j, currentDevice->axis[j]. - positive); - } - } - - currentDevice = NULL; - } - - for(i = 0; i < numDevices; i++) - pDevices[i].device->Acquire(); - - return true; + for (i = 0; i < numDevices; i++) + pDevices[i].device->Acquire(); + + return true; } bool DirectInput::readDevices() { - bool ok = true; - for(int i = 0; i < numDevices; i++) { - if(pDevices[i].needed) { - if(i) { - ok = readJoystick(i); - } else - ok = readKeyboard(); + bool ok = true; + for (int i = 0; i < numDevices; i++) { + if (pDevices[i].needed) { + if (i) { + ok = readJoystick(i); + } else + ok = readKeyboard(); + } } - } - return ok; + return ok; } u32 DirectInput::readDevice(int which) { - u32 res = 0; - int i = theApp.joypadDefault; - if(which >= 0 && which <= 3) - i = which; - - if(checkKey(joypad[i][KEY_BUTTON_A])) - res |= 1; - if(checkKey(joypad[i][KEY_BUTTON_B])) - res |= 2; - if(checkKey(joypad[i][KEY_BUTTON_SELECT])) - res |= 4; - if(checkKey(joypad[i][KEY_BUTTON_START])) - res |= 8; - if(checkKey(joypad[i][KEY_RIGHT])) - res |= 16; - if(checkKey(joypad[i][KEY_LEFT])) - res |= 32; - if(checkKey(joypad[i][KEY_UP])) - res |= 64; - if(checkKey(joypad[i][KEY_DOWN])) - res |= 128; - if(checkKey(joypad[i][KEY_BUTTON_R])) - res |= 256; - if(checkKey(joypad[i][KEY_BUTTON_L])) - res |= 512; - - if(checkKey(joypad[i][KEY_BUTTON_GS])) - res |= 4096; - - res |= theApp.skinButtons; - if(theApp.autoFire) { - res &= (~theApp.autoFire); - if(theApp.autoFireToggle) - res |= theApp.autoFire; - theApp.autoFireToggle = !theApp.autoFireToggle; - } - - // disallow L+R or U+D of being pressed at the same time - if((res & 48) == 48) - res &= ~16; - if((res & 192) == 192) - res &= ~128; - - if(theApp.movieRecording) { - if(i == theApp.joypadDefault) { - if(res != theApp.movieLastJoypad) { - fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile); - fwrite(&res, 1, sizeof(res), theApp.movieFile); - theApp.movieLastJoypad = res; - } - } - } - if(theApp.moviePlaying) { - if(theApp.movieFrame == theApp.moviePlayFrame) { - theApp.movieLastJoypad = theApp.movieNextJoypad; - theApp.movieReadNext(); - } - res = theApp.movieLastJoypad; - } - // we don't record speed up or screen capture buttons - if(checkKey(joypad[i][KEY_BUTTON_SPEED]) || theApp.speedupToggle) - res |= 1024; - if(checkKey(joypad[i][KEY_BUTTON_CAPTURE])) - res |= 2048; - - return res; -} - -CString DirectInput::getKeyName(int key) -{ - int d = (key >> 8); - int k = key & 255; - - DIDEVICEOBJECTINSTANCE di; - - ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); - - di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); - - CString winBuffer = winResLoadString(IDS_ERROR); - - if(d == 0) { - pDevices[0].device->GetObjectInfo(&di,key,DIPH_BYOFFSET); - winBuffer = di.tszName; - } else { - if(k < 16) { - if(k < 4) { - switch(k) { - case 0: - winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d); - break; - case 1: - winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d); - break; - case 2: - winBuffer.Format(winResLoadString(IDS_JOY_UP), d); - break; - case 3: - winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d); - break; + u32 res = 0; + int i = theApp.joypadDefault; + if (which >= 0 && which <= 3) + i = which; + + if (checkKey(joypad[i][KEY_BUTTON_A])) + res |= 1; + if (checkKey(joypad[i][KEY_BUTTON_B])) + res |= 2; + if (checkKey(joypad[i][KEY_BUTTON_SELECT])) + res |= 4; + if (checkKey(joypad[i][KEY_BUTTON_START])) + res |= 8; + if (checkKey(joypad[i][KEY_RIGHT])) + res |= 16; + if (checkKey(joypad[i][KEY_LEFT])) + res |= 32; + if (checkKey(joypad[i][KEY_UP])) + res |= 64; + if (checkKey(joypad[i][KEY_DOWN])) + res |= 128; + if (checkKey(joypad[i][KEY_BUTTON_R])) + res |= 256; + if (checkKey(joypad[i][KEY_BUTTON_L])) + res |= 512; + + if (checkKey(joypad[i][KEY_BUTTON_GS])) + res |= 4096; + + if (theApp.autoFire) { + res &= (~theApp.autoFire); + if (theApp.autoFireToggle) + res |= theApp.autoFire; + theApp.autoFireToggle = !theApp.autoFireToggle; + } + + // disallow L+R or U+D of being pressed at the same time + if ((res & 48) == 48) + res &= ~16; + if ((res & 192) == 192) + res &= ~128; + + if (theApp.movieRecording) { + if (i == theApp.joypadDefault) { + if (res != theApp.movieLastJoypad) { + fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile); + fwrite(&res, 1, sizeof(res), theApp.movieFile); + theApp.movieLastJoypad = res; + } } - } else { - pDevices[d].device->GetObjectInfo(&di, - pDevices[d].axis[k>>1].offset, - DIPH_BYOFFSET); - if(k & 1) - winBuffer.Format("Joy %d %s +", d, di.tszName); - else - winBuffer.Format("Joy %d %s -", d, di.tszName); - } - } else if(k < 48) { - int hat = (k >> 2) & 3; - pDevices[d].device->GetObjectInfo(&di, - DIJOFS_POV(hat), - DIPH_BYOFFSET); - char *dir = "up"; - int dd = k & 3; - if(dd == 1) - dir = "down"; - else if(dd == 2) - dir = "right"; - else if(dd == 3) - dir = "left"; - winBuffer.Format("Joy %d %s %s", d, di.tszName, dir); + } + if (theApp.moviePlaying) { + if (theApp.movieFrame == theApp.moviePlayFrame) { + theApp.movieLastJoypad = theApp.movieNextJoypad; + theApp.movieReadNext(); + } + res = theApp.movieLastJoypad; + } + // we don't record speed up or screen capture buttons + if (checkKey(joypad[i][KEY_BUTTON_SPEED]) || theApp.speedupToggle) + res |= 1024; + if (checkKey(joypad[i][KEY_BUTTON_CAPTURE])) + res |= 2048; + + return res; +} + +CString DirectInput::getKeyName(LONG_PTR key) +{ + LONG_PTR d = (key >> 8); + LONG_PTR k = key & 255; + + DIDEVICEOBJECTINSTANCE di; + + ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); + + di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); + + CString winBuffer = winResLoadString(IDS_ERROR); + + if (d == 0) { + pDevices[0].device->GetObjectInfo( &di, (DWORD)key, DIPH_BYOFFSET ); + winBuffer = di.tszName; } else { - pDevices[d].device->GetObjectInfo(&di, - DIJOFS_BUTTON(k-128), - DIPH_BYOFFSET); - winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName); + if (k < 16) { + if (k < 4) { + switch (k) { + case 0: + winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d); + break; + case 1: + winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d); + break; + case 2: + winBuffer.Format(winResLoadString(IDS_JOY_UP), d); + break; + case 3: + winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d); + break; + } + } else { + pDevices[d].device->GetObjectInfo(&di, + pDevices[d].axis[k>>1].offset, + DIPH_BYOFFSET); + if (k & 1) + winBuffer.Format("Joy %d %s +", d, di.tszName); + else + winBuffer.Format("Joy %d %s -", d, di.tszName); + } + } else if (k < 48) { + LONG_PTR hat = (k >> 2) & 3; + pDevices[d].device->GetObjectInfo(&di, + (DWORD)DIJOFS_POV(hat), + DIPH_BYOFFSET); + char *dir = "up"; + LONG_PTR dd = k & 3; + if (dd == 1) + dir = "down"; + else if (dd == 2) + dir = "right"; + else if (dd == 3) + dir = "left"; + winBuffer.Format("Joy %d %s %s", d, di.tszName, dir); + } else { + pDevices[d].device->GetObjectInfo(&di, + (DWORD)DIJOFS_BUTTON(k-128), + DIPH_BYOFFSET); + winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName); + } } - } - return winBuffer; + return winBuffer; } void DirectInput::checkKeys() { - ::checkKeys(); + ::checkKeys(); } void DirectInput::checkMotionKeys() { - if(checkKey(motion[KEY_LEFT])) { - theApp.sensorX += 3; - if(theApp.sensorX > 2197) - theApp.sensorX = 2197; - if(theApp.sensorX < 2047) - theApp.sensorX = 2057; - } else if(checkKey(motion[KEY_RIGHT])) { - theApp.sensorX -= 3; - if(theApp.sensorX < 1897) - theApp.sensorX = 1897; - if(theApp.sensorX > 2047) - theApp.sensorX = 2037; - } else if(theApp.sensorX > 2047) { - theApp.sensorX -= 2; - if(theApp.sensorX < 2047) - theApp.sensorX = 2047; - } else { - theApp.sensorX += 2; - if(theApp.sensorX > 2047) - theApp.sensorX = 2047; - } - - if(checkKey(motion[KEY_UP])) { - theApp.sensorY += 3; - if(theApp.sensorY > 2197) - theApp.sensorY = 2197; - if(theApp.sensorY < 2047) - theApp.sensorY = 2057; - } else if(checkKey(motion[KEY_DOWN])) { - theApp.sensorY -= 3; - if(theApp.sensorY < 1897) - theApp.sensorY = 1897; - if(theApp.sensorY > 2047) - theApp.sensorY = 2037; - } else if(theApp.sensorY > 2047) { - theApp.sensorY -= 2; - if(theApp.sensorY < 2047) - theApp.sensorY = 2047; - } else { - theApp.sensorY += 2; - if(theApp.sensorY > 2047) - theApp.sensorY = 2047; - } + if (checkKey(motion[KEY_LEFT])) { + theApp.sensorX += 3; + if (theApp.sensorX > 2197) + theApp.sensorX = 2197; + if (theApp.sensorX < 2047) + theApp.sensorX = 2057; + } else if (checkKey(motion[KEY_RIGHT])) { + theApp.sensorX -= 3; + if (theApp.sensorX < 1897) + theApp.sensorX = 1897; + if (theApp.sensorX > 2047) + theApp.sensorX = 2037; + } else if (theApp.sensorX > 2047) { + theApp.sensorX -= 2; + if (theApp.sensorX < 2047) + theApp.sensorX = 2047; + } else { + theApp.sensorX += 2; + if (theApp.sensorX > 2047) + theApp.sensorX = 2047; + } + + if (checkKey(motion[KEY_UP])) { + theApp.sensorY += 3; + if (theApp.sensorY > 2197) + theApp.sensorY = 2197; + if (theApp.sensorY < 2047) + theApp.sensorY = 2057; + } else if (checkKey(motion[KEY_DOWN])) { + theApp.sensorY -= 3; + if (theApp.sensorY < 1897) + theApp.sensorY = 1897; + if (theApp.sensorY > 2047) + theApp.sensorY = 2037; + } else if (theApp.sensorY > 2047) { + theApp.sensorY -= 2; + if (theApp.sensorY < 2047) + theApp.sensorY = 2047; + } else { + theApp.sensorY += 2; + if (theApp.sensorY > 2047) + theApp.sensorY = 2047; + } } Input *newDirectInput() { - return new DirectInput; + return new DirectInput; } void DirectInput::checkDevices() { - checkJoypads(); - checkKeyboard(); + checkJoypads(); + checkKeyboard(); } void DirectInput::activate() { - for(int i = 0; i < numDevices; i++) { - if(pDevices != NULL && pDevices[i].device != NULL) - pDevices[i].device->Acquire(); - } + for (int i = 0; i < numDevices; i++) { + if (pDevices != NULL && pDevices[i].device != NULL) + pDevices[i].device->Acquire(); + } } void DirectInput::loadSettings() { - winReadKeys(); + winReadKeys(); } void DirectInput::saveSettings() { - winSaveKeys(); + winSaveKeys(); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/DirectSound.cpp ./src/win32/DirectSound.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/DirectSound.cpp 2004-05-13 23:27:55 +0900 +++ ./src/win32/DirectSound.cpp 2006-08-26 01:11:43 +0900 @@ -1,6 +1,7 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -16,358 +17,357 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// MFC #include "stdafx.h" -#include "VBA.h" + +// Tools #include "AVIWrite.h" -#include "Sound.h" #include "WavWriter.h" +// Internals #include "../System.h" #include "../GBA.h" #include "../Globals.h" #include "../Sound.h" -#include -#include +// DirectSound8 +#include +#pragma comment( lib, "Dsound" ) +#pragma comment( lib, "Dxguid" ) + class DirectSound : public ISound { private: - HINSTANCE dsoundDLL; - LPDIRECTSOUND pDirectSound; - LPDIRECTSOUNDBUFFER dsbPrimary; - LPDIRECTSOUNDBUFFER dsbSecondary; - LPDIRECTSOUNDNOTIFY dsbNotify; - HANDLE dsbEvent; - WAVEFORMATEX wfx; + LPDIRECTSOUND8 pDirectSound; // DirectSound interface + LPDIRECTSOUNDBUFFER dsbPrimary; // Primary DirectSound buffer + LPDIRECTSOUNDBUFFER dsbSecondary; // Secondary DirectSound buffer + LPDIRECTSOUNDNOTIFY8 dsbNotify; + HANDLE dsbEvent; + WAVEFORMATEX wfx; // Primary buffer wave format public: - DirectSound(); - virtual ~DirectSound(); + DirectSound(); + virtual ~DirectSound(); - bool init(); - void pause(); - void reset(); - void resume(); - void write(); + bool init(); // initialize the primary and secondary sound buffer + void pause(); // pause the secondary sound buffer + void reset(); // stop and reset the secondary sound buffer + void resume(); // resume the secondary sound buffer + void write(); // write the emulated sound to the secondary sound buffer }; + DirectSound::DirectSound() { - dsoundDLL = NULL; - pDirectSound = NULL; - dsbPrimary = NULL; - dsbSecondary = NULL; - dsbNotify = NULL; - dsbEvent = NULL; + CoInitialize( NULL ); + + pDirectSound = NULL; + dsbPrimary = NULL; + dsbSecondary = NULL; + dsbNotify = NULL; + dsbEvent = NULL; } + DirectSound::~DirectSound() { - if(theApp.aviRecorder != NULL) { - delete theApp.aviRecorder; - theApp.aviRecorder = NULL; - theApp.aviFrameNumber = 0; - } - - if(theApp.soundRecording) { - if(theApp.soundRecorder != NULL) { - delete theApp.soundRecorder; - theApp.soundRecorder = NULL; - } - theApp.soundRecording = false; - } - - if(dsbNotify != NULL) { - dsbNotify->Release(); - dsbNotify = NULL; - } - - if(dsbEvent != NULL) { - CloseHandle(dsbEvent); - dsbEvent = NULL; - } - - if(pDirectSound != NULL) { - if(dsbPrimary != NULL) { - dsbPrimary->Release(); - dsbPrimary = NULL; - } - - if(dsbSecondary != NULL) { - dsbSecondary->Release(); - dsbSecondary = NULL; - } - - pDirectSound->Release(); - pDirectSound = NULL; - } - - if(dsoundDLL != NULL) { - FreeLibrary(dsoundDLL); - dsoundDLL = NULL; - } + if(theApp.aviRecorder) { + delete theApp.aviRecorder; + theApp.aviRecorder = NULL; + theApp.aviFrameNumber = 0; + } + + if(theApp.soundRecording) { + if(theApp.soundRecorder) { + delete theApp.soundRecorder; + theApp.soundRecorder = NULL; + } + theApp.soundRecording = false; + } + + if(dsbNotify) { + dsbNotify->Release(); + dsbNotify = NULL; + } + + if(dsbEvent) { + CloseHandle(dsbEvent); + dsbEvent = NULL; + } + + if(pDirectSound) { + if(dsbPrimary) { + dsbPrimary->Release(); + dsbPrimary = NULL; + } + + if(dsbSecondary) { + dsbSecondary->Release(); + dsbSecondary = NULL; + } + + pDirectSound->Release(); + pDirectSound = NULL; + } + + CoUninitialize(); } + bool DirectSound::init() { - HRESULT hr; - - dsoundDLL = LoadLibrary("DSOUND.DLL"); - HRESULT (WINAPI *DSoundCreate)(LPCGUID,LPDIRECTSOUND *,IUnknown *); - if(dsoundDLL != NULL) { - DSoundCreate = (HRESULT (WINAPI *)(LPCGUID,LPDIRECTSOUND *,IUnknown *)) - GetProcAddress(dsoundDLL, "DirectSoundCreate"); - - if(DSoundCreate == NULL) { - theApp.directXMessage("DirectSoundCreate"); - return false; - } - } else { - theApp.directXMessage("DSOUND.DLL"); - return false; - } - - if((hr = DSoundCreate(NULL,&pDirectSound,NULL) != DS_OK)) { - // errorMessage(myLoadString(IDS_ERROR_SOUND_CREATE), hr); - systemMessage(IDS_CANNOT_CREATE_DIRECTSOUND, - "Cannot create DirectSound %08x", hr); - pDirectSound = NULL; - dsbSecondary = NULL; - return false; - } - - if((hr=pDirectSound->SetCooperativeLevel((HWND)*theApp.m_pMainWnd, - DSSCL_EXCLUSIVE)) != DS_OK) { - // errorMessage(myLoadString(IDS_ERROR_SOUND_LEVEL), hr); - systemMessage(IDS_CANNOT_SETCOOPERATIVELEVEL, - "Cannot SetCooperativeLevel %08x", hr); - return false; - } - - DSBUFFERDESC dsbdesc; - ZeroMemory(&dsbdesc,sizeof(DSBUFFERDESC)); - dsbdesc.dwSize=sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; - - if((hr=pDirectSound->CreateSoundBuffer(&dsbdesc, - &dsbPrimary, - NULL) != DS_OK)) { - // errorMessage(myLoadString(IDS_ERROR_SOUND_BUFFER),hr); - systemMessage(IDS_CANNOT_CREATESOUNDBUFFER, - "Cannot CreateSoundBuffer %08x", hr); - return false; - } - - // Set primary buffer format - - memset(&wfx, 0, sizeof(WAVEFORMATEX)); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = 2; - switch(soundQuality) { - case 2: - wfx.nSamplesPerSec = 22050; - soundBufferLen = 736*2; - soundBufferTotalLen = 7360*2; - break; - case 4: - wfx.nSamplesPerSec = 11025; - soundBufferLen = 368*2; - soundBufferTotalLen = 3680*2; - break; - default: - soundQuality = 1; - wfx.nSamplesPerSec = 44100; - soundBufferLen = 1470*2; - soundBufferTotalLen = 14700*2; - } - wfx.wBitsPerSample = 16; - wfx.nBlockAlign = (wfx.wBitsPerSample / 8) * wfx.nChannels; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - - if((hr = dsbPrimary->SetFormat(&wfx)) != DS_OK) { - // errorMessage(myLoadString(IDS_ERROR_SOUND_PRIMARY),hr); - systemMessage(IDS_CANNOT_SETFORMAT_PRIMARY, - "Cannot SetFormat for primary %08x", hr); - return false; - } - - ZeroMemory(&dsbdesc,sizeof(DSBUFFERDESC)); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY; - dsbdesc.dwBufferBytes = soundBufferTotalLen; - dsbdesc.lpwfxFormat = &wfx; - - if((hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL)) - != DS_OK) { - dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2; - if((hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL)) - != DS_OK) { - systemMessage(IDS_CANNOT_CREATESOUNDBUFFER_SEC, - "Cannot CreateSoundBuffer secondary %08x", hr); - return false; - } - } - - dsbSecondary->SetCurrentPosition(0); - - if(!theApp.useOldSync) { - hr = dsbSecondary->QueryInterface(IID_IDirectSoundNotify, - (void **)&dsbNotify); - if(!FAILED(hr)) { - dsbEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - DSBPOSITIONNOTIFY notify[10]; - - for(int i = 0; i < 10; i++) { - notify[i].dwOffset = i*soundBufferLen; - notify[i].hEventNotify = dsbEvent; - } - if(FAILED(dsbNotify->SetNotificationPositions(10, notify))) { - dsbNotify->Release(); - dsbNotify = NULL; - CloseHandle(dsbEvent); - dsbEvent = NULL; - } - } - } - - hr = dsbPrimary->Play(0,0,DSBPLAY_LOOPING); - - if(hr != DS_OK) { - // errorMessage(myLoadString(IDS_ERROR_SOUND_PLAYPRIM), hr); - systemMessage(IDS_CANNOT_PLAY_PRIMARY, "Cannot Play primary %08x", hr); - return false; - } - - systemSoundOn = true; - - return true; + HRESULT hr; + DWORD freq; + DSBUFFERDESC dsbdesc; + int i; + + + // Initialize DirectSound + if( FAILED( hr = DirectSoundCreate8( &DSDEVID_DefaultPlayback, &pDirectSound, NULL ) ) ) { + systemMessage( IDS_CANNOT_CREATE_DIRECTSOUND, _T("Cannot create DirectSound %08x"), hr ); + pDirectSound = NULL; + return false; + } + + + if( FAILED( hr = pDirectSound->SetCooperativeLevel( theApp.m_pMainWnd->GetSafeHwnd(), DSSCL_EXCLUSIVE ) ) ) { + systemMessage( IDS_CANNOT_SETCOOPERATIVELEVEL, _T("Cannot SetCooperativeLevel %08x"), hr ); + return false; + } + + + // Create primary sound buffer + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + if( theApp.dsoundDisableHardwareAcceleration ) { + dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; + } + + if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbPrimary, NULL ) ) ) { + systemMessage(IDS_CANNOT_CREATESOUNDBUFFER, _T("Cannot CreateSoundBuffer %08x"), hr); + return false; + } + + switch(soundQuality) + { + case 4: + freq = 11025; + break; + case 2: + freq = 22050; + break; + default: + soundQuality = 1; + case 1: + freq = 44100; + break; + } + soundBufferLen = freq*2/30; + soundBufferTotalLen = soundBufferLen * 10; + + ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; + wfx.nSamplesPerSec = freq; + wfx.wBitsPerSample = 16; + wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + if( FAILED( hr = dsbPrimary->SetFormat( &wfx ) ) ) { + systemMessage( IDS_CANNOT_SETFORMAT_PRIMARY, _T("CreateSoundBuffer(primary) failed %08x"), hr ); + return false; + } + + + // Create secondary sound buffer + ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS; + if( theApp.dsoundDisableHardwareAcceleration ) { + dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; + } + dsbdesc.dwBufferBytes = soundBufferTotalLen; + dsbdesc.lpwfxFormat = &wfx; + + if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbSecondary, NULL ) ) ) { + systemMessage( IDS_CANNOT_CREATESOUNDBUFFER, _T("CreateSoundBuffer(secondary) failed %08x"), hr ); + return false; + } + + if( FAILED( hr = dsbSecondary->SetCurrentPosition( 0 ) ) ) { + systemMessage( 0, _T("dsbSecondary->SetCurrentPosition failed %08x"), hr ); + return false; + } + + + if( !theApp.useOldSync ) { + if( FAILED( hr = dsbSecondary->QueryInterface( IID_IDirectSoundNotify8, (LPVOID*)&dsbNotify ) ) ) { + dsbEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + DSBPOSITIONNOTIFY notify[10]; + for( i = 0; i < 10; i++ ) { + notify[i].dwOffset = i * soundBufferLen; + notify[i].hEventNotify = dsbEvent; + } + + if( FAILED( dsbNotify->SetNotificationPositions( 10, notify ) ) ) { + dsbNotify->Release(); + dsbNotify = NULL; + CloseHandle(dsbEvent); + dsbEvent = NULL; + } + } + } + + + // Play primary buffer + if( FAILED( hr = dsbPrimary->Play( 0, 0, DSBPLAY_LOOPING ) ) ) { + systemMessage( IDS_CANNOT_PLAY_PRIMARY, _T("Cannot Play primary %08x"), hr ); + return false; + } + + systemSoundOn = true; + + return true; } + void DirectSound::pause() { - if(dsbSecondary != NULL) { - DWORD status = 0; - dsbSecondary->GetStatus(&status); - - if(status & DSBSTATUS_PLAYING) { - dsbSecondary->Stop(); - } - } + if( dsbSecondary == NULL ) return; + + DWORD status; + + dsbSecondary->GetStatus( &status ); + + if( status & DSBSTATUS_PLAYING ) dsbSecondary->Stop(); } + void DirectSound::reset() { - if(dsbSecondary) { - dsbSecondary->Stop(); - dsbSecondary->SetCurrentPosition(0); - } + if( dsbSecondary == NULL ) return; + + dsbSecondary->Stop(); + + dsbSecondary->SetCurrentPosition( 0 ); } + void DirectSound::resume() { - if(dsbSecondary != NULL) { - dsbSecondary->Play(0,0,DSBPLAY_LOOPING); - } + if( dsbSecondary == NULL ) return; + + dsbSecondary->Play( 0, 0, DSBPLAY_LOOPING ); } + void DirectSound::write() { - int len = soundBufferLen; - LPVOID lpvPtr1; - DWORD dwBytes1; - LPVOID lpvPtr2; - DWORD dwBytes2; - - if(!pDirectSound) - return; - - if(theApp.soundRecording) { - if(dsbSecondary) { - if(theApp.soundRecorder == NULL) { - theApp.soundRecorder = new WavWriter; - WAVEFORMATEX format; - dsbSecondary->GetFormat(&format, sizeof(format), NULL); - if(theApp.soundRecorder->Open(theApp.soundRecordName)) - theApp.soundRecorder->SetFormat(&format); - } - } - - if(theApp.soundRecorder) { - theApp.soundRecorder->AddSound((u8 *)soundFinalWave, len); - } - } - - if(theApp.aviRecording) { - if(theApp.aviRecorder) { - if(dsbSecondary) { - if(!theApp.aviRecorder->IsSoundAdded()) { - WAVEFORMATEX format; - dsbSecondary->GetFormat(&format, sizeof(format), NULL); - theApp.aviRecorder->SetSoundFormat(&format); - } - } - - theApp.aviRecorder->AddSound((const char *)soundFinalWave, len); - } - } - - HRESULT hr; - - if(!speedup && synchronize && !theApp.throttle) { - DWORD status=0; - hr = dsbSecondary->GetStatus(&status); - if(status && DSBSTATUS_PLAYING) { - if(!soundPaused) { - DWORD play; - while(true) { - dsbSecondary->GetCurrentPosition(&play, NULL); - - if(play < soundNextPosition || - play > soundNextPosition+soundBufferLen) { - break; - } - - if(dsbEvent) { - WaitForSingleObject(dsbEvent, 50); - } - } - } - } else { - soundPaused = 1; - } - } - // Obtain memory address of write block. This will be in two parts - // if the block wraps around. - hr = dsbSecondary->Lock(soundNextPosition, soundBufferLen, &lpvPtr1, - &dwBytes1, &lpvPtr2, &dwBytes2, - 0); - - // If DSERR_BUFFERLOST is returned, restore and retry lock. - if (DSERR_BUFFERLOST == hr) { - dsbSecondary->Restore(); - hr = dsbSecondary->Lock(soundNextPosition, soundBufferLen,&lpvPtr1, - &dwBytes1, &lpvPtr2, &dwBytes2, - 0); - } - - soundNextPosition += soundBufferLen; - soundNextPosition = soundNextPosition % soundBufferTotalLen; - - if SUCCEEDED(hr) { - // Write to pointers. - CopyMemory(lpvPtr1, soundFinalWave, dwBytes1); - if (NULL != lpvPtr2) { - CopyMemory(lpvPtr2, soundFinalWave+dwBytes1, dwBytes2); - } - // Release the data back to DirectSound. - hr = dsbSecondary->Unlock(lpvPtr1, dwBytes1, lpvPtr2, - dwBytes2); - } + if(!pDirectSound) return; + + + HRESULT hr; + DWORD status = 0; + DWORD play = 0; + WAVEFORMATEX format; + LPVOID lpvPtr1; + DWORD dwBytes1 = 0; + LPVOID lpvPtr2; + DWORD dwBytes2 = 0; + + + if( theApp.soundRecording ) { + if( dsbSecondary ) { + if( theApp.soundRecorder ) { + theApp.soundRecorder->AddSound( (u8 *)soundFinalWave, soundBufferLen ); + } else { + theApp.soundRecorder = new WavWriter; + dsbSecondary->GetFormat( &format, sizeof(format), NULL ); + if( theApp.soundRecorder->Open( theApp.soundRecordName ) ) { + theApp.soundRecorder->SetFormat( &format ); + } + } + } + } + + + if( theApp.aviRecording ) { + if( theApp.aviRecorder ) { + if( dsbSecondary ) { + if( !theApp.aviRecorder->IsSoundAdded() ) { + dsbSecondary->GetFormat( &format, sizeof(format), NULL ); + theApp.aviRecorder->SetSoundFormat( &format ); + } + } + theApp.aviRecorder->AddSound( (const char *)soundFinalWave, soundBufferLen ); + } + } + + + if( !speedup && synchronize && !theApp.throttle ) { + hr = dsbSecondary->GetStatus(&status); + if( status & DSBSTATUS_PLAYING ) { + if( !soundPaused ) { + while( true ) { + dsbSecondary->GetCurrentPosition(&play, NULL); + if( ( play < soundNextPosition ) || ( play > (soundNextPosition + soundBufferLen) ) ) { + break; + } + if( dsbEvent ) { + WaitForSingleObject(dsbEvent, 50); + } + } + } + } else { + soundPaused = 1; + } + } + + + // Obtain memory address of write block. + // This will be in two parts if the block wraps around. + if( DSERR_BUFFERLOST == ( hr = dsbSecondary->Lock( + soundNextPosition, + soundBufferLen, + &lpvPtr1, + &dwBytes1, + &lpvPtr2, + &dwBytes2, + 0 ) ) ) { + // If DSERR_BUFFERLOST is returned, restore and retry lock. + dsbSecondary->Restore(); + hr = dsbSecondary->Lock( + soundNextPosition, + soundBufferLen, + &lpvPtr1, + &dwBytes1, + &lpvPtr2, + &dwBytes2, + 0 ); + } + + soundNextPosition += soundBufferLen; + soundNextPosition = soundNextPosition % soundBufferTotalLen; + + if( SUCCEEDED( hr ) ) { + // Write to pointers. + CopyMemory( lpvPtr1, soundFinalWave, dwBytes1 ); + if ( lpvPtr2 ) { + CopyMemory( lpvPtr2, soundFinalWave + dwBytes1, dwBytes2 ); + } + + // Release the data back to DirectSound. + hr = dsbSecondary->Unlock( lpvPtr1, dwBytes1, lpvPtr2, dwBytes2 ); + } else { + systemMessage( 0, _T("dsbSecondary->Lock() failed: %08x"), hr ); + return; + } } + ISound *newDirectSound() { - return new DirectSound(); + return new DirectSound(); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Directories.cpp ./src/win32/Directories.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Directories.cpp 2004-05-13 23:27:43 +0900 +++ ./src/win32/Directories.cpp 2006-08-04 20:24:24 +0900 @@ -26,6 +26,7 @@ #include "WinResUtil.h" #include +#include #ifdef _DEBUG #define new DEBUG_NEW @@ -54,27 +55,21 @@ Directories::Directories(CWnd* pParent /*=NULL*/) : CDialog(Directories::IDD, pParent) { - //{{AFX_DATA_INIT(Directories) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT } void Directories::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(Directories) DDX_Control(pDX, IDC_SAVE_PATH, m_savePath); DDX_Control(pDX, IDC_ROM_PATH, m_romPath); DDX_Control(pDX, IDC_GBROM_PATH, m_gbromPath); DDX_Control(pDX, IDC_CAPTURE_PATH, m_capturePath); DDX_Control(pDX, IDC_BATTERY_PATH, m_batteryPath); - //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(Directories, CDialog) - //{{AFX_MSG_MAP(Directories) ON_BN_CLICKED(IDC_BATTERY_DIR, OnBatteryDir) ON_BN_CLICKED(IDC_BATTERY_DIR_RESET, OnBatteryDirReset) ON_BN_CLICKED(IDC_CAPTURE_DIR, OnCaptureDir) @@ -85,8 +80,7 @@ ON_BN_CLICKED(IDC_ROM_DIR_RESET, OnRomDirReset) ON_BN_CLICKED(IDC_SAVE_DIR, OnSaveDir) ON_BN_CLICKED(IDC_SAVE_DIR_RESET, OnSaveDirReset) - //}}AFX_MSG_MAP - END_MESSAGE_MAP() +END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Directories message handlers @@ -206,23 +200,76 @@ void Directories::OnOK() { - CString buffer; - m_romPath.GetWindowText(buffer); - if(!buffer.IsEmpty()) - regSetStringValue("romdir", buffer); - m_gbromPath.GetWindowText(buffer); - if(!buffer.IsEmpty()) - regSetStringValue("gbromdir", buffer); - m_batteryPath.GetWindowText(buffer); - if(!buffer.IsEmpty()) - regSetStringValue("batteryDir", buffer); - m_savePath.GetWindowText(buffer); - if(!buffer.IsEmpty()) - regSetStringValue("saveDir", buffer); - m_capturePath.GetWindowText(buffer); - if(!buffer.IsEmpty()) - regSetStringValue("captureDir", buffer); - EndDialog(TRUE); + char baseDir[MAX_PATH+1]; + char temp[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + + + CString buffer; + + m_romPath.GetWindowText(buffer); + if( !buffer.IsEmpty() ) + regSetStringValue( "romdir", buffer ); + if( buffer[0] == '.' ) { + strcpy( temp, baseDir ); + strcat( temp, "\\" ); + strcat( temp, buffer ); + buffer = temp; + } + if( !directoryDoesExist( buffer ) ) + SHCreateDirectoryEx( NULL, buffer, NULL ); + + m_gbromPath.GetWindowText(buffer); + if( !buffer.IsEmpty() ) + regSetStringValue( "gbromdir", buffer ); + if( buffer[0] == '.' ) { + strcpy( temp, baseDir ); + strcat( temp, "\\" ); + strcat( temp, buffer ); + buffer = temp; + } + if( !directoryDoesExist( buffer ) ) + SHCreateDirectoryEx( NULL, buffer, NULL ); + + m_batteryPath.GetWindowText(buffer); + if( !buffer.IsEmpty() ) + regSetStringValue( "batteryDir", buffer ); + if( buffer[0] == '.' ) { + strcpy( temp, baseDir ); + strcat( temp, "\\" ); + strcat( temp, buffer ); + buffer = temp; + } + if( !directoryDoesExist( buffer ) ) + SHCreateDirectoryEx( NULL, buffer, NULL ); + + m_savePath.GetWindowText(buffer); + if( !buffer.IsEmpty() ) + regSetStringValue( "saveDir", buffer ); + if( buffer[0] == '.' ) { + strcpy( temp, baseDir ); + strcat( temp, "\\" ); + strcat( temp, buffer ); + buffer = temp; + } + if( !directoryDoesExist( buffer ) ) + SHCreateDirectoryEx( NULL, buffer, NULL ); + + m_capturePath.GetWindowText(buffer); + if( !buffer.IsEmpty() ) + regSetStringValue( "captureDir", buffer ); + if( buffer[0] == '.' ) { + strcpy( temp, baseDir ); + strcat( temp, "\\" ); + strcat( temp, buffer ); + buffer = temp; + } + if( !directoryDoesExist( buffer ) ) + SHCreateDirectoryEx( NULL, buffer, NULL ); + + EndDialog(TRUE); } CString Directories::browseForDir(CString title) diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Directories.h ./src/win32/Directories.h --- ../VisualBoyAdvance-1.7.2/src/win32/Directories.h 2004-05-13 22:46:19 +0900 +++ ./src/win32/Directories.h 2006-08-04 20:24:24 +0900 @@ -75,7 +75,24 @@ virtual void OnOK(); //}}AFX_MSG DECLARE_MESSAGE_MAP() - }; +private: + + bool directoryDoesExist(const char *directory) + { // returns true if the directory does exist + HANDLE hDir; + hDir = CreateFile( + directory, + GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL ); + bool retval = (hDir == INVALID_HANDLE_VALUE) ? false : true; + CloseHandle( hDir ); + return retval; + } +}; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Disassemble.cpp ./src/win32/Disassemble.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Disassemble.cpp 2004-05-13 23:27:30 +0900 +++ ./src/win32/Disassemble.cpp 2005-06-25 15:23:31 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -118,6 +118,7 @@ void Disassemble::OnArm() { mode = 1; + address&=0xfffffffC; refresh(); } @@ -133,21 +134,30 @@ CString buffer; m_address.GetWindowText(buffer); sscanf(buffer, "%x", &address); + if (mode==1) + address&=0xfffffffc; + else if (mode==2) + address&=0xfffffffe; refresh(); } void Disassemble::OnGopc() { + if(rom != NULL) + { if(armState) address = armNextPC - 16; else address = armNextPC - 8; refresh(); + } } void Disassemble::OnNext() { + if(rom != NULL) + { CPULoop(1); if(armState) { u32 total = address+count*4; @@ -163,6 +173,7 @@ } } refresh(); + } } void Disassemble::OnRefresh() @@ -173,6 +184,7 @@ void Disassemble::OnThumb() { mode = 2; + address&=0xfffffffe; refresh(); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Display.h ./src/win32/Display.h --- ../VisualBoyAdvance-1.7.2/src/win32/Display.h 2004-05-13 22:45:59 +0900 +++ ./src/win32/Display.h 2006-08-06 02:29:31 +0900 @@ -17,6 +17,8 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#pragma once + enum DISPLAY_TYPE { GDI = 0, DIRECT_DRAW = 1, @@ -32,13 +34,15 @@ virtual bool initialize() = 0; virtual void cleanup() = 0; virtual void render() = 0; - virtual void checkFullScreen() { }; - virtual void renderMenu() { }; - virtual void clear()=0; + virtual void checkFullScreen() {}; + virtual void renderMenu() {}; + virtual void clear() = 0; virtual bool changeRenderSize(int w, int h) { return true; }; virtual void resize(int w, int h) {}; - virtual void setOption(const char *option, int value) = 0; + virtual void setOption(const char *option, int value) {}; virtual DISPLAY_TYPE getType() = 0; virtual bool isSkinSupported() { return false; } virtual int selectFullScreenMode(GUID **) = 0; }; + +void copyImage( void *source, void *destination, unsigned int width, unsigned int height, unsigned int destinationPitch, unsigned int colorDepth ); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/FileDlg.cpp ./src/win32/FileDlg.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/FileDlg.cpp 2004-05-13 23:27:04 +0900 +++ ./src/win32/FileDlg.cpp 2006-05-27 23:47:33 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -18,7 +18,7 @@ // FileDlg.cpp: implementation of the FileDlg class. // -////////////////////////////////////////////////////////////////////// + #include "stdafx.h" #include #include @@ -159,20 +159,23 @@ ASSERT(typeControl != NULL); - int sel = ::SendMessage(typeControl, CB_GETCURSEL, 0, 0); + LRESULT sel = ::SendMessage(typeControl, CB_GETCURSEL, 0, 0); ASSERT(sel != -1); LPCTSTR typeName = extensions[sel]; if(filename.GetLength() == 0) { - filename.Format("*%s", typeName); + if(strlen(typeName) != 0) + filename.Format("*%s", typeName); } else { - int index = filename.Find('.'); - if (index == -1) { - filename = filename + typeName; - } else { - filename = filename.Left(index) + typeName; + if(strlen(typeName) != 0) { + int index = filename.Find('.'); + if (index == -1) { + filename = filename + typeName; + } else { + filename = filename.Left(index) + typeName; + } } } SetWindowText(fileNameControl, filename); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBACheats.cpp ./src/win32/GBACheats.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBACheats.cpp 2004-05-13 23:26:53 +0900 +++ ./src/win32/GBACheats.cpp 2006-05-27 23:47:33 +0900 @@ -684,7 +684,7 @@ break; } - cheatsAdd(code, buffer,address, value,-1, sizeType); + cheatsAdd(code, buffer, address ,address, value,-1, sizeType); return true; } ///////////////////////////////////////////////////////////////////////////// @@ -765,16 +765,16 @@ if(mark != -1) { LVITEM item; for(int i = 0; i < count; i++) { - memset(&item,0, sizeof(item)); + memset(&item, 0, sizeof(item)); item.mask = LVIF_PARAM|LVIF_STATE; item.stateMask = LVIS_SELECTED; item.iItem = i; if(m_list.GetItem(&item)) { if(item.state & LVIS_SELECTED) { if(cheatsList[item.lParam].enabled) - cheatsDisable(item.lParam); + cheatsDisable((int)(item.lParam & 0xFFFFFFFF)); else - cheatsEnable(item.lParam); + cheatsEnable((int)(item.lParam & 0xFFFFFFFF)); } } } @@ -796,7 +796,7 @@ item.stateMask = LVIS_SELECTED; if(m_list.GetItem(&item)) { if(item.state & LVIS_SELECTED) { - cheatsDelete(item.lParam, restoreValues); + cheatsDelete((int)(item.lParam & 0xFFFFFFFF), restoreValues); } } } @@ -838,9 +838,9 @@ if(((l->uOldState & LVIS_STATEIMAGEMASK)>>12) != (((l->uNewState & LVIS_STATEIMAGEMASK)>>12))) { if(m_list.GetCheck(l->iItem)) - cheatsEnable(l->lParam); + cheatsEnable((int)(l->lParam & 0xFFFFFFFF)); else - cheatsDisable(l->lParam); + cheatsDisable((int)(l->lParam & 0xFFFFFFFF)); refresh(); } } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBACheats.h ./src/win32/GBACheats.h --- ../VisualBoyAdvance-1.7.2/src/win32/GBACheats.h 2004-05-13 22:45:27 +0900 +++ ./src/win32/GBACheats.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_GBACHEATS_H__FC31D47D_52C8_42B2_95C7_7C3FD09316A4__INCLUDED_) #define AFX_GBACHEATS_H__FC31D47D_52C8_42B2_95C7_7C3FD09316A4__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBCheatsDlg.cpp ./src/win32/GBCheatsDlg.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBCheatsDlg.cpp 2004-05-13 23:26:36 +0900 +++ ./src/win32/GBCheatsDlg.cpp 2006-06-07 06:04:21 +0900 @@ -637,7 +637,7 @@ m_desc.GetWindowText(buffer); - int bank = (address >> 16); + LONG_PTR bank = (address >> 16); address &= 0xFFFF; if(address >= 0xd000) @@ -689,9 +689,7 @@ buffer.Format("%02x:%08x", (address>>16), address&0xFFFF); m_address.SetWindowText(buffer); m_address.EnableWindow(FALSE); - ::SetWindowLong(m_address, - GWL_USERDATA, - address); + ::SetWindowLongPtr( m_address.GetSafeHwnd(), GWLP_USERDATA, address); numberType = regQueryDwordValue("gbCheatsNumberType", 2); if(numberType < 0 || numberType > 2) @@ -826,9 +824,9 @@ item.iItem = mark; if(m_list.GetItem(&item)) { if(gbCheatList[item.lParam].enabled) - gbCheatDisable(item.lParam); + gbCheatDisable((int)item.lParam); else - gbCheatEnable(item.lParam); + gbCheatEnable((int)item.lParam); refresh(); } } @@ -844,7 +842,7 @@ item.mask = LVIF_PARAM; item.iItem = mark; if(m_list.GetItem(&item)) { - gbCheatRemove(item.lParam); + gbCheatRemove((int)item.lParam); refresh(); } } @@ -872,9 +870,9 @@ if(((l->uOldState & LVIS_STATEIMAGEMASK)>>12) != (((l->uNewState & LVIS_STATEIMAGEMASK)>>12))) { if(m_list.GetCheck(l->iItem)) - gbCheatEnable(l->lParam); + gbCheatEnable((int)l->lParam); else - gbCheatDisable(l->lParam); + gbCheatDisable((int)l->lParam); refresh(); } } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBCheatsDlg.h ./src/win32/GBCheatsDlg.h --- ../VisualBoyAdvance-1.7.2/src/win32/GBCheatsDlg.h 2004-05-13 22:45:12 +0900 +++ ./src/win32/GBCheatsDlg.h 2006-06-07 06:04:21 +0900 @@ -121,7 +121,7 @@ // Implementation protected: - u32 address; + LONG_PTR address; // Generated message map functions //{{AFX_MSG(AddGBCheat) diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBColorDlg.cpp ./src/win32/GBColorDlg.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBColorDlg.cpp 2004-05-13 23:26:06 +0900 +++ ./src/win32/GBColorDlg.cpp 2006-05-27 23:47:33 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -32,28 +32,31 @@ static u16 defaultPalettes[][24] = { { - 0x7FFF, 0x56B5, 0x318C, 0x0000, 0x7FFF, 0x56B5, 0x318C, 0x0000, + 0x7FFF, 0x56B5, 0x318C, 0x0000, 0x7FFF, 0x56B5, 0x318C, 0x0000, }, { - 0x6200, 0x7E10, 0x7C10, 0x5000, 0x6200, 0x7E10, 0x7C10, 0x5000, + 0x6200, 0x7E10, 0x7C10, 0x5000, 0x6200, 0x7E10, 0x7C10, 0x5000, }, { - 0x4008, 0x4000, 0x2000, 0x2008, 0x4008, 0x4000, 0x2000, 0x2008, + 0x4008, 0x4000, 0x2000, 0x2008, 0x4008, 0x4000, 0x2000, 0x2008, }, { - 0x43F0, 0x03E0, 0x4200, 0x2200, 0x43F0, 0x03E0, 0x4200, 0x2200, + 0x43F0, 0x03E0, 0x4200, 0x2200, 0x43F0, 0x03E0, 0x4200, 0x2200, }, { - 0x43FF, 0x03FF, 0x221F, 0x021F, 0x43FF, 0x03FF, 0x221F, 0x021F, + 0x43FF, 0x03FF, 0x221F, 0x021F, 0x43FF, 0x03FF, 0x221F, 0x021F, }, { - 0x621F, 0x7E1F, 0x7C1F, 0x2010, 0x621F, 0x7E1F, 0x7C1F, 0x2010, + 0x621F, 0x7E1F, 0x7C1F, 0x2010, 0x621F, 0x7E1F, 0x7C1F, 0x2010, }, { - 0x621F, 0x401F, 0x001F, 0x2010, 0x621F, 0x401F, 0x001F, 0x2010, + 0x621F, 0x401F, 0x001F, 0x2010, 0x621F, 0x401F, 0x001F, 0x2010, }, { - 0x421F, 0x03E0, 0x7C00, 0x401F, 0x021F, 0x2200, 0x4008, 0x2010, + 0x1B8E, 0x02C0, 0x0DA0, 0x1140, 0x1B8E, 0x02C0, 0x0DA0, 0x1140, + }, + { + 0x7BDE, /*0x23F0*/ 0x5778, /*0x5DC0*/ 0x5640, 0x0000, 0x7BDE, /*0x3678*/ 0x529C, /*0x0980*/ 0x2990, 0x0000, } }; @@ -70,20 +73,15 @@ GBColorDlg::GBColorDlg(CWnd* pParent /*=NULL*/) : CDialog(GBColorDlg::IDD, pParent) { - //{{AFX_DATA_INIT(GBColorDlg) - which = -1; - //}}AFX_DATA_INIT which = gbPaletteOption; } void GBColorDlg::DoDataExchange(CDataExchange* pDX) { - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(GBColorDlg) + CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_PREDEFINED, m_predefined); - DDX_Radio(pDX, IDC_DEFAULT, which); - //}}AFX_DATA_MAP + DDX_Radio(pDX, IDC_DEFAULT, which); } @@ -95,8 +93,8 @@ ON_BN_CLICKED(IDC_USER2, OnUser2) ON_BN_CLICKED(ID_OK, OnOk) ON_BN_CLICKED(ID_CANCEL, OnCancel) - ON_CBN_SELCHANGE(IDC_PREDEFINED, OnSelchangePredefined) - //}}AFX_MSG_MAP + ON_CBN_SELCHANGE(IDC_PREDEFINED, OnSelchangePredefined) + //}}AFX_MSG_MAP ON_CONTROL_RANGE(BN_CLICKED, IDC_COLOR_BG0, IDC_COLOR_OB3, OnColorClicked) END_MESSAGE_MAP() @@ -167,10 +165,12 @@ "Green Forest", "Hot Desert", "Pink Dreams", - "Weird Colors" + "Weird Colors", + "Real GB Colors", + "Real 'GB on GBASP' Colors" }; - for(int j = 0; j < 7; j++) { + for(int j = 0; j < 9; j++) { int index = m_predefined.AddString(names[j]); m_predefined.SetItemData(index, j); } @@ -222,15 +222,20 @@ { id -= IDC_COLOR_BG0; - u16 color = colors[id]; + u16 color = colors[which*8+id]; + + COLORREF colorInit = + RGB((color & 0x1f) << 3, ((color >> 5) & 0x1f) << 3, ((color >> 10) & 0x1f) << 3); - CColorDialog dlg(RGB(color & 0x1f, (color >> 5) & 0x1f, (color >> 10) & 0x1f), + CColorDialog dlg(colorInit, CC_FULLOPEN | CC_ANYCOLOR, this); - if(dlg.DoModal()) { + + if(IDOK == dlg.DoModal()) + { COLORREF c = dlg.GetColor(); - colors[which*8+id] = (u16)((c >> 3) & 0x1f | ((c >> 11) & 0x1f) << 5 | - ((c >> 19) & 0x1f) << 10); + colors[which*8+id] = (u16)((c >> 3) & 0x1f | ((c >> 11) & 0x1f) << 5 | ((c >> 19) & 0x1f) << 10); + colorControls[id].setColor(colors[which*8+id]); } } @@ -246,7 +251,7 @@ int sel = m_predefined.GetCurSel(); if(sel != -1) { - int data = m_predefined.GetItemData(sel); + DWORD_PTR data = m_predefined.GetItemData(sel); for(int i = 0; i < 8; i++) { colorControls[i].setColor(defaultPalettes[data][i]); colors[which*8+i] = defaultPalettes[data][i]; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBColorDlg.h ./src/win32/GBColorDlg.h --- ../VisualBoyAdvance-1.7.2/src/win32/GBColorDlg.h 2004-05-13 22:45:01 +0900 +++ ./src/win32/GBColorDlg.h 2006-05-27 23:47:33 +0900 @@ -21,7 +21,7 @@ #define AFX_GBCOLORDLG_H__8D6126EF_06BB_48CF_ABB3_2CC4B1B60358__INCLUDED_ #include "ColorButton.h" // Added by ClassView -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBDisassemble.cpp ./src/win32/GBDisassemble.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBDisassemble.cpp 2004-05-13 23:25:55 +0900 +++ ./src/win32/GBDisassemble.cpp 2006-01-05 00:10:33 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -39,6 +39,7 @@ extern gbRegister HL; extern gbRegister SP; extern gbRegister PC; +extern u8 register_LY; extern u16 IFF; extern int gbDis(char *, u16); @@ -114,8 +115,9 @@ void GBDisassemble::OnGo() { CString buffer; + m_address.GetWindowText(buffer); - sscanf(buffer, "%x", &address); + sscanf(buffer, "%hx", &address); refresh(); } @@ -242,6 +244,8 @@ GetDlgItem(IDC_R5)->SetWindowText(buffer); sprintf(buffer, "%04x", IFF); GetDlgItem(IDC_R6)->SetWindowText(buffer); + sprintf(buffer, "%04x", register_LY); + GetDlgItem(IDC_LY)->SetWindowText(buffer); m_z = (AF.B.B0 & 0x80) != 0; m_n = (AF.B.B0 & 0x40) != 0; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBDisassemble.h ./src/win32/GBDisassemble.h --- ../VisualBoyAdvance-1.7.2/src/win32/GBDisassemble.h 2004-05-13 22:44:47 +0900 +++ ./src/win32/GBDisassemble.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_GBDISASSEMBLE_H__3EFD5B47_6DBF_4F63_8F91_A9511EC590EB__INCLUDED_) #define AFX_GBDISASSEMBLE_H__3EFD5B47_6DBF_4F63_8F91_A9511EC590EB__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBMapView.cpp ./src/win32/GBMapView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBMapView.cpp 2004-05-13 23:25:45 +0900 +++ ./src/win32/GBMapView.cpp 2006-06-07 06:04:21 +0900 @@ -499,8 +499,8 @@ u8 *colors = (u8 *)lParam; mapViewZoom.setColors(colors); - int x = wParam & 0xffff; - int y = (wParam >> 16); + int x = (int)(wParam & 0xffff); + int y = (int)(wParam >> 16); CString buffer; buffer.Format("(%d,%d)", x, y); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBMapView.h ./src/win32/GBMapView.h --- ../VisualBoyAdvance-1.7.2/src/win32/GBMapView.h 2004-05-13 22:44:36 +0900 +++ ./src/win32/GBMapView.h 2006-05-27 23:47:33 +0900 @@ -31,7 +31,7 @@ #include "ZoomControl.h" #include "ResizeDlg.h" #include "IUpdate.h" -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView ///////////////////////////////////////////////////////////////////////////// // GBMapView dialog diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBPaletteView.cpp ./src/win32/GBPaletteView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBPaletteView.cpp 2004-05-13 23:25:08 +0900 +++ ./src/win32/GBPaletteView.cpp 2004-11-01 03:26:01 +0900 @@ -136,6 +136,8 @@ return; } + captureBuffer = dlg.GetPathName(); + PaletteViewControl *p = NULL; if(which == 0) diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GBTileView.cpp ./src/win32/GBTileView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GBTileView.cpp 2004-05-13 23:24:44 +0900 +++ ./src/win32/GBTileView.cpp 2006-05-27 23:47:33 +0900 @@ -460,8 +460,8 @@ u8 *colors = (u8 *)lParam; zoom.setColors(colors); - int x = (wParam & 0xFFFF)/8; - int y = ((wParam >> 16) & 0xFFFF)/8; + int x = (int)((wParam & 0xffff)/8); + int y = (int)(((wParam >> 16) & 0xFFFF)/8); int tiles = 0x0000; if(charBase) diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GDIDisplay.cpp ./src/win32/GDIDisplay.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GDIDisplay.cpp 2004-05-13 23:24:10 +0900 +++ ./src/win32/GDIDisplay.cpp 2006-06-22 01:58:15 +0900 @@ -1,6 +1,7 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -17,12 +18,14 @@ // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" -#include + +#include "Display.h" #include "../System.h" #include "../GBA.h" #include "../Globals.h" #include "../Text.h" +#include "../Util.h" #include "VBA.h" #include "MainWnd.h" @@ -36,7 +39,6 @@ #endif extern void winlog(const char *,...); -extern int RGB_LOW_BITS_MASK; extern int Init_2xSaI(u32); extern int systemSpeed; @@ -216,10 +218,8 @@ if(systemColorDepth == 16) { if(systemGreenShift == 6) { Init_2xSaI(565); - RGB_LOW_BITS_MASK=0x821; } else { Init_2xSaI(555); - RGB_LOW_BITS_MASK=0x421; } } else if(systemColorDepth == 32) Init_2xSaI(32); @@ -241,27 +241,7 @@ cpu_mmx = 0; #endif - switch(systemColorDepth) { - case 16: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - } - 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); - } - } - break; - } + utilUpdateSystemColorMaps(); theApp.updateFilter(); theApp.updateIFB(); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GameOverrides.cpp ./src/win32/GameOverrides.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/GameOverrides.cpp 1970-01-01 09:00:00 +0900 +++ ./src/win32/GameOverrides.cpp 2006-08-02 04:21:16 +0900 @@ -0,0 +1,291 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005-2006 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. + +// GameOverrides.cpp : implementation file +// + +#include "stdafx.h" +#include "vba.h" +#include "GameOverrides.h" +#include "../GBA.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// GameOverrides dialog + + +GameOverrides::GameOverrides(CWnd* pParent /*=NULL*/) + : CDialog(GameOverrides::IDD, pParent) +{ + //{{AFX_DATA_INIT(GameOverrides) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void GameOverrides::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(GameOverrides) + DDX_Control(pDX, IDC_NAME, m_name); + DDX_Control(pDX, IDC_MIRRORING, m_mirroring); + DDX_Control(pDX, IDC_FLASH_SIZE, m_flashSize); + DDX_Control(pDX, IDC_SAVE_TYPE, m_saveType); + DDX_Control(pDX, IDC_RTC, m_rtc); + DDX_Control(pDX, IDC_COMMENT, m_comment); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(GameOverrides, CDialog) + //{{AFX_MSG_MAP(GameOverrides) + ON_BN_CLICKED(IDC_DEFAULTS, OnDefaults) + //}}AFX_MSG_MAP + END_MESSAGE_MAP() + + ///////////////////////////////////////////////////////////////////////////// +// GameOverrides message handlers + +void GameOverrides::OnOK() +{ + char tempName[2048]; + + GetModuleFileName(NULL, tempName, 2048); + + char *p = strrchr(tempName, '\\'); + if(p) + *p = 0; + + char buffer[5]; + strncpy(buffer, (const char *)&rom[0xac], 4); + buffer[4] = 0; + + strcat(tempName, "\\vba-over.ini"); + + char comment[0xFF]; + m_comment.GetWindowText(comment, 0xFF); + WritePrivateProfileString(buffer, "comment", !strncmp(comment, "", 0xFF) ? NULL : comment, tempName); + + int rtc = m_rtc.GetCurSel(); + int flash = m_flashSize.GetCurSel(); + int save = m_saveType.GetCurSel(); + int mirroring = m_mirroring.GetCurSel(); + if(rtc == 0 && flash == 0 && save == 0 && mirroring == 0) + WritePrivateProfileString(buffer, NULL, NULL, tempName); + else { + char *value = NULL; + switch(rtc) { + case 1: + value = "0"; + break; + case 2: + value = "1"; + break; + } + WritePrivateProfileString(buffer, "rtcEnabled", value, tempName); + value = NULL; + switch(flash) { + case 1: + value = "0x10000"; + break; + case 2: + value = "0x20000"; + break; + } + WritePrivateProfileString(buffer, "flashSize", value, tempName); + value = NULL; + switch(save) { + case 1: + value = "0"; + break; + case 2: + value = "1"; + break; + case 3: + value = "2"; + break; + case 4: + value = "3"; + break; + case 5: + value = "4"; + break; + case 6: + value = "5"; + break; + } + WritePrivateProfileString(buffer, "saveType", value, tempName); + value = NULL; + switch(mirroring) { + case 1: + value = "0"; + break; + case 2: + value = "1"; + break; + } + WritePrivateProfileString(buffer, "mirroringEnabled", value, tempName); + } + CDialog::OnOK(); +} + +void GameOverrides::OnDefaults() +{ + m_rtc.SetCurSel(0); + m_flashSize.SetCurSel(0); + m_saveType.SetCurSel(0); + m_mirroring.SetCurSel(0); +} + +void GameOverrides::OnCancel() +{ + CDialog::OnCancel(); +} + +BOOL GameOverrides::OnInitDialog() +{ + CDialog::OnInitDialog(); + + char tempName[2048]; + + const char *rtcValues[] = { + "Default", + "Disabled", + "Enabled" + }; + const char *flashValues[] = { + "Default", + "64K", + "128K" + }; + const char *saveValues[] = { + "Default", + "Automatic", + "EEPROM", + "SRAM", + "Flash", + "EEPROM+Sensor", + "None" + }; + const char *mirroringValues[] = { + "Default", + "Disabled", + "Enabled" + }; + + int i; + + for(i = 0; i < 3; i++) { + m_rtc.AddString(rtcValues[i]); + } + for(i = 0; i < 3; i++) { + m_flashSize.AddString(flashValues[i]); + } + for(i = 0; i < 7; i++) { + m_saveType.AddString(saveValues[i]); + } + for(i = 0; i < 3; i++) { + m_mirroring.AddString(mirroringValues[i]); + } + + GetModuleFileName(NULL, tempName, 2048); + + char *p = strrchr(tempName, '\\'); + if(p) + *p = 0; + + char buffer[5]; + strncpy(buffer, (const char *)&rom[0xac], 4); + buffer[4] = 0; + + strcat(tempName, "\\vba-over.ini"); + + m_name.SetWindowText(buffer); + + char comment[0xFF]; + GetPrivateProfileString(buffer, + "comment", + "", + comment, + 0xFF, + tempName); + m_comment.SetWindowText(comment); + + UINT v = GetPrivateProfileInt(buffer, + "rtcEnabled", + -1, + tempName); + switch(v) { + case 0: + m_rtc.SetCurSel(1); + break; + case 1: + m_rtc.SetCurSel(2); + break; + default: + m_rtc.SetCurSel(0); + } + v = GetPrivateProfileInt(buffer, + "flashSize", + -1, + tempName); + switch(v) { + case 0x10000: + m_flashSize.SetCurSel(1); + break; + case 0x20000: + m_flashSize.SetCurSel(2); + break; + default: + m_flashSize.SetCurSel(0); + } + + v = GetPrivateProfileInt(buffer, + "saveType", + -1, + tempName); + if(v != (UINT)-1 && (v > 5)) + v = (UINT)-1; + if(v != (UINT)-1) + m_saveType.SetCurSel(v+1); + else + m_saveType.SetCurSel(0); + + v = GetPrivateProfileInt(buffer, + "mirroringEnabled", + -1, + tempName); + switch(v) { + case 0: + m_mirroring.SetCurSel(1); + break; + case 1: + m_mirroring.SetCurSel(2); + break; + default: + m_mirroring.SetCurSel(0); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff -urN ../VisualBoyAdvance-1.7.2/src/win32/GameOverrides.h ./src/win32/GameOverrides.h --- ../VisualBoyAdvance-1.7.2/src/win32/GameOverrides.h 1970-01-01 09:00:00 +0900 +++ ./src/win32/GameOverrides.h 2006-08-02 04:21:16 +0900 @@ -0,0 +1,74 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 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. + +#include "afxwin.h" +#if !defined(AFX_GAMEOVERRIDES_H__EEEFE37F_F477_455D_8682_705FB2DBCC0C__INCLUDED_) +#define AFX_GAMEOVERRIDES_H__EEEFE37F_F477_455D_8682_705FB2DBCC0C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GameOverrides.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// GameOverrides dialog + +class GameOverrides : public CDialog +{ +// Construction +public: + GameOverrides(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(GameOverrides) + enum { IDD = IDD_GAME_OVERRIDES }; + CEdit m_name; + CComboBox m_mirroring; + CComboBox m_flashSize; + CComboBox m_saveType; + CComboBox m_rtc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(GameOverrides) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(GameOverrides) + virtual void OnOK(); + afx_msg void OnDefaults(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CEdit m_comment; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GAMEOVERRIDES_H__EEEFE37F_F477_455D_8682_705FB2DBCC0C__INCLUDED_) diff -urN ../VisualBoyAdvance-1.7.2/src/win32/IOViewer.cpp ./src/win32/IOViewer.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/IOViewer.cpp 2004-05-13 23:23:37 +0900 +++ ./src/win32/IOViewer.cpp 2005-06-25 15:23:31 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -67,6 +67,22 @@ ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate) ON_CBN_SELCHANGE(IDC_ADDRESSES, OnSelchangeAddresses) ON_BN_CLICKED(IDC_APPLY, OnApply) + ON_BN_CLICKED(IDC_BIT_0, bitChange) + ON_BN_CLICKED(IDC_BIT_1, bitChange) + ON_BN_CLICKED(IDC_BIT_2, bitChange) + ON_BN_CLICKED(IDC_BIT_3, bitChange) + ON_BN_CLICKED(IDC_BIT_4, bitChange) + ON_BN_CLICKED(IDC_BIT_5, bitChange) + ON_BN_CLICKED(IDC_BIT_6, bitChange) + ON_BN_CLICKED(IDC_BIT_7, bitChange) + ON_BN_CLICKED(IDC_BIT_8, bitChange) + ON_BN_CLICKED(IDC_BIT_9, bitChange) + ON_BN_CLICKED(IDC_BIT_10, bitChange) + ON_BN_CLICKED(IDC_BIT_11, bitChange) + ON_BN_CLICKED(IDC_BIT_12, bitChange) + ON_BN_CLICKED(IDC_BIT_13, bitChange) + ON_BN_CLICKED(IDC_BIT_14, bitChange) + ON_BN_CLICKED(IDC_BIT_15, bitChange) //}}AFX_MSG_MAP END_MESSAGE_MAP() @@ -80,10 +96,29 @@ DestroyWindow(); } +void IOViewer::bitChange() +{ + CString buffer; + u16 data = 0; + + for(int i = 0; i < 16; i++) { + CButton *pWnd = (CButton *)GetDlgItem(IDC_BIT_0 + i); + + if(pWnd) { + if(pWnd->GetCheck()) + data |= (1 << i); + } + } + + buffer.Format("%04X", data); + m_value.SetWindowText(buffer); +} + void IOViewer::OnRefresh() { // TODO: Add your control notification handler code here - + + update(); } void IOViewer::OnAutoUpdate() @@ -186,6 +221,8 @@ void IOViewer::OnApply() { + if(rom != NULL) + { const IOData *sel = &ioViewRegisters[selected]; u16 res = 0; for(int i = 0; i < 16; i++) { @@ -198,4 +235,5 @@ } CPUWriteHalfWord(0x4000000+sel->offset, res); update(); + } } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/IOViewer.h ./src/win32/IOViewer.h --- ../VisualBoyAdvance-1.7.2/src/win32/IOViewer.h 2004-05-13 22:42:26 +0900 +++ ./src/win32/IOViewer.h 2005-06-25 15:23:31 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -37,6 +37,7 @@ // Construction public: void update(); + void bitChange(); bool autoUpdate; int selected; IOViewer(CWnd* pParent = NULL); // standard constructor diff -urN ../VisualBoyAdvance-1.7.2/src/win32/IOViewerRegs.h ./src/win32/IOViewerRegs.h --- ../VisualBoyAdvance-1.7.2/src/win32/IOViewerRegs.h 2004-05-13 22:42:00 +0900 +++ ./src/win32/IOViewerRegs.h 2005-06-25 15:23:31 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -258,7 +258,7 @@ } }, { - &BG2HOFS, 0x18, "0x4000018-BG8HOFS", 0x01FF, + &BG2HOFS, 0x18, "0x4000018-BG2HOFS", 0x01FF, { "", "", @@ -1119,7 +1119,7 @@ } }, { - NULL, 0x82, "0x4000082-SGCNT0_H", 0xFF1F, + NULL, 0x82, "0x4000082-SGCNT0_H", 0xFF0F, { "", "Sound 1-4 Volume (2 bits)", diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Input.h ./src/win32/Input.h --- ../VisualBoyAdvance-1.7.2/src/win32/Input.h 2004-05-13 22:41:34 +0900 +++ ./src/win32/Input.h 2006-06-07 06:04:21 +0900 @@ -43,7 +43,7 @@ virtual bool readDevices() = 0; virtual u32 readDevice(int which) = 0; - virtual CString getKeyName(int key) = 0; + virtual CString getKeyName(LONG_PTR key) = 0; virtual void checkKeys() = 0; virtual void checkMotionKeys() = 0; virtual void checkDevices() = 0; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Joypad.cpp ./src/win32/Joypad.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Joypad.cpp 2004-05-13 23:23:26 +0900 +++ ./src/win32/Joypad.cpp 2006-06-07 06:04:21 +0900 @@ -30,8 +30,8 @@ static char THIS_FILE[] = __FILE__; #endif -extern USHORT joypad[4][13]; -extern USHORT motion[4]; +extern LONG_PTR joypad[4][13]; +extern LONG_PTR motion[4]; ///////////////////////////////////////////////////////////////////////////// // JoypadEditControl @@ -46,27 +46,21 @@ BEGIN_MESSAGE_MAP(JoypadEditControl, CEdit) - //{{AFX_MSG_MAP(JoypadEditControl) - ON_WM_CHAR() - //}}AFX_MSG_MAP ON_MESSAGE(JOYCONFIG_MESSAGE, OnJoyConfig) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // JoypadEditControl message handlers -void JoypadEditControl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) -{ -} - LRESULT JoypadEditControl::OnJoyConfig(WPARAM wParam, LPARAM lParam) { - SetWindowLong(GetSafeHwnd(), GWL_USERDATA,((wParam<<8)|lParam)); - SetWindowText(theApp.input->getKeyName((wParam<<8)|lParam)); - GetParent()->GetNextDlgTabItem(this, FALSE)->SetFocus(); - return TRUE; + SetWindowLongPtr( this->GetSafeHwnd(), GWLP_USERDATA, (wParam<<8) | lParam ); + this->SetWindowText( theApp.input->getKeyName( (int)((wParam<<8)|lParam) ) ); + GetParent()->GetNextDlgTabItem(this, FALSE)->SetFocus(); + return TRUE; } + BOOL JoypadEditControl::PreTranslateMessage(MSG *pMsg) { if(pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)) @@ -112,14 +106,11 @@ BEGIN_MESSAGE_MAP(JoypadConfig, CDialog) - //{{AFX_MSG_MAP(JoypadConfig) ON_BN_CLICKED(ID_CANCEL, OnCancel) ON_BN_CLICKED(ID_OK, OnOk) - ON_WM_CHAR() ON_WM_DESTROY() ON_WM_TIMER() ON_WM_KEYDOWN() - //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// @@ -137,10 +128,6 @@ EndDialog(TRUE); } -void JoypadConfig::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) -{ -} - void JoypadConfig::OnDestroy() { CDialog::OnDestroy(); @@ -148,7 +135,7 @@ KillTimer(timerId); } -void JoypadConfig::OnTimer(UINT nIDEvent) +void JoypadConfig::OnTimer(UINT_PTR nIDEvent) { theApp.input->checkDevices(); @@ -163,45 +150,45 @@ { CDialog::OnInitDialog(); - timerId = SetTimer(0,200,NULL); + timerId = SetTimer(0,50,NULL); - SetWindowLong(up, GWL_USERDATA,joypad[which][KEY_UP]); + SetWindowLongPtr(up, GWLP_USERDATA,joypad[which][KEY_UP]); up.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_UP])); - SetWindowLong(down, GWL_USERDATA,joypad[which][KEY_DOWN]); + SetWindowLongPtr(down, GWLP_USERDATA,joypad[which][KEY_DOWN]); down.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_DOWN])); - SetWindowLong(left, GWL_USERDATA,joypad[which][KEY_LEFT]); + SetWindowLongPtr(left, GWLP_USERDATA,joypad[which][KEY_LEFT]); left.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_LEFT])); - SetWindowLong(right, GWL_USERDATA,joypad[which][KEY_RIGHT]); + SetWindowLongPtr(right, GWLP_USERDATA,joypad[which][KEY_RIGHT]); right.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_RIGHT])); - SetWindowLong(buttonA, GWL_USERDATA,joypad[which][KEY_BUTTON_A]); + SetWindowLongPtr(buttonA, GWLP_USERDATA,joypad[which][KEY_BUTTON_A]); buttonA.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_A])); - SetWindowLong(buttonB, GWL_USERDATA,joypad[which][KEY_BUTTON_B]); + SetWindowLongPtr(buttonB, GWLP_USERDATA,joypad[which][KEY_BUTTON_B]); buttonB.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_B])); - SetWindowLong(buttonL, GWL_USERDATA,joypad[which][KEY_BUTTON_L]); + SetWindowLongPtr(buttonL, GWLP_USERDATA,joypad[which][KEY_BUTTON_L]); buttonL.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_L])); - SetWindowLong(buttonR, GWL_USERDATA,joypad[which][KEY_BUTTON_R]); + SetWindowLongPtr(buttonR, GWLP_USERDATA,joypad[which][KEY_BUTTON_R]); buttonR.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_R])); - SetWindowLong(buttonSelect, GWL_USERDATA,joypad[which][KEY_BUTTON_SELECT]); + SetWindowLongPtr(buttonSelect, GWLP_USERDATA,joypad[which][KEY_BUTTON_SELECT]); buttonSelect.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_SELECT])); - SetWindowLong(buttonStart, GWL_USERDATA,joypad[which][KEY_BUTTON_START]); + SetWindowLongPtr(buttonStart, GWLP_USERDATA,joypad[which][KEY_BUTTON_START]); buttonStart.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_START])); - SetWindowLong(speed, GWL_USERDATA,joypad[which][KEY_BUTTON_SPEED]); + SetWindowLongPtr(speed, GWLP_USERDATA,joypad[which][KEY_BUTTON_SPEED]); speed.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_SPEED])); - SetWindowLong(capture, GWL_USERDATA,joypad[which][KEY_BUTTON_CAPTURE]); + SetWindowLongPtr(capture, GWLP_USERDATA,joypad[which][KEY_BUTTON_CAPTURE]); capture.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_CAPTURE])); - SetWindowLong(buttonGS, GWL_USERDATA,joypad[which][KEY_BUTTON_GS]); + SetWindowLongPtr(buttonGS, GWLP_USERDATA,joypad[which][KEY_BUTTON_GS]); buttonGS.SetWindowText(theApp.input->getKeyName(joypad[which][KEY_BUTTON_GS])); CenterWindow(); @@ -210,7 +197,7 @@ // EXCEPTION: OCX Property Pages should return FALSE } -void JoypadConfig::assignKey(int id, int key) +void JoypadConfig::assignKey(int id, LONG_PTR key) { switch(id) { case IDC_EDIT_LEFT: @@ -260,43 +247,43 @@ int id; id = IDC_EDIT_UP; - assignKey(id, GetWindowLong(up, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(up, GWLP_USERDATA)); id = IDC_EDIT_DOWN; - assignKey(id, GetWindowLong(down, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(down, GWLP_USERDATA)); id = IDC_EDIT_LEFT; - assignKey(id, GetWindowLong(left, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(left, GWLP_USERDATA)); id = IDC_EDIT_RIGHT; - assignKey(id, GetWindowLong(right, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(right, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_A; - assignKey(id, GetWindowLong(buttonA, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonA, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_B; - assignKey(id, GetWindowLong(buttonB, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonB, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_L; - assignKey(id, GetWindowLong(buttonL, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonL, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_R; - assignKey(id, GetWindowLong(buttonR, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonR, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_SELECT; - assignKey(id, GetWindowLong(buttonSelect, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonSelect, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_START; - assignKey(id, GetWindowLong(buttonStart, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonStart, GWLP_USERDATA)); id = IDC_EDIT_SPEED; - assignKey(id, GetWindowLong(speed, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(speed, GWLP_USERDATA)); id = IDC_EDIT_CAPTURE; - assignKey(id, GetWindowLong(capture, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(capture, GWLP_USERDATA)); id = IDC_EDIT_BUTTON_GS; - assignKey(id, GetWindowLong(buttonGS, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(buttonGS, GWLP_USERDATA)); // winSaveKeys(); } @@ -328,14 +315,11 @@ BEGIN_MESSAGE_MAP(MotionConfig, CDialog) - //{{AFX_MSG_MAP(MotionConfig) ON_BN_CLICKED(ID_CANCEL, OnCancel) ON_BN_CLICKED(ID_OK, OnOk) - ON_WM_CHAR() ON_WM_DESTROY() ON_WM_KEYDOWN() ON_WM_TIMER() - //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// @@ -353,10 +337,6 @@ EndDialog( TRUE); } -void MotionConfig::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) -{ -} - void MotionConfig::OnDestroy() { CDialog::OnDestroy(); @@ -370,16 +350,16 @@ timerId = SetTimer(0,200,NULL); - SetWindowLong(up, GWL_USERDATA,motion[KEY_UP]); + SetWindowLongPtr(up, GWLP_USERDATA,motion[KEY_UP]); up.SetWindowText(theApp.input->getKeyName(motion[KEY_UP])); - SetWindowLong(down, GWL_USERDATA,motion[KEY_DOWN]); + SetWindowLongPtr(down, GWLP_USERDATA,motion[KEY_DOWN]); down.SetWindowText(theApp.input->getKeyName(motion[KEY_DOWN])); - SetWindowLong(left, GWL_USERDATA,motion[KEY_LEFT]); + SetWindowLongPtr(left, GWLP_USERDATA,motion[KEY_LEFT]); left.SetWindowText(theApp.input->getKeyName(motion[KEY_LEFT])); - SetWindowLong(right, GWL_USERDATA,motion[KEY_RIGHT]); + SetWindowLongPtr(right, GWLP_USERDATA,motion[KEY_RIGHT]); right.SetWindowText(theApp.input->getKeyName(motion[KEY_RIGHT])); CenterWindow(); @@ -392,14 +372,14 @@ { } -void MotionConfig::OnTimer(UINT nIDEvent) +void MotionConfig::OnTimer(UINT_PTR nIDEvent) { theApp.input->checkDevices(); CDialog::OnTimer(nIDEvent); } -void MotionConfig::assignKey(int id, int key) +void MotionConfig::assignKey(int id, LONG_PTR key) { switch(id) { case IDC_EDIT_LEFT: @@ -422,14 +402,14 @@ int id; id = IDC_EDIT_UP; - assignKey(id, GetWindowLong(up, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(up, GWLP_USERDATA)); id = IDC_EDIT_DOWN; - assignKey(id, GetWindowLong(down, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(down, GWLP_USERDATA)); id = IDC_EDIT_LEFT; - assignKey(id, GetWindowLong(left, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(left, GWLP_USERDATA)); id = IDC_EDIT_RIGHT; - assignKey(id, GetWindowLong(right, GWL_USERDATA)); + assignKey(id, GetWindowLongPtr(right, GWLP_USERDATA)); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Joypad.h ./src/win32/Joypad.h --- ../VisualBoyAdvance-1.7.2/src/win32/Joypad.h 2004-05-13 22:40:44 +0900 +++ ./src/win32/Joypad.h 2006-06-07 06:04:21 +0900 @@ -41,23 +41,12 @@ // Operations public: - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(JoypadEditControl) - //}}AFX_VIRTUAL - // Implementation public: virtual BOOL PreTranslateMessage(MSG *pMsg); afx_msg LRESULT OnJoyConfig(WPARAM wParam, LPARAM lParam); virtual ~JoypadEditControl(); - // Generated message map functions - protected: - //{{AFX_MSG(JoypadEditControl) - afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() }; @@ -71,7 +60,7 @@ // Construction public: void assignKeys(); - void assignKey(int id, int key); + void assignKey(int id, LONG_PTR key); JoypadConfig(int w, CWnd* pParent = NULL); // standard constructor // Dialog Data @@ -102,16 +91,15 @@ // Implementation protected: - UINT timerId; + UINT_PTR timerId; int which; // Generated message map functions //{{AFX_MSG(JoypadConfig) afx_msg void OnCancel(); afx_msg void OnOk(); - afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnDestroy(); - afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); virtual BOOL OnInitDialog(); //}}AFX_MSG @@ -125,7 +113,7 @@ // Construction public: void assignKeys(); - void assignKey(int id, int key); + void assignKey(int id, LONG_PTR key); MotionConfig(CWnd* pParent = NULL); // standard constructor // Dialog Data @@ -149,18 +137,15 @@ protected: // Generated message map functions - //{{AFX_MSG(MotionConfig) afx_msg void OnCancel(); afx_msg void OnOk(); - afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnDestroy(); virtual BOOL OnInitDialog(); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); - afx_msg void OnTimer(UINT nIDEvent); - //}}AFX_MSG + afx_msg void OnTimer(UINT_PTR nIDEvent); DECLARE_MESSAGE_MAP() private: - UINT timerId; + UINT_PTR timerId; }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Logging.cpp ./src/win32/Logging.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Logging.cpp 2004-05-13 23:23:01 +0900 +++ ./src/win32/Logging.cpp 2006-06-07 06:04:21 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -225,7 +225,7 @@ m_dma2 = (systemVerbose & 64) != 0; m_dma3 = (systemVerbose & 128) != 0; m_undefined = (systemVerbose & 256) != 0; - m_agbprint = (systemVerbose & 256) != 0; + m_agbprint = (systemVerbose & 512) != 0; UpdateData(FALSE); m_log.LimitText(-1); @@ -237,7 +237,7 @@ void Logging::log(const char *s) { - int size = ::SendMessage(m_log, WM_GETTEXTLENGTH, 0, 0); + DWORD size = (DWORD)::SendMessage(m_log, WM_GETTEXTLENGTH, 0, 0); m_log.SetSel(size, size); m_log.ReplaceSel(s); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MainWnd.cpp ./src/win32/MainWnd.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MainWnd.cpp 2004-05-13 23:22:47 +0900 +++ ./src/win32/MainWnd.cpp 2006-08-06 21:40:35 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -24,6 +24,7 @@ #include "MainWnd.h" #include +#include #include "FileDlg.h" #include "Reg.h" @@ -52,6 +53,7 @@ #define VBA_CONFIRM_MODE WM_APP + 100 extern void remoteCleanUp(); +extern int gbHardware; ///////////////////////////////////////////////////////////////////////////// // MainWnd @@ -192,14 +194,14 @@ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE, OnUpdateOptionsEmulatorPausewheninactive) ON_COMMAND(ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE, OnOptionsEmulatorSpeeduptoggle) ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE, OnUpdateOptionsEmulatorSpeeduptoggle) - ON_COMMAND(ID_OPTIONS_EMULATOR_REMOVEINTROSGBA, OnOptionsEmulatorRemoveintrosgba) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_REMOVEINTROSGBA, OnUpdateOptionsEmulatorRemoveintrosgba) ON_COMMAND(ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH, OnOptionsEmulatorAutomaticallyipspatch) ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH, OnUpdateOptionsEmulatorAutomaticallyipspatch) ON_COMMAND(ID_OPTIONS_EMULATOR_AGBPRINT, OnOptionsEmulatorAgbprint) ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AGBPRINT, OnUpdateOptionsEmulatorAgbprint) ON_COMMAND(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnOptionsEmulatorRealtimeclock) ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnUpdateOptionsEmulatorRealtimeclock) + ON_COMMAND(ID_OPTIONS_EMULATOR_GENERICFLASHCARD, OnOptionsEmulatorGenericflashcard) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_GENERICFLASHCARD, OnUpdateOptionsEmulatorGenericflashcard) ON_COMMAND(ID_OPTIONS_EMULATOR_AUTOHIDEMENU, OnOptionsEmulatorAutohidemenu) ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOHIDEMENU, OnUpdateOptionsEmulatorAutohidemenu) ON_COMMAND(ID_OPTIONS_EMULATOR_REWINDINTERVAL, OnOptionsEmulatorRewindinterval) @@ -376,6 +378,9 @@ ON_COMMAND(ID_CHEATS_DISABLECHEATS, OnCheatsDisablecheats) ON_UPDATE_COMMAND_UI(ID_CHEATS_DISABLECHEATS, OnUpdateCheatsDisablecheats) ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREENMAXSCALE, OnOptionsVideoFullscreenmaxscale) + ON_COMMAND(ID_OPTIONS_EMULATOR_GAMEOVERRIDES, OnOptionsEmulatorGameoverrides) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_GAMEOVERRIDES, OnUpdateOptionsEmulatorGameoverrides) + ON_COMMAND(ID_HELP_GNUPUBLICLICENSE, OnHelpGnupubliclicense) //}}AFX_MSG_MAP ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE10, OnFileRecentFile) ON_COMMAND_EX_RANGE(ID_FILE_LOADGAME_SLOT1, ID_FILE_LOADGAME_SLOT10, OnFileLoadSlot) @@ -414,6 +419,8 @@ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_JOYPAD_AUTOFIRE_A, ID_OPTIONS_JOYPAD_AUTOFIRE_R, OnUpdateOptionsJoypadAutofire) ON_MESSAGE(VBA_CONFIRM_MODE, OnConfirmMode) ON_MESSAGE(WM_SYSCOMMAND, OnMySysCommand) + ON_COMMAND(ID_OPTIONS_SOUND_HARDWAREACCELERATION, &MainWnd::OnOptionsSoundHardwareacceleration) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_HARDWAREACCELERATION, &MainWnd::OnUpdateOptionsSoundHardwareacceleration) END_MESSAGE_MAP() @@ -422,6 +429,7 @@ void MainWnd::OnClose() { + emulating = false; CWnd::OnClose(); delete this; @@ -469,13 +477,40 @@ return false; } systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - theApp.cartridgeType = (int)type; + theApp.cartridgeType = type; if(type == IMAGE_GB) { + genericflashcardEnable = theApp.winGenericflashcardEnable; + + if(!gbLoadRom(theApp.szFile)) return false; + + gbGetHardwareType(); + + // used for the handling of the gb Boot Rom + if (gbHardware & 5) + { + char tempName[2048]; + GetModuleFileName(NULL, tempName, 2048); + + char *p = strrchr(tempName, '\\'); + if(p) + *p = 0; + + strcat(tempName, "\\DMG_ROM.bin"); + + skipBios = theApp.skipBiosFile ? true : false; + gbCPUInit(tempName, theApp.useBiosFile ? true : false); + } + + + + gbReset(); theApp.emulator = GBSystem; gbBorderOn = theApp.winGbBorderOn; theApp.romSize = gbRomSize; + + if(theApp.autoIPS) { int size = gbRomSize; utilApplyIPS(ipsname, &gbRom, &size); @@ -492,14 +527,11 @@ return false; theApp.romSize = size; - + flashSetSize(theApp.winFlashSize); rtcEnable(theApp.winRtcEnable); cpuSaveType = theApp.winSaveType; - // if(cpuEnhancedDetection && winSaveType == 0) { - // utilGBAFindSave(rom, size); - // } GetModuleFileName(NULL, tempName, 2048); char *p = strrchr(tempName, '\\'); @@ -532,6 +564,12 @@ tempName); if(i != (UINT)-1 && (i <= 5)) cpuSaveType = (int)i; + i = GetPrivateProfileInt(buffer, + "mirroringEnabled", + -1, + tempName); + if(i != (UINT)-1) + doMirroring (i == 0 ? false : true); theApp.emulator = GBASystem; /* disabled due to problems @@ -565,7 +603,7 @@ CPUInit((char *)(LPCTSTR)theApp.biosFileName, theApp.useBiosFile ? true : false); CPUReset(); } - + readBatteryFile(); if(theApp.autoSaveLoadCheatList) @@ -730,6 +768,16 @@ else name = theApp.filename; CString dir = regQueryStringValue("saveDir", NULL); + if( dir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, dir ); + dir = baseDir; + } if(!dir.GetLength()) dir = getDirFromFile(filename); @@ -762,6 +810,16 @@ else name = theApp.filename; CString dir = regQueryStringValue("saveDir", NULL); + if( dir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, dir ); + dir = baseDir; + } if(!dir.GetLength()) dir = getDirFromFile(filename); @@ -824,6 +882,16 @@ buffer = theApp.filename; CString saveDir = regQueryStringValue("batteryDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -851,6 +919,16 @@ buffer = theApp.filename; CString saveDir = regQueryStringValue("batteryDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -915,7 +993,7 @@ info.cch = 256; if(!GetMenuItemInfo(theApp.menu, i, MF_BYPOSITION, &info)) { } - if(!AppendMenu(theApp.popup, MF_POPUP|MF_STRING, (UINT)info.hSubMenu, buffer)) { + if(!AppendMenu(theApp.popup, MF_POPUP|MF_STRING, (UINT_PTR)info.hSubMenu, buffer)) { } } } else { @@ -929,7 +1007,7 @@ info.cch = 256; if(!GetMenuItemInfoW(theApp.menu, i, MF_BYPOSITION, &info)) { } - if(!AppendMenuW(theApp.popup, MF_POPUP|MF_STRING, (UINT)info.hSubMenu, buffer)) { + if(!AppendMenuW(theApp.popup, MF_POPUP|MF_STRING, (UINT_PTR)info.hSubMenu, buffer)) { } } } @@ -951,37 +1029,71 @@ ShowWindow(SW_SHOWMINIMIZED); } -bool MainWnd::fileOpenSelect() + +bool MainWnd::fileOpenSelect( bool gb ) { - theApp.dir = ""; - CString initialDir = regQueryStringValue("romdir","."); - if(!initialDir.IsEmpty()) - theApp.dir = initialDir; - - int selectedFilter = regQueryDwordValue("selectedFilter", 0); - if(selectedFilter < 0 || selectedFilter > 2) - selectedFilter = 0; - - theApp.szFile = ""; - - LPCTSTR exts[] = { "" }; - CString filter = winLoadFilter(IDS_FILTER_ROM); - CString title = winResLoadString(IDS_SELECT_ROM); - - FileDlg dlg(this, "", filter, selectedFilter, "", exts, theApp.dir, title, false); - - if(dlg.DoModal() == IDOK) { - regSetDwordValue("selectedFilter", dlg.m_ofn.nFilterIndex); - theApp.szFile = dlg.GetPathName(); - theApp.dir = theApp.szFile.Left(dlg.m_ofn.nFileOffset); - if(theApp.dir.GetLength() > 3 && theApp.dir[theApp.dir.GetLength()-1] == '\\') - theApp.dir = theApp.dir.Left(theApp.dir.GetLength()-1); - regSetStringValue("romdir", theApp.dir); - return true; - } - return false; + theApp.dir = _T(""); + CString initialDir; + if( gb ) { + initialDir = regQueryStringValue( _T("gbromdir"), _T(".") ); + } else { + initialDir = regQueryStringValue( _T("romdir"), _T(".") ); + } + + if( initialDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, initialDir ); + initialDir = baseDir; + } + + if( !initialDir.IsEmpty() ) { + theApp.dir = initialDir; + } + + int selectedFilter = 0; + if( !gb ) { + selectedFilter = regQueryDwordValue( _T("selectedFilter"), 0); + if( (selectedFilter < 0) || (selectedFilter > 2) ) { + selectedFilter = 0; + } + } + + theApp.szFile = _T(""); + + LPCTSTR exts[] = { _T(""), _T(""), _T(""), _T("") }; + CString filter; + CString title; + if( gb ) { + filter = winLoadFilter( IDS_FILTER_GBROM ); + title = winResLoadString( IDS_SELECT_ROM ); + } else { + filter = winLoadFilter( IDS_FILTER_ROM ); + title = winResLoadString( IDS_SELECT_ROM ); + } + + FileDlg dlg( this, _T(""), filter, selectedFilter, _T(""), exts, theApp.dir, title, false); + + if( dlg.DoModal() == IDOK ) { + if( !gb ) { + regSetDwordValue( _T("selectedFilter"), dlg.m_ofn.nFilterIndex ); + } + theApp.szFile = dlg.GetPathName(); + theApp.dir = theApp.szFile.Left( dlg.m_ofn.nFileOffset ); + if( (theApp.dir.GetLength() > 3) && (theApp.dir[theApp.dir.GetLength()-1] == _T('\\')) ) { + theApp.dir = theApp.dir.Left( theApp.dir.GetLength() - 1 ); + } + SetCurrentDirectory( theApp.dir ); + return true; + } + return false; } + void MainWnd::OnPaint() { CPaintDC dc(this); // device context for painting @@ -1011,6 +1123,16 @@ CString buffer; CString captureDir = regQueryStringValue("captureDir", ""); + if( captureDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, captureDir ); + captureDir = baseDir; + } int index = theApp.filename.ReverseFind('\\'); CString name; @@ -1039,6 +1161,15 @@ captureNumber, ext); + // check if file exists + DWORD dwAttr = GetFileAttributes( buffer ); + if( dwAttr != INVALID_FILE_ATTRIBUTES ) { + // screenshot file already exists + screenCapture(++captureNumber); + // this will recursively use the first non-existent screenshot number + return; + } + if(theApp.captureFormat == 0) theApp.emulator.emuWritePNG(buffer); else @@ -1098,7 +1229,12 @@ } if(theApp.paused && emulating) + { + theApp.painting = true; systemDrawScreen(); + theApp.painting = false; + theApp.renderedFrames--; + } } #if _MSC_VER <= 1200 @@ -1145,3 +1281,4 @@ } return Default(); } + diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MainWnd.h ./src/win32/MainWnd.h --- ../VisualBoyAdvance-1.7.2/src/win32/MainWnd.h 2004-05-13 22:39:34 +0900 +++ ./src/win32/MainWnd.h 2006-08-06 21:40:35 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -55,7 +55,7 @@ void winMouseOn(); void screenCapture(int captureNumber); HACCEL m_hAccelTable; - bool fileOpenSelect(); + bool fileOpenSelect( bool gb = false ); afx_msg LRESULT OnConfirmMode(WPARAM, LPARAM); afx_msg LRESULT OnMySysCommand(WPARAM, LPARAM); afx_msg void OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI); @@ -221,14 +221,14 @@ afx_msg void OnUpdateOptionsEmulatorPausewheninactive(CCmdUI* pCmdUI); afx_msg void OnOptionsEmulatorSpeeduptoggle(); afx_msg void OnUpdateOptionsEmulatorSpeeduptoggle(CCmdUI* pCmdUI); - afx_msg void OnOptionsEmulatorRemoveintrosgba(); - afx_msg void OnUpdateOptionsEmulatorRemoveintrosgba(CCmdUI* pCmdUI); afx_msg void OnOptionsEmulatorAutomaticallyipspatch(); afx_msg void OnUpdateOptionsEmulatorAutomaticallyipspatch(CCmdUI* pCmdUI); afx_msg void OnOptionsEmulatorAgbprint(); afx_msg void OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI); afx_msg void OnOptionsEmulatorRealtimeclock(); afx_msg void OnUpdateOptionsEmulatorRealtimeclock(CCmdUI* pCmdUI); + afx_msg void OnOptionsEmulatorGenericflashcard(); + afx_msg void OnUpdateOptionsEmulatorGenericflashcard(CCmdUI* pCmdUI); afx_msg void OnOptionsEmulatorAutohidemenu(); afx_msg void OnUpdateOptionsEmulatorAutohidemenu(CCmdUI* pCmdUI); afx_msg void OnOptionsEmulatorRewindinterval(); @@ -408,13 +408,20 @@ afx_msg void OnUpdateOptionsSoundVolume5x(CCmdUI* pCmdUI); afx_msg void OnCheatsDisablecheats(); afx_msg void OnUpdateCheatsDisablecheats(CCmdUI* pCmdUI); - afx_msg void OnOptionsVideoFullscreenmaxscale(); + afx_msg void OnOptionsVideoFullscreenmaxscale(); + afx_msg void OnOptionsEmulatorGameoverrides(); + afx_msg void OnUpdateOptionsEmulatorGameoverrides(CCmdUI* pCmdUI); + afx_msg void OnHelpGnupubliclicense(); //}}AFX_MSG DECLARE_MESSAGE_MAP() - + afx_msg BOOL OnFileRecentFile(UINT nID); afx_msg BOOL OnFileLoadSlot(UINT nID); afx_msg BOOL OnFileSaveSlot(UINT nID); +public: + afx_msg void OnOptionsSoundHardwareacceleration(); +public: + afx_msg void OnUpdateOptionsSoundHardwareacceleration(CCmdUI *pCmdUI); }; ///////////////////////////////////////////////////////////////////////////// diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MainWndFile.cpp ./src/win32/MainWndFile.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MainWndFile.cpp 2004-05-13 23:22:25 +0900 +++ ./src/win32/MainWndFile.cpp 2006-08-06 02:29:02 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -19,6 +19,8 @@ #include "stdafx.h" #include "MainWnd.h" +#include + #include "ExportGSASnapshot.h" #include "FileDlg.h" #include "GSACodeSelect.h" @@ -37,15 +39,18 @@ extern int emulating; extern void remoteCleanUp(); +extern void InterframeCleanup(); + void MainWnd::OnFileOpen() { - theApp.winCheckFullscreen(); - if(fileOpenSelect()) { - FileRun(); - } + theApp.winCheckFullscreen(); + if( fileOpenSelect( false ) ) { + FileRun(); + } } + void MainWnd::OnFilePause() { theApp.paused = !theApp.paused; @@ -158,32 +163,16 @@ pCmdUI->Enable(emulating); } + void MainWnd::OnFileOpengameboy() { - theApp.winCheckFullscreen(); - theApp.dir = ""; - CString initialDir = regQueryStringValue("gbromdir","."); - if(!initialDir.IsEmpty()) - theApp.dir = initialDir; - - theApp.szFile = ""; - - LPCTSTR exts[] = { "" }; - CString filter = winLoadFilter(IDS_FILTER_GBROM); - CString title = winResLoadString(IDS_SELECT_ROM); - - FileDlg dlg(this, "", filter, 0, "", exts, initialDir, title, false); - - if(dlg.DoModal() == IDOK) { - theApp.szFile = dlg.GetPathName(); - theApp.dir = theApp.szFile.Left(dlg.m_ofn.nFileOffset); - if(theApp.dir.GetLength() > 3 && theApp.dir[theApp.dir.GetLength()-1] == '\\') - theApp.dir = theApp.dir.Left(theApp.dir.GetLength()-1); - regSetStringValue("gbromdir", theApp.dir); - FileRun(); - } + theApp.winCheckFullscreen(); + if( fileOpenSelect( true ) ) { + FileRun(); + } } + void MainWnd::OnFileLoad() { theApp.winCheckFullscreen(); @@ -198,6 +187,16 @@ buffer = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -245,6 +244,16 @@ buffer = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -254,17 +263,22 @@ else filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID); - bool res = loadSaveGame(filename); - - theApp.rewindCount = 0; - theApp.rewindCounter = 0; - theApp.rewindSaveNeeded = false; - CString format = winResLoadString(IDS_LOADED_STATE_N); buffer.Format(format, nID); - + + bool res = loadSaveGame(filename); + + if (theApp.paused) + InterframeCleanup(); + systemScreenMessage(buffer); - + + systemDrawScreen(); + + //theApp.rewindCount = 0; + //theApp.rewindCounter = 0; + //theApp.rewindSaveNeeded = false; + return res; } @@ -282,6 +296,16 @@ buffer = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -324,6 +348,16 @@ buffer = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -339,6 +373,8 @@ buffer.Format(format, nID); systemScreenMessage(buffer); + + systemDrawScreen(); return res; } @@ -351,6 +387,16 @@ CString title = winResLoadString(IDS_SELECT_BATTERY_FILE); CString saveDir = regQueryStringValue("batteryDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -375,7 +421,8 @@ if(!res) systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", dlg.GetPathName()); else { - theApp.emulator.emuReset(); + //Removed the reset to allow loading a battery file 'within' a save state. + //theApp.emulator.emuReset(); } } @@ -421,7 +468,7 @@ void MainWnd::OnFileImportGamesharksnapshot() { theApp.winCheckFullscreen(); - LPCTSTR exts[] = { "" }; + LPCTSTR exts[] = { ".gbs" }; CString filter = theApp.cartridgeType == 1 ? winLoadFilter(IDS_FILTER_GBS) : winLoadFilter(IDS_FILTER_SPS); CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE); @@ -467,6 +514,16 @@ CString title = winResLoadString(IDS_SELECT_BATTERY_FILE); CString saveDir = regQueryStringValue("batteryDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -564,8 +621,18 @@ name = theApp.filename; CString capdir = regQueryStringValue("captureDir", ""); + if( capdir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, capdir ); + capdir = baseDir; + } if(capdir.IsEmpty()) - capdir = getDirFromFile(name); + capdir = getDirFromFile(theApp.filename); CString ext = "png"; @@ -645,6 +712,8 @@ } theApp.adjustDestRect(); + if(theApp.display) + theApp.display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top); } void MainWnd::OnUpdateFileTogglemenu(CCmdUI* pCmdUI) @@ -680,7 +749,7 @@ } fseek(f, 0x1e, SEEK_SET); fread(&len, 1, 4, f); - int game = 0; + INT_PTR game = 0; if(len > 1) { GSACodeSelect dlg(f); game = dlg.DoModal(); @@ -697,7 +766,7 @@ } if(game != -1) { - return cheatsImportGSACodeFile(fileName, game, v3); + return cheatsImportGSACodeFile(fileName, (int)game, v3); } return true; @@ -718,6 +787,16 @@ filename = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -728,7 +807,7 @@ CString name; CFileStatus status; CString str; - time_t time = -1; + time_t time = (time_t)-1; int found = 0; for(int i = 0; i < 10; i++) { @@ -762,6 +841,16 @@ filename = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -804,6 +893,16 @@ filename = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); @@ -821,7 +920,7 @@ name.Format("%s%s%d.sgm", saveDir, filename, i+1); if(emulating && CFile::GetStatus(name, status)) { - if(status.m_mtime.GetTime() > time) { +if(status.m_mtime.GetTime() < time) { time = status.m_mtime.GetTime(); found = i; } @@ -848,6 +947,16 @@ filename = theApp.filename; CString saveDir = regQueryStringValue("saveDir", NULL); + if( saveDir[0] == '.' ) { + // handle as relative path + char baseDir[MAX_PATH+1]; + GetModuleFileName( NULL, baseDir, MAX_PATH ); + baseDir[MAX_PATH] = '\0'; // for security reasons + PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash + strcat( baseDir, "\\" ); + strcat( baseDir, saveDir ); + saveDir = baseDir; + } if(saveDir.IsEmpty()) saveDir = getDirFromFile(theApp.filename); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MainWndHelp.cpp ./src/win32/MainWndHelp.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MainWndHelp.cpp 2004-05-13 23:22:12 +0900 +++ ./src/win32/MainWndHelp.cpp 2004-12-19 08:11:08 +0900 @@ -44,3 +44,9 @@ dlg.DoModal(); } + +void MainWnd::OnHelpGnupubliclicense() +{ + ::ShellExecute(0, _T("open"), "http://www.gnu.org/licenses/gpl.html", + 0, 0, SW_SHOWNORMAL); +} diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MainWndOptions.cpp ./src/win32/MainWndOptions.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MainWndOptions.cpp 2004-05-13 23:22:01 +0900 +++ ./src/win32/MainWndOptions.cpp 2006-08-11 19:58:39 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -22,6 +22,7 @@ #include "Associate.h" #include "Directories.h" #include "FileDlg.h" +#include "GameOverrides.h" #include "GBColorDlg.h" #include "Joypad.h" #include "MaxScale.h" @@ -41,6 +42,8 @@ #include "../gb/gbGlobals.h" #include "../gb/gbPrinter.h" +#include + extern int emulating; #define VBA_CONFIRM_MODE WM_APP + 100 @@ -50,6 +53,7 @@ void MainWnd::OnOptionsFrameskipThrottleNothrottle() { theApp.throttle = 0; + theApp.autoFrameSkip = false; } void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI) @@ -60,6 +64,7 @@ void MainWnd::OnOptionsFrameskipThrottle25() { theApp.throttle = 25; + theApp.autoFrameSkip = false; } void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI) @@ -70,6 +75,7 @@ void MainWnd::OnOptionsFrameskipThrottle50() { theApp.throttle = 50; + theApp.autoFrameSkip = false; } void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI) @@ -80,6 +86,7 @@ void MainWnd::OnOptionsFrameskipThrottle100() { theApp.throttle = 100; + theApp.autoFrameSkip = false; } void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI) @@ -90,6 +97,7 @@ void MainWnd::OnOptionsFrameskipThrottle150() { theApp.throttle = 150; + theApp.autoFrameSkip = false; } void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI) @@ -100,6 +108,7 @@ void MainWnd::OnOptionsFrameskipThrottle200() { theApp.throttle = 200; + theApp.autoFrameSkip = false; } void MainWnd::OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI) @@ -107,14 +116,19 @@ pCmdUI->SetCheck(theApp.throttle == 200); } + void MainWnd::OnOptionsFrameskipThrottleOther() { - Throttle dlg; - int v = dlg.DoModal(); - if(v) - theApp.throttle = v; + Throttle dlg; + int v = (int)dlg.DoModal(); + + if( v ) { + theApp.throttle = v; + theApp.autoFrameSkip = false; + } } + void MainWnd::OnUpdateOptionsFrameskipThrottleOther(CCmdUI* pCmdUI) { int throttle = theApp.throttle; @@ -127,7 +141,13 @@ { theApp.autoFrameSkip = !theApp.autoFrameSkip; if(!theApp.autoFrameSkip && emulating) - theApp.updateFrameSkip(); + theApp.updateFrameSkip(); + else + { + theApp.throttle = false; + frameSkip = 0; + systemFrameSkip = 0; + } } void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI) @@ -144,26 +164,28 @@ case ID_OPTIONS_VIDEO_FRAMESKIP_3: case ID_OPTIONS_VIDEO_FRAMESKIP_4: case ID_OPTIONS_VIDEO_FRAMESKIP_5: - if(theApp.cartridgeType == 0) { + if(theApp.cartridgeType == IMAGE_GBA) { frameSkip = nID - ID_OPTIONS_VIDEO_FRAMESKIP_0; } else { gbFrameSkip = nID - ID_OPTIONS_VIDEO_FRAMESKIP_0; } if(emulating) theApp.updateFrameSkip(); + theApp.autoFrameSkip = false; return TRUE; break; case ID_OPTIONS_VIDEO_FRAMESKIP_6: case ID_OPTIONS_VIDEO_FRAMESKIP_7: case ID_OPTIONS_VIDEO_FRAMESKIP_8: case ID_OPTIONS_VIDEO_FRAMESKIP_9: - if(theApp.cartridgeType == 0) { + if(theApp.cartridgeType == IMAGE_GBA) { frameSkip = 6 + nID - ID_OPTIONS_VIDEO_FRAMESKIP_6; } else { gbFrameSkip = 6 + nID - ID_OPTIONS_VIDEO_FRAMESKIP_6; } if(emulating) theApp.updateFrameSkip(); + theApp.autoFrameSkip = false; return TRUE; break; } @@ -172,59 +194,64 @@ void MainWnd::OnUpdateOptionsVideoFrameskip0(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 0 : gbFrameSkip == 0); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 0 : gbFrameSkip == 0); } void MainWnd::OnUpdateOptionsVideoFrameskip1(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 1 : gbFrameSkip == 1); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 1 : gbFrameSkip == 1); } void MainWnd::OnUpdateOptionsVideoFrameskip2(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 2 : gbFrameSkip == 2); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 2 : gbFrameSkip == 2); } void MainWnd::OnUpdateOptionsVideoFrameskip3(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 3 : gbFrameSkip == 3); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 3 : gbFrameSkip == 3); } void MainWnd::OnUpdateOptionsVideoFrameskip4(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 4 : gbFrameSkip == 4); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 4 : gbFrameSkip == 4); } void MainWnd::OnUpdateOptionsVideoFrameskip5(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 5 : gbFrameSkip == 5); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 5 : gbFrameSkip == 5); } void MainWnd::OnUpdateOptionsVideoFrameskip6(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 6 : gbFrameSkip == 6); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 6 : gbFrameSkip == 6); } void MainWnd::OnUpdateOptionsVideoFrameskip7(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 7 : gbFrameSkip == 7); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 7 : gbFrameSkip == 7); } void MainWnd::OnUpdateOptionsVideoFrameskip8(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 8 : gbFrameSkip == 8); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 8 : gbFrameSkip == 8); } void MainWnd::OnUpdateOptionsVideoFrameskip9(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 9 : gbFrameSkip == 9); + pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 9 : gbFrameSkip == 9); } + void MainWnd::OnOptionsVideoVsync() { - theApp.vsync = !theApp.vsync; + theApp.vsync = !theApp.vsync; + if( theApp.display ) { + theApp.display->setOption( _T("vsync"), theApp.vsync ); + } } + void MainWnd::OnUpdateOptionsVideoVsync(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.vsync); @@ -268,13 +295,15 @@ pCmdUI->SetCheck(theApp.videoOption == VIDEO_800x600); } + BOOL MainWnd::OnOptionVideoSize(UINT nID) { - theApp.updateVideoSize(nID); - theApp.m_pMainWnd->PostMessage(VBA_CONFIRM_MODE); - return TRUE; + theApp.updateVideoSize(nID); + theApp.m_pMainWnd->PostMessage(VBA_CONFIRM_MODE); + return TRUE; } + void MainWnd::OnOptionsVideoFullscreen320x240() { OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN320X240); @@ -290,6 +319,7 @@ OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN800X600); } + void MainWnd::OnOptionsVideoFullscreen() { theApp.winCheckFullscreen(); @@ -324,6 +354,7 @@ theApp.winAccelMgr.UpdateMenu(theApp.menu); } + void MainWnd::OnUpdateOptionsVideoFullscreen(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.videoOption == VIDEO_OTHER); @@ -332,7 +363,7 @@ void MainWnd::OnOptionsVideoDisablesfx() { cpuDisableSfx = !cpuDisableSfx; - if(emulating && theApp.cartridgeType == 0) + if(emulating && theApp.cartridgeType == IMAGE_GBA) CPUUpdateRender(); } @@ -341,14 +372,20 @@ pCmdUI->SetCheck(cpuDisableSfx); } + void MainWnd::OnOptionsVideoFullscreenstretchtofit() { - theApp.fullScreenStretch = !theApp.fullScreenStretch; - theApp.updateWindowSize(theApp.videoOption); - if(theApp.display) - theApp.display->clear(); + theApp.fullScreenStretch = !theApp.fullScreenStretch; + theApp.updateWindowSize( theApp.videoOption ); + if( theApp.display ) { + if( emulating ) { + theApp.display->clear( ); + } + theApp.display->setOption( _T("fullScreenStretch"), theApp.fullScreenStretch ); + } } + void MainWnd::OnUpdateOptionsVideoFullscreenstretchtofit(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.fullScreenStretch); @@ -425,31 +462,45 @@ pCmdUI->SetCheck(theApp.renderMethod == OPENGL); } + void MainWnd::OnOptionsVideoTriplebuffering() { - theApp.tripleBuffering = !theApp.tripleBuffering; + theApp.tripleBuffering = !theApp.tripleBuffering; + if( theApp.display ) { + theApp.display->setOption( _T("tripleBuffering"), theApp.tripleBuffering ); + } } + void MainWnd::OnUpdateOptionsVideoTriplebuffering(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.tripleBuffering); + pCmdUI->SetCheck(theApp.tripleBuffering); } void MainWnd::OnOptionsVideoDdrawemulationonly() { - theApp.ddrawEmulationOnly = !theApp.ddrawEmulationOnly; + theApp.ddrawEmulationOnly = !theApp.ddrawEmulationOnly; + if( theApp.display ) { + theApp.display->setOption( _T("ddrawEmulationOnly"), theApp.ddrawEmulationOnly ); + } } + void MainWnd::OnUpdateOptionsVideoDdrawemulationonly(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.ddrawEmulationOnly); } + void MainWnd::OnOptionsVideoDdrawusevideomemory() { - theApp.ddrawUseVideoMemory = !theApp.ddrawUseVideoMemory; + theApp.ddrawUseVideoMemory = !theApp.ddrawUseVideoMemory; + if( theApp.display ) { + theApp.display->setOption( _T("ddrawUseVideoMemory"), theApp.ddrawUseVideoMemory ); + } } + void MainWnd::OnUpdateOptionsVideoDdrawusevideomemory(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.ddrawUseVideoMemory); @@ -457,9 +508,10 @@ void MainWnd::OnOptionsVideoRenderoptionsD3dnofilter() { - theApp.d3dFilter = 0; - if(theApp.display) - theApp.display->setOption("d3dFilter", 0); + theApp.d3dFilter = 0; + if( theApp.display ) { + theApp.display->setOption( _T("d3dFilter"), theApp.d3dFilter ); + } } void MainWnd::OnUpdateOptionsVideoRenderoptionsD3dnofilter(CCmdUI* pCmdUI) @@ -467,61 +519,76 @@ pCmdUI->SetCheck(theApp.d3dFilter == 0); } + void MainWnd::OnOptionsVideoRenderoptionsD3dbilinear() { - theApp.d3dFilter = 1; - if(theApp.display) - theApp.display->setOption("d3dFilter", 1); + theApp.d3dFilter = 1; + if( theApp.display ) { + theApp.display->setOption( _T("d3dFilter"), theApp.d3dFilter ); + } } + void MainWnd::OnUpdateOptionsVideoRenderoptionsD3dbilinear(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.d3dFilter == 1); } + void MainWnd::OnOptionsVideoRenderoptionsGlnearest() { - theApp.glFilter = 0; - if(theApp.display) - theApp.display->setOption("glFilter", 0); + theApp.glFilter = 0; + if( theApp.display ) { + theApp.display->setOption( _T("glFilter"), theApp.glFilter ); + } } + void MainWnd::OnUpdateOptionsVideoRenderoptionsGlnearest(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.glFilter == 0); } + void MainWnd::OnOptionsVideoRenderoptionsGlbilinear() { - theApp.glFilter = 1; - if(theApp.display) - theApp.display->setOption("glFilter", 1); + theApp.glFilter = 1; + if( theApp.display ) { + theApp.display->setOption( _T("glFilter"), theApp.glFilter ); + } } + void MainWnd::OnUpdateOptionsVideoRenderoptionsGlbilinear(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.glFilter == 1); } + void MainWnd::OnOptionsVideoRenderoptionsGltriangle() { - theApp.glType = 0; - if(theApp.display) - theApp.display->setOption("glType", 0); + theApp.glType = 0; + if( theApp.display ) { + theApp.display->setOption( _T("glType"), theApp.glType ); + } } + void MainWnd::OnUpdateOptionsVideoRenderoptionsGltriangle(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.glType == 0); } + void MainWnd::OnOptionsVideoRenderoptionsGlquads() { - theApp.glType = 1; - if(theApp.display) - theApp.display->setOption("glType", 1); + theApp.glType = 1; + if( theApp.display ) { + theApp.display->setOption( _T("glType"), theApp.glType ); + } } + void MainWnd::OnUpdateOptionsVideoRenderoptionsGlquads(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.glType == 1); @@ -529,6 +596,7 @@ void MainWnd::OnOptionsVideoRenderoptionsSelectskin() { +#ifndef NOSKINS LPCTSTR exts[] = {".ini" }; CString filter = winLoadFilter(IDS_FILTER_INI); CString title = winResLoadString(IDS_SELECT_SKIN_FILE); @@ -562,6 +630,9 @@ theApp.winUpdateSkin(); theApp.winAccelMgr.UpdateMenu(theApp.menu); +#else + systemMessage( 0, _T("This build of VBA does not support skins!") ); +#endif } void MainWnd::OnUpdateOptionsVideoRenderoptionsSelectskin(CCmdUI* pCmdUI) @@ -572,9 +643,13 @@ void MainWnd::OnOptionsVideoRenderoptionsSkin() { +#ifndef NOSKINS theApp.skinEnabled = !theApp.skinEnabled; theApp.updateRenderMethod(true); theApp.winAccelMgr.UpdateMenu(theApp.menu); +#else + systemMessage( 0, _T("This build of VBA does not support skins!") ); +#endif } void MainWnd::OnUpdateOptionsVideoRenderoptionsSkin(CCmdUI* pCmdUI) @@ -610,6 +685,8 @@ void MainWnd::OnOptionsEmulatorSynchronize() { synchronize = !synchronize; + if (synchronize) + theApp.throttle = false; } void MainWnd::OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI) @@ -637,17 +714,6 @@ pCmdUI->SetCheck(theApp.speedupToggle); } -void MainWnd::OnOptionsEmulatorRemoveintrosgba() -{ - // theApp.removeIntros = !theApp.removeIntros; -} - -void MainWnd::OnUpdateOptionsEmulatorRemoveintrosgba(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(false); - // pCmdUI->SetCheck(theApp.removeIntros); -} - void MainWnd::OnOptionsEmulatorAutomaticallyipspatch() { theApp.autoIPS = !theApp.autoIPS; @@ -683,33 +749,53 @@ theApp.autoHideMenu = !theApp.autoHideMenu; } +void MainWnd::OnOptionsEmulatorGenericflashcard() +{ + if(emulating && theApp.cartridgeType == IMAGE_GB) + theApp.winGenericflashcardEnable = !theApp.winGenericflashcardEnable; +} + +void MainWnd::OnUpdateOptionsEmulatorGenericflashcard(CCmdUI* pCmdUI) +{ + if(emulating && theApp.cartridgeType == IMAGE_GB) + pCmdUI->SetCheck(theApp.winGenericflashcardEnable); + else + pCmdUI->SetCheck(false); + + pCmdUI->Enable(emulating && theApp.cartridgeType == IMAGE_GB); +} + void MainWnd::OnUpdateOptionsEmulatorAutohidemenu(CCmdUI* pCmdUI) { pCmdUI->SetCheck(theApp.autoHideMenu); } + void MainWnd::OnOptionsEmulatorRewindinterval() { - RewindInterval dlg(theApp.rewindTimer/6); - int v = dlg.DoModal(); - - if(v >= 0) { - theApp.rewindTimer = v*6; // convert to a multiple of 10 frames - regSetDwordValue("rewindTimer", v); - if(v == 0) { - if(theApp.rewindMemory) - free(theApp.rewindMemory); - theApp.rewindMemory = NULL; - theApp.rewindCount = 0; - theApp.rewindCounter = 0; - theApp.rewindSaveNeeded = false; - } else { - if(theApp.rewindMemory == NULL) - theApp.rewindMemory = (char *)malloc(8*REWIND_SIZE); - } - } + RewindInterval dlg(theApp.rewindTimer/6); + int v = (int)dlg.DoModal(); + + if( v >= 0 ) { + theApp.rewindTimer = v*6; // convert to a multiple of 10 frames + regSetDwordValue("rewindTimer", v); + if(v == 0) { + if(theApp.rewindMemory) { + free(theApp.rewindMemory); + theApp.rewindMemory = NULL; + } + theApp.rewindCount = 0; + theApp.rewindCounter = 0; + theApp.rewindSaveNeeded = false; + } else { + if(theApp.rewindMemory == NULL) { + theApp.rewindMemory = (char *)malloc(8*REWIND_SIZE); + } + } + } } + BOOL MainWnd::OnOptionsEmulatorShowSpeed(UINT nID) { switch(nID) { @@ -818,7 +904,9 @@ void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash512k(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.winFlashSize == 0x10000); + // changed theApp.winFlashSize to flashSize to reflect the actual + // flashsize value used by the emu (it can change upon battery loading) + pCmdUI->SetCheck(flashSize == 0x10000); } void MainWnd::OnOptionsEmulatorSavetypeFlash1m() @@ -829,7 +917,9 @@ void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash1m(CCmdUI* pCmdUI) { - pCmdUI->SetCheck(theApp.winFlashSize == 0x20000); + // changed theApp.winFlashSize to flashSize to reflect the actual + // flashsize value used by the emu (it can change upon battery loading) + pCmdUI->SetCheck(flashSize == 0x20000); } void MainWnd::OnOptionsEmulatorUsebiosfile() @@ -900,6 +990,7 @@ { soundOffFlag = true; soundShutdown(); + theApp.soundInitialized = false; } void MainWnd::OnUpdateOptionsSoundOff(CCmdUI* pCmdUI) @@ -1456,11 +1547,13 @@ void MainWnd::OnOptionsFilterDisablemmx() { +#ifdef MMX theApp.disableMMX = !theApp.disableMMX; if(!theApp.disableMMX) cpu_mmx = theApp.detectMMX(); else cpu_mmx = 0; +#endif } void MainWnd::OnUpdateOptionsFilterDisablemmx(CCmdUI* pCmdUI) @@ -1650,15 +1743,15 @@ void MainWnd::winConfirmMode() { - if(theApp.renderMethod == DIRECT_DRAW && theApp.videoOption > VIDEO_4X) { - theApp.winCheckFullscreen(); - ModeConfirm dlg(theApp.m_pMainWnd); - - if(!dlg.DoModal()) { - theApp.updateVideoSize(ID_OPTIONS_VIDEO_X2); - } - } - theApp.winAccelMgr.UpdateMenu(theApp.menu); + if( theApp.videoOption > VIDEO_4X ) { + theApp.winCheckFullscreen(); + ModeConfirm dlg(theApp.m_pMainWnd); + + if(!dlg.DoModal()) { + theApp.updateVideoSize(ID_OPTIONS_VIDEO_X2); + } + } + theApp.winAccelMgr.UpdateMenu(theApp.menu); } void MainWnd::OnOptionsVideoFullscreenmaxscale() @@ -1668,4 +1761,34 @@ theApp.winCheckFullscreen(); dlg.DoModal(); + + if( theApp.display ) { + theApp.display->setOption( _T("maxScale"), theApp.fsMaxScale ); + } +} + + +void MainWnd::OnOptionsEmulatorGameoverrides() +{ + if(emulating && theApp.cartridgeType == 0) { + GameOverrides dlg(this); + dlg.DoModal(); + } +} + +void MainWnd::OnUpdateOptionsEmulatorGameoverrides(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(emulating && (theApp.cartridgeType == 0)); +} + +void MainWnd::OnOptionsSoundHardwareacceleration() +{ + theApp.dsoundDisableHardwareAcceleration = !theApp.dsoundDisableHardwareAcceleration; + systemSoundShutdown(); + systemSoundInit(); +} + +void MainWnd::OnUpdateOptionsSoundHardwareacceleration(CCmdUI *pCmdUI) +{ + pCmdUI->SetCheck(!theApp.dsoundDisableHardwareAcceleration); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MainWndTools.cpp ./src/win32/MainWndTools.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MainWndTools.cpp 2004-05-13 23:21:49 +0900 +++ ./src/win32/MainWndTools.cpp 2006-08-25 22:09:04 +0900 @@ -51,7 +51,7 @@ extern bool debugger; extern int emulating; -extern int remoteSocket; +extern SOCKET remoteSocket; extern void remoteCleanUp(); extern void remoteSetSockets(SOCKET, SOCKET); @@ -205,7 +205,7 @@ remoteSetSockets(wait.getListenSocket(), wait.getSocket()); debugger = true; emulating = 1; - theApp.cartridgeType = 0; + theApp.cartridgeType = IMAGE_GBA; theApp.filename = "\\gnu_stub"; rom = (u8 *)malloc(0x2000000); workRAM = (u8 *)calloc(1, 0x40000); @@ -214,7 +214,7 @@ paletteRAM = (u8 *)calloc(1,0x400); vram = (u8 *)calloc(1, 0x20000); oam = (u8 *)calloc(1, 0x400); - pix = (u8 *)calloc(1, 4 * 240 * 160); + pix = (u8 *)calloc(1, 4 * 241 * 162); ioMem = (u8 *)calloc(1, 0x400); theApp.emulator = GBASystem; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MapView.cpp ./src/win32/MapView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MapView.cpp 2004-05-13 23:21:38 +0900 +++ ./src/win32/MapView.cpp 2006-06-07 06:04:21 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -465,6 +465,7 @@ bg = 2; } + void MapView::OnRefresh() { paint(); @@ -511,6 +512,12 @@ case 5: renderMode5(); break; + case 6: + renderMode5(); + break; + case 7: + renderMode5(); + break; } enableButtons(mode); SIZE s; @@ -759,7 +766,7 @@ u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000; // all text bgs (16 bits) - if(mode == 0 ||(mode < 3 && bg < 2)) { + if(mode == 0 ||(mode < 3 && bg < 2) || mode == 6 || mode == 7) { return GetTextClickAddress(base, x, y); } // rot bgs (8 bits) @@ -779,8 +786,8 @@ u8 *colors = (u8 *)lParam; mapViewZoom.setColors(colors); - int x = wParam & 0xffff; - int y = (wParam >> 16); + int x = (int)(wParam & 0xffff); + int y = (int)(wParam >> 16); CString buffer; buffer.Format("(%d,%d)", x, y); @@ -791,7 +798,7 @@ GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer); int mode = DISPCNT & 7; - if(mode >= 3) { + if(mode >= 3 && mode <=5) { // bitmap modes GetDlgItem(IDC_TILE_NUM)->SetWindowText("---"); GetDlgItem(IDC_FLIP)->SetWindowText("--"); @@ -991,36 +998,39 @@ fclose(fp); } -void MapView::OnSave() +void MapView::OnSave() { - CString filename; + if(rom != NULL) + { + CString filename; + + if(theApp.captureFormat == 0) + filename = "map.png"; + else + filename = "map.bmp"; + + LPCTSTR exts[] = {".png", ".bmp" }; + + CString filter = theApp.winLoadFilter(IDS_FILTER_PNG); + CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); + + FileDlg dlg(this, + filename, + filter, + theApp.captureFormat ? 2 : 1, + theApp.captureFormat ? "BMP" : "PNG", + exts, + "", + title, + true); - if(theApp.captureFormat == 0) - filename = "map.png"; - else - filename = "map.bmp"; - - LPCTSTR exts[] = {".png", ".bmp" }; - - CString filter = theApp.winLoadFilter(IDS_FILTER_PNG); - CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); - - FileDlg dlg(this, - filename, - filter, - theApp.captureFormat ? 2 : 1, - theApp.captureFormat ? "BMP" : "PNG", - exts, - "", - title, - true); + if(dlg.DoModal() == IDCANCEL) { + return; + } - if(dlg.DoModal() == IDCANCEL) { - return; + if(dlg.getFilterIndex() == 2) + saveBMP(dlg.GetPathName()); + else + savePNG(dlg.GetPathName()); } - - if(dlg.getFilterIndex() == 2) - saveBMP(dlg.GetPathName()); - else - savePNG(dlg.GetPathName()); } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MapView.h ./src/win32/MapView.h --- ../VisualBoyAdvance-1.7.2/src/win32/MapView.h 2004-05-13 22:38:49 +0900 +++ ./src/win32/MapView.h 2006-05-27 23:47:33 +0900 @@ -31,7 +31,7 @@ #include "ZoomControl.h" #include "ResizeDlg.h" #include "IUpdate.h" -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView ///////////////////////////////////////////////////////////////////////////// // MapView dialog diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewer.cpp ./src/win32/MemoryViewer.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewer.cpp 2004-05-13 23:21:13 +0900 +++ ./src/win32/MemoryViewer.cpp 2006-05-27 23:47:33 +0900 @@ -535,8 +535,8 @@ } LRESULT MemoryViewer::OnWMChar(WPARAM wParam, LPARAM LPARAM) -{ - if(OnEditInput(wParam)) +{ // The WM_CHAR message uses Unicode Transformation Format (UTF)-16. + if(OnEditInput((UINT)(wParam & 0xFFFF))) return 0; return 1; } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewer.h ./src/win32/MemoryViewer.h --- ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewer.h 2004-05-13 22:38:21 +0900 +++ ./src/win32/MemoryViewer.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_MEMORYVIEWER_H__52C50474_5399_4D0B_A3E4_4C52C4E0EAA0__INCLUDED_) #define AFX_MEMORYVIEWER_H__52C50474_5399_4D0B_A3E4_4C52C4E0EAA0__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewerAddressSize.h ./src/win32/MemoryViewerAddressSize.h --- ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewerAddressSize.h 2004-05-13 22:38:09 +0900 +++ ./src/win32/MemoryViewerAddressSize.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_MEMORYVIEWERADDRESSSIZE_H__04605262_2B1D_4EED_A467_B6C56AC2CACD__INCLUDED_) #define AFX_MEMORYVIEWERADDRESSSIZE_H__04605262_2B1D_4EED_A467_B6C56AC2CACD__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewerDlg.cpp ./src/win32/MemoryViewerDlg.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/MemoryViewerDlg.cpp 2004-05-13 23:20:50 +0900 +++ ./src/win32/MemoryViewerDlg.cpp 2005-09-03 21:29:23 +0900 @@ -320,14 +320,59 @@ void MemoryViewerDlg::OnSave() { - MemoryViewerAddressSize dlg; - CString buffer; + if(rom != NULL) + { + MemoryViewerAddressSize dlg; + CString buffer; - dlg.setAddress(m_viewer.getCurrentAddress()); + dlg.setAddress(m_viewer.getCurrentAddress()); - LPCTSTR exts[] = { ".dmp" }; + LPCTSTR exts[] = { ".dmp" }; - if(dlg.DoModal() == IDOK) { + if(dlg.DoModal() == IDOK) { + CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP); + CString title = winResLoadString(IDS_SELECT_DUMP_FILE); + + FileDlg file(this, + buffer, + filter, + 0, + "DMP", + exts, + "", + title, + true); + if(file.DoModal() == IDOK) { + buffer = file.GetPathName(); + + FILE *f = fopen(buffer, "wb"); + + if(f == NULL) { + systemMessage(IDS_ERROR_CREATING_FILE, buffer); + return; + } + + int size = dlg.getSize(); + u32 addr = dlg.getAddress(); + + for(int i = 0; i < size; i++) { + fputc(CPUReadByteQuick(addr), f); + addr++; + } + + fclose(f); + } + } + } +} + +void MemoryViewerDlg::OnLoad() +{ + if(rom != NULL) + { + CString buffer; + LPCTSTR exts[] = { ".dmp" }; + CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP); CString title = winResLoadString(IDS_SELECT_DUMP_FILE); @@ -338,84 +383,45 @@ "DMP", exts, "", - title, - true); + title, + false); + if(file.DoModal() == IDOK) { buffer = file.GetPathName(); - - FILE *f = fopen(buffer, "wb"); - + FILE *f = fopen(buffer, "rb"); if(f == NULL) { - systemMessage(IDS_ERROR_CREATING_FILE, buffer); + systemMessage(IDS_CANNOT_OPEN_FILE, + "Cannot open file %s", + buffer); return; } - - int size = dlg.getSize(); - u32 addr = dlg.getAddress(); - - for(int i = 0; i < size; i++) { - fputc(CPUReadByteQuick(addr), f); - addr++; - } - - fclose(f); - } - } -} - -void MemoryViewerDlg::OnLoad() -{ - CString buffer; - LPCTSTR exts[] = { ".dmp" }; - - CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP); - CString title = winResLoadString(IDS_SELECT_DUMP_FILE); - - FileDlg file(this, - buffer, - filter, - 0, - "DMP", - exts, - "", - title, - false); - - if(file.DoModal() == IDOK) { - buffer = file.GetPathName(); - FILE *f = fopen(buffer, "rb"); - if(f == NULL) { - systemMessage(IDS_CANNOT_OPEN_FILE, - "Cannot open file %s", - buffer); - return; - } - MemoryViewerAddressSize dlg; + MemoryViewerAddressSize dlg; - fseek(f, 0, SEEK_END); - int size = ftell(f); + fseek(f, 0, SEEK_END); + int size = ftell(f); - fseek(f, 0, SEEK_SET); + fseek(f, 0, SEEK_SET); - dlg.setAddress(m_viewer.getCurrentAddress()); - dlg.setSize(size); + dlg.setAddress(m_viewer.getCurrentAddress()); + dlg.setSize(size); - if(dlg.DoModal() == IDOK) { - int size = dlg.getSize(); - u32 addr = dlg.getAddress(); - - for(int i = 0; i < size; i++) { - int c = fgetc(f); - if(c == -1) - break; - CPUWriteByteQuick(addr, c); - addr++; + if(dlg.DoModal() == IDOK) { + int size = dlg.getSize(); + u32 addr = dlg.getAddress(); + + for(int i = 0; i < size; i++) { + int c = fgetc(f); + if(c == -1) + break; + CPUWriteByteQuick(addr, c); + addr++; + } + OnRefresh(); } - OnRefresh(); + fclose(f); } - fclose(f); - } + } } void MemoryViewerDlg::PostNcDestroy() diff -urN ../VisualBoyAdvance-1.7.2/src/win32/ModeConfirm.cpp ./src/win32/ModeConfirm.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/ModeConfirm.cpp 2004-05-13 23:20:38 +0900 +++ ./src/win32/ModeConfirm.cpp 2006-06-07 06:04:21 +0900 @@ -100,7 +100,7 @@ // EXCEPTION: OCX Property Pages should return FALSE } -void ModeConfirm::OnTimer(UINT nIDEvent) +void ModeConfirm::OnTimer(UINT_PTR nIDEvent) { CString buffer; count--; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/ModeConfirm.h ./src/win32/ModeConfirm.h --- ../VisualBoyAdvance-1.7.2/src/win32/ModeConfirm.h 2004-05-13 22:37:41 +0900 +++ ./src/win32/ModeConfirm.h 2006-06-07 06:04:21 +0900 @@ -34,7 +34,7 @@ // Construction public: int count; - UINT timer; + UINT_PTR timer; ModeConfirm(CWnd* pParent); // standard constructor // Dialog Data @@ -60,7 +60,7 @@ afx_msg void OnOk(); afx_msg void OnDestroy(); virtual BOOL OnInitDialog(); - afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnTimer(UINT_PTR nIDEvent); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/OamView.cpp ./src/win32/OamView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/OamView.cpp 2004-05-13 23:20:26 +0900 +++ ./src/win32/OamView.cpp 2005-09-03 21:29:23 +0900 @@ -463,37 +463,40 @@ void OamView::OnSave() { - CString captureBuffer; - - if(theApp.captureFormat == 0) - captureBuffer = "oam.png"; - else - captureBuffer = "oam.bmp"; - - LPCTSTR exts[] = {".png", ".bmp" }; - - CString filter = theApp.winLoadFilter(IDS_FILTER_PNG); - CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); - - FileDlg dlg(this, - captureBuffer, - filter, - theApp.captureFormat ? 2 : 1, - theApp.captureFormat ? "BMP" : "PNG", - exts, - "", - title, - true); - - if(dlg.DoModal() == IDCANCEL) { - return; + if(rom != NULL) + { + CString captureBuffer; + + if(theApp.captureFormat == 0) + captureBuffer = "oam.png"; + else + captureBuffer = "oam.bmp"; + + LPCTSTR exts[] = {".png", ".bmp" }; + + CString filter = theApp.winLoadFilter(IDS_FILTER_PNG); + CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); + + FileDlg dlg(this, + captureBuffer, + filter, + theApp.captureFormat ? 2 : 1, + theApp.captureFormat ? "BMP" : "PNG", + exts, + "", + title, + true); + + if(dlg.DoModal() == IDCANCEL) { + return; + } + captureBuffer = dlg.GetPathName(); + + if(dlg.getFilterIndex() == 2) + saveBMP(captureBuffer); + else + savePNG(captureBuffer); } - captureBuffer = dlg.GetPathName(); - - if(dlg.getFilterIndex() == 2) - saveBMP(captureBuffer); - else - savePNG(captureBuffer); } BOOL OamView::OnInitDialog() diff -urN ../VisualBoyAdvance-1.7.2/src/win32/OpenGL.cpp ./src/win32/OpenGL.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/OpenGL.cpp 2004-05-13 23:20:15 +0900 +++ ./src/win32/OpenGL.cpp 2006-08-11 19:58:39 +0900 @@ -1,6 +1,7 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten // Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005-2006 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 @@ -17,16 +18,25 @@ // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" + #include "MainWnd.h" -#include #include "../System.h" #include "../GBA.h" #include "../Globals.h" #include "../Text.h" +#include "../Util.h" +#include "../gb/gbGlobals.h" + +#include -#include "Reg.h" -#include "resource.h" +// OpenGL +#include // main include file +typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); + +extern int Init_2xSaI(u32); +extern void winlog(const char *,...); +extern int systemSpeed; #ifdef _DEBUG #define new DEBUG_NEW @@ -36,530 +46,624 @@ #ifdef MMX extern "C" bool cpu_mmx; - extern bool detectMMX(); #endif -extern int Init_2xSaI(u32); -extern void winlog(const char *,...); -extern int systemSpeed; class OpenGLDisplay : public IDisplay { private: - HDC hDC; - HGLRC hglrc; - GLuint texture; - int width; - int height; - float size; - u8 *filterData; - bool failed; - - bool initializeTexture(int w, int h); - void updateFiltering(int); -public: - OpenGLDisplay(); - virtual ~OpenGLDisplay(); + HDC hDC; + HGLRC hglrc; + GLuint texture; + int width; + int height; + float size; + u8 *filterData; + RECT destRect; + bool failed; + + void initializeMatrices( int w, int h ); + bool initializeTexture( int w, int h ); + void updateFiltering( int value ); + void setVSync( int interval = 1 ); + void calculateDestRect( int w, int h ); - virtual bool initialize(); - virtual void cleanup(); - virtual void render(); - virtual void checkFullScreen(); - virtual void renderMenu(); - virtual void clear(); - virtual bool changeRenderSize(int w, int h); - virtual void resize(int w, int h); - virtual DISPLAY_TYPE getType() { return OPENGL; }; - virtual void setOption(const char *, int); - virtual int selectFullScreenMode(GUID **); +public: + OpenGLDisplay(); + virtual ~OpenGLDisplay(); + virtual DISPLAY_TYPE getType() { return OPENGL; }; + + virtual bool initialize(); + virtual void cleanup(); + virtual void render(); + virtual void renderMenu(); + virtual void clear(); + virtual bool changeRenderSize( int w, int h ); + virtual void resize( int w, int h ); + virtual void setOption( const char *, int ); + virtual int selectFullScreenMode( GUID ** ); }; + OpenGLDisplay::OpenGLDisplay() { - hDC = NULL; - hglrc = NULL; - texture = 0; - width = 0; - height = 0; - size = 0.0f; - filterData = (u8 *)malloc(4*4*256*240); - failed = false; + hDC = NULL; + hglrc = NULL; + texture = 0; + width = 0; + height = 0; + size = 0.0f; + filterData = (u8 *)malloc(4*4*256*240); + failed = false; } + OpenGLDisplay::~OpenGLDisplay() { - cleanup(); + cleanup(); } + void OpenGLDisplay::cleanup() { - if(texture != 0) { - glDeleteTextures(1, &texture); - texture = 0; - } - if(hglrc != NULL) { - wglDeleteContext(hglrc); - wglMakeCurrent(NULL, NULL); - hglrc = NULL; - } - if(hDC != NULL) { - ReleaseDC(*theApp.m_pMainWnd, hDC); - hDC = NULL; - } - if(filterData) { - free(filterData); - filterData = NULL; - } - width = 0; - height = 0; - size = 0.0f; + if(texture != 0) { + glDeleteTextures(1, &texture); + texture = 0; + } + + if(hglrc != NULL) { + wglDeleteContext(hglrc); + wglMakeCurrent(NULL, NULL); + hglrc = NULL; + } + + if(hDC != NULL) { + ReleaseDC(*theApp.m_pMainWnd, hDC); + hDC = NULL; + } + + if(filterData) { + free(filterData); + filterData = NULL; + } + + width = 0; + height = 0; + size = 0.0f; } + bool OpenGLDisplay::initialize() { - theApp.sizeX = 240; - theApp.sizeY = 160; + switch( theApp.cartridgeType ) + { + case IMAGE_GBA: + theApp.sizeX = 240; + theApp.sizeY = 160; + break; + case IMAGE_GB: + if ( gbBorderOn ) + { + theApp.sizeX = 256; + theApp.sizeY = 224; + } + else + { + theApp.sizeX = 160; + theApp.sizeY = 144; + } + break; + } + + + switch(theApp.videoOption) + { + case VIDEO_1X: + theApp.surfaceSizeX = theApp.sizeX; + theApp.surfaceSizeY = theApp.sizeY; + break; + case VIDEO_2X: + theApp.surfaceSizeX = theApp.sizeX * 2; + theApp.surfaceSizeY = theApp.sizeY * 2; + break; + case VIDEO_3X: + theApp.surfaceSizeX = theApp.sizeX * 3; + theApp.surfaceSizeY = theApp.sizeY * 3; + break; + case VIDEO_4X: + theApp.surfaceSizeX = theApp.sizeX * 4; + theApp.surfaceSizeY = theApp.sizeY * 4; + break; + case VIDEO_320x240: + case VIDEO_640x480: + case VIDEO_800x600: + case VIDEO_OTHER: + { + if( theApp.fullScreenStretch ) { + theApp.surfaceSizeX = theApp.fsWidth; + theApp.surfaceSizeY = theApp.fsHeight; + } else { + float scaleX = (float)theApp.fsWidth / (float)theApp.sizeX; + float scaleY = (float)theApp.fsHeight / (float)theApp.sizeY; + float min = ( scaleX < scaleY ) ? scaleX : scaleY; + if( theApp.fsMaxScale ) + min = ( min > (float)theApp.fsMaxScale ) ? (float)theApp.fsMaxScale : min; + theApp.surfaceSizeX = (int)((float)theApp.sizeX * min); + theApp.surfaceSizeY = (int)((float)theApp.sizeY * min); + } + } + break; + } + + theApp.rect.left = 0; + theApp.rect.top = 0; + theApp.rect.right = theApp.sizeX; + theApp.rect.bottom = theApp.sizeY; + + theApp.dest.left = 0; + theApp.dest.top = 0; + theApp.dest.right = theApp.surfaceSizeX; + theApp.dest.bottom = theApp.surfaceSizeY; + + DWORD style = WS_POPUP | WS_VISIBLE; + DWORD styleEx = 0; + + if( theApp.videoOption <= VIDEO_4X ) + style |= WS_OVERLAPPEDWINDOW; + else + styleEx = 0; + + if( theApp.videoOption <= VIDEO_4X ) + AdjustWindowRectEx( &theApp.dest, style, TRUE, styleEx ); + else + AdjustWindowRectEx( &theApp.dest, style, FALSE, styleEx ); + + int winSizeX = theApp.dest.right - theApp.dest.left; + int winSizeY = theApp.dest.bottom - theApp.dest.top; + int x = 0, y = 0; + + if( theApp.videoOption <= VIDEO_4X ) { + x = theApp.windowPositionX; + y = theApp.windowPositionY; + } else { + winSizeX = theApp.fsWidth; + winSizeY = theApp.fsHeight; + } + + // Create a window + MainWnd *pWnd = new MainWnd; + theApp.m_pMainWnd = pWnd; + + pWnd->CreateEx( + styleEx, + theApp.wndClass, + "VisualBoyAdvance", + style, + x,y,winSizeX,winSizeY, + NULL, + 0 ); + + if (!(HWND)*pWnd) { + winlog("Error creating Window %08x\n", GetLastError()); + return FALSE; + } + + theApp.updateMenuBar(); + + theApp.adjustDestRect(); + + theApp.mode320Available = FALSE; + theApp.mode640Available = FALSE; + theApp.mode800Available = FALSE; + + CDC *dc = pWnd->GetDC(); + HDC hDC = dc->GetSafeHdc(); + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 24, // 24-bit color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + int iPixelFormat; + if( !(iPixelFormat = ChoosePixelFormat( hDC, &pfd )) ) { + winlog( "Failed ChoosePixelFormat\n" ); + return false; + } + + // obtain detailed information about + // the device context's first pixel format + if( !( DescribePixelFormat( + hDC, + iPixelFormat, + sizeof(PIXELFORMATDESCRIPTOR), + &pfd ) ) ) + { + winlog( "Failed DescribePixelFormat\n" ); + return false; + } + + if( !SetPixelFormat( hDC, iPixelFormat, &pfd ) ) { + winlog( "Failed SetPixelFormat\n" ); + return false; + } + + if( !( hglrc = wglCreateContext( hDC ) ) ) { + winlog( "Failed wglCreateContext\n" ); + return false; + } + + if( !wglMakeCurrent(hDC, hglrc) ) { + winlog( "Failed wglMakeCurrent\n" ); + return false; + } + + pWnd->ReleaseDC( dc ); + + // setup 2D gl environment + glPushAttrib( GL_ENABLE_BIT ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_CULL_FACE ); + glEnable( GL_TEXTURE_2D ); + + initializeMatrices( theApp.surfaceSizeX, theApp.surfaceSizeY ); + + setVSync( theApp.vsync ); - switch(theApp.videoOption) { - case VIDEO_1X: - theApp.surfaceSizeX = theApp.sizeX; - theApp.surfaceSizeY = theApp.sizeY; - break; - case VIDEO_2X: - theApp.surfaceSizeX = theApp.sizeX * 2; - theApp.surfaceSizeY = theApp.sizeY * 2; - break; - case VIDEO_3X: - theApp.surfaceSizeX = theApp.sizeX * 3; - theApp.surfaceSizeY = theApp.sizeY * 3; - break; - case VIDEO_4X: - theApp.surfaceSizeX = theApp.sizeX * 4; - theApp.surfaceSizeY = theApp.sizeY * 4; - break; - case VIDEO_320x240: - case VIDEO_640x480: - case VIDEO_800x600: - case VIDEO_OTHER: - { - RECT r; - ::GetWindowRect(GetDesktopWindow(), &r); - theApp.fsWidth = r.right - r.left; - theApp.fsHeight = r.bottom - r.top; - - /* Need to fix this code later. For now, Fullscreen takes the whole - screen. - int scaleX = (fsWidth / sizeX); - int scaleY = (fsHeight / sizeY); - int min = scaleX < scaleY ? scaleX : scaleY; - surfaceSizeX = sizeX * min; - surfaceSizeY = sizeY * min; - if(fullScreenStretch) { - */ - theApp.surfaceSizeX = theApp.fsWidth; - theApp.surfaceSizeY = theApp.fsHeight; - // } - } - break; - } - - theApp.rect.left = 0; - theApp.rect.top = 0; - theApp.rect.right = theApp.sizeX; - theApp.rect.bottom = theApp.sizeY; - - theApp.dest.left = 0; - theApp.dest.top = 0; - theApp.dest.right = theApp.surfaceSizeX; - theApp.dest.bottom = theApp.surfaceSizeY; - - DWORD style = WS_POPUP | WS_VISIBLE; - DWORD styleEx = 0; - - if(theApp.videoOption <= VIDEO_4X) - style |= WS_OVERLAPPEDWINDOW; - else - styleEx = 0; - - if(theApp.videoOption <= VIDEO_4X) - AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx); - else - AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx); - - int winSizeX = theApp.dest.right-theApp.dest.left; - int winSizeY = theApp.dest.bottom-theApp.dest.top; - - if(theApp.videoOption > VIDEO_4X) { - winSizeX = theApp.fsWidth; - winSizeY = theApp.fsHeight; - } - - int x = 0; - int y = 0; - - if(theApp.videoOption <= VIDEO_4X) { - x = theApp.windowPositionX; - y = theApp.windowPositionY; - } - - // Create a window - MainWnd *pWnd = new MainWnd; - theApp.m_pMainWnd = pWnd; - - pWnd->CreateEx(styleEx, - theApp.wndClass, - "VisualBoyAdvance", - style, - x,y,winSizeX,winSizeY, - NULL, - 0); - - if (!(HWND)*pWnd) { - winlog("Error creating Window %08x\n", GetLastError()); - return FALSE; - } - - theApp.updateMenuBar(); - - theApp.adjustDestRect(); - - theApp.mode320Available = FALSE; - theApp.mode640Available = FALSE; - theApp.mode800Available = FALSE; - - CDC *dc = pWnd->GetDC(); - HDC hDC = dc->GetSafeHdc(); - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - PFD_DRAW_TO_WINDOW | // support window - PFD_SUPPORT_OPENGL | // support OpenGL - PFD_DOUBLEBUFFER, // double buffered - PFD_TYPE_RGBA, // RGBA type - 16, // 16-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 0, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // 32-bit z-buffer - 0, // no stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - int iPixelFormat; - - if(!(iPixelFormat = ChoosePixelFormat(hDC, &pfd))) { - winlog("Failed ChoosePixelFormat\n"); - return false; - } - - // obtain detailed information about - // the device context's first pixel format - if(!(DescribePixelFormat(hDC, iPixelFormat, - sizeof(PIXELFORMATDESCRIPTOR), &pfd))) { - winlog("Failed DescribePixelFormat\n"); - return false; - } - - if(!SetPixelFormat(hDC, iPixelFormat, &pfd)) { - winlog("Failed SetPixelFormat\n"); - return false; - } - - if(!(hglrc = wglCreateContext(hDC))) { - winlog("Failed wglCreateContext\n"); - return false; - } - - if(!wglMakeCurrent(hDC, hglrc)) { - winlog("Failed wglMakeCurrent\n"); - return false; - } - pWnd->ReleaseDC(dc); - - // setup 2D gl environment - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_2D); - - glViewport(0, 0, theApp.surfaceSizeX, theApp.surfaceSizeY); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - glOrtho(0.0, (GLdouble)(theApp.surfaceSizeX), (GLdouble)(theApp.surfaceSizeY), - 0.0, 0.0,1.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - systemRedShift = 3; - systemGreenShift = 11; - systemBlueShift = 19; - systemColorDepth = 32; - theApp.fsColorDepth = 32; - - Init_2xSaI(32); #ifdef MMX - if(!theApp.disableMMX) - cpu_mmx = theApp.detectMMX(); - else - cpu_mmx = 0; + if(!theApp.disableMMX) + cpu_mmx = theApp.detectMMX(); + else + cpu_mmx = 0; #endif - - if(theApp.ddrawDebug) { - winlog("R shift: %d\n", systemRedShift); - winlog("G shift: %d\n", systemGreenShift); - winlog("B shift: %d\n", systemBlueShift); - } - - switch(systemColorDepth) { - case 16: - { - for(int i = 0; i < 0x10000; i++) { - systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | - (((i & 0x3e0) >> 5) << systemGreenShift) | - (((i & 0x7c00) >> 10) << systemBlueShift); - } - } - 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); - } - } - break; - } - theApp.updateFilter(); - theApp.updateIFB(); - - if(failed) - return false; - - pWnd->DragAcceptFiles(TRUE); - - return TRUE; + + systemRedShift = 3; + systemGreenShift = 11; + systemBlueShift = 19; + systemColorDepth = 32; + theApp.fsColorDepth = 32; + + Init_2xSaI(32); + + utilUpdateSystemColorMaps(); + theApp.updateFilter(); + theApp.updateIFB(); + + if(failed) + return false; + + pWnd->DragAcceptFiles(TRUE); + + return TRUE; } + void OpenGLDisplay::clear() { + glClear( GL_COLOR_BUFFER_BIT ); } + void OpenGLDisplay::renderMenu() { - checkFullScreen(); - if(theApp.m_pMainWnd) - theApp.m_pMainWnd->DrawMenuBar(); + checkFullScreen(); + if( theApp.m_pMainWnd ) + theApp.m_pMainWnd->DrawMenuBar(); } -void OpenGLDisplay::checkFullScreen() -{ - // if(tripleBuffering) - // pOpenGL->FlipToGDISurface(); -} void OpenGLDisplay::render() { - int pitch = theApp.filterWidth * 4 + 4; - u8 *data = pix + (theApp.sizeX+1)*4; - - if(theApp.filterFunction) { - data = filterData; - theApp.filterFunction(pix+pitch, - pitch, - (u8*)theApp.delta, - (u8*)filterData, - theApp.filterWidth*4*2, - theApp.filterWidth, - theApp.filterHeight); - } - - if(theApp.videoOption > VIDEO_4X && theApp.showSpeed) { - char buffer[30]; - if(theApp.showSpeed == 1) - sprintf(buffer, "%3d%%", systemSpeed); - else - sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed, - systemFrameSkip, - theApp.showRenderedFrames); - - if(theApp.filterFunction) { - int p = theApp.filterWidth * 4; - if(systemColorDepth == 24) - p = theApp.filterWidth * 6; - else if(systemColorDepth == 32) - p = theApp.filterWidth * 8; - if(theApp.showSpeedTransparent) - drawTextTransp((u8*)filterData, - p, - 10, - theApp.filterHeight*2-10, - buffer); - else - drawText((u8*)filterData, - p, - 10, - theApp.filterHeight*2-10, - buffer); - } else { - if(theApp.showSpeedTransparent) - drawTextTransp((u8*)pix, - pitch, - 10, - theApp.filterHeight-10, - buffer); - else - drawText((u8*)pix, - pitch, - 10, - theApp.filterHeight-10, - buffer); - } - } - - // Texturemap complete texture to surface so we have free scaling - // and antialiasing - int mult = 1; - if(theApp.filterFunction) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, 2*theApp.sizeX); - mult = 2; - } else { - glPixelStorei(GL_UNPACK_ROW_LENGTH, theApp.sizeX+1); - } - - glTexSubImage2D( GL_TEXTURE_2D,0, - 0,0, mult*theApp.sizeX,mult*theApp.sizeY, - GL_RGBA,GL_UNSIGNED_BYTE,data); - - if(theApp.glType == 0) { - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0); - glTexCoord2f(mult*theApp.sizeX/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0); - glTexCoord2f(0.0, mult*theApp.sizeY/size); glVertex3i(0, theApp.surfaceSizeY, 0); - glTexCoord2f(mult*theApp.sizeX/size, mult*theApp.sizeY/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0); - glEnd(); - } else { - glBegin(GL_QUADS); - glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0); - glTexCoord2f(mult*theApp.sizeX/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0); - glTexCoord2f(mult*theApp.sizeX/size, mult*theApp.sizeY/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0); - glTexCoord2f(0.0, mult*theApp.sizeY/size); glVertex3i(0, theApp.surfaceSizeY, 0); - glEnd(); - } - - CDC *dc = theApp.m_pMainWnd->GetDC(); - - if(theApp.screenMessage) { - if(((GetTickCount() - theApp.screenMessageTime) < 3000) && - !theApp.disableStatusMessage) { - dc->SetTextColor(RGB(255,0,0)); - dc->SetBkMode(TRANSPARENT); - dc->TextOut(10, theApp.surfaceSizeY - 20, theApp.screenMessageBuffer); - } else { - theApp.screenMessage = false; - } - } - - SwapBuffers(dc->GetSafeHdc()); - - theApp.m_pMainWnd->ReleaseDC(dc); -} - -void OpenGLDisplay::resize(int w, int h) -{ - glViewport(0, 0, w, h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - glOrtho(0.0, (GLdouble)(w), (GLdouble)(h), - 0.0, 0.0,1.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); -} - -void OpenGLDisplay::updateFiltering(int value) -{ - switch(value) { - case 0: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - break; - case 1: - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - break; - } -} - -bool OpenGLDisplay::initializeTexture(int w, int h) -{ - int mySize = 256; - size = 256.0f; - if(w > 255 || h > 255) { - size = 512.0f; - mySize = 512; - } - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - - int filter = regQueryDwordValue("glFilter", 0); - if(filter < 0 || filter > 1) - filter = 0; - updateFiltering(filter); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mySize, mySize, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL ); - width = w; - height = h; - - return true; -} - -bool OpenGLDisplay::changeRenderSize(int w, int h) -{ - if(width != w || height != h) { - if(texture != 0) { - glDeleteTextures(1, &texture); - texture = 0; - } - if(!initializeTexture(w, h)) { - failed = true; - return false; - } - } - return true; -} - -void OpenGLDisplay::setOption(const char *option, int value) -{ - if(!strcmp(option, "glFilter")) - updateFiltering(value); -} - -int OpenGLDisplay::selectFullScreenMode(GUID **) -{ - HWND wnd = GetDesktopWindow(); - RECT r; - GetWindowRect(wnd, &r); - int w = (r.right - r.left) & 4095; - int h = (r.bottom - r.top) & 4095; - HDC dc = GetDC(wnd); - int c = GetDeviceCaps(dc, BITSPIXEL); - ReleaseDC(wnd, dc); + clear(); - return (c << 24) | (w << 12) | h; + int pitch = theApp.filterWidth * 4 + 4; + u8 *data = pix + ( theApp.sizeX + 1 ) * 4; + + // apply pixel filter + if(theApp.filterFunction) { + data = filterData; + theApp.filterFunction( + pix + pitch, + pitch, + (u8*)theApp.delta, + (u8*)filterData, + theApp.filterWidth * 4 * 2, + theApp.filterWidth, + theApp.filterHeight); + } + + // Texturemap complete texture to surface + // so we have free scaling and antialiasing + int mult; + if( theApp.filterFunction ) { + glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX << 1 ); + mult = 2; + } else { + glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 ); + mult = 1; + } + + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + mult * theApp.sizeX, + mult * theApp.sizeY, + GL_RGBA, + GL_UNSIGNED_BYTE, + data ); + + if( theApp.glType == 0 ) { + glBegin( GL_TRIANGLE_STRIP ); + + glTexCoord2f( 0.0f, 0.0f ); + glVertex3i( 0, 0, 0 ); + + glTexCoord2f( (float)(mult * theApp.sizeX) / size, 0.0f ); + glVertex3i( theApp.surfaceSizeX, 0, 0 ); + + glTexCoord2f( 0.0f, (float)(mult * theApp.sizeY) / size ); + glVertex3i( 0, theApp.surfaceSizeY, 0 ); + + glTexCoord2f( (float)(mult * theApp.sizeX) / size, (float)(mult * theApp.sizeY) / size ); + glVertex3i( theApp.surfaceSizeX, theApp.surfaceSizeY, 0 ); + + glEnd(); + } else { + glBegin( GL_QUADS ); + + glTexCoord2f( 0.0f, 0.0f ); + glVertex3i( 0, 0, 0 ); + + glTexCoord2f( (float)(mult * theApp.sizeX) / size, 0.0f ); + glVertex3i( theApp.surfaceSizeX, 0, 0 ); + + glTexCoord2f( (float)(mult * theApp.sizeX) / size, (float)(mult * theApp.sizeY) / size ); + glVertex3i( theApp.surfaceSizeX, theApp.surfaceSizeY, 0 ); + + glTexCoord2f( 0.0f, (float)(mult * theApp.sizeY) / size ); + glVertex3i( 0, theApp.surfaceSizeY, 0 ); + + glEnd(); + } + + CDC *dc = theApp.m_pMainWnd->GetDC(); + + SwapBuffers( dc->GetSafeHdc() ); + // since OpenGL draws on the back buffer, + // we have to swap it to the front buffer to see it + + // draw informations with GDI on the front buffer + dc->SetBkMode( theApp.showSpeedTransparent ? TRANSPARENT : OPAQUE ); + if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) { + char buffer[30]; + if( theApp.showSpeed == 1 ) { + sprintf( buffer, "%3d%%", systemSpeed ); + } else { + sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames ); + } + dc->SetTextColor( RGB(0x00, 0x00, 0xFF) ); + dc->TextOut( 10, 20, buffer ); + } + if( theApp.screenMessage ) { + if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage ) { + dc->SetTextColor( RGB(0xFF, 0x00, 0x00) ); + dc->TextOut( 10, theApp.surfaceSizeY - 20, theApp.screenMessageBuffer ); + } else { + theApp.screenMessage = false; + } + } + + theApp.m_pMainWnd->ReleaseDC( dc ); +} + + +void OpenGLDisplay::resize( int w, int h ) +{ + initializeMatrices( w, h ); +} + + +void OpenGLDisplay::updateFiltering( int value ) +{ + switch( value ) + { + case 0: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + break; + case 1: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + break; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); +} + + +void OpenGLDisplay::initializeMatrices( int w, int h ) +{ + if( theApp.fullScreenStretch ) { + glViewport( 0, 0, w, h ); + } else { + calculateDestRect( w, h ); + glViewport( + destRect.left, + destRect.top, + destRect.right - destRect.left, + destRect.bottom - destRect.top ); + } + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glOrtho( + /* left */ 1.0f, + /* right */ (GLdouble)(w - 1), + /* bottom */ (GLdouble)(h - 1), + /* top */ 1.0f, + 0.0f, + 1.0f ); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +bool OpenGLDisplay::initializeTexture( int w, int h ) +{ + // size = 2^n + // w = 24 > size = 256 = 2^8 + // w = 255 > size = 256 = 2^8 + // w = 256 > size = 512 = 2^9 + // w = 300 > size = 512 = 2^9 + // OpenGL textures have to be square and a power of 2 + + float n1 = log10( (float)w ) / log10( 2.0f ); + float n2 = log10( (float)h ) / log10( 2.0f ); + float n = ( n1 > n2 ) ? n1 : n2; + + if( ((float)((int)n)) != n ) { + // round up + n = ((float)((int)n)) + 1.0f; + } + + size = pow( 2.0f, n ); + + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + updateFiltering( theApp.glFilter ); + + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + (GLsizei)size, + (GLsizei)size, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + NULL ); + + width = w; + height = h; + + return ( glGetError() == GL_NO_ERROR) ? true : false; +} + + +void OpenGLDisplay::setVSync( int interval ) +{ + const char *extensions = (const char *)glGetString( GL_EXTENSIONS ); + + if( strstr( extensions, "WGL_EXT_swap_control" ) == 0 ) { + winlog( "Error: WGL_EXT_swap_control extension not supported on your computer.\n" ); + return; + } else { + PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = NULL; + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" ); + if( wglSwapIntervalEXT ) { + wglSwapIntervalEXT( interval ); + } + } +} + + +bool OpenGLDisplay::changeRenderSize( int w, int h ) +{ + if( (width != w) || (height != h) ) { + if( texture != 0 ) { + glDeleteTextures( 1, &texture ); + texture = 0; + } + + if( !initializeTexture( w, h ) ) { + failed = true; + return false; + } + } + + return true; +} + + +void OpenGLDisplay::calculateDestRect( int w, int h ) +{ + float scaleX = (float)w / (float)width; + float scaleY = (float)h / (float)height; + float min = (scaleX < scaleY) ? scaleX : scaleY; + if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) { + min = (float)theApp.fsMaxScale; + } + destRect.left = 0; + destRect.top = 0; + destRect.right = (LONG)(width * min); + destRect.bottom = (LONG)(height * min); + if( destRect.right != w ) { + LONG diff = (w - destRect.right) / 2; + destRect.left += diff; + destRect.right += diff; + } + if( destRect.bottom != h ) { + LONG diff = (h - destRect.bottom) / 2; + destRect.top += diff; + destRect.bottom += diff; + } +} + + +void OpenGLDisplay::setOption( const char *option, int value ) +{ + if( !_tcscmp( option, _T("vsync") ) ) { + setVSync( value ); + } + + if( !_tcscmp( option, _T("glFilter") ) ) { + updateFiltering( value ); + } + + if( !_tcscmp( option, _T("maxScale") ) ) { + initializeMatrices( theApp.dest.right, theApp.dest.bottom ); + } + + if( !_tcscmp( option, _T("fullScreenStretch") ) ) { + initializeMatrices( theApp.dest.right, theApp.dest.bottom ); + } +} + + +int OpenGLDisplay::selectFullScreenMode( GUID ** ) +{ + HWND wnd = GetDesktopWindow(); + RECT r; + GetWindowRect( wnd, &r ); + int w = ( r.right - r.left ) & 0xFFF; + int h = ( r.bottom - r.top ) & 0xFFF; + HDC dc = GetDC( wnd ); + int c = GetDeviceCaps( dc, BITSPIXEL ); + ReleaseDC( wnd, dc ); + return (c << 24) | (w << 12) | h; } + IDisplay *newOpenGLDisplay() { - return new OpenGLDisplay(); + return new OpenGLDisplay(); } - diff -urN ../VisualBoyAdvance-1.7.2/src/win32/PaletteView.cpp ./src/win32/PaletteView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/PaletteView.cpp 2004-05-13 23:19:05 +0900 +++ ./src/win32/PaletteView.cpp 2005-09-03 21:29:23 +0900 @@ -109,49 +109,54 @@ void PaletteView::save(int which) { - CString captureBuffer; + if(rom != NULL) + { + CString captureBuffer; + + if(which == 0) + captureBuffer = "bg.pal"; + else + captureBuffer = "obj.pal"; - if(which == 0) - captureBuffer = "bg.pal"; - else - captureBuffer = "obj.pal"; - - LPCTSTR exts[] = {".pal", ".pal", ".act" }; + LPCTSTR exts[] = {".pal", ".pal", ".act" }; - CString filter = theApp.winLoadFilter(IDS_FILTER_PAL); - CString title = winResLoadString(IDS_SELECT_PALETTE_NAME); - FileDlg dlg(this, - captureBuffer, - filter, - 1, - "PAL", - exts, - "", - title, - true); - - if(dlg.DoModal() == IDCANCEL) { - return; - } - - PaletteViewControl *p = NULL; - - if(which == 0) - p = &paletteView; - else - p = &paletteViewOBJ; + CString filter = theApp.winLoadFilter(IDS_FILTER_PAL); + CString title = winResLoadString(IDS_SELECT_PALETTE_NAME); + FileDlg dlg(this, + captureBuffer, + filter, + 1, + "PAL", + exts, + "", + title, + true); + + if(dlg.DoModal() == IDCANCEL) { + return; + } + + captureBuffer = dlg.GetPathName(); + + PaletteViewControl *p = NULL; + + if(which == 0) + p = &paletteView; + else + p = &paletteViewOBJ; - switch(dlg.getFilterIndex()) { - case 0: - case 1: - p->saveMSPAL(captureBuffer); - break; - case 2: - p->saveJASCPAL(captureBuffer); - break; - case 3: - p->saveAdobe(captureBuffer); - break; + switch(dlg.getFilterIndex()) { + case 0: + case 1: + p->saveMSPAL(captureBuffer); + break; + case 2: + p->saveJASCPAL(captureBuffer); + break; + case 3: + p->saveAdobe(captureBuffer); + break; + } } } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/Reg.cpp ./src/win32/Reg.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/Reg.cpp 2004-05-13 23:18:44 +0900 +++ ./src/win32/Reg.cpp 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ static char buffer[2048]; static HKEY vbKey = NULL; -static CString regVbaPath; +static CString *regVbaPath = NULL; #define VBA_PREF "preferences" @@ -38,7 +38,12 @@ NULL, &vbKey, &disp); - regVbaPath.Format("%s\\vba.ini", path); + if( regVbaPath != NULL ) { + delete regVbaPath; + regVbaPath = NULL; + } + regVbaPath = new CString(); + regVbaPath->Format("%s\\vba.ini", path); } void regShutdown() @@ -48,7 +53,7 @@ const char *regGetINIPath() { - return regVbaPath; + return *regVbaPath; } char *regQueryStringValue(const char * key, char *def) @@ -75,7 +80,7 @@ def, (LPTSTR)buffer, 2048, - regVbaPath); + *regVbaPath); if(res) return buffer; @@ -106,7 +111,7 @@ return GetPrivateProfileInt(VBA_PREF, key, def, - regVbaPath); + *regVbaPath); } BOOL regQueryBinaryValue(const char * key, char *value, int count) @@ -134,14 +139,14 @@ int size = GetPrivateProfileInt(VBA_PREF, k, -1, - regVbaPath); + *regVbaPath); if(size >= 0 && size < count) count = size; return GetPrivateProfileStruct(VBA_PREF, key, value, count, - regVbaPath); + *regVbaPath); } void regSetStringValue(const char * key, const char * value) @@ -152,12 +157,12 @@ NULL, REG_SZ, (const UCHAR *)value, - strlen(value)+1); + lstrlen(value)+1); } else { WritePrivateProfileString(VBA_PREF, key, value, - regVbaPath); + *regVbaPath); } } @@ -175,7 +180,7 @@ WritePrivateProfileString(VBA_PREF, key, buffer, - regVbaPath); + *regVbaPath); } } @@ -196,13 +201,13 @@ WritePrivateProfileString(VBA_PREF, k, buffer, - regVbaPath); + *regVbaPath); WritePrivateProfileStruct(VBA_PREF, key, value, count, - regVbaPath); + *regVbaPath); } } @@ -215,7 +220,7 @@ WritePrivateProfileString(VBA_PREF, key, NULL, - regVbaPath); + *regVbaPath); } } @@ -238,7 +243,7 @@ 0, REG_SZ, (const UCHAR *)type, - strlen(type)+1); + lstrlen(type)+1); RegCloseKey(key); return true; } @@ -264,7 +269,7 @@ 0, REG_SZ, (const UCHAR *)desc, - strlen(desc)+1); + lstrlen(desc)+1); HKEY key2; res = RegCreateKeyEx(key, "Shell\\Open\\Command", @@ -281,7 +286,7 @@ 0, REG_SZ, (const UCHAR *)application, - strlen(application)+1); + lstrlen(application)+1); RegCloseKey(key2); RegCloseKey(key); return true; @@ -318,14 +323,14 @@ WritePrivateProfileString(section, valueName, temp, - regVbaPath); + *regVbaPath); } break; case REG_SZ: WritePrivateProfileString(section, valueName, buffer, - regVbaPath); + *regVbaPath); break; case REG_BINARY: { @@ -337,12 +342,12 @@ WritePrivateProfileString(section, k, temp, - regVbaPath); + *regVbaPath); WritePrivateProfileStruct(section, valueName, buffer, size, - regVbaPath); + *regVbaPath); } break; } diff -urN ../VisualBoyAdvance-1.7.2/src/win32/ResizeDlg.cpp ./src/win32/ResizeDlg.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/ResizeDlg.cpp 2003-11-04 23:09:52 +0900 +++ ./src/win32/ResizeDlg.cpp 2006-06-07 06:04:21 +0900 @@ -89,7 +89,7 @@ MB_ABORTRETRYIGNORE); if(res == IDRETRY) { - __asm int 3; + DebugBreak(); } else if(res == IDABORT) SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0); } @@ -143,7 +143,7 @@ if(nCode == IDABORT) { ::SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0); } else if(nCode == IDRETRY) - __asm int 3; + DebugBreak(); } long FASTCALL RegQueryValueExRecursive( HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData ) diff -urN ../VisualBoyAdvance-1.7.2/src/win32/RomInfo.cpp ./src/win32/RomInfo.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/RomInfo.cpp 2004-05-13 23:18:06 +0900 +++ ./src/win32/RomInfo.cpp 2006-06-06 23:33:43 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2004-2006 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 @@ -356,6 +356,15 @@ case 0x06: type = "ROM+MBC2+BATT"; break; + case 0x0b: + type = "ROM+MMM01"; + break; + case 0x0c: + type = "ROM+MMM01+RAM"; + break; + case 0x0d: + type = "ROM+MMM01+RAM+BATT"; + break; case 0x0f: type = "ROM+MBC3+TIMER+BATT"; break; @@ -392,6 +401,18 @@ case 0x22: type = "ROM+MBC7+BATT"; break; + case 0x55: + type = "GameGenie"; + break; + case 0x56: + type = "GameShark V3.0"; + break; + case 0xfc: + type = "ROM+POCKET CAMERA"; + break; + case 0xfd: + type = "ROM+BANDAI TAMA5"; + break; case 0xfe: type = "ROM+HuC-3"; break; @@ -533,7 +554,7 @@ BOOL RomInfoGBA::OnInitDialog() { CDialog::OnInitDialog(); - + char buffer[13]; strncpy(buffer, (const char *)&rom[0xa0], 12); @@ -554,6 +575,9 @@ GetDlgItem(IDC_ROM_UNIT_CODE)->SetWindowText(buffer); sprintf(buffer, "%02x", rom[0xb4]); + if( rom[0xb4] & 0x80 ) { + strcat(buffer, " (DACS)"); + } GetDlgItem(IDC_ROM_DEVICE_TYPE)->SetWindowText(buffer); sprintf(buffer, "%02x", rom[0xbc]); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/TileView.cpp ./src/win32/TileView.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/TileView.cpp 2004-05-13 23:16:23 +0900 +++ ./src/win32/TileView.cpp 2006-06-07 06:04:21 +0900 @@ -265,38 +265,41 @@ void TileView::OnSave() { - CString captureBuffer; + if(rom != NULL) + { + CString captureBuffer; + + if(theApp.captureFormat == 0) + captureBuffer = "tiles.png"; + else + captureBuffer = "tiles.bmp"; + + LPCTSTR exts[] = {".png", ".bmp" }; + + CString filter = theApp.winLoadFilter(IDS_FILTER_PNG); + CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); + + FileDlg dlg(this, + captureBuffer, + filter, + theApp.captureFormat ? 2 : 1, + theApp.captureFormat ? "BMP" : "PNG", + exts, + "", + title, + true); - if(theApp.captureFormat == 0) - captureBuffer = "tiles.png"; - else - captureBuffer = "tiles.bmp"; - - LPCTSTR exts[] = {".png", ".bmp" }; - - CString filter = theApp.winLoadFilter(IDS_FILTER_PNG); - CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME); - - FileDlg dlg(this, - captureBuffer, - filter, - theApp.captureFormat ? 2 : 1, - theApp.captureFormat ? "BMP" : "PNG", - exts, - "", - title, - true); - - if(dlg.DoModal() == IDCANCEL) { - return; - } + if(dlg.DoModal() == IDCANCEL) { + return; + } - captureBuffer = dlg.GetPathName(); + captureBuffer = dlg.GetPathName(); - if(dlg.getFilterIndex() == 2) - saveBMP(captureBuffer); - else - savePNG(captureBuffer); + if(dlg.getFilterIndex() == 2) + saveBMP(captureBuffer); + else + savePNG(captureBuffer); + } } void TileView::renderTile256(int tile, int x, int y, u8 *charBase, u16 *palette) @@ -526,8 +529,8 @@ u8 *colors = (u8 *)lParam; zoom.setColors(colors); - int x = (wParam & 0xFFFF)/8; - int y = ((wParam >> 16) & 0xFFFF)/8; + int x = (int)((wParam & 0xFFFF) / 8); + int y = (int)(((wParam >> 16) & 0xFFFF) / 8); u32 address = 0x6000000 + 0x4000 * charBase; int tile = 32 * y + x; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/VBA.clw ./src/win32/VBA.clw --- ../VisualBoyAdvance-1.7.2/src/win32/VBA.clw 2004-01-25 22:38:58 +0900 +++ ./src/win32/VBA.clw 2004-12-19 08:11:08 +0900 @@ -2,13 +2,13 @@ [General Info] Version=1 -LastClass=Hyperlink +LastClass=MainWnd LastTemplate=CDialog NewFileInclude1=#include "stdafx.h" NewFileInclude2=#include "vba.h" LastPage=0 -ClassCount=57 +ClassCount=58 Class1=AboutDialog Class2=Associate Class3=ColorButton @@ -39,48 +39,48 @@ Class28=VideoMode Class29=VideoDriverSelect -ResourceCount=44 -Resource1=IDD_MAX_SCALE -Resource2=IDD_GDB_WAITING -Resource3=IDD_GB_CHEAT_LIST -Resource4=IDD_CONFIG -Resource5=IDD_ADD_CHEAT_DLG -Resource6=IDD_GB_OAM_VIEW -Resource7=IDD_GB_ROM_INFO -Resource8=IDD_OPENDLG -Resource9=IDD_MAP_VIEW -Resource10=IDD_ABOUT -Resource11=IDD_CHEAT_LIST -Resource12=IDD_OAM_VIEW -Resource13=IDD_CODE_SELECT -Resource14=IDD_CHEATS -Resource15=IDD_GBA_ROM_INFO -Resource16=IDD_IO_VIEWER -Resource17=IDD_MEM_VIEWER -Resource18=IDD_ADDR_SIZE -Resource19=IDR_MENU -Resource20=IDD_PALETTE_VIEW -Resource21=IDD_ASSOCIATIONS -Resource22=IDD_GB_COLORS -Resource23=IDD_ADD_CHEAT -Resource24=IDD_DISASSEMBLE -Resource25=IDD_MODES -Resource26=IDD_GDB_PORT -Resource27=IDD_LANG_SELECT -Resource28=IDD_LOGGING -Resource29=IDD_DRIVERS -Resource30=IDD_EXPORT_SPS -Resource31=IDD_THROTTLE -Resource32=IDD_MODE_CONFIRM -Resource33=IDD_GB_DISASSEMBLE -Resource34=IDD_GB_PALETTE_VIEW -Resource35=IDD_REWIND_INTERVAL -Resource36=IDD_GB_TILE_VIEWER -Resource37=IDD_ACCEL_EDITOR -Resource38=IDD_GB_MAP_VIEW -Resource39=IDD_BUG_REPORT -Resource40=IDD_MOTION_CONFIG -Resource41=IDD_TILE_VIEWER +ResourceCount=45 +Resource1=IDD_LOGGING +Resource2=IDD_MOTION_CONFIG +Resource3=IDD_OPENDLG +Resource4=IDD_IO_VIEWER +Resource5=IDR_MENU +Resource6=IDD_TILE_VIEWER +Resource7=IDD_BUG_REPORT +Resource8=IDD_DRIVERS +Resource9=IDD_GB_CHEAT_LIST +Resource10=IDD_MODES +Resource11=IDD_MODE_CONFIRM +Resource12=IDD_ASSOCIATIONS +Resource13=IDD_ABOUT +Resource14=IDD_GB_TILE_VIEWER +Resource15=IDD_GAME_OVERRIDES +Resource16=IDD_EXPORT_SPS +Resource17=IDD_CONFIG +Resource18=IDD_MAP_VIEW +Resource19=IDD_GB_OAM_VIEW +Resource20=IDD_ADD_CHEAT +Resource21=IDD_REWIND_INTERVAL +Resource22=IDD_GBA_ROM_INFO +Resource23=IDD_GB_MAP_VIEW +Resource24=IDD_ADD_CHEAT_DLG +Resource25=IDD_PALETTE_VIEW +Resource26=IDD_GB_PRINTER +Resource27=IDD_DIRECTORIES +Resource28=IDD_LANG_SELECT +Resource29=IDD_MEM_VIEWER +Resource30=IDD_CODE_SELECT +Resource31=IDD_OAM_VIEW +Resource32=IDD_DISASSEMBLE +Resource33=IDD_ACCEL_EDITOR +Resource34=IDD_GDB_PORT +Resource35=IDD_ADDR_SIZE +Resource36=IDD_GB_COLORS +Resource37=IDD_CHEAT_LIST +Resource38=IDD_GDB_WAITING +Resource39=IDD_THROTTLE +Resource40=IDD_CHEATS +Resource41=IDD_GB_ROM_INFO Class30=AddGSACode Class31=GBCheatList Class32=Disassemble @@ -107,11 +107,13 @@ Class53=GDBWaitingDlg Class54=AccelEditor Class55=CKeyboardEdit -Resource42=IDD_DIRECTORIES +Resource42=IDD_GB_DISASSEMBLE Class56=MaxScale -Resource43=IDD_GB_PRINTER +Resource43=IDD_MAX_SCALE Class57=BugReport -Resource44=IDR_ACCELERATOR +Resource44=IDD_GB_PALETTE_VIEW +Class58=GameOverrides +Resource45=IDR_ACCELERATOR [CLS:AboutDialog] Type=0 @@ -239,7 +241,7 @@ BaseClass=CWnd HeaderFile=MainWnd.h ImplementationFile=MainWnd.cpp -LastObject=ID_CHEATS_AUTOMATICSAVELOADCHEATS +LastObject=ID_HELP_GNUPUBLICLICENSE Filter=W VirtualFilter=WC @@ -311,7 +313,7 @@ Control5=IDC_URL,static,1342308353 Control6=IDC_STATIC,static,1342308353 Control7=IDC_STATIC,static,1342308353 -Control8=IDC_VERSION,static,1342308353 +Control8=IDC_VERSION,static,1342308481 [DLG:IDD_ASSOCIATIONS] Type=1 @@ -527,7 +529,7 @@ Control3=ID_CANCEL,button,1342242816 Control4=IDC_STATIC,static,1342308352 Control5=IDC_STATIC,static,1342308352 -Control6=IDC_LANG_NAME,static,1342308352 +Control6=IDC_LANG_NAME,static,1342308480 [DLG:IDD_MODE_CONFIRM] Type=1 @@ -536,7 +538,7 @@ Control1=ID_OK,button,1342242817 Control2=ID_CANCEL,button,1342242816 Control3=IDC_STATIC,static,1342308353 -Control4=IDC_TIMER,static,1342308353 +Control4=IDC_TIMER,static,1342308481 [DLG:IDD_REWIND_INTERVAL] Type=1 @@ -559,25 +561,25 @@ Control5=IDC_STATIC,static,1342308352 Control6=IDC_STATIC,static,1342308352 Control7=IDC_STATIC,static,1342308352 -Control8=IDC_ROM_TITLE,static,1342308352 -Control9=IDC_ROM_MAKER_CODE,static,1342308352 -Control10=IDC_ROM_UNIT_CODE,static,1342308352 -Control11=IDC_ROM_DEVICE_TYPE,static,1342308352 -Control12=IDC_ROM_VERSION,static,1342308352 -Control13=IDC_ROM_CRC,static,1342308352 +Control8=IDC_ROM_TITLE,static,1342308480 +Control9=IDC_ROM_MAKER_CODE,static,1342308480 +Control10=IDC_ROM_UNIT_CODE,static,1342308480 +Control11=IDC_ROM_DEVICE_TYPE,static,1342308480 +Control12=IDC_ROM_VERSION,static,1342308480 +Control13=IDC_ROM_CRC,static,1342308480 Control14=IDC_STATIC,static,1342308352 -Control15=IDC_ROM_COLOR,static,1342308352 +Control15=IDC_ROM_COLOR,static,1342308480 Control16=IDC_STATIC,static,1342308352 -Control17=IDC_ROM_SIZE,static,1342308352 +Control17=IDC_ROM_SIZE,static,1342308480 Control18=IDC_STATIC,static,1342308352 -Control19=IDC_ROM_RAM_SIZE,static,1342308352 +Control19=IDC_ROM_RAM_SIZE,static,1342308480 Control20=IDC_STATIC,static,1342308352 -Control21=IDC_ROM_DEST_CODE,static,1342308352 +Control21=IDC_ROM_DEST_CODE,static,1342308480 Control22=IDC_STATIC,static,1342308352 -Control23=IDC_ROM_LIC_CODE,static,1342308352 +Control23=IDC_ROM_LIC_CODE,static,1342308480 Control24=IDC_STATIC,static,1342308352 -Control25=IDC_ROM_CHECKSUM,static,1342308352 -Control26=IDC_ROM_MAKER_NAME2,static,1342308352 +Control25=IDC_ROM_CHECKSUM,static,1342308480 +Control26=IDC_ROM_MAKER_NAME2,static,1342308480 Control27=IDC_STATIC,static,1342308352 [DLG:IDD_GBA_ROM_INFO] @@ -592,15 +594,15 @@ Control6=IDC_STATIC,static,1342308352 Control7=IDC_STATIC,static,1342308352 Control8=IDC_STATIC,static,1342308352 -Control9=IDC_ROM_TITLE,static,1342308352 -Control10=IDC_ROM_GAME_CODE,static,1342308352 -Control11=IDC_ROM_MAKER_CODE,static,1342308352 -Control12=IDC_ROM_UNIT_CODE,static,1342308352 -Control13=IDC_ROM_DEVICE_TYPE,static,1342308352 -Control14=IDC_ROM_VERSION,static,1342308352 -Control15=IDC_ROM_CRC,static,1342308352 -Control16=IDC_ROM_MAKER_NAME,static,1342308352 -Control17=IDC_STATIC,static,1342308352 +Control9=IDC_STATIC,static,1342308352 +Control10=IDC_ROM_TITLE,static,1342308480 +Control11=IDC_ROM_GAME_CODE,static,1342308480 +Control12=IDC_ROM_MAKER_CODE,static,1342308480 +Control13=IDC_ROM_UNIT_CODE,static,1342308480 +Control14=IDC_ROM_DEVICE_TYPE,static,1342308480 +Control15=IDC_ROM_VERSION,static,1342308480 +Control16=IDC_ROM_CRC,static,1342308480 +Control17=IDC_ROM_MAKER_NAME,static,1342308480 [DLG:IDD_THROTTLE] Type=1 @@ -696,44 +698,44 @@ Control4=IDC_BG1,button,1342177289 Control5=IDC_BG2,button,1342177289 Control6=IDC_BG3,button,1342177289 -Control7=IDC_STRETCH,button,1342242819 -Control8=IDC_REFRESH,button,1342373888 -Control9=IDC_SAVE,button,1342373888 -Control10=IDC_CLOSE,button,1342242816 -Control11=IDC_MAP_VIEW,VbaBitmapControl,1342373888 -Control12=IDC_MAP_VIEW_ZOOM,VbaZoomControl,1342373888 -Control13=IDC_COLOR,VbaColorControl,1342242816 -Control14=IDC_R,static,1342308352 -Control15=IDC_G,static,1342308352 -Control16=IDC_B,static,1342308352 -Control17=IDC_STATIC,button,1342177287 +Control7=IDC_STRETCH,button,1342373891 +Control8=IDC_AUTO_UPDATE,button,1342373891 +Control9=IDC_REFRESH,button,1342373888 +Control10=IDC_SAVE,button,1342373888 +Control11=IDC_CLOSE,button,1342242816 +Control12=IDC_MAP_VIEW,VbaBitmapControl,1342373888 +Control13=IDC_MAP_VIEW_ZOOM,VbaZoomControl,1342373888 +Control14=IDC_COLOR,VbaColorControl,1342242816 +Control15=IDC_R,static,1342308480 +Control16=IDC_G,static,1342308480 +Control17=IDC_B,static,1342308480 Control18=IDC_STATIC,button,1342177287 -Control19=IDC_AUTO_UPDATE,button,1342242819 -Control20=IDC_XY,static,1342308352 +Control19=IDC_STATIC,button,1342177287 +Control20=IDC_XY,static,1342308480 Control21=IDC_STATIC,static,1342308352 -Control22=IDC_MODE,static,1342308352 +Control22=IDC_MODE,static,1342308480 Control23=IDC_STATIC,static,1342308352 -Control24=IDC_MAPBASE,static,1342308352 +Control24=IDC_MAPBASE,static,1342308480 Control25=IDC_STATIC,static,1342308352 -Control26=IDC_CHARBASE,static,1342308352 +Control26=IDC_CHARBASE,static,1342308480 Control27=IDC_STATIC,static,1342308352 -Control28=IDC_DIM,static,1342308352 +Control28=IDC_DIM,static,1342308480 Control29=IDC_STATIC,static,1342308352 -Control30=IDC_NUMCOLORS,static,1342308352 +Control30=IDC_NUMCOLORS,static,1342308480 Control31=IDC_STATIC,static,1342308352 -Control32=IDC_PRIORITY,static,1342308352 +Control32=IDC_PRIORITY,static,1342308480 Control33=IDC_STATIC,static,1342308352 -Control34=IDC_MOSAIC,static,1342308352 +Control34=IDC_MOSAIC,static,1342308480 Control35=IDC_STATIC,static,1342308352 -Control36=IDC_OVERFLOW,static,1342308352 +Control36=IDC_OVERFLOW,static,1342308480 Control37=IDC_STATIC,static,1342308352 -Control38=IDC_ADDRESS,static,1342308352 +Control38=IDC_ADDRESS,static,1342308480 Control39=IDC_STATIC,static,1342308352 -Control40=IDC_TILE_NUM,static,1342308352 +Control40=IDC_TILE_NUM,static,1342308480 Control41=IDC_STATIC,static,1342308352 -Control42=IDC_FLIP,static,1342308352 +Control42=IDC_FLIP,static,1342308480 Control43=IDC_STATIC,static,1342308352 -Control44=IDC_PALETTE_NUM,static,1342308352 +Control44=IDC_PALETTE_NUM,static,1342308480 [DLG:IDD_PALETTE_VIEW] Type=1 @@ -743,11 +745,11 @@ Control2=IDC_SAVE_OBJ,button,1342242816 Control3=IDC_REFRESH2,button,1342242816 Control4=IDC_CLOSE,button,1342242816 -Control5=IDC_ADDRESS,static,1342308352 -Control6=IDC_R,static,1342308352 -Control7=IDC_G,static,1342308352 -Control8=IDC_B,static,1342308352 -Control9=IDC_VALUE,static,1342308352 +Control5=IDC_ADDRESS,static,1342308480 +Control6=IDC_R,static,1342308480 +Control7=IDC_G,static,1342308480 +Control8=IDC_B,static,1342308480 +Control9=IDC_VALUE,static,1342308480 Control10=IDC_COLOR,VbaColorControl,1342242816 Control11=IDC_PALETTE_VIEW,VbaPaletteViewControl,1342242816 Control12=IDC_PALETTE_VIEW_OBJ,VbaPaletteViewControl,1342242816 @@ -793,18 +795,18 @@ Control7=IDC_OAM_VIEW,VbaBitmapControl,1342373888 Control8=IDC_OAM_VIEW_ZOOM,VbaZoomControl,1342373888 Control9=IDC_COLOR,VbaColorControl,1342242816 -Control10=IDC_POS,static,1342308352 -Control11=IDC_MODE,static,1342308352 -Control12=IDC_COLORS,static,1342308352 -Control13=IDC_PALETTE,static,1342308352 -Control14=IDC_TILE,static,1342308352 -Control15=IDC_PRIO,static,1342308352 -Control16=IDC_SIZE2,static,1342308352 -Control17=IDC_ROT,static,1342308352 -Control18=IDC_FLAGS,static,1342308352 -Control19=IDC_R,static,1342308352 -Control20=IDC_G,static,1342308352 -Control21=IDC_B,static,1342308352 +Control10=IDC_POS,static,1342308480 +Control11=IDC_MODE,static,1342308480 +Control12=IDC_COLORS,static,1342308480 +Control13=IDC_PALETTE,static,1342308480 +Control14=IDC_TILE,static,1342308480 +Control15=IDC_PRIO,static,1342308480 +Control16=IDC_SIZE2,static,1342308480 +Control17=IDC_ROT,static,1342308480 +Control18=IDC_FLAGS,static,1342308480 +Control19=IDC_R,static,1342308480 +Control20=IDC_G,static,1342308480 +Control21=IDC_B,static,1342308480 Control22=IDC_STATIC,static,1342308352 Control23=IDC_STATIC,static,1342308352 Control24=IDC_STATIC,static,1342308352 @@ -856,15 +858,15 @@ Control15=IDC_STATIC,button,1342177287 Control16=IDC_MAP_VIEW_ZOOM,VbaZoomControl,1342373888 Control17=IDC_COLOR,VbaColorControl,1342242816 -Control18=IDC_R,static,1342308352 -Control19=IDC_G,static,1342308352 -Control20=IDC_B,static,1342308352 +Control18=IDC_R,static,1342308480 +Control19=IDC_G,static,1342308480 +Control20=IDC_B,static,1342308480 Control21=IDC_STATIC,static,1342308352 Control22=IDC_AUTO_UPDATE,button,1342242819 Control23=IDC_STATIC,static,1342308352 Control24=IDC_STATIC,static,1342308352 -Control25=IDC_TILE_NUMBER,static,1342308352 -Control26=IDC_ADDRESS,static,1342308352 +Control25=IDC_TILE_NUMBER,static,1342308480 +Control26=IDC_ADDRESS,static,1342308480 [DLG:IDD_DISASSEMBLE] Type=1 @@ -874,12 +876,12 @@ Control2=IDC_ARM,button,1342177289 Control3=IDC_THUMB,button,1342177289 Control4=IDC_ADDRESS,edit,1350762632 -Control5=IDC_GO,button,1342242816 +Control5=IDC_GO,button,1342242817 Control6=IDC_DISASSEMBLE,listbox,1350631683 Control7=IDC_AUTO_UPDATE,button,1342242819 Control8=IDC_REFRESH,button,1342242816 Control9=IDC_NEXT,button,1342242816 -Control10=IDC_CLOSE,button,1342242817 +Control10=IDC_CLOSE,button,1342242816 Control11=IDC_STATIC,static,1342308352 Control12=IDC_STATIC,static,1342308352 Control13=IDC_STATIC,static,1342308352 @@ -888,22 +890,22 @@ Control16=IDC_STATIC,static,1342308352 Control17=IDC_STATIC,static,1342308352 Control18=IDC_STATIC,static,1342308352 -Control19=IDC_R0,static,1342308352 -Control20=IDC_R1,static,1342308352 -Control21=IDC_R2,static,1342308352 -Control22=IDC_R3,static,1342308352 -Control23=IDC_R4,static,1342308352 -Control24=IDC_R5,static,1342308352 -Control25=IDC_R6,static,1342308352 -Control26=IDC_R7,static,1342308352 -Control27=IDC_R8,static,1342308352 -Control28=IDC_R9,static,1342308352 -Control29=IDC_R10,static,1342308352 -Control30=IDC_R11,static,1342308352 -Control31=IDC_R12,static,1342308352 -Control32=IDC_R13,static,1342308352 -Control33=IDC_R14,static,1342308352 -Control34=IDC_R15,static,1342308352 +Control19=IDC_R0,static,1342308480 +Control20=IDC_R1,static,1342308480 +Control21=IDC_R2,static,1342308480 +Control22=IDC_R3,static,1342308480 +Control23=IDC_R4,static,1342308480 +Control24=IDC_R5,static,1342308480 +Control25=IDC_R6,static,1342308480 +Control26=IDC_R7,static,1342308480 +Control27=IDC_R8,static,1342308480 +Control28=IDC_R9,static,1342308480 +Control29=IDC_R10,static,1342308480 +Control30=IDC_R11,static,1342308480 +Control31=IDC_R12,static,1342308480 +Control32=IDC_R13,static,1342308480 +Control33=IDC_R14,static,1342308480 +Control34=IDC_R15,static,1342308480 Control35=IDC_STATIC,static,1342308352 Control36=IDC_STATIC,static,1342308352 Control37=IDC_STATIC,static,1342308352 @@ -912,7 +914,7 @@ Control40=IDC_STATIC,static,1342308352 Control41=IDC_STATIC,static,1342308352 Control42=IDC_STATIC,static,1342308352 -Control43=IDC_R16,static,1342308352 +Control43=IDC_R16,static,1342308480 Control44=IDC_STATIC,static,1342308352 Control45=IDC_N,button,1476460547 Control46=IDC_Z,button,1476460547 @@ -922,7 +924,7 @@ Control50=IDC_I,button,1476460547 Control51=IDC_T,button,1476460547 Control52=IDC_STATIC,static,1342308352 -Control53=IDC_MODE,static,1342308352 +Control53=IDC_MODE,static,1342308480 Control54=IDC_VSCROLL,scrollbar,1342177281 Control55=IDC_GOPC,button,1342242816 @@ -941,7 +943,7 @@ ControlCount=3 Control1=ID_CANCEL,button,1342242816 Control2=IDC_STATIC,static,1342308352 -Control3=IDC_PORT,static,1342308352 +Control3=IDC_PORT,static,1342308480 [DLG:IDD_LOGGING] Type=1 @@ -979,22 +981,22 @@ Class=GBDisassemble ControlCount=27 Control1=IDC_ADDRESS,edit,1350762632 -Control2=IDC_GO,button,1342242816 +Control2=IDC_GO,button,1342242817 Control3=IDC_DISASSEMBLE,listbox,1350631683 Control4=IDC_AUTO_UPDATE,button,1342242819 Control5=IDC_REFRESH,button,1342242816 Control6=IDC_NEXT,button,1342242816 -Control7=IDC_CLOSE,button,1342242817 +Control7=IDC_CLOSE,button,1342242816 Control8=IDC_STATIC,static,1342308352 Control9=IDC_STATIC,static,1342308352 Control10=IDC_STATIC,static,1342308352 Control11=IDC_STATIC,static,1342308352 Control12=IDC_STATIC,static,1342308352 -Control13=IDC_R0,static,1342308352 -Control14=IDC_R1,static,1342308352 -Control15=IDC_R2,static,1342308352 -Control16=IDC_R3,static,1342308352 -Control17=IDC_R6,static,1342308352 +Control13=IDC_R0,static,1342308480 +Control14=IDC_R1,static,1342308480 +Control15=IDC_R2,static,1342308480 +Control16=IDC_R3,static,1342308480 +Control17=IDC_R6,static,1342308480 Control18=IDC_N,button,1476460547 Control19=IDC_Z,button,1476460547 Control20=IDC_C,button,1476460547 @@ -1002,9 +1004,9 @@ Control22=IDC_VSCROLL,scrollbar,1342177281 Control23=IDC_GOPC,button,1342242816 Control24=IDC_STATIC,static,1342308352 -Control25=IDC_R4,static,1342308352 +Control25=IDC_R4,static,1342308480 Control26=IDC_STATIC,static,1342308352 -Control27=IDC_R5,static,1342308352 +Control27=IDC_R5,static,1342308480 [DLG:IDD_GB_OAM_VIEW] Type=1 @@ -1019,15 +1021,15 @@ Control7=IDC_OAM_VIEW,VbaBitmapControl,1342373888 Control8=IDC_OAM_VIEW_ZOOM,VbaZoomControl,1342373888 Control9=IDC_COLOR,VbaColorControl,1342242816 -Control10=IDC_POS,static,1342308352 -Control11=IDC_PALETTE,static,1342308352 -Control12=IDC_TILE,static,1342308352 -Control13=IDC_PRIO,static,1342308352 -Control14=IDC_OAP,static,1342308352 -Control15=IDC_FLAGS,static,1342308352 -Control16=IDC_R,static,1342308352 -Control17=IDC_G,static,1342308352 -Control18=IDC_B,static,1342308352 +Control10=IDC_POS,static,1342308480 +Control11=IDC_PALETTE,static,1342308480 +Control12=IDC_TILE,static,1342308480 +Control13=IDC_PRIO,static,1342308480 +Control14=IDC_OAP,static,1342308480 +Control15=IDC_FLAGS,static,1342308480 +Control16=IDC_R,static,1342308480 +Control17=IDC_G,static,1342308480 +Control18=IDC_B,static,1342308480 Control19=IDC_STATIC,static,1342308352 Control20=IDC_STATIC,static,1342308352 Control21=IDC_STATIC,static,1342308352 @@ -1036,7 +1038,7 @@ Control24=IDC_STATIC,static,1342308352 Control25=IDC_STATIC,static,1342308352 Control26=IDC_AUTO_UPDATE,button,1342242819 -Control27=IDC_BANK,static,1342308352 +Control27=IDC_BANK,static,1342308480 Control28=IDC_STATIC,static,1342308352 [DLG:IDD_GB_TILE_VIEWER] @@ -1056,15 +1058,15 @@ Control11=IDC_STATIC,button,1342177287 Control12=IDC_MAP_VIEW_ZOOM,VbaZoomControl,1342373888 Control13=IDC_COLOR,VbaColorControl,1342242816 -Control14=IDC_R,static,1342308352 -Control15=IDC_G,static,1342308352 -Control16=IDC_B,static,1342308352 +Control14=IDC_R,static,1342308480 +Control15=IDC_G,static,1342308480 +Control16=IDC_B,static,1342308480 Control17=IDC_STATIC,static,1342308352 Control18=IDC_AUTO_UPDATE,button,1342242819 Control19=IDC_STATIC,static,1342308352 Control20=IDC_STATIC,static,1342308352 -Control21=IDC_TILE_NUMBER,static,1342308352 -Control22=IDC_ADDRESS,static,1342308352 +Control21=IDC_TILE_NUMBER,static,1342308480 +Control22=IDC_ADDRESS,static,1342308480 Control23=IDC_PALETTE_SLIDER,msctls_trackbar32,1342373889 [DLG:IDD_GB_MAP_VIEW] @@ -1082,23 +1084,23 @@ Control9=IDC_MAP_VIEW,VbaBitmapControl,1342373888 Control10=IDC_MAP_VIEW_ZOOM,VbaZoomControl,1342373888 Control11=IDC_COLOR,VbaColorControl,1342242816 -Control12=IDC_R,static,1342308352 -Control13=IDC_G,static,1342308352 -Control14=IDC_B,static,1342308352 +Control12=IDC_R,static,1342308480 +Control13=IDC_G,static,1342308480 +Control14=IDC_B,static,1342308480 Control15=IDC_STATIC,button,1342177287 Control16=IDC_STATIC,button,1342177287 Control17=IDC_AUTO_UPDATE,button,1342242819 -Control18=IDC_XY,static,1342308352 +Control18=IDC_XY,static,1342308480 Control19=IDC_STATIC,static,1342308352 -Control20=IDC_PRIORITY,static,1342308352 +Control20=IDC_PRIORITY,static,1342308480 Control21=IDC_STATIC,static,1342308352 -Control22=IDC_ADDRESS,static,1342308352 +Control22=IDC_ADDRESS,static,1342308480 Control23=IDC_STATIC,static,1342308352 -Control24=IDC_TILE_NUM,static,1342308352 +Control24=IDC_TILE_NUM,static,1342308480 Control25=IDC_STATIC,static,1342308352 -Control26=IDC_FLIP,static,1342308352 +Control26=IDC_FLIP,static,1342308480 Control27=IDC_STATIC,static,1342308352 -Control28=IDC_PALETTE_NUM,static,1342308352 +Control28=IDC_PALETTE_NUM,static,1342308480 [DLG:IDD_GB_PALETTE_VIEW] Type=1 @@ -1108,11 +1110,11 @@ Control2=IDC_SAVE_OBJ,button,1342242816 Control3=IDC_REFRESH2,button,1342242816 Control4=IDC_CLOSE,button,1342242816 -Control5=IDC_ADDRESS,static,1342308352 -Control6=IDC_R,static,1342308352 -Control7=IDC_G,static,1342308352 -Control8=IDC_B,static,1342308352 -Control9=IDC_VALUE,static,1342308352 +Control5=IDC_ADDRESS,static,1342308480 +Control6=IDC_R,static,1342308480 +Control7=IDC_G,static,1342308480 +Control8=IDC_B,static,1342308480 +Control9=IDC_VALUE,static,1342308480 Control10=IDC_COLOR,VbaColorControl,1342242816 Control11=IDC_PALETTE_VIEW,VbaPaletteViewControl,1342242816 Control12=IDC_PALETTE_VIEW_OBJ,VbaPaletteViewControl,1342242816 @@ -1263,129 +1265,131 @@ Command104=ID_OPTIONS_EMULATOR_REALTIMECLOCK Command105=ID_OPTIONS_EMULATOR_AUTOHIDEMENU Command106=ID_OPTIONS_EMULATOR_REWINDINTERVAL -Command107=ID_OPTIONS_EMULATOR_SHOWSPEED_NONE -Command108=ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE -Command109=ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED -Command110=ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT -Command111=ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC -Command112=ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM -Command113=ID_OPTIONS_EMULATOR_SAVETYPE_SRAM -Command114=ID_OPTIONS_EMULATOR_SAVETYPE_FLASH -Command115=ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR -Command116=ID_OPTIONS_EMULATOR_SAVETYPE_NONE -Command117=ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K -Command118=ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M -Command119=ID_OPTIONS_EMULATOR_SAVETYPE_ENHANCEDDETECTION -Command120=ID_OPTIONS_EMULATOR_USEBIOSFILE -Command121=ID_OPTIONS_EMULATOR_SKIPBIOS -Command122=ID_OPTIONS_EMULATOR_SELECTBIOSFILE -Command123=ID_OPTIONS_EMULATOR_PNGFORMAT -Command124=ID_OPTIONS_EMULATOR_BMPFORMAT -Command125=ID_OPTIONS_SOUND_OFF -Command126=ID_OPTIONS_SOUND_MUTE -Command127=ID_OPTIONS_SOUND_ON -Command128=ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION -Command129=ID_OPTIONS_SOUND_ECHO -Command130=ID_OPTIONS_SOUND_LOWPASSFILTER -Command131=ID_OPTIONS_SOUND_REVERSESTEREO -Command132=ID_OPTIONS_SOUND_CHANNEL1 -Command133=ID_OPTIONS_SOUND_CHANNEL2 -Command134=ID_OPTIONS_SOUND_CHANNEL3 -Command135=ID_OPTIONS_SOUND_CHANNEL4 -Command136=ID_OPTIONS_SOUND_DIRECTSOUNDA -Command137=ID_OPTIONS_SOUND_DIRECTSOUNDB -Command138=ID_OPTIONS_SOUND_11KHZ -Command139=ID_OPTIONS_SOUND_22KHZ -Command140=ID_OPTIONS_SOUND_44KHZ -Command141=ID_OPTIONS_SOUND_VOLUME_25X -Command142=ID_OPTIONS_SOUND_VOLUME_5X -Command143=ID_OPTIONS_SOUND_VOLUME_1X -Command144=ID_OPTIONS_SOUND_VOLUME_2X -Command145=ID_OPTIONS_SOUND_VOLUME_3X -Command146=ID_OPTIONS_SOUND_VOLUME_4X -Command147=ID_OPTIONS_GAMEBOY_BORDER -Command148=ID_OPTIONS_GAMEBOY_PRINTER -Command149=ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC -Command150=ID_OPTIONS_GAMEBOY_AUTOMATIC -Command151=ID_OPTIONS_GAMEBOY_GBA -Command152=ID_OPTIONS_GAMEBOY_CGB -Command153=ID_OPTIONS_GAMEBOY_SGB -Command154=ID_OPTIONS_GAMEBOY_SGB2 -Command155=ID_OPTIONS_GAMEBOY_GB -Command156=ID_OPTIONS_GAMEBOY_REALCOLORS -Command157=ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS -Command158=ID_OPTIONS_GAMEBOY_COLORS -Command159=ID_OPTIONS_PRIORITY_HIGHEST -Command160=ID_OPTIONS_PRIORITY_ABOVENORMAL -Command161=ID_OPTIONS_PRIORITY_NORMAL -Command162=ID_OPTIONS_PRIORITY_BELOWNORMAL -Command163=ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE -Command164=ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR -Command165=ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART -Command166=ID_OPTIONS_FILTER_NORMAL -Command167=ID_OPTIONS_FILTER_TVMODE -Command168=ID_OPTIONS_FILTER_2XSAI -Command169=ID_OPTIONS_FILTER_SUPER2XSAI -Command170=ID_OPTIONS_FILTER_SUPEREAGLE -Command171=ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL -Command172=ID_OPTIONS_FILTER16BIT_MOTIONBLUREXPERIMENTAL -Command173=ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X -Command174=ID_OPTIONS_FILTER16BIT_SIMPLE2X -Command175=ID_OPTIONS_FILTER_BILINEAR -Command176=ID_OPTIONS_FILTER_BILINEARPLUS -Command177=ID_OPTIONS_FILTER_SCANLINES -Command178=ID_OPTIONS_FILTER_HQ2X -Command179=ID_OPTIONS_FILTER_LQ2X -Command180=ID_OPTIONS_FILTER_DISABLEMMX -Command181=ID_OPTIONS_JOYPAD_CONFIGURE_1 -Command182=ID_OPTIONS_JOYPAD_CONFIGURE_2 -Command183=ID_OPTIONS_JOYPAD_CONFIGURE_3 -Command184=ID_OPTIONS_JOYPAD_CONFIGURE_4 -Command185=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1 -Command186=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_2 -Command187=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_3 -Command188=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4 -Command189=ID_OPTIONS_JOYPAD_MOTIONCONFIGURE -Command190=ID_OPTIONS_JOYPAD_AUTOFIRE_A -Command191=ID_OPTIONS_JOYPAD_AUTOFIRE_B -Command192=ID_OPTIONS_JOYPAD_AUTOFIRE_L -Command193=ID_OPTIONS_JOYPAD_AUTOFIRE_R -Command194=ID_OPTIONS_LANGUAGE_SYSTEM -Command195=ID_OPTIONS_LANGUAGE_ENGLISH -Command196=ID_OPTIONS_LANGUAGE_OTHER -Command197=ID_CHEATS_SEARCHFORCHEATS -Command198=ID_CHEATS_CHEATLIST -Command199=ID_CHEATS_AUTOMATICSAVELOADCHEATS -Command200=ID_CHEATS_DISABLECHEATS -Command201=ID_CHEATS_LOADCHEATLIST -Command202=ID_CHEATS_SAVECHEATLIST -Command203=ID_TOOLS_DISASSEMBLE -Command204=ID_TOOLS_LOGGING -Command205=ID_TOOLS_IOVIEWER -Command206=ID_TOOLS_MAPVIEW -Command207=ID_TOOLS_MEMORYVIEWER -Command208=ID_TOOLS_OAMVIEWER -Command209=ID_TOOLS_PALETTEVIEW -Command210=ID_TOOLS_TILEVIEWER -Command211=ID_DEBUG_NEXTFRAME -Command212=ID_TOOLS_DEBUG_GDB -Command213=ID_TOOLS_DEBUG_LOADANDWAIT -Command214=ID_TOOLS_DEBUG_BREAK -Command215=ID_TOOLS_DEBUG_DISCONNECT -Command216=ID_OPTIONS_SOUND_STARTRECORDING -Command217=ID_OPTIONS_SOUND_STOPRECORDING -Command218=ID_TOOLS_RECORD_STARTAVIRECORDING -Command219=ID_TOOLS_RECORD_STOPAVIRECORDING -Command220=ID_TOOLS_RECORD_STARTMOVIERECORDING -Command221=ID_TOOLS_RECORD_STOPMOVIERECORDING -Command222=ID_TOOLS_PLAY_STARTMOVIEPLAYING -Command223=ID_TOOLS_PLAY_STOPMOVIEPLAYING -Command224=ID_TOOLS_REWIND -Command225=ID_TOOLS_CUSTOMIZE -Command226=ID_HELP_BUGREPORT -Command227=ID_HELP_FAQ -Command228=ID_HELP_ABOUT -CommandCount=228 +Command107=ID_OPTIONS_EMULATOR_GAMEOVERRIDES +Command108=ID_OPTIONS_EMULATOR_SHOWSPEED_NONE +Command109=ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE +Command110=ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED +Command111=ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT +Command112=ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC +Command113=ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM +Command114=ID_OPTIONS_EMULATOR_SAVETYPE_SRAM +Command115=ID_OPTIONS_EMULATOR_SAVETYPE_FLASH +Command116=ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR +Command117=ID_OPTIONS_EMULATOR_SAVETYPE_NONE +Command118=ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K +Command119=ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M +Command120=ID_OPTIONS_EMULATOR_SAVETYPE_ENHANCEDDETECTION +Command121=ID_OPTIONS_EMULATOR_USEBIOSFILE +Command122=ID_OPTIONS_EMULATOR_SKIPBIOS +Command123=ID_OPTIONS_EMULATOR_SELECTBIOSFILE +Command124=ID_OPTIONS_EMULATOR_PNGFORMAT +Command125=ID_OPTIONS_EMULATOR_BMPFORMAT +Command126=ID_OPTIONS_SOUND_OFF +Command127=ID_OPTIONS_SOUND_MUTE +Command128=ID_OPTIONS_SOUND_ON +Command129=ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION +Command130=ID_OPTIONS_SOUND_ECHO +Command131=ID_OPTIONS_SOUND_LOWPASSFILTER +Command132=ID_OPTIONS_SOUND_REVERSESTEREO +Command133=ID_OPTIONS_SOUND_CHANNEL1 +Command134=ID_OPTIONS_SOUND_CHANNEL2 +Command135=ID_OPTIONS_SOUND_CHANNEL3 +Command136=ID_OPTIONS_SOUND_CHANNEL4 +Command137=ID_OPTIONS_SOUND_DIRECTSOUNDA +Command138=ID_OPTIONS_SOUND_DIRECTSOUNDB +Command139=ID_OPTIONS_SOUND_11KHZ +Command140=ID_OPTIONS_SOUND_22KHZ +Command141=ID_OPTIONS_SOUND_44KHZ +Command142=ID_OPTIONS_SOUND_VOLUME_25X +Command143=ID_OPTIONS_SOUND_VOLUME_5X +Command144=ID_OPTIONS_SOUND_VOLUME_1X +Command145=ID_OPTIONS_SOUND_VOLUME_2X +Command146=ID_OPTIONS_SOUND_VOLUME_3X +Command147=ID_OPTIONS_SOUND_VOLUME_4X +Command148=ID_OPTIONS_GAMEBOY_BORDER +Command149=ID_OPTIONS_GAMEBOY_PRINTER +Command150=ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC +Command151=ID_OPTIONS_GAMEBOY_AUTOMATIC +Command152=ID_OPTIONS_GAMEBOY_GBA +Command153=ID_OPTIONS_GAMEBOY_CGB +Command154=ID_OPTIONS_GAMEBOY_SGB +Command155=ID_OPTIONS_GAMEBOY_SGB2 +Command156=ID_OPTIONS_GAMEBOY_GB +Command157=ID_OPTIONS_GAMEBOY_REALCOLORS +Command158=ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS +Command159=ID_OPTIONS_GAMEBOY_COLORS +Command160=ID_OPTIONS_PRIORITY_HIGHEST +Command161=ID_OPTIONS_PRIORITY_ABOVENORMAL +Command162=ID_OPTIONS_PRIORITY_NORMAL +Command163=ID_OPTIONS_PRIORITY_BELOWNORMAL +Command164=ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE +Command165=ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR +Command166=ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART +Command167=ID_OPTIONS_FILTER_NORMAL +Command168=ID_OPTIONS_FILTER_TVMODE +Command169=ID_OPTIONS_FILTER_2XSAI +Command170=ID_OPTIONS_FILTER_SUPER2XSAI +Command171=ID_OPTIONS_FILTER_SUPEREAGLE +Command172=ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL +Command173=ID_OPTIONS_FILTER16BIT_MOTIONBLUREXPERIMENTAL +Command174=ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X +Command175=ID_OPTIONS_FILTER16BIT_SIMPLE2X +Command176=ID_OPTIONS_FILTER_BILINEAR +Command177=ID_OPTIONS_FILTER_BILINEARPLUS +Command178=ID_OPTIONS_FILTER_SCANLINES +Command179=ID_OPTIONS_FILTER_HQ2X +Command180=ID_OPTIONS_FILTER_LQ2X +Command181=ID_OPTIONS_FILTER_DISABLEMMX +Command182=ID_OPTIONS_JOYPAD_CONFIGURE_1 +Command183=ID_OPTIONS_JOYPAD_CONFIGURE_2 +Command184=ID_OPTIONS_JOYPAD_CONFIGURE_3 +Command185=ID_OPTIONS_JOYPAD_CONFIGURE_4 +Command186=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1 +Command187=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_2 +Command188=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_3 +Command189=ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4 +Command190=ID_OPTIONS_JOYPAD_MOTIONCONFIGURE +Command191=ID_OPTIONS_JOYPAD_AUTOFIRE_A +Command192=ID_OPTIONS_JOYPAD_AUTOFIRE_B +Command193=ID_OPTIONS_JOYPAD_AUTOFIRE_L +Command194=ID_OPTIONS_JOYPAD_AUTOFIRE_R +Command195=ID_OPTIONS_LANGUAGE_SYSTEM +Command196=ID_OPTIONS_LANGUAGE_ENGLISH +Command197=ID_OPTIONS_LANGUAGE_OTHER +Command198=ID_CHEATS_SEARCHFORCHEATS +Command199=ID_CHEATS_CHEATLIST +Command200=ID_CHEATS_AUTOMATICSAVELOADCHEATS +Command201=ID_CHEATS_DISABLECHEATS +Command202=ID_CHEATS_LOADCHEATLIST +Command203=ID_CHEATS_SAVECHEATLIST +Command204=ID_TOOLS_DISASSEMBLE +Command205=ID_TOOLS_LOGGING +Command206=ID_TOOLS_IOVIEWER +Command207=ID_TOOLS_MAPVIEW +Command208=ID_TOOLS_MEMORYVIEWER +Command209=ID_TOOLS_OAMVIEWER +Command210=ID_TOOLS_PALETTEVIEW +Command211=ID_TOOLS_TILEVIEWER +Command212=ID_DEBUG_NEXTFRAME +Command213=ID_TOOLS_DEBUG_GDB +Command214=ID_TOOLS_DEBUG_LOADANDWAIT +Command215=ID_TOOLS_DEBUG_BREAK +Command216=ID_TOOLS_DEBUG_DISCONNECT +Command217=ID_OPTIONS_SOUND_STARTRECORDING +Command218=ID_OPTIONS_SOUND_STOPRECORDING +Command219=ID_TOOLS_RECORD_STARTAVIRECORDING +Command220=ID_TOOLS_RECORD_STOPAVIRECORDING +Command221=ID_TOOLS_RECORD_STARTMOVIERECORDING +Command222=ID_TOOLS_RECORD_STOPMOVIERECORDING +Command223=ID_TOOLS_PLAY_STARTMOVIEPLAYING +Command224=ID_TOOLS_PLAY_STOPMOVIEPLAYING +Command225=ID_TOOLS_REWIND +Command226=ID_TOOLS_CUSTOMIZE +Command227=ID_HELP_BUGREPORT +Command228=ID_HELP_FAQ +Command229=ID_HELP_GNUPUBLICLICENSE +Command230=ID_HELP_ABOUT +CommandCount=230 [ACL:IDR_ACCELERATOR] Type=1 @@ -1713,3 +1717,28 @@ VirtualFilter=dWC LastObject=BugReport +[DLG:IDD_GAME_OVERRIDES] +Type=1 +Class=GameOverrides +ControlCount=11 +Control1=IDC_RTC,combobox,1344339971 +Control2=IDC_SAVE_TYPE,combobox,1344339971 +Control3=IDC_FLASH_SIZE,combobox,1344339971 +Control4=IDOK,button,1342242817 +Control5=IDC_DEFAULTS,button,1342242816 +Control6=IDCANCEL,button,1342242816 +Control7=IDC_STATIC,static,1342308352 +Control8=IDC_NAME,edit,1484849280 +Control9=IDC_STATIC,static,1342308352 +Control10=IDC_STATIC,static,1342308352 +Control11=IDC_STATIC,static,1342308352 + +[CLS:GameOverrides] +Type=0 +HeaderFile=GameOverrides.h +ImplementationFile=GameOverrides.cpp +BaseClass=CDialog +Filter=D +LastObject=IDOK +VirtualFilter=dWC + diff -urN ../VisualBoyAdvance-1.7.2/src/win32/VBA.cpp ./src/win32/VBA.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/VBA.cpp 2004-05-13 23:16:07 +0900 +++ ./src/win32/VBA.cpp 2006-08-06 21:40:35 +0900 @@ -1,6 +1,6 @@ // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -19,13 +19,13 @@ // VBA.cpp : Defines the class behaviors for the application. // #include "stdafx.h" -#include #include "AVIWrite.h" #include "LangSelect.h" #include "MainWnd.h" #include "Reg.h" #include "resource.h" +#include "resource2.h" #include "skin.h" #include "WavWriter.h" #include "WinResUtil.h" @@ -130,6 +130,23 @@ extern "C" bool cpu_mmx; #endif +namespace Sm60FPS +{ + float K_fCpuSpeed = 98.0f; + float K_fTargetFps = 60.0f * K_fCpuSpeed / 100; + float K_fDT = 1000.0f / K_fTargetFps; + + u32 dwTimeElapse; + u32 dwTime0; + u32 dwTime1; + u32 nFrameCnt; + float fWantFPS; + float fCurFPS; + bool bLastSkip; + int nCurSpeed; + int bSaveMoreCPU; +}; + void directXMessage(const char *msg) { systemMessage(IDS_DIRECTX_7_REQUIRED, @@ -163,9 +180,11 @@ filterType = 0; filterWidth = 0; filterHeight = 0; + fsAdapter = 0; fsWidth = 0; fsHeight = 0; fsColorDepth = 0; + fsFrequency = 0; fsForceChange = false; surfaceSizeX = 0; surfaceSizeY = 0; @@ -183,7 +202,7 @@ display = NULL; menu = NULL; popup = NULL; - cartridgeType = 0; + cartridgeType = IMAGE_GBA; soundInitialized = false; useBiosFile = false; skipBiosFile = false; @@ -197,6 +216,7 @@ winGbBorderOn = 0; winFlashSize = 0x10000; winRtcEnable = false; + winGenericflashcardEnable = false; winSaveType = 0; rewindMemory = NULL; rewindPos = 0; @@ -246,6 +266,7 @@ winPauseNextFrame = false; soundRecording = false; soundRecorder = NULL; + dsoundDisableHardwareAcceleration = true; sound = NULL; aviRecording = false; aviRecorder = NULL; @@ -287,6 +308,15 @@ { InterframeCleanup(); + char winBuffer[2048]; + + GetModuleFileName(NULL, winBuffer, 2048); + char *p = strrchr(winBuffer, '\\'); + if(p) + *p = 0; + + regInit(winBuffer); + saveSettings(); if(moviePlaying) { @@ -350,7 +380,6 @@ // The one and only VBA object VBA theApp; -#include ///////////////////////////////////////////////////////////////////////////// // VBA initialization @@ -407,17 +436,13 @@ BOOL VBA::InitInstance() { - AfxEnableControlContainer(); - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - +#if _MSC_VER < 1400 #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif +#endif SetRegistryKey(_T("VBA")); @@ -504,6 +529,7 @@ return TRUE; } + void VBA::adjustDestRect() { POINT point; @@ -570,6 +596,7 @@ } } + void VBA::updateIFB() { if(systemColorDepth == 16) { @@ -810,6 +837,9 @@ } } + if (Sm60FPS_CanSkipFrame()) + return; + if(theApp.aviRecording && !theApp.painting) { int width = 240; int height = 160; @@ -855,16 +885,15 @@ delete bmp; } - if(theApp.ifbFunction) { - if(systemColorDepth == 16) - theApp.ifbFunction(pix+theApp.filterWidth*2+4, theApp.filterWidth*2+4, - theApp.filterWidth, theApp.filterHeight); - else - theApp.ifbFunction(pix+theApp.filterWidth*4+4, theApp.filterWidth*4+4, - theApp.filterWidth, theApp.filterHeight); + if( theApp.ifbFunction ) { + theApp.ifbFunction( pix + (theApp.filterWidth * (systemColorDepth>>3)) + 4, + (theApp.filterWidth * (systemColorDepth>>3)) + 4, + theApp.filterWidth, theApp.filterHeight ); } theApp.display->render(); + + Sm60FPS_Sleep(); } void systemScreenCapture(int captureNumber) @@ -875,7 +904,7 @@ u32 systemGetClock() { - return timeGetTime(); + return GetTickCount(); } void systemMessage(int number, const char *defaultMsg, ...) @@ -932,34 +961,18 @@ void system10Frames(int rate) { u32 time = systemGetClock(); - if(!theApp.wasPaused && theApp.autoFrameSkip && !theApp.throttle) { - u32 diff = time - theApp.autoFrameSkipLastTime; - int speed = 100; - if(diff) - speed = (1000000/rate)/diff; - - if(speed >= 98) { - theApp.frameskipadjust++; + if (theApp.autoFrameSkip) + { + u32 diff = time - theApp.autoFrameSkipLastTime; + Sm60FPS::nCurSpeed = 100; - if(theApp.frameskipadjust >= 3) { - theApp.frameskipadjust=0; - if(systemFrameSkip > 0) - systemFrameSkip--; - } - } else { - if(speed < 80) - theApp.frameskipadjust -= (90 - speed)/5; - else if(systemFrameSkip < 9) - theApp.frameskipadjust--; - - if(theApp.frameskipadjust <= -2) { - theApp.frameskipadjust += 2; - if(systemFrameSkip < 9) - systemFrameSkip++; - } - } + if (diff) + Sm60FPS::nCurSpeed = (1000000/rate)/diff; } + + + if(!theApp.wasPaused && theApp.throttle) { if(!speedup) { u32 diff = time - theApp.throttleLastTime; @@ -1074,7 +1087,7 @@ void systemGbBorderOn() { - if(emulating && theApp.cartridgeType == 1 && gbBorderOn) { + if(emulating && theApp.cartridgeType == IMAGE_GB && gbBorderOn) { theApp.updateWindowSize(theApp.videoOption); } } @@ -1170,9 +1183,9 @@ winSetLanguageOption(languageOption, true); - frameSkip = regQueryDwordValue("frameSkip", 2); + frameSkip = regQueryDwordValue("frameSkip", 0); if(frameSkip < 0 || frameSkip > 9) - frameSkip = 2; + frameSkip = 0; gbFrameSkip = regQueryDwordValue("gbFrameSkip", 0); if(gbFrameSkip < 0 || gbFrameSkip > 9) @@ -1184,8 +1197,7 @@ synchronize = regQueryDwordValue("synchronize", 1) ? true : false; fullScreenStretch = regQueryDwordValue("stretch", 0) ? true : false; - videoOption = regQueryDwordValue("video", 0); - + videoOption = regQueryDwordValue("video", 1); if(videoOption < 0 || videoOption > VIDEO_OTHER) videoOption = 0; @@ -1202,9 +1214,11 @@ else pVideoDriverGUID = &videoDriverGUID; + fsAdapter = regQueryDwordValue("fsAdapter", 0); fsWidth = regQueryDwordValue("fsWidth", 0); fsHeight = regQueryDwordValue("fsHeight", 0); fsColorDepth = regQueryDwordValue("fsColorDepth", 0); + fsFrequency = regQueryDwordValue("fsFrequency", 0); if(videoOption == VIDEO_OTHER) { if(fsWidth < 0 || fsWidth > 4095 || fsHeight < 0 || fsHeight > 4095) @@ -1214,7 +1228,6 @@ } renderMethod = (DISPLAY_TYPE)regQueryDwordValue("renderMethod", DIRECT_DRAW); - if(renderMethod < GDI || renderMethod > OPENGL) renderMethod = DIRECT_DRAW; @@ -1242,7 +1255,7 @@ soundOffFlag = (regQueryDwordValue("soundOff", 0)) ? true : false; - soundQuality = regQueryDwordValue("soundQuality", 2); + soundQuality = regQueryDwordValue("soundQuality", 1); soundEcho = regQueryDwordValue("soundEcho", 0) ? true : false; @@ -1255,15 +1268,17 @@ soundVolume = 0; ddrawEmulationOnly = regQueryDwordValue("ddrawEmulationOnly", false) ? true : false; - ddrawUseVideoMemory = regQueryDwordValue("ddrawUseVideoMemory", false) ? true : false; - tripleBuffering = regQueryDwordValue("tripleBuffering", true) ? true : false; + ddrawUseVideoMemory = regQueryDwordValue("ddrawUseVideoMemory", true) ? true : false; + tripleBuffering = regQueryDwordValue("tripleBuffering", false) ? true : false; - d3dFilter = regQueryDwordValue("d3dFilter", 0); + d3dFilter = regQueryDwordValue("d3dFilter", 1); if(d3dFilter < 0 || d3dFilter > 1) - d3dFilter = 0; - glFilter = regQueryDwordValue("glFilter", 0); + d3dFilter = 1; + + glFilter = regQueryDwordValue("glFilter", 1); if(glFilter < 0 || glFilter > 1) - glFilter = 0; + glFilter = 1; + glType = regQueryDwordValue("glType", 0); if(glType < 0 || glType > 1) glType = 0; @@ -1272,7 +1287,7 @@ if(filterType < 0 || filterType > 13) filterType = 0; - disableMMX = regQueryDwordValue("disableMMX", 0) ? true: false; + disableMMX = regQueryDwordValue("disableMMX", false) ? true: false; disableStatusMessage = regQueryDwordValue("disableStatus", 0) ? true : false; @@ -1310,9 +1325,6 @@ if(winSaveType < 0 || winSaveType > 5) winSaveType = 0; - cpuEnhancedDetection = regQueryDwordValue("enhancedDetection", 1) ? true : - false; - ifbType = regQueryDwordValue("ifbType", 0); if(ifbType < 0 || ifbType > 2) ifbType = 0; @@ -1320,6 +1332,7 @@ winFlashSize = regQueryDwordValue("flashSize", 0x10000); if(winFlashSize != 0x10000 && winFlashSize != 0x20000) winFlashSize = 0x10000; + flashSize = winFlashSize; agbPrintEnable(regQueryDwordValue("agbPrint", 0) ? true : false); @@ -1407,6 +1420,15 @@ throttle = regQueryDwordValue("throttle", 0); if(throttle < 5 || throttle > 1000) throttle = 0; + + if (autoFrameSkip) + { + throttle = 0; + frameSkip = 0; + systemFrameSkip = 0; + } + + Sm60FPS::bSaveMoreCPU = regQueryDwordValue("saveMoreCPU", 0); } void VBA::updateFrameSkip() @@ -1442,28 +1464,25 @@ value = VIDEO_320x240; fsWidth = 320; fsHeight = 240; - fsColorDepth = 16; + fsColorDepth = 32; break; case ID_OPTIONS_VIDEO_FULLSCREEN640X480: value = VIDEO_640x480; fsWidth = 640; fsHeight = 480; - fsColorDepth = 16; + fsColorDepth = 32; break; case ID_OPTIONS_VIDEO_FULLSCREEN800X600: value = VIDEO_800x600; fsWidth = 800; fsHeight = 600; - fsColorDepth = 16; + fsColorDepth = 32; break; case ID_OPTIONS_VIDEO_FULLSCREEN: value = VIDEO_OTHER; break; } - if(videoOption == value && value != VIDEO_OTHER) - return; - updateWindowSize(value); } @@ -1474,15 +1493,18 @@ HINSTANCE hinstDll; DWORD dwVersion = 0; - hinstDll = AfxLoadLibrary("USER32.DLL"); +#ifdef _AFXDLL + hinstDll = AfxLoadLibrary("user32.dll"); +#else + hinstDll = LoadLibrary( _T("user32.dll") ); +#endif if(hinstDll) { - GETMENUBARINFO func = (GETMENUBARINFO)GetProcAddress(hinstDll, - "GetMenuBarInfo"); + GETMENUBARINFO func = (GETMENUBARINFO)GetProcAddress(hinstDll, "GetMenuBarInfo"); if(func) { MENUBARINFO info; - info.cbSize = sizeof(info); + info.cbSize = sizeof(MENUBARINFO); func(AfxGetMainWnd()->GetSafeHwnd(), OBJID_MENU, 0, &info); @@ -1499,7 +1521,11 @@ SWP_NOMOVE | SWP_SHOWWINDOW); } } - AfxFreeLibrary(hinstDll); +#ifdef _AFXDLL + AfxFreeLibrary( hinstDll ); +#else + FreeLibrary( hinstDll ); +#endif } } @@ -1561,7 +1587,7 @@ videoOption = value; - if(cartridgeType == 1) { + if(cartridgeType == IMAGE_GB) { if(gbBorderOn) { sizeX = 256; sizeY = 224; @@ -1660,6 +1686,9 @@ updateIFB(); updateFilter(); + if(display) + display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top); + m_pMainWnd->RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); } @@ -1670,26 +1699,37 @@ bool VBA::updateRenderMethod(bool force) { - bool res = updateRenderMethod0(force); - - while(!res && renderMethod > 0) { - if(renderMethod == OPENGL) - renderMethod = DIRECT_3D; - else if(renderMethod == DIRECT_3D) - renderMethod = DIRECT_DRAW; - else if(renderMethod == DIRECT_DRAW) { - if(videoOption > VIDEO_4X) { - videoOption = VIDEO_2X; - force = true; - } else - renderMethod = GDI; - } - - res = updateRenderMethod(force); - } - return res; + Sm60FPS_Init(); + bool res = updateRenderMethod0(force); + + while(!res && renderMethod > 0) { + if( fsAdapter > 0 ) { + fsAdapter = 0; + } else { + if( videoOption > VIDEO_4X ) { + videoOption = VIDEO_1X; + force = true; + } else { + if(renderMethod == OPENGL) { + renderMethod = DIRECT_3D; + } else { + if(renderMethod == DIRECT_3D) { + renderMethod = DIRECT_DRAW; + } else { + if(renderMethod == DIRECT_DRAW) { + renderMethod = GDI; + } + } + } + } + } + res = updateRenderMethod(force); + } + + return res; } + bool VBA::updateRenderMethod0(bool force) { bool initInput = false; @@ -1721,17 +1761,19 @@ if(display == NULL) { switch(renderMethod) { case GDI: - display = newGDIDisplay(); - break; + display = newGDIDisplay(); + break; case DIRECT_DRAW: - display = newDirectDrawDisplay(); - break; + pVideoDriverGUID = NULL; + ZeroMemory( &videoDriverGUID, sizeof( GUID ) ); + display = newDirectDrawDisplay(); + break; case DIRECT_3D: - display = newDirect3DDisplay(); - break; - case OPENGL: - display = newOpenGLDisplay(); - break; + display = newDirect3DDisplay(); + break; + case OPENGL: + display = newOpenGLDisplay(); + break; } if(display->initialize()) { @@ -1762,14 +1804,17 @@ return true; } + void VBA::winCheckFullscreen() { - if(videoOption > VIDEO_4X && tripleBuffering) { - if(display) - display->checkFullScreen(); - } + if(videoOption > VIDEO_4X && tripleBuffering) { + if(display) { + display->checkFullScreen(); + } + } } + void VBA::shutdownDisplay() { if(display != NULL) { @@ -1788,6 +1833,7 @@ void VBA::winUpdateSkin() { +#ifndef NOSKINS skinButtons = 0; if(skin) { delete skin; @@ -1809,6 +1855,7 @@ adjustDestRect(); updateMenuBar(); } +#endif } void VBA::updatePriority() @@ -1896,7 +1943,11 @@ } AfxSetResourceHandle(l); if(languageModule != NULL) - AfxFreeLibrary(languageModule); +#ifdef _AFXDLL + AfxFreeLibrary( languageModule ); +#else + FreeLibrary( languageModule ); +#endif languageModule = l; } else { systemMessage(IDS_FAILED_TO_GET_LOCINFO, @@ -1907,7 +1958,11 @@ break; case 1: if(languageModule != NULL) - AfxFreeLibrary(languageModule); +#ifdef _AFXDLL + AfxFreeLibrary( languageModule ); +#else + FreeLibrary( languageModule ); +#endif languageModule = NULL; AfxSetResourceHandle(AfxGetInstanceHandle()); break; @@ -1925,7 +1980,13 @@ } AfxSetResourceHandle(l); if(languageModule != NULL) - AfxFreeLibrary(languageModule); + { +#ifdef _AFXDLL + AfxFreeLibrary( languageModule ); +#else + FreeLibrary( languageModule ); +#endif + } languageModule = l; } } else { @@ -1954,9 +2015,13 @@ { CString buffer; - buffer.Format("vba_%s.dll", name); + buffer.Format( _T("vba_%s.dll"), name); - HINSTANCE l = AfxLoadLibrary(buffer); +#ifdef _AFXDLL + HINSTANCE l = AfxLoadLibrary( buffer ); +#else + HMODULE l = LoadLibrary( buffer ); +#endif if(l == NULL) { if(strlen(name) == 3) { @@ -1966,7 +2031,11 @@ buffer2[2] = 0; buffer.Format("vba_%s.dll", buffer2); - return AfxLoadLibrary(buffer); +#ifdef _AFXDLL + return AfxLoadLibrary( buffer ); +#else + return LoadLibrary( buffer ); +#endif } } return l; @@ -2065,9 +2134,11 @@ } + regSetDwordValue("fsAdapter", fsAdapter); regSetDwordValue("fsWidth", fsWidth); regSetDwordValue("fsHeight", fsHeight); regSetDwordValue("fsColorDepth", fsColorDepth); + regSetDwordValue("fsFrequency", fsFrequency); regSetDwordValue("renderMethod", renderMethod); @@ -2131,8 +2202,6 @@ regSetDwordValue("saveType", winSaveType); - regSetDwordValue("enhancedDetection", cpuEnhancedDetection); - regSetDwordValue("ifbType", ifbType); regSetDwordValue("flashSize", winFlashSize); @@ -2174,6 +2243,8 @@ regSetDwordValue("cheatsEnabled", cheatsEnabled); regSetDwordValue("fsMaxScale", fsMaxScale); regSetDwordValue("throttle", throttle); + + regSetDwordValue("saveMoreCPU", Sm60FPS::bSaveMoreCPU); } void winSignal(int, int) @@ -2201,3 +2272,73 @@ toolsLog(str); } } + + +void Sm60FPS_Init() +{ + Sm60FPS::dwTimeElapse = 0; + Sm60FPS::fWantFPS = 60.f; + Sm60FPS::fCurFPS = 0.f; + Sm60FPS::nFrameCnt = 0; + Sm60FPS::bLastSkip = false; + Sm60FPS::nCurSpeed = 100; +} + + +bool Sm60FPS_CanSkipFrame() +{ + if( theApp.autoFrameSkip ) { + if( Sm60FPS::nFrameCnt == 0 ) { + Sm60FPS::nFrameCnt = 0; + Sm60FPS::dwTimeElapse = 0; + Sm60FPS::dwTime0 = timeGetTime(); + } else { + if( Sm60FPS::nFrameCnt >= 10 ) { + Sm60FPS::nFrameCnt = 0; + Sm60FPS::dwTimeElapse = 0; + + if( Sm60FPS::nCurSpeed > Sm60FPS::K_fCpuSpeed ) { + Sm60FPS::fWantFPS += 1; + if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps ){ + Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps; + } + } else { + if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed - 5) ) { + Sm60FPS::fWantFPS -= 1; + if( Sm60FPS::fWantFPS < 30.f ) { + Sm60FPS::fWantFPS = 30.f; + } + } + } + } else { // between frame 1-10 + Sm60FPS::dwTime1 = timeGetTime(); + Sm60FPS::dwTimeElapse += (Sm60FPS::dwTime1 - Sm60FPS::dwTime0); + Sm60FPS::dwTime0 = Sm60FPS::dwTime1; + if( !Sm60FPS::bLastSkip && + ( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU) ) { + Sm60FPS::fCurFPS = (float)Sm60FPS::nFrameCnt * 1000 / Sm60FPS::dwTimeElapse; + if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU ) { + Sm60FPS::bLastSkip = true; + Sm60FPS::nFrameCnt++; + return true; + } + } + } + } + Sm60FPS::bLastSkip = false; + Sm60FPS::nFrameCnt++; + } + return false; +} + + +void Sm60FPS_Sleep() +{ + if( theApp.autoFrameSkip ) { + u32 dwTimePass = Sm60FPS::dwTimeElapse + (timeGetTime() - Sm60FPS::dwTime0); + u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * Sm60FPS::K_fDT); + if( dwTimeShould > dwTimePass ) { + Sleep(dwTimeShould - dwTimePass); + } + } +} diff -urN ../VisualBoyAdvance-1.7.2/src/win32/VBA.h ./src/win32/VBA.h --- ../VisualBoyAdvance-1.7.2/src/win32/VBA.h 2004-05-13 22:32:30 +0900 +++ ./src/win32/VBA.h 2006-08-06 21:40:35 +0900 @@ -1,7 +1,7 @@ // -*- C++ -*- // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. // Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team +// Copyright (C) 2005 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 @@ -20,26 +20,23 @@ // VBA.h : main header file for the VBA application // -#if !defined(AFX_VBA_H__57514A10_49F9_4B83_A928_0D8A4A7306A3__INCLUDED_) -#define AFX_VBA_H__57514A10_49F9_4B83_A928_0D8A4A7306A3__INCLUDED_ - -#if _MSC_VER > 1000 #pragma once -#endif // _MSC_VER > 1000 #ifndef __AFXWIN_H__ #error include 'stdafx.h' before including this file for PCH #endif -#include +#include "stdafx.h" +#include "resource.h" +//#include #include "AcceleratorManager.h" -#include "resource.h" // main symbols #include "Display.h" #include "Input.h" #include "IUpdate.h" #include "Sound.h" #include "../System.h" +#include "../Util.h" ///////////////////////////////////////////////////////////////////////////// // VBA: @@ -47,8 +44,14 @@ // enum { - VIDEO_1X, VIDEO_2X, VIDEO_3X, VIDEO_4X, - VIDEO_320x240, VIDEO_640x480, VIDEO_800x600, VIDEO_OTHER + VIDEO_1X, + VIDEO_2X, + VIDEO_3X, + VIDEO_4X, + VIDEO_320x240, + VIDEO_640x480, + VIDEO_800x600, + VIDEO_OTHER }; #define REWIND_SIZE 400000 @@ -74,9 +77,11 @@ int filterType; int filterWidth; int filterHeight; + int fsAdapter; int fsWidth; int fsHeight; int fsColorDepth; + int fsFrequency; bool fsForceChange; int sizeX; int sizeY; @@ -94,7 +99,7 @@ u8 *delta[257*244*4]; bool menuToggle; IDisplay *display; - int cartridgeType; + IMAGE_TYPE cartridgeType; bool soundInitialized; bool useBiosFile; bool skipBiosFile; @@ -110,6 +115,7 @@ int winGbBorderOn; int winFlashSize; bool winRtcEnable; + bool winGenericflashcardEnable; int winSaveType; char *rewindMemory; int rewindPos; @@ -150,7 +156,7 @@ bool disableMMX; int languageOption; CString languageName; - HINSTANCE languageModule; + HMODULE languageModule; int renderedFrames; Input *input; int joypadDefault; @@ -160,6 +166,7 @@ bool soundRecording; WavWriter *soundRecorder; CString soundRecordName; + bool dsoundDisableHardwareAcceleration; ISound *sound; bool aviRecording; AVIWrite *aviRecorder; @@ -225,10 +232,10 @@ void saveSettings(); void movieReadNext(); bool initInput(); - HINSTANCE winLoadLanguage(const char *name); + HMODULE winLoadLanguage(const char *name); void winSetLanguageOption(int option, bool force); - bool detectMMX(); #ifdef MMX + bool detectMMX(); #endif void updatePriority(); void winUpdateSkin(); @@ -252,14 +259,8 @@ }; extern VBA theApp; + extern int emulating; #ifdef MMX extern "C" bool cpu_mmx; -#endif - - ///////////////////////////////////////////////////////////////////////////// - - //{{AFX_INSERT_LOCATION}} - // Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_VBA_H__57514A10_49F9_4B83_A928_0D8A4A7306A3__INCLUDED_) +#endif \ No newline at end of file diff -urN ../VisualBoyAdvance-1.7.2/src/win32/VideoMode.cpp ./src/win32/VideoMode.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/VideoMode.cpp 2004-05-13 23:15:52 +0900 +++ ./src/win32/VideoMode.cpp 2006-07-26 22:02:44 +0900 @@ -100,22 +100,31 @@ static HRESULT WINAPI addVideoMode(LPDDSURFACEDESC2 surf, LPVOID lpContext) { - HWND h = (HWND)lpContext; - char buffer[50]; - - switch(surf->ddpfPixelFormat.dwRGBBitCount) { - case 16: - case 24: - case 32: - if(surf->dwWidth >= 640 && surf->dwHeight >= 480) { - sprintf(buffer, "%4dx%4dx%2d", surf->dwWidth, surf->dwHeight, - surf->ddpfPixelFormat.dwRGBBitCount); - int pos = ::SendMessage(h, LB_ADDSTRING, 0, (LPARAM)buffer); - ::SendMessage(h, LB_SETITEMDATA, pos, - (surf->ddpfPixelFormat.dwRGBBitCount << 24) | - ((surf->dwWidth & 4095) << 12) | - (surf->dwHeight & 4095)); - } + HWND h = (HWND)lpContext; + char buffer[50]; + + switch( surf->ddpfPixelFormat.dwRGBBitCount ) + { + case 16: + case 24: + case 32: + sprintf( + buffer, + _T("%4dx%4dx%2d"), + surf->dwWidth, + surf->dwHeight, + surf->ddpfPixelFormat.dwRGBBitCount + ); + WPARAM pos = ::SendMessage( h, LB_ADDSTRING, 0, (LPARAM)buffer ); + ::SendMessage( + h, + LB_SETITEMDATA, + pos, + (surf->ddpfPixelFormat.dwRGBBitCount << 24) | + ((surf->dwWidth & 4095) << 12) | + (surf->dwHeight & 4095) + ); + break; } return DDENUMRET_OK; @@ -123,7 +132,11 @@ int winVideoModeSelect(CWnd *pWnd, GUID **guid) { +#ifdef _AFXDLL HINSTANCE h = AfxLoadLibrary("ddraw.dll"); +#else + HMODULE h = LoadLibrary( _T("ddraw.dll") ); +#endif // If ddraw.dll doesn't exist in the search path, // then DirectX probably isn't installed, so fail. @@ -180,12 +193,14 @@ if(gDriverCnt > 1) { VideoDriverSelect d(pWnd); - selected = d.DoModal(); + INT_PTR selected = d.DoModal(); if(selected == -1) { - // If the library was loaded by calling LoadLibrary(), - // then you must use FreeLibrary() to let go of it. - AfxFreeLibrary(h); +#ifdef _AFXDLL + AfxFreeLibrary( h ); +#else + FreeLibrary( h ); +#endif return -1; } @@ -203,19 +218,27 @@ NULL); if(hret != DD_OK) { systemMessage(0, "Error during DirectDrawCreateEx: %08x", hret); - AfxFreeLibrary(h); +#ifdef _AFXDLL + AfxFreeLibrary( h ); +#else + FreeLibrary( h ); +#endif return -1; } } else { // should not happen.... systemMessage(0, "Error getting DirectDrawCreateEx"); - AfxFreeLibrary(h); +#ifdef _AFXDLL + AfxFreeLibrary( h ); +#else + FreeLibrary( h ); +#endif return -1; } VideoMode dlg(ddraw, pWnd); - int res = dlg.DoModal(); + INT_PTR res = dlg.DoModal(); if(res != -1) { *guid = Drivers[selected].pGUID; @@ -225,9 +248,13 @@ // If the library was loaded by calling LoadLibrary(), // then you must use FreeLibrary() to let go of it. - AfxFreeLibrary(h); +#ifdef _AFXDLL + AfxFreeLibrary( h ); +#else + FreeLibrary( h ); +#endif - return res; + return (int)res; } ///////////////////////////////////////////////////////////////////////////// @@ -278,12 +305,12 @@ void VideoMode::OnOk() { - int cur = m_modes.GetCurSel(); + DWORD_PTR cur = m_modes.GetCurSel(); if(cur != -1) { - cur = m_modes.GetItemData(cur); + cur = m_modes.GetItemData((int)cur); } - EndDialog(cur); + EndDialog((int)cur); } BOOL VideoMode::OnInitDialog() @@ -291,8 +318,11 @@ CDialog::OnInitDialog(); // check for available fullscreen modes - pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, m_modes.m_hWnd, - addVideoMode); + pDirectDraw->EnumDisplayModes( + DDEDM_STANDARDVGAMODES, + NULL, + m_modes.m_hWnd, + addVideoMode); GetDlgItem(ID_OK)->EnableWindow(FALSE); CenterWindow(); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/ZoomControl.h ./src/win32/ZoomControl.h --- ../VisualBoyAdvance-1.7.2/src/win32/ZoomControl.h 2004-05-13 22:30:22 +0900 +++ ./src/win32/ZoomControl.h 2006-05-27 23:47:33 +0900 @@ -20,7 +20,7 @@ #if !defined(AFX_ZOOMCONTROL_H__BC193230_D2D6_4240_93AE_28C2EF2C641A__INCLUDED_) #define AFX_ZOOMCONTROL_H__BC193230_D2D6_4240_93AE_28C2EF2C641A__INCLUDED_ -#include "..\System.h" // Added by ClassView +#include "../System.h" // Added by ClassView #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 diff -urN ../VisualBoyAdvance-1.7.2/src/win32/display.cpp ./src/win32/display.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/display.cpp 1970-01-01 09:00:00 +0900 +++ ./src/win32/display.cpp 2006-08-01 00:51:01 +0900 @@ -0,0 +1,123 @@ +// 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. + +#include "stdafx.h" +#include "Display.h" + +void copyImage( void *source, void *destination, unsigned int width, unsigned int height, unsigned int destinationPitch, unsigned int colorDepth ) +{ +#ifdef ASM + + // Copy the image at [source] to the locked Direct3D texture + __asm + { + mov eax, width ; Initialize + mov ebx, height ; + mov edi, destination ; + mov edx, destinationPitch ; + + cmp colorDepth, 16 ; Check colorDepth==16bit + jnz gbaOtherColor ; + sub edx, eax ; + sub edx, eax ; + mov esi, source ; + lea esi,[esi+2*eax+4] ; + shr eax, 1 ; +gbaLoop16bit: + mov ecx, eax ; + rep movsd ; + add esi, 4 ; + add edi, edx ; + dec ebx ; + jnz gbaLoop16bit ; + jmp gbaLoopEnd ; +gbaOtherColor: + cmp colorDepth, 32 ; Check colorDepth==32bit + jnz gbaOtherColor2 ; + + lea esi, [eax*4] ; + sub edx, esi ; + mov esi, source ; + lea esi, [esi+4*eax+4] ; +gbaLoop32bit: + mov ecx, eax ; + rep movsd ; ECX times: Move DWORD at [ESI] to [EDI] | ESI++ EDI++ + add esi, 4 ; + add edi, edx ; + dec ebx ; + jnz gbaLoop32bit ; + jmp gbaLoopEnd ; +gbaOtherColor2: + lea eax, [eax+2*eax] ; Works like colorDepth==24bit + sub edx, eax ; +gbaLoop24bit: + mov ecx, eax ; + shr ecx, 2 ; + rep movsd ; + add edi, edx ; + dec ebx ; + jnz gbaLoop24bit ; +gbaLoopEnd: + } + +#else // #ifdef ASM + + // optimized C version + register unsigned int lineSize; + register unsigned char *src, *dst; + switch(colorDepth) + { + case 16: + lineSize = width<<1; + src = ((unsigned char*)source) + lineSize + 4; + dst = (unsigned char*)destination; + do { + MoveMemory( dst, src, lineSize ); + src+=lineSize; + dst+=lineSize; + src += 2; + dst += (destinationPitch - lineSize); + } while ( --height); + break; + case 32: + lineSize = width<<2; + src = ((unsigned char*)source) + lineSize + 4; + dst = (unsigned char*)destination; + do { + MoveMemory( dst, src, lineSize ); + src+=lineSize; + dst+=lineSize; + src += 4; + dst += (destinationPitch - lineSize); + } while ( --height); + break; + } + + // very compatible but slow C version + //unsigned int nBytesPerPixel = colorDepth>>3; + //unsigned int i, x, y, srcPitch = (width+1) * nBytesPerPixel; + //unsigned char * src = ((unsigned char*)source)+srcPitch; + //unsigned char * dst = (unsigned char*)destination; + //for (y=0;yGetWindowRect(&r); @@ -168,7 +168,7 @@ pWnd->SetWindowRgn(m_rgnSkin, true); // subclass the window procedure - m_OldWndProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)SkinWndProc); + m_OldWndProc = (WNDPROC)SetWindowLongPtr( m_hWnd, GWLP_WNDPROC, (LONG_PTR)SkinWndProc ); // store a pointer to our class instance inside the window procedure. if (!SetProp(m_hWnd, "skin", (void*)this)) @@ -214,7 +214,7 @@ SetWindowRgn(m_hWnd, NULL, true); // unsubclass the window procedure - OurWnd = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_OldWndProc); + OurWnd = (WNDPROC)SetWindowLongPtr( m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_OldWndProc ); // remove the pointer to our class instance, but if we fail we don't care. RemoveProp(m_hWnd, "skin"); @@ -223,7 +223,7 @@ // we failed to unhook the window. m_bHooked = ( OurWnd ? false : true ); - SetWindowLong(m_hWnd, GWL_STYLE, m_dOldStyle); + SetWindowLongPtr(m_hWnd, GWL_STYLE, m_dOldStyle); RECT r; @@ -533,7 +533,7 @@ { // we will need a pointer to the associated class instance // (it was stored in the window before, remember?) - CSkin *pSkin = (CSkin*)GetProp(hWnd, "skin"); + CSkin *pSkin = (CSkin*)GetProp(hWnd, _T("skin")); // to handle WM_PAINT PAINTSTRUCT ps; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/skin.h ./src/win32/skin.h --- ../VisualBoyAdvance-1.7.2/src/win32/skin.h 2004-05-13 22:31:53 +0900 +++ ./src/win32/skin.h 2006-05-27 23:47:33 +0900 @@ -67,7 +67,7 @@ RECT m_rect; - DWORD m_dOldStyle; + LONG_PTR m_dOldStyle; RECT m_oldRect; int m_nButtons; SkinButton *m_buttons; diff -urN ../VisualBoyAdvance-1.7.2/src/win32/skinButton.cpp ./src/win32/skinButton.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/skinButton.cpp 2004-05-13 23:14:10 +0900 +++ ./src/win32/skinButton.cpp 2006-08-26 00:27:16 +0900 @@ -97,7 +97,7 @@ PAINTSTRUCT ps; HDC hDC = ::BeginPaint(m_hWnd, &ps); HDC memDC = ::CreateCompatibleDC(hDC); - UINT state = ::SendMessage(m_hWnd, BM_GETSTATE, 0, 0); + LRESULT state = ::SendMessage(m_hWnd, BM_GETSTATE, 0, 0); HBITMAP oldBitmap; if(state & BST_PUSHED) oldBitmap = (HBITMAP)SelectObject(memDC, downBmp); @@ -126,6 +126,8 @@ if(region != NULL) inside &= PtInRegion(region, pt.x, pt.y); if(inside) { + ReleaseCapture(); + Invalidate(); HWND hWnd = m_hWnd; if(idCommand != 0) GetParent()->SendMessage(WM_COMMAND, idCommand, 0); diff -urN ../VisualBoyAdvance-1.7.2/src/win32/stdafx.cpp ./src/win32/stdafx.cpp --- ../VisualBoyAdvance-1.7.2/src/win32/stdafx.cpp 2004-05-13 23:13:56 +0900 +++ ./src/win32/stdafx.cpp 2006-05-27 23:47:33 +0900 @@ -16,11 +16,4 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// stdafx.cpp : source file that includes just the standard includes -// DialogSizer.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file +#include "stdafx.h" \ No newline at end of file diff -urN ../VisualBoyAdvance-1.7.2/src/win32/stdafx.h ./src/win32/stdafx.h --- ../VisualBoyAdvance-1.7.2/src/win32/stdafx.h 2004-05-13 22:28:48 +0900 +++ ./src/win32/stdafx.h 2006-05-27 23:47:33 +0900 @@ -33,6 +33,13 @@ // Insert your headers here //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Target for Windows 2000 +#define WINVER 0x0500 +#define _WIN32_WINNT 0x0500 + +#define STRICT + + #include #include #include diff -urN ../VisualBoyAdvance-1.7.2/src/win32/vba.rc ./src/win32/vba.rc --- ../VisualBoyAdvance-1.7.2/src/win32/vba.rc 2004-05-15 20:21:51 +0900 +++ ./src/win32/vba.rc 2006-08-06 21:40:35 +0900 @@ -1,4 +1,4 @@ -//Microsoft Developer Studio generated resource script. +// Microsoft Visual C++ generated resource script. // #include "resource.h" @@ -8,7 +8,7 @@ // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" -#include "vba.rc2" +#include "resource2.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -27,21 +27,20 @@ // TEXTINCLUDE // -1 TEXTINCLUDE DISCARDABLE +1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE DISCARDABLE +2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" - "#include ""vba.rc2""\0" + "#include ""resource2.h""\0" END -3 TEXTINCLUDE DISCARDABLE +3 TEXTINCLUDE BEGIN - "\r\n" - "\0" + "#include ""vba.rc2""\0" END #endif // APSTUDIO_INVOKED @@ -49,94 +48,77 @@ ///////////////////////////////////////////////////////////////////////////// // -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON ICON DISCARDABLE "gbadvance.ico" - -///////////////////////////////////////////////////////////////////////////// -// // Dialog // -IDD_OPENDLG DIALOG DISCARDABLE 36, 24, 202, 117 -STYLE DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | WS_POPUP | WS_CAPTION | - WS_SYSMENU +IDD_OPENDLG DIALOG 36, 24, 202, 117 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Open" FONT 8, "MS Shell Dlg" BEGIN LTEXT "File &name:",1090,2,1,81,8 EDITTEXT 1152,0,10,104,12,ES_AUTOHSCROLL | ES_OEMCONVERT - LISTBOX 1120,1,24,104,53,LBS_SORT | LBS_OWNERDRAWFIXED | - LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | - WS_TABSTOP + LISTBOX 1120,1,24,104,53,LBS_SORT | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "&Folders:",-1,112,0,53,9 LTEXT "",1088,113,10,86,9,SS_NOPREFIX - LISTBOX 1121,112,24,88,52,LBS_SORT | LBS_OWNERDRAWFIXED | - LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | - WS_TABSTOP + LISTBOX 1121,112,24,88,52,LBS_SORT | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "List files of &type:",1089,1,75,81,9 - COMBOBOX 1136,1,87,104,13,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | - WS_VSCROLL | WS_TABSTOP + COMBOBOX 1136,1,87,104,13,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "Dri&ves:",1091,113,76,70,9 - COMBOBOX 1137,112,87,71,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | - CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL | - WS_TABSTOP + COMBOBOX 1137,112,87,71,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK",IDOK,24,102,50,14,WS_GROUP PUSHBUTTON "Cancel",IDCANCEL,90,102,50,14,WS_GROUP END -IDD_ABOUT DIALOG DISCARDABLE 0, 0, 164, 93 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About VisualBoyAdvance" -FONT 8, "MS Sans Serif" -BEGIN - DEFPUSHBUTTON "OK",IDOK,56,72,50,14 - ICON IDI_ICON,IDC_STATIC,5,12,21,20 - CTEXT "VisualBoyAdvance Emulator",IDC_STATIC,14,7,134,8 - CTEXT "Copyright (c) 2004 Forgotten and the VBA team", - IDC_STATIC,6,35,150,8 - CTEXT "http://vba.ngemu.com",IDC_URL,43,55,76,8 - CTEXT "Contribution by Costis",IDC_STATIC,30,45,102,8 - CTEXT "Version",IDC_STATIC,46,16,70,8 - CTEXT "",IDC_VERSION,60,25,43,8 -END - -IDD_DIRECTORIES DIALOG DISCARDABLE 0, 0, 284, 129 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_ABOUT DIALOGEX 0, 0, 157, 78 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "About" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + ICON 101,IDC_STATIC,6,6,20,20 + CTEXT "VisualBoyAdvance Emulator",IDC_STATIC,30,6,120,8 + CTEXT "Copyright © 2006 VBA development team",IDC_STATIC,6,36,144,8 + CTEXT "http://vba.ngemu.com",IDC_URL,6,66,144,8 + CTEXT "Contribution by Costis",IDC_STATIC,6,48,144,8 + CTEXT "Version",IDC_STATIC,30,18,60,8 + CTEXT "",IDC_VERSION,90,18,60,8,SS_NOPREFIX +END + +IDD_DIRECTORIES DIALOGEX 0, 0, 220, 301 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW CAPTION "Directories" -FONT 8, "MS Sans Serif" +FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - PUSHBUTTON "Browse...",IDC_ROM_DIR,174,7,50,14 - PUSHBUTTON "Browse...",IDC_GBROM_DIR,174,26,50,14 - PUSHBUTTON "Browse...",IDC_BATTERY_DIR,174,45,50,14 - PUSHBUTTON "Browse...",IDC_SAVE_DIR,174,64,50,14 - PUSHBUTTON "Browse...",IDC_CAPTURE_DIR,174,83,50,14 - DEFPUSHBUTTON "OK",IDOK,88,108,50,14 - PUSHBUTTON "Cancel",IDCANCEL,145,108,50,14 - LTEXT "ROM:",IDC_STATIC,7,9,20,8 - LTEXT "Battery:",IDC_STATIC,7,47,25,8 - LTEXT "Save Game:",IDC_STATIC,7,66,40,8 - LTEXT "Capture:",IDC_STATIC,7,85,28,8 - EDITTEXT IDC_ROM_PATH,49,7,121,14,ES_AUTOHSCROLL | WS_DISABLED - EDITTEXT IDC_BATTERY_PATH,49,45,121,14,ES_AUTOHSCROLL | - WS_DISABLED - EDITTEXT IDC_SAVE_PATH,49,64,121,14,ES_AUTOHSCROLL | WS_DISABLED - EDITTEXT IDC_CAPTURE_PATH,49,83,121,14,ES_AUTOHSCROLL | - WS_DISABLED - LTEXT "GB ROM:",IDC_STATIC,7,28,32,8 - EDITTEXT IDC_GBROM_PATH,49,26,121,14,ES_AUTOHSCROLL | WS_DISABLED - PUSHBUTTON "Reset",IDC_ROM_DIR_RESET,228,6,50,14 - PUSHBUTTON "Reset",IDC_GBROM_DIR_RESET,228,25,50,14 - PUSHBUTTON "Reset",IDC_BATTERY_DIR_RESET,228,45,50,14 - PUSHBUTTON "Reset",IDC_SAVE_DIR_RESET,228,64,50,14 - PUSHBUTTON "Reset",IDC_CAPTURE_DIR_RESET,228,83,50,14 + PUSHBUTTON "Browse...",IDC_ROM_DIR,12,66,90,12 + PUSHBUTTON "Browse...",IDC_GBROM_DIR,12,114,90,12 + PUSHBUTTON "Browse...",IDC_BATTERY_DIR,12,162,90,12 + PUSHBUTTON "Browse...",IDC_SAVE_DIR,12,210,90,12 + PUSHBUTTON "Browse...",IDC_CAPTURE_DIR,12,258,90,12 + DEFPUSHBUTTON "OK",IDOK,120,282,42,12 + PUSHBUTTON "Cancel",IDCANCEL,168,282,42,12 + EDITTEXT IDC_ROM_PATH,12,54,198,12,ES_AUTOHSCROLL + EDITTEXT IDC_BATTERY_PATH,12,150,198,12,ES_AUTOHSCROLL + EDITTEXT IDC_SAVE_PATH,12,198,198,12,ES_AUTOHSCROLL + EDITTEXT IDC_CAPTURE_PATH,12,246,198,12,ES_AUTOHSCROLL + EDITTEXT IDC_GBROM_PATH,12,102,198,12,ES_AUTOHSCROLL + PUSHBUTTON "Reset",IDC_ROM_DIR_RESET,120,66,90,12 + PUSHBUTTON "Reset",IDC_GBROM_DIR_RESET,120,114,84,12 + PUSHBUTTON "Reset",IDC_BATTERY_DIR_RESET,120,162,90,12 + PUSHBUTTON "Reset",IDC_SAVE_DIR_RESET,120,210,90,12 + PUSHBUTTON "Reset",IDC_CAPTURE_DIR_RESET,120,258,90,12 + CONTROL "You can either select or enter absolute paths to directories,\nor you can use relative paths by beginning with a . (point).\nExamples: c:\\emulation\\roms | .\\battery | ..\\snapshots\\gba",IDC_STATIC, + "Static",SS_LEFTNOWORDWRAP | WS_GROUP,6,6,210,30,WS_EX_STATICEDGE + GROUPBOX "Game Boy Advance ROM Images",IDC_STATIC,6,42,210,42 + GROUPBOX "Game Boy / Game Boy Color ROM Images",IDC_STATIC,6,90,210,42 + GROUPBOX "Game Boy Internal Battery Saves",IDC_STATIC,6,138,210,42 + GROUPBOX "Visual Boy Advance Save Games",IDC_STATIC,6,186,210,42 + GROUPBOX "Screenshots",IDC_STATIC,6,234,210,42 END -IDD_CONFIG DIALOG DISCARDABLE 0, 0, 135, 211 -STYLE DS_SYSMODAL | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_CONFIG DIALOG 0, 0, 135, 211 +STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Joypad configuration" FONT 8, "MS Sans Serif" BEGIN @@ -170,43 +152,27 @@ LTEXT "GS:",IDC_STATIC,5,173,35,10 END -IDD_CHEATS DIALOG DISCARDABLE 0, 0, 276, 253 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_CHEATS DIALOG 0, 0, 276, 253 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Search for cheats" FONT 8, "MS Sans Serif" BEGIN - CONTROL "",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,3,5,265,111 - CONTROL "Ol&d value",IDC_OLD_VALUE,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,11,129,46,10 - CONTROL "Specifi&c value",IDC_SPECIFIC_VALUE,"Button", - BS_AUTORADIOBUTTON,11,141,61,10 - CONTROL "&8 bits",IDC_SIZE_8,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,11,167,33,10 - CONTROL "&16 bits",IDC_SIZE_16,"Button",BS_AUTORADIOBUTTON,11, - 179,37,10 - CONTROL "&32 bits",IDC_SIZE_32,"Button",BS_AUTORADIOBUTTON,11, - 191,37,10 - CONTROL "&Equal",IDC_EQ,"Button",BS_AUTORADIOBUTTON | WS_GROUP, - 100,128,34,10 - CONTROL "&Not equal",IDC_NE,"Button",BS_AUTORADIOBUTTON,100,140, - 47,10 - CONTROL "&Less than",IDC_LT,"Button",BS_AUTORADIOBUTTON,100,152, - 47,10 - CONTROL "Le&ss or equal",IDC_LE,"Button",BS_AUTORADIOBUTTON,100, - 164,58,10 - CONTROL "&Greather than",IDC_GT,"Button",BS_AUTORADIOBUTTON,100, - 176,59,10 - CONTROL "G&reater or equal",IDC_GE,"Button",BS_AUTORADIOBUTTON, - 100,188,67,10 - CONTROL "S&igned",IDC_SIGNED,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,202,130,38,10 - CONTROL "&Unsigned",IDC_UNSIGNED,"Button",BS_AUTORADIOBUTTON,202, - 142,46,10 - CONTROL "&Hexadecimal",IDC_HEXADECIMAL,"Button", - BS_AUTORADIOBUTTON,202,154,57,10 - CONTROL "U&pdate values",IDC_UPDATE,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,192,192,62,10 + CONTROL "",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,3,5,265,111 + CONTROL "Ol&d value",IDC_OLD_VALUE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,11,129,46,10 + CONTROL "Specifi&c value",IDC_SPECIFIC_VALUE,"Button",BS_AUTORADIOBUTTON,11,141,61,10 + CONTROL "&8 bits",IDC_SIZE_8,"Button",BS_AUTORADIOBUTTON | WS_GROUP,11,167,33,10 + CONTROL "&16 bits",IDC_SIZE_16,"Button",BS_AUTORADIOBUTTON,11,179,37,10 + CONTROL "&32 bits",IDC_SIZE_32,"Button",BS_AUTORADIOBUTTON,11,191,37,10 + CONTROL "&Equal",IDC_EQ,"Button",BS_AUTORADIOBUTTON | WS_GROUP,100,128,34,10 + CONTROL "&Not equal",IDC_NE,"Button",BS_AUTORADIOBUTTON,100,140,47,10 + CONTROL "&Less than",IDC_LT,"Button",BS_AUTORADIOBUTTON,100,152,47,10 + CONTROL "Le&ss or equal",IDC_LE,"Button",BS_AUTORADIOBUTTON,100,164,58,10 + CONTROL "&Greather than",IDC_GT,"Button",BS_AUTORADIOBUTTON,100,176,59,10 + CONTROL "G&reater or equal",IDC_GE,"Button",BS_AUTORADIOBUTTON,100,188,67,10 + CONTROL "S&igned",IDC_SIGNED,"Button",BS_AUTORADIOBUTTON | WS_GROUP,202,130,38,10 + CONTROL "&Unsigned",IDC_UNSIGNED,"Button",BS_AUTORADIOBUTTON,202,142,46,10 + CONTROL "&Hexadecimal",IDC_HEXADECIMAL,"Button",BS_AUTORADIOBUTTON,202,154,57,10 + CONTROL "U&pdate values",IDC_UPDATE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,192,192,62,10 EDITTEXT IDC_VALUE,95,211,172,14,ES_AUTOHSCROLL PUSHBUTTON "&Start",IDC_START,15,237,50,14,WS_GROUP PUSHBUTTON "S&earch",IDC_SEARCH,80,236,50,14 @@ -219,26 +185,20 @@ LTEXT "Enter &value:",IDC_STATIC,3,214,69,8 END -IDD_ADD_CHEAT DIALOG DISCARDABLE 0, 0, 186, 137 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_ADD_CHEAT DIALOG 0, 0, 186, 137 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Add cheat" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_ADDRESS,60,6,123,14,ES_AUTOHSCROLL EDITTEXT IDC_VALUE,60,24,123,14,ES_AUTOHSCROLL EDITTEXT IDC_DESC,60,42,123,14,ES_AUTOHSCROLL - CONTROL "8-bit",IDC_SIZE_8,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,11,70,29,10 - CONTROL "16-bit",IDC_SIZE_16,"Button",BS_AUTORADIOBUTTON,62,70, - 33,10 - CONTROL "32-bit",IDC_SIZE_32,"Button",BS_AUTORADIOBUTTON,117,70, - 33,10 - CONTROL "&Signed",IDC_SIGNED,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,11,97,38,10 - CONTROL "&Unsigned",IDC_UNSIGNED,"Button",BS_AUTORADIOBUTTON,62, - 98,46,10 - CONTROL "&Hexadecimal",IDC_HEXADECIMAL,"Button", - BS_AUTORADIOBUTTON,117,98,57,10 + CONTROL "8-bit",IDC_SIZE_8,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,70,29,10 + CONTROL "16-bit",IDC_SIZE_16,"Button",BS_AUTORADIOBUTTON,62,70,33,10 + CONTROL "32-bit",IDC_SIZE_32,"Button",BS_AUTORADIOBUTTON,117,70,33,10 + CONTROL "&Signed",IDC_SIGNED,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,97,38,10 + CONTROL "&Unsigned",IDC_UNSIGNED,"Button",BS_AUTORADIOBUTTON,62,98,46,10 + CONTROL "&Hexadecimal",IDC_HEXADECIMAL,"Button",BS_AUTORADIOBUTTON,117,98,57,10 DEFPUSHBUTTON "&OK",ID_OK,36,116,50,14,WS_GROUP PUSHBUTTON "&Cancel",ID_CANCEL,99,116,50,14 LTEXT "&Value:",IDC_STATIC,3,27,54,8 @@ -248,13 +208,12 @@ LTEXT "&Description:",IDC_STATIC,3,45,55,8 END -IDD_CHEAT_LIST DIALOG DISCARDABLE 0, 0, 280, 250 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_CHEAT_LIST DIALOG 0, 0, 280, 250 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Cheat list" FONT 8, "MS Sans Serif" BEGIN - CONTROL "Restore &previous values",IDC_RESTORE,"Button", - BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,5,183,92,10 + CONTROL "Restore &previous values",IDC_RESTORE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,5,183,92,10 PUSHBUTTON "&Code...",IDC_ADD_CODE,9,208,64,14,WS_GROUP PUSHBUTTON "C&heat...",IDC_ADD_CHEAT,75,208,64,14 PUSHBUTTON "&Gameshark...",IDC_ADD_GAMESHARK,141,208,64,14 @@ -263,41 +222,33 @@ PUSHBUTTON "Remove A&ll",IDC_REMOVE_ALL,75,230,64,14 PUSHBUTTON "&Enable/Dis.",IDC_ENABLE,141,230,64,14 DEFPUSHBUTTON "&OK",ID_OK,206,230,64,14,WS_GROUP - CONTROL "",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | WS_BORDER | - WS_GROUP | WS_TABSTOP,5,15,269,156 + CONTROL "",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | WS_BORDER | WS_GROUP | WS_TABSTOP,5,15,269,156 LTEXT "Status legend:",IDC_STATIC,6,3,46,8 LTEXT "E: Enabled",IDC_STATIC,188,3,36,8 LTEXT "D: Disabled",IDC_STATIC,234,3,38,8 GROUPBOX "Add",IDC_STATIC,5,199,268,27 END -IDD_ASSOCIATIONS DIALOG DISCARDABLE 0, 0, 116, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_ASSOCIATIONS DIALOG 0, 0, 116, 95 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Associations" FONT 8, "MS Sans Serif" BEGIN - CONTROL ".gb",IDC_GB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,15, - 26,10 - CONTROL ".sgb",IDC_SGB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15, - 29,29,10 - CONTROL ".cgb",IDC_CGB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15, - 43,30,10 - CONTROL ".gbc",IDC_GBC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15, - 57,30,10 - CONTROL ".gba",IDC_GBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75, - 13,30,10 - CONTROL ".agb",IDC_AGB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75, - 27,30,10 - CONTROL ".bin",IDC_BIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75, - 41,27,10 + CONTROL ".gb",IDC_GB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,15,26,10 + CONTROL ".sgb",IDC_SGB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,29,29,10 + CONTROL ".cgb",IDC_CGB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,43,30,10 + CONTROL ".gbc",IDC_GBC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,57,30,10 + CONTROL ".gba",IDC_GBA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75,13,30,10 + CONTROL ".agb",IDC_AGB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75,27,30,10 + CONTROL ".bin",IDC_BIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75,41,27,10 DEFPUSHBUTTON "OK",ID_OK,3,78,50,14 PUSHBUTTON "Cancel",ID_CANCEL,63,78,50,14 GROUPBOX "GBA Types",IDC_STATIC,63,3,50,51 GROUPBOX "GB Types",IDC_STATIC,3,3,50,69 END -IDD_GBA_ROM_INFO DIALOG DISCARDABLE 0, 0, 220, 142 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GBA_ROM_INFO DIALOG 0, 0, 220, 142 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Rom information" FONT 8, "MS Sans Serif" BEGIN @@ -309,19 +260,19 @@ LTEXT "Device type:",IDC_STATIC,7,80,60,8 LTEXT "ROM version:",IDC_STATIC,7,94,60,8 LTEXT "CRC:",IDC_STATIC,7,108,60,8 - LTEXT "",IDC_ROM_TITLE,80,10,133,8 - LTEXT "",IDC_ROM_GAME_CODE,80,24,133,8 - LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8 - LTEXT "",IDC_ROM_UNIT_CODE,80,66,133,8 - LTEXT "",IDC_ROM_DEVICE_TYPE,80,80,133,8 - LTEXT "",IDC_ROM_VERSION,80,94,133,8 - LTEXT "",IDC_ROM_CRC,80,108,133,8 - LTEXT "",IDC_ROM_MAKER_NAME,80,52,133,8 LTEXT "Maker name:",IDC_STATIC,7,52,60,8 + LTEXT "",IDC_ROM_TITLE,80,10,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_GAME_CODE,80,24,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_UNIT_CODE,80,66,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_DEVICE_TYPE,80,80,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_VERSION,80,94,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_CRC,80,108,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_MAKER_NAME,80,52,133,8,SS_NOPREFIX END -IDD_GB_ROM_INFO DIALOG DISCARDABLE 0, 0, 220, 225 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GB_ROM_INFO DIALOG 0, 0, 220, 225 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Rom information" FONT 8, "MS Sans Serif" BEGIN @@ -332,39 +283,36 @@ LTEXT "Cartridge type:",IDC_STATIC,7,82,60,8 LTEXT "ROM version:",IDC_STATIC,7,152,60,8 LTEXT "CRC:",IDC_STATIC,7,166,60,8 - LTEXT "",IDC_ROM_TITLE,80,10,133,8 - LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8 - LTEXT "",IDC_ROM_UNIT_CODE,80,68,133,8 - LTEXT "",IDC_ROM_DEVICE_TYPE,80,82,133,8 - LTEXT "",IDC_ROM_VERSION,80,152,133,8 - LTEXT "",IDC_ROM_CRC,80,166,133,8 + LTEXT "",IDC_ROM_TITLE,80,10,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_UNIT_CODE,80,68,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_DEVICE_TYPE,80,82,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_VERSION,80,152,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_CRC,80,166,133,8,SS_NOPREFIX LTEXT "Color:",IDC_STATIC,7,24,60,8 - LTEXT "",IDC_ROM_COLOR,80,24,133,8 + LTEXT "",IDC_ROM_COLOR,80,24,133,8,SS_NOPREFIX LTEXT "ROM size:",IDC_STATIC,7,96,60,8 - LTEXT "",IDC_ROM_SIZE,80,96,133,8 + LTEXT "",IDC_ROM_SIZE,80,96,133,8,SS_NOPREFIX LTEXT "RAM size:",IDC_STATIC,7,110,60,8 - LTEXT "",IDC_ROM_RAM_SIZE,80,110,133,8 + LTEXT "",IDC_ROM_RAM_SIZE,80,110,133,8,SS_NOPREFIX LTEXT "Dest. code:",IDC_STATIC,7,124,60,8 - LTEXT "",IDC_ROM_DEST_CODE,80,124,133,8 + LTEXT "",IDC_ROM_DEST_CODE,80,124,133,8,SS_NOPREFIX LTEXT "License code:",IDC_STATIC,7,138,60,8 - LTEXT "",IDC_ROM_LIC_CODE,80,138,133,8 + LTEXT "",IDC_ROM_LIC_CODE,80,138,133,8,SS_NOPREFIX LTEXT "Checksum:",IDC_STATIC,7,180,60,8 - LTEXT "",IDC_ROM_CHECKSUM,80,180,133,8 - LTEXT "",IDC_ROM_MAKER_NAME2,80,52,133,8 + LTEXT "",IDC_ROM_CHECKSUM,80,180,133,8,SS_NOPREFIX + LTEXT "",IDC_ROM_MAKER_NAME2,80,52,133,8,SS_NOPREFIX LTEXT "Maker name:",IDC_STATIC,7,52,60,8 END -IDD_GB_CHEAT_LIST DIALOG DISCARDABLE 0, 0, 286, 221 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GB_CHEAT_LIST DIALOG 0, 0, 286, 221 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Gameboy Cheat List" FONT 8, "MS Sans Serif" BEGIN - CONTROL "",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | WS_BORDER | - WS_GROUP | WS_TABSTOP,9,20,269,156 - PUSHBUTTON "Add &GameGenie...",IDC_ADD_GG_CHEAT,9,183,80,14, - WS_GROUP - PUSHBUTTON "&Add GameShark...",IDC_ADD_GS_CHEAT,103,183,80,14, - WS_GROUP + CONTROL "",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | WS_BORDER | WS_GROUP | WS_TABSTOP,9,20,269,156 + PUSHBUTTON "Add &GameGenie...",IDC_ADD_GG_CHEAT,9,183,80,14,WS_GROUP + PUSHBUTTON "&Add GameShark...",IDC_ADD_GS_CHEAT,103,183,80,14,WS_GROUP PUSHBUTTON "&Remove",IDC_REMOVE,197,183,80,14 PUSHBUTTON "Remove A&ll",IDC_REMOVE_ALL,9,202,80,14 PUSHBUTTON "&Enable/Dis.",IDC_ENABLE,103,202,80,14 @@ -374,40 +322,37 @@ LTEXT "D: Disabled",IDC_STATIC,241,9,38,8 END -IDD_ADD_CHEAT_DLG DIALOG DISCARDABLE 0, 0, 182, 107 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_ADD_CHEAT_DLG DIALOG 0, 0, 182, 107 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Title" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_DESC,60,7,120,14,ES_AUTOHSCROLL - EDITTEXT IDC_CODE,60,23,120,58,ES_MULTILINE | ES_UPPERCASE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN + EDITTEXT IDC_CODE,60,23,120,58,ES_MULTILINE | ES_UPPERCASE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN DEFPUSHBUTTON "OK",ID_OK,33,86,50,14 PUSHBUTTON "Cancel",ID_CANCEL,99,86,50,14 LTEXT "&Description:",IDC_STATIC,3,10,54,8 LTEXT "&Code:",IDC_STATIC,3,29,54,8 END -IDD_GB_PRINTER DIALOG DISCARDABLE 0, 0, 178, 209 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GB_PRINTER DIALOG 0, 0, 178, 209 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "GB Printer" FONT 8, "MS Sans Serif" BEGIN - CONTROL "&1x",IDC_1X,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13, - 166,22,10 + CONTROL "&1x",IDC_1X,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,166,22,10 CONTROL "&2x",IDC_2X,"Button",BS_AUTORADIOBUTTON,55,166,23,10 CONTROL "&3x",IDC_3X,"Button",BS_AUTORADIOBUTTON,98,166,23,10 CONTROL "&4x",IDC_4X,"Button",BS_AUTORADIOBUTTON,141,166,23,10 DEFPUSHBUTTON "&Print...",ID_PRINT,7,190,50,14,WS_GROUP PUSHBUTTON "&Save...",ID_SAVE,64,190,50,14 PUSHBUTTON "&Close",ID_OK,121,190,50,14 - CONTROL "",IDC_GB_PRINTER,"Static",SS_BLACKFRAME | WS_GROUP,7,6, - 162,146 + CONTROL "",IDC_GB_PRINTER,"Static",SS_BLACKFRAME | WS_GROUP,7,6,162,146 GROUPBOX "Print Size",IDC_STATIC,7,156,162,25 END -IDD_MOTION_CONFIG DIALOG DISCARDABLE 0, 0, 135, 78 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_MOTION_CONFIG DIALOG 0, 0, 135, 78 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Motion Sensor" FONT 8, "MS Sans Serif" BEGIN @@ -423,8 +368,8 @@ LTEXT "Right:",IDC_STATIC,5,44,35,10 END -IDD_LANG_SELECT DIALOG DISCARDABLE 0, 0, 186, 68 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_LANG_SELECT DIALOG 0, 0, 186, 68 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Language selection" FONT 8, "MS Sans Serif" BEGIN @@ -433,82 +378,72 @@ PUSHBUTTON "Cancel",ID_CANCEL,104,49,50,14 LTEXT "Current system language is:",IDC_STATIC,6,9,123,8 LTEXT "Enter language name (3 letter):",IDC_STATIC,6,30,127,8 - LTEXT "",IDC_LANG_NAME,140,9,40,8 + LTEXT "",IDC_LANG_NAME,140,9,40,8,SS_NOPREFIX END -IDD_CODE_SELECT DIALOG DISCARDABLE 0, 0, 316, 235 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_CODE_SELECT DIALOG 0, 0, 316, 235 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Select codes to import" FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",ID_OK,91,214,50,14 PUSHBUTTON "Cancel",ID_CANCEL,174,214,50,14 - LISTBOX IDC_GAME_LIST,7,7,302,205,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | - WS_TABSTOP + LISTBOX IDC_GAME_LIST,7,7,302,205,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP END -IDD_MAP_VIEW DIALOG DISCARDABLE 0, 0, 322, 238 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_MAP_VIEW DIALOG 0, 0, 322, 238 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Map view" FONT 8, "MS Sans Serif" BEGIN - CONTROL "Frame 0",IDC_FRAME_0,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,13,22,41,10 - CONTROL "Frame 1",IDC_FRAME_1,"Button",BS_AUTORADIOBUTTON,13,36, - 41,10 - CONTROL "BG0",IDC_BG0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13, - 63,30,10 + CONTROL "Frame 0",IDC_FRAME_0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,22,41,10 + CONTROL "Frame 1",IDC_FRAME_1,"Button",BS_AUTORADIOBUTTON,13,36,41,10 + CONTROL "BG0",IDC_BG0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,63,30,10 CONTROL "BG1",IDC_BG1,"Button",BS_AUTORADIOBUTTON,13,77,30,10 CONTROL "BG2",IDC_BG2,"Button",BS_AUTORADIOBUTTON,13,91,30,10 CONTROL "BG3",IDC_BG3,"Button",BS_AUTORADIOBUTTON,13,105,30,10 - CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,7,122,68,10 - CONTROL "Auto update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | - WS_GROUP | WS_TABSTOP,7,134,55,10 + CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,122,68,10 + CONTROL "Auto update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,134,55,10 PUSHBUTTON "&Refresh",IDC_REFRESH,25,217,50,14,WS_GROUP PUSHBUTTON "&Save...",IDC_SAVE,88,217,50,14,WS_GROUP PUSHBUTTON "&Close",IDC_CLOSE,155,217,50,14 - CONTROL "MapView",IDC_MAP_VIEW,"VbaBitmapControl",WS_GROUP | - WS_TABSTOP,187,15,128,128 - CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | - WS_TABSTOP,7,148,64,64 - CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,187,164, - 48,47 - LTEXT "",IDC_R,245,173,50,8 - LTEXT "",IDC_G,245,185,50,8 - LTEXT "",IDC_B,245,197,50,8 + CONTROL "MapView",IDC_MAP_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,187,15,128,128 + CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,148,64,64 + CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,187,164,48,47 + LTEXT "",IDC_R,245,173,50,8,SS_NOPREFIX + LTEXT "",IDC_G,245,185,50,8,SS_NOPREFIX + LTEXT "",IDC_B,245,197,50,8,SS_NOPREFIX GROUPBOX "Frame",IDC_STATIC,7,11,63,37 GROUPBOX "Background",IDC_STATIC,7,52,63,67 - LTEXT "",IDC_XY,129,95,53,8 + LTEXT "",IDC_XY,129,95,53,8,SS_NOPREFIX LTEXT "Mode:",IDC_STATIC,80,15,34,8 - LTEXT "",IDC_MODE,130,15,53,8 + LTEXT "",IDC_MODE,130,15,53,8,SS_NOPREFIX LTEXT "Map Base:",IDC_STATIC,80,25,35,8 - LTEXT "",IDC_MAPBASE,130,25,53,8 + LTEXT "",IDC_MAPBASE,130,25,53,8,SS_NOPREFIX LTEXT "Char Base:",IDC_STATIC,80,35,36,8 - LTEXT "",IDC_CHARBASE,130,35,53,8 + LTEXT "",IDC_CHARBASE,130,35,53,8,SS_NOPREFIX LTEXT "Size:",IDC_STATIC,80,45,37,8 - LTEXT "",IDC_DIM,130,45,53,8 + LTEXT "",IDC_DIM,130,45,53,8,SS_NOPREFIX LTEXT "Colors:",IDC_STATIC,80,55,37,8 - LTEXT "",IDC_NUMCOLORS,130,55,53,8 + LTEXT "",IDC_NUMCOLORS,130,55,53,8,SS_NOPREFIX LTEXT "Priority:",IDC_STATIC,80,65,37,8 - LTEXT "",IDC_PRIORITY,130,65,53,8 + LTEXT "",IDC_PRIORITY,130,65,53,8,SS_NOPREFIX LTEXT "Mosaic:",IDC_STATIC,80,75,37,8 - LTEXT "",IDC_MOSAIC,130,75,53,8 + LTEXT "",IDC_MOSAIC,130,75,53,8,SS_NOPREFIX LTEXT "Overflow:",IDC_STATIC,80,85,37,8 - LTEXT "",IDC_OVERFLOW,130,85,53,8 + LTEXT "",IDC_OVERFLOW,130,85,53,8,SS_NOPREFIX LTEXT "Address:",IDC_STATIC,80,105,37,8 - LTEXT "",IDC_ADDRESS,130,105,53,8 + LTEXT "",IDC_ADDRESS,130,105,53,8,SS_NOPREFIX LTEXT "Tile:",IDC_STATIC,80,115,37,8 - LTEXT "",IDC_TILE_NUM,130,115,53,8 + LTEXT "",IDC_TILE_NUM,130,115,53,8,SS_NOPREFIX LTEXT "Flip:",IDC_STATIC,80,125,37,8 - LTEXT "",IDC_FLIP,130,125,53,8 + LTEXT "",IDC_FLIP,130,125,53,8,SS_NOPREFIX LTEXT "Palette:",IDC_STATIC,80,135,37,8 - LTEXT "",IDC_PALETTE_NUM,130,135,53,8 + LTEXT "",IDC_PALETTE_NUM,130,135,53,8,SS_NOPREFIX END -IDD_PALETTE_VIEW DIALOG DISCARDABLE 0, 0, 316, 266 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_PALETTE_VIEW DIALOG 0, 0, 316, 266 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Palette View" FONT 8, "MS Sans Serif" BEGIN @@ -516,15 +451,13 @@ PUSHBUTTON "Save OBJ...",IDC_SAVE_OBJ,98,245,50,14 PUSHBUTTON "&Refresh",IDC_REFRESH2,166,245,50,14 PUSHBUTTON "&Close",IDC_CLOSE,234,245,50,14 - LTEXT "",IDC_ADDRESS,53,168,50,8 - LTEXT "",IDC_R,53,180,50,8 - LTEXT "",IDC_G,53,192,50,8 - LTEXT "",IDC_B,53,204,50,8 - LTEXT "",IDC_VALUE,53,216,50,8 - CONTROL "Custom1",IDC_COLOR,"VbaColorControl",WS_TABSTOP,161,168, - 50,50 - CONTROL "PaletteViewBG",IDC_PALETTE_VIEW,"VbaPaletteViewControl", - WS_TABSTOP,12,30,128,128 + LTEXT "",IDC_ADDRESS,53,168,50,8,SS_NOPREFIX + LTEXT "",IDC_R,53,180,50,8,SS_NOPREFIX + LTEXT "",IDC_G,53,192,50,8,SS_NOPREFIX + LTEXT "",IDC_B,53,204,50,8,SS_NOPREFIX + LTEXT "",IDC_VALUE,53,216,50,8,SS_NOPREFIX + CONTROL "Custom1",IDC_COLOR,"VbaColorControl",WS_TABSTOP,161,168,50,50 + CONTROL "PaletteViewBG",IDC_PALETTE_VIEW,"VbaPaletteViewControl",WS_TABSTOP,12,30,128,128 CONTROL "PaletteViewBG",IDC_PALETTE_VIEW_OBJ, "VbaPaletteViewControl",WS_TABSTOP,166,30,128,128 GROUPBOX "Background",IDC_STATIC,7,20,137,143 @@ -534,73 +467,57 @@ LTEXT "G:",IDC_STATIC,7,192,43,8 LTEXT "B:",IDC_STATIC,7,204,38,8 LTEXT "Value:",IDC_STATIC,7,216,38,8 - LTEXT "Click on a color for more information",IDC_STATIC,7,7, - 302,8 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,229,71,10 + LTEXT "Click on a color for more information",IDC_STATIC,7,7,302,8 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,229,71,10 END -IDD_MEM_VIEWER DIALOG DISCARDABLE 0, 0, 380, 178 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_MEM_VIEWER DIALOG 0, 0, 380, 178 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Memory viewer" FONT 8, "MS Sans Serif" BEGIN - COMBOBOX IDC_ADDRESSES,7,7,109,30,CBS_DROPDOWNLIST | WS_VSCROLL | - WS_TABSTOP - CONTROL "8-bit",IDC_8_BIT,"Button",BS_AUTORADIOBUTTON | WS_GROUP, - 120,9,29,10 - CONTROL "16-bit",IDC_16_BIT,"Button",BS_AUTORADIOBUTTON,154,9,33, - 10 - CONTROL "32-bit",IDC_32_BIT,"Button",BS_AUTORADIOBUTTON,192,9,33, - 10 - EDITTEXT IDC_ADDRESS,238,7,82,14,ES_UPPERCASE | ES_AUTOHSCROLL | - ES_WANTRETURN | WS_GROUP + COMBOBOX IDC_ADDRESSES,7,7,109,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "8-bit",IDC_8_BIT,"Button",BS_AUTORADIOBUTTON | WS_GROUP,120,9,29,10 + CONTROL "16-bit",IDC_16_BIT,"Button",BS_AUTORADIOBUTTON,154,9,33,10 + CONTROL "32-bit",IDC_32_BIT,"Button",BS_AUTORADIOBUTTON,192,9,33,10 + EDITTEXT IDC_ADDRESS,238,7,82,14,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_GROUP DEFPUSHBUTTON "&Go",IDC_GO,323,7,50,14,WS_GROUP - CONTROL "Viewer",IDC_VIEWER,"VbaMemoryViewer",WS_TABSTOP,7,22, - 366,112 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,139,71,10 + CONTROL "Viewer",IDC_VIEWER,"VbaMemoryViewer",WS_TABSTOP,7,22,366,112 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,139,71,10 PUSHBUTTON "&Refresh",IDC_REFRESH,67,157,50,14 PUSHBUTTON "&Load...",IDC_LOAD,132,157,50,14 PUSHBUTTON "&Save...",IDC_SAVE,197,157,50,14 PUSHBUTTON "&Close",IDC_CLOSE,262,157,50,14 - LTEXT "Current address:",IDC_CURRENT_ADDRESS_LABEL,210,142,77, - 8 - EDITTEXT IDC_CURRENT_ADDRESS,291,139,82,14,ES_RIGHT | - ES_AUTOHSCROLL | WS_DISABLED + LTEXT "Current address:",IDC_CURRENT_ADDRESS_LABEL,210,142,77,8 + EDITTEXT IDC_CURRENT_ADDRESS,291,139,82,14,ES_RIGHT | ES_AUTOHSCROLL | WS_DISABLED END -IDD_OAM_VIEW DIALOG DISCARDABLE 0, 0, 234, 185 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_OAM_VIEW DIALOG 0, 0, 234, 185 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Oam Viewer" FONT 8, "MS Sans Serif" BEGIN - EDITTEXT IDC_SPRITE,7,19,76,14,ES_RIGHT | ES_AUTOHSCROLL | - ES_NUMBER + EDITTEXT IDC_SPRITE,7,19,76,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER SCROLLBAR IDC_SCROLLBAR,7,33,76,11 - CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,138,79,10 + CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,138,79,10 PUSHBUTTON "&Refresh",IDC_REFRESH,7,164,50,14,WS_GROUP PUSHBUTTON "&Save...",IDC_SAVE,91,164,50,14,WS_GROUP PUSHBUTTON "&Close",IDC_CLOSE,177,164,50,14 - CONTROL "MapView",IDC_OAM_VIEW,"VbaBitmapControl",WS_GROUP | - WS_TABSTOP,87,7,64,64 - CONTROL "Zoom",IDC_OAM_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | - WS_TABSTOP,163,7,64,64 - CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,87,79,48, - 47 - LTEXT "",IDC_POS,31,47,50,8 - LTEXT "",IDC_MODE,31,57,50,8 - LTEXT "",IDC_COLORS,31,67,50,8 - LTEXT "",IDC_PALETTE,31,77,50,8 - LTEXT "",IDC_TILE,31,87,50,8 - LTEXT "",IDC_PRIO,31,97,50,8 - LTEXT "",IDC_SIZE2,31,107,50,8 - LTEXT "",IDC_ROT,31,117,50,8 - LTEXT "",IDC_FLAGS,31,127,50,8 - LTEXT "",IDC_R,145,88,50,8 - LTEXT "",IDC_G,145,100,50,8 - LTEXT "",IDC_B,145,112,50,8 + CONTROL "MapView",IDC_OAM_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,87,7,64,64 + CONTROL "Zoom",IDC_OAM_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,163,7,64,64 + CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,87,79,48,47 + LTEXT "",IDC_POS,31,47,50,8,SS_NOPREFIX + LTEXT "",IDC_MODE,31,57,50,8,SS_NOPREFIX + LTEXT "",IDC_COLORS,31,67,50,8,SS_NOPREFIX + LTEXT "",IDC_PALETTE,31,77,50,8,SS_NOPREFIX + LTEXT "",IDC_TILE,31,87,50,8,SS_NOPREFIX + LTEXT "",IDC_PRIO,31,97,50,8,SS_NOPREFIX + LTEXT "",IDC_SIZE2,31,107,50,8,SS_NOPREFIX + LTEXT "",IDC_ROT,31,117,50,8,SS_NOPREFIX + LTEXT "",IDC_FLAGS,31,127,50,8,SS_NOPREFIX + LTEXT "",IDC_R,145,88,50,8,SS_NOPREFIX + LTEXT "",IDC_G,145,100,50,8,SS_NOPREFIX + LTEXT "",IDC_B,145,112,50,8,SS_NOPREFIX LTEXT "Pos:",IDC_STATIC,7,47,24,8 LTEXT "Mode:",IDC_STATIC,7,57,24,8 LTEXT "Colors:",IDC_STATIC,7,67,24,8 @@ -611,21 +528,18 @@ LTEXT "Sprite:",IDC_STATIC,7,7,50,8 LTEXT "Rot.:",IDC_STATIC,7,117,24,8 LTEXT "Flags:",IDC_STATIC,7,127,24,8 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,150,71,10 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,150,71,10 END -IDD_ACCEL_EDITOR DIALOG DISCARDABLE 0, 0, 280, 121 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_ACCEL_EDITOR DIALOG 0, 0, 280, 121 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Accelerator editor" FONT 8, "MS Sans Serif" BEGIN LTEXT "&Commands:",IDC_STATIC,9,9,38,8 - LISTBOX IDC_COMMANDS,9,18,100,67,LBS_SORT | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_COMMANDS,9,18,100,67,LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "Current &Keys:",IDC_STATIC1,113,9,43,8 - LISTBOX IDC_CURRENTS,113,18,100,67,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_CURRENTS,113,18,100,67,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK",ID_OK,223,9,50,14 PUSHBUTTON "Cancel",ID_CANCEL,223,25,50,14 LTEXT "Select &New Shortcut Key:",IDC_STATIC3,113,90,82,8 @@ -633,70 +547,52 @@ PUSHBUTTON "&Assign",IDC_ASSIGN,223,70,50,14 PUSHBUTTON "&Remove",IDC_REMOVE,223,86,50,14 PUSHBUTTON "Re&set All",IDC_RESET,223,102,50,14 - LTEXT "Static",IDC_ALREADY_AFFECTED,9,102,100,12, - SS_CENTERIMAGE + LTEXT "Static",IDC_ALREADY_AFFECTED,9,102,100,12,SS_CENTERIMAGE LTEXT "Currently assigned to :",IDC_STATIC2,9,90,73,10 END -IDD_TILE_VIEWER DIALOG DISCARDABLE 0, 0, 326, 266 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_TILE_VIEWER DIALOG 0, 0, 326, 266 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Tile Viewer" FONT 8, "MS Sans Serif" BEGIN - CONTROL "16",IDC_16_COLORS,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,13,20,24,10 - CONTROL "256",IDC_256_COLORS,"Button",BS_AUTORADIOBUTTON,13,30, - 28,10 - CONTROL "0x6000000",IDC_CHARBASE_0,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,13,57,51,10 - CONTROL "0x6004000",IDC_CHARBASE_1,"Button",BS_AUTORADIOBUTTON, - 13,67,51,10 - CONTROL "0x6008000",IDC_CHARBASE_2,"Button",BS_AUTORADIOBUTTON, - 13,77,51,10 - CONTROL "0x600C000",IDC_CHARBASE_3,"Button",BS_AUTORADIOBUTTON, - 13,87,52,10 - CONTROL "0x6010000",IDC_CHARBASE_4,"Button",BS_AUTORADIOBUTTON, - 13,97,49,10 - CONTROL "Slider1",IDC_PALETTE_SLIDER,"msctls_trackbar32", - TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,1,124,76,22 - CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,149,79,10 + CONTROL "16",IDC_16_COLORS,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,20,24,10 + CONTROL "256",IDC_256_COLORS,"Button",BS_AUTORADIOBUTTON,13,30,28,10 + CONTROL "0x6000000",IDC_CHARBASE_0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,57,51,10 + CONTROL "0x6004000",IDC_CHARBASE_1,"Button",BS_AUTORADIOBUTTON,13,67,51,10 + CONTROL "0x6008000",IDC_CHARBASE_2,"Button",BS_AUTORADIOBUTTON,13,77,51,10 + CONTROL "0x600C000",IDC_CHARBASE_3,"Button",BS_AUTORADIOBUTTON,13,87,52,10 + CONTROL "0x6010000",IDC_CHARBASE_4,"Button",BS_AUTORADIOBUTTON,13,97,49,10 + CONTROL "Slider1",IDC_PALETTE_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,1,124,76,22 + CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,149,79,10 PUSHBUTTON "Refresh",IDC_REFRESH,7,245,50,14,WS_GROUP PUSHBUTTON "Save...",IDC_SAVE,138,245,50,14 PUSHBUTTON "Close",IDC_CLOSE,269,245,50,14 - CONTROL "Custom1",IDC_TILE_VIEW,"VbaBitmapControl",WS_GROUP | - WS_TABSTOP,191,7,128,128 + CONTROL "Custom1",IDC_TILE_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,191,7,128,128 GROUPBOX "Colors",IDC_STATIC,7,7,66,38 GROUPBOX "Char Base",IDC_STATIC,7,46,65,64 - CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | - WS_TABSTOP,7,174,64,64 - CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,98,183,48, - 47 - LTEXT "",IDC_R,156,192,50,8 - LTEXT "",IDC_G,156,204,50,8 - LTEXT "",IDC_B,156,216,50,8 + CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,174,64,64 + CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,98,183,48,47 + LTEXT "",IDC_R,156,192,50,8,SS_NOPREFIX + LTEXT "",IDC_G,156,204,50,8,SS_NOPREFIX + LTEXT "",IDC_B,156,216,50,8,SS_NOPREFIX LTEXT "Palette:",IDC_STATIC,7,113,65,8 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,160,71,10 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,160,71,10 LTEXT "Tile:",IDC_STATIC,79,14,41,8 LTEXT "Address:",IDC_STATIC,79,26,41,8 - LTEXT "",IDC_TILE_NUMBER,135,14,50,8 - LTEXT "",IDC_ADDRESS,135,26,50,8 + LTEXT "",IDC_TILE_NUMBER,135,14,50,8,SS_NOPREFIX + LTEXT "",IDC_ADDRESS,135,26,50,8,SS_NOPREFIX END -IDD_GB_COLORS DIALOG DISCARDABLE 0, 0, 169, 121 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GB_COLORS DIALOG 0, 0, 169, 121 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Gameboy Mono Colors" FONT 8, "MS Sans Serif" BEGIN - CONTROL "Default",IDC_DEFAULT,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,7,7,39,10 - CONTROL "User 1",IDC_USER1,"Button",BS_AUTORADIOBUTTON,67,7,37, - 10 - CONTROL "User 2",IDC_USER2,"Button",BS_AUTORADIOBUTTON,125,7,37, - 10 - COMBOBOX IDC_PREDEFINED,7,21,155,30,CBS_DROPDOWNLIST | CBS_SORT | - WS_VSCROLL | WS_TABSTOP + CONTROL "Default",IDC_DEFAULT,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,7,39,10 + CONTROL "User 1",IDC_USER1,"Button",BS_AUTORADIOBUTTON,67,7,37,10 + CONTROL "User 2",IDC_USER2,"Button",BS_AUTORADIOBUTTON,125,7,37,10 + COMBOBOX IDC_PREDEFINED,7,21,155,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "",IDC_COLOR_BG0,15,47,28,14,WS_GROUP PUSHBUTTON "",IDC_COLOR_BG1,52,47,28,14 PUSHBUTTON "",IDC_COLOR_BG2,89,47,28,14 @@ -712,23 +608,18 @@ GROUPBOX "Sprite",IDC_STATIC,8,67,154,30 END -IDD_DISASSEMBLE DIALOG DISCARDABLE 0, 0, 402, 225 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_DISASSEMBLE DIALOG 0, 0, 402, 225 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Disassemble" FONT 8, "MS Sans Serif" BEGIN - CONTROL "Automatic",IDC_AUTOMATIC,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,7,9,47,10 + CONTROL "Automatic",IDC_AUTOMATIC,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,9,47,10 CONTROL "ARM",IDC_ARM,"Button",BS_AUTORADIOBUTTON,62,9,32,10 - CONTROL "THUMB",IDC_THUMB,"Button",BS_AUTORADIOBUTTON,103,9,42, - 10 - EDITTEXT IDC_ADDRESS,158,7,65,14,ES_UPPERCASE | ES_AUTOHSCROLL | - WS_GROUP + CONTROL "THUMB",IDC_THUMB,"Button",BS_AUTORADIOBUTTON,103,9,42,10 + EDITTEXT IDC_ADDRESS,158,7,65,14,ES_UPPERCASE | ES_AUTOHSCROLL | WS_GROUP DEFPUSHBUTTON "Go",IDC_GO,232,7,50,14 - LISTBOX IDC_DISASSEMBLE,7,25,276,161,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_TABSTOP - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,191,71,10 + LISTBOX IDC_DISASSEMBLE,7,25,276,161,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_TABSTOP + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,191,71,10 PUSHBUTTON "Refresh",IDC_REFRESH,120,204,50,14 PUSHBUTTON "Next",IDC_NEXT,233,204,50,14 PUSHBUTTON "Close",IDC_CLOSE,346,204,50,14 @@ -740,22 +631,22 @@ LTEXT "R5:",IDC_STATIC,309,47,18,8 LTEXT "R6:",IDC_STATIC,309,55,18,8 LTEXT "R7:",IDC_STATIC,309,63,18,8 - LTEXT "",IDC_R0,344,7,52,8 - LTEXT "",IDC_R1,344,15,52,8 - LTEXT "",IDC_R2,344,23,52,8 - LTEXT "",IDC_R3,344,31,52,8 - LTEXT "",IDC_R4,344,39,52,8 - LTEXT "",IDC_R5,344,47,52,8 - LTEXT "",IDC_R6,344,55,52,8 - LTEXT "",IDC_R7,344,63,52,8 - LTEXT "",IDC_R8,344,71,52,8 - LTEXT "",IDC_R9,344,79,52,8 - LTEXT "",IDC_R10,344,87,52,8 - LTEXT "",IDC_R11,344,95,52,8 - LTEXT "",IDC_R12,344,103,52,8 - LTEXT "",IDC_R13,344,111,52,8 - LTEXT "",IDC_R14,344,119,52,8 - LTEXT "",IDC_R15,344,127,52,8 + LTEXT "",IDC_R0,344,7,52,8,SS_NOPREFIX + LTEXT "",IDC_R1,344,15,52,8,SS_NOPREFIX + LTEXT "",IDC_R2,344,23,52,8,SS_NOPREFIX + LTEXT "",IDC_R3,344,31,52,8,SS_NOPREFIX + LTEXT "",IDC_R4,344,39,52,8,SS_NOPREFIX + LTEXT "",IDC_R5,344,47,52,8,SS_NOPREFIX + LTEXT "",IDC_R6,344,55,52,8,SS_NOPREFIX + LTEXT "",IDC_R7,344,63,52,8,SS_NOPREFIX + LTEXT "",IDC_R8,344,71,52,8,SS_NOPREFIX + LTEXT "",IDC_R9,344,79,52,8,SS_NOPREFIX + LTEXT "",IDC_R10,344,87,52,8,SS_NOPREFIX + LTEXT "",IDC_R11,344,95,52,8,SS_NOPREFIX + LTEXT "",IDC_R12,344,103,52,8,SS_NOPREFIX + LTEXT "",IDC_R13,344,111,52,8,SS_NOPREFIX + LTEXT "",IDC_R14,344,119,52,8,SS_NOPREFIX + LTEXT "",IDC_R15,344,127,52,8,SS_NOPREFIX LTEXT "R8:",IDC_STATIC,309,71,18,8 LTEXT "R9:",IDC_STATIC,309,79,18,8 LTEXT "R10:",IDC_STATIC,309,87,18,8 @@ -764,30 +655,23 @@ LTEXT "R13:",IDC_STATIC,309,111,18,8 LTEXT "R14:",IDC_STATIC,309,119,18,8 LTEXT "R15:",IDC_STATIC,309,127,18,8 - LTEXT "",IDC_R16,344,135,52,8 + LTEXT "",IDC_R16,344,135,52,8,SS_NOPREFIX LTEXT "R16:",IDC_STATIC,309,135,20,8 - CONTROL "N",IDC_N,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,309,146,21,10 - CONTROL "Z",IDC_Z,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,309,156,21,10 - CONTROL "C",IDC_C,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,309,166,21,10 - CONTROL "V",IDC_V,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,309,176,21,10 - CONTROL "F",IDC_F,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,342,156,20,10 - CONTROL "I",IDC_I,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,342,146,18,10 - CONTROL "T",IDC_T,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,342,166,21,10 + CONTROL "N",IDC_N,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,309,146,21,10 + CONTROL "Z",IDC_Z,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,309,156,21,10 + CONTROL "C",IDC_C,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,309,166,21,10 + CONTROL "V",IDC_V,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,309,176,21,10 + CONTROL "F",IDC_F,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,342,156,20,10 + CONTROL "I",IDC_I,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,342,146,18,10 + CONTROL "T",IDC_T,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,342,166,21,10 LTEXT "Mode:",IDC_STATIC,341,176,21,8 - LTEXT "",IDC_MODE,376,176,20,8 + LTEXT "",IDC_MODE,376,176,20,8,SS_NOPREFIX SCROLLBAR IDC_VSCROLL,283,25,10,161,SBS_VERT PUSHBUTTON "Goto R15",IDC_GOPC,7,204,50,14 END -IDD_GDB_PORT DIALOG DISCARDABLE 0, 0, 186, 51 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GDB_PORT DIALOG 0, 0, 186, 51 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "GDB connection" FONT 8, "MS Sans Serif" BEGIN @@ -797,58 +681,46 @@ EDITTEXT IDC_PORT,125,7,54,14,ES_RIGHT | ES_AUTOHSCROLL END -IDD_GDB_WAITING DIALOG DISCARDABLE 0, 0, 186, 44 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_GDB_WAITING DIALOG 0, 0, 186, 44 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Waiting..." FONT 8, "MS Sans Serif" BEGIN PUSHBUTTON "Cancel",ID_CANCEL,67,23,50,14 LTEXT "Waiting for connection on port:",IDC_STATIC,7,7,117,8 - LTEXT "",IDC_PORT,143,7,36,8 + LTEXT "",IDC_PORT,143,7,36,8,SS_NOPREFIX END -IDD_LOGGING DIALOG DISCARDABLE 0, 0, 366, 218 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_LOGGING DIALOG 0, 0, 366, 218 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Logging" FONT 8, "MS Sans Serif" BEGIN - CONTROL "SWI",IDC_VERBOSE_SWI,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,10,17,87,10 - CONTROL "Unaligned memory",IDC_VERBOSE_UNALIGNED_ACCESS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,10,30,87,10 - CONTROL "Illegal write",IDC_VERBOSE_ILLEGAL_WRITE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,10,43,87,10 - CONTROL "Illegal read",IDC_VERBOSE_ILLEGAL_READ,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,10,56,87,10 - CONTROL "DMA 0",IDC_VERBOSE_DMA0,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,10,69,87,10 - CONTROL "DMA 1",IDC_VERBOSE_DMA1,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,10,82,87,10 - CONTROL "DMA 2",IDC_VERBOSE_DMA2,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,10,95,87,10 - CONTROL "DMA 3",IDC_VERBOSE_DMA3,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,10,108,87,10 - CONTROL "Undefined instruction",IDC_VERBOSE_UNDEFINED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,10,121,87,10 - CONTROL "AGBPrint",IDC_VERBOSE_AGBPRINT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,10,134,87,10 - EDITTEXT IDC_LOG,107,7,252,183,ES_MULTILINE | ES_AUTOVSCROLL | - ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL + CONTROL "SWI",IDC_VERBOSE_SWI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,17,87,10 + CONTROL "Unaligned memory",IDC_VERBOSE_UNALIGNED_ACCESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,30,87,10 + CONTROL "Illegal write",IDC_VERBOSE_ILLEGAL_WRITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,43,87,10 + CONTROL "Illegal read",IDC_VERBOSE_ILLEGAL_READ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,56,87,10 + CONTROL "DMA 0",IDC_VERBOSE_DMA0,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,69,87,10 + CONTROL "DMA 1",IDC_VERBOSE_DMA1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,82,87,10 + CONTROL "DMA 2",IDC_VERBOSE_DMA2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,95,87,10 + CONTROL "DMA 3",IDC_VERBOSE_DMA3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,108,87,10 + CONTROL "Undefined instruction",IDC_VERBOSE_UNDEFINED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,121,87,10 + CONTROL "AGBPrint",IDC_VERBOSE_AGBPRINT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,134,87,10 + EDITTEXT IDC_LOG,107,7,252,183,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL PUSHBUTTON "Save...",IDC_SAVE,75,197,50,14 PUSHBUTTON "Clear",IDC_CLEAR,137,197,50,14 DEFPUSHBUTTON "OK",ID_OK,197,197,50,14 GROUPBOX "Verbose",IDC_STATIC,7,7,93,142 END -IDD_EXPORT_SPS DIALOG DISCARDABLE 0, 0, 248, 148 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_EXPORT_SPS DIALOG 0, 0, 248, 148 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Export Gameshark Snapshot" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_TITLE,84,7,157,14,ES_AUTOHSCROLL EDITTEXT IDC_DESC,84,27,157,14,ES_AUTOHSCROLL - EDITTEXT IDC_NOTES,84,47,157,73,ES_MULTILINE | ES_AUTOHSCROLL | - ES_WANTRETURN + EDITTEXT IDC_NOTES,84,47,157,73,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN DEFPUSHBUTTON "OK",ID_OK,67,127,50,14 PUSHBUTTON "Cancel",ID_CANCEL,130,127,50,14 LTEXT "Title:",IDC_STATIC,7,8,62,8 @@ -856,8 +728,8 @@ LTEXT "Notes:",IDC_STATIC,7,48,60,8 END -IDD_ADDR_SIZE DIALOG DISCARDABLE 0, 0, 186, 67 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_ADDR_SIZE DIALOG 0, 0, 186, 67 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Enter address and size" FONT 8, "MS Sans Serif" BEGIN @@ -869,54 +741,48 @@ LTEXT "Size:",IDC_STATIC,7,29,65,8 END -IDD_MODES DIALOG DISCARDABLE 0, 0, 208, 129 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_MODES DIALOG 0, 0, 208, 129 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Select video mode" FONT 8, "MS Sans Serif" BEGIN - LISTBOX IDC_MODES,7,18,194,80,LBS_SORT | LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_MODES,7,18,194,80,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK",ID_OK,45,108,50,14 PUSHBUTTON "Cancel",ID_CANCEL,112,108,50,14 LTEXT "Available video modes:",IDC_STATIC,7,7,194,8 END -IDD_DRIVERS DIALOG DISCARDABLE 0, 0, 208, 121 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_DRIVERS DIALOG 0, 0, 208, 121 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Select video driver" FONT 8, "MS Sans Serif" BEGIN - LISTBOX IDC_DRIVERS,7,17,194,80,LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_DRIVERS,7,17,194,80,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK",ID_OK,45,104,50,14 PUSHBUTTON "Cancel",ID_CANCEL,112,104,50,14 LTEXT "Available drivers:",IDC_STATIC,7,7,194,8 END -IDD_THROTTLE DIALOG DISCARDABLE 0, 0, 186, 63 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_THROTTLE DIALOG 0, 0, 186, 63 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Throttle" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_THROTTLE,7,20,172,14,ES_AUTOHSCROLL DEFPUSHBUTTON "OK",ID_OK,37,42,50,14 PUSHBUTTON "Cancel",ID_CANCEL,99,42,50,14 - LTEXT "Enter desired throttle (5%...1000%):",IDC_STATIC,7,7, - 172,8 + LTEXT "Enter desired throttle (5%...1000%):",IDC_STATIC,7,7,172,8 END -IDD_GB_DISASSEMBLE DIALOG DISCARDABLE 0, 0, 344, 225 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_GB_DISASSEMBLE DIALOG 0, 0, 344, 225 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "GB Disassemble" FONT 8, "MS Sans Serif" BEGIN - EDITTEXT IDC_ADDRESS,7,7,65,14,ES_UPPERCASE | ES_AUTOHSCROLL | - WS_GROUP + EDITTEXT IDC_ADDRESS,7,7,65,14,ES_UPPERCASE | ES_AUTOHSCROLL | WS_GROUP DEFPUSHBUTTON "Go",IDC_GO,81,7,50,14 - LISTBOX IDC_DISASSEMBLE,7,25,222,161,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_TABSTOP - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,191,71,10 + LISTBOX IDC_DISASSEMBLE,7,25,222,161,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_TABSTOP + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,191,71,10 PUSHBUTTON "Refresh",IDC_REFRESH,100,204,50,14 PUSHBUTTON "Next",IDC_NEXT,193,204,50,14 PUSHBUTTON "Close",IDC_CLOSE,287,204,50,14 @@ -925,55 +791,48 @@ LTEXT "DE:",IDC_STATIC,250,45,18,8 LTEXT "HL:",IDC_STATIC,250,55,18,8 LTEXT "IFF:",IDC_STATIC,250,85,18,8 - LTEXT "",IDC_R0,285,25,52,8 - LTEXT "",IDC_R1,285,35,52,8 - LTEXT "",IDC_R2,285,45,52,8 - LTEXT "",IDC_R3,285,55,52,8 - LTEXT "",IDC_R6,285,85,52,8 - CONTROL "N",IDC_N,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,250,109,21,10 - CONTROL "Z",IDC_Z,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,250,97,21,10 - CONTROL "C",IDC_C,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,250,133,21,10 - CONTROL "H",IDC_H,"Button",BS_AUTOCHECKBOX | WS_DISABLED | - WS_TABSTOP,250,121,21,10 + LTEXT "LY:",IDC_STATIC,272,95,18,8 + LTEXT "",IDC_R0,285,25,52,8,SS_NOPREFIX + LTEXT "",IDC_R1,285,35,52,8,SS_NOPREFIX + LTEXT "",IDC_R2,285,45,52,8,SS_NOPREFIX + LTEXT "",IDC_R3,285,55,52,8,SS_NOPREFIX + LTEXT "",IDC_R6,285,85,52,8,SS_NOPREFIX + LTEXT "",IDC_LY,285,95,52,8,SS_NOPREFIX + CONTROL "N",IDC_N,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,109,21,10 + CONTROL "Z",IDC_Z,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,97,21,10 + CONTROL "C",IDC_C,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,133,21,10 + CONTROL "H",IDC_H,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,121,21,10 SCROLLBAR IDC_VSCROLL,229,25,10,161,SBS_VERT PUSHBUTTON "Goto PC",IDC_GOPC,7,204,50,14 LTEXT "SP:",IDC_STATIC,250,65,18,8 - LTEXT "",IDC_R4,285,65,52,8 + LTEXT "",IDC_R4,285,65,52,8,SS_NOPREFIX LTEXT "PC:",IDC_STATIC,250,75,18,8 - LTEXT "",IDC_R5,285,75,52,8 + LTEXT "",IDC_R5,285,75,52,8,SS_NOPREFIX END -IDD_GB_OAM_VIEW DIALOG DISCARDABLE 0, 0, 234, 185 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +IDD_GB_OAM_VIEW DIALOG 0, 0, 234, 185 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "GB Oam Viewer" FONT 8, "MS Sans Serif" BEGIN - EDITTEXT IDC_SPRITE,7,19,76,14,ES_RIGHT | ES_AUTOHSCROLL | - ES_NUMBER + EDITTEXT IDC_SPRITE,7,19,76,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER SCROLLBAR IDC_SCROLLBAR,7,33,76,11 - CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,138,79,10 + CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,138,79,10 PUSHBUTTON "&Refresh",IDC_REFRESH,7,164,50,14,WS_GROUP PUSHBUTTON "&Save...",IDC_SAVE,91,164,50,14,WS_GROUP PUSHBUTTON "&Close",IDC_CLOSE,177,164,50,14 - CONTROL "MapView",IDC_OAM_VIEW,"VbaBitmapControl",WS_GROUP | - WS_TABSTOP,87,7,64,64 - CONTROL "Zoom",IDC_OAM_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | - WS_TABSTOP,163,7,64,64 - CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,87,79,48, - 47 - LTEXT "",IDC_POS,31,47,50,8 - LTEXT "",IDC_PALETTE,31,87,50,8 - LTEXT "",IDC_TILE,31,57,50,8 - LTEXT "",IDC_PRIO,31,67,50,8 - LTEXT "",IDC_OAP,31,77,50,8 - LTEXT "",IDC_FLAGS,31,97,50,8 - LTEXT "",IDC_R,145,88,50,8 - LTEXT "",IDC_G,145,100,50,8 - LTEXT "",IDC_B,145,112,50,8 + CONTROL "MapView",IDC_OAM_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,87,7,64,64 + CONTROL "Zoom",IDC_OAM_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,163,7,64,64 + CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,87,79,48,47 + LTEXT "",IDC_POS,31,47,50,8,SS_NOPREFIX + LTEXT "",IDC_PALETTE,31,87,50,8,SS_NOPREFIX + LTEXT "",IDC_TILE,31,57,50,8,SS_NOPREFIX + LTEXT "",IDC_PRIO,31,67,50,8,SS_NOPREFIX + LTEXT "",IDC_OAP,31,77,50,8,SS_NOPREFIX + LTEXT "",IDC_FLAGS,31,97,50,8,SS_NOPREFIX + LTEXT "",IDC_R,145,88,50,8,SS_NOPREFIX + LTEXT "",IDC_G,145,100,50,8,SS_NOPREFIX + LTEXT "",IDC_B,145,112,50,8,SS_NOPREFIX LTEXT "Pos:",IDC_STATIC,7,47,24,8 LTEXT "Pal:",IDC_STATIC,7,87,24,8 LTEXT "Tile:",IDC_STATIC,7,57,24,8 @@ -981,96 +840,78 @@ LTEXT "OAP:",IDC_STATIC,7,77,24,8 LTEXT "Sprite:",IDC_STATIC,7,7,50,8 LTEXT "Flags:",IDC_STATIC,7,97,24,8 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,150,71,10 - LTEXT "",IDC_BANK,31,107,50,8 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,150,71,10 + LTEXT "",IDC_BANK,31,107,50,8,SS_NOPREFIX LTEXT "Bank:",IDC_STATIC,7,107,24,8 END -IDD_GB_TILE_VIEWER DIALOG DISCARDABLE 0, 0, 326, 238 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +IDD_GB_TILE_VIEWER DIALOG 0, 0, 326, 238 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "GB Tile Viewer" FONT 8, "MS Sans Serif" BEGIN - CONTROL "0",IDC_BANK_0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13, - 20,20,10 + CONTROL "0",IDC_BANK_0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,20,20,10 CONTROL "1",IDC_BANK_1,"Button",BS_AUTORADIOBUTTON,13,30,20,10 - CONTROL "0x8000",IDC_CHARBASE_0,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,13,57,39,10 - CONTROL "0x8800",IDC_CHARBASE_1,"Button",BS_AUTORADIOBUTTON,13, - 67,39,10 - CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,122,79,10 + CONTROL "0x8000",IDC_CHARBASE_0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,57,39,10 + CONTROL "0x8800",IDC_CHARBASE_1,"Button",BS_AUTORADIOBUTTON,13,67,39,10 + CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,79,10 PUSHBUTTON "Refresh",IDC_REFRESH,7,217,50,14,WS_GROUP PUSHBUTTON "Save...",IDC_SAVE,138,217,50,14 PUSHBUTTON "Close",IDC_CLOSE,269,217,50,14 - CONTROL "Custom1",IDC_TILE_VIEW,"VbaBitmapControl",WS_GROUP | - WS_TABSTOP,191,7,128,128 + CONTROL "Custom1",IDC_TILE_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,191,7,128,128 GROUPBOX "VRAM Bank",IDC_STATIC,7,7,66,38 GROUPBOX "Char Base",IDC_STATIC,7,46,65,35 - CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | - WS_TABSTOP,7,147,64,64 - CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,98,156,48, - 47 - LTEXT "",IDC_R,156,164,50,8 - LTEXT "",IDC_G,156,176,50,8 - LTEXT "",IDC_B,156,188,50,8 + CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,147,64,64 + CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,98,156,48,47 + LTEXT "",IDC_R,156,164,50,8,SS_NOPREFIX + LTEXT "",IDC_G,156,176,50,8,SS_NOPREFIX + LTEXT "",IDC_B,156,188,50,8,SS_NOPREFIX LTEXT "Palette:",IDC_STATIC,7,86,65,8 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,133,71,10 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,133,71,10 LTEXT "Tile:",IDC_STATIC,79,14,41,8 LTEXT "Address:",IDC_STATIC,79,26,41,8 - LTEXT "",IDC_TILE_NUMBER,135,14,50,8 - LTEXT "",IDC_ADDRESS,135,26,50,8 - CONTROL "Slider1",IDC_PALETTE_SLIDER,"msctls_trackbar32", - TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,1,98,76,22 + LTEXT "",IDC_TILE_NUMBER,135,14,50,8,SS_NOPREFIX + LTEXT "",IDC_ADDRESS,135,26,50,8,SS_NOPREFIX + CONTROL "Slider1",IDC_PALETTE_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,1,98,76,22 END -IDD_GB_MAP_VIEW DIALOG DISCARDABLE 0, 0, 322, 238 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_GB_MAP_VIEW DIALOG 0, 0, 322, 238 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "GB Map Viewer" FONT 8, "MS Sans Serif" BEGIN - CONTROL "0x8000",IDC_BANK_0,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,13,22,39,10 - CONTROL "0x8800",IDC_BANK_1,"Button",BS_AUTORADIOBUTTON,13,36,39, - 10 - CONTROL "0x9800",IDC_BG0,"Button",BS_AUTORADIOBUTTON | WS_GROUP, - 13,63,39,10 + CONTROL "0x8000",IDC_BANK_0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,22,39,10 + CONTROL "0x8800",IDC_BANK_1,"Button",BS_AUTORADIOBUTTON,13,36,39,10 + CONTROL "0x9800",IDC_BG0,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,63,39,10 CONTROL "0x9C00",IDC_BG1,"Button",BS_AUTORADIOBUTTON,13,77,40,10 - CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,122,68,10 + CONTROL "Stretch to fit",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,68,10 PUSHBUTTON "&Refresh",IDC_REFRESH,25,217,50,14,WS_GROUP PUSHBUTTON "&Save...",IDC_SAVE,88,217,50,14,WS_GROUP PUSHBUTTON "&Close",IDC_CLOSE,155,217,50,14 - CONTROL "MapView",IDC_MAP_VIEW,"VbaBitmapControl",WS_GROUP | - WS_TABSTOP,187,15,128,128 - CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | - WS_TABSTOP,7,148,64,64 - CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,187,164, - 48,47 - LTEXT "",IDC_R,245,173,50,8 - LTEXT "",IDC_G,245,185,50,8 - LTEXT "",IDC_B,245,197,50,8 + CONTROL "MapView",IDC_MAP_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,187,15,128,128 + CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,148,64,64 + CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,187,164,48,47 + LTEXT "",IDC_R,245,173,50,8,SS_NOPREFIX + LTEXT "",IDC_G,245,185,50,8,SS_NOPREFIX + LTEXT "",IDC_B,245,197,50,8,SS_NOPREFIX GROUPBOX "Char Base",IDC_STATIC,7,11,63,37 GROUPBOX "Map Base",IDC_STATIC,7,52,63,41 - CONTROL "Auto update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,134,55,10 - LTEXT "",IDC_XY,129,18,53,8 + CONTROL "Auto update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,134,55,10 + LTEXT "",IDC_XY,129,18,53,8,SS_NOPREFIX LTEXT "Priority:",IDC_STATIC,80,68,37,8 - LTEXT "",IDC_PRIORITY,130,68,53,8 + LTEXT "",IDC_PRIORITY,130,68,53,8,SS_NOPREFIX LTEXT "Address:",IDC_STATIC,80,28,37,8 - LTEXT "",IDC_ADDRESS,130,28,53,8 + LTEXT "",IDC_ADDRESS,130,28,53,8,SS_NOPREFIX LTEXT "Tile:",IDC_STATIC,80,38,37,8 - LTEXT "",IDC_TILE_NUM,130,38,53,8 + LTEXT "",IDC_TILE_NUM,130,38,53,8,SS_NOPREFIX LTEXT "Flip:",IDC_STATIC,80,48,37,8 - LTEXT "",IDC_FLIP,130,48,53,8 + LTEXT "",IDC_FLIP,130,48,53,8,SS_NOPREFIX LTEXT "Palette:",IDC_STATIC,80,58,37,8 - LTEXT "",IDC_PALETTE_NUM,130,58,53,8 + LTEXT "",IDC_PALETTE_NUM,130,58,53,8,SS_NOPREFIX END -IDD_GB_PALETTE_VIEW DIALOG DISCARDABLE 0, 0, 196, 234 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +IDD_GB_PALETTE_VIEW DIALOG 0, 0, 196, 234 +STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "GB Palette Viewer" FONT 8, "MS Sans Serif" BEGIN @@ -1078,15 +919,13 @@ PUSHBUTTON "Save OBJ...",IDC_SAVE_OBJ,73,191,50,14 PUSHBUTTON "&Refresh",IDC_REFRESH2,139,191,50,14 PUSHBUTTON "&Close",IDC_CLOSE,73,213,50,14 - LTEXT "",IDC_ADDRESS,53,117,50,8 - LTEXT "",IDC_R,53,129,50,8 - LTEXT "",IDC_G,53,141,50,8 - LTEXT "",IDC_B,53,153,50,8 - LTEXT "",IDC_VALUE,53,165,50,8 - CONTROL "Custom1",IDC_COLOR,"VbaColorControl",WS_TABSTOP,119,117, - 50,50 - CONTROL "PaletteViewBG",IDC_PALETTE_VIEW,"VbaPaletteViewControl", - WS_TABSTOP,11,30,64,64 + LTEXT "",IDC_ADDRESS,53,117,50,8,SS_NOPREFIX + LTEXT "",IDC_R,53,129,50,8,SS_NOPREFIX + LTEXT "",IDC_G,53,141,50,8,SS_NOPREFIX + LTEXT "",IDC_B,53,153,50,8,SS_NOPREFIX + LTEXT "",IDC_VALUE,53,165,50,8,SS_NOPREFIX + CONTROL "Custom1",IDC_COLOR,"VbaColorControl",WS_TABSTOP,119,117,50,50 + CONTROL "PaletteViewBG",IDC_PALETTE_VIEW,"VbaPaletteViewControl",WS_TABSTOP,11,30,64,64 CONTROL "PaletteViewBG",IDC_PALETTE_VIEW_OBJ, "VbaPaletteViewControl",WS_TABSTOP,120,30,64,64 GROUPBOX "BG",IDC_STATIC,6,20,74,81 @@ -1096,111 +935,108 @@ LTEXT "G:",IDC_STATIC,7,141,43,8 LTEXT "B:",IDC_STATIC,7,153,38,8 LTEXT "Value:",IDC_STATIC,7,165,38,8 - LTEXT "Click on a color for more information",IDC_STATIC,7,7, - 182,8 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,178,71,10 + LTEXT "Click on a color for more information",IDC_STATIC,7,7,182,8 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,178,71,10 END -IDD_MODE_CONFIRM DIALOG DISCARDABLE 0, 0, 186, 57 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_MODE_CONFIRM DIALOG 0, 0, 186, 57 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Confirm mode" FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",ID_OK,31,36,50,14 PUSHBUTTON "Cancel",ID_CANCEL,103,36,50,14 - CTEXT "Do you want to keep the current mode?",IDC_STATIC,7,7, - 172,8 - CTEXT "",IDC_TIMER,7,19,172,8 + CTEXT "Do you want to keep the current mode?",IDC_STATIC,7,7,172,8 + CTEXT "",IDC_TIMER,7,19,172,8,SS_NOPREFIX,WS_EX_TOOLWINDOW END -IDD_REWIND_INTERVAL DIALOG DISCARDABLE 0, 0, 186, 68 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_REWIND_INTERVAL DIALOG 0, 0, 186, 68 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Select rewind interval" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_INTERVAL,7,28,172,14,ES_AUTOHSCROLL DEFPUSHBUTTON "OK",ID_OK,37,47,50,14 PUSHBUTTON "Cancel",ID_CANCEL,99,47,50,14 - LTEXT "Enter rewind interval (0...600) seconds:",IDC_STATIC,7, - 7,172,8 + LTEXT "Enter rewind interval (0...600) seconds:",IDC_STATIC,7,7,172,8 LTEXT "Enter 0 to disable rewind.",IDC_STATIC,7,17,172,8 END -IDD_IO_VIEWER DIALOG DISCARDABLE 0, 0, 269, 238 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +IDD_IO_VIEWER DIALOG 0, 0, 269, 238 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "I/O Viewer" FONT 8, "MS Sans Serif" BEGIN - COMBOBOX IDC_ADDRESSES,7,7,255,30,CBS_DROPDOWNLIST | WS_VSCROLL | - WS_TABSTOP + COMBOBOX IDC_ADDRESSES,7,7,255,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP RTEXT "",IDC_VALUE,103,23,159,8 - CONTROL "",IDC_BIT_15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,34, - 255,10 - CONTROL "",IDC_BIT_14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,44, - 255,10 - CONTROL "",IDC_BIT_13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,54, - 255,8 - CONTROL "",IDC_BIT_12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,64, - 255,10 - CONTROL "",IDC_BIT_11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,74, - 255,10 - CONTROL "",IDC_BIT_10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,84, - 255,10 - CONTROL "",IDC_BIT_9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,94, - 255,10 - CONTROL "",IDC_BIT_8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,104, - 255,10 - CONTROL "",IDC_BIT_7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,114, - 255,10 - CONTROL "",IDC_BIT_6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,124, - 255,10 - CONTROL "",IDC_BIT_5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,134, - 255,10 - CONTROL "",IDC_BIT_4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,144, - 255,10 - CONTROL "",IDC_BIT_3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,154, - 255,10 - CONTROL "",IDC_BIT_2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,164, - 255,10 - CONTROL "",IDC_BIT_1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,174, - 255,10 - CONTROL "",IDC_BIT_0,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,184, - 255,10 - CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,201,71,10 + CONTROL "",IDC_BIT_15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,34,255,10 + CONTROL "",IDC_BIT_14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,44,255,10 + CONTROL "",IDC_BIT_13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,54,255,8 + CONTROL "",IDC_BIT_12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,64,255,10 + CONTROL "",IDC_BIT_11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,74,255,10 + CONTROL "",IDC_BIT_10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,84,255,10 + CONTROL "",IDC_BIT_9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,94,255,10 + CONTROL "",IDC_BIT_8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,104,255,10 + CONTROL "",IDC_BIT_7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,114,255,10 + CONTROL "",IDC_BIT_6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,124,255,10 + CONTROL "",IDC_BIT_5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,134,255,10 + CONTROL "",IDC_BIT_4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,144,255,10 + CONTROL "",IDC_BIT_3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,154,255,10 + CONTROL "",IDC_BIT_2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,164,255,10 + CONTROL "",IDC_BIT_1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,174,255,10 + CONTROL "",IDC_BIT_0,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,184,255,10 + CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,201,71,10 DEFPUSHBUTTON "&Refresh",IDC_REFRESH,54,221,50,14 DEFPUSHBUTTON "&Apply",IDC_APPLY,110,221,50,14 PUSHBUTTON "&Close",IDC_CLOSE,166,221,50,14 LTEXT "Value:",IDC_STATIC,7,23,72,8 END -IDD_MAX_SCALE DIALOG DISCARDABLE 0, 0, 186, 68 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_MAX_SCALE DIALOG 0, 0, 186, 68 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Fullscreen scale" FONT 8, "MS Sans Serif" BEGIN EDITTEXT IDC_VALUE,7,28,172,14,ES_AUTOHSCROLL DEFPUSHBUTTON "OK",ID_OK,37,47,50,14 PUSHBUTTON "Cancel",ID_CANCEL,99,47,50,14 - LTEXT "Enter the maxium fullscreen scale:",IDC_STATIC,7,7,172, - 8 + LTEXT "Enter the maxium fullscreen scale:",IDC_STATIC,7,7,172,8 LTEXT "Enter 0 to use maximum scale.",IDC_STATIC,7,17,172,8 END -IDD_BUG_REPORT DIALOG DISCARDABLE 0, 0, 296, 186 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_BUG_REPORT DIALOG 0, 0, 296, 186 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Bug Report" FONT 8, "MS Sans Serif" BEGIN PUSHBUTTON "&OK",ID_OK,157,165,50,14 - EDITTEXT IDC_BUG_REPORT,11,22,278,131,ES_MULTILINE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | - WS_VSCROLL + EDITTEXT IDC_BUG_REPORT,11,22,278,131,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL LTEXT "Bug report data:",IDC_STATIC,7,7,282,8 DEFPUSHBUTTON "&Copy",IDC_COPY,87,164,50,14 END +IDD_GAME_OVERRIDES DIALOGEX 0, 0, 268, 132 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Game overrides" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + COMBOBOX IDC_RTC,84,42,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SAVE_TYPE,84,60,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_FLASH_SIZE,84,78,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_MIRRORING,84,96,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,6,114,72,12 + PUSHBUTTON "Defaults",IDC_DEFAULTS,108,114,54,12 + PUSHBUTTON "Cancel",IDCANCEL,192,114,72,12 + LTEXT "Game Code",IDC_STATIC,6,6,72,12 + EDITTEXT IDC_NAME,84,6,180,12,ES_AUTOHSCROLL | WS_DISABLED + LTEXT "Real Time Clock:",IDC_STATIC,6,42,72,12 + LTEXT "Save Type:",IDC_STATIC,6,60,72,12 + LTEXT "Flash Size:",IDC_STATIC,6,78,72,12 + LTEXT "Mirroring:",IDC_STATIC,6,96,72,12 + LTEXT "Comment",IDC_STATIC,6,24,72,12 + EDITTEXT IDC_COMMENT,84,24,180,12,ES_AUTOHSCROLL +END + ///////////////////////////////////////////////////////////////////////////// // @@ -1208,7 +1044,7 @@ // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE +GUIDELINES DESIGNINFO BEGIN IDD_OPENDLG, DIALOG BEGIN @@ -1218,17 +1054,17 @@ IDD_ABOUT, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 157 + RIGHTMARGIN, 150 TOPMARGIN, 7 - BOTTOMMARGIN, 86 + BOTTOMMARGIN, 71 END IDD_DIRECTORIES, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 277 + RIGHTMARGIN, 213 TOPMARGIN, 7 - BOTTOMMARGIN, 122 + BOTTOMMARGIN, 294 END IDD_CONFIG, DIALOG @@ -1542,6 +1378,14 @@ TOPMARGIN, 7 BOTTOMMARGIN, 179 END + + IDD_GAME_OVERRIDES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 261 + TOPMARGIN, 7 + BOTTOMMARGIN, 105 + END END #endif // APSTUDIO_INVOKED @@ -1551,21 +1395,19 @@ // Menu // -IDR_MENU MENU DISCARDABLE +IDR_MENU MENU BEGIN POPUP "&File" BEGIN - MENUITEM "&Open...", ID_FILE_OPEN + MENUITEM "Open...", ID_FILE_OPEN MENUITEM "Open Gameboy...", ID_FILE_OPENGAMEBOY MENUITEM SEPARATOR - MENUITEM "&Load...", ID_FILE_LOAD - MENUITEM "&Save...", ID_FILE_SAVE - POPUP "Loa&d Game" + MENUITEM "Load...", ID_FILE_LOAD + MENUITEM "Save...", ID_FILE_SAVE + POPUP "Load Game" BEGIN MENUITEM "Most recent", ID_FILE_LOADGAME_MOSTRECENT - MENUITEM "Auto load most recent", ID_FILE_LOADGAME_AUTOLOADMOSTRECENT - MENUITEM SEPARATOR MENUITEM "Slot #1", ID_FILE_LOADGAME_SLOT1 MENUITEM "Slot #2", ID_FILE_LOADGAME_SLOT2 @@ -1578,10 +1420,9 @@ MENUITEM "Slot #9", ID_FILE_LOADGAME_SLOT9 MENUITEM "Slot #10", ID_FILE_LOADGAME_SLOT10 END - POPUP "S&ave Game" + POPUP "Save Game" BEGIN MENUITEM "Oldest slot", ID_FILE_SAVEGAME_OLDESTSLOT - MENUITEM SEPARATOR MENUITEM "Slot #1", ID_FILE_SAVEGAME_SLOT1 MENUITEM "Slot #2", ID_FILE_SAVEGAME_SLOT2 @@ -1595,40 +1436,35 @@ MENUITEM "Slot #10", ID_FILE_SAVEGAME_SLOT10 END MENUITEM SEPARATOR - MENUITEM "&Pause", ID_FILE_PAUSE - MENUITEM "&Reset", ID_FILE_RESET + MENUITEM "Pause", ID_FILE_PAUSE + MENUITEM "Reset", ID_FILE_RESET MENUITEM SEPARATOR - POPUP "Re¢" + POPUP "Recent" BEGIN MENUITEM "&Reset", ID_FILE_RECENT_RESET MENUITEM "&Freeze", ID_FILE_RECENT_FREEZE MENUITEM SEPARATOR END MENUITEM SEPARATOR - POPUP "&Import" + POPUP "Import" BEGIN MENUITEM "&Battery file...", ID_FILE_IMPORT_BATTERYFILE - MENUITEM "Gameshark &code file...", ID_FILE_IMPORT_GAMESHARKCODEFILE - MENUITEM "&Gameshark Snapshot...", ID_FILE_IMPORT_GAMESHARKSNAPSHOT - END - POPUP "E&xport" + POPUP "Export" BEGIN MENUITEM "&Battery file...", ID_FILE_EXPORT_BATTERYFILE - MENUITEM "&Gameshark Snapshot...", ID_FILE_EXPORT_GAMESHARKSNAPSHOT - END MENUITEM SEPARATOR - MENUITEM "S&creen capture...", ID_FILE_SCREENCAPTURE - MENUITEM "Ro&m information...", ID_FILE_ROMINFORMATION - MENUITEM "&Toggle menu", ID_FILE_TOGGLEMENU + MENUITEM "Screen capture...", ID_FILE_SCREENCAPTURE + MENUITEM "Rom information...", ID_FILE_ROMINFORMATION + MENUITEM "Toggle menu", ID_FILE_TOGGLEMENU MENUITEM SEPARATOR - MENUITEM "&Close", ID_FILE_CLOSE + MENUITEM "Close", ID_FILE_CLOSE MENUITEM SEPARATOR - MENUITEM "&Exit", ID_FILE_EXIT + MENUITEM "Exit", ID_FILE_EXIT END POPUP "&Options" BEGIN @@ -1637,43 +1473,25 @@ POPUP "Throttle" BEGIN MENUITEM "No throttle", ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE - MENUITEM "25%", ID_OPTIONS_FRAMESKIP_THROTTLE_25 - MENUITEM "50%", ID_OPTIONS_FRAMESKIP_THROTTLE_50 - MENUITEM "100%", ID_OPTIONS_FRAMESKIP_THROTTLE_100 - MENUITEM "150%", ID_OPTIONS_FRAMESKIP_THROTTLE_150 - MENUITEM "200%", ID_OPTIONS_FRAMESKIP_THROTTLE_200 - MENUITEM "Other...", ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER - END MENUITEM "&Automatic", ID_OPTIONS_FRAMESKIP_AUTOMATIC - MENUITEM SEPARATOR MENUITEM "&0", ID_OPTIONS_VIDEO_FRAMESKIP_0 - MENUITEM "&1", ID_OPTIONS_VIDEO_FRAMESKIP_1 - MENUITEM "&2", ID_OPTIONS_VIDEO_FRAMESKIP_2 - MENUITEM "&3", ID_OPTIONS_VIDEO_FRAMESKIP_3 - MENUITEM "&4", ID_OPTIONS_VIDEO_FRAMESKIP_4 - MENUITEM "&5", ID_OPTIONS_VIDEO_FRAMESKIP_5 - MENUITEM "&6", ID_OPTIONS_VIDEO_FRAMESKIP_6 - MENUITEM "&7", ID_OPTIONS_VIDEO_FRAMESKIP_7 - MENUITEM "&8", ID_OPTIONS_VIDEO_FRAMESKIP_8 - MENUITEM "&9", ID_OPTIONS_VIDEO_FRAMESKIP_9 - END POPUP "&Video" BEGIN @@ -1681,39 +1499,24 @@ POPUP "Render Method" BEGIN MENUITEM "GDI", ID_OPTIONS_VIDEO_RENDERMETHOD_GDI - MENUITEM "DirectDraw", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW - MENUITEM "Direct3D", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D - MENUITEM "OpenGL", ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL - MENUITEM SEPARATOR MENUITEM "DDraw &Emulation Only", ID_OPTIONS_VIDEO_DDRAWEMULATIONONLY - MENUITEM "DDraw Use &Video Memory", ID_OPTIONS_VIDEO_DDRAWUSEVIDEOMEMORY - MENUITEM "DDraw Triple Buffering", ID_OPTIONS_VIDEO_TRIPLEBUFFERING - MENUITEM SEPARATOR MENUITEM "D3D Nearest", ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DNOFILTER - MENUITEM "D3D Bilinear", ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DBILINEAR - MENUITEM SEPARATOR MENUITEM "GL Nearest", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLNEAREST - MENUITEM "GL Bilinear", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLBILINEAR - MENUITEM "GL Triangle", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE - MENUITEM "GL Quads", ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS - MENUITEM SEPARATOR MENUITEM "Select skin...", ID_OPTIONS_VIDEO_RENDEROPTIONS_SELECTSKIN - MENUITEM "Skin", ID_OPTIONS_VIDEO_RENDEROPTIONS_SKIN - END MENUITEM SEPARATOR MENUITEM "x&1", ID_OPTIONS_VIDEO_X1 @@ -1721,114 +1524,68 @@ MENUITEM "x&3", ID_OPTIONS_VIDEO_X3 MENUITEM "x&4", ID_OPTIONS_VIDEO_X4 MENUITEM "Full Screen (320x240)", ID_OPTIONS_VIDEO_FULLSCREEN320X240 - MENUITEM "Full Screen (640x480)", ID_OPTIONS_VIDEO_FULLSCREEN640X480 - MENUITEM "Full Screen (800x600)", ID_OPTIONS_VIDEO_FULLSCREEN800X600 - MENUITEM "&Other Full Screen...", ID_OPTIONS_VIDEO_FULLSCREEN - MENUITEM "Full screen max scale...", ID_OPTIONS_VIDEO_FULLSCREENMAXSCALE - MENUITEM SEPARATOR MENUITEM "&Disable SFX", ID_OPTIONS_VIDEO_DISABLESFX - MENUITEM "Fullscreen stretch to &fit", ID_OPTIONS_VIDEO_FULLSCREENSTRETCHTOFIT - MENUITEM SEPARATOR POPUP "&Layers" BEGIN MENUITEM "BG 0", ID_OPTIONS_VIDEO_LAYERS_BG0 - MENUITEM "BG 1", ID_OPTIONS_VIDEO_LAYERS_BG1 - MENUITEM "BG 2", ID_OPTIONS_VIDEO_LAYERS_BG2 - MENUITEM "BG 3", ID_OPTIONS_VIDEO_LAYERS_BG3 - MENUITEM "OBJ", ID_OPTIONS_VIDEO_LAYERS_OBJ - MENUITEM "WIN 0", ID_OPTIONS_VIDEO_LAYERS_WIN0 - MENUITEM "WIN 1", ID_OPTIONS_VIDEO_LAYERS_WIN1 - MENUITEM "OBJ WIN", ID_OPTIONS_VIDEO_LAYERS_OBJWIN - END END POPUP "&Emulator" BEGIN MENUITEM "&Associate...", ID_OPTIONS_EMULATOR_ASSOCIATE - MENUITEM "&Directories...", ID_OPTIONS_EMULATOR_DIRECTORIES - MENUITEM "D&isable status messages", ID_OPTIONS_EMULATOR_DISABLESTATUSMESSAGES - MENUITEM "&Synchronize", ID_OPTIONS_EMULATOR_SYNCHRONIZE - MENUITEM "Pause when inactive window", ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE - MENUITEM "Speed up toggle", ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE - - MENUITEM "Remove intros (GBA)", ID_OPTIONS_EMULATOR_REMOVEINTROSGBA - MENUITEM "Automatic IPS patching", ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH - MENUITEM "AGB Print", ID_OPTIONS_EMULATOR_AGBPRINT - MENUITEM "Real Time Clock", ID_OPTIONS_EMULATOR_REALTIMECLOCK - MENUITEM "Auto hide menu", ID_OPTIONS_EMULATOR_AUTOHIDEMENU - MENUITEM "Rewind interval...", ID_OPTIONS_EMULATOR_REWINDINTERVAL - + MENUITEM "Generic Flashcard (GB/GBC)", ID_OPTIONS_EMULATOR_GENERICFLASHCARD + MENUITEM "&Game Overrides...", ID_OPTIONS_EMULATOR_GAMEOVERRIDES POPUP "Show speed" BEGIN MENUITEM "None", ID_OPTIONS_EMULATOR_SHOWSPEED_NONE - MENUITEM "Percentage", ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE - MENUITEM "Detailed", ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED - MENUITEM SEPARATOR MENUITEM "Transparent", ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT - END POPUP "Save Type" BEGIN MENUITEM "&Automatic", ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC - MENUITEM "EEPROM", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM - MENUITEM "SRAM", ID_OPTIONS_EMULATOR_SAVETYPE_SRAM - MENUITEM "Flash", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH - MENUITEM "EEPROM+Sensor", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR - MENUITEM "None", ID_OPTIONS_EMULATOR_SAVETYPE_NONE - MENUITEM SEPARATOR - MENUITEM "Flash 64K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K - - MENUITEM "Flash 128K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M - - MENUITEM SEPARATOR - MENUITEM "Enhanced detection", ID_OPTIONS_EMULATOR_SAVETYPE_ENHANCEDDETECTION - + MENUITEM "Flash 64 KB", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K + MENUITEM "Flash 128 KB", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M END MENUITEM SEPARATOR MENUITEM "&Use BIOS file", ID_OPTIONS_EMULATOR_USEBIOSFILE - MENUITEM "Skip BIOS", ID_OPTIONS_EMULATOR_SKIPBIOS - MENUITEM "S&elect BIOS file...", ID_OPTIONS_EMULATOR_SELECTBIOSFILE - MENUITEM SEPARATOR MENUITEM "PNG format", ID_OPTIONS_EMULATOR_PNGFORMAT - MENUITEM "BMP format", ID_OPTIONS_EMULATOR_BMPFORMAT - END POPUP "&Sound" BEGIN @@ -1837,26 +1594,17 @@ MENUITEM "&On", ID_OPTIONS_SOUND_ON MENUITEM SEPARATOR MENUITEM "Use old synchronization", ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION - MENUITEM SEPARATOR MENUITEM "Echo", ID_OPTIONS_SOUND_ECHO MENUITEM "Low pass filter", ID_OPTIONS_SOUND_LOWPASSFILTER - MENUITEM "Reverse Stereo", ID_OPTIONS_SOUND_REVERSESTEREO - MENUITEM SEPARATOR - MENUITEM "Channel &1", ID_OPTIONS_SOUND_CHANNEL1 - , CHECKED - MENUITEM "Channel &2", ID_OPTIONS_SOUND_CHANNEL2 - , CHECKED - MENUITEM "Channel &3", ID_OPTIONS_SOUND_CHANNEL3 - , CHECKED - MENUITEM "Channel &4", ID_OPTIONS_SOUND_CHANNEL4 - , CHECKED - MENUITEM "Direct Sound &A", ID_OPTIONS_SOUND_DIRECTSOUNDA - , CHECKED - MENUITEM "Direct Sound &B", ID_OPTIONS_SOUND_DIRECTSOUNDB - , CHECKED + MENUITEM "Channel &1", ID_OPTIONS_SOUND_CHANNEL1, CHECKED + MENUITEM "Channel &2", ID_OPTIONS_SOUND_CHANNEL2, CHECKED + MENUITEM "Channel &3", ID_OPTIONS_SOUND_CHANNEL3, CHECKED + MENUITEM "Channel &4", ID_OPTIONS_SOUND_CHANNEL4, CHECKED + MENUITEM "Direct Sound &A", ID_OPTIONS_SOUND_DIRECTSOUNDA, CHECKED + MENUITEM "Direct Sound &B", ID_OPTIONS_SOUND_DIRECTSOUNDB, CHECKED MENUITEM SEPARATOR MENUITEM "11 &Khz", ID_OPTIONS_SOUND_11KHZ MENUITEM "22 K&hz", ID_OPTIONS_SOUND_22KHZ @@ -1865,30 +1613,21 @@ POPUP "&Volume" BEGIN MENUITEM ".25X", ID_OPTIONS_SOUND_VOLUME_25X - MENUITEM ".5X", ID_OPTIONS_SOUND_VOLUME_5X - MENUITEM "&1x", ID_OPTIONS_SOUND_VOLUME_1X - MENUITEM "&2x", ID_OPTIONS_SOUND_VOLUME_2X - MENUITEM "&3x", ID_OPTIONS_SOUND_VOLUME_3X - MENUITEM "&4x", ID_OPTIONS_SOUND_VOLUME_4X - END + MENUITEM "Hardware Acceleration", ID_OPTIONS_SOUND_HARDWAREACCELERATION END POPUP "&Gameboy" BEGIN MENUITEM "&Border", ID_OPTIONS_GAMEBOY_BORDER - MENUITEM "&Printer", ID_OPTIONS_GAMEBOY_PRINTER - MENUITEM "Border Automatic", ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC - MENUITEM SEPARATOR MENUITEM "&Automatic", ID_OPTIONS_GAMEBOY_AUTOMATIC - MENUITEM "&GBA", ID_OPTIONS_GAMEBOY_GBA MENUITEM "&CGB/GBC", ID_OPTIONS_GAMEBOY_CGB MENUITEM "&SGB", ID_OPTIONS_GAMEBOY_SGB @@ -1896,110 +1635,74 @@ MENUITEM "G&B", ID_OPTIONS_GAMEBOY_GB MENUITEM SEPARATOR MENUITEM "&Real Colors", ID_OPTIONS_GAMEBOY_REALCOLORS - MENUITEM "G&ameboy Colors", ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS - MENUITEM SEPARATOR MENUITEM "Colors...", ID_OPTIONS_GAMEBOY_COLORS - END POPUP "&Priority" BEGIN MENUITEM "&Highest", ID_OPTIONS_PRIORITY_HIGHEST - MENUITEM "&Above Normal", ID_OPTIONS_PRIORITY_ABOVENORMAL - MENUITEM "&Normal", ID_OPTIONS_PRIORITY_NORMAL - MENUITEM "&Below Normal", ID_OPTIONS_PRIORITY_BELOWNORMAL - END POPUP "F&ilter" BEGIN POPUP "Interframe Blending" BEGIN MENUITEM "None", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE - MENUITEM "Motion Blur", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR - MENUITEM "Smart", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART - END MENUITEM SEPARATOR MENUITEM "&Normal", ID_OPTIONS_FILTER_NORMAL MENUITEM "&TV Mode", ID_OPTIONS_FILTER_TVMODE MENUITEM "&2xSaI", ID_OPTIONS_FILTER_2XSAI MENUITEM "&Super 2xSaI", ID_OPTIONS_FILTER_SUPER2XSAI - MENUITEM "Super &Eagle", ID_OPTIONS_FILTER_SUPEREAGLE - MENUITEM "Pixelate", ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL - MENUITEM "Motion Blur", ID_OPTIONS_FILTER16BIT_MOTIONBLUREXPERIMENTAL - MENUITEM "AdvanceMAME Scale2x", ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X - MENUITEM "Simple 2x", ID_OPTIONS_FILTER16BIT_SIMPLE2X - MENUITEM "Bilinear", ID_OPTIONS_FILTER_BILINEAR - MENUITEM "Bilinear Plus", ID_OPTIONS_FILTER_BILINEARPLUS - MENUITEM "Scanlines", ID_OPTIONS_FILTER_SCANLINES - MENUITEM "hq2x", ID_OPTIONS_FILTER_HQ2X MENUITEM "lq2x", ID_OPTIONS_FILTER_LQ2X MENUITEM SEPARATOR MENUITEM "&Disable MMX", ID_OPTIONS_FILTER_DISABLEMMX - END POPUP "&Joypad" BEGIN POPUP "&Configure" BEGIN MENUITEM "&1...", ID_OPTIONS_JOYPAD_CONFIGURE_1 - MENUITEM "&2...", ID_OPTIONS_JOYPAD_CONFIGURE_2 - MENUITEM "&3...", ID_OPTIONS_JOYPAD_CONFIGURE_3 - MENUITEM "&4...", ID_OPTIONS_JOYPAD_CONFIGURE_4 - END POPUP "Default Joypad" BEGIN MENUITEM "1", ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1 - MENUITEM "2", ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_2 - MENUITEM "3", ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_3 - MENUITEM "4", ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4 - END MENUITEM "Motion Configure...", ID_OPTIONS_JOYPAD_MOTIONCONFIGURE - MENUITEM SEPARATOR POPUP "&Autofire" BEGIN MENUITEM "&A", ID_OPTIONS_JOYPAD_AUTOFIRE_A - MENUITEM "&B", ID_OPTIONS_JOYPAD_AUTOFIRE_B - MENUITEM "&L", ID_OPTIONS_JOYPAD_AUTOFIRE_L - MENUITEM "&R", ID_OPTIONS_JOYPAD_AUTOFIRE_R - END END POPUP "&Language" BEGIN MENUITEM "&System", ID_OPTIONS_LANGUAGE_SYSTEM - MENUITEM "&English", ID_OPTIONS_LANGUAGE_ENGLISH - MENUITEM "&Other...", ID_OPTIONS_LANGUAGE_OTHER - END END POPUP "&Cheats" @@ -2008,7 +1711,6 @@ MENUITEM "&Cheat list...", ID_CHEATS_CHEATLIST MENUITEM SEPARATOR MENUITEM "&Automatic save/load cheats", ID_CHEATS_AUTOMATICSAVELOADCHEATS - MENUITEM "Disable cheats", ID_CHEATS_DISABLECHEATS MENUITEM "&Load cheat list...", ID_CHEATS_LOADCHEATLIST MENUITEM "Sa&ve cheat list...", ID_CHEATS_SAVECHEATLIST @@ -2029,33 +1731,23 @@ BEGIN MENUITEM "Wait for connection...", ID_TOOLS_DEBUG_GDB MENUITEM "Load and wait...", ID_TOOLS_DEBUG_LOADANDWAIT - MENUITEM "Break into GDB", ID_TOOLS_DEBUG_BREAK MENUITEM "Disconnect", ID_TOOLS_DEBUG_DISCONNECT - END MENUITEM SEPARATOR POPUP "Record" BEGIN MENUITEM "Start sound recording...", ID_OPTIONS_SOUND_STARTRECORDING - MENUITEM "Stop sound recording", ID_OPTIONS_SOUND_STOPRECORDING - MENUITEM "Start AVI recording...", ID_TOOLS_RECORD_STARTAVIRECORDING - MENUITEM "Stop AVI recording", ID_TOOLS_RECORD_STOPAVIRECORDING - MENUITEM "Start movie recording...", ID_TOOLS_RECORD_STARTMOVIERECORDING - MENUITEM "Stop movie recording", ID_TOOLS_RECORD_STOPMOVIERECORDING - END POPUP "Play" BEGIN MENUITEM "Start playing movie...", ID_TOOLS_PLAY_STARTMOVIEPLAYING - MENUITEM "Stop playing movie", ID_TOOLS_PLAY_STOPMOVIEPLAYING - END MENUITEM SEPARATOR MENUITEM "Rewind", ID_TOOLS_REWIND @@ -2065,6 +1757,7 @@ BEGIN MENUITEM "Bug Report", ID_HELP_BUGREPORT MENUITEM "FAQ (website)", ID_HELP_FAQ + MENUITEM "License...", ID_HELP_GNUPUBLICLICENSE MENUITEM SEPARATOR MENUITEM "&About...", ID_HELP_ABOUT END @@ -2076,7 +1769,7 @@ // Accelerator // -IDR_ACCELERATOR ACCELERATORS DISCARDABLE +IDR_ACCELERATOR ACCELERATORS BEGIN "1", ID_OPTIONS_VIDEO_LAYERS_BG0, VIRTKEY, CONTROL, NOINVERT "1", ID_OPTIONS_JOYPAD_AUTOFIRE_A, VIRTKEY, ALT, NOINVERT @@ -2089,8 +1782,7 @@ "5", ID_OPTIONS_VIDEO_LAYERS_OBJ, VIRTKEY, CONTROL, NOINVERT "6", ID_OPTIONS_VIDEO_LAYERS_WIN0, VIRTKEY, CONTROL, NOINVERT "7", ID_OPTIONS_VIDEO_LAYERS_WIN1, VIRTKEY, CONTROL, NOINVERT - "8", ID_OPTIONS_VIDEO_LAYERS_OBJWIN, VIRTKEY, CONTROL, - NOINVERT + "8", ID_OPTIONS_VIDEO_LAYERS_OBJWIN, VIRTKEY, CONTROL, NOINVERT "B", ID_TOOLS_REWIND, VIRTKEY, CONTROL, NOINVERT "C", ID_CHEATS_SEARCHFORCHEATS, VIRTKEY, CONTROL, NOINVERT "L", ID_FILE_LOAD, VIRTKEY, CONTROL, NOINVERT @@ -2136,17 +1828,10 @@ ///////////////////////////////////////////////////////////////////////////// // -// 24 -// - -1 24 MOVEABLE PURE "VisualBoyAdvance.exe.manifest" - -///////////////////////////////////////////////////////////////////////////// -// // String Table // -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_UNSUPPORTED_VBA_SGM "Unsupported VisualBoyAdvance save game version %d" IDS_CANNOT_LOAD_SGM "Cannot load save game for %s" @@ -2166,10 +1851,10 @@ IDS_UNKNOWN_THUMB_OPCODE "Unknown opcode %04x from %08x" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_ERROR_CREATING_FILE "Error creating file %s" - IDS_FAILED_TO_READ_SGM "Failed to read complete save game %s (%d)" + IDS_FAILED_TO_READ_SGM "Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !" IDS_FAILED_TO_READ_RTC "Failed to read RTC from save game %s (continuing)" IDS_UNSUPPORTED_VB_SGM "Unsupported VisualBoy save game version %d" IDS_CANNOT_LOAD_SGM_FOR "Cannot load save game for %s. Playing %s" @@ -2186,7 +1871,7 @@ IDS_UNSUPPORTED_CHEAT_LIST_VERSION "Unsupported cheat list version %d" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_DIRECTX_7_REQUIRED "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s" IDS_DISABLING_VIDEO_MEMORY "Disabling Use Video Memory setting" @@ -2208,7 +1893,7 @@ IDS_INVALID_ADDRESS "Invalid address: %08x" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_MISALIGNED_HALFWORD "Misaligned half-word address: %08x" IDS_MISALIGNED_WORD "Misaligned word address: %08x" @@ -2228,7 +1913,7 @@ IDS_SELECT_BATTERY_DIR "Select Battery directory:" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_SELECT_SAVE_DIR "Select Save Directory:" IDS_SELECT_CAPTURE_DIR "Select Capture directory:" @@ -2248,7 +1933,7 @@ IDS_LOADED_STATE_N "Loaded state %d" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_WROTE_STATE "Wrote state" IDS_WROTE_STATE_N "Wrote state %d" @@ -2268,7 +1953,7 @@ IDS_UNKNOWN "Unknown" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_NONE "None" IDS_FAILED_TO_LOAD_LIBRARY "Failed to load library %s" @@ -2288,7 +1973,7 @@ IDS_SELECT_BATTERY_FILE "Select battery file" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_UNSUPPORTED_CHEAT_LIST_TYPE "Unsupported cheat list type %d" IDS_INVALID_GSA_CODE "Invalid GSA code. Format is XXXXXXXXYYYYYYYY." @@ -2303,12 +1988,12 @@ IDS_OUT_OF_MEMORY "Failed to allocate memory for %s" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_FILTER_GBS "Gameboy Snapshot_*.GBS__" IDS_FILTER_GCF "Gameshark Code File_*.GCF__" IDS_SELECT_CODE_FILE "Select code file" - IDS_SAVE_WILL_BE_LOST "Importing a snapshot file will erase any saved games and reset the emulator. Do you want to continue?" + IDS_SAVE_WILL_BE_LOST "Importing a snapshot file will erase any saved games. Do you want to continue?" IDS_CONFIRM_ACTION "Please confirm action" IDS_CODES_WILL_BE_LOST "Importing a code file will erase any entered codes. Do you want to continue?" IDS_FILTER_SPC "Gameshark Code File_*.SPC;*.XPC__" @@ -2323,7 +2008,7 @@ IDS_ERROR_LISTENING "Error listening on socket." END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_ERROR_CREATING_SOCKET "Error creating socket." IDS_ACK_NOT_RECEIVED "ACK not received from GDB." @@ -2344,7 +2029,7 @@ IDS_END_OF_MOVIE "end of movie" END -STRINGTABLE DISCARDABLE +STRINGTABLE BEGIN IDS_INVALID_INTERVAL_VALUE "Invalid rewind interval value. Please enter a number between 0 and 600 seconds." @@ -2362,8 +2047,7 @@ // // Generated from the TEXTINCLUDE 3 resource. // - - +#include "vba.rc2" ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED diff -urN ../VisualBoyAdvance-1.7.2/src/win32/vba.rc2 ./src/win32/vba.rc2 --- ../VisualBoyAdvance-1.7.2/src/win32/vba.rc2 2004-05-15 20:26:54 +0900 +++ ./src/win32/vba.rc2 2006-05-26 23:37:41 +0900 @@ -1,5 +1,16 @@ #ifndef _MAC #include "../AutoBuild.h" + +#if _MSC_VER >= 1400 +// use modern icon +IDI_ICON ICON DISCARDABLE "vbavista.ico" +#else +// use traditional icon +IDI_ICON ICON DISCARDABLE "gbadvance.ico" +#endif + + + ///////////////////////////////////////////////////////////////////////////// // // Version @@ -23,11 +34,11 @@ BLOCK "040904b0" BEGIN VALUE "Comments", "VisualBoyAdvance comes with NO WARRANTY. Use it at your own risk.\0" - VALUE "CompanyName", "None\0" + VALUE "CompanyName", "http://vba.ngemu.com/\0" VALUE "FileDescription", "VisualBoyAdvance emulator\0" VALUE "FileVersion", STRFILEVER VALUE "InternalName", "VisualBoyAdvance\0" - VALUE "LegalCopyright", "Copyright © 2004 Forgotten and the VBA team\0" + VALUE "LegalCopyright", "Copyright © 2006 VBA development team\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "VisualBoyAdvance.exe\0" VALUE "PrivateBuild", "0\0" Binary files ../VisualBoyAdvance-1.7.2/src/win32/vbavista.ico and ./src/win32/vbavista.ico differ diff -urN ../VisualBoyAdvance-1.7.2/win32/GBA.dsp ./win32/GBA.dsp --- ../VisualBoyAdvance-1.7.2/win32/GBA.dsp 2004-02-29 22:07:01 +0900 +++ ./win32/GBA.dsp 2004-11-05 09:51:52 +0900 @@ -494,36 +494,36 @@ !IF "$(CFG)" == "GBA - Win32 Release" # Begin Custom Build -OutDir=.\Release +IntDir=.\Release InputPath=..\src\i386\2xSaImmx.asm InputName=2xSaImmx -"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - "c:\Program Files\Nasm\nasmw.exe" -D__DJGPP__ -f win32 -o $(OutDir)\$(InputName).obj $(InputPath) +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + "c:\Program Files\Nasm\nasmw.exe" -D__DJGPP__ -f win32 -o "$(IntDir)\$(InputName).obj" "$(InputPath)" # End Custom Build !ELSEIF "$(CFG)" == "GBA - Win32 Debug" # Begin Custom Build -OutDir=.\Debug +IntDir=.\Debug InputPath=..\src\i386\2xSaImmx.asm InputName=2xSaImmx -"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - "c:\Program Files\Nasm\nasmw.exe" -D__DJGPP__ -f win32 -o $(OutDir)\$(InputName).obj $(InputPath) +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + "c:\Program Files\Nasm\nasmw.exe" -D__DJGPP__ -f win32 -o "$(IntDir)\$(InputName).obj" "$(InputPath)" # End Custom Build !ELSEIF "$(CFG)" == "GBA - Win32 ReleaseNoDev" # Begin Custom Build -OutDir=.\ReleaseNoDev +IntDir=.\ReleaseNoDev InputPath=..\src\i386\2xSaImmx.asm InputName=2xSaImmx -"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - "c:\Program Files\Nasm\nasmw.exe" -D__DJGPP__ -f win32 -o $(OutDir)\$(InputName).obj $(InputPath) +"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + "c:\Program Files\Nasm\nasmw.exe" -D__DJGPP__ -f win32 -o "$(IntDir)\$(InputName).obj" "$(InputPath)" # End Custom Build @@ -560,6 +560,10 @@ # End Source File # Begin Source File +SOURCE=..\src\win32\GameOverrides.cpp +# End Source File +# Begin Source File + SOURCE=..\src\win32\GDIDisplay.cpp # End Source File # Begin Source File @@ -736,6 +740,10 @@ # End Source File # Begin Source File +SOURCE=..\src\win32\GameOverrides.h +# End Source File +# Begin Source File + SOURCE=..\src\gb\GB.h # End Source File # Begin Source File diff -urN ../VisualBoyAdvance-1.7.2/win32/Makefile.in ./win32/Makefile.in --- ../VisualBoyAdvance-1.7.2/win32/Makefile.in 2004-05-14 06:41:19 +0900 +++ ./win32/Makefile.in 2004-09-30 07:23:40 +0900 @@ -77,6 +77,8 @@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL.h ./win32/SDL-1.2.2/include/SDL.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL.h 1970-01-01 09:00:00 +0900 @@ -1,97 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Main include header for the SDL library */ - -#ifndef _SDL_H -#define _SDL_H - -#include "SDL_main.h" -#include "SDL_types.h" -#include "SDL_getenv.h" -#include "SDL_error.h" -#include "SDL_rwops.h" -#include "SDL_timer.h" -#include "SDL_audio.h" -#include "SDL_cdrom.h" -#include "SDL_joystick.h" -#include "SDL_events.h" -#include "SDL_video.h" -#include "SDL_byteorder.h" -#include "SDL_version.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* As of version 0.5, SDL is loaded dynamically into the application */ - -/* These are the flags which may be passed to SDL_Init() -- you should - specify the subsystems which you will be using in your application. -*/ -#define SDL_INIT_TIMER 0x00000001 -#define SDL_INIT_AUDIO 0x00000010 -#define SDL_INIT_VIDEO 0x00000020 -#define SDL_INIT_CDROM 0x00000100 -#define SDL_INIT_JOYSTICK 0x00000200 -#define SDL_INIT_NOPARACHUTE 0x00100000 /* Don't catch fatal signals */ -#define SDL_INIT_EVENTTHREAD 0x01000000 /* Not supported on all OS's */ -#define SDL_INIT_EVERYTHING 0x0000FFFF - -/* This function loads the SDL dynamically linked library and initializes - * the subsystems specified by 'flags' (and those satisfying dependencies) - * Unless the SDL_INIT_NOPARACHUTE flag is set, it will install cleanup - * signal handlers for some commonly ignored fatal signals (like SIGSEGV) - */ -extern DECLSPEC int SDL_Init(Uint32 flags); - -/* This function initializes specific SDL subsystems */ -extern DECLSPEC int SDL_InitSubSystem(Uint32 flags); - -/* This function cleans up specific SDL subsystems */ -extern DECLSPEC void SDL_QuitSubSystem(Uint32 flags); - -/* This function returns mask of the specified subsystems which have - been initialized. - If 'flags' is 0, it returns a mask of all initialized subsystems. -*/ -extern DECLSPEC Uint32 SDL_WasInit(Uint32 flags); - -/* This function cleans up all initialized subsystems and unloads the - * dynamically linked library. You should call it upon all exit conditions. - */ -extern DECLSPEC void SDL_Quit(void); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_H */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_active.h ./win32/SDL-1.2.2/include/SDL_active.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_active.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_active.h 1970-01-01 09:00:00 +0900 @@ -1,60 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_active.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL application focus event handling */ - -#ifndef _SDL_active_h -#define _SDL_active_h - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* The available application states */ -#define SDL_APPMOUSEFOCUS 0x01 /* The app has mouse coverage */ -#define SDL_APPINPUTFOCUS 0x02 /* The app has input focus */ -#define SDL_APPACTIVE 0x04 /* The application is active */ - -/* Function prototypes */ -/* - * This function returns the current state of the application, which is a - * bitwise combination of SDL_APPMOUSEFOCUS, SDL_APPINPUTFOCUS, and - * SDL_APPACTIVE. If SDL_APPACTIVE is set, then the user is able to - * see your application, otherwise it has been iconified or disabled. - */ -extern DECLSPEC Uint8 SDL_GetAppState(void); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_active_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_audio.h ./win32/SDL-1.2.2/include/SDL_audio.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_audio.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_audio.h 1970-01-01 09:00:00 +0900 @@ -1,260 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_audio.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Access to the raw audio mixing buffer for the SDL library */ - -#ifndef _SDL_audio_h -#define _SDL_audio_h - -#include - -#include "SDL_main.h" -#include "SDL_types.h" -#include "SDL_error.h" -#include "SDL_rwops.h" -#include "SDL_byteorder.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* The calculated values in this structure are calculated by SDL_OpenAudio() */ -typedef struct { - int freq; /* DSP frequency -- samples per second */ - Uint16 format; /* Audio data format */ - Uint8 channels; /* Number of channels: 1 mono, 2 stereo */ - Uint8 silence; /* Audio buffer silence value (calculated) */ - Uint16 samples; /* Audio buffer size in samples */ - Uint16 padding; /* Necessary for some compile environments */ - Uint32 size; /* Audio buffer size in bytes (calculated) */ - /* This function is called when the audio device needs more data. - 'stream' is a pointer to the audio data buffer - 'len' is the length of that buffer in bytes. - Once the callback returns, the buffer will no longer be valid. - Stereo samples are stored in a LRLRLR ordering. - */ - void (*callback)(void *userdata, Uint8 *stream, int len); - void *userdata; -} SDL_AudioSpec; - -/* Audio format flags (defaults to LSB byte order) */ -#define AUDIO_U8 0x0008 /* Unsigned 8-bit samples */ -#define AUDIO_S8 0x8008 /* Signed 8-bit samples */ -#define AUDIO_U16LSB 0x0010 /* Unsigned 16-bit samples */ -#define AUDIO_S16LSB 0x8010 /* Signed 16-bit samples */ -#define AUDIO_U16MSB 0x1010 /* As above, but big-endian byte order */ -#define AUDIO_S16MSB 0x9010 /* As above, but big-endian byte order */ -#define AUDIO_U16 AUDIO_U16LSB -#define AUDIO_S16 AUDIO_S16LSB - -/* Native audio byte ordering */ -#if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define AUDIO_U16SYS AUDIO_U16LSB -#define AUDIO_S16SYS AUDIO_S16LSB -#else -#define AUDIO_U16SYS AUDIO_U16MSB -#define AUDIO_S16SYS AUDIO_S16MSB -#endif - - -/* A structure to hold a set of audio conversion filters and buffers */ -typedef struct SDL_AudioCVT { - int needed; /* Set to 1 if conversion possible */ - Uint16 src_format; /* Source audio format */ - Uint16 dst_format; /* Target audio format */ - double rate_incr; /* Rate conversion increment */ - Uint8 *buf; /* Buffer to hold entire audio data */ - int len; /* Length of original audio buffer */ - int len_cvt; /* Length of converted audio buffer */ - int len_mult; /* buffer must be len*len_mult big */ - double len_ratio; /* Given len, final size is len*len_ratio */ - void (*filters[10])(struct SDL_AudioCVT *cvt, Uint16 format); - int filter_index; /* Current audio conversion function */ -} SDL_AudioCVT; - - -/* Function prototypes */ - -/* These functions are used internally, and should not be used unless you - * have a specific need to specify the audio driver you want to use. - * You should normally use SDL_Init() or SDL_InitSubSystem(). - */ -extern DECLSPEC int SDL_AudioInit(const char *driver_name); -extern DECLSPEC void SDL_AudioQuit(void); - -/* This function fills the given character buffer with the name of the - * current audio driver, and returns a pointer to it if the audio driver has - * been initialized. It returns NULL if no driver has been initialized. - */ -extern DECLSPEC char *SDL_AudioDriverName(char *namebuf, int maxlen); - -/* - * This function opens the audio device with the desired parameters, and - * returns 0 if successful, placing the actual hardware parameters in the - * structure pointed to by 'obtained'. If 'obtained' is NULL, the audio - * data passed to the callback function will be guaranteed to be in the - * requested format, and will be automatically converted to the hardware - * audio format if necessary. This function returns -1 if it failed - * to open the audio device, or couldn't set up the audio thread. - * - * When filling in the desired audio spec structure, - * 'desired->freq' should be the desired audio frequency in samples-per-second. - * 'desired->format' should be the desired audio format. - * 'desired->samples' is the desired size of the audio buffer, in samples. - * This number should be a power of two, and may be adjusted by the audio - * driver to a value more suitable for the hardware. Good values seem to - * range between 512 and 8096 inclusive, depending on the application and - * CPU speed. Smaller values yield faster response time, but can lead - * to underflow if the application is doing heavy processing and cannot - * fill the audio buffer in time. A stereo sample consists of both right - * and left channels in LR ordering. - * Note that the number of samples is directly related to time by the - * following formula: ms = (samples*1000)/freq - * 'desired->size' is the size in bytes of the audio buffer, and is - * calculated by SDL_OpenAudio(). - * 'desired->silence' is the value used to set the buffer to silence, - * and is calculated by SDL_OpenAudio(). - * 'desired->callback' should be set to a function that will be called - * when the audio device is ready for more data. It is passed a pointer - * to the audio buffer, and the length in bytes of the audio buffer. - * This function usually runs in a separate thread, and so you should - * protect data structures that it accesses by calling SDL_LockAudio() - * and SDL_UnlockAudio() in your code. - * 'desired->userdata' is passed as the first parameter to your callback - * function. - * - * The audio device starts out playing silence when it's opened, and should - * be enabled for playing by calling SDL_PauseAudio(0) when you are ready - * for your audio callback function to be called. Since the audio driver - * may modify the requested size of the audio buffer, you should allocate - * any local mixing buffers after you open the audio device. - */ -extern DECLSPEC int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained); - -/* - * Get the current audio state: - */ -typedef enum { - SDL_AUDIO_STOPPED = 0, - SDL_AUDIO_PLAYING, - SDL_AUDIO_PAUSED -} SDL_audiostatus; -extern DECLSPEC SDL_audiostatus SDL_GetAudioStatus(void); - -/* - * This function pauses and unpauses the audio callback processing. - * It should be called with a parameter of 0 after opening the audio - * device to start playing sound. This is so you can safely initialize - * data for your callback function after opening the audio device. - * Silence will be written to the audio device during the pause. - */ -extern DECLSPEC void SDL_PauseAudio(int pause_on); - -/* - * This function loads a WAVE from the data source, automatically freeing - * that source if 'freesrc' is non-zero. For example, to load a WAVE file, - * you could do: - * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); - * - * If this function succeeds, it returns the given SDL_AudioSpec, - * filled with the audio data format of the wave data, and sets - * 'audio_buf' to a malloc()'d buffer containing the audio data, - * and sets 'audio_len' to the length of that audio buffer, in bytes. - * You need to free the audio buffer with SDL_FreeWAV() when you are - * done with it. - * - * This function returns NULL and sets the SDL error message if the - * wave file cannot be opened, uses an unknown data format, or is - * corrupt. Currently raw and MS-ADPCM WAVE files are supported. - */ -extern DECLSPEC SDL_AudioSpec *SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, - SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); - -/* Compatibility convenience function -- loads a WAV from a file */ -#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \ - SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) - -/* - * This function frees data previously allocated with SDL_LoadWAV_RW() - */ -extern DECLSPEC void SDL_FreeWAV(Uint8 *audio_buf); - -/* - * This function takes a source format and rate and a destination format - * and rate, and initializes the 'cvt' structure with information needed - * by SDL_ConvertAudio() to convert a buffer of audio data from one format - * to the other. - * This function returns 0, or -1 if there was an error. - */ -extern DECLSPEC int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, - Uint16 src_format, Uint8 src_channels, int src_rate, - Uint16 dst_format, Uint8 dst_channels, int dst_rate); - -/* Once you have initialized the 'cvt' structure using SDL_BuildAudioCVT(), - * created an audio buffer cvt->buf, and filled it with cvt->len bytes of - * audio data in the source format, this function will convert it in-place - * to the desired format. - * The data conversion may expand the size of the audio data, so the buffer - * cvt->buf should be allocated after the cvt structure is initialized by - * SDL_BuildAudioCVT(), and should be cvt->len*cvt->len_mult bytes long. - */ -extern DECLSPEC int SDL_ConvertAudio(SDL_AudioCVT *cvt); - -/* - * This takes two audio buffers of the playing audio format and mixes - * them, performing addition, volume adjustment, and overflow clipping. - * The volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME - * for full audio volume. Note this does not change hardware volume. - * This is provided for convenience -- you can mix your own audio data. - */ -#define SDL_MIX_MAXVOLUME 128 -extern DECLSPEC void SDL_MixAudio(Uint8 *dst, const Uint8 *src, Uint32 len, int volume); - -/* - * The lock manipulated by these functions protects the callback function. - * During a LockAudio/UnlockAudio pair, you can be guaranteed that the - * callback function is not running. Do not call these from the callback - * function or you will cause deadlock. - */ -extern DECLSPEC void SDL_LockAudio(void); -extern DECLSPEC void SDL_UnlockAudio(void); - -/* - * This function shuts down audio processing and closes the audio device. - */ -extern DECLSPEC void SDL_CloseAudio(void); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_audio_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_byteorder.h ./win32/SDL-1.2.2/include/SDL_byteorder.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_byteorder.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_byteorder.h 1970-01-01 09:00:00 +0900 @@ -1,52 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_byteorder.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Macros for determining the byte-order of this platform */ - -#ifndef _SDL_byteorder_h -#define _SDL_byteorder_h - -/* The two types of endianness */ -#define SDL_LIL_ENDIAN 1234 -#define SDL_BIG_ENDIAN 4321 - -/* Pardon the mess, I'm trying to determine the endianness of this host. - I'm doing it by preprocessor defines rather than some sort of configure - script so that application code can use this too. The "right" way would - be to dynamically generate this file on install, but that's a lot of work. - */ -#if defined(__i386__) || defined(__ia64__) || defined(WIN32) || \ - (defined(__alpha__) || defined(__alpha)) || \ - defined(__arm__) || \ - (defined(__mips__) && defined(__MIPSEL__)) || \ - defined(__LITTLE_ENDIAN__) -#define SDL_BYTEORDER SDL_LIL_ENDIAN -#else -#define SDL_BYTEORDER SDL_BIG_ENDIAN -#endif - -#endif /* _SDL_byteorder_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_cdrom.h ./win32/SDL-1.2.2/include/SDL_cdrom.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_cdrom.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_cdrom.h 1970-01-01 09:00:00 +0900 @@ -1,175 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_cdrom.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* This is the CD-audio control API for Simple DirectMedia Layer */ - -#ifndef _SDL_cdrom_h -#define _SDL_cdrom_h - -#include "SDL_types.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* In order to use these functions, SDL_Init() must have been called - with the SDL_INIT_CDROM flag. This causes SDL to scan the system - for CD-ROM drives, and load appropriate drivers. -*/ - -/* The maximum number of CD-ROM tracks on a disk */ -#define SDL_MAX_TRACKS 99 - -/* The types of CD-ROM track possible */ -#define SDL_AUDIO_TRACK 0x00 -#define SDL_DATA_TRACK 0x04 - -/* The possible states which a CD-ROM drive can be in. */ -typedef enum { - CD_TRAYEMPTY, - CD_STOPPED, - CD_PLAYING, - CD_PAUSED, - CD_ERROR = -1 -} CDstatus; - -/* Given a status, returns true if there's a disk in the drive */ -#define CD_INDRIVE(status) ((int)status > 0) - -typedef struct { - Uint8 id; /* Track number */ - Uint8 type; /* Data or audio track */ - Uint16 unused; - Uint32 length; /* Length, in frames, of this track */ - Uint32 offset; /* Offset, in frames, from start of disk */ -} SDL_CDtrack; - -/* This structure is only current as of the last call to SDL_CDStatus() */ -typedef struct SDL_CD { - int id; /* Private drive identifier */ - CDstatus status; /* Current drive status */ - - /* The rest of this structure is only valid if there's a CD in drive */ - int numtracks; /* Number of tracks on disk */ - int cur_track; /* Current track position */ - int cur_frame; /* Current frame offset within current track */ - SDL_CDtrack track[SDL_MAX_TRACKS+1]; -} SDL_CD; - -/* Conversion functions from frames to Minute/Second/Frames and vice versa */ -#define CD_FPS 75 -#define FRAMES_TO_MSF(f, M,S,F) { \ - int value = f; \ - *(F) = value%CD_FPS; \ - value /= CD_FPS; \ - *(S) = value%60; \ - value /= 60; \ - *(M) = value; \ -} -#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F)) - -/* CD-audio API functions: */ - -/* Returns the number of CD-ROM drives on the system, or -1 if - SDL_Init() has not been called with the SDL_INIT_CDROM flag. - */ -extern DECLSPEC int SDL_CDNumDrives(void); - -/* Returns a human-readable, system-dependent identifier for the CD-ROM. - Example: - "/dev/cdrom" - "E:" - "/dev/disk/ide/1/master" -*/ -extern DECLSPEC const char * SDL_CDName(int drive); - -/* Opens a CD-ROM drive for access. It returns a drive handle on success, - or NULL if the drive was invalid or busy. This newly opened CD-ROM - becomes the default CD used when other CD functions are passed a NULL - CD-ROM handle. - Drives are numbered starting with 0. Drive 0 is the system default CD-ROM. -*/ -extern DECLSPEC SDL_CD * SDL_CDOpen(int drive); - -/* This function returns the current status of the given drive. - If the drive has a CD in it, the table of contents of the CD and current - play position of the CD will be stored in the SDL_CD structure. -*/ -extern DECLSPEC CDstatus SDL_CDStatus(SDL_CD *cdrom); - -/* Play the given CD starting at 'start_track' and 'start_frame' for 'ntracks' - tracks and 'nframes' frames. If both 'ntrack' and 'nframe' are 0, play - until the end of the CD. This function will skip data tracks. - This function should only be called after calling SDL_CDStatus() to - get track information about the CD. - For example: - // Play entire CD: - if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) - SDL_CDPlayTracks(cdrom, 0, 0, 0, 0); - // Play last track: - if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) { - SDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0); - } - // Play first and second track and 10 seconds of third track: - if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) - SDL_CDPlayTracks(cdrom, 0, 0, 2, 10); - - This function returns 0, or -1 if there was an error. -*/ -extern DECLSPEC int SDL_CDPlayTracks(SDL_CD *cdrom, - int start_track, int start_frame, int ntracks, int nframes); - -/* Play the given CD starting at 'start' frame for 'length' frames. - It returns 0, or -1 if there was an error. -*/ -extern DECLSPEC int SDL_CDPlay(SDL_CD *cdrom, int start, int length); - -/* Pause play -- returns 0, or -1 on error */ -extern DECLSPEC int SDL_CDPause(SDL_CD *cdrom); - -/* Resume play -- returns 0, or -1 on error */ -extern DECLSPEC int SDL_CDResume(SDL_CD *cdrom); - -/* Stop play -- returns 0, or -1 on error */ -extern DECLSPEC int SDL_CDStop(SDL_CD *cdrom); - -/* Eject CD-ROM -- returns 0, or -1 on error */ -extern DECLSPEC int SDL_CDEject(SDL_CD *cdrom); - -/* Closes the handle for the CD-ROM drive */ -extern DECLSPEC void SDL_CDClose(SDL_CD *cdrom); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_video_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_copying.h ./win32/SDL-1.2.2/include/SDL_copying.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_copying.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_copying.h 1970-01-01 09:00:00 +0900 @@ -1,27 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_copying.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_endian.h ./win32/SDL-1.2.2/include/SDL_endian.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_endian.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_endian.h 1970-01-01 09:00:00 +0900 @@ -1,149 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_endian.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Functions for reading and writing endian-specific values */ - -#ifndef _SDL_endian_h -#define _SDL_endian_h - -/* These functions read and write data of the specified endianness, - dynamically translating to the host machine endianness. - - e.g.: If you want to read a 16 bit value on big-endian machine from - an open file containing little endian values, you would use: - value = SDL_ReadLE16(rp); - Note that the read/write functions use SDL_RWops pointers - instead of FILE pointers. This allows you to read and write - endian values from large chunks of memory as well as files - and other data sources. -*/ - -#include - -#include "SDL_types.h" -#include "SDL_rwops.h" -#include "SDL_byteorder.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* The macros used to swap values */ -/* Try to use superfast macros on systems that support them */ -#ifdef linux -#include -#ifdef __arch__swab16 -#define SDL_Swap16 __arch__swab16 -#endif -#ifdef __arch__swab32 -#define SDL_Swap32 __arch__swab32 -#endif -#endif /* linux */ -/* Use inline functions for compilers that support them, and static - functions for those that do not. Because these functions become - static for compilers that do not support inline functions, this - header should only be included in files that actually use them. -*/ -#ifndef SDL_Swap16 -static __inline__ Uint16 SDL_Swap16(Uint16 D) { - return((D<<8)|(D>>8)); -} -#endif -#ifndef SDL_Swap32 -static __inline__ Uint32 SDL_Swap32(Uint32 D) { - return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24)); -} -#endif -#ifdef SDL_HAS_64BIT_TYPE -#ifndef SDL_Swap64 -static __inline__ Uint64 SDL_Swap64(Uint64 val) { - Uint32 hi, lo; - - /* Separate into high and low 32-bit values and swap them */ - lo = (Uint32)(val&0xFFFFFFFF); - val >>= 32; - hi = (Uint32)(val&0xFFFFFFFF); - val = SDL_Swap32(lo); - val <<= 32; - val |= SDL_Swap32(hi); - return(val); -} -#endif -#else -#ifndef SDL_Swap64 -/* This is mainly to keep compilers from complaining in SDL code. - If there is no real 64-bit datatype, then compilers will complain about - the fake 64-bit datatype that SDL provides when it compiles user code. -*/ -#define SDL_Swap64(X) (X) -#endif -#endif /* SDL_HAS_64BIT_TYPE */ - - -/* Byteswap item from the specified endianness to the native endianness */ -#if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define SDL_SwapLE16(X) (X) -#define SDL_SwapLE32(X) (X) -#define SDL_SwapLE64(X) (X) -#define SDL_SwapBE16(X) SDL_Swap16(X) -#define SDL_SwapBE32(X) SDL_Swap32(X) -#define SDL_SwapBE64(X) SDL_Swap64(X) -#else -#define SDL_SwapLE16(X) SDL_Swap16(X) -#define SDL_SwapLE32(X) SDL_Swap32(X) -#define SDL_SwapLE64(X) SDL_Swap64(X) -#define SDL_SwapBE16(X) (X) -#define SDL_SwapBE32(X) (X) -#define SDL_SwapBE64(X) (X) -#endif - -/* Read an item of the specified endianness and return in native format */ -extern DECLSPEC Uint16 SDL_ReadLE16(SDL_RWops *src); -extern DECLSPEC Uint16 SDL_ReadBE16(SDL_RWops *src); -extern DECLSPEC Uint32 SDL_ReadLE32(SDL_RWops *src); -extern DECLSPEC Uint32 SDL_ReadBE32(SDL_RWops *src); -extern DECLSPEC Uint64 SDL_ReadLE64(SDL_RWops *src); -extern DECLSPEC Uint64 SDL_ReadBE64(SDL_RWops *src); - -/* Write an item of native format to the specified endianness */ -extern DECLSPEC int SDL_WriteLE16(SDL_RWops *dst, Uint16 value); -extern DECLSPEC int SDL_WriteBE16(SDL_RWops *dst, Uint16 value); -extern DECLSPEC int SDL_WriteLE32(SDL_RWops *dst, Uint32 value); -extern DECLSPEC int SDL_WriteBE32(SDL_RWops *dst, Uint32 value); -extern DECLSPEC int SDL_WriteLE64(SDL_RWops *dst, Uint64 value); -extern DECLSPEC int SDL_WriteBE64(SDL_RWops *dst, Uint64 value); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_endian_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_error.h ./win32/SDL-1.2.2/include/SDL_error.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_error.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_error.h 1970-01-01 09:00:00 +0900 @@ -1,62 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_error.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Simple error message routines for SDL */ - -#ifndef _SDL_error_h -#define _SDL_error_h - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Public functions */ -extern DECLSPEC void SDL_SetError(const char *fmt, ...); -extern DECLSPEC char * SDL_GetError(void); -extern DECLSPEC void SDL_ClearError(void); - -/* Private error message function - used internally */ -#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM) -typedef enum { - SDL_ENOMEM, - SDL_EFREAD, - SDL_EFWRITE, - SDL_EFSEEK, - SDL_LASTERROR -} SDL_errorcode; -extern void SDL_Error(SDL_errorcode code); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_error_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_events.h ./win32/SDL-1.2.2/include/SDL_events.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_events.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_events.h 1970-01-01 09:00:00 +0900 @@ -1,334 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_events.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL event handling */ - -#ifndef _SDL_events_h -#define _SDL_events_h - -#include "SDL_types.h" -#include "SDL_active.h" -#include "SDL_keyboard.h" -#include "SDL_mouse.h" -#include "SDL_joystick.h" -#include "SDL_quit.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Event enumerations */ -enum { SDL_NOEVENT = 0, /* Unused (do not remove) */ - SDL_ACTIVEEVENT, /* Application loses/gains visibility */ - SDL_KEYDOWN, /* Keys pressed */ - SDL_KEYUP, /* Keys released */ - SDL_MOUSEMOTION, /* Mouse moved */ - SDL_MOUSEBUTTONDOWN, /* Mouse button pressed */ - SDL_MOUSEBUTTONUP, /* Mouse button released */ - SDL_JOYAXISMOTION, /* Joystick axis motion */ - SDL_JOYBALLMOTION, /* Joystick trackball motion */ - SDL_JOYHATMOTION, /* Joystick hat position change */ - SDL_JOYBUTTONDOWN, /* Joystick button pressed */ - SDL_JOYBUTTONUP, /* Joystick button released */ - SDL_QUIT, /* User-requested quit */ - SDL_SYSWMEVENT, /* System specific event */ - SDL_EVENT_RESERVEDA, /* Reserved for future use.. */ - SDL_EVENT_RESERVEDB, /* Reserved for future use.. */ - SDL_VIDEORESIZE, /* User resized video mode */ - SDL_VIDEOEXPOSE, /* Screen needs to be redrawn */ - SDL_EVENT_RESERVED2, /* Reserved for future use.. */ - SDL_EVENT_RESERVED3, /* Reserved for future use.. */ - SDL_EVENT_RESERVED4, /* Reserved for future use.. */ - SDL_EVENT_RESERVED5, /* Reserved for future use.. */ - SDL_EVENT_RESERVED6, /* Reserved for future use.. */ - SDL_EVENT_RESERVED7, /* Reserved for future use.. */ - /* Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use */ - SDL_USEREVENT = 24, - /* This last event is only for bounding internal arrays - It is the number of bits in the event mask datatype -- Uint32 - */ - SDL_NUMEVENTS = 32 -}; - -/* Predefined event masks */ -#define SDL_EVENTMASK(X) (1<<(X)) -enum { - SDL_ACTIVEEVENTMASK = SDL_EVENTMASK(SDL_ACTIVEEVENT), - SDL_KEYDOWNMASK = SDL_EVENTMASK(SDL_KEYDOWN), - SDL_KEYUPMASK = SDL_EVENTMASK(SDL_KEYUP), - SDL_MOUSEMOTIONMASK = SDL_EVENTMASK(SDL_MOUSEMOTION), - SDL_MOUSEBUTTONDOWNMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN), - SDL_MOUSEBUTTONUPMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONUP), - SDL_MOUSEEVENTMASK = SDL_EVENTMASK(SDL_MOUSEMOTION)| - SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN)| - SDL_EVENTMASK(SDL_MOUSEBUTTONUP), - SDL_JOYAXISMOTIONMASK = SDL_EVENTMASK(SDL_JOYAXISMOTION), - SDL_JOYBALLMOTIONMASK = SDL_EVENTMASK(SDL_JOYBALLMOTION), - SDL_JOYHATMOTIONMASK = SDL_EVENTMASK(SDL_JOYHATMOTION), - SDL_JOYBUTTONDOWNMASK = SDL_EVENTMASK(SDL_JOYBUTTONDOWN), - SDL_JOYBUTTONUPMASK = SDL_EVENTMASK(SDL_JOYBUTTONUP), - SDL_JOYEVENTMASK = SDL_EVENTMASK(SDL_JOYAXISMOTION)| - SDL_EVENTMASK(SDL_JOYBALLMOTION)| - SDL_EVENTMASK(SDL_JOYHATMOTION)| - SDL_EVENTMASK(SDL_JOYBUTTONDOWN)| - SDL_EVENTMASK(SDL_JOYBUTTONUP), - SDL_VIDEORESIZEMASK = SDL_EVENTMASK(SDL_VIDEORESIZE), - SDL_VIDEOEXPOSEMASK = SDL_EVENTMASK(SDL_VIDEOEXPOSE), - SDL_QUITMASK = SDL_EVENTMASK(SDL_QUIT), - SDL_SYSWMEVENTMASK = SDL_EVENTMASK(SDL_SYSWMEVENT) -}; -#define SDL_ALLEVENTS 0xFFFFFFFF - -/* Application visibility event structure */ -typedef struct { - Uint8 type; /* SDL_ACTIVEEVENT */ - Uint8 gain; /* Whether given states were gained or lost (1/0) */ - Uint8 state; /* A mask of the focus states */ -} SDL_ActiveEvent; - -/* Keyboard event structure */ -typedef struct { - Uint8 type; /* SDL_KEYDOWN or SDL_KEYUP */ - Uint8 which; /* The keyboard device index */ - Uint8 state; /* SDL_PRESSED or SDL_RELEASED */ - SDL_keysym keysym; -} SDL_KeyboardEvent; - -/* Mouse motion event structure */ -typedef struct { - Uint8 type; /* SDL_MOUSEMOTION */ - Uint8 which; /* The mouse device index */ - Uint8 state; /* The current button state */ - Uint16 x, y; /* The X/Y coordinates of the mouse */ - Sint16 xrel; /* The relative motion in the X direction */ - Sint16 yrel; /* The relative motion in the Y direction */ -} SDL_MouseMotionEvent; - -/* Mouse button event structure */ -typedef struct { - Uint8 type; /* SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP */ - Uint8 which; /* The mouse device index */ - Uint8 button; /* The mouse button index */ - Uint8 state; /* SDL_PRESSED or SDL_RELEASED */ - Uint16 x, y; /* The X/Y coordinates of the mouse at press time */ -} SDL_MouseButtonEvent; - -/* Joystick axis motion event structure */ -typedef struct { - Uint8 type; /* SDL_JOYAXISMOTION */ - Uint8 which; /* The joystick device index */ - Uint8 axis; /* The joystick axis index */ - Sint16 value; /* The axis value (range: -32768 to 32767) */ -} SDL_JoyAxisEvent; - -/* Joystick trackball motion event structure */ -typedef struct { - Uint8 type; /* SDL_JOYBALLMOTION */ - Uint8 which; /* The joystick device index */ - Uint8 ball; /* The joystick trackball index */ - Sint16 xrel; /* The relative motion in the X direction */ - Sint16 yrel; /* The relative motion in the Y direction */ -} SDL_JoyBallEvent; - -/* Joystick hat position change event structure */ -typedef struct { - Uint8 type; /* SDL_JOYHATMOTION */ - Uint8 which; /* The joystick device index */ - Uint8 hat; /* The joystick hat index */ - Uint8 value; /* The hat position value: - 8 1 2 - 7 0 3 - 6 5 4 - Note that zero means the POV is centered. - */ -} SDL_JoyHatEvent; - -/* Joystick button event structure */ -typedef struct { - Uint8 type; /* SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP */ - Uint8 which; /* The joystick device index */ - Uint8 button; /* The joystick button index */ - Uint8 state; /* SDL_PRESSED or SDL_RELEASED */ -} SDL_JoyButtonEvent; - -/* The "window resized" event - When you get this event, you are responsible for setting a new video - mode with the new width and height. - */ -typedef struct { - Uint8 type; /* SDL_VIDEORESIZE */ - int w; /* New width */ - int h; /* New height */ -} SDL_ResizeEvent; - -/* The "screen redraw" event */ -typedef struct { - Uint8 type; /* SDL_VIDEOEXPOSE */ -} SDL_ExposeEvent; - -/* The "quit requested" event */ -typedef struct { - Uint8 type; /* SDL_QUIT */ -} SDL_QuitEvent; - -/* A user-defined event type */ -typedef struct { - Uint8 type; /* SDL_USEREVENT through SDL_NUMEVENTS-1 */ - int code; /* User defined event code */ - void *data1; /* User defined data pointer */ - void *data2; /* User defined data pointer */ -} SDL_UserEvent; - -/* If you want to use this event, you should include SDL_syswm.h */ -struct SDL_SysWMmsg; -typedef struct SDL_SysWMmsg SDL_SysWMmsg; -typedef struct { - Uint8 type; - SDL_SysWMmsg *msg; -} SDL_SysWMEvent; - -/* General event structure */ -typedef union { - Uint8 type; - SDL_ActiveEvent active; - SDL_KeyboardEvent key; - SDL_MouseMotionEvent motion; - SDL_MouseButtonEvent button; - SDL_JoyAxisEvent jaxis; - SDL_JoyBallEvent jball; - SDL_JoyHatEvent jhat; - SDL_JoyButtonEvent jbutton; - SDL_ResizeEvent resize; - SDL_ExposeEvent expose; - SDL_QuitEvent quit; - SDL_UserEvent user; - SDL_SysWMEvent syswm; -} SDL_Event; - - -/* Function prototypes */ - -/* Pumps the event loop, gathering events from the input devices. - This function updates the event queue and internal input device state. - This should only be run in the thread that sets the video mode. -*/ -extern DECLSPEC void SDL_PumpEvents(void); - -/* Checks the event queue for messages and optionally returns them. - If 'action' is SDL_ADDEVENT, up to 'numevents' events will be added to - the back of the event queue. - If 'action' is SDL_PEEKEVENT, up to 'numevents' events at the front - of the event queue, matching 'mask', will be returned and will not - be removed from the queue. - If 'action' is SDL_GETEVENT, up to 'numevents' events at the front - of the event queue, matching 'mask', will be returned and will be - removed from the queue. - This function returns the number of events actually stored, or -1 - if there was an error. This function is thread-safe. -*/ -typedef enum { - SDL_ADDEVENT, - SDL_PEEKEVENT, - SDL_GETEVENT -} SDL_eventaction; -/* */ -extern DECLSPEC int SDL_PeepEvents(SDL_Event *events, int numevents, - SDL_eventaction action, Uint32 mask); - -/* Polls for currently pending events, and returns 1 if there are any pending - events, or 0 if there are none available. If 'event' is not NULL, the next - event is removed from the queue and stored in that area. - */ -extern DECLSPEC int SDL_PollEvent(SDL_Event *event); - -/* Waits indefinitely for the next available event, returning 1, or 0 if there - was an error while waiting for events. If 'event' is not NULL, the next - event is removed from the queue and stored in that area. - */ -extern DECLSPEC int SDL_WaitEvent(SDL_Event *event); - -/* Add an event to the event queue. - This function returns 0, or -1 if the event couldn't be added to - the event queue. If the event queue is full, this function fails. - */ -extern DECLSPEC int SDL_PushEvent(SDL_Event *event); - -/* - This function sets up a filter to process all events before they - change internal state and are posted to the internal event queue. - - The filter is protypted as: -*/ -typedef int (*SDL_EventFilter)(const SDL_Event *event); -/* - If the filter returns 1, then the event will be added to the internal queue. - If it returns 0, then the event will be dropped from the queue, but the - internal state will still be updated. This allows selective filtering of - dynamically arriving events. - - WARNING: Be very careful of what you do in the event filter function, as - it may run in a different thread! - - There is one caveat when dealing with the SDL_QUITEVENT event type. The - event filter is only called when the window manager desires to close the - application window. If the event filter returns 1, then the window will - be closed, otherwise the window will remain open if possible. - If the quit event is generated by an interrupt signal, it will bypass the - internal queue and be delivered to the application at the next event poll. -*/ -extern DECLSPEC void SDL_SetEventFilter(SDL_EventFilter filter); - -/* - Return the current event filter - can be used to "chain" filters. - If there is no event filter set, this function returns NULL. -*/ -extern DECLSPEC SDL_EventFilter SDL_GetEventFilter(void); - -/* - This function allows you to set the state of processing certain events. - If 'state' is set to SDL_IGNORE, that event will be automatically dropped - from the event queue and will not event be filtered. - If 'state' is set to SDL_ENABLE, that event will be processed normally. - If 'state' is set to SDL_QUERY, SDL_EventState() will return the - current processing state of the specified event. -*/ -#define SDL_QUERY -1 -#define SDL_IGNORE 0 -#define SDL_DISABLE 0 -#define SDL_ENABLE 1 -extern DECLSPEC Uint8 SDL_EventState(Uint8 type, int state); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_events_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_getenv.h ./win32/SDL-1.2.2/include/SDL_getenv.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_getenv.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_getenv.h 1970-01-01 09:00:00 +0900 @@ -1,30 +0,0 @@ - -/* Not all environments have a working getenv()/putenv() */ - -#if defined(macintosh) || defined(_WIN32_WCE) -#define NEED_SDL_GETENV -#endif - -#ifdef NEED_SDL_GETENV - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Put a variable of the form "name=value" into the environment */ -extern DECLSPEC int SDL_putenv(const char *variable); -#define putenv(X) SDL_putenv(X) - -/* Retrieve a variable named "name" from the environment */ -extern DECLSPEC char *SDL_getenv(const char *name); -#define getenv(X) SDL_getenv(X) - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* NEED_GETENV */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_joystick.h ./win32/SDL-1.2.2/include/SDL_joystick.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_joystick.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_joystick.h 1970-01-01 09:00:00 +0900 @@ -1,171 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_joystick.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL joystick event handling */ - -#ifndef _SDL_joystick_h -#define _SDL_joystick_h - -#include "SDL_types.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* In order to use these functions, SDL_Init() must have been called - with the SDL_INIT_JOYSTICK flag. This causes SDL to scan the system - for joysticks, and load appropriate drivers. -*/ - -/* The joystick structure used to identify an SDL joystick */ -struct _SDL_Joystick; -typedef struct _SDL_Joystick SDL_Joystick; - - -/* Function prototypes */ -/* - * Count the number of joysticks attached to the system - */ -extern DECLSPEC int SDL_NumJoysticks(void); - -/* - * Get the implementation dependent name of a joystick. - * This can be called before any joysticks are opened. - * If no name can be found, this function returns NULL. - */ -extern DECLSPEC const char *SDL_JoystickName(int device_index); - -/* - * Open a joystick for use - the index passed as an argument refers to - * the N'th joystick on the system. This index is the value which will - * identify this joystick in future joystick events. - * - * This function returns a joystick identifier, or NULL if an error occurred. - */ -extern DECLSPEC SDL_Joystick *SDL_JoystickOpen(int device_index); - -/* - * Returns 1 if the joystick has been opened, or 0 if it has not. - */ -extern DECLSPEC int SDL_JoystickOpened(int device_index); - -/* - * Get the device index of an opened joystick. - */ -extern DECLSPEC int SDL_JoystickIndex(SDL_Joystick *joystick); - -/* - * Get the number of general axis controls on a joystick - */ -extern DECLSPEC int SDL_JoystickNumAxes(SDL_Joystick *joystick); - -/* - * Get the number of trackballs on a joystick - * Joystick trackballs have only relative motion events associated - * with them and their state cannot be polled. - */ -extern DECLSPEC int SDL_JoystickNumBalls(SDL_Joystick *joystick); - -/* - * Get the number of POV hats on a joystick - */ -extern DECLSPEC int SDL_JoystickNumHats(SDL_Joystick *joystick); - -/* - * Get the number of buttons on a joystick - */ -extern DECLSPEC int SDL_JoystickNumButtons(SDL_Joystick *joystick); - -/* - * Update the current state of the open joysticks. - * This is called automatically by the event loop if any joystick - * events are enabled. - */ -extern DECLSPEC void SDL_JoystickUpdate(void); - -/* - * Enable/disable joystick event polling. - * If joystick events are disabled, you must call SDL_JoystickUpdate() - * yourself and check the state of the joystick when you want joystick - * information. - * The state can be one of SDL_QUERY, SDL_ENABLE or SDL_IGNORE. - */ -extern DECLSPEC int SDL_JoystickEventState(int state); - -/* - * Get the current state of an axis control on a joystick - * The state is a value ranging from -32768 to 32767. - * The axis indices start at index 0. - */ -extern DECLSPEC Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis); - -/* - * Get the current state of a POV hat on a joystick - * The return value is one of the following positions: - */ -#define SDL_HAT_CENTERED 0x00 -#define SDL_HAT_UP 0x01 -#define SDL_HAT_RIGHT 0x02 -#define SDL_HAT_DOWN 0x04 -#define SDL_HAT_LEFT 0x08 -#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) -#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) -#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) -#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) -/* - * The hat indices start at index 0. - */ -extern DECLSPEC Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat); - -/* - * Get the ball axis change since the last poll - * This returns 0, or -1 if you passed it invalid parameters. - * The ball indices start at index 0. - */ -extern DECLSPEC int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy); - -/* - * Get the current state of a button on a joystick - * The button indices start at index 0. - */ -extern DECLSPEC Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button); - -/* - * Close a joystick previously opened with SDL_JoystickOpen() - */ -extern DECLSPEC void SDL_JoystickClose(SDL_Joystick *joystick); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_joystick_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_keyboard.h ./win32/SDL-1.2.2/include/SDL_keyboard.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_keyboard.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_keyboard.h 1970-01-01 09:00:00 +0900 @@ -1,124 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_keyboard.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL keyboard event handling */ - -#ifndef _SDL_keyboard_h -#define _SDL_keyboard_h - -#include "SDL_types.h" -#include "SDL_keysym.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Keysym structure - - The scancode is hardware dependent, and should not be used by general - applications. If no hardware scancode is available, it will be 0. - - - The 'unicode' translated character is only available when character - translation is enabled by the SDL_EnableUNICODE() API. If non-zero, - this is a UNICODE character corresponding to the keypress. If the - high 9 bits of the character are 0, then this maps to the equivalent - ASCII character: - char ch; - if ( (keysym.unicode & 0xFF80) == 0 ) { - ch = keysym.unicode & 0x7F; - } else { - An international character.. - } - */ -typedef struct { - Uint8 scancode; /* hardware specific scancode */ - SDLKey sym; /* SDL virtual keysym */ - SDLMod mod; /* current key modifiers */ - Uint16 unicode; /* translated character */ -} SDL_keysym; - -/* This is the mask which refers to all hotkey bindings */ -#define SDL_ALL_HOTKEYS 0xFFFFFFFF - -/* Function prototypes */ -/* - * Enable/Disable UNICODE translation of keyboard input. - * This translation has some overhead, so translation defaults off. - * If 'enable' is 1, translation is enabled. - * If 'enable' is 0, translation is disabled. - * If 'enable' is -1, the translation state is not changed. - * It returns the previous state of keyboard translation. - */ -extern DECLSPEC int SDL_EnableUNICODE(int enable); - -/* - * Enable/Disable keyboard repeat. Keyboard repeat defaults to off. - * 'delay' is the initial delay in ms between the time when a key is - * pressed, and keyboard repeat begins. - * 'interval' is the time in ms between keyboard repeat events. - */ -#define SDL_DEFAULT_REPEAT_DELAY 500 -#define SDL_DEFAULT_REPEAT_INTERVAL 30 -/* - * If 'delay' is set to 0, keyboard repeat is disabled. - */ -extern DECLSPEC int SDL_EnableKeyRepeat(int delay, int interval); - -/* - * Get a snapshot of the current state of the keyboard. - * Returns an array of keystates, indexed by the SDLK_* syms. - * Used: - * Uint8 *keystate = SDL_GetKeyState(NULL); - * if ( keystate[SDLK_RETURN] ) ... is pressed. - */ -extern DECLSPEC Uint8 * SDL_GetKeyState(int *numkeys); - -/* - * Get the current key modifier state - */ -extern DECLSPEC SDLMod SDL_GetModState(void); - -/* - * Set the current key modifier state - * This does not change the keyboard state, only the key modifier flags. - */ -extern DECLSPEC void SDL_SetModState(SDLMod modstate); - -/* - * Get the name of an SDL virtual keysym - */ -extern DECLSPEC char * SDL_GetKeyName(SDLKey key); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_keyboard_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_keysym.h ./win32/SDL-1.2.2/include/SDL_keysym.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_keysym.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_keysym.h 1970-01-01 09:00:00 +0900 @@ -1,315 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_keysym.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -#ifndef _SDL_keysym_h -#define _SDL_keysym_h - -/* What we really want is a mapping of every raw key on the keyboard. - To support international keyboards, we use the range 0xA1 - 0xFF - as international virtual keycodes. We'll follow in the footsteps of X11... - The names of the keys - */ - -typedef enum { - /* The keyboard syms have been cleverly chosen to map to ASCII */ - SDLK_UNKNOWN = 0, - SDLK_FIRST = 0, - SDLK_BACKSPACE = 8, - SDLK_TAB = 9, - SDLK_CLEAR = 12, - SDLK_RETURN = 13, - SDLK_PAUSE = 19, - SDLK_ESCAPE = 27, - SDLK_SPACE = 32, - SDLK_EXCLAIM = 33, - SDLK_QUOTEDBL = 34, - SDLK_HASH = 35, - SDLK_DOLLAR = 36, - SDLK_AMPERSAND = 38, - SDLK_QUOTE = 39, - SDLK_LEFTPAREN = 40, - SDLK_RIGHTPAREN = 41, - SDLK_ASTERISK = 42, - SDLK_PLUS = 43, - SDLK_COMMA = 44, - SDLK_MINUS = 45, - SDLK_PERIOD = 46, - SDLK_SLASH = 47, - SDLK_0 = 48, - SDLK_1 = 49, - SDLK_2 = 50, - SDLK_3 = 51, - SDLK_4 = 52, - SDLK_5 = 53, - SDLK_6 = 54, - SDLK_7 = 55, - SDLK_8 = 56, - SDLK_9 = 57, - SDLK_COLON = 58, - SDLK_SEMICOLON = 59, - SDLK_LESS = 60, - SDLK_EQUALS = 61, - SDLK_GREATER = 62, - SDLK_QUESTION = 63, - SDLK_AT = 64, - /* - Skip uppercase letters - */ - SDLK_LEFTBRACKET = 91, - SDLK_BACKSLASH = 92, - SDLK_RIGHTBRACKET = 93, - SDLK_CARET = 94, - SDLK_UNDERSCORE = 95, - SDLK_BACKQUOTE = 96, - SDLK_a = 97, - SDLK_b = 98, - SDLK_c = 99, - SDLK_d = 100, - SDLK_e = 101, - SDLK_f = 102, - SDLK_g = 103, - SDLK_h = 104, - SDLK_i = 105, - SDLK_j = 106, - SDLK_k = 107, - SDLK_l = 108, - SDLK_m = 109, - SDLK_n = 110, - SDLK_o = 111, - SDLK_p = 112, - SDLK_q = 113, - SDLK_r = 114, - SDLK_s = 115, - SDLK_t = 116, - SDLK_u = 117, - SDLK_v = 118, - SDLK_w = 119, - SDLK_x = 120, - SDLK_y = 121, - SDLK_z = 122, - SDLK_DELETE = 127, - /* End of ASCII mapped keysyms */ - - /* International keyboard syms */ - SDLK_WORLD_0 = 160, /* 0xA0 */ - SDLK_WORLD_1 = 161, - SDLK_WORLD_2 = 162, - SDLK_WORLD_3 = 163, - SDLK_WORLD_4 = 164, - SDLK_WORLD_5 = 165, - SDLK_WORLD_6 = 166, - SDLK_WORLD_7 = 167, - SDLK_WORLD_8 = 168, - SDLK_WORLD_9 = 169, - SDLK_WORLD_10 = 170, - SDLK_WORLD_11 = 171, - SDLK_WORLD_12 = 172, - SDLK_WORLD_13 = 173, - SDLK_WORLD_14 = 174, - SDLK_WORLD_15 = 175, - SDLK_WORLD_16 = 176, - SDLK_WORLD_17 = 177, - SDLK_WORLD_18 = 178, - SDLK_WORLD_19 = 179, - SDLK_WORLD_20 = 180, - SDLK_WORLD_21 = 181, - SDLK_WORLD_22 = 182, - SDLK_WORLD_23 = 183, - SDLK_WORLD_24 = 184, - SDLK_WORLD_25 = 185, - SDLK_WORLD_26 = 186, - SDLK_WORLD_27 = 187, - SDLK_WORLD_28 = 188, - SDLK_WORLD_29 = 189, - SDLK_WORLD_30 = 190, - SDLK_WORLD_31 = 191, - SDLK_WORLD_32 = 192, - SDLK_WORLD_33 = 193, - SDLK_WORLD_34 = 194, - SDLK_WORLD_35 = 195, - SDLK_WORLD_36 = 196, - SDLK_WORLD_37 = 197, - SDLK_WORLD_38 = 198, - SDLK_WORLD_39 = 199, - SDLK_WORLD_40 = 200, - SDLK_WORLD_41 = 201, - SDLK_WORLD_42 = 202, - SDLK_WORLD_43 = 203, - SDLK_WORLD_44 = 204, - SDLK_WORLD_45 = 205, - SDLK_WORLD_46 = 206, - SDLK_WORLD_47 = 207, - SDLK_WORLD_48 = 208, - SDLK_WORLD_49 = 209, - SDLK_WORLD_50 = 210, - SDLK_WORLD_51 = 211, - SDLK_WORLD_52 = 212, - SDLK_WORLD_53 = 213, - SDLK_WORLD_54 = 214, - SDLK_WORLD_55 = 215, - SDLK_WORLD_56 = 216, - SDLK_WORLD_57 = 217, - SDLK_WORLD_58 = 218, - SDLK_WORLD_59 = 219, - SDLK_WORLD_60 = 220, - SDLK_WORLD_61 = 221, - SDLK_WORLD_62 = 222, - SDLK_WORLD_63 = 223, - SDLK_WORLD_64 = 224, - SDLK_WORLD_65 = 225, - SDLK_WORLD_66 = 226, - SDLK_WORLD_67 = 227, - SDLK_WORLD_68 = 228, - SDLK_WORLD_69 = 229, - SDLK_WORLD_70 = 230, - SDLK_WORLD_71 = 231, - SDLK_WORLD_72 = 232, - SDLK_WORLD_73 = 233, - SDLK_WORLD_74 = 234, - SDLK_WORLD_75 = 235, - SDLK_WORLD_76 = 236, - SDLK_WORLD_77 = 237, - SDLK_WORLD_78 = 238, - SDLK_WORLD_79 = 239, - SDLK_WORLD_80 = 240, - SDLK_WORLD_81 = 241, - SDLK_WORLD_82 = 242, - SDLK_WORLD_83 = 243, - SDLK_WORLD_84 = 244, - SDLK_WORLD_85 = 245, - SDLK_WORLD_86 = 246, - SDLK_WORLD_87 = 247, - SDLK_WORLD_88 = 248, - SDLK_WORLD_89 = 249, - SDLK_WORLD_90 = 250, - SDLK_WORLD_91 = 251, - SDLK_WORLD_92 = 252, - SDLK_WORLD_93 = 253, - SDLK_WORLD_94 = 254, - SDLK_WORLD_95 = 255, /* 0xFF */ - - /* Numeric keypad */ - SDLK_KP0 = 256, - SDLK_KP1 = 257, - SDLK_KP2 = 258, - SDLK_KP3 = 259, - SDLK_KP4 = 260, - SDLK_KP5 = 261, - SDLK_KP6 = 262, - SDLK_KP7 = 263, - SDLK_KP8 = 264, - SDLK_KP9 = 265, - SDLK_KP_PERIOD = 266, - SDLK_KP_DIVIDE = 267, - SDLK_KP_MULTIPLY = 268, - SDLK_KP_MINUS = 269, - SDLK_KP_PLUS = 270, - SDLK_KP_ENTER = 271, - SDLK_KP_EQUALS = 272, - - /* Arrows + Home/End pad */ - SDLK_UP = 273, - SDLK_DOWN = 274, - SDLK_RIGHT = 275, - SDLK_LEFT = 276, - SDLK_INSERT = 277, - SDLK_HOME = 278, - SDLK_END = 279, - SDLK_PAGEUP = 280, - SDLK_PAGEDOWN = 281, - - /* Function keys */ - SDLK_F1 = 282, - SDLK_F2 = 283, - SDLK_F3 = 284, - SDLK_F4 = 285, - SDLK_F5 = 286, - SDLK_F6 = 287, - SDLK_F7 = 288, - SDLK_F8 = 289, - SDLK_F9 = 290, - SDLK_F10 = 291, - SDLK_F11 = 292, - SDLK_F12 = 293, - SDLK_F13 = 294, - SDLK_F14 = 295, - SDLK_F15 = 296, - - /* Key state modifier keys */ - SDLK_NUMLOCK = 300, - SDLK_CAPSLOCK = 301, - SDLK_SCROLLOCK = 302, - SDLK_RSHIFT = 303, - SDLK_LSHIFT = 304, - SDLK_RCTRL = 305, - SDLK_LCTRL = 306, - SDLK_RALT = 307, - SDLK_LALT = 308, - SDLK_RMETA = 309, - SDLK_LMETA = 310, - SDLK_LSUPER = 311, /* Left "Windows" key */ - SDLK_RSUPER = 312, /* Right "Windows" key */ - SDLK_MODE = 313, /* "Alt Gr" key */ - SDLK_COMPOSE = 314, /* Multi-key compose key */ - - /* Miscellaneous function keys */ - SDLK_HELP = 315, - SDLK_PRINT = 316, - SDLK_SYSREQ = 317, - SDLK_BREAK = 318, - SDLK_MENU = 319, - SDLK_POWER = 320, /* Power Macintosh power key */ - SDLK_EURO = 321, /* Some european keyboards */ - - /* Add any other keys here */ - - SDLK_LAST -} SDLKey; - -/* Enumeration of valid key mods (possibly OR'd together) */ -typedef enum { - KMOD_NONE = 0x0000, - KMOD_LSHIFT= 0x0001, - KMOD_RSHIFT= 0x0002, - KMOD_LCTRL = 0x0040, - KMOD_RCTRL = 0x0080, - KMOD_LALT = 0x0100, - KMOD_RALT = 0x0200, - KMOD_LMETA = 0x0400, - KMOD_RMETA = 0x0800, - KMOD_NUM = 0x1000, - KMOD_CAPS = 0x2000, - KMOD_MODE = 0x4000, - KMOD_RESERVED = 0x8000 -} SDLMod; - -#define KMOD_CTRL (KMOD_LCTRL|KMOD_RCTRL) -#define KMOD_SHIFT (KMOD_LSHIFT|KMOD_RSHIFT) -#define KMOD_ALT (KMOD_LALT|KMOD_RALT) -#define KMOD_META (KMOD_LMETA|KMOD_RMETA) - -#endif /* _SDL_keysym_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_main.h ./win32/SDL-1.2.2/include/SDL_main.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_main.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_main.h 1970-01-01 09:00:00 +0900 @@ -1,97 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_main.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -#ifndef _SDL_main_h -#define _SDL_main_h - -/* Redefine main() on Win32 and MacOS so that it is called by winmain.c */ - -#if defined(WIN32) || (defined(__MWERKS__) && !defined(__BEOS__)) || \ - defined(macintosh) || defined(__APPLE__) - -#ifdef __cplusplus -#define C_LINKAGE "C" -#else -#define C_LINKAGE -#endif /* __cplusplus */ - -/* The application's main() function must be called with C linkage, - and should be declared like this: -#ifdef __cplusplus -extern "C" -#endif - int main(int argc, char *argv[]) - { - } - */ -#define main SDL_main - -/* The prototype for the application's main() function */ -extern C_LINKAGE int SDL_main(int argc, char *argv[]); - - -/* From the SDL library code -- needed for registering the app on Win32 */ -#if defined(WIN32) -#include "SDL_types.h" -#include "begin_code.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* This should be called from your WinMain() function, if any */ -extern DECLSPEC int SDL_RegisterApp(char *name, Uint32 style, void *hInst); - -#ifdef __cplusplus -} -#endif -#include "close_code.h" -#endif - -/* From the SDL library code -- needed for registering QuickDraw on MacOS */ -#if defined(macintosh) -#include "begin_code.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Forward declaration so we don't need to include QuickDraw.h */ -struct QDGlobals; - -/* This should be called from your main() function, if any */ -extern DECLSPEC void SDL_InitQuickDraw(struct QDGlobals *the_qd); - -#ifdef __cplusplus -} -#endif -#include "close_code.h" -#endif - -#endif /* Need to redefine main()? */ - -#endif /* _SDL_main_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_mouse.h ./win32/SDL-1.2.2/include/SDL_mouse.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_mouse.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_mouse.h 1970-01-01 09:00:00 +0900 @@ -1,136 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_mouse.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL mouse event handling */ - -#ifndef _SDL_mouse_h -#define _SDL_mouse_h - -#include "SDL_types.h" -#include "SDL_video.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct WMcursor WMcursor; /* Implementation dependent */ -typedef struct { - SDL_Rect area; /* The area of the mouse cursor */ - Sint16 hot_x, hot_y; /* The "tip" of the cursor */ - Uint8 *data; /* B/W cursor data */ - Uint8 *mask; /* B/W cursor mask */ - Uint8 *save[2]; /* Place to save cursor area */ - WMcursor *wm_cursor; /* Window-manager cursor */ -} SDL_Cursor; - -/* Function prototypes */ -/* - * Retrieve the current state of the mouse. - * The current button state is returned as a button bitmask, which can - * be tested using the SDL_BUTTON(X) macros, and x and y are set to the - * current mouse cursor position. You can pass NULL for either x or y. - */ -extern DECLSPEC Uint8 SDL_GetMouseState(int *x, int *y); - -/* - * Retrieve the current state of the mouse. - * The current button state is returned as a button bitmask, which can - * be tested using the SDL_BUTTON(X) macros, and x and y are set to the - * mouse deltas since the last call to SDL_GetRelativeMouseState(). - */ -extern DECLSPEC Uint8 SDL_GetRelativeMouseState(int *x, int *y); - -/* - * Set the position of the mouse cursor (generates a mouse motion event) - */ -extern DECLSPEC void SDL_WarpMouse(Uint16 x, Uint16 y); - -/* - * Create a cursor using the specified data and mask (in MSB format). - * The cursor width must be a multiple of 8 bits. - * - * The cursor is created in black and white according to the following: - * data mask resulting pixel on screen - * 0 1 White - * 1 1 Black - * 0 0 Transparent - * 1 0 Inverted color if possible, black if not. - * - * Cursors created with this function must be freed with SDL_FreeCursor(). - */ -extern DECLSPEC SDL_Cursor *SDL_CreateCursor - (Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); - -/* - * Set the currently active cursor to the specified one. - * If the cursor is currently visible, the change will be immediately - * represented on the display. - */ -extern DECLSPEC void SDL_SetCursor(SDL_Cursor *cursor); - -/* - * Returns the currently active cursor. - */ -extern DECLSPEC SDL_Cursor * SDL_GetCursor(void); - -/* - * Deallocates a cursor created with SDL_CreateCursor(). - */ -extern DECLSPEC void SDL_FreeCursor(SDL_Cursor *cursor); - -/* - * Toggle whether or not the cursor is shown on the screen. - * The cursor start off displayed, but can be turned off. - * SDL_ShowCursor() returns 1 if the cursor was being displayed - * before the call, or 0 if it was not. You can query the current - * state by passing a 'toggle' value of -1. - */ -extern DECLSPEC int SDL_ShowCursor(int toggle); - -/* Used as a mask when testing buttons in buttonstate - Button 1: Left mouse button - Button 2: Middle mouse button - Button 3: Right mouse button - */ -#define SDL_BUTTON(X) (SDL_PRESSED<<(X-1)) -#define SDL_BUTTON_LEFT 1 -#define SDL_BUTTON_MIDDLE 2 -#define SDL_BUTTON_RIGHT 3 -#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT) -#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE) -#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT) - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_mouse_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_mutex.h ./win32/SDL-1.2.2/include/SDL_mutex.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_mutex.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_mutex.h 1970-01-01 09:00:00 +0900 @@ -1,163 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_mutex.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -#ifndef _SDL_mutex_h -#define _SDL_mutex_h - -/* Functions to provide thread synchronization primitives - - These are independent of the other SDL routines. -*/ - -#include "SDL_main.h" -#include "SDL_types.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Synchronization functions which can time out return this value - if they time out. -*/ -#define SDL_MUTEX_TIMEDOUT 1 - -/* This is the timeout value which corresponds to never time out */ -#define SDL_MUTEX_MAXWAIT (~(Uint32)0) - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Mutex functions */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* The SDL mutex structure, defined in SDL_mutex.c */ -struct SDL_mutex; -typedef struct SDL_mutex SDL_mutex; - -/* Create a mutex, initialized unlocked */ -extern DECLSPEC SDL_mutex * SDL_CreateMutex(void); - -/* Lock the mutex (Returns 0, or -1 on error) */ -#define SDL_LockMutex(m) SDL_mutexP(m) -extern DECLSPEC int SDL_mutexP(SDL_mutex *mutex); - -/* Unlock the mutex (Returns 0, or -1 on error) */ -#define SDL_UnlockMutex(m) SDL_mutexV(m) -extern DECLSPEC int SDL_mutexV(SDL_mutex *mutex); - -/* Destroy a mutex */ -extern DECLSPEC void SDL_DestroyMutex(SDL_mutex *mutex); - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Semaphore functions */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* The SDL semaphore structure, defined in SDL_sem.c */ -struct SDL_semaphore; -typedef struct SDL_semaphore SDL_sem; - -/* Create a semaphore, initialized with value, returns NULL on failure. */ -extern DECLSPEC SDL_sem * SDL_CreateSemaphore(Uint32 initial_value); - -/* Destroy a semaphore */ -extern DECLSPEC void SDL_DestroySemaphore(SDL_sem *sem); - -/* This function suspends the calling thread until the semaphore pointed - * to by sem has a positive count. It then atomically decreases the semaphore - * count. - */ -extern DECLSPEC int SDL_SemWait(SDL_sem *sem); - -/* Non-blocking variant of SDL_SemWait(), returns 0 if the wait succeeds, - SDL_MUTEX_TIMEDOUT if the wait would block, and -1 on error. -*/ -extern DECLSPEC int SDL_SemTryWait(SDL_sem *sem); - -/* Variant of SDL_SemWait() with a timeout in milliseconds, returns 0 if - the wait succeeds, SDL_MUTEX_TIMEDOUT if the wait does not succeed in - the allotted time, and -1 on error. - On some platforms this function is implemented by looping with a delay - of 1 ms, and so should be avoided if possible. -*/ -extern DECLSPEC int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 ms); - -/* Atomically increases the semaphore's count (not blocking), returns 0, - or -1 on error. - */ -extern DECLSPEC int SDL_SemPost(SDL_sem *sem); - -/* Returns the current count of the semaphore */ -extern DECLSPEC Uint32 SDL_SemValue(SDL_sem *sem); - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Condition variable functions */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* The SDL condition variable structure, defined in SDL_cond.c */ -struct SDL_cond; -typedef struct SDL_cond SDL_cond; - -/* Create a condition variable */ -extern DECLSPEC SDL_cond * SDL_CreateCond(void); - -/* Destroy a condition variable */ -extern DECLSPEC void SDL_DestroyCond(SDL_cond *cond); - -/* Restart one of the threads that are waiting on the condition variable, - returns 0 or -1 on error. - */ -extern DECLSPEC int SDL_CondSignal(SDL_cond *cond); - -/* Restart all threads that are waiting on the condition variable, - returns 0 or -1 on error. - */ -extern DECLSPEC int SDL_CondBroadcast(SDL_cond *cond); - -/* Wait on the condition variable, unlocking the provided mutex. - The mutex must be locked before entering this function! - Returns 0 when it is signaled, or -1 on error. - */ -extern DECLSPEC int SDL_CondWait(SDL_cond *cond, SDL_mutex *mut); - -/* Waits for at most 'ms' milliseconds, and returns 0 if the condition - variable is signaled, SDL_MUTEX_TIMEDOUT if the condition is not - signaled in the allotted time, and -1 on error. - On some platforms this function is implemented by looping with a delay - of 1 ms, and so should be avoided if possible. -*/ -extern DECLSPEC int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_mutex_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_quit.h ./win32/SDL-1.2.2/include/SDL_quit.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_quit.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_quit.h 1970-01-01 09:00:00 +0900 @@ -1,52 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_quit.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL quit event handling */ - -#ifndef _SDL_quit_h -#define _SDL_quit_h - -/* - An SDL_QUITEVENT is generated when the user tries to close the application - window. If it is ignored or filtered out, the window will remain open. - If it is not ignored or filtered, it is queued normally and the window - is allowed to close. When the window is closed, screen updates will - complete, but have no effect. - - SDL_Init() installs signal handlers for SIGINT (keyboard interrupt) - and SIGTERM (system termination request), if handlers do not already - exist, that generate SDL_QUITEVENT events as well. There is no way - to determine the cause of an SDL_QUITEVENT, but setting a signal - handler in your application will override the default generation of - quit events for that signal. -*/ - -/* There are no functions directly affecting the quit event */ -#define SDL_QuitRequested() \ - (SDL_PumpEvents(), SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUITMASK)) - -#endif /* _SDL_quit_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_rwops.h ./win32/SDL-1.2.2/include/SDL_rwops.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_rwops.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_rwops.h 1970-01-01 09:00:00 +0900 @@ -1,113 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_rwops.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* This file provides a general interface for SDL to read and write - data sources. It can easily be extended to files, memory, etc. -*/ - -#ifndef _SDL_RWops_h -#define _SDL_RWops_h - -#include - -#include "SDL_types.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the read/write operation structure -- very basic */ - -typedef struct SDL_RWops { - /* Seek to 'offset' relative to whence, one of stdio's whence values: - SEEK_SET, SEEK_CUR, SEEK_END - Returns the final offset in the data source. - */ - int (*seek)(struct SDL_RWops *context, int offset, int whence); - - /* Read up to 'num' objects each of size 'objsize' from the data - source to the area pointed at by 'ptr'. - Returns the number of objects read, or -1 if the read failed. - */ - int (*read)(struct SDL_RWops *context, void *ptr, int size, int maxnum); - - /* Write exactly 'num' objects each of size 'objsize' from the area - pointed at by 'ptr' to data source. - Returns 'num', or -1 if the write failed. - */ - int (*write)(struct SDL_RWops *context, const void *ptr, int size, int num); - - /* Close and free an allocated SDL_FSops structure */ - int (*close)(struct SDL_RWops *context); - - Uint32 type; - union { - struct { - int autoclose; - FILE *fp; - } stdio; - struct { - Uint8 *base; - Uint8 *here; - Uint8 *stop; - } mem; - struct { - void *data1; - } unknown; - } hidden; - -} SDL_RWops; - - -/* Functions to create SDL_RWops structures from various data sources */ - -extern DECLSPEC SDL_RWops * SDL_RWFromFile(const char *file, const char *mode); - -extern DECLSPEC SDL_RWops * SDL_RWFromFP(FILE *fp, int autoclose); - -extern DECLSPEC SDL_RWops * SDL_RWFromMem(void *mem, int size); - -extern DECLSPEC SDL_RWops * SDL_AllocRW(void); -extern DECLSPEC void SDL_FreeRW(SDL_RWops *area); - -/* Macros to easily read and write from an SDL_RWops structure */ -#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) -#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, SEEK_CUR) -#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) -#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) -#define SDL_RWclose(ctx) (ctx)->close(ctx) - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_RWops_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_syswm.h ./win32/SDL-1.2.2/include/SDL_syswm.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_syswm.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_syswm.h 1970-01-01 09:00:00 +0900 @@ -1,165 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_syswm.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Include file for SDL custom system window manager hooks */ - -#ifndef _SDL_syswm_h -#define _SDL_syswm_h - -#include "SDL_version.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Your application has access to a special type of event 'SDL_SYSWMEVENT', - which contains window-manager specific information and arrives whenever - an unhandled window event occurs. This event is ignored by default, but - you can enable it with SDL_EventState() -*/ -#ifdef SDL_PROTOTYPES_ONLY -struct SDL_SysWMinfo; -typedef struct SDL_SysWMinfo SDL_SysWMinfo; -#else - -/* This is the structure for custom window manager events */ -#if (defined(unix) || defined(__unix__) || defined(_AIX) || defined(__OpenBSD__)) && \ - (!defined(DISABLE_X11) && !defined(__CYGWIN32__)) - /* AIX is unix, of course, but the native compiler CSet doesn't define unix */ -#include -#include - -/* These are the various supported subsystems under UNIX */ -typedef enum { - SDL_SYSWM_X11 -} SDL_SYSWM_TYPE; - -/* The UNIX custom event structure */ -struct SDL_SysWMmsg { - SDL_version version; - SDL_SYSWM_TYPE subsystem; - union { - XEvent xevent; - } event; -}; - -/* The UNIX custom window manager information structure. - When this structure is returned, it holds information about which - low level system it is using, and will be one of SDL_SYSWM_TYPE. - */ -typedef struct { - SDL_version version; - SDL_SYSWM_TYPE subsystem; - union { - struct { - Display *display; /* The X11 display */ - Window window; /* The X11 display window */ - /* These locking functions should be called around - any X11 functions using the display variable. - They lock the event thread, so should not be - called around event functions or from event filters. - */ - void (*lock_func)(void); - void (*unlock_func)(void); - - /* Introduced in SDL 1.0.2 */ - Window fswindow; /* The X11 fullscreen window */ - Window wmwindow; /* The X11 managed input window */ - } x11; - } info; -} SDL_SysWMinfo; - -#elif defined(ENABLE_NANOX) -#include - -/* The generic custom event structure */ -struct SDL_SysWMmsg { - SDL_version version; - int data; -}; - -/* The windows custom window manager information structure */ -typedef struct { - SDL_version version ; - GR_WINDOW_ID window ; /* The display window */ -} SDL_SysWMinfo; - -#elif defined(WIN32) -#include - -/* The windows custom event structure */ -struct SDL_SysWMmsg { - SDL_version version; - HWND hwnd; /* The window for the message */ - UINT msg; /* The type of message */ - WPARAM wParam; /* WORD message parameter */ - LPARAM lParam; /* LONG message parameter */ -}; - -/* The windows custom window manager information structure */ -typedef struct { - SDL_version version; - HWND window; /* The Win32 display window */ -} SDL_SysWMinfo; - -#else - -/* The generic custom event structure */ -struct SDL_SysWMmsg { - SDL_version version; - int data; -}; - -/* The generic custom window manager information structure */ -typedef struct { - SDL_version version; - int data; -} SDL_SysWMinfo; - -#endif /* OS type */ - -#endif /* SDL_PROTOTYPES_ONLY */ - -/* Function prototypes */ -/* - * This function gives you custom hooks into the window manager information. - * It fills the structure pointed to by 'info' with custom information and - * returns 1 if the function is implemented. If it's not implemented, or - * the version member of the 'info' structure is invalid, it returns 0. - */ -extern DECLSPEC int SDL_GetWMInfo(SDL_SysWMinfo *info); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_syswm_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_thread.h ./win32/SDL-1.2.2/include/SDL_thread.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_thread.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_thread.h 1970-01-01 09:00:00 +0900 @@ -1,79 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_thread.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -#ifndef _SDL_thread_h -#define _SDL_thread_h - -/* Header for the SDL thread management routines - - These are independent of the other SDL routines. -*/ - -#include "SDL_main.h" -#include "SDL_types.h" - -/* Thread synchronization primitives */ -#include "SDL_mutex.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* The SDL thread structure, defined in SDL_thread.c */ -struct SDL_Thread; -typedef struct SDL_Thread SDL_Thread; - -/* Create a thread */ -extern DECLSPEC SDL_Thread * SDL_CreateThread(int (*fn)(void *), void *data); - -/* Get the 32-bit thread identifier for the current thread */ -extern DECLSPEC Uint32 SDL_ThreadID(void); - -/* Get the 32-bit thread identifier for the specified thread, - equivalent to SDL_ThreadID() if the specified thread is NULL. - */ -extern DECLSPEC Uint32 SDL_GetThreadID(SDL_Thread *thread); - -/* Wait for a thread to finish. - The return code for the thread function is placed in the area - pointed to by 'status', if 'status' is not NULL. - */ -extern DECLSPEC void SDL_WaitThread(SDL_Thread *thread, int *status); - -/* Forcefully kill a thread without worrying about its state */ -extern DECLSPEC void SDL_KillThread(SDL_Thread *thread); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_thread_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_timer.h ./win32/SDL-1.2.2/include/SDL_timer.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_timer.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_timer.h 1970-01-01 09:00:00 +0900 @@ -1,118 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_timer.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -#ifndef _SDL_timer_h -#define _SDL_timer_h - -/* Header for the SDL time management routines */ - -#include "SDL_main.h" -#include "SDL_types.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* This is the OS scheduler timeslice, in milliseconds */ -#define SDL_TIMESLICE 10 - -/* This is the maximum resolution of the SDL timer on all platforms */ -#define TIMER_RESOLUTION 10 /* Experimentally determined */ - -/* Get the number of milliseconds since the SDL library initialization. - * Note that this value wraps if the program runs for more than ~49 days. - */ -extern DECLSPEC Uint32 SDL_GetTicks(void); - -/* Wait a specified number of milliseconds before returning */ -extern DECLSPEC void SDL_Delay(Uint32 ms); - -/* Function prototype for the timer callback function */ -typedef Uint32 (*SDL_TimerCallback)(Uint32 interval); - -/* Set a callback to run after the specified number of milliseconds has - * elapsed. The callback function is passed the current timer interval - * and returns the next timer interval. If the returned value is the - * same as the one passed in, the periodic alarm continues, otherwise a - * new alarm is scheduled. If the callback returns 0, the periodic alarm - * is cancelled. - * - * To cancel a currently running timer, call SDL_SetTimer(0, NULL); - * - * The timer callback function may run in a different thread than your - * main code, and so shouldn't call any functions from within itself. - * - * The maximum resolution of this timer is 10 ms, which means that if - * you request a 16 ms timer, your callback will run approximately 20 ms - * later on an unloaded system. If you wanted to set a flag signaling - * a frame update at 30 frames per second (every 33 ms), you might set a - * timer for 30 ms: - * SDL_SetTimer((33/10)*10, flag_update); - * - * If you use this function, you need to pass SDL_INIT_TIMER to SDL_Init(). - * - * Under UNIX, you should not use raise or use SIGALRM and this function - * in the same program, as it is implemented using setitimer(). You also - * should not use this function in multi-threaded applications as signals - * to multi-threaded apps have undefined behavior in some implementations. - */ -extern DECLSPEC int SDL_SetTimer(Uint32 interval, SDL_TimerCallback callback); - -/* New timer API, supports multiple timers - * Written by Stephane Peter - */ - -/* Function prototype for the new timer callback function. - * The callback function is passed the current timer interval and returns - * the next timer interval. If the returned value is the same as the one - * passed in, the periodic alarm continues, otherwise a new alarm is - * scheduled. If the callback returns 0, the periodic alarm is cancelled. - */ -typedef Uint32 (*SDL_NewTimerCallback)(Uint32 interval, void *param); - -/* Definition of the timer ID type */ -typedef struct _SDL_TimerID *SDL_TimerID; - -/* Add a new timer to the pool of timers already running. - Returns a timer ID, or NULL when an error occurs. - */ -extern DECLSPEC SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param); - -/* Remove one of the multiple timers knowing its ID. - * Returns a boolean value indicating success. - */ -extern DECLSPEC SDL_bool SDL_RemoveTimer(SDL_TimerID t); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_timer_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_types.h ./win32/SDL-1.2.2/include/SDL_types.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_types.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_types.h 1970-01-01 09:00:00 +0900 @@ -1,87 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_types.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* General data types used by the SDL library */ - -#ifndef _SDL_types_h -#define _SDL_types_h - -/* The number of elements in a table */ -#define SDL_TABLESIZE(table) (sizeof(table)/sizeof(table[0])) - -/* Basic data types */ -typedef enum { - SDL_FALSE = 0, - SDL_TRUE = 1 -} SDL_bool; -typedef unsigned char Uint8; -typedef signed char Sint8; -typedef unsigned short Uint16; -typedef signed short Sint16; -typedef unsigned int Uint32; -typedef signed int Sint32; - -/* Figure out how to support 64-bit datatypes */ -#if !defined(__STRICT_ANSI__) -#if defined(__GNUC__) || defined(__MWERKS__) /* MJS */ -#define SDL_HAS_64BIT_TYPE long long -#elif defined(_MSC_VER) /* VC++ */ -#define SDL_HAS_64BIT_TYPE __int64 -#endif -#endif /* !__STRICT_ANSI__ */ - -/* The 64-bit datatype isn't supported on all platforms */ -#ifdef SDL_HAS_64BIT_TYPE -typedef unsigned SDL_HAS_64BIT_TYPE Uint64; -typedef SDL_HAS_64BIT_TYPE Sint64; -#else -/* This is really just a hack to prevent the compiler from complaining */ -typedef struct { - Uint32 hi; - Uint32 lo; -} Uint64, Sint64; -#endif - -/* Make sure the types really have the right sizes */ -#define SDL_COMPILE_TIME_ASSERT(name, x) \ - typedef int SDL_dummy_ ## name[(x) * 2 - 1] - -SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); -SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); -SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); -SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); -SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); -SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); -SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8); -SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); - -#undef SDL_COMPILE_TIME_ASSERT - -/* General keyboard/mouse state definitions */ -enum { SDL_PRESSED = 0x01, SDL_RELEASED = 0x00 }; - -#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_version.h ./win32/SDL-1.2.2/include/SDL_version.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_version.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_version.h 1970-01-01 09:00:00 +0900 @@ -1,90 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_version.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* This header defines the current SDL version */ - -#ifndef _SDL_version_h -#define _SDL_version_h - -#include "SDL_types.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL -*/ -#define SDL_MAJOR_VERSION 1 -#define SDL_MINOR_VERSION 2 -#define SDL_PATCHLEVEL 2 - -typedef struct { - Uint8 major; - Uint8 minor; - Uint8 patch; -} SDL_version; - -/* This macro can be used to fill a version structure with the compile-time - * version of the SDL library. - */ -#define SDL_VERSION(X) \ -{ \ - (X)->major = SDL_MAJOR_VERSION; \ - (X)->minor = SDL_MINOR_VERSION; \ - (X)->patch = SDL_PATCHLEVEL; \ -} - -/* This macro turns the version numbers into a numeric value: - (1,2,3) -> (1203) - This assumes that there will never be more than 100 patchlevels -*/ -#define SDL_VERSIONNUM(X, Y, Z) \ - (X)*1000 + (Y)*100 + (Z) - -/* This is the version number macro for the current SDL version */ -#define SDL_COMPILEDVERSION \ - SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) - -/* This macro will evaluate to true if compiled with SDL at least X.Y.Z */ -#define SDL_VERSION_ATLEAST(X, Y, Z) \ - (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) - -/* This function gets the version of the dynamically linked SDL library. - it should NOT be used to fill a version structure, instead you should - use the SDL_Version() macro. - */ -extern DECLSPEC const SDL_version * SDL_Linked_Version(void); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_version_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_video.h ./win32/SDL-1.2.2/include/SDL_video.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/SDL_video.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/SDL_video.h 1970-01-01 09:00:00 +0900 @@ -1,891 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -#ifdef SAVE_RCSID -static char rcsid = - "@(#) SDL_video.h,v 1.1 2002/10/20 13:03:12 forgotten Exp"; -#endif - -/* Header file for access to the SDL raw framebuffer window */ - -#ifndef _SDL_video_h -#define _SDL_video_h - -#include - -#include "SDL_types.h" -#include "SDL_mutex.h" -#include "SDL_rwops.h" - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Transparency definitions: These define alpha as the opacity of a surface */ -#define SDL_ALPHA_OPAQUE 255 -#define SDL_ALPHA_TRANSPARENT 0 - -/* Useful data types */ -typedef struct { - Sint16 x, y; - Uint16 w, h; -} SDL_Rect; - -typedef struct { - Uint8 r; - Uint8 g; - Uint8 b; - Uint8 unused; -} SDL_Color; - -typedef struct { - int ncolors; - SDL_Color *colors; -} SDL_Palette; - -/* Everything in the pixel format structure is read-only */ -typedef struct SDL_PixelFormat { - SDL_Palette *palette; - Uint8 BitsPerPixel; - Uint8 BytesPerPixel; - Uint8 Rloss; - Uint8 Gloss; - Uint8 Bloss; - Uint8 Aloss; - Uint8 Rshift; - Uint8 Gshift; - Uint8 Bshift; - Uint8 Ashift; - Uint32 Rmask; - Uint32 Gmask; - Uint32 Bmask; - Uint32 Amask; - - /* RGB color key information */ - Uint32 colorkey; - /* Alpha value information (per-surface alpha) */ - Uint8 alpha; -} SDL_PixelFormat; - -/* typedef for private surface blitting functions */ -struct SDL_Surface; -typedef int (*SDL_blit)(struct SDL_Surface *src, SDL_Rect *srcrect, - struct SDL_Surface *dst, SDL_Rect *dstrect); - -/* This structure should be treated as read-only, except for 'pixels', - which, if not NULL, contains the raw pixel data for the surface. -*/ -typedef struct SDL_Surface { - Uint32 flags; /* Read-only */ - SDL_PixelFormat *format; /* Read-only */ - int w, h; /* Read-only */ - Uint16 pitch; /* Read-only */ - void *pixels; /* Read-write */ - int offset; /* Private */ - - /* Hardware-specific surface info */ - struct private_hwdata *hwdata; - - /* clipping information */ - SDL_Rect clip_rect; /* Read-only */ - Uint32 unused1; /* for binary compatibility */ - - /* Allow recursive locks */ - Uint32 locked; /* Private */ - - /* info for fast blit mapping to other surfaces */ - struct SDL_BlitMap *map; /* Private */ - - /* format version, bumped at every change to invalidate blit maps */ - unsigned int format_version; /* Private */ - - /* Reference count -- used when freeing surface */ - int refcount; /* Read-mostly */ -} SDL_Surface; - -/* These are the currently supported flags for the SDL_surface */ -/* Available for SDL_CreateRGBSurface() or SDL_SetVideoMode() */ -#define SDL_SWSURFACE 0x00000000 /* Surface is in system memory */ -#define SDL_HWSURFACE 0x00000001 /* Surface is in video memory */ -#define SDL_ASYNCBLIT 0x00000004 /* Use asynchronous blits if possible */ -/* Available for SDL_SetVideoMode() */ -#define SDL_ANYFORMAT 0x10000000 /* Allow any video depth/pixel-format */ -#define SDL_HWPALETTE 0x20000000 /* Surface has exclusive palette */ -#define SDL_DOUBLEBUF 0x40000000 /* Set up double-buffered video mode */ -#define SDL_FULLSCREEN 0x80000000 /* Surface is a full screen display */ -#define SDL_OPENGL 0x00000002 /* Create an OpenGL rendering context */ -#define SDL_OPENGLBLIT 0x0000000A /* Create an OpenGL rendering context and use it for blitting */ -#define SDL_RESIZABLE 0x00000010 /* This video mode may be resized */ -#define SDL_NOFRAME 0x00000020 /* No window caption or edge frame */ -/* Used internally (read-only) */ -#define SDL_HWACCEL 0x00000100 /* Blit uses hardware acceleration */ -#define SDL_SRCCOLORKEY 0x00001000 /* Blit uses a source color key */ -#define SDL_RLEACCELOK 0x00002000 /* Private flag */ -#define SDL_RLEACCEL 0x00004000 /* Surface is RLE encoded */ -#define SDL_SRCALPHA 0x00010000 /* Blit uses source alpha blending */ -#define SDL_PREALLOC 0x01000000 /* Surface uses preallocated memory */ - -/* Evaluates to true if the surface needs to be locked before access */ -#define SDL_MUSTLOCK(surface) \ - (surface->offset || \ - ((surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_RLEACCEL)) != 0)) - - -/* Useful for determining the video hardware capabilities */ -typedef struct { - Uint32 hw_available :1; /* Flag: Can you create hardware surfaces? */ - Uint32 wm_available :1; /* Flag: Can you talk to a window manager? */ - Uint32 UnusedBits1 :6; - Uint32 UnusedBits2 :1; - Uint32 blit_hw :1; /* Flag: Accelerated blits HW --> HW */ - Uint32 blit_hw_CC :1; /* Flag: Accelerated blits with Colorkey */ - Uint32 blit_hw_A :1; /* Flag: Accelerated blits with Alpha */ - Uint32 blit_sw :1; /* Flag: Accelerated blits SW --> HW */ - Uint32 blit_sw_CC :1; /* Flag: Accelerated blits with Colorkey */ - Uint32 blit_sw_A :1; /* Flag: Accelerated blits with Alpha */ - Uint32 blit_fill :1; /* Flag: Accelerated color fill */ - Uint32 UnusedBits3 :16; - Uint32 video_mem; /* The total amount of video memory (in K) */ - SDL_PixelFormat *vfmt; /* Value: The format of the video surface */ -} SDL_VideoInfo; - - -/* The most common video overlay formats. - For an explanation of these pixel formats, see: - http://www.webartz.com/fourcc/indexyuv.htm - - For information on the relationship between color spaces, see: - http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html - */ -#define SDL_YV12_OVERLAY 0x32315659 /* Planar mode: Y + V + U (3 planes) */ -#define SDL_IYUV_OVERLAY 0x56555949 /* Planar mode: Y + U + V (3 planes) */ -#define SDL_YUY2_OVERLAY 0x32595559 /* Packed mode: Y0+U0+Y1+V0 (1 plane) */ -#define SDL_UYVY_OVERLAY 0x59565955 /* Packed mode: U0+Y0+V0+Y1 (1 plane) */ -#define SDL_YVYU_OVERLAY 0x55595659 /* Packed mode: Y0+V0+Y1+U0 (1 plane) */ - -/* The YUV hardware video overlay */ -typedef struct SDL_Overlay { - Uint32 format; /* Read-only */ - int w, h; /* Read-only */ - int planes; /* Read-only */ - Uint16 *pitches; /* Read-only */ - Uint8 **pixels; /* Read-write */ - - /* Hardware-specific surface info */ - struct private_yuvhwfuncs *hwfuncs; - struct private_yuvhwdata *hwdata; - - /* Special flags */ - Uint32 hw_overlay :1; /* Flag: This overlay hardware accelerated? */ - Uint32 UnusedBits :31; -} SDL_Overlay; - - -/* Public enumeration for setting the OpenGL window attributes. */ -typedef enum { - SDL_GL_RED_SIZE, - SDL_GL_GREEN_SIZE, - SDL_GL_BLUE_SIZE, - SDL_GL_ALPHA_SIZE, - SDL_GL_BUFFER_SIZE, - SDL_GL_DOUBLEBUFFER, - SDL_GL_DEPTH_SIZE, - SDL_GL_STENCIL_SIZE, - SDL_GL_ACCUM_RED_SIZE, - SDL_GL_ACCUM_GREEN_SIZE, - SDL_GL_ACCUM_BLUE_SIZE, - SDL_GL_ACCUM_ALPHA_SIZE -} SDL_GLattr; - -/* flags for SDL_SetPalette() */ -#define SDL_LOGPAL 0x01 -#define SDL_PHYSPAL 0x02 - -/* Function prototypes */ - -/* These functions are used internally, and should not be used unless you - * have a specific need to specify the video driver you want to use. - * You should normally use SDL_Init() or SDL_InitSubSystem(). - * - * SDL_VideoInit() initializes the video subsystem -- sets up a connection - * to the window manager, etc, and determines the current video mode and - * pixel format, but does not initialize a window or graphics mode. - * Note that event handling is activated by this routine. - * - * If you use both sound and video in your application, you need to call - * SDL_Init() before opening the sound device, otherwise under Win32 DirectX, - * you won't be able to set full-screen display modes. - */ -extern DECLSPEC int SDL_VideoInit(const char *driver_name, Uint32 flags); -extern DECLSPEC void SDL_VideoQuit(void); - -/* This function fills the given character buffer with the name of the - * video driver, and returns a pointer to it if the video driver has - * been initialized. It returns NULL if no driver has been initialized. - */ -extern DECLSPEC char *SDL_VideoDriverName(char *namebuf, int maxlen); - -/* - * This function returns a pointer to the current display surface. - * If SDL is doing format conversion on the display surface, this - * function returns the publicly visible surface, not the real video - * surface. - */ -extern DECLSPEC SDL_Surface * SDL_GetVideoSurface(void); - -/* - * This function returns a read-only pointer to information about the - * video hardware. If this is called before SDL_SetVideoMode(), the 'vfmt' - * member of the returned structure will contain the pixel format of the - * "best" video mode. - */ -extern DECLSPEC const SDL_VideoInfo * SDL_GetVideoInfo(void); - -/* - * Check to see if a particular video mode is supported. - * It returns 0 if the requested mode is not supported under any bit depth, - * or returns the bits-per-pixel of the closest available mode with the - * given width and height. If this bits-per-pixel is different from the - * one used when setting the video mode, SDL_SetVideoMode() will succeed, - * but will emulate the requested bits-per-pixel with a shadow surface. - * - * The arguments to SDL_VideoModeOK() are the same ones you would pass to - * SDL_SetVideoMode() - */ -extern DECLSPEC int SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags); - -/* - * Return a pointer to an array of available screen dimensions for the - * given format and video flags, sorted largest to smallest. Returns - * NULL if there are no dimensions available for a particular format, - * or (SDL_Rect **)-1 if any dimension is okay for the given format. - * - * If 'format' is NULL, the mode list will be for the format given - * by SDL_GetVideoInfo()->vfmt - */ -extern DECLSPEC SDL_Rect ** SDL_ListModes(SDL_PixelFormat *format, Uint32 flags); - -/* - * Set up a video mode with the specified width, height and bits-per-pixel. - * - * If 'bpp' is 0, it is treated as the current display bits per pixel. - * - * If SDL_ANYFORMAT is set in 'flags', the SDL library will try to set the - * requested bits-per-pixel, but will return whatever video pixel format is - * available. The default is to emulate the requested pixel format if it - * is not natively available. - * - * If SDL_HWSURFACE is set in 'flags', the video surface will be placed in - * video memory, if possible, and you may have to call SDL_LockSurface() - * in order to access the raw framebuffer. Otherwise, the video surface - * will be created in system memory. - * - * If SDL_ASYNCBLIT is set in 'flags', SDL will try to perform rectangle - * updates asynchronously, but you must always lock before accessing pixels. - * SDL will wait for updates to complete before returning from the lock. - * - * If SDL_HWPALETTE is set in 'flags', the SDL library will guarantee - * that the colors set by SDL_SetColors() will be the colors you get. - * Otherwise, in 8-bit mode, SDL_SetColors() may not be able to set all - * of the colors exactly the way they are requested, and you should look - * at the video surface structure to determine the actual palette. - * If SDL cannot guarantee that the colors you request can be set, - * i.e. if the colormap is shared, then the video surface may be created - * under emulation in system memory, overriding the SDL_HWSURFACE flag. - * - * If SDL_FULLSCREEN is set in 'flags', the SDL library will try to set - * a fullscreen video mode. The default is to create a windowed mode - * if the current graphics system has a window manager. - * If the SDL library is able to set a fullscreen video mode, this flag - * will be set in the surface that is returned. - * - * If SDL_DOUBLEBUF is set in 'flags', the SDL library will try to set up - * two surfaces in video memory and swap between them when you call - * SDL_Flip(). This is usually slower than the normal single-buffering - * scheme, but prevents "tearing" artifacts caused by modifying video - * memory while the monitor is refreshing. It should only be used by - * applications that redraw the entire screen on every update. - * - * If SDL_RESIZABLE is set in 'flags', the SDL library will allow the - * window manager, if any, to resize the window at runtime. When this - * occurs, SDL will send a SDL_VIDEORESIZE event to you application, - * and you must respond to the event by re-calling SDL_SetVideoMode() - * with the requested size (or another size that suits the application). - * - * If SDL_NOFRAME is set in 'flags', the SDL library will create a window - * without any title bar or frame decoration. Fullscreen video modes have - * this flag set automatically. - * - * This function returns the video framebuffer surface, or NULL if it fails. - * - * If you rely on functionality provided by certain video flags, check the - * flags of the returned surface to make sure that functionality is available. - * SDL will fall back to reduced functionality if the exact flags you wanted - * are not available. - */ -extern DECLSPEC SDL_Surface *SDL_SetVideoMode - (int width, int height, int bpp, Uint32 flags); - -/* - * Makes sure the given list of rectangles is updated on the given screen. - * If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire - * screen. - * These functions should not be called while 'screen' is locked. - */ -extern DECLSPEC void SDL_UpdateRects - (SDL_Surface *screen, int numrects, SDL_Rect *rects); -extern DECLSPEC void SDL_UpdateRect - (SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); - -/* - * On hardware that supports double-buffering, this function sets up a flip - * and returns. The hardware will wait for vertical retrace, and then swap - * video buffers before the next video surface blit or lock will return. - * On hardware that doesn not support double-buffering, this is equivalent - * to calling SDL_UpdateRect(screen, 0, 0, 0, 0); - * The SDL_DOUBLEBUF flag must have been passed to SDL_SetVideoMode() when - * setting the video mode for this function to perform hardware flipping. - * This function returns 0 if successful, or -1 if there was an error. - */ -extern DECLSPEC int SDL_Flip(SDL_Surface *screen); - -/* - * Set the gamma correction for each of the color channels. - * The gamma values range (approximately) between 0.1 and 10.0 - * - * If this function isn't supported directly by the hardware, it will - * be emulated using gamma ramps, if available. If successful, this - * function returns 0, otherwise it returns -1. - */ -extern DECLSPEC int SDL_SetGamma(float red, float green, float blue); - -/* - * Set the gamma translation table for the red, green, and blue channels - * of the video hardware. Each table is an array of 256 16-bit quantities, - * representing a mapping between the input and output for that channel. - * The input is the index into the array, and the output is the 16-bit - * gamma value at that index, scaled to the output color precision. - * - * You may pass NULL for any of the channels to leave it unchanged. - * If the call succeeds, it will return 0. If the display driver or - * hardware does not support gamma translation, or otherwise fails, - * this function will return -1. - */ -extern DECLSPEC int SDL_SetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue); - -/* - * Retrieve the current values of the gamma translation tables. - * - * You must pass in valid pointers to arrays of 256 16-bit quantities. - * Any of the pointers may be NULL to ignore that channel. - * If the call succeeds, it will return 0. If the display driver or - * hardware does not support gamma translation, or otherwise fails, - * this function will return -1. - */ -extern DECLSPEC int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue); - -/* - * Sets a portion of the colormap for the given 8-bit surface. If 'surface' - * is not a palettized surface, this function does nothing, returning 0. - * If all of the colors were set as passed to SDL_SetColors(), it will - * return 1. If not all the color entries were set exactly as given, - * it will return 0, and you should look at the surface palette to - * determine the actual color palette. - * - * When 'surface' is the surface associated with the current display, the - * display colormap will be updated with the requested colors. If - * SDL_HWPALETTE was set in SDL_SetVideoMode() flags, SDL_SetColors() - * will always return 1, and the palette is guaranteed to be set the way - * you desire, even if the window colormap has to be warped or run under - * emulation. - */ -extern DECLSPEC int SDL_SetColors(SDL_Surface *surface, - SDL_Color *colors, int firstcolor, int ncolors); - -/* - * Sets a portion of the colormap for a given 8-bit surface. - * 'flags' is one or both of: - * SDL_LOGPAL -- set logical palette, which controls how blits are mapped - * to/from the surface, - * SDL_PHYSPAL -- set physical palette, which controls how pixels look on - * the screen - * Only screens have physical palettes. Separate change of physical/logical - * palettes is only possible if the screen has SDL_HWPALETTE set. - * - * The return value is 1 if all colours could be set as requested, and 0 - * otherwise. - * - * SDL_SetColors() is equivalent to calling this function with - * flags = (SDL_LOGPAL|SDL_PHYSPAL). - */ -extern DECLSPEC int SDL_SetPalette(SDL_Surface *surface, int flags, - SDL_Color *colors, int firstcolor, - int ncolors); - -/* - * Maps an RGB triple to an opaque pixel value for a given pixel format - */ -extern DECLSPEC Uint32 SDL_MapRGB - (SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b); - -/* - * Maps an RGBA quadruple to a pixel value for a given pixel format - */ -extern DECLSPEC Uint32 SDL_MapRGBA(SDL_PixelFormat *format, - Uint8 r, Uint8 g, Uint8 b, Uint8 a); - -/* - * Maps a pixel value into the RGB components for a given pixel format - */ -extern DECLSPEC void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, - Uint8 *r, Uint8 *g, Uint8 *b); - -/* - * Maps a pixel value into the RGBA components for a given pixel format - */ -extern DECLSPEC void SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt, - Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); - -/* - * Allocate and free an RGB surface (must be called after SDL_SetVideoMode) - * If the depth is 4 or 8 bits, an empty palette is allocated for the surface. - * If the depth is greater than 8 bits, the pixel format is set using the - * flags '[RGB]mask'. - * If the function runs out of memory, it will return NULL. - * - * The 'flags' tell what kind of surface to create. - * SDL_SWSURFACE means that the surface should be created in system memory. - * SDL_HWSURFACE means that the surface should be created in video memory, - * with the same format as the display surface. This is useful for surfaces - * that will not change much, to take advantage of hardware acceleration - * when being blitted to the display surface. - * SDL_ASYNCBLIT means that SDL will try to perform asynchronous blits with - * this surface, but you must always lock it before accessing the pixels. - * SDL will wait for current blits to finish before returning from the lock. - * SDL_SRCCOLORKEY indicates that the surface will be used for colorkey blits. - * If the hardware supports acceleration of colorkey blits between - * two surfaces in video memory, SDL will try to place the surface in - * video memory. If this isn't possible or if there is no hardware - * acceleration available, the surface will be placed in system memory. - * SDL_SRCALPHA means that the surface will be used for alpha blits and - * if the hardware supports hardware acceleration of alpha blits between - * two surfaces in video memory, to place the surface in video memory - * if possible, otherwise it will be placed in system memory. - * If the surface is created in video memory, blits will be _much_ faster, - * but the surface format must be identical to the video surface format, - * and the only way to access the pixels member of the surface is to use - * the SDL_LockSurface() and SDL_UnlockSurface() calls. - * If the requested surface actually resides in video memory, SDL_HWSURFACE - * will be set in the flags member of the returned surface. If for some - * reason the surface could not be placed in video memory, it will not have - * the SDL_HWSURFACE flag set, and will be created in system memory instead. - */ -#define SDL_AllocSurface SDL_CreateRGBSurface -extern DECLSPEC SDL_Surface *SDL_CreateRGBSurface - (Uint32 flags, int width, int height, int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); -extern DECLSPEC SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, - int width, int height, int depth, int pitch, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); -extern DECLSPEC void SDL_FreeSurface(SDL_Surface *surface); - -/* - * SDL_LockSurface() sets up a surface for directly accessing the pixels. - * Between calls to SDL_LockSurface()/SDL_UnlockSurface(), you can write - * to and read from 'surface->pixels', using the pixel format stored in - * 'surface->format'. Once you are done accessing the surface, you should - * use SDL_UnlockSurface() to release it. - * - * Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates - * to 0, then you can read and write to the surface at any time, and the - * pixel format of the surface will not change. In particular, if the - * SDL_HWSURFACE flag is not given when calling SDL_SetVideoMode(), you - * will not need to lock the display surface before accessing it. - * - * No operating system or library calls should be made between lock/unlock - * pairs, as critical system locks may be held during this time. - * - * SDL_LockSurface() returns 0, or -1 if the surface couldn't be locked. - */ -extern DECLSPEC int SDL_LockSurface(SDL_Surface *surface); -extern DECLSPEC void SDL_UnlockSurface(SDL_Surface *surface); - -/* - * Load a surface from a seekable SDL data source (memory or file.) - * If 'freesrc' is non-zero, the source will be closed after being read. - * Returns the new surface, or NULL if there was an error. - * The new surface should be freed with SDL_FreeSurface(). - */ -extern DECLSPEC SDL_Surface * SDL_LoadBMP_RW(SDL_RWops *src, int freesrc); - -/* Convenience macro -- load a surface from a file */ -#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) - -/* - * Save a surface to a seekable SDL data source (memory or file.) - * If 'freedst' is non-zero, the source will be closed after being written. - * Returns 0 if successful or -1 if there was an error. - */ -extern DECLSPEC int SDL_SaveBMP_RW - (SDL_Surface *surface, SDL_RWops *dst, int freedst); - -/* Convenience macro -- save a surface to a file */ -#define SDL_SaveBMP(surface, file) \ - SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) - -/* - * Sets the color key (transparent pixel) in a blittable surface. - * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), - * 'key' will be the transparent pixel in the source image of a blit. - * SDL_RLEACCEL requests RLE acceleration for the surface if present, - * and removes RLE acceleration if absent. - * If 'flag' is 0, this function clears any current color key. - * This function returns 0, or -1 if there was an error. - */ -extern DECLSPEC int SDL_SetColorKey - (SDL_Surface *surface, Uint32 flag, Uint32 key); - -/* - * This function sets the alpha value for the entire surface, as opposed to - * using the alpha component of each pixel. This value measures the range - * of transparency of the surface, 0 being completely transparent to 255 - * being completely opaque. An 'alpha' value of 255 causes blits to be - * opaque, the source pixels copied to the destination (the default). Note - * that per-surface alpha can be combined with colorkey transparency. - * - * If 'flag' is 0, alpha blending is disabled for the surface. - * If 'flag' is SDL_SRCALPHA, alpha blending is enabled for the surface. - * OR:ing the flag with SDL_RLEACCEL requests RLE acceleration for the - * surface; if SDL_RLEACCEL is not specified, the RLE accel will be removed. - */ -extern DECLSPEC int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha); - -/* - * Sets the clipping rectangle for the destination surface in a blit. - * - * If the clip rectangle is NULL, clipping will be disabled. - * If the clip rectangle doesn't intersect the surface, the function will - * return SDL_FALSE and blits will be completely clipped. Otherwise the - * function returns SDL_TRUE and blits to the surface will be clipped to - * the intersection of the surface area and the clipping rectangle. - * - * Note that blits are automatically clipped to the edges of the source - * and destination surfaces. - */ -extern DECLSPEC SDL_bool SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect); - -/* - * Gets the clipping rectangle for the destination surface in a blit. - * 'rect' must be a pointer to a valid rectangle which will be filled - * with the correct values. - */ -extern DECLSPEC void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect); - -/* - * Creates a new surface of the specified format, and then copies and maps - * the given surface to it so the blit of the converted surface will be as - * fast as possible. If this function fails, it returns NULL. - * - * The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those - * semantics. You can also pass SDL_RLEACCEL in the flags parameter and - * SDL will try to RLE accelerate colorkey and alpha blits in the resulting - * surface. - * - * This function is used internally by SDL_DisplayFormat(). - */ -extern DECLSPEC SDL_Surface *SDL_ConvertSurface - (SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags); - -/* - * This performs a fast blit from the source surface to the destination - * surface. It assumes that the source and destination rectangles are - * the same size. If either 'srcrect' or 'dstrect' are NULL, the entire - * surface (src or dst) is copied. The final blit rectangles are saved - * in 'srcrect' and 'dstrect' after all clipping is performed. - * If the blit is successful, it returns 0, otherwise it returns -1. - * - * The blit function should not be called on a locked surface. - * - * The blit semantics for surfaces with and without alpha and colorkey - * are defined as follows: - * - * RGBA->RGB: - * SDL_SRCALPHA set: - * alpha-blend (using alpha-channel). - * SDL_SRCCOLORKEY ignored. - * SDL_SRCALPHA not set: - * copy RGB. - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * RGB values of the source colour key, ignoring alpha in the - * comparison. - * - * RGB->RGBA: - * SDL_SRCALPHA set: - * alpha-blend (using the source per-surface alpha value); - * set destination alpha to opaque. - * SDL_SRCALPHA not set: - * copy RGB, set destination alpha to opaque. - * both: - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * source colour key. - * - * RGBA->RGBA: - * SDL_SRCALPHA set: - * alpha-blend (using the source alpha channel) the RGB values; - * leave destination alpha untouched. [Note: is this correct?] - * SDL_SRCCOLORKEY ignored. - * SDL_SRCALPHA not set: - * copy all of RGBA to the destination. - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * RGB values of the source colour key, ignoring alpha in the - * comparison. - * - * RGB->RGB: - * SDL_SRCALPHA set: - * alpha-blend (using the source per-surface alpha value). - * SDL_SRCALPHA not set: - * copy RGB. - * both: - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * source colour key. - * - * If either of the surfaces were in video memory, and the blit returns -2, - * the video memory was lost, so it should be reloaded with artwork and - * re-blitted: - while ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) { - while ( SDL_LockSurface(image) < 0 ) - Sleep(10); - -- Write image pixels to image->pixels -- - SDL_UnlockSurface(image); - } - * This happens under DirectX 5.0 when the system switches away from your - * fullscreen application. The lock will also fail until you have access - * to the video memory again. - */ -/* You should call SDL_BlitSurface() unless you know exactly how SDL - blitting works internally and how to use the other blit functions. -*/ -#define SDL_BlitSurface SDL_UpperBlit - -/* This is the public blit function, SDL_BlitSurface(), and it performs - rectangle validation and clipping before passing it to SDL_LowerBlit() -*/ -extern DECLSPEC int SDL_UpperBlit - (SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); -/* This is a semi-private blit function and it performs low-level surface - blitting only. -*/ -extern DECLSPEC int SDL_LowerBlit - (SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); - -/* - * This function performs a fast fill of the given rectangle with 'color' - * The given rectangle is clipped to the destination surface clip area - * and the final fill rectangle is saved in the passed in pointer. - * If 'dstrect' is NULL, the whole surface will be filled with 'color' - * The color should be a pixel of the format used by the surface, and - * can be generated by the SDL_MapRGB() function. - * This function returns 0 on success, or -1 on error. - */ -extern DECLSPEC int SDL_FillRect - (SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); - -/* - * This function takes a surface and copies it to a new surface of the - * pixel format and colors of the video framebuffer, suitable for fast - * blitting onto the display surface. It calls SDL_ConvertSurface() - * - * If you want to take advantage of hardware colorkey or alpha blit - * acceleration, you should set the colorkey and alpha value before - * calling this function. - * - * If the conversion fails or runs out of memory, it returns NULL - */ -extern DECLSPEC SDL_Surface * SDL_DisplayFormat(SDL_Surface *surface); - -/* - * This function takes a surface and copies it to a new surface of the - * pixel format and colors of the video framebuffer (if possible), - * suitable for fast alpha blitting onto the display surface. - * The new surface will always have an alpha channel. - * - * If you want to take advantage of hardware colorkey or alpha blit - * acceleration, you should set the colorkey and alpha value before - * calling this function. - * - * If the conversion fails or runs out of memory, it returns NULL - */ -extern DECLSPEC SDL_Surface * SDL_DisplayFormatAlpha(SDL_Surface *surface); - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* YUV video surface overlay functions */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* This function creates a video output overlay - Calling the returned surface an overlay is something of a misnomer because - the contents of the display surface underneath the area where the overlay - is shown is undefined - it may be overwritten with the converted YUV data. -*/ -extern DECLSPEC SDL_Overlay *SDL_CreateYUVOverlay(int width, int height, - Uint32 format, SDL_Surface *display); - -/* Lock an overlay for direct access, and unlock it when you are done */ -extern DECLSPEC int SDL_LockYUVOverlay(SDL_Overlay *overlay); -extern DECLSPEC void SDL_UnlockYUVOverlay(SDL_Overlay *overlay); - -/* Blit a video overlay to the display surface. - The contents of the video surface underneath the blit destination are - not defined. - The width and height of the destination rectangle may be different from - that of the overlay, but currently only 2x scaling is supported. -*/ -extern DECLSPEC int SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect); - -/* Free a video overlay */ -extern DECLSPEC void SDL_FreeYUVOverlay(SDL_Overlay *overlay); - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* OpenGL support functions. */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Dynamically load a GL driver, if SDL is built with dynamic GL. - * - * SDL links normally with the OpenGL library on your system by default, - * but you can compile it to dynamically load the GL driver at runtime. - * If you do this, you need to retrieve all of the GL functions used in - * your program from the dynamic library using SDL_GL_GetProcAddress(). - * - * This is disabled in default builds of SDL. - */ -extern DECLSPEC int SDL_GL_LoadLibrary(const char *path); - -/* - * Get the address of a GL function (for extension functions) - */ -extern DECLSPEC void *SDL_GL_GetProcAddress(const char* proc); - -/* - * Set an attribute of the OpenGL subsystem before intialization. - */ -extern DECLSPEC int SDL_GL_SetAttribute(SDL_GLattr attr, int value); - -/* - * Get an attribute of the OpenGL subsystem from the windowing - * interface, such as glX. This is of course different from getting - * the values from SDL's internal OpenGL subsystem, which only - * stores the values you request before initialization. - * - * Developers should track the values they pass into SDL_GL_SetAttribute - * themselves if they want to retrieve these values. - */ -extern DECLSPEC int SDL_GL_GetAttribute(SDL_GLattr attr, int* value); - -/* - * Swap the OpenGL buffers, if double-buffering is supported. - */ -extern DECLSPEC void SDL_GL_SwapBuffers(void); - -/* - * Internal functions that should not be called unless you have read - * and understood the source code for these functions. - */ -extern DECLSPEC void SDL_GL_UpdateRects(int numrects, SDL_Rect* rects); -extern DECLSPEC void SDL_GL_Lock(void); -extern DECLSPEC void SDL_GL_Unlock(void); - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* These functions allow interaction with the window manager, if any. */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Sets/Gets the title and icon text of the display window - */ -extern DECLSPEC void SDL_WM_SetCaption(const char *title, const char *icon); -extern DECLSPEC void SDL_WM_GetCaption(char **title, char **icon); - -/* - * Sets the icon for the display window. - * This function must be called before the first call to SDL_SetVideoMode(). - * It takes an icon surface, and a mask in MSB format. - * If 'mask' is NULL, the entire icon surface will be used as the icon. - */ -extern DECLSPEC void SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask); - -/* - * This function iconifies the window, and returns 1 if it succeeded. - * If the function succeeds, it generates an SDL_APPACTIVE loss event. - * This function is a noop and returns 0 in non-windowed environments. - */ -extern DECLSPEC int SDL_WM_IconifyWindow(void); - -/* - * Toggle fullscreen mode without changing the contents of the screen. - * If the display surface does not require locking before accessing - * the pixel information, then the memory pointers will not change. - * - * If this function was able to toggle fullscreen mode (change from - * running in a window to fullscreen, or vice-versa), it will return 1. - * If it is not implemented, or fails, it returns 0. - * - * The next call to SDL_SetVideoMode() will set the mode fullscreen - * attribute based on the flags parameter - if SDL_FULLSCREEN is not - * set, then the display will be windowed by default where supported. - * - * This is currently only implemented in the X11 video driver. - */ -extern DECLSPEC int SDL_WM_ToggleFullScreen(SDL_Surface *surface); - -/* - * This function allows you to set and query the input grab state of - * the application. It returns the new input grab state. - */ -typedef enum { - SDL_GRAB_QUERY = -1, - SDL_GRAB_OFF = 0, - SDL_GRAB_ON = 1, - SDL_GRAB_FULLSCREEN /* Used internally */ -} SDL_GrabMode; -/* - * Grabbing means that the mouse is confined to the application window, - * and nearly all keyboard input is passed directly to the application, - * and not interpreted by a window manager, if any. - */ -extern DECLSPEC SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode); - -/* Not in public API at the moment - do not use! */ -extern DECLSPEC int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -#endif /* _SDL_video_h */ diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/begin_code.h ./win32/SDL-1.2.2/include/begin_code.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/begin_code.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/begin_code.h 1970-01-01 09:00:00 +0900 @@ -1,91 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -/* This file sets things up for C dynamic library function definitions, - static inlined functions, and structures aligned at 4-byte alignment. - If you don't like ugly C preprocessor code, don't look at this file. :) -*/ - -/* This shouldn't be nested -- included it around code only. */ -#ifdef _begin_code_h -#error Nested inclusion of begin_code.h -#endif -#define _begin_code_h - -/* Some compilers use a special export keyword */ -#ifndef DECLSPEC -# ifdef __BEOS__ -# if defined(__GNUC__) -# define DECLSPEC __declspec(dllexport) -# else -# define DECLSPEC __declspec(export) -# endif -# else -# ifdef WIN32 -# define DECLSPEC __declspec(dllexport) -# else -# define DECLSPEC -# endif -# endif -#endif - -/* Force structure packing at 4 byte alignment. - This is necessary if the header is included in code which has structure - packing set to an alternate value, say for loading structures from disk. - The packing is reset to the previous value in close_code.h - */ -#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__BORLANDC__) -#ifdef _MSC_VER -#pragma warning(disable: 4103) -#endif -#ifdef __BORLANDC__ -#pragma nopackwarning -#endif -#pragma pack(push,4) -#endif /* Compiler needs structure packing set */ - -/* Set up compiler-specific options for inlining functions */ -#ifndef SDL_INLINE_OKAY -#ifdef __GNUC__ -#define SDL_INLINE_OKAY -#else -/* Add any special compiler-specific cases here */ -#if defined(_MSC_VER) -#define __inline__ __inline -#define SDL_INLINE_OKAY -#else -#if !defined(__MRC__) && !defined(_SGI_SOURCE) -#define __inline__ inline -#define SDL_INLINE_OKAY -#endif /* Not a funky compiler */ -#endif /* Visual C++ */ -#endif /* GNU C */ -#endif /* SDL_INLINE_OKAY */ - -/* If inlining isn't supported, remove "__inline__", turning static - inlined functions into static functions (resulting in code bloat - in all files which include the offending header files) -*/ -#ifndef SDL_INLINE_OKAY -#define __inline__ -#endif - diff -urN ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/close_code.h ./win32/SDL-1.2.2/include/close_code.h --- ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/include/close_code.h 2002-10-20 22:03:12 +0900 +++ ./win32/SDL-1.2.2/include/close_code.h 1970-01-01 09:00:00 +0900 @@ -1,36 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -/* This file reverses the effects of begin_code.h and should be included - after you finish any function and structure declarations in your headers -*/ - -#undef _begin_code_h - -/* Reset structure packing at previous byte alignment */ -#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__BORLANDC__) -#ifdef __BORLANDC__ -#pragma nopackwarning -#endif -#pragma pack(pop) -#endif /* Compiler needs structure packing set */ - Binary files ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/lib/SDL.dll and ./win32/SDL-1.2.2/lib/SDL.dll differ Binary files ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/lib/SDL.lib and ./win32/SDL-1.2.2/lib/SDL.lib differ Binary files ../VisualBoyAdvance-1.7.2/win32/SDL-1.2.2/lib/SDLmain.lib and ./win32/SDL-1.2.2/lib/SDLmain.lib differ diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/cximage.vcproj ./win32/dependencies/cximage/cximage.vcproj --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/cximage.vcproj 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/cximage.vcproj 2006-08-24 07:16:02 +0900 @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/license.txt ./win32/dependencies/cximage/license.txt --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/license.txt 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/license.txt 2006-08-24 07:16:02 +0900 @@ -0,0 +1,48 @@ +This copy of the CxImage notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file ximage.h that is +included in the CxImage distribution, the latter shall prevail. + +If you modify CxImage you may insert additional notices immediately following +this sentence. + +-------------------------------------------------------------------------------- + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +CxImage version 5.99c 17/Oct/2004 + +CxImage : Copyright (C) 2001 - 2004, Davide Pizzolato + +Original CImage and CImageIterator implementation are: +Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx) + +Covered code is provided under this license on an "as is" basis, without warranty +of any kind, either expressed or implied, including, without limitation, warranties +that the covered code is free of defects, merchantable, fit for a particular purpose +or non-infringing. The entire risk as to the quality and performance of the covered +code is with you. Should any covered code prove defective in any respect, you (not +the initial developer or any other contributor) assume the cost of any necessary +servicing, repair or correction. This disclaimer of warranty constitutes an essential +part of this license. No use of any covered code is authorized hereunder except under +this disclaimer. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, including commercial applications, +freely and without fee, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. + +-------------------------------------------------------------------------------- + +Other information: about CxImage, and the latest version, can be found at the +CxImage home page: http://www.xdp.it + +-------------------------------------------------------------------------------- diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/tif_xfile.cpp ./win32/dependencies/cximage/tif_xfile.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/tif_xfile.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/tif_xfile.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,208 @@ +/* + * TIFF file IO, using CxFile. + */ + +#ifdef WIN32 + #include +#endif +#include + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_TIF + +#include "../tiff/tiffiop.h" + +#include "xfile.h" + +static tsize_t +_tiffReadProcEx(thandle_t fd, tdata_t buf, tsize_t size) +{ + return ((CxFile*)fd)->Read(buf, 1, size); +} + +static tsize_t +_tiffWriteProcEx(thandle_t fd, tdata_t buf, tsize_t size) +{ + return ((CxFile*)fd)->Write(buf, 1, size); +} + +static toff_t +_tiffSeekProcEx(thandle_t fd, toff_t off, int whence) +{ + if ( off == 0xFFFFFFFF ) + return 0xFFFFFFFF; + if (!((CxFile*)fd)->Seek(off, whence)) + return 0xFFFFFFFF; + if (whence == SEEK_SET) + return off; + + return (toff_t)((CxFile*)fd)->Tell(); +} + +// Return nonzero if error +static int +_tiffCloseProcEx(thandle_t fd) +{ +// return !((CxFile*)fd)->Close(); // "//" needed for memory files + return 0; +} + +#include + +static toff_t +_tiffSizeProcEx(thandle_t fd) +{ + return ((CxFile*)fd)->Size(); +} + +static int +_tiffMapProcEx(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void +_tiffUnmapProcEx(thandle_t fd, tdata_t base, toff_t size) +{ +} + +// Open a TIFF file descriptor for read/writing. +/* +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + FILE* stream = fopen(name, mode); + if (stream == NULL) + { + TIFFError(module, "%s: Cannot open", name); + return NULL; + } + return (TIFFFdOpen((int)stream, name, mode)); +} +*/ + +TIFF* +_TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (thandle_t) fd, + _tiffReadProcEx, _tiffWriteProcEx, _tiffSeekProcEx, _tiffCloseProcEx, + _tiffSizeProcEx, _tiffMapProcEx, _tiffUnmapProcEx); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode) +{ + return (_TIFFFdOpen((int)stream, "TIFF IMAGE", mode)); +} + +#ifdef __GNUC__ +extern char* malloc(); +extern char* realloc(); +#else +#include +#endif + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return (malloc((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + free(p); +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (realloc(p, (size_t) s)); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +static void +Win32WarningHandler(const char* module, const char* fmt, va_list ap) +{ +#ifdef _DEBUG +#if (!defined(_CONSOLE) && defined(WIN32)) + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Warning"; + LPCTSTR szDefaultModule = "TIFFLIB"; + szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) + + lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL) + return; + wsprintf(szTitle, szTitleText, szTmp); + szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR); + wvsprintf(szTmp, fmt, ap); + MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); + LocalFree(szTitle); + return; +#else + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif +#endif +} +TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler; + +static void +Win32ErrorHandler(const char* module, const char* fmt, va_list ap) +{ +#ifdef _DEBUG +#if (!defined(_CONSOLE) && defined(WIN32)) + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Error"; + LPCTSTR szDefaultModule = "TIFFLIB"; + szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) + + lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL) + return; + wsprintf(szTitle, szTitleText, szTmp); + szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR); + wvsprintf(szTmp, fmt, ap); + MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); + LocalFree(szTitle); + return; +#else + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif +#endif +} +TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler; + +#endif + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/xfile.h ./win32/dependencies/cximage/xfile.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/xfile.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/xfile.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,76 @@ +/* + * File: xfile.h + * Purpose: General Purpose File Class + */ +/* + -------------------------------------------------------------------------------- + + COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + + CxFile (c) 11/May/2002 Davide Pizzolato - www.xdp.it + CxFile version 2.00 23/Aug/2002 + + Special thanks to Chris Shearer Cooper for new features, enhancements and bugfixes + + Covered code is provided under this license on an "as is" basis, without warranty + of any kind, either expressed or implied, including, without limitation, warranties + that the covered code is free of defects, merchantable, fit for a particular purpose + or non-infringing. The entire risk as to the quality and performance of the covered + code is with you. Should any covered code prove defective in any respect, you (not + the initial developer or any other contributor) assume the cost of any necessary + servicing, repair or correction. This disclaimer of warranty constitutes an essential + part of this license. No use of any covered code is authorized hereunder except under + this disclaimer. + + Permission is hereby granted to use, copy, modify, and distribute this + source code, or portions hereof, for any purpose, including commercial applications, + freely and without fee, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + -------------------------------------------------------------------------------- + */ +#if !defined(__xfile_h) +#define __xfile_h + +#ifdef WIN32 + #include +#endif + +#include +#include + +#include "ximadef.h" + +class DLL_EXP CxFile +{ +public: + CxFile(void) { }; + virtual ~CxFile() { }; + + virtual bool Close() = 0; + virtual size_t Read(void *buffer, size_t size, size_t count) = 0; + virtual size_t Write(const void *buffer, size_t size, size_t count) = 0; + virtual bool Seek(long offset, int origin) = 0; + virtual long Tell() = 0; + virtual long Size() = 0; + virtual bool Flush() = 0; + virtual bool Eof() = 0; + virtual long Error() = 0; + virtual bool PutC(unsigned char c) + { + // Default implementation + size_t nWrote = Write(&c, 1, 1); + return (bool)(nWrote == 1); + } + virtual long GetC() = 0; +}; + +#endif //__xfile_h diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximabmp.cpp ./win32/dependencies/cximage/ximabmp.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximabmp.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximabmp.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,361 @@ +/* + * File: ximabmp.cpp + * Purpose: Platform Independent BMP Image Class Loader and Writer + * 07/Aug/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximabmp.h" + +#if CXIMAGE_SUPPORT_BMP + +#include "ximaiter.h" + +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageBMP::Encode(CxFile * hFile) +{ + + if (EncodeSafeCheck(hFile)) return false; + + BITMAPFILEHEADER hdr; + + hdr.bfType = 0x4d42; // 'BM' WINDOWS_BITMAP_SIGNATURE + hdr.bfSize = GetSize() + 14 /*sizeof(BITMAPFILEHEADER)*/; + hdr.bfReserved1 = hdr.bfReserved2 = 0; + hdr.bfOffBits = 14 /*sizeof(BITMAPFILEHEADER)*/ + head.biSize + GetPaletteSize(); + + //copy attributes + memcpy(pDib,&head,sizeof(BITMAPINFOHEADER)); + // Write the file header + hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1); + // Write the DIB header and the pixels + hFile->Write(pDib,GetSize(),1); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_DECODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageBMP::Decode(CxFile * hFile) +{ + if (hFile == NULL) return false; + + BITMAPFILEHEADER bf; + DWORD off = hFile->Tell(); // + try { + if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) throw "Not a BMP"; + if (bf.bfType != BFT_BITMAP) { //do we have a RC HEADER? + bf.bfOffBits = 0L; + hFile->Seek(off,SEEK_SET); + } + + BITMAPINFOHEADER bmpHeader; + if (!DibReadBitmapInfo(hFile,&bmpHeader)) throw "Error reading BMP info"; + DWORD dwCompression=bmpHeader.biCompression; + DWORD dwBitCount=bmpHeader.biBitCount; //preserve for BI_BITFIELDS compression + bool bIsOldBmp = bmpHeader.biSize == sizeof(BITMAPCOREHEADER); + + bool bTopDownDib = bmpHeader.biHeight<0; // check if it's a top-down bitmap + if (bTopDownDib) bmpHeader.biHeight=-bmpHeader.biHeight; + + if (info.nEscape == -1) { + // Return output dimensions only + head.biWidth = bmpHeader.biWidth; + head.biHeight = bmpHeader.biHeight; + throw "output dimensions returned"; + } + + if (!Create(bmpHeader.biWidth,bmpHeader.biHeight,bmpHeader.biBitCount,CXIMAGE_FORMAT_BMP)) + throw "Can't allocate memory"; + + head.biXPelsPerMeter = bmpHeader.biXPelsPerMeter; + head.biYPelsPerMeter = bmpHeader.biYPelsPerMeter; + info.xDPI = (long) floor(bmpHeader.biXPelsPerMeter * 254.0 / 10000.0 + 0.5); + info.yDPI = (long) floor(bmpHeader.biYPelsPerMeter * 254.0 / 10000.0 + 0.5); + + if (info.nEscape) throw "Cancelled"; // - cancel decoding + + RGBQUAD *pRgb = GetPalette(); + if (pRgb){ + if (bIsOldBmp){ + // convert a old color table (3 byte entries) to a new + // color table (4 byte entries) + hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1); + for (int i=DibNumColors(&head)-1; i>=0; i--){ + pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed; + pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue; + pRgb[i].rgbGreen = ((RGBTRIPLE *)pRgb)[i].rgbtGreen; + pRgb[i].rgbReserved = (BYTE)0; + } + } else { + hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1); + //force rgbReserved=0, to avoid problems with some WinXp bitmaps + for (unsigned int i=0; i - cancel decoding + + switch (dwBitCount) { + case 32 : + if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); + if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){ + long imagesize=4*head.biHeight*head.biWidth; + BYTE* buff32=(BYTE*)malloc(imagesize); + if (buff32){ + hFile->Read(buff32, imagesize,1); // read in the pixels + Bitfield2RGB(buff32,0,0,0,32); + free(buff32); + } else throw "can't allocate memory"; + } else throw "unknown compression"; + break; + case 24 : + if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); + if (dwCompression == BI_RGB){ + hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels + } else throw "unknown compression"; + break; + case 16 : + { + DWORD bfmask[3]; + if (dwCompression == BI_BITFIELDS) + { + hFile->Read(bfmask, 12, 1); + } else { + bfmask[0]=0x7C00; bfmask[1]=0x3E0; bfmask[2]=0x1F; //RGB555 + } + // bf.bfOffBits required after the bitfield mask + if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); + // read in the pixels + hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1); + // transform into RGB + Bitfield2RGB(info.pImage,(WORD)bfmask[0],(WORD)bfmask[1],(WORD)bfmask[2],16); + break; + } + case 8 : + case 4 : + case 1 : + if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); + switch (dwCompression) { + case BI_RGB : + hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels + break; + case BI_RLE4 : + { + BYTE status_byte = 0; + BYTE second_byte = 0; + int scanline = 0; + int bits = 0; + BOOL low_nibble = FALSE; + CImageIterator iter(this); + + for (BOOL bContinue = TRUE; bContinue;) { + hFile->Read(&status_byte, sizeof(BYTE), 1); + switch (status_byte) { + case RLE_COMMAND : + hFile->Read(&status_byte, sizeof(BYTE), 1); + switch (status_byte) { + case RLE_ENDOFLINE : + bits = 0; + scanline++; + low_nibble = FALSE; + break; + case RLE_ENDOFBITMAP : + bContinue=FALSE; + break; + case RLE_DELTA : + { + // read the delta values + BYTE delta_x; + BYTE delta_y; + hFile->Read(&delta_x, sizeof(BYTE), 1); + hFile->Read(&delta_y, sizeof(BYTE), 1); + // apply them + bits += delta_x / 2; + scanline += delta_y; + break; + } + default : + hFile->Read(&second_byte, sizeof(BYTE), 1); + BYTE *sline = iter.GetRow(scanline); + for (int i = 0; i < status_byte; i++) { + if (low_nibble) { + if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ + *(sline + bits) |= (second_byte & 0x0F); + } + if (i != status_byte - 1) + hFile->Read(&second_byte, sizeof(BYTE), 1); + bits++; + } else { + if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ + *(sline + bits) = (BYTE)(second_byte & 0xF0); + } + } + low_nibble = !low_nibble; + } + if ((((status_byte+1) >> 1) & 1 )== 1) + hFile->Read(&second_byte, sizeof(BYTE), 1); + break; + }; + break; + default : + { + BYTE *sline = iter.GetRow(scanline); + hFile->Read(&second_byte, sizeof(BYTE), 1); + for (unsigned i = 0; i < status_byte; i++) { + if (low_nibble) { + if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ + *(sline + bits) |= (second_byte & 0x0F); + } + bits++; + } else { + if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ + *(sline + bits) = (BYTE)(second_byte & 0xF0); + } + } + low_nibble = !low_nibble; + } + } + break; + }; + } + break; + } + case BI_RLE8 : + { + BYTE status_byte = 0; + BYTE second_byte = 0; + int scanline = 0; + int bits = 0; + CImageIterator iter(this); + + for (BOOL bContinue = TRUE; bContinue; ) { + hFile->Read(&status_byte, sizeof(BYTE), 1); + switch (status_byte) { + case RLE_COMMAND : + hFile->Read(&status_byte, sizeof(BYTE), 1); + switch (status_byte) { + case RLE_ENDOFLINE : + bits = 0; + scanline++; + break; + case RLE_ENDOFBITMAP : + bContinue=FALSE; + break; + case RLE_DELTA : + { + // read the delta values + BYTE delta_x; + BYTE delta_y; + hFile->Read(&delta_x, sizeof(BYTE), 1); + hFile->Read(&delta_y, sizeof(BYTE), 1); + // apply them + bits += delta_x; + scanline += delta_y; + break; + } + default : + hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(BYTE) * status_byte, 1); + // align run length to even number of bytes + if ((status_byte & 1) == 1) + hFile->Read(&second_byte, sizeof(BYTE), 1); + bits += status_byte; + break; + }; + break; + default : + BYTE *sline = iter.GetRow(scanline); + hFile->Read(&second_byte, sizeof(BYTE), 1); + for (unsigned i = 0; i < status_byte; i++) { + if ((DWORD)bits + + } catch (char *message) { + strncpy(info.szLastError,message,255); + if (info.nEscape==-1) return true; + return false; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/* ReadDibBitmapInfo() + * + * Will read a file in DIB format and return a global HANDLE to its + * BITMAPINFO. This function will work with both "old" and "new" + * bitmap formats, but will always return a "new" BITMAPINFO. + */ +bool CxImageBMP::DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib) +{ + if ((fh==NULL)||(pdib==NULL)) return false; + + if (fh->Read(pdib,sizeof(BITMAPINFOHEADER),1)==0) return false; + + BITMAPCOREHEADER bc; + + switch (pdib->biSize) // what type of bitmap info is this? + { + case sizeof(BITMAPINFOHEADER): + break; + + case 64: //sizeof(OS2_BMP_HEADER): + fh->Seek((long)(64 - sizeof(BITMAPINFOHEADER)),SEEK_CUR); + break; + + case sizeof(BITMAPCOREHEADER): + bc = *(BITMAPCOREHEADER*)pdib; + pdib->biSize = bc.bcSize; + pdib->biWidth = (DWORD)bc.bcWidth; + pdib->biHeight = (DWORD)bc.bcHeight; + pdib->biPlanes = bc.bcPlanes; + pdib->biBitCount = bc.bcBitCount; + pdib->biCompression = BI_RGB; + pdib->biSizeImage = 0; + pdib->biXPelsPerMeter = 0; + pdib->biYPelsPerMeter = 0; + pdib->biClrUsed = 0; + pdib->biClrImportant = 0; + + fh->Seek((long)(sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER)), SEEK_CUR); + + break; + default: + //give a last chance + if (pdib->biSize>(sizeof(BITMAPINFOHEADER))&& + (pdib->biSizeImage==(unsigned long)(pdib->biHeight*((((pdib->biBitCount*pdib->biWidth)+31)/32)*4)))&& + (pdib->biPlanes==1)&&(pdib->biCompression==BI_RGB)&&(pdib->biClrUsed==0)) + { + fh->Seek((long)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR); + break; + } + return false; + } + + FixBitmapInfo(pdib); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_DECODE +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_BMP +//////////////////////////////////////////////////////////////////////////////// diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximabmp.h ./win32/dependencies/cximage/ximabmp.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximabmp.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximabmp.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,79 @@ +/* + * File: ximabmp.h + * Purpose: BMP Image Class Loader and Writer + */ +/* ========================================================== + * CxImageBMP (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes + * + * original CImageBMP and CImageIterator implementation are: + * Copyright: (c) 1995, Alejandro Aguilar Sierra + * + * ========================================================== + */ + +#if !defined(__ximaBMP_h) +#define __ximaBMP_h + +#include "ximage.h" + +const int RLE_COMMAND = 0; +const int RLE_ENDOFLINE = 0; +const int RLE_ENDOFBITMAP = 1; +const int RLE_DELTA = 2; + +#if !defined(BI_RLE8) + #define BI_RLE8 1L +#endif +#if !defined(BI_RLE4) + #define BI_RLE4 2L +#endif + +#if CXIMAGE_SUPPORT_BMP + +class CxImageBMP: public CxImage +{ +public: + CxImageBMP(): CxImage(CXIMAGE_FORMAT_BMP) {}; + + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE + +protected: + bool DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib); +}; + +#define BFT_ICON 0x4349 /* 'IC' */ +#define BFT_BITMAP 0x4d42 /* 'BM' */ +#define BFT_CURSOR 0x5450 /* 'PT' */ + +#ifndef WIDTHBYTES +#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */ +#endif + +#endif + +#define DibWidthBytesN(lpbi, n) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)(n)) +#define DibWidthBytes(lpbi) DibWidthBytesN(lpbi, (lpbi)->biBitCount) + +#define DibSizeImage(lpbi) ((lpbi)->biSizeImage == 0 \ + ? ((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)(lpbi)->biHeight) \ + : (lpbi)->biSizeImage) + +#define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \ + ? (int)(1 << (int)(lpbi)->biBitCount) \ + : (int)(lpbi)->biClrUsed) + +#define FixBitmapInfo(lpbi) if ((lpbi)->biSizeImage == 0) \ + (lpbi)->biSizeImage = DibSizeImage(lpbi); \ + if ((lpbi)->biClrUsed == 0) \ + (lpbi)->biClrUsed = DibNumColors(lpbi); \ + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximacfg.h ./win32/dependencies/cximage/ximacfg.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximacfg.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximacfg.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,52 @@ +#if !defined(__ximaCFG_h) +#define __ximaCFG_h + +///////////////////////////////////////////////////////////////////////////// +// CxImage supported features +#define CXIMAGE_SUPPORT_ALPHA 1 +#define CXIMAGE_SUPPORT_SELECTION 1 +#define CXIMAGE_SUPPORT_TRANSFORMATION 1 +#define CXIMAGE_SUPPORT_DSP 1 +#define CXIMAGE_SUPPORT_LAYERS 1 +#define CXIMAGE_SUPPORT_INTERPOLATION 1 + +#define CXIMAGE_SUPPORT_DECODE 1 +#define CXIMAGE_SUPPORT_ENCODE 1 // +#define CXIMAGE_SUPPORT_WINDOWS 1 +#define CXIMAGE_SUPPORT_WINCE 0 // + +///////////////////////////////////////////////////////////////////////////// +// CxImage supported formats +#define CXIMAGE_SUPPORT_BMP 1 +#define CXIMAGE_SUPPORT_GIF 1 +#define CXIMAGE_SUPPORT_JPG 0 +#define CXIMAGE_SUPPORT_PNG 0 +#define CXIMAGE_SUPPORT_MNG 0 +#define CXIMAGE_SUPPORT_ICO 1 +#define CXIMAGE_SUPPORT_TIF 0 +#define CXIMAGE_SUPPORT_TGA 1 +#define CXIMAGE_SUPPORT_PCX 1 +#define CXIMAGE_SUPPORT_WBMP 1 +#define CXIMAGE_SUPPORT_WMF 1 +#define CXIMAGE_SUPPORT_J2K 0 // Beta, use JP2 +#define CXIMAGE_SUPPORT_JBG 0 // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm + +#define CXIMAGE_SUPPORT_JP2 0 +#define CXIMAGE_SUPPORT_JPC 0 +#define CXIMAGE_SUPPORT_PGX 0 +#define CXIMAGE_SUPPORT_PNM 0 +#define CXIMAGE_SUPPORT_RAS 0 + + +///////////////////////////////////////////////////////////////////////////// +#define CXIMAGE_MAX_MEMORY 256000000 + +#define CXIMAGE_ERR_NOFILE "null file handler" +#define CXIMAGE_ERR_NOIMAGE "null image!!!" + +///////////////////////////////////////////////////////////////////////////// +//color to grey mapping +//#define RGB2GRAY(r,g,b) (((b)*114 + (g)*587 + (r)*299)/1000) +#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10) + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximadef.h ./win32/dependencies/cximage/ximadef.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximadef.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximadef.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,197 @@ +#if !defined(__ximadefs_h) +#define __ximadefs_h + +#include "ximacfg.h" + +#if defined(_AFXDLL)||defined(_USRDLL) + #define DLL_EXP __declspec(dllexport) +#elif defined(_MSC_VER)&&(_MSC_VER<1200) + #define DLL_EXP __declspec(dllimport) +#else + #define DLL_EXP +#endif + +#if CXIMAGE_SUPPORT_JP2 || CXIMAGE_SUPPORT_JPC || CXIMAGE_SUPPORT_PGX || CXIMAGE_SUPPORT_PNM || CXIMAGE_SUPPORT_RAS + #define CXIMAGE_SUPPORT_JASPER 1 +#else + #define CXIMAGE_SUPPORT_JASPER 0 +#endif + +#if CXIMAGE_SUPPORT_DSP +#undef CXIMAGE_SUPPORT_TRANSFORMATION + #define CXIMAGE_SUPPORT_TRANSFORMATION 1 +#endif + +#if CXIMAGE_SUPPORT_TRANSFORMATION || CXIMAGE_SUPPORT_TIF || CXIMAGE_SUPPORT_TGA || CXIMAGE_SUPPORT_BMP || CXIMAGE_SUPPORT_WINDOWS + #define CXIMAGE_SUPPORT_BASICTRANSFORMATIONS 1 +#endif + +#if CXIMAGE_SUPPORT_DSP || CXIMAGE_SUPPORT_TRANSFORMATION +#undef CXIMAGE_SUPPORT_INTERPOLATION + #define CXIMAGE_SUPPORT_INTERPOLATION 1 +#endif + +#if CXIMAGE_SUPPORT_WINCE + #undef CXIMAGE_SUPPORT_WMF + #define CXIMAGE_SUPPORT_WMF 0 + #undef CXIMAGE_SUPPORT_WINDOWS + #define CXIMAGE_SUPPORT_WINDOWS 0 +#endif + +#ifndef WIN32 + #undef CXIMAGE_SUPPORT_WINDOWS + #define CXIMAGE_SUPPORT_WINDOWS 0 +#endif + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +#ifndef PI + #define PI 3.141592653589793f +#endif + + +#ifdef WIN32 +#include +#include +#endif + +#include +#include + + +#ifdef __BORLANDC__ + +#ifndef _COMPLEX_DEFINED + +typedef struct tagcomplex { + double x,y; +} _complex; + +#endif + +#define _cabs(c) sqrt(c.x*c.x+c.y*c.y) + +#endif + + +#ifndef WIN32 + +#include +#include +#include + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef unsigned int UINT; + +typedef DWORD COLORREF; +typedef unsigned int HANDLE; +typedef void* HRGN; + +#ifndef BOOL +#define BOOL bool +#endif + +#ifndef TRUE +#define TRUE true +#endif + +#ifndef FALSE +#define FALSE false +#endif + +#ifndef TCHAR +#define TCHAR char +#define _T +#endif + +typedef struct tagRECT +{ + long left; + long top; + long right; + long bottom; +} RECT; + +typedef struct tagPOINT +{ + long x; + long y; +} POINT; + +typedef struct tagRGBQUAD { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD; + +#pragma pack(1) + +typedef struct tagBITMAPINFOHEADER{ + DWORD biSize; + long biWidth; + long biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER; + +typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; +} BITMAPFILEHEADER; + +typedef struct tagBITMAPCOREHEADER { + DWORD bcSize; + WORD bcWidth; + WORD bcHeight; + WORD bcPlanes; + WORD bcBitCount; +} BITMAPCOREHEADER; + +typedef struct tagRGBTRIPLE { + BYTE rgbtBlue; + BYTE rgbtGreen; + BYTE rgbtRed; +} RGBTRIPLE; + +#pragma pack() + +#define BI_RGB 0L +#define BI_RLE8 1L +#define BI_RLE4 2L +#define BI_BITFIELDS 3L + +#define GetRValue(rgb) ((BYTE)(rgb)) +#define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8)) +#define GetBValue(rgb) ((BYTE)((rgb)>>16)) +#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + +#ifndef _COMPLEX_DEFINED + +typedef struct tagcomplex { + double x,y; +} _complex; + +#endif + +#define _cabs(c) sqrt(c.x*c.x+c.y*c.y) + +#endif + +#endif //__ximadefs diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximadsp.cpp ./win32/dependencies/cximage/ximadsp.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximadsp.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximadsp.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,2370 @@ +// xImaDsp.cpp : DSP functions +/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +#include "ximaiter.h" + +#if CXIMAGE_SUPPORT_DSP + +//////////////////////////////////////////////////////////////////////////////// +/** + * Converts the image to B&W. + * The Mean() function can be used for calculating the optimal threshold. + * \param level: the lightness threshold. + * \return true if everything is ok + */ +bool CxImage::Threshold(BYTE level) +{ + if (!pDib) return false; + if (head.biBitCount == 1) return true; + + GrayScale(); + + CxImage tmp(head.biWidth,head.biHeight,1); + if (!tmp.IsValid()) return false; + + for (long y=0;ylevel) + tmp.SetPixelIndex(x,y,1); + else + tmp.SetPixelIndex(x,y,0); + } + } + tmp.SetPaletteColor(0,0,0,0); + tmp.SetPaletteColor(1,255,255,255); + Transfer(tmp); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Extract RGB channels from the image. Each channel is an 8 bit grayscale image. + * \param r,g,b: pointers to CxImage objects, to store the splited channels + * \return true if everything is ok + */ +bool CxImage::SplitRGB(CxImage* r,CxImage* g,CxImage* b) +{ + if (!pDib) return false; + if (r==NULL && g==NULL && b==NULL) return false; + + CxImage tmpr(head.biWidth,head.biHeight,8); + CxImage tmpg(head.biWidth,head.biHeight,8); + CxImage tmpb(head.biWidth,head.biHeight,8); + + RGBQUAD color; + for(long y=0; yTransfer(tmpr); + if (g) g->Transfer(tmpg); + if (b) b->Transfer(tmpb); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Extract CMYK channels from the image. Each channel is an 8 bit grayscale image. + * \param c,m,y,k: pointers to CxImage objects, to store the splited channels + * \return true if everything is ok + */ +bool CxImage::SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k) +{ + if (!pDib) return false; + if (c==NULL && m==NULL && y==NULL && k==NULL) return false; + + CxImage tmpc(head.biWidth,head.biHeight,8); + CxImage tmpm(head.biWidth,head.biHeight,8); + CxImage tmpy(head.biWidth,head.biHeight,8); + CxImage tmpk(head.biWidth,head.biHeight,8); + + RGBQUAD color; + for(long yy=0; yyTransfer(tmpc); + if (m) m->Transfer(tmpm); + if (y) y->Transfer(tmpy); + if (k) k->Transfer(tmpk); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Extract YUV channels from the image. Each channel is an 8 bit grayscale image. + * \param y,u,v: pointers to CxImage objects, to store the splited channels + * \return true if everything is ok + */ +bool CxImage::SplitYUV(CxImage* y,CxImage* u,CxImage* v) +{ + if (!pDib) return false; + if (y==NULL && u==NULL && v==NULL) return false; + + CxImage tmpy(head.biWidth,head.biHeight,8); + CxImage tmpu(head.biWidth,head.biHeight,8); + CxImage tmpv(head.biWidth,head.biHeight,8); + + RGBQUAD color; + for(long yy=0; yyTransfer(tmpy); + if (u) u->Transfer(tmpu); + if (v) v->Transfer(tmpv); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Extract YIQ channels from the image. Each channel is an 8 bit grayscale image. + * \param y,i,q: pointers to CxImage objects, to store the splited channels + * \return true if everything is ok + */ +bool CxImage::SplitYIQ(CxImage* y,CxImage* i,CxImage* q) +{ + if (!pDib) return false; + if (y==NULL && i==NULL && q==NULL) return false; + + CxImage tmpy(head.biWidth,head.biHeight,8); + CxImage tmpi(head.biWidth,head.biHeight,8); + CxImage tmpq(head.biWidth,head.biHeight,8); + + RGBQUAD color; + for(long yy=0; yyTransfer(tmpy); + if (i) i->Transfer(tmpi); + if (q) q->Transfer(tmpq); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Extract XYZ channels from the image. Each channel is an 8 bit grayscale image. + * \param x,y,z: pointers to CxImage objects, to store the splited channels + * \return true if everything is ok + */ +bool CxImage::SplitXYZ(CxImage* x,CxImage* y,CxImage* z) +{ + if (!pDib) return false; + if (x==NULL && y==NULL && z==NULL) return false; + + CxImage tmpx(head.biWidth,head.biHeight,8); + CxImage tmpy(head.biWidth,head.biHeight,8); + CxImage tmpz(head.biWidth,head.biHeight,8); + + RGBQUAD color; + for(long yy=0; yyTransfer(tmpx); + if (y) y->Transfer(tmpy); + if (z) z->Transfer(tmpz); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Extract HSL channels from the image. Each channel is an 8 bit grayscale image. + * \param h,s,l: pointers to CxImage objects, to store the splited channels + * \return true if everything is ok + */ +bool CxImage::SplitHSL(CxImage* h,CxImage* s,CxImage* l) +{ + if (!pDib) return false; + if (h==NULL && s==NULL && l==NULL) return false; + + CxImage tmph(head.biWidth,head.biHeight,8); + CxImage tmps(head.biWidth,head.biHeight,8); + CxImage tmpl(head.biWidth,head.biHeight,8); + + RGBQUAD color; + for(long y=0; yTransfer(tmph); + if (s) s->Transfer(tmps); + if (l) l->Transfer(tmpl); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#define HSLMAX 255 /* H,L, and S vary over 0-HSLMAX */ +#define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */ + /* HSLMAX BEST IF DIVISIBLE BY 6 */ + /* RGBMAX, HSLMAX must each fit in a BYTE. */ +/* Hue is undefined if Saturation is 0 (grey-scale) */ +/* This value determines where the Hue scrollbar is */ +/* initially set for achromatic colors */ +#define HSLUNDEFINED (HSLMAX*2/3) +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::RGBtoHSL(RGBQUAD lRGBColor) +{ + BYTE R,G,B; /* input RGB values */ + BYTE H,L,S; /* output HSL values */ + BYTE cMax,cMin; /* max and min RGB values */ + WORD Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max*/ + + R = lRGBColor.rgbRed; /* get R, G, and B out of DWORD */ + G = lRGBColor.rgbGreen; + B = lRGBColor.rgbBlue; + + cMax = max( max(R,G), B); /* calculate lightness */ + cMin = min( min(R,G), B); + L = (BYTE)((((cMax+cMin)*HSLMAX)+RGBMAX)/(2*RGBMAX)); + + if (cMax==cMin){ /* r=g=b --> achromatic case */ + S = 0; /* saturation */ + H = HSLUNDEFINED; /* hue */ + } else { /* chromatic case */ + if (L <= (HSLMAX/2)) /* saturation */ + S = (BYTE)((((cMax-cMin)*HSLMAX)+((cMax+cMin)/2))/(cMax+cMin)); + else + S = (BYTE)((((cMax-cMin)*HSLMAX)+((2*RGBMAX-cMax-cMin)/2))/(2*RGBMAX-cMax-cMin)); + /* hue */ + Rdelta = (WORD)((((cMax-R)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin)); + Gdelta = (WORD)((((cMax-G)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin)); + Bdelta = (WORD)((((cMax-B)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin)); + + if (R == cMax) + H = (BYTE)(Bdelta - Gdelta); + else if (G == cMax) + H = (BYTE)((HSLMAX/3) + Rdelta - Bdelta); + else /* B == cMax */ + H = (BYTE)(((2*HSLMAX)/3) + Gdelta - Rdelta); + +// if (H < 0) H += HSLMAX; //always false + if (H > HSLMAX) H -= HSLMAX; + } + RGBQUAD hsl={L,S,H,0}; + return hsl; +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::HueToRGB(float n1,float n2, float hue) +{ + // fixed implementation for HSL2RGB routine + float rValue; + + if (hue > 360) + hue = hue - 360; + else if (hue < 0) + hue = hue + 360; + + if (hue < 60) + rValue = n1 + (n2-n1)*hue/60.0f; + else if (hue < 180) + rValue = n2; + else if (hue < 240) + rValue = n1+(n2-n1)*(240-hue)/60; + else + rValue = n1; + + return rValue; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::HSLtoRGB(COLORREF cHSLColor) +{ + return HSLtoRGB(RGBtoRGBQUAD(cHSLColor)); +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::HSLtoRGB(RGBQUAD lHSLColor) +{ + // fixed implementation for HSL2RGB routine + float h,s,l; + float m1,m2; + BYTE r,g,b; + + h = (float)lHSLColor.rgbRed * 360.0f/255.0f; + s = (float)lHSLColor.rgbGreen/255.0f; + l = (float)lHSLColor.rgbBlue/255.0f; + + if (l <= 0.5) m2 = l * (1+s); + else m2 = l + s - l*s; + + m1 = 2 * l - m2; + + if (s == 0) { + r=g=b=(BYTE)(l*255.0f); + } else { + r = (BYTE)(HueToRGB(m1,m2,h+120) * 255.0f); + g = (BYTE)(HueToRGB(m1,m2,h) * 255.0f); + b = (BYTE)(HueToRGB(m1,m2,h-120) * 255.0f); + } + + RGBQUAD rgb = {b,g,r,0}; + return rgb; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::YUVtoRGB(RGBQUAD lYUVColor) +{ + int U,V,R,G,B; + float Y = lYUVColor.rgbRed; + U = lYUVColor.rgbGreen - 128; + V = lYUVColor.rgbBlue - 128; + +// R = (int)(1.164 * Y + 2.018 * U); +// G = (int)(1.164 * Y - 0.813 * V - 0.391 * U); +// B = (int)(1.164 * Y + 1.596 * V); + R = (int)( Y + 1.403f * V); + G = (int)( Y - 0.344f * U - 0.714f * V); + B = (int)( Y + 1.770f * U); + + R= min(255,max(0,R)); + G= min(255,max(0,G)); + B= min(255,max(0,B)); + RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0}; + return rgb; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::RGBtoYUV(RGBQUAD lRGBColor) +{ + int Y,U,V,R,G,B; + R = lRGBColor.rgbRed; + G = lRGBColor.rgbGreen; + B = lRGBColor.rgbBlue; + +// Y = (int)( 0.257 * R + 0.504 * G + 0.098 * B); +// U = (int)( 0.439 * R - 0.368 * G - 0.071 * B + 128); +// V = (int)(-0.148 * R - 0.291 * G + 0.439 * B + 128); + Y = (int)(0.299f * R + 0.587f * G + 0.114f * B); + U = (int)((B-Y) * 0.565f + 128); + V = (int)((R-Y) * 0.713f + 128); + + Y= min(255,max(0,Y)); + U= min(255,max(0,U)); + V= min(255,max(0,V)); + RGBQUAD yuv={(BYTE)V,(BYTE)U,(BYTE)Y,0}; + return yuv; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::YIQtoRGB(RGBQUAD lYIQColor) +{ + int I,Q,R,G,B; + float Y = lYIQColor.rgbRed; + I = lYIQColor.rgbGreen - 128; + Q = lYIQColor.rgbBlue - 128; + + R = (int)( Y + 0.956f * I + 0.621f * Q); + G = (int)( Y - 0.273f * I - 0.647f * Q); + B = (int)( Y - 1.104f * I + 1.701f * Q); + + R= min(255,max(0,R)); + G= min(255,max(0,G)); + B= min(255,max(0,B)); + RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0}; + return rgb; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::RGBtoYIQ(RGBQUAD lRGBColor) +{ + int Y,I,Q,R,G,B; + R = lRGBColor.rgbRed; + G = lRGBColor.rgbGreen; + B = lRGBColor.rgbBlue; + + Y = (int)( 0.2992f * R + 0.5868f * G + 0.1140f * B); + I = (int)( 0.5960f * R - 0.2742f * G - 0.3219f * B + 128); + Q = (int)( 0.2109f * R - 0.5229f * G + 0.3120f * B + 128); + + Y= min(255,max(0,Y)); + I= min(255,max(0,I)); + Q= min(255,max(0,Q)); + RGBQUAD yiq={(BYTE)Q,(BYTE)I,(BYTE)Y,0}; + return yiq; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::XYZtoRGB(RGBQUAD lXYZColor) +{ + int X,Y,Z,R,G,B; + X = lXYZColor.rgbRed; + Y = lXYZColor.rgbGreen; + Z = lXYZColor.rgbBlue; + double k=1.088751; + + R = (int)( 3.240479f * X - 1.537150f * Y - 0.498535f * Z * k); + G = (int)( -0.969256f * X + 1.875992f * Y + 0.041556f * Z * k); + B = (int)( 0.055648f * X - 0.204043f * Y + 1.057311f * Z * k); + + R= min(255,max(0,R)); + G= min(255,max(0,G)); + B= min(255,max(0,B)); + RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0}; + return rgb; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::RGBtoXYZ(RGBQUAD lRGBColor) +{ + int X,Y,Z,R,G,B; + R = lRGBColor.rgbRed; + G = lRGBColor.rgbGreen; + B = lRGBColor.rgbBlue; + + X = (int)( 0.412453f * R + 0.357580f * G + 0.180423f * B); + Y = (int)( 0.212671f * R + 0.715160f * G + 0.072169f * B); + Z = (int)((0.019334f * R + 0.119193f * G + 0.950227f * B)*0.918483657f); + + //X= min(255,max(0,X)); + //Y= min(255,max(0,Y)); + //Z= min(255,max(0,Z)); + RGBQUAD xyz={(BYTE)Z,(BYTE)Y,(BYTE)X,0}; + return xyz; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Generates a "rainbow" palette with saturated colors + * \param correction: 1 generates a single hue spectrum. 0.75 is nice for scientific applications. + */ +void CxImage::HuePalette(float correction) +{ + if (head.biClrUsed==0) return; + + for(DWORD j=0; j 1.0f) blend = 1.0f; + int a0 = (int)(256*blend); + int a1 = 256 - a0; + + bool bFullBlend = false; + if (blend > 0.999f) bFullBlend = true; + + RGBQUAD color,hsl; + if (head.biClrUsed==0){ + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; y>8); + color.rgbBlue = (BYTE)((hsl.rgbBlue * a0 + color.rgbBlue * a1)>>8); + color.rgbGreen = (BYTE)((hsl.rgbGreen * a0 + color.rgbGreen * a1)>>8); + SetPixelColor(x,y,color); + } + } + } + } + } else { + for(DWORD j=0; j + for (int i=0;i<256;i++) { + cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*c + brightness))); + } + + return Lut(cTable); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \return mean lightness of the image. Useful with Threshold() and Light() + */ +float CxImage::Mean() +{ + if (!pDib) return 0; + + CxImage tmp(*this,true); + if (!tmp.IsValid()) return false; + + tmp.GrayScale(); + float sum=0; + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + if (xmin==xmax || ymin==ymax) return (float)0.0; + + BYTE *iSrc=tmp.info.pImage; + iSrc += tmp.info.dwEffWidth*ymin; // necessary for selections + + for(long y=ymin; y + for(long x=xmin; x 0 && (y+kmax-1) < head.biHeight && x-k2 > 0 && (x+kmax-1) < head.biWidth) + { + b=0; + iCount = 0; + iY2 = ((y-k2)*info.dwEffWidth); + for(long j=-k2;j r) r=c.rgbRed; + if (c.rgbGreen > g) g=c.rgbGreen; + if (c.rgbBlue > b) b=c.rgbBlue; + } + } + c.rgbRed = r; + c.rgbGreen = g; + c.rgbBlue = b; + tmp.SetPixelColor(x,y,c); + } + } + } + Transfer(tmp); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Enhance the variations between adjacent pixels. + * Similar results can be achieved using Filter(), + * but the algorithms are different both in Edge() and in Contour(). + * \param Ksize: size of the kernel. + * \return true if everything is ok + */ +bool CxImage::Edge(long Ksize) +{ + if (!pDib) return false; + + long k2 = Ksize/2; + long kmax= Ksize-k2; + BYTE r,g,b,rr,gg,bb; + RGBQUAD c; + + CxImage tmp(*this,pSelection!=0,true,true); + if (!tmp.IsValid()) return false; + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; y r) r=c.rgbRed; + if (c.rgbGreen > g) g=c.rgbGreen; + if (c.rgbBlue > b) b=c.rgbBlue; + + if (c.rgbRed < rr) rr=c.rgbRed; + if (c.rgbGreen < gg) gg=c.rgbGreen; + if (c.rgbBlue < bb) bb=c.rgbBlue; + } + } + c.rgbRed = 255-abs(r-rr); + c.rgbGreen = 255-abs(g-gg); + c.rgbBlue = 255-abs(b-bb); + tmp.SetPixelColor(x,y,c); + } + } + } + Transfer(tmp); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Blends two images + * \param imgsrc2: image to be mixed with this + * \param op: blending method; see ImageOpType + * \param lXOffset, lYOffset: image displacement + * \param bMixAlpha: if true and imgsrc2 has a valid alpha layer, it will be mixed in the destination image. + * \return true if everything is ok + * + * thanks to Mwolski + */ +// +void CxImage::Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset, long lYOffset, bool bMixAlpha) +{ + long lWide = min(GetWidth(),imgsrc2.GetWidth()-lXOffset); + long lHeight = min(GetHeight(),imgsrc2.GetHeight()-lYOffset); + + bool bEditAlpha = imgsrc2.AlphaIsValid() & bMixAlpha; + + if (bEditAlpha && AlphaIsValid()==false){ + AlphaCreate(); + } + + RGBQUAD rgbBackgrnd = GetTransColor(); + RGBQUAD rgb1, rgb2, rgbDest; + + for(long lY=0;lY>8); + } else { + a=255; + } + + if (a==0){ //transparent + rgbDest = rgb1; + } else if (a==255){ //opaque + rgbDest = rgb2; + } else { //blend + a1 = (BYTE)~a; + rgbDest.rgbBlue = (BYTE)((rgb1.rgbBlue*a1+rgb2.rgbBlue*a)>>8); + rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)>>8); + rgbDest.rgbRed = (BYTE)((rgb1.rgbRed*a1+rgb2.rgbRed*a)>>8); + } + + if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(((1+rgb1.rgbReserved)*a)>>8); + } + break; + case OpSrcBlend: + if(memcmp(&rgb1,&rgbBackgrnd,sizeof(RGBQUAD))==0) + rgbDest = rgb2; + else + { + long lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd.rgbBlue); + long lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd.rgbGreen); + long lRDiff = abs(rgb1.rgbRed - rgbBackgrnd.rgbRed); + + double lAverage = (lBDiff+lGDiff+lRDiff)/3; + double lThresh = 16; + double dLarge = lAverage/lThresh; + double dSmall = (lThresh-lAverage)/lThresh; + double dSmallAmt = dSmall*((double)rgb2.rgbBlue); + + if( lAverage < lThresh+1){ + rgbDest.rgbBlue = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbBlue) + + dSmallAmt))); + rgbDest.rgbGreen = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbGreen) + + dSmallAmt))); + rgbDest.rgbRed = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbRed) + + dSmallAmt))); + } + else + rgbDest = rgb1; + } + break; + default: + return; + } + SetPixelColor(lX,lY,rgbDest,bEditAlpha); + } + } + } +} +//////////////////////////////////////////////////////////////////////////////// +// thanks to Kenneth Ballard +void CxImage::MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset) +{ + RGBQUAD rgbBackgrnd = imagesrc2.GetTransColor(); + RGBQUAD rgb1; + + long width = imagesrc2.GetWidth(); + long height = imagesrc2.GetHeight(); + + int x, y; + + for(x = 0; x < width; x++) + { + for(y = 0; y < height; y++) + { + rgb1 = imagesrc2.GetPixelColor(x, y); + if(memcmp(&rgb1, &rgbBackgrnd, sizeof(RGBQUAD)) != 0) + SetPixelColor(x + lXOffset, y + lYOffset, rgb1); + } + } +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Adjusts separately the red, green, and blue values in the image. + * \param r, g, b: can be from -255 to +255. + * \return true if everything is ok + */ +bool CxImage::ShiftRGB(long r, long g, long b) +{ + if (!pDib) return false; + RGBQUAD color; + if (head.biClrUsed==0){ + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; y + for (int i=0;i<256;i++) { + cTable[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax))); + } + + return Lut(cTable); +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_WINCE == 0 +/** + * Adjusts the intensity of each pixel to the median intensity of its surrounding pixels. + * \param Ksize: size of the kernel. + * \return true if everything is ok + */ +bool CxImage::Median(long Ksize) +{ + if (!pDib) return false; + + long k2 = Ksize/2; + long kmax= Ksize-k2; + long i,j,k; + + RGBQUAD* kernel = (RGBQUAD*)malloc(Ksize*Ksize*sizeof(RGBQUAD)); + + CxImage tmp(*this,pSelection!=0,true,true); + if (!tmp.IsValid()) return false; + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; y + for(long x=xmin; xGetWidth(); + h=srcReal->GetHeight(); + } else { + w=srcImag->GetWidth(); + h=srcImag->GetHeight(); + } + + bool bXpow2 = IsPowerof2(w); + bool bYpow2 = IsPowerof2(h); + //if bForceFFT, width AND height must be powers of 2 + if (bForceFFT && !(bXpow2 && bYpow2)) { + long i; + + i=0; + while((1< copy the image + if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false); + if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false); + + // dst&&src are empty -> create new one, else turn to GrayScale + if (srcReal==0 && dstReal==0){ + tmpReal = new CxImage(w,h,8); + tmpReal->Clear(0); + tmpReal->SetGrayPalette(); + } else { + if (!tmpReal->IsGrayScale()) tmpReal->GrayScale(); + } + if (srcImag==0 && dstImag==0){ + tmpImag = new CxImage(w,h,8); + tmpImag->Clear(0); + tmpImag->SetGrayPalette(); + } else { + if (!tmpImag->IsGrayScale()) tmpImag->GrayScale(); + } + + if (!(tmpReal->IsValid() && tmpImag->IsValid())){ + if (srcReal==0 && dstReal==0) delete tmpReal; + if (srcImag==0 && dstImag==0) delete tmpImag; + return false; + } + + //resample for FFT, if necessary + tmpReal->Resample(w,h,0); + tmpImag->Resample(w,h,0); + + //ok, here we have 2 (w x h), grayscale images ready for a FFT + + double* real; + double* imag; + long j,k,m; + + _complex **grid; + //double mean = tmpReal->Mean(); + /* Allocate memory for the grid */ + grid = (_complex **)malloc(w * sizeof(_complex)); + for (k=0;kGetPixelIndex(k,j)-128; + grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128; + } + } + + //DFT buffers + double *real2,*imag2; + real2 = (double*)malloc(max(w,h) * sizeof(double)); + imag2 = (double*)malloc(max(w,h) * sizeof(double)); + + /* Transform the rows */ + real = (double *)malloc(w * sizeof(double)); + imag = (double *)malloc(w * sizeof(double)); + + m=0; + while((1<SetPixelIndex(k,j,(BYTE)max(0,min(255,(nn*(3+log(_cabs(grid[k][j]))))))); + if (grid[k][j].x==0){ + tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn))))); + } else { + tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn))))); + } + } else { + tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].x*nn)))); + tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].y*nn)))); + } + } + } + + for (k=0;k> 1; + j = 0; + for (i=0;i>= 1; + } + j += k; + } + + /* Compute the FFT */ + c1 = -1.0; + c2 = 0.0; + l2 = 1; + for (l=0;lGetWidth(); + long h = r->GetHeight(); + + Create(w,h,24); + + g->Resample(w,h); + b->Resample(w,h); + + if (a) { + a->Resample(w,h); +#if CXIMAGE_SUPPORT_ALPHA + AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + } + + RGBQUAD c; + for (long y=0;y + for (long x=0;xGetPixelIndex(x,y); + c.rgbGreen=g->GetPixelIndex(x,y); + c.rgbBlue=b->GetPixelIndex(x,y); + switch (colorspace){ + case 1: + SetPixelColor(x,y,HSLtoRGB(c)); + break; + case 2: + SetPixelColor(x,y,YUVtoRGB(c)); + break; + case 3: + SetPixelColor(x,y,YIQtoRGB(c)); + break; + case 4: + SetPixelColor(x,y,XYZtoRGB(c)); + break; + default: + SetPixelColor(x,y,c); + } +#if CXIMAGE_SUPPORT_ALPHA + if (a) AlphaSet(x,y,a->GetPixelIndex(x,y)); +#endif //CXIMAGE_SUPPORT_ALPHA + } + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Smart blurring to remove small defects, dithering or artifacts. + * \param radius: normally between 0.01 and 0.5 + * \param niterations: should be trimmed with radius, to avoid blurring should be (radius*niterations)<1 + * \param colorspace: 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ + * \return true if everything is ok + */ +bool CxImage::Repair(float radius, long niterations, long colorspace) +{ + if (!IsValid()) return false; + + long w = GetWidth(); + long h = GetHeight(); + + CxImage r,g,b; + + r.Create(w,h,8); + g.Create(w,h,8); + b.Create(w,h,8); + + switch (colorspace){ + case 1: + SplitHSL(&r,&g,&b); + break; + case 2: + SplitYUV(&r,&g,&b); + break; + case 3: + SplitYIQ(&r,&g,&b); + break; + case 4: + SplitXYZ(&r,&g,&b); + break; + default: + SplitRGB(&r,&g,&b); + } + + for (int i=0; iGetWidth()-1; + long h = ch->GetHeight()-1; + + double correction,ix,iy,ixx,ixy,iyy,den,num; + int x,y,xy0,xp1,xm1,yp1,ym1; + for(x=1; xGetPixelIndex(x,y); + xm1 = ch->GetPixelIndex(x-1,y); + xp1 = ch->GetPixelIndex(x+1,y); + ym1 = ch->GetPixelIndex(x,y-1); + yp1 = ch->GetPixelIndex(x,y+1); + + ix= (xp1-xm1)/2.0; + iy= (yp1-ym1)/2.0; + ixx= xp1 - 2.0 * xy0 + xm1; + iyy= yp1 - 2.0 * xy0 + ym1; + ixy=(ch->GetPixelIndex(x+1,y+1)+ch->GetPixelIndex(x-1,y-1)- + ch->GetPixelIndex(x-1,y+1)-ch->GetPixelIndex(x+1,y-1))/4.0; + + num= (1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy; + den= 1.0+ix*ix+iy*iy; + correction = num/den; + + tmp.SetPixelIndex(x,y,(BYTE)min(255,max(0,(xy0 + radius * correction)))); + } + } + + for (x=0;x<=w;x++){ + tmp.SetPixelIndex(x,0,ch->GetPixelIndex(x,0)); + tmp.SetPixelIndex(x,h,ch->GetPixelIndex(x,h)); + } + for (y=0;y<=h;y++){ + tmp.SetPixelIndex(0,y,ch->GetPixelIndex(0,y)); + tmp.SetPixelIndex(w,y,ch->GetPixelIndex(w,y)); + } + ch->Transfer(tmp); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Enhance the variations between adjacent pixels. + * Similar results can be achieved using Filter(), + * but the algorithms are different both in Edge() and in Contour(). + * \return true if everything is ok + */ +bool CxImage::Contour() +{ + if (!pDib) return false; + + long Ksize = 3; + long k2 = Ksize/2; + long kmax= Ksize-k2; + long i,j,k; + BYTE maxr,maxg,maxb; + RGBQUAD pix1,pix2; + + CxImage tmp(*this,pSelection!=0,true,true); + if (!tmp.IsValid()) return false; + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; ymaxb) maxb = pix2.rgbBlue; + if ((pix2.rgbGreen-pix1.rgbGreen)>maxg) maxg = pix2.rgbGreen; + if ((pix2.rgbRed-pix1.rgbRed)>maxr) maxr = pix2.rgbRed; + } + } + pix1.rgbBlue=(BYTE)(255-maxb); + pix1.rgbGreen=(BYTE)(255-maxg); + pix1.rgbRed=(BYTE)(255-maxr); + tmp.SetPixelColor(x,y,pix1); + } + } + } + Transfer(tmp); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Adds a random offset to each pixel in the image + * \param radius: maximum pixel displacement + * \return true if everything is ok + */ +bool CxImage::Jitter(long radius) +{ + if (!pDib) return false; + + long nx,ny; + + CxImage tmp(*this,pSelection!=0,true,true); + if (!tmp.IsValid()) return false; + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; y y) + { + for (row = 0; row < y ; row++) + { + scale=0; + /* find the scale factor */ + for (j = 0; j < y ; j++) + { + /* if the index is in bounds, add it to the scale counter */ + if ((j + cmatrix_length/2 - row >= 0) && + (j + cmatrix_length/2 - row < cmatrix_length)) + scale += cmatrix[j + cmatrix_length/2 - row]; + } + for (i = 0; i= row - cmatrix_length/2) && + (j <= row + cmatrix_length/2)) + sum += cur_col[j*bytes + i] * cmatrix[j]; + } + dest_col[row*bytes + i] = (BYTE)(0.5f + sum / scale); + } + } + } + else + { + /* for the edge condition, we only use available info and scale to one */ + for (row = 0; row < cmatrix_middle; row++) + { + /* find scale factor */ + scale=0; + for (j = cmatrix_middle - row; j0; j--) + { + sum += *(ctable_p + *cur_col_p1); + cur_col_p1 += bytes; + ctable_p += 256; + } + cur_col_p++; + *(dest_col_p++) = (BYTE)(0.5f + sum); + } + } + + /* for the edge condition , we only use available info, and scale to one */ + for (; row < y; row++) + { + /* find scale factor */ + scale=0; + for (j = 0; j< y-row + cmatrix_middle; j++) + scale += cmatrix[j]; + for (i = 0; i 255) dest_row[u*3+v] = 255; + else dest_row[u*3+v] = value; + } + } + } + + Transfer(tmp); + + return TRUE; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Apply a look up table to the image. + * \param pLut: BYTE[256] look up table + * \return true if everything is ok + */ +bool CxImage::Lut(BYTE* pLut) +{ + if (!pDib || !pLut) return false; + RGBQUAD color; + + double dbScaler; + if (head.biClrUsed==0){ + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + // faster loop for full image + BYTE *iSrc=info.pImage; + for(unsigned long i=0; i < head.biSizeImage ; i++){ + *iSrc++ = pLut[*iSrc]; + } + return true; + } + + dbScaler = 100.0/ymax; + + for(long y=ymin; y + for(long x=xmin; x + if (!pDib) return false; + FloodFill2(x,y,GetPixelColor(x,y),FillColor); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::FloodFill2(int x, int y, RGBQUAD old_color, RGBQUAD new_color) +{ + // Fill in the actual pixels. + // Function steps recursively until it finds borders (color that is not old_color) + if (!IsInside(x,y)) return; + + RGBQUAD r = GetPixelColor(x,y); + COLORREF cr = RGB(r.rgbRed,r.rgbGreen,r.rgbBlue); + + if(cr == RGB(old_color.rgbRed,old_color.rgbGreen,old_color.rgbBlue) + && cr != RGB(new_color.rgbRed,new_color.rgbGreen,new_color.rgbBlue) ) { + + // the above if statement, after && is there to prevent + // stack overflows. The program will continue to find + // colors if you flood-fill an entire region (entire picture) + + SetPixelColor(x,y,new_color); + + FloodFill2((x+1),y,old_color,new_color); + FloodFill2((x-1),y,old_color,new_color); + FloodFill2(x,(y+1),old_color,new_color); + FloodFill2(x,(y-1),old_color,new_color); + } +}*/ +/////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_DSP diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaenc.cpp ./win32/dependencies/cximage/ximaenc.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaenc.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximaenc.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,920 @@ +// xImaCodec.cpp : Encode Decode functions +/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_JPG +#include "ximajpg.h" +#endif + +#if CXIMAGE_SUPPORT_GIF +#include "ximagif.h" +#endif + +#if CXIMAGE_SUPPORT_PNG +#include "ximapng.h" +#endif + +#if CXIMAGE_SUPPORT_MNG +#include "ximamng.h" +#endif + +#if CXIMAGE_SUPPORT_BMP +#include "ximabmp.h" +#endif + +#if CXIMAGE_SUPPORT_ICO +#include "ximaico.h" +#endif + +#if CXIMAGE_SUPPORT_TIF +#include "ximatif.h" +#endif + +#if CXIMAGE_SUPPORT_TGA +#include "ximatga.h" +#endif + +#if CXIMAGE_SUPPORT_PCX +#include "ximapcx.h" +#endif + +#if CXIMAGE_SUPPORT_WBMP +#include "ximawbmp.h" +#endif + +#if CXIMAGE_SUPPORT_WMF +#include "ximawmf.h" // - WMF/EMF support +#endif + +#if CXIMAGE_SUPPORT_J2K +#include "ximaj2k.h" +#endif + +#if CXIMAGE_SUPPORT_JBG +#include "ximajbg.h" +#endif + +#if CXIMAGE_SUPPORT_JASPER +#include "ximajas.h" +#endif + +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::EncodeSafeCheck(CxFile *hFile) +{ + if (hFile==NULL) { + strcpy(info.szLastError,CXIMAGE_ERR_NOFILE); + return true; + } + + if (pDib==NULL){ + strcpy(info.szLastError,CXIMAGE_ERR_NOIMAGE); + return true; + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +//#ifdef WIN32 +//bool CxImage::Save(LPCWSTR filename, DWORD imagetype) +//{ +// FILE* hFile; //file handle to write the image +// if ((hFile=_wfopen(filename,L"wb"))==NULL) return false; +// bool bOK = Encode(hFile,imagetype); +// fclose(hFile); +// return bOK; +//} +//#endif //WIN32 +//////////////////////////////////////////////////////////////////////////////// +// For UNICODE support: char -> TCHAR +/** + * Saves to disk the image in a specific format. + * \param filename: file name + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + */ +bool CxImage::Save(const TCHAR * filename, DWORD imagetype) +{ + FILE* hFile; //file handle to write the image + +#ifdef WIN32 + if ((hFile=_tfopen(filename,_T("wb")))==NULL) return false; // For UNICODE support +#else + if ((hFile=fopen(filename,"wb"))==NULL) return false; +#endif + + bool bOK = Encode(hFile,imagetype); + fclose(hFile); + return bOK; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Saves to disk the image in a specific format. + * \param hFile: file handle, open and enabled for writing. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + */ +bool CxImage::Encode(FILE *hFile, DWORD imagetype) +{ + CxIOFile file(hFile); + return Encode(&file,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Saves to memory buffer the image in a specific format. + * \param buffer: output memory buffer pointer. Must be NULL, + * the function allocates and fill the memory, + * the application must free the buffer, see also FreeMemory(). + * \param size: output memory buffer size. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + */ +bool CxImage::Encode(BYTE * &buffer, long &size, DWORD imagetype) +{ + if (buffer!=NULL){ + strcpy(info.szLastError,"the buffer must be empty"); + return false; + } + CxMemFile file; + file.Open(); + if(Encode(&file,imagetype)){ + buffer=file.GetBuffer(); + size=file.Size(); + return true; + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Saves to disk the image in a specific format. + * \param hFile: file handle (implemented using CxMemFile or CxIOFile), + * open and enabled for writing. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + * \sa ENUM_CXIMAGE_FORMATS + */ +bool CxImage::Encode(CxFile *hFile, DWORD imagetype) +{ + +#if CXIMAGE_SUPPORT_BMP + + if (imagetype==CXIMAGE_FORMAT_BMP){ + CxImageBMP newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_ICO + if (imagetype==CXIMAGE_FORMAT_ICO){ + CxImageICO newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_TIF + if (imagetype==CXIMAGE_FORMAT_TIF){ + CxImageTIF newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_JPG + if (imagetype==CXIMAGE_FORMAT_JPG){ + CxImageJPG newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_GIF + if (imagetype==CXIMAGE_FORMAT_GIF){ + CxImageGIF newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_PNG + if (imagetype==CXIMAGE_FORMAT_PNG){ + CxImagePNG newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_MNG + if (imagetype==CXIMAGE_FORMAT_MNG){ + CxImageMNG newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_TGA + if (imagetype==CXIMAGE_FORMAT_TGA){ + CxImageTGA newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_PCX + if (imagetype==CXIMAGE_FORMAT_PCX){ + CxImagePCX newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_WBMP + if (imagetype==CXIMAGE_FORMAT_WBMP){ + CxImageWBMP newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // - WMF/EMF support + if (imagetype==CXIMAGE_FORMAT_WMF){ + CxImageWMF newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_J2K + if (imagetype==CXIMAGE_FORMAT_J2K){ + CxImageJ2K newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_JBG + if (imagetype==CXIMAGE_FORMAT_JBG){ + CxImageJBG newima; + newima.Ghost(this); + if (newima.Encode(hFile)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_JASPER + if ( + #if CXIMAGE_SUPPORT_JP2 + imagetype==CXIMAGE_FORMAT_JP2 || + #endif + #if CXIMAGE_SUPPORT_JPC + imagetype==CXIMAGE_FORMAT_JPC || + #endif + #if CXIMAGE_SUPPORT_PGX + imagetype==CXIMAGE_FORMAT_PGX || + #endif + #if CXIMAGE_SUPPORT_PNM + imagetype==CXIMAGE_FORMAT_PNM || + #endif + #if CXIMAGE_SUPPORT_RAS + imagetype==CXIMAGE_FORMAT_RAS || + #endif + false ){ + CxImageJAS newima; + newima.Ghost(this); + if (newima.Encode(hFile,imagetype)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif + + strcpy(info.szLastError,"Encode: Unknown format"); + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers. + * \param hFile: file handle. + * \param pImages: array of CxImage pointers. + * \param pagecount: number of images. + * \param imagetype: can be CXIMAGE_FORMAT_TIF or CXIMAGE_FORMAT_GIF. + * \return true if everything is ok + */ +bool CxImage::Encode(FILE * hFile, CxImage ** pImages, int pagecount, DWORD imagetype) +{ + CxIOFile file(hFile); + return Encode(&file, pImages, pagecount,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers. + * \param hFile: file handle (implemented using CxMemFile or CxIOFile). + * \param pImages: array of CxImage pointers. + * \param pagecount: number of images. + * \param imagetype: can be CXIMAGE_FORMAT_TIF or CXIMAGE_FORMAT_GIF. + * \return true if everything is ok + */ +bool CxImage::Encode(CxFile * hFile, CxImage ** pImages, int pagecount, DWORD imagetype) +{ +#if CXIMAGE_SUPPORT_TIF + if (imagetype==CXIMAGE_FORMAT_TIF){ + CxImageTIF newima; + newima.Ghost(this); + if (newima.Encode(hFile,pImages,pagecount)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_GIF + if (imagetype==CXIMAGE_FORMAT_GIF){ + CxImageGIF newima; + newima.Ghost(this); + if (newima.Encode(hFile,pImages,pagecount)){ + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif + strcpy(info.szLastError,"Multipage Encode, Unsupported operation for this format"); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * exports the image into a RGBA buffer, Useful for OpenGL applications. + * \param buffer: output memory buffer pointer. Must be NULL, + * the function allocates and fill the memory, + * the application must free the buffer, see also FreeMemory(). + * \param size: output memory buffer size. + * \return true if everything is ok + */ +bool CxImage::Encode2RGBA(BYTE * &buffer, long &size) +{ + if (buffer!=NULL){ + strcpy(info.szLastError,"the buffer must be empty"); + return false; + } + CxMemFile file; + file.Open(); + if(Encode2RGBA(&file)){ + buffer=file.GetBuffer(); + size=file.Size(); + return true; + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * exports the image into a RGBA buffer, Useful for OpenGL applications. + * \param hFile: file handle (implemented using CxMemFile or CxIOFile). + * \return true if everything is ok + */ +bool CxImage::Encode2RGBA(CxFile *hFile) +{ + if (EncodeSafeCheck(hFile)) return false; + + for (DWORD y = 0; yPutC(color.rgbRed); + hFile->PutC(color.rgbGreen); + hFile->PutC(color.rgbBlue); + hFile->PutC(color.rgbReserved); + } + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_DECODE +//////////////////////////////////////////////////////////////////////////////// +// For UNICODE support: char -> TCHAR +/** + * Reads from disk the image in a specific format. + * - If decoding fails using the specified image format, + * the function will try the automatic file format recognition. + * + * \param filename: file name + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + */ +bool CxImage::Load(const TCHAR * filename, DWORD imagetype) +//bool CxImage::Load(const char * filename, DWORD imagetype) +{ + /*FILE* hFile; //file handle to read the image + if ((hFile=fopen(filename,"rb"))==NULL) return false; + bool bOK = Decode(hFile,imagetype); + fclose(hFile);*/ + + /* automatic file type recognition */ + bool bOK = false; + if ( imagetype > 0 && imagetype < CMAX_IMAGE_FORMATS ){ + FILE* hFile; //file handle to read the image + +#ifdef WIN32 + if ((hFile=_tfopen(filename,_T("rb")))==NULL) return false; // For UNICODE support +#else + if ((hFile=fopen(filename,"rb"))==NULL) return false; +#endif + + bOK = Decode(hFile,imagetype); + fclose(hFile); + if (bOK) return bOK; + } + + char szError[256]; + strcpy(szError,info.szLastError); //save the first error + + // if failed, try automatic recognition of the file... + FILE* hFile; + +#ifdef WIN32 + if ((hFile=_tfopen(filename,_T("rb")))==NULL) return false; // For UNICODE support +#else + if ((hFile=fopen(filename,"rb"))==NULL) return false; +#endif + + bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN); + fclose(hFile); + + if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error + + return bOK; +} +//////////////////////////////////////////////////////////////////////////////// +#ifdef WIN32 +//bool CxImage::Load(LPCWSTR filename, DWORD imagetype) +//{ +// /*FILE* hFile; //file handle to read the image +// if ((hFile=_wfopen(filename, L"rb"))==NULL) return false; +// bool bOK = Decode(hFile,imagetype); +// fclose(hFile);*/ +// +// /* automatic file type recognition */ +// bool bOK = false; +// if ( imagetype > 0 && imagetype < CMAX_IMAGE_FORMATS ){ +// FILE* hFile; //file handle to read the image +// if ((hFile=_wfopen(filename,L"rb"))==NULL) return false; +// bOK = Decode(hFile,imagetype); +// fclose(hFile); +// if (bOK) return bOK; +// } +// +// char szError[256]; +// strcpy(szError,info.szLastError); //save the first error +// +// // if failed, try automatic recognition of the file... +// FILE* hFile; //file handle to read the image +// if ((hFile=_wfopen(filename,L"rb"))==NULL) return false; +// bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN); +// fclose(hFile); +// +// if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error +// +// return bOK; +//} +//////////////////////////////////////////////////////////////////////////////// +/** + * Loads an image from the application resources. + * \param hRes: the resource handle returned by FindResource(). + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS. + * \param hModule: NULL for internal resource, or external application/DLL hinstance returned by LoadLibray. + * \return true if everything is ok + */ +bool CxImage::LoadResource(HRSRC hRes, DWORD imagetype, HMODULE hModule) +{ + DWORD rsize=SizeofResource(hModule,hRes); + HGLOBAL hMem=::LoadResource(hModule,hRes); + if (hMem){ + char* lpVoid=(char*)LockResource(hMem); + if (lpVoid){ + // FILE* fTmp=tmpfile(); doesn't work with network + /*char tmpPath[MAX_PATH] = {0}; + char tmpFile[MAX_PATH] = {0}; + GetTempPath(MAX_PATH,tmpPath); + GetTempFileName(tmpPath,"IMG",0,tmpFile); + FILE* fTmp=fopen(tmpFile,"w+b"); + if (fTmp){ + fwrite(lpVoid,rsize,1,fTmp); + fseek(fTmp,0,SEEK_SET); + bool bOK = Decode(fTmp,imagetype); + fclose(fTmp); + DeleteFile(tmpFile); + return bOK; + }*/ + + CxMemFile fTmp((BYTE*)lpVoid,rsize); + return Decode(&fTmp,imagetype); + } + } else strcpy(info.szLastError,"Unable to load resource!"); + return false; +} +#endif //WIN32 +//////////////////////////////////////////////////////////////////////////////// +/** + * Constructor from file name, see Load() + * \param filename: file name + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + */ +// +// > filename: file name +// > imagetype: specify the image format (CXIMAGE_FORMAT_BMP,...) +// For UNICODE support: char -> TCHAR +CxImage::CxImage(const TCHAR * filename, DWORD imagetype) +//CxImage::CxImage(const char * filename, DWORD imagetype) +{ + Startup(imagetype); + Load(filename,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Constructor from file handle, see Decode() + * \param stream: file handle, with read access. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + */ +CxImage::CxImage(FILE * stream, DWORD imagetype) +{ + Startup(imagetype); + Decode(stream,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Constructor from CxFile object, see Decode() + * \param stream: file handle (implemented using CxMemFile or CxIOFile), with read access. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + */ +CxImage::CxImage(CxFile * stream, DWORD imagetype) +{ + Startup(imagetype); + Decode(stream,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Constructor from memory buffer, see Decode() + * \param buffer: memory buffer + * \param size: size of buffer + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + */ +CxImage::CxImage(BYTE * buffer, DWORD size, DWORD imagetype) +{ + Startup(imagetype); + CxMemFile stream(buffer,size); + Decode(&stream,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Loads an image from memory buffer + * \param buffer: memory buffer + * \param size: size of buffer + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + */ +bool CxImage::Decode(BYTE * buffer, DWORD size, DWORD imagetype) +{ + CxMemFile file(buffer,size); + return Decode(&file,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Loads an image from file handle. + * \param hFile: file handle, with read access. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + */ +bool CxImage::Decode(FILE *hFile, DWORD imagetype) +{ + CxIOFile file(hFile); + return Decode(&file,imagetype); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Loads an image from CxFile object + * \param hFile: file handle (implemented using CxMemFile or CxIOFile), with read access. + * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS + * \return true if everything is ok + * \sa ENUM_CXIMAGE_FORMATS + */ +bool CxImage::Decode(CxFile *hFile, DWORD imagetype) +{ + + if (imagetype==CXIMAGE_FORMAT_UNKNOWN){ + DWORD pos = hFile->Tell(); +#if CXIMAGE_SUPPORT_BMP + { CxImageBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_JPG + { CxImageJPG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_ICO + { CxImageICO newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_GIF + { CxImageGIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_PNG + { CxImagePNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_TIF + { CxImageTIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_MNG + { CxImageMNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_TGA + { CxImageTGA newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_PCX + { CxImagePCX newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_WBMP + { CxImageWBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS + { CxImageWMF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_J2K + { CxImageJ2K newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_JBG + { CxImageJBG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif +#if CXIMAGE_SUPPORT_JASPER + { CxImageJAS newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); } +#endif + } + +#if CXIMAGE_SUPPORT_BMP + if (imagetype==CXIMAGE_FORMAT_BMP){ + CxImageBMP newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_JPG + if (imagetype==CXIMAGE_FORMAT_JPG){ + CxImageJPG newima; + newima.CopyInfo(*this); // + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_ICO + if (imagetype==CXIMAGE_FORMAT_ICO){ + CxImageICO newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + info.nNumFrames = newima.info.nNumFrames; + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_GIF + if (imagetype==CXIMAGE_FORMAT_GIF){ + CxImageGIF newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + info.nNumFrames = newima.info.nNumFrames; + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_PNG + if (imagetype==CXIMAGE_FORMAT_PNG){ + CxImagePNG newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_TIF + if (imagetype==CXIMAGE_FORMAT_TIF){ + CxImageTIF newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + info.nNumFrames = newima.info.nNumFrames; + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_MNG + if (imagetype==CXIMAGE_FORMAT_MNG){ + CxImageMNG newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + info.nNumFrames = newima.info.nNumFrames; + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_TGA + if (imagetype==CXIMAGE_FORMAT_TGA){ + CxImageTGA newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_PCX + if (imagetype==CXIMAGE_FORMAT_PCX){ + CxImagePCX newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_WBMP + if (imagetype==CXIMAGE_FORMAT_WBMP){ + CxImageWBMP newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // vho - WMF support + if (imagetype == CXIMAGE_FORMAT_WMF){ + CxImageWMF newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_J2K + if (imagetype==CXIMAGE_FORMAT_J2K){ + CxImageJ2K newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_JBG + if (imagetype==CXIMAGE_FORMAT_JBG){ + CxImageJBG newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif +#if CXIMAGE_SUPPORT_JASPER + if ( + #if CXIMAGE_SUPPORT_JP2 + imagetype==CXIMAGE_FORMAT_JP2 || + #endif + #if CXIMAGE_SUPPORT_JPC + imagetype==CXIMAGE_FORMAT_JPC || + #endif + #if CXIMAGE_SUPPORT_PGX + imagetype==CXIMAGE_FORMAT_PGX || + #endif + #if CXIMAGE_SUPPORT_PNM + imagetype==CXIMAGE_FORMAT_PNM || + #endif + #if CXIMAGE_SUPPORT_RAS + imagetype==CXIMAGE_FORMAT_RAS || + #endif + false ){ + CxImageJAS newima; + newima.CopyInfo(*this); + if (newima.Decode(hFile,imagetype)){ + Transfer(newima); + return true; + } else { + strcpy(info.szLastError,newima.GetLastError()); + return false; + } + } +#endif + + strcpy(info.szLastError,"Decode: Unknown or wrong format"); + return false; +} +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_DECODE +//////////////////////////////////////////////////////////////////////////////// diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaexif.cpp ./win32/dependencies/cximage/ximaexif.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaexif.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximaexif.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,873 @@ +/* + * File: ximaexif.cpp + * Purpose: EXIF reader + * 18/Aug/2002 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + * based on jhead-1.8 by Matthias Wandel + */ + +#include "ximajpg.h" + +#if CXIMAGEJPG_SUPPORT_EXIF + +//////////////////////////////////////////////////////////////////////////////// +CxImageJPG::CxExifInfo::CxExifInfo(EXIFINFO* info) +{ + if (info) { + m_exifinfo = info; + freeinfo = false; + } else { + m_exifinfo = new EXIFINFO; + memset(m_exifinfo,0,sizeof(EXIFINFO)); + freeinfo = true; + } + + m_szLastError[0]='\0'; + ExifImageWidth = MotorolaOrder = 0; + SectionsRead=0; + memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t)); +} +//////////////////////////////////////////////////////////////////////////////// +CxImageJPG::CxExifInfo::~CxExifInfo() +{ + for(int i=0;iGetC(); + + if (a != 0xff || hFile->GetC() != M_SOI){ + return FALSE; + } + + for(;;){ + int itemlen; + int marker = 0; + int ll,lh, got; + BYTE * Data; + + if (SectionsRead >= MAX_SECTIONS){ + strcpy(m_szLastError,"Too many sections in jpg file"); + return false; + } + + for (a=0;a<7;a++){ + marker = hFile->GetC(); + if (marker != 0xff) break; + + if (a >= 6){ + printf("too many padding bytes\n"); + return false; + } + } + + if (marker == 0xff){ + // 0xff is legal padding, but if we get that many, something's wrong. + strcpy(m_szLastError,"too many padding bytes!"); + return false; + } + + Sections[SectionsRead].Type = marker; + + // Read the length of the section. + lh = hFile->GetC(); + ll = hFile->GetC(); + + itemlen = (lh << 8) | ll; + + if (itemlen < 2){ + strcpy(m_szLastError,"invalid marker"); + return false; + } + + Sections[SectionsRead].Size = itemlen; + + Data = (BYTE *)malloc(itemlen); + if (Data == NULL){ + strcpy(m_szLastError,"Could not allocate memory"); + return false; + } + Sections[SectionsRead].Data = Data; + + // Store first two pre-read bytes. + Data[0] = (BYTE)lh; + Data[1] = (BYTE)ll; + + got = hFile->Read(Data+2, 1, itemlen-2); // Read the whole section. + if (got != itemlen-2){ + strcpy(m_szLastError,"Premature end of file?"); + return false; + } + SectionsRead += 1; + + switch(marker){ + + case M_SOS: // stop before hitting compressed data + // If reading entire image is requested, read the rest of the data. + if (nReadMode & EXIF_READ_IMAGE){ + int cp, ep, size; + // Determine how much file is left. + cp = hFile->Tell(); + hFile->Seek(0, SEEK_END); + ep = hFile->Tell(); + hFile->Seek(cp, SEEK_SET); + + size = ep-cp; + Data = (BYTE *)malloc(size); + if (Data == NULL){ + strcpy(m_szLastError,"could not allocate data for entire image"); + return false; + } + + got = hFile->Read(Data, 1, size); + if (got != size){ + strcpy(m_szLastError,"could not read the rest of the image"); + return false; + } + + Sections[SectionsRead].Data = Data; + Sections[SectionsRead].Size = size; + Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; + SectionsRead ++; + } + return true; + + case M_EOI: // in case it's a tables-only JPEG stream + printf("No image in jpeg!\n"); + return FALSE; + + case M_COM: // Comment section + if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0)){ + // Discard this section. + free(Sections[--SectionsRead].Data); + Sections[SectionsRead].Data=0; + }else{ + process_COM(Data, itemlen); + HaveCom = TRUE; + } + break; + + case M_JFIF: + // Regular jpegs always have this tag, exif images have the exif + // marker instead, althogh ACDsee will write images with both markers. + // this program will re-create this marker on absence of exif marker. + // hence no need to keep the copy from the file. + free(Sections[--SectionsRead].Data); + Sections[SectionsRead].Data=0; + break; + + case M_EXIF: + // Seen files from some 'U-lead' software with Vivitar scanner + // that uses marker 31 for non exif stuff. Thus make sure + // it says 'Exif' in the section before treating it as exif. + if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ + m_exifinfo->IsExif = process_EXIF((BYTE *)Data+2, itemlen); + }else{ + // Discard this section. + free(Sections[--SectionsRead].Data); + Sections[SectionsRead].Data=0; + } + break; + + case M_SOF0: + case M_SOF1: + case M_SOF2: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + process_SOFn(Data, marker); + break; + default: + // Skip any other sections. + //if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen); + break; + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------------------------------------------- + Process a EXIF marker + Describes all the drivel that most digital cameras include... +--------------------------------------------------------------------------*/ +bool CxImageJPG::CxExifInfo::process_EXIF(unsigned char * CharBuf, unsigned int length) +{ + m_exifinfo->FlashUsed = 0; + /* If it's from a digicam, and it used flash, it says so. */ + m_exifinfo->Comments[0] = '\0'; /* Initial value - null string */ + + ExifImageWidth = 0; + + { /* Check the EXIF header component */ + static const unsigned char ExifHeader[] = "Exif\0\0"; + if (memcmp(CharBuf+0, ExifHeader,6)){ + strcpy(m_szLastError,"Incorrect Exif header"); + return false; + } + } + + if (memcmp(CharBuf+6,"II",2) == 0){ + MotorolaOrder = 0; + }else{ + if (memcmp(CharBuf+6,"MM",2) == 0){ + MotorolaOrder = 1; + }else{ + strcpy(m_szLastError,"Invalid Exif alignment marker."); + return false; + } + } + + /* Check the next two values for correctness. */ + if (Get16u(CharBuf+8) != 0x2a){ + strcpy(m_szLastError,"Invalid Exif start (1)"); + return false; + } + + int FirstOffset = Get32u(CharBuf+10); + /* + if (FirstOffset < 8 || FirstOffset > 16){ + // I used to ensure this was set to 8 (website I used indicated its 8) + // but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002) + strcpy(m_szLastError,"Suspicious offset of first IFD value"); + return false; + }*/ + + unsigned char * LastExifRefd = CharBuf; + + /* First directory starts 16 bytes in. Offsets start at 8 bytes in. */ + if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd)) + return false; + + /* give a chance for a second directory */ + if (FirstOffset > 8) { + if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd)) + return false; + } + + /* This is how far the interesting (non thumbnail) part of the exif went. */ + // int ExifSettingsLength = LastExifRefd - CharBuf; + + /* Compute the CCD width, in milimeters. */ + if (m_exifinfo->FocalplaneXRes != 0){ + m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes); + } + + return true; +} +//-------------------------------------------------------------------------- +// Get 16 bits motorola order (always) for jpeg header stuff. +//-------------------------------------------------------------------------- +int CxImageJPG::CxExifInfo::Get16m(void * Short) +{ + return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1]; +} +//////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------------------------------------------- + Convert a 16 bit unsigned value from file's native byte order +--------------------------------------------------------------------------*/ +int CxImageJPG::CxExifInfo::Get16u(void * Short) +{ + if (MotorolaOrder){ + return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1]; + }else{ + return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0]; + } +} +//////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------------------------------------------- + Convert a 32 bit signed value from file's native byte order +--------------------------------------------------------------------------*/ +long CxImageJPG::CxExifInfo::Get32s(void * Long) +{ + if (MotorolaOrder){ + return ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16) + | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 ); + }else{ + return ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16) + | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 ); + } +} +//////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------------------------------------------- + Convert a 32 bit unsigned value from file's native byte order +--------------------------------------------------------------------------*/ +unsigned long CxImageJPG::CxExifInfo::Get32u(void * Long) +{ + return (unsigned long)Get32s(Long) & 0xffffffff; +} +//////////////////////////////////////////////////////////////////////////////// + +/* Describes format descriptor */ +static const int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; +#define NUM_FORMATS 12 + +#define FMT_BYTE 1 +#define FMT_STRING 2 +#define FMT_USHORT 3 +#define FMT_ULONG 4 +#define FMT_URATIONAL 5 +#define FMT_SBYTE 6 +#define FMT_UNDEFINED 7 +#define FMT_SSHORT 8 +#define FMT_SLONG 9 +#define FMT_SRATIONAL 10 +#define FMT_SINGLE 11 +#define FMT_DOUBLE 12 + +/* Describes tag values */ + +#define TAG_EXIF_VERSION 0x9000 +#define TAG_EXIF_OFFSET 0x8769 +#define TAG_INTEROP_OFFSET 0xa005 + +#define TAG_MAKE 0x010F +#define TAG_MODEL 0x0110 + +#define TAG_ORIENTATION 0x0112 +#define TAG_XRESOLUTION 0x011A +#define TAG_YRESOLUTION 0x011B +#define TAG_RESOLUTIONUNIT 0x0128 + +#define TAG_EXPOSURETIME 0x829A +#define TAG_FNUMBER 0x829D + +#define TAG_SHUTTERSPEED 0x9201 +#define TAG_APERTURE 0x9202 +#define TAG_BRIGHTNESS 0x9203 +#define TAG_MAXAPERTURE 0x9205 +#define TAG_FOCALLENGTH 0x920A + +#define TAG_DATETIME_ORIGINAL 0x9003 +#define TAG_USERCOMMENT 0x9286 + +#define TAG_SUBJECT_DISTANCE 0x9206 +#define TAG_FLASH 0x9209 + +#define TAG_FOCALPLANEXRES 0xa20E +#define TAG_FOCALPLANEYRES 0xa20F +#define TAG_FOCALPLANEUNITS 0xa210 +#define TAG_EXIF_IMAGEWIDTH 0xA002 +#define TAG_EXIF_IMAGELENGTH 0xA003 + +/* the following is added 05-jan-2001 vcs */ +#define TAG_EXPOSURE_BIAS 0x9204 +#define TAG_WHITEBALANCE 0x9208 +#define TAG_METERING_MODE 0x9207 +#define TAG_EXPOSURE_PROGRAM 0x8822 +#define TAG_ISO_EQUIVALENT 0x8827 +#define TAG_COMPRESSION_LEVEL 0x9102 + +#define TAG_THUMBNAIL_OFFSET 0x0201 +#define TAG_THUMBNAIL_LENGTH 0x0202 + + +/*-------------------------------------------------------------------------- + Process one of the nested EXIF directories. +--------------------------------------------------------------------------*/ +bool CxImageJPG::CxExifInfo::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength, + EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP ) +{ + int de; + int a; + int NumDirEntries; + unsigned ThumbnailOffset = 0; + unsigned ThumbnailSize = 0; + + NumDirEntries = Get16u(DirStart); + + if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){ + strcpy(m_szLastError,"Illegally sized directory"); + return false; + } + + for (de=0;de= NUM_FORMATS) { + /* (-1) catches illegal zero case as unsigned underflows to positive large */ + strcpy(m_szLastError,"Illegal format code in EXIF dir"); + return false; + } + + ByteCount = Components * BytesPerFormat[Format]; + + if (ByteCount > 4){ + unsigned OffsetVal; + OffsetVal = Get32u(DirEntry+8); + /* If its bigger than 4 bytes, the dir entry contains an offset.*/ + if (OffsetVal+ByteCount > ExifLength){ + /* Bogus pointer offset and / or bytecount value */ + strcpy(m_szLastError,"Illegal pointer offset value in EXIF."); + return false; + } + ValuePtr = OffsetBase+OffsetVal; + }else{ + /* 4 bytes or less and value is in the dir entry itself */ + ValuePtr = DirEntry+8; + } + + if (*LastExifRefdP < ValuePtr+ByteCount){ + /* Keep track of last byte in the exif header that was + actually referenced. That way, we know where the + discardable thumbnail data begins. + */ + *LastExifRefdP = ValuePtr+ByteCount; + } + + /* Extract useful components of tag */ + switch(Tag){ + + case TAG_MAKE: + strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31); + break; + + case TAG_MODEL: + strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39); + break; + + case TAG_EXIF_VERSION: + strncpy(m_exifinfo->Version,(char*)ValuePtr, 4); + break; + + case TAG_DATETIME_ORIGINAL: + strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19); + break; + + case TAG_USERCOMMENT: + // Olympus has this padded with trailing spaces. Remove these first. + for (a=ByteCount;;){ + a--; + if (((char*)ValuePtr)[a] == ' '){ + ((char*)ValuePtr)[a] = '\0'; + }else{ + break; + } + if (a == 0) break; + } + + /* Copy the comment */ + if (memcmp(ValuePtr, "ASCII",5) == 0){ + for (a=5;a<10;a++){ + char c; + c = ((char*)ValuePtr)[a]; + if (c != '\0' && c != ' '){ + strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199); + break; + } + } + + }else{ + strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199); + } + break; + + case TAG_FNUMBER: + /* Simplest way of expressing aperture, so I trust it the most. + (overwrite previously computd value if there is one) + */ + m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_APERTURE: + case TAG_MAXAPERTURE: + /* More relevant info always comes earlier, so only + use this field if we don't have appropriate aperture + information yet. + */ + if (m_exifinfo->ApertureFNumber == 0){ + m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)*0.5); + } + break; + + case TAG_BRIGHTNESS: + m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_FOCALLENGTH: + /* Nice digital cameras actually save the focal length + as a function of how farthey are zoomed in. + */ + + m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_SUBJECT_DISTANCE: + /* Inidcates the distacne the autofocus camera is focused to. + Tends to be less accurate as distance increases. + */ + m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_EXPOSURETIME: + /* Simplest way of expressing exposure time, so I + trust it most. (overwrite previously computd value + if there is one) + */ + m_exifinfo->ExposureTime = + (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_SHUTTERSPEED: + /* More complicated way of expressing exposure time, + so only use this value if we don't already have it + from somewhere else. + */ + if (m_exifinfo->ExposureTime == 0){ + m_exifinfo->ExposureTime = (float) + (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f))); + } + break; + + case TAG_FLASH: + if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){ + m_exifinfo->FlashUsed = 1; + }else{ + m_exifinfo->FlashUsed = 0; + } + break; + + case TAG_ORIENTATION: + m_exifinfo->Orientation = (int)ConvertAnyFormat(ValuePtr, Format); + if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){ + strcpy(m_szLastError,"Undefined rotation value"); + m_exifinfo->Orientation = 0; + } + break; + + case TAG_EXIF_IMAGELENGTH: + case TAG_EXIF_IMAGEWIDTH: + /* Use largest of height and width to deal with images + that have been rotated to portrait format. + */ + a = (int)ConvertAnyFormat(ValuePtr, Format); + if (ExifImageWidth < a) ExifImageWidth = a; + break; + + case TAG_FOCALPLANEXRES: + m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_FOCALPLANEYRES: + m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_RESOLUTIONUNIT: + switch((int)ConvertAnyFormat(ValuePtr, Format)){ + case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */ + case 2: m_exifinfo->ResolutionUnit = 1.0f; break; + case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/ + case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/ + case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/ + } + break; + + case TAG_FOCALPLANEUNITS: + switch((int)ConvertAnyFormat(ValuePtr, Format)){ + case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */ + case 2: m_exifinfo->FocalplaneUnits = 1.0f; break; + case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/ + case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/ + case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/ + } + break; + + // Remaining cases contributed by: Volker C. Schoech + + case TAG_EXPOSURE_BIAS: + m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_WHITEBALANCE: + m_exifinfo->Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_METERING_MODE: + m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_EXPOSURE_PROGRAM: + m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_ISO_EQUIVALENT: + m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format); + if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200; + break; + + case TAG_COMPRESSION_LEVEL: + m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_XRESOLUTION: + m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format); + break; + case TAG_YRESOLUTION: + m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_THUMBNAIL_OFFSET: + ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_THUMBNAIL_LENGTH: + ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format); + break; + + } + + if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){ + unsigned char * SubdirStart; + unsigned Offset = Get32u(ValuePtr); + if (Offset>8){ + SubdirStart = OffsetBase + Offset; + if (SubdirStart < OffsetBase || + SubdirStart > OffsetBase+ExifLength){ + strcpy(m_szLastError,"Illegal subdirectory link"); + return false; + } + ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP); + } + continue; + } + } + + + { + /* In addition to linking to subdirectories via exif tags, + there's also a potential link to another directory at the end + of each directory. This has got to be the result of a + committee! + */ + unsigned char * SubdirStart; + unsigned Offset; + Offset = Get16u(DirStart+2+12*NumDirEntries); + if (Offset){ + SubdirStart = OffsetBase + Offset; + if (SubdirStart < OffsetBase + || SubdirStart > OffsetBase+ExifLength){ + strcpy(m_szLastError,"Illegal subdirectory link"); + return false; + } + ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP); + } + } + + + if (ThumbnailSize && ThumbnailOffset){ + if (ThumbnailSize + ThumbnailOffset <= ExifLength){ + /* The thumbnail pointer appears to be valid. Store it. */ + m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset; + m_exifinfo->ThumbnailSize = ThumbnailSize; + } + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------------------------------------------- + Evaluate number, be it int, rational, or float from directory. +--------------------------------------------------------------------------*/ +double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int Format) +{ + double Value; + Value = 0; + + switch(Format){ + case FMT_SBYTE: Value = *(signed char *)ValuePtr; break; + case FMT_BYTE: Value = *(unsigned char *)ValuePtr; break; + + case FMT_USHORT: Value = Get16u(ValuePtr); break; + case FMT_ULONG: Value = Get32u(ValuePtr); break; + + case FMT_URATIONAL: + case FMT_SRATIONAL: + { + int Num,Den; + Num = Get32s(ValuePtr); + Den = Get32s(4+(char *)ValuePtr); + if (Den == 0){ + Value = 0; + }else{ + Value = (double)Num/Den; + } + break; + } + + case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break; + case FMT_SLONG: Value = Get32s(ValuePtr); break; + + /* Not sure if this is correct (never seen float used in Exif format) + */ + case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break; + case FMT_DOUBLE: Value = *(double *)ValuePtr; break; + } + return Value; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageJPG::CxExifInfo::process_COM (const BYTE * Data, int length) +{ + int ch; + char Comment[MAX_COMMENT+1]; + int nch; + int a; + + nch = 0; + + if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure. + + for (a=2;aComments,Comment); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageJPG::CxExifInfo::process_SOFn (const BYTE * Data, int marker) +{ + int data_precision, num_components; + + data_precision = Data[2]; + m_exifinfo->Height = Get16m((void*)(Data+3)); + m_exifinfo->Width = Get16m((void*)(Data+5)); + num_components = Data[7]; + + if (num_components == 3){ + m_exifinfo->IsColor = 1; + }else{ + m_exifinfo->IsColor = 0; + } + + m_exifinfo->Process = marker; + + //if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", + // ImageInfo.Width, ImageInfo.Height, num_components, data_precision); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * this will work only on a CxImageJPG object, if the image originally has valid EXIF data + \verbatim + CxImageJPG jpg; + CxIOFile in,out; + in.Open("D:\\exif_in.jpg","rb"); + out.Open("D:\\exif_out.jpg","w+b"); + jpg.Decode(&in); + if (jpg.IsValid()){ + jpg.RotateLeft(); + jpg.Encode(&out); + } + \endverbatim +*/ +bool CxImageJPG::CxExifInfo::EncodeExif(CxFile * hFile) +{ + int a; + + if (FindSection(M_SOS)==NULL){ + strcpy(m_szLastError,"Can't write exif : didn't read all"); + return false; + } + + // Initial static jpeg marker. + hFile->PutC(0xff); + hFile->PutC(0xd8); + + if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){ + // The image must start with an exif or jfif marker. If we threw those away, create one. + static BYTE JfifHead[18] = { + 0xff, M_JFIF, + 0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01, + 0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00 + }; + hFile->Write(JfifHead, 18, 1); + } + + // Write all the misc sections + for (a=0;aPutC(0xff); + hFile->PutC(Sections[a].Type); + hFile->Write(Sections[a].Data, Sections[a].Size, 1); + } + + // Write the remaining image data. + hFile->Write(Sections[a].Data, Sections[a].Size, 1); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageJPG::CxExifInfo::DiscardAllButExif() +{ + Section_t ExifKeeper; + Section_t CommentKeeper; + int a; + + memset(&ExifKeeper, 0, sizeof(ExifKeeper)); + memset(&CommentKeeper, 0, sizeof(ExifKeeper)); + + for (a=0;a Use it before Create() + */ +void CxImage::CopyInfo(const CxImage &src) +{ + if (pDib==NULL) memcpy(&info,&src.info,sizeof(CXIMAGEINFO)); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \sa Copy + */ +CxImage& CxImage::operator = (const CxImage& isrc) +{ + if (this != &isrc) Copy(isrc); + return *this; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Initializes or rebuilds the image. + * \param dwWidth: width + * \param dwHeight: height + * \param wBpp: bit per pixel, can be 1, 4, 8, 24 + * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS + * \return pointer to the internal pDib object; NULL if an error occurs. + */ +void* CxImage::Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype) +{ + // destroy the existing image (if any) + if (!Destroy()) + return NULL; + + // prevent further actions if width or height are not vaild + if ((dwWidth == 0) || (dwHeight == 0)){ + strcpy(info.szLastError,"CxImage::Create : width and height must be greater than zero"); + return NULL; + } + + // Make sure bits per pixel is valid + if (wBpp <= 1) wBpp = 1; + else if (wBpp <= 4) wBpp = 4; + else if (wBpp <= 8) wBpp = 8; + else wBpp = 24; + + // limit memory requirements (and also a check for bad parameters) + if (((dwWidth*dwHeight*wBpp)>>8) > CXIMAGE_MAX_MEMORY){ + strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded"); + return NULL; + } + + // set the correct bpp value + switch (wBpp){ + case 1: + head.biClrUsed = 2; break; + case 4: + head.biClrUsed = 16; break; + case 8: + head.biClrUsed = 256; break; + default: + head.biClrUsed = 0; + } + + //set the common image informations + info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4); + info.dwType = imagetype; + + // initialize BITMAPINFOHEADER + head.biSize = sizeof(BITMAPINFOHEADER); // + head.biWidth = dwWidth; // fill in width from parameter + head.biHeight = dwHeight; // fill in height from parameter + head.biPlanes = 1; // must be 1 + head.biBitCount = (WORD)wBpp; // from parameter + head.biCompression = BI_RGB; + head.biSizeImage = info.dwEffWidth * dwHeight; +// head.biXPelsPerMeter = 0; See SetXDPI +// head.biYPelsPerMeter = 0; See SetYDPI + head.biClrImportant = 0; + + pDib = malloc(GetSize()); // alloc memory block to store our bitmap + if (!pDib){ + strcpy(info.szLastError,"CxImage::Create can't allocate memory"); + return NULL; + } + + //clear the palette + RGBQUAD* pal=GetPalette(); + if (pal) memset(pal,0,GetPaletteSize()); + //Destroy the existing selection +#if CXIMAGE_SUPPORT_SELECTION + if (pSelection) SelectionDelete(); +#endif //CXIMAGE_SUPPORT_SELECTION + //Destroy the existing alpha channel +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha) AlphaDelete(); +#endif //CXIMAGE_SUPPORT_ALPHA + + // use our bitmap info structure to fill in first part of + // our DIB with the BITMAPINFOHEADER + BITMAPINFOHEADER* lpbi; + lpbi = (BITMAPINFOHEADER*)(pDib); + *lpbi = head; + + info.pImage=GetBits(); + + return pDib; //return handle to the DIB +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \return pointer to the image pixels. USE CAREFULLY + */ +BYTE* CxImage::GetBits(DWORD row) +{ + if (pDib){ + if (row) { + if (row<(DWORD)head.biHeight){ + return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize() + (info.dwEffWidth * row)); + } else { + return NULL; + } + } else { + return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize()); + } + } + return NULL; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \return the size in bytes of the internal pDib object + */ +long CxImage::GetSize() +{ + return head.biSize + head.biSizeImage + GetPaletteSize(); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Checks if the coordinates are inside the image + * \return true if x and y are both inside the image + */ +bool CxImage::IsInside(long x, long y) +{ + return (0<=y && y 0) bval = 255; + } + if (GetBpp() == 4){ + bval = (BYTE)(17*(0x0F & bval)); + } + + memset(info.pImage,bval,head.biSizeImage); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Transfers the image from an existing source image. The source becomes empty. + * \return true if everything is ok + */ +bool CxImage::Transfer(CxImage &from) +{ + if (!Destroy()) + return false; + + memcpy(&head,&from.head,sizeof(BITMAPINFOHEADER)); + memcpy(&info,&from.info,sizeof(CXIMAGEINFO)); + + pDib = from.pDib; + pSelection = from.pSelection; + pAlpha = from.pAlpha; + pLayers = from.pLayers; + + memset(&from.head,0,sizeof(BITMAPINFOHEADER)); + memset(&from.info,0,sizeof(CXIMAGEINFO)); + from.pDib = from.pSelection = from.pAlpha = NULL; + from.pLayers = NULL; + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * (this) points to the same pDib owned by (*from), the image remains in (*from) + * but (this) has the access to the pixels. Use carefully !!! + */ +void CxImage::Ghost(CxImage *from) +{ + if (from){ + memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER)); + memcpy(&info,&from->info,sizeof(CXIMAGEINFO)); + pDib = from->pDib; + pSelection = from->pSelection; + pAlpha = from->pAlpha; + pLayers = from->pLayers; + info.pGhost=from; + } +} +//////////////////////////////////////////////////////////////////////////////// +/** + * turns a 16 or 32 bit bitfield image into a RGB image + */ +void CxImage::Bitfield2RGB(BYTE *src, WORD redmask, WORD greenmask, WORD bluemask, BYTE bpp) +{ + switch (bpp){ + case 16: + { + DWORD ns[3]={0,0,0}; + // compute the number of shift for each mask + for (int i=0;i<16;i++){ + if ((redmask>>i)&0x01) ns[0]++; + if ((greenmask>>i)&0x01) ns[1]++; + if ((bluemask>>i)&0x01) ns[2]++; + } + ns[1]+=ns[0]; ns[2]+=ns[1]; ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8; + // dword aligned width for 16 bit image + long effwidth2=(((head.biWidth + 1) / 2) * 4); + WORD w; + long y2,y3,x2,x3; + BYTE *p=info.pImage; + // scan the buffer in reverse direction to avoid reallocations + for (long y=head.biHeight-1; y>=0; y--){ + y2=effwidth2*y; + y3=info.dwEffWidth*y; + for (long x=head.biWidth-1; x>=0; x--){ + x2 = 2*x+y2; + x3 = 3*x+y3; + w = (WORD)(src[x2]+256*src[1+x2]); + p[ x3]=(BYTE)((w & bluemask)<>ns[1]); + p[2+x3]=(BYTE)((w & redmask)>>ns[2]); + } + } + break; + } + case 32: + { + // dword aligned width for 32 bit image + long effwidth4 = head.biWidth * 4; + long y4,y3,x4,x3; + BYTE *p=info.pImage; + // scan the buffer in reverse direction to avoid reallocations + for (long y=head.biHeight-1; y>=0; y--){ + y4=effwidth4*y; + y3=info.dwEffWidth*y; + for (long x=head.biWidth-1; x>=0; x--){ + x4 = 4*x+y4; + x3 = 3*x+y3; + p[ x3]=src[ x4]; + p[1+x3]=src[1+x4]; + p[2+x3]=src[2+x4]; + } + } + } + + } + return; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Creates an image from a generic buffer + * \param pArray: source memory buffer + * \param dwWidth: image width + * \param dwHeight: image height + * \param dwBitsperpixel: can be 1,4,8,24,32 + * \param dwBytesperline: line alignment, in bytes, for a single row stored in pArray + * \param bFlipImage: tune this parameter if the image is upsidedown + * \return true if everything is ok + */ +bool CxImage::CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage) +{ + if (pArray==NULL) return false; + if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)|| + (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false; + + if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false; + + if (dwBitsperpixel<24) SetGrayPalette(); + +#if CXIMAGE_SUPPORT_ALPHA + if (dwBitsperpixel==32) AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + + BYTE *dst,*src; + + for (DWORD y = 0; yrgbRed,c1->rgbGreen,c1->rgbBlue); + int g2 = (int)RGB2GRAY(c2->rgbRed,c2->rgbGreen,c2->rgbBlue); + + return (g1-g2); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * simply calls "if (memblock) free(memblock);". + * Useful when calling Encode for a memory buffer, + * from a DLL compiled with different memory management options. + * CxImage::FreeMemory will use the same memory environment used by Encode. + */ +void CxImage::FreeMemory(void* memblock) +{ + if (memblock) + free(memblock); +} +//////////////////////////////////////////////////////////////////////////////// +//EOF diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximage.h ./win32/dependencies/cximage/ximage.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximage.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximage.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,648 @@ +/* + * File: ximage.h + * Purpose: General Purpose Image Class + */ +/* + -------------------------------------------------------------------------------- + + COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + + CxImage version 5.99c 17/Oct/2004 + + CxImage : Copyright (C) 2001 - 2004, Davide Pizzolato + + Original CImage and CImageIterator implementation are: + Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx) + + Covered code is provided under this license on an "as is" basis, without warranty + of any kind, either expressed or implied, including, without limitation, warranties + that the covered code is free of defects, merchantable, fit for a particular purpose + or non-infringing. The entire risk as to the quality and performance of the covered + code is with you. Should any covered code prove defective in any respect, you (not + the initial developer or any other contributor) assume the cost of any necessary + servicing, repair or correction. This disclaimer of warranty constitutes an essential + part of this license. No use of any covered code is authorized hereunder except under + this disclaimer. + + Permission is hereby granted to use, copy, modify, and distribute this + source code, or portions hereof, for any purpose, including commercial applications, + freely and without fee, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + -------------------------------------------------------------------------------- + + Other information: about CxImage, and the latest version, can be found at the + CxImage home page: http://www.xdp.it + + -------------------------------------------------------------------------------- + */ +#if !defined(__CXIMAGE_H) +#define __CXIMAGE_H + +#if _MSC_VER > 1000 +#pragma once +#endif + +///////////////////////////////////////////////////////////////////////////// +#include "xfile.h" +#include "xiofile.h" +#include "xmemfile.h" +#include "ximadef.h" // adjust some #define + +/* see "ximacfg.h" for CxImage configuration options */ + +///////////////////////////////////////////////////////////////////////////// +// CxImage formats enumerator +enum ENUM_CXIMAGE_FORMATS{ +CXIMAGE_FORMAT_UNKNOWN, +#if CXIMAGE_SUPPORT_BMP +CXIMAGE_FORMAT_BMP, +#endif +#if CXIMAGE_SUPPORT_GIF +CXIMAGE_FORMAT_GIF, +#endif +#if CXIMAGE_SUPPORT_JPG +CXIMAGE_FORMAT_JPG, +#endif +#if CXIMAGE_SUPPORT_PNG +CXIMAGE_FORMAT_PNG, +#endif +#if CXIMAGE_SUPPORT_MNG +CXIMAGE_FORMAT_MNG, +#endif +#if CXIMAGE_SUPPORT_ICO +CXIMAGE_FORMAT_ICO, +#endif +#if CXIMAGE_SUPPORT_TIF +CXIMAGE_FORMAT_TIF, +#endif +#if CXIMAGE_SUPPORT_TGA +CXIMAGE_FORMAT_TGA, +#endif +#if CXIMAGE_SUPPORT_PCX +CXIMAGE_FORMAT_PCX, +#endif +#if CXIMAGE_SUPPORT_WBMP +CXIMAGE_FORMAT_WBMP, +#endif +#if CXIMAGE_SUPPORT_WMF +CXIMAGE_FORMAT_WMF, +#endif +#if CXIMAGE_SUPPORT_J2K +CXIMAGE_FORMAT_J2K, +#endif +#if CXIMAGE_SUPPORT_JBG +CXIMAGE_FORMAT_JBG, +#endif +#if CXIMAGE_SUPPORT_JP2 +CXIMAGE_FORMAT_JP2, +#endif +#if CXIMAGE_SUPPORT_JPC +CXIMAGE_FORMAT_JPC, +#endif +#if CXIMAGE_SUPPORT_PGX +CXIMAGE_FORMAT_PGX, +#endif +#if CXIMAGE_SUPPORT_PNM +CXIMAGE_FORMAT_PNM, +#endif +#if CXIMAGE_SUPPORT_RAS +CXIMAGE_FORMAT_RAS, +#endif +CMAX_IMAGE_FORMATS +}; + +///////////////////////////////////////////////////////////////////////////// +// CxImage class +///////////////////////////////////////////////////////////////////////////// +class DLL_EXP CxImage +{ +//extensible information collector +typedef struct tagCxImageInfo { + DWORD dwEffWidth; ///< DWORD aligned scan line width + BYTE* pImage; ///< THE IMAGE BITS + CxImage* pGhost; ///< if this is a ghost, pGhost points to the body + CxImage* pParent; ///< if this is a layer, pParent points to the body + DWORD dwType; ///< original image format + char szLastError[256]; ///< debugging + long nProgress; ///< monitor + long nEscape; ///< escape + long nBkgndIndex; ///< used for GIF, PNG, MNG + RGBQUAD nBkgndColor; ///< used for RGB transparency + BYTE nQuality; ///< used for JPEG + BYTE nJpegScale; ///< used for JPEG [ignacio] + long nFrame; ///< used for TIF, GIF, MNG : actual frame + long nNumFrames; ///< used for TIF, GIF, MNG : total number of frames + DWORD dwFrameDelay; ///< used for GIF, MNG + long xDPI; ///< horizontal resolution + long yDPI; ///< vertical resolution + RECT rSelectionBox; ///< bounding rectangle + BYTE nAlphaMax; ///< max opacity (fade) + bool bAlphaPaletteEnabled; ///< true if alpha values in the palette are enabled. + bool bEnabled; ///< enables the painting functions + long xOffset; + long yOffset; + DWORD dwCodecOpt[CMAX_IMAGE_FORMATS]; ///< for GIF, TIF : 0=def.1=unc,2=fax3,3=fax4,4=pack,5=jpg + RGBQUAD last_c; ///< for GetNearestIndex optimization + BYTE last_c_index; + bool last_c_isvalid; + long nNumLayers; + DWORD dwFlags; ///< 0x??00000 = reserved, 0x00??0000 = blend mode, 0x0000???? = layer id - user flags + +} CXIMAGEINFO; + +public: + //public structures +struct rgb_color { BYTE r,g,b; }; + +#if CXIMAGE_SUPPORT_WINDOWS +// text placement data +// members must be initialized with the InitTextInfo(&this) function. +typedef struct tagCxTextInfo +{ + TCHAR text[4096]; ///< text (char -> TCHAR for UNICODE [Cesar M]) + LOGFONT lfont; ///< font and codepage data + COLORREF fcolor; ///< foreground color + long align; ///< DT_CENTER, DT_RIGHT, DT_LEFT aligment for multiline text + BYTE opaque; ///< text has background or hasn't. Default is true. + ///< data for background (ignored if .opaque==FALSE) + COLORREF bcolor; ///< background color + float b_opacity; ///< opacity value for background between 0.0-1.0 Default is 0. (opaque) + BYTE b_outline; ///< outline width for background (zero: no outline) + BYTE b_round; ///< rounding radius for background rectangle. % of the height, between 0-50. Default is 10. + ///< (backgr. always has a frame: width = 3 pixel + 10% of height by default.) +} CXTEXTINFO; +#endif + +public: +/** \addtogroup Constructors */ //@{ + CxImage(DWORD imagetype = 0); + CxImage(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0); + CxImage(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true); + CxImage(const TCHAR * filename, DWORD imagetype); // For UNICODE support: char -> TCHAR + CxImage(FILE * stream, DWORD imagetype); + CxImage(CxFile * stream, DWORD imagetype); + CxImage(BYTE * buffer, DWORD size, DWORD imagetype); + virtual ~CxImage() { Destroy(); }; + CxImage& operator = (const CxImage&); +//@} + +/** \addtogroup Initialization */ //@{ + void* Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0); + bool Destroy(); + void Clear(BYTE bval=0); + void Copy(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true); + bool Transfer(CxImage &from); + bool CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage); + bool CreateFromMatrix(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage); + void FreeMemory(void* memblock); +//@} + +/** \addtogroup Attributes */ //@{ + long GetSize(); + BYTE* GetBits(DWORD row = 0); + BYTE GetColorType(); + void* GetDIB() const; + DWORD GetHeight() const; + DWORD GetWidth() const; + DWORD GetEffWidth() const; + DWORD GetNumColors() const; + WORD GetBpp() const; + DWORD GetType() const; + const char* GetLastError(); + const TCHAR* GetVersion(); + const float GetVersionNumber(); + + DWORD GetFrameDelay() const; + void SetFrameDelay(DWORD d); + + void GetOffset(long *x,long *y); + void SetOffset(long x,long y); + + BYTE GetJpegQuality() const; + void SetJpegQuality(BYTE q); + + BYTE GetJpegScale() const; + void SetJpegScale(BYTE q); + + long GetXDPI() const; + long GetYDPI() const; + void SetXDPI(long dpi); + void SetYDPI(long dpi); + + DWORD GetClrImportant() const; + void SetClrImportant(DWORD ncolors = 0); + + long GetProgress() const; + long GetEscape() const; + void SetProgress(long p); + void SetEscape(long i); + + long GetTransIndex() const; + RGBQUAD GetTransColor(); + void SetTransIndex(long idx); + void SetTransColor(RGBQUAD rgb); + bool IsTransparent() const; + + DWORD GetCodecOption(DWORD imagetype = 0); + bool SetCodecOption(DWORD opt, DWORD imagetype = 0); + + DWORD GetFlags() const; + void SetFlags(DWORD flags, bool bLockReservedFlags = true); + + //void* GetUserData() const {return info.pUserData;} + //void SetUserData(void* pUserData) {info.pUserData = pUserData;} +//@} + +/** \addtogroup Palette + * These functions have no effects on RGB images and in this case the returned value is always 0. + * @{ */ + bool IsGrayScale(); + bool IsIndexed() const; + bool IsSamePalette(CxImage &img, bool bCheckAlpha = true); + DWORD GetPaletteSize(); + RGBQUAD* GetPalette() const; + RGBQUAD GetPaletteColor(BYTE idx); + bool GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b); + BYTE GetNearestIndex(RGBQUAD c); + void BlendPalette(COLORREF cr,long perc); + void SetGrayPalette(); + void SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b); + void SetPalette(RGBQUAD* pPal,DWORD nColors=256); + void SetPalette(rgb_color *rgb,DWORD nColors=256); + void SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha=0); + void SetPaletteColor(BYTE idx, RGBQUAD c); + void SetPaletteColor(BYTE idx, COLORREF cr); + void SwapIndex(BYTE idx1, BYTE idx2); + void SetStdPalette(); +//@} + +/** \addtogroup Pixel */ //@{ + bool IsInside(long x, long y); + bool IsTransparent(long x,long y); + RGBQUAD GetPixelColor(long x,long y, bool bGetAlpha = true); + BYTE GetPixelIndex(long x,long y); + BYTE GetPixelGray(long x, long y); + void SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha = false); + void SetPixelColor(long x,long y,COLORREF cr); + void SetPixelIndex(long x,long y,BYTE i); + void DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha=false); + void DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr); + void BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha = false); +//@} + +protected: +/** \addtogroup Protected */ //@{ + BYTE BlindGetPixelIndex(const long x,const long y); + RGBQUAD BlindGetPixelColor(const long x,const long y); + void *BlindGetPixelPointer(const long x,const long y); +//@} + +public: + +#if CXIMAGE_SUPPORT_INTERPOLATION +/** \addtogroup Interpolation */ //@{ + //overflow methods: + enum OverflowMethod { + OM_COLOR=1, + OM_BACKGROUND=2, + OM_TRANSPARENT=3, + OM_WRAP=4, + OM_REPEAT=5, + OM_MIRROR=6 + }; + void OverflowCoordinates(float &x, float &y, OverflowMethod const ofMethod); + void OverflowCoordinates(long &x, long &y, OverflowMethod const ofMethod); + RGBQUAD GetPixelColorWithOverflow(long x, long y, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0); + //interpolation methods: + enum InterpolationMethod { + IM_NEAREST_NEIGHBOUR=1, + IM_BILINEAR =2, + IM_BSPLINE =3, + IM_BICUBIC =4, + IM_BICUBIC2 =5, + IM_LANCZOS =6, + IM_BOX =7, + IM_HERMITE =8, + IM_HAMMING =9, + IM_SINC =10, + IM_BLACKMAN =11, + IM_BESSEL =12, + IM_GAUSSIAN =13, + IM_QUADRATIC =14, + IM_MITCHELL =15, + IM_CATROM =16 + }; + RGBQUAD GetPixelColorInterpolated(float x,float y, InterpolationMethod const inMethod=IM_BILINEAR, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0); + RGBQUAD GetAreaColorInterpolated(float const xc, float const yc, float const w, float const h, InterpolationMethod const inMethod, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0); +//@} + +protected: +/** \addtogroup Protected */ //@{ + void AddAveragingCont(RGBQUAD const &color, float const surf, float &rr, float &gg, float &bb, float &aa); +//@} + +/** \addtogroup Kernels */ //@{ +public: + static float KernelBSpline(const float x); + static float KernelLinear(const float t); + static float KernelCubic(const float t); + static float KernelGeneralizedCubic(const float t, const float a=-1); + static float KernelLanczosSinc(const float t, const float r = 3); + static float KernelBox(const float x); + static float KernelHermite(const float x); + static float KernelHamming(const float x); + static float KernelSinc(const float x); + static float KernelBlackman(const float x); + static float KernelBessel_J1(const float x); + static float KernelBessel_P1(const float x); + static float KernelBessel_Q1(const float x); + static float KernelBessel_Order1(float x); + static float KernelBessel(const float x); + static float KernelGaussian(const float x); + static float KernelQuadratic(const float x); + static float KernelMitchell(const float x); + static float KernelCatrom(const float x); +//@} +#endif //CXIMAGE_SUPPORT_INTERPOLATION + +/** \addtogroup Painting */ //@{ +#if CXIMAGE_SUPPORT_WINCE + long Blt(HDC pDC, long x=0, long y=0); +#endif +#if CXIMAGE_SUPPORT_WINDOWS + HBITMAP MakeBitmap(HDC hdc = NULL); + HANDLE CopyToHandle(); + bool CreateFromHANDLE(HANDLE hMem); //Windows objects (clipboard) + bool CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal=0); //Windows resource + bool CreateFromHICON(HICON hico); + long Draw(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1, RECT* pClipRect = 0, bool bSmooth = false); + long Draw(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false); + long Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD dwRop = SRCCOPY); + long Stretch(HDC hdc, const RECT& rect, DWORD dwRop = SRCCOPY); + long Tile(HDC hdc, RECT *rc); + long Draw2(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1); + long Draw2(HDC hdc, const RECT& rect); + //long DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize=0, long lWeight=400, BYTE bItalic=0, BYTE bUnderline=0, bool bSetAlpha=false); + long DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize=0, long lWeight=400, BYTE bItalic=0, BYTE bUnderline=0, bool bSetAlpha=false); + // extensions + long DrawStringEx(HDC hdc, long x, long y, CXTEXTINFO *pTextType, bool bSetAlpha=false ); + void InitTextInfo( CXTEXTINFO *txt ); +#endif //CXIMAGE_SUPPORT_WINDOWS +//@} + + // file operations +#if CXIMAGE_SUPPORT_DECODE +/** \addtogroup Decode */ //@{ +#ifdef WIN32 + //bool Load(LPCWSTR filename, DWORD imagetype=0); + bool LoadResource(HRSRC hRes, DWORD imagetype, HMODULE hModule=NULL); +#endif + // For UNICODE support: char -> TCHAR + bool Load(const TCHAR* filename, DWORD imagetype=0); + //bool Load(const char * filename, DWORD imagetype=0); + bool Decode(FILE * hFile, DWORD imagetype); + bool Decode(CxFile * hFile, DWORD imagetype); + bool Decode(BYTE * buffer, DWORD size, DWORD imagetype); +//@} +#endif //CXIMAGE_SUPPORT_DECODE + +#if CXIMAGE_SUPPORT_ENCODE +protected: +/** \addtogroup Protected */ //@{ + bool EncodeSafeCheck(CxFile *hFile); +//@} + +public: +/** \addtogroup Encode */ //@{ +#ifdef WIN32 + //bool Save(LPCWSTR filename, DWORD imagetype=0); +#endif + // For UNICODE support: char -> TCHAR + bool Save(const TCHAR* filename, DWORD imagetype); + //bool Save(const char * filename, DWORD imagetype=0); + bool Encode(FILE * hFile, DWORD imagetype); + bool Encode(CxFile * hFile, DWORD imagetype); + bool Encode(CxFile * hFile, CxImage ** pImages, int pagecount, DWORD imagetype); + bool Encode(FILE *hFile, CxImage ** pImages, int pagecount, DWORD imagetype); + bool Encode(BYTE * &buffer, long &size, DWORD imagetype); + + bool Encode2RGBA(CxFile *hFile); + bool Encode2RGBA(BYTE * &buffer, long &size); +//@} +#endif //CXIMAGE_SUPPORT_ENCODE + +/** \addtogroup Attributes */ //@{ + //misc. + bool IsValid() const; + bool IsEnabled() const; + void Enable(bool enable=true); + + // frame operations + long GetNumFrames() const; + long GetFrame() const; + void SetFrame(long nFrame); +//@} + +#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS +/** \addtogroup BasicTransformations */ //@{ + bool GrayScale(); + bool Flip(); + bool Mirror(); + bool Negative(); + bool RotateLeft(CxImage* iDst = NULL); + bool RotateRight(CxImage* iDst = NULL); +//@} +#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS + +#if CXIMAGE_SUPPORT_TRANSFORMATION +/** \addtogroup Transformations */ //@{ + // image operations + bool Rotate(float angle, CxImage* iDst = NULL); + bool Rotate2(float angle, CxImage *iDst = NULL, InterpolationMethod inMethod=IM_BILINEAR, + OverflowMethod ofMethod=OM_BACKGROUND, RGBQUAD *replColor=0, + bool const optimizeRightAngles=true, bool const bKeepOriginalSize=false); + bool Rotate180(CxImage* iDst = NULL); + bool Resample(long newx, long newy, int mode = 1, CxImage* iDst = NULL); + bool Resample2(long newx, long newy, InterpolationMethod const inMethod=IM_BICUBIC2, + OverflowMethod const ofMethod=OM_REPEAT, CxImage* const iDst = NULL, + bool const disableAveraging=false); + bool DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal = 0, DWORD clrimportant = 0); + bool IncreaseBpp(DWORD nbit); + bool Dither(long method = 0); + bool Crop(long left, long top, long right, long bottom, CxImage* iDst = NULL); + bool Crop(const RECT& rect, CxImage* iDst = NULL); + bool CropRotatedRectangle( long topx, long topy, long width, long height, float angle, CxImage* iDst = NULL); + bool Skew(float xgain, float ygain, long xpivot=0, long ypivot=0, bool bEnableInterpolation = false); + bool Expand(long left, long top, long right, long bottom, RGBQUAD canvascolor, CxImage* iDst = 0); + bool Expand(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst = 0); + bool Thumbnail(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst = 0); + bool CircleTransform(int type,long rmax=0,float Koeff=1.0f); + bool RedEyeRemove(); + bool QIShrink(long newx, long newy, CxImage* const iDst = NULL); +//@} +#endif //CXIMAGE_SUPPORT_TRANSFORMATION + +#if CXIMAGE_SUPPORT_DSP +/** \addtogroup DSP */ //@{ + bool Contour(); + bool HistogramStretch(long method = 0); + bool HistogramEqualize(); + bool HistogramNormalize(); + bool HistogramRoot(); + bool HistogramLog(); + long Histogram(long* red, long* green = 0, long* blue = 0, long* gray = 0, long colorspace = 0); + bool Jitter(long radius=2); + bool Repair(float radius = 0.25f, long niterations = 1, long colorspace = 0); + bool Combine(CxImage* r,CxImage* g,CxImage* b,CxImage* a, long colorspace = 0); + bool FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag, long direction = 1, bool bForceFFT = true, bool bMagnitude = true); + bool Noise(long level); + bool Median(long Ksize=3); + bool Gamma(float gamma); + bool ShiftRGB(long r, long g, long b); + bool Threshold(BYTE level); + bool Colorize(BYTE hue, BYTE sat, float blend = 1.0f); + bool Light(long brightness, long contrast = 0); + float Mean(); + bool Filter(long* kernel, long Ksize, long Kfactor, long Koffset); + bool Erode(long Ksize=2); + bool Dilate(long Ksize=2); + bool Edge(long Ksize=2); + void HuePalette(float correction=1); + enum ImageOpType { OpAdd, OpAnd, OpXor, OpOr, OpMask, OpSrcCopy, OpDstCopy, OpSub, OpSrcBlend, OpScreen }; + void Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset = 0, long lYOffset = 0, bool bMixAlpha = false); + void MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset); + bool UnsharpMask(float radius = 5.0, float amount = 0.5, int threshold = 0); + bool Lut(BYTE* pLut); + bool Lut(BYTE* pLutR, BYTE* pLutG, BYTE* pLutB, BYTE* pLutA = 0); +//@} + +protected: +/** \addtogroup Protected */ //@{ + bool IsPowerof2(long x); + bool FFT(int dir,int m,double *x,double *y); + bool DFT(int dir,long m,double *x1,double *y1,double *x2,double *y2); + bool RepairChannel(CxImage *ch, float radius); + // + int gen_convolve_matrix (float radius, float **cmatrix_p); + float* gen_lookup_table (float *cmatrix, int cmatrix_length); + void blur_line (float *ctable, float *cmatrix, int cmatrix_length, BYTE* cur_col, BYTE* dest_col, int y, long bytes); +//@} + +public: +/** \addtogroup ColorSpace */ //@{ + bool SplitRGB(CxImage* r,CxImage* g,CxImage* b); + bool SplitYUV(CxImage* y,CxImage* u,CxImage* v); + bool SplitHSL(CxImage* h,CxImage* s,CxImage* l); + bool SplitYIQ(CxImage* y,CxImage* i,CxImage* q); + bool SplitXYZ(CxImage* x,CxImage* y,CxImage* z); + bool SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k); + static RGBQUAD HSLtoRGB(COLORREF cHSLColor); + static RGBQUAD RGBtoHSL(RGBQUAD lRGBColor); + static RGBQUAD HSLtoRGB(RGBQUAD lHSLColor); + static RGBQUAD YUVtoRGB(RGBQUAD lYUVColor); + static RGBQUAD RGBtoYUV(RGBQUAD lRGBColor); + static RGBQUAD YIQtoRGB(RGBQUAD lYIQColor); + static RGBQUAD RGBtoYIQ(RGBQUAD lRGBColor); + static RGBQUAD XYZtoRGB(RGBQUAD lXYZColor); + static RGBQUAD RGBtoXYZ(RGBQUAD lRGBColor); +#endif //CXIMAGE_SUPPORT_DSP + static RGBQUAD RGBtoRGBQUAD(COLORREF cr); + static COLORREF RGBQUADtoRGB (RGBQUAD c); +//@} + +#if CXIMAGE_SUPPORT_SELECTION +/** \addtogroup Selection */ //@{ + bool SelectionClear(); + bool SelectionCreate(); + bool SelectionDelete(); + bool SelectionInvert(); + bool SelectionAddRect(RECT r); + bool SelectionAddEllipse(RECT r); + bool SelectionAddPolygon(POINT *points, long npoints); + bool SelectionAddColor(RGBQUAD c); + bool SelectionAddPixel(int x, int y); + bool SelectionCopy(CxImage &from); + bool SelectionIsInside(long x, long y); + bool SelectionIsValid(); + void SelectionGetBox(RECT& r); + bool SelectionToHRGN(HRGN& region); + bool SelectionSplit(CxImage *dest); +//@} +#endif //CXIMAGE_SUPPORT_SELECTION + +#if CXIMAGE_SUPPORT_ALPHA +/** \addtogroup Alpha */ //@{ + void AlphaClear(); + void AlphaCreate(); + void AlphaDelete(); + void AlphaInvert(); + bool AlphaMirror(); + bool AlphaFlip(); + bool AlphaCopy(CxImage &from); + bool AlphaSplit(CxImage *dest); + void AlphaStrip(); + void AlphaSet(BYTE level); + bool AlphaSet(CxImage &from); + void AlphaSet(const long x,const long y,const BYTE level); + BYTE AlphaGet(const long x,const long y); + BYTE AlphaGetMax() const; + void AlphaSetMax(BYTE nAlphaMax); + bool AlphaIsValid(); + BYTE* AlphaGetPointer(const long x = 0,const long y = 0); + + void AlphaPaletteClear(); + void AlphaPaletteEnable(bool enable=true); + bool AlphaPaletteIsEnabled(); + bool AlphaPaletteIsValid(); + bool AlphaPaletteSplit(CxImage *dest); +//@} + +protected: +/** \addtogroup Protected */ //@{ + BYTE BlindAlphaGet(const long x,const long y); +//@} +#endif //CXIMAGE_SUPPORT_ALPHA + +public: +#if CXIMAGE_SUPPORT_LAYERS +/** \addtogroup Layers */ //@{ + bool LayerCreate(long position = -1); + bool LayerDelete(long position = -1); + void LayerDeleteAll(); + CxImage* GetLayer(long position); + CxImage* GetParent() const; + long GetNumLayers() const; +//@} +#endif //CXIMAGE_SUPPORT_LAYERS + +protected: +/** \addtogroup Protected */ //@{ + void Startup(DWORD imagetype = 0); + void CopyInfo(const CxImage &src); + void Ghost(CxImage *src); + void RGBtoBGR(BYTE *buffer, int length); + static float HueToRGB(float n1,float n2, float hue); + void Bitfield2RGB(BYTE *src, WORD redmask, WORD greenmask, WORD bluemask, BYTE bpp); + static int CompareColors(const void *elem1, const void *elem2); + + void* pDib; //contains the header, the palette, the pixels + BITMAPINFOHEADER head; //standard header + CXIMAGEINFO info; //extended information + BYTE* pSelection; //selected region + BYTE* pAlpha; //alpha channel + CxImage** pLayers; //generic layers +//@} +}; + +//////////////////////////////////////////////////////////////////////////// +#endif // !defined(__CXIMAGE_H) diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximagif.cpp ./win32/dependencies/cximage/ximagif.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximagif.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximagif.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,1564 @@ +/* + * File: ximagif.cpp + * Purpose: Platform Independent GIF Image Class Loader and Writer + * 07/Aug/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximagif.h" + +#if CXIMAGE_SUPPORT_GIF + +#include "ximaiter.h" + +#if CXIMAGE_SUPPORT_WINCE + #define assert(s) +#else + #include +#endif + +//////////////////////////////////////////////////////////////////////////////// +bool CxImageGIF::Decode(CxFile *fp) +{ + /* AD - for transparency */ + struct_dscgif dscgif; + struct_image image; + struct_TabCol TabCol; + + if (fp == NULL) return false; + + fp->Read(&dscgif,/*sizeof(dscgif)*/13,1); + //if (strncmp(dscgif.header,"GIF8",3)!=0) { + if (strncmp(dscgif.header,"GIF8",4)!=0) return FALSE; + + if (info.nEscape == -1) { + // Return output dimensions only + head.biWidth = dscgif.scrwidth; + head.biHeight = dscgif.scrheight; + return true; + } + + /* AD - for interlace */ + TabCol.sogct = (short)(1 << ((dscgif.pflds & 0x07)+1)); + TabCol.colres = (short)(((dscgif.pflds & 0x70) >> 3) + 1); + + // assume that the image is a truecolor-gif if + // 1) no global color map found + // 2) (image.w, image.h) of the 1st image != (dscgif.scrwidth, dscgif.scrheight) + long bTrueColor=0; + CxImage* imaRGB=NULL; + + // Global colour map? + if (dscgif.pflds & 0x80) + fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1); + else + bTrueColor++; //first chance for a truecolor gif + + long first_transparent_index; + + int iImage = 0; + info.nNumFrames=get_num_frames(fp,&TabCol,&dscgif); + + if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)) return false; + + //it cannot be a true color GIF with only one frame + if (info.nNumFrames == 1) + bTrueColor=0; + + char ch; + bool bPreviousWasNull = true; + int prevdispmeth = 0; + + for (BOOL bContinue = TRUE; bContinue; ) + { + if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;} + + if (info.nEscape > 0) return false; // - cancel decoding + if (bPreviousWasNull || ch==0) + { + switch (ch) + { + case '!': // extension + { + bContinue = DecodeExtension(fp); + break; + } + case ',': // image + { + assert(sizeof(image) == 9); + fp->Read(&image,sizeof(image),1); + //avoid byte order problems with Solaris + BYTE *byteData = (BYTE *) & image; + image.l = byteData[0]+byteData[1]*256; + image.t = byteData[2]+byteData[3]*256; + image.w = byteData[4]+byteData[5]*256; + image.h = byteData[6]+byteData[7]*256; + + if (((image.l + image.w) > dscgif.scrwidth)||((image.t + image.h) > dscgif.scrheight)) + break; + + // check if it could be a truecolor gif + if ((iImage==0) && (image.w != dscgif.scrwidth) && (image.h != dscgif.scrheight)) + bTrueColor++; + + // Local colour map? + if (image.pf & 0x80) { + TabCol.sogct = (short)(1 << ((image.pf & 0x07) +1)); + assert(3 == sizeof(struct rgb_color)); + fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1); + //log << "Local colour map" << endl; + } + + int bpp; // select the correct bit per pixel value + if (TabCol.sogct <= 2) bpp = 1; + else if (TabCol.sogct <= 16) bpp = 4; + else bpp = 8; + + CxImageGIF backimage; + backimage.CopyInfo(*this); + if (iImage==0){ + //first frame: build image background + backimage.Create(dscgif.scrwidth, dscgif.scrheight, bpp, CXIMAGE_FORMAT_GIF); + first_transparent_index = info.nBkgndIndex; + backimage.Clear((BYTE)gifgce.transpcolindex); + } else { + //generic frame: handle disposal method from previous one + /*Values : 0 - No disposal specified. The decoder is + not required to take any action. + 1 - Do not dispose. The graphic is to be left + in place. + 2 - Restore to background color. The area used by the + graphic must be restored to the background color. + 3 - Restore to previous. The decoder is required to + restore the area overwritten by the graphic with + what was there prior to rendering the graphic. + */ + backimage.Copy(*this); + if (prevdispmeth==2){ + backimage.Clear((BYTE)first_transparent_index); + } + } + + //active frame + Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF); + + if ((image.pf & 0x80) || (dscgif.pflds & 0x80)) { + unsigned char r[256], g[256], b[256]; + int i, has_white = 0; + + for (i=0; i < TabCol.sogct; i++) { + r[i] = TabCol.paleta[i].r; + g[i] = TabCol.paleta[i].g; + b[i] = TabCol.paleta[i].b; + + if (RGB(r[i],g[i],b[i]) == 0xFFFFFF) has_white = 1; + } + + // Force transparency colour white... + //if (0) if (info.nBkgndIndex != -1) + // r[info.nBkgndIndex] = g[info.nBkgndIndex] = b[info.nBkgndIndex] = 255; + // Fill in with white // AD + if (info.nBkgndIndex != -1) { + while (i < 256) { + has_white = 1; + r[i] = g[i] = b[i] = 255; + i++; + } + } + + // Force last colour to white... // AD + //if ((info.nBkgndIndex != -1) && !has_white) { + // r[255] = g[255] = b[255] = 255; + //} + + SetPalette((info.nBkgndIndex != -1 ? 256 : TabCol.sogct), r, g, b); + } + + CImageIterator* iter = new CImageIterator(this); + iter->Upset(); + int badcode=0; + ibf = GIFBUFTAM+1; + + interlaced = image.pf & 0x40; + iheight = image.h; + istep = 8; + iypos = 0; + ipass = 0; + + long pos_start = fp->Tell(); + //if (interlaced) log << "Interlaced" << endl; + decoder(fp, iter, image.w, badcode); + delete iter; + + if (info.nEscape) return false; // - cancel decoding + + if (bTrueColor<2 ){ //standard GIF: mix frame with background + backimage.GifMix(*this,image); + backimage.SetTransIndex(first_transparent_index); + backimage.SetPalette(GetPalette()); + Transfer(backimage); + } else { //it's a truecolor gif! + //force full image decoding + info.nFrame=info.nNumFrames-1; + //build the RGB image + if (imaRGB==NULL) imaRGB = new CxImage(dscgif.scrwidth,dscgif.scrheight,24,CXIMAGE_FORMAT_GIF); + //copy the partial image into the full RGB image + for(long y=0;ySetPixelColor(x+image.l,dscgif.scrheight-1-image.t-y,GetPixelColor(x,image.h-y-1)); + } + } + } + + prevdispmeth = gifgce.dispmeth; + + //restore the correct position in the file for the next image + if (badcode){ + seek_next_image(fp,pos_start); + } else { + fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR); + } + + if (info.nFrame==iImage) bContinue=false; else iImage++; + + break; + } + case ';': //terminator + bContinue=false; + break; + default: + bPreviousWasNull = (ch==0); + break; + } + } + } + + if (bTrueColor>=2 && imaRGB){ + if (gifgce.transpcolflag){ + imaRGB->SetTransColor(GetPaletteColor((BYTE)info.nBkgndIndex)); + imaRGB->SetTransIndex(0); + } + Transfer(*imaRGB); + } + delete imaRGB; + + return true; + +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageGIF::DecodeExtension(CxFile *fp) +{ + bool bContinue; + unsigned char count; + unsigned char fc; + + bContinue = (1 == fp->Read(&fc, sizeof(fc), 1)); + if (bContinue) { + /* AD - for transparency */ + if (fc == 0xF9) { + bContinue = (1 == fp->Read(&count, sizeof(count), 1)); + if (bContinue) { + assert(sizeof(gifgce) == 4); + bContinue = (count == fp->Read(&gifgce, 1, sizeof(gifgce))); + if (bContinue) { + if (gifgce.transpcolflag) info.nBkgndIndex = gifgce.transpcolindex; + info.dwFrameDelay = gifgce.delaytime; + m_dispmeth = gifgce.dispmeth; + } } } + + if (fc == 0xFE) { // Comment block + bContinue = (1 == fp->Read(&count, sizeof(count), 1)); + if (bContinue) { + bContinue = (1 == fp->Read(m_comment, count, 1)); + m_comment[count]='\0'; + } } + + if (fc == 0xFF) { // Application Extension block + bContinue = (1 == fp->Read(&count, sizeof(count), 1)); + if (bContinue) { + bContinue = (count==11); + if (bContinue){ + char AppID[11]; + bContinue = (1 == fp->Read(AppID, count, 1)); + if (bContinue) { + bContinue = (1 == fp->Read(&count, sizeof(count), 1)); + if (bContinue) { + BYTE* dati = (BYTE*)malloc(count); + bContinue = (dati!=NULL); + if (bContinue){ + bContinue = (1 == fp->Read(dati, count, 1)); + if (count>2){ + m_loops = dati[1]+256*dati[2]; + } + } + free(dati); + } } } } } + + while (bContinue && fp->Read(&count, sizeof(count), 1) && count) { + //log << "Skipping " << count << " bytes" << endl; + fp->Seek(count, SEEK_CUR); + } + } + return bContinue; + +} + + +// - This external (machine specific) function is expected to return +// either the next BYTE from the GIF file, or a negative error number. +int CxImageGIF::get_byte(CxFile* file) +{ + if (ibf>=GIFBUFTAM){ + // FW 06/02/98 >>> + ibfmax = file->Read( buf , 1 , GIFBUFTAM) ; + if( ibfmax < GIFBUFTAM ) buf[ ibfmax ] = 255 ; + // FW 06/02/98 <<< + ibf = 0; + } + if (ibf>=ibfmax) return -1; // avoid overflows + return buf[ibf++]; +} +//////////////////////////////////////////////////////////////////////////////// +/* - This function takes a full line of pixels (one BYTE per pixel) and + * displays them (or does whatever your program wants with them...). It + * should return zero, or negative if an error or some other event occurs + * which would require aborting the decode process... Note that the length + * passed will almost always be equal to the line length passed to the + * decoder function, with the sole exception occurring when an ending code + * occurs in an odd place in the GIF file... In any case, linelen will be + * equal to the number of pixels passed... +*/ +int CxImageGIF::out_line(CImageIterator* iter, unsigned char *pixels, int linelen) +{ + // for 1 & 4 bpp images, the pixels are compressed + if (head.biBitCount < 8){ + for(long x=0;x> 3); + if (head.biBitCount==4){ + pos = (BYTE)(4*(1-x%2)); + *iDst &= ~(0x0F<SetY(iheight-iypos-1); + iter->SetRow(pixels, linelen); + + if ((iypos += istep) >= iheight) { + do { + if (ipass++ > 0) istep /= 2; + iypos = istep / 2; + } + while (iypos > iheight); + } + return 0; + } else { + if (iter->ItOK()) { + iter->SetRow(pixels, linelen); + (void)iter->PrevRow(); + return 0; + } else { + // puts("chafeo"); + return -1; + } + } +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +// SaveFile - writes GIF87a gif file +// Randy Spann 6/15/97 +// R.Spann@ConnRiver.net +bool CxImageGIF::Encode(CxFile * fp) +{ + if (EncodeSafeCheck(fp)) return false; + + if(head.biBitCount > 8) { + //strcpy(info.szLastError,"GIF Images must be 8 bit or less"); + //return FALSE; + return EncodeRGB(fp); + } + + EncodeHeader(fp); + + EncodeExtension(fp); + + EncodeComment(fp); + + EncodeBody(fp); + + fp->PutC(';'); // Write the GIF file terminator + + return true; // done! +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageGIF::Encode(CxFile * fp, CxImage ** pImages, int pagecount, bool bLocalColorMap) +{ + try{ + if (fp==NULL) throw "invalid file pointer"; + if (pImages==NULL || pagecount==0 || pImages[0]==NULL) throw "multipage GIF, no images!"; + + CxImageGIF ghost; + + //write the first image + ghost.Ghost(pImages[0]); + ghost.EncodeHeader(fp); + + if (m_loops!=1){ + ghost.SetLoops(max(0,m_loops-1)); + ghost.EncodeLoopExtension(fp); + } + + ghost.SetDisposalMethod(GetDisposalMethod()); + ghost.EncodeExtension(fp); + + EncodeComment(fp); + + ghost.EncodeBody(fp); + + for (int i=2; i<=pagecount; i++){ + if (pImages[i-1]==NULL) throw "Bad image pointer"; + ghost.Ghost(pImages[i-1]); + + ghost.SetDisposalMethod(GetDisposalMethod()); + ghost.EncodeExtension(fp); + + ghost.EncodeBody(fp,bLocalColorMap); + } + + fp->PutC(';'); // Write the GIF file terminator + + } catch (char *message) { + strncpy(info.szLastError,message,255); + return false; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::EncodeHeader(CxFile *fp) +{ + fp->Write("GIF89a",1,6); //GIF Header + + Putword(head.biWidth,fp); //Logical screen descriptor + Putword(head.biHeight,fp); + + BYTE Flags; + if (head.biClrUsed==0){ + Flags=0x11; + } else { + Flags = 0x80; + Flags |=(head.biBitCount - 1) << 5; + Flags |=(head.biBitCount - 1); + } + + fp->PutC(Flags); //GIF "packed fields" + fp->PutC(0); //GIF "BackGround" + fp->PutC(0); //GIF "pixel aspect ratio" + + if (head.biClrUsed!=0){ + RGBQUAD* pPal = GetPalette(); + for(DWORD i=0; iPutC(pPal[i].rgbRed); + fp->PutC(pPal[i].rgbGreen); + fp->PutC(pPal[i].rgbBlue); + } + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::EncodeExtension(CxFile *fp) +{ + // TRK BEGIN : transparency + fp->PutC('!'); + fp->PutC(TRANSPARENCY_CODE); + + gifgce.transpcolflag = (info.nBkgndIndex != -1) ? 1 : 0; + gifgce.userinputflag = 0; + gifgce.dispmeth = m_dispmeth; + gifgce.res = 0; + gifgce.delaytime = (WORD)info.dwFrameDelay; + gifgce.transpcolindex = (BYTE)info.nBkgndIndex; + fp->PutC(sizeof(gifgce)); + fp->Write(&gifgce, sizeof(gifgce), 1); + fp->PutC(0); + // TRK END +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::EncodeLoopExtension(CxFile *fp) +{ + fp->PutC('!'); //byte 1 : 33 (hex 0x21) GIF Extension code + fp->PutC(255); //byte 2 : 255 (hex 0xFF) Application Extension Label + fp->PutC(11); //byte 3 : 11 (hex (0x0B) Length of Application Block (eleven bytes of data to follow) + fp->Write("NETSCAPE2.0",11,1); + fp->PutC(3); //byte 15 : 3 (hex 0x03) Length of Data Sub-Block (three bytes of data to follow) + fp->PutC(1); //byte 16 : 1 (hex 0x01) + Putword(m_loops,fp); //bytes 17 to 18 : 0 to 65535, an unsigned integer in lo-hi byte format. + //This indicate the number of iterations the loop should be executed. + fp->PutC(0); //bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator. +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::EncodeBody(CxFile *fp, bool bLocalColorMap) +{ + curx = 0; + cury = head.biHeight - 1; //because we read the image bottom to top + CountDown = (long)head.biWidth * (long)head.biHeight; + + fp->PutC(','); + + Putword(info.xOffset,fp); + Putword(info.yOffset,fp); + Putword(head.biWidth,fp); + Putword(head.biHeight,fp); + + BYTE Flags=0x00; //non-interlaced (0x40 = interlaced) (0x80 = LocalColorMap) + if (bLocalColorMap) { Flags|=0x80; Flags|=head.biBitCount-1; } + fp->PutC(Flags); + + if (bLocalColorMap){ + Flags|=0x87; + RGBQUAD* pPal = GetPalette(); + for(DWORD i=0; iPutC(pPal[i].rgbRed); + fp->PutC(pPal[i].rgbGreen); + fp->PutC(pPal[i].rgbBlue); + } + } + + int InitCodeSize = head.biBitCount <=1 ? 2 : head.biBitCount; + // Write out the initial code size + fp->PutC((BYTE)InitCodeSize); + + // Go and actually compress the data + switch (GetCodecOption(CXIMAGE_FORMAT_GIF)) + { + case 1: //uncompressed + compressNONE(InitCodeSize+1, fp); + break; + case 2: //RLE + compressRLE(InitCodeSize+1, fp); + break; + default: //LZW + compressLZW(InitCodeSize+1, fp); + } + + // Write out a Zero-length packet (to end the series) + fp->PutC(0); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::EncodeComment(CxFile *fp) +{ + unsigned long n = (unsigned long) strlen(m_comment); + if (n>255) n=255; + if (n) { + fp->PutC('!'); //extension code: + fp->PutC(254); //comment extension + fp->PutC((BYTE)n); //size of comment + fp->Write(m_comment,n,1); + fp->PutC(0); //block terminator + } +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageGIF::EncodeRGB(CxFile *fp) +{ + EncodeHeader(fp); + +// EncodeLoopExtension(fp); + + EncodeComment(fp); + + unsigned long w,h; + w=h=0; + const long cellw = 17; + const long cellh = 15; + CxImageGIF tmp; + for (long y=0;yPutC(';'); // Write the GIF file terminator + + return true; // done! +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +// Return the next pixel from the image +// fix for 1 & 4 bpp images +int CxImageGIF::GifNextPixel( ) +{ + if( CountDown == 0 ) return EOF; + --CountDown; + int r = GetPixelIndex(curx,cury); + // Bump the current X position + ++curx; + if( curx == head.biWidth ){ + curx = 0; + cury--; //bottom to top + } + return r; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::Putword(int w, CxFile *fp ) +{ + fp->PutC((BYTE)(w & 0xff)); + fp->PutC((BYTE)((w / 256) & 0xff)); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::compressNONE( int init_bits, CxFile* outfile) +{ + register long c; + register long ent; + + // g_init_bits - initial number of bits + // g_outfile - pointer to output file + g_init_bits = init_bits; + g_outfile = outfile; + + // Set up the necessary values + cur_accum = cur_bits = clear_flg = 0; + maxcode = (short)MAXCODE(n_bits = g_init_bits); + code_int maxmaxcode = (code_int)1 << MAXBITSCODES; + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = (short)(ClearCode + 2); + + a_count=0; + ent = GifNextPixel( ); + + output( (code_int)ClearCode ); + + while ( ent != EOF ) { + c = GifNextPixel(); + + output ( (code_int) ent ); + ent = c; + if ( free_ent < maxmaxcode ) { + free_ent++; + } else { + free_ent=(short)(ClearCode+2); + clear_flg=1; + output((code_int)ClearCode); + } + } + // Put out the final code. + output( (code_int) EOFCode ); +} +//////////////////////////////////////////////////////////////////////////////// + +/*************************************************************************** + * + * GIFCOMPR.C - LZW GIF Image compression routines + * + ***************************************************************************/ + +void CxImageGIF::compressLZW( int init_bits, CxFile* outfile) +{ + register long fcode; + register long c; + register long ent; + register long hshift; + register long disp; + register long i; + + // g_init_bits - initial number of bits + // g_outfile - pointer to output file + g_init_bits = init_bits; + g_outfile = outfile; + + // Set up the necessary values + cur_accum = cur_bits = clear_flg = 0; + maxcode = (short)MAXCODE(n_bits = g_init_bits); + code_int maxmaxcode = (code_int)1 << MAXBITSCODES; + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = (short)(ClearCode + 2); + + a_count=0; + ent = GifNextPixel( ); + + hshift = 0; + for ( fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L ) ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + cl_hash((long)HSIZE); /* clear hash table */ + output( (code_int)ClearCode ); + + while ( (c = GifNextPixel( )) != EOF ) { + + fcode = (long) (((long) c << MAXBITSCODES) + ent); + i = (((code_int)c << hshift) ^ ent); /* xor hashing */ + + if ( HashTabOf (i) == fcode ) { + ent = CodeTabOf (i); + continue; + } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */ + goto nomatch; + disp = HSIZE - i; /* secondary hash (after G. Knott) */ + if ( i == 0 ) disp = 1; +probe: + if ( (i -= disp) < 0 ) i += HSIZE; + if ( HashTabOf (i) == fcode ) { ent = CodeTabOf (i); continue; } + if ( (long)HashTabOf (i) > 0 ) goto probe; +nomatch: + output ( (code_int) ent ); + ent = c; + if ( free_ent < maxmaxcode ) { + CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } else { + cl_hash((long)HSIZE); + free_ent=(short)(ClearCode+2); + clear_flg=1; + output((code_int)ClearCode); + } + } + // Put out the final code. + output( (code_int)ent ); + output( (code_int) EOFCode ); +} +//////////////////////////////////////////////////////////////////////////////// + +static const unsigned long code_mask[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::output( code_int code) +{ + cur_accum &= code_mask[ cur_bits ]; + + if( cur_bits > 0 ) + cur_accum |= ((long)code << cur_bits); + else + cur_accum = code; + + cur_bits += n_bits; + + while( cur_bits >= 8 ) { + char_out( (unsigned int)(cur_accum & 0xff) ); + cur_accum >>= 8; + cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + + if ( free_ent > maxcode || clear_flg ) { + if( clear_flg ) { + maxcode = (short)MAXCODE(n_bits = g_init_bits); + clear_flg = 0; + } else { + ++n_bits; + if ( n_bits == MAXBITSCODES ) + maxcode = (code_int)1 << MAXBITSCODES; /* should NEVER generate this code */ + else + maxcode = (short)MAXCODE(n_bits); + } + } + + if( code == EOFCode ) { + // At EOF, write the rest of the buffer. + while( cur_bits > 0 ) { + char_out( (unsigned int)(cur_accum & 0xff) ); + cur_accum >>= 8; + cur_bits -= 8; + } + + flush_char(); + g_outfile->Flush(); + + if(g_outfile->Error()) strcpy(info.szLastError,"Write Error in GIF file"); + } +} +//////////////////////////////////////////////////////////////////////////////// + +void CxImageGIF::cl_hash(register long hsize) + +{ + register long *htab_p = htab+hsize; + + register long i; + register long m1 = -1L; + + i = hsize - 16; + + do { + *(htab_p-16)=m1; + *(htab_p-15)=m1; + *(htab_p-14)=m1; + *(htab_p-13)=m1; + *(htab_p-12)=m1; + *(htab_p-11)=m1; + *(htab_p-10)=m1; + *(htab_p-9)=m1; + *(htab_p-8)=m1; + *(htab_p-7)=m1; + *(htab_p-6)=m1; + *(htab_p-5)=m1; + *(htab_p-4)=m1; + *(htab_p-3)=m1; + *(htab_p-2)=m1; + *(htab_p-1)=m1; + + htab_p-=16; + } while ((i-=16) >=0); + + for (i+=16;i>0;--i) + *--htab_p=m1; +} + +/******************************************************************************* +* GIF specific +*******************************************************************************/ + +void CxImageGIF::char_out(int c) +{ + accum[a_count++]=(char)c; + if (a_count >=254) + flush_char(); +} + +void CxImageGIF::flush_char() +{ + if (a_count > 0) { + g_outfile->PutC((BYTE)a_count); + g_outfile->Write(accum,1,a_count); + a_count=0; + } +} + +/******************************************************************************* +* GIF decoder +*******************************************************************************/ +/* DECODE.C - An LZW decoder for GIF + * Copyright (C) 1987, by Steven A. Bennett + * Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra +* + * Permission is given by the author to freely redistribute and include + * this code in any program as long as this credit is given where due. + * + * In accordance with the above, I want to credit Steve Wilhite who wrote + * the code which this is heavily inspired by... + * + * GIF and 'Graphics Interchange Format' are trademarks (tm) of + * Compuserve, Incorporated, an H&R Block Company. + * + * Release Notes: This file contains a decoder routine for GIF images + * which is similar, structurally, to the original routine by Steve Wilhite. + * It is, however, somewhat noticably faster in most cases. + * + */ + +//////////////////////////////////////////////////////////////////////////////// + +short CxImageGIF::init_exp(short size) +{ + curr_size = (short)(size + 1); + top_slot = (short)(1 << curr_size); + clear = (short)(1 << size); + ending = (short)(clear + 1); + slot = newcodes = (short)(ending + 1); + navail_bytes = nbits_left = 0; + + memset(stack,0,MAX_CODES + 1); + memset(prefix,0,MAX_CODES + 1); + memset(suffix,0,MAX_CODES + 1); + return(0); +} +//////////////////////////////////////////////////////////////////////////////// + +/* get_next_code() + * - gets the next code from the GIF file. Returns the code, or else + * a negative number in case of file errors... + */ +short CxImageGIF::get_next_code(CxFile* file) +{ + short i, x; + DWORD ret; + + if (nbits_left == 0) { + if (navail_bytes <= 0) { + /* Out of bytes in current block, so read next block */ + pbytes = byte_buff; + if ((navail_bytes = (short)get_byte(file)) < 0) + return(navail_bytes); + else if (navail_bytes) { + for (i = 0; i < navail_bytes; ++i) { + if ((x = (short)get_byte(file)) < 0) return(x); + byte_buff[i] = (BYTE)x; + } + } + } + b1 = *pbytes++; + nbits_left = 8; + --navail_bytes; + } + + if (navail_bytes<0) return ending; // prevent deadlocks (thanks to Mike Melnikov) + + ret = b1 >> (8 - nbits_left); + while (curr_size > nbits_left){ + if (navail_bytes <= 0){ + /* Out of bytes in current block, so read next block*/ + pbytes = byte_buff; + if ((navail_bytes = (short)get_byte(file)) < 0) + return(navail_bytes); + else if (navail_bytes){ + for (i = 0; i < navail_bytes; ++i){ + if ((x = (short)get_byte(file)) < 0) return(x); + byte_buff[i] = (BYTE)x; + } + } + } + b1 = *pbytes++; + ret |= b1 << nbits_left; + nbits_left += 8; + --navail_bytes; + } + nbits_left = (short)(nbits_left-curr_size); + ret &= code_mask[curr_size]; + return((short)(ret)); +} +//////////////////////////////////////////////////////////////////////////////// + +/* short decoder(linewidth) + * short linewidth; * Pixels per line of image * + * + * - This function decodes an LZW image, according to the method used + * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded + * will generate a call to out_line(), which is a user specific function + * to display a line of pixels. The function gets it's codes from + * get_next_code() which is responsible for reading blocks of data and + * seperating them into the proper size codes. Finally, get_byte() is + * the global routine to read the next BYTE from the GIF file. + * + * It is generally a good idea to have linewidth correspond to the actual + * width of a line (as specified in the Image header) to make your own + * code a bit simpler, but it isn't absolutely necessary. + * + * Returns: 0 if successful, else negative. (See ERRS.H) + * + */ +/* bad_code_count is incremented each time an out of range code is read. + * When this value is non-zero after a decode, your GIF file is probably + * corrupt in some way... + */ +short CxImageGIF::decoder(CxFile* file, CImageIterator* iter, short linewidth, int &bad_code_count) +{ + register BYTE *sp, *bufptr; + BYTE *buf; + register short code, fc, oc, bufcnt; + short c, size, ret; + + /* Initialize for decoding a new image... */ + bad_code_count = 0; + if ((size = (short)get_byte(file)) < 0) return(size); + if (size < 2 || 9 < size) return(BAD_CODE_SIZE); + // out_line = outline; + init_exp(size); + //printf("L %d %x\n",linewidth,size); + + /* Initialize in case they forgot to put in a clear code. + * (This shouldn't happen, but we'll try and decode it anyway...) + */ + oc = fc = 0; + + /* Allocate space for the decode buffer */ + if ((buf = new BYTE[linewidth + 1]) == NULL) return(OUT_OF_MEMORY); + + /* Set up the stack pointer and decode buffer pointer */ + sp = stack; + bufptr = buf; + bufcnt = linewidth; + + /* This is the main loop. For each code we get we pass through the + * linked list of prefix codes, pushing the corresponding "character" for + * each code onto the stack. When the list reaches a single "character" + * we push that on the stack too, and then start unstacking each + * character for output in the correct order. Special handling is + * included for the clear code, and the whole thing ends when we get + * an ending code. + */ + while ((c = get_next_code(file)) != ending) { + /* If we had a file error, return without completing the decode*/ + if (c < 0){ + delete[] buf; + return(0); + } + /* If the code is a clear code, reinitialize all necessary items.*/ + if (c == clear){ + curr_size = (short)(size + 1); + slot = newcodes; + top_slot = (short)(1 << curr_size); + + /* Continue reading codes until we get a non-clear code + * (Another unlikely, but possible case...) + */ + while ((c = get_next_code(file)) == clear); + + /* If we get an ending code immediately after a clear code + * (Yet another unlikely case), then break out of the loop. + */ + if (c == ending) break; + + /* Finally, if the code is beyond the range of already set codes, + * (This one had better NOT happen... I have no idea what will + * result from this, but I doubt it will look good...) then set it + * to color zero. + */ + if (c >= slot) c = 0; + oc = fc = c; + + /* And let us not forget to put the char into the buffer... And + * if, on the off chance, we were exactly one pixel from the end + * of the line, we have to send the buffer to the out_line() + * routine... + */ + *bufptr++ = (BYTE)c; + if (--bufcnt == 0) { + if ((ret = (short)out_line(iter, buf, linewidth)) < 0) { + delete[] buf; + return(ret); + } + bufptr = buf; + bufcnt = linewidth; + } + } else { + /* In this case, it's not a clear code or an ending code, so + * it must be a code code... So we can now decode the code into + * a stack of character codes. (Clear as mud, right?) + */ + code = c; + + /* Here we go again with one of those off chances... If, on the + * off chance, the code we got is beyond the range of those already + * set up (Another thing which had better NOT happen...) we trick + * the decoder into thinking it actually got the last code read. + * (Hmmn... I'm not sure why this works... But it does...) + */ + if (code >= slot) { + if (code > slot) ++bad_code_count; + code = oc; + *sp++ = (BYTE)fc; + } + + /* Here we scan back along the linked list of prefixes, pushing + * helpless characters (ie. suffixes) onto the stack as we do so. + */ + while (code >= newcodes) { + *sp++ = suffix[code]; + code = prefix[code]; + } + + /* Push the last character on the stack, and set up the new + * prefix and suffix, and if the required slot number is greater + * than that allowed by the current bit size, increase the bit + * size. (NOTE - If we are all full, we *don't* save the new + * suffix and prefix... I'm not certain if this is correct... + * it might be more proper to overwrite the last code... + */ + *sp++ = (BYTE)code; + if (slot < top_slot){ + suffix[slot] = (BYTE)(fc = (BYTE)code); + prefix[slot++] = oc; + oc = c; + } + if (slot >= top_slot){ + if (curr_size < 12) { + top_slot <<= 1; + ++curr_size; + } + } + + /* Now that we've pushed the decoded string (in reverse order) + * onto the stack, lets pop it off and put it into our decode + * buffer... And when the decode buffer is full, write another + * line... + */ + while (sp > stack) { + *bufptr++ = *(--sp); + if (--bufcnt == 0) { + if ((ret = (short)out_line(iter, buf, linewidth)) < 0) { + delete[] buf; + return(ret); + } + bufptr = buf; + bufcnt = linewidth; + } + } + } + } + ret = 0; + if (bufcnt != linewidth) + ret = (short)out_line(iter, buf, (linewidth - bufcnt)); + delete[] buf; + return(ret); +} +//////////////////////////////////////////////////////////////////////////////// +int CxImageGIF::get_num_frames(CxFile *fp,struct_TabCol* TabColSrc,struct_dscgif* dscgif) +{ + struct_image image; + + long pos=fp->Tell(); + int nframes=0; + + struct_TabCol TempTabCol; + memcpy(&TempTabCol,TabColSrc,sizeof(struct_TabCol)); + + char ch; + bool bPreviousWasNull = true; + + for (BOOL bContinue = TRUE; bContinue; ) + { + if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;} + + if (bPreviousWasNull || ch==0) + { + switch (ch) + { + case '!': // extension + { + DecodeExtension(fp); + break; + } + case ',': // image + { + + assert(sizeof(image) == 9); + //log << "Image header" << endl; + fp->Read(&image,sizeof(image),1); + + //avoid byte order problems with Solaris + BYTE *byteData = (BYTE *) & image; + image.l = byteData[0]+byteData[1]*256; + image.t = byteData[2]+byteData[3]*256; + image.w = byteData[4]+byteData[5]*256; + image.h = byteData[6]+byteData[7]*256; + + if (((image.l + image.w) > dscgif->scrwidth)||((image.t + image.h) > dscgif->scrheight)) + break; + + nframes++; + + // Local colour map? + if (image.pf & 0x80) { + TempTabCol.sogct = (short)(1 << ((image.pf & 0x07) +1)); + assert(3 == sizeof(struct rgb_color)); + fp->Read(TempTabCol.paleta,sizeof(struct rgb_color)*TempTabCol.sogct,1); + //log << "Local colour map" << endl; + } + + int bpp; // select the correct bit per pixel value + if (TempTabCol.sogct <= 2) bpp = 1; + else if (TempTabCol.sogct <= 16) bpp = 4; + else bpp = 8; + + Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF); + + CImageIterator* iter = new CImageIterator(this); + iter->Upset(); + int badcode=0; + ibf = GIFBUFTAM+1; + + interlaced = image.pf & 0x40; + iheight = image.h; + istep = 8; + iypos = 0; + ipass = 0; + + long pos_start = fp->Tell(); + + //if (interlaced) log << "Interlaced" << endl; + decoder(fp, iter, image.w, badcode); + delete iter; + + if (badcode){ + seek_next_image(fp,pos_start); + } else { + fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR); + } + + break; + } + case ';': //terminator + bContinue=false; + break; + default: + bPreviousWasNull = (ch==0); + break; + } + } + } + + fp->Seek(pos,SEEK_SET); + return nframes; +} +//////////////////////////////////////////////////////////////////////////////// +long CxImageGIF::seek_next_image(CxFile* fp, long position) +{ + fp->Seek(position, SEEK_SET); + char ch1,ch2; + ch1=ch2=0; + while(fp->Read(&ch2,sizeof(char),1)>0){ + if (ch1 == 0 && ch2 == ','){ + fp->Seek(-1,SEEK_CUR); + return fp->Tell(); + } else { + ch1 = ch2; + } + } + return -1; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::SetDisposalMethod(int dm) +{ m_dispmeth=dm; } +//////////////////////////////////////////////////////////////////////////////// +long CxImageGIF::GetDisposalMethod() +{ return m_dispmeth; } +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::SetLoops(int loops) +{ m_loops=loops; } +//////////////////////////////////////////////////////////////////////////////// +long CxImageGIF::GetLoops() +{ return m_loops; } +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::SetComment(const char* sz_comment_in) +{ if (sz_comment_in) strncpy(m_comment,sz_comment_in,255); } +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::GetComment(char* sz_comment_out) +{ if (sz_comment_out) strncpy(sz_comment_out,m_comment,255); } +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::GifMix(CxImage & imgsrc2, struct_image & imgdesc) +{ + long ymin = max(0,(long)(GetHeight()-imgdesc.t - imgdesc.h)); + long ymax = GetHeight()-imgdesc.t; + long xmin = imgdesc.l; + long xmax = min(GetWidth(), (DWORD)(imgdesc.l + imgdesc.w)); + + long ibg2= imgsrc2.GetTransIndex(); + BYTE i2; + + for(long y = ymin; y < ymax; y++){ + for(long x = xmin; x < xmax; x++){ + i2 = imgsrc2.GetPixelIndex(x-xmin,y-ymin); + if(i2!=ibg2) SetPixelIndex(x,y,i2); + } + } +} +//////////////////////////////////////////////////////////////////////////////// +/*----------------------------------------------------------------------- + * + * miGIF Compression - mouse and ivo's GIF-compatible compression + * + * -run length encoding compression routines- + * + * Copyright (C) 1998 Hutchison Avenue Software Corporation + * http://www.hasc.com + * info@hasc.com + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "AS IS." The Hutchison Avenue + * Software Corporation disclaims all warranties, either express or implied, + * including but not limited to implied warranties of merchantability and + * fitness for a particular purpose, with respect to this code and accompanying + * documentation. + * + * The miGIF compression routines do not, strictly speaking, generate files + * conforming to the GIF spec, since the image data is not LZW-compressed + * (this is the point: in order to avoid transgression of the Unisys patent + * on the LZW algorithm.) However, miGIF generates data streams that any + * reasonably sane LZW decompresser will decompress to what we want. + * + * miGIF compression uses run length encoding. It compresses horizontal runs + * of pixels of the same color. This type of compression gives good results + * on images with many runs, for example images with lines, text and solid + * shapes on a solid-colored background. It gives little or no compression + * on images with few runs, for example digital or scanned photos. + * + * der Mouse + * mouse@rodents.montreal.qc.ca + * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B + * + * ivo@hasc.com + * + * The Graphics Interchange Format(c) is the Copyright property of + * CompuServe Incorporated. GIF(sm) is a Service Mark property of + * CompuServe Incorporated. + * + */ +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_clear(struct_RLE* rle) +{ + rle->out_bits = rle->out_bits_init; + rle->out_bump = rle->out_bump_init; + rle->out_clear = rle->out_clear_init; + rle->out_count = 0; + rle->rl_table_max = 0; + rle->just_cleared = 1; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_flush(struct_RLE* rle) +{ + if (rle->rl_count == 1){ + rle_output_plain(rle->rl_pixel,rle); + rle->rl_count = 0; + return; + } + if (rle->just_cleared){ + rle_flush_fromclear(rle->rl_count,rle); + } else if ((rle->rl_table_max < 2) || (rle->rl_table_pixel != rle->rl_pixel)) { + rle_flush_clearorrep(rle->rl_count,rle); + } else { + rle_flush_withtable(rle->rl_count,rle); + } + rle->rl_count = 0; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_output_plain(int c,struct_RLE* rle) +{ + rle->just_cleared = 0; + rle_output(c,rle); + rle->out_count++; + if (rle->out_count >= rle->out_bump){ + rle->out_bits ++; + rle->out_bump += 1 << (rle->out_bits - 1); + } + if (rle->out_count >= rle->out_clear){ + rle_output(rle->code_clear,rle); + rle_clear(rle); + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_flush_fromclear(int count,struct_RLE* rle) +{ + int n; + + rle->out_clear = rle->max_ocodes; + rle->rl_table_pixel = rle->rl_pixel; + n = 1; + while (count > 0){ + if (n == 1){ + rle->rl_table_max = 1; + rle_output_plain(rle->rl_pixel,rle); + count --; + } else if (count >= n){ + rle->rl_table_max = n; + rle_output_plain(rle->rl_basecode+n-2,rle); + count -= n; + } else if (count == 1){ + rle->rl_table_max ++; + rle_output_plain(rle->rl_pixel,rle); + count = 0; + } else { + rle->rl_table_max ++; + rle_output_plain(rle->rl_basecode+count-2,rle); + count = 0; + } + if (rle->out_count == 0) n = 1; else n ++; + } + rle_reset_out_clear(rle); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_reset_out_clear(struct_RLE* rle) +{ + rle->out_clear = rle->out_clear_init; + if (rle->out_count >= rle->out_clear){ + rle_output(rle->code_clear,rle); + rle_clear(rle); + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_flush_withtable(int count, struct_RLE* rle) +{ + int repmax; + int repleft; + int leftover; + + repmax = count / rle->rl_table_max; + leftover = count % rle->rl_table_max; + repleft = (leftover ? 1 : 0); + if (rle->out_count+repmax+repleft > rle->max_ocodes){ + repmax = rle->max_ocodes - rle->out_count; + leftover = count - (repmax * rle->rl_table_max); + repleft = 1 + rle_compute_triangle_count(leftover,rle->max_ocodes); + } + if (1+rle_compute_triangle_count(count,rle->max_ocodes) < (unsigned int)(repmax+repleft)){ + rle_output(rle->code_clear,rle); + rle_clear(rle); + rle_flush_fromclear(count,rle); + return; + } + rle->out_clear = rle->max_ocodes; + for (;repmax>0;repmax--) rle_output_plain(rle->rl_basecode+rle->rl_table_max-2,rle); + if (leftover){ + if (rle->just_cleared){ + rle_flush_fromclear(leftover,rle); + } else if (leftover == 1){ + rle_output_plain(rle->rl_pixel,rle); + } else { + rle_output_plain(rle->rl_basecode+leftover-2,rle); + } + } + rle_reset_out_clear(rle); +} +//////////////////////////////////////////////////////////////////////////////// +unsigned int CxImageGIF::rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes) +{ + unsigned int perrep; + unsigned int cost; + + cost = 0; + perrep = (nrepcodes * (nrepcodes+1)) / 2; + while (count >= perrep){ + cost += nrepcodes; + count -= perrep; + } + if (count > 0){ + unsigned int n; + n = rle_isqrt(count); + while ((n*(n+1)) >= 2*count) n --; + while ((n*(n+1)) < 2*count) n ++; + cost += n; + } + return(cost); +} +//////////////////////////////////////////////////////////////////////////////// +unsigned int CxImageGIF::rle_isqrt(unsigned int x) +{ + unsigned int r; + unsigned int v; + + if (x < 2) return(x); + for (v=x,r=1;v;v>>=2,r<<=1) ; + while (1){ + v = ((x / r) + r) / 2; + if ((v == r) || (v == r+1)) return(r); + r = v; + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_flush_clearorrep(int count, struct_RLE* rle) +{ + int withclr; + withclr = 1 + rle_compute_triangle_count(count,rle->max_ocodes); + if (withclr < count) { + rle_output(rle->code_clear,rle); + rle_clear(rle); + rle_flush_fromclear(count,rle); + } else { + for (;count>0;count--) rle_output_plain(rle->rl_pixel,rle); + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_write_block(struct_RLE* rle) +{ + g_outfile->PutC((BYTE)rle->oblen); + g_outfile->Write(rle->oblock,1,rle->oblen); + rle->oblen = 0; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_block_out(unsigned char c, struct_RLE* rle) +{ + rle->oblock[rle->oblen++] = c; + if (rle->oblen >= 255) rle_write_block(rle); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_block_flush(struct_RLE* rle) +{ + if (rle->oblen > 0) rle_write_block(rle); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_output(int val, struct_RLE* rle) +{ + rle->obuf |= val << rle->obits; + rle->obits += rle->out_bits; + while (rle->obits >= 8){ + rle_block_out(rle->obuf&0xff,rle); + rle->obuf >>= 8; + rle->obits -= 8; + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::rle_output_flush(struct_RLE* rle) +{ + if (rle->obits > 0) rle_block_out(rle->obuf,rle); + rle_block_flush(rle); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageGIF::compressRLE( int init_bits, CxFile* outfile) +{ + g_init_bits = init_bits; + g_outfile = outfile; + + struct_RLE rle; + rle.code_clear = 1 << (init_bits - 1); + rle.code_eof = rle.code_clear + 1; + rle.rl_basecode = rle.code_eof + 1; + rle.out_bump_init = (1 << (init_bits - 1)) - 1; + rle.out_clear_init = (init_bits <= 3) ? 9 : (rle.out_bump_init-1); + rle.out_bits_init = init_bits; + rle.max_ocodes = (1 << MAXBITSCODES) - ((1 << (rle.out_bits_init - 1)) + 3); + rle.rl_count = 0; + rle_clear(&rle); + rle.obuf = 0; + rle.obits = 0; + rle.oblen = 0; + + rle_output(rle.code_clear,&rle); + + int c; + while (1){ + c = GifNextPixel(); + if ((rle.rl_count > 0) && (c != rle.rl_pixel)) rle_flush(&rle); + if (c == EOF) break; + if (rle.rl_pixel == c){ + rle.rl_count++; + } else { + rle.rl_pixel = c; + rle.rl_count = 1; + } + } + rle_output(rle.code_eof,&rle); + rle_output_flush(&rle); +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_GIF diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximagif.h ./win32/dependencies/cximage/ximagif.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximagif.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximagif.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,248 @@ +/* + * File: ximagif.h + * Purpose: GIF Image Class Loader and Writer + */ +/* ========================================================== + * CxImageGIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes + * + * original CImageGIF and CImageIterator implementation are: + * Copyright: (c) 1995, Alejandro Aguilar Sierra + * + * 6/15/97 Randy Spann: Added GIF87a writing support + * R.Spann@ConnRiver.net + * + * DECODE.C - An LZW decoder for GIF + * Copyright (C) 1987, by Steven A. Bennett + * Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra + * + * In accordance with the above, I want to credit Steve Wilhite who wrote + * the code which this is heavily inspired by... + * + * GIF and 'Graphics Interchange Format' are trademarks (tm) of + * Compuserve, Incorporated, an H&R Block Company. + * + * Release Notes: This file contains a decoder routine for GIF images + * which is similar, structurally, to the original routine by Steve Wilhite. + * It is, however, somewhat noticably faster in most cases. + * + * ========================================================== + */ + +#if !defined(__ximaGIF_h) +#define __ximaGIF_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_GIF + +typedef short int code_int; + +/* Various error codes used by decoder */ +#define OUT_OF_MEMORY -10 +#define BAD_CODE_SIZE -20 +#define READ_ERROR -1 +#define WRITE_ERROR -2 +#define OPEN_ERROR -3 +#define CREATE_ERROR -4 +#define MAX_CODES 4095 +#define GIFBUFTAM 16383 +#define TRANSPARENCY_CODE 0xF9 + +//LZW GIF Image compression +#define MAXBITSCODES 12 +#define HSIZE 5003 /* 80% occupancy */ +#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) +#define HashTabOf(i) htab[i] +#define CodeTabOf(i) codetab[i] + + +class CImageIterator; +class DLL_EXP CxImageGIF: public CxImage +{ +#pragma pack(1) + +typedef struct tag_gifgce{ + BYTE transpcolflag:1; + BYTE userinputflag:1; + BYTE dispmeth:3; + BYTE res:3; + WORD delaytime; + BYTE transpcolindex; +} struct_gifgce; + +typedef struct tag_dscgif{ /* Logic Screen Descriptor */ + char header[6]; /* Firma and version */ + WORD scrwidth; + WORD scrheight; + char pflds; + char bcindx; + char pxasrat; +} struct_dscgif; + +typedef struct tag_image{ /* Image Descriptor */ + WORD l; + WORD t; + WORD w; + WORD h; + BYTE pf; +} struct_image; + +typedef struct tag_TabCol{ /* Tabla de colores */ + short colres; /* color resolution */ + short sogct; /* size of global color table */ + rgb_color paleta[256]; /* paleta */ +} struct_TabCol; + +typedef struct tag_RLE{ + int rl_pixel; + int rl_basecode; + int rl_count; + int rl_table_pixel; + int rl_table_max; + int just_cleared; + int out_bits; + int out_bits_init; + int out_count; + int out_bump; + int out_bump_init; + int out_clear; + int out_clear_init; + int max_ocodes; + int code_clear; + int code_eof; + unsigned int obuf; + int obits; + unsigned char oblock[256]; + int oblen; +} struct_RLE; +#pragma pack() + +public: + CxImageGIF(): CxImage(CXIMAGE_FORMAT_GIF) {m_loops=0; m_dispmeth=0; m_comment[0]='\0';} + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_GIF);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_GIF);} + + bool Decode(CxFile * fp); + bool Decode(FILE *fp) { CxIOFile file(fp); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * fp); + bool Encode(CxFile * fp, CxImage ** pImages, int pagecount, bool bLocalColorMap = false); + bool Encode(FILE *fp) { CxIOFile file(fp); return Encode(&file); } + bool Encode(FILE *fp, CxImage ** pImages, int pagecount, bool bLocalColorMap = false) + { CxIOFile file(fp); return Encode(&file, pImages, pagecount, bLocalColorMap); } +#endif // CXIMAGE_SUPPORT_ENCODE + + void SetLoops(int loops); + long GetLoops(); + void SetComment(const char* sz_comment_in); + void GetComment(char* sz_comment_out); + void SetDisposalMethod(int dm); + long GetDisposalMethod(); + +protected: + bool DecodeExtension(CxFile *fp); + void EncodeHeader(CxFile *fp); + void EncodeLoopExtension(CxFile *fp); + void EncodeExtension(CxFile *fp); + void EncodeBody(CxFile *fp, bool bLocalColorMap = false); + void EncodeComment(CxFile *fp); + bool EncodeRGB(CxFile *fp); + void GifMix(CxImage & imgsrc2, struct_image & imgdesc); + + struct_gifgce gifgce; + + int curx, cury; + long CountDown; + unsigned long cur_accum; + int cur_bits; + int interlaced, iypos, istep, iheight, ipass; + int ibf; + int ibfmax; + BYTE buf[GIFBUFTAM + 1]; +// Implementation + int GifNextPixel (); + void Putword (int w, CxFile* fp ); + void compressNONE (int init_bits, CxFile* outfile); + void compressLZW (int init_bits, CxFile* outfile); + void output (code_int code ); + void cl_hash (long hsize); + void char_out (int c); + void flush_char (); + short init_exp(short size); + short get_next_code(CxFile*); + short decoder(CxFile*, CImageIterator* iter, short linewidth, int &bad_code_count); + int get_byte(CxFile*); + int out_line(CImageIterator* iter, unsigned char *pixels, int linelen); + int get_num_frames(CxFile *f,struct_TabCol* TabColSrc,struct_dscgif* dscgif); + long seek_next_image(CxFile* fp, long position); + + short curr_size; /* The current code size */ + short clear; /* Value for a clear code */ + short ending; /* Value for a ending code */ + short newcodes; /* First available code */ + short top_slot; /* Highest code for current size */ + short slot; /* Last read code */ + + /* The following static variables are used + * for seperating out codes */ + short navail_bytes; /* # bytes left in block */ + short nbits_left; /* # bits left in current BYTE */ + BYTE b1; /* Current BYTE */ + BYTE byte_buff[257]; /* Current block */ + BYTE *pbytes; /* Pointer to next BYTE in block */ + /* The reason we have these seperated like this instead of using + * a structure like the original Wilhite code did, is because this + * stuff generally produces significantly faster code when compiled... + * This code is full of similar speedups... (For a good book on writing + * C for speed or for space optomisation, see Efficient C by Tom Plum, + * published by Plum-Hall Associates...) + */ + BYTE stack[MAX_CODES + 1]; /* Stack for storing pixels */ + BYTE suffix[MAX_CODES + 1]; /* Suffix table */ + WORD prefix[MAX_CODES + 1]; /* Prefix linked list */ + +//LZW GIF Image compression routines + long htab [HSIZE]; + unsigned short codetab [HSIZE]; + int n_bits; /* number of bits/code */ + code_int maxcode; /* maximum code, given n_bits */ + code_int free_ent; /* first unused entry */ + int clear_flg; + int g_init_bits; + CxFile* g_outfile; + int ClearCode; + int EOFCode; + + int a_count; + char accum[256]; + + char m_comment[256]; + int m_loops; + int m_dispmeth; + +//RLE compression routines + void compressRLE( int init_bits, CxFile* outfile); + void rle_clear(struct_RLE* rle); + void rle_flush(struct_RLE* rle); + void rle_flush_withtable(int count, struct_RLE* rle); + void rle_flush_clearorrep(int count, struct_RLE* rle); + void rle_flush_fromclear(int count,struct_RLE* rle); + void rle_output_plain(int c,struct_RLE* rle); + void rle_reset_out_clear(struct_RLE* rle); + unsigned int rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes); + unsigned int rle_isqrt(unsigned int x); + void rle_write_block(struct_RLE* rle); + void rle_block_out(unsigned char c, struct_RLE* rle); + void rle_block_flush(struct_RLE* rle); + void rle_output(int val, struct_RLE* rle); + void rle_output_flush(struct_RLE* rle); +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximahist.cpp ./win32/dependencies/cximage/ximahist.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximahist.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximahist.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,649 @@ +// xImaHist.cpp : histogram functions +/* 28/01/2004 v1.00 - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_DSP + +//////////////////////////////////////////////////////////////////////////////// +long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace) +{ + if (!pDib) return 0; + RGBQUAD color; + + if (red) memset(red,0,256*sizeof(long)); + if (green) memset(green,0,256*sizeof(long)); + if (blue) memset(blue,0,256*sizeof(long)); + if (gray) memset(gray,0,256*sizeof(long)); + + long xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(long y=ymin; yn) n=red[i]; + if (green && green[i]>n) n=green[i]; + if (blue && blue[i]>n) n=blue[i]; + if (gray && gray[i]>n) n=gray[i]; + } + + return n; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * HistogramStretch + * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels. + * \return true if everything is ok + * \author [dave] and [nipper] + */ +bool CxImage::HistogramStretch(long method) +{ + if (!pDib) return false; + + if ((head.biBitCount==8) && IsGrayScale()){ + // get min/max info + BYTE minc = 255, maxc = 0; + BYTE gray; + long y; + + double dbScaler = 50.0/head.biHeight; + + for (y=0; y maxc) maxc = gray; + } + } + + if (minc == 0 && maxc == 255) return true; + + // calculate LUT + BYTE lut[256]; + BYTE range = maxc - minc; + if (range != 0){ + for (long x = minc; x <= maxc; x++){ + lut[x] = (BYTE)(255 * (x - minc) / range); + } + } else lut[minc] = minc; + + for (y=0; y + // get min/max info + BYTE minc = 255, maxc = 0; + RGBQUAD color; + long y; + + for (y=0; y maxc) maxc = color.rgbRed; + if (color.rgbBlue > maxc) maxc = color.rgbBlue; + if (color.rgbGreen > maxc) maxc = color.rgbGreen; + } + } + + if (minc == 0 && maxc == 255) + return true; + + // calculate LUT + BYTE lut[256]; + BYTE range = maxc - minc; + + if (range != 0){ + for (long x = minc; x <= maxc; x++){ + lut[x] = (BYTE)(255 * (x - minc) / range); + } + } else lut[minc] = minc; + + // normalize image + double dbScaler = 100.0/head.biHeight; + + for (y=0; y + // get min/max info + BYTE minR = 255, maxR = 0; + BYTE minG = 255, maxG = 0; + BYTE minB = 255, maxB = 0; + RGBQUAD color; + long y; + + for (y=0; y maxR) maxR = color.rgbRed; + if (color.rgbBlue > maxB) maxB = color.rgbBlue; + if (color.rgbGreen > maxG) maxG = color.rgbGreen; + } + } + + if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255) + return true; + + // calculate LUT + BYTE lutR[256]; + BYTE range = maxR - minR; + if (range != 0) { + for (long x = minR; x <= maxR; x++){ + lutR[x] = (BYTE)(255 * (x - minR) / range); + } + } else lutR[minR] = minR; + + BYTE lutG[256]; + range = maxG - minG; + if (range != 0) { + for (long x = minG; x <= maxG; x++){ + lutG[x] = (BYTE)(255 * (x - minG) / range); + } + } else lutG[minG] = minG; + + BYTE lutB[256]; + range = maxB - minB; + if (range != 0) { + for (long x = minB; x <= maxB; x++){ + lutB[x] = (BYTE)(255 * (x - minB) / range); + } + } else lutB[minB] = minB; + + // normalize image + double dbScaler = 100.0/head.biHeight; + + for (y=0; y + // S = ( R - C ) ( B - A / D - C ) + double alimit = 0.0; + double blimit = 255.0; + double lowerc = 255.0; + double upperd = 0.0; + double tmpGray; + + RGBQUAD color; + RGBQUAD yuvClr; + double stretcheds; + + if ( head.biClrUsed == 0 ){ + long x, y, xmin, xmax, ymin, ymax; + xmin = ymin = 0; + xmax = head.biWidth; + ymax = head.biHeight; + + for( y = ymin; y < ymax; y++ ){ + info.nProgress = (long)(50*y/ymax); + if (info.nEscape) break; + for( x = xmin; x < xmax; x++ ){ + color = GetPixelColor( x, y ); + tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if ( tmpGray < lowerc ) lowerc = tmpGray; + if ( tmpGray > upperd ) upperd = tmpGray; + } + } + if (upperd==lowerc) return false; + + for( y = ymin; y < ymax; y++ ){ + info.nProgress = (long)(50+50*y/ymax); + if (info.nEscape) break; + for( x = xmin; x < xmax; x++ ){ + + color = GetPixelColor( x, y ); + yuvClr = RGBtoYUV(color); + + // Stretch Luminance + tmpGray = (double)yuvClr.rgbRed; + stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit; + if ( stretcheds < 0.0 ) stretcheds = 0.0; + else if ( stretcheds > 255.0 ) stretcheds = 255.0; + yuvClr.rgbRed = (BYTE)stretcheds; + + color = YUVtoRGB(yuvClr); + SetPixelColor( x, y, color ); + } + } + } else { + DWORD j; + for( j = 0; j < head.biClrUsed; j++ ){ + color = GetPaletteColor( (BYTE)j ); + tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if ( tmpGray < lowerc ) lowerc = tmpGray; + if ( tmpGray > upperd ) upperd = tmpGray; + } + if (upperd==lowerc) return false; + + for( j = 0; j < head.biClrUsed; j++ ){ + + color = GetPaletteColor( (BYTE)j ); + yuvClr = RGBtoYUV( color ); + + // Stretch Luminance + tmpGray = (double)yuvClr.rgbRed; + stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit; + if ( stretcheds < 0.0 ) stretcheds = 0.0; + else if ( stretcheds > 255.0 ) stretcheds = 255.0; + yuvClr.rgbRed = (BYTE)stretcheds; + + color = YUVtoRGB(yuvClr); + SetPaletteColor( (BYTE)j, color ); + } + } + } + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +// HistogramEqualize function by : dave(at)posortho(dot)com +bool CxImage::HistogramEqualize() +{ + if (!pDib) return false; + + int histogram[256]; + int map[256]; + int equalize_map[256]; + int x, y, i, j; + RGBQUAD color; + RGBQUAD yuvClr; + unsigned int YVal, high, low; + + memset( &histogram, 0, sizeof(int) * 256 ); + memset( &map, 0, sizeof(int) * 256 ); + memset( &equalize_map, 0, sizeof(int) * 256 ); + + // form histogram + for(y=0; y < head.biHeight; y++){ + info.nProgress = (long)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = GetPixelColor( x, y ); + YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + histogram[YVal]++; + } + } + + // integrate the histogram to get the equalization map. + j = 0; + for(i=0; i <= 255; i++){ + j += histogram[i]; + map[i] = j; + } + + // equalize + low = map[0]; + high = map[255]; + if (low == high) return false; + for( i = 0; i <= 255; i++ ){ + equalize_map[i] = (unsigned int)((((double)( map[i] - low ) ) * 255) / ( high - low ) ); + } + + // stretch the histogram + if(head.biClrUsed == 0){ // No Palette + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (long)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = GetPixelColor( x, y ); + yuvClr = RGBtoYUV(color); + + yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB(yuvClr); + SetPixelColor( x, y, color ); + } + } + } else { // Palette + for( i = 0; i < (int)head.biClrUsed; i++ ){ + + color = GetPaletteColor((BYTE)i); + yuvClr = RGBtoYUV(color); + + yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB(yuvClr); + SetPaletteColor( (BYTE)i, color ); + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +// HistogramNormalize function by : dave(at)posortho(dot)com +bool CxImage::HistogramNormalize() +{ + if (!pDib) return false; + + int histogram[256]; + int threshold_intensity, intense; + int x, y, i; + unsigned int normalize_map[256]; + unsigned int high, low, YVal; + + RGBQUAD color; + RGBQUAD yuvClr; + + memset( &histogram, 0, sizeof( int ) * 256 ); + memset( &normalize_map, 0, sizeof( unsigned int ) * 256 ); + + // form histogram + for(y=0; y < head.biHeight; y++){ + info.nProgress = (long)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = GetPixelColor( x, y ); + YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + histogram[YVal]++; + } + } + + // find histogram boundaries by locating the 1 percent levels + threshold_intensity = ( head.biWidth * head.biHeight) / 100; + + intense = 0; + for( low = 0; low < 255; low++ ){ + intense += histogram[low]; + if( intense > threshold_intensity ) break; + } + + intense = 0; + for( high = 255; high != 0; high--){ + intense += histogram[ high ]; + if( intense > threshold_intensity ) break; + } + + if ( low == high ){ + // Unreasonable contrast; use zero threshold to determine boundaries. + threshold_intensity = 0; + intense = 0; + for( low = 0; low < 255; low++){ + intense += histogram[low]; + if( intense > threshold_intensity ) break; + } + intense = 0; + for( high = 255; high != 0; high-- ){ + intense += histogram [high ]; + if( intense > threshold_intensity ) break; + } + } + if( low == high ) return false; // zero span bound + + // Stretch the histogram to create the normalized image mapping. + for(i = 0; i <= 255; i++){ + if ( i < (int) low ){ + normalize_map[i] = 0; + } else { + if(i > (int) high) + normalize_map[i] = 255; + else + normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low ); + } + } + + // Normalize + if( head.biClrUsed == 0 ){ + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (long)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = GetPixelColor( x, y ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB( yuvClr ); + SetPixelColor( x, y, color ); + } + } + } else { + for(i = 0; i < (int)head.biClrUsed; i++){ + + color = GetPaletteColor( (BYTE)i ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB( yuvClr ); + SetPaletteColor( (BYTE)i, color ); + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +// HistogramLog function by : dave(at)posortho(dot)com +bool CxImage::HistogramLog() +{ + if (!pDib) return false; + + //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|); + int x, y, i; + RGBQUAD color; + RGBQUAD yuvClr; + + unsigned int YVal, high = 1; + + // Find Highest Luminance Value in the Image + if( head.biClrUsed == 0 ){ // No Palette + for(y=0; y < head.biHeight; y++){ + info.nProgress = (long)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = GetPixelColor( x, y ); + YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + } else { // Palette + for(i = 0; i < (int)head.biClrUsed; i++){ + color = GetPaletteColor((BYTE)i); + YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + + // Logarithm Operator + double k = 255.0 / ::log( 1.0 + (double)high ); + if( head.biClrUsed == 0 ){ + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (long)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = GetPixelColor( x, y ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); + + color = YUVtoRGB( yuvClr ); + SetPixelColor( x, y, color ); + } + } + } else { + for(i = 0; i < (int)head.biClrUsed; i++){ + + color = GetPaletteColor( (BYTE)i ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); + + color = YUVtoRGB( yuvClr ); + SetPaletteColor( (BYTE)i, color ); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// HistogramRoot function by : dave(at)posortho(dot)com +bool CxImage::HistogramRoot() +{ + if (!pDib) return false; + //q(i,j) = sqrt(|p(i,j)|); + + int x, y, i; + RGBQUAD color; + RGBQUAD yuvClr; + double dtmp; + unsigned int YVal, high = 1; + + // Find Highest Luminance Value in the Image + if( head.biClrUsed == 0 ){ // No Palette + for(y=0; y < head.biHeight; y++){ + info.nProgress = (long)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = GetPixelColor( x, y ); + YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + } else { // Palette + for(i = 0; i < (int)head.biClrUsed; i++){ + color = GetPaletteColor((BYTE)i); + YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + + // Root Operator + double k = 128.0 / ::log( 1.0 + (double)high ); + if( head.biClrUsed == 0 ){ + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (long)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = GetPixelColor( x, y ); + yuvClr = RGBtoYUV( color ); + + dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); + if ( dtmp > 255.0 ) dtmp = 255.0; + if ( dtmp < 0 ) dtmp = 0; + yuvClr.rgbRed = (BYTE)dtmp; + + color = YUVtoRGB( yuvClr ); + SetPixelColor( x, y, color ); + } + } + } else { + for(i = 0; i < (int)head.biClrUsed; i++){ + + color = GetPaletteColor( (BYTE)i ); + yuvClr = RGBtoYUV( color ); + + dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); + if ( dtmp > 255.0 ) dtmp = 255.0; + if ( dtmp < 0 ) dtmp = 0; + yuvClr.rgbRed = (BYTE)dtmp; + + color = YUVtoRGB( yuvClr ); + SetPaletteColor( (BYTE)i, color ); + } + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaico.cpp ./win32/dependencies/cximage/ximaico.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaico.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximaico.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,299 @@ +/* + * File: ximaico.cpp + * Purpose: Platform Independent ICON Image Class Loader and Writer (MS version) + * 07/Aug/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximaico.h" + +#if CXIMAGE_SUPPORT_ICO + +//////////////////////////////////////////////////////////////////////////////// +bool CxImageICO::Decode(CxFile *hFile) +{ + if (hFile==NULL) return false; + + DWORD off = hFile->Tell(); // + int page=info.nFrame; //internal icon structure indexes + + // read the first part of the header + ICONHEADER icon_header; + hFile->Read(&icon_header,sizeof(ICONHEADER),1); + // check if it's an icon or a cursor + if ((icon_header.idReserved == 0) && ((icon_header.idType == 1)||(icon_header.idType == 2))) { + + info.nNumFrames = icon_header.idCount; + + // load the icon descriptions + ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY)); + int c; + for (c = 0; c < icon_header.idCount; c++) + hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1); + + if ((page>=0)&&(page + BITMAPINFOHEADER bih; + hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET); + hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1); + c = bih.biBitCount; + + // allocate memory for one icon + Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO); //image creation + + // read the palette + RGBQUAD pal[256]; + hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1); + SetPalette(pal,head.biClrUsed); //palette assign + + //read the icon + if (c<=24){ + hFile->Read(info.pImage, head.biSizeImage, 1); + } else { // 32 bit icon + BYTE* dst = info.pImage; + BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth); + BYTE* src = buf; + hFile->Read(buf, 4*head.biHeight*head.biWidth, 1); +#if CXIMAGE_SUPPORT_ALPHA + if (!AlphaIsValid()) AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + for (long y = 0; y < head.biHeight; y++) { + for(long x=0;xRead(mask, masksize, 1)){ + + bool bGoodMask=false; + for (int im=0;im>3)]>>(7-x%8))&0x01)){ + AlphaSet(x,y,0); + bNeedAlpha=true; + } + } + } + if (!bNeedAlpha) AlphaDelete(); +#endif //CXIMAGE_SUPPORT_ALPHA + + if (c==24){ //check if there is only one transparent color + RGBQUAD cc,ct; + long* pcc = (long*)&cc; + long* pct = (long*)&ct; + int nTransColors=0; + for (int y = 0; y < head.biHeight; y++){ + for (int x = 0; x < head.biWidth; x++){ + if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){ + cc = GetPixelColor(x,y,false); + if (nTransColors==0){ + nTransColors++; + ct = cc; + } else { + if (*pct!=*pcc){ + nTransColors++; + } + } + } + } + } + if (nTransColors==1){ + SetTransColor(ct); + SetTransIndex(0); +#if CXIMAGE_SUPPORT_ALPHA + AlphaDelete(); //because we have a unique transparent color in the image +#endif //CXIMAGE_SUPPORT_ALPHA + } + } + + // - Transparency support w/o Alpha support + if (c <= 8){ // only for icons with less than 256 colors (XP icons need alpha). + + // find a color index, which is not used in the image + // it is almost sure to find one, bcs. nobody uses all possible colors for an icon + + BYTE colorsUsed[256]; + memset(colorsUsed, 0, sizeof(colorsUsed)); + + for (int y = 0; y < head.biHeight; y++){ + for (int x = 0; x < head.biWidth; x++){ + colorsUsed[GetPixelIndex(x,y)] = 1; + } + } + + int iTransIdx = -1; + for (int x = 0; x < (int)head.biClrUsed; x++){ + if (colorsUsed[x] == 0){ + iTransIdx = x; // this one is not in use. we may use it as transparent color + break; + } + } + + // Go thru image and set unused color as transparent index if needed + if (iTransIdx >= 0){ + bool bNeedTrans = false; + for (int y = 0; y < head.biHeight; y++){ + for (int x = 0; x < head.biWidth; x++){ + // AND mask (Each Byte represents 8 Pixels) + if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){ + // AND mask is set (!=0). This is a transparent part + SetPixelIndex(x, y, iTransIdx); + bNeedTrans = true; + } + } + } + // set transparent index if needed + if (bNeedTrans) SetTransIndex(iTransIdx); +#if CXIMAGE_SUPPORT_ALPHA + AlphaDelete(); //because we have a transparent color in the palette +#endif //CXIMAGE_SUPPORT_ALPHA + } + } + } else { + SetTransIndex(0); //empty mask, set black as transparent color + Negative(); + } + } + free(mask); + + free(icon_list); + // icon has been loaded successfully! + return true; + } + free(icon_list); + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageICO::Encode(CxFile * hFile) +{ + if (EncodeSafeCheck(hFile)) return false; + + //check format limits + if ((head.biWidth>255)||(head.biHeight>255)){ + strcpy(info.szLastError,"Can't save this image as icon"); + return false; + } + + //prepare the palette struct + RGBQUAD* pal=GetPalette(); + if (head.biBitCount<=8 && pal==NULL) return false; + + int maskwdt=((head.biWidth+31)/32)*4; //mask line width + int masksize=head.biHeight * maskwdt; //size of mask + int bitcount=head.biBitCount; + int imagesize=head.biSizeImage; +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid() && head.biClrUsed==0){ + bitcount=32; + imagesize=4*head.biHeight*head.biWidth; + } +#endif + + //fill the icon headers + ICONHEADER icon_header={0,1,1}; + ICONDIRENTRY icon_list={(BYTE)head.biWidth,(BYTE)head.biHeight,(BYTE)head.biClrUsed ,0,0,(WORD)bitcount, + sizeof(BITMAPINFOHEADER)+head.biClrUsed*sizeof(RGBQUAD)+ + imagesize+masksize, + sizeof(ICONHEADER)+sizeof(ICONDIRENTRY)}; + BITMAPINFOHEADER bi={sizeof(BITMAPINFOHEADER),head.biWidth,2*head.biHeight,1,(WORD)bitcount, + 0,imagesize,0,0,0,0}; + + hFile->Write(&icon_header,sizeof(ICONHEADER),1); //write the headers + hFile->Write(&icon_list,sizeof(ICONDIRENTRY),1); + hFile->Write(&bi,sizeof(BITMAPINFOHEADER),1); + if (pal) hFile->Write(pal,head.biClrUsed*sizeof(RGBQUAD),1); //write palette + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid() && head.biClrUsed==0){ + BYTE* src = info.pImage; + BYTE* buf=(BYTE*)malloc(imagesize); + BYTE* dst = buf; + for (long y = 0; y < head.biHeight; y++) { + for(long x=0;xWrite(buf,imagesize, 1); + free(buf); + } else { + hFile->Write(info.pImage,imagesize,1); //write image + } +#else + hFile->Write(info.pImage,imagesize,1); //write image +#endif + + //save transparency mask + BYTE* mask=(BYTE*)calloc(masksize,1); //create empty AND/XOR masks + if (!mask) return false; + + //prepare the variables to build the mask + BYTE* iDst; + int pos,i; + RGBQUAD c={0,0,0,0}; + RGBQUAD ct = GetTransColor(); + long* pc = (long*)&c; + long* pct= (long*)&ct; + bool bTransparent = info.nBkgndIndex != -1; +#if CXIMAGE_SUPPORT_ALPHA + bool bAlphaPaletteIsValid = AlphaPaletteIsValid(); + bool bAlphaIsValid = AlphaIsValid(); +#endif + //build the mask + for (int y = 0; y < head.biHeight; y++) { + for (int x = 0; x < head.biWidth; x++) { + i=0; +#if CXIMAGE_SUPPORT_ALPHA + if (bAlphaIsValid && AlphaGet(x,y)==0) i=1; + if (bAlphaPaletteIsValid && GetPixelColor(x,y).rgbReserved==0) i=1; +#endif + c=GetPixelColor(x,y,false); + if (bTransparent && *pc==*pct) i=1; + iDst = mask + y*maskwdt + (x>>3); + pos = 7-x%8; + *iDst &= ~(0x01<Write(mask,masksize,1); + free(mask); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ICO + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaico.h ./win32/dependencies/cximage/ximaico.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaico.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximaico.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,52 @@ +/* + * File: ximaico.h + * Purpose: ICON Image Class Loader and Writer + */ +/* ========================================================== + * CxImageICO (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * ========================================================== + */ +#if !defined(__ximaICO_h) +#define __ximaICO_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_ICO + +class CxImageICO: public CxImage +{ +typedef struct tagIconDirectoryEntry { + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; + WORD wPlanes; + WORD wBitCount; + DWORD dwBytesInRes; + DWORD dwImageOffset; +} ICONDIRENTRY; + +typedef struct tagIconDir { + WORD idReserved; + WORD idType; + WORD idCount; +} ICONHEADER; + +public: + CxImageICO(): CxImage(CXIMAGE_FORMAT_ICO) {} + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximainfo.cpp ./win32/dependencies/cximage/ximainfo.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximainfo.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximainfo.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,388 @@ +// ximainfo.cpp : main attributes +/* 03/10/2004 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +//////////////////////////////////////////////////////////////////////////////// +/** + * \return the color used for transparency, and/or for background color + */ +RGBQUAD CxImage::GetTransColor() +{ + if (head.biBitCount<24 && info.nBkgndIndex != -1) return GetPaletteColor((BYTE)info.nBkgndIndex); + return info.nBkgndColor; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Gets the index used for transparency. Returns -1 for no transparancy. + */ +long CxImage::GetTransIndex() const +{ + return info.nBkgndIndex; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Sets the index used for transparency with 1, 4 and 8 bpp images. Set to -1 to remove the effect. + */ +void CxImage::SetTransIndex(long idx) +{ + info.nBkgndIndex = idx; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Sets the color used for transparency with 24 bpp images. + * You must call SetTransIndex(0) to enable the effect, SetTransIndex(-1) to disable it. + */ +void CxImage::SetTransColor(RGBQUAD rgb) +{ + rgb.rgbReserved=0; + info.nBkgndColor = rgb; +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::IsTransparent() const +{ + return info.nBkgndIndex>=0; // +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Returns true if the image has 256 colors or less. + */ +bool CxImage::IsIndexed() const +{ + return head.biClrUsed!=0; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \return 1 = indexed, 2 = RGB, 4 = RGBA + */ +BYTE CxImage::GetColorType() +{ + BYTE b = (BYTE)((head.biBitCount>8) ? 2 /*COLORTYPE_COLOR*/ : 1 /*COLORTYPE_PALETTE*/); +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) b = 4 /*COLORTYPE_ALPHA*/; +#endif //CXIMAGE_SUPPORT_ALPHA + return b; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \return Resolution for TIFF, JPEG, PNG and BMP formats. + */ +long CxImage::GetXDPI() const +{ + return info.xDPI; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \return Resolution for TIFF, JPEG, PNG and BMP formats. + */ +long CxImage::GetYDPI() const +{ + return info.yDPI; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Set resolution for TIFF, JPEG, PNG and BMP formats. + */ +void CxImage::SetXDPI(long dpi) +{ + if (dpi<=0) dpi=96; + info.xDPI = dpi; + head.biXPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Set resolution for TIFF, JPEG, PNG and BMP formats. + */ +void CxImage::SetYDPI(long dpi) +{ + if (dpi<=0) dpi=96; + info.yDPI = dpi; + head.biYPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \sa SetFlags + */ +DWORD CxImage::GetFlags() const +{ + return info.dwFlags; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Image flags, for future use + * \param flags + * - 0x??00000 = reserved for 16 bit, CMYK, multilayer + * - 0x00??0000 = blend modes + * - 0x0000???? = layer id or user flags + * + * \param bLockReservedFlags protects the "reserved" and "blend modes" flags + */ +void CxImage::SetFlags(DWORD flags, bool bLockReservedFlags) +{ + if (bLockReservedFlags) info.dwFlags = flags & 0x0000ffff; + else info.dwFlags = flags; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * \sa SetCodecOption + */ +DWORD CxImage::GetCodecOption(DWORD imagetype) +{ + if (imagetype=head.biWidth) x=head.biWidth-(x % head.biWidth + 1); + if (y<0) y=((-y) % head.biHeight); + else if (y>=head.biHeight) y=head.biHeight-(y % head.biHeight + 1); + break; + default: + return; + }//switch +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * See OverflowCoordinates for integer version + * \author ***bd*** 2.2004 + */ +void CxImage::OverflowCoordinates(float &x, float &y, OverflowMethod const ofMethod) +{ + if (x>=0 && x=0 && y=head.biWidth) x=head.biWidth-((float)fmod(x, (float) head.biWidth) + 1); + if (y<0) y=(float)fmod(-y, (float) head.biHeight); + else if (y>=head.biHeight) y=head.biHeight-((float)fmod(y, (float) head.biHeight) + 1); + break; + default: + return; + }//switch +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * Method return pixel color. Different methods are implemented for out of bounds pixels. + * If an image has alpha channel, alpha value is returned in .RGBReserved. + * + * \param x,y : pixel coordinates + * \param ofMethod : out-of-bounds method: + * - OF_WRAP - wrap over to pixels on other side of the image + * - OF_REPEAT - repeat last pixel on the edge + * - OF_COLOR - return input value of color + * - OF_BACKGROUND - return background color (if not set, return input color) + * - OF_TRANSPARENT - return transparent pixel + * + * \param rplColor : input color (returned for out-of-bound coordinates in OF_COLOR mode and if other mode is not applicable) + * + * \return color : color of pixel + * \author ***bd*** 2.2004 + */ +RGBQUAD CxImage::GetPixelColorWithOverflow(long x, long y, OverflowMethod const ofMethod, RGBQUAD* const rplColor) +{ + RGBQUAD color; //color to return + if ((!IsInside(x,y)) || pDib==NULL) { //is pixel within bouns?: + //pixel is out of bounds or no DIB + if (rplColor!=NULL) + color=*rplColor; + else { + color.rgbRed=color.rgbGreen=color.rgbBlue=255; color.rgbReserved=0; //default replacement colour: white transparent + }//if + if (pDib==NULL) return color; + //pixel is out of bounds: + switch (ofMethod) { + case OM_TRANSPARENT: +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) { + //alpha transparency is supported and image has alpha layer + color.rgbReserved=0; + } else { +#endif //CXIMAGE_SUPPORT_ALPHA + //no alpha transparency + if (GetTransIndex()>=0) { + color=GetTransColor(); //single color transparency enabled (return transparent color) + }//if +#if CXIMAGE_SUPPORT_ALPHA + }//if +#endif //CXIMAGE_SUPPORT_ALPHA + return color; + case OM_BACKGROUND: + //return background color (if it exists, otherwise input value) + if (info.nBkgndIndex != -1) { + if (head.biBitCount<24) color = GetPaletteColor((BYTE)info.nBkgndIndex); + else color = info.nBkgndColor; + }//if + return color; + case OM_REPEAT: + case OM_WRAP: + case OM_MIRROR: + OverflowCoordinates(x,y,ofMethod); + break; + default: + //simply return replacement color (OM_COLOR and others) + return color; + }//switch + }//if + //just return specified pixel (it's within bounds) + return BlindGetPixelColor(x,y); +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * This method reconstructs image according to chosen interpolation method and then returns pixel (x,y). + * (x,y) can lie between actual image pixels. If (x,y) lies outside of image, method returns value + * according to overflow method. + * This method is very useful for geometrical image transformations, where destination pixel + * can often assume color value lying between source pixels. + * + * \param (x,y) - coordinates of pixel to return + * GPCI method recreates "analogue" image back from digital data, so x and y + * are float values and color value of point (1.1,1) will generally not be same + * as (1,1). Center of first pixel is at (0,0) and center of pixel right to it is (1,0). + * (0.5,0) is half way between these two pixels. + * \param inMethod - interpolation (reconstruction) method (kernel) to use: + * - IM_NEAREST_NEIGHBOUR - returns colour of nearest lying pixel (causes stairy look of + * processed images) + * - IM_BILINEAR - interpolates colour from four neighbouring pixels (softens image a bit) + * - IM_BICUBIC - interpolates from 16 neighbouring pixels (can produce "halo" artifacts) + * - IM_BICUBIC2 - interpolates from 16 neighbouring pixels (perhaps a bit less halo artifacts + than IM_BICUBIC) + * - IM_BSPLINE - interpolates from 16 neighbouring pixels (softens image, washes colours) + * (As far as I know, image should be prefiltered for this method to give + * good results... some other time :) ) + * This method uses bicubic interpolation kernel from CXImage 5.99a and older + * versions. + * - IM_LANCZOS - interpolates from 12*12 pixels (slow, ringing artifacts) + * + * \param ofMethod - overflow method (see comments at GetPixelColorWithOverflow) + * \param rplColor - pointer to color used for out of borders pixels in OM_COLOR mode + * (and other modes if colour can't calculated in a specified way) + * + * \return interpolated color value (including interpolated alpha value, if image has alpha layer) + * + * \author ***bd*** 2.2004 + */ +RGBQUAD CxImage::GetPixelColorInterpolated( + float x,float y, + InterpolationMethod const inMethod, + OverflowMethod const ofMethod, + RGBQUAD* const rplColor) +{ + //calculate nearest pixel + int xi=(int)(x); if (x<0) xi--; //these replace (incredibly slow) floor (Visual c++ 2003, AMD Athlon) + int yi=(int)(y); if (y<0) yi--; + RGBQUAD color; //calculated colour + + switch (inMethod) { + case IM_NEAREST_NEIGHBOUR: + return GetPixelColorWithOverflow((long)(x+0.5f), (long)(y+0.5f), ofMethod, rplColor); + default: { + //bilinear interpolation + if (xi<-1 || xi>=head.biWidth || yi<-1 || yi>=head.biHeight) { //all 4 points are outside bounds?: + switch (ofMethod) { + case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND: + //we don't need to interpolate anything with all points outside in this case + return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor); + default: + //recalculate coordinates and use faster method later on + OverflowCoordinates(x,y,ofMethod); + xi=(int)(x); if (x<0) xi--; //x and/or y have changed ... recalculate xi and yi + yi=(int)(y); if (y<0) yi--; + }//switch + }//if + //get four neighbouring pixels + if ((xi+1)=0 && (yi+1)=0 && head.biClrUsed==0) { + //all pixels are inside RGB24 image... optimize reading (and use fixed point arithmetic) + WORD wt1=(WORD)((x-xi)*256.0f), wt2=(WORD)((y-yi)*256.0f); + WORD wd=wt1*wt2>>8; + WORD wb=wt1-wd; + WORD wc=wt2-wd; + WORD wa=256-wt1-wc; + WORD wrr,wgg,wbb; + BYTE *pxptr=(BYTE*)info.pImage+yi*info.dwEffWidth+xi*3; + wbb=wa*(*pxptr++); wgg=wa*(*pxptr++); wrr=wa*(*pxptr++); + wbb+=wb*(*pxptr++); wgg+=wb*(*pxptr++); wrr+=wb*(*pxptr); + pxptr+=(info.dwEffWidth-5); //move to next row + wbb+=wc*(*pxptr++); wgg+=wc*(*pxptr++); wrr+=wc*(*pxptr++); + wbb+=wd*(*pxptr++); wgg+=wd*(*pxptr++); wrr+=wd*(*pxptr); + color.rgbRed=(BYTE) (wrr>>8); color.rgbGreen=(BYTE) (wgg>>8); color.rgbBlue=(BYTE) (wbb>>8); +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha) { + WORD waa; + //image has alpha layer... we have to do the same for alpha data + pxptr=AlphaGetPointer(xi,yi); //pointer to first byte + waa=wa*(*pxptr++); waa+=wb*(*pxptr); //first two pixels + pxptr+=(head.biWidth-1); //move to next row + waa+=wc*(*pxptr++); waa+=wd*(*pxptr); //and second row pixels + color.rgbReserved=(BYTE) (waa>>8); + } else +#endif + { //Alpha not supported or no alpha at all + color.rgbReserved = 0; + } + return color; + } else { + //default (slower) way to get pixels (not RGB24 or some pixels out of borders) + float t1=x-xi, t2=y-yi; + float d=t1*t2; + float b=t1-d; + float c=t2-d; + float a=1-t1-c; + RGBQUAD rgb11,rgb21,rgb12,rgb22; + rgb11=GetPixelColorWithOverflow(xi, yi, ofMethod, rplColor); + rgb21=GetPixelColorWithOverflow(xi+1, yi, ofMethod, rplColor); + rgb12=GetPixelColorWithOverflow(xi, yi+1, ofMethod, rplColor); + rgb22=GetPixelColorWithOverflow(xi+1, yi+1, ofMethod, rplColor); + //calculate linear interpolation + color.rgbRed=(BYTE) (a*rgb11.rgbRed+b*rgb21.rgbRed+c*rgb12.rgbRed+d*rgb22.rgbRed); + color.rgbGreen=(BYTE) (a*rgb11.rgbGreen+b*rgb21.rgbGreen+c*rgb12.rgbGreen+d*rgb22.rgbGreen); + color.rgbBlue=(BYTE) (a*rgb11.rgbBlue+b*rgb21.rgbBlue+c*rgb12.rgbBlue+d*rgb22.rgbBlue); +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) + color.rgbReserved=(BYTE) (a*rgb11.rgbReserved+b*rgb21.rgbReserved+c*rgb12.rgbReserved+d*rgb22.rgbReserved); + else +#endif + { //Alpha not supported or no alpha at all + color.rgbReserved = 0; + } + return color; + }//if + }//default + case IM_BICUBIC: + case IM_BICUBIC2: + case IM_BSPLINE: + case IM_BOX: + case IM_HERMITE: + case IM_HAMMING: + case IM_SINC: + case IM_BLACKMAN: + case IM_BESSEL: + case IM_GAUSSIAN: + case IM_QUADRATIC: + case IM_MITCHELL: + case IM_CATROM: + //bicubic interpolation(s) + if (((xi+2)<0) || ((xi-1)>=head.biWidth) || ((yi+2)<0) || ((yi-1)>=head.biHeight)) { //all points are outside bounds?: + switch (ofMethod) { + case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND: + //we don't need to interpolate anything with all points outside in this case + return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor); + break; + default: + //recalculate coordinates and use faster method later on + OverflowCoordinates(x,y,ofMethod); + xi=(int)(x); if (x<0) xi--; //x and/or y have changed ... recalculate xi and yi + yi=(int)(y); if (y<0) yi--; + }//switch + }//if + + //some variables needed from here on + int xii,yii; //x any y integer indexes for loops + float kernel, kernelyc; //kernel cache + float kernelx[12], kernely[4]; //precalculated kernel values + float rr,gg,bb,aa; //accumulated color values + //calculate multiplication factors for all pixels + int i; + switch (inMethod) { + case IM_BICUBIC: + for (i=0; i<4; i++) { + kernelx[i]=KernelCubic((float)(xi+i-1-x)); + kernely[i]=KernelCubic((float)(yi+i-1-y)); + }//for i + break; + case IM_BICUBIC2: + for (i=0; i<4; i++) { + kernelx[i]=KernelGeneralizedCubic((float)(xi+i-1-x), -0.5); + kernely[i]=KernelGeneralizedCubic((float)(yi+i-1-y), -0.5); + }//for i + break; + case IM_BSPLINE: + for (i=0; i<4; i++) { + kernelx[i]=KernelBSpline((float)(xi+i-1-x)); + kernely[i]=KernelBSpline((float)(yi+i-1-y)); + }//for i + break; + case IM_BOX: + for (i=0; i<4; i++) { + kernelx[i]=KernelBox((float)(xi+i-1-x)); + kernely[i]=KernelBox((float)(yi+i-1-y)); + }//for i + break; + case IM_HERMITE: + for (i=0; i<4; i++) { + kernelx[i]=KernelHermite((float)(xi+i-1-x)); + kernely[i]=KernelHermite((float)(yi+i-1-y)); + }//for i + break; + case IM_HAMMING: + for (i=0; i<4; i++) { + kernelx[i]=KernelHamming((float)(xi+i-1-x)); + kernely[i]=KernelHamming((float)(yi+i-1-y)); + }//for i + break; + case IM_SINC: + for (i=0; i<4; i++) { + kernelx[i]=KernelSinc((float)(xi+i-1-x)); + kernely[i]=KernelSinc((float)(yi+i-1-y)); + }//for i + break; + case IM_BLACKMAN: + for (i=0; i<4; i++) { + kernelx[i]=KernelBlackman((float)(xi+i-1-x)); + kernely[i]=KernelBlackman((float)(yi+i-1-y)); + }//for i + break; + case IM_BESSEL: + for (i=0; i<4; i++) { + kernelx[i]=KernelBessel((float)(xi+i-1-x)); + kernely[i]=KernelBessel((float)(yi+i-1-y)); + }//for i + break; + case IM_GAUSSIAN: + for (i=0; i<4; i++) { + kernelx[i]=KernelGaussian((float)(xi+i-1-x)); + kernely[i]=KernelGaussian((float)(yi+i-1-y)); + }//for i + break; + case IM_QUADRATIC: + for (i=0; i<4; i++) { + kernelx[i]=KernelQuadratic((float)(xi+i-1-x)); + kernely[i]=KernelQuadratic((float)(yi+i-1-y)); + }//for i + break; + case IM_MITCHELL: + for (i=0; i<4; i++) { + kernelx[i]=KernelMitchell((float)(xi+i-1-x)); + kernely[i]=KernelMitchell((float)(yi+i-1-y)); + }//for i + break; + case IM_CATROM: + for (i=0; i<4; i++) { + kernelx[i]=KernelCatrom((float)(xi+i-1-x)); + kernely[i]=KernelCatrom((float)(yi+i-1-y)); + }//for i + break; + }//switch + rr=gg=bb=aa=0; + if (((xi+2)=1 && ((yi+2)=1) && !IsIndexed()) { + //optimized interpolation (faster pixel reads) for RGB24 images with all pixels inside bounds + BYTE *pxptr, *pxptra; + for (yii=yi-1; yii255) rr=255; if (rr<0) rr=0; color.rgbRed=(BYTE) rr; + if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg; + if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb; +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) { + if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa; + } else +#endif + { //Alpha not supported or no alpha at all + color.rgbReserved = 0; + } + return color; + case IM_LANCZOS: + //lanczos window (16*16) sinc interpolation + if (((xi+6)<0) || ((xi-5)>=head.biWidth) || ((yi+6)<0) || ((yi-5)>=head.biHeight)) { + //all points are outside bounds + switch (ofMethod) { + case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND: + //we don't need to interpolate anything with all points outside in this case + return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor); + break; + default: + //recalculate coordinates and use faster method later on + OverflowCoordinates(x,y,ofMethod); + xi=(int)(x); if (x<0) xi--; //x and/or y have changed ... recalculate xi and yi + yi=(int)(y); if (y<0) yi--; + }//switch + }//if + + for (xii=xi-5; xii=0) && ((yi+6)=0) && !IsIndexed()) { + //optimized interpolation (faster pixel reads) for RGB24 images with all pixels inside bounds + BYTE *pxptr, *pxptra; + for (yii=yi-5; yii255) rr=255; if (rr<0) rr=0; color.rgbRed=(BYTE) rr; + if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg; + if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb; +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) { + if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa; + } else +#endif + { //Alpha not supported or no alpha at all + color.rgbReserved = 0; + } + return color; + }//switch +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Helper function for GetAreaColorInterpolated. + * Adds 'surf' portion of image pixel with color 'color' to (rr,gg,bb,aa). + */ +void CxImage::AddAveragingCont(RGBQUAD const &color, float const surf, float &rr, float &gg, float &bb, float &aa) +{ + rr+=color.rgbRed*surf; + gg+=color.rgbGreen*surf; + bb+=color.rgbBlue*surf; +#if CXIMAGE_SUPPORT_ALPHA + aa+=color.rgbReserved*surf; +#endif +} +//////////////////////////////////////////////////////////////////////////////// +/** + * This method is similar to GetPixelColorInterpolated, but this method also properly handles + * subsampling. + * If you need to sample original image with interval of more than 1 pixel (as when shrinking an image), + * you should use this method instead of GetPixelColorInterpolated or aliasing will occur. + * When area width and height are both less than pixel, this method gets pixel color by interpolating + * color of frame center with selected (inMethod) interpolation by calling GetPixelColorInterpolated. + * If width and height are more than 1, method calculates color by averaging color of pixels within area. + * Interpolation method is not used in this case. Pixel color is interpolated by averaging instead. + * If only one of both is more than 1, method uses combination of interpolation and averaging. + * Chosen interpolation method is used, but since it is averaged later on, there is little difference + * between IM_BILINEAR (perhaps best for this case) and better methods. IM_NEAREST_NEIGHBOUR again + * leads to aliasing artifacts. + * This method is a bit slower than GetPixelColorInterpolated and when aliasing is not a problem, you should + * simply use the later. + * + * \param xc, yc - center of (rectangular) area + * \param w, h - width and height of area + * \param inMethod - interpolation method that is used, when interpolation is used (see above) + * \param ofMethod - overflow method used when retrieving individual pixel colors + * \param rplColor - replacement colour to use, in OM_COLOR + * + * \author ***bd*** 2.2004 + */ +RGBQUAD CxImage::GetAreaColorInterpolated( + float const xc, float const yc, float const w, float const h, + InterpolationMethod const inMethod, + OverflowMethod const ofMethod, + RGBQUAD* const rplColor) +{ + RGBQUAD color; //calculated colour + + if (h<=1 && w<=1) { + //both width and height are less than one... we will use interpolation of center point + return GetPixelColorInterpolated(xc, yc, inMethod, ofMethod, rplColor); + } else { + //area is wider and/or taller than one pixel: + CxRect2 area(xc-w/2.0f, yc-h/2.0f, xc+w/2.0f, yc+h/2.0f); //area + int xi1=(int)(area.botLeft.x+0.49999999f); //low x + int yi1=(int)(area.botLeft.y+0.49999999f); //low y + + + int xi2=(int)(area.topRight.x+0.5f); //top x + int yi2=(int)(area.topRight.y+0.5f); //top y (for loops) + + float rr,gg,bb,aa; //red, green, blue and alpha components + rr=gg=bb=aa=0; + int x,y; //loop counters + float s=0; //surface of all pixels + float cps; //surface of current crosssection + if (h>1 && w>1) { + //width and height of area are greater than one pixel, so we can employ "ordinary" averaging + CxRect2 intBL, intTR; //bottom left and top right intersection + intBL=area.CrossSection(CxRect2(((float)xi1)-0.5f, ((float)yi1)-0.5f, ((float)xi1)+0.5f, ((float)yi1)+0.5f)); + intTR=area.CrossSection(CxRect2(((float)xi2)-0.5f, ((float)yi2)-0.5f, ((float)xi2)+0.5f, ((float)yi2)+0.5f)); + float wBL, wTR, hBL, hTR; + wBL=intBL.Width(); //width of bottom left pixel-area intersection + hBL=intBL.Height(); //height of bottom left... + wTR=intTR.Width(); //width of top right... + hTR=intTR.Height(); //height of top right... + + AddAveragingCont(GetPixelColorWithOverflow(xi1,yi1,ofMethod,rplColor), wBL*hBL, rr, gg, bb, aa); //bottom left pixel + AddAveragingCont(GetPixelColorWithOverflow(xi2,yi1,ofMethod,rplColor), wTR*hBL, rr, gg, bb, aa); //bottom right pixel + AddAveragingCont(GetPixelColorWithOverflow(xi1,yi2,ofMethod,rplColor), wBL*hTR, rr, gg, bb, aa); //top left pixel + AddAveragingCont(GetPixelColorWithOverflow(xi2,yi2,ofMethod,rplColor), wTR*hTR, rr, gg, bb, aa); //top right pixel + //bottom and top row + for (x=xi1+1; x255) rr=255; if (rr<0) rr=0; color.rgbRed=(BYTE) rr; + if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg; + if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb; +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) { + if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa; + }//if +#endif + }//if + return color; +} + +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBSpline(const float x) +{ + if (x>2.0f) return 0.0f; + // thanks to Kristian Kratzenstein + float a, b, c, d; + float xm1 = x - 1.0f; // Was calculatet anyway cause the "if((x-1.0f) < 0)" + float xp1 = x + 1.0f; + float xp2 = x + 2.0f; + + if ((xp2) <= 0.0f) a = 0.0f; else a = xp2*xp2*xp2; // Only float, not float -> double -> float + if ((xp1) <= 0.0f) b = 0.0f; else b = xp1*xp1*xp1; + if (x <= 0) c = 0.0f; else c = x*x*x; + if ((xm1) <= 0.0f) d = 0.0f; else d = xm1*xm1*xm1; + + return (0.16666666666666666667f * (a - (4.0f * b) + (6.0f * c) - (4.0f * d))); + + /* equivalent + if (x < -2.0) + return(0.0f); + if (x < -1.0) + return((2.0f+x)*(2.0f+x)*(2.0f+x)*0.16666666666666666667f); + if (x < 0.0) + return((4.0f+x*x*(-6.0f-3.0f*x))*0.16666666666666666667f); + if (x < 1.0) + return((4.0f+x*x*(-6.0f+3.0f*x))*0.16666666666666666667f); + if (x < 2.0) + return((2.0f-x)*(2.0f-x)*(2.0f-x)*0.16666666666666666667f); + return(0.0f); + */ +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * Bilinear interpolation kernel: + \verbatim + / + | 1-t , if 0 <= t <= 1 + h(t) = | t+1 , if -1 <= t < 0 + | 0 , otherwise + \ + \endverbatim + * ***bd*** 2.2004 + */ +float CxImage::KernelLinear(const float t) +{ +// if (0<=t && t<=1) return 1-t; +// if (-1<=t && t<0) return 1+t; +// return 0; + + // + if (t < -1.0f) + return 0.0f; + if (t < 0.0f) + return 1.0f+t; + if (t < 1.0f) + return 1.0f-t; + return 0.0f; +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * Bicubic interpolation kernel (a=-1): + \verbatim + / + | 1-2|t|**2+|t|**3 , if |t| < 1 + h(t) = | 4-8|t|+5|t|**2-|t|**3 , if 1<=|t|<2 + | 0 , otherwise + \ + \endverbatim + * ***bd*** 2.2004 + */ +float CxImage::KernelCubic(const float t) +{ + float abs_t = (float)fabs(t); + float abs_t_sq = abs_t * abs_t; + if (abs_t<1) return 1-2*abs_t_sq+abs_t_sq*abs_t; + if (abs_t<2) return 4 - 8*abs_t +5*abs_t_sq - abs_t_sq*abs_t; + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * Bicubic kernel (for a=-1 it is the same as BicubicKernel): + \verbatim + / + | (a+2)|t|**3 - (a+3)|t|**2 + 1 , |t| <= 1 + h(t) = | a|t|**3 - 5a|t|**2 + 8a|t| - 4a , 1 < |t| <= 2 + | 0 , otherwise + \ + \endverbatim + * Often used values for a are -1 and -1/2. + */ +float CxImage::KernelGeneralizedCubic(const float t, const float a) +{ + float abs_t = (float)fabs(t); + float abs_t_sq = abs_t * abs_t; + if (abs_t<1) return (a+2)*abs_t_sq*abs_t - (a+3)*abs_t_sq + 1; + if (abs_t<2) return a*abs_t_sq*abs_t - 5*a*abs_t_sq + 8*a*abs_t - 4*a; + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * Lanczos windowed sinc interpolation kernel with radius r. + \verbatim + / + h(t) = | sinc(t)*sinc(t/r) , if |t| r) return 0; + if (t==0) return 1; + float pit=PI*t; + float pitd=pit/r; + return (float)((sin(pit)/pit) * (sin(pitd)/pitd)); +} + +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBox(const float x) +{ + if (x < -0.5f) + return 0.0f; + if (x < 0.5f) + return 1.0f; + return 0.0f; +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelHermite(const float x) +{ + if (x < -1.0f) + return 0.0f; + if (x < 0.0f) + return (-2.0f*x-3.0f)*x*x+1.0f; + if (x < 1.0f) + return (2.0f*x-3.0f)*x*x+1.0f; + return 0.0f; +// if (fabs(x)>1) return 0.0f; +// return(0.5f+0.5f*(float)cos(PI*x)); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelHamming(const float x) +{ + if (x < -1.0f) + return 0.0f; + if (x < 0.0f) + return 0.92f*(-2.0f*x-3.0f)*x*x+1.0f; + if (x < 1.0f) + return 0.92f*(2.0f*x-3.0f)*x*x+1.0f; + return 0.0f; +// if (fabs(x)>1) return 0.0f; +// return(0.54f+0.46f*(float)cos(PI*x)); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelSinc(const float x) +{ + if (x == 0.0) + return(1.0); + return((float)sin(PI*x)/(PI*x)); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBlackman(const float x) +{ + //if (fabs(x)>1) return 0.0f; + return (0.42f+0.5f*(float)cos(PI*x)+0.08f*(float)cos(2.0f*PI*x)); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBessel_J1(const float x) +{ + double p, q; + + register long i; + + static const double + Pone[] = + { + 0.581199354001606143928050809e+21, + -0.6672106568924916298020941484e+20, + 0.2316433580634002297931815435e+19, + -0.3588817569910106050743641413e+17, + 0.2908795263834775409737601689e+15, + -0.1322983480332126453125473247e+13, + 0.3413234182301700539091292655e+10, + -0.4695753530642995859767162166e+7, + 0.270112271089232341485679099e+4 + }, + Qone[] = + { + 0.11623987080032122878585294e+22, + 0.1185770712190320999837113348e+20, + 0.6092061398917521746105196863e+17, + 0.2081661221307607351240184229e+15, + 0.5243710262167649715406728642e+12, + 0.1013863514358673989967045588e+10, + 0.1501793594998585505921097578e+7, + 0.1606931573481487801970916749e+4, + 0.1e+1 + }; + + p = Pone[8]; + q = Qone[8]; + for (i=7; i >= 0; i--) + { + p = p*x*x+Pone[i]; + q = q*x*x+Qone[i]; + } + return (float)(p/q); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBessel_P1(const float x) +{ + double p, q; + + register long i; + + static const double + Pone[] = + { + 0.352246649133679798341724373e+5, + 0.62758845247161281269005675e+5, + 0.313539631109159574238669888e+5, + 0.49854832060594338434500455e+4, + 0.2111529182853962382105718e+3, + 0.12571716929145341558495e+1 + }, + Qone[] = + { + 0.352246649133679798068390431e+5, + 0.626943469593560511888833731e+5, + 0.312404063819041039923015703e+5, + 0.4930396490181088979386097e+4, + 0.2030775189134759322293574e+3, + 0.1e+1 + }; + + p = Pone[5]; + q = Qone[5]; + for (i=4; i >= 0; i--) + { + p = p*(8.0/x)*(8.0/x)+Pone[i]; + q = q*(8.0/x)*(8.0/x)+Qone[i]; + } + return (float)(p/q); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBessel_Q1(const float x) +{ + double p, q; + + register long i; + + static const double + Pone[] = + { + 0.3511751914303552822533318e+3, + 0.7210391804904475039280863e+3, + 0.4259873011654442389886993e+3, + 0.831898957673850827325226e+2, + 0.45681716295512267064405e+1, + 0.3532840052740123642735e-1 + }, + Qone[] = + { + 0.74917374171809127714519505e+4, + 0.154141773392650970499848051e+5, + 0.91522317015169922705904727e+4, + 0.18111867005523513506724158e+4, + 0.1038187585462133728776636e+3, + 0.1e+1 + }; + + p = Pone[5]; + q = Qone[5]; + for (i=4; i >= 0; i--) + { + p = p*(8.0/x)*(8.0/x)+Pone[i]; + q = q*(8.0/x)*(8.0/x)+Qone[i]; + } + return (float)(p/q); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBessel_Order1(float x) +{ + float p, q; + + if (x == 0.0) + return (0.0f); + p = x; + if (x < 0.0) + x=(-x); + if (x < 8.0) + return(p*KernelBessel_J1(x)); + q = (float)sqrt(2.0f/(PI*x))*(float)(KernelBessel_P1(x)*(1.0f/sqrt(2.0f)*(sin(x)-cos(x)))-8.0f/x*KernelBessel_Q1(x)* + (-1.0f/sqrt(2.0f)*(sin(x)+cos(x)))); + if (p < 0.0f) + q = (-q); + return (q); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelBessel(const float x) +{ + if (x == 0.0f) + return(PI/4.0f); + return(KernelBessel_Order1(PI*x)/(2.0f*x)); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelGaussian(const float x) +{ + return (float)(exp(-2.0f*x*x)*0.79788456080287f/*sqrt(2.0f/PI)*/); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelQuadratic(const float x) +{ + if (x < -1.5f) + return(0.0f); + if (x < -0.5f) + return(0.5f*(x+1.5f)*(x+1.5f)); + if (x < 0.5f) + return(0.75f-x*x); + if (x < 1.5f) + return(0.5f*(x-1.5f)*(x-1.5f)); + return(0.0f); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelMitchell(const float x) +{ +#define KM_B (1.0f/3.0f) +#define KM_C (1.0f/3.0f) +#define KM_P0 (( 6.0f - 2.0f * KM_B ) / 6.0f) +#define KM_P2 ((-18.0f + 12.0f * KM_B + 6.0f * KM_C) / 6.0f) +#define KM_P3 (( 12.0f - 9.0f * KM_B - 6.0f * KM_C) / 6.0f) +#define KM_Q0 (( 8.0f * KM_B + 24.0f * KM_C) / 6.0f) +#define KM_Q1 ((-12.0f * KM_B - 48.0f * KM_C) / 6.0f) +#define KM_Q2 (( 6.0f * KM_B + 30.0f * KM_C) / 6.0f) +#define KM_Q3 (( -1.0f * KM_B - 6.0f * KM_C) / 6.0f) + + if (x < -2.0) + return(0.0f); + if (x < -1.0) + return(KM_Q0-x*(KM_Q1-x*(KM_Q2-x*KM_Q3))); + if (x < 0.0f) + return(KM_P0+x*x*(KM_P2-x*KM_P3)); + if (x < 1.0f) + return(KM_P0+x*x*(KM_P2+x*KM_P3)); + if (x < 2.0f) + return(KM_Q0+x*(KM_Q1+x*(KM_Q2+x*KM_Q3))); + return(0.0f); +} +//////////////////////////////////////////////////////////////////////////////// +float CxImage::KernelCatrom(const float x) +{ + if (x < -2.0) + return(0.0f); + if (x < -1.0) + return(0.5f*(4.0f+x*(8.0f+x*(5.0f+x)))); + if (x < 0.0) + return(0.5f*(2.0f+x*x*(-5.0f-3.0f*x))); + if (x < 1.0) + return(0.5f*(2.0f+x*x*(-5.0f+3.0f*x))); + if (x < 2.0) + return(0.5f*(4.0f+x*(-8.0f+x*(5.0f-x)))); + return(0.0f); +} +//////////////////////////////////////////////////////////////////////////////// + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaiter.h ./win32/dependencies/cximage/ximaiter.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaiter.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximaiter.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,252 @@ +/* + * File: ImaIter.h + * Purpose: Declaration of the Platform Independent Image Base Class + * Author: Alejandro Aguilar Sierra + * Created: 1995 + * Copyright: (c) 1995, Alejandro Aguilar Sierra + * + * 07/08/2001 Davide Pizzolato - www.xdp.it + * - removed slow loops + * - added safe checks + * + * Permission is given by the author to freely redistribute and include + * this code in any program as long as this credit is given where due. + * + * COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY + * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES + * THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE + * OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED + * CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT + * THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY + * SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL + * PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER. + * + * Use at your own risk! + * ========================================================== + */ + +#if !defined(__ImaIter_h) +#define __ImaIter_h + +#include "ximage.h" +#include "ximadef.h" + +class CImageIterator +{ +friend class CxImage; +protected: + int Itx, Ity; // Counters + int Stepx, Stepy; + BYTE* IterImage; // Image pointer + CxImage *ima; +public: + // Constructors + CImageIterator ( void ); + CImageIterator ( CxImage *image ); + operator CxImage* (); + + // Iterators + BOOL ItOK (); + void Reset (); + void Upset (); + void SetRow(BYTE *buf, int n); + void GetRow(BYTE *buf, int n); + BYTE GetByte( ) { return IterImage[Itx]; } + void SetByte(BYTE b) { IterImage[Itx] = b; } + BYTE* GetRow(void); + BYTE* GetRow(int n); + BOOL NextRow(); + BOOL PrevRow(); + BOOL NextByte(); + BOOL PrevByte(); + + void SetSteps(int x, int y=0) { Stepx = x; Stepy = y; } + void GetSteps(int *x, int *y) { *x = Stepx; *y = Stepy; } + BOOL NextStep(); + BOOL PrevStep(); + + void SetY(int y); /* AD - for interlace */ + int GetY() {return Ity;} + BOOL GetCol(BYTE* pCol, DWORD x); + BOOL SetCol(BYTE* pCol, DWORD x); +}; + +///////////////////////////////////////////////////////////////////// +inline +CImageIterator::CImageIterator(void) +{ + ima = 0; + IterImage = 0; + Itx = Ity = 0; + Stepx = Stepy = 0; +} +///////////////////////////////////////////////////////////////////// +inline +CImageIterator::CImageIterator(CxImage *imageImpl): ima(imageImpl) +{ + if (ima) IterImage = ima->GetBits(); + Itx = Ity = 0; + Stepx = Stepy = 0; +} +///////////////////////////////////////////////////////////////////// +inline +CImageIterator::operator CxImage* () +{ + return ima; +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::ItOK () +{ + if (ima) return ima->IsInside(Itx, Ity); + else return FALSE; +} +///////////////////////////////////////////////////////////////////// +inline void CImageIterator::Reset() +{ + if (ima) IterImage = ima->GetBits(); + else IterImage=0; + Itx = Ity = 0; +} +///////////////////////////////////////////////////////////////////// +inline void CImageIterator::Upset() +{ + Itx = 0; + Ity = ima->GetHeight()-1; + IterImage = ima->GetBits() + ima->GetEffWidth()*(ima->GetHeight()-1); +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::NextRow() +{ + if (++Ity >= (int)ima->GetHeight()) return 0; + IterImage += ima->GetEffWidth(); + return 1; +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::PrevRow() +{ + if (--Ity < 0) return 0; + IterImage -= ima->GetEffWidth(); + return 1; +} +/* AD - for interlace */ +inline void CImageIterator::SetY(int y) +{ + if ((y < 0) || (y > (int)ima->GetHeight())) return; + Ity = y; + IterImage = ima->GetBits() + ima->GetEffWidth()*y; +} +///////////////////////////////////////////////////////////////////// +inline void CImageIterator::SetRow(BYTE *buf, int n) +{ + if (n<0) n = (int)ima->GetEffWidth(); + else n = min(n,(int)ima->GetEffWidth()); + + if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0)) memcpy(IterImage,buf,n); +} +///////////////////////////////////////////////////////////////////// +inline void CImageIterator::GetRow(BYTE *buf, int n) +{ + if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0)) memcpy(buf,IterImage,n); +} +///////////////////////////////////////////////////////////////////// +inline BYTE* CImageIterator::GetRow() +{ + return IterImage; +} +///////////////////////////////////////////////////////////////////// +inline BYTE* CImageIterator::GetRow(int n) +{ + SetY(n); + return IterImage; +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::NextByte() +{ + if (++Itx < (int)ima->GetEffWidth()) return 1; + else + if (++Ity < (int)ima->GetHeight()){ + IterImage += ima->GetEffWidth(); + Itx = 0; + return 1; + } else + return 0; +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::PrevByte() +{ + if (--Itx >= 0) return 1; + else + if (--Ity >= 0){ + IterImage -= ima->GetEffWidth(); + Itx = 0; + return 1; + } else + return 0; +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::NextStep() +{ + Itx += Stepx; + if (Itx < (int)ima->GetEffWidth()) return 1; + else { + Ity += Stepy; + if (Ity < (int)ima->GetHeight()){ + IterImage += ima->GetEffWidth(); + Itx = 0; + return 1; + } else + return 0; + } +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::PrevStep() +{ + Itx -= Stepx; + if (Itx >= 0) return 1; + else { + Ity -= Stepy; + if (Ity >= 0 && Ity < (int)ima->GetHeight()) { + IterImage -= ima->GetEffWidth(); + Itx = 0; + return 1; + } else + return 0; + } +} +///////////////////////////////////////////////////////////////////// +inline BOOL CImageIterator::GetCol(BYTE* pCol, DWORD x) +{ + if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth())) + return 0; + DWORD h = ima->GetHeight(); + //DWORD line = ima->GetEffWidth(); + BYTE bytes = ima->GetBpp()>>3; + BYTE* pSrc; + for (DWORD y=0;yGetBits(y) + x*bytes; + for (BYTE w=0;wGetBpp()<8)||(x>=ima->GetWidth())) + return 0; + DWORD h = ima->GetHeight(); + //DWORD line = ima->GetEffWidth(); + BYTE bytes = ima->GetBpp()>>3; + BYTE* pSrc; + for (DWORD y=0;yGetBits(y) + x*bytes; + for (BYTE w=0;wSize(); + src=(BYTE*)malloc(len); + hFile->Read(src, len, 1); + + if (!j2k_decode(src, len, &img, &cp)) { + free(src); + throw "failed to decode J2K image!"; + } + + free(src); + + if (img->numcomps==3 && + img->comps[0].dx==img->comps[1].dx && + img->comps[1].dx==img->comps[2].dx && + img->comps[0].dy==img->comps[1].dy && + img->comps[1].dy==img->comps[2].dy && + img->comps[0].prec==img->comps[1].prec && + img->comps[1].prec==img->comps[2].prec) + { + w=CEILDIV(img->x1-img->x0, img->comps[0].dx); + h=CEILDIV(img->y1-img->y0, img->comps[0].dy); + max=(1<comps[0].prec)-1; + + Create(w,h,24,CXIMAGE_FORMAT_J2K); + + RGBQUAD c; + for (i=0,y=0; ycomps[0].data[i]; + c.rgbGreen = img->comps[1].data[i]; + c.rgbBlue = img->comps[2].data[i]; + SetPixelColor(x,h-1-y,c); + } + } + } else { + int compno; + info.nNumFrames = img->numcomps; + if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)){ + j2k_destroy(&img,&cp); + throw "wrong frame!"; + } + for (compno=0; compno<=info.nFrame; compno++) { + w=CEILDIV(img->x1-img->x0, img->comps[compno].dx); + h=CEILDIV(img->y1-img->y0, img->comps[compno].dy); + max=(1<comps[compno].prec)-1; + Create(w,h,8,CXIMAGE_FORMAT_J2K); + SetGrayPalette(); + for (i=0,y=0; ycomps[compno].data[i]); + } + } + } + } + + j2k_destroy(&img,&cp); + + } catch (char *message) { + strncpy(info.szLastError,message,255); + return FALSE; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageJ2K::Encode(CxFile * hFile) +{ + if (EncodeSafeCheck(hFile)) return false; + + if (head.biClrUsed!=0 && !IsGrayScale()){ + strcpy(info.szLastError,"J2K can save only RGB or GrayScale images"); + return false; + } + + int i,x,y; + j2k_image_t *img; + j2k_cp_t *cp; + j2k_tcp_t *tcp; + j2k_tccp_t *tccp; + + img = (j2k_image_t *)calloc(sizeof(j2k_image_t),1); + cp = (j2k_cp_t *)calloc(sizeof(j2k_cp_t),1); + + cp->tx0=0; cp->ty0=0; + cp->tw=1; cp->th=1; + cp->tcps=(j2k_tcp_t*)calloc(sizeof(j2k_tcp_t),1); + tcp=&cp->tcps[0]; + + long w=head.biWidth; + long h=head.biHeight; + + tcp->numlayers=1; + for (i=0;inumlayers;i++) tcp->rates[i]=(w*h*GetJpegQuality())/600; + + + if (IsGrayScale()) { + img->x0=0; + img->y0=0; + img->x1=w; + img->y1=h; + img->numcomps=1; + img->comps=(j2k_comp_t*)calloc(sizeof(j2k_comp_t),1); + img->comps[0].data=(int*)calloc(w*h*sizeof(int),1); + img->comps[0].prec=8; + img->comps[0].sgnd=0; + img->comps[0].dx=1; + img->comps[0].dy=1; + for (i=0,y=0; ycomps[0].data[i]=GetPixelIndex(x,h-1-y); + } + } + } else if (!IsIndexed()) { + img->x0=0; + img->y0=0; + img->x1=w; + img->y1=h; + img->numcomps=3; + img->comps=(j2k_comp_t*)calloc(img->numcomps*sizeof(j2k_comp_t),1); + for (i=0; inumcomps; i++) { + img->comps[i].data=(int*)calloc(w*h*sizeof(int),1); + img->comps[i].prec=8; + img->comps[i].sgnd=0; + img->comps[i].dx=1; + img->comps[i].dy=1; + } + RGBQUAD c; + for (i=0,y=0; ycomps[0].data[i]=c.rgbRed; + img->comps[1].data[i]=c.rgbGreen; + img->comps[2].data[i]=c.rgbBlue; + } + } + } else { + return 0; + } + + cp->tdx=img->x1-img->x0; + cp->tdy=img->y1-img->y0; + + tcp->csty=0; + tcp->prg=0; + tcp->mct=img->numcomps==3?1:0; + tcp->tccps=(j2k_tccp_t*)calloc(img->numcomps*sizeof(j2k_tccp_t),1); + + int ir=0; /* or 1 ???*/ + + for (i=0; inumcomps; i++) { + tccp=&tcp->tccps[i]; + tccp->csty=0; + tccp->numresolutions=6; + tccp->cblkw=6; + tccp->cblkh=6; + tccp->cblksty=0; + tccp->qmfbid=ir?0:1; + tccp->qntsty=ir?J2K_CCP_QNTSTY_SEQNT:J2K_CCP_QNTSTY_NOQNT; + tccp->numgbits=2; + tccp->roishift=0; + j2k_calc_explicit_stepsizes(tccp, img->comps[i].prec); + } + + BYTE* dest=(BYTE*)calloc(tcp->rates[tcp->numlayers-1]+2,1); + long len = j2k_encode(img, cp, dest, tcp->rates[tcp->numlayers-1]+2); + + if (len==0) { + strcpy(info.szLastError,"J2K failed to encode image"); + } else { + hFile->Write(dest, len, 1); + } + + free(dest); + j2k_destroy(&img,&cp); + + return (len!=0); +} +//////////////////////////////////////////////////////////////////////////////// + +static const double dwt_norms_97[4][10]={ + {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2} +}; + +//////////////////////////////////////////////////////////////////////////////// +void CxImageJ2K::j2k_calc_explicit_stepsizes(j2k_tccp_t *tccp, int prec) { + int numbands, bandno; + numbands=3*tccp->numresolutions-2; + for (bandno=0; bandnonumresolutions-1-resno; + gain=tccp->qmfbid==0?0:(orient==0?0:(orient==1||orient==2?1:2)); + if (tccp->qntsty==J2K_CCP_QNTSTY_NOQNT) { + stepsize=1.0; + } else { + double norm=dwt_norms_97[orient][level]; + stepsize=(1<<(gain+1))/norm; + } + j2k_encode_stepsize((int)floor(stepsize*8192.0), prec+gain, &tccp->stepsizes[bandno].expn, &tccp->stepsizes[bandno].mant); + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageJ2K::j2k_encode_stepsize(int stepsize, int numbps, int *expn, int *mant) { + int p, n; + p=j2k_floorlog2(stepsize)-13; + n=11-j2k_floorlog2(stepsize); + *mant=(n<0?stepsize>>-n:stepsize<1; l++) { + a>>=1; + } + return l; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_J2K diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaj2k.h ./win32/dependencies/cximage/ximaj2k.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximaj2k.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximaj2k.h 2006-08-24 07:16:02 +0900 @@ -0,0 +1,46 @@ +/* + * File: ximaj2k.h + * Purpose: J2K Image Class Loader and Writer + */ +/* ========================================================== + * CxImageJ2K (c) 04/Aug/2002 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * based on LIBJ2K Copyright (c) 2001-2002, David Janssens - All rights reserved. + * ========================================================== + */ +#if !defined(__ximaJ2K_h) +#define __ximaJ2K_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_J2K + +#define LIBJ2K_EXPORTS +extern "C" { +#include "../j2k/j2k.h" +}; + +class CxImageJ2K: public CxImage +{ +public: + CxImageJ2K(): CxImage(CXIMAGE_FORMAT_J2K) {} + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_J2K);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_J2K);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE +protected: + void j2k_calc_explicit_stepsizes(j2k_tccp_t *tccp, int prec); + void j2k_encode_stepsize(int stepsize, int numbps, int *expn, int *mant); + int j2k_floorlog2(int a); +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajas.cpp ./win32/dependencies/cximage/ximajas.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajas.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximajas.cpp 2006-08-24 07:16:02 +0900 @@ -0,0 +1,265 @@ +/* + * File: ximajas.cpp + * Purpose: Platform Independent JasPer Image Class Loader and Writer + * 12/Apr/2003 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximajas.h" + +#if CXIMAGE_SUPPORT_JASPER + +//////////////////////////////////////////////////////////////////////////////// +bool CxImageJAS::Decode(CxFile *hFile, DWORD imagetype) +{ + if (hFile == NULL) return false; + + jas_image_t *image=0; + jas_stream_t *in=0; + jas_matrix_t **bufs=0; + long i,error=0; + //jas_setdbglevel(0); + + try + { + if (jas_init()) + throw "cannot initialize jasper"; + + if (!(in = jas_stream_fdopen(0, "rb"))) + throw "error: cannot open standard input"; + + CxFileJas src(hFile,in); + + if (!(image = jas_image_decode(in, -1, 0))) + throw "error: cannot load image data"; + + long x,y,w,h,depth,cmptno; + + w = jas_image_cmptwidth(image,0); + h = jas_image_cmptheight(image,0); + depth = jas_image_cmptprec(image,0); + + if (image->numcmpts_ > 64 || image->numcmpts_ < 0) + throw "error: too much components"; + + if (depth!=1 && depth!=4 && depth!=8){ + jas_image_t *newimage; + jas_cmprof_t *outprof; + //jas_eprintf("forcing conversion to sRGB\n"); + if (!(outprof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) { + throw "cannot create sRGB profile"; + } + if (!(newimage = jas_image_chclrspc(image, outprof, JAS_CMXFORM_INTENT_PER))) { + throw "cannot convert to sRGB"; + } + jas_image_destroy(image); + jas_cmprof_destroy(outprof); + image = newimage; + } + + bufs = (jas_matrix_t **)calloc(image->numcmpts_, sizeof(jas_matrix_t**)); + for (i = 0; i < image->numcmpts_; ++i) { + if (!(bufs[i] = jas_matrix_create(1, w))) { + throw "error: cannot allocate memory"; + } + } + + if (image->numcmpts_==3 && + image->cmpts_[0]->width_ == image->cmpts_[1]->width_ && + image->cmpts_[1]->width_ == image->cmpts_[2]->width_ && + image->cmpts_[0]->height_ == image->cmpts_[1]->height_ && + image->cmpts_[1]->height_ == image->cmpts_[2]->height_ && + image->cmpts_[0]->prec_ == image->cmpts_[1]->prec_ && + image->cmpts_[1]->prec_ == image->cmpts_[2]->prec_ ) + { + + if(!Create(w,h,24,imagetype)) + throw "Can't allocate memory"; + + RGBQUAD c; + for (y=0; ynumcmpts_; ++cmptno) { + jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[cmptno]); + } + + for (x=0; xnumcmpts_; + if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)){ + throw "wrong frame!"; + } + for (cmptno=0; cmptno<=info.nFrame; cmptno++) { + w = jas_image_cmptwidth(image,cmptno); + h = jas_image_cmptheight(image,cmptno); + depth = jas_image_cmptprec(image,cmptno); + if (depth>8) depth=8; + if(!Create(w,h,depth,imagetype)) + throw "Can't allocate memory"; + SetGrayPalette(); + for (y=0; ynumcmpts_; ++i){ if (bufs[i]) jas_matrix_destroy(bufs[i]);} + free(bufs); + } + jas_cleanup(); + if (image) jas_image_destroy(image); + if (in) jas_stream_close(in); + return (error==0); +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageJAS::Encode(CxFile * hFile, DWORD imagetype) +{ + if (EncodeSafeCheck(hFile)) return false; + + if (head.biClrUsed!=0 && !IsGrayScale()){ + strcpy(info.szLastError,"JasPer can save only RGB or GrayScale images"); + return false; + } + + jas_image_t *image=0; + jas_stream_t *out=0; + jas_matrix_t *cmpts[3]; + long x,y,yflip,error=0; + uint_fast16_t cmptno, numcmpts; + jas_image_cmptparm_t cmptparms[3], *cmptparm; + + try + { + + if (jas_init()) + throw "cannot initialize jasper"; + + if (!(out = jas_stream_fdopen(0, "wb"))) + throw "error: cannot open standard output"; + + CxFileJas src(hFile,out); + + numcmpts = head.biClrUsed==0 ? 3 : 1; + + for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, ++cmptparm) { + cmptparm->tlx = 0; + cmptparm->tly = 0; + cmptparm->hstep = 1; + cmptparm->vstep = 1; + cmptparm->width = head.biWidth; + cmptparm->height = head.biHeight; + cmptparm->prec = 8; + cmptparm->sgnd = false; + } + + /* Create image object. */ + if (!(image = jas_image_create(numcmpts, cmptparms, JAS_CLRSPC_UNKNOWN))) + throw "error : jas_image_create"; + + if (numcmpts == 3) { + jas_image_setclrspc(image, JAS_CLRSPC_SRGB); + jas_image_setcmpttype(image, 0, + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); + jas_image_setcmpttype(image, 1, + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); + jas_image_setcmpttype(image, 2, + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); + } else { + jas_image_setclrspc(image, JAS_CLRSPC_SGRAY); + jas_image_setcmpttype(image, 0, + JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); + } + + + for (x = 0; x < numcmpts; ++x) { cmpts[x] = 0; } + /* Create temporary matrices to hold component data. */ + for (x = 0; x < numcmpts; ++x) { + if (!(cmpts[x] = jas_matrix_create(1, head.biWidth))) { + throw "error : can't allocate memory"; + } + } + + RGBQUAD c; + for (y = 0; y < head.biHeight; ++y) { + for (x = 0; x < head.biWidth; ++x) { + if (head.biClrUsed==0){ + c = GetPixelColor(x,y); + jas_matrix_setv(cmpts[0], x, c.rgbRed); + jas_matrix_setv(cmpts[1], x, c.rgbGreen); + jas_matrix_setv(cmpts[2], x, c.rgbBlue); + } else { + jas_matrix_setv(cmpts[0], x, GetPixelIndex(x,y)); + } + } + yflip = head.biHeight - 1 - y; + for (cmptno = 0; cmptno < numcmpts; ++cmptno) { + if (jas_image_writecmpt(image, cmptno, 0, yflip, head.biWidth, 1, cmpts[cmptno])) { + throw "error : jas_image_writecmpt"; + } + } + } + + char szfmt[4]; + *szfmt = '\0'; +#if CXIMAGE_SUPPORT_JP2 + if (imagetype == CXIMAGE_FORMAT_JP2) strcpy(szfmt,"jp2"); +#endif +#if CXIMAGE_SUPPORT_JPC + if (imagetype == CXIMAGE_FORMAT_JPC) strcpy(szfmt,"jpc"); +#endif +#if CXIMAGE_SUPPORT_RAS + if (imagetype == CXIMAGE_FORMAT_RAS) strcpy(szfmt,"ras"); +#endif +#if CXIMAGE_SUPPORT_PNM + if (imagetype == CXIMAGE_FORMAT_PNM) strcpy(szfmt,"pnm"); +#endif +#if CXIMAGE_SUPPORT_PGX + if (imagetype == CXIMAGE_FORMAT_PGX){ + strcpy(szfmt,"pgx"); + if (head.biClrUsed==0) throw "PGX can save only GrayScale images"; + } +#endif + int outfmt = jas_image_strtofmt(szfmt); + + char szoutopts[16]; + sprintf(szoutopts,"rate=%.3f", info.nQuality/100.0f); + + if (jas_image_encode(image, out, outfmt, szoutopts)) { + throw "error: cannot encode image\n"; + } + jas_stream_flush(out); + + } catch (char *message) { + strncpy(info.szLastError,message,255); + error = 1; + } + + for (x = 0; x < numcmpts; ++x) { if (cmpts[x]) { jas_matrix_destroy(cmpts[x]); } } + jas_cleanup(); + if (image) jas_image_destroy(image); + if (out) jas_stream_close(out); + + return (error==0); +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_JASPER + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajas.h ./win32/dependencies/cximage/ximajas.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajas.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximajas.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,84 @@ +/* + * File: ximajas.h + * Purpose: Jasper Image Class Loader and Writer + */ +/* ========================================================== + * CxImageJAS (c) 12/Apr/2003 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * based on JasPer Copyright (c) 2001-2003 Michael David Adams - All rights reserved. + * ========================================================== + */ +#if !defined(__ximaJAS_h) +#define __ximaJAS_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_JASPER + +#include "../jasper/include/jasper/jasper.h" + +class CxImageJAS: public CxImage +{ +public: + CxImageJAS(): CxImage((DWORD)0) {} // cast to DWORD + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,0);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,0);} + bool Decode(CxFile * hFile, DWORD imagetype = 0); + bool Decode(FILE *hFile, DWORD imagetype = 0) { CxIOFile file(hFile); return Decode(&file,imagetype); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile, DWORD imagetype = 0); + bool Encode(FILE *hFile, DWORD imagetype = 0) { CxIOFile file(hFile); return Encode(&file,imagetype); } +#endif // CXIMAGE_SUPPORT_ENCODE +protected: + + class CxFileJas + { + public: + CxFileJas(CxFile* pFile,jas_stream_t *stream) + { + if (stream->obj_) jas_free(stream->obj_); + stream->obj_ = pFile; + + // - cannot set the stream->ops_->functions here, + // because this overwrites a static structure in the Jasper library. + // This structure is used by Jasper for internal operations too, e.g. tempfile. + // However the ops_ pointer in the stream can be overwritten. + + //stream->ops_->close_ = JasClose; + //stream->ops_->read_ = JasRead; + //stream->ops_->seek_ = JasSeek; + //stream->ops_->write_ = JasWrite; + + jas_stream_CxFile.close_ = JasClose; + jas_stream_CxFile.read_ = JasRead; + jas_stream_CxFile.seek_ = JasSeek; + jas_stream_CxFile.write_ = JasWrite; + + stream->ops_ = &jas_stream_CxFile; + + // - end + } + static int JasRead(jas_stream_obj_t *obj, char *buf, int cnt) + { return ((CxFile*)obj)->Read(buf,1,cnt); } + static int JasWrite(jas_stream_obj_t *obj, char *buf, int cnt) + { return ((CxFile*)obj)->Write(buf,1,cnt); } + static long JasSeek(jas_stream_obj_t *obj, long offset, int origin) + { return ((CxFile*)obj)->Seek(offset,origin); } + static int JasClose(jas_stream_obj_t *obj) + { return 1; } + + // + private: + jas_stream_ops_t jas_stream_CxFile; + // - end + + }; + +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajbg.cpp ./win32/dependencies/cximage/ximajbg.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajbg.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximajbg.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,162 @@ +/* + * File: ximajbg.cpp + * Purpose: Platform Independent JBG Image Class Loader and Writer + * 18/Aug/2002 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximajbg.h" + +#if CXIMAGE_SUPPORT_JBG + +#include "ximaiter.h" + +#define JBIG_BUFSIZE 8192 + +//////////////////////////////////////////////////////////////////////////////// +bool CxImageJBG::Decode(CxFile *hFile) +{ + if (hFile == NULL) return false; + + struct jbg_dec_state jbig_state; + unsigned long xmax = 4294967295UL, ymax = 4294967295UL; + unsigned int len, cnt; + BYTE *buffer,*p; + int result; + + try + { + jbg_dec_init(&jbig_state); + jbg_dec_maxsize(&jbig_state, xmax, ymax); + + buffer = (BYTE*)malloc(JBIG_BUFSIZE); + if (!buffer) throw "Sorry, not enough memory available!"; + + result = JBG_EAGAIN; + do { + len = hFile->Read(buffer, 1, JBIG_BUFSIZE); + if (!len) break; + cnt = 0; + p = buffer; + while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) { + result = jbg_dec_in(&jbig_state, p, len, &cnt); + p += cnt; + len -= cnt; + } + } while (result == JBG_EAGAIN || result == JBG_EOK); + + if (hFile->Error()) + throw "Problem while reading input file"; + if (result != JBG_EOK && result != JBG_EOK_INTR) + throw "Problem with input file"; + + int w, h, bpp, planes, ew; + + w = jbg_dec_getwidth(&jbig_state); + h = jbg_dec_getheight(&jbig_state); + planes = jbg_dec_getplanes(&jbig_state); + bpp = (planes+7)>>3; + ew = (w + 7)>>3; + + switch (planes){ + case 1: + { + BYTE* binary_image = jbg_dec_getimage(&jbig_state, 0); + + if (!Create(w,h,1,CXIMAGE_FORMAT_JBG)) + throw "Can't allocate memory"; + + SetPaletteColor(0,255,255,255); + SetPaletteColor(1,0,0,0); + + CImageIterator iter(this); + iter.Upset(); + for (int i=0;i>3; + ew = (w + 7)>>3; + + BYTE mask; + RGBQUAD *rgb = GetPalette(); + if (CompareColors(&rgb[0],&rgb[1])<0) mask=255; else mask=0; + + BYTE *buffer = (BYTE*)malloc(ew*h*2); + if (!buffer) { + strcpy(info.szLastError,"Sorry, not enough memory available!"); + return false; + } + + for (y=0; yError()){ + strcpy(info.szLastError,"Problem while writing JBG file"); + return false; + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_JBG + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajbg.h ./win32/dependencies/cximage/ximajbg.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajbg.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximajbg.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,44 @@ +/* + * File: ximajbg.h + * Purpose: JBG Image Class Loader and Writer + */ +/* ========================================================== + * CxImageJBG (c) 18/Aug/2002 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * based on LIBJBG Copyright (c) 2002, Markus Kuhn - All rights reserved. + * ========================================================== + */ +#if !defined(__ximaJBG_h) +#define __ximaJBG_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_JBG + +extern "C" { +#include "../jbig/jbig.h" +}; + +class CxImageJBG: public CxImage +{ +public: + CxImageJBG(): CxImage(CXIMAGE_FORMAT_JBG) {} + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JBG);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JBG);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE +protected: + static void jbig_data_out(BYTE *buffer, unsigned int len, void *file) + {((CxFile*)file)->Write(buffer,len,1);} +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajpg.cpp ./win32/dependencies/cximage/ximajpg.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajpg.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximajpg.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,454 @@ +/* + * File: ximajpg.cpp + * Purpose: Platform Independent JPEG Image Class Loader and Writer + * 07/Aug/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximajpg.h" + +#if CXIMAGE_SUPPORT_JPG + +#include "../jpeg/jmorecfg.h" + +#include "ximaiter.h" + +#include + +struct jpg_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ + char* buffer; /* error message */ +}; +typedef jpg_error_mgr *jpg_error_ptr; + +//////////////////////////////////////////////////////////////////////////////// +// Here's the routine that will replace the standard error_exit method: +//////////////////////////////////////////////////////////////////////////////// +static void +ima_jpeg_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + jpg_error_ptr myerr = (jpg_error_ptr) cinfo->err; + /* Create the message */ + myerr->pub.format_message (cinfo, myerr->buffer); + /* Send it to stderr, adding a newline */ + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} +//////////////////////////////////////////////////////////////////////////////// +CxImageJPG::CxImageJPG(): CxImage(CXIMAGE_FORMAT_JPG) +{ +#if CXIMAGEJPG_SUPPORT_EXIF + m_exif = NULL; + memset(&m_exifinfo, 0, sizeof(EXIFINFO)); +#endif +} +//////////////////////////////////////////////////////////////////////////////// +CxImageJPG::~CxImageJPG() +{ +#if CXIMAGEJPG_SUPPORT_EXIF + if (m_exif) delete m_exif; +#endif +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGEJPG_SUPPORT_EXIF +bool CxImageJPG::DecodeExif(CxFile * hFile) +{ + m_exif = new CxExifInfo(&m_exifinfo); + if (m_exif){ + long pos=hFile->Tell(); + m_exif->DecodeExif(hFile); + hFile->Seek(pos,SEEK_SET); + return m_exif->m_exifinfo->IsExif; + } else { + return false; + } +} +#endif //CXIMAGEJPG_SUPPORT_EXIF +//////////////////////////////////////////////////////////////////////////////// +bool CxImageJPG::Decode(CxFile * hFile) +{ + + bool is_exif = false; +#if CXIMAGEJPG_SUPPORT_EXIF + is_exif = DecodeExif(hFile); +#endif + + CImageIterator iter(this); + /* This struct contains the JPEG decompression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + */ + struct jpeg_decompress_struct cinfo; + /* We use our private extension JPEG error handler. */ + struct jpg_error_mgr jerr; + jerr.buffer=info.szLastError; + /* More stuff */ + JSAMPARRAY buffer; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + + /* In this example we want to open the input file before doing anything else, + * so that the setjmp() error recovery below can assume the file is open. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to read binary files. + */ + + /* Step 1: allocate and initialize JPEG decompression object */ + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = ima_jpeg_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(&cinfo); + return 0; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + + /* Step 2: specify data source (eg, a file) */ + //jpeg_stdio_src(&cinfo, infile); + CxFileJpg src(hFile); + cinfo.src = &src; + + /* Step 3: read file parameters with jpeg_read_header() */ + (void) jpeg_read_header(&cinfo, TRUE); + + /* Step 4 handle decoder options*/ + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_GRAYSCALE) != 0) + cinfo.out_color_space = JCS_GRAYSCALE; + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_QUANTIZE) != 0) { + cinfo.quantize_colors = TRUE; + cinfo.desired_number_of_colors = info.nQuality; + } + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_DITHER) != 0) + cinfo.dither_mode = m_nDither; + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_ONEPASS) != 0) + cinfo.two_pass_quantize = FALSE; + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_NOSMOOTH) != 0) + cinfo.do_fancy_upsampling = FALSE; + +//: Load true color images as RGB (no quantize) +/* Step 4: set parameters for decompression */ +/* if (cinfo.jpeg_color_space!=JCS_GRAYSCALE) { + * cinfo.quantize_colors = TRUE; + * cinfo.desired_number_of_colors = 128; + *} + */ // + + // Set the scale + cinfo.scale_denom = GetJpegScale(); + + // Borrowed the idea from GIF implementation + if (info.nEscape == -1) { + // Return output dimensions only + jpeg_calc_output_dimensions(&cinfo); + head.biWidth = cinfo.output_width; + head.biHeight = cinfo.output_height; + jpeg_destroy_decompress(&cinfo); + return true; + } + + /* Step 5: Start decompressor */ + jpeg_start_decompress(&cinfo); + + /* We may need to do some setup of our own at this point before reading + * the data. After jpeg_start_decompress() we have the correct scaled + * output image dimensions available, as well as the output colormap + * if we asked for color quantization. + */ + //Create the image using output dimensions + //Create(cinfo.image_width, cinfo.image_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG); + Create(cinfo.output_width, cinfo.output_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG); + + if (!pDib) longjmp(jerr.setjmp_buffer, 1); // check if the image has been created + + if (is_exif){ +#if CXIMAGEJPG_SUPPORT_EXIF + if ((m_exifinfo.Xresolution != 0.0) && (m_exifinfo.ResolutionUnit != 0)) + SetXDPI((long)(m_exifinfo.Xresolution/m_exifinfo.ResolutionUnit)); + if ((m_exifinfo.Yresolution != 0.0) && (m_exifinfo.ResolutionUnit != 0)) + SetYDPI((long)(m_exifinfo.Yresolution/m_exifinfo.ResolutionUnit)); +#endif + } else { + if (cinfo.density_unit==2){ + SetXDPI((long)floor(cinfo.X_density * 254.0 / 10000.0 + 0.5)); + SetYDPI((long)floor(cinfo.Y_density * 254.0 / 10000.0 + 0.5)); + } else { + SetXDPI(cinfo.X_density); + SetYDPI(cinfo.Y_density); + } + } + + if (cinfo.out_color_space==JCS_GRAYSCALE){ + SetGrayPalette(); + head.biClrUsed =256; + } else { + if (cinfo.quantize_colors==TRUE){ + SetPalette(cinfo.actual_number_of_colors, cinfo.colormap[0], cinfo.colormap[1], cinfo.colormap[2]); + head.biClrUsed=cinfo.actual_number_of_colors; + } else { + head.biClrUsed=0; + } + } + + /* JSAMPLEs per row in output buffer */ + row_stride = cinfo.output_width * cinfo.output_components; + + /* Make a one-row-high sample array that will go away when done with image */ + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + /* Step 6: while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + iter.Upset(); + while (cinfo.output_scanline < cinfo.output_height) { + + if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // - cancel decoding + + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + // info.nProgress = (long)(100*cinfo.output_scanline/cinfo.output_height); + // Step 6a: CMYK->RGB */ + if ((cinfo.num_components==4)&&(cinfo.quantize_colors==FALSE)){ + BYTE k,*dst,*src; + dst=iter.GetRow(); + src=buffer[0]; + for(long x3=0,x4=0; x3<(long)info.dwEffWidth && x4 Step 7A: Swap red and blue components + // not necessary if swapped red and blue definition in jmorecfg.h;ln322 + if ((cinfo.num_components==3)&&(cinfo.quantize_colors==FALSE)){ + BYTE* r0=GetBits(); + for(long y=0;y - cancel decoding + RGBtoBGR(r0,3*head.biWidth); + r0+=info.dwEffWidth; + } + } + + /* Step 8: Release JPEG decompression object */ + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(&cinfo); + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + */ + + /* And we're done! */ + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageJPG::Encode(CxFile * hFile) +{ + if (EncodeSafeCheck(hFile)) return false; + + if (head.biClrUsed!=0 && !IsGrayScale()){ + strcpy(info.szLastError,"JPEG can save only RGB or GreyScale images"); + return false; + } + + // necessary for EXIF, and for roll backs + long pos=hFile->Tell(); + + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + //struct jpeg_error_mgr jerr; + /* We use our private extension JPEG error handler. */ + struct jpg_error_mgr jerr; + jerr.buffer=info.szLastError; + /* More stuff */ + int row_stride; /* physical row width in image buffer */ + JSAMPARRAY buffer; /* Output row buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + //cinfo.err = jpeg_std_error(&jerr); + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = ima_jpeg_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + strcpy(info.szLastError, jerr.buffer); // + jpeg_destroy_compress(&cinfo); + return 0; + } + + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + + //jpeg_stdio_dest(&cinfo, outfile); + CxFileJpg dest(hFile); + cinfo.dest = &dest; + + /* Step 3: set parameters for compression */ + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = GetWidth(); // image width and height, in pixels + cinfo.image_height = GetHeight(); + + if (IsGrayScale()){ + cinfo.input_components = 1; // # of color components per pixel + cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ + } else { + cinfo.input_components = 3; // # of color components per pixel + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + } + + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + +//#ifdef C_ARITH_CODING_SUPPORTED + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_ARITHMETIC) != 0) + cinfo.arith_code = TRUE; +//#endif + +//#ifdef ENTROPY_OPT_SUPPORTED + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_OPTIMIZE) != 0) + cinfo.optimize_coding = TRUE; +//#endif + + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_GRAYSCALE) != 0) + jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE); + + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_SMOOTHING) != 0) + cinfo.smoothing_factor = m_nSmoothing; + + jpeg_set_quality(&cinfo, GetJpegQuality(), (GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_BASELINE) != 0); + +//#ifdef C_PROGRESSIVE_SUPPORTED + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_PROGRESSIVE) != 0) + jpeg_simple_progression(&cinfo); +//#endif + +#ifdef C_LOSSLESS_SUPPORTED + if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_LOSSLESS) != 0) + jpeg_simple_lossless(&cinfo, m_nPredictor, m_nPointTransform); +#endif + + cinfo.density_unit=1; + cinfo.X_density=(unsigned short)GetXDPI(); + cinfo.Y_density=(unsigned short)GetYDPI(); + + /* Step 4: Start compressor */ + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = info.dwEffWidth; /* JSAMPLEs per row in image_buffer */ + + // "8+row_stride" fix heap deallocation problem during debug??? + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, 8+row_stride, 1); + + CImageIterator iter(this); + + iter.Upset(); + while (cinfo.next_scanline < cinfo.image_height) { + // info.nProgress = (long)(100*cinfo.next_scanline/cinfo.image_height); + iter.GetRow(buffer[0], row_stride); + // not necessary if swapped red and blue definition in jmorecfg.h;ln322 + if (head.biClrUsed==0){ // swap R & B for RGB images + RGBtoBGR(buffer[0], row_stride); // Lance : 1998/09/01 : Bug ID: EXP-2.1.1-9 + } + iter.PrevRow(); + (void) jpeg_write_scanlines(&cinfo, buffer, 1); + } + + /* Step 6: Finish compression */ + jpeg_finish_compress(&cinfo); + + /* Step 7: release JPEG compression object */ + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + +#if CXIMAGEJPG_SUPPORT_EXIF + if (m_exif && m_exif->m_exifinfo->IsExif){ + // discard useless sections (if any) read from original image + m_exif->DiscardAllButExif(); + // read new created image, to split the sections + hFile->Seek(pos,SEEK_SET); + m_exif->DecodeExif(hFile,EXIF_READ_IMAGE); + // save back the image, adding EXIF section + hFile->Seek(pos,SEEK_SET); + m_exif->EncodeExif(hFile); + } +#endif + + + /* And we're done! */ + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_JPG + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajpg.h ./win32/dependencies/cximage/ximajpg.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximajpg.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximajpg.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,315 @@ +/* + * File: ximajpg.h + * Purpose: JPG Image Class Loader and Writer + */ +/* ========================================================== + * CxImageJPG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes + * + * Special thanks to Chris Shearer Cooper for CxFileJpg tips & code + * + * EXIF support based on jhead-1.8 by Matthias Wandel + * + * original CImageJPG and CImageIterator implementation are: + * Copyright: (c) 1995, Alejandro Aguilar Sierra + * + * This software is based in part on the work of the Independent JPEG Group. + * Copyright (C) 1991-1998, Thomas G. Lane. + * ========================================================== + */ +#if !defined(__ximaJPEG_h) +#define __ixmaJPEG_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_JPG + +#define CXIMAGEJPG_SUPPORT_EXIF 1 + +extern "C" { + #include "../jpeg/jpeglib.h" + #include "../jpeg/jerror.h" +} + +class DLL_EXP CxImageJPG: public CxImage +{ +public: + CxImageJPG(); + ~CxImageJPG(); + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JPG);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JPG);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE + +/* + * EXIF support based on jhead-1.8 by Matthias Wandel + */ + +#if CXIMAGEJPG_SUPPORT_EXIF + +#define MAX_COMMENT 1000 +#define MAX_SECTIONS 20 + +typedef struct tag_ExifInfo { + char Version [5]; + char CameraMake [32]; + char CameraModel [40]; + char DateTime [20]; + int Height, Width; + int Orientation; + int IsColor; + int Process; + int FlashUsed; + float FocalLength; + float ExposureTime; + float ApertureFNumber; + float Distance; + float CCDWidth; + float ExposureBias; + int Whitebalance; + int MeteringMode; + int ExposureProgram; + int ISOequivalent; + int CompressionLevel; + float FocalplaneXRes; + float FocalplaneYRes; + float FocalplaneUnits; + float Xresolution; + float Yresolution; + float ResolutionUnit; + float Brightness; + char Comments[MAX_COMMENT]; + + unsigned char * ThumbnailPointer; /* Pointer at the thumbnail */ + unsigned ThumbnailSize; /* Size of thumbnail. */ + + bool IsExif; +} EXIFINFO; + +//-------------------------------------------------------------------------- +// JPEG markers consist of one or more 0xFF bytes, followed by a marker +// code byte (which is not an FF). Here are the marker codes of interest +// in this program. (See jdmarker.c for a more complete list.) +//-------------------------------------------------------------------------- + +#define M_SOF0 0xC0 // Start Of Frame N +#define M_SOF1 0xC1 // N indicates which compression process +#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 // Start Of Image (beginning of datastream) +#define M_EOI 0xD9 // End Of Image (end of datastream) +#define M_SOS 0xDA // Start Of Scan (begins compressed data) +#define M_JFIF 0xE0 // Jfif marker +#define M_EXIF 0xE1 // Exif marker +#define M_COM 0xFE // COMment + +#define PSEUDO_IMAGE_MARKER 0x123; // Extra value. + +#define EXIF_READ_EXIF 0x01 +#define EXIF_READ_IMAGE 0x02 +#define EXIF_READ_ALL 0x03 + +class DLL_EXP CxExifInfo +{ + +typedef struct tag_Section_t{ + BYTE* Data; + int Type; + unsigned Size; +} Section_t; + +public: + EXIFINFO* m_exifinfo; + char m_szLastError[256]; + CxExifInfo(EXIFINFO* info = NULL); + ~CxExifInfo(); + bool DecodeExif(CxFile * hFile, int nReadMode = EXIF_READ_EXIF); + bool EncodeExif(CxFile * hFile); + void DiscardAllButExif(); +protected: + bool process_EXIF(unsigned char * CharBuf, unsigned int length); + void process_COM (const BYTE * Data, int length); + void process_SOFn (const BYTE * Data, int marker); + int Get16u(void * Short); + int Get16m(void * Short); + long Get32s(void * Long); + unsigned long Get32u(void * Long); + double ConvertAnyFormat(void * ValuePtr, int Format); + void* FindSection(int SectionType); + bool ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength, + EXIFINFO * const pInfo, unsigned char ** const LastExifRefdP); + int ExifImageWidth; + int MotorolaOrder; + Section_t Sections[MAX_SECTIONS]; + int SectionsRead; + bool freeinfo; +}; + + CxExifInfo* m_exif; + EXIFINFO m_exifinfo; + bool DecodeExif(CxFile * hFile); + bool DecodeExif(FILE * hFile) { CxIOFile file(hFile); return DecodeExif(&file); } + +#endif //CXIMAGEJPG_SUPPORT_EXIF + +//////////////////////////////////////////////////////////////////////////////////////// +////////////////////// C x F i l e J p g //////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +// thanks to Chris Shearer Cooper +class CxFileJpg : public jpeg_destination_mgr, public jpeg_source_mgr + { +public: + enum { eBufSize = 4096 }; + + CxFileJpg(CxFile* pFile) + { + m_pFile = pFile; + + init_destination = InitDestination; + empty_output_buffer = EmptyOutputBuffer; + term_destination = TermDestination; + + init_source = InitSource; + fill_input_buffer = FillInputBuffer; + skip_input_data = SkipInputData; + resync_to_restart = jpeg_resync_to_restart; // use default method + term_source = TermSource; + next_input_byte = NULL; //* => next byte to read from buffer + bytes_in_buffer = 0; //* # of bytes remaining in buffer + + m_pBuffer = new unsigned char[eBufSize]; + } + ~CxFileJpg() + { + delete [] m_pBuffer; + } + + static void InitDestination(j_compress_ptr cinfo) + { + CxFileJpg* pDest = (CxFileJpg*)cinfo->dest; + pDest->next_output_byte = pDest->m_pBuffer; + pDest->free_in_buffer = eBufSize; + } + + static boolean EmptyOutputBuffer(j_compress_ptr cinfo) + { + CxFileJpg* pDest = (CxFileJpg*)cinfo->dest; + if (pDest->m_pFile->Write(pDest->m_pBuffer,1,eBufSize)!=(size_t)eBufSize) + ERREXIT(cinfo, JERR_FILE_WRITE); + pDest->next_output_byte = pDest->m_pBuffer; + pDest->free_in_buffer = eBufSize; + return TRUE; + } + + static void TermDestination(j_compress_ptr cinfo) + { + CxFileJpg* pDest = (CxFileJpg*)cinfo->dest; + size_t datacount = eBufSize - pDest->free_in_buffer; + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (!pDest->m_pFile->Write(pDest->m_pBuffer,1,datacount)) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + pDest->m_pFile->Flush(); + /* Make sure we wrote the output file OK */ + if (pDest->m_pFile->Error()) ERREXIT(cinfo, JERR_FILE_WRITE); + return; + } + + static void InitSource(j_decompress_ptr cinfo) + { + CxFileJpg* pSource = (CxFileJpg*)cinfo->src; + pSource->m_bStartOfFile = TRUE; + } + + static boolean FillInputBuffer(j_decompress_ptr cinfo) + { + size_t nbytes; + CxFileJpg* pSource = (CxFileJpg*)cinfo->src; + nbytes = pSource->m_pFile->Read(pSource->m_pBuffer,1,eBufSize); + if (nbytes <= 0){ + if (pSource->m_bStartOfFile) //* Treat empty input file as fatal error + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + // Insert a fake EOI marker + pSource->m_pBuffer[0] = (JOCTET) 0xFF; + pSource->m_pBuffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + pSource->next_input_byte = pSource->m_pBuffer; + pSource->bytes_in_buffer = nbytes; + pSource->m_bStartOfFile = FALSE; + return TRUE; + } + + static void SkipInputData(j_decompress_ptr cinfo, long num_bytes) + { + CxFileJpg* pSource = (CxFileJpg*)cinfo->src; + if (num_bytes > 0){ + while (num_bytes > (long)pSource->bytes_in_buffer){ + num_bytes -= (long)pSource->bytes_in_buffer; + FillInputBuffer(cinfo); + // note we assume that fill_input_buffer will never return FALSE, + // so suspension need not be handled. + } + pSource->next_input_byte += (size_t) num_bytes; + pSource->bytes_in_buffer -= (size_t) num_bytes; + } + } + + static void TermSource(j_decompress_ptr cinfo) + { + return; + } +protected: + CxFile *m_pFile; + unsigned char *m_pBuffer; + bool m_bStartOfFile; +}; + +public: + enum CODEC_OPTION + { + ENCODE_BASELINE = 0x1, + ENCODE_ARITHMETIC = 0x2, + ENCODE_GRAYSCALE = 0x4, + ENCODE_OPTIMIZE = 0x8, + ENCODE_PROGRESSIVE = 0x10, + ENCODE_LOSSLESS = 0x20, + ENCODE_SMOOTHING = 0x40, + DECODE_GRAYSCALE = 0x80, + DECODE_QUANTIZE = 0x100, + DECODE_DITHER = 0x200, + DECODE_ONEPASS = 0x400, + DECODE_NOSMOOTH = 0x800 + }; + + int m_nPredictor; + int m_nPointTransform; + int m_nSmoothing; + int m_nQuantize; + J_DITHER_MODE m_nDither; + +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximalpha.cpp ./win32/dependencies/cximage/ximalpha.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximalpha.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximalpha.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,321 @@ +// xImalpha.cpp : Alpha channel functions +/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_ALPHA + +//////////////////////////////////////////////////////////////////////////////// +/** + * \sa AlphaSetMax + */ +BYTE CxImage::AlphaGetMax() const +{ + return info.nAlphaMax; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Sets global Alpha (opacity) value applied to the whole image, + * valid only for painting functions. + * \param nAlphaMax: can be from 0 to 255 + */ +void CxImage::AlphaSetMax(BYTE nAlphaMax) +{ + info.nAlphaMax=nAlphaMax; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Checks if the image has a valid alpha channel. + */ +bool CxImage::AlphaIsValid() +{ + return pAlpha!=0; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Enables the alpha palette, so the Draw() function changes its behavior. + */ +void CxImage::AlphaPaletteEnable(bool enable) +{ + info.bAlphaPaletteEnabled=enable; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * True if the alpha palette is enabled for painting. + */ +bool CxImage::AlphaPaletteIsEnabled() +{ + return info.bAlphaPaletteEnabled; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Inverts the alpha channel. + */ +void CxImage::AlphaClear() +{ + if (pAlpha) memset(pAlpha,0,head.biWidth * head.biHeight); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Sets the alpha level for the whole image + */ +void CxImage::AlphaSet(BYTE level) +{ + if (pAlpha) memset(pAlpha,level,head.biWidth * head.biHeight); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Allocates an empty (opaque) alpha channel. + */ +void CxImage::AlphaCreate() +{ + if (pAlpha==NULL) { + pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight); + if (pAlpha) memset(pAlpha,255,head.biWidth * head.biHeight); + } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::AlphaDelete() +{ + if (pAlpha) { free(pAlpha); pAlpha=0; } +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::AlphaInvert() +{ + if (pAlpha) { + BYTE *iSrc=pAlpha; + long n=head.biHeight*head.biWidth; + for(long i=0; i < n; i++){ + *iSrc=(BYTE)~(*(iSrc)); + iSrc++; + } + } +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Imports an existing alpa channel from another image with the same width and height. + */ +bool CxImage::AlphaCopy(CxImage &from) +{ + if (from.pAlpha == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false; + if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight); + if (pAlpha==NULL) return false; + memcpy(pAlpha,from.pAlpha,head.biWidth * head.biHeight); + info.nAlphaMax=from.info.nAlphaMax; + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Creates the alpha channel from a gray scale image. + */ +bool CxImage::AlphaSet(CxImage &from) +{ + if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false; + if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight); + BYTE* src = from.info.pImage; + BYTE* dst = pAlpha; + if (src==NULL || dst==NULL) return false; + for (long y=0; yTransfer(tmp); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Exports the alpha palette channel in a 8bpp grayscale image. + */ +bool CxImage::AlphaPaletteSplit(CxImage *dest) +{ + if (!AlphaPaletteIsValid() || !dest) return false; + + CxImage tmp(head.biWidth,head.biHeight,8); + if (!tmp.IsValid()) return false; + + for(long y=0; yTransfer(tmp); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_ALPHA diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximalyr.cpp ./win32/dependencies/cximage/ximalyr.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximalyr.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximalyr.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,105 @@ +// xImaLyr.cpp : Layers functions +/* 21/04/2003 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_LAYERS + +//////////////////////////////////////////////////////////////////////////////// +/** + * If the object is an internal layer, GetParent return its parent in the hierarchy. + */ +CxImage* CxImage::GetParent() const +{ + return info.pParent; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Number of layers allocated directly by the object. + */ +long CxImage::GetNumLayers() const +{ + return info.nNumLayers; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Creates an empty layer. If position is less than 0, the new layer will be placed in the last position + */ +bool CxImage::LayerCreate(long position) +{ + if ( position < 0 || position > info.nNumLayers ) position = info.nNumLayers; + + CxImage** ptmp = (CxImage**)malloc((info.nNumLayers + 1)*sizeof(CxImage**)); + if (ptmp==0) return false; + + int i=0; + for (int n=0; ninfo.pParent = this; + } else { + free(ptmp); + return false; + } + + info.nNumLayers++; + if (pLayers) free(pLayers); + pLayers = ptmp; + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Deletes a layer. If position is less than 0, the last layer will be deleted + */ +bool CxImage::LayerDelete(long position) +{ + if ( position >= info.nNumLayers ) return false; + if ( position < 0) position = info.nNumLayers - 1; + + CxImage** ptmp = (CxImage**)malloc((info.nNumLayers - 1)*sizeof(CxImage**)); + if (ptmp==0) return false; + + int i=0; + for (int n=0; n<(info.nNumLayers - 1); n++){ + if (position == n){ + delete pLayers[n]; + i=1; + } + ptmp[n]=pLayers[n+i]; + } + if (i==0) delete pLayers[info.nNumLayers - 1]; + + info.nNumLayers--; + if (pLayers) free(pLayers); + pLayers = ptmp; + return true; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::LayerDeleteAll() +{ + if (pLayers) { + for(long n=0; n= info.nNumLayers ) return 0; + if ( position < 0) position = info.nNumLayers - 1; + return pLayers[position]; +} +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_LAYERS diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximamng.cpp ./win32/dependencies/cximage/ximamng.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximamng.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximamng.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,366 @@ +/* + * File: ximamng.cpp + * Purpose: Platform Independent MNG Image Class Loader and Writer + * Author: 07/Aug/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximamng.h" + +#if CXIMAGE_SUPPORT_MNG + +//////////////////////////////////////////////////////////////////////////////// +// callbacks for the mng decoder: +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// memory allocation; data must be zeroed +static mng_ptr +mymngalloc( mng_uint32 size ) +{ + return (mng_ptr)calloc(1, size); +} + +//////////////////////////////////////////////////////////////////////////////// +// memory deallocation +static void mymngfree(mng_ptr p, mng_uint32 size) +{ + free(p); +} + +//////////////////////////////////////////////////////////////////////////////// +// Stream open/close: +// since the user is responsible for opening and closing the file, +// we leave the default implementation open +static mng_bool mymngopenstream(mng_handle mng) { return MNG_TRUE; } +static mng_bool mymngopenstreamwrite(mng_handle mng) { return MNG_TRUE; } +static mng_bool mymngclosestream(mng_handle mng) { return MNG_TRUE; } + +//////////////////////////////////////////////////////////////////////////////// +// feed data to the decoder +static mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) +{ + mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); + // read the requested amount of data from the file + *bytesread = mymng->file->Read( buffer, sizeof(BYTE), size); + return MNG_TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +static mng_bool mymngwritestream (mng_handle mng, mng_ptr pBuf, mng_uint32 iSize, mng_uint32 *iWritten) +{ + mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); + // write it + *iWritten = mymng->file->Write (pBuf, 1, iSize); + return MNG_TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// the header's been read. set up the display stuff +static mng_bool mymngprocessheader( mng_handle mng, mng_uint32 width, mng_uint32 height ) +{ + // normally the image buffer is allocated here, + // but in this module we don't know nothing about + // the final environment. + + mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); + + mymng->width = width; + mymng->height = height; + mymng->bpp = 24; + mymng->effwdt = ((((width * mymng->bpp) + 31) >> 5) << 2); + + if (mng->bUseBKGD){ + mymng->nBkgndIndex = 0; + mymng->nBkgndColor.rgbRed = mng->iBGred >> 8; + mymng->nBkgndColor.rgbGreen =mng->iBGgreen >> 8; + mymng->nBkgndColor.rgbBlue = mng->iBGblue >> 8; + } + + mymng->image = (BYTE*)malloc(height * mymng->effwdt); + + // tell the mng decoder about our bit-depth choice + mng_set_canvasstyle( mng, MNG_CANVAS_BGR8 ); + return MNG_TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// return a row pointer for the decoder to fill +static mng_ptr mymnggetcanvasline( mng_handle mng, mng_uint32 line ) +{ + mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); + return (mng_ptr)(mymng->image + (mymng->effwdt * (mymng->height - 1 - line))); +} + +//////////////////////////////////////////////////////////////////////////////// +// timer +static mng_uint32 mymnggetticks(mng_handle mng) +{ +#ifdef WIN32 + return (mng_uint32)GetTickCount(); +#else + return 0; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Refresh: actual frame need to be updated (Invalidate) +static mng_bool mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) +{ +// mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); + return MNG_TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// interframe delay callback +static mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs) +{ + mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); + mymng->delay = msecs; // set the timer for when the decoder wants to be woken + return MNG_TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +static mng_bool mymngerror(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text) +{ + //throw (const char *)text; + return mng_cleanup(&mng); // +} + +//////////////////////////////////////////////////////////////////////////////// +// CxImage members +//////////////////////////////////////////////////////////////////////////////// +CxImageMNG::CxImageMNG(): CxImage(CXIMAGE_FORMAT_MNG) +{ + hmng = NULL; + memset(&mnginfo,0,sizeof(mngstuff)); + mnginfo.nBkgndIndex = -1; + mnginfo.speed = 1.0f; +} +//////////////////////////////////////////////////////////////////////////////// +CxImageMNG::~CxImageMNG() +{ + // cleanup and return + if (mnginfo.thread){ //close the animation thread + mnginfo.animation_enabled=0; + ResumeThread(mnginfo.thread); + WaitForSingleObject(mnginfo.thread,500); + CloseHandle(mnginfo.thread); + } + // free objects + if (mnginfo.image) free(mnginfo.image); + if (hmng) mng_cleanup(&hmng); //be sure it's not needed any more. (active timers ?) +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageMNG::SetCallbacks(mng_handle mng) +{ + // set the callbacks + mng_setcb_errorproc(mng, mymngerror); + mng_setcb_openstream(mng, mymngopenstream); + mng_setcb_closestream(mng, mymngclosestream); + mng_setcb_readdata(mng, mymngreadstream); + mng_setcb_processheader(mng, mymngprocessheader); + mng_setcb_getcanvasline(mng, mymnggetcanvasline); + mng_setcb_refresh(mng, mymngrefresh); + mng_setcb_gettickcount(mng, mymnggetticks); + mng_setcb_settimer(mng, mymngsettimer); + mng_setcb_refresh(mng, mymngrefresh); +} +//////////////////////////////////////////////////////////////////////////////// +// can't use the CxImage implementation because it looses mnginfo +bool CxImageMNG::Load(const char * imageFileName){ + FILE* hFile; //file handle to read the image + if ((hFile=fopen(imageFileName,"rb"))==NULL) return false; + bool bOK = Decode(hFile); + fclose(hFile); + return bOK; +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageMNG::Decode(CxFile *hFile) +{ + if (hFile == NULL) return false; + + try { + // set up the mng decoder for our stream + hmng = mng_initialize(&mnginfo, mymngalloc, mymngfree, MNG_NULL); + if (hmng == NULL) throw "could not initialize libmng"; + + // set the file we want to play + mnginfo.file = hFile; + + // Set the colorprofile, lcms uses this: + mng_set_srgb(hmng, MNG_TRUE ); + // Set white as background color: + WORD Red,Green,Blue; + Red = Green = Blue = (255 << 8) + 255; + mng_set_bgcolor(hmng, Red, Green, Blue ); + // If PNG Background is available, use it: + mng_set_usebkgd(hmng, MNG_TRUE ); + + // No need to store chunks: + mng_set_storechunks(hmng, MNG_FALSE); + // No need to wait: straight reading + mng_set_suspensionmode(hmng, MNG_FALSE); + + SetCallbacks(hmng); + + mng_datap pData = (mng_datap)hmng; + + // read in the image + info.nNumFrames=0; + mng_readdisplay(hmng); + + // read all + int retval=MNG_NOERROR; + while(pData->bReading){ + retval = mng_display_resume(hmng); + info.nNumFrames++; + } + + // single frame check: + if (retval != MNG_NEEDTIMERWAIT){ + info.nNumFrames--; + } else { + mnginfo.animation=1; + } + + if (info.nNumFrames<=0) info.nNumFrames=1; + + if (mnginfo.animation_enabled==0){ + // select the frame + if (info.nFrame>=0 && info.nFramewidth,OffsetH=mymng->height; + + BYTE *tmpbuffer = new BYTE[ (mymng->effwdt+1) * mymng->height]; + if( tmpbuffer == 0 ) return; + + // Write DEFI chunk. + mng_putchunk_defi( hMNG, 0, 0, 0, MNG_TRUE, OffsetX, OffsetY, MNG_FALSE, 0, 0, 0, 0 ); + + // Write Header: + mng_putchunk_ihdr( + hMNG, + OffsetW, OffsetH, + MNG_BITDEPTH_8, + MNG_COLORTYPE_RGB, + MNG_COMPRESSION_DEFLATE, + MNG_FILTER_ADAPTIVE, + MNG_INTERLACE_NONE + ); + + // transfer data, add Filterbyte: + for( int Row=0; Row No Filter. + tmpbuffer[Row*(mymng->effwdt+1)]=0; + // Copy the scanline: (reverse order) + memcpy(tmpbuffer+Row*(mymng->effwdt+1)+1, + mymng->image+((OffsetH-1-(OffsetY+Row))*(mymng->effwdt))+OffsetX,mymng->effwdt); + // swap red and blue components + RGBtoBGR(tmpbuffer+Row*(mymng->effwdt+1)+1,mymng->effwdt); + } + + // Compress data with ZLib (Deflate): + BYTE *dstbuffer = new BYTE[(mymng->effwdt+1)*OffsetH]; + if( dstbuffer == 0 ) return; + DWORD dstbufferSize=(mymng->effwdt+1)*OffsetH; + + // Compress data: + if(Z_OK != compress2((Bytef *)dstbuffer,(ULONG *)&dstbufferSize,(const Bytef*)tmpbuffer, + (ULONG) (mymng->effwdt+1)*OffsetH,9 )) return; + + // Write Data into MNG File: + mng_putchunk_idat( hMNG, dstbufferSize, (mng_ptr*)dstbuffer); + mng_putchunk_iend(hMNG); + + // Free the stuff: + delete [] tmpbuffer; + delete [] dstbuffer; +} +//////////////////////////////////////////////////////////////////////////////// +long CxImageMNG::Resume() +{ + if (MNG_NEEDTIMERWAIT == mng_display_resume(hmng)){ + if (info.pImage==NULL) Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG); + if (IsValid()) memcpy(GetBits(), mnginfo.image, mnginfo.effwdt * mnginfo.height); + } else { + mnginfo.animation_enabled = 0; + } + return mnginfo.animation_enabled; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageMNG::SetSpeed(float speed) +{ + if (speed>10.0) mnginfo.speed = 10.0f; + else if (speed<0.1) mnginfo.speed = 0.1f; + else mnginfo.speed=speed; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_MNG diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximamng.h ./win32/dependencies/cximage/ximamng.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximamng.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximamng.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,86 @@ +/* + * File: ximamng.h + * Purpose: Declaration of the MNG Image Class + * Author: Davide Pizzolato - www.xdp.it + * Created: 2001 + */ +/* ========================================================== + * CxImageMNG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Special thanks to Frank Haug for suggestions and code. + * + * original mng.cpp code created by Nikolaus Brennig, November 14th, 2000. + * + * LIBMNG Copyright (c) 2000,2001 Gerard Juyn (gerard@libmng.com) + * ========================================================== + */ + +#if !defined(__ximaMNG_h) +#define __ximaMNG_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_MNG + +//#define MNG_NO_CMS +#define MNG_SUPPORT_DISPLAY +#define MNG_SUPPORT_READ +#define MNG_SUPPORT_WRITE +#define MNG_ACCESS_CHUNKS +#define MNG_STORE_CHUNKS + +extern "C" { +#include "../mng/libmng.h" +#include "../mng/libmng_data.h" +} + +//unsigned long _stdcall RunMNGThread(void *lpParam); + +typedef struct tagmngstuff +{ + CxFile *file; + BYTE *image; + HANDLE thread; + mng_uint32 delay; + mng_uint32 width; + mng_uint32 height; + mng_uint32 effwdt; + mng_int16 bpp; + mng_bool animation; + mng_bool animation_enabled; + float speed; + long nBkgndIndex; + RGBQUAD nBkgndColor; +} mngstuff; + +class CxImageMNG: public CxImage +{ +public: + CxImageMNG(); + ~CxImageMNG(); + + bool Load(const char * imageFileName); + bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_MNG);} + + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE + + long Resume(); + void SetSpeed(float speed); + + mng_handle hmng; + mngstuff mnginfo; +protected: + void WritePNG(mng_handle hMNG, int Frame, int FrameCount ); + void SetCallbacks(mng_handle mng); +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximapal.cpp ./win32/dependencies/cximage/ximapal.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximapal.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximapal.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,707 @@ +// xImaPal.cpp : Palette and Pixel functions +/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +//////////////////////////////////////////////////////////////////////////////// +/** + * returns the palette dimension in byte + */ +DWORD CxImage::GetPaletteSize() +{ + return (head.biClrUsed * sizeof(RGBQUAD)); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha) +{ + if ((pDib)&&(head.biClrUsed)){ + BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); + if (idx=head.biWidth)||(y>=head.biHeight)) { + if (info.nBkgndIndex != -1) return (BYTE)info.nBkgndIndex; + else return *info.pImage; + } + if (head.biBitCount==8){ + return info.pImage[y*info.dwEffWidth + x]; + } else { + BYTE pos; + BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)]; + if (head.biBitCount==4){ + pos = (BYTE)(4*(1-x%2)); + iDst &= (0x0F<> pos); + } else if (head.biBitCount==1){ + pos = (BYTE)(7-x%8); + iDst &= (0x01<> pos); + } + } + return 0; +} +//////////////////////////////////////////////////////////////////////////////// +BYTE CxImage::BlindGetPixelIndex(const long x,const long y) +{ +#ifdef _DEBUG + if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y)) throw 0; +#endif + + if (head.biBitCount==8){ + return info.pImage[y*info.dwEffWidth + x]; + } else { + BYTE pos; + BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)]; + if (head.biBitCount==4){ + pos = (BYTE)(4*(1-x%2)); + iDst &= (0x0F<> pos); + } else if (head.biBitCount==1){ + pos = (BYTE)(7-x%8); + iDst &= (0x01<> pos); + } + } + return 0; +} +//////////////////////////////////////////////////////////////////////////////// +RGBQUAD CxImage::GetPixelColor(long x,long y, bool bGetAlpha) +{ +// RGBQUAD rgb={0,0,0,0}; + RGBQUAD rgb=info.nBkgndColor; // + if ((pDib==NULL)||(x<0)||(y<0)|| + (x>=head.biWidth)||(y>=head.biHeight)){ + if (info.nBkgndIndex != -1){ + if (head.biBitCount<24) return GetPaletteColor((BYTE)info.nBkgndIndex); + else return info.nBkgndColor; + } else if (pDib) return GetPixelColor(0,0); + return rgb; + } + + if (head.biClrUsed){ + rgb = GetPaletteColor(GetPixelIndex(x,y)); + } else { + BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; + rgb.rgbBlue = *iDst++; + rgb.rgbGreen= *iDst++; + rgb.rgbRed = *iDst; + } +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha && bGetAlpha) rgb.rgbReserved = AlphaGet(x,y); +#else + rgb.rgbReserved = 0; +#endif //CXIMAGE_SUPPORT_ALPHA + return rgb; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * This is (a bit) faster version of GetPixelColor. + * It tests bounds only in debug mode (_DEBUG defined). + * + * It is an error to request out-of-borders pixel with this method. + * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode. + * \author ***bd*** 2.2004 + */ +RGBQUAD CxImage::BlindGetPixelColor(const long x,const long y) +{ + RGBQUAD rgb; +#ifdef _DEBUG + if ((pDib==NULL) || !IsInside(x,y)) throw 0; +#endif + + if (head.biClrUsed){ + return GetPaletteColor(BlindGetPixelIndex(x,y)); + } + + BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; + rgb.rgbBlue = *iDst++; + rgb.rgbGreen= *iDst++; + rgb.rgbRed = *iDst; +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha) rgb.rgbReserved = pAlpha[x+y*head.biWidth]; +#else + rgb.rgbReserved = 0; +#endif //CXIMAGE_SUPPORT_ALPHA + return rgb; +} +//////////////////////////////////////////////////////////////////////////////// +BYTE CxImage::GetPixelGray(long x, long y) +{ + RGBQUAD color = GetPixelColor(x,y); + return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::SetPixelIndex(long x,long y,BYTE i) +{ + if ((pDib==NULL)||(head.biClrUsed==0)|| + (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ; + + if (head.biBitCount==8){ + info.pImage[y*info.dwEffWidth + x]=i; + return; + } else { + BYTE pos; + BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3); + if (head.biBitCount==4){ + pos = (BYTE)(4*(1-x%2)); + *iDst &= ~(0x0F<=head.biWidth)||(y>=head.biHeight)) return; + if (head.biClrUsed) + SetPixelIndex(x,y,GetNearestIndex(c)); + else { + BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; + *iDst++ = c.rgbBlue; + *iDst++ = c.rgbGreen; + *iDst = c.rgbRed; +#if CXIMAGE_SUPPORT_ALPHA + if (bSetAlpha) AlphaSet(x,y,c.rgbReserved); +#endif //CXIMAGE_SUPPORT_ALPHA + } +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Blends the current pixel color with a new color. + * \param x,y = pixel + * \param c = new color + * \param blend = can be from 0 (no effect) to 1 (full effect). + * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved + */ +void CxImage::BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha) +{ + if ((pDib==NULL)||(x<0)||(y<0)|| + (x>=head.biWidth)||(y>=head.biHeight)) return; + + int a0 = (int)(256*blend); + int a1 = 256 - a0; + + RGBQUAD c0 = BlindGetPixelColor(x,y); + c.rgbRed = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8); + c.rgbBlue = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8); + c.rgbGreen = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8); + + if (head.biClrUsed) + SetPixelIndex(x,y,GetNearestIndex(c)); + else { + BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; + *iDst++ = c.rgbBlue; + *iDst++ = c.rgbGreen; + *iDst = c.rgbRed; +#if CXIMAGE_SUPPORT_ALPHA + if (bSetAlpha) AlphaSet(x,y,c.rgbReserved); +#endif //CXIMAGE_SUPPORT_ALPHA + } +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Returns the best palette index that matches a specified color. + */ +BYTE CxImage::GetNearestIndex(RGBQUAD c) +{ + if ((pDib==NULL)||(head.biClrUsed==0)) return 0; + + // check matching with the previous result + if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index; + info.last_c = c; + info.last_c_isvalid = true; + + BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); + long distance=200000; + int i,j = 0; + long k,l; + int m = (int)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant); + for(i=0,l=0;i100) perc=100; + for(i=0;i=0){ + if (head.biClrUsed){ + if (GetPixelIndex(x,y) == info.nBkgndIndex) return true; + } else { + RGBQUAD ct = info.nBkgndColor; + RGBQUAD c = GetPixelColor(x,y,false); + if (*(long*)&c==*(long*)&ct) return true; + } + } + +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha) return AlphaGet(x,y)==0; +#endif + + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Checks if image has the same palette, if any. + * \param img = image to compare. + * \param bCheckAlpha = check also the rgbReserved field. + */ +bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha) +{ + if (head.biClrUsed != img.head.biClrUsed) + return false; + if (head.biClrUsed == 0) + return false; + + RGBQUAD c1,c2; + for (DWORD n=0; n256) { + head.biClrImportant = 0; + return; + } + + switch(head.biBitCount){ + case 1: + head.biClrImportant = min(ncolors,2); + break; + case 4: + head.biClrImportant = min(ncolors,16); + break; + case 8: + head.biClrImportant = ncolors; + break; + } + return; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Returns pointer to pixel. Currently implemented only for truecolor images. + * + * \param x,y - coordinates + * + * \return pointer to first byte of pixel data + * + * \author ***bd*** 2.2004 + */ +void* CxImage::BlindGetPixelPointer(const long x, const long y) +{ + if (!IsIndexed()) + return info.pImage + y*info.dwEffWidth + x*3; + else + return 0; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr) +{ + DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr)); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha) +{ + if (!pDib) return; + ////////////////////////////////////////////////////// + // Draws a line using the Bresenham line algorithm + // Thanks to Jordan DeLozier + ////////////////////////////////////////////////////// + int x1 = StartX; + int y1 = StartY; + int x = x1; // Start x off at the first pixel + int y = y1; // Start y off at the first pixel + int x2 = EndX; + int y2 = EndY; + + int xinc1,xinc2,yinc1,yinc2; // Increasing values + int den, num, numadd,numpixels; + int deltax = abs(x2 - x1); // The difference between the x's + int deltay = abs(y2 - y1); // The difference between the y's + + // Get Increasing Values + if (x2 >= x1) { // The x-values are increasing + xinc1 = 1; + xinc2 = 1; + } else { // The x-values are decreasing + xinc1 = -1; + xinc2 = -1; + } + + if (y2 >= y1) { // The y-values are increasing + yinc1 = 1; + yinc2 = 1; + } else { // The y-values are decreasing + yinc1 = -1; + yinc2 = -1; + } + + // Actually draw the line + if (deltax >= deltay) // There is at least one x-value for every y-value + { + xinc1 = 0; // Don't change the x when numerator >= denominator + yinc2 = 0; // Don't change the y for every iteration + den = deltax; + num = deltax / 2; + numadd = deltay; + numpixels = deltax; // There are more x-values than y-values + } + else // There is at least one y-value for every x-value + { + xinc2 = 0; // Don't change the x for every iteration + yinc1 = 0; // Don't change the y when numerator >= denominator + den = deltay; + num = deltay / 2; + numadd = deltax; + numpixels = deltay; // There are more y-values than x-values + } + + for (int curpixel = 0; curpixel <= numpixels; curpixel++) + { + // Draw the current pixel + SetPixelColor(x,y,color,bSetAlpha); + + num += numadd; // Increase the numerator by the top of the fraction + if (num >= den) // Check if numerator >= denominator + { + num -= den; // Calculate the new numerator value + x += xinc1; // Change the x as appropriate + y += yinc1; // Change the y as appropriate + } + x += xinc2; // Change the x as appropriate + y += yinc2; // Change the y as appropriate + } +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Sets a palette with standard colors for 4 and 8 bpp images. + */ +void CxImage::SetStdPalette() +{ + if (!pDib) return; + switch (head.biBitCount){ + case 8: + { + const BYTE pal256[1024] = {0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0, + 192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0, + 72,184,255,0,37,170,255,0,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0, + 50,80,0,212,227,255,0,177,199,255,0,142,171,255,0,107,143,255,0,72,115,255,0,37,87,255,0,0, + 85,255,0,0,73,220,0,0,61,185,0,0,49,150,0,0,37,115,0,0,25,80,0,212,212,255,0,177,177,255,0, + 142,142,255,0,107,107,255,0,72,72,255,0,37,37,255,0,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0, + 0,0,115,0,0,0,80,0,227,212,255,0,199,177,255,0,171,142,255,0,143,107,255,0,115,72,255,0, + 87,37,255,0,85,0,255,0,73,0,220,0,61,0,185,0,49,0,150,0,37,0,115,0,25,0,80,0,240,212,255,0, + 226,177,255,0,212,142,255,0,198,107,255,0,184,72,255,0,170,37,255,0,170,0,255,0,146,0,220,0, + 122,0,185,0,98,0,150,0,74,0,115,0,50,0,80,0,255,212,255,0,255,177,255,0,255,142,255,0,255,107,255,0, + 255,72,255,0,255,37,255,0,254,0,254,0,220,0,220,0,185,0,185,0,150,0,150,0,115,0,115,0,80,0,80,0, + 255,212,240,0,255,177,226,0,255,142,212,0,255,107,198,0,255,72,184,0,255,37,170,0,255,0,170,0, + 220,0,146,0,185,0,122,0,150,0,98,0,115,0,74,0,80,0,50,0,255,212,227,0,255,177,199,0,255,142,171,0, + 255,107,143,0,255,72,115,0,255,37,87,0,255,0,85,0,220,0,73,0,185,0,61,0,150,0,49,0,115,0,37,0, + 80,0,25,0,255,212,212,0,255,177,177,0,255,142,142,0,255,107,107,0,255,72,72,0,255,37,37,0,254,0, + 0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,0,255,227,212,0,255,199,177,0,255,171,142,0, + 255,143,107,0,255,115,72,0,255,87,37,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,115,37,0, + 0,80,25,0,0,255,240,212,0,255,226,177,0,255,212,142,0,255,198,107,0,255,184,72,0,255,170,37,0, + 255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,0,255,255,212,0,255,255,177,0, + 255,255,142,0,255,255,107,0,255,255,72,0,255,255,37,0,254,254,0,0,220,220,0,0,185,185,0,0,150,150,0, + 0,115,115,0,0,80,80,0,0,240,255,212,0,226,255,177,0,212,255,142,0,198,255,107,0,184,255,72,0, + 170,255,37,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,50,80,0,0,227,255,212,0, + 199,255,177,0,171,255,142,0,143,255,107,0,115,255,72,0,87,255,37,0,85,255,0,0,73,220,0,0,61,185,0, + 0,49,150,0,0,37,115,0,0,25,80,0,0,212,255,212,0,177,255,177,0,142,255,142,0,107,255,107,0,72,255,72,0, + 37,255,37,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,212,255,227,0,177,255,199,0, + 142,255,171,0,107,255,143,0,72,255,115,0,37,255,87,0,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0, + 115,37,0,0,80,25,0,212,255,240,0,177,255,226,0,142,255,212,0,107,255,198,0,72,255,184,0,37,255,170,0, + 0,255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,212,255,255,0,177,255,255,0, + 142,255,255,0,107,255,255,0,72,255,255,0,37,255,255,0,0,254,254,0,0,220,220,0,0,185,185,0,0, + 150,150,0,0,115,115,0,0,80,80,0,242,242,242,0,230,230,230,0,218,218,218,0,206,206,206,0,194,194,194,0, + 182,182,182,0,170,170,170,0,158,158,158,0,146,146,146,0,134,134,134,0,122,122,122,0,110,110,110,0, + 98,98,98,0,86,86,86,0,74,74,74,0,62,62,62,0,50,50,50,0,38,38,38,0,26,26,26,0,14,14,14,0,240,251,255,0, + 164,160,160,0,128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0}; + memcpy(GetPalette(),pal256,1024); + break; + } + case 4: + { + const BYTE pal16[64]={0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0, + 128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0}; + memcpy(GetPalette(),pal16,64); + break; + } + } + return; +} +//////////////////////////////////////////////////////////////////////////////// diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximapcx.cpp ./win32/dependencies/cximage/ximapcx.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximapcx.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximapcx.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,445 @@ +/* + * File: ximapcx.cpp + * Purpose: Platform Independent PCX Image Class Loader and Writer + * 05/Jan/2002 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + * + * based on ppmtopcx.c - convert a portable pixmap to PCX + * Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) + * based on ppmtopcx.c by Michael Davidson + */ + +#include "ximapcx.h" + +#if CXIMAGE_SUPPORT_PCX + +#include "xmemfile.h" + +#define PCX_MAGIC 0X0A // PCX magic number +#define PCX_256_COLORS 0X0C // magic number for 256 colors +#define PCX_HDR_SIZE 128 // size of PCX header +#define PCX_MAXCOLORS 256 +#define PCX_MAXPLANES 4 +#define PCX_MAXVAL 255 + +//////////////////////////////////////////////////////////////////////////////// +bool CxImagePCX::Decode(CxFile *hFile) +{ + if (hFile == NULL) return false; + + PCXHEADER pcxHeader; + int i, x, y, y2, nbytes, count, Height, Width; + BYTE c, ColorMap[PCX_MAXCOLORS][3]; + BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL; + BYTE *pcxplanes, *pcxpixels; + + try + { + if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) throw "Can't read PCX image"; + + if (pcxHeader.Manufacturer != PCX_MAGIC) throw "Error: Not a PCX file"; + // Check for PCX run length encoding + if (pcxHeader.Encoding != 1) throw "PCX file has unknown encoding scheme"; + + Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1; + Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1; + info.xDPI = pcxHeader.Hres; + info.yDPI = pcxHeader.Vres; + + // Check that we can handle this image format + if (pcxHeader.ColorPlanes > 4) + throw "Can't handle image with more than 4 planes"; + + // Create the image + if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){ + Create (Width, Height, 24, CXIMAGE_FORMAT_PCX); +#if CXIMAGE_SUPPORT_ALPHA + if (pcxHeader.ColorPlanes==4) AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1) + Create (Width, Height, 4, CXIMAGE_FORMAT_PCX); + else + Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX); + + if (info.nEscape) throw "Cancelled"; // - cancel decoding + + //Read the image and check if it's ok + nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height; + lpHead1 = pcximage = (BYTE*)malloc(nbytes); + while (nbytes > 0){ + if (hFile == NULL || hFile->Eof()) throw "corrupted PCX"; + + hFile->Read(&c,1,1); + if ((c & 0XC0) != 0XC0){ // Repeated group + *pcximage++ = c; + --nbytes; + continue; + } + count = c & 0X3F; // extract count + hFile->Read(&c,1,1); + if (count > nbytes) throw "repeat count spans end of image"; + + nbytes -= count; + while (--count >=0) *pcximage++ = c; + } + pcximage = lpHead1; + + //store the palette + for (i = 0; i < 16; i++){ + ColorMap[i][0] = pcxHeader.ColorMap[i][0]; + ColorMap[i][1] = pcxHeader.ColorMap[i][1]; + ColorMap[i][2] = pcxHeader.ColorMap[i][2]; + } + if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){ + hFile->Read(&c,1,1); + if (c != PCX_256_COLORS) throw "bad color map signature"; + + for (i = 0; i < PCX_MAXCOLORS; i++){ + hFile->Read(&ColorMap[i][0],1,1); + hFile->Read(&ColorMap[i][1],1,1); + hFile->Read(&ColorMap[i][2],1,1); + } + } + if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ + ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0; + ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255; + } + + for (DWORD idx=0; idx - cancel decoding + + y2=Height-1-y; + pcxpixels = lpHead2; + pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes); + + if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){ + // Deal with 24 bit color image + for (x = 0; x < Width; x++){ + SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x])); + } + continue; +#if CXIMAGE_SUPPORT_ALPHA + } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){ + for (x = 0; x < Width; x++){ + SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x])); + AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]); + } + continue; +#endif //CXIMAGE_SUPPORT_ALPHA + } else if (pcxHeader.ColorPlanes == 1) { + PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel); + } else { + PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel); + } + for (x = 0; x < Width; x++) SetPixelIndex(x,y2,pcxpixels[x]); + } + + } catch (char *message) { + strncpy(info.szLastError,message,255); + if (lpHead1){ free(lpHead1); lpHead1 = NULL; } + if (lpHead2){ free(lpHead2); lpHead2 = NULL; } + return false; + } + if (lpHead1){ free(lpHead1); lpHead1 = NULL; } + if (lpHead2){ free(lpHead2); lpHead2 = NULL; } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImagePCX::Encode(CxFile * hFile) +{ + if (EncodeSafeCheck(hFile)) return false; + + try { + PCXHEADER pcxHeader; + memset(&pcxHeader,0,sizeof(pcxHeader)); + pcxHeader.Manufacturer = PCX_MAGIC; + pcxHeader.Version = 5; + pcxHeader.Encoding = 1; + pcxHeader.Xmin = 0; + pcxHeader.Ymin = 0; + pcxHeader.Xmax = (WORD)head.biWidth-1; + pcxHeader.Ymax = (WORD)head.biHeight-1; + pcxHeader.Hres = (WORD)info.xDPI; + pcxHeader.Vres = (WORD)info.yDPI; + pcxHeader.Reserved = 0; + pcxHeader.PaletteType = head.biClrUsed==0; + + switch(head.biBitCount){ + case 24: + case 8: + { + pcxHeader.BitsPerPixel = 8; + pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1; +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4; +#endif //CXIMAGE_SUPPORT_ALPHA + pcxHeader.BytesPerLine = (WORD)head.biWidth; + break; + } + default: //(4 1) + pcxHeader.BitsPerPixel = 1; + pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1; + pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3); + } + + if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ + pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0; + pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255; + } + if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){ + RGBQUAD c; + for (int i = 0; i < 16; i++){ + c=GetPaletteColor(i); + pcxHeader.ColorMap[i][0] = c.rgbRed; + pcxHeader.ColorMap[i][1] = c.rgbGreen; + pcxHeader.ColorMap[i][2] = c.rgbBlue; + } + } + + pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1); + + if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 ) + throw "cannot write PCX header"; + + CxMemFile buffer; + buffer.Open(); + + BYTE c,n; + long x,y; + if (head.biClrUsed==0){ + for (y = head.biHeight-1; y >=0 ; y--){ + for (int p=0; pWrite(buffer.GetBuffer(false),buffer.Size(),1); + + } else if (head.biBitCount==8) { + + for (y = head.biHeight-1; y >=0 ; y--){ + c=n=0; + for (x = 0; xWrite(buffer.GetBuffer(false),buffer.Size(),1); + + if (head.biBitCount == 8){ + hFile->PutC(0x0C); + BYTE* pal = (BYTE*)malloc(768); + RGBQUAD c; + for (int i=0;i<256;i++){ + c=GetPaletteColor(i); + pal[3*i+0] = c.rgbRed; + pal[3*i+1] = c.rgbGreen; + pal[3*i+2] = c.rgbBlue; + } + hFile->Write(pal,768,1); + free(pal); + } + } else { //(head.biBitCount==4) || (head.biBitCount==1) + + RGBQUAD *rgb = GetPalette(); + bool binvert = false; + if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1); + + BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine); + BYTE* raw = (BYTE*)malloc(head.biWidth); + + for(y = head.biHeight-1; y >=0 ; y--) { + + for( x = 0; x < head.biWidth; x++) raw[x] = (BYTE)GetPixelIndex(x,y); + + if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x]; + + for( x = 0; x < pcxHeader.ColorPlanes; x++ ) { + PCX_PixelsToPlanes(raw, head.biWidth, plane, x); + PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer); + } + } + + free(plane); + free(raw); + + hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); + + } + + } catch (char *message) { + strncpy(info.szLastError,message,255); + return false; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +// Convert multi-plane format into 1 pixel per byte +// from unpacked file data bitplanes[] into pixel row pixels[] +// image Height rows, with each row having planes image planes each +// bytesperline bytes +void CxImagePCX::PCX_PlanesToPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel) +{ + int i, j, npixels; + BYTE * p; + if (planes > 4) throw "Can't handle more than 4 planes"; + if (bitsperpixel != 1) throw "Can't handle more than 1 bit per pixel"; + + // Clear the pixel buffer + npixels = (bytesperline * 8) / bitsperpixel; + p = pixels; + while (--npixels >= 0) *p++ = 0; + + // Do the format conversion + for (i = 0; i < planes; i++){ + int pixbit, bits, mask; + p = pixels; + pixbit = (1 << i); // pixel bit for this plane + for (j = 0; j < bytesperline; j++){ + bits = *bitplanes++; + for (mask = 0X80; mask != 0; mask >>= 1, p++) + if (bits & mask) *p |= pixbit; + } + } +} +//////////////////////////////////////////////////////////////////////////////// +// convert packed pixel format into 1 pixel per byte +// from unpacked file data bitplanes[] into pixel row pixels[] +// image Height rows, with each row having planes image planes each +// bytesperline bytes +void CxImagePCX::PCX_UnpackPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel) +{ + register int bits; + if (planes != 1) throw "Can't handle packed pixels with more than 1 plane."; + + if (bitsperpixel == 8){ // 8 bits/pixels, no unpacking needed + while (bytesperline-- > 0) *pixels++ = *bitplanes++; + } else if (bitsperpixel == 4){ // 4 bits/pixel, two pixels per byte + while (bytesperline-- > 0){ + bits = *bitplanes++; + *pixels++ = (BYTE)((bits >> 4) & 0X0F); + *pixels++ = (BYTE)((bits) & 0X0F); + } + } else if (bitsperpixel == 2){ // 2 bits/pixel, four pixels per byte + while (bytesperline-- > 0){ + bits = *bitplanes++; + *pixels++ = (BYTE)((bits >> 6) & 0X03); + *pixels++ = (BYTE)((bits >> 4) & 0X03); + *pixels++ = (BYTE)((bits >> 2) & 0X03); + *pixels++ = (BYTE)((bits) & 0X03); + } + } else if (bitsperpixel == 1){ // 1 bits/pixel, 8 pixels per byte + while (bytesperline-- > 0){ + bits = *bitplanes++; + *pixels++ = ((bits & 0X80) != 0); + *pixels++ = ((bits & 0X40) != 0); + *pixels++ = ((bits & 0X20) != 0); + *pixels++ = ((bits & 0X10) != 0); + *pixels++ = ((bits & 0X08) != 0); + *pixels++ = ((bits & 0X04) != 0); + *pixels++ = ((bits & 0X02) != 0); + *pixels++ = ((bits & 0X01) != 0); + } + } +} +//////////////////////////////////////////////////////////////////////////////// +/* PCX_PackPixels(const long p,BYTE &c, BYTE &n, long &l, CxFile &f) + * p = current pixel (-1 ends the line -2 ends odd line) + * c = previous pixel + * n = number of consecutive pixels + */ +void CxImagePCX::PCX_PackPixels(const long p,BYTE &c, BYTE &n, CxFile &f) +{ + if (p!=c && n){ + if (n==1 && c<0xC0){ + f.PutC(c); + } else { + f.PutC(0xC0|n); + f.PutC(c); + } + n=0; + } + if (n==0x3F) { + f.PutC(0xFF); + f.PutC(c); + n=0; + } + if (p==-2) f.PutC(0); + c=(BYTE)p; + n++; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImagePCX::PCX_PackPlanes(BYTE* buff, const long size, CxFile &f) +{ + BYTE *start,*end; + BYTE c, previous, count; + + start = buff; + end = buff + size; + previous = *start++; + count = 1; + + while (start < end) { + c = *start++; + if (c == previous && count < 63) { + ++count; + continue; + } + + if (count > 1 || (previous & 0xc0) == 0xc0) { + f.PutC( count | 0xc0 ); + } + f.PutC(previous); + previous = c; + count = 1; + } + + if (count > 1 || (previous & 0xc0) == 0xc0) { + count |= 0xc0; + f.PutC(count); + } + f.PutC(previous); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImagePCX::PCX_PixelsToPlanes(BYTE* raw, long width, BYTE* buf, long plane) +{ + int cbit, x, mask; + unsigned char *cp = buf-1; + + mask = 1 << plane; + cbit = -1; + for( x = 0; x < width; x++ ) { + if( cbit < 0 ) { + cbit = 7; + *++cp = 0; + } + if( raw[x] & mask ) + *cp |= (1<jmpbuf, 1); +} +//////////////////////////////////////////////////////////////////////////////// +void CxImagePNG::expand2to4bpp(BYTE* prow) +{ + BYTE *psrc,*pdst; + BYTE pos,idx; + for(long x=head.biWidth-1;x>=0;x--){ + psrc = prow + ((2*x)>>3); + pdst = prow + ((4*x)>>3); + pos = (BYTE)(2*(3-x%4)); + idx = (BYTE)((*psrc & (0x03<>pos); + pos = (BYTE)(4*(1-x%2)); + *pdst &= ~(0x0F<jmpbuf)) { + /* Free all of the memory associated with the png_ptr and info_ptr */ + if (row_pointers) delete[] row_pointers; + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + throw ""; + } + /* set up the input control */ + //png_init_io(png_ptr, hFile); + + // use custom I/O functions + png_set_read_fn(png_ptr, hFile, (png_rw_ptr)user_read_data); + png_set_error_fn(png_ptr,info.szLastError,(png_error_ptr)user_error_fn,NULL); + + /* read the file information */ + png_read_info(png_ptr, info_ptr); + + /* allocate the memory to hold the image using the fields of png_info. */ + png_color_16 my_background={ 0, 192, 192, 192, 0 }; + png_color_16 *image_background; + + if (info_ptr->pixel_depth != 32){ + // preserve original background info. + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background,PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background,PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); +// - we call png_set_bgr() below +// // safe check +// if (info_ptr->pixel_depth > 16 ) info_ptr->color_type = COLORTYPE_COLOR; + } + + // hack for images with alpha channel + if (info_ptr->pixel_depth == 32){ +// info.nBkgndIndex = 0; //enable transparency + if (png_get_bKGD(png_ptr, info_ptr, &image_background)){ + info.nBkgndColor.rgbRed = (BYTE)image_background->red; + info.nBkgndColor.rgbGreen = (BYTE)image_background->green; + info.nBkgndColor.rgbBlue = (BYTE)image_background->blue; + info.nBkgndColor.rgbReserved = 0; // + } + } + + /* tell libpng to strip 16 bit depth files down to 8 bits */ + if (info_ptr->bit_depth == 16) png_set_strip_16(png_ptr); + + int pixel_depth=info_ptr->pixel_depth; + if (pixel_depth > 16 ) pixel_depth=24; + if (pixel_depth == 16 ) pixel_depth=8; + + Create(info_ptr->width, info_ptr->height, pixel_depth, CXIMAGE_FORMAT_PNG); + + /* get metrics */ + switch (info_ptr->phys_unit_type) + { + case PNG_RESOLUTION_UNKNOWN: + SetXDPI(info_ptr->x_pixels_per_unit); + SetYDPI(info_ptr->y_pixels_per_unit); + break; + case PNG_RESOLUTION_METER: + SetXDPI((long)floor(info_ptr->x_pixels_per_unit * 254.0 / 10000.0 + 0.5)); + SetYDPI((long)floor(info_ptr->y_pixels_per_unit * 254.0 / 10000.0 + 0.5)); + break; + } + + if (info_ptr->num_palette>0) + SetPalette((rgb_color*)info_ptr->palette,info_ptr->num_palette); + else if (info_ptr->bit_depth ==2) { // needed for 2 bpp grayscale PNGs + SetPaletteColor(0,0,0,0); + SetPaletteColor(1,85,85,85); + SetPaletteColor(2,170,170,170); + SetPaletteColor(3,255,255,255); + } else SetGrayPalette(); // needed for grayscale PNGs + + // simple transparency (the real PGN transparency is more complex) + if (info_ptr->num_trans!=0){ + //palette transparency + RGBQUAD* pal=GetPalette(); + if (pal){ + DWORD ip; + for (ip=0;ipnum_trans);ip++) + pal[ip].rgbReserved=info_ptr->trans[ip]; + if (info_ptr->num_trans==1 && pal[0].rgbReserved==0){ + info.nBkgndIndex = 0; + } else { + info.bAlphaPaletteEnabled=true; + for (;ipcolor_type == PNG_COLOR_TYPE_RGB_ALPHA || //Alpha channel + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && info_ptr->pixel_depth == 32)){ + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA){ + png_set_gray_to_rgb(png_ptr); + png_set_expand(png_ptr); + } +#if CXIMAGE_SUPPORT_ALPHA // + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + AlphaCreate(); +#else + png_set_strip_alpha(png_ptr); +#endif //CXIMAGE_SUPPORT_ALPHA + } + + // - flip the RGB pixels to BGR (or RGBA to BGRA) + if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) png_set_bgr(png_ptr); + + // - handle cancel + if (info.nEscape) longjmp(png_ptr->jmpbuf, 1); + + //allocate the buffer + int row_stride = info_ptr->width * ((info_ptr->pixel_depth+7)>>3); + row_pointers = new BYTE[10+row_stride]; + + // turn on interlace handling + number_passes = png_set_interlace_handling(png_ptr); + + if (number_passes>1){ + SetCodecOption(1); + } else { + SetCodecOption(0); + } + + for (int pass=0; pass< number_passes; pass++) { + iter.Upset(); + int y=0; + do { + + // - handle cancel + if (info.nEscape) longjmp(png_ptr->jmpbuf, 1); + +#if CXIMAGE_SUPPORT_ALPHA // + if (!AlphaIsValid()) +#endif // CXIMAGE_SUPPORT_ALPHA + { + //recover data from previous scan + if (info_ptr->interlace_type && pass>0) + iter.GetRow(row_pointers, info.dwEffWidth); + //read next row + png_read_row(png_ptr, row_pointers, NULL); +// - already done by png_set_bgr() +// //HACK BY OP && ( for interlace, swap only in the last pass) +// if (info_ptr->color_type==COLORTYPE_COLOR && pass==(number_passes-1)) +// RGBtoBGR(row_pointers, info.dwEffWidth); + // expand 2 bpp images only in the last pass + if (info_ptr->bit_depth==2 && pass==(number_passes-1)) + expand2to4bpp(row_pointers); + //copy the pixels + iter.SetRow(row_pointers, info.dwEffWidth); + //go on + iter.PrevRow(); + } +#if CXIMAGE_SUPPORT_ALPHA // + else { //alpha blend + + //compute the correct position of the line + long ax,ay; + ay = head.biHeight-1-y; + BYTE* prow= iter.GetRow(ay); + + //recover data from previous scan + if (info_ptr->interlace_type && pass>0 && pass!=7){ + for(ax=head.biWidth;ax>=0;ax--){ + row_pointers[ax*4]=prow[3*ax]; + row_pointers[ax*4+1]=prow[3*ax+1]; + row_pointers[ax*4+2]=prow[3*ax+2]; + row_pointers[ax*4+3]=AlphaGet(ax,ay); + } + } + + //read next row + png_read_row(png_ptr, row_pointers, NULL); + + //RGBA -> RGB + A + for(ax=0;axjmpbuf)){ + /* If we get here, we had a problem reading the file */ + if (info_ptr->palette) free(info_ptr->palette); + png_destroy_write_struct(&png_ptr, (png_infopp)&info_ptr); + throw "Error saving PNG file"; + } + + int row_stride = info.dwEffWidth; + /* set up the output control */ + //png_init_io(png_ptr, hFile); + + // use custom I/O functions + png_set_write_fn(png_ptr,hFile,(png_rw_ptr)user_write_data,(png_flush_ptr)user_flush_data); + + /* set the file information here */ + info_ptr->width = GetWidth(); + info_ptr->height = GetHeight(); + info_ptr->pixel_depth = (BYTE)GetBpp(); + info_ptr->channels = (GetBpp()>8) ? (BYTE)3: (BYTE)1; + info_ptr->bit_depth = (BYTE)(GetBpp()/info_ptr->channels); + info_ptr->color_type = GetColorType(); + info_ptr->compression_type = info_ptr->filter_type = 0; + info_ptr->valid = 0; + info_ptr->rowbytes = row_stride; + + switch(GetCodecOption(CXIMAGE_FORMAT_PNG)){ + case 1: + info_ptr->interlace_type = PNG_INTERLACE_ADAM7; + break; + default: + info_ptr->interlace_type = PNG_INTERLACE_NONE; + } + + /* set compression level */ + //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + + /* set background */ + png_color_16 image_background={ 0, 255, 255, 255, 0 }; + if (info.nBkgndIndex!=-1) { + image_background.blue = info.nBkgndColor.rgbBlue; + image_background.green = info.nBkgndColor.rgbGreen; + image_background.red = info.nBkgndColor.rgbRed; + } + png_set_bKGD(png_ptr, info_ptr, &image_background); + + /* set metrics */ + png_set_pHYs(png_ptr, info_ptr, head.biXPelsPerMeter, head.biYPelsPerMeter, PNG_RESOLUTION_METER); + + /* set the palette if there is one */ + if (GetPalette()){ + png_set_IHDR(png_ptr, info_ptr, info_ptr->width, info_ptr->height, info_ptr->bit_depth, + PNG_COLOR_TYPE_PALETTE, info_ptr->interlace_type, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + info_ptr->valid |= PNG_INFO_PLTE; + + // simple transparency + if (info.nBkgndIndex != -1){ + trans[0]=0; + info_ptr->num_trans = 1; + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->trans = trans; + // the transparency indexes start from 0 + if (info.nBkgndIndex){ + SwapIndex(0,(BYTE)info.nBkgndIndex); + // the ghost must set the changed attributes in the body + if (info.pGhost) info.pGhost->SetTransIndex(0); + } + } + + int nc = GetNumColors(); + + /* We not need to write unused colors! */ + /* only for small images */ + if ((nc>2)&&((head.biWidth*head.biHeight)<65536)){ + nc = 0; + for (DWORD y=0;ync){ + nc=GetPixelIndex(x,y); + } + } + } + nc++; + } + + if (info.bAlphaPaletteEnabled){ + for(WORD ip=0; ipnum_trans = (WORD)nc; + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->trans = trans; + } + + // copy the palette colors + info_ptr->palette = new png_color[nc]; + info_ptr->num_palette = (png_uint_16) nc; + for (int i=0; ipalette[i].red, &info_ptr->palette[i].green, &info_ptr->palette[i].blue); + + } + +#if CXIMAGE_SUPPORT_ALPHA // + //Merge the transparent color with the alpha channel + bool bNeedTempAlpha = false; + if (head.biBitCount==24 && info.nBkgndIndex>=0){ + if (!AlphaIsValid()){ + bNeedTempAlpha = true; + AlphaCreate(); + } + RGBQUAD c,ct=GetTransColor(); + for(long y=0; y < head.biHeight; y++){ + for(long x=0; x < head.biWidth ; x++){ + c=GetPixelColor(x,y,false); + if (*(long*)&c==*(long*)&ct) + AlphaSet(x,y,0); + }} + } +#endif // CXIMAGE_SUPPORT_ALPHA // + +#if CXIMAGE_SUPPORT_ALPHA // + if (AlphaIsValid()){ + row_stride = 4 * head.biWidth; + + info_ptr->pixel_depth = 32; + info_ptr->channels = 4; + info_ptr->bit_depth = 8; + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + info_ptr->rowbytes = row_stride; + + /* write the file information */ + png_write_info(png_ptr, info_ptr); + + // "10+row_stride" fix heap deallocation problem during debug??? + BYTE *row_pointers = new BYTE[10+row_stride]; + + //interlace handling + int num_pass = png_set_interlace_handling(png_ptr); + for (int pass = 0; pass < num_pass; pass++){ + + //write image + iter.Upset(); + long ay=head.biHeight-1; + RGBQUAD c; + do { + for (long ax=head.biWidth-1; ax>=0;ax--){ + c=GetPixelColor(ax,ay); + row_pointers[ax*4+3]=(BYTE)((AlphaGet(ax,ay)*info.nAlphaMax)/255); + row_pointers[ax*4+2]=c.rgbBlue; + row_pointers[ax*4+1]=c.rgbGreen; + row_pointers[ax*4]=c.rgbRed; + } + png_write_row(png_ptr, row_pointers); + ay--; + } while(iter.PrevRow()); + } + + delete [] row_pointers; + } + else +#endif //CXIMAGE_SUPPORT_ALPHA // + { + /* write the file information */ + png_write_info(png_ptr, info_ptr); + /* If you are only writing one row at a time, this works */ + BYTE *row_pointers = new BYTE[10+row_stride]; + + //interlace handling + int num_pass = png_set_interlace_handling(png_ptr); + for (int pass = 0; pass < num_pass; pass++){ + + //write image + iter.Upset(); + do { + iter.GetRow(row_pointers, row_stride); + //HACK BY OP + if (info_ptr->color_type == 2 /*COLORTYPE_COLOR*/) + RGBtoBGR(row_pointers, row_stride); + png_write_row(png_ptr, row_pointers); + } while(iter.PrevRow()); + + } + + delete [] row_pointers; + } + +#if CXIMAGE_SUPPORT_ALPHA // + /* remove the temporary alpha channel*/ + if (bNeedTempAlpha) AlphaDelete(); +#endif // CXIMAGE_SUPPORT_ALPHA // + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + /* if you malloced the palette, free it here */ + if (info_ptr->palette) delete[] (info_ptr->palette); + + /* clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, (png_infopp)&info_ptr); + + } catch (char *message) { + strncpy(info.szLastError,message,255); + return FALSE; + } + /* that's it */ + return TRUE; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_PNG diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximapng.h ./win32/dependencies/cximage/ximapng.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximapng.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximapng.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,73 @@ +/* + * File: ximapng.h + * Purpose: PNG Image Class Loader and Writer + */ +/* ========================================================== + * CxImagePNG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes + * + * original CImagePNG and CImageIterator implementation are: + * Copyright: (c) 1995, Alejandro Aguilar Sierra + * + * libpng Copyright (c) 1998-2003 Glenn Randers-Pehrson + * ========================================================== + */ +#if !defined(__ximaPNG_h) +#define __ximaPNG_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_PNG + +extern "C" { +#include "../png/png.h" +} + +class CxImagePNG: public CxImage +{ +public: + CxImagePNG(): CxImage(CXIMAGE_FORMAT_PNG) {} + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_PNG);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_PNG);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE + +protected: + void ima_png_error(png_struct *png_ptr, char *message); + void expand2to4bpp(BYTE* prow); + + static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) + { + CxFile* hFile = (CxFile*)png_ptr->io_ptr; + if (hFile->Read(data,1,length) != length) png_error(png_ptr, "Read Error"); + } + + static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length) + { + CxFile* hFile = (CxFile*)png_ptr->io_ptr; + if (hFile->Write(data,1,length) != length) png_error(png_ptr, "Write Error"); + } + + static void user_flush_data(png_structp png_ptr) + { + CxFile* hFile = (CxFile*)png_ptr->io_ptr; + if (!hFile->Flush()) png_error(png_ptr, "Flush Error"); + } + static void user_error_fn(png_structp png_ptr,png_const_charp error_msg) + { + strncpy((char*)png_ptr->error_ptr,error_msg,255); + longjmp(png_ptr->jmpbuf, 1); + } +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximasel.cpp ./win32/dependencies/cximage/ximasel.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximasel.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximasel.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,469 @@ +// xImaSel.cpp : Selection functions +/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_SELECTION + +//////////////////////////////////////////////////////////////////////////////// +/** + * Checks if the image has a valid selection. + */ +bool CxImage::SelectionIsValid() +{ + return pSelection!=0; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Gets the smallest rectangle that contains the selection + */ +void CxImage::SelectionGetBox(RECT& r) +{ + memcpy(&r,&info.rSelectionBox,sizeof(RECT)); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Empties the selection. + */ +bool CxImage::SelectionClear() +{ + if (pSelection){ + memset(pSelection,0,head.biWidth * head.biHeight); + info.rSelectionBox.left = head.biWidth; + info.rSelectionBox.bottom = head.biHeight; + info.rSelectionBox.right = info.rSelectionBox.top = 0; + return true; + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Allocates an empty selection. + */ +bool CxImage::SelectionCreate() +{ + SelectionDelete(); + pSelection = (BYTE*)calloc(head.biWidth * head.biHeight, 1); + return (pSelection!=0); +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Deallocates the selction. + */ +bool CxImage::SelectionDelete() +{ + if (pSelection){ free(pSelection); pSelection=NULL; } + info.rSelectionBox.left = head.biWidth; + info.rSelectionBox.bottom = head.biHeight; + info.rSelectionBox.right = info.rSelectionBox.top = 0; + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Checks if the coordinates are inside the selection. + */ +bool CxImage::SelectionIsInside(long x, long y) +{ + if (IsInside(x,y)){ + if (pSelection==NULL) return true; + return pSelection[x+y*head.biWidth]!=0; + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Adds a rectangle to the existing selection. + */ +bool CxImage::SelectionAddRect(RECT r) +{ + if (pSelection==NULL) SelectionCreate(); + if (pSelection==NULL) return false; + + RECT r2; + if (r.left r2.left) info.rSelectionBox.left = max(0L,min(head.biWidth,r2.left)); + if (info.rSelectionBox.right < r2.right) info.rSelectionBox.right = max(0L,min(head.biWidth,r2.right)); + if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0L,min(head.biHeight,r2.bottom)); + + long ymin = max(0L,min(head.biHeight,r2.bottom)); + long ymax = max(0L,min(head.biHeight,r2.top)); + long xmin = max(0L,min(head.biWidth,r2.left)); + long xmax = max(0L,min(head.biWidth,r2.right)); + + for (long y=ymin; y (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius))); + if (info.rSelectionBox.right < (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius))); + if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius))); + if (info.rSelectionBox.top < (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius))); + + long xmin = max(0L,min(head.biWidth,xcenter - xradius)); + long xmax = max(0L,min(head.biWidth,xcenter + xradius)); + long ymin = max(0L,min(head.biHeight,ycenter - yradius)); + long ymax = max(0L,min(head.biHeight,ycenter + yradius)); + + long y,yo; + for (y=ymin; yy) pSelection[x + y * head.biWidth] = 255; + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Inverts the selection. + */ +bool CxImage::SelectionInvert() +{ + if (pSelection) { + BYTE *iSrc=pSelection; + long n=head.biHeight*head.biWidth; + for(long i=0; i < n; i++){ + *iSrc=(BYTE)~(*(iSrc)); + iSrc++; + } + return true; + } + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Imports an existing region from another image with the same width and height. + */ +bool CxImage::SelectionCopy(CxImage &from) +{ + if (from.pSelection == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false; + if (pSelection==NULL) pSelection = (BYTE*)malloc(head.biWidth * head.biHeight); + if (pSelection==NULL) return false; + memcpy(pSelection,from.pSelection,head.biWidth * head.biHeight); + memcpy(&info.rSelectionBox,&from.info.rSelectionBox,sizeof(RECT)); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Adds a polygonal region to the existing selection. points points to an array of POINT structures. + * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon. + * npoints specifies the number of POINT structures in the array pointed to by points. + */ +bool CxImage::SelectionAddPolygon(POINT *points, long npoints) +{ + if (points==NULL || npoints<3) return false; + + if (pSelection==NULL) SelectionCreate(); + if (pSelection==NULL) return false; + + BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1); + RECT localbox = {head.biWidth,0,0,head.biHeight}; + + long x,y,i=0; + POINT *current,*next,*start; + //trace contour + while (i < npoints){ + current = &points[i]; + if (current->x!=-1){ + if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i]; + + if ((i+1)==npoints || points[i+1].x==-1) + next = start; + else + next = &points[i+1]; + + float beta; + if (current->x != next->x){ + beta = (float)(next->y - current->y)/(float)(next->x - current->x); + if (current->x < next->x){ + for (x=current->x; x<=next->x; x++){ + y = (long)(current->y + (x - current->x) * beta); + if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; + } + } else { + for (x=current->x; x>=next->x; x--){ + y = (long)(current->y + (x - current->x) * beta); + if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; + } + } + } + if (current->y != next->y){ + beta = (float)(next->x - current->x)/(float)(next->y - current->y); + if (current->y < next->y){ + for (y=current->y; y<=next->y; y++){ + x = (long)(current->x + (y - current->y) * beta); + if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; + } + } else { + for (y=current->y; y>=next->y; y--){ + x = (long)(current->x + (y - current->y) * beta); + if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; + } + } + } + } + + RECT r2; + if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; } + if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; } + if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1)); + if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1)); + if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1)); + if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1)); + + i++; + } + + //fill the outer region + long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom); + POINT* pix = (POINT*)calloc(npix,sizeof(POINT)); + BYTE back=0, mark=1; + long fx, fy, fxx, fyy, first, last,xmin,xmax,ymin,ymax; + + for (int side=0; side<4; side++){ + switch(side){ + case 0: + xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1; + break; + case 1: + xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1; + break; + case 2: + xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1; + break; + case 3: + xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1; + break; + } + //fill from the border points + for(y=ymin;y=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) + { + plocal[fxx + fyy*head.biWidth] = mark; + if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ + pix[last].x = fx; + pix[last].y = fy - 1; + last++; + if (last == npix) last = 0; + } + if ((fyy + 1)=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) + { + plocal[fxx + (y + fy)*head.biWidth] = mark; + if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ + pix[last].x = fx; + pix[last].y = fy - 1; + last++; + if (last == npix) last = 0; + } + if ((fyy + 1) localbox.left) info.rSelectionBox.left = localbox.left; + if (info.rSelectionBox.right < localbox.right) info.rSelectionBox.right = localbox.right+1; + if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom; + + free(plocal); + free(pix); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Adds to the selection all the pixels matching the specified color. + */ +bool CxImage::SelectionAddColor(RGBQUAD c) +{ + if (pSelection==NULL) SelectionCreate(); + if (pSelection==NULL) return false; + + RECT localbox = {head.biWidth,0,0,head.biHeight}; + + for (long y = 0; y < head.biHeight; y++){ + for (long x = 0; x < head.biWidth; x++){ + RGBQUAD color = GetPixelColor(x, y); + if (color.rgbRed == c.rgbRed && + color.rgbGreen == c.rgbGreen && + color.rgbBlue == c.rgbBlue) + { + pSelection[x + y * head.biWidth] = 255; // set the correct mask bit + + if (localbox.top < y) localbox.top = y; + if (localbox.left > x) localbox.left = x; + if (localbox.right < x) localbox.right = x; + if (localbox.bottom > y) localbox.bottom = y; + } + } + } + + if (info.rSelectionBox.top < localbox.top) info.rSelectionBox.top = localbox.top; + if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left; + if (info.rSelectionBox.right < localbox.right) info.rSelectionBox.right = localbox.right; + if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom; + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Adds a single pixel to the existing selection. + */ +bool CxImage::SelectionAddPixel(int x, int y) +{ + if (pSelection==NULL) SelectionCreate(); + if (pSelection==NULL) return false; + + if (IsInside(x,y)) { + pSelection[x + y * head.biWidth] = 255; // set the correct mask bit + return true; + } + + return false; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Exports the selection channel in a 8bpp grayscale image. + */ +bool CxImage::SelectionSplit(CxImage *dest) +{ + if (!pSelection || !dest) return false; + + CxImage tmp(head.biWidth,head.biHeight,8); + if (!tmp.IsValid()) return false; + + for(long y=0; yTransfer(tmp); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_WINDOWS +/** + * Converts the selection in a HRGN object. + */ +bool CxImage::SelectionToHRGN(HRGN& region) +{ + if (pSelection && region){ + for(int y = 0; y < head.biHeight; y++){ + HRGN hTemp = NULL; + int iStart = -1; + int x = 0; + for(; x < head.biWidth; x++){ + if (pSelection[x + y * head.biWidth] == 255){ + if (iStart == -1) iStart = x; + continue; + }else{ + if (iStart >= 0){ + hTemp = CreateRectRgn(iStart, y, x, y + 1); + CombineRgn(region, hTemp, region, RGN_OR); + DeleteObject(hTemp); + iStart = -1; + } + } + } + if (iStart >= 0){ + hTemp = CreateRectRgn(iStart, y, x, y + 1); + CombineRgn(region, hTemp, region, RGN_OR); + DeleteObject(hTemp); + iStart = -1; + } + } + return true; + } + return false; +} +#endif //CXIMAGE_SUPPORT_WINDOWS +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_SELECTION diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatga.cpp ./win32/dependencies/cximage/ximatga.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatga.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximatga.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,300 @@ +/* + * File: ximatga.cpp + * Purpose: Platform Independent TGA Image Class Loader and Writer + * 05/Jan/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximatga.h" + +#if CXIMAGE_SUPPORT_TGA + +#include "ximaiter.h" + +// Definitions for image types. +#define TGA_Null 0 +#define TGA_Map 1 +#define TGA_RGB 2 +#define TGA_Mono 3 +#define TGA_RLEMap 9 +#define TGA_RLERGB 10 +#define TGA_RLEMono 11 +#define TGA_CompMap 32 +#define TGA_CompMap4 33 + +//////////////////////////////////////////////////////////////////////////////// +bool CxImageTGA::Decode(CxFile *hFile) +{ + if (hFile == NULL) return false; + + TGAHEADER tgaHead; + + try + { + if (hFile->Read(&tgaHead,sizeof(tgaHead),1)==0) + throw "Not a TGA"; + + bool bCompressed; + switch (tgaHead.ImageType){ + case TGA_Map: + case TGA_RGB: + case TGA_Mono: + bCompressed = false; + break; + case TGA_RLEMap: + case TGA_RLERGB: + case TGA_RLEMono: + bCompressed = true; + break; + default: + throw "Unknown TGA image type"; + } + + if (tgaHead.ImageWidth==0 || tgaHead.ImageHeight==0 || tgaHead.PixelDepth==0 || tgaHead.CmapLength>256) + throw "bad TGA header"; + + if (tgaHead.PixelDepth!=8 && tgaHead.PixelDepth!=15 && tgaHead.PixelDepth!=16 && tgaHead.PixelDepth!=24 && tgaHead.PixelDepth!=32) + throw "bad TGA header"; + + if (tgaHead.IdLength>0) hFile->Seek(tgaHead.IdLength,SEEK_CUR); //skip descriptor + + Create(tgaHead.ImageWidth, tgaHead.ImageHeight, tgaHead.PixelDepth, CXIMAGE_FORMAT_TGA); +#if CXIMAGE_SUPPORT_ALPHA // + if (tgaHead.PixelDepth==32) AlphaCreate(); // Image has alpha channel +#endif //CXIMAGE_SUPPORT_ALPHA + + if (!IsValid()) throw "TGA Create failed"; + + if (info.nEscape) throw "Cancelled"; // - cancel decoding + + if (tgaHead.CmapType != 0){ // read the palette + rgb_color pal[256]; + hFile->Read(pal,tgaHead.CmapLength*sizeof(rgb_color), 1); + for (int i=0;i - cancel decoding + + if (hFile == NULL || hFile->Eof()) throw "corrupted TGA"; + + if (bYReversed) pDest = iter.GetRow(tgaHead.ImageHeight-y-1); + else pDest = iter.GetRow(y); + + if (bCompressed) rleLeftover = ExpandCompressedLine(pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,rleLeftover); + else ExpandUncompressedLine (pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,0); + } + + if (bXReversed) Mirror(); + +#if CXIMAGE_SUPPORT_ALPHA + if (bYReversed && tgaHead.PixelDepth==32) AlphaFlip(); // +#endif //CXIMAGE_SUPPORT_ALPHA + + } catch (char *message) { + strncpy(info.szLastError,message,255); + return FALSE; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageTGA::Encode(CxFile * hFile) +{ + if (EncodeSafeCheck(hFile)) return false; + + if (head.biBitCount<8){ + strcpy(info.szLastError,"Bit depth must be 8 or 24"); + return false; + } + + TGAHEADER tgaHead; + + tgaHead.IdLength = 0; // Image ID Field Length + tgaHead.CmapType = GetPalette()!=0; // Color Map Type + tgaHead.ImageType = (head.biBitCount == 8) ? (BYTE)TGA_Map : (BYTE)TGA_RGB; // Image Type + + tgaHead.CmapIndex=0; // First Entry Index + tgaHead.CmapLength=(head.biBitCount == 8) ? 256 : 0; // Color Map Length + tgaHead.CmapEntrySize=(head.biBitCount == 8) ? (BYTE)24 : (BYTE)0; // Color Map Entry Size + + tgaHead.X_Origin=0; // X-origin of Image + tgaHead.Y_Origin=0; // Y-origin of Image + tgaHead.ImageWidth=(WORD)head.biWidth; // Image Width + tgaHead.ImageHeight=(WORD)head.biHeight; // Image Height + tgaHead.PixelDepth=(BYTE)head.biBitCount; // Pixel Depth + tgaHead.ImagDesc=0; // Image Descriptor + + if (pAlpha && head.biBitCount==24) tgaHead.PixelDepth=32; + + hFile->Write(&tgaHead,sizeof(TGAHEADER),1); + + if (head.biBitCount==8){ + rgb_color pal[256]; + RGBQUAD* ppal = GetPalette(); + for (int i=0;i<256; i++){ + pal[i].r = ppal[i].rgbBlue; + pal[i].g = ppal[i].rgbGreen; + pal[i].b = ppal[i].rgbRed; + } + hFile->Write(&pal,256*sizeof(rgb_color),1); + } + + CImageIterator iter(this); + BYTE* pDest; + if (pAlpha==0 || head.biBitCount==8){ + for (int y=0; y < tgaHead.ImageHeight; y++){ + pDest = iter.GetRow(y); + hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1); + } + } else { + pDest = (BYTE*)malloc(4*tgaHead.ImageWidth); + RGBQUAD c; + for (int y=0; y < tgaHead.ImageHeight; y++){ + for(int x=0, x4=0;x + pDest[x4+3]=(BYTE)((AlphaGet(x,y)*info.nAlphaMax)/255); +#else + pDest[x4+3]=0; +#endif //CXIMAGE_SUPPORT_ALPHA + } + hFile->Write(pDest,4*tgaHead.ImageWidth,1); + } + free(pDest); + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +BYTE CxImageTGA::ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover) +{ + try{ + BYTE rle; + long filePos; + for (int x=0; xRead(&rle,1,1); + } + if (rle & 128) { // RLE-Encoded packet + rle -= 127; // Calculate real repeat count. + if ((x+rle)>width){ + rleLeftover = 128 + (rle - (width - x) - 1); + filePos = hFile->Tell(); + rle=width-x; + } + switch (ptgaHead->PixelDepth) + { + case 32: { + RGBQUAD color; + hFile->Read(&color,4,1); + for (int ix = 0; ix < rle; ix++){ + memcpy(&pDest[3*ix],&color,3); +#if CXIMAGE_SUPPORT_ALPHA // + AlphaSet(ix+x,y,color.rgbReserved); +#endif //CXIMAGE_SUPPORT_ALPHA + } + break; + } + case 24: { + rgb_color triple; + hFile->Read(&triple,3,1); + for (int ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3); + break; + } + case 15: + case 16: { + WORD pixel; + hFile->Read(&pixel,2,1); + rgb_color triple; + triple.r = (BYTE)(( pixel & 0x1F ) * 8); // red + triple.g = (BYTE)(( pixel >> 2 ) & 0x0F8); // green + triple.b = (BYTE)(( pixel >> 7 ) & 0x0F8); // blue + for (int ix = 0; ix < rle; ix++){ + memcpy(&pDest[3*ix],&triple,3); + } + break; + } + case 8: { + BYTE pixel; + hFile->Read(&pixel,1,1); + for (int ix = 0; ix < rle; ix++) pDest[ix] = pixel; + } + } + if (rleLeftover!=255) hFile->Seek(filePos, SEEK_SET); + } else { // Raw packet + rle += 1; // Calculate real repeat count. + if ((x+rle)>width){ + rleLeftover = rle - (width - x) - 1; + rle=width-x; + } + ExpandUncompressedLine(pDest,ptgaHead,hFile,rle,y,x); + } + if (head.biBitCount == 24) pDest += rle*3; else pDest += rle; + x += rle; + } + } catch(...){ } + return rleLeftover; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageTGA::ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset) +{ + try{ + switch (ptgaHead->PixelDepth){ + case 8: + hFile->Read(pDest,width,1); + break; + case 15: + case 16:{ + BYTE* dst=pDest; + WORD pixel; + for (int x=0; xRead(&pixel,2,1); + *dst++ = (BYTE)(( pixel & 0x1F ) * 8); // blue + *dst++ = (BYTE)(( pixel >> 2 ) & 0x0F8); // green + *dst++ = (BYTE)(( pixel >> 7 ) & 0x0F8); // red + } + break; + } + case 24: + hFile->Read(pDest,3*width,1); + break; + case 32:{ + BYTE* dst=pDest; + for (int x=0; xRead(&pixel,4,1); + *dst++ = pixel.rgbBlue; + *dst++ = pixel.rgbGreen; + *dst++ = pixel.rgbRed; +#if CXIMAGE_SUPPORT_ALPHA // + AlphaSet(x+xoffset,y,pixel.rgbReserved); //alpha +#endif //CXIMAGE_SUPPORT_ALPHA + } + break; + } + } + } catch(...){ } +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_TGA + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatga.h ./win32/dependencies/cximage/ximatga.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatga.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximatga.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,60 @@ +/* + * File: ximatga.h + * Purpose: TARGA Image Class Loader and Writer + */ +/* ========================================================== + * CxImageTGA (c) 05/Jan/2002 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Parts of the code come from Paintlib : Copyright (c) 1996-1998 Ulrich von Zadow + * ========================================================== + */ +#if !defined(__ximaTGA_h) +#define __ximaTGA_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_TGA + +class CxImageTGA: public CxImage +{ +#pragma pack(1) +typedef struct tagTgaHeader +{ + BYTE IdLength; // Image ID Field Length + BYTE CmapType; // Color Map Type + BYTE ImageType; // Image Type + + WORD CmapIndex; // First Entry Index + WORD CmapLength; // Color Map Length + BYTE CmapEntrySize; // Color Map Entry Size + + WORD X_Origin; // X-origin of Image + WORD Y_Origin; // Y-origin of Image + WORD ImageWidth; // Image Width + WORD ImageHeight; // Image Height + BYTE PixelDepth; // Pixel Depth + BYTE ImagDesc; // Image Descriptor +} TGAHEADER; +#pragma pack() + +public: + CxImageTGA(): CxImage(CXIMAGE_FORMAT_TGA) {} + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TGA);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TGA);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile); + bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } +#endif // CXIMAGE_SUPPORT_ENCODE +protected: + BYTE ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover); + void ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset); +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximath.cpp ./win32/dependencies/cximage/ximath.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximath.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximath.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,97 @@ +#include "ximage.h" +#include "ximath.h" +#include + +//this module should contain some classes for geometrical transformations +//usable with selections, etc... once it's done, that is. :) + +CxPoint2::CxPoint2() +{ + x=y=0.0f; +} + +CxPoint2::CxPoint2(float const x_, float const y_) +{ + x=x_; + y=y_; +} + +CxPoint2::CxPoint2(CxPoint2 const &p) +{ + x=p.x; + y=p.y; +} + +float CxPoint2::Distance(CxPoint2 const p2) +{ + return (float)sqrt((x-p2.x)*(x-p2.x)+(y-p2.y)*(y-p2.y)); +} + +float CxPoint2::Distance(float const x_, float const y_) +{ + return (float)sqrt((x-x_)*(x-x_)+(y-y_)*(y-y_)); +} + +CxRect2::CxRect2() +{ +} + +CxRect2::CxRect2(float const x1_, float const y1_, float const x2_, float const y2_) +{ + botLeft.x=x1_; + botLeft.y=y1_; + topRight.x=x2_; + topRight.y=y2_; +} + +CxRect2::CxRect2(CxRect2 const &p) +{ + botLeft=p.botLeft; + topRight=p.topRight; +} + +float CxRect2::Surface() const +/* + * Returns the surface of rectangle. + */ +{ + return (topRight.x-botLeft.x)*(topRight.y-botLeft.y); +} + +CxRect2 CxRect2::CrossSection(CxRect2 const &r2) const +/* + * Returns crossection with another rectangle. + */ +{ + CxRect2 cs; + cs.botLeft.x=max(botLeft.x, r2.botLeft.x); + cs.botLeft.y=max(botLeft.y, r2.botLeft.y); + cs.topRight.x=min(topRight.x, r2.topRight.x); + cs.topRight.y=min(topRight.y, r2.topRight.y); + if (cs.botLeft.x<=cs.topRight.x && cs.botLeft.y<=cs.topRight.y) { + return cs; + } else { + return CxRect2(0,0,0,0); + }//if +} + +CxPoint2 CxRect2::Center() const +/* + * Returns the center point of rectangle. + */ +{ + return CxPoint2((topRight.x+botLeft.x)/2.0f, (topRight.y+botLeft.y)/2.0f); +} + +float CxRect2::Width() const +//returns rectangle width +{ + return topRight.x-botLeft.x; +} + +float CxRect2::Height() const +//returns rectangle height +{ + return topRight.y-botLeft.y; +} + diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximath.h ./win32/dependencies/cximage/ximath.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximath.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximath.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,39 @@ +#if !defined(__ximath_h) +#define __ximath_h + +#include "ximadef.h" + +//***bd*** simple floating point point +class DLL_EXP CxPoint2 +{ +public: + CxPoint2(); + CxPoint2(float const x_, float const y_); + CxPoint2(CxPoint2 const &p); + + float Distance(CxPoint2 const p2); + float Distance(float const x_, float const y_); + + float x,y; +}; + +//and simple rectangle +class DLL_EXP CxRect2 +{ +public: + CxRect2(); + CxRect2(float const x1_, float const y1_, float const x2_, float const y2_); + CxRect2(CxPoint2 const &bl, CxPoint2 const &tr); + CxRect2(CxRect2 const &p); + + float Surface() const; + CxRect2 CrossSection(CxRect2 const &r2) const; + CxPoint2 Center() const; + float Width() const; + float Height() const; + + CxPoint2 botLeft; + CxPoint2 topRight; +}; + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatif.cpp ./win32/dependencies/cximage/ximatif.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatif.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximatif.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,763 @@ +/* + * File: ximatif.cpp + * Purpose: Platform Independent TIFF Image Class Loader and Writer + * 07/Aug/2001 Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximatif.h" + +#if CXIMAGE_SUPPORT_TIF + +#include "../tiff/tiffio.h" + +#define CVT(x) (((x) * 255L) / ((1L<<16)-1)) +#define SCALE(x) (((x)*((1L<<16)-1))/255) +#define CalculateLine(width,bitdepth) (((width * bitdepth) + 7) / 8) +#define CalculatePitch(line) (line + 3 & ~3) + +extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode); + +//////////////////////////////////////////////////////////////////////////////// +CxImageTIF::~CxImageTIF() +{ + if (m_tif2) TIFFClose(m_tif2); +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageTIF::Decode(CxFile * hFile) +{ + //Comment this line if you need more information on errors + // TIFFSetErrorHandler(NULL); // + + //Open file and fill the TIFF structure + // m_tif = TIFFOpen(imageFileName,"rb"); + TIFF* m_tif = _TIFFOpenEx(hFile, "rb"); + + uint32 height=0; + uint32 width=0; + uint16 bitspersample=1; + uint16 samplesperpixel=1; + uint32 rowsperstrip=(DWORD)-1; + uint16 photometric=0; + uint16 compression=1; + uint16 orientation=ORIENTATION_TOPLEFT; // + uint16 res_unit; // + uint32 x, y; + float resolution, offset; + BOOL isRGB; + BYTE *bits; //pointer to source data + BYTE *bits2; //pointer to destination data + + try{ + //check if it's a tiff file + if (!m_tif) + throw "Error encountered while opening TIFF file"; + + // - 12/2002 : get NumFrames directly, instead of looping + // info.nNumFrames=0; + // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++; + info.nNumFrames = TIFFNumberOfDirectories(m_tif); + + if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame)) + throw "Error: page not present in TIFF file"; + + //get image info + TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height); + TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); + TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); + TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric); + TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation); + + if (info.nEscape == -1) { + // Return output dimensions only + head.biWidth = width; + head.biHeight = height; + throw "output dimensions returned"; + } + + TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit); + if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution)) + { + if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); + SetXDPI((long)resolution); + } + if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution)) + { + if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); + SetYDPI((long)resolution); + } + + if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset)) info.xOffset = (long)offset; + if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset)) info.yOffset = (long)offset; + + head.biClrUsed=0; + info.nBkgndIndex =-1; + + if (rowsperstrip>height){ + rowsperstrip=height; + TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + } + + isRGB = (bitspersample >= 8) && + (photometric == PHOTOMETRIC_RGB) || + (photometric == PHOTOMETRIC_YCBCR) || + (photometric == PHOTOMETRIC_SEPARATED) || + (photometric == PHOTOMETRIC_LOGL) || + (photometric == PHOTOMETRIC_LOGLUV); + + if (isRGB){ + head.biBitCount=24; + }else{ + if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)){ + if (bitspersample == 1){ + head.biBitCount=1; //B&W image + head.biClrUsed =2; + } else if (bitspersample == 4) { + head.biBitCount=4; //16 colors gray scale + head.biClrUsed =16; + } else { + head.biBitCount=8; //gray scale + head.biClrUsed =256; + } + } else if (bitspersample == 4) { + head.biBitCount=4; // 16 colors + head.biClrUsed=16; + } else { + head.biBitCount=8; //256 colors + head.biClrUsed=256; + } + } + + if (info.nEscape) throw "Cancelled"; // - cancel decoding + + Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF); //image creation + if (!pDib) throw "CxImageTIF can't create image"; + +#if CXIMAGE_SUPPORT_ALPHA + if (samplesperpixel==4) AlphaCreate(); //add alpha support for 32bpp tiffs + if (samplesperpixel==2 && bitspersample==8) AlphaCreate(); //add alpha support for 8bpp + alpha +#endif //CXIMAGE_SUPPORT_ALPHA + + TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression); + SetCodecOption(compression); // save original compression type + + if (isRGB) { + // Read the whole image into one big RGBA buffer using + // the traditional TIFFReadRGBAImage() API that we trust. + uint32* raster; // retrieve RGBA image + uint32 *row; + + raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); + if (raster == NULL) throw "No space for raster buffer"; + + // Read the image in one chunk into an RGBA array + if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) { + _TIFFfree(raster); + throw "Corrupted TIFF file!"; + } + + // read the raster lines and save them in the DIB + // with RGB mode, we have to change the order of the 3 samples RGB + row = &raster[0]; + bits2 = info.pImage; + for (y = 0; y < height; y++) { + + if (info.nEscape){ // - cancel decoding + _TIFFfree(raster); + throw "Cancelled"; + } + + bits = bits2; + for (x = 0; x < width; x++) { + *bits++ = (BYTE)TIFFGetB(row[x]); + *bits++ = (BYTE)TIFFGetG(row[x]); + *bits++ = (BYTE)TIFFGetR(row[x]); +#if CXIMAGE_SUPPORT_ALPHA + if (samplesperpixel==4) AlphaSet(x,y,(BYTE)TIFFGetA(row[x])); +#endif //CXIMAGE_SUPPORT_ALPHA + } + row += width; + bits2 += info.dwEffWidth; + } + _TIFFfree(raster); + } else { + RGBQUAD *pal; + pal=(RGBQUAD*)calloc(256,sizeof(RGBQUAD)); + if (pal==NULL) throw "Unable to allocate TIFF palette"; + + // set up the colormap based on photometric + switch(photometric) { + case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types + case PHOTOMETRIC_MINISWHITE: + if (bitspersample == 1) { // Monochrome image + if (photometric == PHOTOMETRIC_MINISBLACK) { + pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; + } else { + pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; + } + } else { // need to build the scale for greyscale images + if (photometric == PHOTOMETRIC_MINISBLACK) { + for (DWORD i=0; i 0) { + if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) { + Palette16Bits=TRUE; + break; + } + } + + // load the palette in the DIB + for (int i = (1 << bitspersample) - 1; i >= 0; i--) { + if (Palette16Bits) { + pal[i].rgbRed =(BYTE) CVT(red[i]); + pal[i].rgbGreen = (BYTE) CVT(green[i]); + pal[i].rgbBlue = (BYTE) CVT(blue[i]); + } else { + pal[i].rgbRed = (BYTE) red[i]; + pal[i].rgbGreen = (BYTE) green[i]; + pal[i].rgbBlue = (BYTE) blue[i]; + } + } + break; + } + SetPalette(pal,head.biClrUsed); //palette assign + free(pal); + + // read the tiff lines and save them in the DIB + uint32 nrow; + uint32 ys; + int line = CalculateLine(width, bitspersample * samplesperpixel); + long bitsize= TIFFStripSize(m_tif); + //verify bitsize: could be wrong if StripByteCounts is missing. + if (bitsize>(long)(head.biSizeImage*samplesperpixel)) bitsize=head.biSizeImage*samplesperpixel; + + int tiled_image = TIFFIsTiled(m_tif); + uint32 tw, tl; + BYTE* tilebuf; + if (tiled_image){ + TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl); + rowsperstrip = tl; + bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw); + tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif)); + } + + bits = (BYTE*)malloc(bitsize); + if (bits==NULL){ + throw "CxImageTIF can't allocate memory"; + } + + for (ys = 0; ys < height; ys += rowsperstrip) { + + if (info.nEscape){ // - cancel decoding + free(bits); + throw "Cancelled"; + } + + nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip); + + if (tiled_image){ + uint32 imagew = TIFFScanlineSize(m_tif); + uint32 tilew = TIFFTileRowSize(m_tif); + int iskew = imagew - tilew; + uint8* bufp = (uint8*) bits; + + uint32 colb = 0; + for (uint32 col = 0; col < width; col += tw) { + if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){ + free(tilebuf); + free(bits); + throw "Corrupted tiled TIFF file!"; + } + + if (colb + tw > imagew) { + uint32 owidth = imagew - colb; + uint32 oskew = tilew - owidth; + TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew ); + } else { + TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0); + } + colb += tilew; + } + + } else { + if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), bits, nrow * line) == -1) { + free(bits); + throw "Corrupted TIFF file!"; + } + } + + for (y = 0; y < nrow; y++) { + long offset=(nrow-y-1)*line; + if (bitspersample==16) for (DWORD xi=0;xi=(int)width){ + yi--; + xi=0; + } + } + } else { //photometric==PHOTOMETRIC_CIELAB + if (head.biBitCount!=24){ //fix image + Create(width,height,24,CXIMAGE_FORMAT_TIF); +#if CXIMAGE_SUPPORT_ALPHA + if (samplesperpixel==4) AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + } + + int xi=0; + int ii=0; + int yi=height-ys-nrow+y; + RGBQUAD c; + int l,a,b,bitsoffset; + double p,cx,cy,cz,cr,cg,cb; + while (ii127) a-=256; + if (b>127) b-=256; + // lab to xyz + p = (l/2.55 + 16) / 116.0; + cx = pow( p + a * 0.002, 3); + cy = pow( p, 3); + cz = pow( p - b * 0.005, 3); + // white point + cx*=0.95047; + //cy*=1.000; + cz*=1.0883; + // xyz to rgb + cr = 3.240479 * cx - 1.537150 * cy - 0.498535 * cz; + cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz; + cb = 0.055648 * cx - 0.204043 * cy + 1.057311 * cz; + + if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055; + else cr = 12.92 * cr; + if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055; + else cg = 12.92 * cg; + if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055; + else cb = 12.92 * cb; + + c.rgbRed =(BYTE)max(0,min(255,(int)(cr*255))); + c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255))); + c.rgbBlue =(BYTE)max(0,min(255,(int)(cb*255))); + + SetPixelColor(xi,yi,c); +#if CXIMAGE_SUPPORT_ALPHA + if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]); +#endif //CXIMAGE_SUPPORT_ALPHA + ii++; + xi++; + if (xi>=(int)width){ + yi--; + xi=0; + } + } + } + } + } + free(bits); + if (tiled_image) free(tilebuf); + + switch(orientation){ + case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */ + Mirror(); + break; + case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */ + Flip(); + Mirror(); + break; + case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */ + Flip(); + break; + case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */ + RotateRight(); + Mirror(); + break; + case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */ + RotateLeft(); + break; + case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */ + RotateLeft(); + Mirror(); + break; + case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */ + RotateRight(); + break; + } + + } + } catch (char *message) { + strncpy(info.szLastError,message,255); + if (m_tif) TIFFClose(m_tif); + if (info.nEscape==-1) return true; + return false; + } + TIFFClose(m_tif); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_ENCODE +//////////////////////////////////////////////////////////////////////////////// +bool CxImageTIF::Encode(CxFile * hFile, bool bAppend) +{ + try{ + if (hFile==NULL) throw CXIMAGE_ERR_NOFILE; + if (pDib==NULL) throw CXIMAGE_ERR_NOIMAGE; + + // replaced "w+b" with "a", to append an image directly on an existing file + if (m_tif2==NULL) m_tif2=_TIFFOpenEx(hFile, "a"); + if (m_tif2==NULL) throw "initialization fail"; + + if (bAppend || m_pages) m_multipage=true; + m_pages++; + + if (!EncodeBody(m_tif2,m_multipage,m_pages,m_pages)) throw "Error saving TIFF file"; + if (bAppend) { + if (!TIFFWriteDirectory(m_tif2)) throw "Error saving TIFF directory"; + } + } catch (char *message) { + strncpy(info.szLastError,message,255); + if (m_tif2){ + TIFFClose(m_tif2); + m_tif2=NULL; + m_multipage=false; + m_pages=0; + } + return false; + } + if (!bAppend){ + TIFFClose(m_tif2); + m_tif2=NULL; + m_multipage=false; + m_pages=0; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +// Thanks to Abe +bool CxImageTIF::Encode(CxFile * hFile, CxImage ** pImages, int pagecount) +{ + try{ + if (hFile==NULL) throw "invalid file pointer"; + if (pImages==NULL || pagecount==0) throw "multipage TIFF, no images!"; + + CxImageTIF ghost; + for (int i=1; i<=pagecount; i++){ + if (pImages[i-1]==NULL) throw "Bad image pointer"; + ghost.Ghost(pImages[i-1]); + if (!ghost.Encode(hFile,true)) throw "Error saving TIFF file"; + } + } catch (char *message) { + strncpy(info.szLastError,message,255); + return false; + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImageTIF::EncodeBody(TIFF *m_tif, bool multipage, int page, int pagecount) +{ + uint32 height=head.biHeight; + uint32 width=head.biWidth; + uint16 bitcount=head.biBitCount; + uint16 bitspersample; + uint16 samplesperpixel; + uint16 photometric=0; + uint16 compression; +// uint16 pitch; +// int line; + uint32 x, y; + + samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (BYTE)3 : (BYTE)1; +#if CXIMAGE_SUPPORT_ALPHA + if (bitcount==24 && AlphaIsValid()) { bitcount=32; samplesperpixel=4; } +#endif //CXIMAGE_SUPPORT_ALPHA + + bitspersample = bitcount / samplesperpixel; + + //set the PHOTOMETRIC tag + RGBQUAD *rgb = GetPalette(); + switch (bitcount) { + case 1: + if (CompareColors(&rgb[0],&rgb[1])<0) { + /* some viewers do not handle PHOTOMETRIC_MINISBLACK: + * let's transform the image in PHOTOMETRIC_MINISWHITE + */ + //invert the colors + RGBQUAD tempRGB=GetPaletteColor(0); + SetPaletteColor(0,GetPaletteColor(1)); + SetPaletteColor(1,tempRGB); + //invert the pixels + BYTE *iSrc=info.pImage; + for (unsigned long i=0;irgbRed != x)||(rgb->rgbRed != rgb->rgbGreen)||(rgb->rgbRed != rgb->rgbBlue)){ + photometric = PHOTOMETRIC_PALETTE; + break; + } + rgb++; + } + break; + case 24: + case 32: + photometric = PHOTOMETRIC_RGB; + break; + } + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid() && bitcount==8) samplesperpixel=2; //8bpp + alpha layer +#endif //CXIMAGE_SUPPORT_ALPHA + +// line = CalculateLine(width, bitspersample * samplesperpixel); +// pitch = (uint16)CalculatePitch(line); + + //prepare the palette struct + RGBQUAD pal[256]; + if (GetPalette()){ + BYTE b; + memcpy(pal,GetPalette(),GetPaletteSize()); + for(WORD a=0;a gives better compression + TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + + // handle metrics + TIFFSetField(m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + TIFFSetField(m_tif, TIFFTAG_XRESOLUTION, (float)info.xDPI); + TIFFSetField(m_tif, TIFFTAG_YRESOLUTION, (float)info.yDPI); +// TIFFSetField(m_tif, TIFFTAG_XPOSITION, (float)info.xOffset); +// TIFFSetField(m_tif, TIFFTAG_YPOSITION, (float)info.yOffset); + + // multi-paging - Thanks to Abe + if (multipage) + { + char page_number[20]; + sprintf(page_number, "Page %d", page); + + TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); + TIFFSetField(m_tif, TIFFTAG_PAGENUMBER, page,pagecount); + TIFFSetField(m_tif, TIFFTAG_PAGENAME, page_number); + } else { + TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, 0); + } + + // palettes (image colormaps are automatically scaled to 16-bits) + if (photometric == PHOTOMETRIC_PALETTE) { + uint16 *r, *g, *b; + r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256); + g = r + 256; + b = g + 256; + + for (int i = 255; i >= 0; i--) { + b[i] = (uint16)SCALE((uint16)pal[i].rgbRed); + g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen); + r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue); + } + + TIFFSetField(m_tif, TIFFTAG_COLORMAP, r, g, b); + _TIFFfree(r); + } + + // compression + if (GetCodecOption(CXIMAGE_FORMAT_TIF)) { + compression = (WORD)GetCodecOption(CXIMAGE_FORMAT_TIF); + } else { + switch (bitcount) { + case 1 : + compression = COMPRESSION_CCITTFAX4; + break; + case 4 : + case 8 : + compression = COMPRESSION_LZW; + break; + case 24 : + case 32 : + compression = COMPRESSION_JPEG; + break; + default : + compression = COMPRESSION_NONE; + break; + } + } + TIFFSetField(m_tif, TIFFTAG_COMPRESSION, compression); + + switch (compression) { + case COMPRESSION_JPEG: + TIFFSetField(m_tif, TIFFTAG_JPEGQUALITY, info.nQuality); + TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, ((7+rowsperstrip)>>3)<<3); + break; + case COMPRESSION_LZW: + if (bitcount>=8) TIFFSetField(m_tif, TIFFTAG_PREDICTOR, 2); + break; + } + + // read the DIB lines from bottom to top and save them in the TIF + + BYTE *bits; + switch(bitcount) { + case 1 : + case 4 : + case 8 : + { + if (samplesperpixel==1){ + for (y = 0; y < height; y++) { + bits= info.pImage + (height - y - 1)*info.dwEffWidth; + if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) return false; + } + } +#if CXIMAGE_SUPPORT_ALPHA + else { //8bpp + alpha layer + bits = (BYTE*)malloc(2*width); + if (!bits) return false; + for (y = 0; y < height; y++) { + for (x=0;x 0) { + uint32 j = cols; + while (j-- > 0) + *out++ = *in++; + out += outskew; + in += inskew; + } +} +//////////////////////////////////////////////////////////////////////////////// +TIFF* CxImageTIF::TIFFOpenEx(CxFile * hFile) +{ + if (hFile) return _TIFFOpenEx(hFile, "rb"); + return NULL; +} +//////////////////////////////////////////////////////////////////////////////// +void CxImageTIF::TIFFCloseEx(TIFF* tif) +{ + if (tif) TIFFClose(tif); +} +//////////////////////////////////////////////////////////////////////////////// +#endif // CXIMAGE_SUPPORT_TIF diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatif.h ./win32/dependencies/cximage/ximatif.h --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatif.h 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximatif.h 2006-08-24 07:16:03 +0900 @@ -0,0 +1,60 @@ +/* + * File: ximatif.h + * Purpose: TIFF Image Class Loader and Writer + */ +/* ========================================================== + * CxImageTIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it + * For conditions of distribution and use, see copyright notice in ximage.h + * + * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes + * + * Special thanks to Abe for MultiPageTIFF code. + * + * LibTIFF is: + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * ========================================================== + */ + +#if !defined(__ximatif_h) +#define __ximatif_h + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_TIF + +#include "../tiff/tiffio.h" + +class DLL_EXP CxImageTIF: public CxImage +{ +public: + CxImageTIF(): CxImage(CXIMAGE_FORMAT_TIF) {m_tif2=NULL; m_multipage=false; m_pages=0;} + ~CxImageTIF(); + + TIFF* TIFFOpenEx(CxFile * hFile); + void TIFFCloseEx(TIFF* tif); + +// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TIF);} +// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TIF);} + bool Decode(CxFile * hFile); + bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } + +#if CXIMAGE_SUPPORT_ENCODE + bool Encode(CxFile * hFile, bool bAppend=false); + bool Encode(CxFile * hFile, CxImage ** pImages, int pagecount); + bool Encode(FILE *hFile, bool bAppend=false) { CxIOFile file(hFile); return Encode(&file,bAppend); } + bool Encode(FILE *hFile, CxImage ** pImages, int pagecount) + { CxIOFile file(hFile); return Encode(&file, pImages, pagecount); } +#endif // CXIMAGE_SUPPORT_ENCODE + +protected: + void TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew); + bool EncodeBody(TIFF *m_tif, bool multipage=false, int page=0, int pagecount=0); + TIFF *m_tif2; + bool m_multipage; + int m_pages; +}; + +#endif + +#endif diff -urN ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatran.cpp ./win32/dependencies/cximage/ximatran.cpp --- ../VisualBoyAdvance-1.7.2/win32/dependencies/cximage/ximatran.cpp 1970-01-01 09:00:00 +0900 +++ ./win32/dependencies/cximage/ximatran.cpp 2006-08-24 07:16:03 +0900 @@ -0,0 +1,2439 @@ +// xImaTran.cpp : Transformation functions +/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it + * CxImage version 5.99c 17/Oct/2004 + */ + +#include "ximage.h" +#include "ximath.h" + +#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::GrayScale() +{ + if (!pDib) return false; + if (head.biBitCount<=8){ + RGBQUAD* ppal=GetPalette(); + int gray; + //converts the colors to gray, use the blue channel only + for(DWORD i=0;iIsValid()) return false; + BYTE *iSrc,*iDst; + iSrc=info.pImage + (head.biHeight-1)*info.dwEffWidth; + iDst=imatmp->info.pImage; + for(long y=0; y < head.biHeight; y++){ + memcpy(iDst,iSrc,info.dwEffWidth); + iSrc-=info.dwEffWidth; + iDst+=info.dwEffWidth; + } + +#if CXIMAGE_SUPPORT_ALPHA + imatmp->AlphaFlip(); +#endif //CXIMAGE_SUPPORT_ALPHA + + Transfer(*imatmp); + delete imatmp; + return true; +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::Mirror() +{ + if (!pDib) return false; + + CxImage* imatmp = new CxImage(*this,false,false,true); + if (!imatmp) return false; + BYTE *iSrc,*iDst; + long wdt=(head.biWidth-1) * (head.biBitCount==24 ? 3:1); + iSrc=info.pImage + wdt; + iDst=imatmp->info.pImage; + long x,y; + switch (head.biBitCount){ + case 24: + for(y=0; y < head.biHeight; y++){ + for(x=0; x <= wdt; x+=3){ + *(iDst+x)=*(iSrc-x); + *(iDst+x+1)=*(iSrc-x+1); + *(iDst+x+2)=*(iSrc-x+2); + } + iSrc+=info.dwEffWidth; + iDst+=info.dwEffWidth; + } + break; + case 8: + for(y=0; y < head.biHeight; y++){ + for(x=0; x <= wdt; x++) + *(iDst+x)=*(iSrc-x); + iSrc+=info.dwEffWidth; + iDst+=info.dwEffWidth; + } + break; + default: + for(y=0; y < head.biHeight; y++){ + for(x=0; x <= wdt; x++) + imatmp->SetPixelIndex(x,y,GetPixelIndex(wdt-x,y)); + } + } + +#if CXIMAGE_SUPPORT_ALPHA + imatmp->AlphaMirror(); +#endif //CXIMAGE_SUPPORT_ALPHA + + Transfer(*imatmp); + delete imatmp; + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +#define RBLOCK 64 + +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::RotateLeft(CxImage* iDst) +{ + if (!pDib) return false; + + long newWidth = GetHeight(); + long newHeight = GetWidth(); + + CxImage imgDest; + imgDest.CopyInfo(*this); + imgDest.Create(newWidth,newHeight,GetBpp(),GetType()); + imgDest.SetPalette(GetPalette()); + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) imgDest.AlphaCreate(); +#endif + + long x,x2,y,dlineup; + + // Speedy rotate for BW images + if (head.biBitCount == 1) { + + BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp; + div_t div_r; + + BYTE *bsrc = GetBits(), *bdest = imgDest.GetBits(); + dbitsmax = bdest + imgDest.head.biSizeImage - 1; + dlineup = 8 * imgDest.info.dwEffWidth - imgDest.head.biWidth; + + imgDest.Clear(0); + for (y = 0; y < head.biHeight; y++) { + // Figure out the Column we are going to be copying to + div_r = div((int)(y + dlineup), 8); + // set bit pos of src column byte + bitpos = 1 << div_r.rem; + srcdisp = bsrc + y * info.dwEffWidth; + for (x = 0; x < (long)info.dwEffWidth; x++) { + // Get Source Bits + sbits = srcdisp + x; + // Get destination column + nrow = bdest + (x * 8) * imgDest.info.dwEffWidth + imgDest.info.dwEffWidth - 1 - div_r.quot; + for (long z = 0; z < 8; z++) { + // Get Destination Byte + dbits = nrow + z * imgDest.info.dwEffWidth; + if ((dbits < bdest) || (dbits > dbitsmax)) break; + if (*sbits & (128 >> z)) *dbits |= bitpos; + } + } + }//for y + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) { + for (x = 0; x < newWidth; x++){ + x2=newWidth-x-1; + for (y = 0; y < newHeight; y++){ + imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2)); + }//for y + }//for x + } +#endif //CXIMAGE_SUPPORT_ALPHA + + } else { + //anything other than BW: + //bd, 10. 2004: This optimized version of rotation rotates image by smaller blocks. It is quite + //a bit faster than obvious algorithm, because it produces much less CPU cache misses. + //This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current + //CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase + //speed somehow, but once you drop out of CPU's cache, things will slow down drastically. + //For older CPUs with less cache, lower value would yield better results. + + BYTE *srcPtr, *dstPtr; //source and destionation for 24-bit version + int xs, ys; //x-segment and y-segment + for (xs = 0; xs < newWidth; xs+=RBLOCK) { //for all image blocks of RBLOCK*RBLOCK pixels + for (ys = 0; ys < newHeight; ys+=RBLOCK) { + if (head.biBitCount==24) { + //RGB24 optimized pixel access: + for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ //do rotation + info.nProgress = (long)(100*x/newWidth); + x2=newWidth-x-1; + dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(x,ys); + srcPtr = (BYTE*) BlindGetPixelPointer(ys, x2); + for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ + //imgDest.SetPixelColor(x, y, GetPixelColor(y, x2)); + *(dstPtr) = *(srcPtr); + *(dstPtr+1) = *(srcPtr+1); + *(dstPtr+2) = *(srcPtr+2); + srcPtr += 3; + dstPtr += imgDest.info.dwEffWidth; + }//for y + }//for x + } else { + //anything else than 24bpp (and 1bpp): palette + for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ + info.nProgress = (long)(100*x/newWidth); // + x2=newWidth-x-1; + for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ + imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y, x2)); + }//for y + }//for x + }//if (version selection) +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha) { + for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ + x2=newWidth-x-1; + for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ + imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2)); + }//for y + }//for x + }//if (alpha channel) +#endif //CXIMAGE_SUPPORT_ALPHA + }//for ys + }//for xs + }//if + + //select the destination + if (iDst) iDst->Transfer(imgDest); + else Transfer(imgDest); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::RotateRight(CxImage* iDst) +{ + if (!pDib) return false; + + long newWidth = GetHeight(); + long newHeight = GetWidth(); + + CxImage imgDest; + imgDest.CopyInfo(*this); + imgDest.Create(newWidth,newHeight,GetBpp(),GetType()); + imgDest.SetPalette(GetPalette()); + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) imgDest.AlphaCreate(); +#endif + + long x,y,y2; + // Speedy rotate for BW images + if (head.biBitCount == 1) { + + BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp; + div_t div_r; + + BYTE *bsrc = GetBits(), *bdest = imgDest.GetBits(); + dbitsmax = bdest + imgDest.head.biSizeImage - 1; + + imgDest.Clear(0); + for (y = 0; y < head.biHeight; y++) { + // Figure out the Column we are going to be copying to + div_r = div((int)y, 8); + // set bit pos of src column byte + bitpos = 128 >> div_r.rem; + srcdisp = bsrc + y * info.dwEffWidth; + for (x = 0; x < (long)info.dwEffWidth; x++) { + // Get Source Bits + sbits = srcdisp + x; + // Get destination column + nrow = bdest + (imgDest.head.biHeight-1-(x*8)) * imgDest.info.dwEffWidth + div_r.quot; + for (long z = 0; z < 8; z++) { + // Get Destination Byte + dbits = nrow - z * imgDest.info.dwEffWidth; + if ((dbits < bdest) || (dbits > dbitsmax)) break; + if (*sbits & (128 >> z)) *dbits |= bitpos; + } + } + } + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()){ + for (y = 0; y < newHeight; y++){ + y2=newHeight-y-1; + for (x = 0; x < newWidth; x++){ + imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x)); + } + } + } +#endif //CXIMAGE_SUPPORT_ALPHA + + } else { + //anything else but BW + BYTE *srcPtr, *dstPtr; //source and destionation for 24-bit version + int xs, ys; //x-segment and y-segment + for (xs = 0; xs < newWidth; xs+=RBLOCK) { + for (ys = 0; ys < newHeight; ys+=RBLOCK) { + if (head.biBitCount==24) { + //RGB24 optimized pixel access: + for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ + info.nProgress = (long)(100*y/newHeight); // + y2=newHeight-y-1; + dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(xs,y); + srcPtr = (BYTE*) BlindGetPixelPointer(y2, xs); + for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ + //imgDest.SetPixelColor(x, y, GetPixelColor(y2, x)); + *(dstPtr) = *(srcPtr); + *(dstPtr+1) = *(srcPtr+1); + *(dstPtr+2) = *(srcPtr+2); + dstPtr += 3; + srcPtr += info.dwEffWidth; + }//for x + }//for y + } else { + //anything else than BW & RGB24: palette + for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ + info.nProgress = (long)(100*y/newHeight); // + y2=newHeight-y-1; + for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ + imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y2, x)); + }//for x + }//for y + }//if +#if CXIMAGE_SUPPORT_ALPHA + if (pAlpha){ + for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ + y2=newHeight-y-1; + for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ + imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x)); + }//for x + }//for y + }//if (has alpha) +#endif //CXIMAGE_SUPPORT_ALPHA + }//for ys + }//for xs + }//if + + //select the destination + if (iDst) iDst->Transfer(imgDest); + else Transfer(imgDest); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::Negative() +{ + if (!pDib) return false; + + if (head.biBitCount<=8){ + if (IsGrayScale()){ //GRAYSCALE, selection + if (pSelection){ + for(long y=info.rSelectionBox.bottom; y invert transparent color too + info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue); + info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen); + info.nBkgndColor.rgbRed = (BYTE)(255-info.nBkgndColor.rgbRed); + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS +//////////////////////////////////////////////////////////////////////////////// +#if CXIMAGE_SUPPORT_TRANSFORMATION +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::Rotate(float angle, CxImage* iDst) +{ + if (!pDib) return false; + + // Copyright (c) 1996-1998 Ulrich von Zadow + + // Negative the angle, because the y-axis is negative. + double ang = -angle*acos((float)0)/90; + int newWidth, newHeight; + int nWidth = GetWidth(); + int nHeight= GetHeight(); + double cos_angle = cos(ang); + double sin_angle = sin(ang); + + // Calculate the size of the new bitmap + POINT p1={0,0}; + POINT p2={nWidth,0}; + POINT p3={0,nHeight}; + POINT p4={nWidth-1,nHeight}; + POINT newP1,newP2,newP3,newP4, leftTop, rightTop, leftBottom, rightBottom; + + newP1.x = p1.x; + newP1.y = p1.y; + newP2.x = (long)floor(p2.x*cos_angle - p2.y*sin_angle); + newP2.y = (long)floor(p2.x*sin_angle + p2.y*cos_angle); + newP3.x = (long)floor(p3.x*cos_angle - p3.y*sin_angle); + newP3.y = (long)floor(p3.x*sin_angle + p3.y*cos_angle); + newP4.x = (long)floor(p4.x*cos_angle - p4.y*sin_angle); + newP4.y = (long)floor(p4.x*sin_angle + p4.y*cos_angle); + + leftTop.x = min(min(newP1.x,newP2.x),min(newP3.x,newP4.x)); + leftTop.y = min(min(newP1.y,newP2.y),min(newP3.y,newP4.y)); + rightBottom.x = max(max(newP1.x,newP2.x),max(newP3.x,newP4.x)); + rightBottom.y = max(max(newP1.y,newP2.y),max(newP3.y,newP4.y)); + leftBottom.x = leftTop.x; + leftBottom.y = 2+rightBottom.y; + rightTop.x = 2+rightBottom.x; + rightTop.y = leftTop.y; + + newWidth = rightTop.x - leftTop.x; + newHeight= leftBottom.y - leftTop.y; + CxImage imgDest; + imgDest.CopyInfo(*this); + imgDest.Create(newWidth,newHeight,GetBpp(),GetType()); + imgDest.SetPalette(GetPalette()); + +#if CXIMAGE_SUPPORT_ALPHA + if(AlphaIsValid()) //MTA: Fix for rotation problem when the image has an alpha channel + { + imgDest.AlphaCreate(); + imgDest.AlphaClear(); + } +#endif //CXIMAGE_SUPPORT_ALPHA + + int x,y,newX,newY,oldX,oldY; + + if (head.biClrUsed==0){ //RGB + for (y = leftTop.y, newY = 0; y<=leftBottom.y; y++,newY++){ + info.nProgress = (long)(100*newY/newHeight); + if (info.nEscape) break; + for (x = leftTop.x, newX = 0; x<=rightTop.x; x++,newX++){ + oldX = (long)(x*cos_angle + y*sin_angle - 0.5); + oldY = (long)(y*cos_angle - x*sin_angle - 0.5); + imgDest.SetPixelColor(newX,newY,GetPixelColor(oldX,oldY)); +#if CXIMAGE_SUPPORT_ALPHA + imgDest.AlphaSet(newX,newY,AlphaGet(oldX,oldY)); //MTA: copy the alpha value +#endif //CXIMAGE_SUPPORT_ALPHA + } + } + } else { //PALETTE + for (y = leftTop.y, newY = 0; y<=leftBottom.y; y++,newY++){ + info.nProgress = (long)(100*newY/newHeight); + if (info.nEscape) break; + for (x = leftTop.x, newX = 0; x<=rightTop.x; x++,newX++){ + oldX = (long)(x*cos_angle + y*sin_angle - 0.5); + oldY = (long)(y*cos_angle - x*sin_angle - 0.5); + imgDest.SetPixelIndex(newX,newY,GetPixelIndex(oldX,oldY)); +#if CXIMAGE_SUPPORT_ALPHA + imgDest.AlphaSet(newX,newY,AlphaGet(oldX,oldY)); //MTA: copy the alpha value +#endif //CXIMAGE_SUPPORT_ALPHA + } + } + } + //select the destination + if (iDst) iDst->Transfer(imgDest); + else Transfer(imgDest); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Rotates image around it's center. + * Method can use interpolation with paletted images, but does not change pallete, so results vary. + * (If you have only four colours in a palette, there's not much room for interpolation.) + * + * \param angle - angle in degrees (positive values rotate clockwise) + * \param *iDst - destination image (if null, this image is changed) + * \param inMethod - interpolation method used + * (IM_NEAREST_NEIGHBOUR produces aliasing (fast), IM_BILINEAR softens picture a bit (slower) + * IM_SHARPBICUBIC is slower and produces some halos...) + * \param ofMethod - overflow method (how to choose colour of pixels that have no source) + * \param replColor - replacement colour to use (OM_COLOR, OM_BACKGROUND with no background colour...) + * \param optimizeRightAngles - call faster methods for 90, 180, and 270 degree rotations. Faster methods + * are called for angles, where error (in location of corner pixels) is less + * than 0.25 pixels. + * \param bKeepOriginalSize - rotates the image without resizing. + * + * \author ***bd*** 2.2004 + */ +bool CxImage::Rotate2(float angle, + CxImage *iDst, + InterpolationMethod inMethod, + OverflowMethod ofMethod, + RGBQUAD *replColor, + bool const optimizeRightAngles, + bool const bKeepOriginalSize) +{ + if (!pDib) return false; //no dib no go + + double ang = -angle*acos(0.0f)/90.0f; //convert angle to radians and invert (positive angle performs clockwise rotation) + float cos_angle = (float) cos(ang); //these two are needed later (to rotate) + float sin_angle = (float) sin(ang); + + //Calculate the size of the new bitmap (rotate corners of image) + CxPoint2 p[4]; //original corners of the image + p[0]=CxPoint2(-0.5f,-0.5f); + p[1]=CxPoint2(GetWidth()-0.5f,-0.5f); + p[2]=CxPoint2(-0.5f,GetHeight()-0.5f); + p[3]=CxPoint2(GetWidth()-0.5f,GetHeight()-0.5f); + CxPoint2 newp[4]; //rotated positions of corners + //(rotate corners) + if (bKeepOriginalSize){ + for (int i=0; i<4; i++) { + newp[i].x = p[i].x; + newp[i].y = p[i].y; + }//for + } else { + for (int i=0; i<4; i++) { + newp[i].x = (p[i].x*cos_angle - p[i].y*sin_angle); + newp[i].y = (p[i].x*sin_angle + p[i].y*cos_angle); + }//for i + + if (optimizeRightAngles) { + //For rotations of 90, -90 or 180 or 0 degrees, call faster routines + if (newp[3].Distance(CxPoint2(GetHeight()-0.5f, 0.5f-GetWidth())) < 0.25) + //rotation right for circa 90 degrees (diagonal pixels less than 0.25 pixel away from 90 degree rotation destination) + return RotateRight(iDst); + if (newp[3].Distance(CxPoint2(0.5f-GetHeight(), -0.5f+GetWidth())) < 0.25) + //rotation left for ~90 degrees + return RotateLeft(iDst); + if (newp[3].Distance(CxPoint2(0.5f-GetWidth(), 0.5f-GetHeight())) < 0.25) + //rotation left for ~180 degrees + return Rotate180(iDst); + if (newp[3].Distance(p[3]) < 0.25) { + //rotation not significant + if (iDst) iDst->Copy(*this); //copy image to iDst, if required + return true; //and we're done + }//if + }//if + }//if + + //(read new dimensions from location of corners) + float minx = (float) min(min(newp[0].x,newp[1].x),min(newp[2].x,newp[3].x)); + float miny = (float) min(min(newp[0].y,newp[1].y),min(newp[2].y,newp[3].y)); + float maxx = (float) max(max(newp[0].x,newp[1].x),max(newp[2].x,newp[3].x)); + float maxy = (float) max(max(newp[0].y,newp[1].y),max(newp[2].y,newp[3].y)); + int newWidth = (int) floor(maxx-minx+0.5f); + int newHeight= (int) floor(maxy-miny+0.5f); + float ssx=((maxx+minx)- ((float) newWidth-1))/2.0f; //start for x + float ssy=((maxy+miny)- ((float) newHeight-1))/2.0f; //start for y + + float newxcenteroffset = 0.5f * newWidth; + float newycenteroffset = 0.5f * newHeight; + if (bKeepOriginalSize){ + ssx -= 0.5f * GetWidth(); + ssy -= 0.5f * GetHeight(); + } + + //create destination image + CxImage imgDest; + imgDest.CopyInfo(*this); + imgDest.Create(newWidth,newHeight,GetBpp(),GetType()); + imgDest.SetPalette(GetPalette()); +#if CXIMAGE_SUPPORT_ALPHA + if(AlphaIsValid()) imgDest.AlphaCreate(); //MTA: Fix for rotation problem when the image has an alpha channel +#endif //CXIMAGE_SUPPORT_ALPHA + + RGBQUAD rgb; //pixel colour + RGBQUAD rc; + if (replColor!=0) + rc=*replColor; + else { + rc.rgbRed=255; rc.rgbGreen=255; rc.rgbBlue=255; rc.rgbReserved=0; + }//if + float x,y; //destination location (float, with proper offset) + float origx, origy; //origin location + int destx, desty; //destination location + + y=ssy; //initialize y + if (!IsIndexed()){ //RGB24 + //optimized RGB24 implementation (direct write to destination): + BYTE *pxptr; +#if CXIMAGE_SUPPORT_ALPHA + BYTE *pxptra=0; +#endif //CXIMAGE_SUPPORT_ALPHA + for (desty=0; destyTransfer(imgDest); + else Transfer(imgDest); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +bool CxImage::Rotate180(CxImage* iDst) +{ + if (!pDib) return false; + + long wid = GetWidth(); + long ht = GetHeight(); + + CxImage imgDest; + imgDest.CopyInfo(*this); + imgDest.Create(wid,ht,GetBpp(),GetType()); + imgDest.SetPalette(GetPalette()); + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) imgDest.AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + + long x,y,y2; + for (y = 0; y < ht; y++){ + info.nProgress = (long)(100*y/ht); // + y2=ht-y-1; + for (x = 0; x < wid; x++){ + if(head.biClrUsed==0)//RGB + imgDest.SetPixelColor(wid-x-1, y2, GetPixelColor(x, y)); + else //PALETTE + imgDest.SetPixelIndex(wid-x-1, y2, GetPixelIndex(x, y)); + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) imgDest.AlphaSet(wid-x-1, y2,AlphaGet(x, y)); +#endif //CXIMAGE_SUPPORT_ALPHA + + } + } + + //select the destination + if (iDst) iDst->Transfer(imgDest); + else Transfer(imgDest); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/** + * Resizes the image. mode can be 0 for slow (bilinear) method , + * 1 for fast (nearest pixel) method, or 2 for accurate (bicubic spline interpolation) method. + * The function is faster with 24 and 1 bpp images, slow for 4 bpp images and slowest for 8 bpp images. + */ +bool CxImage::Resample(long newx, long newy, int mode, CxImage* iDst) +{ + if (newx==0 || newy==0) return false; + + if (head.biWidth==newx && head.biHeight==newy){ + if (iDst) iDst->Copy(*this); + return true; + } + + float xScale, yScale, fX, fY; + xScale = (float)head.biWidth / (float)newx; + yScale = (float)head.biHeight / (float)newy; + + CxImage newImage; + newImage.CopyInfo(*this); + newImage.Create(newx,newy,head.biBitCount,GetType()); + newImage.SetPalette(GetPalette()); + if (!newImage.IsValid()) return false; + + switch (mode) { + case 1: // nearest pixel + { + for(long y=0; y=head.biHeight) yy = head.biHeight-1; + for(int n=-1; n<3; n++) { + r2 = r1 * KernelBSpline(b - (float)n); + xx = i_x+n; + if (xx<0) xx=0; + if (xx>=head.biWidth) xx=head.biWidth-1; + + if (head.biClrUsed){ + rgb = GetPixelColor(xx,yy); + } else { + iDst = info.pImage + yy*info.dwEffWidth + xx*3; + rgb.rgbBlue = *iDst++; + rgb.rgbGreen= *iDst++; + rgb.rgbRed = *iDst; + } + + rr += rgb.rgbRed * r2; + gg += rgb.rgbGreen * r2; + bb += rgb.rgbBlue * r2; + } + } + + if (head.biClrUsed) + newImage.SetPixelColor(x,y,RGB(rr,gg,bb)); + else { + iDst = newImage.info.pImage + y*newImage.info.dwEffWidth + x*3; + *iDst++ = (BYTE)bb; + *iDst++ = (BYTE)gg; + *iDst = (BYTE)rr; + } + + } + } + break; + } + default: // bilinear interpolation + if (!(head.biWidth>newx && head.biHeight>newy && head.biBitCount==24)) { + //© 1999 Steve McMahon (steve@dogma.demon.co.uk) + long ifX, ifY, ifX1, ifY1, xmax, ymax; + float ir1, ir2, ig1, ig2, ib1, ib2, dx, dy; + BYTE r,g,b; + RGBQUAD rgb1, rgb2, rgb3, rgb4; + xmax = head.biWidth-1; + ymax = head.biHeight-1; + for(long y=0; y + const long ACCURACY = 1000; + long i,j; // index for faValue + long x,y; // coordinates in source image + BYTE* pSource; + BYTE* pDest = newImage.info.pImage; + long* naAccu = new long[3 * newx + 3]; + long* naCarry = new long[3 * newx + 3]; + long* naTemp; + long nWeightX,nWeightY; + float fEndX; + long nScale = (long)(ACCURACY * xScale * yScale); + + memset(naAccu, 0, sizeof(long) * 3 * newx); + memset(naCarry, 0, sizeof(long) * 3 * newx); + + int u, v = 0; // coordinates in dest image + float fEndY = yScale - 1.0f; + for (y = 0; y < head.biHeight; y++){ + info.nProgress = (long)(100*y/head.biHeight); // + if (info.nEscape) break; + pSource = info.pImage + y * info.dwEffWidth; + u = i = 0; + fEndX = xScale - 1.0f; + if ((float)y < fEndY) { // complete source row goes into dest row + for (x = 0; x < head.biWidth; x++){ + if ((float)x < fEndX){ // complete source pixel goes into dest pixel + for (j = 0; j < 3; j++) naAccu[i + j] += (*pSource++) * ACCURACY; + } else { // source pixel is splitted for 2 dest pixels + nWeightX = (long)(((float)x - fEndX) * ACCURACY); + for (j = 0; j < 3; j++){ + naAccu[i] += (ACCURACY - nWeightX) * (*pSource); + naAccu[3 + i++] += nWeightX * (*pSource++); + } + fEndX += xScale; + u++; + } + } + } else { // source row is splitted for 2 dest rows + nWeightY = (long)(((float)y - fEndY) * ACCURACY); + for (x = 0; x < head.biWidth; x++){ + if ((float)x < fEndX){ // complete source pixel goes into 2 pixel + for (j = 0; j < 3; j++){ + naAccu[i + j] += ((ACCURACY - nWeightY) * (*pSource)); + naCarry[i + j] += nWeightY * (*pSource++); + } + } else { // source pixel is splitted for 4 dest pixels + nWeightX = (int)(((float)x - fEndX) * ACCURACY); + for (j = 0; j < 3; j++) { + naAccu[i] += ((ACCURACY - nWeightY) * (ACCURACY - nWeightX)) * (*pSource) / ACCURACY; + *pDest++ = (BYTE)(naAccu[i] / nScale); + naCarry[i] += (nWeightY * (ACCURACY - nWeightX) * (*pSource)) / ACCURACY; + naAccu[i + 3] += ((ACCURACY - nWeightY) * nWeightX * (*pSource)) / ACCURACY; + naCarry[i + 3] = (nWeightY * nWeightX * (*pSource)) / ACCURACY; + i++; + pSource++; + } + fEndX += xScale; + u++; + } + } + if (u < newx){ // possibly not completed due to rounding errors + for (j = 0; j < 3; j++) *pDest++ = (BYTE)(naAccu[i++] / nScale); + } + naTemp = naCarry; + naCarry = naAccu; + naAccu = naTemp; + memset(naCarry, 0, sizeof(int) * 3); // need only to set first pixel zero + pDest = newImage.info.pImage + (++v * newImage.info.dwEffWidth); + fEndY += yScale; + } + } + if (v < newy){ // possibly not completed due to rounding errors + for (i = 0; i < 3 * newx; i++) *pDest++ = (BYTE)(naAccu[i] / nScale); + } + delete [] naAccu; + delete [] naCarry; + } + } + +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()){ + newImage.AlphaCreate(); + for(long y=0; yTransfer(newImage); + else Transfer(newImage); + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * New simpler resample. Adds new interpolation methods and simplifies code (using GetPixelColorInterpolated + * and GetAreaColorInterpolated). It also (unlike old method) interpolates alpha layer. + * + * \param newx, newy - size of resampled image + * \param inMethod - interpolation method to use (see comments at GetPixelColorInterpolated) + * If image size is being reduced, averaging is used instead (or simultaneously with) inMethod. + * \param ofMethod - what to replace outside pixels by (only significant for bordering pixels of enlarged image) + * \param iDst - pointer to destination CxImage or NULL. + * \param disableAveraging - force no averaging when shrinking images (Produces aliasing. + * You probably just want to leave this off...) + * + * \author ***bd*** 2.2004 + */ +bool CxImage::Resample2( + long newx, long newy, + InterpolationMethod const inMethod, + OverflowMethod const ofMethod, + CxImage* const iDst, + bool const disableAveraging) +{ + if (newx<=0 || newy<=0 || !pDib) return false; + + if (head.biWidth==newx && head.biHeight==newy) { + //image already correct size (just copy and return) + if (iDst) iDst->Copy(*this); + return true; + }//if + + //calculate scale of new image (less than 1 for enlarge) + float xScale, yScale; + xScale = (float)head.biWidth / (float)newx; + yScale = (float)head.biHeight / (float)newy; + + //create temporary destination image + CxImage newImage; + newImage.CopyInfo(*this); + newImage.Create(newx,newy,head.biBitCount,GetType()); + newImage.SetPalette(GetPalette()); + if (!newImage.IsValid()) return false; + + //and alpha channel if required +#if CXIMAGE_SUPPORT_ALPHA + if (AlphaIsValid()) newImage.AlphaCreate(); +#endif + + float sX, sY; //source location + long dX,dY; //destination pixel (int value) + if ((xScale<=1 && yScale<=1) || disableAveraging) { + //image is being enlarged (or interpolation on demand) + if (!IsIndexed()) { + //RGB24 image (optimized version with direct writes) + RGBQUAD q; //pixel colour + BYTE *pxptr; //pointer to destination pixel +#if CXIMAGE_SUPPORT_ALPHA + BYTE *pxptra; //and destination alpha data +#endif + for(dY=0; dYTransfer(newImage); + else + Transfer(newImage); + return true; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * Reduces the number of bits per pixel to nbit (1, 4 or 8). + * ppal points to a valid palette for the final image; if not supplied the function will use a standard palette. + * ppal is not necessary for reduction to 1 bpp. + */ +bool CxImage::DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal, DWORD clrimportant) +{ + if (!pDib) return false; + if (head.biBitCount < nbit) return false; + if (head.biBitCount == nbit){ + if (clrimportant==0) return true; + if (head.biClrImportant && (head.biClrImportant4) return false; + + CxImage tmp; + tmp.CopyInfo(*this); + tmp.Create(head.biWidth,head.biHeight,4,info.dwType); + tmp.SetPalette(GetPalette(),GetNumColors()); + if (!tmp.IsValid()) return false; + + +#if CXIMAGE_SUPPORT_SELECTION + tmp.SelectionCopy(*this); +#endif //CXIMAGE_SUPPORT_SELECTION + +#if CXIMAGE_SUPPORT_ALPHA + tmp.AlphaCopy(*this); +#endif //CXIMAGE_SUPPORT_ALPHA + + for (long y=0;y8) return false; + + CxImage tmp; + tmp.CopyInfo(*this); + tmp.Create(head.biWidth,head.biHeight,8,info.dwType); + tmp.SetPalette(GetPalette(),GetNumColors()); + if (!tmp.IsValid()) return false; + +#if CXIMAGE_SUPPORT_SELECTION + tmp.SelectionCopy(*this); +#endif //CXIMAGE_SUPPORT_SELECTION + +#if CXIMAGE_SUPPORT_ALPHA + tmp.AlphaCopy(*this); +#endif //CXIMAGE_SUPPORT_ALPHA + + for (long y=0;y24) return false; + + CxImage tmp; + tmp.CopyInfo(*this); + tmp.Create(head.biWidth,head.biHeight,24,info.dwType); + if (!tmp.IsValid()) return false; + + if (info.nBkgndIndex>=0) //translate transparency + tmp.info.nBkgndColor=GetPaletteColor((BYTE)info.nBkgndIndex); + +#if CXIMAGE_SUPPORT_SELECTION + tmp.SelectionCopy(*this); +#endif //CXIMAGE_SUPPORT_SELECTION + +#if CXIMAGE_SUPPORT_ALPHA + tmp.AlphaCopy(*this); + if (AlphaPaletteIsValid() && !AlphaIsValid()) tmp.AlphaCreate(); +#endif //CXIMAGE_SUPPORT_ALPHA + + for (long y=0;y