From 89e4c5a67444623a9c80b14c1cfa8f5e05fd59f7 Mon Sep 17 00:00:00 2001 From: beirich Date: Tue, 11 Jan 2011 02:55:51 +0000 Subject: [PATCH] --- BizHawk.Emulation/BizHawk.Emulation.csproj | 161 + BizHawk.Emulation/CPUs/68000/Diassembler.cs | 85 + .../CPUs/68000/Instructions/BitArithemetic.cs | 608 + .../CPUs/68000/Instructions/DataMovement.cs | 518 + .../CPUs/68000/Instructions/IntegerMath.cs | 812 ++ .../CPUs/68000/Instructions/ProgramFlow.cs | 387 + .../CPUs/68000/Instructions/Supervisor.cs | 86 + BizHawk.Emulation/CPUs/68000/M68000.cs | 145 + BizHawk.Emulation/CPUs/68000/Memory.cs | 626 + BizHawk.Emulation/CPUs/68000/OpcodeTable.cs | 323 + BizHawk.Emulation/CPUs/68000/Tables.cs | 61 + .../CPUs/HuC6280/Disassembler.cs | 253 + BizHawk.Emulation/CPUs/HuC6280/Execute.cs | 2136 +++ BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs | 353 + BizHawk.Emulation/CPUs/MC68000/Helpers.cs | 130 + .../CPUs/MC68000/IMemoryController.cs | 17 + BizHawk.Emulation/CPUs/MC68000/MC68K.cs | 238 + .../CPUs/MC68000/MemoryAccess.cs | 819 ++ BizHawk.Emulation/CPUs/MC68000/OpTable.cs | 153 + .../MC68000/Operations/BitManipulation.cs | 207 + .../CPUs/MC68000/Operations/DataMovement.cs | 396 + .../MC68000/Operations/IntegerArithmetic.cs | 869 ++ .../CPUs/MC68000/Operations/Logical.cs | 405 + .../CPUs/MC68000/Operations/Multiprocessor.cs | 29 + .../CPUs/MC68000/Operations/ProgramControl.cs | 208 + .../CPUs/MC68000/Operations/ShiftRotate.cs | 622 + .../CPUs/MC68000/Operations/SystemControl.cs | 271 + .../CPUs/MOS 6502/Disassembler.cs | 171 + BizHawk.Emulation/CPUs/MOS 6502/Execute.cs | 1120 ++ BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs | 184 + BizHawk.Emulation/CPUs/Z80-GB/Disassembler.cs | 173 + BizHawk.Emulation/CPUs/Z80-GB/Execute.cs | 2320 +++ BizHawk.Emulation/CPUs/Z80-GB/Interrupts.cs | 52 + BizHawk.Emulation/CPUs/Z80-GB/Registers.cs | 166 + BizHawk.Emulation/CPUs/Z80-GB/Tables.cs | 149 + BizHawk.Emulation/CPUs/Z80-GB/Z80.cs | 147 + BizHawk.Emulation/CPUs/Z80/Disassembler.cs | 297 + BizHawk.Emulation/CPUs/Z80/Execute.cs | 11636 ++++++++++++++++ BizHawk.Emulation/CPUs/Z80/Interrupts.cs | 55 + BizHawk.Emulation/CPUs/Z80/Registers.cs | 239 + BizHawk.Emulation/CPUs/Z80/Tables.cs | 321 + BizHawk.Emulation/CPUs/Z80/Z80A.cs | 199 + BizHawk.Emulation/CPUs/x86/Disassembler.cs | 199 + BizHawk.Emulation/CPUs/x86/Execute.cs | 84 + BizHawk.Emulation/CPUs/x86/Timing.cs | 19 + BizHawk.Emulation/CPUs/x86/x86.cs | 100 + BizHawk.Emulation/Consoles/Gameboy/Bios.cs | 25 + .../Consoles/Gameboy/Debugger.Designer.cs | 758 + .../Consoles/Gameboy/Debugger.cs | 382 + .../Consoles/Gameboy/Debugger.resx | 126 + BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs | 838 ++ BizHawk.Emulation/Consoles/Gameboy/Input.cs | 18 + BizHawk.Emulation/Consoles/Gameboy/Mappers.cs | 16 + .../Consoles/PC Engine/Compat.txt | 58 + BizHawk.Emulation/Consoles/PC Engine/Input.cs | 44 + .../Consoles/PC Engine/MemoryMap.SF2.cs | 90 + .../PC Engine/MemoryMap.SuperGrafx.cs | 71 + .../Consoles/PC Engine/MemoryMap.cs | 64 + .../Consoles/PC Engine/PCEngine.cs | 279 + BizHawk.Emulation/Consoles/PC Engine/VCE.cs | 116 + .../Consoles/PC Engine/VDC.Render.cs | 337 + BizHawk.Emulation/Consoles/PC Engine/VDC.cs | 331 + BizHawk.Emulation/Consoles/PC Engine/VPC.cs | 466 + .../Consoles/Sega/Genesis/GenVDP.DMA.cs | 73 + .../Consoles/Sega/Genesis/GenVDP.Render.cs | 113 + .../Consoles/Sega/Genesis/GenVDP.cs | 264 + .../Consoles/Sega/Genesis/Genesis.Input.cs | 18 + .../Consoles/Sega/Genesis/Genesis.cs | 191 + BizHawk.Emulation/Consoles/Sega/Genesis/IO.cs | 35 + .../Consoles/Sega/Genesis/MemoryMap.68000.cs | 208 + .../Consoles/Sega/Genesis/MemoryMap.Z80.cs | 60 + BizHawk.Emulation/Consoles/Sega/SMS/BIOS.cs | 1916 +++ .../Consoles/Sega/SMS/Compat.txt | 20 + BizHawk.Emulation/Consoles/Sega/SMS/Input.cs | 77 + .../Sega/SMS/MemoryMap.CodeMasters.cs | 40 + .../Consoles/Sega/SMS/MemoryMap.Sega.cs | 81 + BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs | 398 + BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs | 515 + BizHawk.Emulation/Database/CRC32.cs | 37 + BizHawk.Emulation/Database/Database.cs | 85 + .../Interfaces/Base Implementations/Game.cs | 69 + .../Interfaces/Base Implementations/IPS.cs | 64 + .../Interfaces/Base Implementations/Movies.cs | 125 + .../Base Implementations/NullController.cs | 15 + .../Base Implementations/NullEmulator.cs | 37 + .../Base Implementations/SmdGame.cs | 83 + BizHawk.Emulation/Interfaces/IController.cs | 23 + BizHawk.Emulation/Interfaces/IEmulator.cs | 32 + BizHawk.Emulation/Interfaces/IGame.cs | 9 + .../Interfaces/ISoundProvider.cs | 7 + .../Interfaces/IVideoProvider.cs | 11 + BizHawk.Emulation/Log.cs | 75 + BizHawk.Emulation/Notes.txt | 64 + BizHawk.Emulation/Properties/AssemblyInfo.cs | 36 + BizHawk.Emulation/Sound/HuC6280PSG.cs | 341 + BizHawk.Emulation/Sound/SN76489.cs | 440 + .../Sound/Utilities/BufferedAsync.cs | 47 + BizHawk.Emulation/Sound/Utilities/Metaspu.cs | 486 + .../Sound/Utilities/SoundMixer.cs | 34 + BizHawk.Emulation/Sound/Utilities/Waves.cs | 77 + BizHawk.Emulation/Sound/YM2413.cs | 1815 +++ BizHawk.Emulation/Sound/YM2612.cs | 25 + BizHawk.Emulation/Util.cs | 239 + .../BizHawk.MultiClient.csproj | 133 + BizHawk.MultiClient/Config.cs | 53 + BizHawk.MultiClient/ConfigService.cs | 77 + BizHawk.MultiClient/Global.cs | 21 + BizHawk.MultiClient/HawkFile.cs | 94 + .../Input/ControllerBinding.cs | 95 + BizHawk.MultiClient/Input/GamePad.cs | 160 + BizHawk.MultiClient/Input/Input.cs | 69 + BizHawk.MultiClient/Input/Keyboard.cs | 81 + BizHawk.MultiClient/MainForm.Designer.cs | 383 + BizHawk.MultiClient/MainForm.cs | 389 + BizHawk.MultiClient/MainForm.resources | Bin 0 -> 180 bytes BizHawk.MultiClient/MainForm.resx | 123 + BizHawk.MultiClient/MruStack.cs | 53 + BizHawk.MultiClient/NameStateForm.Designer.cs | 98 + BizHawk.MultiClient/NameStateForm.cs | 38 + BizHawk.MultiClient/NameStateForm.resources | Bin 0 -> 180 bytes BizHawk.MultiClient/NameStateForm.resx | 120 + BizHawk.MultiClient/Program.cs | 39 + .../Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 71 + .../Properties/Resources.resources | Bin 0 -> 180 bytes BizHawk.MultiClient/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 30 + .../Properties/Settings.settings | 7 + BizHawk.MultiClient/RenderPanel.cs | 287 + BizHawk.MultiClient/Rewind.cs | 171 + BizHawk.MultiClient/RomGame.cs | 144 + BizHawk.MultiClient/ScreenSaver.cs | 47 + BizHawk.MultiClient/Sound.cs | 110 + BizHawk.MultiClient/output/7z.dll | Bin 0 -> 878592 bytes BizHawk.MultiClient/output/config.ini | 38 + BizHawk.Util/7z.dll | Bin 0 -> 878592 bytes .../7z/ArchiveEmulationStreamProxy.cs | 101 + BizHawk.Util/7z/ArchiveExtractCallback.cs | 602 + BizHawk.Util/7z/ArchiveOpenCallback.cs | 192 + BizHawk.Util/7z/ArchiveUpdateCallback.cs | 806 ++ BizHawk.Util/7z/COM.cs | 1244 ++ BizHawk.Util/7z/Common.cs | 833 ++ BizHawk.Util/7z/EventArgs.cs | 383 + BizHawk.Util/7z/Exceptions.cs | 464 + BizHawk.Util/7z/FileSignatureChecker.cs | 240 + BizHawk.Util/7z/Formats.cs | 529 + BizHawk.Util/7z/LibraryFeature.cs | 112 + BizHawk.Util/7z/LibraryManager.cs | 563 + BizHawk.Util/7z/LzmaDecodeStream.cs | 240 + BizHawk.Util/7z/LzmaEncodeStream.cs | 304 + BizHawk.Util/7z/LzmaProgressCallback.cs | 72 + BizHawk.Util/7z/NativeMethods.cs | 77 + BizHawk.Util/7z/SevenZipCompressor.cs | 2048 +++ .../7z/SevenZipCompressorAsynchronous.cs | 689 + BizHawk.Util/7z/SevenZipExtractor.cs | 1374 ++ .../7z/SevenZipExtractorAsynchronous.cs | 294 + BizHawk.Util/7z/SevenZipSfx.cs | 499 + BizHawk.Util/7z/StreamWrappers.cs | 545 + BizHawk.Util/7z/arch/Test.bzip2.7z | Bin 0 -> 149 bytes BizHawk.Util/7z/arch/Test.lzma.7z | Bin 0 -> 121 bytes BizHawk.Util/7z/arch/Test.lzma2.7z | Bin 0 -> 114 bytes BizHawk.Util/7z/arch/Test.ppmd.7z | Bin 0 -> 121 bytes BizHawk.Util/7z/arch/Test.rar | Bin 0 -> 76 bytes BizHawk.Util/7z/arch/Test.tar | Bin 0 -> 2048 bytes BizHawk.Util/7z/arch/Test.txt | 1 + BizHawk.Util/7z/arch/Test.txt.bz2 | Bin 0 -> 43 bytes BizHawk.Util/7z/arch/Test.txt.gz | Bin 0 -> 33 bytes BizHawk.Util/7z/arch/Test.txt.xz | Bin 0 -> 56 bytes BizHawk.Util/7z/arch/Test.zip | Bin 0 -> 118 bytes BizHawk.Util/7z/sdk/Common/CRC.cs | 75 + BizHawk.Util/7z/sdk/Common/InBuffer.cs | 119 + BizHawk.Util/7z/sdk/Common/OutBuffer.cs | 85 + .../7z/sdk/Compress/LZ/IMatchFinder.cs | 40 + BizHawk.Util/7z/sdk/Compress/LZ/LzBinTree.cs | 405 + BizHawk.Util/7z/sdk/Compress/LZ/LzInWindow.cs | 197 + .../7z/sdk/Compress/LZ/LzOutWindow.cs | 125 + BizHawk.Util/7z/sdk/Compress/LZMA/LzmaBase.cs | 108 + .../7z/sdk/Compress/LZMA/LzmaDecoder.cs | 480 + .../7z/sdk/Compress/LZMA/LzmaEncoder.cs | 1587 +++ .../7z/sdk/Compress/RangeCoder/RangeCoder.cs | 249 + .../sdk/Compress/RangeCoder/RangeCoderBit.cs | 146 + .../Compress/RangeCoder/RangeCoderBitTree.cs | 173 + BizHawk.Util/7z/sdk/ICoder.cs | 191 + BizHawk.Util/BizHawk.Util.csproj | 128 + BizHawk.Util/Dictionaries.cs | 81 + BizHawk.Util/InputConfigBase.cs | 26 + BizHawk.Util/KeyTurbo.cs | 41 + BizHawk.Util/Properties/AssemblyInfo.cs | 36 + BizHawk.Util/SmartTextBoxControl.cs | 34 + BizHawk.Util/TextDebugView.cs | 59 + BizHawk.Util/ViewportPanel.cs | 115 + BizHawk.sln | 39 + CpuCoreGenerator.sln | 20 + CpuCoreGenerator/CpuCoreGenerator.csproj | 52 + CpuCoreGenerator/HuC6280/CoreGenerator.cs | 823 ++ CpuCoreGenerator/HuC6280/Instructions.cs | 698 + CpuCoreGenerator/MOS 6502/CoreGenerator.cs | 565 + CpuCoreGenerator/MOS 6502/Instructions.cs | 401 + CpuCoreGenerator/Program.cs | 15 + CpuCoreGenerator/Properties/AssemblyInfo.cs | 36 + SlimDX.dll | Bin 0 -> 3335680 bytes 201 files changed, 63298 insertions(+) create mode 100644 BizHawk.Emulation/BizHawk.Emulation.csproj create mode 100644 BizHawk.Emulation/CPUs/68000/Diassembler.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs create mode 100644 BizHawk.Emulation/CPUs/68000/M68000.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Memory.cs create mode 100644 BizHawk.Emulation/CPUs/68000/OpcodeTable.cs create mode 100644 BizHawk.Emulation/CPUs/68000/Tables.cs create mode 100644 BizHawk.Emulation/CPUs/HuC6280/Disassembler.cs create mode 100644 BizHawk.Emulation/CPUs/HuC6280/Execute.cs create mode 100644 BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Helpers.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/IMemoryController.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/MC68K.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/MemoryAccess.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/OpTable.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/BitManipulation.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/DataMovement.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/IntegerArithmetic.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/Logical.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/Multiprocessor.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/ProgramControl.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/ShiftRotate.cs create mode 100644 BizHawk.Emulation/CPUs/MC68000/Operations/SystemControl.cs create mode 100644 BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs create mode 100644 BizHawk.Emulation/CPUs/MOS 6502/Execute.cs create mode 100644 BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs create mode 100644 BizHawk.Emulation/CPUs/Z80-GB/Disassembler.cs create mode 100644 BizHawk.Emulation/CPUs/Z80-GB/Execute.cs create mode 100644 BizHawk.Emulation/CPUs/Z80-GB/Interrupts.cs create mode 100644 BizHawk.Emulation/CPUs/Z80-GB/Registers.cs create mode 100644 BizHawk.Emulation/CPUs/Z80-GB/Tables.cs create mode 100644 BizHawk.Emulation/CPUs/Z80-GB/Z80.cs create mode 100644 BizHawk.Emulation/CPUs/Z80/Disassembler.cs create mode 100644 BizHawk.Emulation/CPUs/Z80/Execute.cs create mode 100644 BizHawk.Emulation/CPUs/Z80/Interrupts.cs create mode 100644 BizHawk.Emulation/CPUs/Z80/Registers.cs create mode 100644 BizHawk.Emulation/CPUs/Z80/Tables.cs create mode 100644 BizHawk.Emulation/CPUs/Z80/Z80A.cs create mode 100644 BizHawk.Emulation/CPUs/x86/Disassembler.cs create mode 100644 BizHawk.Emulation/CPUs/x86/Execute.cs create mode 100644 BizHawk.Emulation/CPUs/x86/Timing.cs create mode 100644 BizHawk.Emulation/CPUs/x86/x86.cs create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Bios.cs create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Debugger.Designer.cs create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Debugger.cs create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Debugger.resx create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Input.cs create mode 100644 BizHawk.Emulation/Consoles/Gameboy/Mappers.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/Compat.txt create mode 100644 BizHawk.Emulation/Consoles/PC Engine/Input.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SF2.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SuperGrafx.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/VCE.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/VDC.cs create mode 100644 BizHawk.Emulation/Consoles/PC Engine/VPC.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.DMA.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.Input.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/IO.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.68000.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.Z80.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/BIOS.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/Compat.txt create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/Input.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.CodeMasters.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.Sega.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs create mode 100644 BizHawk.Emulation/Consoles/Sega/SMS/VDP.cs create mode 100644 BizHawk.Emulation/Database/CRC32.cs create mode 100644 BizHawk.Emulation/Database/Database.cs create mode 100644 BizHawk.Emulation/Interfaces/Base Implementations/Game.cs create mode 100644 BizHawk.Emulation/Interfaces/Base Implementations/IPS.cs create mode 100644 BizHawk.Emulation/Interfaces/Base Implementations/Movies.cs create mode 100644 BizHawk.Emulation/Interfaces/Base Implementations/NullController.cs create mode 100644 BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs create mode 100644 BizHawk.Emulation/Interfaces/Base Implementations/SmdGame.cs create mode 100644 BizHawk.Emulation/Interfaces/IController.cs create mode 100644 BizHawk.Emulation/Interfaces/IEmulator.cs create mode 100644 BizHawk.Emulation/Interfaces/IGame.cs create mode 100644 BizHawk.Emulation/Interfaces/ISoundProvider.cs create mode 100644 BizHawk.Emulation/Interfaces/IVideoProvider.cs create mode 100644 BizHawk.Emulation/Log.cs create mode 100644 BizHawk.Emulation/Notes.txt create mode 100644 BizHawk.Emulation/Properties/AssemblyInfo.cs create mode 100644 BizHawk.Emulation/Sound/HuC6280PSG.cs create mode 100644 BizHawk.Emulation/Sound/SN76489.cs create mode 100644 BizHawk.Emulation/Sound/Utilities/BufferedAsync.cs create mode 100644 BizHawk.Emulation/Sound/Utilities/Metaspu.cs create mode 100644 BizHawk.Emulation/Sound/Utilities/SoundMixer.cs create mode 100644 BizHawk.Emulation/Sound/Utilities/Waves.cs create mode 100644 BizHawk.Emulation/Sound/YM2413.cs create mode 100644 BizHawk.Emulation/Sound/YM2612.cs create mode 100644 BizHawk.Emulation/Util.cs create mode 100644 BizHawk.MultiClient/BizHawk.MultiClient.csproj create mode 100644 BizHawk.MultiClient/Config.cs create mode 100644 BizHawk.MultiClient/ConfigService.cs create mode 100644 BizHawk.MultiClient/Global.cs create mode 100644 BizHawk.MultiClient/HawkFile.cs create mode 100644 BizHawk.MultiClient/Input/ControllerBinding.cs create mode 100644 BizHawk.MultiClient/Input/GamePad.cs create mode 100644 BizHawk.MultiClient/Input/Input.cs create mode 100644 BizHawk.MultiClient/Input/Keyboard.cs create mode 100644 BizHawk.MultiClient/MainForm.Designer.cs create mode 100644 BizHawk.MultiClient/MainForm.cs create mode 100644 BizHawk.MultiClient/MainForm.resources create mode 100644 BizHawk.MultiClient/MainForm.resx create mode 100644 BizHawk.MultiClient/MruStack.cs create mode 100644 BizHawk.MultiClient/NameStateForm.Designer.cs create mode 100644 BizHawk.MultiClient/NameStateForm.cs create mode 100644 BizHawk.MultiClient/NameStateForm.resources create mode 100644 BizHawk.MultiClient/NameStateForm.resx create mode 100644 BizHawk.MultiClient/Program.cs create mode 100644 BizHawk.MultiClient/Properties/AssemblyInfo.cs create mode 100644 BizHawk.MultiClient/Properties/Resources.Designer.cs create mode 100644 BizHawk.MultiClient/Properties/Resources.resources create mode 100644 BizHawk.MultiClient/Properties/Resources.resx create mode 100644 BizHawk.MultiClient/Properties/Settings.Designer.cs create mode 100644 BizHawk.MultiClient/Properties/Settings.settings create mode 100644 BizHawk.MultiClient/RenderPanel.cs create mode 100644 BizHawk.MultiClient/Rewind.cs create mode 100644 BizHawk.MultiClient/RomGame.cs create mode 100644 BizHawk.MultiClient/ScreenSaver.cs create mode 100644 BizHawk.MultiClient/Sound.cs create mode 100644 BizHawk.MultiClient/output/7z.dll create mode 100644 BizHawk.MultiClient/output/config.ini create mode 100644 BizHawk.Util/7z.dll create mode 100644 BizHawk.Util/7z/ArchiveEmulationStreamProxy.cs create mode 100644 BizHawk.Util/7z/ArchiveExtractCallback.cs create mode 100644 BizHawk.Util/7z/ArchiveOpenCallback.cs create mode 100644 BizHawk.Util/7z/ArchiveUpdateCallback.cs create mode 100644 BizHawk.Util/7z/COM.cs create mode 100644 BizHawk.Util/7z/Common.cs create mode 100644 BizHawk.Util/7z/EventArgs.cs create mode 100644 BizHawk.Util/7z/Exceptions.cs create mode 100644 BizHawk.Util/7z/FileSignatureChecker.cs create mode 100644 BizHawk.Util/7z/Formats.cs create mode 100644 BizHawk.Util/7z/LibraryFeature.cs create mode 100644 BizHawk.Util/7z/LibraryManager.cs create mode 100644 BizHawk.Util/7z/LzmaDecodeStream.cs create mode 100644 BizHawk.Util/7z/LzmaEncodeStream.cs create mode 100644 BizHawk.Util/7z/LzmaProgressCallback.cs create mode 100644 BizHawk.Util/7z/NativeMethods.cs create mode 100644 BizHawk.Util/7z/SevenZipCompressor.cs create mode 100644 BizHawk.Util/7z/SevenZipCompressorAsynchronous.cs create mode 100644 BizHawk.Util/7z/SevenZipExtractor.cs create mode 100644 BizHawk.Util/7z/SevenZipExtractorAsynchronous.cs create mode 100644 BizHawk.Util/7z/SevenZipSfx.cs create mode 100644 BizHawk.Util/7z/StreamWrappers.cs create mode 100644 BizHawk.Util/7z/arch/Test.bzip2.7z create mode 100644 BizHawk.Util/7z/arch/Test.lzma.7z create mode 100644 BizHawk.Util/7z/arch/Test.lzma2.7z create mode 100644 BizHawk.Util/7z/arch/Test.ppmd.7z create mode 100644 BizHawk.Util/7z/arch/Test.rar create mode 100644 BizHawk.Util/7z/arch/Test.tar create mode 100644 BizHawk.Util/7z/arch/Test.txt create mode 100644 BizHawk.Util/7z/arch/Test.txt.bz2 create mode 100644 BizHawk.Util/7z/arch/Test.txt.gz create mode 100644 BizHawk.Util/7z/arch/Test.txt.xz create mode 100644 BizHawk.Util/7z/arch/Test.zip create mode 100644 BizHawk.Util/7z/sdk/Common/CRC.cs create mode 100644 BizHawk.Util/7z/sdk/Common/InBuffer.cs create mode 100644 BizHawk.Util/7z/sdk/Common/OutBuffer.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZ/IMatchFinder.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZ/LzBinTree.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZ/LzInWindow.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZ/LzOutWindow.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZMA/LzmaBase.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZMA/LzmaDecoder.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/LZMA/LzmaEncoder.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoder.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBit.cs create mode 100644 BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBitTree.cs create mode 100644 BizHawk.Util/7z/sdk/ICoder.cs create mode 100644 BizHawk.Util/BizHawk.Util.csproj create mode 100644 BizHawk.Util/Dictionaries.cs create mode 100644 BizHawk.Util/InputConfigBase.cs create mode 100644 BizHawk.Util/KeyTurbo.cs create mode 100644 BizHawk.Util/Properties/AssemblyInfo.cs create mode 100644 BizHawk.Util/SmartTextBoxControl.cs create mode 100644 BizHawk.Util/TextDebugView.cs create mode 100644 BizHawk.Util/ViewportPanel.cs create mode 100644 BizHawk.sln create mode 100644 CpuCoreGenerator.sln create mode 100644 CpuCoreGenerator/CpuCoreGenerator.csproj create mode 100644 CpuCoreGenerator/HuC6280/CoreGenerator.cs create mode 100644 CpuCoreGenerator/HuC6280/Instructions.cs create mode 100644 CpuCoreGenerator/MOS 6502/CoreGenerator.cs create mode 100644 CpuCoreGenerator/MOS 6502/Instructions.cs create mode 100644 CpuCoreGenerator/Program.cs create mode 100644 CpuCoreGenerator/Properties/AssemblyInfo.cs create mode 100644 SlimDX.dll diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj new file mode 100644 index 0000000000..03bb1f7368 --- /dev/null +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -0,0 +1,161 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {197D4314-8A9F-49BA-977D-54ACEFAEB6BA} + Library + Properties + BizHawk.Emulation + BizHawk.Emulation + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + x86 + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/68000/Diassembler.cs b/BizHawk.Emulation/CPUs/68000/Diassembler.cs new file mode 100644 index 0000000000..f3f8f9a2ff --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Diassembler.cs @@ -0,0 +1,85 @@ +using System.Text; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public class DisassemblyInfo + { + public int PC; + public string Mnemonic; + public string Args; + public string RawBytes; + public int Length; + + public override string ToString() + { + return string.Format("{0:X6} {3,-20} {1,-8} {2}", PC, Mnemonic, Args, RawBytes); + } + } + + public partial class M68000 + { + public DisassemblyInfo Disassemble(int pc) + { + var info = new DisassemblyInfo { Mnemonic = "UNKNOWN", PC = pc, Length = 2 }; + op = (ushort)ReadWord(pc); + + if (Opcodes[op] == MOVE) MOVE_Disasm(info); + else if (Opcodes[op] == MOVEA) MOVEA_Disasm(info); + else if (Opcodes[op] == MOVEQ) MOVEQ_Disasm(info); + else if (Opcodes[op] == MOVEM0) MOVEM0_Disasm(info); + else if (Opcodes[op] == MOVEM1) MOVEM1_Disasm(info); + else if (Opcodes[op] == LEA) LEA_Disasm(info); + else if (Opcodes[op] == CLR) CLR_Disasm(info); + else if (Opcodes[op] == EXT) EXT_Disasm(info); + + else if (Opcodes[op] == ANDI) ANDI_Disasm(info); + else if (Opcodes[op] == ORI) ORI_Disasm(info); + else if (Opcodes[op] == LSLd) LSLd_Disasm(info); + else if (Opcodes[op] == LSRd) LSRd_Disasm(info); + else if (Opcodes[op] == ASLd) ASLd_Disasm(info); + else if (Opcodes[op] == ASRd) ASRd_Disasm(info); + else if (Opcodes[op] == ROLd) ROLd_Disasm(info); + else if (Opcodes[op] == RORd) RORd_Disasm(info); + else if (Opcodes[op] == SWAP) SWAP_Disasm(info); + + else if (Opcodes[op] == JMP) JMP_Disasm(info); + else if (Opcodes[op] == JSR) JSR_Disasm(info); + else if (Opcodes[op] == Bcc) Bcc_Disasm(info); + else if (Opcodes[op] == BRA) BRA_Disasm(info); + else if (Opcodes[op] == BSR) BSR_Disasm(info); + else if (Opcodes[op] == DBcc) DBcc_Disasm(info); + else if (Opcodes[op] == RTS) RTS_Disasm(info); + else if (Opcodes[op] == TST) TST_Disasm(info); + else if (Opcodes[op] == BTSTi) BTSTi_Disasm(info); + else if (Opcodes[op] == BTSTr) BTSTr_Disasm(info); + else if (Opcodes[op] == LINK) LINK_Disasm(info); + else if (Opcodes[op] == NOP) NOP_Disasm(info); + + else if (Opcodes[op] == ADD0) ADD_Disasm(info); + else if (Opcodes[op] == ADD1) ADD_Disasm(info); + else if (Opcodes[op] == ADDA) ADDA_Disasm(info); + else if (Opcodes[op] == ADDI) ADDI_Disasm(info); + else if (Opcodes[op] == ADDQ) ADDQ_Disasm(info); + else if (Opcodes[op] == SUB0) SUB_Disasm(info); + else if (Opcodes[op] == SUB1) SUB_Disasm(info); + else if (Opcodes[op] == SUBA) SUBA_Disasm(info); + else if (Opcodes[op] == SUBI) SUBI_Disasm(info); + else if (Opcodes[op] == SUBQ) SUBQ_Disasm(info); + else if (Opcodes[op] == CMP) CMP_Disasm(info); + else if (Opcodes[op] == CMPA) CMPA_Disasm(info); + else if (Opcodes[op] == CMPI) CMPI_Disasm(info); + + else if (Opcodes[op] == MOVEtSR) MOVEtSR_Disasm(info); + else if (Opcodes[op] == MOVEfSR) MOVEfSR_Disasm(info); + else if (Opcodes[op] == MOVEUSP) MOVEUSP_Disasm(info); + else if (Opcodes[op] == ORI_SR) ORI_SR_Disasm(info); + + var sb = new StringBuilder(); + for (int p = info.PC; p < info.PC + info.Length; p++) + sb.AppendFormat("{0:X2}", ReadByte(p)); + info.RawBytes = sb.ToString(); + + return info; + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs b/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs new file mode 100644 index 0000000000..acc0ef1f28 --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Instructions/BitArithemetic.cs @@ -0,0 +1,608 @@ +using System; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private void ANDI() // AND immediate + { + int size = ((op >> 6) & 0x03); + int dstMode = ((op >> 3) & 0x07); + int dstReg = (op & 0x07); + + V = false; + C = false; + + switch (size) + { + case 0: // Byte + { + sbyte imm = (sbyte) ReadWord(PC); PC += 2; + sbyte arg = PeekValueB(dstMode, dstReg); + sbyte result = (sbyte) (imm & arg); + WriteValueB(dstMode, dstReg, result); + PendingCycles -= (dstMode == 0) ? 8 : 12 + EACyclesBW[dstMode, dstReg]; + N = (result < 0); + Z = (result == 0); + return; + } + case 1: // Word + { + short imm = ReadWord(PC); PC += 2; + short arg = PeekValueW(dstMode, dstReg); + short result = (short) (imm & arg); + WriteValueW(dstMode, dstReg, result); + PendingCycles -= (dstMode == 0) ? 8 : 12 + EACyclesBW[dstMode, dstReg]; + N = (result < 0); + Z = (result == 0); + return; + } + case 2: // Long + { + int imm = ReadLong(PC); PC += 2; + int arg = PeekValueL(dstMode, dstReg); + int result = imm & arg; + WriteValueL(dstMode, dstReg, result); + PendingCycles -= (dstMode == 0) ? 8 : 12 + EACyclesL[dstMode, dstReg]; + N = (result < 0); + Z = (result == 0); + return; + } + } + } + + private void ANDI_Disasm(DisassemblyInfo info) + { + int size = ((op >> 6) & 0x03); + int dstMode = ((op >> 3) & 0x07); + int dstReg = (op & 0x07); + + int pc = info.PC + 2; + + switch (size) + { + case 0: // Byte + { + info.Mnemonic = "andi.b"; + sbyte imm = (sbyte)ReadWord(pc); pc += 2; + info.Args = string.Format("${0:X}, ", imm); + info.Args += DisassembleValue(dstMode, dstReg, 1, ref pc); + break; + } + case 1: // Word + { + info.Mnemonic = "andi.w"; + short imm = ReadWord(pc); pc += 2; + info.Args = string.Format("${0:X}, ", imm); + info.Args += DisassembleValue(dstMode, dstReg, 2, ref pc); + break; + } + case 2: // Long + { + info.Mnemonic = "andi.l"; + int imm = ReadLong(pc); pc += 4; + info.Args = string.Format("${0:X}, ", imm); + info.Args += DisassembleValue(dstMode, dstReg, 4, ref pc); + break; + } + } + + info.Length = pc - info.PC; + } + + private void ORI() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + V = C = false; + + switch (size) + { + case 0: // byte + { + sbyte immed = (sbyte) ReadWord(PC); PC += 2; + sbyte value = (sbyte) (PeekValueB(mode, reg) | immed); + WriteValueB(mode, reg, value); + N = value < 0; + Z = value == 0; + PendingCycles -= mode == 0 ? 8 : 12 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + short immed = ReadWord(PC); PC += 2; + short value = (short)(PeekValueW(mode, reg) | immed); + WriteValueW(mode, reg, value); + N = value < 0; + Z = value == 0; + PendingCycles -= mode == 0 ? 8 : 12 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + int immed = ReadLong(PC); PC += 4; + int value = PeekValueL(mode, reg) | immed; + WriteValueL(mode, reg, value); + N = value < 0; + Z = value == 0; + PendingCycles -= mode == 0 ? 17 : 20 + EACyclesL[mode, reg]; + return; + } + } + } + + private void ORI_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + info.Mnemonic = "ori.b"; + sbyte immed = (sbyte) ReadWord(pc); pc += 2; + info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 1, ref pc)); + break; + } + case 1: // word + { + info.Mnemonic = "ori.w"; + short immed = ReadWord(pc); pc += 2; + info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 2, ref pc)); + break; + } + case 2: // long + { + info.Mnemonic = "ori.l"; + int immed = ReadLong(pc); pc += 4; + info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 4, ref pc)); + break; + } + } + + info.Length = pc - info.PC; + } + + private void LSLd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + for (int i=0; i> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "lsl.b"; break; + case 1: info.Mnemonic = "lsl.w"; break; + case 2: info.Mnemonic = "lsl.l"; break; + } + if (m==0) info.Args = rot+", D"+reg; + else info.Args = "D"+rot+", D"+reg; + + info.Length = pc - info.PC; + } + + private void LSRd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u8 & 1) != 0; + D[reg].u8 >>= 1; + } + N = D[reg].s8 < 0; + Z = D[reg].u8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u16 & 1) != 0; + D[reg].u16 >>= 1; + } + N = D[reg].s16 < 0; + Z = D[reg].u16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u32 & 1) != 0; + D[reg].u32 >>= 1; + } + N = D[reg].s32 < 0; + Z = D[reg].u32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + private void LSRd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "lsr.b"; break; + case 1: info.Mnemonic = "lsr.w"; break; + case 2: info.Mnemonic = "lsr.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + + private void ASLd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u8 & 0x80) != 0; + D[reg].s8 <<= 1; + } + N = D[reg].s8 < 0; + Z = D[reg].u8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u16 & 0x8000) != 0; + D[reg].s16 <<= 1; + } + N = D[reg].s16 < 0; + Z = D[reg].u16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u32 & 0x80000000) != 0; + D[reg].s32 <<= 1; + } + N = D[reg].s32 < 0; + Z = D[reg].u32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + private void ASLd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "asl.b"; break; + case 1: info.Mnemonic = "asl.w"; break; + case 2: info.Mnemonic = "asl.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + + private void ASRd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u8 & 1) != 0; + D[reg].s8 >>= 1; + } + N = D[reg].s8 < 0; + Z = D[reg].u8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u16 & 1) != 0; + D[reg].s16 >>= 1; + } + N = D[reg].s16 < 0; + Z = D[reg].u16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = X = (D[reg].u32 & 1) != 0; + D[reg].s32 >>= 1; + } + N = D[reg].s32 < 0; + Z = D[reg].u32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + private void ASRd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "asr.b"; break; + case 1: info.Mnemonic = "asr.w"; break; + case 2: info.Mnemonic = "asr.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + + private void ROLd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = (D[reg].u8 & 0x80) != 0; + D[reg].u8 = (byte) ((D[reg].u8 << 1) | (D[reg].u8 >> 7)); + } + N = D[reg].s8 < 0; + Z = D[reg].u8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = (D[reg].u16 & 0x8000) != 0; + D[reg].u16 = (ushort) ((D[reg].u16 << 1) | (D[reg].u16 >> 15)); + } + N = D[reg].s16 < 0; + Z = D[reg].u16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = (D[reg].u32 & 0x80000000) != 0; + D[reg].u32 = ((D[reg].u32 << 1) | (D[reg].u32 >> 31)); + } + N = D[reg].s32 < 0; + Z = D[reg].u32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + private void ROLd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "rol.b"; break; + case 1: info.Mnemonic = "rol.w"; break; + case 2: info.Mnemonic = "rol.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + + private void RORd() + { + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + else if (m == 1) rot = D[rot].s32 & 63; + + V = false; + C = false; + + switch (size) + { + case 0: // byte + for (int i = 0; i < rot; i++) + { + C = (D[reg].u8 & 1) != 0; + D[reg].u8 = (byte)((D[reg].u8 >> 1) | (D[reg].u8 << 7)); + } + N = D[reg].s8 < 0; + Z = D[reg].u8 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 1: // word + for (int i = 0; i < rot; i++) + { + C = (D[reg].u16 & 1) != 0; + D[reg].u16 = (ushort)((D[reg].u16 >> 1) | (D[reg].u16 << 15)); + } + N = D[reg].s16 < 0; + Z = D[reg].u16 == 0; + PendingCycles -= 6 + (rot * 2); + return; + case 2: // long + for (int i = 0; i < rot; i++) + { + C = (D[reg].u32 & 1) != 0; + D[reg].u32 = ((D[reg].u32 >> 1) | (D[reg].u32 << 31)); + } + N = D[reg].s32 < 0; + Z = D[reg].u32 == 0; + PendingCycles -= 8 + (rot * 2); + return; + } + } + + private void RORd_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int rot = (op >> 9) & 7; + int size = (op >> 6) & 3; + int m = (op >> 5) & 1; + int reg = op & 7; + + if (m == 0 && rot == 0) rot = 8; + + switch (size) + { + case 0: info.Mnemonic = "ror.b"; break; + case 1: info.Mnemonic = "ror.w"; break; + case 2: info.Mnemonic = "ror.l"; break; + } + if (m == 0) info.Args = rot + ", D" + reg; + else info.Args = "D" + rot + ", D" + reg; + + info.Length = pc - info.PC; + } + + private void SWAP() + { + int reg = op & 7; + D[reg].u32 = (D[reg].u32 << 16) | (D[reg].u32 >> 16); + V = C = false; + Z = D[reg].u32 == 0; + N = D[reg].s32 < 0; + PendingCycles -= 4; + } + + private void SWAP_Disasm(DisassemblyInfo info) + { + int reg = op & 7; + info.Mnemonic = "swap"; + info.Args = "D" + reg; + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs b/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs new file mode 100644 index 0000000000..14add03f99 --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Instructions/DataMovement.cs @@ -0,0 +1,518 @@ +using System; +using System.Text; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private void MOVE() + { + int size = ((op >> 12) & 0x03); + int dstMode = ((op >> 6) & 0x07); + int dstReg = ((op >> 9) & 0x07); + int srcMode = ((op >> 3) & 0x07); + int srcReg = (op & 0x07); + + int value = 0; + switch(size) + { + case 1: // Byte + value = ReadValueB(srcMode, srcReg); + WriteValueB(dstMode, dstReg, (sbyte) value); + PendingCycles -= MoveCyclesBW[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)]; + N = (value < 0); + break; + case 3: // Word + value = ReadValueW(srcMode, srcReg); + WriteValueW(dstMode, dstReg, (short)value); + PendingCycles -= MoveCyclesBW[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)]; + N = (value < 0); + break; + case 2: // Long + value = ReadValueL(srcMode, srcReg); + WriteValueL(dstMode, dstReg, value); + PendingCycles -= MoveCyclesL[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)]; + N = (value < 0); + break; + } + + V = false; + C = false; + Z = (value == 0); + } + + private void MOVE_Disasm(DisassemblyInfo info) + { + int size = ((op >> 12) & 0x03); + int dstMode = ((op >> 6) & 0x07); + int dstReg = ((op >> 9) & 0x07); + int srcMode = ((op >> 3) & 0x07); + int srcReg = (op & 0x07); + + int pc = info.PC + 2; + + switch (size) + { + case 1: + info.Mnemonic = "move.b"; + info.Args = DisassembleValue(srcMode, srcReg, 1, ref pc) +", "; + info.Args += DisassembleValue(dstMode, dstReg, 1, ref pc); + break; + case 3: + info.Mnemonic = "move.w"; + info.Args = DisassembleValue(srcMode, srcReg, 2, ref pc) + ", "; + info.Args += DisassembleValue(dstMode, dstReg, 2, ref pc); + break; + case 2: + info.Mnemonic = "move.l"; + info.Args = DisassembleValue(srcMode, srcReg, 4, ref pc) + ", "; + info.Args += DisassembleValue(dstMode, dstReg, 4, ref pc); + break; + } + + info.Length = pc - info.PC; + } + + private void MOVEA() + { + int size = ((op >> 12) & 0x03); + int dstReg = ((op >> 9) & 0x07); + int srcMode = ((op >> 3) & 0x07); + int srcReg = (op & 0x07); + + if (size == 3) // Word + { + A[dstReg].s32 = ReadValueW(srcMode, srcReg); + PendingCycles -= EACyclesBW[srcMode, srcReg]; // TODO this is wrong, check pg 957 + } else { // Long + A[dstReg].s32 = ReadValueL(srcMode, srcReg); + PendingCycles -= EACyclesL[srcMode, srcReg]; // TODO this is wrong, check pg 957 + } + } + + private void MOVEA_Disasm(DisassemblyInfo info) + { + int size = ((op >> 12) & 0x03); + int dstReg = ((op >> 9) & 0x07); + int srcMode = ((op >> 3) & 0x07); + int srcReg = (op & 0x07); + int pc = info.PC + 2; + + if (size == 3) + { + info.Mnemonic = "movea.w"; + info.Args = DisassembleValue(srcMode, srcReg, 2, ref pc) + ", A" + dstReg; + } else { + info.Mnemonic = "movea.l"; + info.Args = DisassembleValue(srcMode, srcReg, 4, ref pc) + ", A" + dstReg; + } + info.Length = pc - info.PC; + } + + private void MOVEQ() + { + int value = (sbyte) op; // 8-bit data payload is sign-extended to 32-bits. + N = (value < 0); + Z = (value == 0); + V = false; + C = false; + D[(op >> 9) & 7].s32 = value; + PendingCycles -= 4; + } + + private void MOVEQ_Disasm(DisassemblyInfo info) + { + info.Mnemonic = "moveq"; + info.Args = String.Format("{0}, D{1}", (sbyte) op, (op >> 9) & 7); + } + + private void MOVEM0() + { + // Move register to memory + int size = (op >> 6) & 1; + int dstMode = (op >> 3) & 7; + int dstReg = (op >> 0) & 7; + + ushort registers = (ushort) ReadWord(PC); PC += 2; + int address = ReadAddress(dstMode, dstReg); + int regCount = 0; + + if (size == 0) + { + // word-assign + if (dstMode == 4) // decrement address + { + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + address -= 2; + WriteWord(address, A[i].s16); + regCount++; + } + registers >>= 1; + } + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + address -= 2; + WriteWord(address, D[i].s16); + regCount++; + } + registers >>= 1; + } + A[dstReg].s32 = address; + } + else + { // increment address + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + WriteWord(address, A[i].s16); + address += 2; + regCount++; + } + registers >>= 1; + } + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + WriteWord(address, D[i].s16); + address += 2; + regCount++; + } + registers >>= 1; + } + } + PendingCycles -= regCount*4; + } else { + // long-assign + if (dstMode == 4) // decrement address + { + for (int i=7; i>= 0; i--) + { + if ((registers & 1) == 1) + { + address -= 4; + WriteLong(address, A[i].s32); + regCount++; + } + registers >>= 1; + } + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + address -= 4; + WriteLong(address, D[i].s32); + regCount++; + } + registers >>= 1; + } + A[dstReg].s32 = address; + } else { // increment address + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + WriteLong(address, A[i].s32); + address += 4; + regCount++; + } + registers >>= 1; + } + for (int i = 7; i >= 0; i--) + { + if ((registers & 1) == 1) + { + WriteLong(address, D[i].s32); + address += 4; + regCount++; + } + registers >>= 1; + } + } + PendingCycles -= regCount * 8; + } + + switch (dstMode) + { + case 2: PendingCycles -= 8; break; + case 4: PendingCycles -= 8; break; + case 5: PendingCycles -= 12; break; + case 6: PendingCycles -= 14; break; + case 7: + switch (dstReg) + { + case 0: PendingCycles -= 12; break; + case 1: PendingCycles -= 16; break; + } + break; + } + } + + private void MOVEM1() + { + // Move memory to register + int size = (op >> 6) & 1; + int srcMode = (op >> 3) & 7; + int srcReg = (op >> 0) & 7; + + ushort registers = (ushort)ReadWord(PC); PC += 2; + int address = ReadAddress(srcMode, srcReg); + int regCount = 0; + + if (size == 0) + { + // word-assign + for (int i = 0; i < 8; i++) + { + if ((registers & 1) == 1) + { + D[i].s32 = ReadWord(address); + address += 2; + regCount++; + } + registers >>= 1; + } + for (int i = 0; i < 8; i++) + { + if ((registers & 1) == 1) + { + A[i].s32 = ReadWord(address); + address += 2; + regCount++; + } + registers >>= 1; + } + PendingCycles -= regCount * 4; + if (srcMode == 3) + A[srcReg].s32 = address; + } else { + // long-assign + for (int i = 0; i < 8; i++) + { + if ((registers & 1) == 1) + { + D[i].s32 = ReadLong(address); + address += 4; + regCount++; + } + registers >>= 1; + } + for (int i = 0; i < 8; i++) + { + if ((registers & 1) == 1) + { + A[i].s32 = ReadLong(address); + address += 4; + regCount++; + } + registers >>= 1; + } + PendingCycles -= regCount * 8; + if (srcMode == 3) + A[srcReg].s32 = address; + } + + switch (srcMode) + { + case 2: PendingCycles -= 12; break; + case 4: PendingCycles -= 12; break; + case 5: PendingCycles -= 16; break; + case 6: PendingCycles -= 18; break; + case 7: + switch (srcReg) + { + case 0: PendingCycles -= 16; break; + case 1: PendingCycles -= 20; break; + case 2: PendingCycles -= 16; break; + case 3: PendingCycles -= 18; break; + } + break; + } + } + + private static string DisassembleRegisterList0(ushort registers) + { + var str = new StringBuilder(); + int count = 0; + for (int i = 0; i<8; i++) + { + if ((registers & 0x8000) != 0) + { + if (count > 0) str.Append(","); + str.Append("D"+i); + count++; + } + registers <<= 1; + } + for (int i = 0; i < 8; i++) + { + if ((registers & 0x8000) != 0) + { + if (count > 0) str.Append("/"); + str.Append("A"+i); + count++; + } + registers <<= 1; + } + return str.ToString(); + } + + private static string DisassembleRegisterList1(ushort registers) + { + var str = new StringBuilder(); + int count = 0; + for (int i = 0; i < 8; i++) + { + if ((registers & 1) != 0) + { + if (count > 0) str.Append(","); + str.Append("D" + i); + count++; + } + registers >>= 1; + } + for (int i = 0; i < 8; i++) + { + if ((registers & 1) != 0) + { + if (count > 0) str.Append("/"); + str.Append("A" + i); + count++; + } + registers >>= 1; + } + return str.ToString(); + } + + private void MOVEM0_Disasm(DisassemblyInfo info) + { + int size = (op >> 6) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + int pc = info.PC + 2; + + string address = DisassembleAddress(mode, reg, ref pc); + ushort registers = (ushort) ReadWord(pc); pc += 2; + + info.Mnemonic = size == 0 ? "movem.w" : "movem.l"; + info.Args = DisassembleRegisterList0(registers) + ", " + address; + info.Length = pc - info.PC; + } + + private void MOVEM1_Disasm(DisassemblyInfo info) + { + int size = (op >> 6) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + int pc = info.PC + 2; + + string address = DisassembleAddress(mode, reg, ref pc); + ushort registers = (ushort)ReadWord(pc); pc += 2; + + info.Mnemonic = size == 0 ? "movem.w" : "movem.l"; + info.Args = address + ", " + DisassembleRegisterList1(registers); + info.Length = pc - info.PC; + } + + private void LEA() + { + int mode = (op >> 3) & 7; + int sReg = (op >> 0) & 7; + int dReg = (op >> 9) & 7; + + A[dReg].u32 = (uint)ReadAddress(mode, sReg); + switch (mode) + { + case 2: PendingCycles -= 4; break; + case 5: PendingCycles -= 8; break; + case 6: PendingCycles -= 12; break; + case 7: + switch (sReg) + { + case 0: PendingCycles -= 8; break; + case 1: PendingCycles -= 12; break; + case 2: PendingCycles -= 8; break; + case 3: PendingCycles -= 12; break; + } + break; + } + } + + private void LEA_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int mode = (op >> 3) & 7; + int sReg = (op >> 0) & 7; + int dReg = (op >> 9) & 7; + + info.Mnemonic = "lea"; + info.Args = DisassembleAddress(mode, sReg, ref pc); + info.Args += ", A"+dReg; + + info.Length = pc - info.PC; + } + + private void CLR() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: WriteValueB(mode, reg, 0); PendingCycles -= mode == 0 ? 4 : 8 + EACyclesBW[mode, reg]; break; + case 1: WriteValueW(mode, reg, 0); PendingCycles -= mode == 0 ? 4 : 8 + EACyclesBW[mode, reg]; break; + case 2: WriteValueL(mode, reg, 0); PendingCycles -= mode == 0 ? 6 : 12 + EACyclesL[mode, reg]; break; + } + + N = V = C = false; + Z = true; + } + + private void CLR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: info.Mnemonic = "clr.b"; info.Args = DisassembleValue(mode, reg, 1, ref pc); break; + case 1: info.Mnemonic = "clr.w"; info.Args = DisassembleValue(mode, reg, 2, ref pc); break; + case 2: info.Mnemonic = "clr.l"; info.Args = DisassembleValue(mode, reg, 4, ref pc); break; + } + info.Length = pc - info.PC; + } + + private void EXT() + { + int size = (op >> 6) & 1; + int reg = op & 7; + switch (size) + { + case 0: D[reg].s16 = D[reg].s8; break; + case 1: D[reg].s32 = D[reg].s16; break; + } + PendingCycles -= 4; + } + + private void EXT_Disasm(DisassemblyInfo info) + { + int size = (op >> 6) & 1; + int reg = op & 7; + switch (size) + { + case 0: info.Mnemonic = "ext.w"; info.Args = "D" + reg; break; + case 1: info.Mnemonic = "ext.l"; info.Args = "D" + reg; break; + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs b/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs new file mode 100644 index 0000000000..7c2d29630a --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Instructions/IntegerMath.cs @@ -0,0 +1,812 @@ +using System; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private void ADD0() + { + int Dreg = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int result = D[Dreg].s8 + ReadValueB(mode, reg); + X = C = (result & 0x100) != 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + N = result < 0; + Z = result == 0; + D[Dreg].s8 = (sbyte)result; + PendingCycles -= 4 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result = D[Dreg].s16 + ReadValueW(mode, reg); + X = C = (result & 0x10000) != 0; + V = result > short.MaxValue || result < short.MinValue; + N = result < 0; + Z = result == 0; + D[Dreg].s16 = (short)result; + PendingCycles -= 4 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + long result = D[Dreg].s32 + ReadValueL(mode, reg); + X = C = (result & 0x100000000) != 0; + V = result > int.MaxValue || result < int.MinValue; + N = result < 0; + Z = result == 0; + D[Dreg].s32 = (int)result; + PendingCycles -= 6 + EACyclesL[mode, reg]; + return; + } + } + } + + private void ADD1() + { + int Dreg = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int result = PeekValueB(mode, reg) + D[Dreg].s8; + X = C = (result & 0x100) != 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + N = result < 0; + Z = result == 0; + WriteValueB(mode, reg, (sbyte)result); + PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result = PeekValueW(mode, reg) + D[Dreg].s16; + X = C = (result & 0x10000) != 0; + V = result > short.MaxValue || result < short.MinValue; + N = result < 0; + Z = result == 0; + WriteValueW(mode, reg, (short)result); + PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + long result = PeekValueL(mode, reg) + D[Dreg].s32; + X = C = (result & 0x100000000) != 0; + V = result > int.MaxValue || result < int.MinValue; + N = result < 0; + Z = result == 0; + WriteValueL(mode, reg, (int)result); + PendingCycles -= 12 + EACyclesL[mode, reg]; + return; + } + } + } + + private void ADD_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int Dreg = (op >> 9) & 7; + int dir = (op >> 8) & 1; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + string op1 = "D" + Dreg; + string op2; + + switch (size) + { + case 0: info.Mnemonic = "add.b"; op2 = DisassembleValue(mode, reg, 1, ref pc); break; + case 1: info.Mnemonic = "add.w"; op2 = DisassembleValue(mode, reg, 2, ref pc); break; + default: info.Mnemonic = "add.l"; op2 = DisassembleValue(mode, reg, 4, ref pc); break; + } + info.Args = dir == 0 ? (op2 + ", " + op1) : (op1 + ", " + op2); + info.Length = pc - info.PC; + } + + private void ADDI() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int immed = (sbyte) ReadWord(PC); PC += 2; + int result = PeekValueB(mode, reg) + immed; + X = C = (result & 0x100) != 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + N = result < 0; + Z = result == 0; + WriteValueB(mode, reg, (sbyte)result); + if (mode == 0) PendingCycles -= 8; + else PendingCycles -= 12 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int immed = ReadWord(PC); PC += 2; + int result = PeekValueW(mode, reg) + immed; + X = C = (result & 0x10000) != 0; + V = result > short.MaxValue || result < short.MinValue; + N = result < 0; + Z = result == 0; + WriteValueW(mode, reg, (short)result); + if (mode == 0) PendingCycles -= 8; + else PendingCycles -= 12 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + int immed = ReadLong(PC); PC += 2; + long result = PeekValueL(mode, reg) + immed; + X = C = (result & 0x100000000) != 0; + V = result > int.MaxValue || result < int.MinValue; + N = result < 0; + Z = result == 0; + WriteValueL(mode, reg, (int)result); + if (mode == 0) PendingCycles -= 16; + else PendingCycles -= 20 + EACyclesBW[mode, reg]; + return; + } + } + } + + private void ADDI_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 3; + + switch (size) + { + case 0: + info.Mnemonic = "addi.b"; + info.Args = DisassembleImmediate(1, ref pc) + ", " + DisassembleValue(mode, reg, 1, ref pc); + break; + case 1: + info.Mnemonic = "addi.w"; + info.Args = DisassembleImmediate(2, ref pc) + ", " + DisassembleValue(mode, reg, 2, ref pc); + break; + case 2: + info.Mnemonic = "addi.l"; + info.Args = DisassembleImmediate(4, ref pc) + ", " + DisassembleValue(mode, reg, 4, ref pc); + break; + } + info.Length = pc - info.PC; + } + + private void ADDQ() + { + int data = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + data = data == 0 ? 8 : data; // range is 1-8; 0 represents 8 + + switch (size) + { + case 0: // byte + { + if (mode == 1) throw new Exception("ADDQ.B on address reg is invalid"); + int result = PeekValueB(mode, reg) + data; + N = result < 0; + Z = result == 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + C = X = (result & 0x100) != 0; + WriteValueB(mode, reg, (sbyte) result); + if (mode == 0) PendingCycles -= 4; + else PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result; + if (mode == 1) + { + result = PeekValueL(mode, reg) + data; + WriteValueL(mode, reg, (short) result); + } else { + result = PeekValueW(mode, reg) + data; + N = result < 0; + Z = result == 0; + V = result > short.MaxValue || result < short.MinValue; + C = X = (result & 0x10000) != 0; + WriteValueW(mode, reg, (short)result); + } + if (mode <= 1) PendingCycles -= 4; + else PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + default: // long + { + long result = PeekValueL(mode, reg) + data; + if (mode != 1) + { + N = result < 0; + Z = result == 0; + V = result > int.MaxValue || result < int.MinValue; + C = X = (result & 0x100000000) != 0; + } + WriteValueL(mode, reg, (int)result); + if (mode <= 1) PendingCycles -= 8; + else PendingCycles -= 12 + EACyclesL[mode, reg]; + return; + } + } + } + + private void ADDQ_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int data = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + data = data == 0 ? 8 : data; // range is 1-8; 0 represents 8 + + switch (size) + { + case 0: info.Mnemonic = "addq.b"; info.Args = data+", "+DisassembleValue(mode, reg, 1, ref pc); break; + case 1: info.Mnemonic = "addq.w"; info.Args = data+", "+DisassembleValue(mode, reg, 2, ref pc); break; + case 2: info.Mnemonic = "addq.l"; info.Args = data+", "+DisassembleValue(mode, reg, 4, ref pc); break; + } + info.Length = pc - info.PC; + } + + private void ADDA() + { + int aReg = (op >> 9) & 7; + int size = (op >> 8) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + if (size == 0) // word + { + int value = ReadValueW(mode, reg); + A[aReg].s32 += value; + PendingCycles -= 8 + EACyclesBW[mode, reg]; + } else { // long + int value = ReadValueL(mode, reg); + A[aReg].s32 -= value; + PendingCycles += 6 + EACyclesL[mode, reg]; + } + } + + private void ADDA_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int aReg = (op >> 9) & 7; + int size = (op >> 8) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + info.Mnemonic = (size == 0) ? "adda.w" : "adda.l"; + info.Args = DisassembleValue(mode, reg, (size == 0) ? 2 : 4, ref pc) + ", A" + aReg; + + info.Length = pc - info.PC; + } + + private void SUB0() + { + int Dreg = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int result = D[Dreg].s8 - ReadValueB(mode, reg); + X = C = (result & 0x100) != 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + N = result < 0; + Z = result == 0; + D[Dreg].s8 = (sbyte) result; + PendingCycles -= 4 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result = D[Dreg].s16 - ReadValueW(mode, reg); + X = C = (result & 0x10000) != 0; + V = result > short.MaxValue || result < short.MinValue; + N = result < 0; + Z = result == 0; + D[Dreg].s16 = (short) result; + PendingCycles -= 4 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + long result = D[Dreg].s32 - ReadValueL(mode, reg); + X = C = (result & 0x100000000) != 0; + V = result > int.MaxValue || result < int.MinValue; + N = result < 0; + Z = result == 0; + D[Dreg].s32 = (int)result; + PendingCycles -= 6 + EACyclesL[mode, reg]; + return; + } + } + } + + private void SUB1() + { + int Dreg = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int result = PeekValueB(mode, reg) - D[Dreg].s8; + X = C = (result & 0x100) != 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + N = result < 0; + Z = result == 0; + WriteValueB(mode, reg, (sbyte) result); + PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result = PeekValueW(mode, reg) - D[Dreg].s16; + X = C = (result & 0x10000) != 0; + V = result > short.MaxValue || result < short.MinValue; + N = result < 0; + Z = result == 0; + WriteValueW(mode, reg, (short) result); + PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + long result = PeekValueL(mode, reg) - D[Dreg].s32; + X = C = (result & 0x100000000) != 0; + V = result > int.MaxValue || result < int.MinValue; + N = result < 0; + Z = result == 0; + WriteValueL(mode, reg, (int) result); + PendingCycles -= 12 + EACyclesL[mode, reg]; + return; + } + } + } + + private void SUB_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int Dreg = (op >> 9) & 7; + int dir = (op >> 8) & 1; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + string op1 = "D" + Dreg; + string op2; + + switch (size) + { + case 0: info.Mnemonic = "sub.b"; op2 = DisassembleValue(mode, reg, 1, ref pc); break; + case 1: info.Mnemonic = "sub.w"; op2 = DisassembleValue(mode, reg, 2, ref pc); break; + default: info.Mnemonic = "sub.l"; op2 = DisassembleValue(mode, reg, 4, ref pc); break; + } + info.Args = dir == 0 ? (op2 + ", " + op1) : (op1 + ", " + op2); + info.Length = pc - info.PC; + } + + private void SUBI() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int immed = (sbyte) ReadWord(PC); PC += 2; + int result = PeekValueB(mode, reg) - immed; + X = C = (result & 0x100) != 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + N = result < 0; + Z = result == 0; + WriteValueB(mode, reg, (sbyte)result); + if (mode == 0) PendingCycles -= 8; + else PendingCycles -= 12 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int immed = ReadWord(PC); PC += 2; + int result = PeekValueW(mode, reg) - immed; + X = C = (result & 0x10000) != 0; + V = result > short.MaxValue || result < short.MinValue; + N = result < 0; + Z = result == 0; + WriteValueW(mode, reg, (short)result); + if (mode == 0) PendingCycles -= 8; + else PendingCycles -= 12 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + int immed = ReadLong(PC); PC += 2; + long result = PeekValueL(mode, reg) - immed; + X = C = (result & 0x100000000) != 0; + V = result > int.MaxValue || result < int.MinValue; + N = result < 0; + Z = result == 0; + WriteValueL(mode, reg, (int)result); + if (mode == 0) PendingCycles -= 16; + else PendingCycles -= 20 + EACyclesBW[mode, reg]; + return; + } + } + } + + private void SUBI_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 3; + + switch (size) + { + case 0: + info.Mnemonic = "subi.b"; + info.Args = DisassembleImmediate(1, ref pc) + ", " + DisassembleValue(mode, reg, 1, ref pc); + break; + case 1: + info.Mnemonic = "subi.w"; + info.Args = DisassembleImmediate(2, ref pc) + ", " + DisassembleValue(mode, reg, 2, ref pc); + break; + case 2: + info.Mnemonic = "subi.l"; + info.Args = DisassembleImmediate(4, ref pc) + ", " + DisassembleValue(mode, reg, 4, ref pc); + break; + } + info.Length = pc - info.PC; + } + + private void SUBQ() + { + int data = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + data = data == 0 ? 8 : data; // range is 1-8; 0 represents 8 + + switch (size) + { + case 0: // byte + { + if (mode == 1) throw new Exception("SUBQ.B on address reg is invalid"); + int result = PeekValueB(mode, reg) - data; + N = result < 0; + Z = result == 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + C = X = (result & 0x100) != 0; + WriteValueB(mode, reg, (sbyte) result); + if (mode == 0) PendingCycles -= 4; + else PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result = PeekValueW(mode, reg) - data; + if (mode != 1) + { + N = result < 0; + Z = result == 0; + V = result > short.MaxValue || result < short.MinValue; + C = X = (result & 0x10000) != 0; + } + WriteValueW(mode, reg, (short)result); + if (mode <= 1) PendingCycles -= 4; + else PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + default: // long + { + long result = PeekValueL(mode, reg) - data; + if (mode != 1) + { + N = result < 0; + Z = result == 0; + V = result > int.MaxValue || result < int.MinValue; + C = X = (result & 0x100000000) != 0; + } + WriteValueL(mode, reg, (int)result); + if (mode <= 1) PendingCycles -= 8; + else PendingCycles -= 12 + EACyclesL[mode, reg]; + return; + } + } + } + + private void SUBQ_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int data = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + data = data == 0 ? 8 : data; // range is 1-8; 0 represents 8 + + switch (size) + { + case 0: info.Mnemonic = "subq.b"; info.Args = data+", "+DisassembleValue(mode, reg, 1, ref pc); break; + case 1: info.Mnemonic = "subq.w"; info.Args = data+", "+DisassembleValue(mode, reg, 2, ref pc); break; + case 2: info.Mnemonic = "subq.l"; info.Args = data+", "+DisassembleValue(mode, reg, 4, ref pc); break; + } + info.Length = pc - info.PC; + } + + private void SUBA() + { + int aReg = (op >> 9) & 7; + int size = (op >> 8) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + if (size == 0) // word + { + int value = ReadValueW(mode, reg); + A[aReg].s32 -= value; + PendingCycles -= 8 + EACyclesBW[mode, reg]; + } else { // long + int value = ReadValueL(mode, reg); + A[aReg].s32 -= value; + PendingCycles -= 6 + EACyclesL[mode, reg]; + } + } + + private void SUBA_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int aReg = (op >> 9) & 7; + int size = (op >> 8) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + info.Mnemonic = (size == 0) ? "suba.w" : "suba.l"; + info.Args = DisassembleValue(mode, reg, (size == 0) ? 2 : 4, ref pc) + ", A"+aReg; + + info.Length = pc - info.PC; + } + + private void CMP() + { + int dReg = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int result = ReadValueB(mode, reg) - D[dReg].s8; + N = result < 0; + Z = result == 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + C = (result & 0x100) != 0; + if (mode == 0) PendingCycles -= 8; + PendingCycles -= 4 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int result = ReadValueW(mode, reg) - D[dReg].s16; + N = result < 0; + Z = result == 0; + V = result > short.MaxValue || result < short.MinValue; + C = (result & 0x10000) != 0; + if (mode == 0) PendingCycles -= 8; + PendingCycles -= 4 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + long result = ReadValueL(mode, reg) - D[dReg].s32; + N = result < 0; + Z = result == 0; + V = result > int.MaxValue || result < int.MinValue; + C = (result & 0x100000000) != 0; + PendingCycles -= 6 + EACyclesL[mode, reg]; + return; + } + } + } + + private void CMP_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int dReg = (op >> 9) & 7; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: + info.Mnemonic = "cmp.b"; + info.Args = DisassembleValue(mode, reg, 1, ref pc) + ", D" + dReg; + break; + case 1: + info.Mnemonic = "cmp.w"; + info.Args = DisassembleValue(mode, reg, 2, ref pc) + ", D" + dReg; + break; + case 2: + info.Mnemonic = "cmp.l"; + info.Args = DisassembleValue(mode, reg, 4, ref pc) + ", D" + dReg; + break; + } + info.Length = pc - info.PC; + } + + private void CMPA() + { + int aReg = (op >> 9) & 7; + int size = (op >> 8) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // word + { + long result = A[aReg].s32 - ReadValueW(mode, reg); + N = result < 0; + Z = result == 0; + V = result > int.MaxValue || result < int.MinValue; + C = (result & 0x100000000) != 0; + PendingCycles -= 6 + EACyclesBW[mode, reg]; + return; + } + case 1: // long + { + long result = A[aReg].s32 - ReadValueL(mode, reg); + N = result < 0; + Z = result == 0; + V = result > int.MaxValue || result < int.MinValue; + C = (result & 0x100000000) != 0; + PendingCycles -= 6 + EACyclesL[mode, reg]; + return; + } + } + } + + private void CMPA_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + + int aReg = (op >> 9) & 7; + int size = (op >> 8) & 1; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: + info.Mnemonic = "cmpa.w"; + info.Args = DisassembleValue(mode, reg, 2, ref pc) + ", A" + aReg; + break; + case 1: + info.Mnemonic = "cmpa.l"; + info.Args = DisassembleValue(mode, reg, 4, ref pc) + ", A" + aReg; + break; + } + info.Length = pc - info.PC; + } + + + private void CMPI() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: // byte + { + int immed = (sbyte) ReadWord(PC); PC += 2; + int result = ReadValueB(mode, reg) - immed; + N = result < 0; + Z = result == 0; + V = result > sbyte.MaxValue || result < sbyte.MinValue; + C = (result & 0x100) != 0; + if (mode == 0) PendingCycles -= 8; + else PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 1: // word + { + int immed = ReadWord(PC); PC += 2; + int result = ReadValueW(mode, reg) - immed; + N = result < 0; + Z = result == 0; + V = result > short.MaxValue || result < short.MinValue; + C = (result & 0x10000) != 0; + if (mode == 0) PendingCycles -= 8; + else PendingCycles -= 8 + EACyclesBW[mode, reg]; + return; + } + case 2: // long + { + int immed = ReadLong(PC); PC += 4; + long result = ReadValueL(mode, reg) - immed; + N = result < 0; + Z = result == 0; + V = result > int.MaxValue || result < int.MinValue; + C = (result & 0x100000000) != 0; + if (mode == 0) PendingCycles -= 14; + else PendingCycles -= 12 + EACyclesL[mode, reg]; + return; + } + } + } + + private void CMPI_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + int immediate; + + switch (size) + { + case 0: + immediate = (byte)ReadWord(pc); pc += 2; + info.Mnemonic = "cmpi.b"; + info.Args = String.Format("${0:X}, {1}", immediate, DisassembleValue(mode, reg, 1, ref pc)); + break; + case 1: + immediate = ReadWord(pc); pc += 2; + info.Mnemonic = "cmpi.w"; + info.Args = String.Format("${0:X}, {1}", immediate, DisassembleValue(mode, reg, 2, ref pc)); + break; + case 2: + immediate = ReadLong(pc); pc += 4; + info.Mnemonic = "cmpi.l"; + info.Args = String.Format("${0:X}, {1}", immediate, DisassembleValue(mode, reg, 4, ref pc)); + break; + } + info.Length = pc - info.PC; + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs b/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs new file mode 100644 index 0000000000..67932bed56 --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Instructions/ProgramFlow.cs @@ -0,0 +1,387 @@ + +using System; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private bool TestCondition(int condition) + { + switch (condition) + { + case 0x00: return true; // True + case 0x01: return false; // False + case 0x02: return !C && !Z; // High (Unsigned) + case 0x03: return C || Z; // Less or Same (Unsigned) + case 0x04: return !C; // Carry Clear (High or Same) + case 0x05: return C; // Carry Set (Lower) + case 0x06: return !Z; // Not Equal + case 0x07: return Z; // Equal + case 0x08: return !V; // Overflow Clear + case 0x09: return V; // Overflow Set + case 0x0A: return !N; // Plus (Positive) + case 0x0B: return N; // Minus (Negative) + case 0x0C: return N && V || !N && !V; // Greater or Equal + case 0x0D: return N && !V || !N && V; // Less Than + case 0x0E: return N && V && !Z || !N && !V && !Z; // Greater Than + case 0x0F: return Z || N && !V || !N && V; // Less or Equal + default: + throw new Exception("Invalid condition "+condition); + } + } + + private string DisassembleCondition(int condition) + { + switch (condition) + { + case 0x00: return "t"; // True + case 0x01: return "f"; // False + case 0x02: return "hi"; // High (Unsigned) + case 0x03: return "ls"; // Less or Same (Unsigned) + case 0x04: return "cc"; // Carry Clear (High or Same) + case 0x05: return "cs"; // Carry Set (Lower) + case 0x06: return "ne"; // Not Equal + case 0x07: return "eq"; // Equal + case 0x08: return "vc"; // Overflow Clear + case 0x09: return "vs"; // Overflow Set + case 0x0A: return "pl"; // Plus (Positive) + case 0x0B: return "mi"; // Minus (Negative) + case 0x0C: return "ge"; // Greater or Equal + case 0x0D: return "lt"; // Less Than + case 0x0E: return "gt"; // Greater Than + case 0x0F: return "le"; // Less or Equal + default: return "??"; // Invalid condition + } + } + + private void Bcc() // Branch on condition + { + sbyte displacement8 = (sbyte) op; + int cond = (op >> 8) & 0x0F; + + if (TestCondition(cond) == true) + { + if (displacement8 != 0) + { + // use opcode-embedded displacement + PC += displacement8; + PendingCycles -= 10; + } else { + // use extension word displacement + PC += ReadWord(PC); + PendingCycles -= 10; + } + } else { // false + if (displacement8 != 0) + PendingCycles -= 8; + else { + PC += 2; + PendingCycles -= 12; + } + } + } + + private void Bcc_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + sbyte displacement8 = (sbyte)op; + int cond = (op >> 8) & 0x0F; + + info.Mnemonic = "b" + DisassembleCondition(cond); + if (displacement8 != 0) + { + info.Args = string.Format("${0:X}", pc + displacement8); + } else { + info.Args = string.Format("${0:X}", pc + ReadWord(pc)); + pc += 2; + } + info.Length = pc - info.PC; + } + + private void BRA() + { + sbyte displacement8 = (sbyte)op; + + if (displacement8 != 0) + PC += displacement8; + else + PC += ReadWord(PC); + PendingCycles -= 10; + } + + private void BRA_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + info.Mnemonic = "bra"; + + sbyte displacement8 = (sbyte)op; + if (displacement8 != 0) + info.Args = String.Format("${0:X}", pc + displacement8); + else + { + info.Args = String.Format("${0:X}", pc + ReadWord(pc)); + pc += 2; + } + info.Length = pc - info.PC; + } + + private void BSR() + { + sbyte displacement8 = (sbyte)op; + + A[7].s32 -= 4; + if (displacement8 != 0) + { + // use embedded displacement + WriteLong(A[7].s32, PC); + PC += displacement8; + } else { + // use extension word displacement + WriteLong(A[7].s32, PC + 2); + PC += ReadWord(PC); + } + PendingCycles -= 18; + } + + private void BSR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + info.Mnemonic = "bsr"; + + sbyte displacement8 = (sbyte)op; + if (displacement8 != 0) + info.Args = String.Format("${0:X}", pc + displacement8); + else { + info.Args = String.Format("${0:X}", pc + ReadWord(pc)); + pc += 2; + } + info.Length = pc - info.PC; + } + + private void DBcc() + { + if (TestCondition((op >> 8) & 0x0F) == true) + { + // break out of loop + PC += 2; + PendingCycles -= 12; + } else { + int reg = op & 7; + D[reg].u16--; + + if (D[reg].u16 == 0xFFFF) + { + PC += 2; + PendingCycles -= 14; + } else { + PC += ReadWord(PC); + TotalExecutedCycles -= 10; + } + } + } + + private void DBcc_Disasm(DisassemblyInfo info) + { + int cond = (op >> 8) & 0x0F; + if (cond == 1) + info.Mnemonic = "dbra"; + else + info.Mnemonic = "db" + DisassembleCondition(cond); + + int pc = info.PC + 2; + info.Args = String.Format("D{0}, ${1:X}", op & 7, pc + ReadWord(pc)); + info.Length = 4; + } + + private void RTS() + { + PC = ReadLong(A[7].s32); + A[7].s32 += 4; + PendingCycles -= 16; + } + + private void RTS_Disasm(DisassemblyInfo info) + { + info.Mnemonic = "rts"; + info.Args = ""; + } + + private void TST() + { + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + int value; + switch (size) + { + case 0: value = ReadValueB(mode, reg); PendingCycles -= 4 + EACyclesBW[mode, reg]; break; + case 1: value = ReadValueW(mode, reg); PendingCycles -= 4 + EACyclesBW[mode, reg]; break; + default: value = ReadValueL(mode, reg); PendingCycles -= 4 + EACyclesL[mode, reg]; break; + } + V = false; + C = false; + N = (value < 0); + Z = (value == 0); + } + + private void TST_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int size = (op >> 6) & 3; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + + switch (size) + { + case 0: info.Mnemonic = "tst.b"; info.Args = DisassembleValue(mode, reg, 1, ref pc); break; + case 1: info.Mnemonic = "tst.w"; info.Args = DisassembleValue(mode, reg, 2, ref pc); break; + case 2: info.Mnemonic = "tst.l"; info.Args = DisassembleValue(mode, reg, 4, ref pc); break; + } + info.Length = pc - info.PC; + } + + private void BTSTi() + { + int bit = ReadWord(PC); + PC += 2; + int mode = (op >> 3) & 7; + int reg = op & 7; + + if (mode == 0) + { + bit &= 31; + int mask = 1 << bit; + Z = (D[reg].s32 & mask) == 0; + PendingCycles -= 10; + } else { + bit &= 7; + int mask = 1 << bit; + Z = (ReadValueB(mode, reg) & mask) == 0; + PendingCycles -= 8 + EACyclesBW[mode, reg]; + } + } + + private void BTSTi_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int bit = ReadWord(pc); pc += 2; + int mode = (op >> 3) & 7; + int reg = op & 7; + + info.Mnemonic = "btst"; + info.Args = String.Format("${0:X}, {1}", bit, DisassembleValue(mode, reg, 1, ref pc)); + + info.Length = pc - info.PC; + } + + private void BTSTr() + { + throw new NotImplementedException(); + } + + private void BTSTr_Disasm(DisassemblyInfo info) + { + throw new NotImplementedException(); + } + + private void JMP() + { + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + PC = ReadAddress(mode, reg); + + switch (mode) + { + case 2: PendingCycles -= 8; break; + case 5: PendingCycles -= 10; break; + case 6: PendingCycles -= 14; break; + case 7: + switch (reg) + { + case 0: PendingCycles -= 10; break; + case 1: PendingCycles -= 12; break; + case 2: PendingCycles -= 10; break; + case 3: PendingCycles -= 14; break; + } + break; + } + } + + private void JMP_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + info.Mnemonic = "jmp"; + info.Args = DisassembleValue(mode, reg, 1, ref pc); + info.Length = pc - info.PC; + } + + private void JSR() + { + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + int addr = ReadAddress(mode, reg); + + A[7].s32 -= 4; + WriteLong(A[7].s32, PC); + PC = addr; + + switch (mode) + { + case 2: PendingCycles -= 16; break; + case 5: PendingCycles -= 18; break; + case 6: PendingCycles -= 22; break; + case 7: + switch (reg) + { + case 0: PendingCycles -= 18; break; + case 1: PendingCycles -= 20; break; + case 2: PendingCycles -= 18; break; + case 3: PendingCycles -= 22; break; + } + break; + } + } + + private void JSR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + info.Mnemonic = "jsr"; + info.Args = DisassembleAddress(mode, reg, ref pc); + info.Length = pc - info.PC; + } + + private void LINK() + { + int reg = op & 7; + A[7].s32 -= 4; + short offset = ReadWord(PC); PC += 2; + WriteLong(A[7].s32, A[reg].s32); + A[reg].s32 = A[7].s32 + offset; + PendingCycles -= 16; + } + + private void LINK_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int reg = op & 7; + info.Mnemonic = "link"; + info.Args = "A"+reg+", "+DisassembleImmediate(2, ref pc); // TODO need a DisassembleSigned or something + info.Length = pc - info.PC; + } + + private void NOP() + { + PendingCycles -= 4; + } + + private void NOP_Disasm(DisassemblyInfo info) + { + info.Mnemonic = "nop"; + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs b/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs new file mode 100644 index 0000000000..a1dc88491d --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Instructions/Supervisor.cs @@ -0,0 +1,86 @@ +using System; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private void MOVEtSR() + { + if (S == false) + throw new Exception("Write to SR when not in supervisor mode. supposed to trap or something..."); + + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + SR = ReadValueW(mode, reg); + PendingCycles -= (mode == 0) ? 12 : 12 + EACyclesBW[mode, reg]; + } + + private void MOVEtSR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + info.Mnemonic = "move"; + info.Args = DisassembleValue(mode, reg, 2, ref pc) + ", SR"; + info.Length = pc - info.PC; + } + + private void MOVEfSR() + { + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + WriteValueW(mode, reg, (short) SR); + PendingCycles -= (mode == 0) ? 6 : 8 + EACyclesBW[mode, reg]; + } + + private void MOVEfSR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int mode = (op >> 3) & 7; + int reg = (op >> 0) & 7; + info.Mnemonic = "move"; + info.Args = "SR, " + DisassembleValue(mode, reg, 2, ref pc); + info.Length = pc - info.PC; + } + + private void MOVEUSP() + { + if (S == false) + throw new Exception("MOVE to USP when not supervisor. needs to trap"); + + int dir = (op >> 3) & 1; + int reg = op & 7; + + if (dir == 0) usp = A[reg].s32; + else A[reg].s32 = usp; + + PendingCycles -= 4; + } + + private void MOVEUSP_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + int dir = (op >> 3) & 1; + int reg = op & 7; + info.Mnemonic = "move"; + info.Args = (dir == 0) ? ("A" + reg + ", USP") : ("USP, A" + reg); + info.Length = pc - info.PC; + } + + private void ORI_SR() + { + if (S == false) + throw new Exception("trap!"); + SR |= ReadWord(PC); PC += 2; + PendingCycles -= 20; + } + + private void ORI_SR_Disasm(DisassemblyInfo info) + { + int pc = info.PC + 2; + info.Mnemonic = "ori"; + info.Args = DisassembleImmediate(2, ref pc) + ", SR"; + info.Length = pc - info.PC; + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/M68000.cs b/BizHawk.Emulation/CPUs/68000/M68000.cs new file mode 100644 index 0000000000..2445f37383 --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/M68000.cs @@ -0,0 +1,145 @@ +using System; +using System.Runtime.InteropServices; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public sealed partial class M68000 + { + // Machine State + public Register[] D = new Register[8]; + public Register[] A = new Register[8]; + public int PC; + + public int TotalExecutedCycles; + public int PendingCycles; + + // Status Registers + private int InterruptMaskLevel; + + private bool s, m; + private int usp, ssp; + + /// Machine/Interrupt mode + public bool M { get { return m; } set { m = value; } } // TODO probably have some switch logic maybe + + /// Supervisor/User mode + public bool S + { + get { return s; } + set + { + if (value == s) return; + if (value == true) // entering supervisor mode + { + Console.WriteLine("&^&^&^&^& ENTER SUPERVISOR MODE"); + usp = A[7].s32; + A[7].s32 = ssp; + s = true; + } else { // exiting supervisor mode + Console.WriteLine("&^&^&^&^& LEAVE SUPERVISOR MODE"); + ssp = A[7].s32; + A[7].s32 = usp; + } + } + } + + /// Extend Flag + public bool X; + /// Negative Flag + public bool N; + /// Zero Flag + public bool Z; + /// Overflow Flag + public bool V; + /// Carry Flag + public bool C; + + /// Status Register + public int SR + { + get + { + int value = 0; + if (C) value |= 0x0001; + if (V) value |= 0x0002; + if (Z) value |= 0x0004; + if (N) value |= 0x0008; + if (X) value |= 0x0010; + if (M) value |= 0x1000; + if (S) value |= 0x2000; + value |= (InterruptMaskLevel & 7) << 8; + return value; + } + set + { + C = (value & 0x0001) != 0; + V = (value & 0x0002) != 0; + Z = (value & 0x0004) != 0; + N = (value & 0x0008) != 0; + X = (value & 0x0010) != 0; + M = (value & 0x1000) != 0; + S = (value & 0x2000) != 0; + InterruptMaskLevel = (value >> 8) & 7; + } + } + + // Memory Access + public Func ReadByte; + public Func ReadWord; + public Func ReadLong; + + public Action WriteByte; + public Action WriteWord; + public Action WriteLong; + + // Initialization + + public M68000() + { + BuildOpcodeTable(); + } + + public void Reset() + { + s = true; + A[7].s32 = ReadLong(0); + PC = ReadLong(4); + } + + public Action[] Opcodes = new Action[0x10000]; + public ushort op; + + public void Exec() + { + Console.WriteLine(Disassemble(PC)); + + op = (ushort) ReadWord(PC); + PC += 2; + Opcodes[op](); + } + } + + [StructLayout(LayoutKind.Explicit)] + public struct Register + { + [FieldOffset(0)] + public uint u32; + [FieldOffset(0)] + public int s32; + + [FieldOffset(0)] + public ushort u16; + [FieldOffset(0)] + public short s16; + + [FieldOffset(0)] + public byte u8; + [FieldOffset(0)] + public sbyte s8; + + public override string ToString() + { + return String.Format("{0:X8}", u32); + } + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Memory.cs b/BizHawk.Emulation/CPUs/68000/Memory.cs new file mode 100644 index 0000000000..a823910fd5 --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Memory.cs @@ -0,0 +1,626 @@ +using System; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private sbyte ReadValueB(int mode, int reg) + { + sbyte value; + switch (mode) + { + case 0: // Dn + return D[reg].s8; + case 1: // An + return A[reg].s8; + case 2: // (An) + return ReadByte(A[reg].s32); + case 3: // (An)+ + value = ReadByte(A[reg].s32); + A[reg].s32 += reg == 7 ? 2 : 1; + return value; + case 4: // -(An) + A[reg].s32 -= reg == 7 ? 2 : 1; + return ReadByte(A[reg].s32); + case 5: // (d16,An) + value = ReadByte((A[reg].s32 + ReadWord(PC))); PC += 2; + return value; + case 6: // (d8,An,Xn) + return ReadByte(A[reg].s32 + GetIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = ReadByte(ReadWord(PC)); PC += 2; + return value; + case 1: // (imm).L + value = ReadByte(ReadLong(PC)); PC += 4; + return value; + case 2: // (d16,PC) + value = ReadByte(PC + ReadWord(PC)); PC += 2; + return value; + case 3: // (d8,PC,Xn) + int pc = PC; + value = ReadByte((pc + GetIndex())); + return value; + case 4: // immediate + value = (sbyte) ReadWord(PC); PC += 2; + return value; + default: + throw new Exception("Invalid addressing mode!"); + } + } + throw new Exception("Invalid addressing mode!"); + } + + private short ReadValueW(int mode, int reg) + { + short value; + switch (mode) + { + case 0: // Dn + return D[reg].s16; + case 1: // An + return A[reg].s16; + case 2: // (An) + return ReadWord(A[reg].s32); + case 3: // (An)+ + value = ReadWord(A[reg].s32); + A[reg].s32 += 2; + return value; + case 4: // -(An) + A[reg].s32 -= 2; + return ReadWord(A[reg].s32); + case 5: // (d16,An) + value = ReadWord((A[reg].s32 + ReadWord(PC))); PC += 2; + return value; + case 6: // (d8,An,Xn) + return ReadWord(A[reg].s32 + GetIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = ReadWord(ReadWord(PC)); PC += 2; + return value; + case 1: // (imm).L + value = ReadWord(ReadLong(PC)); PC += 4; + return value; + case 2: // (d16,PC) + value = ReadWord(PC + ReadWord(PC)); PC += 2; + return value; + case 3: // (d8,PC,Xn) + int pc = PC; + value = ReadWord((pc + GetIndex())); + return value; + case 4: // immediate + value = ReadWord(PC); PC += 2; + return value; + default: + throw new Exception("Invalid addressing mode!"); + } + } + throw new Exception("Invalid addressing mode!"); + } + + private int ReadValueL(int mode, int reg) + { + int value; + switch (mode) + { + case 0: // Dn + return D[reg].s32; + case 1: // An + return A[reg].s32; + case 2: // (An) + return ReadLong(A[reg].s32); + case 3: // (An)+ + value = ReadLong(A[reg].s32); + A[reg].s32 += 4; + return value; + case 4: // -(An) + A[reg].s32 -= 4; + return ReadLong(A[reg].s32); + case 5: // (d16,An) + value = ReadLong((A[reg].s32 + ReadWord(PC))); PC += 2; + return value; + case 6: // (d8,An,Xn) + return ReadLong(A[reg].s32 + GetIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = ReadLong(ReadWord(PC)); PC += 2; + return value; + case 1: // (imm).L + value = ReadLong(ReadLong(PC)); PC += 4; + return value; + case 2: // (d16,PC) + value = ReadLong(PC + ReadWord(PC)); PC += 2; + return value; + case 3: // (d8,PC,Xn) + int pc = PC; + value = ReadLong((pc + GetIndex())); + return value; + case 4: // immediate + value = ReadLong(PC); PC += 4; + return value; + default: + throw new Exception("Invalid addressing mode!"); + } + } + throw new Exception("Invalid addressing mode!"); + } + + private sbyte PeekValueB(int mode, int reg) + { + sbyte value; + switch (mode) + { + case 0: // Dn + return D[reg].s8; + case 1: // An + return A[reg].s8; + case 2: // (An) + return ReadByte(A[reg].s32); + case 3: // (An)+ + value = ReadByte(A[reg].s32); + A[reg].s32 += reg == 7 ? 2 : 1; + return value; + case 4: // -(An) + A[reg].s32 -= reg == 7 ? 2 : 1; + return ReadByte(A[reg].s32); + case 5: // (d16,An) + value = ReadByte((A[reg].s32 + ReadWord(PC))); + return value; + case 6: // (d8,An,Xn) + return ReadByte(A[reg].s32 + GetIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = ReadByte(ReadWord(PC)); + return value; + case 1: // (imm).L + value = ReadByte(ReadLong(PC)); + return value; + case 2: // (d16,PC) + value = ReadByte(PC + ReadWord(PC)); + return value; + case 3: // (d8,PC,Xn) + value = ReadByte((PC + PeekIndex())); + return value; + case 4: // immediate + return (sbyte) ReadWord(PC); + default: + throw new Exception("Invalid addressing mode!"); + } + } + throw new Exception("Invalid addressing mode!"); + } + + private short PeekValueW(int mode, int reg) + { + short value; + switch (mode) + { + case 0: // Dn + return D[reg].s16; + case 1: // An + return A[reg].s16; + case 2: // (An) + return ReadWord(A[reg].s32); + case 3: // (An)+ + value = ReadWord(A[reg].s32); + A[reg].s32 += 2; + return value; + case 4: // -(An) + A[reg].s32 -= 2; + return ReadWord(A[reg].s32); + case 5: // (d16,An) + value = ReadWord((A[reg].s32 + ReadWord(PC))); + return value; + case 6: // (d8,An,Xn) + return ReadWord(A[reg].s32 + PeekIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = ReadWord(ReadWord(PC)); + return value; + case 1: // (imm).L + value = ReadWord(ReadLong(PC)); + return value; + case 2: // (d16,PC) + value = ReadWord(PC + ReadWord(PC)); + return value; + case 3: // (d8,PC,Xn) + value = ReadWord((PC + PeekIndex())); + return value; + case 4: // immediate + return ReadWord(PC); + default: + throw new Exception("Invalid addressing mode!"); + } + } + throw new Exception("Invalid addressing mode!"); + } + + private int PeekValueL(int mode, int reg) + { + int value; + switch (mode) + { + case 0: // Dn + return D[reg].s32; + case 1: // An + return A[reg].s32; + case 2: // (An) + return ReadLong(A[reg].s32); + case 3: // (An)+ + value = ReadLong(A[reg].s32); + A[reg].s32 += 4; + return value; + case 4: // -(An) + A[reg].s32 -= 4; + return ReadLong(A[reg].s32); + case 5: // (d16,An) + value = ReadLong((A[reg].s32 + ReadWord(PC))); + return value; + case 6: // (d8,An,Xn) + return ReadLong(A[reg].s32 + PeekIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = ReadLong(ReadWord(PC)); + return value; + case 1: // (imm).L + value = ReadLong(ReadLong(PC)); + return value; + case 2: // (d16,PC) + value = ReadLong(PC + ReadWord(PC)); + return value; + case 3: // (d8,PC,Xn) + value = ReadLong((PC + PeekIndex())); + return value; + case 4: // immediate + return ReadLong(PC); + default: + throw new Exception("Invalid addressing mode!"); + } + } + throw new Exception("Invalid addressing mode!"); + } + + private int ReadAddress(int mode, int reg) + { + int addr; + switch (mode) + { + case 0: throw new Exception("Invalid addressing mode!"); // Dn + case 1: throw new Exception("Invalid addressing mode!"); // An + case 2: return A[reg].s32; // (An) + case 3: return A[reg].s32; // (An)+ + case 4: return A[reg].s32; // -(An) + case 5: // (d16,An) + addr = A[reg].s32 + ReadWord(PC); + PC += 2; + return addr; + case 6: return A[reg].s32 + GetIndex(); // (d8,An,Xn) + case 7: + switch (reg) + { + case 0: addr = ReadWord(PC); PC += 2; return addr; // (imm).w + case 1: addr = ReadLong(PC); PC += 4; return addr; // (imm).l + case 2: addr = PC; addr += ReadWord(PC); PC += 2; return addr; // (d16,PC) + case 3: addr = PC; addr += GetIndex(); return addr; // (d8,PC,Xn) + case 4: throw new Exception("Invalid addressing mode!"); // immediate + } + break; + } + throw new Exception("Invalid addressing mode!"); + } + + private string DisassembleValue(int mode, int reg, int size, ref int pc) + { + string value; + switch (mode) + { + case 0: return "D"+reg; // Dn + case 1: return "A"+reg; // An + case 2: return "(A"+reg+")"; // (An) + case 3: return "(A"+reg+")+"; // (An)+ + case 4: return "-(A"+reg+")"; // -(An) + case 5: // (d16,An) + // TODO need to figure out how to print signed-hex + value = string.Format("(${0:X},A{1})", ReadWord(pc), reg); + pc += 2; + return value; + case 6: return "NOT IMPLEMENTED"; // (d8,An,Xn) + //return ReadByte(A[reg].Long + GetIndex()); + case 7: + switch (reg) + { + case 0: // (imm).W + value = String.Format("(${0:X})", ReadWord(pc)); + pc += 2; + return value; + case 1: // (imm).L + value = String.Format("(${0:X})", ReadLong(pc)); + pc += 4; + return value; + case 2: // (d16,PC) + value = String.Format("(${0:X})", pc + ReadWord(pc)); + pc += 2; + return value; + case 3: // (d8,PC,Xn) + return "NOT IMPLEMENTED"; + /* uint _pc = PC; + value = ReadByte((_pc + GetIndex())); + return value;*/ + case 4: + switch (size) + { + case 1: value = String.Format("${0:X}", (byte)ReadWord(pc)); pc += 2; return value; + case 2: value = String.Format("${0:X}", ReadWord(pc)); pc += 2; return value; + case 4: value = String.Format("${0:X}", ReadLong(pc)); pc += 4; return value; + } + break; + } + break; + } + throw new Exception("Invalid addressing mode!"); + } + + private string DisassembleImmediate(int size, ref int pc) + { + int immed; + switch (size) + { + case 1: + immed = (byte)ReadWord(pc); pc += 2; + return String.Format("${0:X}", immed); + case 2: + immed = (ushort) ReadWord(pc); pc += 2; + return String.Format("${0:X}", immed); + case 4: + immed = ReadLong(pc); pc += 4; + return String.Format("${0:X}", immed); + } + throw new ArgumentException("Invalid size"); + } + + private string DisassembleAddress(int mode, int reg, ref int pc) + { + int addr; + switch (mode) + { + case 0: return "INVALID"; // Dn + case 1: return "INVALID"; // An + case 2: return "(A"+reg+")"; // (An) + case 3: return "(A"+reg+")+"; // (An)+ + case 4: return "-(A"+reg+")"; // -(An) + case 5: // (d16,An) + addr = ReadWord(pc); + pc += 2; + return String.Format("({0},A{1})", addr, reg); + case 6: return "NOT IMPLEMENTED"; // (d8,An,Xn) + case 7: + switch (reg) + { + case 0: addr = ReadWord(pc); pc += 2; return String.Format("${0:X}.w",addr); // (imm).w + case 1: addr = ReadLong(pc); pc += 4; return String.Format("${0:X}.l",addr); // (imm).l + case 2: addr = ReadWord(pc); pc += 2; return String.Format("(${0:X},PC)",addr); // (d16,PC) + case 3: return "NOT IMPLEMENTED"; // (d8,PC,Xn) + case 4: return "INVALID"; // immediate + } + break; + } + throw new Exception("Invalid addressing mode!"); + } + + private void WriteValueB(int mode, int reg, sbyte value) + { + switch (mode) + { + case 0x00: // Dn + D[reg].s8 = value; + return; + case 0x01: // An + A[reg].s32 = value; + return; + case 0x02: // (An) + WriteByte(A[reg].s32, value); + return; + case 0x03: // (An)+ + WriteByte(A[reg].s32, value); + A[reg].s32 += reg == 7 ? 2 : 1; + return; + case 0x04: // -(An) + A[reg].s32 -= reg == 7 ? 2 : 1; + WriteByte(A[reg].s32, value); + return; + case 0x05: // (d16,An) + WriteByte(A[reg].s32 + ReadWord(PC), value); PC += 2; + return; + case 0x06: // (d8,An,Xn) + WriteByte(A[reg].s32 + GetIndex(), value); + return; + case 0x07: + switch (reg) + { + case 0x00: // (imm).W + WriteByte(ReadWord(PC), value); PC += 2; + return; + case 0x01: // (imm).L + WriteByte(ReadLong(PC), value); PC += 4; + return; + case 0x02: // (d16,PC) + WriteByte(PC + ReadWord(PC), value); PC += 2; + return; + case 0x03: // (d8,PC,Xn) + int pc = PC; + WriteByte(pc + PeekIndex(), value); + PC += 2; + return; + default: throw new Exception("Invalid addressing mode!"); + } + } + } + + private void WriteValueW(int mode, int reg, short value) + { + switch (mode) + { + case 0x00: // Dn + D[reg].s16 = value; + return; + case 0x01: // An + A[reg].s32 = value; + return; + case 0x02: // (An) + WriteWord(A[reg].s32, value); + return; + case 0x03: // (An)+ + WriteWord(A[reg].s32, value); + A[reg].s32 += 2; + return; + case 0x04: // -(An) + A[reg].s32 -= 2; + WriteWord(A[reg].s32, value); + return; + case 0x05: // (d16,An) + WriteWord(A[reg].s32 + ReadWord(PC), value); PC += 2; + return; + case 0x06: // (d8,An,Xn) + WriteWord(A[reg].s32 + GetIndex(), value); + return; + case 0x07: + switch (reg) + { + case 0x00: // (imm).W + WriteWord(ReadWord(PC), value); PC += 2; + return; + case 0x01: // (imm).L + WriteWord(ReadLong(PC), value); PC += 4; + return; + case 0x02: // (d16,PC) + WriteWord(PC + ReadWord(PC), value); PC += 2; + return; + case 0x03: // (d8,PC,Xn) + int pc = PC; + WriteWord(pc + PeekIndex(), value); + PC += 2; + return; + default: throw new Exception("Invalid addressing mode!"); + } + } + } + + private void WriteValueL(int mode, int reg, int value) + { + switch (mode) + { + case 0x00: // Dn + D[reg].s32 = value; + return; + case 0x01: // An + A[reg].s32 = value; + return; + case 0x02: // (An) + WriteLong(A[reg].s32, value); + return; + case 0x03: // (An)+ + WriteLong(A[reg].s32, value); + A[reg].s32 += 4; + return; + case 0x04: // -(An) + A[reg].s32 -= 4; + WriteLong(A[reg].s32, value); + return; + case 0x05: // (d16,An) + WriteLong(A[reg].s32 + ReadWord(PC), value); PC += 2; + return; + case 0x06: // (d8,An,Xn) + WriteLong(A[reg].s32 + GetIndex(), value); + return; + case 0x07: + switch (reg) + { + case 0x00: // (imm).W + WriteLong(ReadWord(PC), value); PC += 2; + return; + case 0x01: // (imm).L + WriteLong(ReadLong(PC), value); PC += 4; + return; + case 0x02: // (d16,PC) + WriteLong(PC + ReadWord(PC), value); PC += 2; + return; + case 0x03: // (d8,PC,Xn) + int pc = PC; + WriteLong(pc + PeekIndex(), value); + PC += 2; + return; + default: throw new Exception("Invalid addressing mode!"); + } + } + } + + private int GetIndex() + { + Console.WriteLine("IN INDEX PORTION - NOT VERIFIED!!!"); + // TODO kid chameleon triggers this in startup sequence + + short extension = ReadWord(PC); PC += 2; + + int da = (extension >> 15) & 0x1; + int reg = (extension >> 12) & 0x7; + int size = (extension >> 11) & 0x1; + int scale = (extension >> 9) & 0x3; + sbyte displacement = (sbyte)extension; + + int indexReg; + switch (scale) + { + case 0: indexReg = 1; break; + case 1: indexReg = 2; break; + case 2: indexReg = 4; break; + default: indexReg = 8; break; + } + if (da == 0) + indexReg *= size == 0 ? D[reg].s16 : D[reg].s32; + else + indexReg *= size == 0 ? A[reg].s16 : A[reg].s32; + + return displacement + indexReg; + } + + private int PeekIndex() + { + Console.WriteLine("IN INDEX PORTION - NOT VERIFIED!!!"); + + short extension = ReadWord(PC); + + int da = (extension >> 15) & 0x1; + int reg = (extension >> 12) & 0x7; + int size = (extension >> 11) & 0x1; + int scale = (extension >> 9) & 0x3; + sbyte displacement = (sbyte)extension; + + int indexReg; + switch (scale) + { + case 0: indexReg = 1; break; + case 1: indexReg = 2; break; + case 2: indexReg = 4; break; + default: indexReg = 8; break; + } + if (da == 0) + indexReg *= size == 0 ? D[reg].s16 : D[reg].s32; + else + indexReg *= size == 0 ? A[reg].s16 : A[reg].s32; + + return displacement + indexReg; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs new file mode 100644 index 0000000000..bef2e36e9f --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/OpcodeTable.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private void BuildOpcodeTable() + { + // NOTE: Do not change the order of these assigns without testing. There is + // some overwriting of less-specific opcodes with more-specific opcodes. + // * MOVEA overwrites MOVE. + // * EXT overwrites MOVEM0 + // * DBcc overwrites Scc + // * ORI to SR overwrites ORI + + Assign("move", MOVE, "00", "Size2_0", "XnAm", "AmXn"); + Assign("movea", MOVEA, "00", "Size2_0", "Xn", "001", "AmXn"); + Assign("moveq", MOVEQ, "0111", "Xn", "0", "Data8"); + Assign("movem", MOVEM0,"010010001", "Size1", "AmXn"); + Assign("movem", MOVEM1,"010011001", "Size1", "AmXn"); + Assign("lea", LEA, "0100", "Xn", "111", "AmXn"); + Assign("clr", CLR, "01000010", "Size2_1", "AmXn"); + Assign("ext", EXT, "010010001", "Size1", "000", "Xn"); + + Assign("andi", ANDI, "00000010", "Size2_1", "AmXn"); + Assign("ori", ORI, "00000000", "Size2_1", "AmXn"); + Assign("lsl", LSLd, "1110", "Data3", "1", "Size2_1", "Data1", "01", "Xn"); + Assign("lsr", LSRd, "1110", "Data3", "0", "Size2_1", "Data1", "01", "Xn"); + Assign("asl", ASLd, "1110", "Data3", "1", "Size2_1", "Data1", "00", "Xn"); + Assign("asr", ASRd, "1110", "Data3", "0", "Size2_1", "Data1", "00", "Xn"); + Assign("rol", ROLd, "1110", "Data3", "1", "Size2_1", "Data1", "11", "Xn"); + Assign("ror", RORd, "1110", "Data3", "0", "Size2_1", "Data1", "11", "Xn"); + Assign("swap", SWAP, "0100100001000","Xn"); + + Assign("jmp", JMP, "0100111011", "AmXn"); + Assign("jsr", JSR, "0100111010", "AmXn"); + Assign("bcc", Bcc, "0110", "CondMain", "Data8"); + Assign("bra", BRA, "01100000", "Data8"); + Assign("bsr", BSR, "01100001", "Data8"); + // NOTE: Scc must be assigned before DBcc + Assign("dbcc", DBcc, "0101", "CondAll", "11001", "Xn"); + Assign("rts", RTS, "0100111001110101"); + Assign("tst", TST, "01001010", "Size2_1", "AmXn"); + Assign("btst", BTSTi, "0000100000", "AmXn"); + Assign("btst", BTSTr, "0000", "Xn", "100", "AmXn"); + Assign("link", LINK, "0100111001010", "Xn"); + Assign("nop", NOP, "0100111001110001"); + + Assign("add", ADD0, "1101", "Xn", "0", "Size2_1", "AmXn"); + Assign("add", ADD1, "1101", "Xn", "1", "Size2_1", "AmXn"); + Assign("adda", ADDA, "1101", "Xn", "Size1", "11", "AmXn"); + Assign("addi", ADDI, "00000110", "Size2_1", "AmXn"); + Assign("addq", ADDQ, "0101", "Data3", "0", "Size2_1", "AmXn"); + Assign("sub", SUB0, "1001", "Xn", "0", "Size2_1", "AmXn"); + Assign("sub", SUB1, "1001", "Xn", "1", "Size2_1", "AmXn"); + Assign("suba", SUBA, "1001", "Xn", "Size1", "11", "AmXn"); + Assign("subi", SUBI, "00000100", "Size2_1", "AmXn"); + Assign("subq", SUBQ, "0101", "Data3", "1", "Size2_1", "AmXn"); + Assign("cmp", CMP, "1011", "Xn", "0", "Size2_1", "AmXn"); + Assign("cmpa", CMPA, "1011", "Xn", "Size1", "11", "AmXn"); + Assign("cmpi", CMPI, "00001100", "Size2_1", "AmXn"); + + Assign("move2sr", MOVEtSR, "0100011011", "AmXn"); + Assign("movefsr", MOVEfSR, "0100000011", "AmXn"); + Assign("moveusp", MOVEUSP, "010011100110", "Data1", "Xn"); + Assign("ori2sr", ORI_SR, "0000000001111100"); + } + + private void Assign(string instr, Action exec, string root, params string[] bitfield) + { + List opList = new List(); + opList.Add(root); + + foreach (var component in bitfield) + { + if (component.IsBinary()) AppendConstant(opList, component); + else if (component == "Size1") opList = AppendPermutations(opList, Size1); + else if (component == "Size2_0") opList = AppendPermutations(opList, Size2_0); + else if (component == "Size2_1") opList = AppendPermutations(opList, Size2_1); + else if (component == "XnAm") opList = AppendPermutations(opList, Xn3Am3); + else if (component == "AmXn") opList = AppendPermutations(opList, Am3Xn3); + else if (component == "Xn") opList = AppendPermutations(opList, Xn3); + else if (component == "CondMain") opList = AppendPermutations(opList, ConditionMain); + else if (component == "CondAll") opList = AppendPermutations(opList, ConditionAll); + else if (component == "Data1") opList = AppendData(opList, 1); + else if (component == "Data3") opList = AppendData(opList, 3); + else if (component == "Data8") opList = AppendData(opList, 8); + } + + foreach (var opcode in opList) + { + int opc = Convert.ToInt32(opcode, 2); + if (Opcodes[opc] != null && instr.NotIn("movea","ori2sr","ext")) + Console.WriteLine("Setting opcode for {0}, a handler is already set. overwriting. {1:X4}", instr, opc); + Opcodes[opc] = exec; + } + } + + private void AppendConstant(List ops, string constant) + { + for (int i=0; i AppendPermutations(List ops, string[] permutations) + { + List output = new List(); + + foreach (var input in ops) + foreach (var perm in permutations) + output.Add(input + perm); + + return output; + } + + private List AppendData(List ops, int bits) + { + List output = new List(); + + foreach (var input in ops) + for (int i = 0; i < BinaryExp(bits); i++) + output.Add(input+Convert.ToString(i, 2).PadLeft(bits, '0')); + + return output; + } + + private int BinaryExp(int bits) + { + int res = 1; + for (int i = 0; i < bits; i++) + res *= 2; + return res; + } + + #region Tables + + private static readonly string[] Size2_0 = {"01", "11", "10"}; + private static readonly string[] Size2_1 = {"00", "01", "10"}; + private static readonly string[] Size1 = {"0", "1" }; + private static readonly string[] Xn3 = {"000","001","010","011","100","101","110","111"}; + + private static readonly string[] Xn3Am3 = { + "000000", // Dn Data register + "001000", + "010000", + "011000", + "100000", + "101000", + "110000", + "111000", + + "000001", // An Address register + "001001", + "010001", + "011001", + "100001", + "101001", + "110001", + "111001", + + "000010", // (An) Address + "001010", + "010010", + "011010", + "100010", + "101010", + "110010", + "111010", + + "000011", // (An)+ Address with Postincrement + "001011", + "010011", + "011011", + "100011", + "101011", + "110011", + "111011", + + "000100", // -(An) Address with Predecrement + "001100", + "010100", + "011100", + "100100", + "101100", + "110100", + "111100", + + "000101", // (d16, An) Address with Displacement + "001101", + "010101", + "011101", + "100101", + "101101", + "110101", + "111101", + + "000110", // (d8, An, Xn) Address with Index + "001110", + "010110", + "011110", + "100110", + "101110", + "110110", + "111110", + + "010111", // (d16, PC) PC with Displacement + "011111", // (d8, PC, Xn) PC with Index + "000111", // (xxx).W Absolute Short + "001111", // (xxx).L Absolute Long + "100111", // #imm Immediate + }; + + private static readonly string[] Am3Xn3 = { + "000000", // Dn Data register + "000001", + "000010", + "000011", + "000100", + "000101", + "000110", + "000111", + + "001000", // An Address register + "001001", + "001010", + "001011", + "001100", + "001101", + "001110", + "001111", + + "010000", // (An) Address + "010001", + "010010", + "010011", + "010100", + "010101", + "010110", + "010111", + + "011000", // (An)+ Address with Postincrement + "011001", + "011010", + "011011", + "011100", + "011101", + "011110", + "011111", + + "100000", // -(An) Address with Predecrement + "100001", + "100010", + "100011", + "100100", + "100101", + "100110", + "100111", + + "101000", // (d16, An) Address with Displacement + "101001", + "101010", + "101011", + "101100", + "101101", + "101110", + "101111", + + "110000", // (d8, An, Xn) Address with Index + "110001", + "110010", + "110011", + "110100", + "110101", + "110110", + "110111", + + "111010", // (d16, PC) PC with Displacement + "111011", // (d8, PC, Xn) PC with Index + "111000", // (xxx).W Absolute Short + "111001", // (xxx).L Absolute Long + "111100", // #imm Immediate + }; + + private static readonly string[] ConditionMain = { + "0010", // HI Higher (unsigned) + "0011", // LS Lower or Same (unsigned) + "0100", // CC Carry Clear (aka Higher or Same, unsigned) + "0101", // CS Carry Set (aka Lower, unsigned) + "0110", // NE Not Equal + "0111", // EQ Equal + "1000", // VC Overflow Clear + "1001", // VS Overflow Set + "1010", // PL Plus + "1011", // MI Minus + "1100", // GE Greater or Equal (signed) + "1101", // LT Less Than (signed) + "1110", // GT Greater Than (signed) + "1111" // LE Less or Equal (signed) + }; + + private static readonly string[] ConditionAll = { + "0000", // T True + "0001", // F False + "0010", // HI Higher (unsigned) + "0011", // LS Lower or Same (unsigned) + "0100", // CC Carry Clear (aka Higher or Same, unsigned) + "0101", // CS Carry Set (aka Lower, unsigned) + "0110", // NE Not Equal + "0111", // EQ Equal + "1000", // VC Overflow Clear + "1001", // VS Overflow Set + "1010", // PL Plus + "1011", // MI Minus + "1100", // GE Greater or Equal (signed) + "1101", // LT Less Than (signed) + "1110", // GT Greater Than (signed) + "1111" // LE Less or Equal (signed) + }; + + #endregion + } +} diff --git a/BizHawk.Emulation/CPUs/68000/Tables.cs b/BizHawk.Emulation/CPUs/68000/Tables.cs new file mode 100644 index 0000000000..b108786c85 --- /dev/null +++ b/BizHawk.Emulation/CPUs/68000/Tables.cs @@ -0,0 +1,61 @@ +namespace BizHawk.Emulation.CPUs.M68K +{ + public partial class M68000 + { + private static readonly int[,] MoveCyclesBW = new int[12,9] + { + { 4, 4, 8, 8, 8, 12, 14, 12, 16 }, + { 4, 4, 8, 8, 8, 12, 14, 12, 16 }, + { 8, 8, 12, 12, 12, 16, 18, 16, 20 }, + { 8, 8, 12, 12, 12, 16, 18, 16, 20 }, + { 10, 10, 14, 14, 14, 18, 20, 18, 22 }, + { 12, 12, 16, 16, 16, 20, 22, 20, 24 }, + { 14, 14, 18, 18, 18, 22, 24, 22, 26 }, + { 12, 12, 16, 16, 16, 20, 22, 20, 24 }, + { 16, 16, 20, 20, 20, 24, 26, 24, 28 }, + { 12, 12, 16, 16, 16, 20, 22, 20, 24 }, + { 14, 14, 18, 18, 18, 22, 24, 22, 26 }, + { 8, 8, 12, 12, 12, 16, 18, 16, 20 } + }; + + private static readonly int[,] MoveCyclesL = new int[12, 9] + { + { 4, 4, 12, 12, 12, 16, 18, 16, 20 }, + { 4, 4, 12, 12, 12, 16, 18, 16, 20 }, + { 12, 12, 20, 20, 20, 24, 26, 24, 28 }, + { 12, 12, 20, 20, 20, 24, 26, 24, 28 }, + { 14, 14, 22, 22, 22, 26, 28, 26, 30 }, + { 16, 16, 24, 24, 24, 28, 30, 28, 32 }, + { 18, 18, 26, 26, 26, 30, 32, 30, 34 }, + { 16, 16, 24, 24, 24, 28, 30, 28, 32 }, + { 20, 20, 28, 28, 28, 32, 34, 32, 36 }, + { 16, 16, 24, 24, 24, 28, 30, 28, 32 }, + { 18, 18, 26, 26, 26, 30, 32, 30, 34 }, + { 12, 12, 20, 20, 20, 24, 26, 24, 28 } + }; + + private static readonly int[,] EACyclesBW = new int[8, 9] + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4 }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4 }, + { 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 10, 10, 10, 10, 10, 10, 10, 10, 10 }, + { 8, 12, 8, 10, 4, 99, 99, 99, 99 } + }; + + private static readonly int[,] EACyclesL = new int[8, 9] + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 8, 8, 8, 8, 8, 8, 8, 8, 8 }, + { 10, 10, 10, 10, 10, 10, 10, 10, 10 }, + { 12, 12, 12, 12, 12, 12, 12, 12, 12 }, + { 14, 14, 14, 14, 14, 14, 14, 14, 14 }, + { 12, 16, 12, 14, 8, 99, 99, 99, 99 } + }; + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/HuC6280/Disassembler.cs b/BizHawk.Emulation/CPUs/HuC6280/Disassembler.cs new file mode 100644 index 0000000000..920cebed95 --- /dev/null +++ b/BizHawk.Emulation/CPUs/HuC6280/Disassembler.cs @@ -0,0 +1,253 @@ +namespace BizHawk.Emulation.CPUs.H6280 + +// Do not modify this file directly! This is GENERATED code. +// Please open the CpuCoreGenerator solution and make your modifications there. + +{ + public partial class HuC6280 + { + public string Disassemble(ushort pc, out int bytesToAdvance) + { + byte op = ReadMemory(pc); + switch (op) + { + case 0x00: bytesToAdvance = 1; return "BRK"; + case 0x01: bytesToAdvance = 2; return string.Format("ORA (${0:X2},X)", ReadMemory(++pc)); + case 0x02: bytesToAdvance = 1; return "SXY"; + case 0x03: bytesToAdvance = 2; return string.Format("ST0 #${0:X2}", ReadMemory(++pc)); + case 0x04: bytesToAdvance = 2; return string.Format("TSB ${0:X2}", ReadMemory(++pc)); + case 0x05: bytesToAdvance = 2; return string.Format("ORA ${0:X2}", ReadMemory(++pc)); + case 0x06: bytesToAdvance = 2; return string.Format("ASL ${0:X2}", ReadMemory(++pc)); + case 0x07: bytesToAdvance = 2; return string.Format("RMB0 ${0:X2}", ReadMemory(++pc)); + case 0x08: bytesToAdvance = 1; return "PHP"; + case 0x09: bytesToAdvance = 2; return string.Format("ORA #${0:X2}", ReadMemory(++pc)); + case 0x0A: bytesToAdvance = 1; return "ASL A"; + case 0x0C: bytesToAdvance = 3; return string.Format("TSB ${0:X4}", ReadWord(++pc)); + case 0x0D: bytesToAdvance = 3; return string.Format("ORA ${0:X4}", ReadWord(++pc)); + case 0x0E: bytesToAdvance = 3; return string.Format("ASL ${0:X4}", ReadWord(++pc)); + case 0x0F: bytesToAdvance = 3; return string.Format("BBR0 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x10: bytesToAdvance = 2; return string.Format("BPL {0}", (sbyte)ReadMemory(++pc)); + case 0x11: bytesToAdvance = 2; return string.Format("ORA (${0:X2}),Y", ReadMemory(++pc)); + case 0x12: bytesToAdvance = 2; return string.Format("ORA (${0:X2})", ReadMemory(++pc)); + case 0x13: bytesToAdvance = 2; return string.Format("ST1 #${0:X2}", ReadMemory(++pc)); + case 0x14: bytesToAdvance = 2; return string.Format("TRB ${0:X2}", ReadMemory(++pc)); + case 0x15: bytesToAdvance = 2; return string.Format("ORA ${0:X2},X", ReadMemory(++pc)); + case 0x16: bytesToAdvance = 2; return string.Format("ASL ${0:X2},X", ReadMemory(++pc)); + case 0x17: bytesToAdvance = 2; return string.Format("RMB1 ${0:X2}", ReadMemory(++pc)); + case 0x18: bytesToAdvance = 1; return "CLC"; + case 0x19: bytesToAdvance = 3; return string.Format("ORA ${0:X4},Y", ReadWord(++pc)); + case 0x1A: bytesToAdvance = 1; return "INC A"; + case 0x1C: bytesToAdvance = 3; return string.Format("TRB ${0:X4}", ReadWord(++pc)); + case 0x1D: bytesToAdvance = 3; return string.Format("ORA ${0:X4},X", ReadWord(++pc)); + case 0x1E: bytesToAdvance = 3; return string.Format("ASL ${0:X4},X", ReadWord(++pc)); + case 0x1F: bytesToAdvance = 3; return string.Format("BBR1 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x20: bytesToAdvance = 3; return string.Format("JSR ${0:X4}", ReadWord(++pc)); + case 0x21: bytesToAdvance = 2; return string.Format("AND (${0:X2},X)", ReadMemory(++pc)); + case 0x22: bytesToAdvance = 1; return "SAX"; + case 0x23: bytesToAdvance = 2; return string.Format("ST2 #${0:X2}", ReadMemory(++pc)); + case 0x24: bytesToAdvance = 2; return string.Format("BIT ${0:X2}", ReadMemory(++pc)); + case 0x25: bytesToAdvance = 2; return string.Format("AND ${0:X2}", ReadMemory(++pc)); + case 0x26: bytesToAdvance = 2; return string.Format("ROL ${0:X2}", ReadMemory(++pc)); + case 0x27: bytesToAdvance = 2; return string.Format("RMB2 ${0:X2}", ReadMemory(++pc)); + case 0x28: bytesToAdvance = 1; return "PLP"; + case 0x29: bytesToAdvance = 2; return string.Format("AND #${0:X2}", ReadMemory(++pc)); + case 0x2A: bytesToAdvance = 1; return "ROL A"; + case 0x2C: bytesToAdvance = 3; return string.Format("BIT ${0:X4}", ReadWord(++pc)); + case 0x2D: bytesToAdvance = 3; return string.Format("AND ${0:X4}", ReadWord(++pc)); + case 0x2E: bytesToAdvance = 3; return string.Format("ROL ${0:X4}", ReadWord(++pc)); + case 0x2F: bytesToAdvance = 3; return string.Format("BBR2 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x30: bytesToAdvance = 2; return string.Format("BMI {0}", (sbyte)ReadMemory(++pc)); + case 0x31: bytesToAdvance = 2; return string.Format("AND (${0:X2}),Y", ReadMemory(++pc)); + case 0x32: bytesToAdvance = 2; return string.Format("AND (${0:X2})", ReadMemory(++pc)); + case 0x34: bytesToAdvance = 2; return string.Format("BIT ${0:X2},X", ReadMemory(++pc)); + case 0x35: bytesToAdvance = 2; return string.Format("AND ${0:X2},X", ReadMemory(++pc)); + case 0x36: bytesToAdvance = 2; return string.Format("ROL ${0:X2},X", ReadMemory(++pc)); + case 0x37: bytesToAdvance = 2; return string.Format("RMB3 ${0:X2}", ReadMemory(++pc)); + case 0x38: bytesToAdvance = 1; return "SEC"; + case 0x39: bytesToAdvance = 3; return string.Format("AND ${0:X4},Y", ReadWord(++pc)); + case 0x3A: bytesToAdvance = 1; return "DEC A"; + case 0x3C: bytesToAdvance = 3; return string.Format("BIT ${0:X4},X", ReadWord(++pc)); + case 0x3D: bytesToAdvance = 3; return string.Format("AND ${0:X4},X", ReadWord(++pc)); + case 0x3E: bytesToAdvance = 3; return string.Format("ROL ${0:X4},X", ReadWord(++pc)); + case 0x3F: bytesToAdvance = 3; return string.Format("BBR3 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x40: bytesToAdvance = 1; return "RTI"; + case 0x41: bytesToAdvance = 2; return string.Format("EOR (${0:X2},X)", ReadMemory(++pc)); + case 0x42: bytesToAdvance = 1; return "SAY"; + case 0x43: bytesToAdvance = 2; return string.Format("TMA #${0:X2}", ReadMemory(++pc)); + case 0x44: bytesToAdvance = 2; return string.Format("BSR {0}", (sbyte)ReadMemory(++pc)); + case 0x45: bytesToAdvance = 2; return string.Format("EOR ${0:X2}", ReadMemory(++pc)); + case 0x46: bytesToAdvance = 2; return string.Format("LSR ${0:X2}", ReadMemory(++pc)); + case 0x47: bytesToAdvance = 2; return string.Format("RMB4 ${0:X2}", ReadMemory(++pc)); + case 0x48: bytesToAdvance = 1; return "PHA"; + case 0x49: bytesToAdvance = 2; return string.Format("EOR #${0:X2}", ReadMemory(++pc)); + case 0x4A: bytesToAdvance = 1; return "LSR A"; + case 0x4C: bytesToAdvance = 3; return string.Format("JMP ${0:X4}", ReadWord(++pc)); + case 0x4D: bytesToAdvance = 3; return string.Format("EOR ${0:X4}", ReadWord(++pc)); + case 0x4E: bytesToAdvance = 3; return string.Format("LSR ${0:X4}", ReadWord(++pc)); + case 0x4F: bytesToAdvance = 3; return string.Format("BBR4 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x50: bytesToAdvance = 2; return string.Format("BVC {0}", (sbyte)ReadMemory(++pc)); + case 0x51: bytesToAdvance = 2; return string.Format("EOR (${0:X2}),Y", ReadMemory(++pc)); + case 0x52: bytesToAdvance = 2; return string.Format("EOR (${0:X2})", ReadMemory(++pc)); + case 0x53: bytesToAdvance = 2; return string.Format("TAM #${0:X2}", ReadMemory(++pc)); + case 0x54: bytesToAdvance = 1; return "CSL"; + case 0x55: bytesToAdvance = 2; return string.Format("EOR ${0:X2},X", ReadMemory(++pc)); + case 0x56: bytesToAdvance = 2; return string.Format("LSR ${0:X2},X", ReadMemory(++pc)); + case 0x57: bytesToAdvance = 2; return string.Format("RMB5 ${0:X2}", ReadMemory(++pc)); + case 0x58: bytesToAdvance = 1; return "CLI"; + case 0x59: bytesToAdvance = 3; return string.Format("EOR ${0:X4},Y", ReadWord(++pc)); + case 0x5A: bytesToAdvance = 1; return "PHY"; + case 0x5D: bytesToAdvance = 3; return string.Format("EOR ${0:X4},X", ReadWord(++pc)); + case 0x5E: bytesToAdvance = 3; return string.Format("LSR ${0:X4},X", ReadWord(++pc)); + case 0x5F: bytesToAdvance = 3; return string.Format("BBR5 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x60: bytesToAdvance = 1; return "RTS"; + case 0x61: bytesToAdvance = 2; return string.Format("ADC (${0:X2},X)", ReadMemory(++pc)); + case 0x62: bytesToAdvance = 1; return "CLA"; + case 0x64: bytesToAdvance = 2; return string.Format("STZ ${0:X2}", ReadMemory(++pc)); + case 0x65: bytesToAdvance = 2; return string.Format("ADC ${0:X2}", ReadMemory(++pc)); + case 0x66: bytesToAdvance = 2; return string.Format("ROR ${0:X2}", ReadMemory(++pc)); + case 0x67: bytesToAdvance = 2; return string.Format("RMB6 ${0:X2}", ReadMemory(++pc)); + case 0x68: bytesToAdvance = 1; return "PLA"; + case 0x69: bytesToAdvance = 2; return string.Format("ADC #${0:X2}", ReadMemory(++pc)); + case 0x6A: bytesToAdvance = 1; return "ROR A"; + case 0x6C: bytesToAdvance = 3; return string.Format("JMP (${0:X4})", ReadWord(++pc)); + case 0x6D: bytesToAdvance = 3; return string.Format("ADC ${0:X4}", ReadWord(++pc)); + case 0x6E: bytesToAdvance = 3; return string.Format("ROR ${0:X4}", ReadWord(++pc)); + case 0x6F: bytesToAdvance = 3; return string.Format("BBR6 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x70: bytesToAdvance = 2; return string.Format("BVS {0}", (sbyte)ReadMemory(++pc)); + case 0x71: bytesToAdvance = 2; return string.Format("ADC (${0:X2}),Y", ReadMemory(++pc)); + case 0x72: bytesToAdvance = 2; return string.Format("ADC (${0:X2})", ReadMemory(++pc)); + case 0x73: bytesToAdvance = 7; return string.Format("TII {0:X4},{1:X4},{2:X4}", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5))); + case 0x74: bytesToAdvance = 2; return string.Format("STZ ${0:X2},X", ReadMemory(++pc)); + case 0x75: bytesToAdvance = 2; return string.Format("ADC ${0:X2},X", ReadMemory(++pc)); + case 0x76: bytesToAdvance = 2; return string.Format("ROR ${0:X2},X", ReadMemory(++pc)); + case 0x77: bytesToAdvance = 2; return string.Format("RMB7 ${0:X2}", ReadMemory(++pc)); + case 0x78: bytesToAdvance = 1; return "SEI"; + case 0x79: bytesToAdvance = 3; return string.Format("ADC ${0:X4},Y", ReadWord(++pc)); + case 0x7A: bytesToAdvance = 1; return "PLY"; + case 0x7C: bytesToAdvance = 3; return string.Format("JMP (${0:X4},X)", ReadWord(++pc)); + case 0x7D: bytesToAdvance = 3; return string.Format("ADC ${0:X4},X", ReadWord(++pc)); + case 0x7E: bytesToAdvance = 3; return string.Format("ROR ${0:X4},X", ReadWord(++pc)); + case 0x7F: bytesToAdvance = 3; return string.Format("BBR7 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x80: bytesToAdvance = 2; return string.Format("BRA {0}", (sbyte)ReadMemory(++pc)); + case 0x81: bytesToAdvance = 2; return string.Format("STA (${0:X2},X)", ReadMemory(++pc)); + case 0x82: bytesToAdvance = 1; return "CLX"; + case 0x83: bytesToAdvance = 3; return string.Format("TST #${0:X2}, ${1:X2}", ReadMemory(++pc), ReadMemory(++pc)); + case 0x84: bytesToAdvance = 2; return string.Format("STY ${0:X2}", ReadMemory(++pc)); + case 0x85: bytesToAdvance = 2; return string.Format("STA ${0:X2}", ReadMemory(++pc)); + case 0x86: bytesToAdvance = 2; return string.Format("STX ${0:X2}", ReadMemory(++pc)); + case 0x87: bytesToAdvance = 2; return string.Format("SMB0 ${0:X2}", ReadMemory(++pc)); + case 0x88: bytesToAdvance = 1; return "DEY"; + case 0x89: bytesToAdvance = 2; return string.Format("BIT #${0:X2}", ReadMemory(++pc)); + case 0x8A: bytesToAdvance = 1; return "TXA"; + case 0x8C: bytesToAdvance = 3; return string.Format("STY ${0:X4}", ReadWord(++pc)); + case 0x8D: bytesToAdvance = 3; return string.Format("STA ${0:X4}", ReadWord(++pc)); + case 0x8E: bytesToAdvance = 3; return string.Format("STX ${0:X4}", ReadWord(++pc)); + case 0x8F: bytesToAdvance = 3; return string.Format("BBS0 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0x90: bytesToAdvance = 2; return string.Format("BCC {0}", (sbyte)ReadMemory(++pc)); + case 0x91: bytesToAdvance = 2; return string.Format("STA (${0:X2}),Y", ReadMemory(++pc)); + case 0x92: bytesToAdvance = 2; return string.Format("STA (${0:X2})", ReadMemory(++pc)); + case 0x93: bytesToAdvance = 4; return string.Format("TST #${0:X2}, ${1:X4}", ReadMemory(++pc), ReadWord(++pc)); + case 0x94: bytesToAdvance = 2; return string.Format("STY ${0:X2},X", ReadMemory(++pc)); + case 0x95: bytesToAdvance = 2; return string.Format("STA ${0:X2},X", ReadMemory(++pc)); + case 0x96: bytesToAdvance = 2; return string.Format("STX ${0:X2},Y", ReadMemory(++pc)); + case 0x97: bytesToAdvance = 2; return string.Format("SMB1 ${0:X2}", ReadMemory(++pc)); + case 0x98: bytesToAdvance = 1; return "TYA"; + case 0x99: bytesToAdvance = 3; return string.Format("STA ${0:X4},Y", ReadWord(++pc)); + case 0x9A: bytesToAdvance = 1; return "TXS"; + case 0x9C: bytesToAdvance = 3; return string.Format("STZ ${0:X4}", ReadWord(++pc)); + case 0x9D: bytesToAdvance = 3; return string.Format("STA ${0:X4},X", ReadWord(++pc)); + case 0x9E: bytesToAdvance = 3; return string.Format("STZ ${0:X4},X", ReadWord(++pc)); + case 0x9F: bytesToAdvance = 3; return string.Format("BBS1 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0xA0: bytesToAdvance = 2; return string.Format("LDY #${0:X2}", ReadMemory(++pc)); + case 0xA1: bytesToAdvance = 2; return string.Format("LDA (${0:X2},X)", ReadMemory(++pc)); + case 0xA2: bytesToAdvance = 2; return string.Format("LDX #${0:X2}", ReadMemory(++pc)); + case 0xA3: bytesToAdvance = 3; return string.Format("TST #${0:X2}, ${1:X2},X", ReadMemory(++pc), ReadMemory(++pc)); + case 0xA4: bytesToAdvance = 2; return string.Format("LDY ${0:X2}", ReadMemory(++pc)); + case 0xA5: bytesToAdvance = 2; return string.Format("LDA ${0:X2}", ReadMemory(++pc)); + case 0xA6: bytesToAdvance = 2; return string.Format("LDX ${0:X2}", ReadMemory(++pc)); + case 0xA7: bytesToAdvance = 2; return string.Format("SMB2 ${0:X2}", ReadMemory(++pc)); + case 0xA8: bytesToAdvance = 1; return "TAY"; + case 0xA9: bytesToAdvance = 2; return string.Format("LDA #${0:X2}", ReadMemory(++pc)); + case 0xAA: bytesToAdvance = 1; return "TAX"; + case 0xAC: bytesToAdvance = 3; return string.Format("LDY ${0:X4}", ReadWord(++pc)); + case 0xAD: bytesToAdvance = 3; return string.Format("LDA ${0:X4}", ReadWord(++pc)); + case 0xAE: bytesToAdvance = 3; return string.Format("LDX ${0:X4}", ReadWord(++pc)); + case 0xAF: bytesToAdvance = 3; return string.Format("BBS2 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0xB0: bytesToAdvance = 2; return string.Format("BCS {0}", (sbyte)ReadMemory(++pc)); + case 0xB1: bytesToAdvance = 2; return string.Format("LDA (${0:X2}),Y", ReadMemory(++pc)); + case 0xB2: bytesToAdvance = 2; return string.Format("LDA (${0:X2})", ReadMemory(++pc)); + case 0xB3: bytesToAdvance = 4; return string.Format("TST #${0:X2}, ${1:X4},X", ReadMemory(++pc), ReadWord(++pc)); + case 0xB4: bytesToAdvance = 2; return string.Format("LDY ${0:X2},X", ReadMemory(++pc)); + case 0xB5: bytesToAdvance = 2; return string.Format("LDA ${0:X2},X", ReadMemory(++pc)); + case 0xB6: bytesToAdvance = 2; return string.Format("LDX ${0:X2},Y", ReadMemory(++pc)); + case 0xB7: bytesToAdvance = 2; return string.Format("SMB3 ${0:X2}", ReadMemory(++pc)); + case 0xB8: bytesToAdvance = 1; return "CLV"; + case 0xB9: bytesToAdvance = 3; return string.Format("LDA ${0:X4},Y", ReadWord(++pc)); + case 0xBA: bytesToAdvance = 1; return "TSX"; + case 0xBC: bytesToAdvance = 3; return string.Format("LDY ${0:X4},X", ReadWord(++pc)); + case 0xBD: bytesToAdvance = 3; return string.Format("LDA ${0:X4},X", ReadWord(++pc)); + case 0xBE: bytesToAdvance = 3; return string.Format("LDX ${0:X4},Y", ReadWord(++pc)); + case 0xBF: bytesToAdvance = 3; return string.Format("BBS3 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0xC0: bytesToAdvance = 2; return string.Format("CPY #${0:X2}", ReadMemory(++pc)); + case 0xC1: bytesToAdvance = 2; return string.Format("CMP (${0:X2},X)", ReadMemory(++pc)); + case 0xC2: bytesToAdvance = 1; return "CLY"; + case 0xC3: bytesToAdvance = 7; return string.Format("TDD {0:X4},{1:X4},{2:X4}", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5))); + case 0xC4: bytesToAdvance = 2; return string.Format("CPY ${0:X2}", ReadMemory(++pc)); + case 0xC5: bytesToAdvance = 2; return string.Format("CMP ${0:X2}", ReadMemory(++pc)); + case 0xC6: bytesToAdvance = 2; return string.Format("DEC ${0:X2}", ReadMemory(++pc)); + case 0xC7: bytesToAdvance = 2; return string.Format("SMB4 ${0:X2}", ReadMemory(++pc)); + case 0xC8: bytesToAdvance = 1; return "INY"; + case 0xC9: bytesToAdvance = 2; return string.Format("CMP #${0:X2}", ReadMemory(++pc)); + case 0xCA: bytesToAdvance = 1; return "DEX"; + case 0xCC: bytesToAdvance = 3; return string.Format("CPY ${0:X4}", ReadWord(++pc)); + case 0xCD: bytesToAdvance = 3; return string.Format("CMP ${0:X4}", ReadWord(++pc)); + case 0xCE: bytesToAdvance = 3; return string.Format("DEC ${0:X4}", ReadWord(++pc)); + case 0xCF: bytesToAdvance = 3; return string.Format("BBS4 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0xD0: bytesToAdvance = 2; return string.Format("BNE {0}", (sbyte)ReadMemory(++pc)); + case 0xD1: bytesToAdvance = 2; return string.Format("CMP (${0:X2}),Y", ReadMemory(++pc)); + case 0xD2: bytesToAdvance = 2; return string.Format("CMP (${0:X2})", ReadMemory(++pc)); + case 0xD3: bytesToAdvance = 7; return string.Format("TIN {0:X4},{1:X4},{2:X4}", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5))); + case 0xD4: bytesToAdvance = 1; return "CSH"; + case 0xD5: bytesToAdvance = 2; return string.Format("CMP ${0:X2},X", ReadMemory(++pc)); + case 0xD6: bytesToAdvance = 2; return string.Format("DEC ${0:X2},X", ReadMemory(++pc)); + case 0xD7: bytesToAdvance = 2; return string.Format("SMB5 ${0:X2}", ReadMemory(++pc)); + case 0xD8: bytesToAdvance = 1; return "CLD"; + case 0xD9: bytesToAdvance = 3; return string.Format("CMP ${0:X4},Y", ReadWord(++pc)); + case 0xDA: bytesToAdvance = 1; return "PHX"; + case 0xDD: bytesToAdvance = 3; return string.Format("CMP ${0:X4},X", ReadWord(++pc)); + case 0xDE: bytesToAdvance = 3; return string.Format("DEC ${0:X4},X", ReadWord(++pc)); + case 0xDF: bytesToAdvance = 3; return string.Format("BBS5 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0xE0: bytesToAdvance = 2; return string.Format("CPX #${0:X2}", ReadMemory(++pc)); + case 0xE1: bytesToAdvance = 2; return string.Format("SBC (${0:X2},X)", ReadMemory(++pc)); + case 0xE3: bytesToAdvance = 7; return string.Format("TIA {0:X4},{1:X4},{2:X4}", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5))); + case 0xE4: bytesToAdvance = 2; return string.Format("CPX ${0:X2}", ReadMemory(++pc)); + case 0xE5: bytesToAdvance = 2; return string.Format("SBC ${0:X2}", ReadMemory(++pc)); + case 0xE6: bytesToAdvance = 2; return string.Format("INC ${0:X2}", ReadMemory(++pc)); + case 0xE7: bytesToAdvance = 2; return string.Format("SMB6 ${0:X2}", ReadMemory(++pc)); + case 0xE8: bytesToAdvance = 1; return "INX"; + case 0xE9: bytesToAdvance = 2; return string.Format("SBC #${0:X2}", ReadMemory(++pc)); + case 0xEA: bytesToAdvance = 1; return "NOP"; + case 0xEC: bytesToAdvance = 3; return string.Format("CPX ${0:X4}", ReadWord(++pc)); + case 0xED: bytesToAdvance = 3; return string.Format("SBC ${0:X4}", ReadWord(++pc)); + case 0xEE: bytesToAdvance = 3; return string.Format("INC ${0:X4}", ReadWord(++pc)); + case 0xEF: bytesToAdvance = 3; return string.Format("BBS6 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + case 0xF0: bytesToAdvance = 2; return string.Format("BEQ {0}", (sbyte)ReadMemory(++pc)); + case 0xF1: bytesToAdvance = 2; return string.Format("SBC (${0:X2}),Y", ReadMemory(++pc)); + case 0xF2: bytesToAdvance = 2; return string.Format("SBC (${0:X2})", ReadMemory(++pc)); + case 0xF3: bytesToAdvance = 7; return string.Format("TAI {0:X4},{1:X4},{2:X4}", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5))); + case 0xF4: bytesToAdvance = 1; return "SET"; + case 0xF5: bytesToAdvance = 2; return string.Format("SBC ${0:X2},X", ReadMemory(++pc)); + case 0xF6: bytesToAdvance = 2; return string.Format("INC ${0:X2},X", ReadMemory(++pc)); + case 0xF7: bytesToAdvance = 2; return string.Format("SMB7 ${0:X2}", ReadMemory(++pc)); + case 0xF8: bytesToAdvance = 1; return "SED"; + case 0xF9: bytesToAdvance = 3; return string.Format("SBC ${0:X4},Y", ReadWord(++pc)); + case 0xFA: bytesToAdvance = 1; return "PLX"; + case 0xFD: bytesToAdvance = 3; return string.Format("SBC ${0:X4},X", ReadWord(++pc)); + case 0xFE: bytesToAdvance = 3; return string.Format("INC ${0:X4},X", ReadWord(++pc)); + case 0xFF: bytesToAdvance = 3; return string.Format("BBS7 ${0:X2},{1}", ReadMemory(++pc), (sbyte)ReadMemory(++pc)); + } + bytesToAdvance = 1; + return "???"; + } + } +} diff --git a/BizHawk.Emulation/CPUs/HuC6280/Execute.cs b/BizHawk.Emulation/CPUs/HuC6280/Execute.cs new file mode 100644 index 0000000000..3ba48d8983 --- /dev/null +++ b/BizHawk.Emulation/CPUs/HuC6280/Execute.cs @@ -0,0 +1,2136 @@ +using System; + +// Do not modify this file directly! This is GENERATED code. +// Please open the CpuCoreGenerator solution and make your modifications there. + +namespace BizHawk.Emulation.CPUs.H6280 +{ + public partial class HuC6280 + { + public void Execute(int cycles) + { + sbyte rel8; + byte value8, temp8, source8; + ushort value16, temp16; + ushort from, to, len; + int temp, lo, hi; + + PendingCycles += cycles; + while (PendingCycles > 0) + { + int lastCycles = PendingCycles; + + if (IRQ1Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ1Selector) == 0) + { + FlagB = false; + WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8)); + WriteMemory((ushort)(S-- + 0x2100), (byte)PC); + WriteMemory((ushort)(S-- + 0x2100), P); + FlagD = false; + FlagI = true; + PC = ReadWord(IRQ1Vector); + PendingCycles -= 7; + //Log.Note("CPU", "ENTERING IRQ1 INTERRUPT"); + } + + if (TimerAssert && FlagI == false && LagIFlag == false && (IRQControlByte & TimerSelector) == 0) + { + FlagB = false; + WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8)); + WriteMemory((ushort)(S-- + 0x2100), (byte)PC); + WriteMemory((ushort)(S-- + 0x2100), P); + FlagD = false; + FlagI = true; + PC = ReadWord(TimerVector); + PendingCycles -= 7; + //Log.Note("CPU", "ENTERING __TIMER__ INTERRUPT"); + } + + IRQControlByte = IRQNextControlByte; + LagIFlag = FlagI; + +//if (debug) Log.Note("CPU", State()); + byte opcode = ReadMemory(PC++); + switch (opcode) + { + case 0x00: // BRK +throw new Exception("break"); + break; + case 0x01: // ORA (addr,X) + value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0x02: // SXY + temp8 = X; + X = Y; + Y = temp8; + PendingCycles -= 3; + break; + case 0x03: // ST0 #nn + value8 = ReadMemory(PC++); + WriteVDC(0,value8); + PendingCycles -= 4; + break; + case 0x04: // TSB zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + WriteMemory(value16, (byte)(value8 | A)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A | value8) == 0; + PendingCycles -= 6; + break; + case 0x05: // ORA zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0x06: // ASL zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x07: // RMB0 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xFE; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x08: // PHP + WriteMemory((ushort)(S-- + 0x2100), P); + PendingCycles -= 3; + break; + case 0x09: // ORA #nn + value8 = ReadMemory(PC++); + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x0A: // ASL A + FlagC = (A & 0x80) != 0; + A = (byte) (A << 1); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x0C: // TSB addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + WriteMemory(value16, (byte)(value8 | A)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A | value8) == 0; + PendingCycles -= 7; + break; + case 0x0D: // ORA addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0x0E: // ASL addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x0F: // BBR0 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x01) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x10: // BPL +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagN == false) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0x11: // ORA (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0x12: // ORA (addr) + value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0x13: // ST1 #nn + value8 = ReadMemory(PC++); + WriteVDC(2,value8); + PendingCycles -= 4; + break; + case 0x14: // TRB zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + WriteMemory(value16, (byte)(value8 & ~A)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 6; + break; + case 0x15: // ORA zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0x16: // ASL zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x17: // RMB1 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xFD; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x18: // CLC + FlagC = false; + PendingCycles -= 2; + break; + case 0x19: // ORA addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0x1A: // INC A + P = (byte)((P & 0x5D) | TableNZ[++A]); + PendingCycles -= 2; + break; + case 0x1C: // TRB addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + WriteMemory(value16, (byte)(value8 & ~A)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 7; + break; + case 0x1D: // ORA addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + A |= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0x1E: // ASL addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x1F: // BBR1 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x02) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x20: // JSR addr + temp16 = (ushort)(PC+1); + WriteMemory((ushort)(S-- + 0x2100), (byte)(temp16 >> 8)); + WriteMemory((ushort)(S-- + 0x2100), (byte)temp16); + PC = ReadWord(PC); + PendingCycles -= 6; + break; + case 0x21: // AND (addr,X) + value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0x22: // SAX + temp8 = A; + A = X; + X = temp8; + PendingCycles -= 3; + break; + case 0x23: // ST2 #nn + value8 = ReadMemory(PC++); + WriteVDC(3,value8); + PendingCycles -= 4; + break; + case 0x24: // BIT zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 4; + break; + case 0x25: // AND zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0x26: // ROL zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x27: // RMB2 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xFB; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x28: // PLP + P = ReadMemory((ushort)(++S + 0x2100)); + PendingCycles -= 4; + break; + case 0x29: // AND #nn + value8 = ReadMemory(PC++); + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x2A: // ROL A + temp8 = A; + A = (byte)((A << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x2C: // BIT addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 5; + break; + case 0x2D: // AND addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0x2E: // ROL addr + value16 = ReadWord(PC); PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x2F: // BBR2 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x04) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x30: // BMI +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagN == true) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0x31: // AND (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0x32: // AND (addr) + value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0x34: // BIT zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 4; + break; + case 0x35: // AND zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0x36: // ROL zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x37: // RMB3 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xF7; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x38: // SEC + FlagC = true; + PendingCycles -= 2; + break; + case 0x39: // AND addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0x3A: // DEC A + P = (byte)((P & 0x5D) | TableNZ[--A]); + PendingCycles -= 2; + break; + case 0x3C: // BIT addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 5; + break; + case 0x3D: // AND addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + A &= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0x3E: // ROL addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x3F: // BBR3 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x08) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x40: // RTI + P = ReadMemory((ushort)(++S + 0x2100)); + PC = ReadMemory((ushort)(++S + 0x2100)); + PC |= (ushort)(ReadMemory((ushort)(++S + 0x2100)) << 8); + PendingCycles -= 7; + break; + case 0x41: // EOR (addr,X) + value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 10; + } + break; + case 0x42: // SAY + temp8 = A; + A = Y; + Y = temp8; + PendingCycles -= 3; + break; + case 0x43: // TMA #nn + value8 = ReadMemory(PC++); + if ((value8 & 0x01) != 0) A = MPR[0]; + else if ((value8 & 0x02) != 0) A = MPR[1]; + else if ((value8 & 0x04) != 0) A = MPR[2]; + else if ((value8 & 0x08) != 0) A = MPR[3]; + else if ((value8 & 0x10) != 0) A = MPR[4]; + else if ((value8 & 0x20) != 0) A = MPR[5]; + else if ((value8 & 0x40) != 0) A = MPR[6]; + else if ((value8 & 0x80) != 0) A = MPR[7]; + PendingCycles -= 4; + break; + case 0x44: // BSR +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + temp16 = (ushort)(PC-1); + WriteMemory((ushort)(S-- + 0x2100), (byte)(temp16 >> 8)); + WriteMemory((ushort)(S-- + 0x2100), (byte)temp16); + PC = value16; + PendingCycles -= 8; + break; + case 0x45: // EOR zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 7; + } + break; + case 0x46: // LSR zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x47: // RMB4 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xEF; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x48: // PHA + WriteMemory((ushort)(S-- + 0x2100), A); + PendingCycles -= 3; + break; + case 0x49: // EOR #nn + value8 = ReadMemory(PC++); + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 5; + } + break; + case 0x4A: // LSR A + FlagC = (A & 1) != 0; + A = (byte) (A >> 1); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x4C: // JMP addr + PC = ReadWord(PC); + PendingCycles -= 4; + break; + case 0x4D: // EOR addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 8; + } + break; + case 0x4E: // LSR addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x4F: // BBR4 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x10) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x50: // BVC +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagV == false) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0x51: // EOR (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 10; + } + break; + case 0x52: // EOR (addr) + value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 10; + } + break; + case 0x53: // TAM #nn + value8 = ReadMemory(PC++); + for (byte reg=0; reg<8; reg++) + { + if ((value8 & (1 << reg)) != 0) + MPR[reg] = A; + } + PendingCycles -= 5; + break; + case 0x54: // CSL + PendingCycles -= 2; + break; + case 0x55: // EOR zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 7; + } + break; + case 0x56: // LSR zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x57: // RMB5 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xDF; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x58: // CLI + FlagI = false; + PendingCycles -= 2; + break; + case 0x59: // EOR addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 8; + } + break; + case 0x5A: // PHY + WriteMemory((ushort)(S-- + 0x2100), Y); + PendingCycles -= 3; + break; + case 0x5D: // EOR addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + if (FlagT == false) { + A ^= value8; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + } else { + temp8 = ReadMemory((ushort)(0x2000 + X)); + temp8 ^= value8; + P = (byte)((P & 0x5D) | TableNZ[temp8]); + WriteMemory((ushort)(0x2000 + X), temp8); + PendingCycles -= 8; + } + break; + case 0x5E: // LSR addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x5F: // BBR5 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x20) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x60: // RTS + PC = ReadMemory((ushort)(++S + 0x2100)); + PC |= (ushort)(ReadMemory((ushort)(++S + 0x2100)) << 8); + PC++; + PendingCycles -= 7; + break; + case 0x61: // ADC (addr,X) + value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 7; + break; + case 0x62: // CLA + A = 0; + PendingCycles -= 2; + break; + case 0x64: // STZ zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + WriteMemory(value16, 0); + PendingCycles -= 4; + break; + case 0x65: // ADC zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 4; + break; + case 0x66: // ROR zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x67: // RMB6 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0xBF; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x68: // PLA + A = ReadMemory((ushort)(++S + 0x2100)); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0x69: // ADC #nn + value8 = ReadMemory(PC++); + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 2; + break; + case 0x6A: // ROR A + temp8 = A; + A = (byte)((A >> 1) | ((P & 1)<<7)); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x6C: // JMP + PC = ReadWord(ReadWord(PC)); + PendingCycles -= 7; + break; + case 0x6D: // ADC addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 5; + break; + case 0x6E: // ROR addr + value16 = ReadWord(PC); PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x6F: // BBR6 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x40) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x70: // BVS +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagV == true) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0x71: // ADC (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 7; + break; + case 0x72: // ADC (addr) + value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 7; + break; + case 0x73: // TII src, dest, len + from = ReadWord(PC); PC += 2; + to = ReadWord(PC); PC += 2; + len = ReadWord(PC); PC += 2; + temp = (len * 6) + 17; + while (len-- != 0) + WriteMemory(to++,ReadMemory(from++)); + PendingCycles -= temp; + break; + case 0x74: // STZ zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + WriteMemory(value16, 0); + PendingCycles -= 4; + break; + case 0x75: // ADC zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 4; + break; + case 0x76: // ROR zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0x77: // RMB7 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 &= 0x7F; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x78: // SEI + FlagI = true; + PendingCycles -= 2; + break; + case 0x79: // ADC addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 5; + break; + case 0x7A: // PLY + Y = ReadMemory((ushort)(++S + 0x2100)); + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 4; + break; + case 0x7C: // JMP + PC = ReadWord((ushort)(ReadWord(PC)+X)); + PendingCycles -= 7; + break; + case 0x7D: // ADC addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A; + + if ((P & 0x08) != 0) { + lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (source8 & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0; + FlagC = (hi & 0xFF00) != 0; + source8 = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + temp = value8 + source8 + (FlagC ? 1 : 0); + FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + source8 = (byte)temp; + } + if (FlagT == false) + A = source8; + else { + WriteMemory((ushort)(0x2000 + X), source8); + PendingCycles -= 3; + } + P = (byte)((P & 0x5D) | TableNZ[source8]); + PendingCycles -= 5; + break; + case 0x7E: // ROR addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0x7F: // BBR7 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x80) == 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x80: // BRA +/-rel + rel8 = (sbyte)ReadMemory(PC++); + PC = (ushort)(PC+rel8); + PendingCycles -= 4; + break; + case 0x81: // STA (addr,X) + value16 = ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000)); + WriteMemory(value16, A); + PendingCycles -= 7; + break; + case 0x82: // CLX + X = 0; + PendingCycles -= 2; + break; + case 0x83: // TST + value8 = ReadMemory(PC++); + temp8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + FlagN = (temp8 & 0x80) != 0; + FlagV = (temp8 & 0x40) != 0; + FlagZ = (temp8 & value8) == 0; + PendingCycles -= 7; + break; + case 0x84: // STY zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + WriteMemory(value16, Y); + PendingCycles -= 4; + break; + case 0x85: // STA zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + WriteMemory(value16, A); + PendingCycles -= 4; + break; + case 0x86: // STX zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + WriteMemory(value16, X); + PendingCycles -= 4; + break; + case 0x87: // SMB0 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x01; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x88: // DEY + P = (byte)((P & 0x5D) | TableNZ[--Y]); + PendingCycles -= 2; + break; + case 0x89: // BIT #nn + value8 = ReadMemory(PC++); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 2; + break; + case 0x8A: // TXA + A = X; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x8C: // STY addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, Y); + PendingCycles -= 5; + break; + case 0x8D: // STA addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; + break; + case 0x8E: // STX addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, X); + PendingCycles -= 5; + break; + case 0x8F: // BBS0 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x01) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0x90: // BCC +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagC == false) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0x91: // STA (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value16 = (ushort)(temp16+Y); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + WriteMemory(value16, A); + PendingCycles -= 7; + break; + case 0x92: // STA (addr) + value16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + WriteMemory(value16, A); + PendingCycles -= 7; + break; + case 0x93: // TST + value8 = ReadMemory(PC++); + temp8 = ReadMemory(ReadWord(PC)); PC += 2; + FlagN = (temp8 & 0x80) != 0; + FlagV = (temp8 & 0x40) != 0; + FlagZ = (temp8 & value8) == 0; + PendingCycles -= 8; + break; + case 0x94: // STY zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + WriteMemory(value16, Y); + PendingCycles -= 4; + break; + case 0x95: // STA zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + WriteMemory(value16, A); + PendingCycles -= 4; + break; + case 0x96: // STX zp,Y + value16 = (ushort)(((ReadMemory(PC++)+Y)&0xFF)+0x2000); + WriteMemory(value16, X); + PendingCycles -= 4; + break; + case 0x97: // SMB1 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x02; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0x98: // TYA + A = Y; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0x99: // STA addr,Y + value16 = (ushort)(ReadWord(PC)+Y); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; + break; + case 0x9A: // TXS + S = X; + PendingCycles -= 2; + break; + case 0x9C: // STZ addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, 0); + PendingCycles -= 5; + break; + case 0x9D: // STA addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; + break; + case 0x9E: // STZ addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + WriteMemory(value16, 0); + PendingCycles -= 5; + break; + case 0x9F: // BBS1 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x02) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0xA0: // LDY #nn + Y = ReadMemory(PC++); + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 2; + break; + case 0xA1: // LDA (addr,X) + A = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0xA2: // LDX #nn + X = ReadMemory(PC++); + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 2; + break; + case 0xA3: // TST + value8 = ReadMemory(PC++); + temp8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + FlagN = (temp8 & 0x80) != 0; + FlagV = (temp8 & 0x40) != 0; + FlagZ = (temp8 & value8) == 0; + PendingCycles -= 7; + break; + case 0xA4: // LDY zp + Y = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 4; + break; + case 0xA5: // LDA zp + A = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0xA6: // LDX zp + X = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 4; + break; + case 0xA7: // SMB2 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x04; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0xA8: // TAY + Y = A; + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 2; + break; + case 0xA9: // LDA #nn + A = ReadMemory(PC++); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0xAA: // TAX + X = A; + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 2; + break; + case 0xAC: // LDY addr + Y = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 5; + break; + case 0xAD: // LDA addr + A = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0xAE: // LDX addr + X = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 5; + break; + case 0xAF: // BBS2 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x04) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0xB0: // BCS +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagC == true) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0xB1: // LDA (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + A = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0xB2: // LDA (addr) + A = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0xB3: // TST + value8 = ReadMemory(PC++); + temp8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + FlagN = (temp8 & 0x80) != 0; + FlagV = (temp8 & 0x40) != 0; + FlagZ = (temp8 & value8) == 0; + PendingCycles -= 8; + break; + case 0xB4: // LDY zp,X + Y = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 4; + break; + case 0xB5: // LDA zp,X + A = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0xB6: // LDX zp,Y + X = ReadMemory((ushort)(((ReadMemory(PC++)+Y)&0xFF)+0x2000)); + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 4; + break; + case 0xB7: // SMB3 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x08; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0xB8: // CLV + FlagV = false; + PendingCycles -= 2; + break; + case 0xB9: // LDA addr,Y + A = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0xBA: // TSX + X = S; + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 2; + break; + case 0xBC: // LDY addr,X + Y = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + P = (byte)((P & 0x5D) | TableNZ[Y]); + PendingCycles -= 5; + break; + case 0xBD: // LDA addr,X + A = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0xBE: // LDX addr,Y + X = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 5; + break; + case 0xBF: // BBS3 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x08) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0xC0: // CPY #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xC1: // CMP (addr,X) + value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 7; + break; + case 0xC2: // CLY + Y = 0; + PendingCycles -= 2; + break; + case 0xC3: // TDD src, dest, len + from = ReadWord(PC); PC += 2; + to = ReadWord(PC); PC += 2; + len = ReadWord(PC); PC += 2; + temp = (len * 6) + 17; + while (len-- != 0) + WriteMemory(to--,ReadMemory(from--)); + PendingCycles -= temp; + break; + case 0xC4: // CPY zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xC5: // CMP zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xC6: // DEC zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0xC7: // SMB4 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x10; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0xC8: // INY + P = (byte)((P & 0x5D) | TableNZ[++Y]); + PendingCycles -= 2; + break; + case 0xC9: // CMP #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xCA: // DEX + P = (byte)((P & 0x5D) | TableNZ[--X]); + PendingCycles -= 2; + break; + case 0xCC: // CPY addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xCD: // CMP addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xCE: // DEC addr + value16 = ReadWord(PC); PC += 2; + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0xCF: // BBS4 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x10) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0xD0: // BNE +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagZ == false) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0xD1: // CMP (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 7; + break; + case 0xD2: // CMP (addr) + value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 7; + break; + case 0xD3: // TIN src, dest, len + from = ReadWord(PC); PC += 2; + to = ReadWord(PC); PC += 2; + len = ReadWord(PC); PC += 2; + temp = (len * 6) + 17; + while (len-- != 0) + WriteMemory(to,ReadMemory(from++)); + PendingCycles -= temp; + break; + case 0xD4: // CSH + PendingCycles -= 2; + break; + case 0xD5: // CMP zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xD6: // DEC zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0xD7: // SMB5 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x20; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0xD8: // CLD + FlagD = false; + PendingCycles -= 2; + break; + case 0xD9: // CMP addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xDA: // PHX + WriteMemory((ushort)(S-- + 0x2100), X); + PendingCycles -= 3; + break; + case 0xDD: // CMP addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xDE: // DEC addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0xDF: // BBS5 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x20) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0xE0: // CPX #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xE1: // SBC (addr,X) + value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000))); + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0xE3: // TIA src, dest, len + from = ReadWord(PC); PC += 2; + to = ReadWord(PC); PC += 2; + len = ReadWord(PC); PC += 2; + temp = (len * 6) + 17; + temp8 = 0; + while (len-- != 0) + { + WriteMemory((ushort)(to+temp8),ReadMemory(from++)); + temp8 ^= 1; + } + PendingCycles -= temp; + break; + case 0xE4: // CPX zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xE5: // SBC zp + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0xE6: // INC zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0xE7: // SMB6 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x40; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0xE8: // INX + P = (byte)((P & 0x5D) | TableNZ[++X]); + PendingCycles -= 2; + break; + case 0xE9: // SBC #nn + value8 = ReadMemory(PC++); + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 2; + break; + case 0xEA: // NOP + PendingCycles -= 2; + break; + case 0xEC: // CPX addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x5D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xED: // SBC addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0xEE: // INC addr + value16 = ReadWord(PC); PC += 2; + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0xEF: // BBS6 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x40) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + case 0xF0: // BEQ +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagZ == true) { + PendingCycles--; + PC = value16; + } + PendingCycles -= 2; + break; + case 0xF1: // SBC (addr),Y + temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + PendingCycles--; + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0xF2: // SBC (addr) + value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000))); + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 7; + break; + case 0xF3: // TAI src, dest, len + from = ReadWord(PC); PC += 2; + to = ReadWord(PC); PC += 2; + len = ReadWord(PC); PC += 2; + temp = (len * 6) + 17; + temp8 = 0; + while (len-- != 0) + { + WriteMemory(to++,ReadMemory((ushort)(from+temp8))); + temp8 ^= 1; + } + PendingCycles -= temp; + break; + case 0xF4: // SET + int a; // TODO remove these extra checks + string b = Disassemble(PC, out a); + if (b.StartsWith("ADC") == false && b.StartsWith("EOR") == false) + Console.WriteLine("SETTING T FLAG, NEXT INSTRUCTION IS UNHANDLED: {0}", b); + FlagT = true; + PendingCycles -= 2; + goto AfterClearTFlag; + case 0xF5: // SBC zp,X + value8 = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000)); + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 4; + break; + case 0xF6: // INC zp,X + value16 = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000); + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 6; + break; + case 0xF7: // SMB7 zp + value16 = (ushort)(ReadMemory(PC++)+0x2000); + value8 = ReadMemory(value16); + value8 |= 0x80; + WriteMemory(value16, value8); + PendingCycles -= 7; + break; + case 0xF8: // SED + FlagD = true; + PendingCycles -= 2; + break; + case 0xF9: // SBC addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0xFA: // PLX + X = ReadMemory((ushort)(++S + 0x2100)); + P = (byte)((P & 0x5D) | TableNZ[X]); + PendingCycles -= 4; + break; + case 0xFD: // SBC addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + temp = A - value8 - (FlagC ? 0 : 1); + if ((P & 0x08) != 0) { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte) ((lo & 0x0F) | (hi & 0xF0)); + PendingCycles--; + } else { + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + } + P = (byte)((P & 0x5D) | TableNZ[A]); + PendingCycles -= 5; + break; + case 0xFE: // INC addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + PendingCycles--; + PC += 2; + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x5D) | TableNZ[value8]); + PendingCycles -= 7; + break; + case 0xFF: // BBS7 + value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000)); + rel8 = (sbyte) ReadMemory(PC++); + if ((value8 & 0x80) != 0) { + PendingCycles--; + PC = (ushort)(PC+rel8); + } + PendingCycles -= 6; + break; + default: + throw new Exception(String.Format("Unhandled opcode: {0:X2}", opcode)); + } + + P &= 0xDF; // Clear T flag + AfterClearTFlag: // SET command jumps here + int delta = lastCycles - PendingCycles; + TotalExecutedCycles += delta; + + if (TimerEnabled) + { + TimerTickCounter += delta; + if (TimerTickCounter >= 1024) + { + TimerValue--; + TimerTickCounter &= 1023; + if (TimerValue == 0xFF) + { + TimerValue = TimerReloadValue; + TimerAssert = true; + } + } + } + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs b/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs new file mode 100644 index 0000000000..0f28ea6486 --- /dev/null +++ b/BizHawk.Emulation/CPUs/HuC6280/HuC6280.cs @@ -0,0 +1,353 @@ +using System; +using System.Globalization; +using System.IO; + +namespace BizHawk.Emulation.CPUs.H6280 +{ + public sealed partial class HuC6280 + { + public HuC6280() + { + Reset(); + } + + public void Reset() + { + A = 0; + X = 0; + Y = 0; + //P = 0x14; // Set I and B + P = 0x04; // Set I + S = 0; + PC = 0; + PendingCycles = 0; + TotalExecutedCycles = 0; + LagIFlag = true; + } + + public void ResetPC() + { + PC = ReadWord(ResetVector); + } + + // ==== CPU State ==== + + public byte A; + public byte X; + public byte Y; + public byte P; + public ushort PC; + public byte S; + public byte[] MPR = new byte[8]; + + public bool LagIFlag; + public bool IRQ1Assert; + public bool TimerAssert; + public byte IRQControlByte, IRQNextControlByte; + + public int TotalExecutedCycles; + public int PendingCycles; + + public bool debug = true; + + // -- Timer Support -- + + public int TimerTickCounter; + public byte TimerReloadValue; + public byte TimerValue; + public bool TimerEnabled; + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[HuC6280]"); + writer.WriteLine("A {0:X2}", A); + writer.WriteLine("X {0:X2}", X); + writer.WriteLine("Y {0:X2}", Y); + writer.WriteLine("P {0:X2}", P); + writer.WriteLine("PC {0:X4}", PC); + writer.WriteLine("S {0:X2}", S); + writer.Write("MPR "); + MPR.SaveAsHex(writer); + writer.WriteLine("IRQ1Assert {0}", IRQ1Assert); + writer.WriteLine("TimerAssert {0}", TimerAssert); + writer.WriteLine("IRQControlByte {0:X2}", IRQControlByte); + writer.WriteLine("IRQNextControlByte {0:X2}", IRQNextControlByte); + writer.WriteLine("ExecutedCycles {0}", TotalExecutedCycles); + writer.WriteLine("PendingCycles {0}", PendingCycles); + writer.WriteLine("TimerTickCounter {0}", TimerTickCounter); + writer.WriteLine("TimerReloadValue {0}", TimerReloadValue); + writer.WriteLine("TimerValue {0}", TimerValue); + writer.WriteLine("TimerEnabled {0}", TimerEnabled); + writer.WriteLine("[/HuC6280]\n"); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/HuC6280]") break; + if (args[0] == "A") + A = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "X") + X = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Y") + Y = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "P") + P = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "PC") + PC = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "S") + S = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "MPR") + MPR.ReadFromHex(args[1]); + else if (args[0] == "IRQ1Assert") + IRQ1Assert = bool.Parse(args[1]); + else if (args[0] == "TimerAssert") + TimerAssert = bool.Parse(args[1]); + else if (args[0] == "IRQControlByte") + IRQControlByte = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "IRQNextControlByte") + IRQNextControlByte = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ExecutedCycles") + TotalExecutedCycles = int.Parse(args[1]); + else if (args[0] == "PendingCycles") + PendingCycles = int.Parse(args[1]); + else if (args[0] == "TimerTickCounter") + TimerTickCounter = int.Parse(args[1]); + else if (args[0] == "TimerReloadValue") + TimerReloadValue = byte.Parse(args[1]); + else if (args[0] == "TimerValue") + TimerValue = byte.Parse(args[1]); + else if (args[0] == "TimerEnabled") + TimerEnabled = bool.Parse(args[1]); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(A); + writer.Write(X); + writer.Write(Y); + writer.Write(P); + writer.Write(PC); + writer.Write(S); + writer.Write(MPR); + writer.Write(IRQ1Assert); + writer.Write(TimerAssert); + writer.Write(IRQControlByte); + writer.Write(IRQNextControlByte); + writer.Write(TotalExecutedCycles); + writer.Write(PendingCycles); + + writer.Write(TimerTickCounter); + writer.Write(TimerReloadValue); + writer.Write(TimerValue); + writer.Write(TimerEnabled); + } + + public void LoadStateBinary(BinaryReader reader) + { + A = reader.ReadByte(); + X = reader.ReadByte(); + Y = reader.ReadByte(); + P = reader.ReadByte(); + PC = reader.ReadUInt16(); + S = reader.ReadByte(); + MPR = reader.ReadBytes(8); + IRQ1Assert = reader.ReadBoolean(); + TimerAssert = reader.ReadBoolean(); + IRQControlByte = reader.ReadByte(); + IRQNextControlByte = reader.ReadByte(); + TotalExecutedCycles = reader.ReadInt32(); + PendingCycles = reader.ReadInt32(); + + TimerTickCounter = reader.ReadInt32(); + TimerReloadValue = reader.ReadByte(); + TimerValue = reader.ReadByte(); + TimerEnabled = reader.ReadBoolean(); + } + + // ==== Interrupts ==== + + private const ushort ResetVector = 0xFFFE; + private const ushort NMIVector = 0xFFFC; + private const ushort TimerVector = 0xFFFA; + private const ushort IRQ1Vector = 0xFFF8; + private const ushort IRQ2Vector = 0xFFF6; + + private const byte IRQ2Selector = 0x01; + private const byte IRQ1Selector = 0x02; + private const byte TimerSelector = 0x04; + + public void WriteIrqControl(byte value) + { + // There is a single-instruction delay before writes to the IRQ Control Byte take effect. + // After Burner requires this to function, as it ACKs the timer interrupt AFTER un-masking + // the interrupt. + + value &= 7; + IRQNextControlByte = value; + //Console.WriteLine("WROTTEN TO IRQ COTRL {0:X2}", value); + } + + public void WriteIrqStatus() + { + //Console.WriteLine("ACKNOWLDGED TIMER INT"); + TimerAssert = false; + } + + public byte ReadIrqStatus() + { + byte status = 0; + //if (IRQ2Assert) status |= 1; + if (IRQ1Assert) status |= 2; + if (TimerAssert) status |= 4; + //Console.WriteLine("READING IRQ STATUS BYTE {0:X2}",status); + return status; + } + + public void WriteTimer(byte value) + { + value &= 0x7F; + TimerReloadValue = value; + //Console.WriteLine("*** Timer Countdown Set {0}, {1} per sec",value,7160000/1024/(TimerReloadValue+1)); + } + + public void WriteTimerEnable(byte value) + { + if (TimerEnabled == false && (value & 1) == 1) + { + TimerValue = TimerReloadValue; // timer value is reset when toggled from off to on + TimerTickCounter = 0; + } + TimerEnabled = (value & 1) == 1; + //Console.WriteLine("*** Timer "+(TimerEnabled?"Enabled":"Disabled")); + } + + // ==== Flags ==== + + /// Carry Flag + private bool FlagC + { + get { return (P & 0x01) != 0; } + set { P = (byte)((P & ~0x01) | (value ? 0x01 : 0x00)); } + } + + /// Zero Flag + private bool FlagZ + { + get { return (P & 0x02) != 0; } + set { P = (byte)((P & ~0x02) | (value ? 0x02 : 0x00)); } + } + + /// Interrupt Disable Flag + private bool FlagI + { + get { return (P & 0x04) != 0; } + set { P = (byte)((P & ~0x04) | (value ? 0x04 : 0x00)); } + } + + /// Decimal Mode Flag + private bool FlagD + { + get { return (P & 0x08) != 0; } + set { P = (byte)((P & ~0x08) | (value ? 0x08 : 0x00)); } + } + + /// Break Flag + private bool FlagB + { + get { return (P & 0x10) != 0; } + set { P = (byte)((P & ~0x10) | (value ? 0x10 : 0x00)); } + } + + /// T... Flag + private bool FlagT + { + get { return (P & 0x20) != 0; } + set { P = (byte)((P & ~0x20) | (value ? 0x20 : 0x00)); } + } + + /// Overflow Flag + private bool FlagV + { + get { return (P & 0x40) != 0; } + set { P = (byte)((P & ~0x40) | (value ? 0x40 : 0x00)); } + } + + /// Negative Flag + private bool FlagN + { + get { return (P & 0x80) != 0; } + set { P = (byte)((P & ~0x80) | (value ? 0x80 : 0x00)); } + } + + // ==== Memory ==== + + public Func ReadMemory; + public Action WriteMemory; + public Action WriteVDC; + + private ushort ReadWord(ushort address) + { + byte l = ReadMemory(address); + byte h = ReadMemory(++address); + return (ushort)((h << 8) | l); + } + + private void WriteWord(ushort address, ushort value) + { + byte l = (byte)(value & 0xFF); + byte h = (byte)(value >> 8); + WriteMemory(address, l); + WriteMemory(++address, h); + } + + private ushort ReadWordPageWrap(ushort address) + { + ushort highAddress = (ushort)((address & 0xFF00) + ((address + 1) & 0xFF)); + return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8)); + } + + public string State() + { + int notused; + string a = string.Format("{0:X4} {1:X2} {2} ", PC, ReadMemory(PC), Disassemble(PC, out notused)).PadRight(41); + string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); + string val = a + b + " "; + if (FlagN) val = val + "N"; + if (FlagV) val = val + "V"; + if (FlagT) val = val + "T"; + if (FlagB) val = val + "B"; + if (FlagD) val = val + "D"; + if (FlagI) val = val + "I"; + if (FlagZ) val = val + "Z"; + if (FlagC) val = val + "C"; + return val; + } + + private static readonly byte[] TableNZ = + { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 + }; + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/MC68000/Helpers.cs b/BizHawk.Emulation/CPUs/MC68000/Helpers.cs new file mode 100644 index 0000000000..0a2abd9072 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Helpers.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public enum ShiftDirection + { + Right = 0, + Left = 1 + } + + public class Helpers + { + public static int[,] MOVECyclesBW; + public static int[,] MOVECyclesL; + + static Helpers() + { + MOVECyclesBW = new int[12,9] { + { 4, 4, 8, 8, 8, 12, 14, 12, 16 }, + { 4, 4, 8, 8, 8, 12, 14, 12, 16 }, + { 8, 8, 12, 12, 12, 16, 18, 16, 20 }, + { 8, 8, 12, 12, 12, 16, 18, 16, 20 }, + { 10, 10, 14, 14, 14, 18, 20, 18, 22 }, + { 12, 12, 16, 16, 16, 20, 22, 20, 24 }, + { 14, 14, 18, 18, 18, 22, 24, 22, 26 }, + { 12, 12, 16, 16, 16, 20, 22, 20, 24 }, + { 16, 16, 20, 20, 20, 24, 26, 24, 28 }, + { 12, 12, 16, 16, 16, 20, 22, 20, 24 }, + { 14, 14, 18, 18, 18, 22, 24, 22, 26 }, + { 8, 8, 12, 12, 12, 16, 18, 16, 20 } + }; + + MOVECyclesL = new int[12,9] { + { 4, 4, 12, 12, 12, 16, 18, 16, 20 }, + { 4, 4, 12, 12, 12, 16, 18, 16, 20 }, + { 12, 12, 20, 20, 20, 24, 26, 24, 28 }, + { 12, 12, 20, 20, 20, 24, 26, 24, 28 }, + { 14, 14, 22, 22, 22, 26, 28, 26, 30 }, + { 16, 16, 24, 24, 24, 28, 30, 28, 32 }, + { 18, 18, 26, 26, 26, 30, 32, 30, 34 }, + { 16, 16, 24, 24, 24, 28, 30, 28, 32 }, + { 20, 20, 28, 28, 28, 32, 34, 32, 36 }, + { 16, 16, 24, 24, 24, 28, 30, 28, 32 }, + { 18, 18, 26, 26, 26, 30, 32, 30, 34 }, + { 12, 12, 20, 20, 20, 24, 26, 24, 28 } + }; + } + + #region Inject + public static void Inject(ref int register, byte value) + { + register = (register & -0x100) | value; + } + + public static void Inject(ref int register, sbyte value) + { + register = (register & -0x100) | (byte)value; + } + + public static void Inject(ref int register, ushort value) + { + register = (register & -0x10000) | value; + } + + public static void Inject(ref int register, short value) + { + register = (register & -0x10000) | (ushort)value; + } + #endregion Inject + + public static void Swap(ref int a, ref int b) + { + int c = a; + a = b; + b = c; + } + + public static int EACalcTimeBW(int mode, int register) + { + switch (mode) + { + case 0: return 0; + case 1: return 0; + case 2: return 4; + case 3: return 4; + case 4: return 6; + case 5: return 8; + case 6: return 10; + case 7: + switch (register) + { + case 0: return 8; + case 1: return 12; + case 2: return 8; + case 3: return 10; + case 4: return 4; + } + break; + } + throw new ArgumentException(); + } + + public static int EACalcTimeL(int mode, int register) + { + switch (mode) + { + case 0: return 0; + case 1: return 0; + case 2: return 8; + case 3: return 8; + case 4: return 10; + case 5: return 12; + case 6: return 14; + case 7: + switch (register) + { + case 0: return 12; + case 1: return 16; + case 2: return 12; + case 3: return 14; + case 4: return 8; + } + break; + } + throw new ArgumentException(); + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/IMemoryController.cs b/BizHawk.Emulation/CPUs/MC68000/IMemoryController.cs new file mode 100644 index 0000000000..967fe3d5ee --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/IMemoryController.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public interface IMemoryController + { + sbyte ReadB(int address); + short ReadW(int address); + int ReadL(int address); + + void WriteB(int address, sbyte value); + void WriteW(int address, short value); + void WriteL(int address, int value); + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/MC68K.cs b/BizHawk.Emulation/CPUs/MC68000/MC68K.cs new file mode 100644 index 0000000000..1064f78904 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/MC68K.cs @@ -0,0 +1,238 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +// BIG NOTICE!!!!!! + +// This is the 68000 core from Sega360. +// IT IS GPL! It is a starter core so I can work on Genesis hardware emulation first. +// This core MUST BE, and WILL BE replaced with new code at a later date. + +namespace MC68000 +{ + public sealed partial class MC68K + { + public int m_PC; + private int m_SR; + private ushort m_IR; + + public int[] m_D = new int[8]; + public int[] m_A = new int[8]; + + private int m_Usp; + private int m_Ssp; + + private IMemoryController m_Controller; + + public long m_Cycles; + + private int m_InterruptFlag; + + public MC68K(IMemoryController controller) + { + this.m_Controller = controller; + this.BuildOpTable(); + } + + public void Interrupt(int vector) + { + this.m_InterruptFlag = vector; + } + + private void HandleInterrupt() + { + int vector = 24 + this.m_InterruptFlag; + this.m_InterruptFlag = 0; + Trap(vector); + } + + public void Reset() + { + this.m_SR = 0x2000; + this.SP = ReadL(0x0); + this.m_PC = ReadL(0x4); + this.m_Cycles = 0; + } + + private class OpHistory + { + public int PC; + public Operation Operation; + public OpHistory(int pc, Operation op) + { + this.PC = pc; + this.Operation = op; + } + } + + List m_OpList = new List(200); + public void Execute(long cycles) + { + this.m_Cycles = 0; + do + { +// if (m_PC == 0x02DD8) + //m_PC = 0x02DD8; + if (this.m_Cycles >= cycles) + { + return; + } + + if (this.m_InterruptFlag > 0) + { + HandleInterrupt(); + } + + //if (this.m_PC == 0x4752) + //{ } + + // Fetch + this.m_IR = (ushort)FetchW(); + + // Decode + Operation op = this.m_OpTable[this.m_IR]; + + //if (op == null) + //{ + // ShowOpList(); + //} + + //if (m_OpList.Count == m_OpList.Capacity) + //{ + // m_OpList.RemoveAt(0); + //} + //m_OpList.Add(new OpHistory(this.m_PC - 2, op)); + + // Execute + op(); + } while (true); + } + + public void Step() + { + if (this.m_InterruptFlag > 0) + { + HandleInterrupt(); + } + + this.m_IR = (ushort)FetchW(); + Operation op = this.m_OpTable[this.m_IR]; + op(); + } + + private void ShowOpList() + { + for (int i = 0; i < m_OpList.Count; i++) + { + Console.WriteLine(Convert.ToString(m_OpList[i].PC, 16) + "\t" + m_OpList[i].Operation.Method.Name); + } + } + + public bool C // Carry + { + get { return (this.m_SR & 1) > 0; } + set + { + if (value) { this.m_SR |= 1; } + else { this.m_SR &= -2; } + } + } + + public bool V // Overflow + { + get { return (this.m_SR & 2) > 0; } + set + { + if (value) { this.m_SR |= 2; } + else { this.m_SR &= -3; } + } + } + + public bool Z // Zero + { + get { return (this.m_SR & 4) > 0; } + set + { + if (value) { this.m_SR |= 4; } + else { this.m_SR &= -5; } + } + } + + public bool N // Negative + { + get { return (this.m_SR & 8) > 0; } + set + { + if (value) { this.m_SR |= 8; } + else { this.m_SR &= -9; } + } + } + + public bool X // Extend + { + get { return (this.m_SR & 16) > 0; } + set + { + if (value) { this.m_SR |= 16; } + else { this.m_SR &= -17; } + } + } + + public bool S // Supervisor Mode + { + get { return (this.m_SR & 8192) > 0; } + set + { + if (value) { this.m_SR |= 8192; } + else { this.m_SR &= -8193; } + } + } + + private int SP + { + get { return this.m_A[7]; } + set { this.m_A[7] = value; } + } + + private bool TestCondition(int cCode) + { + switch (cCode) + { + case 0x0: // T + return true; + case 0x1: // F + return false; + case 0x2: // HI + return !C && !Z; + case 0x3: // LS + return C || Z; + case 0x4: // CC(HI) + return !C; + case 0x5: // CS(LO) + return C; + case 0x6: // NE + return !Z; + case 0x7: // EQ + return Z; + case 0x8: // VC + return !V; + case 0x9: // VS + return V; + case 0xA: // PL + return !N; + case 0xB: // MI + return N; + case 0xC: // GE + return N && V || !N && !V; + case 0xD: // LT + return N && !V || !N && V; + case 0xE: // GT + return N && V && !Z || !N && !V && !Z; + case 0xF: // LE + return Z || N && !V || !N && V; + default: + throw new ArgumentException("Bad condition code"); + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/MemoryAccess.cs b/BizHawk.Emulation/CPUs/MC68000/MemoryAccess.cs new file mode 100644 index 0000000000..1dd0cfe025 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/MemoryAccess.cs @@ -0,0 +1,819 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + #region Read + private sbyte ReadB(int address) + { + return this.m_Controller.ReadB(address &= 0x00FFFFFF); + } + + private short ReadW(int address) + { + return this.m_Controller.ReadW(address &= 0x00FFFFFF); + } + + private int ReadL(int address) + { + return this.m_Controller.ReadL(address &= 0x00FFFFFF); + } + #endregion Read + + #region Write + private void WriteB(int address, sbyte value) + { + this.m_Controller.WriteB(address &= 0x00FFFFFF, value); + } + + private void WriteW(int address, short value) + { + this.m_Controller.WriteW(address &= 0x00FFFFFF, value); + } + + private void WriteL(int address, int value) + { + this.m_Controller.WriteL(address &= 0x00FFFFFF, value); + } + #endregion Write + + #region Fetch + private sbyte FetchB() + { + return ReadB(this.m_PC++); + } + + private short FetchW() + { + short data = ReadW(this.m_PC); + this.m_PC += 2; + return data; + } + + private int FetchL() + { + int data = ReadL(this.m_PC); + this.m_PC += 4; + return data; + } + #endregion Fetch + + #region Peek + private sbyte PeekB() + { + return ReadB(this.m_PC); + } + + private short PeekW() + { + return ReadW(this.m_PC); + } + + private int PeekL() + { + return ReadL(this.m_PC); + } + #endregion Peek + + private int FetchIndex() + { + short extension = FetchW(); + int da = (extension >> 15) & 0x1; + int reg = (extension >> 12) & 0x7; + int wl = (extension >> 11) & 0x1; + int scale = (extension >> 9) & 0x3; + sbyte displacement = (sbyte)extension; + + int indexReg = (scale == 0) ? 1 : ((scale == 1) ? 2 : ((scale == 2) ? 4 : 8)); + if (da == 0) + { + indexReg *= (wl == 0) ? (short)this.m_D[reg] : this.m_D[reg]; + } + else + { + indexReg *= (wl == 0) ? (short)this.m_A[reg] : this.m_A[reg]; + } + + return displacement + indexReg; + } + + private int PeekIndex() + { + short extension = PeekW(); + int da = extension >> 15 & 0x1; + int reg = extension >> 12 & 0x7; + int wl = extension >> 11 & 0x1; + int scale = extension >> 9 & 0x3; + sbyte displacement = (sbyte)extension; + + int indexReg = (scale == 0) ? 1 : ((scale == 1) ? 2 : ((scale == 2) ? 4 : 8)); + if (da == 0) + { + indexReg *= (wl == 0) ? (short)this.m_D[reg] : this.m_D[reg]; + } + else + { + indexReg *= (wl == 0) ? (short)this.m_A[reg] : this.m_A[reg]; + } + + return displacement + indexReg; + } + + #region FetchOperand + private sbyte FetchOperandB(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + return (sbyte)this.m_D[register]; + } + case 0x1: // An + { + return (sbyte)this.m_A[register]; + } + case 0x2: // (An) + { + return ReadB(this.m_A[register]); + } + case 0x3: // (An)+ + { + sbyte operand = ReadB(this.m_A[register]); + this.m_A[register] += (register == 7) ? 2 : 1; + return operand; + } + case 0x4: // -(An) + { + this.m_A[register] -= (register == 7) ? 2 : 1; + return ReadB(this.m_A[register]); + } + case 0x5: //(d16,An) + { + return ReadB(this.m_A[register] + FetchW()); + } + case 0x6: // (d8,An,Xn) + { + return this.ReadB(this.m_A[register] + FetchIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return ReadB(FetchW()); + } + case 0x1: // (xxx).L + { + return ReadB(FetchL()); + } + case 0x2: // (d16,PC) + { + return ReadB(this.m_PC + FetchW()); + } + case 0x3: // (d8,PC,Xn) + { + sbyte operand = ReadB(this.m_PC + PeekIndex()); + this.m_PC += 2; + return operand; + } + case 0x4: // # + { + return (sbyte)FetchW(); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + } + + private short FetchOperandW(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + return (short)this.m_D[register]; + } + case 0x1: // An + { + return (short)this.m_A[register]; + } + case 0x2: // (An) + { + return ReadW(this.m_A[register]); + } + case 0x3: // (An)+ + { + short operand = ReadW(this.m_A[register]); + this.m_A[register] += 2; + return operand; + } + case 0x4: // -(An) + { + this.m_A[register] -= 2; + return ReadW(this.m_A[register]); + } + case 0x5: //(d16,An) + { + return ReadW(this.m_A[register] + FetchW()); + } + case 0x6: // (d8,An,Xn) + { + return ReadW(this.m_A[register] + FetchIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return ReadW(FetchW()); + } + case 0x1: // (xxx).L + { + return ReadW(FetchL()); + } + case 0x4: // # + { + return FetchW(); + } + case 0x2: // (d16,PC) + { + return ReadW(this.m_PC + FetchW()); + } + case 0x3: // (d8,PC,Xn) + { + short operand = ReadW(this.m_PC + PeekIndex()); + this.m_PC += 2; + return operand; + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + } + + private int FetchOperandL(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + return this.m_D[register]; + } + case 0x1: // An + { + return this.m_A[register]; + } + case 0x2: // (An) + { + return ReadL(this.m_A[register]); + } + case 0x3: // (An)+ + { + int operand = ReadL(this.m_A[register]); + this.m_A[register] += 4; + return operand; + } + case 0x4: // -(An) + { + this.m_A[register] -= 4; + return ReadL(this.m_A[register]); + } + case 0x5: //(d16,An) + { + return ReadL(this.m_A[register] + FetchW()); + } + case 0x6: // (d8,An,Xn) + { + return ReadL(this.m_A[register] + FetchIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return ReadL(FetchW()); + } + case 0x1: // (xxx).L + { + return ReadL(FetchL()); + } + case 0x4: // # + { + return FetchL(); + } + case 0x2: // (d16,PC) + { + return ReadL(this.m_PC + FetchW()); + } + case 0x3: // (d8,PC,Xn) + { + int operand = ReadL(this.m_PC + PeekIndex()); + this.m_PC += 2; + return operand; + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + } + #endregion FetchOperand + + #region FetchAddress + private int FetchAddress(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + throw new ArgumentException("Invalid mode!"); + } + case 0x1: // An + { + throw new ArgumentException("Invalid mode!"); + } + case 0x2: // (An) + { + return this.m_A[register]; + } + case 0x3: // (An)+ + { + return this.m_A[register]; + } + case 0x4: // -(An) + { + return this.m_A[register]; + } + case 0x5: //(d16,An) + { + return (this.m_A[register]); + } + case 0x6: // (d8,An,Xn) + { + return (this.m_A[register] + FetchIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return FetchW(); + } + case 0x1: // (xxx).L + { + return FetchL(); + } + case 0x4: // # + { + throw new ArgumentException("Invalid mode!"); + } + case 0x2: // (d16,PC) + { + return (this.m_PC + FetchW()); + } + case 0x3: // (d8,PC,Xn) + { + int address = (this.m_PC + PeekIndex()); + this.m_PC += 2; + return address; + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new NotImplementedException("Addressing mode doesn't exist!"); + } + } + #endregion FetchAddress + + #region SetOperand + private void SetOperandB(int mode, int register, sbyte value) + { + switch (mode) + { + case 0x0: // Dn + { + Helpers.Inject(ref this.m_D[register], value); + return; + } + case 0x1: // An + { + this.m_A[register] = value; + return; + } + case 0x2: // (An) + { + WriteB(this.m_A[register], value); + return; + } + case 0x3: // (An)+ + { + WriteB(this.m_A[register]++, value); + return; + } + case 0x4: // -(An) + { + WriteB(--this.m_A[register], value); + return; + } + case 0x5: //(d16,An) + { + WriteB(this.m_A[register] + FetchW(), value); + return; + } + case 0x6: // (d8,An,Xn) + { + WriteB(this.m_A[register] + FetchIndex(), value); + return; + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + WriteB(FetchW(), value); + return; + } + case 0x1: // (xxx).L + { + WriteB(FetchL(), value); + return; + } + case 0x4: // # + { + throw new ArgumentException("Invalid mode!"); + } + case 0x2: // (d16,PC) + { + WriteB(this.m_PC + FetchW(), value); + return; + } + case 0x3: // (d8,PC,Xn) + { + WriteB(this.m_PC + PeekIndex(), value); + return; + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new NotImplementedException("Addressing mode doesn't exist!"); + } + } + + private void SetOperandW(int mode, int register, short value) + { + switch (mode) + { + case 0x0: // Dn + { + Helpers.Inject(ref this.m_D[register], value); + break; + } + case 0x1: // An + { + this.m_A[register] = value; + return; + } + case 0x2: // (An) + { + WriteW(m_A[register], value); + return; + } + case 0x3: // (An)+ + { + WriteW(m_A[register], value); + m_A[register] += 2; + return; + } + case 0x4: // -(An) + { + m_A[register] -= 2; + WriteW(m_A[register], value); + return; + } + case 0x5: //(d16,An) + { + WriteW(this.m_A[register] + FetchW(), value); + return; + } + case 0x6: // (d8,An,Xn) + { + WriteW(this.m_A[register] + FetchIndex(), value); + return; + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + WriteW(FetchW(), value); + return; + } + case 0x1: // (xxx).L + { + WriteW(FetchL(), value); + return; + } + case 0x4: // # + { + throw new ArgumentException("Invalid mode!"); + } + case 0x2: // (d16,PC) + { + WriteW(this.m_PC + FetchW(), value); + return; + } + case 0x3: // (d8,PC,Xn) + { + WriteW(this.m_PC + PeekIndex(), value); + return; + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new NotImplementedException("Addressing mode doesn't exist!"); + } + } + + private void SetOperandL(int mode, int register, int value) + { + switch (mode) + { + case 0x0: // Dn + { + this.m_D[register] = value; + return; + } + case 0x1: + { + // When setting address registers, need to fill whole byte + this.m_A[register] = value; + return; + } + case 0x2: // (An) + { + WriteL(this.m_A[register], value); + return; + } + case 0x3: // (An)+ + { + WriteL(this.m_A[register], value); + this.m_A[register] += 4; + return; + } + case 0x4: // -(An) + { + this.m_A[register] -= 4; + WriteL(this.m_A[register], value); + return; + } + case 0x5: //(d16,An) + { + WriteL(this.m_A[register] + FetchW(), value); + return; + } + case 0x6: // (d8,An,Xn) + { + WriteL(this.m_A[register] + FetchIndex(), value); + return; + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + WriteL(FetchW(), value); + return; + } + case 0x1: // (xxx).L + { + WriteL(FetchL(), value); + return; + } + case 0x4: // # + { + throw new ArgumentException("Invalid mode!"); + } + case 0x2: // (d16,PC) + { + WriteL(this.m_PC + FetchW(), value); + return; + } + case 0x3: // (d8,PC,Xn) + { + WriteL(this.m_A[register] + PeekIndex(), value); + return; + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new NotImplementedException("Addressing mode doesn't exist!"); + } + } + #endregion SetOperand + + #region PeekOperand + private sbyte PeekOperandB(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + return (sbyte)this.m_D[register]; + } + case 0x1: // An + { + return (sbyte)this.m_A[register]; + } + case 0x2: // (An) + { + return ReadB(this.m_A[register]); + } + case 0x3: // (An)+ + { + return ReadB(this.m_A[register]); + } + case 0x4: // -(An) + { + return ReadB(this.m_A[register]); + } + case 0x5: //(d16,An) + { + return ReadB(this.m_A[register] + PeekW()); + } + case 0x6: // (d8,An,Xn) + { + return this.ReadB(this.m_A[register] + PeekIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return ReadB(PeekW()); + } + case 0x1: // (xxx).L + { + return ReadB(PeekL()); + } + case 0x4: // # + { + return (sbyte)PeekW(); + } + case 0x2: // (d16,PC) + { + return ReadB(this.m_PC + PeekW()); + } + case 0x3: // (d8,PC,Xn) + { + return this.ReadB(this.m_PC + FetchIndex()); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + } + + private short PeekOperandW(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + return (short)this.m_D[register]; + } + case 0x1: // An + { + return (short)this.m_A[register]; + } + case 0x2: // (An) + { + return ReadW(this.m_A[register]); + } + case 0x3: // (An)+ + { + return ReadW(this.m_A[register]); + } + case 0x4: // -(An) + { + return ReadW(this.m_A[register]); + } + case 0x5: //(d16,An) + { + return ReadW(this.m_A[register] + PeekW()); + } + case 0x6: // (d8,An,Xn) + { + return ReadW(this.m_A[register] + PeekIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return ReadW(PeekW()); + } + case 0x1: // (xxx).L + { + return ReadW(PeekL()); + } + case 0x4: // # + { + return PeekW(); + } + case 0x2: // (d16,PC) + { + return ReadW(this.m_PC + PeekW()); + } + case 0x3: // (d8,PC,Xn) + { + return ReadW(this.m_PC + PeekIndex()); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + } + + private int PeekOperandL(int mode, int register) + { + switch (mode) + { + case 0x0: // Dn + { + return this.m_D[register]; + } + case 0x1: // An + { + return this.m_A[register]; + } + case 0x2: // (An) + { + return ReadL(this.m_A[register]); + } + case 0x3: // (An)+ + { + return ReadL(this.m_A[register]); + } + case 0x4: // -(An) + { + return ReadL(this.m_A[register]); + } + case 0x5: //(d16,An) + { + return ReadL(this.m_A[register] + PeekW()); + } + case 0x6: // (d8,An,Xn) + { + return this.ReadL(this.m_A[register] + FetchIndex()); + } + case 0x7: + switch (register) + { + case 0x0: // (xxx).W + { + return ReadL(PeekW()); + } + case 0x1: // (xxx).L + { + return ReadL(PeekL()); + } + case 0x4: // # + { + return PeekL(); + } + case 0x2: // (d16,PC) + { + return ReadL(this.m_PC + PeekW()); + } + case 0x3: // (d8,PC,Xn) + { + return this.ReadB(this.m_PC + FetchIndex()); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + default: + throw new ArgumentException("Addressing mode doesn't exist!"); + } + } + #endregion PeekOperand + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/OpTable.cs b/BizHawk.Emulation/CPUs/MC68000/OpTable.cs new file mode 100644 index 0000000000..2c191118cf --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/OpTable.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace MC68000 +{ + internal delegate void Operation(); + + public partial class MC68K + { + private Operation[] m_OpTable = new Operation[0x10000]; + + private void BuildOpTable() + { + // First, define regular expressions for each operation + Dictionary opIndex = new Dictionary(); + + // Data Movement + opIndex.Add(new Operation(EXG), new Regex("1100" + "[0-1]{3}" + "1" + "(01000|01001|10001)" + "[0-1]{3}")); + opIndex.Add(new Operation(LEA), new Regex("0100" + "[0-1]{3}" + "111" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))")); + opIndex.Add(new Operation(LINK), new Regex("0100111001010" + "[0-1]{3}")); + opIndex.Add(new Operation(MOVE), new Regex("00" + "(01|11|10)" + "(([0-1]{3}(000|010|011|100|101|110))|((000|001)111))" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(MOVEA), new Regex("00" + "(11|10)" + "[0-1]{3}" + "001" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(MOVEM_Mem2Reg), new Regex("01001" + "1" + "001" + "[0-1]" + "((010|011|101|110)[0-1]{3}|(111(000|001|010|011)))")); + opIndex.Add(new Operation(MOVEM_Reg2Mem), new Regex("01001" + "0" + "001" + "[0-1]" + "((010|100|101|110)[0-1]{3}|(111(000|001)))")); + opIndex.Add(new Operation(MOVEP), new Regex("0000" + "[0-1]{3}" + "(100|101|110|111)" + "001" + "[0-1]{3}")); + opIndex.Add(new Operation(MOVEQ), new Regex("0111" + "[0-1]{3}" + "0" + "[0-1]{8}")); + opIndex.Add(new Operation(PEA), new Regex("0100100001" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))")); + opIndex.Add(new Operation(UNLK), new Regex("0100111001011" + "[0-1]{3}")); + + // Integer Arithmetic + opIndex.Add(new Operation(ADD_Dest), new Regex("1101" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(ADD_Source), new Regex("1101" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(ADDA), new Regex("1101" + "[0-1]{3}" + "(011|111)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(ADDI), new Regex("00000110" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(ADDQ), new Regex("0101" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(ADDX), new Regex("1101" + "[0-1]{3}" + "1" + "(00|01|10)" + "00" + "[0-1]" + "[0-1]{3}")); + opIndex.Add(new Operation(CLR), new Regex("01000010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(CMP), new Regex("1011" + "[0-1]{3}" + "(000|001|010)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(CMPA), new Regex("1011" + "[0-1]{3}" + "(011|111)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(CMPI), new Regex("00001100" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|010|011)))")); + opIndex.Add(new Operation(CMPM), new Regex("1011" + "[0-1]{3}" + "1" + "(00|01|10)" + "001" + "[0-1]{3}")); + opIndex.Add(new Operation(DIVS), new Regex("1000" + "[0-1]{3}" + "111" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(DIVU), new Regex("1000" + "[0-1]{3}" + "011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(EXT), new Regex("0100100" + "(010|011|111)" + "000" + "[0-1]{3}")); + opIndex.Add(new Operation(MULS), new Regex("1100" + "[0-1]{3}" + "111" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(MULU), new Regex("1100" + "[0-1]{3}" + "011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(NEG), new Regex("01000100" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(NEGX), new Regex("01000000" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(SUB_Dest), new Regex("1001" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(SUB_Source), new Regex("1001" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(SUBA), new Regex("1001" + "[0-1]{3}" + "(011|111)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(SUBI), new Regex("00000100" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(SUBQ), new Regex("0101" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(SUBX), new Regex("1001" + "[0-1]{3}" + "1" + "(00|01|10)" + "00" + "[0-1]" + "[0-1]{3}")); + + // Logical + opIndex.Add(new Operation(AND_Dest), new Regex("1100" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(AND_Source), new Regex("1100" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(ANDI), new Regex("00000010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(EOR), new Regex("1011" + "[0-1]{3}" + "(100|101|110)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(EORI), new Regex("00001010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(OR_Dest), new Regex("1000" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(OR_Source), new Regex("1000" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(ORI), new Regex("00000000" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(NOT), new Regex("01000110" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + + // Shift and Rotate + opIndex.Add(new Operation(ASL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "00" + "[0-1]{3}")); + opIndex.Add(new Operation(ASR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "00" + "[0-1]{3}")); + opIndex.Add(new Operation(ASL_ASR_Memory), new Regex("1110000" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(LSL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "01" + "[0-1]{3}")); + opIndex.Add(new Operation(LSR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "01" + "[0-1]{3}")); + opIndex.Add(new Operation(LSL_LSR_Memory), new Regex("1110001" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(ROL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "11" + "[0-1]{3}")); + opIndex.Add(new Operation(ROR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "11" + "[0-1]{3}")); + opIndex.Add(new Operation(ROL_ROR_Memory), new Regex("1110011" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(ROXL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "10" + "[0-1]{3}")); + opIndex.Add(new Operation(ROXR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "10" + "[0-1]{3}")); + opIndex.Add(new Operation(ROXL_ROXR_Memory), new Regex("1110010" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(SWAP), new Regex("0100100001000" + "[0-1]{3}")); + + // Bit Manipulation + opIndex.Add(new Operation(BTST_Dynamic), new Regex("0000" + "[0-1]{3}" + "100" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(BTST_Static), new Regex("0000100000" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|010|011)))")); + + opIndex.Add(new Operation(BSET_Dynamic), new Regex("0000" + "[0-1]{3}" + "111" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(BSET_Static), new Regex("0000100011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + + opIndex.Add(new Operation(BCLR_Dynamic), new Regex("0000" + "[0-1]{3}" + "110" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(BCLR_Static), new Regex("0000100010" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + + opIndex.Add(new Operation(BCHG_Dynamic), new Regex("0000" + "[0-1]{3}" + "101" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(BCHG_Static), new Regex("0000100001" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + + // Program Control + opIndex.Add(new Operation(Bcc), new Regex("0110" + "(001|010|011|100|101|110|111)[0-1]" + "[0-1]{8}")); + opIndex.Add(new Operation(DBcc), new Regex("0101" + "[0-1]{4}" + "11001" + "[0-1]{3}")); + opIndex.Add(new Operation(Scc), new Regex("0101" + "[0-1]{4}" + "11" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + + opIndex.Add(new Operation(BRA), new Regex("01100000" + "[0-1]{8}")); + opIndex.Add(new Operation(BSR), new Regex("01100001" + "[0-1]{8}")); + opIndex.Add(new Operation(JMP), new Regex("0100111011" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))")); + opIndex.Add(new Operation(JSR), new Regex("0100111010" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))")); + opIndex.Add(new Operation(NOP), new Regex("0100111001110001")); + + opIndex.Add(new Operation(RTS), new Regex("0100111001110101")); + + opIndex.Add(new Operation(TST), new Regex("01001010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + + // System Control + opIndex.Add(new Operation(ANDI_to_CCR), new Regex("0000001000111100")); + opIndex.Add(new Operation(ANDI_to_SR), new Regex("0000001001111100")); + opIndex.Add(new Operation(CHK), new Regex("0100" + "[0-1]{3}" + "(11|10)" + "0" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(EORI_to_CCR), new Regex("0000101000111100")); + opIndex.Add(new Operation(EORI_to_SR), new Regex("0000101001111100")); + opIndex.Add(new Operation(ILLEGAL), new Regex("0100101011111100")); + opIndex.Add(new Operation(MOVE_from_SR), new Regex("0100000011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))")); + opIndex.Add(new Operation(MOVE_to_CCR), new Regex("0100010011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(MOVE_to_SR), new Regex("0100011011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))")); + opIndex.Add(new Operation(MOVE_USP), new Regex("010011100110" + "[0-1]" + "[0-1]{3}")); + opIndex.Add(new Operation(ORI_to_CCR), new Regex("0000000000111100")); + opIndex.Add(new Operation(ORI_to_SR), new Regex("0000000001111100")); + opIndex.Add(new Operation(RESET), new Regex("0100111001110000")); + opIndex.Add(new Operation(RTE), new Regex("0100111001110011")); + opIndex.Add(new Operation(RTR), new Regex("0100111001110111")); + opIndex.Add(new Operation(STOP), new Regex("0100111001110010")); + opIndex.Add(new Operation(TRAP), new Regex("010011100100" + "[0-1]{4}")); + opIndex.Add(new Operation(TRAPV), new Regex("0100111001110110")); + + // Now, run through every possible 16-bit binary number, + // find the matching expression, and add that code to the table + for (int i = 0; i < 0x10000; i++) + { + string binaryString = Convert.ToString(i, 2); + binaryString = binaryString.PadLeft(16, '0'); + Dictionary.Enumerator enumerator = opIndex.GetEnumerator(); + while (enumerator.MoveNext()) + { + if (enumerator.Current.Value.IsMatch(binaryString)) + { + if (this.m_OpTable[i] != null) + { + throw new Exception("Two operations with clashing codes!"); + } + this.m_OpTable[i] = enumerator.Current.Key; + } + } + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/BitManipulation.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/BitManipulation.cs new file mode 100644 index 0000000000..677efcaeb2 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/BitManipulation.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + private void Btst(int mode, int register, int mask) + { + switch (mode) + { + case 0: // Destination is data register + { + int operand = FetchOperandL(mode, register); + this.Z = ((operand & mask) == 0); + return; + } + default: + { + byte operand = (byte)FetchOperandB(mode, register); + this.Z = ((operand & mask) == 0); + return; + } + } + } + + private void BTST_Dynamic() + { + int bitNumberRegister = (this.m_IR >> 9) & 0x7; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = this.m_D[bitNumberRegister]; + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Btst(mode, register, mask); + this.m_Cycles += (mode == 0) ? 6 : 4 + Helpers.EACalcTimeBW(mode, register); + } + + private void BTST_Static() + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = (byte)(FetchW() & 0x00FF); + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Btst(mode, register, mask); + this.m_Cycles += (mode == 0) ? 10 : 8 + Helpers.EACalcTimeBW(mode, register); + } + + private void Bset(int mode, int register, int mask) + { + switch (mode) + { + case 0: // Destination is data register + { + int operand = PeekOperandL(mode, register); + this.Z = ((operand & mask) == 0); + SetOperandL(mode, register, (operand | mask)); + return; + } + default: + { + byte operand = (byte)PeekOperandB(mode, register); + this.Z = ((operand & mask) == 0); + SetOperandB(mode, register, (sbyte)(operand | mask)); + return; + } + } + } + + private void BSET_Dynamic() + { + int bitNumberRegister = (this.m_IR >> 9) & 0x7; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = this.m_D[bitNumberRegister]; + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Bset(mode, register, mask); + this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register); + } + + private void BSET_Static() + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = (byte)(FetchW() & 0x00FF); + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Bset(mode, register, mask); + this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register); + } + + private void Bclr(int mode, int register, int mask) + { + switch (mode) + { + case 0: // Destination is data register + { + int operand = PeekOperandL(mode, register); + this.Z = ((operand & mask) > 0); + SetOperandL(mode, register, (operand & ~mask)); + return; + } + default: + { + byte operand = (byte)PeekOperandB(mode, register); + this.Z = ((operand & mask) > 0); + SetOperandB(mode, register, (sbyte)(operand & ~mask)); + return; + } + } + } + + private void BCLR_Dynamic() + { + int bitNumberRegister = (this.m_IR >> 9) & 0x7; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = this.m_D[bitNumberRegister]; + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Bclr(mode, register, mask); + this.m_Cycles += (mode == 0) ? 10 : 8 + Helpers.EACalcTimeBW(mode, register); + } + + private void BCLR_Static() + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = (byte)(FetchW() & 0x00FF); + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Bclr(mode, register, mask); + this.m_Cycles += (mode == 0) ? 14 : 12 + Helpers.EACalcTimeBW(mode, register); + } + + private void Bchg(int mode, int register, int mask) + { + switch (mode) + { + case 0: // Destination is data register + { + int operand = PeekOperandL(mode, register); + this.Z = ((operand & mask) > 0); + SetOperandL(mode, register, (operand ^ mask)); + return; + } + default: + { + byte operand = (byte)PeekOperandB(mode, register); + this.Z = ((operand & mask) > 0); + SetOperandB(mode, register, (sbyte)(operand ^ mask)); + return; + } + } + } + + private void BCHG_Dynamic() + { + int bitNumberRegister = (this.m_IR >> 9) & 0x7; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = this.m_D[bitNumberRegister]; + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Bchg(mode, register, mask); + this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register); + } + + private void BCHG_Static() + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Need to convert bit number into a mask + int bitNumber = (byte)(FetchW() & 0x00FF); + bitNumber %= (mode == 0) ? 32 : 8; + int mask = 1 << bitNumber; + + Bchg(mode, register, mask); + this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register); + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/DataMovement.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/DataMovement.cs new file mode 100644 index 0000000000..8e04345b94 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/DataMovement.cs @@ -0,0 +1,396 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + private void EXG() // Exchange registers + { + this.m_Cycles += 6; + + switch ((this.m_IR >> 3) & 0x31) + { + case 8: + Helpers.Swap(ref this.m_D[(this.m_IR >> 9) & 0x7], ref this.m_D[this.m_IR & 0x7]); + return; + + case 9: + Helpers.Swap(ref this.m_A[(this.m_IR >> 9) & 0x7], ref this.m_A[this.m_IR & 0x7]); + return; + + case 17: + Helpers.Swap(ref this.m_D[(this.m_IR >> 9) & 0x7], ref this.m_A[this.m_IR & 0x7]); + return; + } + } + + private void LEA() // Load effective address + { + this.m_A[(this.m_IR >> 9) & 0x7] = + FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + + switch ((this.m_IR >> 3) & 0x7) + { + case 0x2: this.m_Cycles += 4; break; + case 0x5: this.m_Cycles += 8; break; + case 0x6: this.m_Cycles += 12; break; + case 0x7: + switch (this.m_IR & 0x7) + { + case 0x0: this.m_Cycles += 8; break; + case 0x1: this.m_Cycles += 12; break; + case 0x2: this.m_Cycles += 8; break; + case 0x3: this.m_Cycles += 12; break; + } + break; + } + } + + private void LINK() + { + this.SP -= 4; + WriteL(this.SP, this.m_A[this.m_IR & 0x7]); + this.m_A[this.m_IR & 0x7] = this.SP; + this.SP += FetchW(); + + this.m_Cycles += 16; + } + + private void MOVE() // Move data from source to destination + { + int src_mode = (this.m_IR >> 3) & 0x7; + int src_reg = this.m_IR & 0x7; + int dest_mode = (this.m_IR >> 6) & 0x7; + int dest_reg = (this.m_IR >> 9) & 0x7; + + int operand = 0; + switch ((this.m_IR >> 12) & 0x3) + { + case 1: // B + operand = FetchOperandB(src_mode, src_reg); + SetOperandB(dest_mode, dest_reg, (sbyte)operand); + this.m_Cycles += Helpers.MOVECyclesBW[src_mode + ((src_mode == 7) ? src_reg : 0), + dest_mode + ((dest_mode == 7) ? dest_reg : 0)]; + break; + case 3: // W + operand = FetchOperandW(src_mode, src_reg); + SetOperandW(dest_mode, dest_reg, (short)operand); + this.m_Cycles += Helpers.MOVECyclesBW[src_mode + ((src_mode == 7) ? src_reg : 0), + dest_mode + ((dest_mode == 7) ? dest_reg : 0)]; + break; + case 2: // L + operand = FetchOperandL(src_mode, src_reg); + SetOperandL(dest_mode, dest_reg, operand); + this.m_Cycles += Helpers.MOVECyclesL[src_mode + ((src_mode == 7) ? src_reg : 0), + dest_mode + ((dest_mode == 7) ? dest_reg : 0)]; + break; + } + this.V = this.C = false; + this.N = (operand < 0); + this.Z = (operand == 0); + } + + private void MOVEA() // Move Address + { + // W + if ((this.m_IR >> 12 & 0x3) == 3) + { + this.m_A[this.m_IR >> 9 & 0x7] = + FetchOperandW(this.m_IR >> 3 & 0x7, this.m_IR & 0x7); + // TODO Need to check these clock cycles + this.m_Cycles += Helpers.MOVECyclesBW[(this.m_IR >> 3 & 0x7) + (((this.m_IR >> 3 & 0x7) == 7) ? (this.m_IR & 0x7) : 0), 1]; + } + // L + else + { + this.m_A[this.m_IR >> 9 & 0x7] = + FetchOperandL(this.m_IR >> 3 & 0x7, this.m_IR & 0x7); + // TODO Need to check these clock cycles + this.m_Cycles += Helpers.MOVECyclesL[(this.m_IR >> 3 & 0x7) + (((this.m_IR >> 3 & 0x7) == 7) ? (this.m_IR & 0x7) : 0), 1]; + } + } + + private void MOVEM_Mem2Reg() + { + int size = (this.m_IR >> 6) & 0x1; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + ushort regMap = (ushort)FetchW(); + int count = 0; + + int address = FetchAddress(src_mode, src_register); + switch (size) + { + case 0: // W + { + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + this.m_D[i] = ReadW(address); + address += 2; + count++; + } + regMap = (ushort)(regMap >> 1); + } + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + this.m_A[i] = ReadW(address); + address += 2; + count++; + } + regMap = (ushort)(regMap >> 1); + } + if (src_mode == 3) // Postincrement mode + { + this.m_A[src_register] = address; + } + + this.m_Cycles += count * 4; + break; + } + case 1: // L + { + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + this.m_D[i] = (int)ReadL(address); + address += 4; + count++; + } + regMap = (ushort)(regMap >> 1); + } + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + this.m_A[i] = (int)ReadL(address); + address += 4; + count++; + } + regMap = (ushort)(regMap >> 1); + } + if (src_mode == 3) // Postincrement mode + { + this.m_A[src_register] = address; + } + + this.m_Cycles += count * 8; + break; + } + } + + switch (src_mode) + { + case 0x2: this.m_Cycles += 12; break; + case 0x3: this.m_Cycles += 12; break; + case 0x5: this.m_Cycles += 16; break; + case 0x6: this.m_Cycles += 18; break; + case 0x7: + switch (src_register) + { + case 0x0: this.m_Cycles += 16; break; + case 0x1: this.m_Cycles += 20; break; + case 0x2: this.m_Cycles += 16; break; + case 0x3: this.m_Cycles += 18; break; + } + break; + } + } + + private void MOVEM_Reg2Mem() + { + int size = (this.m_IR >> 6) & 0x1; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + ushort regMap = (ushort)FetchW(); + + int count = 0; + int address = FetchAddress(src_mode, src_register); + switch (size) + { + case 0: // W + { + if (src_mode == 4) // Pre-decrement mode + { + for (int i = 7; i >= 0; i--) + { + if ((regMap & 0x1) > 0) + { + address -= 2; + WriteW(address, (sbyte)this.m_A[i]); + count++; + } + regMap = (ushort)(regMap >> 1); + } + for (int i = 7; i >= 0; i--) + { + if ((regMap & 0x1) > 0) + { + address -= 2; + WriteW(address, (sbyte)this.m_D[i]); + count++; + } + regMap = (ushort)(regMap >> 1); + } + this.m_A[src_register] = address; + } + else + { + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + WriteW(address, (sbyte)this.m_D[i]); + address += 2; + count++; + } + regMap = (ushort)(regMap >> 1); + } + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + WriteW(address, (sbyte)this.m_A[i]); + address += 2; + count++; + } + regMap = (ushort)(regMap >> 1); + } + } + this.m_Cycles += 4 * count; + break; + } + case 1: // L + { + if (src_mode == 4) // Pre-decrement mode + { + for (int i = 7; i >= 0; i--) + { + if ((regMap & 0x1) > 0) + { + address -= 4; + WriteL(address, this.m_A[i]); + count++; + } + regMap = (ushort)(regMap >> 1); + } + for (int i = 7; i >= 0; i--) + { + if ((regMap & 0x1) > 0) + { + address -= 4; + WriteL(address, this.m_D[i]); + count++; + } + regMap = (ushort)(regMap >> 1); + } + this.m_A[src_register] = address; + } + else + { + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + WriteL(address, this.m_D[i]); + address += 4; + count++; + } + regMap = (ushort)(regMap >> 1); + } + for (int i = 0; i < 8; i++) + { + if ((regMap & 0x1) > 0) + { + WriteL(address, this.m_A[i]); + address += 4; + count++; + } + regMap = (ushort)(regMap >> 1); + } + } + this.m_Cycles += 8 * count; + break; + } + } + + switch (src_mode) + { + case 0x2: this.m_Cycles += 8; break; + case 0x4: this.m_Cycles += 8; break; + case 0x5: this.m_Cycles += 12; break; + case 0x6: this.m_Cycles += 14; break; + case 0x7: + switch (src_register) + { + case 0x0: this.m_Cycles += 12; break; + case 0x1: this.m_Cycles += 16; break; + } + break; + } + } + + private void MOVEP() + { + int dataregister = (this.m_IR >> 9) & 0x7; + int opmode = (this.m_IR >> 6) & 0x7; + int addressregister = this.m_IR & 0x7; + short displacement = FetchW(); + + throw new NotImplementedException(); + } + + private void MOVEQ() // Move quick + { + // Data byte is sign-extended to 32 bits + int data = (sbyte)this.m_IR; + + this.N = (data < 0); + this.Z = (data == 0); + this.V = this.C = false; + + this.m_D[(this.m_IR >> 9) & 0x7] = data; + + this.m_Cycles += 4; + } + + private void PEA() // Push effective address + { + this.SP -= 4; + WriteL(this.SP, FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7)); + + switch ((this.m_IR >> 3) & 0x7) + { + case 0x2: this.m_Cycles += 12; break; + case 0x5: this.m_Cycles += 16; break; + case 0x6: this.m_Cycles += 20; break; + case 0x7: + switch (this.m_IR & 0x7) + { + case 0x0: this.m_Cycles += 16; break; + case 0x1: this.m_Cycles += 20; break; + case 0x2: this.m_Cycles += 16; break; + case 0x3: this.m_Cycles += 20; break; + } + break; + } + } + + private void UNLK() + { + this.SP = this.m_A[this.m_IR & 0x7]; + this.m_A[this.m_IR & 0x7] = ReadL(this.SP); + this.SP += 4; + + this.m_Cycles += 12; + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/IntegerArithmetic.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/IntegerArithmetic.cs new file mode 100644 index 0000000000..109683dc7b --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/IntegerArithmetic.cs @@ -0,0 +1,869 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + #region Add Helper Functions + private sbyte Add(sbyte a, sbyte b, bool updateConditions, bool useX) + { + int result = useX ? (int)a + (int)b + (this.X ? 1 : 0) : (int)a + (int)b; + + if (updateConditions) + { + this.C = this.X = (result & 0x100) > 0; + this.V = result > sbyte.MaxValue || result < sbyte.MinValue; + this.N = result < 0; + if (!useX) { this.Z = result == 0; } + } + + return (sbyte)result; + } + + private short Add(short a, short b, bool updateConditions, bool useX) + { + int result = useX ? (int)a + (int)b + (this.X ? 1 : 0) : (int)a + (int)b; + + if (updateConditions) + { + this.C = this.X = (result & 0x10000) > 0; + this.V = result > short.MaxValue || result < short.MinValue; + this.N = result < 0; + if (!useX) { this.Z = result == 0; } + } + + return (short)result; + } + + private int Add(int a, int b, bool updateConditions, bool useX) + { + long result = useX ? (long)a + (long)b + (this.X ? 1 : 0) : (long)a + (long)b; + + if (updateConditions) + { + this.C = this.X = (result & 0x100000000) > 0; + this.V = result > int.MaxValue || result < int.MinValue; + this.N = result < 0; + if (!useX) { this.Z = result == 0; } + } + + return (int)result; + } + #endregion Add Helper Functions + + #region Sub Helper Functions + private sbyte Sub(sbyte a, sbyte b, bool updateConditions, bool setX, bool useX) + { + int result = useX ? (int)b - (int)a - (this.X ? 1 : 0) : (int)b - (int)a; + + if (updateConditions) + { + this.C = (result & 0x100) > 0; + this.V = result > sbyte.MaxValue || result < sbyte.MinValue; + this.N = result < 0; + if (!useX) { this.Z = result == 0; } + if (setX) { this.X = this.C; } + } + + return (sbyte)result; + } + + private short Sub(short a, short b, bool updateConditions, bool setX, bool useX) + { + int result = useX ? (int)b - (int)a - (this.X ? 1 : 0) : (int)b - (int)a; + + if (updateConditions) + { + this.C = (result & 0x10000) > 0; + this.V = result > short.MaxValue || result < short.MinValue; + this.N = result < 0; + if (!useX) { this.Z = result == 0; } + if (setX) { this.X = this.C; } + } + + return (short)result; + } + + private int Sub(int a, int b, bool updateConditions, bool setX, bool useX) + { + long result = useX ? (long)b - (long)a - (this.X ? 1 : 0) : (long)b - (long)a; + + if (updateConditions) + { + this.C = (result & 0x100000000) > 0; + this.V = result > int.MaxValue || result < int.MinValue; + this.N = result < 0; + if (!useX) { this.Z = result == 0; } + if (setX) { this.X = this.C; } + } + + return (int)result; + } + #endregion Sub Helper Functions + + private void ADD_Dest() + { + int src_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: + { + sbyte result = Add((sbyte)this.m_D[src_register], PeekOperandB(mode, register), true, false); + SetOperandB(mode, register, result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 1: + { + short result = Add((short)this.m_D[src_register], PeekOperandW(mode, register), true, false); + SetOperandW(mode, register, result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 2: + { + int result = Add(this.m_D[src_register], PeekOperandL(mode, register), true, false); + SetOperandL(mode, register, result); + this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, register); + return; + } + } + } + + private void ADD_Source() + { + int dest_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (size) + { + case 0: + { + sbyte result = Add((sbyte)this.m_D[dest_register], FetchOperandB(src_mode, src_register), true, false); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 1: + { + short result = Add((short)this.m_D[dest_register], FetchOperandW(src_mode, src_register), true, false); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 2: + { + int result = Add(this.m_D[dest_register], FetchOperandL(src_mode, src_register), true, false); + this.m_D[dest_register] = result; + this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register); + return; + } + } + } + + private void ADDA() + { + int register = (this.m_IR >> 9) & 0x7; + int opmode = (this.m_IR >> 6) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (opmode) + { + case 3: // W + this.m_A[register] += FetchOperandW(src_mode, src_register); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + case 7: // L + this.m_A[register] += FetchOperandL(src_mode, src_register); + this.m_Cycles += 6 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + } + + private void ADDI() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Add((sbyte)FetchW(), PeekOperandB(mode, register), true, false); + SetOperandB(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 1: // W + { + short result = Add(FetchW(), PeekOperandW(mode, register), true, false); + SetOperandW(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 2: // L + { + int result = Add(FetchL(), PeekOperandL(mode, register), true, false); + SetOperandL(mode, register, result); + this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register); + return; + } + } + } + + private void ADDQ() // Add Quick + { + int data = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // With data, 0 means 8 + data = (data == 0) ? 8 : data; + + switch (size) + { + case 0: // B + { + if (mode == 1) + { + throw new ArgumentException("Byte operation not allowed on address registers"); + } + sbyte result = Add(PeekOperandB(mode, register), (sbyte)data, (mode != 1), false); + SetOperandB(mode, register, result); + switch (mode) { + case 0: this.m_Cycles += 4; break; + case 1: this.m_Cycles += 4; break; + default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break; + } + return; + } + case 1: // W + { + if (mode == 1) + { + int result = Add(PeekOperandL(mode, register), data, false, false); + SetOperandL(mode, register, result); + } + else + { + short result = Add(PeekOperandW(mode, register), (short)data, true, false); + SetOperandW(mode, register, result); + } + switch (mode) + { + case 0: this.m_Cycles += 4; break; + case 1: this.m_Cycles += 4; break; + default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break; + } + return; + } + case 2: // L + { + int result = Add(PeekOperandL(mode, register), data, (mode != 1), false); + SetOperandL(mode, register, result); + switch (mode) + { + case 0: this.m_Cycles += 8; break; + case 1: this.m_Cycles += 8; break; + default: this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, register); break; + } + return; + } + } + } + + private void ADDX() + { + int regRx = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int rm = (this.m_IR >> 3) & 0x1; + int regRy = this.m_IR & 0x7; + + switch (size) + { + case 0: + { + if (rm == 0) + { + this.m_D[regRy] = Add((sbyte)this.m_D[regRx], (sbyte)this.m_D[regRy], true, true); + this.m_Cycles += 4; + } + else + { + WriteB(this.m_A[regRy], Add(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true)); + this.m_Cycles += 18; + } + return; + } + case 1: + { + if (rm == 0) + { + this.m_D[regRy] = Add((short)this.m_D[regRx], (short)this.m_D[regRy], true, true); + this.m_Cycles += 4; + } + else + { + WriteW(this.m_A[regRy], Add(ReadW(this.m_A[regRx]), ReadW(this.m_A[regRy]), true, true)); + this.m_Cycles += 18; + } + return; + } + case 2: + { + if (rm == 0) + { + this.m_D[regRy] = Add(this.m_D[regRx], this.m_D[regRy], true, true); + this.m_Cycles += 8; + } + else + { + WriteL(this.m_A[regRy], Add(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true)); + this.m_Cycles += 30; + } + return; + } + } + } + + private void CLR() // Clear an operand + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + this.C = this.N = this.V = false; + this.Z = true; + + switch (size) + { + case 0: // B + SetOperandB(mode, register, 0); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 1: // W + SetOperandW(mode, register, 0); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 2: // L + SetOperandL(mode, register, 0); + this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register); + return; + } + } + + private void CMP() // Compare + { + int dest_register = (this.m_IR >> 9) & 0x7; + int opmode = (this.m_IR >> 6) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (opmode) + { + case 0: // B + Sub(FetchOperandB(src_mode, src_register), (sbyte)this.m_D[dest_register], true, false, false); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + case 1: // W + Sub(FetchOperandW(src_mode, src_register), (short)this.m_D[dest_register], true, false, false); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + case 2: // L + Sub(FetchOperandL(src_mode, src_register), this.m_D[dest_register], true, false, false); + this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register); + return; + } + } + + private void CMPA() + { + int dest_register = (this.m_IR >> 9) & 0x7; + int opmode = (this.m_IR >> 6) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (opmode) + { + case 3: // W + Sub((int)FetchOperandW(src_mode, src_register), this.m_A[dest_register], true, false, false); + this.m_Cycles += 6 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + case 7: // L + Sub(FetchOperandL(src_mode, src_register), this.m_A[dest_register], true, false, false); + this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register); + return; + } + } + + private void CMPI() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + Sub((sbyte)FetchW(), FetchOperandB(mode, register), true, false, false); + this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 1: // W + Sub((short)FetchW(), FetchOperandW(mode, register), true, false, false); + this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 2: // L + Sub(FetchL(), FetchOperandL(mode, register), true, false, false); + this.m_Cycles += (mode == 0) ? 14 : 12 + Helpers.EACalcTimeL(mode, register); + return; + } + } + + private void CMPM() + { + int registerAx = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int registerAy = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + Sub((sbyte)this.m_A[registerAy], (sbyte)this.m_A[registerAy], true, false, false); + this.m_Cycles += 12; + return; + case 1: // W + Sub((short)this.m_A[registerAy], (short)this.m_A[registerAy], true, false, false); + this.m_Cycles += 12; + return; + case 2: // L + Sub(this.m_A[registerAy], this.m_A[registerAy], true, false, false); + this.m_Cycles += 20; + return; + } + } + + private void DIVS() // Unsigned multiply + { + int dest_register = (this.m_IR >> 9) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + // On 68000, only allowable size is Word + int source = (short)FetchOperandW(src_mode, src_register); + int dest = this.m_D[dest_register]; + + this.C = false; + if (source == 0) + { + throw new ArgumentException("Divide by zero..."); + } + + int quotient = dest / source; + int remainder = dest % source; + + // Detect overflow + if (quotient < short.MinValue || quotient > short.MaxValue) + { + this.V = true; + throw new ArgumentException("Division overflow"); + } + this.m_D[dest_register] = (remainder << 16) | quotient; + + this.m_Cycles += 158 + Helpers.EACalcTimeBW(src_mode, src_register); + + this.N = quotient < 0; + this.Z = quotient == 0; + this.V = false; + } + + private void DIVU() // Unsigned multiply + { + int dest_register = (this.m_IR >> 9) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + // On 68000, only allowable size is Word + uint source = (uint)FetchOperandW(src_mode, src_register); + uint dest = (uint)this.m_D[dest_register]; + + this.C = false; + if (source == 0) + { + throw new ArgumentException("Divide by zero..."); + } + + uint quotient = dest / source; + uint remainder = dest % source; + + // Detect overflow + if (quotient < ushort.MinValue || quotient > ushort.MaxValue || + remainder < ushort.MinValue || remainder > ushort.MaxValue) + { + this.V = true; + throw new ArgumentException("Division overflow"); + } + this.m_D[dest_register] = (int)((remainder << 16) | quotient); + + this.m_Cycles += 140 + Helpers.EACalcTimeBW(src_mode, src_register); + + this.N = quotient < 0; + this.Z = quotient == 0; + this.V = false; + } + + private void EXT() // Sign extend + { + this.m_Cycles += 4; + + switch ((this.m_IR >> 6) & 0x7) + { + case 2: // Byte to word + Helpers.Inject(ref this.m_D[this.m_IR & 0x7], (short)((sbyte)this.m_D[this.m_IR & 0x7])); + break; + case 3: // Word to long + this.m_D[this.m_IR & 0x7] = (short)this.m_D[this.m_IR & 0x7]; + break; + } + } + + private void MULS() // Unsigned multiply + { + int dest_register = (this.m_IR >> 9) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + // On 68000, only allowable size is Word + short operand = FetchOperandW(src_mode, src_register); + short currentValue = (short)this.m_D[dest_register]; + + int newValue = operand * currentValue; + this.m_D[dest_register] = newValue; + + this.m_Cycles += 70 + Helpers.EACalcTimeBW(src_mode, src_register); + + this.N = newValue < 0; + this.Z = newValue == 0; + this.V = false; // Can't get an overflow + this.C = false; + } + + private void MULU() // Unsigned multiply + { + int dest_register = (this.m_IR >> 9) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + // On 68000, only allowable size is Word + ushort operand = (ushort)FetchOperandW(src_mode, src_register); + ushort currentValue = (ushort)this.m_D[dest_register]; + + uint newValue = (uint)(operand * currentValue); + this.m_D[dest_register] = (int)newValue; + + this.m_Cycles += 70 + Helpers.EACalcTimeBW(src_mode, src_register); + + this.N = (int)newValue < 0; + this.Z = (newValue == 0); + this.V = false; // Can't get an overflow + this.C = false; + } + + private void NEG() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: + SetOperandB(mode, register, Sub(PeekOperandB(mode, register), (sbyte)0, true, true, false)); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 1: + SetOperandW(mode, register, Sub(PeekOperandW(mode, register), (short)0, true, true, false)); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 2: + SetOperandL(mode, register, Sub(PeekOperandL(mode, register), (int)0, true, true, false)); + this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register); + return; + } + } + + private void NEGX() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: + SetOperandB(mode, register, Sub(PeekOperandB(mode, register), (sbyte)0, true, true, false)); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 1: + SetOperandW(mode, register, Sub(PeekOperandW(mode, register), (short)0, true, true, false)); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + return; + case 2: + SetOperandL(mode, register, Sub(PeekOperandL(mode, register), (int)0, true, true, false)); + this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register); + return; + } + } + + private void SUB_Dest() + { + int src_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: + { + sbyte result = Sub((sbyte)this.m_D[src_register], PeekOperandB(mode, register), true, true, false); + SetOperandB(mode, register, result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, src_register); + return; + } + case 1: + { + short result = Sub((short)this.m_D[src_register], PeekOperandW(mode, register), true, true, false); + SetOperandW(mode, register, result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, src_register); + return; + } + case 2: + { + int result = Sub(this.m_D[src_register], PeekOperandL(mode, register), true, true, false); + SetOperandL(mode, register, result); + this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, src_register); + return; + } + } + } + + private void SUB_Source() + { + int dest_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (size) + { + case 0: + { + sbyte result = Sub(FetchOperandB(src_mode, src_register), (sbyte)this.m_D[dest_register], true, true, false); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 1: + { + short result = Sub(FetchOperandW(src_mode, src_register), (short)this.m_D[dest_register], true, true, false); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 2: + { + int result = Sub(FetchOperandL(src_mode, src_register), this.m_D[dest_register], true, true, false); + this.m_D[dest_register] = (int)result; + this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register); + return; + } + } + } + + private void SUBA() + { + int dest_register = (this.m_IR >> 9) & 0x7; + int opmode = (this.m_IR >> 6) & 0x7; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (opmode) + { + case 3: // W + { + int operand = FetchOperandW(src_mode, src_register); // Sign-extended + this.m_A[dest_register] -= operand; + this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register); + break; + } + case 7: // L + { + int operand = FetchOperandL(src_mode, src_register); + this.m_A[dest_register] -= operand; + this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register); + break; + } + } + } + + private void SUBI() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Sub((sbyte)FetchW(), PeekOperandB(mode, register), true, true, false); + SetOperandB(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 1: // W + { + short result = Sub(FetchW(), PeekOperandW(mode, register), true, true, false); + SetOperandW(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 2: // L + { + int result = Sub(FetchL(), PeekOperandL(mode, register), true, true, false); + SetOperandL(mode, register, result); + this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register); + return; + } + } + } + + private void SUBQ() // Add Quick + { + int data = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // With data, 0 means 8 + data = (data == 0) ? 8 : data; + + switch (size) + { + case 0: // B + { + if (mode == 1) + { + throw new ArgumentException("Byte operation not allowed on address registers"); + } + sbyte result = Sub((sbyte)data, PeekOperandB(mode, register), (mode != 1), true, false); + SetOperandB(mode, register, result); + switch (mode) + { + case 0: this.m_Cycles += 4; break; + case 1: this.m_Cycles += 8; break; + default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break; + } + return; + } + case 1: // W + { + if (mode == 1) + { + int result = Sub(data, PeekOperandL(mode, register), false, true, false); + SetOperandL(mode, register, result); + } + else + { + short result = Sub((short)data, PeekOperandW(mode, register), true, true, false); + SetOperandW(mode, register, result); + } + switch (mode) + { + case 0: this.m_Cycles += 4; break; + case 1: this.m_Cycles += 8; break; + default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break; + } + return; + } + case 2: // L + { + int result = Sub(data, PeekOperandL(mode, register), (mode != 1), true, false); + SetOperandL(mode, register, result); + switch (mode) + { + case 0: this.m_Cycles += 8; break; + case 1: this.m_Cycles += 8; break; + default: this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, register); break; + } + return; + } + } + } + + private void SUBX() + { + int regRx = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int rm = (this.m_IR >> 3) & 0x1; + int regRy = this.m_IR & 0x7; + + switch (size) + { + case 0: + { + if (rm == 0) + { + this.m_D[regRy] = Sub((sbyte)this.m_D[regRx], (sbyte)this.m_D[regRy], true, true, true); + this.m_Cycles += 4; + } + else + { + WriteB(this.m_A[regRy], Sub(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true, true)); + this.m_Cycles += 18; + } + return; + } + case 1: + { + if (rm == 0) + { + this.m_D[regRy] = Sub((short)this.m_D[regRx], (short)this.m_D[regRy], true, true, true); + this.m_Cycles += 4; + } + else + { + WriteW(this.m_A[regRy], Sub(ReadW(this.m_A[regRx]), ReadW(this.m_A[regRy]), true, true, true)); + this.m_Cycles += 18; + } + return; + } + case 2: + { + if (rm == 0) + { + this.m_D[regRy] = Sub(this.m_D[regRx], this.m_D[regRy], true, true, true); + this.m_Cycles += 8; + } + else + { + WriteL(this.m_A[regRy], Sub(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true, true)); + this.m_Cycles += 30; + } + return; + } + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/Logical.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/Logical.cs new file mode 100644 index 0000000000..4a4fb7fb3f --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/Logical.cs @@ -0,0 +1,405 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + #region AND Helpers + private sbyte And(sbyte a, sbyte b) + { + sbyte result = (sbyte)(a & b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + + private short And(short a, short b) + { + short result = (short)(a & b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + + private int And(int a, int b) + { + int result = (int)(a & b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + #endregion AND Helpers + + private void AND_Dest() + { + int src_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int dest_mode = (this.m_IR >> 3) & 0x7; + int dest_register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = And((sbyte)this.m_D[src_register], PeekOperandB(dest_mode, dest_register)); + SetOperandB(dest_mode, dest_register, result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(dest_mode, dest_register); + return; + } + case 1: // W + { + short result = And((short)this.m_D[src_register], PeekOperandW(dest_mode, dest_register)); + SetOperandW(dest_mode, dest_register, result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(dest_mode, dest_register); + return; + } + case 2: // L + { + int result = And(this.m_D[src_register], PeekOperandL(dest_mode, dest_register)); + SetOperandL(dest_mode, dest_register, result); + this.m_Cycles += 6 + Helpers.EACalcTimeL(dest_mode, dest_register); + return; + } + } + } + + private void AND_Source() + { + int dest_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = And((sbyte)this.m_D[dest_register], FetchOperandB(src_mode, src_register)); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 1: // W + { + short result = And((short)this.m_D[dest_register], FetchOperandW(src_mode, src_register)); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 2: // L + { + int result = And(this.m_D[dest_register], FetchOperandL(src_mode, src_register)); + this.m_D[dest_register] = result; + this.m_Cycles += 12 + Helpers.EACalcTimeL(src_mode, src_register); + return; + } + } + } + + private void ANDI() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = And((sbyte)FetchW(), PeekOperandB(mode, register)); + SetOperandB(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 1: // W + { + short result = And(FetchW(), PeekOperandW(mode, register)); + SetOperandW(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 2: // L + { + int result = And(FetchL(), PeekOperandL(mode, register)); + SetOperandL(mode, register, result); + this.m_Cycles += (mode == 0) ? 14 : 20 + Helpers.EACalcTimeL(mode, register); + return; + } + } + } + + #region EOR Helpers + private sbyte Eor(sbyte a, sbyte b) + { + sbyte result = (sbyte)(a ^ b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + + private short Eor(short a, short b) + { + short result = (short)(a ^ b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + + private int Eor(int a, int b) + { + int result = (int)(a ^ b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + #endregion EOR Helpers + + private void EOR() + { + int src_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int dest_mode = (this.m_IR >> 3) & 0x7; + int dest_register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Eor((sbyte)this.m_D[src_register], PeekOperandB(dest_mode, dest_register)); + SetOperandB(dest_mode, dest_register, result); + this.m_Cycles += (dest_mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(dest_mode, dest_register); + return; + } + case 1: // W + { + short result = Eor((short)this.m_D[src_register], PeekOperandW(dest_mode, dest_register)); + SetOperandW(dest_mode, dest_register, result); + this.m_Cycles += (dest_mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(dest_mode, dest_register); + return; + } + case 2: // L + { + int result = Eor(this.m_D[src_register], PeekOperandL(dest_mode, dest_register)); + SetOperandL(dest_mode, dest_register, result); + this.m_Cycles += (dest_mode == 0) ? 8 : 12 + Helpers.EACalcTimeL(dest_mode, dest_register); + return; + } + } + } + + private void EORI() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Eor((sbyte)FetchW(), PeekOperandB(mode, register)); + SetOperandB(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 1: // W + { + short result = Eor(FetchW(), PeekOperandW(mode, register)); + SetOperandW(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 2: // L + { + int result = Eor(FetchL(), PeekOperandL(mode, register)); + SetOperandL(mode, register, result); + this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register); + return; + } + } + } + + #region OR Helpers + private sbyte Or(sbyte a, sbyte b) + { + sbyte result = (sbyte)(a | b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + + private short Or(short a, short b) + { + short result = (short)(a | b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + + private int Or(int a, int b) + { + int result = (int)(a | b); + + this.V = this.C = false; + this.N = result < 0; + this.Z = result == 0; + + return result; + } + #endregion OR Helpers + + private void OR_Dest() + { + int src_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int dest_mode = (this.m_IR >> 3) & 0x7; + int dest_register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Or((sbyte)this.m_D[src_register], PeekOperandB(dest_mode, dest_register)); + SetOperandB(dest_mode, dest_register, result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(dest_mode, dest_register); + return; + } + case 1: // W + { + short result = Or((short)this.m_D[src_register], PeekOperandW(dest_mode, dest_register)); + SetOperandW(dest_mode, dest_register, result); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(dest_mode, dest_register); + return; + } + case 2: // L + { + int result = Or(this.m_D[src_register], PeekOperandL(dest_mode, dest_register)); + SetOperandL(dest_mode, dest_register, result); + this.m_Cycles += 12 + Helpers.EACalcTimeL(dest_mode, dest_register); + return; + } + } + } + + private void OR_Source() + { + int dest_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int src_mode = (this.m_IR >> 3) & 0x7; + int src_register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Or((sbyte)this.m_D[dest_register], FetchOperandB(src_mode, src_register)); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 1: // W + { + short result = Or((short)this.m_D[dest_register], FetchOperandW(src_mode, src_register)); + Helpers.Inject(ref this.m_D[dest_register], result); + this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register); + return; + } + case 2: // L + { + int result = Or(this.m_D[dest_register], FetchOperandL(src_mode, src_register)); + this.m_D[dest_register] = result; + this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register); + return; + } + } + } + + private void ORI() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + switch (size) + { + case 0: // B + { + sbyte result = Or((sbyte)FetchW(), PeekOperandB(mode, register)); + SetOperandB(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 1: // W + { + short result = Or(FetchW(), PeekOperandW(mode, register)); + SetOperandW(mode, register, result); + this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register); + return; + } + case 2: // L + { + int result = Or(FetchL(), PeekOperandL(mode, register)); + SetOperandL(mode, register, result); + this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register); + return; + } + } + } + + private void NOT() + { + int size = (this.m_IR >> 6) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + long result = 0; + this.V = this.C = false; + switch (size) + { + case 0: + result = ~PeekOperandB(mode, register); + SetOperandB(mode, register, (sbyte)result); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + break; + case 1: + result = ~PeekOperandW(mode, register); + SetOperandW(mode, register, (short)result); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + break; + case 2: + result = ~PeekOperandL(mode, register); + SetOperandL(mode, register, (int)result); + this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register); + break; + } + this.N = result < 0; + this.Z = result == 0; + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/Multiprocessor.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/Multiprocessor.cs new file mode 100644 index 0000000000..8a9c5b7513 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/Multiprocessor.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + private void TAS() // Test and set + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + sbyte operand = PeekOperandB(mode, register); + + this.N = (operand < 0); + this.Z = (operand == 0); + this.V = false; + this.C = false; + + this.m_Cycles += (mode == 0) ? 4 : 14 + Helpers.EACalcTimeBW(mode, register); + + // Set the 7th bit + byte uOperand = (byte)operand; + uOperand |= 0x80; + SetOperandB(mode, register, (sbyte)uOperand); + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/ProgramControl.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/ProgramControl.cs new file mode 100644 index 0000000000..13926acda9 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/ProgramControl.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + private void Bcc() // Branch conditionally + { + if ((sbyte)this.m_IR == 0) + { + if (TestCondition((this.m_IR >> 8) & 0xF)) + { + this.m_PC += FetchW(); + this.m_Cycles += 10; + } + else + { + this.m_PC += 2; + this.m_Cycles += 12; + } + } + else + { + if (TestCondition((this.m_IR >> 8) & 0xF)) + { + this.m_PC += (sbyte)this.m_IR; + this.m_Cycles += 10; + } + else + { + this.m_Cycles += 8; + } + } + } + + private void DBcc() // Test condition, decrement, branch + { + if (TestCondition((this.m_IR >> 8) & 0xF)) + { + // Need to move PC on... + this.m_PC += 2; + this.m_Cycles += 12; + } + else + { + short counter = (short)this.m_D[this.m_IR & 0x7]; + Helpers.Inject(ref this.m_D[this.m_IR & 0x7], --counter); + + if (counter == -1) + { + this.m_PC += 2; + this.m_Cycles += 14; + } + else + { + this.m_PC += FetchW(); + this.m_Cycles += 10; + } + } + } + + private void Scc() // Set according to condition + { + int cCode = (this.m_IR >> 8) & 0xF; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + if (TestCondition(cCode)) + { + // Set all the bits + SetOperandB(mode, register, -1); + this.m_Cycles += (mode == 0) ? 6 : 8 + Helpers.EACalcTimeBW(mode, register); + } + else + { + // Clear all the bits + SetOperandB(mode, register, 0); + this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register); + } + } + + private void BRA() // Branch Always + { + this.m_Cycles += 10; + + if ((sbyte)this.m_IR == 0) + { + this.m_PC += PeekW(); + } + else + { + this.m_PC += (sbyte)this.m_IR; + } + } + + private void BSR() // Branch to subroutine + { + this.SP -= 4; + + // 16-bit displacement + if ((sbyte)this.m_IR == 0) + { + WriteL(this.SP, this.m_PC + 2); + this.m_PC += PeekW(); + } + + // 8-bit displacement + else + { + WriteL(this.SP, this.m_PC); + this.m_PC += (sbyte)this.m_IR; + } + + this.m_Cycles += 18; + } + + private void JMP() // Jump + { + this.m_PC = FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + + switch ((this.m_IR >> 3) & 0x7) + { + case 0x2: this.m_Cycles += 8; break; + case 0x5: this.m_Cycles += 10; break; + case 0x6: this.m_Cycles += 14; break; + case 0x7: + switch (this.m_IR & 0x7) + { + case 0x0: this.m_Cycles += 10; break; + case 0x1: this.m_Cycles += 12; break; + case 0x2: this.m_Cycles += 10; break; + case 0x3: this.m_Cycles += 14; break; + } + break; + } + } + + private void JSR() // Jump to subroutine + { + int address = FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7) & 0x00FFFFFF; + this.SP -= 4; + WriteL(this.SP, this.m_PC); + this.m_PC = address; + + switch ((this.m_IR >> 3) & 0x7) + { + case 0x2: this.m_Cycles += 16; break; + case 0x5: this.m_Cycles += 18; break; + case 0x6: this.m_Cycles += 22; break; + case 0x7: + switch (this.m_IR & 0x7) + { + case 0x0: this.m_Cycles += 18; break; + case 0x1: this.m_Cycles += 20; break; + case 0x2: this.m_Cycles += 18; break; + case 0x3: this.m_Cycles += 22; break; + } + break; + } + } + + private void NOP() // No operation + { + // Doesn't do anything, it's there to help flush the integer pipeline + this.m_Cycles += 4; + } + + private void RTS() // Return from Subroutine + { + this.m_PC = ReadL(this.SP); + this.SP += 4; + this.m_Cycles += 16; + } + + private void TST() // Test an operand + { + // Use an integer operand, it gets sign-extended and we can check it afterwards + int operand = 0; + switch ((this.m_IR >> 6) & 0x3) + { + case 0: // B + { + operand = FetchOperandB((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + this.m_Cycles += 4 + Helpers.EACalcTimeBW((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + break; + } + case 1: // W + { + operand = FetchOperandW((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + this.m_Cycles += 4 + Helpers.EACalcTimeBW((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + break; + } + case 2: // L + { + operand = FetchOperandL((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + this.m_Cycles += 4 + Helpers.EACalcTimeL((this.m_IR >> 3) & 0x7, this.m_IR & 0x7); + break; + } + } + + this.V = this.C = false; + this.N = (operand < 0); + this.Z = (operand == 0); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/ShiftRotate.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/ShiftRotate.cs new file mode 100644 index 0000000000..919db8b940 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/ShiftRotate.cs @@ -0,0 +1,622 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + #region Arithmetic Shift + private void ASL() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.C = this.V = false; + + switch (size) + { + case 0: + { + sbyte value = (sbyte)this.m_D[register]; + bool msbit = value < 0; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = value < 0; + value <<= 1; + this.V |= ((value < 0) != msbit); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = value < 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + short value = (short)this.m_D[register]; + bool msbit = value < 0; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = value < 0; + value <<= 1; + this.V |= ((value < 0) != msbit); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = value < 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + int value = this.m_D[register]; + bool msbit = value < 0; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = value < 0; + value <<= 1; + this.V |= ((value < 0) != msbit); + } + this.m_D[register] = value; + this.N = value < 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void ASR() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.C = this.V = false; + + switch (size) + { + case 0: + { + sbyte value = (sbyte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = value < 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + short value = (short)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = value < 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + int value = this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + this.m_D[register] = value; + this.N = value < 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void ASL_ASR_Memory() + { + int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + short value = PeekOperandW(mode, register); + if (direction == 0) + { + this.C = this.X = (value & 1) > 0; + this.V = false; // For right shift, MSB can't change + value >>= 1; + } + else + { + bool msbit = (value < 0); + this.C = this.X = value < 0; + value <<= 1; + this.V |= ((value < 0) != msbit); + } + this.N = value < 0; + this.Z = value == 0; + SetOperandW(mode, register, value); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); + } + #endregion Arithmetic Shift + + #region Logical Shift + private void LSL() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.C = this.V = false; + + switch (size) + { + case 0: + { + byte value = (byte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 0x80) > 0; + value <<= 1; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x80) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + ushort value = (ushort)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 0x8000) > 0; + value <<= 1; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + uint value = (uint)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 0x80000000) > 0; + value <<= 1; + } + this.m_D[register] = (int)value; + this.N = (value & 0x80000000) > 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void LSR() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.C = this.V = false; + + switch (size) + { + case 0: + { + byte value = (byte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x80) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + ushort value = (ushort)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + uint value = (uint)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + this.m_D[register] = (int)value; + this.N = (value & 0x80000000) > 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void LSL_LSR_Memory() + { + int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + ushort value = (ushort)PeekOperandW(mode, register); + if (direction == 0) + { + this.C = this.X = (value & 1) > 0; + value >>= 1; + } + else + { + this.C = this.X = (value & 0x8000) > 0; + value <<= 1; + } + this.V = false; + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + SetOperandW(mode, register, (short)value); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); + } + #endregion Logical Shift + + #region Rotate (without extend) + private void ROL() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.C = this.V = false; + + switch (size) + { + case 0: + { + byte value = (byte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 0x80) > 0; + value = (byte)((value >> 7) | (value << 1)); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x80) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + ushort value = (ushort)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 0x8000) > 0; + value = (ushort)((value >> 15) | (value << 1)); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + uint value = (uint)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 0x80000000) > 0; + value = (uint)((value >> 31) | (value << 1)); + } + this.m_D[register] = (int)value; + this.N = (value & 0x80000000) > 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void ROR() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.C = this.V = false; + + switch (size) + { + case 0: + { + byte value = (byte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 1) > 0; + value = (byte)((value << 7) | (value >> 1)); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x80) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + ushort value = (ushort)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 1) > 0; + value = (ushort)((value << 15) | (value >> 1)); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + uint value = (uint)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 1) > 0; + value = (uint)((value << 31) | (value >> 1)); + } + this.m_D[register] = (int)value; + this.N = (value & 0x80000000) > 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void ROL_ROR_Memory() + { + int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + ushort value = (ushort)PeekOperandW(mode, register); + if (direction == 0) + { + this.C = (value & 1) > 0; + value = (ushort)((value >> 1) | (value << 15)); + } + else + { + this.C = (value & 0x8000) > 0; + value = (ushort)((value >> 15) | (value << 1)); + } + this.V = false; + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + SetOperandW(mode, register, (short)value); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); + } + #endregion Rotate (without extend) + + #region Rotate (with extend) + private void ROXL() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.V = false; + this.C = this.X; + + switch (size) + { + case 0: + { + byte value = (byte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 0x80) > 0; + value = (byte)((value << 1) | ((this.X) ? 1: 0)); + this.X = this.C; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x80) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + ushort value = (ushort)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 0x8000) > 0; + value = (ushort)((value << 1) | ((this.X) ? 1 : 0)); + this.X = this.C; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + uint value = (uint)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 0x80000000) > 0; + value = (uint)((value << 1) | ((this.X) ? (uint)1 : (uint)0)); + this.X = this.C; + } + this.m_D[register] = (int)value; + this.N = (value & 0x80000000) > 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void ROXR() + { + int count_register = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 6) & 0x3; + int ir = (this.m_IR >> 5) & 0x1; + int register = this.m_IR & 0x7; + + int shift_count = (ir == 0) ? + ((count_register == 0) ? 8 : count_register) : + (this.m_D[count_register] % 64); + + this.V = false; + this.C = this.X; + + switch (size) + { + case 0: + { + byte value = (byte)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 1) > 0; + value = (byte)(((this.X) ? 0x80 : 0) | (value >> 1)); + this.X = this.C; + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x80) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 1: + { + ushort value = (ushort)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 1) > 0; + value = (ushort)(((this.X) ? 0x8000 : 0) | (value >> 1)); + } + Helpers.Inject(ref this.m_D[register], value); + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + this.m_Cycles += 6 + 2 * shift_count; + return; + } + case 2: + { + uint value = (uint)this.m_D[register]; + for (int i = 0; i < shift_count; i++) + { + this.C = (value & 1) > 0; + value = (uint)(((this.X) ? 0x80000000 : 0) | (value >> 1)); + } + this.m_D[register] = (int)value; + this.N = (value & 0x80000000) > 0; + this.Z = value == 0; + this.m_Cycles += 8 + 2 * shift_count; + return; + } + } + } + + private void ROXL_ROXR_Memory() + { + int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + ushort value = (ushort)PeekOperandW(mode, register); + if (direction == 0) + { + this.C = (value & 1) > 0; + value = (ushort)(((this.X) ? 0x8000 : 0) | (value >> 1)); + this.X = this.C; + } + else + { + this.C = (value & 0x8000) > 0; + value = (ushort)((value << 1) | ((this.X) ? 1 : 0)); + this.X = this.C; + } + this.V = false; + this.N = (value & 0x8000) > 0; + this.Z = value == 0; + SetOperandW(mode, register, (short)value); + this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); + } + #endregion Rotate (with extend) + + private void SWAP() // Swap halves of a register + { + int register = this.m_IR & 0x7; + this.m_D[register] = (int)(((uint)this.m_D[register] << 16) | + ((uint)this.m_D[register] >> 16)); + + this.N = (this.m_D[register] < 0); + this.Z = (this.m_D[register] == 0); + this.V = this.C = false; + + this.m_Cycles += 4; + } + } +} diff --git a/BizHawk.Emulation/CPUs/MC68000/Operations/SystemControl.cs b/BizHawk.Emulation/CPUs/MC68000/Operations/SystemControl.cs new file mode 100644 index 0000000000..006a82ad2e --- /dev/null +++ b/BizHawk.Emulation/CPUs/MC68000/Operations/SystemControl.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MC68000 +{ + public partial class MC68K + { + private void ANDI_to_CCR() + { + Helpers.Inject(ref this.m_SR, (byte)(this.m_SR & FetchW())); + this.m_Cycles += 20; + } + + private void ANDI_to_SR() + { + if (this.S) + { + this.m_SR &= FetchW(); + + // Might not be in supervisor mode any more... + if (!this.S) + { + this.m_Ssp = this.SP; + this.SP = this.m_Usp; + } + + this.m_Cycles += 20; + } + else + { + // TODO - cycle counter + Trap(8); + } + } + + private void CHK() + { + int registerToCheck = (this.m_IR >> 9) & 0x7; + int size = (this.m_IR >> 7) & 0x3; + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + // Only word size is legal on the 68000 + + if ((short)this.m_D[registerToCheck] < 0) + { + this.N = true; + Trap(6); + } + else if ((short)this.m_D[registerToCheck] > FetchOperandW(mode, size)) + { + this.N = false; + Trap(6); + } + else + { + this.m_Cycles += 10 + Helpers.EACalcTimeBW(mode, register); + } + } + + private void EORI_to_CCR() + { + Helpers.Inject(ref this.m_SR, (byte)(this.m_SR ^ FetchW())); + this.m_Cycles += 20; + } + + private void EORI_to_SR() + { + if (this.S) + { + this.m_SR ^= FetchW(); + + // Might not be in supervisor mode any more... + if (!this.S) + { + this.m_Ssp = this.SP; + this.SP = this.m_Usp; + } + + this.m_Cycles += 20; + } + else + { + // TODO - cycle counter + Trap(8); + } + } + + private void ILLEGAL() + { + Trap(4); + } + + private void MOVE_from_SR() + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + SetOperandW(mode, register, (short)this.m_SR); + this.m_Cycles += (mode == 0) ? 6 : 8 + Helpers.EACalcTimeBW(mode, register); + } + + private void MOVE_to_CCR() + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + this.m_SR &= 0xFF00; + this.m_SR |= (ushort)(FetchOperandW(mode, register) & 0x00FF); + this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register); + } + + private void MOVE_to_SR() // Move to the Status Register + { + int mode = (this.m_IR >> 3) & 0x7; + int register = this.m_IR & 0x7; + + if (this.S) + { + this.m_SR = (ushort)FetchOperandW(mode, register); + this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register); + + // Might not be in supervisor mode now... + if (!this.S) + { + this.m_Ssp = this.SP; + this.SP = this.m_Usp; + } + } + else + { + Trap(8); + } + } + + private void MOVE_USP() // Move User Stack Pointer + { + if (this.S) + { + if (((this.m_IR >> 3) & 0x1) == 0) + { + this.m_Usp = this.m_A[this.m_IR & 0x7]; + } + else + { + this.m_A[this.m_IR & 0x7] = this.m_Usp; + } + + this.m_Cycles += 4; + } + else + { + // TODO Cycles + Trap(8); + } + } + + private void ORI_to_CCR() + { + Helpers.Inject(ref this.m_SR, (byte)(this.m_SR | (ushort)FetchW())); + this.m_Cycles += 20; + } + + private void ORI_to_SR() + { + if (this.S) + { + this.m_SR |= (ushort)FetchW(); + + // Might not be in supervisor mode any more... + if (!this.S) + { + this.m_Ssp = this.SP; + this.SP = this.m_Usp; + } + + this.m_Cycles += 20; + } + else + { + // TODO - TRAP, cycle counter + throw new NotImplementedException(); + } + } + + private void RESET() + { + this.m_Cycles += 132; + throw new NotImplementedException(); + } + + private void RTE() + { + if (this.S) + { + this.m_SR = (ushort)ReadW(this.SP); + this.SP += 2; + this.m_PC = ReadL(this.SP); + this.SP += 4; + + // Might not be in supervisor mode any more... + if (!this.S) + { + this.m_Ssp = this.SP; + this.SP = this.m_Usp; + } + + this.m_Cycles += 20; + } + else + { + // Privilege exception + Trap(8); + } + } + + private void RTR() + { + // Seems a bit like RTE, but only affects condition codes + this.m_SR = (ushort)((0x00FF & ReadW(this.m_Ssp)) | (0xFF00 & this.m_SR)); + this.SP += 2; + this.m_PC = ReadL(this.SP); + this.SP += 4; + this.m_Cycles += 20; + } + + private void STOP() + { + this.m_Cycles += 4; + throw new NotImplementedException(); + } + + private void Trap(int trapVector) + { + // Make sure we're in supervisor mode + if (!this.S) + { + this.m_Usp = this.SP; + this.SP = this.m_Ssp; + } + + // Add stack frame + this.SP -= 4; + WriteL(this.SP, this.m_PC); + this.SP -= 2; + WriteW(this.SP, (short)this.m_SR); + + // Enter supervisor mode + this.S = true; + + // Get vector address from ROM header + this.m_PC = ReadL(trapVector * 4); + } + + private void TRAP() + { + int trapVector = (this.m_IR & 0x000F); + Trap(trapVector + 32); + } + + private void TRAPV() + { + this.m_Cycles += 4; + if (this.V) + { + Trap(7); + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs b/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs new file mode 100644 index 0000000000..f65f1bcdf5 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs @@ -0,0 +1,171 @@ +using System; + +// Do not modify this file directly! This is GENERATED code. +// Please open the CpuCoreGenerator solution and make your modifications there. + +namespace BizHawk.Emulation.CPUs.M6502 +{ + public partial class MOS6502 + { + public string Disassemble(ushort pc, out int bytesToAdvance) + { + byte op = ReadMemory(pc); + switch (op) + { + case 0x00: bytesToAdvance = 1; return "BRK"; + case 0x01: bytesToAdvance = 2; return string.Format("ORA (${0:X2},X)", ReadMemory(++pc)); + case 0x05: bytesToAdvance = 2; return string.Format("ORA ${0:X2}", ReadMemory(++pc)); + case 0x06: bytesToAdvance = 2; return string.Format("ASL ${0:X2}", ReadMemory(++pc)); + case 0x08: bytesToAdvance = 1; return "PHP"; + case 0x09: bytesToAdvance = 2; return string.Format("ORA #${0:X2}", ReadMemory(++pc)); + case 0x0A: bytesToAdvance = 1; return "ASL A"; + case 0x0D: bytesToAdvance = 3; return string.Format("ORA ${0:X4}", ReadWord(++pc)); + case 0x0E: bytesToAdvance = 3; return string.Format("ASL ${0:X4}", ReadWord(++pc)); + case 0x10: bytesToAdvance = 2; return string.Format("BPL {0}", (sbyte)ReadMemory(++pc)); + case 0x11: bytesToAdvance = 2; return string.Format("ORA (${0:X2}),Y", ReadMemory(++pc)); + case 0x15: bytesToAdvance = 2; return string.Format("ORA ${0:X2},X", ReadMemory(++pc)); + case 0x16: bytesToAdvance = 2; return string.Format("ASL ${0:X2},X", ReadMemory(++pc)); + case 0x18: bytesToAdvance = 1; return "CLC"; + case 0x19: bytesToAdvance = 3; return string.Format("ORA ${0:X4},Y", ReadWord(++pc)); + case 0x1D: bytesToAdvance = 3; return string.Format("ORA ${0:X4},X", ReadWord(++pc)); + case 0x1E: bytesToAdvance = 3; return string.Format("ASL ${0:X4},X", ReadWord(++pc)); + case 0x20: bytesToAdvance = 3; return string.Format("JSR ${0:X4}", ReadWord(++pc)); + case 0x21: bytesToAdvance = 2; return string.Format("AND (${0:X2},X)", ReadMemory(++pc)); + case 0x24: bytesToAdvance = 2; return string.Format("BIT ${0:X2}", ReadMemory(++pc)); + case 0x25: bytesToAdvance = 2; return string.Format("AND ${0:X2}", ReadMemory(++pc)); + case 0x26: bytesToAdvance = 2; return string.Format("ROL ${0:X2}", ReadMemory(++pc)); + case 0x28: bytesToAdvance = 1; return "PLP"; + case 0x29: bytesToAdvance = 2; return string.Format("AND #${0:X2}", ReadMemory(++pc)); + case 0x2A: bytesToAdvance = 1; return "ROL A"; + case 0x2C: bytesToAdvance = 3; return string.Format("BIT ${0:X4}", ReadWord(++pc)); + case 0x2D: bytesToAdvance = 3; return string.Format("AND ${0:X4}", ReadWord(++pc)); + case 0x2E: bytesToAdvance = 3; return string.Format("ROL ${0:X4}", ReadWord(++pc)); + case 0x30: bytesToAdvance = 2; return string.Format("BMI {0}", (sbyte)ReadMemory(++pc)); + case 0x31: bytesToAdvance = 2; return string.Format("AND (${0:X2}),Y", ReadMemory(++pc)); + case 0x35: bytesToAdvance = 2; return string.Format("AND ${0:X2},X", ReadMemory(++pc)); + case 0x36: bytesToAdvance = 2; return string.Format("ROL ${0:X2},X", ReadMemory(++pc)); + case 0x38: bytesToAdvance = 1; return "SEC"; + case 0x39: bytesToAdvance = 3; return string.Format("AND ${0:X4},Y", ReadWord(++pc)); + case 0x3D: bytesToAdvance = 3; return string.Format("AND ${0:X4},X", ReadWord(++pc)); + case 0x3E: bytesToAdvance = 3; return string.Format("ROL ${0:X4},X", ReadWord(++pc)); + case 0x40: bytesToAdvance = 1; return "RTI"; + case 0x41: bytesToAdvance = 2; return string.Format("EOR (${0:X2},X)", ReadMemory(++pc)); + case 0x45: bytesToAdvance = 2; return string.Format("EOR ${0:X2}", ReadMemory(++pc)); + case 0x46: bytesToAdvance = 2; return string.Format("LSR ${0:X2}", ReadMemory(++pc)); + case 0x48: bytesToAdvance = 1; return "PHA"; + case 0x49: bytesToAdvance = 2; return string.Format("EOR #${0:X2}", ReadMemory(++pc)); + case 0x4A: bytesToAdvance = 1; return "LSR A"; + case 0x4C: bytesToAdvance = 3; return string.Format("JMP ${0:X4}", ReadWord(++pc)); + case 0x4D: bytesToAdvance = 3; return string.Format("EOR ${0:X4}", ReadWord(++pc)); + case 0x4E: bytesToAdvance = 3; return string.Format("LSR ${0:X4}", ReadWord(++pc)); + case 0x50: bytesToAdvance = 2; return string.Format("BVC {0}", (sbyte)ReadMemory(++pc)); + case 0x51: bytesToAdvance = 2; return string.Format("EOR (${0:X2}),Y", ReadMemory(++pc)); + case 0x55: bytesToAdvance = 2; return string.Format("EOR ${0:X2},X", ReadMemory(++pc)); + case 0x56: bytesToAdvance = 2; return string.Format("LSR ${0:X2},X", ReadMemory(++pc)); + case 0x58: bytesToAdvance = 1; return "CLI"; + case 0x59: bytesToAdvance = 3; return string.Format("EOR ${0:X4},Y", ReadWord(++pc)); + case 0x5D: bytesToAdvance = 3; return string.Format("EOR ${0:X4},X", ReadWord(++pc)); + case 0x5E: bytesToAdvance = 3; return string.Format("LSR ${0:X4},X", ReadWord(++pc)); + case 0x60: bytesToAdvance = 1; return "RTS"; + case 0x61: bytesToAdvance = 2; return string.Format("ADC (${0:X2},X)", ReadMemory(++pc)); + case 0x65: bytesToAdvance = 2; return string.Format("ADC ${0:X2}", ReadMemory(++pc)); + case 0x66: bytesToAdvance = 2; return string.Format("ROR ${0:X2}", ReadMemory(++pc)); + case 0x68: bytesToAdvance = 1; return "PLA"; + case 0x69: bytesToAdvance = 2; return string.Format("ADC #${0:X2}", ReadMemory(++pc)); + case 0x6A: bytesToAdvance = 1; return "ROR A"; + case 0x6C: bytesToAdvance = 3; return string.Format("JMP (${0:X4})", ReadWord(++pc)); + case 0x6D: bytesToAdvance = 3; return string.Format("ADC ${0:X4}", ReadWord(++pc)); + case 0x6E: bytesToAdvance = 3; return string.Format("ROR ${0:X4}", ReadWord(++pc)); + case 0x70: bytesToAdvance = 2; return string.Format("BVS {0}", (sbyte)ReadMemory(++pc)); + case 0x71: bytesToAdvance = 2; return string.Format("ADC (${0:X2}),Y", ReadMemory(++pc)); + case 0x75: bytesToAdvance = 2; return string.Format("ADC ${0:X2},X", ReadMemory(++pc)); + case 0x76: bytesToAdvance = 2; return string.Format("ROR ${0:X2},X", ReadMemory(++pc)); + case 0x78: bytesToAdvance = 1; return "SEI"; + case 0x79: bytesToAdvance = 3; return string.Format("ADC ${0:X4},Y", ReadWord(++pc)); + case 0x7D: bytesToAdvance = 3; return string.Format("ADC ${0:X4},X", ReadWord(++pc)); + case 0x7E: bytesToAdvance = 3; return string.Format("ROR ${0:X4},X", ReadWord(++pc)); + case 0x81: bytesToAdvance = 2; return string.Format("STA (${0:X2},X)", ReadMemory(++pc)); + case 0x84: bytesToAdvance = 2; return string.Format("STY ${0:X2}", ReadMemory(++pc)); + case 0x85: bytesToAdvance = 2; return string.Format("STA ${0:X2}", ReadMemory(++pc)); + case 0x86: bytesToAdvance = 2; return string.Format("STX ${0:X2}", ReadMemory(++pc)); + case 0x88: bytesToAdvance = 1; return "DEY"; + case 0x8A: bytesToAdvance = 1; return "TXA"; + case 0x8C: bytesToAdvance = 3; return string.Format("STY ${0:X4}", ReadWord(++pc)); + case 0x8D: bytesToAdvance = 3; return string.Format("STA ${0:X4}", ReadWord(++pc)); + case 0x8E: bytesToAdvance = 3; return string.Format("STX ${0:X4}", ReadWord(++pc)); + case 0x90: bytesToAdvance = 2; return string.Format("BCC {0}", (sbyte)ReadMemory(++pc)); + case 0x91: bytesToAdvance = 2; return string.Format("STA (${0:X2}),Y", ReadMemory(++pc)); + case 0x94: bytesToAdvance = 2; return string.Format("STY ${0:X2},X", ReadMemory(++pc)); + case 0x95: bytesToAdvance = 2; return string.Format("STA ${0:X2},X", ReadMemory(++pc)); + case 0x96: bytesToAdvance = 2; return string.Format("STX ${0:X2},Y", ReadMemory(++pc)); + case 0x98: bytesToAdvance = 1; return "TYA"; + case 0x99: bytesToAdvance = 3; return string.Format("STA ${0:X4},Y", ReadWord(++pc)); + case 0x9A: bytesToAdvance = 1; return "TXS"; + case 0x9D: bytesToAdvance = 3; return string.Format("STA ${0:X4},X", ReadWord(++pc)); + case 0xA0: bytesToAdvance = 2; return string.Format("LDY #${0:X2}", ReadMemory(++pc)); + case 0xA1: bytesToAdvance = 2; return string.Format("LDA (${0:X2},X)", ReadMemory(++pc)); + case 0xA2: bytesToAdvance = 2; return string.Format("LDX #${0:X2}", ReadMemory(++pc)); + case 0xA4: bytesToAdvance = 2; return string.Format("LDY ${0:X2}", ReadMemory(++pc)); + case 0xA5: bytesToAdvance = 2; return string.Format("LDA ${0:X2}", ReadMemory(++pc)); + case 0xA6: bytesToAdvance = 2; return string.Format("LDX ${0:X2}", ReadMemory(++pc)); + case 0xA8: bytesToAdvance = 1; return "TAY"; + case 0xA9: bytesToAdvance = 2; return string.Format("LDA #${0:X2}", ReadMemory(++pc)); + case 0xAA: bytesToAdvance = 1; return "TAX"; + case 0xAC: bytesToAdvance = 3; return string.Format("LDY ${0:X4}", ReadWord(++pc)); + case 0xAD: bytesToAdvance = 3; return string.Format("LDA ${0:X4}", ReadWord(++pc)); + case 0xAE: bytesToAdvance = 3; return string.Format("LDX ${0:X4}", ReadWord(++pc)); + case 0xB0: bytesToAdvance = 2; return string.Format("BCS {0}", (sbyte)ReadMemory(++pc)); + case 0xB1: bytesToAdvance = 2; return string.Format("LDA (${0:X2}),Y", ReadMemory(++pc)); + case 0xB4: bytesToAdvance = 2; return string.Format("LDY ${0:X2},X", ReadMemory(++pc)); + case 0xB5: bytesToAdvance = 2; return string.Format("LDA ${0:X2},X", ReadMemory(++pc)); + case 0xB6: bytesToAdvance = 2; return string.Format("LDX ${0:X2},Y", ReadMemory(++pc)); + case 0xB8: bytesToAdvance = 1; return "CLV"; + case 0xB9: bytesToAdvance = 3; return string.Format("LDA ${0:X4},Y", ReadWord(++pc)); + case 0xBA: bytesToAdvance = 1; return "TSX"; + case 0xBC: bytesToAdvance = 3; return string.Format("LDY ${0:X4},X", ReadWord(++pc)); + case 0xBD: bytesToAdvance = 3; return string.Format("LDA ${0:X4},X", ReadWord(++pc)); + case 0xBE: bytesToAdvance = 3; return string.Format("LDX ${0:X4},Y", ReadWord(++pc)); + case 0xC0: bytesToAdvance = 2; return string.Format("CPY #${0:X2}", ReadMemory(++pc)); + case 0xC1: bytesToAdvance = 2; return string.Format("CMP (${0:X2},X)", ReadMemory(++pc)); + case 0xC4: bytesToAdvance = 2; return string.Format("CPY ${0:X2}", ReadMemory(++pc)); + case 0xC5: bytesToAdvance = 2; return string.Format("CMP ${0:X2}", ReadMemory(++pc)); + case 0xC6: bytesToAdvance = 2; return string.Format("DEC ${0:X2}", ReadMemory(++pc)); + case 0xC8: bytesToAdvance = 1; return "INY"; + case 0xC9: bytesToAdvance = 2; return string.Format("CMP #${0:X2}", ReadMemory(++pc)); + case 0xCA: bytesToAdvance = 1; return "DEX"; + case 0xCC: bytesToAdvance = 3; return string.Format("CPY ${0:X4}", ReadWord(++pc)); + case 0xCD: bytesToAdvance = 3; return string.Format("CMP ${0:X4}", ReadWord(++pc)); + case 0xCE: bytesToAdvance = 3; return string.Format("DEC ${0:X4}", ReadWord(++pc)); + case 0xD0: bytesToAdvance = 2; return string.Format("BNE {0}", (sbyte)ReadMemory(++pc)); + case 0xD1: bytesToAdvance = 2; return string.Format("CMP (${0:X2}),Y", ReadMemory(++pc)); + case 0xD5: bytesToAdvance = 2; return string.Format("CMP ${0:X2},X", ReadMemory(++pc)); + case 0xD6: bytesToAdvance = 2; return string.Format("DEC ${0:X2},X", ReadMemory(++pc)); + case 0xD8: bytesToAdvance = 1; return "CLD"; + case 0xD9: bytesToAdvance = 3; return string.Format("CMP ${0:X4},Y", ReadWord(++pc)); + case 0xDD: bytesToAdvance = 3; return string.Format("CMP ${0:X4},X", ReadWord(++pc)); + case 0xDE: bytesToAdvance = 3; return string.Format("DEC ${0:X4},X", ReadWord(++pc)); + case 0xE0: bytesToAdvance = 2; return string.Format("CPX #${0:X2}", ReadMemory(++pc)); + case 0xE1: bytesToAdvance = 2; return string.Format("SBC (${0:X2},X)", ReadMemory(++pc)); + case 0xE4: bytesToAdvance = 2; return string.Format("CPX ${0:X2}", ReadMemory(++pc)); + case 0xE5: bytesToAdvance = 2; return string.Format("SBC ${0:X2}", ReadMemory(++pc)); + case 0xE6: bytesToAdvance = 2; return string.Format("INC ${0:X2}", ReadMemory(++pc)); + case 0xE8: bytesToAdvance = 1; return "INX"; + case 0xE9: bytesToAdvance = 2; return string.Format("SBC #${0:X2}", ReadMemory(++pc)); + case 0xEA: bytesToAdvance = 1; return "NOP"; + case 0xEC: bytesToAdvance = 3; return string.Format("CPX ${0:X4}", ReadWord(++pc)); + case 0xED: bytesToAdvance = 3; return string.Format("SBC ${0:X4}", ReadWord(++pc)); + case 0xEE: bytesToAdvance = 3; return string.Format("INC ${0:X4}", ReadWord(++pc)); + case 0xF0: bytesToAdvance = 2; return string.Format("BEQ {0}", (sbyte)ReadMemory(++pc)); + case 0xF1: bytesToAdvance = 2; return string.Format("SBC (${0:X2}),Y", ReadMemory(++pc)); + case 0xF5: bytesToAdvance = 2; return string.Format("SBC ${0:X2},X", ReadMemory(++pc)); + case 0xF6: bytesToAdvance = 2; return string.Format("INC ${0:X2},X", ReadMemory(++pc)); + case 0xF8: bytesToAdvance = 1; return "SED"; + case 0xF9: bytesToAdvance = 3; return string.Format("SBC ${0:X4},Y", ReadWord(++pc)); + case 0xFD: bytesToAdvance = 3; return string.Format("SBC ${0:X4},X", ReadWord(++pc)); + case 0xFE: bytesToAdvance = 3; return string.Format("INC ${0:X4},X", ReadWord(++pc)); + } + bytesToAdvance = 1; + return "???"; + } + } +} diff --git a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs new file mode 100644 index 0000000000..851d7ce3e4 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs @@ -0,0 +1,1120 @@ +using System; + +// Do not modify this file directly! This is GENERATED code. +// Please open the CpuCoreGenerator solution and make your modifications there. + +namespace BizHawk.Emulation.CPUs.M6502 +{ + public partial class MOS6502 + { + public void Execute(int cycles) + { + sbyte rel8; + byte value8, temp8; + ushort value16, temp16; + int temp; + + PendingCycles += cycles; + while (PendingCycles > 0) + { +Console.WriteLine(State()); + byte opcode = ReadMemory(PC++); + switch (opcode) + { + case 0x00: // BRK +throw new Exception("break"); + break; + case 0x01: // ORA (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x05: // ORA zp + value8 = ReadMemory(ReadMemory(PC++)); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x06: // ASL zp + value16 = ReadMemory(PC++); + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x08: // PHP + WriteMemory((ushort)(S-- + 0x100), P); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x09: // ORA #nn + value8 = ReadMemory(PC++); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x0A: // ASL A + FlagC = (A & 0x80) != 0; + A = (byte) (A << 1); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x0D: // ORA addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x0E: // ASL addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x10: // BPL +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagN == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x11: // ORA (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x15: // ORA zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x16: // ASL zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x18: // CLC + FlagC = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x19: // ORA addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x1D: // ORA addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A |= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x1E: // ASL addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 0x80) != 0; + value8 = (byte)(value8 << 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x20: // JSR addr + temp16 = (ushort)(PC+1); + WriteMemory((ushort)(S-- + 0x100), (byte)(temp16 >> 8)); + WriteMemory((ushort)(S-- + 0x100), (byte)temp16); + PC = ReadWord(PC); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x21: // AND (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x24: // BIT zp + value8 = ReadMemory(ReadMemory(PC++)); + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x25: // AND zp + value8 = ReadMemory(ReadMemory(PC++)); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x26: // ROL zp + value16 = ReadMemory(PC++); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x28: // PLP + P = ReadMemory((ushort)(++S + 0x100)); +FlagT = true;//this seems wrong + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x29: // AND #nn + value8 = ReadMemory(PC++); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x2A: // ROL A + temp8 = A; + A = (byte)((A << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x2C: // BIT addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + FlagN = (value8 & 0x80) != 0; + FlagV = (value8 & 0x40) != 0; + FlagZ = (A & value8) == 0; + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x2D: // AND addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x2E: // ROL addr + value16 = ReadWord(PC); PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x30: // BMI +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagN == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x31: // AND (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x35: // AND zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x36: // ROL zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x38: // SEC + FlagC = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x39: // AND addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x3D: // AND addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A &= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x3E: // ROL addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 << 1) | (P & 1)); + WriteMemory(value16, value8); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x40: // RTI + P = ReadMemory((ushort)(++S + 0x100)); +FlagT = true;// this seems wrong + PC = ReadMemory((ushort)(++S + 0x100)); + PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x41: // EOR (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x45: // EOR zp + value8 = ReadMemory(ReadMemory(PC++)); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x46: // LSR zp + value16 = ReadMemory(PC++); + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x48: // PHA + WriteMemory((ushort)(S-- + 0x100), A); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x49: // EOR #nn + value8 = ReadMemory(PC++); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x4A: // LSR A + FlagC = (A & 1) != 0; + A = (byte) (A >> 1); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x4C: // JMP addr + PC = ReadWord(PC); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x4D: // EOR addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x4E: // LSR addr + value16 = ReadWord(PC); PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x50: // BVC +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagV == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x51: // EOR (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x55: // EOR zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x56: // LSR zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x58: // CLI + FlagI = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x59: // EOR addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x5D: // EOR addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + A ^= value8; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x5E: // LSR addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value8 = ReadMemory(value16); + FlagC = (value8 & 1) != 0; + value8 = (byte)(value8 >> 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x60: // RTS + PC = ReadMemory((ushort)(++S + 0x100)); + PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8); + PC++; + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x61: // ADC (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x65: // ADC zp + value8 = ReadMemory(ReadMemory(PC++)); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x66: // ROR zp + value16 = ReadMemory(PC++); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x68: // PLA + A = ReadMemory((ushort)(++S + 0x100)); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x69: // ADC #nn + value8 = ReadMemory(PC++); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x6A: // ROR A + temp8 = A; + A = (byte)((A >> 1) | ((P & 1)<<7)); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x6C: // JMP (addr) + PC = ReadWordPageWrap(ReadWord(PC)); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x6D: // ADC addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x6E: // ROR addr + value16 = ReadWord(PC); PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x70: // BVS +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagV == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x71: // ADC (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x75: // ADC zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x76: // ROR zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x78: // SEI + FlagI = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x79: // ADC addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x7D: // ADC addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp > 0xFF; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x7E: // ROR addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value8 = temp8 = ReadMemory(value16); + value8 = (byte)((value8 >> 1) | ((P & 1)<<7)); + WriteMemory(value16, value8); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0x81: // STA (addr,X) + value16 = ReadWordPageWrap((byte)(ReadMemory(PC++)+X)); + WriteMemory(value16, A); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x84: // STY zp + value16 = ReadMemory(PC++); + WriteMemory(value16, Y); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x85: // STA zp + value16 = ReadMemory(PC++); + WriteMemory(value16, A); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x86: // STX zp + value16 = ReadMemory(PC++); + WriteMemory(value16, X); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0x88: // DEY + P = (byte)((P & 0x7D) | TableNZ[--Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x8A: // TXA + A = X; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x8C: // STY addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, Y); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x8D: // STA addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, A); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x8E: // STX addr + value16 = ReadWord(PC); PC += 2; + WriteMemory(value16, X); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x90: // BCC +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagC == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x91: // STA (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value16 = (ushort)(temp16+Y); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + WriteMemory(value16, A); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0x94: // STY zp,X + value16 = (byte)(ReadMemory(PC++)+X); + WriteMemory(value16, Y); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x95: // STA zp,X + value16 = (byte)(ReadMemory(PC++)+X); + WriteMemory(value16, A); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x96: // STX zp,Y + value16 = (byte)(ReadMemory(PC++)+Y); + WriteMemory(value16, X); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0x98: // TYA + A = Y; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x99: // STA addr,Y + value16 = (ushort)(ReadWord(PC)+Y); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0x9A: // TXS + S = X; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0x9D: // STA addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + WriteMemory(value16, A); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xA0: // LDY #nn + Y = ReadMemory(PC++); + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xA1: // LDA (addr,X) + A = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xA2: // LDX #nn + X = ReadMemory(PC++); + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xA4: // LDY zp + Y = ReadMemory(ReadMemory(PC++)); + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xA5: // LDA zp + A = ReadMemory(ReadMemory(PC++)); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xA6: // LDX zp + X = ReadMemory(ReadMemory(PC++)); + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xA8: // TAY + Y = A; + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xA9: // LDA #nn + A = ReadMemory(PC++); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xAA: // TAX + X = A; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xAC: // LDY addr + Y = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xAD: // LDA addr + A = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xAE: // LDX addr + X = ReadMemory(ReadWord(PC)); PC += 2; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB0: // BCS +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagC == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xB1: // LDA (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + A = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xB4: // LDY zp,X + Y = ReadMemory((byte)(ReadMemory(PC++)+X)); + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB5: // LDA zp,X + A = ReadMemory((byte)(ReadMemory(PC++)+X)); + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB6: // LDX zp,Y + X = ReadMemory((byte)(ReadMemory(PC++)+Y)); + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xB8: // CLV + FlagV = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xB9: // LDA addr,Y + A = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xBA: // TSX + X = S; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xBC: // LDY addr,X + Y = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[Y]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xBD: // LDA addr,X + A = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xBE: // LDX addr,Y + X = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + P = (byte)((P & 0x7D) | TableNZ[X]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xC0: // CPY #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xC1: // CMP (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 6; + break; + case 0xC4: // CPY zp + value8 = ReadMemory(ReadMemory(PC++)); + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xC5: // CMP zp + value8 = ReadMemory(ReadMemory(PC++)); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 3; + break; + case 0xC6: // DEC zp + value16 = ReadMemory(PC++); + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xC8: // INY + P = (byte)((P & 0x7D) | TableNZ[++Y]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xC9: // CMP #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xCA: // DEX + P = (byte)((P & 0x7D) | TableNZ[--X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xCC: // CPY addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xCD: // CMP addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xCE: // DEC addr + value16 = ReadWord(PC); PC += 2; + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xD0: // BNE +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagZ == false) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xD1: // CMP (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 5; + break; + case 0xD5: // CMP zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xD6: // DEC zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xD8: // CLD + FlagD = false; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xD9: // CMP addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xDD: // CMP addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value16 = (ushort) (A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xDE: // DEC addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value8 = (byte)(ReadMemory(value16) - 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + case 0xE0: // CPX #nn + value8 = ReadMemory(PC++); + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xE1: // SBC (addr,X) + value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X))); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xE4: // CPX zp + value8 = ReadMemory(ReadMemory(PC++)); + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 2; + break; + case 0xE5: // SBC zp + value8 = ReadMemory(ReadMemory(PC++)); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 3; TotalExecutedCycles += 3; + break; + case 0xE6: // INC zp + value16 = ReadMemory(PC++); + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xE8: // INX + P = (byte)((P & 0x7D) | TableNZ[++X]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xE9: // SBC #nn + value8 = ReadMemory(PC++); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xEA: // NOP + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xEC: // CPX addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + value16 = (ushort) (X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + PendingCycles -= 4; + break; + case 0xED: // SBC addr + value8 = ReadMemory(ReadWord(PC)); PC += 2; + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xEE: // INC addr + value16 = ReadWord(PC); PC += 2; + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xF0: // BEQ +/-rel + rel8 = (sbyte)ReadMemory(PC++); + value16 = (ushort)(PC+rel8); + if (FlagZ == true) { + PendingCycles--; TotalExecutedCycles++; + if ((PC & 0xFF00) != (value16 & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC = value16; + } + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xF1: // SBC (addr),Y + temp16 = ReadWordPageWrap(ReadMemory(PC++)); + value8 = ReadMemory((ushort)(temp16+Y)); + if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 5; TotalExecutedCycles += 5; + break; + case 0xF5: // SBC zp,X + value8 = ReadMemory((byte)(ReadMemory(PC++)+X)); + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xF6: // INC zp,X + value16 = (byte)(ReadMemory(PC++)+X); + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 6; TotalExecutedCycles += 6; + break; + case 0xF8: // SED + FlagD = true; + PendingCycles -= 2; TotalExecutedCycles += 2; + break; + case 0xF9: // SBC addr,Y + value8 = ReadMemory((ushort)(ReadWord(PC)+Y)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xFD: // SBC addr,X + value8 = ReadMemory((ushort)(ReadWord(PC)+X)); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + temp = A - value8 - (FlagC?0:1); + FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0; + FlagC = temp >= 0; + A = (byte)temp; + P = (byte)((P & 0x7D) | TableNZ[A]); + PendingCycles -= 4; TotalExecutedCycles += 4; + break; + case 0xFE: // INC addr,X + value16 = (ushort)(ReadWord(PC)+X); + if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) + { PendingCycles--; TotalExecutedCycles++; } + PC += 2; + value8 = (byte)(ReadMemory(value16) + 1); + WriteMemory(value16, value8); + P = (byte)((P & 0x7D) | TableNZ[value8]); + PendingCycles -= 7; TotalExecutedCycles += 7; + break; + default: + throw new Exception(String.Format("Unhandled opcode: {0:X2}", opcode)); + } + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs new file mode 100644 index 0000000000..8ddca04242 --- /dev/null +++ b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs @@ -0,0 +1,184 @@ +using System; + +namespace BizHawk.Emulation.CPUs.M6502 +{ + public sealed partial class MOS6502 + { + public MOS6502() + { + //InitTableNZ(); + Reset(); + } +/* + private byte[] TableNZ; + private void InitTableNZ() + { + TableNZ = new byte[256]; + for (int i = 0; i < 256; i++) + { + byte b = 0; + if (i == 0) b |= 0x02; + if (i > 127) b |= 0x80; + TableNZ[i] = b; + } + }*/ + + public void Reset() + { + A = 0; + X = 0; + Y = 0; + P = 0; + S = 0; + PC = 0; + PendingCycles = 0; + TotalExecutedCycles = 0; + } + + public void ResetPC() + { + PC = ReadWord(0xFFFE); + } + + public string State() + { + int notused; + string a = string.Format("{0:X4} {1:X2} {2} ", PC, ReadMemory(PC), Disassemble(PC, out notused)).PadRight(41); + string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); + string val = a + b + " "; + if (FlagN) val = val + "N"; + if (FlagV) val = val + "V"; + if (FlagT) val = val + "T"; + if (FlagB) val = val + "B"; + if (FlagD) val = val + "D"; + if (FlagI) val = val + "I"; + if (FlagZ) val = val + "Z"; + if (FlagC) val = val + "C"; + return val; + } + + // ==== CPU State ==== + + public byte A; + public byte X; + public byte Y; + public byte P; + public ushort PC; + public byte S; + + // TODO IRQ, NMI functions + public bool Interrupt; + public bool NMI;// + + // ==== End State ==== + + /// Carry Flag + private bool FlagC + { + get { return (P & 0x01) != 0; } + set { P = (byte)((P & ~0x01) | (value ? 0x01 : 0x00)); } + } + + /// Zero Flag + private bool FlagZ + { + get { return (P & 0x02) != 0; } + set { P = (byte)((P & ~0x02) | (value ? 0x02 : 0x00)); } + } + + /// Interrupt Disable Flag + private bool FlagI + { + get { return (P & 0x04) != 0; } + set { P = (byte)((P & ~0x04) | (value ? 0x04 : 0x00)); } + } + + /// Decimal Mode Flag + private bool FlagD + { + get { return (P & 0x08) != 0; } + set { P = (byte)((P & ~0x08) | (value ? 0x08 : 0x00)); } + } + + /// Break Flag + private bool FlagB + { + get { return (P & 0x10) != 0; } + set { P = (byte)((P & ~0x10) | (value ? 0x10 : 0x00)); } + } + + /// T... Flag + private bool FlagT + { + get { return (P & 0x20) != 0; } + set { P = (byte)((P & ~0x20) | (value ? 0x20 : 0x00)); } + } + + /// Overflow Flag + private bool FlagV + { + get { return (P & 0x40) != 0; } + set { P = (byte)((P & ~0x40) | (value ? 0x40 : 0x00)); } + } + + /// Negative Flag + private bool FlagN + { + get { return (P & 0x80) != 0; } + set { P = (byte)((P & ~0x80) | (value ? 0x80 : 0x00)); } + } + + public int TotalExecutedCycles; + public int PendingCycles; + + public Func ReadMemory; + public Action WriteMemory; + + public void UnregisterMemoryMapper() + { + ReadMemory = null; + WriteMemory = null; + } + + private ushort ReadWord(ushort address) + { + byte l = ReadMemory(address); + byte h = ReadMemory(++address); + return (ushort)((h << 8) | l); + } + + private void WriteWord(ushort address, ushort value) + { + byte l = (byte)(value & 0xFF); + byte h = (byte)(value >> 8); + WriteMemory(address, l); + WriteMemory(++address, h); + } + + private ushort ReadWordPageWrap(ushort address) + { + ushort highAddress = (ushort)((address & 0xFF00) + ((address + 1) & 0xFF)); + return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8)); + } + + private static readonly byte[] TableNZ = + { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 + }; + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80-GB/Disassembler.cs b/BizHawk.Emulation/CPUs/Z80-GB/Disassembler.cs new file mode 100644 index 0000000000..ce09306a09 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80-GB/Disassembler.cs @@ -0,0 +1,173 @@ +/** GBDASM: GameBoy Disassembler ******************************/ +/** **/ +/** gbdasm.c **/ +/** **/ +/** This file contains the source of a portable disassembler **/ +/** for the customized Z80 CPU used in GameBoy handheld **/ +/** videogame console. **/ +/** **/ +/** Copyright (C) Marat Fayzullin 1995-2001 **/ +/** You are not allowed to distribute this software **/ +/** commercially. Please, notify me, if you make any **/ +/** changes to this file. **/ +/**************************************************************/ + +using System; +using System.Text; + +namespace BizHawk.Emulation.CPUs.Z80GB +{ + public static class Disassembler + { + readonly static string[] mnemonics = new string[] + { + "NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA", + "LD (#h),SP","ADD HL,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA", + "STOP","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA", + "JR @h","ADD HL,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA", + "JR NZ,@h","LD HL,#h","LD (HL+),A","INC HL","INC H","DEC H","LD H,*h","DAA", + "JR Z,@h","ADD HL,HL","LD A,(HL+)","DEC HL","INC L","DEC L","LD L,*h","CPL", + "JR NC,@h","LD SP,#h","LD (HL-),A","INC SP","INC (HL)","DEC (HL)","LD (HL),*h","SCF", + "JR C,@h","ADD HL,SP","LD A,(HL-)","DEC SP","INC A","DEC A","LD A,*h","CCF", + "LD B,B","LD B,C","LD B,D","LD B,E","LD B,H","LD B,L","LD B,(HL)","LD B,A", + "LD C,B","LD C,C","LD C,D","LD C,E","LD C,H","LD C,L","LD C,(HL)","LD C,A", + "LD D,B","LD D,C","LD D,D","LD D,E","LD D,H","LD D,L","LD D,(HL)","LD D,A", + "LD E,B","LD E,C","LD E,D","LD E,E","LD E,H","LD E,L","LD E,(HL)","LD E,A", + "LD H,B","LD H,C","LD H,D","LD H,E","LD H,H","LD H,L","LD H,(HL)","LD H,A", + "LD L,B","LD L,C","LD L,D","LD L,E","LD L,H","LD L,L","LD L,(HL)","LD L,A", + "LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E","LD (HL),H","LD (HL),L","HALT","LD (HL),A", + "LD A,B","LD A,C","LD A,D","LD A,E","LD A,H","LD A,L","LD A,(HL)","LD A,A", + "ADD B","ADD C","ADD D","ADD E","ADD H","ADD L","ADD (HL)","ADD A", + "ADC B","ADC C","ADC D","ADC E","ADC H","ADC L","ADC (HL)","ADC A", + "SUB B","SUB C","SUB D","SUB E","SUB H","SUB L","SUB (HL)","SUB A", + "SBC B","SBC C","SBC D","SBC E","SBC H","SBC L","SBC (HL)","SBC A", + "AND B","AND C","AND D","AND E","AND H","AND L","AND (HL)","AND A", + "XOR B","XOR C","XOR D","XOR E","XOR H","XOR L","XOR (HL)","XOR A", + "OR B","OR C","OR D","OR E","OR H","OR L","OR (HL)","OR A", + "CP B","CP C","CP D","CP E","CP H","CP L","CP (HL)","CP A", + "RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h", + "RET Z","RET","JP Z,#h","PREFIX CBh","CALL Z,#h","CALL #h","ADC *h","RST 08h", + "RET NC","POP DE","JP NC,#h","DB D3h","CALL NC,#h","PUSH DE","SUB *h","RST 10h", + "RET C","RETI","JP C,#h","DB DBh","CALL C,#h","DB DDh","SBC *h","RST 18h", + "LD (FF*h),A","POP HL","LD (FF00h+C),A","DB E3h","DB E4h","PUSH HL","AND *h","RST 20h", + "ADD SP,@h","LD PC,HL","LD (#h),A","DB EBh","DB ECh","PREFIX EDh","XOR *h","RST 28h", + "LD A,(FF*h)","POP AF","LD A,(FF00h+C)","DI","DB F4h","PUSH AF","OR *h","RST 30h", + "LDHL SP,@h","LD SP,HL","LD A,(#h)","EI","DB FCh","DB FDh","CP *h","RST 38h" + }; + + readonly static string[] mnemonicsCB = new string[] + { + "RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (HL)","RLC A", + "RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (HL)","RRC A", + "RL B","RL C","RL D","RL E","RL H","RL L","RL (HL)","RL A", + "RR B","RR C","RR D","RR E","RR H","RR L","RR (HL)","RR A", + "SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (HL)","SLA A", + "SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (HL)","SRA A", + "SWAP B","SWAP C","SWAP D","SWAP E","SWAP H","SWAP L","SWAP (HL)","SWAP A", + "SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (HL)","SRL A", + "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A", + "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A", + "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A", + "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A", + "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A", + "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A", + "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A", + "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A", + "RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A", + "RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A", + "RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A", + "RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A", + "RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A", + "RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A", + "RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A", + "RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A", + "SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A", + "SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A", + "SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A", + "SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A", + "SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A", + "SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A", + "SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A", + "SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A" + }; + + class OpcodeReader + { + public OpcodeReader(ushort addr, Func reader) + { + this.startAddr = addr; + this.addr = addr; + this.reader = reader; + } + ushort addr, startAddr; + + Func reader; + int[] bytes = new int[] {-1,-1,-1}; + int bytectr = 0; + public int Size { get { return bytectr; } } + public byte Read() + { + byte val = reader(addr++); ; + bytes[bytectr] = val; + bytectr++; + return val; + } + + public string Format(string mnemonic) + { + StringBuilder sb = new StringBuilder(32); + sb.AppendFormat("{0:X4}:", startAddr); + for (int i = 0; i < 3; i++) + { + if (bytectr > i) + sb.AppendFormat("{0:X2} ", bytes[i]); + else sb.AppendFormat(" "); + } + sb.AppendFormat(" {0}",mnemonic); + return sb.ToString(); + } + } + + public static string DAsm(ushort addr, Func reader, out ushort size) + { + string ret; + OpcodeReader or = new OpcodeReader(addr, reader); + + byte A = or.Read(); + string str; + switch (A) + { + case 0xCB: + str = mnemonicsCB[or.Read()]; + break; + default: + str = mnemonics[A]; + break; + } + + if (str.IndexOf('*') != -1) + { + ret = str.Replace("*", string.Format("{0:X2}", or.Read())); + } + else if (str.IndexOf('@') != -1) + { + byte B = or.Read(); + bool neg = ((B & 0x80) != 0); + char sign = neg ? '-' : '+'; + int val = neg ? 256 - B : B; + ret = str.Replace("@", string.Format("{0}{1:X2}", sign, val)); + } + else if (str.IndexOf('#') != -1) + { + byte B = or.Read(); + byte C = or.Read(); + ret = str.Replace("#", string.Format("{0:X4}", B + C * 256)); + } + else ret = str; + + size = (ushort)or.Size; + return or.Format(ret); + } + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80-GB/Execute.cs b/BizHawk.Emulation/CPUs/Z80-GB/Execute.cs new file mode 100644 index 0000000000..ce4b72f0db --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80-GB/Execute.cs @@ -0,0 +1,2320 @@ +using System; + +/* TODO: ++ http://www.devrs.com/gb/files/opcodes.html was used as a flags and timing reference. ++ [Opt] The DAA Table could be reduced from 128k to 8k. ++ Currently all instructions are using fixed m-cycles. Any instruction with variable cycles (ie branches) need to be checked. ++ The following instructions were rewritten or substantially modified for Z80-GB. They should be + treated with caution and checked further when the emulator is farther along. + + ADD + ADC + SUB + SBC + AND + OR + XOR + CP + SWAP + DAA + RLCA + RLA + RRCA + RRA + RLC + RL + RRC + RR + SLA + SRA + SRL +*/ + +namespace BizHawk.Emulation.CPUs.Z80GB +{ + public partial class Z80 + { + public int TotalExecutedCycles; + public int PendingCycles; + + bool Interruptable; + + public void ExecuteInstruction() + { + byte TB; byte TB2; sbyte TSB; ushort TUS; int TI1; int TI2; int TIR; + + byte op = ReadMemory(RegPC.Word++); + int mCycleTime = mCycleTable[op]; + PendingCycles -= mCycleTime; + TotalExecutedCycles += mCycleTime; + switch (op) + { + case 0x00: // NOP + break; + case 0x01: // LD BC, nn + RegBC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + break; + case 0x02: // LD (BC), A + WriteMemory(RegBC.Word, RegAF.High); + break; + case 0x03: // INC BC + ++RegBC.Word; + break; + case 0x04: // INC B + RegAF.Low = (byte)(IncTable[++RegBC.High] | (RegAF.Low & 16)); + break; + case 0x05: // DEC B + RegAF.Low = (byte)(DecTable[--RegBC.High] | (RegAF.Low & 16)); + break; + case 0x06: // LD B, n + RegBC.High = ReadMemory(RegPC.Word++); + break; + case 0x07: // RLCA + RegAF.Low = (byte)((RegAF.High & 0x80) >> 3); + RegAF.High = (byte)((RegAF.High >> 7) | (RegAF.High << 1)); + break; + case 0x08: // LD (imm), SP + TUS = (ushort)(ReadMemory(RegPC.Word++) | (ReadMemory(RegPC.Word++) << 8)); + WriteMemory(TUS++, RegSP.Low); + WriteMemory(TUS, RegSP.High); + break; + case 0x09: // ADD HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + FlagN = false; + FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + break; + case 0x0A: // LD A, (BC) + RegAF.High = ReadMemory(RegBC.Word); + break; + case 0x0B: // DEC BC + --RegBC.Word; + break; + case 0x0C: // INC C + RegAF.Low = (byte)(IncTable[++RegBC.Low] | (RegAF.Low & 16)); + break; + case 0x0D: // DEC C + RegAF.Low = (byte)(DecTable[--RegBC.Low] | (RegAF.Low & 16)); + break; + case 0x0E: // LD C, n + RegBC.Low = ReadMemory(RegPC.Word++); + break; + case 0x0F: // RRCA + RegAF.High = (byte)((RegAF.High << 7) | (RegAF.High >> 1)); + RegAF.Low = (byte)((RegAF.High & 0x80) >> 3); + break; + case 0x10: // STOP + Console.WriteLine("STOP!!!!!!!!!!!!!!!!!!!!!!"); // TODO this instruction is actually STOP. not DJNZ d. + throw new Exception("CPU stopped. What now?"); + break; + case 0x11: // LD DE, nn + RegDE.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + break; + case 0x12: // LD (DE), A + WriteMemory(RegDE.Word, RegAF.High); + break; + case 0x13: // INC DE + ++RegDE.Word; + break; + case 0x14: // INC D + RegAF.Low = (byte)(IncTable[++RegDE.High] | (RegAF.Low & 16)); + break; + case 0x15: // DEC D + RegAF.Low = (byte)(DecTable[--RegDE.High] | (RegAF.Low & 16)); + break; + case 0x16: // LD D, n + RegDE.High = ReadMemory(RegPC.Word++); + break; + case 0x17: // RLA + TB = (byte)((RegAF.High & 0x80) >> 3); + RegAF.High = (byte)((RegAF.High << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + break; + case 0x18: // JR d + TSB = (sbyte)ReadMemory(RegPC.Word++); + RegPC.Word = (ushort)(RegPC.Word + TSB); + break; + case 0x19: // ADD HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + FlagN = false; + FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + break; + case 0x1A: // LD A, (DE) + RegAF.High = ReadMemory(RegDE.Word); + break; + case 0x1B: // DEC DE + --RegDE.Word; + break; + case 0x1C: // INC E + RegAF.Low = (byte)(IncTable[++RegDE.Low] | (RegAF.Low & 16)); + break; + case 0x1D: // DEC E + RegAF.Low = (byte)(DecTable[--RegDE.Low] | (RegAF.Low & 16)); + break; + case 0x1E: // LD E, n + RegDE.Low = ReadMemory(RegPC.Word++); + break; + case 0x1F: // RRA + TB = (byte)((RegAF.High & 0x1) << 4); + RegAF.High = (byte)((RegAF.High >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + break; + case 0x20: // JR NZ, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!FlagZ) + RegPC.Word = (ushort)(RegPC.Word + TSB); + break; + case 0x21: // LD HL, nn + RegHL.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + break; + case 0x22: // LDI (HL), A + WriteMemory(RegHL.Word++, RegAF.High); + break; + case 0x23: // INC HL + ++RegHL.Word; + break; + case 0x24: // INC H + RegAF.Low = (byte)(IncTable[++RegHL.High] | (RegAF.Low & 16)); + break; + case 0x25: // DEC H + RegAF.Low = (byte)(DecTable[--RegHL.High] | (RegAF.Low & 16)); + break; + case 0x26: // LD H, n + RegHL.High = ReadMemory(RegPC.Word++); + break; + case 0x27: // DAA + RegAF.Word = TableDaa[RegAF.Word]; + break; + case 0x28: // JR Z, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (FlagZ) + RegPC.Word = (ushort)(RegPC.Word + TSB); + break; + case 0x29: // ADD HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + FlagN = false; + FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + break; + case 0x2A: // LDI A, (HL) + RegAF.High = ReadMemory(RegHL.Word++); + break; + case 0x2B: // DEC HL + --RegHL.Word; + break; + case 0x2C: // INC L + RegAF.Low = (byte)(IncTable[++RegHL.Low] | (RegAF.Low & 16)); + break; + case 0x2D: // DEC L + RegAF.Low = (byte)(DecTable[--RegHL.Low] | (RegAF.Low & 16)); + break; + case 0x2E: // LD L, n + RegHL.Low = ReadMemory(RegPC.Word++); + break; + case 0x2F: // CPL + RegAF.High ^= 0xFF; FlagH = true; FlagN = true; + break; + case 0x30: // JR NC, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!FlagC) + RegPC.Word = (ushort)(RegPC.Word + TSB); + break; + case 0x31: // LD SP, nn + RegSP.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + break; + case 0x32: // LDD (HL), A + WriteMemory(RegHL.Word--, RegAF.High); + break; + case 0x33: // INC SP + ++RegSP.Word; + break; + case 0x34: // INC (HL) + TB = ReadMemory(RegHL.Word); RegAF.Low = (byte)(IncTable[++TB] | (RegAF.Low & 16)); WriteMemory(RegHL.Word, TB); + break; + case 0x35: // DEC (HL) + TB = ReadMemory(RegHL.Word); RegAF.Low = (byte)(DecTable[--TB] | (RegAF.Low & 16)); WriteMemory(RegHL.Word, TB); + break; + case 0x36: // LD (HL), n + WriteMemory(RegHL.Word, ReadMemory(RegPC.Word++)); + break; + case 0x37: // SCF + FlagH = false; FlagN = false; FlagC = true; + break; + case 0x38: // JR C, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (FlagC) + RegPC.Word = (ushort)(RegPC.Word + TSB); + break; + case 0x39: // ADD HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + FlagN = false; + FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + break; + case 0x3A: // LDD A, (HL) + RegAF.High = ReadMemory(RegHL.Word--); + break; + case 0x3B: // DEC SP + --RegSP.Word; + break; + case 0x3C: // INC A + RegAF.Low = (byte)(IncTable[++RegAF.High] | (RegAF.Low & 16)); + break; + case 0x3D: // DEC A + RegAF.Low = (byte)(DecTable[--RegAF.High] | (RegAF.Low & 16)); + break; + case 0x3E: // LD A, n + RegAF.High = ReadMemory(RegPC.Word++); + break; + case 0x3F: // CCF + FlagH = FlagC; FlagN = false; FlagC ^= true; + break; + case 0x40: // LD B, B + break; + case 0x41: // LD B, C + RegBC.High = RegBC.Low; + break; + case 0x42: // LD B, D + RegBC.High = RegDE.High; + break; + case 0x43: // LD B, E + RegBC.High = RegDE.Low; + break; + case 0x44: // LD B, H + RegBC.High = RegHL.High; + break; + case 0x45: // LD B, L + RegBC.High = RegHL.Low; + break; + case 0x46: // LD B, (HL) + RegBC.High = ReadMemory(RegHL.Word); + break; + case 0x47: // LD B, A + RegBC.High = RegAF.High; + break; + case 0x48: // LD C, B + RegBC.Low = RegBC.High; + break; + case 0x49: // LD C, C + break; + case 0x4A: // LD C, D + RegBC.Low = RegDE.High; + break; + case 0x4B: // LD C, E + RegBC.Low = RegDE.Low; + break; + case 0x4C: // LD C, H + RegBC.Low = RegHL.High; + break; + case 0x4D: // LD C, L + RegBC.Low = RegHL.Low; + break; + case 0x4E: // LD C, (HL) + RegBC.Low = ReadMemory(RegHL.Word); + break; + case 0x4F: // LD C, A + RegBC.Low = RegAF.High; + break; + case 0x50: // LD D, B + RegDE.High = RegBC.High; + break; + case 0x51: // LD D, C + RegDE.High = RegBC.Low; + break; + case 0x52: // LD D, D + break; + case 0x53: // LD D, E + RegDE.High = RegDE.Low; + break; + case 0x54: // LD D, H + RegDE.High = RegHL.High; + break; + case 0x55: // LD D, L + RegDE.High = RegHL.Low; + break; + case 0x56: // LD D, (HL) + RegDE.High = ReadMemory(RegHL.Word); + break; + case 0x57: // LD D, A + RegDE.High = RegAF.High; + break; + case 0x58: // LD E, B + RegDE.Low = RegBC.High; + break; + case 0x59: // LD E, C + RegDE.Low = RegBC.Low; + break; + case 0x5A: // LD E, D + RegDE.Low = RegDE.High; + break; + case 0x5B: // LD E, E + break; + case 0x5C: // LD E, H + RegDE.Low = RegHL.High; + break; + case 0x5D: // LD E, L + RegDE.Low = RegHL.Low; + break; + case 0x5E: // LD E, (HL) + RegDE.Low = ReadMemory(RegHL.Word); + break; + case 0x5F: // LD E, A + RegDE.Low = RegAF.High; + break; + case 0x60: // LD H, B + RegHL.High = RegBC.High; + break; + case 0x61: // LD H, C + RegHL.High = RegBC.Low; + break; + case 0x62: // LD H, D + RegHL.High = RegDE.High; + break; + case 0x63: // LD H, E + RegHL.High = RegDE.Low; + break; + case 0x64: // LD H, H + break; + case 0x65: // LD H, L + RegHL.High = RegHL.Low; + break; + case 0x66: // LD H, (HL) + RegHL.High = ReadMemory(RegHL.Word); + break; + case 0x67: // LD H, A + RegHL.High = RegAF.High; + break; + case 0x68: // LD L, B + RegHL.Low = RegBC.High; + break; + case 0x69: // LD L, C + RegHL.Low = RegBC.Low; + break; + case 0x6A: // LD L, D + RegHL.Low = RegDE.High; + break; + case 0x6B: // LD L, E + RegHL.Low = RegDE.Low; + break; + case 0x6C: // LD L, H + RegHL.Low = RegHL.High; + break; + case 0x6D: // LD L, L + break; + case 0x6E: // LD L, (HL) + RegHL.Low = ReadMemory(RegHL.Word); + break; + case 0x6F: // LD L, A + RegHL.Low = RegAF.High; + break; + case 0x70: // LD (HL), B + WriteMemory(RegHL.Word, RegBC.High); + break; + case 0x71: // LD (HL), C + WriteMemory(RegHL.Word, RegBC.Low); + break; + case 0x72: // LD (HL), D + WriteMemory(RegHL.Word, RegDE.High); + break; + case 0x73: // LD (HL), E + WriteMemory(RegHL.Word, RegDE.Low); + break; + case 0x74: // LD (HL), H + WriteMemory(RegHL.Word, RegHL.High); + break; + case 0x75: // LD (HL), L + WriteMemory(RegHL.Word, RegHL.Low); + break; + case 0x76: // HALT + Halt(); + break; + case 0x77: // LD (HL), A + WriteMemory(RegHL.Word, RegAF.High); + break; + case 0x78: // LD A, B + RegAF.High = RegBC.High; + break; + case 0x79: // LD A, C + RegAF.High = RegBC.Low; + break; + case 0x7A: // LD A, D + RegAF.High = RegDE.High; + break; + case 0x7B: // LD A, E + RegAF.High = RegDE.Low; + break; + case 0x7C: // LD A, H + RegAF.High = RegHL.High; + break; + case 0x7D: // LD A, L + RegAF.High = RegHL.Low; + break; + case 0x7E: // LD A, (HL) + RegAF.High = ReadMemory(RegHL.Word); + break; + case 0x7F: // LD A, A + break; + case 0x80: // ADD B + TI1 = RegAF.High + RegBC.High; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegBC.High & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x81: // ADD C + TI1 = RegAF.High + RegBC.Low; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegBC.Low & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x82: // ADD D + TI1 = RegAF.High + RegDE.High; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegDE.High & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x83: // ADD E + TI1 = RegAF.High + RegDE.Low; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegDE.Low & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x84: // ADD H + TI1 = RegAF.High + RegHL.High; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegHL.High & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x85: // ADD L + TI1 = RegAF.High + RegHL.Low; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegHL.Low & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x86: // ADD (HL) + TB = ReadMemory(RegHL.Word); + TI1 = RegAF.High + TB; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (TB & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x87: // ADD A + TI1 = RegAF.High + RegAF.High; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegAF.High & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x88: // ADC B + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegBC.High + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegBC.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x89: // ADC C + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegBC.Low + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegBC.Low & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x8A: // ADC D + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegDE.High + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegDE.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x8B: // ADC E + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegDE.Low + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegDE.Low & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x8C: // ADC H + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegHL.High + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegHL.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x8D: // ADC L + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegHL.Low + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegHL.Low & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x8E: // ADC (HL) + TB = ReadMemory(RegHL.Word); + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + TB + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (TB & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x8F: // ADC A + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + RegAF.High + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (RegAF.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x90: // SUB B + TI1 = RegAF.High - RegBC.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegBC.High & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x91: // SUB C + TI1 = RegAF.High - RegBC.Low; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegBC.Low & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x92: // SUB D + TI1 = RegAF.High - RegDE.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegDE.High & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x93: // SUB E + TI1 = RegAF.High - RegDE.Low; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegDE.Low & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x94: // SUB H + TI1 = RegAF.High - RegHL.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegHL.High & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x95: // SUB L + TI1 = RegAF.High - RegHL.Low; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegHL.Low & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x96: // SUB (HL) + TB = ReadMemory(RegHL.Word); + TI1 = RegAF.High - TB; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x97: // SUB A + TI1 = RegAF.High - RegAF.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegAF.High & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x98: // SBC B + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegBC.High - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegBC.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x99: // SBC C + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegBC.Low - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegBC.Low & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x9A: // SBC D + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegDE.High - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegDE.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x9B: // SBC E + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegDE.Low - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegDE.Low & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x9C: // SBC H + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegHL.High - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegHL.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x9D: // SBC L + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegHL.Low - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegHL.Low & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x9E: // SBC (HL) + TB = ReadMemory(RegHL.Word); + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - TB - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (TB & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0x9F: // SBC A + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - RegAF.High - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegAF.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0xA0: // AND B + RegAF.High &= RegBC.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA1: // AND C + RegAF.High &= RegBC.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA2: // AND D + RegAF.High &= RegDE.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA3: // AND E + RegAF.High &= RegDE.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA4: // AND H + RegAF.High &= RegHL.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA5: // AND L + RegAF.High &= RegHL.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA6: // AND (HL) + RegAF.High &= ReadMemory(RegHL.Word); + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA7: // AND A + RegAF.High &= RegAF.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xA8: // XOR B + RegAF.High ^= RegBC.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xA9: // XOR C + RegAF.High ^= RegBC.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xAA: // XOR D + RegAF.High ^= RegDE.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xAB: // XOR E + RegAF.High ^= RegDE.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xAC: // XOR H + RegAF.High ^= RegHL.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xAD: // XOR L + RegAF.High ^= RegHL.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xAE: // XOR (HL) + RegAF.High ^= ReadMemory(RegHL.Word); + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xAF: // XOR A + RegAF.High ^= RegAF.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB0: // OR B + RegAF.High |= RegBC.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB1: // OR C + RegAF.High |= RegBC.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB2: // OR D + RegAF.High |= RegDE.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB3: // OR E + RegAF.High |= RegDE.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB4: // OR H + RegAF.High |= RegHL.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB5: // OR L + RegAF.High |= RegHL.Low; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB6: // OR (HL) + RegAF.High |= ReadMemory(RegHL.Word); + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB7: // OR A + RegAF.High |= RegAF.High; + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xB8: // CP B + TI1 = RegAF.High - RegBC.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegBC.High & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xB9: // CP C + TI1 = RegAF.High - RegBC.Low; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegBC.Low & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xBA: // CP D + TI1 = RegAF.High - RegDE.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegDE.High & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xBB: // CP E + TI1 = RegAF.High - RegDE.Low; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegDE.Low & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xBC: // CP H + TI1 = RegAF.High - RegHL.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegHL.High & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xBD: // CP L + TI1 = RegAF.High - RegHL.Low; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegHL.Low & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xBE: // CP (HL) + TB = ReadMemory(RegHL.Word); + TI1 = RegAF.High - TB; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xBF: // CP A + TI1 = RegAF.High - RegAF.High; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (RegAF.High & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xC0: // RET NZ + if (!FlagZ) + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + break; + case 0xC1: // POP BC + RegBC.Low = ReadMemory(RegSP.Word++); RegBC.High = ReadMemory(RegSP.Word++); + break; + case 0xC2: // JP NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!FlagZ) + RegPC.Word = TUS; + break; + case 0xC3: // JP nn + RegPC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + break; + case 0xC4: // CALL NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!FlagZ) + { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + } + break; + case 0xC5: // PUSH BC + WriteMemory(--RegSP.Word, RegBC.High); WriteMemory(--RegSP.Word, RegBC.Low); + break; + case 0xC6: // ADD n + TB = ReadMemory(RegPC.Word++); + TI1 = RegAF.High + TB; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (TB & 0x0F) > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0xC7: // RST $00 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x00; + break; + case 0xC8: // RET Z + if (FlagZ) + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + break; + case 0xC9: // RET + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + break; + case 0xCA: // JP Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (FlagZ) + RegPC.Word = TUS; + break; + case 0xCB: // (Prefix) + op = ReadMemory(RegPC.Word++); + mCycleTime = cbMCycleTable[op]; + PendingCycles -= mCycleTime; + TotalExecutedCycles += mCycleTime; + switch (op) + { + case 0x00: // RLC B + RegAF.Low = (byte)((RegBC.High & 0x80) >> 3); + RegBC.High = (byte)((RegBC.High >> 7) | (RegBC.High << 1)); + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x01: // RLC C + RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3); + RegBC.Low = (byte)((RegBC.Low >> 7) | (RegBC.Low << 1)); + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x02: // RLC D + RegAF.Low = (byte)((RegDE.High & 0x80) >> 3); + RegDE.High = (byte)((RegDE.High >> 7) | (RegDE.High << 1)); + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x03: // RLC E + RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3); + RegDE.Low = (byte)((RegDE.Low >> 7) | (RegDE.Low << 1)); + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x04: // RLC H + RegAF.Low = (byte)((RegHL.High & 0x80) >> 3); + RegHL.High = (byte)((RegHL.High >> 7) | (RegHL.High << 1)); + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x05: // RLC L + RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3); + RegHL.Low = (byte)((RegHL.Low >> 7) | (RegHL.Low << 1)); + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x06: // RLC (HL) + TB = ReadMemory(RegHL.Word); + RegAF.Low = (byte)((TB & 0x80) >> 3); + TB = (byte)((TB >> 7) | (TB << 1)); + if (TB == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB); + break; + case 0x07: // RLC A + RegAF.Low = (byte)((RegAF.High & 0x80) >> 3); + RegAF.High = (byte)((RegAF.High >> 7) | (RegAF.High << 1)); + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x08: // RRC B + RegBC.High = (byte)((RegBC.High << 7) | (RegBC.High >> 1)); + RegAF.Low = (byte)((RegBC.High & 0x80) >> 3); + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x09: // RRC C + RegBC.Low = (byte)((RegBC.Low << 7) | (RegBC.Low >> 1)); + RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3); + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x0A: // RRC D + RegDE.High = (byte)((RegDE.High << 7) | (RegDE.High >> 1)); + RegAF.Low = (byte)((RegDE.High & 0x80) >> 3); + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x0B: // RRC E + RegDE.Low = (byte)((RegDE.Low << 7) | (RegDE.Low >> 1)); + RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3); + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x0C: // RRC H + RegHL.High = (byte)((RegHL.High << 7) | (RegHL.High >> 1)); + RegAF.Low = (byte)((RegHL.High & 0x80) >> 3); + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x0D: // RRC L + RegHL.Low = (byte)((RegHL.Low << 7) | (RegHL.Low >> 1)); + RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3); + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x0E: // RRC (HL) + TB = ReadMemory(RegHL.Word); + TB = (byte)((TB << 7) | (TB >> 1)); + RegAF.Low = (byte)((TB & 0x80) >> 3); + if (TB == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB); + break; + case 0x0F: // RRC A + RegAF.High = (byte)((RegAF.High << 7) | (RegAF.High >> 1)); + RegAF.Low = (byte)((RegAF.High & 0x80) >> 3); + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x10: // RL B + TB = (byte)((RegBC.High & 0x80) >> 3); + RegBC.High = (byte)((RegBC.High << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x11: // RL C + TB = (byte)((RegBC.Low & 0x80) >> 3); + RegBC.Low = (byte)((RegBC.Low << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x12: // RL D + TB = (byte)((RegDE.High & 0x80) >> 3); + RegDE.High = (byte)((RegDE.High << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x13: // RL E + TB = (byte)((RegDE.Low & 0x80) >> 3); + RegDE.Low = (byte)((RegDE.Low << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x14: // RL H + TB = (byte)((RegHL.High & 0x80) >> 3); + RegHL.High = (byte)((RegHL.High << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x15: // RL L + TB = (byte)((RegHL.Low & 0x80) >> 3); + RegHL.Low = (byte)((RegHL.Low << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x16: // RL (HL) + TB2 = ReadMemory(RegHL.Word); + TB = (byte)((TB2 & 0x80) >> 3); + TB2 = (byte)((TB2 << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (TB2 == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB2); + break; + case 0x17: // RL A + TB = (byte)((RegAF.High & 0x80) >> 3); + RegAF.High = (byte)((RegAF.High << 1) | (FlagC ? 1 : 0)); + RegAF.Low = TB; + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x18: // RR B + TB = (byte)((RegBC.High & 0x1) << 4); + RegBC.High = (byte)((RegBC.High >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x19: // RR C + TB = (byte)((RegBC.Low & 0x1) << 4); + RegBC.Low = (byte)((RegBC.Low >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x1A: // RR D + TB = (byte)((RegDE.High & 0x1) << 4); + RegDE.High = (byte)((RegDE.High >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x1B: // RR E + TB = (byte)((RegDE.Low & 0x1) << 4); + RegDE.Low = (byte)((RegDE.Low >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x1C: // RR H + TB = (byte)((RegHL.High & 0x1) << 4); + RegHL.High = (byte)((RegHL.High >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x1D: // RR L + TB = (byte)((RegHL.Low & 0x1) << 4); + RegHL.Low = (byte)((RegHL.Low >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x1E: // RR (HL) + TB2 = ReadMemory(RegHL.Word); + TB = (byte)((TB2 & 0x1) << 4); + TB2 = (byte)((TB2 >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (TB2 == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB2); + break; + case 0x1F: // RR A + TB = (byte)((RegAF.High & 0x1) << 4); + RegAF.High = (byte)((RegAF.High >> 1) | (FlagC ? 0x80 : 0)); + RegAF.Low = TB; + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x20: // SLA B + RegAF.Low = 0; + if ((RegBC.High & 0x80) != 0) RegAF.Low |= 0x10; + RegBC.High <<= 1; + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x21: // SLA C + RegAF.Low = 0; + if ((RegBC.Low & 0x80) != 0) RegAF.Low |= 0x10; + RegBC.Low <<= 1; + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x22: // SLA D + RegAF.Low = 0; + if ((RegDE.High & 0x80) != 0) RegAF.Low |= 0x10; + RegDE.High <<= 1; + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x23: // SLA E + RegAF.Low = 0; + if ((RegDE.Low & 0x80) != 0) RegAF.Low |= 0x10; + RegDE.Low <<= 1; + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x24: // SLA H + RegAF.Low = 0; + if ((RegHL.High & 0x80) != 0) RegAF.Low |= 0x10; + RegHL.High <<= 1; + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x25: // SLA L + RegAF.Low = 0; + if ((RegHL.Low & 0x80) != 0) RegAF.Low |= 0x10; + RegHL.Low <<= 1; + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x26: // SLA (HL) + TB = ReadMemory(RegHL.Word); + RegAF.Low = 0; + if ((TB & 0x80) != 0) RegAF.Low |= 0x10; + TB <<= 1; + if (TB == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB); + break; + case 0x27: // SLA A + RegAF.Low = 0; + if ((RegAF.High & 0x80) != 0) RegAF.Low |= 0x10; + RegAF.High <<= 1; + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x28: // SRA B + RegAF.Low = 0; + if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10; + RegBC.High = (byte) ((RegBC.High >> 1) | (RegBC.High & 0x80)); + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x29: // SRA C + RegAF.Low = 0; + if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10; + RegBC.Low = (byte)((RegBC.Low >> 1) | (RegBC.Low & 0x80)); + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x2A: // SRA D + RegAF.Low = 0; + if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10; + RegDE.High = (byte)((RegDE.High >> 1) | (RegDE.High & 0x80)); + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x2B: // SRA E + RegAF.Low = 0; + if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10; + RegDE.Low = (byte)((RegDE.Low >> 1) | (RegDE.Low & 0x80)); + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x2C: // SRA H + RegAF.Low = 0; + if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10; + RegHL.High = (byte)((RegHL.High >> 1) | (RegHL.High & 0x80)); + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x2D: // SRA L + RegAF.Low = 0; + if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10; + RegHL.Low = (byte)((RegHL.Low >> 1) | (RegHL.Low & 0x80)); + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x2E: // SRA (HL) + TB = ReadMemory(RegHL.Word); + RegAF.Low = 0; + if ((TB & 1) != 0) RegAF.Low |= 0x10; + TB = (byte)((TB >> 1) | (TB & 0x80)); + if (TB == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB); + break; + case 0x2F: // SRA A + RegAF.Low = 0; + if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10; + RegAF.High = (byte)((RegAF.High >> 1) | (RegAF.High & 0x80)); + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x30: // SWAP B + RegBC.High = SwapTable[RegBC.High]; + FlagZ = (RegBC.High == 0); + break; + case 0x31: // SWAP C + RegBC.Low = SwapTable[RegBC.Low]; + FlagZ = (RegBC.Low == 0); + break; + case 0x32: // SWAP D + RegDE.High = SwapTable[RegDE.High]; + FlagZ = (RegDE.High == 0); + break; + case 0x33: // SWAP E + RegDE.Low = SwapTable[RegDE.Low]; + FlagZ = (RegDE.Low == 0); + break; + case 0x34: // SWAP H + RegHL.High = SwapTable[RegHL.High]; + FlagZ = (RegHL.High == 0); + break; + case 0x35: // SWAP L + RegHL.Low = SwapTable[RegHL.Low]; + FlagZ = (RegHL.Low == 0); + break; + case 0x36: // SWAP (HL) + TB = SwapTable[ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, TB); + FlagZ = (TB == 0); + break; + case 0x37: // SWAP A + RegAF.High = SwapTable[RegAF.High]; + FlagZ = (RegAF.High == 0); + break; + case 0x38: // SRL B + RegAF.Low = 0; + if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10; + RegBC.High >>= 1; + if (RegBC.High == 0) RegAF.Low |= 0x80; + break; + case 0x39: // SRL C + RegAF.Low = 0; + if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10; + RegBC.Low >>= 1; + if (RegBC.Low == 0) RegAF.Low |= 0x80; + break; + case 0x3A: // SRL D + RegAF.Low = 0; + if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10; + RegDE.High >>= 1; + if (RegDE.High == 0) RegAF.Low |= 0x80; + break; + case 0x3B: // SRL E + RegAF.Low = 0; + if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10; + RegDE.Low >>= 1; + if (RegDE.Low == 0) RegAF.Low |= 0x80; + break; + case 0x3C: // SRL H + RegAF.Low = 0; + if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10; + RegHL.High >>= 1; + if (RegHL.High == 0) RegAF.Low |= 0x80; + break; + case 0x3D: // SRL L + RegAF.Low = 0; + if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10; + RegHL.Low >>= 1; + if (RegHL.Low == 0) RegAF.Low |= 0x80; + break; + case 0x3E: // SRL (HL) + TB = ReadMemory(RegHL.Word); + RegAF.Low = 0; + if ((TB & 1) != 0) RegAF.Low |= 0x10; + TB >>= 1; + if (TB == 0) RegAF.Low |= 0x80; + WriteMemory(RegHL.Word, TB); + break; + case 0x3F: // SRL A + RegAF.Low = 0; + if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10; + RegAF.High >>= 1; + if (RegAF.High == 0) RegAF.Low |= 0x80; + break; + case 0x40: // BIT 0, B + FlagZ = (RegBC.High & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x41: // BIT 0, C + FlagZ = (RegBC.Low & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x42: // BIT 0, D + FlagZ = (RegDE.High & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x43: // BIT 0, E + FlagZ = (RegDE.Low & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x44: // BIT 0, H + FlagZ = (RegHL.High & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x45: // BIT 0, L + FlagZ = (RegHL.Low & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x46: // BIT 0, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x47: // BIT 0, A + FlagZ = (RegAF.High & 0x01) == 0; + FlagH = true; + FlagN = false; + break; + case 0x48: // BIT 1, B + FlagZ = (RegBC.High & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x49: // BIT 1, C + FlagZ = (RegBC.Low & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x4A: // BIT 1, D + FlagZ = (RegDE.High & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x4B: // BIT 1, E + FlagZ = (RegDE.Low & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x4C: // BIT 1, H + FlagZ = (RegHL.High & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x4D: // BIT 1, L + FlagZ = (RegHL.Low & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x4E: // BIT 1, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x4F: // BIT 1, A + FlagZ = (RegAF.High & 0x02) == 0; + FlagH = true; + FlagN = false; + break; + case 0x50: // BIT 2, B + FlagZ = (RegBC.High & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x51: // BIT 2, C + FlagZ = (RegBC.Low & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x52: // BIT 2, D + FlagZ = (RegDE.High & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x53: // BIT 2, E + FlagZ = (RegDE.Low & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x54: // BIT 2, H + FlagZ = (RegHL.High & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x55: // BIT 2, L + FlagZ = (RegHL.Low & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x56: // BIT 2, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x57: // BIT 2, A + FlagZ = (RegAF.High & 0x04) == 0; + FlagH = true; + FlagN = false; + break; + case 0x58: // BIT 3, B + FlagZ = (RegBC.High & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x59: // BIT 3, C + FlagZ = (RegBC.Low & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x5A: // BIT 3, D + FlagZ = (RegDE.High & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x5B: // BIT 3, E + FlagZ = (RegDE.Low & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x5C: // BIT 3, H + FlagZ = (RegHL.High & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x5D: // BIT 3, L + FlagZ = (RegHL.Low & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x5E: // BIT 3, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x5F: // BIT 3, A + FlagZ = (RegAF.High & 0x08) == 0; + FlagH = true; + FlagN = false; + break; + case 0x60: // BIT 4, B + FlagZ = (RegBC.High & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x61: // BIT 4, C + FlagZ = (RegBC.Low & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x62: // BIT 4, D + FlagZ = (RegDE.High & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x63: // BIT 4, E + FlagZ = (RegDE.Low & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x64: // BIT 4, H + FlagZ = (RegHL.High & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x65: // BIT 4, L + FlagZ = (RegHL.Low & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x66: // BIT 4, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x67: // BIT 4, A + FlagZ = (RegAF.High & 0x10) == 0; + FlagH = true; + FlagN = false; + break; + case 0x68: // BIT 5, B + FlagZ = (RegBC.High & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x69: // BIT 5, C + FlagZ = (RegBC.Low & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x6A: // BIT 5, D + FlagZ = (RegDE.High & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x6B: // BIT 5, E + FlagZ = (RegDE.Low & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x6C: // BIT 5, H + FlagZ = (RegHL.High & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x6D: // BIT 5, L + FlagZ = (RegHL.Low & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x6E: // BIT 5, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x6F: // BIT 5, A + FlagZ = (RegAF.High & 0x20) == 0; + FlagH = true; + FlagN = false; + break; + case 0x70: // BIT 6, B + FlagZ = (RegBC.High & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x71: // BIT 6, C + FlagZ = (RegBC.Low & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x72: // BIT 6, D + FlagZ = (RegDE.High & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x73: // BIT 6, E + FlagZ = (RegDE.Low & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x74: // BIT 6, H + FlagZ = (RegHL.High & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x75: // BIT 6, L + FlagZ = (RegHL.Low & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x76: // BIT 6, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x77: // BIT 6, A + FlagZ = (RegAF.High & 0x40) == 0; + FlagH = true; + FlagN = false; + break; + case 0x78: // BIT 7, B + FlagZ = (RegBC.High & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x79: // BIT 7, C + FlagZ = (RegBC.Low & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x7A: // BIT 7, D + FlagZ = (RegDE.High & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x7B: // BIT 7, E + FlagZ = (RegDE.Low & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x7C: // BIT 7, H + FlagZ = (RegHL.High & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x7D: // BIT 7, L + FlagZ = (RegHL.Low & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x7E: // BIT 7, (HL) + FlagZ = (ReadMemory(RegHL.Word) & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x7F: // BIT 7, A + FlagZ = (RegAF.High & 0x80) == 0; + FlagH = true; + FlagN = false; + break; + case 0x80: // RES 0, B + RegBC.High &= unchecked((byte)~0x01); + break; + case 0x81: // RES 0, C + RegBC.Low &= unchecked((byte)~0x01); + break; + case 0x82: // RES 0, D + RegDE.High &= unchecked((byte)~0x01); + break; + case 0x83: // RES 0, E + RegDE.Low &= unchecked((byte)~0x01); + break; + case 0x84: // RES 0, H + RegHL.High &= unchecked((byte)~0x01); + break; + case 0x85: // RES 0, L + RegHL.Low &= unchecked((byte)~0x01); + break; + case 0x86: // RES 0, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x01))); + break; + case 0x87: // RES 0, A + RegAF.High &= unchecked((byte)~0x01); + break; + case 0x88: // RES 1, B + RegBC.High &= unchecked((byte)~0x02); + break; + case 0x89: // RES 1, C + RegBC.Low &= unchecked((byte)~0x02); + break; + case 0x8A: // RES 1, D + RegDE.High &= unchecked((byte)~0x02); + break; + case 0x8B: // RES 1, E + RegDE.Low &= unchecked((byte)~0x02); + break; + case 0x8C: // RES 1, H + RegHL.High &= unchecked((byte)~0x02); + break; + case 0x8D: // RES 1, L + RegHL.Low &= unchecked((byte)~0x02); + break; + case 0x8E: // RES 1, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x02))); + break; + case 0x8F: // RES 1, A + RegAF.High &= unchecked((byte)~0x02); + break; + case 0x90: // RES 2, B + RegBC.High &= unchecked((byte)~0x04); + break; + case 0x91: // RES 2, C + RegBC.Low &= unchecked((byte)~0x04); + break; + case 0x92: // RES 2, D + RegDE.High &= unchecked((byte)~0x04); + break; + case 0x93: // RES 2, E + RegDE.Low &= unchecked((byte)~0x04); + break; + case 0x94: // RES 2, H + RegHL.High &= unchecked((byte)~0x04); + break; + case 0x95: // RES 2, L + RegHL.Low &= unchecked((byte)~0x04); + break; + case 0x96: // RES 2, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x04))); + break; + case 0x97: // RES 2, A + RegAF.High &= unchecked((byte)~0x04); + break; + case 0x98: // RES 3, B + RegBC.High &= unchecked((byte)~0x08); + break; + case 0x99: // RES 3, C + RegBC.Low &= unchecked((byte)~0x08); + break; + case 0x9A: // RES 3, D + RegDE.High &= unchecked((byte)~0x08); + break; + case 0x9B: // RES 3, E + RegDE.Low &= unchecked((byte)~0x08); + break; + case 0x9C: // RES 3, H + RegHL.High &= unchecked((byte)~0x08); + break; + case 0x9D: // RES 3, L + RegHL.Low &= unchecked((byte)~0x08); + break; + case 0x9E: // RES 3, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x08))); + break; + case 0x9F: // RES 3, A + RegAF.High &= unchecked((byte)~0x08); + break; + case 0xA0: // RES 4, B + RegBC.High &= unchecked((byte)~0x10); + break; + case 0xA1: // RES 4, C + RegBC.Low &= unchecked((byte)~0x10); + break; + case 0xA2: // RES 4, D + RegDE.High &= unchecked((byte)~0x10); + break; + case 0xA3: // RES 4, E + RegDE.Low &= unchecked((byte)~0x10); + break; + case 0xA4: // RES 4, H + RegHL.High &= unchecked((byte)~0x10); + break; + case 0xA5: // RES 4, L + RegHL.Low &= unchecked((byte)~0x10); + break; + case 0xA6: // RES 4, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x10))); + break; + case 0xA7: // RES 4, A + RegAF.High &= unchecked((byte)~0x10); + break; + case 0xA8: // RES 5, B + RegBC.High &= unchecked((byte)~0x20); + break; + case 0xA9: // RES 5, C + RegBC.Low &= unchecked((byte)~0x20); + break; + case 0xAA: // RES 5, D + RegDE.High &= unchecked((byte)~0x20); + break; + case 0xAB: // RES 5, E + RegDE.Low &= unchecked((byte)~0x20); + break; + case 0xAC: // RES 5, H + RegHL.High &= unchecked((byte)~0x20); + break; + case 0xAD: // RES 5, L + RegHL.Low &= unchecked((byte)~0x20); + break; + case 0xAE: // RES 5, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x20))); + break; + case 0xAF: // RES 5, A + RegAF.High &= unchecked((byte)~0x20); + break; + case 0xB0: // RES 6, B + RegBC.High &= unchecked((byte)~0x40); + break; + case 0xB1: // RES 6, C + RegBC.Low &= unchecked((byte)~0x40); + break; + case 0xB2: // RES 6, D + RegDE.High &= unchecked((byte)~0x40); + break; + case 0xB3: // RES 6, E + RegDE.Low &= unchecked((byte)~0x40); + break; + case 0xB4: // RES 6, H + RegHL.High &= unchecked((byte)~0x40); + break; + case 0xB5: // RES 6, L + RegHL.Low &= unchecked((byte)~0x40); + break; + case 0xB6: // RES 6, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x40))); + break; + case 0xB7: // RES 6, A + RegAF.High &= unchecked((byte)~0x40); + break; + case 0xB8: // RES 7, B + RegBC.High &= unchecked((byte)~0x80); + break; + case 0xB9: // RES 7, C + RegBC.Low &= unchecked((byte)~0x80); + break; + case 0xBA: // RES 7, D + RegDE.High &= unchecked((byte)~0x80); + break; + case 0xBB: // RES 7, E + RegDE.Low &= unchecked((byte)~0x80); + break; + case 0xBC: // RES 7, H + RegHL.High &= unchecked((byte)~0x80); + break; + case 0xBD: // RES 7, L + RegHL.Low &= unchecked((byte)~0x80); + break; + case 0xBE: // RES 7, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x80))); + break; + case 0xBF: // RES 7, A + RegAF.High &= unchecked((byte)~0x80); + break; + case 0xC0: // SET 0, B + RegBC.High |= unchecked(0x01); + break; + case 0xC1: // SET 0, C + RegBC.Low |= unchecked(0x01); + break; + case 0xC2: // SET 0, D + RegDE.High |= unchecked(0x01); + break; + case 0xC3: // SET 0, E + RegDE.Low |= unchecked(0x01); + break; + case 0xC4: // SET 0, H + RegHL.High |= unchecked(0x01); + break; + case 0xC5: // SET 0, L + RegHL.Low |= unchecked(0x01); + break; + case 0xC6: // SET 0, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x01))); + break; + case 0xC7: // SET 0, A + RegAF.High |= unchecked(0x01); + break; + case 0xC8: // SET 1, B + RegBC.High |= unchecked(0x02); + break; + case 0xC9: // SET 1, C + RegBC.Low |= unchecked(0x02); + break; + case 0xCA: // SET 1, D + RegDE.High |= unchecked(0x02); + break; + case 0xCB: // SET 1, E + RegDE.Low |= unchecked(0x02); + break; + case 0xCC: // SET 1, H + RegHL.High |= unchecked(0x02); + break; + case 0xCD: // SET 1, L + RegHL.Low |= unchecked(0x02); + break; + case 0xCE: // SET 1, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x02))); + break; + case 0xCF: // SET 1, A + RegAF.High |= unchecked(0x02); + break; + case 0xD0: // SET 2, B + RegBC.High |= unchecked(0x04); + break; + case 0xD1: // SET 2, C + RegBC.Low |= unchecked(0x04); + break; + case 0xD2: // SET 2, D + RegDE.High |= unchecked(0x04); + break; + case 0xD3: // SET 2, E + RegDE.Low |= unchecked(0x04); + break; + case 0xD4: // SET 2, H + RegHL.High |= unchecked(0x04); + break; + case 0xD5: // SET 2, L + RegHL.Low |= unchecked(0x04); + break; + case 0xD6: // SET 2, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x04))); + break; + case 0xD7: // SET 2, A + RegAF.High |= unchecked(0x04); + break; + case 0xD8: // SET 3, B + RegBC.High |= unchecked(0x08); + break; + case 0xD9: // SET 3, C + RegBC.Low |= unchecked(0x08); + break; + case 0xDA: // SET 3, D + RegDE.High |= unchecked(0x08); + break; + case 0xDB: // SET 3, E + RegDE.Low |= unchecked(0x08); + break; + case 0xDC: // SET 3, H + RegHL.High |= unchecked(0x08); + break; + case 0xDD: // SET 3, L + RegHL.Low |= unchecked(0x08); + break; + case 0xDE: // SET 3, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x08))); + break; + case 0xDF: // SET 3, A + RegAF.High |= unchecked(0x08); + break; + case 0xE0: // SET 4, B + RegBC.High |= unchecked(0x10); + break; + case 0xE1: // SET 4, C + RegBC.Low |= unchecked(0x10); + break; + case 0xE2: // SET 4, D + RegDE.High |= unchecked(0x10); + break; + case 0xE3: // SET 4, E + RegDE.Low |= unchecked(0x10); + break; + case 0xE4: // SET 4, H + RegHL.High |= unchecked(0x10); + break; + case 0xE5: // SET 4, L + RegHL.Low |= unchecked(0x10); + break; + case 0xE6: // SET 4, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x10))); + break; + case 0xE7: // SET 4, A + RegAF.High |= unchecked(0x10); + break; + case 0xE8: // SET 5, B + RegBC.High |= unchecked(0x20); + break; + case 0xE9: // SET 5, C + RegBC.Low |= unchecked(0x20); + break; + case 0xEA: // SET 5, D + RegDE.High |= unchecked(0x20); + break; + case 0xEB: // SET 5, E + RegDE.Low |= unchecked(0x20); + break; + case 0xEC: // SET 5, H + RegHL.High |= unchecked(0x20); + break; + case 0xED: // SET 5, L + RegHL.Low |= unchecked(0x20); + break; + case 0xEE: // SET 5, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x20))); + break; + case 0xEF: // SET 5, A + RegAF.High |= unchecked(0x20); + break; + case 0xF0: // SET 6, B + RegBC.High |= unchecked(0x40); + break; + case 0xF1: // SET 6, C + RegBC.Low |= unchecked(0x40); + break; + case 0xF2: // SET 6, D + RegDE.High |= unchecked(0x40); + break; + case 0xF3: // SET 6, E + RegDE.Low |= unchecked(0x40); + break; + case 0xF4: // SET 6, H + RegHL.High |= unchecked(0x40); + break; + case 0xF5: // SET 6, L + RegHL.Low |= unchecked(0x40); + break; + case 0xF6: // SET 6, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x40))); + break; + case 0xF7: // SET 6, A + RegAF.High |= unchecked(0x40); + break; + case 0xF8: // SET 7, B + RegBC.High |= unchecked(0x80); + break; + case 0xF9: // SET 7, C + RegBC.Low |= unchecked(0x80); + break; + case 0xFA: // SET 7, D + RegDE.High |= unchecked(0x80); + break; + case 0xFB: // SET 7, E + RegDE.Low |= unchecked(0x80); + break; + case 0xFC: // SET 7, H + RegHL.High |= unchecked(0x80); + break; + case 0xFD: // SET 7, L + RegHL.Low |= unchecked(0x80); + break; + case 0xFE: // SET 7, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x80))); + break; + case 0xFF: // SET 7, A + RegAF.High |= unchecked(0x80); + break; + } + break; + case 0xCC: // CALL Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (FlagZ) + { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + } + break; + case 0xCD: // CALL nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + break; + case 0xCE: // ADC n + TB = ReadMemory(RegPC.Word++); + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High + TB + TI2; + RegAF.Low = 0; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 > 0xFF) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) + (TB & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0xCF: // RST $08 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x08; + break; + case 0xD0: // RET NC + if (!FlagC) + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + break; + case 0xD1: // POP DE + RegDE.Low = ReadMemory(RegSP.Word++); RegDE.High = ReadMemory(RegSP.Word++); + break; + case 0xD2: // JP NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!FlagC) + RegPC.Word = TUS; + break; + case 0xD3: // NOP + break; + case 0xD4: // CALL NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!FlagC) + { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + } + break; + case 0xD5: // PUSH DE + WriteMemory(--RegSP.Word, RegDE.High); WriteMemory(--RegSP.Word, RegDE.Low); + break; + case 0xD6: // SUB n + TB = ReadMemory(RegPC.Word++); + TI1 = RegAF.High - TB; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0xD7: // RST $10 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x10; + break; + case 0xD8: // RET C + if (FlagC) + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + break; + case 0xD9: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + // TODO Nothing else special needs to be done? + break; + case 0xDA: // JP C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (FlagC) + RegPC.Word = TUS; + break; + case 0xDB: // NOP + break; + case 0xDC: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (FlagC) + { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + } + break; + case 0xDD: // NOP + break; + case 0xDE: // SBC A, n + TB = ReadMemory(RegPC.Word++); + TI2 = FlagC ? 1 : 0; + TI1 = RegAF.High - TB - TI2; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (TB & 0x0F) - TI2 < 0) RegAF.Low |= 0x20; + RegAF.High = (byte)TI1; + break; + case 0xDF: // RST $18 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x18; + break; + case 0xE0: // LD ($FF00+nn), A + WriteMemory((ushort)(0xFF00 + ReadMemory(RegPC.Word++)), RegAF.High); + break; + case 0xE1: // POP HL + RegHL.Low = ReadMemory(RegSP.Word++); RegHL.High = ReadMemory(RegSP.Word++); + break; + case 0xE2: // LD ($FF00+C), A + WriteMemory((ushort)(0xFF00 + RegBC.Low), RegAF.High); + break; + case 0xE3: // NOP + break; + case 0xE4: // NOP + break; + case 0xE5: // PUSH HL + WriteMemory(--RegSP.Word, RegHL.High); WriteMemory(--RegSP.Word, RegHL.Low); + break; + case 0xE6: // AND n + RegAF.High &= ReadMemory(RegPC.Word++); + RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20); + break; + case 0xE7: // RST $20 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x20; + break; + case 0xE8: // ADD SP, n + Console.WriteLine("E8 : ADD SP, n being executed. verify correctness"); + TSB = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Low = 0; + if (RegSP.Word + TSB > 0xFFFF) RegAF.Low |= 0x10; + if (((RegSP.Word & 0xFFF) + TSB) > 0xFFF) RegAF.Low |= 0x20; + RegSP.Word = (ushort)(RegSP.Word + TSB); + break; + case 0xE9: // JP HL + RegPC.Word = RegHL.Word; + break; + case 0xEA: // LD (imm), A + TUS = (ushort)(ReadMemory(RegPC.Word++) | (ReadMemory(RegPC.Word++) << 8)); + WriteMemory(TUS, RegAF.High); + break; + case 0xEB: // NOP + break; + case 0xEC: // NOP + break; + case 0xED: // NOP + break; + case 0xEE: // XOR n + RegAF.High ^= ReadMemory(RegPC.Word++); + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xEF: // RST $28 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x28; + break; + case 0xF0: // LD A, ($FF00+nn) + RegAF.High = ReadMemory((ushort)(0xFF00 + ReadMemory(RegPC.Word++))); + break; + case 0xF1: // POP AF + RegAF.Low = ReadMemory(RegSP.Word++); RegAF.High = ReadMemory(RegSP.Word++); + break; + case 0xF2: // LD A, ($FF00+C) + RegAF.High = ReadMemory((ushort)(0xFF00 + RegBC.Low)); + break; + case 0xF3: // DI + IFF1 = IFF2 = false; + break; + case 0xF4: // NOP + break; + case 0xF5: // PUSH AF + WriteMemory(--RegSP.Word, RegAF.High); WriteMemory(--RegSP.Word, RegAF.Low); + break; + case 0xF6: // OR n + RegAF.High |= ReadMemory(RegPC.Word++); + RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0); + break; + case 0xF7: // RST $30 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x30; + break; + case 0xF8: // LD HL, SP+nn + Console.WriteLine("F8 : LD HL, SP+n being executed. verify correctness"); + TSB = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Low = 0; + if (RegSP.Word + TSB > 0xFFFF) RegAF.Low |= 0x10; + if (((RegSP.Word & 0xFFF) + TSB) > 0xFFF) RegAF.Low |= 0x20; + RegHL.Word = (ushort)(RegSP.Word + TSB); + break; + case 0xF9: // LD SP, HL + RegSP.Word = RegHL.Word; + break; + case 0xFA: // LD A, (nnnn) + TUS = (ushort)(ReadMemory(RegPC.Word++) | (ReadMemory(RegPC.Word++) << 8)); + RegAF.High = ReadMemory(TUS); + break; + case 0xFB: // EI + IFF1 = IFF2 = true; + Interruptable = false; + break; + case 0xFC: // NOP + break; + case 0xFD: // NOP + break; + case 0xFE: // CP n + TB = ReadMemory(RegPC.Word++); + TI1 = RegAF.High - TB; + RegAF.Low = 0x40; + if ((byte)TI1 == 0) RegAF.Low |= 0x80; + if (TI1 < 0) RegAF.Low |= 0x10; + if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20; + break; + case 0xFF: // RST $38 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x38; + break; + default: throw new Exception("unhandled opcode"); + } + } + + void CheckIrq() + { + if (nonMaskableInterruptPending) + { + halted = false; + + PendingCycles -= 3; + TotalExecutedCycles += 3; + nonMaskableInterruptPending = false; + + iff2 = iff1; + iff1 = false; + + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x66; + } + else if (iff1 && interrupt && Interruptable) + { + Halted = false; + + iff1 = iff2 = false; + + switch (interruptMode) + { + case 0: + PendingCycles -= 4; + TotalExecutedCycles += 4; + break; + case 1: + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x38; + PendingCycles -= 4; + TotalExecutedCycles += 4; + break; + case 2: + ushort TUS = (ushort)(RegI * 256 + 0); + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Low = ReadMemory(TUS++); RegPC.High = ReadMemory(TUS); + PendingCycles -= 5; + TotalExecutedCycles += 5; + break; + } + } + } + + public void SingleStepInto() + { + if (halted) return; + ExecuteInstruction(); + CheckIrq(); + } + + public void ExecuteCycles(int cycles) + { + PendingCycles += cycles; + + while (PendingCycles > 0) + { + Interruptable = true; + + if (halted) + { + PendingCycles -= 1; + } + else + { + ExecuteInstruction(); + } + + CheckIrq(); + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80-GB/Interrupts.cs b/BizHawk.Emulation/CPUs/Z80-GB/Interrupts.cs new file mode 100644 index 0000000000..f876089c07 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80-GB/Interrupts.cs @@ -0,0 +1,52 @@ +using System; + +namespace BizHawk.Emulation.CPUs.Z80GB +{ + public partial class Z80 + { + private bool iff1; + public bool IFF1 { get { return iff1; } set { iff1 = value; } } + + private bool iff2; + public bool IFF2 { get { return iff2; } set { iff2 = value; } } + + private bool interrupt; + public bool Interrupt { get { return interrupt; } set { interrupt = value; } } + + private bool nonMaskableInterrupt; + public bool NonMaskableInterrupt + { + get { return nonMaskableInterrupt; } + set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; } + } + + private bool nonMaskableInterruptPending; + public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } } + + private int interruptMode; + public int InterruptMode + { + get { return interruptMode; } + set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; } + } + + private bool halted; + public bool Halted { get { return halted; } set { halted = value; } } + + private void ResetInterrupts() + { + IFF1 = false; + IFF2 = false; + Interrupt = false; + NonMaskableInterrupt = false; + NonMaskableInterruptPending = false; + InterruptMode = 1; + Halted = false; + } + + private void Halt() + { + Halted = true; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80-GB/Registers.cs b/BizHawk.Emulation/CPUs/Z80-GB/Registers.cs new file mode 100644 index 0000000000..4c4fcda434 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80-GB/Registers.cs @@ -0,0 +1,166 @@ +using System.Runtime.InteropServices; +using System; + +namespace BizHawk.Emulation.CPUs.Z80GB +{ + public partial class Z80 + { + [StructLayout(LayoutKind.Explicit)] + [Serializable] + public struct RegisterPair + { + [FieldOffset(0)] + public ushort Word; + + [FieldOffset(0)] + public byte Low; + + [FieldOffset(1)] + public byte High; + + public RegisterPair(ushort value) + { + Word = value; + Low = (byte)(Word); + High = (byte)(Word >> 8); + } + + public static implicit operator ushort(RegisterPair rp) + { + return rp.Word; + } + + public static implicit operator RegisterPair(ushort value) + { + return new RegisterPair(value); + } + } + + public bool FlagC + { + get { return (RegAF.Low & 0x10) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x10) | (value ? 0x10 : 0x00)); } + } + + public bool FlagH + { + get { return (RegAF.Low & 0x20) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x20) | (value ? 0x20 : 0x00)); } + } + + public bool FlagN + { + get { return (RegAF.Low & 0x40) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x40) | (value ? 0x40 : 0x00)); } + } + + public bool FlagZ + { + get { return (RegAF.Low & 0x80) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x80) | (value ? 0x80 : 0x00)); } + } + + private RegisterPair RegAF; + private RegisterPair RegBC; + private RegisterPair RegDE; + private RegisterPair RegHL; + + private byte RegI; // I (interrupt vector) + + private RegisterPair RegSP; // SP (stack pointer) + private RegisterPair RegPC; // PC (program counter) + + private void ResetRegisters() + { + RegAF = 0; RegBC = 0; RegDE = 0; RegHL = 0; + RegI = 0; + RegSP.Word = 0; RegPC.Word = 0; + } + + public byte RegisterA + { + get { return RegAF.High; } + set { RegAF.High = value; } + } + + public byte RegisterF + { + get { return RegAF.Low; } + set { RegAF.Low = (byte)(value&0xF0); } + } + + public ushort RegisterAF + { + get { return RegAF.Word; } + set { RegAF.Word = (byte)(value&0xFFF0); } + } + + public byte RegisterB + { + get { return RegBC.High; } + set { RegBC.High = value; } + } + + public byte RegisterC + { + get { return RegBC.Low; } + set { RegBC.Low = value; } + } + + public ushort RegisterBC + { + get { return RegBC.Word; } + set { RegBC.Word = value; } + } + + public byte RegisterD + { + get { return RegDE.High; } + set { RegDE.High = value; } + } + + public byte RegisterE + { + get { return RegDE.Low; } + set { RegDE.Low = value; } + } + public ushort RegisterDE + { + get { return RegDE.Word; } + set { RegDE.Word = value; } + } + + public byte RegisterH + { + get { return RegHL.High; } + set { RegHL.High = value; } + } + + public byte RegisterL + { + get { return RegHL.Low; } + set { RegHL.Low = value; } + } + public ushort RegisterHL + { + get { return RegHL.Word; } + set { RegHL.Word = value; } + } + + public ushort RegisterPC + { + get { return RegPC.Word; } + set { RegPC.Word = value; } + } + public ushort RegisterSP + { + get { return RegSP.Word; } + set { RegSP.Word = value; } + } + public byte RegisterI + { + get { return RegI; } + set { RegI = value; } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80-GB/Tables.cs b/BizHawk.Emulation/CPUs/Z80-GB/Tables.cs new file mode 100644 index 0000000000..bc876c7e08 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80-GB/Tables.cs @@ -0,0 +1,149 @@ +namespace BizHawk.Emulation.CPUs.Z80GB +{ + public partial class Z80 + { + private void InitializeTables() + { + InitTableDaa(); + } + + private static readonly byte[] IncTable = + { + 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + private static readonly byte[] DecTable = + { + 192, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96, + 064, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96 + }; + + private static readonly byte[] SwapTable = + { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF + }; + + private static readonly byte[] mCycleTable = new byte[] + { + 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, + 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, + 3, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, + 3, 3, 2, 2, 1, 3, 3, 3, 3, 2, 2, 2, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 5, 3, 4, 4, 6, 4, 2, 4, 5, 4, 4, 1, 6, 6, 2, 4, + 5, 3, 4, 0, 6, 4, 2, 4, 5, 4, 4, 0, 6, 0, 2, 4, + 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4, + 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4, + }; + + private static readonly byte[] cbMCycleTable = new byte[] + { + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, + }; + + private ushort[] TableDaa; + private void InitTableDaa() + { + TableDaa = new ushort[65536]; + for (int af = 0; af < 65536; ++af) + { + byte a = (byte)(af >> 8); + byte tmp = a; + + if (IsN(af)) + { + if (IsH(af) || ((a & 0x0F) > 0x09)) tmp -= 0x06; + if (IsC(af) || a > 0x99) tmp -= 0x60; + } + else + { + if (IsH(af) || ((a & 0x0F) > 0x09)) tmp += 0x06; + if (IsC(af) || a > 0x99) tmp += 0x60; + } + + TableDaa[af] = (ushort)((tmp * 256) + FlagByte(IsC(af) || a > 0x99, ((a ^ tmp) & 0x10) != 0, IsN(af), tmp == 0)); + } + } + + private static byte FlagByte(bool C, bool H, bool N, bool Z) + { + return (byte)( + (C ? 0x10 : 0) + + (H ? 0x20 : 0) + + (N ? 0x40 : 0) + + (Z ? 0x80 : 0) + ); + } + + private static bool IsC(int value) { return (value & 0x10) != 0; } + private static bool IsH(int value) { return (value & 0x20) != 0; } + private static bool IsN(int value) { return (value & 0x40) != 0; } + private static bool IsZ(int value) { return (value & 0x80) != 0; } + } +} diff --git a/BizHawk.Emulation/CPUs/Z80-GB/Z80.cs b/BizHawk.Emulation/CPUs/Z80-GB/Z80.cs new file mode 100644 index 0000000000..92fd75a98e --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80-GB/Z80.cs @@ -0,0 +1,147 @@ +using System; +using System.Globalization; +using System.IO; + +// This Z80-Gameboy emulator is a modified version of Ben Ryves 'Brazil' emulator. +// It is MIT licensed (not public domain). (See Licenses) + +namespace BizHawk.Emulation.CPUs.Z80GB +{ + public sealed partial class Z80 + { + public Z80() + { + InitializeTables(); + Reset(); + } + + public void Reset() + { + ResetRegisters(); + ResetInterrupts(); + PendingCycles = 0; + TotalExecutedCycles = 0; + } + + // Memory Access + + public Func ReadMemory; + public Action WriteMemory; + + public void UnregisterMemoryMapper() + { + ReadMemory = null; + WriteMemory = null; + } + + // State Save/Load + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[Z80]"); + writer.WriteLine("AF {0:X4}", RegAF.Word); + writer.WriteLine("BC {0:X4}", RegBC.Word); + writer.WriteLine("DE {0:X4}", RegDE.Word); + writer.WriteLine("HL {0:X4}", RegHL.Word); + writer.WriteLine("I {0:X2}", RegI); + writer.WriteLine("SP {0:X4}", RegSP.Word); + writer.WriteLine("PC {0:X4}", RegPC.Word); + writer.WriteLine("IRQ {0}", interrupt); + writer.WriteLine("NMI {0}", nonMaskableInterrupt); + writer.WriteLine("NMIPending {0}", nonMaskableInterruptPending); + writer.WriteLine("IM {0}", InterruptMode); + writer.WriteLine("IFF1 {0}", IFF1); + writer.WriteLine("IFF2 {0}", IFF2); + writer.WriteLine("Halted {0}", Halted); + writer.WriteLine("ExecutedCycles {0}", TotalExecutedCycles); + writer.WriteLine("PendingCycles {0}", PendingCycles); + writer.WriteLine("[/Z80]"); + writer.WriteLine(); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/Z80]") break; + if (args[0] == "AF") + RegAF.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "BC") + RegBC.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "DE") + RegDE.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "HL") + RegHL.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "I") + RegI = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "SP") + RegSP.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "PC") + RegPC.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "IRQ") + interrupt = bool.Parse(args[1]); + else if (args[0] == "NMI") + nonMaskableInterrupt = bool.Parse(args[1]); + else if (args[0] == "NMIPending") + nonMaskableInterruptPending = bool.Parse(args[1]); + else if (args[0] == "IM") + InterruptMode = int.Parse(args[1]); + else if (args[0] == "IFF1") + IFF1 = bool.Parse(args[1]); + else if (args[0] == "IFF2") + IFF2 = bool.Parse(args[1]); + else if (args[0] == "Halted") + Halted = bool.Parse(args[1]); + else if (args[0] == "ExecutedCycles") + TotalExecutedCycles = int.Parse(args[1]); + else if (args[0] == "PendingCycles") + PendingCycles = int.Parse(args[1]); + + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(RegAF.Word); + writer.Write(RegBC.Word); + writer.Write(RegDE.Word); + writer.Write(RegHL.Word); + writer.Write(RegI); + writer.Write(RegSP.Word); + writer.Write(RegPC.Word); + writer.Write(interrupt); + writer.Write(nonMaskableInterrupt); + writer.Write(nonMaskableInterruptPending); + writer.Write(InterruptMode); + writer.Write(IFF1); + writer.Write(IFF2); + writer.Write(Halted); + writer.Write(TotalExecutedCycles); + writer.Write(PendingCycles); + } + + public void LoadStateBinary(BinaryReader reader) + { + RegAF.Word = reader.ReadUInt16(); + RegBC.Word = reader.ReadUInt16(); + RegDE.Word = reader.ReadUInt16(); + RegHL.Word = reader.ReadUInt16(); + RegI = reader.ReadByte(); + RegSP.Word = reader.ReadUInt16(); + RegPC.Word = reader.ReadUInt16(); + interrupt = reader.ReadBoolean(); + nonMaskableInterrupt = reader.ReadBoolean(); + nonMaskableInterruptPending = reader.ReadBoolean(); + InterruptMode = reader.ReadInt32(); + IFF1 = reader.ReadBoolean(); + IFF2 = reader.ReadBoolean(); + Halted = reader.ReadBoolean(); + TotalExecutedCycles = reader.ReadInt32(); + PendingCycles = reader.ReadInt32(); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80/Disassembler.cs b/BizHawk.Emulation/CPUs/Z80/Disassembler.cs new file mode 100644 index 0000000000..038c618314 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80/Disassembler.cs @@ -0,0 +1,297 @@ +using System; + +namespace BizHawk.Emulation.CPUs.Z80 +{ + public partial class Z80A + { + #region Mnemonics + private static readonly string[] Opcodes = new[] + { + "NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA", + "EX AF,AF'","ADD HL,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA", + "DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA", + "JR @h","ADD HL,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA", + "JR NZ,@h","LD HL,#h","LD (#h),HL","INC HL","INC H","DEC H","LD H,*h","DAA", + "JR Z,@h","ADD HL,HL","LD HL,(#h)","DEC HL","INC L","DEC L","LD L,*h","CPL", + "JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (HL)","DEC (HL)","LD (HL),*h","SCF", + "JR C,@h","ADD HL,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF", + "LD B,B","LD B,C","LD B,D","LD B,E","LD B,H","LD B,L","LD B,(HL)","LD B,A", + "LD C,B","LD C,C","LD C,D","LD C,E","LD C,H","LD C,L","LD C,(HL)","LD C,A", + "LD D,B","LD D,C","LD D,D","LD D,E","LD D,H","LD D,L","LD D,(HL)","LD D,A", + "LD E,B","LD E,C","LD E,D","LD E,E","LD E,H","LD E,L","LD E,(HL)","LD E,A", + "LD H,B","LD H,C","LD H,D","LD H,E","LD H,H","LD H,L","LD H,(HL)","LD H,A", + "LD L,B","LD L,C","LD L,D","LD L,E","LD L,H","LD L,L","LD L,(HL)","LD L,A", + "LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E","LD (HL),H","LD (HL),L","HALT","LD (HL),A", + "LD A,B","LD A,C","LD A,D","LD A,E","LD A,H","LD A,L","LD A,(HL)","LD A,A", + "ADD B","ADD C","ADD D","ADD E","ADD H","ADD L","ADD (HL)","ADD A", + "ADC B","ADC C","ADC D","ADC E","ADC H","ADC L","ADC (HL)","ADC A", + "SUB B","SUB C","SUB D","SUB E","SUB H","SUB L","SUB (HL)","SUB A", + "SBC B","SBC C","SBC D","SBC E","SBC H","SBC L","SBC (HL)","SBC A", + "AND B","AND C","AND D","AND E","AND H","AND L","AND (HL)","AND A", + "XOR B","XOR C","XOR D","XOR E","XOR H","XOR L","XOR (HL)","XOR A", + "OR B","OR C","OR D","OR E","OR H","OR L","OR (HL)","OR A", + "CP B","CP C","CP D","CP E","CP H","CP L","CP (HL)","CP A", + "RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h", + "RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h", + "RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h", + "RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h", + "RET PO","POP HL","JP PO,#h","EX HL,(SP)","CALL PO,#h","PUSH HL","AND *h","RST 20h", + "RET PE","LD PC,HL","JP PE,#h","EX DE,HL","CALL PE,#h","PFX_ED","XOR *h","RST 28h", + "RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h", + "RET M","LD SP,HL","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h" + }; + + private static readonly string[] CBPrefixOpcodes = new[] + { + "RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (HL)","RLC A", + "RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (HL)","RRC A", + "RL B","RL C","RL D","RL E","RL H","RL L","RL (HL)","RL A", + "RR B","RR C","RR D","RR E","RR H","RR L","RR (HL)","RR A", + "SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (HL)","SLA A", + "SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (HL)","SRA A", + "SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (HL)","SLL A", + "SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (HL)","SRL A", + "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A", + "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A", + "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A", + "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A", + "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A", + "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A", + "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A", + "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A", + "RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A", + "RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A", + "RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A", + "RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A", + "RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A", + "RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A", + "RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A", + "RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A", + "SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A", + "SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A", + "SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A", + "SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A", + "SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A", + "SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A", + "SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A", + "SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A" + }; + + private static readonly string[] EDPrefixOpcodes = new[] + { + "DB EDh,00h","DB EDh,01h","DB EDh,02h","DB EDh,03h", + "DB EDh,04h","DB EDh,05h","DB EDh,06h","DB EDh,07h", + "DB EDh,08h","DB EDh,09h","DB EDh,0Ah","DB EDh,0Bh", + "DB EDh,0Ch","DB EDh,0Dh","DB EDh,0Eh","DB EDh,0Fh", + "DB EDh,10h","DB EDh,11h","DB EDh,12h","DB EDh,13h", + "DB EDh,14h","DB EDh,15h","DB EDh,16h","DB EDh,17h", + "DB EDh,18h","DB EDh,19h","DB EDh,1Ah","DB EDh,1Bh", + "DB EDh,1Ch","DB EDh,1Dh","DB EDh,1Eh","DB EDh,1Fh", + "DB EDh,20h","DB EDh,21h","DB EDh,22h","DB EDh,23h", + "DB EDh,24h","DB EDh,25h","DB EDh,26h","DB EDh,27h", + "DB EDh,28h","DB EDh,29h","DB EDh,2Ah","DB EDh,2Bh", + "DB EDh,2Ch","DB EDh,2Dh","DB EDh,2Eh","DB EDh,2Fh", + "DB EDh,30h","DB EDh,31h","DB EDh,32h","DB EDh,33h", + "DB EDh,34h","DB EDh,35h","DB EDh,36h","DB EDh,37h", + "DB EDh,38h","DB EDh,39h","DB EDh,3Ah","DB EDh,3Bh", + "DB EDh,3Ch","DB EDh,3Dh","DB EDh,3Eh","DB EDh,3Fh", + "IN B,(C)","OUT (C),B","SBC HL,BC","LD (#h),BC", + "NEG","RETN","IM 0","LD I,A", + "IN C,(C)","OUT (C),C","ADC HL,BC","LD BC,(#h)", + "DB EDh,4Ch","RETI","DB EDh,4Eh","LD R,A", + "IN D,(C)","OUT (C),D","SBC HL,DE","LD (#h),DE", + "DB EDh,54h","DB EDh,55h","IM 1","LD A,I", + "IN E,(C)","OUT (C),E","ADC HL,DE","LD DE,(#h)", + "DB EDh,5Ch","DB EDh,5Dh","IM 2","LD A,R", + "IN H,(C)","OUT (C),H","SBC HL,HL","LD (#h),HL", + "DB EDh,64h","DB EDh,65h","DB EDh,66h","RRD", + "IN L,(C)","OUT (C),L","ADC HL,HL","LD HL,(#h)", + "DB EDh,6Ch","DB EDh,6Dh","DB EDh,6Eh","RLD", + "IN F,(C)","DB EDh,71h","SBC HL,SP","LD (#h),SP", + "DB EDh,74h","DB EDh,75h","DB EDh,76h","DB EDh,77h", + "IN A,(C)","OUT (C),A","ADC HL,SP","LD SP,(#h)", + "DB EDh,7Ch","DB EDh,7Dh","DB EDh,7Eh","DB EDh,7Fh", + "DB EDh,80h","DB EDh,81h","DB EDh,82h","DB EDh,83h", + "DB EDh,84h","DB EDh,85h","DB EDh,86h","DB EDh,87h", + "DB EDh,88h","DB EDh,89h","DB EDh,8Ah","DB EDh,8Bh", + "DB EDh,8Ch","DB EDh,8Dh","DB EDh,8Eh","DB EDh,8Fh", + "DB EDh,90h","DB EDh,91h","DB EDh,92h","DB EDh,93h", + "DB EDh,94h","DB EDh,95h","DB EDh,96h","DB EDh,97h", + "DB EDh,98h","DB EDh,99h","DB EDh,9Ah","DB EDh,9Bh", + "DB EDh,9Ch","DB EDh,9Dh","DB EDh,9Eh","DB EDh,9Fh", + "LDI","CPI","INI","OUTI", + "DB EDh,A4h","DB EDh,A5h","DB EDh,A6h","DB EDh,A7h", + "LDD","CPD","IND","OUTD", + "DB EDh,ACh","DB EDh,ADh","DB EDh,AEh","DB EDh,AFh", + "LDIR","CPIR","INIR","OTIR", + "DB EDh,B4h","DB EDh,B5h","DB EDh,B6h","DB EDh,B7h", + "LDDR","CPDR","INDR","OTDR", + "DB EDh,BCh","DB EDh,BDh","DB EDh,BEh","DB EDh,BFh", + "DB EDh,C0h","DB EDh,C1h","DB EDh,C2h","DB EDh,C3h", + "DB EDh,C4h","DB EDh,C5h","DB EDh,C6h","DB EDh,C7h", + "DB EDh,C8h","DB EDh,C9h","DB EDh,CAh","DB EDh,CBh", + "DB EDh,CCh","DB EDh,CDh","DB EDh,CEh","DB EDh,CFh", + "DB EDh,D0h","DB EDh,D1h","DB EDh,D2h","DB EDh,D3h", + "DB EDh,D4h","DB EDh,D5h","DB EDh,D6h","DB EDh,D7h", + "DB EDh,D8h","DB EDh,D9h","DB EDh,DAh","DB EDh,DBh", + "DB EDh,DCh","DB EDh,DDh","DB EDh,DEh","DB EDh,DFh", + "DB EDh,E0h","DB EDh,E1h","DB EDh,E2h","DB EDh,E3h", + "DB EDh,E4h","DB EDh,E5h","DB EDh,E6h","DB EDh,E7h", + "DB EDh,E8h","DB EDh,E9h","DB EDh,EAh","DB EDh,EBh", + "DB EDh,ECh","DB EDh,EDh","DB EDh,EEh","DB EDh,EFh", + "DB EDh,F0h","DB EDh,F1h","DB EDh,F2h","DB EDh,F3h", + "DB EDh,F4h","DB EDh,F5h","DB EDh,F6h","DB EDh,F7h", + "DB EDh,F8h","DB EDh,F9h","DB EDh,FAh","DB EDh,FBh", + "DB EDh,FCh","DB EDh,FDh","DB EDh,FEh","DB EDh,FFh" + }; + + private static readonly string[] DDPrefixOpcodes = new[] + { + "NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA", + "EX AF,AF'","ADD I%,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA", + "DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA", + "JR @h","ADD I%,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA", + "JR NZ,@h","LD I%,#h","LD (#h),I%","INC I%","INC I%h","DEC I%h","LD I%h,*h","DAA", + "JR Z,@h","ADD I%,I%","LD I%,(#h)","DEC I%","INC I%l","DEC I%l","LD I%l,*h","CPL", + "JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (I%+^h)","DEC (I%+^h)","LD (I%+^h),*h","SCF", + "JR C,@h","ADD I%,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF", + "LD B,B","LD B,C","LD B,D","LD B,E","LD B,I%h","LD B,I%l","LD B,(I%+^h)","LD B,A", + "LD C,B","LD C,C","LD C,D","LD C,E","LD C,I%h","LD C,I%l","LD C,(I%+^h)","LD C,A", + "LD D,B","LD D,C","LD D,D","LD D,E","LD D,I%h","LD D,I%l","LD D,(I%+^h)","LD D,A", + "LD E,B","LD E,C","LD E,D","LD E,E","LD E,I%h","LD E,I%l","LD E,(I%+^h)","LD E,A", + "LD I%h,B","LD I%h,C","LD I%h,D","LD I%h,E","LD I%h,I%h","LD I%h,I%l","LD H,(I%+^h)","LD I%h,A", + "LD I%l,B","LD I%l,C","LD I%l,D","LD I%l,E","LD I%l,I%h","LD I%l,I%l","LD L,(I%+^h)","LD I%l,A", + "LD (I%+^h),B","LD (I%+^h),C","LD (I%+^h),D","LD (I%+^h),E","LD (I%+^h),H","LD (I%+^h),L","HALT","LD (I%+^h),A", + "LD A,B","LD A,C","LD A,D","LD A,E","LD A,I%h","LD A,I%l","LD A,(I%+^h)","LD A,A", + "ADD B","ADD C","ADD D","ADD E","ADD I%h","ADD I%l","ADD (I%+^h)","ADD A", + "ADC B","ADC C","ADC D","ADC E","ADC I%h","ADC I%l","ADC (I%+^h)","ADC,A", + "SUB B","SUB C","SUB D","SUB E","SUB I%h","SUB I%l","SUB (I%+^h)","SUB A", + "SBC B","SBC C","SBC D","SBC E","SBC I%h","SBC I%l","SBC (I%+^h)","SBC A", + "AND B","AND C","AND D","AND E","AND I%h","AND I%l","AND (I%+^h)","AND A", + "XOR B","XOR C","XOR D","XOR E","XOR I%h","XOR I%l","XOR (I%+^h)","XOR A", + "OR B","OR C","OR D","OR E","OR I%h","OR I%l","OR (I%+^h)","OR A", + "CP B","CP C","CP D","CP E","CP I%h","CP I%l","CP (I%+^h)","CP A", + "RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h", + "RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h", + "RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h", + "RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h", + "RET PO","POP I%","JP PO,#h","EX I%,(SP)","CALL PO,#h","PUSH I%","AND *h","RST 20h", + "RET PE","LD PC,I%","JP PE,#h","EX DE,I%","CALL PE,#h","PFX_ED","XOR *h","RST 28h", + "RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h", + "RET M","LD SP,I%","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h" + }; + + private static readonly string[] DDCBPrefixOpcodes = new[] + { + "RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (I%@h)","RLC A", + "RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (I%@h)","RRC A", + "RL B","RL C","RL D","RL E","RL H","RL L","RL (I%@h)","RL A", + "RR B","RR C","RR D","RR E","RR H","RR L","RR (I%@h)","RR A", + "SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (I%@h)","SLA A", + "SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (I%@h)","SRA A", + "SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (I%@h)","SLL A", + "SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (I%@h)","SRL A", + "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(I%@h)","BIT 0,A", + "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(I%@h)","BIT 1,A", + "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(I%@h)","BIT 2,A", + "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(I%@h)","BIT 3,A", + "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(I%@h)","BIT 4,A", + "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(I%@h)","BIT 5,A", + "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(I%@h)","BIT 6,A", + "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(I%@h)","BIT 7,A", + "RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(I%@h)","RES 0,A", + "RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(I%@h)","RES 1,A", + "RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(I%@h)","RES 2,A", + "RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(I%@h)","RES 3,A", + "RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(I%@h)","RES 4,A", + "RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(I%@h)","RES 5,A", + "RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(I%@h)","RES 6,A", + "RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(I%@h)","RES 7,A", + "SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(I%@h)","SET 0,A", + "SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(I%@h)","SET 1,A", + "SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(I%@h)","SET 2,A", + "SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(I%@h)","SET 3,A", + "SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(I%@h)","SET 4,A", + "SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(I%@h)","SET 5,A", + "SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(I%@h)","SET 6,A", + "SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(I%@h)","SET 7,A" + }; + #endregion + + public string Disassemble(ushort pc, out int bytesToAdvance) + { + byte op = ReadMemory(pc++); + string disassembly; + switch (op) + { + case 0xCB: + op = ReadMemory(pc++); + disassembly = CBPrefixOpcodes[op]; + bytesToAdvance = 2; + break; + case 0xED: + op = ReadMemory(pc++); + disassembly = EDPrefixOpcodes[op]; + bytesToAdvance = 2; + break; + case 0xDD: + op = ReadMemory(pc++); + if (op == 0xCB) + { + op = ReadMemory(pc++); + disassembly = DDCBPrefixOpcodes[op]; + bytesToAdvance = 3; + } else { + disassembly = DDPrefixOpcodes[op]; + bytesToAdvance = 2; + } + break; + default: + disassembly = Opcodes[op]; + bytesToAdvance = 1; + break; + } + + if (disassembly.IndexOf('*') != -1) + { + disassembly = disassembly.Replace("*", string.Format("{0:X2}", ReadMemory(pc++))); + bytesToAdvance++; + } + if (disassembly.IndexOf('#') != -1) + { + byte L = ReadMemory(pc++); + byte H = ReadMemory(pc++); + disassembly = disassembly.Replace("#", string.Format("{0:X4}", H << 8 | L)); + bytesToAdvance += 2; + } + if (disassembly.IndexOf('@') != -1) + { + sbyte b = (sbyte) ReadMemory(pc++); + char sign = b < 0 ? '-' : '+'; + disassembly = disassembly.Replace("@", string.Format("{0}{1:X2}", sign, b)); + bytesToAdvance++; + } + + return disassembly; + } + + public string State() + { + int notused; + string a = string.Format("{0:X4} {1}", RegPC.Word, Disassemble(RegPC.Word, out notused)).PadRight(41); + string b = string.Format("AF: {0:X4} BC: {1:X4} DE: {2:X4} HL: {3:X4} IX: {4:X4} IY: {5:X4} SP: {6:X4} ", + RegAF.Word, RegBC.Word, RegDE.Word, RegHL.Word, RegIX.Word, RegIY.Word, RegSP.Word); + string val = a + b; + if (RegFlagC) val += "C"; + if (RegFlagN) val += "N"; + if (RegFlagP) val += "P"; + if (RegFlag3) val += "3"; + if (RegFlagH) val += "H"; + if (RegFlag5) val += "5"; + if (RegFlagZ) val += "Z"; + if (RegFlagS) val += "S"; + + return val; + } + } +} diff --git a/BizHawk.Emulation/CPUs/Z80/Execute.cs b/BizHawk.Emulation/CPUs/Z80/Execute.cs new file mode 100644 index 0000000000..11fe3120ec --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80/Execute.cs @@ -0,0 +1,11636 @@ +namespace BizHawk.Emulation.CPUs.Z80 +{ + public partial class Z80A + { + private int totalExecutedCycles; + public int TotalExecutedCycles { get { return totalExecutedCycles; } set { totalExecutedCycles = value; } } + + private int expectedExecutedCycles; + public int ExpectedExecutedCycles { get { return expectedExecutedCycles; } set { expectedExecutedCycles = value; } } + + private int pendingCycles; + public int PendingCycles { get { return pendingCycles; } set { pendingCycles = value; } } + + /// + /// Runs the CPU for a particular number of clock cycles. + /// + /// The number of cycles to run the CPU emulator for. Specify -1 to run for a single instruction. + public void ExecuteCycles(int cycles) + { + expectedExecutedCycles += cycles; + pendingCycles += cycles; + + sbyte Displacement; + + byte TB; byte TBH; byte TBL; byte TB1; byte TB2; sbyte TSB; ushort TUS; int TI1; int TI2; int TIR; + + bool Interruptable; + + while (pendingCycles > 0) + { + Interruptable = true; + + if (halted) + { + ++RegR; + totalExecutedCycles += 4; pendingCycles -= 4; + } else { + ++RegR; +//System.Console.WriteLine(State()); + + switch (ReadMemory(RegPC.Word++)) + { + case 0x00: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x01: // LD BC, nn + RegBC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x02: // LD (BC), A + WriteMemory(RegBC.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x03: // INC BC + ++RegBC.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x04: // INC B + RegAF.Low = (byte)(TableInc[++RegBC.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x05: // DEC B + RegAF.Low = (byte)(TableDec[--RegBC.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x06: // LD B, n + RegBC.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x07: // RLCA + RegAF.Word = TableRotShift[0, 0, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x08: // EX AF, AF' + TUS = RegAF.Word; RegAF.Word = RegAltAF.Word; RegAltAF.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x09: // ADD HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0x0A: // LD A, (BC) + RegAF.High = ReadMemory(RegBC.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x0B: // DEC BC + --RegBC.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x0C: // INC C + RegAF.Low = (byte)(TableInc[++RegBC.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0D: // DEC C + RegAF.Low = (byte)(TableDec[--RegBC.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0E: // LD C, n + RegBC.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x0F: // RRCA + RegAF.Word = TableRotShift[0, 1, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x10: // DJNZ d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (--RegBC.High != 0) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 13; pendingCycles -= 13; + } else { + totalExecutedCycles += 8; pendingCycles -= 8; + } + break; + case 0x11: // LD DE, nn + RegDE.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x12: // LD (DE), A + WriteMemory(RegDE.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x13: // INC DE + ++RegDE.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x14: // INC D + RegAF.Low = (byte)(TableInc[++RegDE.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x15: // DEC D + RegAF.Low = (byte)(TableDec[--RegDE.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x16: // LD D, n + RegDE.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x17: // RLA + RegAF.Word = TableRotShift[0, 2, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x18: // JR d + TSB = (sbyte)ReadMemory(RegPC.Word++); + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x19: // ADD HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0x1A: // LD A, (DE) + RegAF.High = ReadMemory(RegDE.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x1B: // DEC DE + --RegDE.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x1C: // INC E + RegAF.Low = (byte)(TableInc[++RegDE.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1D: // DEC E + RegAF.Low = (byte)(TableDec[--RegDE.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1E: // LD E, n + RegDE.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x1F: // RRA + RegAF.Word = TableRotShift[0, 3, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x20: // JR NZ, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!RegFlagZ) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x21: // LD HL, nn + RegHL.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x22: // LD (nn), HL + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegHL.Low); + WriteMemory(TUS, RegHL.High); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x23: // INC HL + ++RegHL.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x24: // INC H + RegAF.Low = (byte)(TableInc[++RegHL.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x25: // DEC H + RegAF.Low = (byte)(TableDec[--RegHL.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x26: // LD H, n + RegHL.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x27: // DAA + RegAF.Word = TableDaa[RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x28: // JR Z, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (RegFlagZ) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x29: // ADD HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0x2A: // LD HL, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegHL.Low = ReadMemory(TUS++); RegHL.High = ReadMemory(TUS); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x2B: // DEC HL + --RegHL.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x2C: // INC L + RegAF.Low = (byte)(TableInc[++RegHL.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2D: // DEC L + RegAF.Low = (byte)(TableDec[--RegHL.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2E: // LD L, n + RegHL.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x2F: // CPL + RegAF.High ^= 0xFF; RegFlagH = true; RegFlagN = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x30: // JR NC, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!RegFlagC) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x31: // LD SP, nn + RegSP.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x32: // LD (nn), A + WriteMemory((ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256), RegAF.High); + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 0x33: // INC SP + ++RegSP.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x34: // INC (HL) + TB = ReadMemory(RegHL.Word); RegAF.Low = (byte)(TableInc[++TB] | (RegAF.Low & 1)); WriteMemory(RegHL.Word, TB); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0x35: // DEC (HL) + TB = ReadMemory(RegHL.Word); RegAF.Low = (byte)(TableDec[--TB] | (RegAF.Low & 1)); WriteMemory(RegHL.Word, TB); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0x36: // LD (HL), n + WriteMemory(RegHL.Word, ReadMemory(RegPC.Word++)); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x37: // SCF + RegFlagH = false; RegFlagN = false; RegFlagC = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x38: // JR C, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (RegFlagC) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x39: // ADD HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0x3A: // LD A, (nn) + RegAF.High = ReadMemory((ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256)); + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 0x3B: // DEC SP + --RegSP.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x3C: // INC A + RegAF.Low = (byte)(TableInc[++RegAF.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3D: // DEC A + RegAF.Low = (byte)(TableDec[--RegAF.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3E: // LD A, n + RegAF.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x3F: // CCF + RegFlagH = RegFlagC; RegFlagN = false; RegFlagC ^= true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x40: // LD B, B + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x41: // LD B, C + RegBC.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x42: // LD B, D + RegBC.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x43: // LD B, E + RegBC.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x44: // LD B, H + RegBC.High = RegHL.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x45: // LD B, L + RegBC.High = RegHL.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x46: // LD B, (HL) + RegBC.High = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x47: // LD B, A + RegBC.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x48: // LD C, B + RegBC.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x49: // LD C, C + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4A: // LD C, D + RegBC.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4B: // LD C, E + RegBC.Low = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4C: // LD C, H + RegBC.Low = RegHL.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4D: // LD C, L + RegBC.Low = RegHL.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4E: // LD C, (HL) + RegBC.Low = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x4F: // LD C, A + RegBC.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x50: // LD D, B + RegDE.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x51: // LD D, C + RegDE.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x52: // LD D, D + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x53: // LD D, E + RegDE.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x54: // LD D, H + RegDE.High = RegHL.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x55: // LD D, L + RegDE.High = RegHL.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x56: // LD D, (HL) + RegDE.High = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x57: // LD D, A + RegDE.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x58: // LD E, B + RegDE.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x59: // LD E, C + RegDE.Low = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5A: // LD E, D + RegDE.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5B: // LD E, E + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5C: // LD E, H + RegDE.Low = RegHL.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5D: // LD E, L + RegDE.Low = RegHL.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5E: // LD E, (HL) + RegDE.Low = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x5F: // LD E, A + RegDE.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x60: // LD H, B + RegHL.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x61: // LD H, C + RegHL.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x62: // LD H, D + RegHL.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x63: // LD H, E + RegHL.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x64: // LD H, H + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x65: // LD H, L + RegHL.High = RegHL.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x66: // LD H, (HL) + RegHL.High = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x67: // LD H, A + RegHL.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x68: // LD L, B + RegHL.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x69: // LD L, C + RegHL.Low = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x6A: // LD L, D + RegHL.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x6B: // LD L, E + RegHL.Low = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x6C: // LD L, H + RegHL.Low = RegHL.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x6D: // LD L, L + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x6E: // LD L, (HL) + RegHL.Low = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x6F: // LD L, A + RegHL.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x70: // LD (HL), B + WriteMemory(RegHL.Word, RegBC.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x71: // LD (HL), C + WriteMemory(RegHL.Word, RegBC.Low); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x72: // LD (HL), D + WriteMemory(RegHL.Word, RegDE.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x73: // LD (HL), E + WriteMemory(RegHL.Word, RegDE.Low); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x74: // LD (HL), H + WriteMemory(RegHL.Word, RegHL.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x75: // LD (HL), L + WriteMemory(RegHL.Word, RegHL.Low); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x76: // HALT + Halt(); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x77: // LD (HL), A + WriteMemory(RegHL.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x78: // LD A, B + RegAF.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x79: // LD A, C + RegAF.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7A: // LD A, D + RegAF.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7B: // LD A, E + RegAF.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7C: // LD A, H + RegAF.High = RegHL.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7D: // LD A, L + RegAF.High = RegHL.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7E: // LD A, (HL) + RegAF.High = ReadMemory(RegHL.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x7F: // LD A, A + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x80: // ADD A, B + RegAF.Word = TableALU[0, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x81: // ADD A, C + RegAF.Word = TableALU[0, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x82: // ADD A, D + RegAF.Word = TableALU[0, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x83: // ADD A, E + RegAF.Word = TableALU[0, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x84: // ADD A, H + RegAF.Word = TableALU[0, RegAF.High, RegHL.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x85: // ADD A, L + RegAF.Word = TableALU[0, RegAF.High, RegHL.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x86: // ADD A, (HL) + RegAF.Word = TableALU[0, RegAF.High, ReadMemory(RegHL.Word), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x87: // ADD A, A + RegAF.Word = TableALU[0, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x88: // ADC A, B + RegAF.Word = TableALU[1, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x89: // ADC A, C + RegAF.Word = TableALU[1, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8A: // ADC A, D + RegAF.Word = TableALU[1, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8B: // ADC A, E + RegAF.Word = TableALU[1, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8C: // ADC A, H + RegAF.Word = TableALU[1, RegAF.High, RegHL.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8D: // ADC A, L + RegAF.Word = TableALU[1, RegAF.High, RegHL.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8E: // ADC A, (HL) + RegAF.Word = TableALU[1, RegAF.High, ReadMemory(RegHL.Word), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x8F: // ADC A, A + RegAF.Word = TableALU[1, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x90: // SUB B + RegAF.Word = TableALU[2, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x91: // SUB C + RegAF.Word = TableALU[2, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x92: // SUB D + RegAF.Word = TableALU[2, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x93: // SUB E + RegAF.Word = TableALU[2, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x94: // SUB H + RegAF.Word = TableALU[2, RegAF.High, RegHL.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x95: // SUB L + RegAF.Word = TableALU[2, RegAF.High, RegHL.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x96: // SUB (HL) + RegAF.Word = TableALU[2, RegAF.High, ReadMemory(RegHL.Word), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x97: // SUB A, A + RegAF.Word = TableALU[2, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x98: // SBC A, B + RegAF.Word = TableALU[3, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x99: // SBC A, C + RegAF.Word = TableALU[3, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9A: // SBC A, D + RegAF.Word = TableALU[3, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9B: // SBC A, E + RegAF.Word = TableALU[3, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9C: // SBC A, H + RegAF.Word = TableALU[3, RegAF.High, RegHL.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9D: // SBC A, L + RegAF.Word = TableALU[3, RegAF.High, RegHL.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9E: // SBC A, (HL) + RegAF.Word = TableALU[3, RegAF.High, ReadMemory(RegHL.Word), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x9F: // SBC A, A + RegAF.Word = TableALU[3, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA0: // AND B + RegAF.Word = TableALU[4, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA1: // AND C + RegAF.Word = TableALU[4, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA2: // AND D + RegAF.Word = TableALU[4, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA3: // AND E + RegAF.Word = TableALU[4, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA4: // AND H + RegAF.Word = TableALU[4, RegAF.High, RegHL.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA5: // AND L + RegAF.Word = TableALU[4, RegAF.High, RegHL.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA6: // AND (HL) + RegAF.Word = TableALU[4, RegAF.High, ReadMemory(RegHL.Word), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xA7: // AND A + RegAF.Word = TableALU[4, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA8: // XOR B + RegAF.Word = TableALU[5, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA9: // XOR C + RegAF.Word = TableALU[5, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAA: // XOR D + RegAF.Word = TableALU[5, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAB: // XOR E + RegAF.Word = TableALU[5, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAC: // XOR H + RegAF.Word = TableALU[5, RegAF.High, RegHL.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAD: // XOR L + RegAF.Word = TableALU[5, RegAF.High, RegHL.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAE: // XOR (HL) + RegAF.Word = TableALU[5, RegAF.High, ReadMemory(RegHL.Word), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xAF: // XOR A + RegAF.Word = TableALU[5, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB0: // OR B + RegAF.Word = TableALU[6, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB1: // OR C + RegAF.Word = TableALU[6, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB2: // OR D + RegAF.Word = TableALU[6, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB3: // OR E + RegAF.Word = TableALU[6, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB4: // OR H + RegAF.Word = TableALU[6, RegAF.High, RegHL.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB5: // OR L + RegAF.Word = TableALU[6, RegAF.High, RegHL.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB6: // OR (HL) + RegAF.Word = TableALU[6, RegAF.High, ReadMemory(RegHL.Word), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xB7: // OR A + RegAF.Word = TableALU[6, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB8: // CP B + RegAF.Word = TableALU[7, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB9: // CP C + RegAF.Word = TableALU[7, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBA: // CP D + RegAF.Word = TableALU[7, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBB: // CP E + RegAF.Word = TableALU[7, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBC: // CP H + RegAF.Word = TableALU[7, RegAF.High, RegHL.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBD: // CP L + RegAF.Word = TableALU[7, RegAF.High, RegHL.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBE: // CP (HL) + RegAF.Word = TableALU[7, RegAF.High, ReadMemory(RegHL.Word), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xBF: // CP A + RegAF.Word = TableALU[7, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC0: // RET NZ + if (!RegFlagZ) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xC1: // POP BC + RegBC.Low = ReadMemory(RegSP.Word++); RegBC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC2: // JP NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagZ) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC3: // JP nn + RegPC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC4: // CALL NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagZ) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xC5: // PUSH BC + WriteMemory(--RegSP.Word, RegBC.High); WriteMemory(--RegSP.Word, RegBC.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xC6: // ADD A, n + RegAF.Word = TableALU[0, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xC7: // RST $00 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x00; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xC8: // RET Z + if (RegFlagZ) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xC9: // RET + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xCA: // JP Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagZ) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xCB: // (Prefix) + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // RLC B + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x01: // RLC C + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x02: // RLC D + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x03: // RLC E + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x04: // RLC H + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x05: // RLC L + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x06: // RLC (HL) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x07: // RLC A + TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x08: // RRC B + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x09: // RRC C + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x0A: // RRC D + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x0B: // RRC E + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x0C: // RRC H + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x0D: // RRC L + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x0E: // RRC (HL) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x0F: // RRC A + TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x10: // RL B + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x11: // RL C + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x12: // RL D + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x13: // RL E + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x14: // RL H + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x15: // RL L + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x16: // RL (HL) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x17: // RL A + TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x18: // RR B + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x19: // RR C + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x1A: // RR D + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x1B: // RR E + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x1C: // RR H + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x1D: // RR L + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x1E: // RR (HL) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x1F: // RR A + TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x20: // SLA B + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x21: // SLA C + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x22: // SLA D + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x23: // SLA E + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x24: // SLA H + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x25: // SLA L + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x26: // SLA (HL) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x27: // SLA A + TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x28: // SRA B + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x29: // SRA C + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x2A: // SRA D + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x2B: // SRA E + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x2C: // SRA H + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x2D: // SRA L + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x2E: // SRA (HL) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x2F: // SRA A + TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x30: // SL1 B + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x31: // SL1 C + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x32: // SL1 D + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x33: // SL1 E + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x34: // SL1 H + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x35: // SL1 L + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x36: // SL1 (HL) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x37: // SL1 A + TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x38: // SRL B + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegBC.High]; + RegBC.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x39: // SRL C + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegBC.Low]; + RegBC.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x3A: // SRL D + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegDE.High]; + RegDE.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x3B: // SRL E + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegDE.Low]; + RegDE.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x3C: // SRL H + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegHL.High]; + RegHL.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x3D: // SRL L + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegHL.Low]; + RegHL.Low = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x3E: // SRL (HL) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory(RegHL.Word)]; + WriteMemory(RegHL.Word, (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x3F: // SRL A + TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegAF.High]; + RegAF.High = (byte)(TUS >> 8); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x40: // BIT 0, B + RegFlagZ = (RegBC.High & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x41: // BIT 0, C + RegFlagZ = (RegBC.Low & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x42: // BIT 0, D + RegFlagZ = (RegDE.High & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x43: // BIT 0, E + RegFlagZ = (RegDE.Low & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x44: // BIT 0, H + RegFlagZ = (RegHL.High & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x45: // BIT 0, L + RegFlagZ = (RegHL.Low & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x46: // BIT 0, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x47: // BIT 0, A + RegFlagZ = (RegAF.High & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x48: // BIT 1, B + RegFlagZ = (RegBC.High & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x49: // BIT 1, C + RegFlagZ = (RegBC.Low & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4A: // BIT 1, D + RegFlagZ = (RegDE.High & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4B: // BIT 1, E + RegFlagZ = (RegDE.Low & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4C: // BIT 1, H + RegFlagZ = (RegHL.High & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4D: // BIT 1, L + RegFlagZ = (RegHL.Low & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4E: // BIT 1, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x4F: // BIT 1, A + RegFlagZ = (RegAF.High & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x50: // BIT 2, B + RegFlagZ = (RegBC.High & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x51: // BIT 2, C + RegFlagZ = (RegBC.Low & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x52: // BIT 2, D + RegFlagZ = (RegDE.High & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x53: // BIT 2, E + RegFlagZ = (RegDE.Low & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x54: // BIT 2, H + RegFlagZ = (RegHL.High & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x55: // BIT 2, L + RegFlagZ = (RegHL.Low & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x56: // BIT 2, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x57: // BIT 2, A + RegFlagZ = (RegAF.High & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x58: // BIT 3, B + RegFlagZ = (RegBC.High & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x59: // BIT 3, C + RegFlagZ = (RegBC.Low & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5A: // BIT 3, D + RegFlagZ = (RegDE.High & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5B: // BIT 3, E + RegFlagZ = (RegDE.Low & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5C: // BIT 3, H + RegFlagZ = (RegHL.High & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5D: // BIT 3, L + RegFlagZ = (RegHL.Low & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5E: // BIT 3, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x5F: // BIT 3, A + RegFlagZ = (RegAF.High & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = !RegFlagZ; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x60: // BIT 4, B + RegFlagZ = (RegBC.High & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x61: // BIT 4, C + RegFlagZ = (RegBC.Low & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x62: // BIT 4, D + RegFlagZ = (RegDE.High & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x63: // BIT 4, E + RegFlagZ = (RegDE.Low & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x64: // BIT 4, H + RegFlagZ = (RegHL.High & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x65: // BIT 4, L + RegFlagZ = (RegHL.Low & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x66: // BIT 4, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x67: // BIT 4, A + RegFlagZ = (RegAF.High & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x68: // BIT 5, B + RegFlagZ = (RegBC.High & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x69: // BIT 5, C + RegFlagZ = (RegBC.Low & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6A: // BIT 5, D + RegFlagZ = (RegDE.High & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6B: // BIT 5, E + RegFlagZ = (RegDE.Low & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6C: // BIT 5, H + RegFlagZ = (RegHL.High & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6D: // BIT 5, L + RegFlagZ = (RegHL.Low & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6E: // BIT 5, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x6F: // BIT 5, A + RegFlagZ = (RegAF.High & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x70: // BIT 6, B + RegFlagZ = (RegBC.High & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x71: // BIT 6, C + RegFlagZ = (RegBC.Low & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x72: // BIT 6, D + RegFlagZ = (RegDE.High & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x73: // BIT 6, E + RegFlagZ = (RegDE.Low & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x74: // BIT 6, H + RegFlagZ = (RegHL.High & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x75: // BIT 6, L + RegFlagZ = (RegHL.Low & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x76: // BIT 6, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x77: // BIT 6, A + RegFlagZ = (RegAF.High & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x78: // BIT 7, B + RegFlagZ = (RegBC.High & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x79: // BIT 7, C + RegFlagZ = (RegBC.Low & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7A: // BIT 7, D + RegFlagZ = (RegDE.High & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7B: // BIT 7, E + RegFlagZ = (RegDE.Low & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7C: // BIT 7, H + RegFlagZ = (RegHL.High & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7D: // BIT 7, L + RegFlagZ = (RegHL.Low & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7E: // BIT 7, (HL) + RegFlagZ = (ReadMemory(RegHL.Word) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x7F: // BIT 7, A + RegFlagZ = (RegAF.High & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlag3 = false; + RegFlag5 = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x80: // RES 0, B + RegBC.High &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x81: // RES 0, C + RegBC.Low &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x82: // RES 0, D + RegDE.High &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x83: // RES 0, E + RegDE.Low &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x84: // RES 0, H + RegHL.High &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x85: // RES 0, L + RegHL.Low &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x86: // RES 0, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x01))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x87: // RES 0, A + RegAF.High &= unchecked((byte)~0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x88: // RES 1, B + RegBC.High &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x89: // RES 1, C + RegBC.Low &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x8A: // RES 1, D + RegDE.High &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x8B: // RES 1, E + RegDE.Low &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x8C: // RES 1, H + RegHL.High &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x8D: // RES 1, L + RegHL.Low &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x8E: // RES 1, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x02))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x8F: // RES 1, A + RegAF.High &= unchecked((byte)~0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x90: // RES 2, B + RegBC.High &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x91: // RES 2, C + RegBC.Low &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x92: // RES 2, D + RegDE.High &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x93: // RES 2, E + RegDE.Low &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x94: // RES 2, H + RegHL.High &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x95: // RES 2, L + RegHL.Low &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x96: // RES 2, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x04))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x97: // RES 2, A + RegAF.High &= unchecked((byte)~0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x98: // RES 3, B + RegBC.High &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x99: // RES 3, C + RegBC.Low &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x9A: // RES 3, D + RegDE.High &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x9B: // RES 3, E + RegDE.Low &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x9C: // RES 3, H + RegHL.High &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x9D: // RES 3, L + RegHL.Low &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x9E: // RES 3, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x08))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x9F: // RES 3, A + RegAF.High &= unchecked((byte)~0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA0: // RES 4, B + RegBC.High &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA1: // RES 4, C + RegBC.Low &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA2: // RES 4, D + RegDE.High &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA3: // RES 4, E + RegDE.Low &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA4: // RES 4, H + RegHL.High &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA5: // RES 4, L + RegHL.Low &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA6: // RES 4, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x10))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xA7: // RES 4, A + RegAF.High &= unchecked((byte)~0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA8: // RES 5, B + RegBC.High &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xA9: // RES 5, C + RegBC.Low &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xAA: // RES 5, D + RegDE.High &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xAB: // RES 5, E + RegDE.Low &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xAC: // RES 5, H + RegHL.High &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xAD: // RES 5, L + RegHL.Low &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xAE: // RES 5, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x20))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xAF: // RES 5, A + RegAF.High &= unchecked((byte)~0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB0: // RES 6, B + RegBC.High &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB1: // RES 6, C + RegBC.Low &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB2: // RES 6, D + RegDE.High &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB3: // RES 6, E + RegDE.Low &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB4: // RES 6, H + RegHL.High &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB5: // RES 6, L + RegHL.Low &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB6: // RES 6, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x40))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xB7: // RES 6, A + RegAF.High &= unchecked((byte)~0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB8: // RES 7, B + RegBC.High &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xB9: // RES 7, C + RegBC.Low &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xBA: // RES 7, D + RegDE.High &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xBB: // RES 7, E + RegDE.Low &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xBC: // RES 7, H + RegHL.High &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xBD: // RES 7, L + RegHL.Low &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xBE: // RES 7, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x80))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xBF: // RES 7, A + RegAF.High &= unchecked((byte)~0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC0: // SET 0, B + RegBC.High |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC1: // SET 0, C + RegBC.Low |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC2: // SET 0, D + RegDE.High |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC3: // SET 0, E + RegDE.Low |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC4: // SET 0, H + RegHL.High |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC5: // SET 0, L + RegHL.Low |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC6: // SET 0, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x01))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xC7: // SET 0, A + RegAF.High |= unchecked((byte)0x01); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC8: // SET 1, B + RegBC.High |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xC9: // SET 1, C + RegBC.Low |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xCA: // SET 1, D + RegDE.High |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xCB: // SET 1, E + RegDE.Low |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xCC: // SET 1, H + RegHL.High |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xCD: // SET 1, L + RegHL.Low |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xCE: // SET 1, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x02))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xCF: // SET 1, A + RegAF.High |= unchecked((byte)0x02); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD0: // SET 2, B + RegBC.High |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD1: // SET 2, C + RegBC.Low |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD2: // SET 2, D + RegDE.High |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD3: // SET 2, E + RegDE.Low |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD4: // SET 2, H + RegHL.High |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD5: // SET 2, L + RegHL.Low |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD6: // SET 2, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x04))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xD7: // SET 2, A + RegAF.High |= unchecked((byte)0x04); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD8: // SET 3, B + RegBC.High |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xD9: // SET 3, C + RegBC.Low |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xDA: // SET 3, D + RegDE.High |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xDB: // SET 3, E + RegDE.Low |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xDC: // SET 3, H + RegHL.High |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xDD: // SET 3, L + RegHL.Low |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xDE: // SET 3, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x08))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xDF: // SET 3, A + RegAF.High |= unchecked((byte)0x08); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE0: // SET 4, B + RegBC.High |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE1: // SET 4, C + RegBC.Low |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE2: // SET 4, D + RegDE.High |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE3: // SET 4, E + RegDE.Low |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE4: // SET 4, H + RegHL.High |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE5: // SET 4, L + RegHL.Low |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE6: // SET 4, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x10))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xE7: // SET 4, A + RegAF.High |= unchecked((byte)0x10); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE8: // SET 5, B + RegBC.High |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xE9: // SET 5, C + RegBC.Low |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xEA: // SET 5, D + RegDE.High |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xEB: // SET 5, E + RegDE.Low |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xEC: // SET 5, H + RegHL.High |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xED: // SET 5, L + RegHL.Low |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xEE: // SET 5, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x20))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xEF: // SET 5, A + RegAF.High |= unchecked((byte)0x20); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF0: // SET 6, B + RegBC.High |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF1: // SET 6, C + RegBC.Low |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF2: // SET 6, D + RegDE.High |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF3: // SET 6, E + RegDE.Low |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF4: // SET 6, H + RegHL.High |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF5: // SET 6, L + RegHL.Low |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF6: // SET 6, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x40))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xF7: // SET 6, A + RegAF.High |= unchecked((byte)0x40); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF8: // SET 7, B + RegBC.High |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xF9: // SET 7, C + RegBC.Low |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xFA: // SET 7, D + RegDE.High |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xFB: // SET 7, E + RegDE.Low |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xFC: // SET 7, H + RegHL.High |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xFD: // SET 7, L + RegHL.Low |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xFE: // SET 7, (HL) + WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked((byte)0x80))); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xFF: // SET 7, A + RegAF.High |= unchecked((byte)0x80); + totalExecutedCycles += 8; pendingCycles -= 8; + break; + } + break; + case 0xCC: // CALL Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagZ) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xCD: // CALL nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + break; + case 0xCE: // ADC A, n + RegAF.Word = TableALU[1, RegAF.High, ReadMemory(RegPC.Word++), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xCF: // RST $08 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x08; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD0: // RET NC + if (!RegFlagC) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xD1: // POP DE + RegDE.Low = ReadMemory(RegSP.Word++); RegDE.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xD2: // JP NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagC) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xD3: // OUT n, A + WriteHardware(ReadMemory(RegPC.Word++), RegAF.High); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD4: // CALL NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xD5: // PUSH DE + WriteMemory(--RegSP.Word, RegDE.High); WriteMemory(--RegSP.Word, RegDE.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD6: // SUB n + RegAF.Word = TableALU[2, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xD7: // RST $10 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x10; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD8: // RET C + if (RegFlagC) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xD9: // EXX + TUS = RegBC.Word; RegBC.Word = RegAltBC.Word; RegAltBC.Word = TUS; + TUS = RegDE.Word; RegDE.Word = RegAltDE.Word; RegAltDE.Word = TUS; + TUS = RegHL.Word; RegHL.Word = RegAltHL.Word; RegAltHL.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDA: // JP C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xDB: // IN A, n + RegAF.High = ReadHardware((ushort)ReadMemory(RegPC.Word++)); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xDC: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xDD: // (Prefix) + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x01: // LD BC, nn + RegBC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x02: // LD (BC), A + WriteMemory(RegBC.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x03: // INC BC + ++RegBC.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x04: // INC B + RegAF.Low = (byte)(TableInc[++RegBC.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x05: // DEC B + RegAF.Low = (byte)(TableDec[--RegBC.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x06: // LD B, n + RegBC.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x07: // RLCA + RegAF.Word = TableRotShift[0, 0, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x08: // EX AF, AF' + TUS = RegAF.Word; RegAF.Word = RegAltAF.Word; RegAltAF.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x09: // ADD IX, BC + TI1 = (short)RegIX.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIX.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x0A: // LD A, (BC) + RegAF.High = ReadMemory(RegBC.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x0B: // DEC BC + --RegBC.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x0C: // INC C + RegAF.Low = (byte)(TableInc[++RegBC.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0D: // DEC C + RegAF.Low = (byte)(TableDec[--RegBC.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0E: // LD C, n + RegBC.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x0F: // RRCA + RegAF.Word = TableRotShift[0, 1, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x10: // DJNZ d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (--RegBC.High != 0) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 13; pendingCycles -= 13; + } else { + totalExecutedCycles += 8; pendingCycles -= 8; + } + break; + case 0x11: // LD DE, nn + RegDE.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x12: // LD (DE), A + WriteMemory(RegDE.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x13: // INC DE + ++RegDE.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x14: // INC D + RegAF.Low = (byte)(TableInc[++RegDE.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x15: // DEC D + RegAF.Low = (byte)(TableDec[--RegDE.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x16: // LD D, n + RegDE.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x17: // RLA + RegAF.Word = TableRotShift[0, 2, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x18: // JR d + TSB = (sbyte)ReadMemory(RegPC.Word++); + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x19: // ADD IX, DE + TI1 = (short)RegIX.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIX.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x1A: // LD A, (DE) + RegAF.High = ReadMemory(RegDE.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x1B: // DEC DE + --RegDE.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x1C: // INC E + RegAF.Low = (byte)(TableInc[++RegDE.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1D: // DEC E + RegAF.Low = (byte)(TableDec[--RegDE.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1E: // LD E, n + RegDE.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x1F: // RRA + RegAF.Word = TableRotShift[0, 3, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x20: // JR NZ, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!RegFlagZ) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x21: // LD IX, nn + RegIX.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x22: // LD (nn), IX + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegIX.Low); + WriteMemory(TUS, RegIX.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x23: // INC IX + ++RegIX.Word; + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x24: // INC IXH + RegAF.Low = (byte)(TableInc[++RegIX.High] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x25: // DEC IXH + RegAF.Low = (byte)(TableDec[--RegIX.High] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x26: // LD IXH, n + RegIX.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x27: // DAA + RegAF.Word = TableDaa[RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x28: // JR Z, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (RegFlagZ) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x29: // ADD IX, IX + TI1 = (short)RegIX.Word; TI2 = (short)RegIX.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIX.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x2A: // LD IX, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegIX.Low = ReadMemory(TUS++); RegIX.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x2B: // DEC IX + --RegIX.Word; + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x2C: // INC IXL + RegAF.Low = (byte)(TableInc[++RegIX.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x2D: // DEC IXL + RegAF.Low = (byte)(TableDec[--RegIX.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x2E: // LD IXL, n + RegIX.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x2F: // CPL + RegAF.High ^= 0xFF; RegFlagH = true; RegFlagN = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x30: // JR NC, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!RegFlagC) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x31: // LD SP, nn + RegSP.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x32: // LD (nn), A + WriteMemory((ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256), RegAF.High); + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 0x33: // INC SP + ++RegSP.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x34: // INC (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + TB = ReadMemory((ushort)(RegIX.Word + Displacement)); RegAF.Low = (byte)(TableInc[++TB] | (RegAF.Low & 1)); WriteMemory((ushort)(RegIX.Word + Displacement), TB); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x35: // DEC (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + TB = ReadMemory((ushort)(RegIX.Word + Displacement)); RegAF.Low = (byte)(TableDec[--TB] | (RegAF.Low & 1)); WriteMemory((ushort)(RegIX.Word + Displacement), TB); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x36: // LD (IX+d), n + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), ReadMemory(RegPC.Word++)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x37: // SCF + RegFlagH = false; RegFlagN = false; RegFlagC = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x38: // JR C, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (RegFlagC) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x39: // ADD IX, SP + TI1 = (short)RegIX.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIX.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x3A: // LD A, (nn) + RegAF.High = ReadMemory((ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256)); + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 0x3B: // DEC SP + --RegSP.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x3C: // INC A + RegAF.Low = (byte)(TableInc[++RegAF.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3D: // DEC A + RegAF.Low = (byte)(TableDec[--RegAF.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3E: // LD A, n + RegAF.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x3F: // CCF + RegFlagH = RegFlagC; RegFlagN = false; RegFlagC ^= true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x40: // LD B, B + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x41: // LD B, C + RegBC.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x42: // LD B, D + RegBC.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x43: // LD B, E + RegBC.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x44: // LD B, IXH + RegBC.High = RegIX.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x45: // LD B, IXL + RegBC.High = RegIX.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x46: // LD B, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegBC.High = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x47: // LD B, A + RegBC.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x48: // LD C, B + RegBC.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x49: // LD C, C + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4A: // LD C, D + RegBC.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4B: // LD C, E + RegBC.Low = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4C: // LD C, IXH + RegBC.Low = RegIX.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x4D: // LD C, IXL + RegBC.Low = RegIX.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x4E: // LD C, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegBC.Low = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x4F: // LD C, A + RegBC.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x50: // LD D, B + RegDE.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x51: // LD D, C + RegDE.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x52: // LD D, D + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x53: // LD D, E + RegDE.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x54: // LD D, IXH + RegDE.High = RegIX.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x55: // LD D, IXL + RegDE.High = RegIX.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x56: // LD D, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegDE.High = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x57: // LD D, A + RegDE.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x58: // LD E, B + RegDE.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x59: // LD E, C + RegDE.Low = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5A: // LD E, D + RegDE.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5B: // LD E, E + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5C: // LD E, IXH + RegDE.Low = RegIX.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x5D: // LD E, IXL + RegDE.Low = RegIX.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x5E: // LD E, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegDE.Low = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x5F: // LD E, A + RegDE.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x60: // LD IXH, B + RegIX.High = RegBC.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x61: // LD IXH, C + RegIX.High = RegBC.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x62: // LD IXH, D + RegIX.High = RegDE.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x63: // LD IXH, E + RegIX.High = RegDE.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x64: // LD IXH, IXH + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x65: // LD IXH, IXL + RegIX.High = RegIX.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x66: // LD H, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegHL.High = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x67: // LD IXH, A + RegIX.High = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x68: // LD IXL, B + RegIX.Low = RegBC.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x69: // LD IXL, C + RegIX.Low = RegBC.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6A: // LD IXL, D + RegIX.Low = RegDE.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6B: // LD IXL, E + RegIX.Low = RegDE.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6C: // LD IXL, IXH + RegIX.Low = RegIX.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6D: // LD IXL, IXL + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6E: // LD L, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegHL.Low = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x6F: // LD IXL, A + RegIX.Low = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x70: // LD (IX+d), B + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x71: // LD (IX+d), C + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x72: // LD (IX+d), D + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x73: // LD (IX+d), E + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x74: // LD (IX+d), H + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x75: // LD (IX+d), L + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x76: // HALT + Halt(); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x77: // LD (IX+d), A + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x78: // LD A, B + RegAF.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x79: // LD A, C + RegAF.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7A: // LD A, D + RegAF.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7B: // LD A, E + RegAF.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7C: // LD A, IXH + RegAF.High = RegIX.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x7D: // LD A, IXL + RegAF.High = RegIX.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x7E: // LD A, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.High = ReadMemory((ushort)(RegIX.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x7F: // LD A, A + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x80: // ADD A, B + RegAF.Word = TableALU[0, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x81: // ADD A, C + RegAF.Word = TableALU[0, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x82: // ADD A, D + RegAF.Word = TableALU[0, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x83: // ADD A, E + RegAF.Word = TableALU[0, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x84: // ADD A, IXH + RegAF.Word = TableALU[0, RegAF.High, RegIX.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x85: // ADD A, IXL + RegAF.Word = TableALU[0, RegAF.High, RegIX.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x86: // ADD A, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[0, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), 0]; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x87: // ADD A, A + RegAF.Word = TableALU[0, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x88: // ADC A, B + RegAF.Word = TableALU[1, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x89: // ADC A, C + RegAF.Word = TableALU[1, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8A: // ADC A, D + RegAF.Word = TableALU[1, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8B: // ADC A, E + RegAF.Word = TableALU[1, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8C: // ADC A, IXH + RegAF.Word = TableALU[1, RegAF.High, RegIX.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x8D: // ADC A, IXL + RegAF.Word = TableALU[1, RegAF.High, RegIX.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x8E: // ADC A, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[1, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), RegFlagC ? 1 : 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x8F: // ADC A, A + RegAF.Word = TableALU[1, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x90: // SUB B + RegAF.Word = TableALU[2, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x91: // SUB C + RegAF.Word = TableALU[2, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x92: // SUB D + RegAF.Word = TableALU[2, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x93: // SUB E + RegAF.Word = TableALU[2, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x94: // SUB IXH + RegAF.Word = TableALU[2, RegAF.High, RegIX.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x95: // SUB IXL + RegAF.Word = TableALU[2, RegAF.High, RegIX.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x96: // SUB (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[2, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x97: // SUB A, A + RegAF.Word = TableALU[2, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x98: // SBC A, B + RegAF.Word = TableALU[3, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x99: // SBC A, C + RegAF.Word = TableALU[3, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9A: // SBC A, D + RegAF.Word = TableALU[3, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9B: // SBC A, E + RegAF.Word = TableALU[3, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9C: // SBC A, IXH + RegAF.Word = TableALU[3, RegAF.High, RegIX.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x9D: // SBC A, IXL + RegAF.Word = TableALU[3, RegAF.High, RegIX.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x9E: // SBC A, (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[3, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), RegFlagC ? 1 : 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x9F: // SBC A, A + RegAF.Word = TableALU[3, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA0: // AND B + RegAF.Word = TableALU[4, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA1: // AND C + RegAF.Word = TableALU[4, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA2: // AND D + RegAF.Word = TableALU[4, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA3: // AND E + RegAF.Word = TableALU[4, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA4: // AND IXH + RegAF.Word = TableALU[4, RegAF.High, RegIX.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xA5: // AND IXL + RegAF.Word = TableALU[4, RegAF.High, RegIX.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xA6: // AND (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[4, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xA7: // AND A + RegAF.Word = TableALU[4, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA8: // XOR B + RegAF.Word = TableALU[5, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA9: // XOR C + RegAF.Word = TableALU[5, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAA: // XOR D + RegAF.Word = TableALU[5, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAB: // XOR E + RegAF.Word = TableALU[5, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAC: // XOR IXH + RegAF.Word = TableALU[5, RegAF.High, RegIX.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xAD: // XOR IXL + RegAF.Word = TableALU[5, RegAF.High, RegIX.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xAE: // XOR (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[5, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xAF: // XOR A + RegAF.Word = TableALU[5, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB0: // OR B + RegAF.Word = TableALU[6, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB1: // OR C + RegAF.Word = TableALU[6, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB2: // OR D + RegAF.Word = TableALU[6, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB3: // OR E + RegAF.Word = TableALU[6, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB4: // OR IXH + RegAF.Word = TableALU[6, RegAF.High, RegIX.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xB5: // OR IXL + RegAF.Word = TableALU[6, RegAF.High, RegIX.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xB6: // OR (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[6, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xB7: // OR A + RegAF.Word = TableALU[6, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB8: // CP B + RegAF.Word = TableALU[7, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB9: // CP C + RegAF.Word = TableALU[7, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBA: // CP D + RegAF.Word = TableALU[7, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBB: // CP E + RegAF.Word = TableALU[7, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBC: // CP IXH + RegAF.Word = TableALU[7, RegAF.High, RegIX.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xBD: // CP IXL + RegAF.Word = TableALU[7, RegAF.High, RegIX.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xBE: // CP (IX+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[7, RegAF.High, ReadMemory((ushort)(RegIX.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xBF: // CP A + RegAF.Word = TableALU[7, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC0: // RET NZ + if (!RegFlagZ) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xC1: // POP BC + RegBC.Low = ReadMemory(RegSP.Word++); RegBC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC2: // JP NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagZ) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC3: // JP nn + RegPC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC4: // CALL NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagZ) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xC5: // PUSH BC + WriteMemory(--RegSP.Word, RegBC.High); WriteMemory(--RegSP.Word, RegBC.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xC6: // ADD A, n + RegAF.Word = TableALU[0, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xC7: // RST $00 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x00; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xC8: // RET Z + if (RegFlagZ) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xC9: // RET + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xCA: // JP Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagZ) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xCB: // (Prefix) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // RLC (IX+d)→B + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x01: // RLC (IX+d)→C + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x02: // RLC (IX+d)→D + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x03: // RLC (IX+d)→E + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x04: // RLC (IX+d)→H + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x05: // RLC (IX+d)→L + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x06: // RLC (IX+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x07: // RLC (IX+d)→A + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x08: // RRC (IX+d)→B + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x09: // RRC (IX+d)→C + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0A: // RRC (IX+d)→D + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0B: // RRC (IX+d)→E + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0C: // RRC (IX+d)→H + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0D: // RRC (IX+d)→L + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0E: // RRC (IX+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0F: // RRC (IX+d)→A + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x10: // RL (IX+d)→B + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x11: // RL (IX+d)→C + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x12: // RL (IX+d)→D + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x13: // RL (IX+d)→E + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x14: // RL (IX+d)→H + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x15: // RL (IX+d)→L + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x16: // RL (IX+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x17: // RL (IX+d)→A + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x18: // RR (IX+d)→B + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x19: // RR (IX+d)→C + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1A: // RR (IX+d)→D + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1B: // RR (IX+d)→E + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1C: // RR (IX+d)→H + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1D: // RR (IX+d)→L + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1E: // RR (IX+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1F: // RR (IX+d)→A + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x20: // SLA (IX+d)→B + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x21: // SLA (IX+d)→C + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x22: // SLA (IX+d)→D + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x23: // SLA (IX+d)→E + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x24: // SLA (IX+d)→H + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x25: // SLA (IX+d)→L + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x26: // SLA (IX+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x27: // SLA (IX+d)→A + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x28: // SRA (IX+d)→B + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x29: // SRA (IX+d)→C + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2A: // SRA (IX+d)→D + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2B: // SRA (IX+d)→E + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2C: // SRA (IX+d)→H + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2D: // SRA (IX+d)→L + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2E: // SRA (IX+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2F: // SRA (IX+d)→A + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x30: // SL1 (IX+d)→B + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x31: // SL1 (IX+d)→C + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x32: // SL1 (IX+d)→D + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x33: // SL1 (IX+d)→E + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x34: // SL1 (IX+d)→H + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x35: // SL1 (IX+d)→L + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x36: // SL1 (IX+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x37: // SL1 (IX+d)→A + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x38: // SRL (IX+d)→B + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x39: // SRL (IX+d)→C + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegBC.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3A: // SRL (IX+d)→D + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3B: // SRL (IX+d)→E + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegDE.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3C: // SRL (IX+d)→H + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3D: // SRL (IX+d)→L + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegHL.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3E: // SRL (IX+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3F: // SRL (IX+d)→A + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIX.Word + Displacement))]; + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + RegAF.High = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x40: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x41: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x42: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x43: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x44: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x45: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x46: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x47: // BIT 0, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x48: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x49: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4A: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4B: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4C: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4D: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4E: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4F: // BIT 1, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x50: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x51: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x52: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x53: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x54: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x55: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x56: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x57: // BIT 2, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x58: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x59: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5A: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5B: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5C: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5D: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5E: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5F: // BIT 3, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x60: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x61: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x62: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x63: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x64: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x65: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x66: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x67: // BIT 4, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x68: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x69: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6A: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6B: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6C: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6D: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6E: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6F: // BIT 5, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x70: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x71: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x72: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x73: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x74: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x75: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x76: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x77: // BIT 6, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x78: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x79: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7A: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7B: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7C: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7D: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7E: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7F: // BIT 7, (IX+d) + RegFlagZ = (ReadMemory((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x80: // RES 0, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x81: // RES 0, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x82: // RES 0, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x83: // RES 0, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x84: // RES 0, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x85: // RES 0, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x86: // RES 0, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x87: // RES 0, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x88: // RES 1, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x89: // RES 1, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8A: // RES 1, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8B: // RES 1, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8C: // RES 1, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8D: // RES 1, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8E: // RES 1, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8F: // RES 1, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x90: // RES 2, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x91: // RES 2, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x92: // RES 2, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x93: // RES 2, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x94: // RES 2, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x95: // RES 2, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x96: // RES 2, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x97: // RES 2, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x98: // RES 3, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x99: // RES 3, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9A: // RES 3, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9B: // RES 3, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9C: // RES 3, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9D: // RES 3, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9E: // RES 3, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9F: // RES 3, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA0: // RES 4, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA1: // RES 4, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA2: // RES 4, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA3: // RES 4, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA4: // RES 4, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA5: // RES 4, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA6: // RES 4, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA7: // RES 4, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA8: // RES 5, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA9: // RES 5, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAA: // RES 5, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAB: // RES 5, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAC: // RES 5, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAD: // RES 5, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAE: // RES 5, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAF: // RES 5, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB0: // RES 6, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB1: // RES 6, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB2: // RES 6, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB3: // RES 6, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB4: // RES 6, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB5: // RES 6, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB6: // RES 6, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB7: // RES 6, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB8: // RES 7, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB9: // RES 7, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBA: // RES 7, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBB: // RES 7, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBC: // RES 7, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBD: // RES 7, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBE: // RES 7, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBF: // RES 7, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC0: // SET 0, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC1: // SET 0, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC2: // SET 0, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC3: // SET 0, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC4: // SET 0, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC5: // SET 0, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC6: // SET 0, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC7: // SET 0, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC8: // SET 1, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC9: // SET 1, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCA: // SET 1, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCB: // SET 1, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCC: // SET 1, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCD: // SET 1, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCE: // SET 1, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCF: // SET 1, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD0: // SET 2, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD1: // SET 2, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD2: // SET 2, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD3: // SET 2, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD4: // SET 2, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD5: // SET 2, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD6: // SET 2, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD7: // SET 2, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD8: // SET 3, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD9: // SET 3, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDA: // SET 3, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDB: // SET 3, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDC: // SET 3, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDD: // SET 3, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDE: // SET 3, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDF: // SET 3, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE0: // SET 4, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE1: // SET 4, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE2: // SET 4, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE3: // SET 4, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE4: // SET 4, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE5: // SET 4, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE6: // SET 4, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE7: // SET 4, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE8: // SET 5, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE9: // SET 5, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEA: // SET 5, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEB: // SET 5, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEC: // SET 5, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xED: // SET 5, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEE: // SET 5, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEF: // SET 5, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF0: // SET 6, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF1: // SET 6, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF2: // SET 6, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF3: // SET 6, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF4: // SET 6, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF5: // SET 6, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF6: // SET 6, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF7: // SET 6, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF8: // SET 7, (IX+d)→B + RegBC.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF9: // SET 7, (IX+d)→C + RegBC.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegBC.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFA: // SET 7, (IX+d)→D + RegDE.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFB: // SET 7, (IX+d)→E + RegDE.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegDE.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFC: // SET 7, (IX+d)→H + RegHL.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFD: // SET 7, (IX+d)→L + RegHL.Low = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegHL.Low); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFE: // SET 7, (IX+d) + WriteMemory((ushort)(RegIX.Word + Displacement), (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFF: // SET 7, (IX+d)→A + RegAF.High = (byte)(ReadMemory((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); + WriteMemory((ushort)(RegIX.Word + Displacement), RegAF.High); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + } + break; + case 0xCC: // CALL Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagZ) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xCD: // CALL nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + break; + case 0xCE: // ADC A, n + RegAF.Word = TableALU[1, RegAF.High, ReadMemory(RegPC.Word++), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xCF: // RST $08 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x08; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD0: // RET NC + if (!RegFlagC) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xD1: // POP DE + RegDE.Low = ReadMemory(RegSP.Word++); RegDE.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xD2: // JP NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagC) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xD3: // OUT n, A + WriteHardware(ReadMemory(RegPC.Word++), RegAF.High); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD4: // CALL NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xD5: // PUSH DE + WriteMemory(--RegSP.Word, RegDE.High); WriteMemory(--RegSP.Word, RegDE.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD6: // SUB n + RegAF.Word = TableALU[2, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xD7: // RST $10 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x10; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD8: // RET C + if (RegFlagC) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xD9: // EXX + TUS = RegBC.Word; RegBC.Word = RegAltBC.Word; RegAltBC.Word = TUS; + TUS = RegDE.Word; RegDE.Word = RegAltDE.Word; RegAltDE.Word = TUS; + TUS = RegHL.Word; RegHL.Word = RegAltHL.Word; RegAltHL.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDA: // JP C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xDB: // IN A, n + RegAF.High = ReadHardware((ushort)ReadMemory(RegPC.Word++)); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xDC: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xDD: // <- + // Invalid sequence. + totalExecutedCycles += 1337; pendingCycles -= 1337; + break; + case 0xDE: // SBC A, n + RegAF.Word = TableALU[3, RegAF.High, ReadMemory(RegPC.Word++), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xDF: // RST $18 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x18; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE0: // RET PO + if (!RegFlagP) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xE1: // POP IX + RegIX.Low = ReadMemory(RegSP.Word++); RegIX.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0xE2: // JP PO, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagP) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xE3: // EX (SP), IX + TUS = RegSP.Word; TBL = ReadMemory(TUS++); TBH = ReadMemory(TUS--); + WriteMemory(TUS++, RegIX.Low); WriteMemory(TUS, RegIX.High); + RegIX.Low = TBL; RegIX.High = TBH; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE4: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xE5: // PUSH IX + WriteMemory(--RegSP.Word, RegIX.High); WriteMemory(--RegSP.Word, RegIX.Low); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xE6: // AND n + RegAF.Word = TableALU[4, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xE7: // RST $20 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x20; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE8: // RET PE + if (RegFlagP) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xE9: // JP IX + RegPC.Word = RegIX.Word; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xEA: // JP PE, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagP) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xEB: // EX DE, HL + TUS = RegDE.Word; RegDE.Word = RegHL.Word; RegHL.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEC: // CALL PE, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagP) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xED: // (Prefix) + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x01: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x02: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x03: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x04: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x05: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x06: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x07: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x08: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x09: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x10: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x11: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x12: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x13: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x14: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x15: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x16: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x17: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x18: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x19: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x20: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x21: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x22: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x23: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x24: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x25: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x26: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x27: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x28: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x29: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x30: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x31: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x32: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x33: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x34: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x35: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x36: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x37: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x38: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x39: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x40: // IN B, C + RegBC.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegBC.High > 127; + RegFlagZ = RegBC.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegBC.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x41: // OUT C, B + WriteHardware(RegBC.Low, RegBC.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x42: // SBC HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegBC.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegBC.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x43: // LD (nn), BC + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegBC.Low); + WriteMemory(TUS, RegBC.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x44: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x45: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x46: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x47: // LD I, A + RegI = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x48: // IN C, C + RegBC.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegBC.Low > 127; + RegFlagZ = RegBC.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegBC.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x49: // OUT C, C + WriteHardware(RegBC.Low, RegBC.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x4A: // ADC HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x4B: // LD BC, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegBC.Low = ReadMemory(TUS++); RegBC.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x4E: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4F: // LD R, A + RegR = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x50: // IN D, C + RegDE.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegDE.High > 127; + RegFlagZ = RegDE.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegDE.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x51: // OUT C, D + WriteHardware(RegBC.Low, RegDE.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x52: // SBC HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegDE.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegDE.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x53: // LD (nn), DE + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegDE.Low); + WriteMemory(TUS, RegDE.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x54: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x55: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x56: // IM $1 + interruptMode = 1; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x57: // LD A, I + RegAF.High = RegI; + RegFlagS = RegI > 127; + RegFlagZ = RegI == 0; + RegFlagH = false; + RegFlagN = false; + RegFlagP = IFF2; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x58: // IN E, C + RegDE.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegDE.Low > 127; + RegFlagZ = RegDE.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegDE.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x59: // OUT C, E + WriteHardware(RegBC.Low, RegDE.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x5A: // ADC HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x5B: // LD DE, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegDE.Low = ReadMemory(TUS++); RegDE.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x5E: // IM $2 + interruptMode = 2; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5F: // LD A, R + RegAF.High = (byte)(RegR & 0x7F); + RegFlagS = (byte)(RegR & 0x7F) > 127; + RegFlagZ = (byte)(RegR & 0x7F) == 0; + RegFlagH = false; + RegFlagN = false; + RegFlagP = IFF2; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x60: // IN H, C + RegHL.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegHL.High > 127; + RegFlagZ = RegHL.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegHL.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x61: // OUT C, H + WriteHardware(RegBC.Low, RegHL.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x62: // SBC HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegHL.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegHL.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x63: // LD (nn), HL + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegHL.Low); + WriteMemory(TUS, RegHL.High); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x64: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x65: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x66: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x67: // RRD + TB1 = RegAF.High; TB2 = ReadMemory(RegHL.Word); + WriteMemory(RegHL.Word, (byte)((TB2 >> 4) + (TB1 << 4))); + RegAF.High = (byte)((TB1 & 0xF0) + (TB2 & 0x0F)); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + RegFlag3 = (RegAF.High & 0x08) != 0; + RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 18; pendingCycles -= 18; + break; + case 0x68: // IN L, C + RegHL.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegHL.Low > 127; + RegFlagZ = RegHL.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegHL.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x69: // OUT C, L + WriteHardware(RegBC.Low, RegHL.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x6A: // ADC HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x6B: // LD HL, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegHL.Low = ReadMemory(TUS++); RegHL.High = ReadMemory(TUS); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x6C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x6E: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6F: // RLD + TB1 = RegAF.High; TB2 = ReadMemory(RegHL.Word); + WriteMemory(RegHL.Word, (byte)((TB1 & 0x0F) + (TB2 << 4))); + RegAF.High = (byte)((TB1 & 0xF0) + (TB2 >> 4)); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + RegFlag3 = (RegAF.High & 0x08) != 0; + RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 18; pendingCycles -= 18; + break; + case 0x70: // IN 0, C + TB = ReadHardware((ushort)RegBC.Low); + RegFlagS = TB > 127; + RegFlagZ = TB == 0; + RegFlagH = false; + RegFlagP = TableParity[TB]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x71: // OUT C, 0 + WriteHardware(RegBC.Low, 0); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x72: // SBC HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegSP.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegSP.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x73: // LD (nn), SP + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegSP.Low); + WriteMemory(TUS, RegSP.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x74: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x75: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x76: // IM $1 + interruptMode = 1; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x77: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x78: // IN A, C + RegAF.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x79: // OUT C, A + WriteHardware(RegBC.Low, RegAF.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x7A: // ADC HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x7B: // LD SP, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegSP.Low = ReadMemory(TUS++); RegSP.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x7E: // IM $2 + interruptMode = 2; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x80: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x81: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x82: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x83: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x84: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x85: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x86: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x87: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x88: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x89: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x90: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x91: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x92: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x93: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x94: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x95: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x96: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x97: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x98: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x99: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA0: // LDI + WriteMemory(RegDE.Word++, TB1 = ReadMemory(RegHL.Word++)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA1: // CPI + TB1 = ReadMemory(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA2: // INI + WriteMemory(RegHL.Word++, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA3: // OUTI + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word++)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA8: // LDD + WriteMemory(RegDE.Word--, TB1 = ReadMemory(RegHL.Word--)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA9: // CPD + TB1 = ReadMemory(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAA: // IND + WriteMemory(RegHL.Word--, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAB: // OUTD + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word--)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB0: // LDIR + WriteMemory(RegDE.Word++, TB1 = ReadMemory(RegHL.Word++)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + if (RegBC.Word != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB1: // CPIR + TB1 = ReadMemory(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + if (RegBC.Word != 0 && !RegFlagZ) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB2: // INIR + WriteMemory(RegHL.Word++, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB3: // OTIR + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word++)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB8: // LDDR + WriteMemory(RegDE.Word--, TB1 = ReadMemory(RegHL.Word--)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + if (RegBC.Word != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB9: // CPDR + TB1 = ReadMemory(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + if (RegBC.Word != 0 && !RegFlagZ) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBA: // INDR + WriteMemory(RegHL.Word--, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBB: // OTDR + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word--)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xED: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + } + break; + case 0xEE: // XOR n + RegAF.Word = TableALU[5, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xEF: // RST $28 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x28; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF0: // RET P + if (!RegFlagS) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xF1: // POP AF + RegAF.Low = ReadMemory(RegSP.Word++); RegAF.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xF2: // JP P, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagS) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xF3: // DI + IFF1 = IFF2 = false; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF4: // CALL P, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagS) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xF5: // PUSH AF + WriteMemory(--RegSP.Word, RegAF.High); WriteMemory(--RegSP.Word, RegAF.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF6: // OR n + RegAF.Word = TableALU[6, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xF7: // RST $30 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x30; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF8: // RET M + if (RegFlagS) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xF9: // LD SP, IX + RegSP.Word = RegIX.Word; + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xFA: // JP M, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagS) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xFB: // EI + IFF1 = IFF2 = true; + Interruptable = false; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFC: // CALL M, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagS) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xFD: // <- + // Invalid sequence. + totalExecutedCycles += 1337; pendingCycles -= 1337; + break; + case 0xFE: // CP n + RegAF.Word = TableALU[7, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xFF: // RST $38 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x38; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + } + break; + case 0xDE: // SBC A, n + RegAF.Word = TableALU[3, RegAF.High, ReadMemory(RegPC.Word++), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xDF: // RST $18 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x18; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE0: // RET PO + if (!RegFlagP) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xE1: // POP HL + RegHL.Low = ReadMemory(RegSP.Word++); RegHL.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xE2: // JP PO, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagP) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xE3: // EX (SP), HL + TUS = RegSP.Word; TBL = ReadMemory(TUS++); TBH = ReadMemory(TUS--); + WriteMemory(TUS++, RegHL.Low); WriteMemory(TUS, RegHL.High); + RegHL.Low = TBL; RegHL.High = TBH; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xE4: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xE5: // PUSH HL + WriteMemory(--RegSP.Word, RegHL.High); WriteMemory(--RegSP.Word, RegHL.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE6: // AND n + RegAF.Word = TableALU[4, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xE7: // RST $20 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x20; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE8: // RET PE + if (RegFlagP) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xE9: // JP HL + RegPC.Word = RegHL.Word; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEA: // JP PE, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagP) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xEB: // EX DE, HL + TUS = RegDE.Word; RegDE.Word = RegHL.Word; RegHL.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEC: // CALL PE, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagP) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xED: // (Prefix) + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x01: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x02: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x03: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x04: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x05: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x06: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x07: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x08: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x09: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x10: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x11: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x12: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x13: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x14: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x15: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x16: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x17: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x18: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x19: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x20: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x21: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x22: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x23: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x24: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x25: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x26: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x27: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x28: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x29: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x30: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x31: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x32: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x33: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x34: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x35: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x36: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x37: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x38: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x39: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x40: // IN B, C + RegBC.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegBC.High > 127; + RegFlagZ = RegBC.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegBC.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x41: // OUT C, B + WriteHardware(RegBC.Low, RegBC.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x42: // SBC HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegBC.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegBC.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x43: // LD (nn), BC + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegBC.Low); + WriteMemory(TUS, RegBC.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x44: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x45: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x46: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x47: // LD I, A + RegI = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x48: // IN C, C + RegBC.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegBC.Low > 127; + RegFlagZ = RegBC.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegBC.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x49: // OUT C, C + WriteHardware(RegBC.Low, RegBC.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x4A: // ADC HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x4B: // LD BC, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegBC.Low = ReadMemory(TUS++); RegBC.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x4E: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4F: // LD R, A + RegR = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x50: // IN D, C + RegDE.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegDE.High > 127; + RegFlagZ = RegDE.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegDE.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x51: // OUT C, D + WriteHardware(RegBC.Low, RegDE.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x52: // SBC HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegDE.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegDE.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x53: // LD (nn), DE + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegDE.Low); + WriteMemory(TUS, RegDE.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x54: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x55: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x56: // IM $1 + interruptMode = 1; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x57: // LD A, I + RegAF.High = RegI; + RegFlagS = RegI > 127; + RegFlagZ = RegI == 0; + RegFlagH = false; + RegFlagN = false; + RegFlagP = IFF2; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x58: // IN E, C + RegDE.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegDE.Low > 127; + RegFlagZ = RegDE.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegDE.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x59: // OUT C, E + WriteHardware(RegBC.Low, RegDE.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x5A: // ADC HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x5B: // LD DE, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegDE.Low = ReadMemory(TUS++); RegDE.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x5E: // IM $2 + interruptMode = 2; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5F: // LD A, R + RegAF.High = (byte)(RegR & 0x7F); + RegFlagS = (byte)(RegR & 0x7F) > 127; + RegFlagZ = (byte)(RegR & 0x7F) == 0; + RegFlagH = false; + RegFlagN = false; + RegFlagP = IFF2; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x60: // IN H, C + RegHL.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegHL.High > 127; + RegFlagZ = RegHL.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegHL.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x61: // OUT C, H + WriteHardware(RegBC.Low, RegHL.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x62: // SBC HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegHL.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegHL.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x63: // LD (nn), HL + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegHL.Low); + WriteMemory(TUS, RegHL.High); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x64: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x65: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x66: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x67: // RRD + TB1 = RegAF.High; TB2 = ReadMemory(RegHL.Word); + WriteMemory(RegHL.Word, (byte)((TB2 >> 4) + (TB1 << 4))); + RegAF.High = (byte)((TB1 & 0xF0) + (TB2 & 0x0F)); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + RegFlag3 = (RegAF.High & 0x08) != 0; + RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 18; pendingCycles -= 18; + break; + case 0x68: // IN L, C + RegHL.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegHL.Low > 127; + RegFlagZ = RegHL.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegHL.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x69: // OUT C, L + WriteHardware(RegBC.Low, RegHL.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x6A: // ADC HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x6B: // LD HL, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegHL.Low = ReadMemory(TUS++); RegHL.High = ReadMemory(TUS); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x6C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x6E: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6F: // RLD + TB1 = RegAF.High; TB2 = ReadMemory(RegHL.Word); + WriteMemory(RegHL.Word, (byte)((TB1 & 0x0F) + (TB2 << 4))); + RegAF.High = (byte)((TB1 & 0xF0) + (TB2 >> 4)); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + RegFlag3 = (RegAF.High & 0x08) != 0; + RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 18; pendingCycles -= 18; + break; + case 0x70: // IN 0, C + TB = ReadHardware((ushort)RegBC.Low); + RegFlagS = TB > 127; + RegFlagZ = TB == 0; + RegFlagH = false; + RegFlagP = TableParity[TB]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x71: // OUT C, 0 + WriteHardware(RegBC.Low, 0); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x72: // SBC HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegSP.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegSP.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x73: // LD (nn), SP + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegSP.Low); + WriteMemory(TUS, RegSP.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x74: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x75: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x76: // IM $1 + interruptMode = 1; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x77: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x78: // IN A, C + RegAF.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x79: // OUT C, A + WriteHardware(RegBC.Low, RegAF.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x7A: // ADC HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x7B: // LD SP, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegSP.Low = ReadMemory(TUS++); RegSP.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x7E: // IM $2 + interruptMode = 2; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x80: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x81: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x82: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x83: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x84: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x85: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x86: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x87: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x88: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x89: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x90: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x91: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x92: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x93: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x94: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x95: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x96: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x97: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x98: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x99: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA0: // LDI + WriteMemory(RegDE.Word++, TB1 = ReadMemory(RegHL.Word++)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA1: // CPI + TB1 = ReadMemory(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA2: // INI + WriteMemory(RegHL.Word++, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA3: // OUTI + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word++)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA8: // LDD + WriteMemory(RegDE.Word--, TB1 = ReadMemory(RegHL.Word--)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA9: // CPD + TB1 = ReadMemory(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAA: // IND + WriteMemory(RegHL.Word--, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAB: // OUTD + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word--)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB0: // LDIR + WriteMemory(RegDE.Word++, TB1 = ReadMemory(RegHL.Word++)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + if (RegBC.Word != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB1: // CPIR + TB1 = ReadMemory(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + if (RegBC.Word != 0 && !RegFlagZ) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB2: // INIR + WriteMemory(RegHL.Word++, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB3: // OTIR + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word++)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB8: // LDDR + WriteMemory(RegDE.Word--, TB1 = ReadMemory(RegHL.Word--)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + if (RegBC.Word != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB9: // CPDR + TB1 = ReadMemory(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + if (RegBC.Word != 0 && !RegFlagZ) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBA: // INDR + WriteMemory(RegHL.Word--, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBB: // OTDR + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word--)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xED: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + } + break; + case 0xEE: // XOR n + RegAF.Word = TableALU[5, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xEF: // RST $28 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x28; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF0: // RET P + if (!RegFlagS) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xF1: // POP AF + RegAF.Low = ReadMemory(RegSP.Word++); RegAF.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xF2: // JP P, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagS) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xF3: // DI + IFF1 = IFF2 = false; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF4: // CALL P, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagS) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xF5: // PUSH AF + WriteMemory(--RegSP.Word, RegAF.High); WriteMemory(--RegSP.Word, RegAF.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF6: // OR n + RegAF.Word = TableALU[6, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xF7: // RST $30 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x30; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF8: // RET M + if (RegFlagS) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xF9: // LD SP, HL + RegSP.Word = RegHL.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0xFA: // JP M, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagS) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xFB: // EI + IFF1 = IFF2 = true; + Interruptable = false; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFC: // CALL M, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagS) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xFD: // (Prefix) + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x01: // LD BC, nn + RegBC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x02: // LD (BC), A + WriteMemory(RegBC.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x03: // INC BC + ++RegBC.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x04: // INC B + RegAF.Low = (byte)(TableInc[++RegBC.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x05: // DEC B + RegAF.Low = (byte)(TableDec[--RegBC.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x06: // LD B, n + RegBC.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x07: // RLCA + RegAF.Word = TableRotShift[0, 0, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x08: // EX AF, AF' + TUS = RegAF.Word; RegAF.Word = RegAltAF.Word; RegAltAF.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x09: // ADD IY, BC + TI1 = (short)RegIY.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIY.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x0A: // LD A, (BC) + RegAF.High = ReadMemory(RegBC.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x0B: // DEC BC + --RegBC.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x0C: // INC C + RegAF.Low = (byte)(TableInc[++RegBC.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0D: // DEC C + RegAF.Low = (byte)(TableDec[--RegBC.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0E: // LD C, n + RegBC.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x0F: // RRCA + RegAF.Word = TableRotShift[0, 1, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x10: // DJNZ d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (--RegBC.High != 0) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 13; pendingCycles -= 13; + } else { + totalExecutedCycles += 8; pendingCycles -= 8; + } + break; + case 0x11: // LD DE, nn + RegDE.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x12: // LD (DE), A + WriteMemory(RegDE.Word, RegAF.High); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x13: // INC DE + ++RegDE.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x14: // INC D + RegAF.Low = (byte)(TableInc[++RegDE.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x15: // DEC D + RegAF.Low = (byte)(TableDec[--RegDE.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x16: // LD D, n + RegDE.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x17: // RLA + RegAF.Word = TableRotShift[0, 2, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x18: // JR d + TSB = (sbyte)ReadMemory(RegPC.Word++); + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x19: // ADD IY, DE + TI1 = (short)RegIY.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIY.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x1A: // LD A, (DE) + RegAF.High = ReadMemory(RegDE.Word); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x1B: // DEC DE + --RegDE.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x1C: // INC E + RegAF.Low = (byte)(TableInc[++RegDE.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1D: // DEC E + RegAF.Low = (byte)(TableDec[--RegDE.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1E: // LD E, n + RegDE.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x1F: // RRA + RegAF.Word = TableRotShift[0, 3, RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x20: // JR NZ, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!RegFlagZ) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x21: // LD IY, nn + RegIY.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x22: // LD (nn), IY + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegIY.Low); + WriteMemory(TUS, RegIY.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x23: // INC IY + ++RegIY.Word; + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x24: // INC IYH + RegAF.Low = (byte)(TableInc[++RegIY.High] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x25: // DEC IYH + RegAF.Low = (byte)(TableDec[--RegIY.High] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x26: // LD IYH, n + RegIY.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x27: // DAA + RegAF.Word = TableDaa[RegAF.Word]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x28: // JR Z, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (RegFlagZ) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x29: // ADD IY, IY + TI1 = (short)RegIY.Word; TI2 = (short)RegIY.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIY.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x2A: // LD IY, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegIY.Low = ReadMemory(TUS++); RegIY.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x2B: // DEC IY + --RegIY.Word; + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x2C: // INC IYL + RegAF.Low = (byte)(TableInc[++RegIY.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x2D: // DEC IYL + RegAF.Low = (byte)(TableDec[--RegIY.Low] | (RegAF.Low & 1)); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x2E: // LD IYL, n + RegIY.Low = ReadMemory(RegPC.Word++); + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x2F: // CPL + RegAF.High ^= 0xFF; RegFlagH = true; RegFlagN = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x30: // JR NC, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (!RegFlagC) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x31: // LD SP, nn + RegSP.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0x32: // LD (nn), A + WriteMemory((ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256), RegAF.High); + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 0x33: // INC SP + ++RegSP.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x34: // INC (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + TB = ReadMemory((ushort)(RegIY.Word + Displacement)); RegAF.Low = (byte)(TableInc[++TB] | (RegAF.Low & 1)); WriteMemory((ushort)(RegIY.Word + Displacement), TB); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x35: // DEC (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + TB = ReadMemory((ushort)(RegIY.Word + Displacement)); RegAF.Low = (byte)(TableDec[--TB] | (RegAF.Low & 1)); WriteMemory((ushort)(RegIY.Word + Displacement), TB); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x36: // LD (IY+d), n + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), ReadMemory(RegPC.Word++)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x37: // SCF + RegFlagH = false; RegFlagN = false; RegFlagC = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x38: // JR C, d + TSB = (sbyte)ReadMemory(RegPC.Word++); + if (RegFlagC) { + RegPC.Word = (ushort)(RegPC.Word + TSB); + totalExecutedCycles += 12; pendingCycles -= 12; + } else { + totalExecutedCycles += 7; pendingCycles -= 7; + } + break; + case 0x39: // ADD IY, SP + TI1 = (short)RegIY.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegIY.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x3A: // LD A, (nn) + RegAF.High = ReadMemory((ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256)); + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 0x3B: // DEC SP + --RegSP.Word; + totalExecutedCycles += 6; pendingCycles -= 6; + break; + case 0x3C: // INC A + RegAF.Low = (byte)(TableInc[++RegAF.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3D: // DEC A + RegAF.Low = (byte)(TableDec[--RegAF.High] | (RegAF.Low & 1)); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3E: // LD A, n + RegAF.High = ReadMemory(RegPC.Word++); + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0x3F: // CCF + RegFlagH = RegFlagC; RegFlagN = false; RegFlagC ^= true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x40: // LD B, B + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x41: // LD B, C + RegBC.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x42: // LD B, D + RegBC.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x43: // LD B, E + RegBC.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x44: // LD B, IYH + RegBC.High = RegIY.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x45: // LD B, IYL + RegBC.High = RegIY.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x46: // LD B, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegBC.High = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x47: // LD B, A + RegBC.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x48: // LD C, B + RegBC.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x49: // LD C, C + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4A: // LD C, D + RegBC.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4B: // LD C, E + RegBC.Low = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x4C: // LD C, IYH + RegBC.Low = RegIY.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x4D: // LD C, IYL + RegBC.Low = RegIY.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x4E: // LD C, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegBC.Low = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x4F: // LD C, A + RegBC.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x50: // LD D, B + RegDE.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x51: // LD D, C + RegDE.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x52: // LD D, D + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x53: // LD D, E + RegDE.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x54: // LD D, IYH + RegDE.High = RegIY.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x55: // LD D, IYL + RegDE.High = RegIY.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x56: // LD D, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegDE.High = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x57: // LD D, A + RegDE.High = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x58: // LD E, B + RegDE.Low = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x59: // LD E, C + RegDE.Low = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5A: // LD E, D + RegDE.Low = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5B: // LD E, E + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x5C: // LD E, IYH + RegDE.Low = RegIY.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x5D: // LD E, IYL + RegDE.Low = RegIY.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x5E: // LD E, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegDE.Low = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x5F: // LD E, A + RegDE.Low = RegAF.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x60: // LD IYH, B + RegIY.High = RegBC.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x61: // LD IYH, C + RegIY.High = RegBC.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x62: // LD IYH, D + RegIY.High = RegDE.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x63: // LD IYH, E + RegIY.High = RegDE.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x64: // LD IYH, IYH + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x65: // LD IYH, IYL + RegIY.High = RegIY.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x66: // LD H, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegHL.High = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x67: // LD IYH, A + RegIY.High = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x68: // LD IYL, B + RegIY.Low = RegBC.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x69: // LD IYL, C + RegIY.Low = RegBC.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6A: // LD IYL, D + RegIY.Low = RegDE.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6B: // LD IYL, E + RegIY.Low = RegDE.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6C: // LD IYL, IYH + RegIY.Low = RegIY.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6D: // LD IYL, IYL + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x6E: // LD L, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegHL.Low = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x6F: // LD IYL, A + RegIY.Low = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x70: // LD (IY+d), B + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegBC.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x71: // LD (IY+d), C + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegBC.Low); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x72: // LD (IY+d), D + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegDE.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x73: // LD (IY+d), E + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegDE.Low); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x74: // LD (IY+d), H + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegHL.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x75: // LD (IY+d), L + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegHL.Low); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x76: // HALT + Halt(); + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x77: // LD (IY+d), A + Displacement = (sbyte)ReadMemory(RegPC.Word++); + WriteMemory((ushort)(RegIY.Word + Displacement), RegAF.High); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x78: // LD A, B + RegAF.High = RegBC.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x79: // LD A, C + RegAF.High = RegBC.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7A: // LD A, D + RegAF.High = RegDE.High; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7B: // LD A, E + RegAF.High = RegDE.Low; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x7C: // LD A, IYH + RegAF.High = RegIY.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x7D: // LD A, IYL + RegAF.High = RegIY.Low; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x7E: // LD A, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.High = ReadMemory((ushort)(RegIY.Word + Displacement)); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x7F: // LD A, A + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x80: // ADD A, B + RegAF.Word = TableALU[0, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x81: // ADD A, C + RegAF.Word = TableALU[0, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x82: // ADD A, D + RegAF.Word = TableALU[0, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x83: // ADD A, E + RegAF.Word = TableALU[0, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x84: // ADD A, IYH + RegAF.Word = TableALU[0, RegAF.High, RegIY.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x85: // ADD A, IYL + RegAF.Word = TableALU[0, RegAF.High, RegIY.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x86: // ADD A, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[0, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), 0]; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x87: // ADD A, A + RegAF.Word = TableALU[0, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x88: // ADC A, B + RegAF.Word = TableALU[1, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x89: // ADC A, C + RegAF.Word = TableALU[1, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8A: // ADC A, D + RegAF.Word = TableALU[1, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8B: // ADC A, E + RegAF.Word = TableALU[1, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8C: // ADC A, IYH + RegAF.Word = TableALU[1, RegAF.High, RegIY.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x8D: // ADC A, IYL + RegAF.Word = TableALU[1, RegAF.High, RegIY.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x8E: // ADC A, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[1, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), RegFlagC ? 1 : 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x8F: // ADC A, A + RegAF.Word = TableALU[1, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x90: // SUB B + RegAF.Word = TableALU[2, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x91: // SUB C + RegAF.Word = TableALU[2, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x92: // SUB D + RegAF.Word = TableALU[2, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x93: // SUB E + RegAF.Word = TableALU[2, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x94: // SUB IYH + RegAF.Word = TableALU[2, RegAF.High, RegIY.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x95: // SUB IYL + RegAF.Word = TableALU[2, RegAF.High, RegIY.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x96: // SUB (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[2, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x97: // SUB A, A + RegAF.Word = TableALU[2, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x98: // SBC A, B + RegAF.Word = TableALU[3, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x99: // SBC A, C + RegAF.Word = TableALU[3, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9A: // SBC A, D + RegAF.Word = TableALU[3, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9B: // SBC A, E + RegAF.Word = TableALU[3, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9C: // SBC A, IYH + RegAF.Word = TableALU[3, RegAF.High, RegIY.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x9D: // SBC A, IYL + RegAF.Word = TableALU[3, RegAF.High, RegIY.Low, RegFlagC ? 1 : 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x9E: // SBC A, (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[3, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), RegFlagC ? 1 : 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0x9F: // SBC A, A + RegAF.Word = TableALU[3, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA0: // AND B + RegAF.Word = TableALU[4, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA1: // AND C + RegAF.Word = TableALU[4, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA2: // AND D + RegAF.Word = TableALU[4, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA3: // AND E + RegAF.Word = TableALU[4, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA4: // AND IYH + RegAF.Word = TableALU[4, RegAF.High, RegIY.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xA5: // AND IYL + RegAF.Word = TableALU[4, RegAF.High, RegIY.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xA6: // AND (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[4, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xA7: // AND A + RegAF.Word = TableALU[4, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA8: // XOR B + RegAF.Word = TableALU[5, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA9: // XOR C + RegAF.Word = TableALU[5, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAA: // XOR D + RegAF.Word = TableALU[5, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAB: // XOR E + RegAF.Word = TableALU[5, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAC: // XOR IYH + RegAF.Word = TableALU[5, RegAF.High, RegIY.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xAD: // XOR IYL + RegAF.Word = TableALU[5, RegAF.High, RegIY.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xAE: // XOR (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[5, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xAF: // XOR A + RegAF.Word = TableALU[5, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB0: // OR B + RegAF.Word = TableALU[6, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB1: // OR C + RegAF.Word = TableALU[6, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB2: // OR D + RegAF.Word = TableALU[6, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB3: // OR E + RegAF.Word = TableALU[6, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB4: // OR IYH + RegAF.Word = TableALU[6, RegAF.High, RegIY.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xB5: // OR IYL + RegAF.Word = TableALU[6, RegAF.High, RegIY.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xB6: // OR (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[6, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xB7: // OR A + RegAF.Word = TableALU[6, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB8: // CP B + RegAF.Word = TableALU[7, RegAF.High, RegBC.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB9: // CP C + RegAF.Word = TableALU[7, RegAF.High, RegBC.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBA: // CP D + RegAF.Word = TableALU[7, RegAF.High, RegDE.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBB: // CP E + RegAF.Word = TableALU[7, RegAF.High, RegDE.Low, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBC: // CP IYH + RegAF.Word = TableALU[7, RegAF.High, RegIY.High, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xBD: // CP IYL + RegAF.Word = TableALU[7, RegAF.High, RegIY.Low, 0]; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0xBE: // CP (IY+d) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + RegAF.Word = TableALU[7, RegAF.High, ReadMemory((ushort)(RegIY.Word + Displacement)), 0]; + totalExecutedCycles += 19; pendingCycles -= 19; + break; + case 0xBF: // CP A + RegAF.Word = TableALU[7, RegAF.High, RegAF.High, 0]; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC0: // RET NZ + if (!RegFlagZ) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xC1: // POP BC + RegBC.Low = ReadMemory(RegSP.Word++); RegBC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC2: // JP NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagZ) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC3: // JP nn + RegPC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xC4: // CALL NZ, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagZ) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xC5: // PUSH BC + WriteMemory(--RegSP.Word, RegBC.High); WriteMemory(--RegSP.Word, RegBC.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xC6: // ADD A, n + RegAF.Word = TableALU[0, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xC7: // RST $00 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x00; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xC8: // RET Z + if (RegFlagZ) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xC9: // RET + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xCA: // JP Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagZ) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xCB: // (Prefix) + Displacement = (sbyte)ReadMemory(RegPC.Word++); + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x01: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x02: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x03: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x04: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x05: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x06: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x07: // RLC (IY+d) + TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x08: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x09: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0A: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0B: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0C: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0D: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0E: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x0F: // RRC (IY+d) + TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x10: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x11: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x12: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x13: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x14: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x15: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x16: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x17: // RL (IY+d) + TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x18: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x19: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1A: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1B: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1C: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1D: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1E: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x1F: // RR (IY+d) + TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x20: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x21: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x22: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x23: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x24: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x25: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x26: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x27: // SLA (IY+d) + TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x28: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x29: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2A: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2B: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2C: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2D: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2E: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x2F: // SRA (IY+d) + TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x30: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x31: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x32: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x33: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x34: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x35: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x36: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x37: // SL1 (IY+d) + TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x38: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x39: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3A: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3B: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3C: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3D: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3E: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x3F: // SRL (IY+d) + TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemory((ushort)(RegIY.Word + Displacement))]; + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); + RegAF.Low = (byte)TUS; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x40: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x41: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x42: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x43: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x44: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x45: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x46: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x47: // BIT 0, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x48: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x49: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4A: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4B: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4C: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4D: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4E: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4F: // BIT 1, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x50: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x51: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x52: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x53: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x54: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x55: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x56: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x57: // BIT 2, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x58: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x59: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5A: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5B: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5C: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5D: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5E: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5F: // BIT 3, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x60: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x61: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x62: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x63: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x64: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x65: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x66: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x67: // BIT 4, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x68: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x69: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6A: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6B: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6C: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6D: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6E: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x6F: // BIT 5, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x70: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x71: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x72: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x73: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x74: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x75: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x76: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x77: // BIT 6, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; + RegFlagP = RegFlagZ; + RegFlagS = false; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x78: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x79: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7A: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7B: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7C: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7D: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7E: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7F: // BIT 7, (IY+d) + RegFlagZ = (ReadMemory((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; + RegFlagP = RegFlagZ; + RegFlagS = !RegFlagZ; + RegFlagH = true; + RegFlagN = false; + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x80: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x81: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x82: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x83: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x84: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x85: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x86: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x87: // RES 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x88: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x89: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8A: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8B: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8C: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8D: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8E: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x8F: // RES 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x90: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x91: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x92: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x93: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x94: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x95: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x96: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x97: // RES 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x98: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x99: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9A: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9B: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9C: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9D: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9E: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0x9F: // RES 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA0: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA1: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA2: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA3: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA4: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA5: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA6: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA7: // RES 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA8: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xA9: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAA: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAB: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAC: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAD: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAE: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xAF: // RES 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB0: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB1: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB2: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB3: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB4: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB5: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB6: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB7: // RES 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB8: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xB9: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBA: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBB: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBC: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBD: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBE: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xBF: // RES 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC0: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC1: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC2: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC3: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC4: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC5: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC6: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC7: // SET 0, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC8: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xC9: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCA: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCB: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCC: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCD: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCE: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xCF: // SET 1, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD0: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD1: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD2: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD3: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD4: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD5: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD6: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD7: // SET 2, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD8: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xD9: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDA: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDB: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDC: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDD: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDE: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xDF: // SET 3, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE0: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE1: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE2: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE3: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE4: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE5: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE6: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE7: // SET 4, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE8: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE9: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEA: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEB: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEC: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xED: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEE: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xEF: // SET 5, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF0: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF1: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF2: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF3: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF4: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF5: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF6: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF7: // SET 6, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF8: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xF9: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFA: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFB: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFC: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFD: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFE: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xFF: // SET 7, (IY+d) + WriteMemory((ushort)(RegIY.Word + Displacement), (byte)(ReadMemory((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); + totalExecutedCycles += 23; pendingCycles -= 23; + break; + } + break; + case 0xCC: // CALL Z, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagZ) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xCD: // CALL nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + break; + case 0xCE: // ADC A, n + RegAF.Word = TableALU[1, RegAF.High, ReadMemory(RegPC.Word++), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xCF: // RST $08 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x08; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD0: // RET NC + if (!RegFlagC) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xD1: // POP DE + RegDE.Low = ReadMemory(RegSP.Word++); RegDE.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xD2: // JP NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagC) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xD3: // OUT n, A + WriteHardware(ReadMemory(RegPC.Word++), RegAF.High); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD4: // CALL NC, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xD5: // PUSH DE + WriteMemory(--RegSP.Word, RegDE.High); WriteMemory(--RegSP.Word, RegDE.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD6: // SUB n + RegAF.Word = TableALU[2, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xD7: // RST $10 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x10; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xD8: // RET C + if (RegFlagC) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xD9: // EXX + TUS = RegBC.Word; RegBC.Word = RegAltBC.Word; RegAltBC.Word = TUS; + TUS = RegDE.Word; RegDE.Word = RegAltDE.Word; RegAltDE.Word = TUS; + TUS = RegHL.Word; RegHL.Word = RegAltHL.Word; RegAltHL.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDA: // JP C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xDB: // IN A, n + RegAF.High = ReadHardware((ushort)ReadMemory(RegPC.Word++)); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xDC: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xDD: // <- + // Invalid sequence. + totalExecutedCycles += 1337; pendingCycles -= 1337; + break; + case 0xDE: // SBC A, n + RegAF.Word = TableALU[3, RegAF.High, ReadMemory(RegPC.Word++), RegFlagC ? 1 : 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xDF: // RST $18 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x18; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE0: // RET PO + if (!RegFlagP) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xE1: // POP IY + RegIY.Low = ReadMemory(RegSP.Word++); RegIY.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0xE2: // JP PO, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagP) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xE3: // EX (SP), IY + TUS = RegSP.Word; TBL = ReadMemory(TUS++); TBH = ReadMemory(TUS--); + WriteMemory(TUS++, RegIY.Low); WriteMemory(TUS, RegIY.High); + RegIY.Low = TBL; RegIY.High = TBH; + totalExecutedCycles += 23; pendingCycles -= 23; + break; + case 0xE4: // CALL C, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagC) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xE5: // PUSH IY + WriteMemory(--RegSP.Word, RegIY.High); WriteMemory(--RegSP.Word, RegIY.Low); + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0xE6: // AND n + RegAF.Word = TableALU[4, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xE7: // RST $20 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x20; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xE8: // RET PE + if (RegFlagP) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xE9: // JP IY + RegPC.Word = RegIY.Word; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0xEA: // JP PE, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagP) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xEB: // EX DE, HL + TUS = RegDE.Word; RegDE.Word = RegHL.Word; RegHL.Word = TUS; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEC: // CALL PE, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagP) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xED: // (Prefix) + ++RegR; + switch (ReadMemory(RegPC.Word++)) { + case 0x00: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x01: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x02: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x03: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x04: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x05: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x06: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x07: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x08: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x09: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x0F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x10: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x11: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x12: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x13: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x14: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x15: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x16: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x17: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x18: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x19: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x1F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x20: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x21: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x22: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x23: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x24: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x25: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x26: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x27: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x28: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x29: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x2F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x30: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x31: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x32: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x33: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x34: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x35: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x36: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x37: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x38: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x39: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x3F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x40: // IN B, C + RegBC.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegBC.High > 127; + RegFlagZ = RegBC.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegBC.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x41: // OUT C, B + WriteHardware(RegBC.Low, RegBC.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x42: // SBC HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegBC.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegBC.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x43: // LD (nn), BC + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegBC.Low); + WriteMemory(TUS, RegBC.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x44: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x45: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x46: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x47: // LD I, A + RegI = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x48: // IN C, C + RegBC.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegBC.Low > 127; + RegFlagZ = RegBC.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegBC.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x49: // OUT C, C + WriteHardware(RegBC.Low, RegBC.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x4A: // ADC HL, BC + TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x4B: // LD BC, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegBC.Low = ReadMemory(TUS++); RegBC.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x4C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x4E: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x4F: // LD R, A + RegR = RegAF.High; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x50: // IN D, C + RegDE.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegDE.High > 127; + RegFlagZ = RegDE.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegDE.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x51: // OUT C, D + WriteHardware(RegBC.Low, RegDE.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x52: // SBC HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegDE.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegDE.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x53: // LD (nn), DE + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegDE.Low); + WriteMemory(TUS, RegDE.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x54: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x55: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x56: // IM $1 + interruptMode = 1; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x57: // LD A, I + RegAF.High = RegI; + RegFlagS = RegI > 127; + RegFlagZ = RegI == 0; + RegFlagH = false; + RegFlagN = false; + RegFlagP = IFF2; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x58: // IN E, C + RegDE.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegDE.Low > 127; + RegFlagZ = RegDE.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegDE.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x59: // OUT C, E + WriteHardware(RegBC.Low, RegDE.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x5A: // ADC HL, DE + TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x5B: // LD DE, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegDE.Low = ReadMemory(TUS++); RegDE.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x5C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x5E: // IM $2 + interruptMode = 2; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x5F: // LD A, R + RegAF.High = (byte)(RegR & 0x7F); + RegFlagS = (byte)(RegR & 0x7F) > 127; + RegFlagZ = (byte)(RegR & 0x7F) == 0; + RegFlagH = false; + RegFlagN = false; + RegFlagP = IFF2; + totalExecutedCycles += 9; pendingCycles -= 9; + break; + case 0x60: // IN H, C + RegHL.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegHL.High > 127; + RegFlagZ = RegHL.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegHL.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x61: // OUT C, H + WriteHardware(RegBC.Low, RegHL.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x62: // SBC HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegHL.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegHL.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x63: // LD (nn), HL + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegHL.Low); + WriteMemory(TUS, RegHL.High); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x64: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x65: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x66: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x67: // RRD + TB1 = RegAF.High; TB2 = ReadMemory(RegHL.Word); + WriteMemory(RegHL.Word, (byte)((TB2 >> 4) + (TB1 << 4))); + RegAF.High = (byte)((TB1 & 0xF0) + (TB2 & 0x0F)); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + RegFlag3 = (RegAF.High & 0x08) != 0; + RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 18; pendingCycles -= 18; + break; + case 0x68: // IN L, C + RegHL.Low = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegHL.Low > 127; + RegFlagZ = RegHL.Low == 0; + RegFlagH = false; + RegFlagP = TableParity[RegHL.Low]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x69: // OUT C, L + WriteHardware(RegBC.Low, RegHL.Low); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x6A: // ADC HL, HL + TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x6B: // LD HL, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegHL.Low = ReadMemory(TUS++); RegHL.High = ReadMemory(TUS); + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0x6C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x6E: // IM $0 + interruptMode = 0; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x6F: // RLD + TB1 = RegAF.High; TB2 = ReadMemory(RegHL.Word); + WriteMemory(RegHL.Word, (byte)((TB1 & 0x0F) + (TB2 << 4))); + RegAF.High = (byte)((TB1 & 0xF0) + (TB2 >> 4)); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + RegFlag3 = (RegAF.High & 0x08) != 0; + RegFlag5 = (RegAF.High & 0x20) != 0; + totalExecutedCycles += 18; pendingCycles -= 18; + break; + case 0x70: // IN 0, C + TB = ReadHardware((ushort)RegBC.Low); + RegFlagS = TB > 127; + RegFlagZ = TB == 0; + RegFlagH = false; + RegFlagP = TableParity[TB]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x71: // OUT C, 0 + WriteHardware(RegBC.Low, 0); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x72: // SBC HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 - TI2; + if (RegFlagC) { --TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((RegHL.Word ^ RegSP.Word ^ TUS) & 0x1000) != 0; + RegFlagN = true; + RegFlagC = (((int)RegHL.Word - (int)RegSP.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x73: // LD (nn), SP + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + WriteMemory(TUS++, RegSP.Low); + WriteMemory(TUS, RegSP.High); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x74: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x75: // RETN + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + IFF1 = IFF2; + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x76: // IM $1 + interruptMode = 1; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x77: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x78: // IN A, C + RegAF.High = ReadHardware((ushort)RegBC.Low); + RegFlagS = RegAF.High > 127; + RegFlagZ = RegAF.High == 0; + RegFlagH = false; + RegFlagP = TableParity[RegAF.High]; + RegFlagN = false; + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x79: // OUT C, A + WriteHardware(RegBC.Low, RegAF.High); + totalExecutedCycles += 12; pendingCycles -= 12; + break; + case 0x7A: // ADC HL, SP + TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; + if (RegFlagC) { ++TIR; ++TI2; } + TUS = (ushort)TIR; + RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; + RegFlagN = false; + RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; + RegFlagP = TIR > 32767 || TIR < -32768; + RegFlagS = TUS > 32767; + RegFlagZ = TUS == 0; + RegHL.Word = TUS; + RegFlag3 = (TUS & 0x0800) != 0; + RegFlag5 = (TUS & 0x2000) != 0; + totalExecutedCycles += 15; pendingCycles -= 15; + break; + case 0x7B: // LD SP, (nn) + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + RegSP.Low = ReadMemory(TUS++); RegSP.High = ReadMemory(TUS); + totalExecutedCycles += 20; pendingCycles -= 20; + break; + case 0x7C: // NEG + RegAF.Word = TableNeg[RegAF.Word]; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7D: // RETI + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 14; pendingCycles -= 14; + break; + case 0x7E: // IM $2 + interruptMode = 2; + totalExecutedCycles += 8; pendingCycles -= 8; + break; + case 0x7F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x80: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x81: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x82: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x83: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x84: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x85: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x86: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x87: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x88: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x89: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x8F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x90: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x91: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x92: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x93: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x94: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x95: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x96: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x97: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x98: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x99: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9A: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9B: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9C: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9D: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9E: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0x9F: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA0: // LDI + WriteMemory(RegDE.Word++, TB1 = ReadMemory(RegHL.Word++)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA1: // CPI + TB1 = ReadMemory(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA2: // INI + WriteMemory(RegHL.Word++, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA3: // OUTI + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word++)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xA8: // LDD + WriteMemory(RegDE.Word--, TB1 = ReadMemory(RegHL.Word--)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xA9: // CPD + TB1 = ReadMemory(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAA: // IND + WriteMemory(RegHL.Word--, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAB: // OUTD + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word--)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + totalExecutedCycles += 16; pendingCycles -= 16; + break; + case 0xAC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xAF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB0: // LDIR + WriteMemory(RegDE.Word++, TB1 = ReadMemory(RegHL.Word++)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + if (RegBC.Word != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB1: // CPIR + TB1 = ReadMemory(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + if (RegBC.Word != 0 && !RegFlagZ) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB2: // INIR + WriteMemory(RegHL.Word++, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB3: // OTIR + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word++)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xB8: // LDDR + WriteMemory(RegDE.Word--, TB1 = ReadMemory(RegHL.Word--)); + TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + RegFlagH = false; + RegFlagN = false; + if (RegBC.Word != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xB9: // CPDR + TB1 = ReadMemory(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); + RegFlagN = true; + RegFlagH = TableHalfBorrow[RegAF.High, TB1]; + RegFlagZ = TB2 == 0; + RegFlagS = TB2 > 127; + TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; + --RegBC.Word; + RegFlagP = RegBC.Word != 0; + if (RegBC.Word != 0 && !RegFlagZ) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBA: // INDR + WriteMemory(RegHL.Word--, ReadHardware(RegBC.Word)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBB: // OTDR + WriteHardware(RegBC.Word, ReadMemory(RegHL.Word--)); + --RegBC.High; + RegFlagZ = RegBC.High == 0; + RegFlagN = true; + if (RegBC.High != 0) { + RegPC.Word -= 2; + totalExecutedCycles += 21; pendingCycles -= 21; + } else { + totalExecutedCycles += 16; pendingCycles -= 16; + } + break; + case 0xBC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xBF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xC9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xCF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xD9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xDF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xE9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xED: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xEF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF0: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF1: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF2: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF3: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF4: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF5: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF6: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF7: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF8: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF9: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFA: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFB: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFC: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFD: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFE: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFF: // NOP + totalExecutedCycles += 4; pendingCycles -= 4; + break; + } + break; + case 0xEE: // XOR n + RegAF.Word = TableALU[5, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xEF: // RST $28 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x28; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF0: // RET P + if (!RegFlagS) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xF1: // POP AF + RegAF.Low = ReadMemory(RegSP.Word++); RegAF.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xF2: // JP P, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagS) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xF3: // DI + IFF1 = IFF2 = false; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xF4: // CALL P, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (!RegFlagS) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xF5: // PUSH AF + WriteMemory(--RegSP.Word, RegAF.High); WriteMemory(--RegSP.Word, RegAF.Low); + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF6: // OR n + RegAF.Word = TableALU[6, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xF7: // RST $30 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x30; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + case 0xF8: // RET M + if (RegFlagS) { + RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++); + totalExecutedCycles += 11; pendingCycles -= 11; + } else { + totalExecutedCycles += 5; pendingCycles -= 5; + } + break; + case 0xF9: // LD SP, IY + RegSP.Word = RegIY.Word; + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xFA: // JP M, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagS) { + RegPC.Word = TUS; + } + totalExecutedCycles += 10; pendingCycles -= 10; + break; + case 0xFB: // EI + IFF1 = IFF2 = true; + Interruptable = false; + totalExecutedCycles += 4; pendingCycles -= 4; + break; + case 0xFC: // CALL M, nn + TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256); + if (RegFlagS) { + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = TUS; + totalExecutedCycles += 17; pendingCycles -= 17; + } else { + totalExecutedCycles += 10; pendingCycles -= 10; + } + break; + case 0xFD: // <- + // Invalid sequence. + totalExecutedCycles += 1337; pendingCycles -= 1337; + break; + case 0xFE: // CP n + RegAF.Word = TableALU[7, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xFF: // RST $38 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x38; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + } + break; + case 0xFE: // CP n + RegAF.Word = TableALU[7, RegAF.High, ReadMemory(RegPC.Word++), 0]; + totalExecutedCycles += 7; pendingCycles -= 7; + break; + case 0xFF: // RST $38 + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x38; + totalExecutedCycles += 11; pendingCycles -= 11; + break; + } + + } + + // Process interrupt requests. + if (nonMaskableInterruptPending) + { + halted = false; + + totalExecutedCycles += 11; pendingCycles -= 11; + nonMaskableInterruptPending = false; + + iff2 = iff1; + iff1 = false; + + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x66; + NMICallback(); + + } else if (iff1 && interrupt && Interruptable) { + + Halted = false; + + iff1 = iff2 = false; + + switch (interruptMode) + { + case 0: + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 1: + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Word = 0x38; + totalExecutedCycles += 13; pendingCycles -= 13; + break; + case 2: + TUS = (ushort)(RegI * 256 + 0); + WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low); + RegPC.Low = ReadMemory(TUS++); RegPC.High = ReadMemory(TUS); + totalExecutedCycles += 19; pendingCycles -= 19; + break; + } + IRQCallback(); + } + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80/Interrupts.cs b/BizHawk.Emulation/CPUs/Z80/Interrupts.cs new file mode 100644 index 0000000000..e1acd01ca1 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80/Interrupts.cs @@ -0,0 +1,55 @@ +using System; + +namespace BizHawk.Emulation.CPUs.Z80 +{ + public partial class Z80A + { + private bool iff1; + public bool IFF1 { get { return iff1; } set { iff1 = value; } } + + private bool iff2; + public bool IFF2 { get { return iff2; } set { iff2 = value; } } + + private bool interrupt; + public bool Interrupt { get { return interrupt; } set { interrupt = value; } } + + private bool nonMaskableInterrupt; + public bool NonMaskableInterrupt + { + get { return nonMaskableInterrupt; } + set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; } + } + + private bool nonMaskableInterruptPending; + public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } } + + private int interruptMode; + public int InterruptMode + { + get { return interruptMode; } + set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; } + } + + private bool halted; + public bool Halted { get { return halted; } set { halted = value; } } + + public Action IRQCallback = delegate() { }; + public Action NMICallback = delegate() { }; + + private void ResetInterrupts() + { + IFF1 = false; + IFF2 = false; + Interrupt = false; + NonMaskableInterrupt = false; + NonMaskableInterruptPending = false; + InterruptMode = 1; + Halted = false; + } + + private void Halt() + { + Halted = true; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80/Registers.cs b/BizHawk.Emulation/CPUs/Z80/Registers.cs new file mode 100644 index 0000000000..98b395749b --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80/Registers.cs @@ -0,0 +1,239 @@ +using System.Runtime.InteropServices; +using System; + +namespace BizHawk.Emulation.CPUs.Z80 +{ + public partial class Z80A + { + [StructLayout(LayoutKind.Explicit)] + [Serializable()] + public struct RegisterPair + { + [FieldOffset(0)] + public ushort Word; + + [FieldOffset(0)] + public byte Low; + + [FieldOffset(1)] + public byte High; + + public RegisterPair(ushort value) + { + Word = value; + Low = (byte)(Word); + High = (byte)(Word >> 8); + } + + public static implicit operator ushort(RegisterPair rp) + { + return rp.Word; + } + + public static implicit operator RegisterPair(ushort value) + { + return new RegisterPair(value); + } + } + + private bool RegFlagC + { + get { return (RegAF.Low & 0x01) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x01) | (value ? 0x01 : 0x00)); } + } + + private bool RegFlagN + { + get { return (RegAF.Low & 0x02) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x02) | (value ? 0x02 : 0x00)); } + } + + private bool RegFlagP + { + get { return (RegAF.Low & 0x04) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x04) | (value ? 0x04 : 0x00)); } + } + + private bool RegFlag3 + { + get { return (RegAF.Low & 0x08) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x08) | (value ? 0x08 : 0x00)); } + } + + private bool RegFlagH + { + get { return (RegAF.Low & 0x10) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x10) | (value ? 0x10 : 0x00)); } + } + + private bool RegFlag5 + { + get { return (RegAF.Low & 0x20) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x20) | (value ? 0x20 : 0x00)); } + } + + private bool RegFlagZ + { + get { return (RegAF.Low & 0x40) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x40) | (value ? 0x40 : 0x00)); } + } + + private bool RegFlagS + { + get { return (RegAF.Low & 0x80) != 0; } + set { RegAF.Low = (byte)((RegAF.Low & ~0x80) | (value ? 0x80 : 0x00)); } + } + + private RegisterPair RegAF; + private RegisterPair RegBC; + private RegisterPair RegDE; + private RegisterPair RegHL; + + private RegisterPair RegAltAF; // Shadow for A and F + private RegisterPair RegAltBC; // Shadow for B and C + private RegisterPair RegAltDE; // Shadow for D and E + private RegisterPair RegAltHL; // Shadow for H and L + + private byte RegI; // I (interrupt vector) + private byte RegR; // R (memory refresh) + + private RegisterPair RegIX; // IX (index register x) + private RegisterPair RegIY; // IY (index register y) + + private RegisterPair RegSP; // SP (stack pointer) + private RegisterPair RegPC; // PC (program counter) + + private void ResetRegisters() + { + // Clear main registers + RegAF = 0; RegBC = 0; RegDE = 0; RegHL = 0; + // Clear alternate registers + RegAltAF = 0; RegAltBC = 0; RegAltDE = 0; RegAltHL = 0; + // Clear special purpose registers + RegI = 0; RegR = 0; + RegIX.Word = 0; RegIY.Word = 0; + RegSP.Word = 0; RegPC.Word = 0; + } + + public byte RegisterA + { + get { return RegAF.High; } + set { RegAF.High = value; } + } + + public byte RegisterF + { + get { return RegAF.Low; } + set { RegAF.Low = value; } + } + + public ushort RegisterAF + { + get { return RegAF.Word; } + set { RegAF.Word = value; } + } + + public byte RegisterB + { + get { return RegBC.High; } + set { RegBC.High = value; } + } + + public byte RegisterC + { + get { return RegBC.Low; } + set { RegBC.Low = value; } + } + + public ushort RegisterBC + { + get { return RegBC.Word; } + set { RegBC.Word = value; } + } + + public byte RegisterD + { + get { return RegDE.High; } + set { RegDE.High = value; } + } + + public byte RegisterE + { + get { return RegDE.Low; } + set { RegDE.Low = value; } + } + public ushort RegisterDE + { + get { return RegDE.Word; } + set { RegDE.Word = value; } + } + + public byte RegisterH + { + get { return RegHL.High; } + set { RegHL.High = value; } + } + + public byte RegisterL + { + get { return RegHL.Low; } + set { RegHL.Low = value; } + } + public ushort RegisterHL + { + get { return RegHL.Word; } + set { RegHL.Word = value; } + } + + public ushort RegisterPC + { + get { return RegPC.Word; } + set { RegPC.Word = value; } + } + public ushort RegisterSP + { + get { return RegSP.Word; } + set { RegSP.Word = value; } + } + public ushort RegisterIX + { + get { return RegIX.Word; } + set { RegIX.Word = value; } + } + public ushort RegisterIY + { + get { return RegIY.Word; } + set { RegIY.Word = value; } + } + public byte RegisterI + { + get { return RegI; } + set { RegI = value; } + } + public byte RegisterR + { + get { return RegR; } + set { RegR = value; } + } + public ushort RegisterShadowAF + { + get { return RegAltAF.Word; } + set { RegAltAF.Word = value; } + } + public ushort RegisterShadowBC + { + get { return RegAltBC.Word; } + set { RegAltBC.Word = value; } + } + public ushort RegisterShadowDE + { + get { return RegAltDE.Word; } + set { RegAltDE.Word = value; } + } + public ushort RegisterShadowHL + { + get { return RegAltHL.Word; } + set { RegAltHL.Word = value; } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/CPUs/Z80/Tables.cs b/BizHawk.Emulation/CPUs/Z80/Tables.cs new file mode 100644 index 0000000000..1c52578800 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80/Tables.cs @@ -0,0 +1,321 @@ +namespace BizHawk.Emulation.CPUs.Z80 +{ + public partial class Z80A + { + private void InitialiseTables() + { + InitTableInc(); + InitTableDec(); + InitTableParity(); + InitTableALU(); + InitTableRotShift(); + InitTableHalfBorrow(); + InitTableHalfCarry(); + InitTableNeg(); + InitTableDaa(); + } + + private byte[] TableInc; + private void InitTableInc() + { + TableInc = new byte[256]; + for (int i = 0; i < 256; ++i) + TableInc[i] = FlagByte(false, false, i == 0x80, UndocumentedX(i), (i & 0xF) == 0x0, UndocumentedY(i), i == 0, i > 127); + } + + private byte[] TableDec; + private void InitTableDec() + { + TableDec = new byte[256]; + for (int i = 0; i < 256; ++i) + TableDec[i] = FlagByte(false, true, i == 0x7F, UndocumentedX(i), (i & 0xF) == 0xF, UndocumentedY(i), i == 0, i > 127); + } + + private bool[] TableParity; + private void InitTableParity() + { + TableParity = new bool[256]; + for (int i = 0; i < 256; ++i) + { + int Bits = 0; + for (int j = 0; j < 8; ++j) + { + Bits += (i >> j) & 1; + } + TableParity[i] = (Bits & 1) == 0; + } + } + + private ushort[, , ,] TableALU; + private void InitTableALU() + { + TableALU = new ushort[8, 256, 256, 2]; // Class, OP1, OP2, Carry + + for (int i = 0; i < 8; ++i) + { + for (int op1 = 0; op1 < 256; ++op1) + { + for (int op2 = 0; op2 < 256; ++op2) + { + for (int c = 0; c < 2; ++c) + { + + int ac = (i == 1 || i == 3) ? c : 0; + + bool S = false; + bool Z = false; + bool C = false; + bool H = false; + bool N = false; + bool P = false; + + byte result_b = 0; + int result_si = 0; + int result_ui = 0; + + // Fetch result + switch (i) + { + case 0: + case 1: + result_si = (sbyte)op1 + (sbyte)op2 + ac; + result_ui = op1 + op2 + ac; + break; + case 2: + case 3: + case 7: + result_si = (sbyte)op1 - (sbyte)op2 - ac; + result_ui = op1 - op2 - ac; + break; + case 4: + result_si = op1 & op2; + break; + case 5: + result_si = op1 ^ op2; + break; + case 6: + result_si = op1 | op2; + break; + } + + result_b = (byte)result_si; + + // Parity/Carry + + switch (i) + { + case 0: + case 1: + case 2: + case 3: + case 7: + P = result_si < -128 || result_si > 127; + C = result_ui < 0 || result_ui > 255; + break; + case 4: + case 5: + case 6: + P = TableParity[result_b]; + C = false; + break; + } + + // Subtraction + N = i == 2 || i == 3 || i == 7; + + // Half carry + switch (i) + { + case 0: + case 1: + H = ((op1 & 0xF) + (op2 & 0xF) + (ac & 0xF)) > 0xF; + break; + case 2: + case 3: + case 7: + H = ((op1 & 0xF) - (op2 & 0xF) - (ac & 0xF)) < 0x0; + break; + case 4: + H = true; + break; + case 5: + case 6: + H = false; + break; + } + + // Undocumented + byte UndocumentedFlags = (byte)(result_b & 0x28); + if (i == 7) UndocumentedFlags = (byte)(op2 & 0x28); + + S = result_b > 127; + Z = result_b == 0; + + if (i == 7) result_b = (byte)op1; + + TableALU[i, op1, op2, c] = (ushort)( + result_b * 256 + + ((C ? 0x01 : 0) + (N ? 0x02 : 0) + (P ? 0x04 : 0) + (H ? 0x10 : 0) + (Z ? 0x40 : 0) + (S ? 0x80 : 0)) + + (UndocumentedFlags)); + + } + } + } + } + } + + private bool[,] TableHalfBorrow; + private void InitTableHalfBorrow() + { + TableHalfBorrow = new bool[256, 256]; + for (int i = 0; i < 256; i++) + { + for (int j = 0; j < 256; j++) + { + TableHalfBorrow[i, j] = ((i & 0xF) - (j & 0xF)) < 0; + } + } + } + + private bool[,] TableHalfCarry; + private void InitTableHalfCarry() + { + TableHalfCarry = new bool[256, 256]; + for (int i = 0; i < 256; i++) + { + for (int j = 0; j < 256; j++) + { + TableHalfCarry[i, j] = ((i & 0xF) + (j & 0xF)) > 0xF; + } + } + } + + private ushort[, ,] TableRotShift; + private void InitTableRotShift() + { + TableRotShift = new ushort[2, 8, 65536]; // All, operation, AF + for (int all = 0; all < 2; all++) + { + for (int y = 0; y < 8; ++y) + { + for (int af = 0; af < 65536; af++) + { + byte Old = (byte)(af >> 8); + bool OldCarry = (af & 0x01) != 0; + + ushort newAf = (ushort)(af & ~(0x13)); // Clear HALF-CARRY, SUBTRACT and CARRY flags + + byte New = Old; + if ((y & 1) == 0) + { + if ((Old & 0x80) != 0) ++newAf; + + New <<= 1; + + if ((y & 0x04) == 0) { + if (((y & 0x02) == 0) ? ((newAf & 0x01) != 0) : OldCarry) New |= 0x01; + } else { + if ((y & 0x02) != 0) New |= 0x01; + } + + } else { + + if ((Old & 0x01) != 0) ++newAf; + + New >>= 1; + + if ((y & 0x04) == 0) { + if (((y & 0x02) == 0) ? ((newAf & 0x01) != 0) : OldCarry) New |= 0x80; + } else { + if ((y & 0x02) == 0) New |= (byte)(Old & 0x80); + } + } + + newAf &= 0xFF; + newAf |= (ushort)(New * 256); + + if (all == 1) + { + newAf &= unchecked((ushort)~0xC4); // Clear S, Z, P + if (New > 127) newAf |= 0x80; + if (New == 0) newAf |= 0x40; + if (TableParity[New]) newAf |= 0x04; + } + + TableRotShift[all, y, af] = (ushort)((newAf & ~0x28) | ((newAf >> 8) & 0x28)); + } + } + } + } + + private ushort[] TableNeg; + private void InitTableNeg() + { + TableNeg = new ushort[65536]; + for (int af = 0; af < 65536; af++) + { + ushort raf = 0; + byte b = (byte)(af >> 8); + byte a = (byte)-b; + raf |= (ushort)(a * 256); + raf |= FlagByte(b != 0x00, true, b == 0x80, UndocumentedX(a), TableHalfCarry[a, b], UndocumentedY(a), a == 0, a > 127); + TableNeg[af] = raf; + } + } + + private ushort[] TableDaa; + private void InitTableDaa() + { + TableDaa = new ushort[65536]; + for (int af = 0; af < 65536; ++af) + { + byte a = (byte)(af >> 8); + byte tmp = a; + + if (IsN(af)) + { + if (IsH(af) || ((a & 0x0F) > 0x09)) tmp -= 0x06; + if (IsC(af) || a > 0x99) tmp -= 0x60; + } else { + if (IsH(af) || ((a & 0x0F) > 0x09)) tmp += 0x06; + if (IsC(af) || a > 0x99) tmp += 0x60; + } + + TableDaa[af] = (ushort)((tmp * 256) + FlagByte(IsC(af) || a > 0x99, IsN(af), TableParity[tmp], UndocumentedX(tmp), ((a ^ tmp) & 0x10) != 0, UndocumentedY(tmp), tmp == 0, tmp > 127)); + } + } + + private byte FlagByte(bool C, bool N, bool P, bool X, bool H, bool Y, bool Z, bool S) + { + return (byte)( + (C ? 0x01 : 0) + + (N ? 0x02 : 0) + + (P ? 0x04 : 0) + + (X ? 0x08 : 0) + + (H ? 0x10 : 0) + + (Y ? 0x20 : 0) + + (Z ? 0x40 : 0) + + (S ? 0x80 : 0) + ); + } + + private bool UndocumentedX(int value) + { + return (value & 0x08) != 0; + } + + private bool UndocumentedY(int value) + { + return (value & 0x20) != 0; + } + + private bool IsC(int value) { return (value & 0x01) != 0; } + private bool IsN(int value) { return (value & 0x02) != 0; } + private bool IsP(int value) { return (value & 0x04) != 0; } + private bool IsX(int value) { return (value & 0x08) != 0; } + private bool IsH(int value) { return (value & 0x10) != 0; } + private bool IsY(int value) { return (value & 0x20) != 0; } + private bool IsZ(int value) { return (value & 0x40) != 0; } + private bool IsS(int value) { return (value & 0x80) != 0; } + } +} diff --git a/BizHawk.Emulation/CPUs/Z80/Z80A.cs b/BizHawk.Emulation/CPUs/Z80/Z80A.cs new file mode 100644 index 0000000000..158c0a3fd7 --- /dev/null +++ b/BizHawk.Emulation/CPUs/Z80/Z80A.cs @@ -0,0 +1,199 @@ +using System; +using System.Globalization; +using System.IO; + +// This Z80 emulator is a modified version of Ben Ryves 'Brazil' emulator. +// It is MIT licensed (not public domain). (See Licenses) + +namespace BizHawk.Emulation.CPUs.Z80 +{ + /// + /// ZiLOG Z80A CPU Emulator + /// + public sealed partial class Z80A + { + /// + /// Creates an instance of the emulator class. + /// + public Z80A() + { + InitialiseTables(); + Reset(); + } + + /// + /// Reset the Z80 to its initial state + /// + public void Reset() + { + ResetRegisters(); + ResetInterrupts(); + PendingCycles = 0; + ExpectedExecutedCycles = 0; + TotalExecutedCycles = 0; + } + + // Memory Access + + public Func ReadMemory; + public Action WriteMemory; + + public void UnregisterMemoryMapper() + { + ReadMemory = null; + WriteMemory = null; + } + + // Hardware I/O Port Access + + public Func ReadHardware; + public Action WriteHardware; + + // State Save/Load + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[Z80]"); + writer.WriteLine("AF {0:X4}", RegAF.Word); + writer.WriteLine("BC {0:X4}", RegBC.Word); + writer.WriteLine("DE {0:X4}", RegDE.Word); + writer.WriteLine("HL {0:X4}", RegHL.Word); + writer.WriteLine("ShadowAF {0:X4}", RegAltAF.Word); + writer.WriteLine("ShadowBC {0:X4}", RegAltBC.Word); + writer.WriteLine("ShadowDE {0:X4}", RegAltDE.Word); + writer.WriteLine("ShadowHL {0:X4}", RegAltHL.Word); + writer.WriteLine("I {0:X2}", RegI); + writer.WriteLine("R {0:X2}", RegR); + writer.WriteLine("IX {0:X4}", RegIX.Word); + writer.WriteLine("IY {0:X4}", RegIY.Word); + writer.WriteLine("SP {0:X4}", RegSP.Word); + writer.WriteLine("PC {0:X4}", RegPC.Word); + writer.WriteLine("IRQ {0}", interrupt); + writer.WriteLine("NMI {0}", nonMaskableInterrupt); + writer.WriteLine("NMIPending {0}", nonMaskableInterruptPending); + writer.WriteLine("IM {0}", InterruptMode); + writer.WriteLine("IFF1 {0}", IFF1); + writer.WriteLine("IFF2 {0}", IFF2); + writer.WriteLine("Halted {0}", Halted); + writer.WriteLine("ExecutedCycles {0}", TotalExecutedCycles); + writer.WriteLine("PendingCycles {0}", PendingCycles); + writer.WriteLine("[/Z80]"); + writer.WriteLine(); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/Z80]") break; + if (args[0] == "AF") + RegAF.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "BC") + RegBC.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "DE") + RegDE.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "HL") + RegHL.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ShadowAF") + RegAltAF.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ShadowBC") + RegAltBC.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ShadowDE") + RegAltDE.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ShadowHL") + RegAltHL.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "I") + RegI = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "R") + RegR = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "IX") + RegIX.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "IY") + RegIY.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "SP") + RegSP.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "PC") + RegPC.Word = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "IRQ") + interrupt = bool.Parse(args[1]); + else if (args[0] == "NMI") + nonMaskableInterrupt = bool.Parse(args[1]); + else if (args[0] == "NMIPending") + nonMaskableInterruptPending = bool.Parse(args[1]); + else if (args[0] == "IM") + InterruptMode = int.Parse(args[1]); + else if (args[0] == "IFF1") + IFF1 = bool.Parse(args[1]); + else if (args[0] == "IFF2") + IFF2 = bool.Parse(args[1]); + else if (args[0] == "Halted") + Halted = bool.Parse(args[1]); + else if (args[0] == "ExecutedCycles") + TotalExecutedCycles = int.Parse(args[1]); + else if (args[0] == "PendingCycles") + PendingCycles = int.Parse(args[1]); + + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(RegAF.Word); + writer.Write(RegBC.Word); + writer.Write(RegDE.Word); + writer.Write(RegHL.Word); + writer.Write(RegAltAF.Word); + writer.Write(RegAltBC.Word); + writer.Write(RegAltDE.Word); + writer.Write(RegAltHL.Word); + writer.Write(RegAltAF.Word); + writer.Write(RegI); + writer.Write(RegR); + writer.Write(RegIX.Word); + writer.Write(RegIY.Word); + writer.Write(RegSP.Word); + writer.Write(RegPC.Word); + writer.Write(interrupt); + writer.Write(nonMaskableInterrupt); + writer.Write(nonMaskableInterruptPending); + writer.Write(InterruptMode); + writer.Write(IFF1); + writer.Write(IFF2); + writer.Write(Halted); + writer.Write(TotalExecutedCycles); + writer.Write(PendingCycles); + } + + public void LoadStateBinary(BinaryReader reader) + { + RegAF.Word = reader.ReadUInt16(); + RegBC.Word = reader.ReadUInt16(); + RegDE.Word = reader.ReadUInt16(); + RegHL.Word = reader.ReadUInt16(); + RegAltAF.Word = reader.ReadUInt16(); + RegAltBC.Word = reader.ReadUInt16(); + RegAltDE.Word = reader.ReadUInt16(); + RegAltHL.Word = reader.ReadUInt16(); + RegAltAF.Word = reader.ReadUInt16(); + RegI = reader.ReadByte(); + RegR = reader.ReadByte(); + RegIX.Word = reader.ReadUInt16(); + RegIY.Word = reader.ReadUInt16(); + RegSP.Word = reader.ReadUInt16(); + RegPC.Word = reader.ReadUInt16(); + interrupt = reader.ReadBoolean(); + nonMaskableInterrupt = reader.ReadBoolean(); + nonMaskableInterruptPending = reader.ReadBoolean(); + InterruptMode = reader.ReadInt32(); + IFF1 = reader.ReadBoolean(); + IFF2 = reader.ReadBoolean(); + Halted = reader.ReadBoolean(); + TotalExecutedCycles = reader.ReadInt32(); + PendingCycles = reader.ReadInt32(); + } + } +} diff --git a/BizHawk.Emulation/CPUs/x86/Disassembler.cs b/BizHawk.Emulation/CPUs/x86/Disassembler.cs new file mode 100644 index 0000000000..acfbae8917 --- /dev/null +++ b/BizHawk.Emulation/CPUs/x86/Disassembler.cs @@ -0,0 +1,199 @@ +using System.Text; + +namespace BizHawk.Emulation.CPUs.x86 +{ + public class DisassemblyInfo + { + public int Addr; + public string Mnemonic; + public string Args; + public string RawBytes; + public int Length; + + public override string ToString() + { + return string.Format("{0:X6} {3,-12} {1,-8} {2}", Addr, Mnemonic, Args, RawBytes); + } + } + + public partial class x86 where CpuType : struct, x86CpuType + { + private ushort ReadWord(int addr) + { + return (ushort)(ReadMemory(addr++) + (ReadMemory(addr) << 8)); + } + + private string DisassembleRM8(ref int addr) + { + byte ModRM = ReadMemory(addr++); + int mod = (ModRM >> 6) & 3; + int r = (ModRM >> 3) & 7; + int m = ModRM & 7; + + string reg; + switch (r) + { + case 0: reg = "AL"; break; + case 1: reg = "CL"; break; + case 2: reg = "DL"; break; + case 3: reg = "BL"; break; + case 4: reg = "AH"; break; + case 5: reg = "CH"; break; + case 6: reg = "DH"; break; + case 7: reg = "BH"; break; + default: reg = "UNKNOWN"; break; + } + return reg+", "+DisassembleMod(ref addr, mod, m, 1); + } + + private string DisassembleMod(ref int addr, int mod, int m, int size) + { + string ret; + switch (mod) + { + case 0: + switch (m) + { + case 0: return "[BX+SI]"; + case 1: return "[BX+DI]"; + case 2: return "[BP+SI]"; + case 3: return "[BP+DI]"; + case 4: return "[SI]"; + case 5: return "[DI]"; + case 6: ret = string.Format("{0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 7: return "[BX]"; + } + break; + case 1: + switch (m) + { + case 0: return string.Format("[BX+SI] + {0:X2}h", ReadMemory(addr++)); + case 1: return string.Format("[BX+DI] + {0:X2}h", ReadMemory(addr++)); + case 2: return string.Format("[BP+SI] + {0:X2}h", ReadMemory(addr++)); + case 3: return string.Format("[BP+DI] + {0:X2}h", ReadMemory(addr++)); + case 4: return string.Format("[SI] + {0:X2}h", ReadMemory(addr++)); + case 5: return string.Format("[DI] + {0:X2}h", ReadMemory(addr++)); + case 6: return string.Format("[BP] + {0:X2}h", ReadMemory(addr++)); + case 7: return string.Format("[BX] + {0:X2}h", ReadMemory(addr++)); + } + break; + case 2: + switch (m) + { + case 0: ret = string.Format("[BX+SI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 1: ret = string.Format("[BX+DI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 2: ret = string.Format("[BP+SI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 3: ret = string.Format("[BP+DI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 4: ret = string.Format("[SI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 5: ret = string.Format("[DI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 6: ret = string.Format("[BP] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + case 7: ret = string.Format("[BX] + {0:X4}h", ReadWord(addr)); addr += 2; return ret; + } + break; + case 3: + switch (m) + { + case 0: return size == 1 ? "AL" : "AX"; + case 1: return size == 1 ? "CL" : "CX"; + case 2: return size == 1 ? "DL" : "DX"; + case 3: return size == 1 ? "BL" : "BX"; + case 4: return size == 1 ? "AH" : "SP"; + case 5: return size == 1 ? "CH" : "BP"; + case 6: return size == 1 ? "DH" : "SI"; + case 7: return size == 1 ? "BH" : "DI"; + } + break; + } + return "Disassembly Error"; + } + + public DisassemblyInfo Disassemble(int addr) + { + var info = new DisassemblyInfo { Addr = addr }; + byte op1 = ReadMemory(addr++); + switch (op1) + { + case 0x02: // ADD r8,r/m8 + info.Mnemonic = "ADD"; + info.Args = DisassembleRM8(ref addr); + break; + case 0xB0: // MOV AL, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("AL, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB1: // MOV CL, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("CL, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB2: // MOV DL, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("DL, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB3: // MOV BL, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("BL, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB4: // MOV AH, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("AH, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB5: // MOV CH, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("CH, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB6: // MOV DH, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("DH, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB7: // MOV BH, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("BH, {0:X2}h", ReadMemory(addr++)); + break; + case 0xB8: // MOV AX, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("AX, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xB9: // MOV CX, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("CX, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xBA: // MOV DX, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("DX, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xBB: // MOV BX, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("BX, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xBC: // MOV SP, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("SP, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xBD: // MOV BP, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("BP, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xBE: // MOV SI, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("SI, {0:X4}h", ReadWord(addr)); addr += 2; + break; + case 0xBF: // MOV DI, immed + info.Mnemonic = "MOV"; + info.Args = string.Format("DI, {0:X4}h", ReadWord(addr)); addr += 2; + break; + default: + info.Mnemonic = "DB"; + info.Args = string.Format("{0:X2}h", op1); + break; + } + + info.Length = addr - info.Addr; + var sb = new StringBuilder(); + for (int p = info.Addr; p < info.Addr + info.Length; p++) + sb.AppendFormat("{0:X2}", ReadMemory(p)); + info.RawBytes = sb.ToString(); + + return info; + } + } +} diff --git a/BizHawk.Emulation/CPUs/x86/Execute.cs b/BizHawk.Emulation/CPUs/x86/Execute.cs new file mode 100644 index 0000000000..f9f64ea8dc --- /dev/null +++ b/BizHawk.Emulation/CPUs/x86/Execute.cs @@ -0,0 +1,84 @@ +using System; + +namespace BizHawk.Emulation.CPUs.x86 +{ + public partial class x86 where CpuType: struct, x86CpuType + { + public void Execute(int cycles) + { + Console.WriteLine(Disassemble((CS << 4) + IP)); + byte opcode1 = ReadMemory((CS << 4) + IP); + IP++; + + switch (opcode1) + { + case 0xB0: // MOV AL, imm + AL = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB1: // MOV CL, immed + CL = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB2: // MOV DL, immed + DL = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB3: // MOV BL, immed + BL = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB4: // MOV AH, immed + AH = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB5: // MOV CH, immed + CH = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB6: // MOV DH, immed + DH = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB7: // MOV BH, immed + BH = ReadMemory((CS << 4) + IP++); + PendingCycles -= timing_mov_ri8; + break; + case 0xB8: // MOV AX, immed + AX = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xB9: // MOV CX, imm + CX = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xBA: // MOV DX, immed + DX = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xBB: // MOV BX, immed + BX = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xBC: // MOV SP, immed + SP = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xBD: // MOV BP, immed + BP = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xBE: // MOV SI, immed + SI = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + case 0xBF: // MOV DI, immed + DI = (ushort)(ReadMemory((CS << 4) + IP++) + (ReadMemory((CS << 4) + IP++) << 8)); + PendingCycles -= timing_mov_ri16; + break; + default: + throw new NotImplementedException(); + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/x86/Timing.cs b/BizHawk.Emulation/CPUs/x86/Timing.cs new file mode 100644 index 0000000000..b3a696ef64 --- /dev/null +++ b/BizHawk.Emulation/CPUs/x86/Timing.cs @@ -0,0 +1,19 @@ +namespace BizHawk.Emulation.CPUs.x86 +{ + public partial class x86 where CpuType : struct, x86CpuType + { + // TODO test if static on these is a performance boost + // it would be appropriate if so because closed types have their own static variables + private int timing_mov_ri8; + private int timing_mov_ri16; + + private void InitTiming() + { + if (typeof(CpuType) == typeof(Intel8086)) + { + timing_mov_ri8 = 4; + timing_mov_ri16 = 4; + } + } + } +} diff --git a/BizHawk.Emulation/CPUs/x86/x86.cs b/BizHawk.Emulation/CPUs/x86/x86.cs new file mode 100644 index 0000000000..df940bfa82 --- /dev/null +++ b/BizHawk.Emulation/CPUs/x86/x86.cs @@ -0,0 +1,100 @@ +using System; +using System.Runtime.InteropServices; + +namespace BizHawk.Emulation.CPUs.x86 +{ + public interface x86CpuType { }; + public struct Intel8086 : x86CpuType { }; + + public sealed partial class x86 where CpuType: struct, x86CpuType + { + // Machine State + public Register16 RegAX; + public Register16 RegBX; + public Register16 RegCX; + public Register16 RegDX; + + public ushort CS; + public ushort DS; + public ushort ES; + public ushort SS; + + public ushort SI; + public ushort DI; + public ushort IP; + public ushort SP; + public ushort BP; + + public bool CF; + public bool PF; + public bool AF; + public bool ZF; + public bool SF; + public bool TP; + public bool IF; + public bool DF; + public bool OF; + + public ushort Flags + { + get + { + ushort value = 2; + if (CF) value |= 1; + if (PF) value |= 4; + if (AF) value |= 16; + if (ZF) value |= 64; + if (SF) value |= 128; + if (TP) value |= 256; + if (IF) value |= 512; + if (DF) value |= 1024; + if (OF) value |= 2048; + return value; + } + } + + public int PendingCycles; + public int TotalExecutedCycles; + + // Memory Access + public Func ReadMemory; + public Action WriteMemory; + + public x86() + { + InitTiming(); + } + + // We expect these properties to get inlined by the CLR -- at some point we should test this assumption + public ushort AX { get { return RegAX.Word; } set { RegAX.Word = value; } } + public ushort BX { get { return RegBX.Word; } set { RegBX.Word = value; } } + public ushort CX { get { return RegCX.Word; } set { RegCX.Word = value; } } + public ushort DX { get { return RegDX.Word; } set { RegDX.Word = value; } } + public byte AL { get { return RegAX.Low; } set { RegAX.Low = value; } } + public byte BL { get { return RegBX.Low; } set { RegBX.Low = value; } } + public byte CL { get { return RegCX.Low; } set { RegCX.Low = value; } } + public byte DL { get { return RegDX.Low; } set { RegDX.Low = value; } } + public byte AH { get { return RegAX.High; } set { RegAX.High = value; } } + public byte BH { get { return RegBX.High; } set { RegBX.High = value; } } + public byte CH { get { return RegCX.High; } set { RegCX.High = value; } } + public byte DH { get { return RegDX.High; } set { RegDX.High = value; } } + } + + [StructLayout(LayoutKind.Explicit)] + public struct Register16 + { + [FieldOffset(0)] + public ushort Word; + + [FieldOffset(0)] + public byte Low; + + [FieldOffset(1)] + public byte High; + + public override string ToString() + { + return String.Format("{0:X4}", Word); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Gameboy/Bios.cs b/BizHawk.Emulation/Consoles/Gameboy/Bios.cs new file mode 100644 index 0000000000..9f49982eb6 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Bios.cs @@ -0,0 +1,25 @@ +namespace BizHawk.Emulation.Consoles.Gameboy +{ + public partial class Gameboy + { + public static readonly byte[] Bios = + { + 0x31, 0xFE, 0xFF, 0xAF, 0x21, 0xFF, 0x9F, 0x32, 0xCB, 0x7C, 0x20, 0xFB, 0x21, 0x26, 0xFF, 0x0E, + 0x11, 0x3E, 0x80, 0x32, 0xE2, 0x0C, 0x3E, 0xF3, 0xE2, 0x32, 0x3E, 0x77, 0x77, 0x3E, 0xFC, 0xE0, + 0x47, 0x11, 0x04, 0x01, 0x21, 0x10, 0x80, 0x1A, 0xCD, 0x95, 0x00, 0xCD, 0x96, 0x00, 0x13, 0x7B, + 0xFE, 0x34, 0x20, 0xF3, 0x11, 0xD8, 0x00, 0x06, 0x08, 0x1A, 0x13, 0x22, 0x23, 0x05, 0x20, 0xF9, + 0x3E, 0x19, 0xEA, 0x10, 0x99, 0x21, 0x2F, 0x99, 0x0E, 0x0C, 0x3D, 0x28, 0x08, 0x32, 0x0D, 0x20, + 0xF9, 0x2E, 0x0F, 0x18, 0xF3, 0x67, 0x3E, 0x64, 0x57, 0xE0, 0x42, 0x3E, 0x91, 0xE0, 0x40, 0x04, + 0x1E, 0x02, 0x0E, 0x0C, 0xF0, 0x44, 0xFE, 0x90, 0x20, 0xFA, 0x0D, 0x20, 0xF7, 0x1D, 0x20, 0xF2, + 0x0E, 0x13, 0x24, 0x7C, 0x1E, 0x83, 0xFE, 0x62, 0x28, 0x06, 0x1E, 0xC1, 0xFE, 0x64, 0x20, 0x06, + 0x7B, 0xE2, 0x0C, 0x3E, 0x87, 0xF2, 0xF0, 0x42, 0x90, 0xE0, 0x42, 0x15, 0x20, 0xD2, 0x05, 0x20, + 0x4F, 0x16, 0x20, 0x18, 0xCB, 0x4F, 0x06, 0x04, 0xC5, 0xCB, 0x11, 0x17, 0xC1, 0xCB, 0x11, 0x17, + 0x05, 0x20, 0xF5, 0x22, 0x23, 0x22, 0x23, 0xC9, 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, + 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, + 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, + 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E, 0x3c, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x4C, + 0x21, 0x04, 0x01, 0x11, 0xA8, 0x00, 0x1A, 0x13, 0xBE, 0x20, 0xFE, 0x23, 0x7D, 0xFE, 0x34, 0x20, + 0xF5, 0x06, 0x19, 0x78, 0x86, 0x23, 0x05, 0x20, 0xFB, 0x86, 0x20, 0xFE, 0x3E, 0x01, 0xE0, 0x50 + }; + } +} diff --git a/BizHawk.Emulation/Consoles/Gameboy/Debugger.Designer.cs b/BizHawk.Emulation/Consoles/Gameboy/Debugger.Designer.cs new file mode 100644 index 0000000000..ff35bfdd13 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Debugger.Designer.cs @@ -0,0 +1,758 @@ +using BizHawk.Core; + +namespace VgMuseum.Gameboy +{ + partial class Debugger + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.btnRun = new System.Windows.Forms.Button(); + this.btnStepInto = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.txtRegAF = new System.Windows.Forms.TextBox(); + this.txtRegDE = new System.Windows.Forms.TextBox(); + this.txtRegPC = new System.Windows.Forms.TextBox(); + this.txtRegSP = new System.Windows.Forms.TextBox(); + this.txtRegHL = new System.Windows.Forms.TextBox(); + this.txtRegBC = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.checkFlag_Z = new System.Windows.Forms.CheckBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.checkFlag_H = new System.Windows.Forms.CheckBox(); + this.checkFlag_N = new System.Windows.Forms.CheckBox(); + this.checkFlag_C = new System.Windows.Forms.CheckBox(); + this.label12 = new System.Windows.Forms.Label(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.vScrollBar1 = new System.Windows.Forms.VScrollBar(); + this.btnSeekPC = new System.Windows.Forms.Button(); + this.btnSeekUser = new System.Windows.Forms.Button(); + this.txtSeekUser = new System.Windows.Forms.TextBox(); + this.listBreakpoints = new System.Windows.Forms.ListBox(); + this.menuContextBreakpoints = new System.Windows.Forms.ContextMenuStrip(this.components); + this.miBreakpointAdd = new System.Windows.Forms.ToolStripMenuItem(); + this.miBreakpointDelete = new System.Windows.Forms.ToolStripMenuItem(); + this.label10 = new System.Windows.Forms.Label(); + this.timerRunUpdate = new System.Windows.Forms.Timer(this.components); + this.btnBreak = new System.Windows.Forms.Button(); + this.txtFrame = new System.Windows.Forms.TextBox(); + this.label13 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.txtLine = new System.Windows.Forms.TextBox(); + this.txtDot = new System.Windows.Forms.TextBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.checkViewBg = new System.Windows.Forms.CheckBox(); + this.checkViewObj = new System.Windows.Forms.CheckBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.checkViewObjNoLimit = new System.Windows.Forms.CheckBox(); + this.lblInputActive = new System.Windows.Forms.Label(); + this.viewTiles0x9000 = new ViewportPanel(); + this.viewTiles0x8000 = new ViewportPanel(); + this.panelMemory = new ScrollableViewportPanel(); + this.viewDisassembly = new ViewportPanel(); + this.viewBG = new ViewportPanel(); + this.groupBox1.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.menuContextBreakpoints.SuspendLayout(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // btnRun + // + this.btnRun.Location = new System.Drawing.Point(377, 2); + this.btnRun.Name = "btnRun"; + this.btnRun.Size = new System.Drawing.Size(75, 23); + this.btnRun.TabIndex = 1; + this.btnRun.Text = "Run"; + this.btnRun.UseVisualStyleBackColor = true; + this.btnRun.Click += new System.EventHandler(this.btnRun_Click); + // + // btnStepInto + // + this.btnStepInto.Location = new System.Drawing.Point(458, 2); + this.btnStepInto.Name = "btnStepInto"; + this.btnStepInto.Size = new System.Drawing.Size(75, 23); + this.btnStepInto.TabIndex = 2; + this.btnStepInto.Text = "Step Into"; + this.btnStepInto.UseVisualStyleBackColor = true; + this.btnStepInto.Click += new System.EventHandler(this.btnStepInto_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(369, 63); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(23, 13); + this.label1.TabIndex = 3; + this.label1.Text = "AF:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(428, 63); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(24, 13); + this.label2.TabIndex = 4; + this.label2.Text = "BC:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(367, 83); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(25, 13); + this.label3.TabIndex = 5; + this.label3.Text = "DE:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(428, 83); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(24, 13); + this.label4.TabIndex = 6; + this.label4.Text = "HL:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(428, 104); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(24, 13); + this.label5.TabIndex = 7; + this.label5.Text = "PC:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(367, 104); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(24, 13); + this.label6.TabIndex = 8; + this.label6.Text = "SP:"; + // + // txtRegAF + // + this.txtRegAF.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRegAF.Location = new System.Drawing.Point(392, 60); + this.txtRegAF.MaxLength = 4; + this.txtRegAF.Name = "txtRegAF"; + this.txtRegAF.Size = new System.Drawing.Size(34, 20); + this.txtRegAF.TabIndex = 10; + this.txtRegAF.Text = "FFF0"; + this.txtRegAF.Validating += new System.ComponentModel.CancelEventHandler(this.reg16_Validating); + // + // txtRegDE + // + this.txtRegDE.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRegDE.Location = new System.Drawing.Point(392, 80); + this.txtRegDE.MaxLength = 4; + this.txtRegDE.Name = "txtRegDE"; + this.txtRegDE.Size = new System.Drawing.Size(34, 20); + this.txtRegDE.TabIndex = 11; + this.txtRegDE.Text = "FFF0"; + this.txtRegDE.Validating += new System.ComponentModel.CancelEventHandler(this.reg16_Validating); + // + // txtRegPC + // + this.txtRegPC.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRegPC.Location = new System.Drawing.Point(452, 100); + this.txtRegPC.MaxLength = 4; + this.txtRegPC.Name = "txtRegPC"; + this.txtRegPC.Size = new System.Drawing.Size(34, 20); + this.txtRegPC.TabIndex = 12; + this.txtRegPC.Text = "FFF0"; + this.txtRegPC.Validating += new System.ComponentModel.CancelEventHandler(this.reg16_Validating); + // + // txtRegSP + // + this.txtRegSP.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRegSP.Location = new System.Drawing.Point(392, 100); + this.txtRegSP.MaxLength = 4; + this.txtRegSP.Name = "txtRegSP"; + this.txtRegSP.Size = new System.Drawing.Size(34, 20); + this.txtRegSP.TabIndex = 15; + this.txtRegSP.Text = "FFF0"; + this.txtRegSP.Validating += new System.ComponentModel.CancelEventHandler(this.reg16_Validating); + // + // txtRegHL + // + this.txtRegHL.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRegHL.Location = new System.Drawing.Point(452, 80); + this.txtRegHL.MaxLength = 4; + this.txtRegHL.Name = "txtRegHL"; + this.txtRegHL.Size = new System.Drawing.Size(34, 20); + this.txtRegHL.TabIndex = 14; + this.txtRegHL.Text = "FFF0"; + this.txtRegHL.Validating += new System.ComponentModel.CancelEventHandler(this.reg16_Validating); + // + // txtRegBC + // + this.txtRegBC.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtRegBC.Location = new System.Drawing.Point(452, 60); + this.txtRegBC.MaxLength = 4; + this.txtRegBC.Name = "txtRegBC"; + this.txtRegBC.Size = new System.Drawing.Size(34, 20); + this.txtRegBC.TabIndex = 13; + this.txtRegBC.Text = "FFF0"; + this.txtRegBC.Validating += new System.ComponentModel.CancelEventHandler(this.reg16_Validating); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.tableLayoutPanel1); + this.groupBox1.Location = new System.Drawing.Point(370, 149); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(96, 59); + this.groupBox1.TabIndex = 16; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "CPU Flags"; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.AutoSize = true; + this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel1.ColumnCount = 4; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Controls.Add(this.checkFlag_Z, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.label8, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.label11, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.label9, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.checkFlag_H, 2, 1); + this.tableLayoutPanel1.Controls.Add(this.checkFlag_N, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.checkFlag_C, 3, 1); + this.tableLayoutPanel1.Controls.Add(this.label12, 3, 0); + this.tableLayoutPanel1.Location = new System.Drawing.Point(6, 19); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(80, 33); + this.tableLayoutPanel1.TabIndex = 17; + // + // checkFlag_Z + // + this.checkFlag_Z.AutoSize = true; + this.checkFlag_Z.Location = new System.Drawing.Point(3, 16); + this.checkFlag_Z.Name = "checkFlag_Z"; + this.checkFlag_Z.Size = new System.Drawing.Size(14, 14); + this.checkFlag_Z.TabIndex = 8; + this.checkFlag_Z.UseVisualStyleBackColor = true; + this.checkFlag_Z.CheckedChanged += new System.EventHandler(this.cpuflag_checkChanged); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(3, 0); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(14, 13); + this.label8.TabIndex = 2; + this.label8.Text = "Z"; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(23, 0); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(14, 13); + this.label11.TabIndex = 5; + this.label11.Text = "N"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(43, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(14, 13); + this.label9.TabIndex = 3; + this.label9.Text = "H"; + // + // checkFlag_H + // + this.checkFlag_H.AutoSize = true; + this.checkFlag_H.Location = new System.Drawing.Point(43, 16); + this.checkFlag_H.Name = "checkFlag_H"; + this.checkFlag_H.Size = new System.Drawing.Size(14, 14); + this.checkFlag_H.TabIndex = 0; + this.checkFlag_H.UseVisualStyleBackColor = true; + this.checkFlag_H.CheckedChanged += new System.EventHandler(this.cpuflag_checkChanged); + // + // checkFlag_N + // + this.checkFlag_N.AutoSize = true; + this.checkFlag_N.Location = new System.Drawing.Point(23, 16); + this.checkFlag_N.Name = "checkFlag_N"; + this.checkFlag_N.Size = new System.Drawing.Size(14, 14); + this.checkFlag_N.TabIndex = 10; + this.checkFlag_N.UseVisualStyleBackColor = true; + this.checkFlag_N.CheckedChanged += new System.EventHandler(this.cpuflag_checkChanged); + // + // checkFlag_C + // + this.checkFlag_C.AutoSize = true; + this.checkFlag_C.Location = new System.Drawing.Point(63, 16); + this.checkFlag_C.Name = "checkFlag_C"; + this.checkFlag_C.Size = new System.Drawing.Size(14, 14); + this.checkFlag_C.TabIndex = 11; + this.checkFlag_C.UseVisualStyleBackColor = true; + this.checkFlag_C.CheckedChanged += new System.EventHandler(this.cpuflag_checkChanged); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(63, 0); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(14, 13); + this.label12.TabIndex = 6; + this.label12.Text = "C"; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 2; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.Controls.Add(this.vScrollBar1, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.viewDisassembly, 0, 0); + this.tableLayoutPanel2.Location = new System.Drawing.Point(2, 2); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 1; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(350, 205); + this.tableLayoutPanel2.TabIndex = 19; + // + // vScrollBar1 + // + this.vScrollBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.vScrollBar1.Location = new System.Drawing.Point(334, 0); + this.vScrollBar1.Maximum = 65535; + this.vScrollBar1.Name = "vScrollBar1"; + this.vScrollBar1.Size = new System.Drawing.Size(16, 205); + this.vScrollBar1.TabIndex = 20; + this.vScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.vScrollBar1_Scroll); + // + // btnSeekPC + // + this.btnSeekPC.Location = new System.Drawing.Point(489, 100); + this.btnSeekPC.Name = "btnSeekPC"; + this.btnSeekPC.Size = new System.Drawing.Size(52, 20); + this.btnSeekPC.TabIndex = 20; + this.btnSeekPC.Text = "Seek"; + this.btnSeekPC.UseVisualStyleBackColor = true; + this.btnSeekPC.Click += new System.EventHandler(this.btnSeekPC_Click); + // + // btnSeekUser + // + this.btnSeekUser.Location = new System.Drawing.Point(489, 124); + this.btnSeekUser.Name = "btnSeekUser"; + this.btnSeekUser.Size = new System.Drawing.Size(52, 20); + this.btnSeekUser.TabIndex = 21; + this.btnSeekUser.Text = "Seek"; + this.btnSeekUser.UseVisualStyleBackColor = true; + this.btnSeekUser.Click += new System.EventHandler(this.btnSeekUser_Click); + // + // txtSeekUser + // + this.txtSeekUser.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtSeekUser.Location = new System.Drawing.Point(452, 123); + this.txtSeekUser.MaxLength = 4; + this.txtSeekUser.Name = "txtSeekUser"; + this.txtSeekUser.Size = new System.Drawing.Size(34, 20); + this.txtSeekUser.TabIndex = 22; + // + // listBreakpoints + // + this.listBreakpoints.ContextMenuStrip = this.menuContextBreakpoints; + this.listBreakpoints.FormattingEnabled = true; + this.listBreakpoints.Location = new System.Drawing.Point(915, 245); + this.listBreakpoints.Name = "listBreakpoints"; + this.listBreakpoints.Size = new System.Drawing.Size(120, 95); + this.listBreakpoints.TabIndex = 25; + // + // menuContextBreakpoints + // + this.menuContextBreakpoints.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.miBreakpointAdd, + this.miBreakpointDelete}); + this.menuContextBreakpoints.Name = "menuContextBreakpoints"; + this.menuContextBreakpoints.Size = new System.Drawing.Size(117, 48); + this.menuContextBreakpoints.Opening += new System.ComponentModel.CancelEventHandler(this.menuContextBreakpoints_Opening); + // + // miBreakpointAdd + // + this.miBreakpointAdd.Name = "miBreakpointAdd"; + this.miBreakpointAdd.Size = new System.Drawing.Size(116, 22); + this.miBreakpointAdd.Text = "Add"; + // + // miBreakpointDelete + // + this.miBreakpointDelete.Name = "miBreakpointDelete"; + this.miBreakpointDelete.Size = new System.Drawing.Size(116, 22); + this.miBreakpointDelete.Text = "Delete"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(912, 227); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(63, 13); + this.label10.TabIndex = 26; + this.label10.Text = "Breakpoints"; + // + // timerRunUpdate + // + this.timerRunUpdate.Enabled = true; + this.timerRunUpdate.Tick += new System.EventHandler(this.timerRunUpdate_Tick); + // + // btnBreak + // + this.btnBreak.Location = new System.Drawing.Point(377, 27); + this.btnBreak.Name = "btnBreak"; + this.btnBreak.Size = new System.Drawing.Size(75, 23); + this.btnBreak.TabIndex = 29; + this.btnBreak.Text = "Break"; + this.btnBreak.UseVisualStyleBackColor = true; + this.btnBreak.Click += new System.EventHandler(this.btnBreak_Click); + // + // txtFrame + // + this.txtFrame.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtFrame.Location = new System.Drawing.Point(775, 21); + this.txtFrame.MaxLength = 4; + this.txtFrame.Name = "txtFrame"; + this.txtFrame.ReadOnly = true; + this.txtFrame.Size = new System.Drawing.Size(48, 20); + this.txtFrame.TabIndex = 31; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(730, 24); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(39, 13); + this.label13.TabIndex = 32; + this.label13.Text = "Frame:"; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(739, 44); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(30, 13); + this.label14.TabIndex = 33; + this.label14.Text = "Line:"; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(742, 66); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(27, 13); + this.label15.TabIndex = 34; + this.label15.Text = "Dot:"; + // + // txtLine + // + this.txtLine.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtLine.Location = new System.Drawing.Point(775, 43); + this.txtLine.MaxLength = 4; + this.txtLine.Name = "txtLine"; + this.txtLine.ReadOnly = true; + this.txtLine.Size = new System.Drawing.Size(48, 20); + this.txtLine.TabIndex = 35; + // + // txtDot + // + this.txtDot.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtDot.Location = new System.Drawing.Point(775, 65); + this.txtDot.MaxLength = 4; + this.txtDot.Name = "txtDot"; + this.txtDot.ReadOnly = true; + this.txtDot.Size = new System.Drawing.Size(48, 20); + this.txtDot.TabIndex = 36; + // + // panel1 + // + this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.panel1.Controls.Add(this.panelMemory); + this.panel1.Location = new System.Drawing.Point(5, 225); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(545, 181); + this.panel1.TabIndex = 38; + // + // checkViewBg + // + this.checkViewBg.AutoSize = true; + this.checkViewBg.Checked = true; + this.checkViewBg.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkViewBg.Location = new System.Drawing.Point(564, 3); + this.checkViewBg.Name = "checkViewBg"; + this.checkViewBg.Size = new System.Drawing.Size(41, 17); + this.checkViewBg.TabIndex = 39; + this.checkViewBg.Text = "BG"; + this.checkViewBg.UseVisualStyleBackColor = true; + this.checkViewBg.CheckedChanged += new System.EventHandler(this.checkViewBg_CheckedChanged); + // + // checkViewObj + // + this.checkViewObj.AutoSize = true; + this.checkViewObj.Checked = true; + this.checkViewObj.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkViewObj.Location = new System.Drawing.Point(611, 3); + this.checkViewObj.Name = "checkViewObj"; + this.checkViewObj.Size = new System.Drawing.Size(46, 17); + this.checkViewObj.TabIndex = 40; + this.checkViewObj.Text = "OBJ"; + this.checkViewObj.UseVisualStyleBackColor = true; + this.checkViewObj.CheckedChanged += new System.EventHandler(this.checkViewObj_CheckedChanged); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(561, 195); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(45, 13); + this.label7.TabIndex = 42; + this.label7.Text = "0x8000:"; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(701, 197); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(45, 13); + this.label16.TabIndex = 44; + this.label16.Text = "0x8800:"; + // + // checkViewObjNoLimit + // + this.checkViewObjNoLimit.AutoSize = true; + this.checkViewObjNoLimit.Checked = true; + this.checkViewObjNoLimit.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkViewObjNoLimit.Location = new System.Drawing.Point(663, 3); + this.checkViewObjNoLimit.Name = "checkViewObjNoLimit"; + this.checkViewObjNoLimit.Size = new System.Drawing.Size(44, 17); + this.checkViewObjNoLimit.TabIndex = 45; + this.checkViewObjNoLimit.Text = ">10"; + this.checkViewObjNoLimit.UseVisualStyleBackColor = true; + this.checkViewObjNoLimit.CheckedChanged += new System.EventHandler(this.checkViewObjNoLimit_CheckedChanged); + // + // lblInputActive + // + this.lblInputActive.AutoSize = true; + this.lblInputActive.Location = new System.Drawing.Point(711, 10); + this.lblInputActive.Name = "lblInputActive"; + this.lblInputActive.Size = new System.Drawing.Size(13, 13); + this.lblInputActive.TabIndex = 46; + this.lblInputActive.Text = "o"; + // + // viewTiles0x9000 + // + this.viewTiles0x9000.Location = new System.Drawing.Point(704, 215); + this.viewTiles0x9000.Name = "viewTiles0x9000"; + this.viewTiles0x9000.Size = new System.Drawing.Size(128, 128); + this.viewTiles0x9000.TabIndex = 43; + this.viewTiles0x9000.Paint += new System.Windows.Forms.PaintEventHandler(this.viewTiles0x9000_Paint); + // + // viewTiles0x8000 + // + this.viewTiles0x8000.Location = new System.Drawing.Point(561, 215); + this.viewTiles0x8000.Name = "viewTiles0x8000"; + this.viewTiles0x8000.Size = new System.Drawing.Size(128, 128); + this.viewTiles0x8000.TabIndex = 41; + this.viewTiles0x8000.Paint += new System.Windows.Forms.PaintEventHandler(this.viewTiles0x8000_Paint); + // + // panelMemory + // + this.panelMemory.AutoSize = true; + this.panelMemory.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelMemory.Location = new System.Drawing.Point(0, 0); + this.panelMemory.Name = "panelMemory"; + this.panelMemory.ScrollLargeChange = 10; + this.panelMemory.ScrollMax = 4095; + this.panelMemory.Size = new System.Drawing.Size(541, 177); + this.panelMemory.TabIndex = 37; + this.panelMemory.Paint += new System.Windows.Forms.PaintEventHandler(this.panelMemory_Paint); + this.panelMemory.Scroll += new System.Windows.Forms.ScrollEventHandler(this.panelMemory_Scroll); + // + // viewDisassembly + // + this.viewDisassembly.Dock = System.Windows.Forms.DockStyle.Fill; + this.viewDisassembly.Location = new System.Drawing.Point(3, 3); + this.viewDisassembly.Name = "viewDisassembly"; + this.viewDisassembly.Size = new System.Drawing.Size(328, 199); + this.viewDisassembly.TabIndex = 0; + this.viewDisassembly.Paint += new System.Windows.Forms.PaintEventHandler(this.viewDisassembly_Paint); + // + // viewBG + // + this.viewBG.Location = new System.Drawing.Point(564, 27); + this.viewBG.Name = "viewBG"; + this.viewBG.Size = new System.Drawing.Size(160, 144); + this.viewBG.TabIndex = 23; + this.viewBG.Paint += new System.Windows.Forms.PaintEventHandler(this.viewBG_Paint); + this.viewBG.Leave += new System.EventHandler(this.viewBG_Leave); + this.viewBG.KeyUp += new System.Windows.Forms.KeyEventHandler(this.viewBG_KeyUp); + this.viewBG.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.viewBG_KeyPress); + this.viewBG.Enter += new System.EventHandler(this.viewBG_Enter); + this.viewBG.KeyDown += new System.Windows.Forms.KeyEventHandler(this.viewBG_KeyDown); + // + // Debugger + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1065, 483); + this.Controls.Add(this.lblInputActive); + this.Controls.Add(this.checkViewObjNoLimit); + this.Controls.Add(this.viewTiles0x9000); + this.Controls.Add(this.label16); + this.Controls.Add(this.label7); + this.Controls.Add(this.viewTiles0x8000); + this.Controls.Add(this.checkViewObj); + this.Controls.Add(this.panel1); + this.Controls.Add(this.checkViewBg); + this.Controls.Add(this.label13); + this.Controls.Add(this.txtDot); + this.Controls.Add(this.txtLine); + this.Controls.Add(this.label15); + this.Controls.Add(this.label14); + this.Controls.Add(this.btnBreak); + this.Controls.Add(this.txtFrame); + this.Controls.Add(this.label10); + this.Controls.Add(this.tableLayoutPanel2); + this.Controls.Add(this.listBreakpoints); + this.Controls.Add(this.txtSeekUser); + this.Controls.Add(this.viewBG); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.btnSeekUser); + this.Controls.Add(this.btnSeekPC); + this.Controls.Add(this.btnStepInto); + this.Controls.Add(this.txtRegAF); + this.Controls.Add(this.txtRegSP); + this.Controls.Add(this.txtRegHL); + this.Controls.Add(this.txtRegBC); + this.Controls.Add(this.txtRegPC); + this.Controls.Add(this.txtRegDE); + this.Controls.Add(this.label2); + this.Controls.Add(this.label6); + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.btnRun); + this.Controls.Add(this.label1); + this.KeyPreview = true; + this.Name = "Debugger"; + this.Text = "Debugger"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.tableLayoutPanel2.ResumeLayout(false); + this.menuContextBreakpoints.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private ViewportPanel viewDisassembly; + private System.Windows.Forms.Button btnRun; + private System.Windows.Forms.Button btnStepInto; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox txtRegAF; + private System.Windows.Forms.TextBox txtRegDE; + private System.Windows.Forms.TextBox txtRegPC; + private System.Windows.Forms.TextBox txtRegSP; + private System.Windows.Forms.TextBox txtRegHL; + private System.Windows.Forms.TextBox txtRegBC; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.CheckBox checkFlag_H; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.CheckBox checkFlag_Z; + private System.Windows.Forms.CheckBox checkFlag_N; + private System.Windows.Forms.CheckBox checkFlag_C; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.VScrollBar vScrollBar1; + private System.Windows.Forms.Button btnSeekPC; + private System.Windows.Forms.Button btnSeekUser; + private System.Windows.Forms.TextBox txtSeekUser; + private ViewportPanel viewBG; + private System.Windows.Forms.ListBox listBreakpoints; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.ContextMenuStrip menuContextBreakpoints; + private System.Windows.Forms.ToolStripMenuItem miBreakpointAdd; + private System.Windows.Forms.ToolStripMenuItem miBreakpointDelete; + private System.Windows.Forms.Timer timerRunUpdate; + private System.Windows.Forms.Button btnBreak; + private System.Windows.Forms.TextBox txtFrame; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox txtLine; + private System.Windows.Forms.TextBox txtDot; + private ScrollableViewportPanel panelMemory; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.CheckBox checkViewBg; + private System.Windows.Forms.CheckBox checkViewObj; + private ViewportPanel viewTiles0x8000; + private System.Windows.Forms.Label label7; + private ViewportPanel viewTiles0x9000; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.CheckBox checkViewObjNoLimit; + private System.Windows.Forms.Label lblInputActive; + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Gameboy/Debugger.cs b/BizHawk.Emulation/Consoles/Gameboy/Debugger.cs new file mode 100644 index 0000000000..3a42d1b37c --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Debugger.cs @@ -0,0 +1,382 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; +using BizHawk.Core; + +namespace VgMuseum.Gameboy +{ + public partial class Debugger : Form + { + readonly Gameboy gb; + public Debugger(Gameboy gb) + { + this.gb = gb; + InitializeComponent(); + Refresh(); + } + + private void viewDisassembly_Paint(object sender, PaintEventArgs e) + { + e.Graphics.Clear(SystemColors.Control); + StringBuilder sb = new StringBuilder(); + ushort addr = (ushort)vScrollBar1.Value; + for (int i = 0; i < 16; i++) + { + ushort size; + string str = VgMuseum.Z80GB.Disassembler.DAsm(addr, gb.Cpu.ReadMemory, out size); + addr += size; + sb.AppendLine(str); + } + using (Font font = new Font("Courier New", 8)) + { + e.Graphics.DrawString(sb.ToString(), font, Brushes.Black, 0, 0); + } + } + + public override void Refresh() + { + txtRegAF.Text = string.Format("{0:X4}", gb.Cpu.RegisterAF); + txtRegDE.Text = string.Format("{0:X4}", gb.Cpu.RegisterDE); + txtRegPC.Text = string.Format("{0:X4}", gb.Cpu.RegisterPC); + txtRegBC.Text = string.Format("{0:X4}", gb.Cpu.RegisterBC); + txtRegHL.Text = string.Format("{0:X4}", gb.Cpu.RegisterHL); + txtRegSP.Text = string.Format("{0:X4}", gb.Cpu.RegisterSP); + checkFlag_Z.Checked = gb.Cpu.FlagZ; + checkFlag_N.Checked = gb.Cpu.FlagN; + checkFlag_H.Checked = gb.Cpu.FlagH; + checkFlag_C.Checked = gb.Cpu.FlagC; + txtFrame.Text = gb.Registers.Timing.frame.ToString(); + txtLine.Text = gb.Registers.Timing.line.ToString(); + txtDot.Text = gb.Registers.Timing.dot.ToString(); + base.Refresh(); + } + + void DoStepInto() + { + DoBreak(); + gb.SingleStepInto(); + vScrollBar1.Value = gb.Cpu.RegisterPC; + Refresh(); + } + + bool Running = false; + void DoRun() + { + Running = true; + gb.RunForever(); + Running = false; + } + + void DoBreak() + { + gb.DebugBreak = true; + } + + private void btnStepInto_Click(object sender, EventArgs e) + { + DoStepInto(); + } + + bool TryParse16(string str, out ushort val) + { + return ushort.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val); + } + + private void reg16_Validating(object sender, CancelEventArgs e) + { + var tb = (TextBox)sender; + ushort val = 0; + TryParse16(tb.Text, out val); + if (sender == txtRegAF) gb.Cpu.RegisterAF = val; + if (sender == txtRegDE) gb.Cpu.RegisterDE = val; + if (sender == txtRegPC) gb.Cpu.RegisterPC = val; + if (sender == txtRegBC) gb.Cpu.RegisterBC = val; + if (sender == txtRegHL) gb.Cpu.RegisterHL = val; + if (sender == txtRegSP) gb.Cpu.RegisterSP = val; + Refresh(); + } + + private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) + { + Refresh(); + } + + private void btnSeekPC_Click(object sender, EventArgs e) + { + vScrollBar1.Value = gb.Cpu.RegisterPC; + Refresh(); + } + + private void btnSeekUser_Click(object sender, EventArgs e) + { + ushort val; + if (TryParse16(txtSeekUser.Text, out val)) + { + vScrollBar1.Value = val; + Refresh(); + } + } + + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + switch (keyData) + { + case Keys.F11: + DoStepInto(); + break; + case Keys.F5: + DoRun(); + break; + case Keys.Escape: + DoBreak(); + break; + default: + return false; + } + return true; + } + + private void menuContextBreakpoints_Opening(object sender, CancelEventArgs e) + { + miBreakpointDelete.Enabled = false; + } + + private void viewTiles0x8000_Paint(object sender, PaintEventArgs e) + { + using (Bitmap bmp = new Bitmap(160, 144, e.Graphics)) + { + var linebuf = new byte[128]; + for (int y = 0; y < 144; y++) + { + gb.RenderTileLine(y, linebuf, 0x8000); + for (int x = 0; x < 128; x++) + { + int gray = linebuf[x] << 6; + bmp.SetPixel(x, y, Color.FromArgb(gray, gray, gray)); + } + } + e.Graphics.DrawImageUnscaled(bmp, 0, 0); + } + } + + private void viewTiles0x9000_Paint(object sender, PaintEventArgs e) + { + using (Bitmap bmp = new Bitmap(160, 144, e.Graphics)) + { + var linebuf = new byte[128]; + for (int y = 0; y < 144; y++) + { + gb.RenderTileLine(y, linebuf, 0x8800); + for (int x = 0; x < 128; x++) + { + int gray = linebuf[x] << 6; + bmp.SetPixel(x, y, Color.FromArgb(gray, gray, gray)); + } + } + e.Graphics.DrawImageUnscaled(bmp, 0, 0); + } + } + + + private void viewBG_Paint(object sender, PaintEventArgs e) + { + using (Bitmap bmp = new Bitmap(160, 144, e.Graphics)) + { + var linebuf = new byte[160]; + for (int y = 0; y < 144; y++) + { + if(checkViewBg.Checked) gb.RenderBGLine(y, linebuf, false); + if (checkViewObj.Checked) gb.RenderOBJLine(y, linebuf, !checkViewObjNoLimit.Checked); + for (int x = 0; x < 160; x++) + { + int gray = linebuf[x]<<6; + bmp.SetPixel(x, y, Color.FromArgb(gray, gray, gray)); + } + } + e.Graphics.DrawImageUnscaled(bmp, 0, 0); + } + } + + private void timerRunUpdate_Tick(object sender, EventArgs e) + { + if(Running) + Refresh(); + } + + private void btnRun_Click(object sender, EventArgs e) + { + DoRun(); + } + + private void btnBreak_Click(object sender, EventArgs e) + { + DoBreak(); + } + + private void checkFlag_Z_CheckedChanged(object sender, EventArgs e) + { + + } + + private void cpuflag_checkChanged(object sender, EventArgs e) + { + var cb = (CheckBox)sender; + if (sender == checkFlag_Z) gb.Cpu.FlagZ = cb.Checked; + if (sender == checkFlag_N) gb.Cpu.FlagN = cb.Checked; + if (sender == checkFlag_H) gb.Cpu.FlagH = cb.Checked; + if (sender == checkFlag_C) gb.Cpu.FlagC = cb.Checked; + Refresh(); + } + + static char Remap(byte val) + { + if (val < ' ') return '.'; + else if (val >= 0x80) return '.'; + else return (char)val; + } + + private void panelMemory_Paint(object sender, PaintEventArgs e) + { + e.Graphics.Clear(SystemColors.Control); + StringBuilder sb = new StringBuilder(); + ushort addr = (ushort)(panelMemory.Scrollbar.Value * 16); + for (int i = 0; i < 16; i++) + { + sb.AppendFormat("{0}:{1:X4} ", gb.DescribeParagraph(addr),addr); + for (int x = 0; x < 16; x++) + sb.AppendFormat("{0:X2} ", gb.ReadMemory((ushort)(addr+x))); + sb.AppendFormat("| "); + for (int x = 0; x < 16; x++) + sb.Append(Remap(gb.ReadMemory((ushort)(addr + x)))); + sb.AppendLine(); + addr += 16; + } + using (Font font = new Font("Courier New", 8)) + { + e.Graphics.DrawString(sb.ToString(), font, Brushes.Black, 0, 0); + } + } + + private void panelMemory_Scroll(object sender, ScrollEventArgs e) + { + Refresh(); + } + + private void checkViewBg_CheckedChanged(object sender, EventArgs e) + { + Refresh(); + } + + private void checkViewObj_CheckedChanged(object sender, EventArgs e) + { + Refresh(); + } + + private void checkViewObjNoLimit_CheckedChanged(object sender, EventArgs e) + { + Refresh(); + } + + private void viewBG_KeyUp(object sender, KeyEventArgs e) + { + UpdateKeys(); + } + + private void viewBG_KeyPress(object sender, KeyPressEventArgs e) + { + UpdateKeys(); + } + + private void viewBG_KeyDown(object sender, KeyEventArgs e) + { + UpdateKeys(); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + if (viewBG.Focused) return true; + else return base.ProcessDialogKey(keyData); + } + + void UpdateKeys() + { + gb.Registers.Input.up = Keyboard.IsKeyDown(Keys.Up); + gb.Registers.Input.down = Keyboard.IsKeyDown(Keys.Down); + gb.Registers.Input.left = Keyboard.IsKeyDown(Keys.Left); + gb.Registers.Input.right = Keyboard.IsKeyDown(Keys.Right); + gb.Registers.Input.a = Keyboard.IsKeyDown(Keys.X); + gb.Registers.Input.b = Keyboard.IsKeyDown(Keys.Z); + gb.Registers.Input.select = Keyboard.IsKeyDown(Keys.E); + gb.Registers.Input.right = Keyboard.IsKeyDown(Keys.R); + } + + private void viewBG_Enter(object sender, EventArgs e) + { + lblInputActive.ForeColor = Color.Red; + UpdateKeys(); + } + + private void viewBG_Leave(object sender, EventArgs e) + { + lblInputActive.ForeColor = SystemColors.ControlText; + gb.Registers.Input.up = false; + gb.Registers.Input.down = false; + gb.Registers.Input.left = false; + gb.Registers.Input.right = false; + gb.Registers.Input.a = false; + gb.Registers.Input.b = false; + gb.Registers.Input.select = false; + gb.Registers.Input.right = false; + } + + static class Keyboard + { + [Flags] + private enum KeyStates + { + None = 0, + Down = 1, + Toggled = 2 + } + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + private static extern short GetKeyState(int keyCode); + + private static KeyStates GetKeyState(Keys key) + { + KeyStates state = KeyStates.None; + + short retVal = GetKeyState((int)key); + + //If the high-order bit is 1, the key is down + //otherwise, it is up. + if ((retVal & 0x8000) == 0x8000) + state |= KeyStates.Down; + + //If the low-order bit is 1, the key is toggled. + if ((retVal & 1) == 1) + state |= KeyStates.Toggled; + + return state; + } + + public static bool IsKeyDown(Keys key) + { + return KeyStates.Down == (GetKeyState(key) & KeyStates.Down); + } + + public static bool IsKeyToggled(Keys key) + { + return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled); + } + } + + } +} diff --git a/BizHawk.Emulation/Consoles/Gameboy/Debugger.resx b/BizHawk.Emulation/Consoles/Gameboy/Debugger.resx new file mode 100644 index 0000000000..5e66c132f0 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Debugger.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 193, 17 + + \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs b/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs new file mode 100644 index 0000000000..4c3df08a8c --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Gameboy.cs @@ -0,0 +1,838 @@ +using System; +using System.Collections.Generic; +using BizHawk.Emulation.CPUs.Z80GB; + +namespace BizHawk.Emulation.Consoles.Gameboy +{ + public partial class Gameboy : IEmulator + { + public enum ECartType + { + ROM_ONLY = 0x00, + ROM_MBC1 = 0x01, + ROM_MBC1_RAM = 0x02, + ROM_MBC1_RAM_BATT = 0x03, + ROM_MBC2 = 0x05, + ROM_MBC2_BATTERY = 0x06, + ROM_RAM = 0x08, + ROM_RAM_BATTERY = 0x09, + ROM_MMM01 = 0x0B, + ROM_MMM01_SRAM = 0x0C, + ROM_MMM01_SRAM_BATT = 0x0D, + ROM_MBC3_TIMER_BATT = 0x0F, + ROM_MBC3_TIMER_RAM_BATT = 0x10, + ROM_MBC3 = 0x11, + ROM_MBC3_RAM = 0x12, + ROM_MBC3_RAM_BATT = 0x13, + ROM_MBC5 = 0x19, + ROM_MBC5_RAM = 0x1A, + ROM_MBC5_RAM_BATT = 0x1B, + ROM_MBC5_RUMBLE = 0x1C, + ROM_MBC5_RUMBLE_SRAM = 0x1D, + ROM_MBC5_RUMBLE_SRAM_BATT = 0x1E, + PocketCamera = 0x1F, + Bandai_TAMA5 = 0xFD, + Hudson_HuC_3 = 0xFE, + Hudson_HuC_1 = 0xFF, + } + + public enum ESystemType + { + GB, //original gameboy + GBP, //gameboy pocket + GBC, //gameboy color + SGB, //super gameboy + GBA, //gameboy advance (emulating old hardware) + } + + public ECartType CartType; + public ESystemType SystemType; + + public struct TCartFlags + { + public bool GBC; //cart indicates itself as GBC aware + public bool SGB; //cart indicates itself as SGB aware + } + public TCartFlags CartFlags = new TCartFlags(); + + static byte SetBit8(byte variable, int bit, bool val) + { + int mask = 1 << bit; + int temp = variable; + temp &= ~mask; + if (val) temp |= mask; + return (byte)temp; + } + + static byte SetBit8(byte variable, int bit, int val) + { + return SetBit8(variable, bit, val != 0); + } + + static bool GetBit8(byte variable, int bit) + { + return (variable & (1 << bit)) != 0; + } + + public class TRegisters + { + Gameboy gb; + public TRegisters(Gameboy gb) + { + this.gb = gb; + STAT = new TSTAT(gb); + } + + public bool BiosMapped = true; + public class TLCDC + { + byte val; + public bool Enabled { get { return GetBit8(val, 7); } set { val = SetBit8(val, 7, value); } } + public ETileMap WindowTileMap { get { return GetBit8(val, 6) ? ETileMap.Region_9C00_9FFF : ETileMap.Region_9800_9BFF; } set { val = SetBit8(val, 6, (int)value); } } + public ushort WindowTileMapAddr { get { return GetTileMapAddrFor(WindowTileMap); } } + public bool WindowDisplay { get { return GetBit8(val, 5); } set { val = SetBit8(val, 5, value); } } + public ETileData TileData { get { return GetBit8(val, 4) ? ETileData.Region_8000_8FFF : ETileData.Region_8800_97FF; } set { val = SetBit8(val, 4, (int)value); } } + public ushort TileDataAddr { get { return GetTileDataAddrFor(TileData); } } + public ETileMap BgTileMap { get { return GetBit8(val, 3) ? ETileMap.Region_9C00_9FFF : ETileMap.Region_9800_9BFF; } set { val = SetBit8(val, 3, (int)value); } } + public ushort BgTileMapAddr { get { return GetTileMapAddrFor(BgTileMap); } } + public EObjSize ObjSize { get { return GetBit8(val, 2) ? EObjSize.ObjSize_8x16 : EObjSize.ObjSize_8x8; } set { val = SetBit8(val, 2, (int)value); } } + public bool ObjEnabled { get { return GetBit8(val, 1); } set { val = SetBit8(val, 1, value); } } + public bool BgEnabled { get { return GetBit8(val, 0); } set { val = SetBit8(val, 0, value); } } + + public byte Read() { return val; } + public void Write(byte value) { val = value; } + public void Poke(byte value) { val = value; } + + public enum ETileMap + { + Region_9800_9BFF = 0, + Region_9C00_9FFF = 1, + } + + public enum ETileData + { + Region_8800_97FF = 0, + Region_8000_8FFF = 1, + } + + public ushort GetTileMapAddrFor(ETileMap tm) { return (ushort)(tm == ETileMap.Region_9800_9BFF ? 0x9800 : 0x9C00); } + public ushort GetTileDataAddrFor(ETileData tm) { return (ushort)(tm == ETileData.Region_8800_97FF ? 0x8800 : 0x8000); } + + + public enum EObjSize + { + ObjSize_8x8 = 0, + ObjSize_8x16 = 1, + } + } + public TLCDC LCDC = new TLCDC(); + public byte SCY, SCX; + + public class TSTAT + { + readonly Gameboy gb; + public TSTAT(Gameboy gb) { this.gb = gb; } + + public byte Read() + { + //TODO (not done yet) + int mode; + if (gb.Registers.Timing.line >= 160) mode = 1; + else if (gb.Registers.Timing.dot < 80) mode = 2; + else if (gb.Registers.Timing.dot < 172 + 80) mode = 3; + else mode = 0; + + return (byte)mode; + } + } + public TSTAT STAT; + + public class TTiming + { + public int frame; + public int line; + public int dot; + } + public TTiming Timing = new TTiming(); + + public class TInput + { + public bool up, down, left, right, a, b, select, start; + int val; + public void Write(byte value) + { + val = value & 0x30; + } + public byte Read() + { + if ((val & 0x10) == 0) + { + int ret = SetBit8(0, 0, right) | SetBit8(0, 1, left) | SetBit8(0, 2, up) | SetBit8(0, 3, down); + return (byte) (~ret); + } + else if((val & 0x10) == 0) + { + int ret = SetBit8(0, 0, a) | SetBit8(0, 1, b) | SetBit8(0, 2, select) | SetBit8(0, 3, start); + return (byte)(~ret); + } + else return 0xFF; + + //TODO return system type??? + } + } + public TInput Input = new TInput(); + + public byte Read_LY() { return (byte)Timing.line; } + + }; + public TRegisters Registers; + + public void SingleStepInto() + { + Cpu.TotalExecutedCycles = 0; + Cpu.SingleStepInto(); + int elapsed = Cpu.TotalExecutedCycles; + Timekeeping(elapsed); + } + + public bool DebugBreak; + public void RunForever() + { + int sanity = 0; + + for (; ; ) + { + SingleStepInto(); + + sanity++; + if (sanity == 100000) + { + //System.Windows.Forms.Application.DoEvents(); + if (DebugBreak) break; + sanity = 0; + } + } + + DebugBreak = false; + } + + public void Timekeeping(int elapsed) + { + Registers.Timing.dot += elapsed; + if (Registers.Timing.dot >= 456) + { + Registers.Timing.line++; + Registers.Timing.dot -= 456; + } + if (Registers.Timing.line > 153) + { + Registers.Timing.frame++; + Registers.Timing.line = 0; + } + } + + public void DetachBios() + { + Registers.BiosMapped = false; + Cpu.ReadMemory = ReadMemory; + } + + public class TSound + { + public byte[] WavePatternRam = new byte[16]; + } + + public TSound Sound; + + public byte[] Rom; + public byte[] WRam; + public byte[] SRam; + public byte[] VRam; + public byte[] HRam; + public byte[] OAM; + + public Z80 Cpu; + public MemoryMapper Mapper; + + public Gameboy() + { + } + + public void LoadGame(IGame game) + { + Rom = game.GetRomData(); + + //inspect mapper and GBC flags + CartType = (ECartType)Rom[0x0147]; + Mapper = new MemoryMapper(this); + CartFlags.GBC = Rom[0x0143] == 0x80; + CartFlags.SGB = Rom[0x0146] == 0x03; + } + + public bool BootFromBios = true; + + public void HardReset() + { + Cpu = new CPUs.Z80GB.Z80(); + Cpu.ReadMemory = ReadMemoryBios; + Cpu.WriteMemory = WriteMemory; + Cpu.Reset(); + + //setup initial cpu registers. based on no evidence: + //registers which may be used to identify system type are judged to be important; and + //the initial contents of the stack are judged to be unimportant. + switch (SystemType) + { + case ESystemType.GB: + case ESystemType.SGB: + Cpu.RegisterAF = 0x01; + break; + case ESystemType.GBP: + Cpu.RegisterAF = 0xFF; + break; + case ESystemType.GBC: + Cpu.RegisterAF = 0x11; + break; + case ESystemType.GBA: + throw new NotImplementedException(); //decide what to do + } + Cpu.RegisterF = 0xB0; + if (SystemType == ESystemType.GBA) + Cpu.RegisterB = 0x01; + else Cpu.RegisterB = 0x00; + Cpu.RegisterC = 0x13; + Cpu.RegisterDE = 0x00D8; + Cpu.RegisterHL = 0x014D; + Cpu.RegisterSP = 0xFFFE; + if (BootFromBios) Cpu.RegisterPC = 0x0000; + else Cpu.RegisterPC = 0x0100; + + WRam = new byte[32 * 1024]; //GB has 4KB of WRam; GBC has 32KB of WRam + SRam = new byte[8 * 1024]; //different carts may have different amounts of this + VRam = new byte[0x2000]; + HRam = new byte[128]; + OAM = new byte[0xA0]; + + Sound = new TSound(); + Registers = new TRegisters(this); + + Registers.LCDC.Poke(0x91); + } + + public byte ReadMemoryBios(ushort addr) + { + //we speculate that the bios unmaps itself after the first read of 0x100 + if (addr < 0x100) + return Bios[addr]; + else if(addr == 0x100) + DetachBios(); + return ReadMemory(addr); + } + + public string DescribeParagraph(ushort addr) + { + //todo - later on, this must say "RO1F" for bank 0x1F and etc. + //and so it must call through to the mapper + if (addr < 0x4000) + return "ROM0"; + else if (addr < 0x8000) + return "ROM1"; + else if (addr < 0xA000) + return "VRA0"; + else if (addr < 0xC000) + return "SRA0"; + else if (addr < 0xD000) + return "WRA0"; + else if (addr < 0xE000) + return "WRA1"; + else if (addr < 0xFE00) + return "ECH0"; + else if (addr < 0xFEA0) + return "OAM "; + else if (addr < 0xFF00) + return "----"; + else if (addr < 0xFF80) + return "I/O "; + else return "HRAM"; + } + + public byte ReadMemory(ushort addr) + { + if (addr < 0x8000) + return Rom[addr]; + else if (addr < 0xA000) + return VRam[addr - 0x8000]; + else if (addr < 0xC000) + return SRam[addr - 0xA000]; + else if (addr < 0xD000) + return WRam[addr - 0xC000]; //bank 0 of WRam + else if (addr < 0xE000) + return WRam[addr - 0xC000]; //bank 1 of WRam (needs to be switchable) + else if (addr < 0xFE00) + return ReadMemory((ushort)(addr - 0xE000)); //echo of WRam; unusable; reserved ???? + else if (addr < 0xFEA0) + return OAM[addr - 0xFE00]; + else if (addr < 0xFF00) + return 0xFF; //"unusable memory" + else if (addr < 0xFF80) + return ReadRegister(addr); + else if (addr < 0xFFFF) + return HRam[addr - 0xFF80]; + else return ReadRegister(addr); + } + + public byte ReadRegister(ushort addr) + { + switch (addr) + { + case 0xFF00: //REG_P1 - Register for reading joy pad info and determining system type. (R/W) + return Registers.Input.Read(); + case 0xFF01: //REG_SB - Serial transfer data (R/W) + return 0xFF; + case 0xFF02: //REG_SC - SIO control (R/W) + return 0xFF; + case 0xFF04: //REG_DIV - Divider Register (R/W) + return 0xFF; + case 0xFF05: //REG_TIMA - Timer counter (R/W) + return 0xFF; + case 0xFF06: //REG_TMA - Timer Modulo (R/W) + return 0xFF; + case 0xFF07: //REG_TAC - Timer Control (R/W) + return 0xFF; + case 0xFF0F: //REG_IF - Interrupt Flag (R/W) + return 0xFF; + case 0xFF10: //REG_NR10 - Sound Mode 1 register, Sweep register (R/W) + return 0xFF; + case 0xFF11: //REG_NR11 - Sound Mode 1 register, Sound length/Wave pattern duty (R/W) + return 0xFF; + case 0xFF12: //REG_NR12 - Sound Mode 1 register, Envelope (R/W) + return 0xFF; + case 0xFF13: //REG_NR13 - Sound Mode 1 register, Frequency lo (W) + return 0xFF; + case 0xFF14: //REG_NR14 - Sound Mode 1 register, Frequency hi (R/W) + return 0xFF; + + //0xFF15 ??????????????? + + case 0xFF16: //REG_NR21 - Sound Mode 2 register, Sound Length; Wave Pattern Duty (R/W) + return 0xFF; + case 0xFF17: //REG_NR22 - Sound Mode 2 register, envelope (R/W) + return 0xFF; + case 0xFF18: //REG_NR23 - Sound Mode 2 register, frequency lo data (W) + return 0xFF; + case 0xFF19: //REG_NR24 - Sound Mode 2 register, frequency hi data (R/W) + return 0xFF; + case 0xFF1A: //REG_NR30 - Sound Mode 3 register, Sound on/off (R/W) + return 0xFF; + case 0xFF1B: //REG_NR31 - Sound Mode 3 register, sound length (R/W) + return 0xFF; + case 0xFF1C: //REG_NR32 - Sound Mode 3 register, Select output level (R/W) + return 0xFF; + case 0xFF1D: //REG_NR33 - Sound Mode 3 register, frequency's lower data (W) + return 0xFF; + case 0xFF1E: //REG_NR34 - Sound Mode 3 register, frequency's higher data (R/W) + return 0xFF; + + //0xFF1F ??????????????? + + case 0xFF20: //REG_NR41 - Sound Mode 4 register, sound length (R/W) + return 0xFF; + case 0xFF21: //REG_NR42 - Sound Mode 4 register, envelope (R/W) + return 0xFF; + case 0xFF22: //REG_NR43 - Sound Mode 4 register, polynomial counter (R/W) + return 0xFF; + case 0xFF23: //REG_NR44 - Sound Mode 4 register, counter/consecutive; inital (R/W) + return 0xFF; + case 0xFF24: //REG_NR50 - Channel control / ON-OFF / Volume (R/W) + return 0xFF; + case 0xFF25: //REG_NR51 - Selection of Sound output terminal (R/W) + return 0xFF; + case 0xFF26: //REG_NR52 - Sound on/off (R/W) (Value at reset: $F1-GB, $F0-SGB) + return 0xFF; + case 0xFF30: return Sound.WavePatternRam[0x00]; case 0xFF31: return Sound.WavePatternRam[0x01]; + case 0xFF32: return Sound.WavePatternRam[0x02]; case 0xFF33: return Sound.WavePatternRam[0x03]; + case 0xFF34: return Sound.WavePatternRam[0x04]; case 0xFF35: return Sound.WavePatternRam[0x05]; + case 0xFF36: return Sound.WavePatternRam[0x06]; case 0xFF37: return Sound.WavePatternRam[0x07]; + case 0xFF38: return Sound.WavePatternRam[0x08]; case 0xFF39: return Sound.WavePatternRam[0x09]; + case 0xFF3A: return Sound.WavePatternRam[0x0A]; case 0xFF3B: return Sound.WavePatternRam[0x0B]; + case 0xFF3C: return Sound.WavePatternRam[0x0C]; case 0xFF3D: return Sound.WavePatternRam[0x0D]; + case 0xFF3E: return Sound.WavePatternRam[0x0E]; case 0xFF3F: return Sound.WavePatternRam[0x0F]; + case 0xFF40: //REG_LCDC - LCD Control (R/W) (value $91 at reset) + return Registers.LCDC.Read(); + case 0xFF41: //REG_STAT - LCDC Status (R/W) + return Registers.STAT.Read(); + case 0xFF42: //REG_SCY - Scroll Y (R/W) + return Registers.SCY; + case 0xFF43: //REG_SCX - Scroll X (R/W) + return Registers.SCX; + case 0xFF44: //REG_LY - LCDC Y-Coordinate (R) + return Registers.Read_LY(); + case 0xFF45: //REG_LYC - LY Compare (R/W) + return 0xFF; + case 0xFF46: //REG_DMA - DMA Transfer and Start Address (W) + return 0xFF; + case 0xFF47: //REG_BGP - BG & Window Palette Data (R/W) + return 0xFF; + case 0xFF48: //REG_OBP0 - Object Palette 0 Data (R/W) + return 0xFF; + case 0xFF49: //REG_OBP1 - Object Palette 1 Data (R/W) + return 0xFF; + case 0xFF4A: //REG_WY - Window Y Position (R/W) + return 0xFF; + case 0xFF4B: //REG_WX - Window X Position (R/W) + return 0xFF; + case 0xFFFF: //REG_IE + return 0xFF; + default: + return 0xFF; + } + } + + public void WriteRegister(ushort addr, byte value) + { + switch (addr) + { + case 0xFF00: //REG_P1 - Register for reading joy pad info and determining system type. (R/W) + Registers.Input.Write(value); + break; + case 0xFF01: //REG_SB - Serial transfer data (R/W) + return; + case 0xFF02: //REG_SC - SIO control (R/W) + return; + case 0xFF04: //REG_DIV - Divider Register (R/W) + return; + case 0xFF05: //REG_TIMA - Timer counter (R/W) + return; + case 0xFF06: //REG_TMA - Timer Modulo (R/W) + return; + case 0xFF07: //REG_TAC - Timer Control (R/W) + return; + case 0xFF0F: //REG_IF - Interrupt Flag (R/W) + return; + case 0xFF10: //REG_NR10 - Sound Mode 1 register, Sweep register (R/W) + return; + case 0xFF11: //REG_NR11 - Sound Mode 1 register, Sound length/Wave pattern duty (R/W) + return; + case 0xFF12: //REG_NR12 - Sound Mode 1 register, Envelope (R/W) + return; + case 0xFF13: //REG_NR13 - Sound Mode 1 register, Frequency lo (W) + return; + case 0xFF14: //REG_NR14 - Sound Mode 1 register, Frequency hi (R/W) + return; + + //0xFF15 ??????????????? + + case 0xFF16: //REG_NR21 - Sound Mode 2 register, Sound Length; Wave Pattern Duty (R/W) + return; + case 0xFF17: //REG_NR22 - Sound Mode 2 register, envelope (R/W) + return; + case 0xFF18: //REG_NR23 - Sound Mode 2 register, frequency lo data (W) + return; + case 0xFF19: //REG_NR24 - Sound Mode 2 register, frequency hi data (R/W) + return; + case 0xFF1A: //REG_NR30 - Sound Mode 3 register, Sound on/off (R/W) + return; + case 0xFF1B: //REG_NR31 - Sound Mode 3 register, sound length (R/W) + return; + case 0xFF1C: //REG_NR32 - Sound Mode 3 register, Select output level (R/W) + return; + case 0xFF1D: //REG_NR33 - Sound Mode 3 register, frequency's lower data (W) + return; + case 0xFF1E: //REG_NR34 - Sound Mode 3 register, frequency's higher data (R/W) + return; + + //0xFF1F ??????????????? + + case 0xFF20: //REG_NR41 - Sound Mode 4 register, sound length (R/W) + return; + case 0xFF21: //REG_NR42 - Sound Mode 4 register, envelope (R/W) + return; + case 0xFF22: //REG_NR43 - Sound Mode 4 register, polynomial counter (R/W) + return; + case 0xFF23: //REG_NR44 - Sound Mode 4 register, counter/consecutive; inital (R/W) + return; + case 0xFF24: //REG_NR50 - Channel control / ON-OFF / Volume (R/W) + return; + case 0xFF25: //REG_NR51 - Selection of Sound output terminal (R/W) + return; + case 0xFF26: //REG_NR52 - Sound on/off (R/W) (Value at reset: $F1-GB, $F0-SGB) + return; + case 0xFF30: Sound.WavePatternRam[0x00] = value; break; case 0xFF31: Sound.WavePatternRam[0x01] = value; break; + case 0xFF32: Sound.WavePatternRam[0x02] = value; break; case 0xFF33: Sound.WavePatternRam[0x03] = value; break; + case 0xFF34: Sound.WavePatternRam[0x04] = value; break; case 0xFF35: Sound.WavePatternRam[0x05] = value; break; + case 0xFF36: Sound.WavePatternRam[0x06] = value; break; case 0xFF37: Sound.WavePatternRam[0x07] = value; break; + case 0xFF38: Sound.WavePatternRam[0x08] = value; break; case 0xFF39: Sound.WavePatternRam[0x09] = value; break; + case 0xFF3A: Sound.WavePatternRam[0x0A] = value; break; case 0xFF3B: Sound.WavePatternRam[0x0B] = value; break; + case 0xFF3C: Sound.WavePatternRam[0x0C] = value; break; case 0xFF3D: Sound.WavePatternRam[0x0D] = value; break; + case 0xFF3E: Sound.WavePatternRam[0x0E] = value; break; case 0xFF3F: Sound.WavePatternRam[0x0F] = value; break; + case 0xFF40: //REG_LCDC - LCD Control (R/W) (value $91 at reset) + Registers.LCDC.Write(value); + break; + case 0xFF41: //REG_STAT - LCDC Status (R/W) + return; + case 0xFF42: //REG_SCY - Scroll Y (R/W) + Registers.SCY = value; + break; + case 0xFF43: //REG_SCX - Scroll X (R/W) + Registers.SCX = value; + break; + case 0xFF44: //REG_LY - LCDC Y-Coordinate (R) + return; + case 0xFF45: //REG_LYC - LY Compare (R/W) + return; + case 0xFF46: //REG_DMA - DMA Transfer and Start Address (W) + return; + case 0xFF47: //REG_BGP - BG & Window Palette Data (R/W) + return; + case 0xFF48: //REG_OBP0 - Object Palette 0 Data (R/W) + return; + case 0xFF49: //REG_OBP1 - Object Palette 1 Data (R/W) + return; + case 0xFF4A: //REG_WY - Window Y Position (R/W) + return; + case 0xFF4B: //REG_WX - Window X Position (R/W) + return; + case 0xFFFF: //REG_IE + return; + default: + return; + } + } + + public void WriteMemory(ushort addr, byte value) + { + if (addr < 0x8000) + return; + else if (addr < 0xA000) + VRam[addr - 0x8000] = value; + else if (addr < 0xC000) + SRam[addr - 0xA000] = value; + else if (addr < 0xD000) + WRam[addr - 0xC000] = value; + else if (addr < 0xE000) + WRam[addr - 0xC000] = value; + else if (addr < 0xFE00) + WriteMemory((ushort)(addr - 0xE000), value); + else if (addr < 0xFEA0) + OAM[addr - 0xFE00] = value; + else if (addr < 0xFF00) + return; + else if (addr < 0xFF80) + WriteRegister(addr,value); + else if (addr < 0xFFFF) + HRam[addr - 0xFF80] = value; + else WriteRegister(addr, value); + } + + public void FrameAdvance(bool render) + { + Cpu.ExecuteCycles(4096); + } + + public IVideoProvider VideoProvider + { + get { throw new NotImplementedException(); } + } + + public ISoundProvider SoundProvider + { + get { throw new NotImplementedException(); } + } + + public int Frame + { + get { throw new NotImplementedException(); } + } + + public byte[] SaveRam + { + get { throw new NotImplementedException(); } + } + + public bool SaveRamModified + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void SaveStateText(System.IO.TextWriter writer) + { + throw new NotImplementedException(); + } + + public void LoadStateText(System.IO.TextReader reader) + { + throw new NotImplementedException(); + } + + public void SaveStateBinary(System.IO.BinaryWriter writer) + { + throw new NotImplementedException(); + } + + public void LoadStateBinary(System.IO.BinaryReader reader) + { + throw new NotImplementedException(); + } + + public byte[] SaveStateBinary() + { + throw new NotImplementedException(); + } + + public void RenderOBJLine(int line, byte[] output, bool limit) + { + int height = Registers.LCDC.ObjSize == TRegisters.TLCDC.EObjSize.ObjSize_8x16 ? 16 : 8; + List sprites = new List(); + + //1st pass: select sprites to draw + for (int s = 0; s < 40; s++) + { + int y = OAM[s * 4 + 0]; + y -= 16; + if (line < y) continue; + if (line < y + height) continue; + + sprites.Add(s); + if (sprites.Count == 10 && limit) break; //sprite limit + } + + //now render from low priority to high + for (int i = sprites.Count - 1; i >= 0; i--) + { + int s = sprites[i]; + int y = OAM[s*4 + 0]; + int x = OAM[s*4 + 1]; + int pat = OAM[s*4 + 2]; + byte flags = OAM[s*4 + 3]; + bool priority = GetBit8(flags, 7); + bool yflip = GetBit8(flags, 6); + bool xflip = GetBit8(flags, 5); + bool pal = GetBit8(flags, 4); + + y -= 16; + x -= 8; + + int sprline = line - y; + if(yflip) + sprline = height - sprline - 1; + + if (height == 16) pat = ~1; + + ushort patternAddr = (ushort)(0x8000 + (pat << 4)); + patternAddr += (ushort)(sprline << 1); + + int _lobits = ReadMemory(patternAddr); + patternAddr += 1; + int _hibits = ReadMemory(patternAddr); + + for (int j = 0; j < 8; j++) + { + int px = x + j; + if (px < 0) continue; + if (px >= 160) continue; + + int lobits; + int hibits; + + if (xflip) + { + lobits = _lobits >> (j); + hibits = _hibits >> (j); + } + else + { + lobits = _lobits >> (7 - j); + hibits = _hibits >> (7 - j); + } + lobits &= 1; + hibits &= 1; + int pixel = lobits | (hibits << 1); + output[x] = (byte) pixel; + } + } + + } + + public void RenderTileLine(int line, byte[] output, ushort tiledata) + { + int py = line; + int ty = py >> 3; + int tyr = py & 7; + int tileRowOffset = ty << 5; + + for (int x = 0; x < 128; x++) + { + int px = x; + px &= 0xFF; + int tx = px >> 3; + int txr = px & 7; + int tileOffset = tileRowOffset + tx; + int tileAddr = tileOffset; + int tileNum = ty * 16 + tx; + tileNum = (tileNum) & 0xFF; + ushort patternAddr = (ushort)(tiledata + (tileNum << 4)); + patternAddr += (ushort)(tyr << 1); + + int lobits = ReadMemory(patternAddr); + patternAddr += 1; + int hibits = ReadMemory(patternAddr); + lobits >>= (7 - txr); + hibits >>= (7 - txr); + lobits &= 1; + hibits &= 1; + int pixel = lobits | (hibits << 1); + output[x] = (byte)pixel; + } + } + + public void RenderBGLine(int line, byte[] output, bool scroll) + { + ushort tilemap = Registers.LCDC.BgTileMapAddr; + ushort tiledata = Registers.LCDC.TileDataAddr; + + int tileAdjust = (Registers.LCDC.TileData == TRegisters.TLCDC.ETileData.Region_8800_97FF ? 128 : 0); + + int py = line; + if(scroll) line += Registers.SCY; + py &= 0xFF; + int ty = py >> 3; + int tyr = py & 7; + int tileRowOffset = ty << 5; + + for (int x = 0; x < 160; x++) + { + int px = x; + if(scroll) px += Registers.SCX; + px &= 0xFF; + int tx = px >> 3; + int txr = px & 7; + int tileOffset = tileRowOffset + tx; + int tileAddr = tilemap + tileOffset; + int tileNum = ReadMemory((ushort)tileAddr); + tileNum = (tileNum + tileAdjust) & 0xFF; + ushort patternAddr = (ushort)(tiledata + (tileNum << 4)); + patternAddr += (ushort)(tyr<<1); + + int lobits = ReadMemory(patternAddr); + patternAddr += 1; + int hibits = ReadMemory(patternAddr); + lobits >>= (7 - txr); + hibits >>= (7 - txr); + lobits &= 1; + hibits &= 1; + int pixel = lobits | (hibits << 1); + output[x] = (byte)pixel; + } + + } + + public bool DeterministicEmulation { get; set; } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Gameboy/Input.cs b/BizHawk.Emulation/Consoles/Gameboy/Input.cs new file mode 100644 index 0000000000..bf5d4a79b8 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Input.cs @@ -0,0 +1,18 @@ +namespace BizHawk.Emulation.Consoles.Gameboy +{ + public partial class Gameboy + { + public static readonly ControllerDefinition GbController = new ControllerDefinition + { + Name = "Gameboy Controller", + BoolButtons = + { + "Up", "Down", "Left", "Right", "A", "B", "Select", "Start" + } + }; + + public ControllerDefinition ControllerDefinition { get { return GbController; } } + public IController Controller { get; set; } + + } +} diff --git a/BizHawk.Emulation/Consoles/Gameboy/Mappers.cs b/BizHawk.Emulation/Consoles/Gameboy/Mappers.cs new file mode 100644 index 0000000000..e852adcb14 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Gameboy/Mappers.cs @@ -0,0 +1,16 @@ +using System; + +namespace BizHawk.Emulation.Consoles.Gameboy +{ + partial class Gameboy + { + public class MemoryMapper + { + private readonly Gameboy gb; + public MemoryMapper(Gameboy gb) + { + this.gb = gb; + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/PC Engine/Compat.txt b/BizHawk.Emulation/Consoles/PC Engine/Compat.txt new file mode 100644 index 0000000000..2d21557d51 --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/Compat.txt @@ -0,0 +1,58 @@ +======= TurboGrafx compatibility issues ======= + +General: + + Noise Channel isn't right. Less obnoxious now, still not happy. + + T Flag implemented for ADC, EOR. Log warning if used by any other instructions. Should probably just do it for the others, but I hate not having a test case. + + Video timing is off. + + Audio volumes are probably wrong. + + LFO is not implemented, though I can't tell. + +Air Zonk - Freezes shortly into a new game +Battle Ace - Some gfx glitches +Battle Royale - Doesnt boot +Bravoman - Doesn't boot +Cadash - Camera is all crazy. Very sensitive to interrupt timing and timing in general. +Chouzetsu Rinjin - Doesnt boot +Cyber Dodge - Minor gfx issues +Davis Cup Tennis - uh lets just say it doesnt work in creative ways +Dead Moon - Minor gfx issues +Dragon Curse - Terribly annoying sprite flicker - presumably timing related +Dragon Egg - Doesn't boot +Fighting Run - Corruption issues +Final Solider - Graphics corruption issues +Griffon - Dies in the new game sequence +Gunboat - Crash / CPU Break (Needs BRAM) +Hisou Kihei Serd - Doesn't boot +Idol Hanafuda Fan Club - Doesn't boot +Impossamole - Gfx issues +Legendary Axe - Doesn't boot +Legendary Axe II - Corruption, freezes in opening sequence +Madoo Granzort - Graphics issues because VPC renderer is not using new frame timing +Magical Chase - Freezes when starting 1st level - waiting for DMA completion IRQ? +MML Demo - Echo channels are too loud (equal volume!) +Naxat Open - Crashes when you start new game +New Adventure Island - Minor gfx issues +Night Creatures - Some gfx glitches +Outrun - 'Sea Wind' sample when selecting music is not playing ...... raster issues, now more annoying than before +Populous - Game freezes on starting new game - *** NEEDS BATTERY SAVERAM *** +Power Drift - Timing glitch... starting new game runs slower than it should +R-Type - Funky corruption after killing final boss in Stage 8 +Side Arms - Video timing issue - bottom arms display shouldn't be visible +Sinistron - Raster effect errors +Soldier Blade - Freezes about 5 minutes in. Always in the same spot, fortunately. I have a savestate. +Strip Fighter - Minor gfx glitches (status area) +Turrican - Playable, issues with opening sequence +Valkyrie No Densetsu - Freezes in title sequence + + +Stuff I Fixed That's Not In Other Docs: + ++ Street Fighter II special mapper ++ Populous has special BRAM / saveRAM (I have not yet fixed this) - Gunboat appears to be the same ++ After Burner - There is a 1-instruction delay on changes to IRQ Control Byte taking effect ++ There is a one-instruction delay on changes to the I flag taking effect + - Affects (Not a complete list): Blodia, Body Conquest 2, Champions Forever Boxing, + Cross Wiber, Jackie Chan, Jigoku Meguri, New Adventure Island, World Beach volley + - Actually, I'm not at all convinced there's always a 1-instruction delay on the I-flag. + But this fixes several games; clearly there are delays in some scenarios. But it's not clear + to me that this delay is ALWAYS present. \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/PC Engine/Input.cs b/BizHawk.Emulation/Consoles/PC Engine/Input.cs new file mode 100644 index 0000000000..2ea3fcfa30 --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/Input.cs @@ -0,0 +1,44 @@ +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + public partial class PCEngine + { + public static readonly ControllerDefinition PCEngineController = + new ControllerDefinition + { + Name = "PC Engine Controller", + BoolButtons = { "Up", "Down", "Left", "Right", "II", "I", "Select", "Run" } + }; + + public ControllerDefinition ControllerDefinition { get { return PCEngineController; } } + public IController Controller { get; set; } + + private byte inputSelector; + public bool SEL { get { return ((inputSelector & 1) != 0) ;} } + + private void WriteInput(byte value) + { + inputSelector = value; + } + + private byte ReadInput() + { + byte value = 0xBF; + if (SEL == false) // return buttons + { + if (Controller["I"]) value &= 0xFE; + if (Controller["II"]) value &= 0xFD; + if (Controller["Select"]) value &= 0xFB; + if (Controller["Run"]) value &= 0xF7; + } else { //return directions + if (Controller["Up"]) value &= 0xFE; + if (Controller["Right"]) value &= 0xFD; + if (Controller["Down"]) value &= 0xFB; + if (Controller["Left"]) value &= 0xF7; + } + + if (Region == "Japan") value |= 0x40; + + return value; + } + } +} diff --git a/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SF2.cs b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SF2.cs new file mode 100644 index 0000000000..b081de7f1e --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SF2.cs @@ -0,0 +1,90 @@ +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + public partial class PCEngine + { + // Street Fighter 2 was a 20-megabit HuCard. The PCE has a maximum 8-megabit addressable ROM space. + // Therefore SF2 had a special mapper to make this work. + + // TODO: need to update SF2 mapper to reflect updates made to the primary mapper + // (ie, the IOBuffer) + // However, I believe more fixes will be made in the future, and SF2 works, so this is not + // currently a priority. + + private byte SF2MapperLatch; + + private byte ReadMemorySF2(ushort addr) + { + int page = Cpu.MPR[addr >> 13]; + ushort addr13 = (ushort)(addr & 0x1FFF); + + if (page < 0x40) + { + // read rom. + return RomData[(page % RomPages << 13) | (addr13)]; + } + if (page < 0x80) + { + // read rom with extended SF2 mapper. + return RomData[(((page << 13) | addr13) & 0x7FFFF) + ((SF2MapperLatch + 1)*0x80000)]; + } + if (page >= 0xF8 && page <= 0xFB) + { + // read RAM. + return Ram[((page-0xF8) << 13) | addr13]; + } + + if (page == 0xFF) + { + // hardware page. + if (addr13 < 0x400) return VDC1.ReadVDC(addr13 & 0x03); + if (addr13 < 0x800) return VCE.ReadVCE((addr13 & 0x07)); + if ((addr13 & ~1) == 0x0C00) return Cpu.TimerValue; + if (addr13 >= 0x1000 && addr13 < 0x1400) return ReadInput(); + if (addr13 == 0x1402) return Cpu.IRQControlByte; + if (addr13 == 0x1403) return Cpu.ReadIrqStatus(); + } + Log.Error("MEM", "UNHANDLED READ: [{0:X2}] {1:X4}", page, addr13); + return 0xFF; + } + + private void WriteMemorySF2(ushort addr, byte value) + { + int page = Cpu.MPR[addr >> 13]; + ushort addr13 = (ushort)(addr & 0x1FFF); + + if ((addr & 0x1FFC) == 0x1FF0) + { + // Set SF2 pager. + SF2MapperLatch = (byte) (addr & 0x03); + return; + } + + if (page >= 0xF8 && page <= 0xFB) + { + // write RAM. + Ram[addr13] = value; + } + + if (page == 0xFF) + { + // hardware page. + if (addr13 < 0x400) + VDC1.WriteVDC(addr13 & 3, value); + else if (addr13 < 0x800) + VCE.WriteVCE(addr13 & 7, value); + else if (addr13 < 0x80A) + PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); + else if (addr13 == 0x0C00) + Cpu.WriteTimer(value); + else if (addr13 == 0x0C01) + Cpu.WriteTimerEnable(value); + else if (addr13 >= 0x1000 && addr13 < 0x1400) + WriteInput(value); + else if (addr13 == 0x1402) + Cpu.WriteIrqControl(value); + else if (addr13 == 0x1403) + Cpu.WriteIrqStatus(); + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SuperGrafx.cs b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SuperGrafx.cs new file mode 100644 index 0000000000..336599ce30 --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.SuperGrafx.cs @@ -0,0 +1,71 @@ +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + public partial class PCEngine + { + // The SuperGrafx has 32K of RAM and a different port configuration to allow + // I/O access to VDC1, VDC2, and the VPC. + + private byte ReadMemorySGX(ushort addr) + { + int page = Cpu.MPR[addr >> 13]; + ushort addr13 = (ushort)(addr & 0x1FFF); + + if (page < 0x80) // read ROM + return RomData[(page % RomPages << 13) | (addr13)]; + + if (page >= 0xF8 && page <= 0xFB) // read RAM + return Ram[((page-0xF8) << 13) | addr13]; + + if (page == 0xFF) // hardware page. + { + if (addr13 < 0x400) + { + addr13 &= 0x1F; + if (addr13 <= 0x07) return VDC1.ReadVDC(addr13 & 3); + if (addr13 <= 0x0F) return VPC.ReadVPC(addr13); + if (addr13 <= 0x17) return VDC2.ReadVDC(addr13 & 3); + return 0xFF; + } + if (addr13 < 0x0800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr13 & 0x07)); } + if (addr13 < 0x080F) return IOBuffer; + if ((addr13 & ~1) == 0x0C00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; } + if (addr13 >= 0x1000 && + addr13 < 0x1400) { IOBuffer = ReadInput(); return IOBuffer; } + if ((addr13 & ~1) == 0x1400) return IOBuffer; + if (addr13 == 0x1402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; } + if (addr13 == 0x1403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; } + } + Log.Error("MEM", "UNHANDLED READ: [{0:X2}] {1:X4}", page, addr13); + return 0xFF; + } + + private void WriteMemorySGX(ushort addr, byte value) + { + int page = Cpu.MPR[addr >> 13]; + ushort addr13 = (ushort)(addr & 0x1FFF); + + if (page >= 0xF8 && page <= 0xFB) // write RAM. + Ram[((page-0xF8) << 13) | addr13] = value; + + else if (page == 0xFF) // hardware page. + { + if (addr13 < 0x0400) + { + addr13 &= 0x1F; + if (addr13 <= 0x07) VDC1.WriteVDC(addr13 & 3, value); + else if (addr13 <= 0x0F) VPC.WriteVPC(addr13, value); + else if (addr13 <= 0x17) VDC2.WriteVDC(addr13 & 3, value); + } + else if (addr13 < 0x0800) { Cpu.PendingCycles--; VCE.WriteVCE(addr13 & 7, value); } + else if (addr13 < 0x080A) { IOBuffer = value; PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); } + else if (addr13 == 0x0C00) { IOBuffer = value; Cpu.WriteTimer(value); } + else if (addr13 == 0x0C01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } + else if (addr13 >= 0x1000 && + addr13 < 0x1400) { IOBuffer = value; WriteInput(value); } + else if (addr13 == 0x1402) { IOBuffer = value; Cpu.WriteIrqControl(value); } + else if (addr13 == 0x1403) { IOBuffer = value; Cpu.WriteIrqStatus(); } + else Log.Error("MEM", "unhandled hardware write [{0:X4}] : {1:X2}", addr13, value); + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs new file mode 100644 index 0000000000..cc6d90aa8b --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/MemoryMap.cs @@ -0,0 +1,64 @@ +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + public partial class PCEngine + { + // Much to my surprise, this silly I/O Buffer mechanic described in Charles MacDonald's doc is actually used by games. + // As one example, Cyber Core requires emulation of the IOBuffer to boot. + private byte IOBuffer; + + private byte ReadMemory(ushort addr) + { + int page = Cpu.MPR[addr >> 13]; + ushort addr13 = (ushort)(addr & 0x1FFF); + + if (page < 0x80) // read ROM + return RomData[(page % RomPages << 13) | (addr13)]; + + if (page >= 0xF8 && page <= 0xFB) // read RAM + return Ram[addr13]; + + if (page == 0xFF) // hardware page. + { + if (addr13 < 0x0400) return VDC1.ReadVDC(addr13 & 0x03); + if (addr13 < 0x0800) { Cpu.PendingCycles--; return VCE.ReadVCE((addr13 & 0x07)); } + if (addr13 < 0x080F) return IOBuffer; + if ((addr13 & ~1) == 0x0C00) { IOBuffer = (byte) (Cpu.TimerValue | (IOBuffer & 0x80)); return IOBuffer; } + if (addr13 >= 0x1000 && + addr13 < 0x1400) { IOBuffer = ReadInput(); return IOBuffer; } + if ((addr13 & ~1) == 0x1400) return IOBuffer; + if (addr13 == 0x1402) { IOBuffer = (byte) (Cpu.IRQControlByte | (IOBuffer & 0xF8)); return IOBuffer; } + if (addr13 == 0x1403) { IOBuffer = (byte) (Cpu.ReadIrqStatus() | (IOBuffer & 0xF8)); return IOBuffer; } + } + + Log.Error("MEM", "UNHANDLED READ: [{0:X2}] {1:X4}", page, addr13); + return 0xFF; + } + + private void WriteMemory(ushort addr, byte value) + { + int page = Cpu.MPR[addr >> 13]; + ushort addr13 = (ushort)(addr & 0x1FFF); + + if (page >= 0xF8 && page <= 0xFB) // write RAM. + { + if (Cpu.debug) + Log.Note("MEM", "*Mem* Changed {0:X4} from {1:X2} to {2:X2}", addr13, Ram[addr13], value); + Ram[addr13] = value; + } + + if (page == 0xFF) // hardware page. + { + if (addr13 < 0x0400) VDC1.WriteVDC(addr13 & 3, value); + else if (addr13 < 0x0800) { Cpu.PendingCycles--; VCE.WriteVCE(addr13 & 7, value); } + else if (addr13 < 0x080A) { IOBuffer = value; PSG.WritePSG(addr13, value, Cpu.TotalExecutedCycles); } + else if (addr13 == 0x0C00) { IOBuffer = value; Cpu.WriteTimer(value); } + else if (addr13 == 0x0C01) { IOBuffer = value; Cpu.WriteTimerEnable(value); } + else if (addr13 >= 0x1000 && + addr13 < 0x1400) { IOBuffer = value; WriteInput(value); } + else if (addr13 == 0x1402) { IOBuffer = value; Cpu.WriteIrqControl(value); } + else if (addr13 == 0x1403) { IOBuffer = value; Cpu.WriteIrqStatus(); } + else Log.Error("MEM", "unhandled hardware write [{0:X4}] : {1:X2}", addr13, value); + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs new file mode 100644 index 0000000000..5c164185a0 --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/PCEngine.cs @@ -0,0 +1,279 @@ +using System; +using System.Globalization; +using System.IO; +using BizHawk.Emulation.CPUs.H6280; +using BizHawk.Emulation.Sound; + +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + public enum NecSystemType + { + TurboGrafx, + TurboCD, + SuperGrafx + } + + public sealed partial class PCEngine : IEmulator + { + // ROM + public byte[] RomData; + public int RomPages; + + // Machine + public NecSystemType Type; + public HuC6280 Cpu; + public VDC VDC1, VDC2; + public VCE VCE; + public HuC6280PSG PSG; + public VPC VPC; + + private bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } } + private bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } } + private bool TurboCD { get { return Type == NecSystemType.TurboCD; } } + + // Memory system + public byte[] Ram; + + // PC Engine timings: + // 21,477,270 Machine clocks / sec + // 7,159,090 Cpu cycles / sec + + // At 60.00 FPS + // 357,954 mclks / frame + // 119,318 Cpu cycles / frame + + // 263 lines / frame: + // 1361 mclks / line + // 454 Cpu cycles / line + + public PCEngine(NecSystemType type) + { + Type = type; + Controller = NullController.GetNullController(); + Init(); + } + + private void Init() + { + Cpu = new HuC6280(); + VCE = new VCE(); + VDC1 = new VDC(Cpu, VCE); + PSG = new HuC6280PSG(); + + if (TurboGrafx || TurboCD) + { + Ram = new byte[0x2000]; + Cpu.ReadMemory = ReadMemory; + Cpu.WriteMemory = WriteMemory; + Cpu.WriteVDC = VDC1.WriteVDC; + } + + if (SuperGrafx) + { + VDC2 = new VDC(Cpu, VCE); + VPC = new VPC(VDC1, VDC2, VCE, Cpu); + Ram = new byte[0x8000]; + Cpu.ReadMemory = ReadMemorySGX; + Cpu.WriteMemory = WriteMemorySGX; + Cpu.WriteVDC = VDC1.WriteVDC; + } + } + + public void LoadGame(IGame game) + { + if (game.GetRomData().Length == 0x60000) + { + // 384k roms require special loading code. Why ;_; + // In memory, 384k roms look like [1st 256k][Then full 384k] + RomData = new byte[0xA0000]; + var origRom = game.GetRomData(); + for (int i=0; i<0x40000; i++) + RomData[i] = origRom[i]; + for (int i = 0; i < 0x60000; i++) + RomData[i+0x40000] = origRom[i]; + RomPages = RomData.Length/8192; + } else if (game.GetRomData().Length > 1024 * 1024) { + // If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper + Cpu.ReadMemory = ReadMemorySF2; + Cpu.WriteMemory = WriteMemorySF2; + RomData = game.GetRomData(); + RomPages = RomData.Length / 8192; + } else { + // normal rom. + RomData = game.GetRomData(); + RomPages = RomData.Length / 8192; + } + Cpu.ResetPC(); + } + + public int Frame { get; set; } + + public void FrameAdvance(bool render) + { + Controller.FrameNumber = Frame++; + //Log.Note("CPU","======== FRAME {0} =========",Frame); + PSG.BeginFrame(Cpu.TotalExecutedCycles); + + if (SuperGrafx) + VPC.ExecFrame(); // TODO supergrafx frameskipping (waiting on a larger update of VPC frame timing, once I get VDC timing correct) + else + VDC1.ExecFrame(render); + + PSG.EndFrame(Cpu.TotalExecutedCycles); + } + + public void HardReset() + { + Init(); + Cpu.ResetPC(); + } + + public IVideoProvider VideoProvider + { + get { return (IVideoProvider) VPC ?? VDC1; } + } + + public ISoundProvider SoundProvider + { + get { return PSG; } + } + + public string Region { get; set; } + public bool DeterministicEmulation { get; set; } + + public byte[] SaveRam + { + get { throw new NotImplementedException(); } + } + + public bool SaveRamModified + { + get { return false; } + set { throw new NotImplementedException(); } + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[PCEngine]"); + writer.Write("RAM "); + Ram.SaveAsHex(writer); + writer.WriteLine("Frame " + Frame); + if (Cpu.ReadMemory == ReadMemorySF2) + writer.WriteLine("SF2MapperLatch " + SF2MapperLatch); + writer.WriteLine("IOBuffer {0:X2}", IOBuffer); + writer.WriteLine(); + + if (SuperGrafx) + { + Cpu.SaveStateText(writer); + VPC.SaveStateText(writer); + VCE.SaveStateText(writer); + VDC1.SaveStateText(writer, 1); + VDC2.SaveStateText(writer, 2); + PSG.SaveStateText(writer); + } + else + { + Cpu.SaveStateText(writer); + VCE.SaveStateText(writer); + VDC1.SaveStateText(writer, 1); + PSG.SaveStateText(writer); + } + writer.WriteLine("[/PCEngine]"); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[PCEngine]") continue; + if (args[0] == "[/PCEngine]") break; + if (args[0] == "Frame") + Frame = int.Parse(args[1]); + else if (args[0] == "SF2MapperLatch") + SF2MapperLatch = byte.Parse(args[1]); + else if (args[0] == "IOBuffer") + IOBuffer = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "RAM") + Ram.ReadFromHex(args[1]); + else if (args[0] == "[HuC6280]") + Cpu.LoadStateText(reader); + else if (args[0] == "[PSG]") + PSG.LoadStateText(reader); + else if (args[0] == "[VCE]") + VCE.LoadStateText(reader); + else if (args[0] == "[VPC]") + VPC.LoadStateText(reader); + else if (args[0] == "[VDC1]") + VDC1.LoadStateText(reader,1); + else if (args[0] == "[VDC2]") + VDC2.LoadStateText(reader,2); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + if (SuperGrafx == false) + { + writer.Write(Ram); + writer.Write(Frame); + writer.Write(SF2MapperLatch); + writer.Write(IOBuffer); + Cpu.SaveStateBinary(writer); + VCE.SaveStateBinary(writer); + VDC1.SaveStateBinary(writer); + PSG.SaveStateBinary(writer); + } else { + writer.Write(Ram); + writer.Write(Frame); + writer.Write(IOBuffer); + Cpu.SaveStateBinary(writer); + VCE.SaveStateBinary(writer); + VPC.SaveStateBinary(writer); + VDC1.SaveStateBinary(writer); + VDC2.SaveStateBinary(writer); + PSG.SaveStateBinary(writer); + } + } + + public void LoadStateBinary(BinaryReader reader) + { + if (SuperGrafx == false) + { + Ram = reader.ReadBytes(0x2000); + Frame = reader.ReadInt32(); + SF2MapperLatch = reader.ReadByte(); + IOBuffer = reader.ReadByte(); + Cpu.LoadStateBinary(reader); + VCE.LoadStateBinary(reader); + VDC1.LoadStateBinary(reader); + PSG.LoadStateBinary(reader); + } else { + Ram = reader.ReadBytes(0x8000); + Frame = reader.ReadInt32(); + IOBuffer = reader.ReadByte(); + Cpu.LoadStateBinary(reader); + VCE.LoadStateBinary(reader); + VPC.LoadStateBinary(reader); + VDC1.LoadStateBinary(reader); + VDC2.LoadStateBinary(reader); + PSG.LoadStateBinary(reader); + } + } + + public byte[] SaveStateBinary() + { + var buf = new byte[SuperGrafx ? 166550 : 75852]; + var stream = new MemoryStream(buf); + var writer = new BinaryWriter(stream); + SaveStateBinary(writer); + //Console.WriteLine("LENGTH " + stream.Position); + writer.Close(); + return buf; + } + } +} diff --git a/BizHawk.Emulation/Consoles/PC Engine/VCE.cs b/BizHawk.Emulation/Consoles/PC Engine/VCE.cs new file mode 100644 index 0000000000..efeac2f31c --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/VCE.cs @@ -0,0 +1,116 @@ +using System; +using System.Globalization; +using System.IO; + +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + // HuC6260 Video Color Encoder + public sealed class VCE + { + public ushort VceAddress; + public ushort[] VceData = new ushort[512]; + public int[] Palette = new int[512]; + + public void WriteVCE(int port, byte value) + { + //cpu.PendingCycles--; // VCE access puts CPU into a 1-cycle wait state. + switch (port) + { + case 0: // Control Port. Doesn't control anything we care about... + break; + case 2: // Address LSB + VceAddress &= 0xFF00; + VceAddress |= value; + break; + case 3: // Address MSB + VceAddress &= 0x00FF; + VceAddress |= (ushort) (value << 8); + VceAddress &= 0x01FF; + break; + case 4: // Data LSB + VceData[VceAddress] &= 0xFF00; + VceData[VceAddress] |= value; + PrecomputePalette(VceAddress); + break; + case 5: // Data MSB + VceData[VceAddress] &= 0x00FF; + VceData[VceAddress] |= (ushort) (value << 8); + PrecomputePalette(VceAddress); + VceAddress++; + VceAddress &= 0x1FF; + break; + } + } + + public byte ReadVCE(int port) + { + //cpu.PendingCycles--; + switch (port) + { + case 4: // Data LSB + return (byte) (VceData[VceAddress] & 0xFF); + case 5: // Data MSB + byte value = (byte) ((VceData[VceAddress] >> 8) | 0xFE); + VceAddress++; + VceAddress &= 0x1FF; + return value; + default: return 0xFF; + } + } + + private static readonly byte[] PalConvert = {0, 36, 72, 109, 145, 182, 218, 255}; + + public void PrecomputePalette(int slot) + { + byte r = PalConvert[(VceData[slot] >> 3) & 7]; + byte g = PalConvert[(VceData[slot] >> 6) & 7]; + byte b = PalConvert[VceData[slot] & 7]; + Palette[slot] = Colors.ARGB(r, g, b); + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[VCE]"); + writer.WriteLine("VceAddress {0:X4}", VceAddress); + writer.Write("VceData "); + VceData.SaveAsHex(writer); + writer.WriteLine("[/VCE]\n"); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/VCE]") break; + if (args[0] == "VceAddress") + VceAddress = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "VceData") + VceData.ReadFromHex(args[1]); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + + for (int i = 0; i < VceData.Length; i++) + PrecomputePalette(i); + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(VceAddress); + for (int i = 0; i < VceData.Length; i++) + writer.Write(VceData[i]); + } + + public void LoadStateBinary(BinaryReader reader) + { + VceAddress = reader.ReadUInt16(); + for (int i = 0; i < VceData.Length; i++) + { + VceData[i] = reader.ReadUInt16(); + PrecomputePalette(i); + } + } + } +} diff --git a/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs b/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs new file mode 100644 index 0000000000..8ddbaf9f6a --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/VDC.Render.cs @@ -0,0 +1,337 @@ +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + // This rendering code is only used for TurboGrafx/TurboCD Mode. + // In SuperGrafx mode, separate rendering functions in the VPC class are used. + + public partial class VDC + { + /* There are many line-counters here. Here is a breakdown of what they each are: + + + ScanLine is the current NTSC scanline. It has a range from 0 to 262. + + ActiveLine is the current offset into the framebuffer. 0 is the first + line of active display, and the last value will be BufferHeight-1. + + BackgroundY is the current offset into the scroll plane. It is set with BYR + register at certain sync points and incremented every scanline. + Its values range from 0 - $1FF. + + RCRCount is the current offset into the RCR register. It is reset to $40 + on the first active display line of, and incremented every line. Its effective + range is $40 - $146. + + */ + public int ScanLine; + public int BackgroundY; + + private byte[] PriorityBuffer = new byte[512]; + private byte[] InterSpritePriorityBuffer = new byte[512]; + private int latchedDisplayStartLine; + private int ActiveLine; + private int RCRCount; + + // One possible cause of graphics corruption is that I am executing DMAs immediately. + // DMAs are only executed when the system is OUTSIDE of the the active display period. + // So... that could be a thing. + // Although its actually not probably very much of a thing. + + public void ExecFrame(bool render) + { + latchedDisplayStartLine = DisplayStartLine; + ActiveLine = 0 - latchedDisplayStartLine; + ScanLine = 0; + + for (; ScanLine < 262;) + { + //Log.Note("VDC","ScanLine {0} (ActiveLine {1}, RCR {2}, BGY {3})",ScanLine, ActiveLine, RCRCount, BackgroundY); + bool InActiveDisplay = false; + if (ScanLine >= latchedDisplayStartLine && ScanLine < latchedDisplayStartLine + FrameHeight) + InActiveDisplay = true; + + if (ActiveLine == 0) + { + BackgroundY = Registers[BYR]; + RCRCount = 0x40; + //Console.WriteLine("Latched BYR {0} at scanline {1}",BackgroundY, ScanLine); + } + + if ((RCRCount) == (Registers[RCR] & 0x3FF)) + { + if (IntRasterCompare) + { + //Log.Note("VDC", "Enter RCR interrupt at scanline {0}",ScanLine); + StatusByte |= StatusRasterCompare; + cpu.IRQ1Assert = true; + } + } + + if (ActiveLine == BufferHeight && IntVerticalBlank) + { + StatusByte |= StatusVerticalBlanking; + cpu.IRQ1Assert = true; + } + cpu.Execute(82); + + if (InActiveDisplay && render) + RenderScanLine(); + + cpu.Execute(373); + + ScanLine++; + ActiveLine++; + RCRCount++; + BackgroundY++; + BackgroundY &= 0x01FF; + } + } + + public void RenderScanLine() + { + RenderBackgroundScanline(); + RenderSpritesScanline(); + + if (ScanLine == FrameHeight - 1) + UpdateSpriteAttributeTable(); + } + + public void UpdateSpriteAttributeTable() + { + if (/*(Registers[DCR] & 0x10) != 0 &&*/ Registers[SATB] <= 0x7F00) + { + for (int i = 0; i < 256; i++) + { + SpriteAttributeTable[i] = VRAM[Registers[SATB] + i]; + } + } + } + + private void RenderBackgroundScanline() + { + // clear priority buffer + for (int i = 0; i < FrameWidth; i++) + PriorityBuffer[i] = 0; + + if (BackgroundEnabled == false) + { + for (int i = 0; i < FrameWidth; i++) + FrameBuffer[(ActiveLine * FrameWidth) + i] = vce.Palette[0]; + return; + } + + int batHeight = BatHeight * 8; + int batWidth = BatWidth * 8; + + int vertLine = BackgroundY; + vertLine %= batHeight; + int yTile = (vertLine / 8); + int yOfs = vertLine % 8; + + // TODO: x-scrolling is done super quick and shitty here and slow. + // Ergo, make it better later. + + int xScroll = Registers[BXR] & 0x3FF; + for (int x = 0; x < FrameWidth; x++) + { + int xTile = ((x + xScroll) / 8) % BatWidth; + int xOfs = (x + xScroll) & 7; + int tileNo = VRAM[(ushort)(((yTile * BatWidth) + xTile))] & 2047; + int paletteNo = VRAM[(ushort)(((yTile * BatWidth) + xTile))] >> 12; + int paletteBase = paletteNo * 16; + + byte c = PatternBuffer[(tileNo * 64) + (yOfs * 8) + xOfs]; + if (c == 0) + FrameBuffer[(ActiveLine * FrameWidth) + x] = vce.Palette[0]; + else + { + FrameBuffer[(ActiveLine * FrameWidth) + x] = vce.Palette[paletteBase + c]; + PriorityBuffer[x] = 1; + } + } + } + + private static byte[] heightTable = { 16, 32, 64, 64 }; + + public void RenderSpritesScanline() + { + if (SpritesEnabled == false) + return; + + // clear inter-sprite priority buffer + for (int i = 0; i < FrameWidth; i++) + InterSpritePriorityBuffer[i] = 0; + + for (int i = 0; i < 64; i++) + { + int y = (SpriteAttributeTable[(i * 4) + 0] & 1023) - 64; + int x = (SpriteAttributeTable[(i * 4) + 1] & 1023) - 32; + ushort flags = SpriteAttributeTable[(i * 4) + 3]; + int height = heightTable[(flags >> 12) & 3]; + + if (y + height <= ActiveLine || y > ActiveLine) + continue; + + int patternNo = (((SpriteAttributeTable[(i * 4) + 2]) >> 1) & 0x1FF); + int paletteBase = 256 + ((flags & 15) * 16); + int width = (flags & 0x100) == 0 ? 16 : 32; + bool priority = (flags & 0x80) != 0; + bool hflip = (flags & 0x0800) != 0; + bool vflip = (flags & 0x8000) != 0; + + if (width == 32) + patternNo &= 0x1FE; + + int yofs = 0; + if (vflip == false) + { + yofs = (ActiveLine - y) & 15; + if (height == 32) + { + patternNo &= 0x1FD; + if (ActiveLine - y >= 16) + { + y += 16; + patternNo += 2; + } + } + else if (height == 64) + { + patternNo &= 0x1F9; + if (ActiveLine - y >= 48) + { + y += 48; + patternNo += 6; + } + else if (ActiveLine - y >= 32) + { + y += 32; + patternNo += 4; + } + else if (ActiveLine - y >= 16) + { + y += 16; + patternNo += 2; + } + } + } + else // vflip == true + { + yofs = 15 - ((ActiveLine - y) & 15); + if (height == 32) + { + patternNo &= 0x1FD; + if (ActiveLine - y < 16) + { + y += 16; + patternNo += 2; + } + } + else if (height == 64) + { + patternNo &= 0x1F9; + if (ActiveLine - y < 16) + { + y += 48; + patternNo += 6; + } + else if (ActiveLine - y < 32) + { + y += 32; + patternNo += 4; + } + else if (ActiveLine - y < 48) + { + y += 16; + patternNo += 2; + } + } + } + if (hflip == false) + { + if (x + width > 0 && y + height > 0) + { + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = SpriteBuffer[(patternNo * 256) + (yofs * 16) + (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + if (priority || PriorityBuffer[xs] == 0) + FrameBuffer[(ActiveLine * FrameWidth) + xs] = vce.Palette[paletteBase + pixel]; + } + } + } + if (width == 32) + { + patternNo++; + x += 16; + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = SpriteBuffer[(patternNo * 256) + (yofs * 16) + (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + if (priority || PriorityBuffer[xs] == 0) + FrameBuffer[(ActiveLine * FrameWidth) + xs] = vce.Palette[paletteBase + pixel]; + } + + } + } + } + else + { // hflip = true + if (x + width > 0 && y + height > 0) + { + if (width == 32) + patternNo++; + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = SpriteBuffer[(patternNo * 256) + (yofs * 16) + 15 - (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + if (priority || PriorityBuffer[xs] == 0) + FrameBuffer[(ActiveLine * FrameWidth) + xs] = vce.Palette[paletteBase + pixel]; + } + } + if (width == 32) + { + patternNo--; + x += 16; + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = SpriteBuffer[(patternNo * 256) + (yofs * 16) + 15 - (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + if (priority || PriorityBuffer[xs] == 0) + FrameBuffer[(ActiveLine * FrameWidth) + xs] = vce.Palette[paletteBase + pixel]; + } + } + } + } + } + } + } + + private int FrameWidth = 256; + private int FrameHeight = 240; + private int[] FrameBuffer = new int[256 * 240]; + + public int[] GetVideoBuffer() + { + return FrameBuffer; + } + + public int BufferWidth + { + get { return FrameWidth; } + } + + public int BufferHeight + { + get { return FrameHeight; } + } + + public int BackgroundColor + { + get { return vce.Palette[256]; } + } + } +} diff --git a/BizHawk.Emulation/Consoles/PC Engine/VDC.cs b/BizHawk.Emulation/Consoles/PC Engine/VDC.cs new file mode 100644 index 0000000000..357aaa1290 --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/VDC.cs @@ -0,0 +1,331 @@ +using System; +using System.Globalization; +using System.IO; +using BizHawk.Emulation.CPUs.H6280; + +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + // HuC6270 Video Display Controller + + public sealed partial class VDC : IVideoProvider + { + public ushort[] VRAM = new ushort[0x8000]; + public ushort[] SpriteAttributeTable = new ushort[256]; + public byte[] PatternBuffer = new byte[0x20000]; + public byte[] SpriteBuffer = new byte[0x20000]; + public byte RegisterLatch; + public ushort[] Registers = new ushort[0x20]; + public ushort ReadBuffer; + public byte StatusByte; + + public ushort IncrementWidth + { + get + { + switch ((Registers[5] >> 11) & 3) + { + case 0: return 1; + case 1: return 32; + case 2: return 64; + case 3: return 128; + } + return 1; + } + } + + public bool BackgroundEnabled { get { return (Registers[CR] & 0x80) != 0; } } + public bool SpritesEnabled { get { return (Registers[CR] & 0x40) != 0; } } + public bool IntVerticalBlank { get { return (Registers[CR] & 0x08) != 0; } } + public bool IntRasterCompare { get { return (Registers[CR] & 0x04) != 0; } } + public bool IntSpriteOverflow { get { return (Registers[CR] & 0x02) != 0; } } + public bool IntSpriteCollision { get { return (Registers[CR] & 0x01) != 0; } } + + public int BatWidth { get { switch((Registers[MWR] >> 4) & 3) { case 0: return 32; case 1: return 64; default: return 128; } } } + public int BatHeight { get { return ((Registers[MWR] & 0x40) == 0) ? 32 : 64; } } + + public int RequestedFrameWidth { get { return ((Registers[HDR] & 0x3F) + 1) * 8; } } + public int RequestedFrameHeight { get { return ((Registers[VDW] & 0x1FF) + 1); } } + + public int DisplayStartLine { get { return (Registers[VPR] >> 8) + (Registers[VPR] & 0x1F); } } + + private const int MAWR = 0; // Memory Address Write Register + private const int MARR = 1; // Memory Address Read Register + private const int VRR = 2; // VRAM Read Register + private const int VWR = 2; // VRAM Write Register + private const int CR = 5; // Control Register + private const int RCR = 6; // Raster Compare Register + private const int BXR = 7; // Background X-scroll Register + private const int BYR = 8; // Background Y-scroll Register + private const int MWR = 9; // Memory-access Width Register + private const int HSR = 10; // Horizontal Sync Register + private const int HDR = 11; // Horizontal Display Register + private const int VPR = 12; // Vertical synchronous register + private const int VDW = 13; // Vertical display register + private const int VCR = 14; // Vertical display END position register; + private const int DCR = 15; // DMA Control Register + private const int SOUR = 16; // Source address for DMA + private const int DESR = 17; // Destination address for DMA + private const int LENR = 18; // Length of DMA transfer. Writing this will initiate DMA. + private const int SATB = 19; // Sprite Attribute Table base location in VRAM + + private const int RegisterSelect = 0; + private const int LSB = 2; + private const int MSB = 3; + + public const byte StatusVerticalBlanking = 0x20; + public const byte StatusVramVramDmaComplete = 0x10; + public const byte StatusVramSatDmaComplete = 0x08; + public const byte StatusRasterCompare = 0x04; + public const byte StatusSpriteOverflow = 0x02; + public const byte StatusSprite0Collision = 0x01; + + private HuC6280 cpu; + private VCE vce; + + public VDC(HuC6280 cpu, VCE vce) + { + this.cpu = cpu; + this.vce = vce; + } + + public void WriteVDC(int port, byte value) + { + cpu.PendingCycles--; + if (port == RegisterSelect) + { + RegisterLatch = (byte)(value & 0x1F); + Log.Note("CPU","LATCH VDC REGISTER: {0:X}",RegisterLatch); + } + else if (port == LSB) + { + Registers[RegisterLatch] &= 0xFF00; + Registers[RegisterLatch] |= value; + } + else if (port == MSB) + { + Registers[RegisterLatch] &= 0x00FF; + Registers[RegisterLatch] |= (ushort) (value << 8); + CompleteMSBWrite(); + } + } + + private void CompleteMSBWrite() + { + switch (RegisterLatch) + { + case MARR: // Memory Address Read Register + ReadBuffer = VRAM[Registers[MARR] & 0x7FFF]; + break; + case VWR: // VRAM Write Register + VRAM[Registers[MAWR] & 0x7FFF] = Registers[VWR]; + UpdatePatternData((ushort) (Registers[MAWR] & 0x7FFF)); + UpdateSpriteData((ushort) (Registers[MAWR] & 0x7FFF)); + Registers[MAWR] += IncrementWidth; + break; +case CR: +//if (Registers[CR] == 0) +Log.Note("CPU", "****************** WRITE TO CR: {0:X}", Registers[CR]); +break; + case BXR: + Registers[BXR] &= 0x3FF; + break; + case BYR: + Registers[BYR] &= 0x1FF; + BackgroundY = Registers[BYR]; + Console.WriteLine("Updating BYR to {0} at scanline {1}", BackgroundY, ScanLine); + break; + case HDR: // Horizontal Display Register - update framebuffer size + FrameWidth = RequestedFrameWidth; + if (FrameBuffer.Length != FrameWidth * FrameHeight) + { + FrameBuffer = new int[FrameWidth*FrameHeight]; + Console.WriteLine("RESIZED FRAME BUFFER: width="+FrameWidth); + } + break; + case VPR: + int vds = Registers[VPR] >> 8; + int vsw = Registers[VPR] & 0x1F; + Console.WriteLine("SET VPR: VDS {0} VSW {1} startpos={2} {3}",vds, vsw, vds+vsw, DisplayStartLine); + break; + case VDW: // Vertical Display Word? - update framebuffer size + Console.WriteLine("REQUEST FRAME HEIGHT=" + RequestedFrameHeight); + FrameHeight = RequestedFrameHeight; + if (FrameBuffer.Length != FrameWidth * FrameHeight) + { + FrameBuffer = new int[FrameWidth * FrameHeight]; + Console.WriteLine("RESIZED FRAME BUFFER: height="+FrameHeight); + } + break; + case VCR: + Console.WriteLine("VCR / END POSITION: "+(Registers[VCR] & 0xFF)); + break; + case LENR: // Initiate DMA transfer + InitiateDMA(); + break; + } + } + + public byte ReadVDC(int port) + { + cpu.PendingCycles--; + byte retval = 0; + switch (port) + { + case 0: // return status byte; + retval = StatusByte; + StatusByte = 0; // TODO maybe bit 6 should be preserved. but we dont currently emulate it. + cpu.IRQ1Assert = false; + return retval; + case 1: // unused + return 0; + case 2: // LSB + return (byte) (ReadBuffer & 0xFF); + case 3: // MSB + retval = (byte)(ReadBuffer >> 8); + if (RegisterLatch == VRR) + { + Registers[MARR] += IncrementWidth; + ReadBuffer = VRAM[Registers[MARR]&0x7FFF]; + } + return retval; + } + return 0; + } + + private void InitiateDMA() + { + Console.WriteLine("DOING DMA ********************************************* "); + int advanceSource = (Registers[DCR] & 4) == 0 ? +1 : -1; + int advanceDest = (Registers[DCR] & 8) == 0 ? +1 : -1; + + for (;Registers[LENR]<0xFFFF;Registers[LENR]--) + { + VRAM[Registers[DESR] & 0x7FFF] = VRAM[Registers[SOUR] & 0x7FFF]; + UpdatePatternData(Registers[DESR]); + UpdateSpriteData(Registers[DESR]); + Registers[DESR] = (ushort)(Registers[DESR] + advanceDest); + Registers[SOUR] = (ushort)(Registers[SOUR] + advanceSource); + } + } + + public void UpdatePatternData(ushort addr) + { + int tileNo = (addr >> 4); + int tileLineOffset = (addr & 0x7); + + int bitplane01 = VRAM[(tileNo * 16) + tileLineOffset]; + int bitplane23 = VRAM[(tileNo * 16) + tileLineOffset + 8]; + + int patternBufferBase = (tileNo * 64) + (tileLineOffset * 8); + + for (int x = 0; x < 8; x++) + { + byte pixel = (byte) ((bitplane01 >> x) & 1); + pixel |= (byte) (((bitplane01 >> (x + 8)) & 1) << 1); + pixel |= (byte) (((bitplane23 >> x) & 1) << 2); + pixel |= (byte) (((bitplane23 >> (x + 8)) & 1) << 3); + PatternBuffer[patternBufferBase + (7 - x)] = pixel; + } + } + + public void UpdateSpriteData(ushort addr) + { + int tileNo = addr >> 6; + int tileOfs = addr & 0x3F; + int bitplane = tileOfs/16; + int line = addr & 0x0F; + + int ofs = (tileNo*256) + (line*16) + 15; + ushort value = VRAM[addr]; + byte bitAnd = (byte) (~(1 << bitplane)); + byte bitOr = (byte) (1 << bitplane); + + for (int i=0; i<16; i++) + { + + if ((value & 1) == 1) + SpriteBuffer[ofs] |= bitOr; + else + SpriteBuffer[ofs] &= bitAnd; + ofs--; + value >>= 1; + } + } + + public void SaveStateText(TextWriter writer, int vdcNo) + { + writer.WriteLine("[VDC"+vdcNo+"]"); + writer.Write("VRAM "); + VRAM.SaveAsHex(writer); + writer.Write("SAT "); + SpriteAttributeTable.SaveAsHex(writer); + writer.Write("Registers "); + Registers.SaveAsHex(writer); + + writer.WriteLine("RegisterLatch {0:X2}", RegisterLatch); + writer.WriteLine("ReadBuffer {0:X4}", ReadBuffer); + writer.WriteLine("StatusByte {0:X2}", StatusByte); + writer.WriteLine("[/VDC"+vdcNo+"]\n"); + } + + public void LoadStateText(TextReader reader, int vdcNo) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/VDC"+vdcNo+"]") break; + if (args[0] == "VRAM") + VRAM.ReadFromHex(args[1]); + else if (args[0] == "SAT") + SpriteAttributeTable.ReadFromHex(args[1]); + else if (args[0] == "Registers") + Registers.ReadFromHex(args[1]); + else if (args[0] == "RegisterLatch") + RegisterLatch = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ReadBuffer") + ReadBuffer = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "StatusByte") + StatusByte = byte.Parse(args[1], NumberStyles.HexNumber); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + + for (ushort i = 0; i < VRAM.Length; i++) + { + UpdatePatternData(i); + UpdateSpriteData(i); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + for (int i=0; i < VRAM.Length; i++) + writer.Write(VRAM[i]); + for (int i=0; i < SpriteAttributeTable.Length; i++) + writer.Write(SpriteAttributeTable[i]); + for (int i = 0; i < Registers.Length; i++) + writer.Write(Registers[i]); + writer.Write(RegisterLatch); + writer.Write(ReadBuffer); + writer.Write(StatusByte); + } + + public void LoadStateBinary(BinaryReader reader) + { + for (ushort i=0; i < VRAM.Length; i++) + { + VRAM[i] = reader.ReadUInt16(); + UpdatePatternData(i); + UpdateSpriteData(i); + } + for (int i=0; i < SpriteAttributeTable.Length; i++) + SpriteAttributeTable[i] = reader.ReadUInt16(); + for (int i=0; i < Registers.Length; i++) + Registers[i] = reader.ReadUInt16(); + RegisterLatch = reader.ReadByte(); + ReadBuffer = reader.ReadUInt16(); + StatusByte = reader.ReadByte(); + } + } +} diff --git a/BizHawk.Emulation/Consoles/PC Engine/VPC.cs b/BizHawk.Emulation/Consoles/PC Engine/VPC.cs new file mode 100644 index 0000000000..df461fc0fa --- /dev/null +++ b/BizHawk.Emulation/Consoles/PC Engine/VPC.cs @@ -0,0 +1,466 @@ +using System; +using System.IO; +using BizHawk.Emulation.CPUs.H6280; + +namespace BizHawk.Emulation.Consoles.TurboGrafx +{ + // ------------------------------------------------------ + // HuC6202 Video Priority Controller + // ------------------------------------------------------ + // Responsible for merging VDC1 and VDC2 data on the SuperGrafx. + // Pretty much all documentation on the SuperGrafx courtesy of Charles MacDonald. + + // VPC Frame timing has not been updated with new stuff. I expect Madoo Granzort to be fixed once the timing is updated. + // However, 1) The new frame timing is not working 100% yet, 2) I haven't decided if I want to continue having separate + // rendering in the VPC and the VDC. + + public sealed class VPC : IVideoProvider + { + public VDC VDC1; + public VDC VDC2; + public VCE VCE; + private HuC6280 CPU; + + public byte[] Registers = {0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00}; + + public int Window1Width { get { return ((Registers[3] & 3) << 8) | Registers[2]; } } + public int Window2Width { get { return ((Registers[5] & 3) << 8) | Registers[4]; } } + public int PriorityModeSlot0 { get { return Registers[0] & 0x0F; } } + public int PriorityModeSlot1 { get { return (Registers[0] >> 4) & 0x0F; } } + public int PriorityModeSlot2 { get { return Registers[1] & 0x0F; } } + public int PriorityModeSlot3 { get { return (Registers[1] >> 4) & 0x0F; } } + + public VPC(VDC vdc1, VDC vdc2, VCE vce, HuC6280 cpu) + { + VDC1 = vdc1; + VDC2 = vdc2; + VCE = vce; + CPU = cpu; + + // latch initial video buffer + FrameBuffer = vdc1.GetVideoBuffer(); + FrameWidth = vdc1.BufferWidth; + FrameHeight = vdc1.BufferHeight; + } + + public byte ReadVPC(int port) + { + switch (port) + { + case 0x08: return Registers[0]; + case 0x09: return Registers[1]; + case 0x0A: return Registers[2]; + case 0x0B: return Registers[3]; + case 0x0C: return Registers[4]; + case 0x0D: return Registers[5]; + case 0x0E: return Registers[6]; + case 0x0F: return 0; + default: return 0xFF; + } + } + + public void WriteVPC(int port, byte value) + { + switch (port) + { + case 0x08: Registers[0] = value; break; + case 0x09: Registers[1] = value; break; + case 0x0A: Registers[2] = value; break; + case 0x0B: Registers[3] = value; break; + case 0x0C: Registers[4] = value; break; + case 0x0D: Registers[5] = value; break; + case 0x0E: + // CPU Store Immediate VDC Select + CPU.WriteVDC = (value & 1) == 0 ? (Action) VDC1.WriteVDC : VDC2.WriteVDC; + Registers[6] = value; + break; + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(Registers); + } + + public void LoadStateBinary(BinaryReader reader) + { + Registers = reader.ReadBytes(7); + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[VPC]"); + writer.Write("Registers "); + Registers.SaveAsHex(writer); + writer.WriteLine("[/VPC]\n"); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/VPC]") break; + if (args[0] == "Registers") + Registers.ReadFromHex(args[1]); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + // We use a single priority mode for the whole frame. + // No commercial SGX games really use the 'window' features AFAIK. + // And there are no homebrew SGX games I know of. + + private const int BXR = 7; + private const int BYR = 8; + + private int EffectivePriorityMode = 0; + + private int FrameHeight; + private int FrameWidth; + private int[] FrameBuffer; + + private byte[] PriorityBuffer = new byte[512]; + private byte[] InterSpritePriorityBuffer = new byte[512]; + + public void ExecFrame() + { + // Determine the effective priority mode. + if (Window1Width < 0x40 && Window2Width < 0x40) + EffectivePriorityMode = PriorityModeSlot3 >> 2; + else if (Window2Width > 512) + EffectivePriorityMode = PriorityModeSlot1 >> 2; + else + { + Console.WriteLine("Unsupported VPC window settings"); + EffectivePriorityMode = 0; + } + + // Latch frame dimensions and framebuffer, for purely dumb reasons + FrameWidth = VDC1.BufferWidth; + FrameHeight = VDC1.BufferHeight; + FrameBuffer = VDC1.GetVideoBuffer(); + + for (int ScanLine = 0; ScanLine < 262; ScanLine++) + { + VDC1.ScanLine = ScanLine; + VDC2.ScanLine = ScanLine; + + if ((ScanLine + 64) == (VDC1.Registers[6] & 0x3FF)) + { + if (VDC1.IntRasterCompare) + { + VDC1.StatusByte |= VDC.StatusRasterCompare; + CPU.IRQ1Assert = true; + } + } + + if ((ScanLine + 64) == (VDC2.Registers[6] & 0x3FF)) + { + if (VDC2.IntRasterCompare) + { + VDC2.StatusByte |= VDC.StatusRasterCompare; + CPU.IRQ1Assert = true; + } + } + + if (ScanLine == 240 && VDC1.IntVerticalBlank) + { + VDC1.StatusByte |= VDC.StatusVerticalBlanking; + CPU.IRQ1Assert = true; + } + + if (ScanLine == 240 && VDC2.IntVerticalBlank) + { + VDC2.StatusByte |= VDC.StatusVerticalBlanking; + CPU.IRQ1Assert = true; + } + + CPU.Execute(455); + + if (ScanLine < FrameHeight) + RenderScanLine(); + } + } + + private void RenderScanLine() + { + if (VDC1.ScanLine == 0) + { + VDC1.BackgroundY = VDC1.Registers[BYR]; + VDC2.BackgroundY = VDC2.Registers[BYR]; + } + + InitializeScanLine(VDC1.ScanLine); + + switch (EffectivePriorityMode) + { + case 0: + RenderBackgroundScanline(VDC1, 12); + RenderBackgroundScanline(VDC2, 2); + RenderSpritesScanline(VDC1, 11, 14); + RenderSpritesScanline(VDC2, 1, 3); + break; + case 1: + RenderBackgroundScanline(VDC1, 12); + RenderBackgroundScanline(VDC2, 2); + RenderSpritesScanline(VDC1, 11, 14); + RenderSpritesScanline(VDC2, 1, 13); + break; + } + + if (VDC1.ScanLine == FrameHeight - 1) + { + VDC1.UpdateSpriteAttributeTable(); + VDC2.UpdateSpriteAttributeTable(); + } + } + + private void InitializeScanLine(int scanline) + { + // Clear priority buffer + for (int i = 0; i < FrameWidth; i++) + PriorityBuffer[i] = 0; + + // Initialize scanline to background color + for (int i = 0; i < FrameWidth; i++) + FrameBuffer[(scanline * FrameWidth) + i] = VCE.Palette[0]; + } + + private void RenderBackgroundScanline(VDC vdc, byte priority) + { + if (vdc.BackgroundEnabled == false) + { + vdc.BackgroundY++; + vdc.BackgroundY &= 0x01FF; + return; + } + + int vertLine = vdc.BackgroundY; + vertLine %= vdc.BatHeight * 8; + int yTile = (vertLine / 8); + int yOfs = vertLine % 8; + vdc.BackgroundY++; + vdc.BackgroundY &= 0x01FF; + + int xScroll = vdc.Registers[BXR] & 0x3FF; + for (int x = 0; x < FrameWidth; x++) + { + if (PriorityBuffer[x] >= priority) continue; + int xTile = ((x + xScroll) / 8) % vdc.BatWidth; + int xOfs = (x + xScroll) & 7; + int tileNo = vdc.VRAM[(ushort)(((yTile * vdc.BatWidth) + xTile))] & 2047; + int paletteNo = vdc.VRAM[(ushort)(((yTile * vdc.BatWidth) + xTile))] >> 12; + int paletteBase = paletteNo * 16; + + byte c = vdc.PatternBuffer[(tileNo * 64) + (yOfs * 8) + xOfs]; + if (c != 0) + { + FrameBuffer[(vdc.ScanLine * FrameWidth) + x] = VCE.Palette[paletteBase + c]; + PriorityBuffer[x] = priority; + } + } + } + + private static byte[] heightTable = { 16, 32, 64, 64 }; + + private void RenderSpritesScanline(VDC vdc, byte lowPriority, byte highPriority) + { + if (vdc.SpritesEnabled == false) + return; + + // clear inter-sprite priority buffer + for (int i = 0; i < FrameWidth; i++) + InterSpritePriorityBuffer[i] = 0; + + for (int i = 0; i < 64; i++) + { + int y = (vdc.SpriteAttributeTable[(i * 4) + 0] & 1023) - 64; + int x = (vdc.SpriteAttributeTable[(i * 4) + 1] & 1023) - 32; + ushort flags = vdc.SpriteAttributeTable[(i * 4) + 3]; + int height = heightTable[(flags >> 12) & 3]; + + if (y + height <= vdc.ScanLine || y > vdc.ScanLine) + continue; + + int patternNo = (((vdc.SpriteAttributeTable[(i * 4) + 2]) >> 1) & 0x1FF); + int paletteBase = 256 + ((flags & 15) * 16); + int width = (flags & 0x100) == 0 ? 16 : 32; + bool priority = (flags & 0x80) != 0; + bool hflip = (flags & 0x0800) != 0; + bool vflip = (flags & 0x8000) != 0; + + if (width == 32) + patternNo &= 0x1FE; + + int yofs = 0; + if (vflip == false) + { + yofs = (vdc.ScanLine - y) & 15; + if (height == 32) + { + patternNo &= 0x1FD; + if (vdc.ScanLine - y >= 16) + { + y += 16; + patternNo += 2; + } + } + else if (height == 64) + { + patternNo &= 0x1F9; + if (vdc.ScanLine - y >= 48) + { + y += 48; + patternNo += 6; + } + else if (vdc.ScanLine - y >= 32) + { + y += 32; + patternNo += 4; + } + else if (vdc.ScanLine - y >= 16) + { + y += 16; + patternNo += 2; + } + } + } + else // vflip == true + { + yofs = 15 - ((vdc.ScanLine - y) & 15); + if (height == 32) + { + patternNo &= 0x1FD; + if (vdc.ScanLine - y < 16) + { + y += 16; + patternNo += 2; + } + } + else if (height == 64) + { + patternNo &= 0x1F9; + if (vdc.ScanLine - y < 16) + { + y += 48; + patternNo += 6; + } + else if (vdc.ScanLine - y < 32) + { + y += 32; + patternNo += 4; + } + else if (vdc.ScanLine - y < 48) + { + y += 16; + patternNo += 2; + } + } + } + if (hflip == false) + { + if (x + width > 0 && y + height > 0) + { + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = vdc.SpriteBuffer[(patternNo * 256) + (yofs * 16) + (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + byte myPriority = priority ? highPriority : lowPriority; + if (PriorityBuffer[xs] < myPriority) + { + FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; + PriorityBuffer[xs] = myPriority; + } + } + } + } + if (width == 32) + { + patternNo++; + x += 16; + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = vdc.SpriteBuffer[(patternNo * 256) + (yofs * 16) + (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + byte myPriority = priority ? highPriority : lowPriority; + if (PriorityBuffer[xs] < myPriority) + { + FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; + PriorityBuffer[xs] = myPriority; + } + } + } + } + } + else + { // hflip = true + if (x + width > 0 && y + height > 0) + { + if (width == 32) + patternNo++; + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = vdc.SpriteBuffer[(patternNo * 256) + (yofs * 16) + 15 - (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + byte myPriority = priority ? highPriority : lowPriority; + if (PriorityBuffer[xs] < myPriority) + { + FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; + PriorityBuffer[xs] = myPriority; + } + } + } + if (width == 32) + { + patternNo--; + x += 16; + for (int xs = x >= 0 ? x : 0; xs < x + 16 && xs >= 0 && xs < FrameWidth; xs++) + { + byte pixel = vdc.SpriteBuffer[(patternNo * 256) + (yofs * 16) + 15 - (xs - x)]; + if (pixel != 0 && InterSpritePriorityBuffer[xs] == 0) + { + InterSpritePriorityBuffer[xs] = 1; + byte myPriority = priority ? highPriority : lowPriority; + if (PriorityBuffer[xs] < myPriority) + { + FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; + PriorityBuffer[xs] = myPriority; + } + } + } + } + } + } + } + } + + public int[] GetVideoBuffer() + { + return FrameBuffer; + } + + public int BufferWidth + { + get { return FrameWidth; } + } + + public int BufferHeight + { + get { return FrameHeight; } + } + + public int BackgroundColor + { + get { return VCE.Palette[0]; } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.DMA.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.DMA.cs new file mode 100644 index 0000000000..46a4cab1d5 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.DMA.cs @@ -0,0 +1,73 @@ +using System; + +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class GenVDP + { + // TODO: make this a requirement of constructor? + public Func DmaReadFrom68000; // TODO make ushort + + public int DmaLength { get { return Registers[19] | (Registers[20] << 8); } } + + public int DmaSource + { + get + { + if ((Registers[23] & 0x80) == 0) // 68000 -> VRAM copy mode + return ((Registers[21] << 1) | (Registers[22] << 9) | (Registers[23] << 17)) & 0xFFFFFE; + + // Else VRAM/VRAM copy mode + return (Registers[21] | (Registers[22] << 8)) & 0xFFFFFE; + } + } + + + private bool DmaFillModePending; + + private void ExecuteDmaFill(ushort data) + { + Console.WriteLine("DMA FILL REQD, WRITE {0:X4}, {1:X4} times, at {2:X4}", data, DmaLength, VdpDataAddr); + + // TODO: Is the address really VdpDataAddr and not DMA source? I guess that makes sense. + // TODO: It should spread this out, not do it all at once. + // TODO: DMA can go to places besides just VRAM (eg CRAM, VSRAM) + // TODO: Does DMA fill really use the actual increment register value? + + int length = DmaLength; + if (length == 0) + length = 0x10000; // Really necessary? + + byte fillByte = (byte)(data >> 8); + + do + { + VRAM[VdpDataAddr & 0xFFFF] = fillByte; + UpdatePatternBuffer(VdpDataAddr & 0xFFFF); + VdpDataAddr += Registers[15]; + } while (--length > 0); + + DmaFillModePending = false; + } + + private void Execute68000VramCopy() + { + Console.WriteLine("DMA 68000 -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource); + + int length = DmaLength; + if (length == 0) + length = 0x10000; + + int source = DmaSource; + + do + { + ushort value = (ushort) DmaReadFrom68000(source); + source += 2; + // TODO funky source behavior + WriteVdpData(value); + } while (--length > 0); + + // TODO: find correct number of 68k cycles to burn + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs new file mode 100644 index 0000000000..e8c7260f30 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.Render.cs @@ -0,0 +1,113 @@ +using System; + +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class GenVDP + { + public void RenderLine() + { + if (ScanLine == 223) + { + for (int i = 0; i < FrameBuffer.Length; i++) + FrameBuffer[i] = 0; + + //RenderPatterns(); + RenderPalette(); + RenderScrollA(); + RenderScrollB(); + RenderSprites(); + } + } + + private void RenderPalette() + { + for (int p = 0; p < 4; p++) + for (int i = 0; i < 16; i++) + FrameBuffer[(p*FrameWidth) + i] = Palette[(p*16) + i]; + } + + private void RenderPatterns() + { + for (int yi=0; yi<28; yi++) + for (int xi=0; xi<(Display40Mode?40:32); xi++) + RenderPattern(xi * 8, yi * 8, (yi * (Display40Mode ? 40 : 32)) + xi, 0); + } + + private void RenderPattern(int x, int y, int pattern, int palette) + { + for (int yi = 0; yi < 8; yi++) + { + for (int xi = 0; xi < 8; xi++) + { + byte c = PatternBuffer[(pattern*64) + (yi*8) + xi]; + if (c != 0) + FrameBuffer[((y + yi)*FrameWidth) + xi + x] = Palette[(palette*16) + c]; + } + } + } + + private void RenderScrollA() + { + for (int yc=0; yc<24; yc++) + { + for (int xc=0; xc<32; xc++) + { + int cellOfs = NameTableAddrA + (yc*NameTableWidth*2) + (xc*2); + int info = (VRAM[cellOfs+1] << 8) | VRAM[cellOfs]; + int pattern = info & 0x7FF; + int palette = (info >> 13) & 3; + RenderPattern(xc*8, yc*8, pattern,palette); + } + } + } + + private void RenderScrollB() + { + for (int yc = 0; yc < 24; yc++) + { + for (int xc = 0; xc < 40; xc++) + { + int cellOfs = NameTableAddrB + (yc * NameTableWidth * 2) + (xc * 2); + int info = (VRAM[cellOfs+1] << 8) | VRAM[cellOfs]; + int pattern = info & 0x7FF; + int palette = (info >> 13) & 3; + RenderPattern(xc * 8, yc * 8, pattern, palette); + } + } + } + + + private void RenderSprites() + { + Sprite sprite = FetchSprite(0); + /*if (sprite.X > 0) + Console.WriteLine("doot");*/ + } + + private Sprite FetchSprite(int spriteNo) + { + int satbase = SpriteAttributeTableAddr + (spriteNo*8); + Sprite sprite = new Sprite(); + sprite.Y = (VRAM[satbase + 1] | (VRAM[satbase + 0] << 8) & 0x3FF) - 128; + sprite.X = (VRAM[satbase + 7] | (VRAM[satbase + 6] << 8) & 0x3FF) - 128; + sprite.Width = ((VRAM[satbase + 2] >> 2) & 3) + 1; + sprite.Height = (VRAM[satbase + 2] & 3) + 1; + sprite.Link = VRAM[satbase + 3] & 0x7F; + sprite.PatternIndex = VRAM[satbase + 5] | (VRAM[satbase + 6] << 8) & 0x7FF; + sprite.Palette = (VRAM[satbase + 5] >> 5) & 3; + return sprite; + } + + + struct Sprite + { + public int X, Y; + public int Width, Height; + public int Link; + public int Palette; + public int PatternIndex; + } + } + + +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs new file mode 100644 index 0000000000..2f05bdde81 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs @@ -0,0 +1,264 @@ +using System; + +namespace BizHawk.Emulation.Consoles.Sega +{ + public sealed partial class GenVDP : IVideoProvider + { + // Memory + public byte[] VRAM = new byte[0x10000]; + public ushort[] CRAM = new ushort[64]; + public ushort[] VSRAM = new ushort[40]; + public byte[] Registers = new byte[0x20]; + + public byte[] PatternBuffer = new byte[0x20000]; + public int[] Palette = new int[64]; + public int[] FrameBuffer = new int[256*224]; + public int FrameWidth = 256; + + public int ScanLine; + + public bool HInterruptsEnabled { get { return (Registers[0] & 0x10) != 0; } } + public bool DisplayEnabled { get { return (Registers[1] & 0x40) != 0; } } + public bool VInterruptEnabled { get { return (Registers[1] & 0x20) != 0; } } + public bool DmaEnabled { get { return (Registers[1] & 0x10) != 0; } } + public bool CellBasedVertScroll { get { return (Registers[11] & 0x08) != 0; } } + public bool Display40Mode { get { return (Registers[12] & 0x81) != 0; } } + + private ushort NameTableAddrA; + private ushort NameTableAddrB; + private ushort NameTableAddrWindow; + private ushort SpriteAttributeTableAddr; + private ushort HScrollTableAddr; + private byte NameTableWidth; + private byte NameTableHeight; + + private bool ControlWordPending; + private ushort VdpDataAddr; + private byte VdpDataCode; + + private static readonly byte[] PalXlatTable = { 0, 0, 36, 36, 73, 73, 109, 109, 145, 145, 182, 182, 219, 219, 255, 255 }; + + public void WriteVdpControl(ushort data) + { + Console.WriteLine("[PC = {0:X6}] VDP: Control Write {1:X4}", /*Genesis._MainCPU.PC*/0, data); + + if (ControlWordPending == false) + { + if ((data & 0xC000) == 0x8000) + { + int reg = (data >> 8) & 0x1F; + byte value = (byte) (data & 0xFF); + WriteVdpRegister(reg, value); + VdpDataCode = 0; // should we just clone GenesisPlus behavior? + } else { + ControlWordPending = true; + VdpDataAddr &= 0xC000; + VdpDataAddr |= (ushort) (data & 0x3FFF); + VdpDataCode &= 0x3C; + VdpDataCode |= (byte) (data >> 14); + Console.WriteLine("Address = {0:X4}", VdpDataAddr); + Console.WriteLine("Code = {0:X2}", VdpDataCode); + } + } else { + ControlWordPending = false; + + // Update data address and code + VdpDataAddr &= 0x3FFF; + VdpDataAddr |= (ushort) ((data & 0x03) << 14); + Console.WriteLine("Address = {0:X4}", VdpDataAddr); + VdpDataCode &= 0x03; + VdpDataCode |= (byte) ((data >> 2) & 0x3C); + Console.WriteLine("Code = {0:X2}", VdpDataCode); + + if ((VdpDataCode & 0x20) != 0 && DmaEnabled) // DMA triggered + { + Console.WriteLine("DMA TIME!"); + + // what type of DMA? + switch (Registers[23] >> 6) + { + case 2: + Console.WriteLine("VRAM FILL"); + DmaFillModePending = true; + break; + case 3: + Console.WriteLine("VRAM COPY **** UNIMPLEMENTED ***"); + break; + default: + Console.WriteLine("68k->VRAM COPY **** UNIMPLEMENTED ***"); + Execute68000VramCopy(); + break; + } + Console.WriteLine("DMA LEN = "+DmaLength); + } + } + } + + public ushort ReadVdpControl() + { + Console.WriteLine("VDP: Control Read"); + ushort value = 0; + value |= 0x8000; // Fifo empty + return value; + } + + public void WriteVdpData(ushort data) + { + ControlWordPending = false; + + // byte-swap incoming data when A0 is set + if ((VdpDataAddr & 1) != 0) + data = (ushort) ((data >> 8) | (data << 8)); + + if (DmaFillModePending) + { + ExecuteDmaFill(data); + } + + switch (VdpDataCode & 7) + { + case 1: // VRAM Write + VRAM[VdpDataAddr & 0xFFFE] = (byte) data; + VRAM[(VdpDataAddr & 0xFFFE) + 1] = (byte) (data >> 8); + UpdatePatternBuffer(VdpDataAddr & 0xFFFE); + UpdatePatternBuffer((VdpDataAddr & 0xFFFE) + 1); + Console.WriteLine("Wrote VRAM[{0:X4}] = {1:X4}", VdpDataAddr, data); + VdpDataAddr += Registers[0x0F]; + break; + case 3: // CRAM write + CRAM[(VdpDataAddr / 2) % 64] = data; + Console.WriteLine("Wrote CRAM[{0:X2}] = {1:X4}", (VdpDataAddr / 2) % 64, data); + ProcessPalette((VdpDataAddr/2)%64); + VdpDataAddr += Registers[0x0F]; + break; + case 5: // VSRAM write + VSRAM[(VdpDataAddr / 2) % 40] = data; + Console.WriteLine("Wrote VSRAM[{0:X2}] = {1:X4}", (VdpDataAddr / 2) % 40, data); + VdpDataAddr += Registers[0x0F]; + break; + default: + Console.WriteLine("VDP DATA WRITE WITH UNHANDLED CODE!!!"); + break; + } + } + + public ushort ReadVdpData() + { + Console.WriteLine("VDP: Data Read"); + return 0; + } + + public void WriteVdpRegister(int register, byte data) + { + Console.WriteLine("Register {0}: {1:X2}", register, data); + switch (register) + { + case 0x00: + Registers[register] = data; + Console.WriteLine("HINT enabled: "+ HInterruptsEnabled); + break; + case 0x01: + Registers[register] = data; + Console.WriteLine("DmaEnabled: "+DmaEnabled); + Console.WriteLine("VINT enabled: " + VInterruptEnabled); + break; + case 0x02: // Name Table Address for Layer A + NameTableAddrA = (ushort) ((data & 0x38) << 10); + Console.WriteLine("SET NTa A = {0:X4}",NameTableAddrA); + break; + case 0x03: // Name Table Address for Window + NameTableAddrWindow = (ushort) ((data & 0x3E) << 10); + Console.WriteLine("SET NTa W = {0:X4}", NameTableAddrWindow); + break; + case 0x04: // Name Table Address for Layer B + NameTableAddrB = (ushort) (data << 13); + Console.WriteLine("SET NTa B = {0:X4}", NameTableAddrB); + break; + case 0x05: // Sprite Attribute Table Address + SpriteAttributeTableAddr = (ushort) (data << 9); + Console.WriteLine("SET SAT attr = {0:X4}", SpriteAttributeTableAddr); + break; + case 0x0C: // Mode Set #4 + // TODO interlaced modes + if ((data & 0x81) == 0) + { + // Display is 32 cells wide + if (FrameWidth != 256) + { + FrameBuffer = new int[256*224]; + FrameWidth = 256; + Console.WriteLine("SWITCH TO 32 CELL WIDE MODE"); + } + } else { + // Display is 40 cells wide + if (FrameWidth != 320) + { + FrameBuffer = new int[320*224]; + FrameWidth = 320; + Console.WriteLine("SWITCH TO 40 CELL WIDE MODE"); + } + } + break; + case 0x0D: // H Scroll Table Address + HScrollTableAddr = (ushort) (data << 10); + Console.WriteLine("SET HScrollTab attr = {0:X4}", HScrollTableAddr); + break; + case 0x0F: + Console.WriteLine("Set Data Increment to "+data); + break; + case 0x10: + switch (data & 0x03) + { + case 0: NameTableWidth = 32; break; + case 1: NameTableWidth = 64; break; + case 2: NameTableWidth = 32; break; // invalid setting + case 3: NameTableWidth = 128; break; + } + switch ((data>>4) & 0x03) + { + case 0: NameTableHeight = 32; break; + case 1: NameTableHeight = 64; break; + case 2: NameTableHeight = 32; break; // invalid setting + case 3: NameTableHeight = 128; break; + } + Console.WriteLine("Name Table Dimensions set to {0}x{1}", NameTableWidth, NameTableHeight); + break; + } + Registers[register] = data; + } + + private void ProcessPalette(int slot) + { + byte r = PalXlatTable[(CRAM[slot] & 0x000F) >> 0]; + byte g = PalXlatTable[(CRAM[slot] & 0x00F0) >> 4]; + byte b = PalXlatTable[(CRAM[slot] & 0x0F00) >> 8]; + Palette[slot] = Colors.ARGB(r, g, b); + } + + private void UpdatePatternBuffer(int addr) + { + PatternBuffer[(addr*2) + 1] = (byte) (VRAM[addr^1] & 0x0F); + PatternBuffer[(addr*2) + 0] = (byte) (VRAM[addr^1] >> 4); + } + + public int[] GetVideoBuffer() + { + return FrameBuffer; + } + + public int BufferWidth + { + get { return FrameWidth; } + } + + public int BufferHeight + { + get { return 224; } + } + + public int BackgroundColor + { + get { return Palette[Registers[7] & 0x3F]; } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.Input.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.Input.cs new file mode 100644 index 0000000000..f36c4a015b --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.Input.cs @@ -0,0 +1,18 @@ +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class Genesis + { + public static readonly ControllerDefinition GenesisController = new ControllerDefinition + { + Name = "Genesis 3-Button Controller", + BoolButtons = + { + "Reset", + "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 A", "P1 B", "P1 C", "P1 Start" + } + }; + + public ControllerDefinition ControllerDefinition { get { return GenesisController; } } + public IController Controller { get; set; } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs new file mode 100644 index 0000000000..9399053062 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs @@ -0,0 +1,191 @@ +using System; +using System.IO; +using BizHawk.Emulation.CPUs.M68K; +using BizHawk.Emulation.CPUs.Z80; +using BizHawk.Emulation.Sound; +using MC68000; + +namespace BizHawk.Emulation.Consoles.Sega +{ + public sealed partial class Genesis : IEmulator, IMemoryController + { + // ROM + public byte[] RomData; + + // Machine stuff + public MC68K MainCPU; // TODO un-static + public M68000 _MainCPU; + public Z80A SoundCPU; + public GenVDP VDP; + public SN76489 PSG; + public YM2612 YM2612; + public byte[] Ram = new byte[0x10000]; + public byte[] Z80Ram = new byte[0x2000]; + + private bool M68000HasZ80Bus = false; + private bool Z80Reset = false; + private bool Z80Runnable { get { return (Z80Reset == false && M68000HasZ80Bus == false); } } + + private SoundMixer SoundMixer; + + // Genesis timings: + // 53,693,175 Machine clocks / sec + // 7,670,454 Main 68000 cycles / sec (7 mclk divisor) + // 3,579,545 Z80 cycles / sec (15 mclk divisor) + + // At 59.92 FPS: + // 896,081 mclks / frame + // 128,011 Main 68000 cycles / frame + // 59,738 Z80 cycles / frame + + // At 262 lines/frame: + // 3420 mclks / line + // ~ 488.5 Main 68000 cycles / line + // 228 Z80 cycles / line + + // Video characteristics: + // 224 lines are active display. The remaining 38 lines are vertical blanking. + // In H40 mode, the dot clock is 480 pixels per line. + // 320 are active display, the remaining 160 are horizontal blanking. + // A total of 3420 mclks per line, but 2560 mclks are active display and 860 mclks are blanking. + + public Genesis(bool sega360) + { + if (sega360) MainCPU = new MC68K(this); + _MainCPU = new M68000(); + SoundCPU = new Z80A(); + YM2612 = new YM2612(); + PSG = new SN76489(); + VDP = new GenVDP(); + VDP.DmaReadFrom68000 = ReadW; + SoundMixer = new SoundMixer(YM2612, PSG); + + _MainCPU.ReadByte = ReadB; + _MainCPU.ReadWord = ReadW; + _MainCPU.ReadLong = ReadL; + _MainCPU.WriteByte = WriteB; + _MainCPU.WriteWord = WriteW; + _MainCPU.WriteLong = WriteL; + + SoundCPU.ReadMemory = ReadMemoryZ80; + SoundCPU.WriteMemory = WriteMemoryZ80; + SoundCPU.WriteHardware = (a, v) => { Console.WriteLine("Z80: Attempt I/O Write {0:X2}:{1:X2}", a, v); }; + SoundCPU.ReadHardware = x => 0xFF; + SoundCPU.IRQCallback = () => SoundCPU.Interrupt = false; + Z80Reset = true; + } + + public void LoadGame(IGame game) + { + RomData = new byte[0x400000]; + byte[] rom = game.GetRomData(); + for (int i = 0; i < rom.Length; i++) + RomData[i] = rom[i]; + + if (MainCPU != null) MainCPU.Reset(); + _MainCPU.Reset(); + } + + public void StepMine() + { + _MainCPU.Exec(); + } + + public void StepHis() + { + MainCPU.Step(); + } + + public void FrameAdvance(bool render) + { + Frame++; + PSG.BeginFrame(SoundCPU.TotalExecutedCycles); + for (VDP.ScanLine = 0; VDP.ScanLine < 262; VDP.ScanLine++) + { + Console.WriteLine("Frame {0} ScanLine {1}", Frame, VDP.ScanLine); + + if (VDP.ScanLine < 224) + VDP.RenderLine(); + + MainCPU.Execute(488); + if (Z80Runnable) + { + //Console.WriteLine("running z80"); + SoundCPU.ExecuteCycles(228); + SoundCPU.Interrupt = false; + } + + if (VDP.ScanLine == 224) + { + // End-frame stuff + if (VDP.VInterruptEnabled) + MainCPU.Interrupt(6); + + if (Z80Runnable) + SoundCPU.Interrupt = true; + } + } + PSG.EndFrame(SoundCPU.TotalExecutedCycles); + } + + public IVideoProvider VideoProvider + { + get { return VDP; } + } + + public ISoundProvider SoundProvider + { + get { return SoundMixer; } + } + + public int Frame { get; set; } + public bool DeterministicEmulation { get; set; } + + public void HardReset() + { + throw new NotImplementedException(); + } + + public byte[] SaveRam + { + get { throw new NotImplementedException(); } + } + + public bool SaveRamModified + { + get + { + return false; // TODO implement + } + set + { + throw new NotImplementedException(); + } + } + + public void SaveStateText(TextWriter writer) + { + throw new NotImplementedException(); + } + + public void LoadStateText(TextReader reader) + { + throw new NotImplementedException(); + } + + public void SaveStateBinary(BinaryWriter writer) + { + throw new NotImplementedException(); + } + + public void LoadStateBinary(BinaryReader reader) + { + throw new NotImplementedException(); + } + + public byte[] SaveStateBinary() + { + return new byte[0]; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/IO.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/IO.cs new file mode 100644 index 0000000000..cc55ab5aab --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/IO.cs @@ -0,0 +1,35 @@ +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class Genesis + { + // todo ??????? + public bool SegaCD = false; + + public int ReadIO(int offset) + { + int value; + switch (offset) + { + case 0: // version + value = SegaCD ? 0x00 : 0x20; + switch((char)RomData[0x01F0]) + { + case 'J': value |= 0x00; break; + case 'U': value |= 0x80; break; + case 'E': value |= 0xC0; break; + case 'A': value |= 0xC0; break; + case '4': value |= 0x80; break; + default: value |= 0x80; break; + } + value |= 1; // US + return value; + } + return 0xFF; + } + + public void WriteIO(int offset, int value) + { + + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.68000.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.68000.cs new file mode 100644 index 0000000000..6b9c88f2a3 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.68000.cs @@ -0,0 +1,208 @@ +using System; + +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class Genesis + { + private byte ReadByte(uint address) { return (byte) ReadB((int)address); } + private ushort ReadWord(uint address) { return (ushort) ReadW((int)address); } + private uint ReadLong(uint address) { return (uint) ReadL((int)address); } + + private void WriteByte(uint address, byte value) { WriteB((int)address, (sbyte)value); } + private void WriteWord(uint address, ushort value) { WriteW((int)address, (short)value); } + private void WriteLong(uint address, uint value) { WriteL((int)address, (int) value); } + + public sbyte ReadB(int address) + { + address &= 0x00FFFFFF; + + if (address < 0x400000) + return (sbyte) RomData[address]; + if (address >= 0xA10000 && address < 0xA1001F) + return (sbyte) ReadIO((address >> 1) & 0x0F); + + if (address >= 0xE00000) + return (sbyte) Ram[address & 0xFFFF]; + + if (address == 0xA11100) // Z80 BUS status + { + Console.WriteLine("QUERY z80 bus status. 68000 can access? " + (M68000HasZ80Bus && Z80Reset == false)); + return (sbyte) (M68000HasZ80Bus && Z80Reset == false ? 0 : 1); + } + + if ((address & 0xFF0000) == 0xA00000) + { + return (sbyte) ReadMemoryZ80((ushort) (address & 0x7FFF)); + } + + if (address >= 0xC00004 && address < 0xC00008) + { + ushort value = VDP.ReadVdpControl(); + if ((address & 1) == 0) // read MSB + return (sbyte) (value >> 8); + return (sbyte) value; // read LSB + } + + Console.WriteLine("UNHANDLED READB {0:X6}", address); + return 0x7D; + } + + public short ReadW(int address) + { + address &= 0x00FFFFFF; + + int maskedAddr; + if (address < 0x400000) + return (short)((RomData[address] << 8) | RomData[address + 1]); + + if (address >= 0xE00000) // Work RAM + { + maskedAddr = address & 0xFFFF; + return (short)((Ram[maskedAddr] << 8) | Ram[maskedAddr + 1]); + } + + if (address >= 0xC00004 && address < 0xC00008) + return (short) VDP.ReadVdpControl(); + + Console.WriteLine("UNHANDLED READW {0:X6}", address); + return 0x7DCD; + } + + public int ReadL(int address) + { + address &= 0x00FFFFFF; + + int maskedAddr; + if (address < 0x400000) // Cartridge ROM + return (RomData[address] << 24) | (RomData[address + 1] << 16) | (RomData[address + 2] << 8) | RomData[address + 3]; + + if (address >= 0xE00000) // Work RAM + { + maskedAddr = address & 0xFFFF; + return (Ram[maskedAddr] << 24) | (Ram[maskedAddr + 1] << 16) | (Ram[maskedAddr + 2] << 8) | Ram[maskedAddr + 3]; + } + Console.WriteLine("UNHANDLED READL {0:X6}", address); + return 0x7DCDCDCD; + } + + public void WriteB(int address, sbyte value) + { + address &= 0x00FFFFFF; + + if (address >= 0xE00000) // Work RAM + { + Console.WriteLine("MEM[{0:X4}] change from {1:X2} to {2:X2}", address & 0xFFFF, Ram[address & 0xFFFF], value); + Ram[address & 0xFFFF] = (byte)value; + return; + } + if ((address & 0xFF0000) == 0xA00000) + { + WriteMemoryZ80((ushort)(address & 0x7FFF), (byte)value); + return; + } + if (address == 0xA11100) + { + M68000HasZ80Bus = (value & 1) != 0; + Console.WriteLine("68000 has the z80 bus: " + M68000HasZ80Bus); + return; + } + if (address == 0xA11200) // Z80 RESET + { + Z80Reset = (value & 1) == 0; + if (Z80Reset) + SoundCPU.Reset(); + Console.WriteLine("z80 reset: " + Z80Reset); + return; + } + if (address >= 0xC00000) + { + // when writing to VDP in byte mode, the LSB is duplicated into the MSB + switch (address & 0x1F) + { + case 0x00: + case 0x02: + VDP.WriteVdpData((ushort) (value | (value << 8))); + return; + case 0x04: + case 0x06: + VDP.WriteVdpControl((ushort) (value | (value << 8))); + return; + case 0x11: + case 0x13: + case 0x15: + case 0x17: + Console.WriteLine("!+!+!+ PSG WRITE => {0:X2}",value); + PSG.WritePsgData((byte) value, SoundCPU.TotalExecutedCycles); + return; + } + } + + Console.WriteLine("UNHANDLED WRITEB {0:X6}:{1:X2}", address, value); + } + + public void WriteW(int address, short value) + { + address &= 0x00FFFFFF; + + if (address >= 0xE00000) // Work RAM + { + Console.WriteLine("MEM[{0:X4}] change to {1:X4}", address & 0xFFFF, value); + Ram[(address & 0xFFFF) + 0] = (byte)(value >> 8); + Ram[(address & 0xFFFF) + 1] = (byte)value; + return; + } + if (address >= 0xC00000) + { + switch (address & 0x1F) + { + case 0x00: + case 0x02: + VDP.WriteVdpData((ushort)value); + return; + case 0x04: + case 0x06: + VDP.WriteVdpControl((ushort)value); + return; + } + } + if (address == 0xA11100) // Z80 BUSREQ + { + M68000HasZ80Bus = (value & 0x100) != 0; + Console.WriteLine("68000 has the z80 bus: " + M68000HasZ80Bus); + return; + } + if (address == 0xA11200) // Z80 RESET + { + Z80Reset = (value & 0x100) == 0; + if (Z80Reset) + SoundCPU.Reset(); + Console.WriteLine("z80 reset: " + Z80Reset); + return; + } + Console.WriteLine("UNHANDLED WRITEW {0:X6}:{1:X4}", address, value); + } + + public void WriteL(int address, int value) + { + address &= 0x00FFFFFF; + + if (address >= 0xE00000) // Work RAM + { + Console.WriteLine("MEM[{0:X4}] change to {1:X8}", address & 0xFFFF, value); + Ram[(address & 0xFFFF) + 0] = (byte)(value >> 24); + Ram[(address & 0xFFFF) + 1] = (byte)(value >> 16); + Ram[(address & 0xFFFF) + 2] = (byte)(value >> 8); + Ram[(address & 0xFFFF) + 3] = (byte)value; + return; + } + if (address >= 0xC00000) + { + WriteW(address, (short)(value >> 16)); + WriteW(address, (short)value); + return; + } + + Console.WriteLine("UNHANDLED WRITEL {0:X6}:{1:X8}", address, value); + } + } +} diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.Z80.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.Z80.cs new file mode 100644 index 0000000000..870159aa24 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/MemoryMap.Z80.cs @@ -0,0 +1,60 @@ +using System; + +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class Genesis + { + private int BankRegion; + + public byte ReadMemoryZ80(ushort address) + { + if (address < 0x4000) + { + //Console.WriteLine("read z80 memory {0:X4}: {1:X2}",address, Z80Ram[address & 0x1FFF]); + return Z80Ram[address & 0x1FFF]; + } + if (address >= 0x4000 && address < 0x6000) + { + //Console.WriteLine(" === Z80 READS FM STATUS ==="); + return YM2612.ReadStatus(); + } + if (address >= 0x8000) + { + // 68000 Bank region + return (byte) ReadB(BankRegion | (address & 0x7FFF)); + } + Console.WriteLine("UNHANDLED Z80 READ {0:X4}",address); + return 0xCD; + } + + public void WriteMemoryZ80(ushort address, byte value) + { + if (address < 0x4000) + { + //Console.WriteLine("write z80 memory {0:X4}: {1:X2}",address, value); + Z80Ram[address & 0x1FFF] = value; + return; + } + if (address >= 0x4000 && address < 0x6000) + { + //Console.WriteLine(" === Z80 WRITES Z80 {0:X4}:{1:X2} ===",address, value); + YM2612.Write(address & 3, value); + return; + } + if (address == 0x6000) + { + BankRegion >>= 1; + BankRegion |= (value & 1) << 23; + BankRegion &= 0x00FF8000; + Console.WriteLine("Bank pointing at {0:X8}",BankRegion); + return; + } + if (address >= 0x8000) + { + WriteB(BankRegion | (address & 0x7FFF), (sbyte) value); + return; + } + Console.WriteLine("UNHANDLED Z80 WRITE {0:X4}:{1:X2}", address, value); + } + } +} diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/BIOS.cs b/BizHawk.Emulation/Consoles/Sega/SMS/BIOS.cs new file mode 100644 index 0000000000..483e7b8644 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/SMS/BIOS.cs @@ -0,0 +1,1916 @@ +namespace BizHawk.Emulation.Consoles.Sega +{ + public static class BIOS + { + #region USA System BIOS (SMS 1) [No Cartridge Present] + public static readonly byte[] USABios = + { + 0xf3, 0xed, 0x56, 0x31, 0xf0, 0xdf, 0x18, 0x65, 0xf5, 0xe7, 0xf1, 0xd3, 0xbe, + 0xc9, 0xff, 0xff, 0xe7, 0xaf, 0x0e, 0xbe, 0xed, 0xa3, 0xf5, 0xf1, 0xed, 0x79, + 0x20, 0xf8, 0xc9, 0x11, 0xe0, 0x81, 0x7b, 0xd3, 0xbf, 0x7a, 0xd3, 0xbf, 0xc9, + 0xff, 0xe7, 0x79, 0xb7, 0x28, 0x01, 0x04, 0x7d, 0xd3, 0xbe, 0x0d, 0x20, 0xfb, + 0x10, 0xf9, 0xc9, 0xff, 0xc3, 0xb7, 0x03, 0xe7, 0x79, 0xb7, 0x28, 0x01, 0x04, + 0x78, 0x41, 0x0e, 0xbe, 0xed, 0xa3, 0x20, 0xfc, 0x3d, 0x20, 0xf9, 0xc9, 0x21, + 0x00, 0xc3, 0x11, 0x00, 0x7f, 0x01, 0xbe, 0x64, 0xe7, 0xed, 0xb3, 0x21, 0x80, + 0xc3, 0x11, 0x80, 0x7f, 0x06, 0x80, 0xe7, 0xed, 0xb3, 0xc9, 0xff, 0xed, 0x45, + 0x11, 0xa0, 0x81, 0x18, 0xb3, 0x21, 0xd1, 0x08, 0x0e, 0x7f, 0x06, 0x04, 0xed, + 0xb3, 0x21, 0x80, 0x04, 0x01, 0xbf, 0x18, 0xed, 0xb3, 0xaf, 0xd3, 0xbe, 0x21, + 0x00, 0xc0, 0x11, 0x01, 0xc0, 0x01, 0xff, 0x1f, 0x36, 0x00, 0xed, 0xb0, 0x06, + 0x0e, 0xcd, 0x66, 0x03, 0x21, 0x80, 0x04, 0x01, 0xbf, 0x18, 0xed, 0xb3, 0xaf, + 0xd3, 0xbe, 0x21, 0x94, 0x03, 0x22, 0x03, 0xc2, 0x3e, 0xd0, 0x32, 0x00, 0xc3, + 0xfb, 0x3e, 0x03, 0xcd, 0x26, 0x04, 0xf3, 0x11, 0x00, 0x40, 0x01, 0x20, 0x00, + 0xef, 0xcd, 0xe6, 0x04, 0x11, 0xe0, 0x67, 0x01, 0x20, 0x00, 0xef, 0x21, 0x04, + 0x17, 0x11, 0x60, 0x43, 0x01, 0x28, 0x02, 0x3e, 0x09, 0xcd, 0x61, 0x04, 0x21, + 0x2c, 0x19, 0x11, 0x00, 0x4c, 0xcd, 0x98, 0x04, 0xaf, 0x32, 0x02, 0xc2, 0x11, + 0x16, 0x7a, 0x21, 0xbb, 0x0f, 0x01, 0x0a, 0x04, 0xcd, 0x51, 0x04, 0x3e, 0x81, + 0x32, 0x00, 0xcf, 0x11, 0xc0, 0x4e, 0x21, 0x28, 0x10, 0xcd, 0x98, 0x04, 0x21, + 0xc5, 0x15, 0x11, 0x60, 0x40, 0xcd, 0x98, 0x04, 0xcd, 0x20, 0x05, 0xcd, 0x1d, + 0x00, 0xcd, 0xfd, 0x04, 0xf3, 0x21, 0x89, 0x02, 0x11, 0x00, 0xc7, 0x01, 0xdd, + 0x00, 0xed, 0xb0, 0xc3, 0x90, 0x0b, 0xf3, 0x3a, 0x00, 0xc0, 0xb7, 0x28, 0x1a, + 0x2a, 0x70, 0xc2, 0xed, 0x5b, 0x6a, 0xc2, 0xb7, 0xed, 0x52, 0xca, 0xd1, 0xc7, + 0xcd, 0xe6, 0x04, 0x21, 0x76, 0x01, 0x06, 0x03, 0xcd, 0x6a, 0x01, 0x18, 0xfe, + 0xcd, 0x62, 0x01, 0xfb, 0x3e, 0x80, 0xcd, 0x26, 0x04, 0x3a, 0x07, 0xc2, 0xe6, + 0x31, 0xfe, 0x31, 0xca, 0x90, 0x0b, 0x18, 0xee, 0x11, 0x54, 0x7d, 0x06, 0x0b, + 0x21, 0x57, 0x01, 0xd7, 0xc9, 0x1b, 0x20, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x31, + 0x39, 0x38, 0x36, 0xcd, 0xe6, 0x04, 0x06, 0x0c, 0x21, 0xa3, 0x01, 0xc5, 0x5e, + 0x23, 0x56, 0x23, 0x46, 0x23, 0xd7, 0xc1, 0x10, 0xf5, 0xc9, 0x84, 0x78, 0x19, + 0x4d, 0x41, 0x53, 0x54, 0x45, 0x52, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x20, 0x1b, 0x20, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x31, 0x39, 0x38, 0x36, 0x04, + 0x79, 0x0e, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x34, 0x78, 0x04, 0x56, 0x31, 0x2e, 0x33, 0x84, 0x78, 0x13, + 0x57, 0x45, 0x4c, 0x43, 0x4f, 0x4d, 0x45, 0x20, 0x54, 0x4f, 0x20, 0x54, 0x48, + 0x45, 0x20, 0x53, 0x45, 0x47, 0x41, 0x04, 0x79, 0x0e, 0x4d, 0x41, 0x53, 0x54, + 0x45, 0x52, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x2e, 0xc4, 0x79, 0x19, + 0x54, 0x4f, 0x20, 0x50, 0x4c, 0x41, 0x59, 0x2c, 0x4a, 0x55, 0x53, 0x54, 0x20, + 0x46, 0x4f, 0x4c, 0x4c, 0x4f, 0x57, 0x20, 0x54, 0x48, 0x45, 0x53, 0x45, 0x44, + 0x7a, 0x0d, 0x49, 0x4e, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x53, 0x3a, 0x04, 0x7b, 0x19, 0x31, 0x2e, 0x54, 0x55, 0x52, 0x4e, 0x20, 0x4f, + 0x46, 0x46, 0x20, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x20, 0x4f, 0x4e, 0x20, 0x50, + 0x4f, 0x57, 0x45, 0x52, 0x88, 0x7b, 0x05, 0x42, 0x41, 0x53, 0x45, 0x2e, 0x04, + 0x7c, 0x1c, 0x32, 0x2e, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, 0x20, 0x43, 0x41, + 0x52, 0x44, 0x2f, 0x43, 0x41, 0x52, 0x54, 0x52, 0x49, 0x44, 0x47, 0x45, 0x20, + 0x49, 0x4e, 0x54, 0x4f, 0x88, 0x7c, 0x07, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x2e, 0x04, 0x7d, 0x1c, 0x33, 0x2e, 0x54, 0x55, 0x52, 0x4e, 0x20, 0x50, 0x4f, + 0x57, 0x45, 0x52, 0x20, 0x42, 0x41, 0x43, 0x4b, 0x20, 0x4f, 0x4e, 0x2c, 0x41, + 0x4e, 0x44, 0x2e, 0x2e, 0x2e, 0x2e, 0x92, 0x7d, 0x0d, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x63, 0x63, 0x63, 0xd2, 0x7d, 0x0d, 0x6a, + 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x00, 0x73, 0x73, 0x73, 0xdb, + 0xdc, 0x21, 0x5e, 0xc7, 0x06, 0x03, 0x3e, 0xeb, 0xd3, 0x3e, 0x7e, 0x32, 0x00, + 0xc0, 0xd3, 0x3e, 0xd9, 0xcd, 0x36, 0xc7, 0xcd, 0x31, 0xc7, 0xcd, 0x2c, 0xc7, + 0xd9, 0x23, 0x10, 0xe8, 0xaf, 0x32, 0x00, 0xc0, 0x3e, 0xeb, 0xd3, 0x3e, 0x3e, + 0xe3, 0xd3, 0x3e, 0xc9, 0x21, 0xf0, 0x1f, 0x18, 0x08, 0x21, 0xf0, 0x3f, 0x18, + 0x03, 0x21, 0xf0, 0x7f, 0x11, 0x60, 0xc2, 0x01, 0x10, 0x00, 0xed, 0xb0, 0x21, + 0x56, 0xc7, 0x11, 0x60, 0xc2, 0x06, 0x08, 0x1a, 0xbe, 0xc0, 0x23, 0x13, 0x10, + 0xf9, 0xcd, 0x61, 0xc7, 0xf1, 0x18, 0xcd, 0x54, 0x4d, 0x52, 0x20, 0x53, 0x45, + 0x47, 0x41, 0xcb, 0xab, 0x6b, 0x11, 0x00, 0x00, 0x3a, 0x6f, 0xc2, 0x4f, 0xe6, + 0xf0, 0xfe, 0x40, 0x28, 0x08, 0x2a, 0x70, 0xc2, 0x23, 0x22, 0x6a, 0xc2, 0xc9, + 0x79, 0xd6, 0x0a, 0xe6, 0x0f, 0xf5, 0x21, 0xc4, 0xc7, 0x4f, 0x06, 0x00, 0x09, + 0x46, 0x0e, 0xf0, 0x21, 0x00, 0x00, 0xcd, 0xb6, 0xc7, 0xed, 0x53, 0x70, 0xc2, + 0xf1, 0xd6, 0x04, 0xd8, 0x4f, 0x06, 0x00, 0x21, 0xcd, 0xc7, 0x09, 0x46, 0x3e, + 0x02, 0xc5, 0x32, 0xff, 0xff, 0x3c, 0xf5, 0xcd, 0xb0, 0xc7, 0xf1, 0xc1, 0x10, + 0xf3, 0xed, 0x53, 0x70, 0xc2, 0xc9, 0x01, 0x00, 0x40, 0x21, 0x00, 0x80, 0x7b, + 0x86, 0x5f, 0x7a, 0xce, 0x00, 0x57, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf3, 0xc9, + 0x1f, 0x3f, 0x7f, 0xbf, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x02, 0x06, 0x0e, 0x1e, + 0x3e, 0xeb, 0xd3, 0x3e, 0x3a, 0x00, 0xc0, 0xd3, 0x3e, 0xc3, 0x00, 0x00, 0x11, + 0x00, 0x40, 0x1b, 0x7a, 0xb3, 0x20, 0xfb, 0x10, 0xf6, 0xc9, 0x0e, 0x0d, 0x0c, + 0x0a, 0x08, 0x06, 0xf3, 0x31, 0xf0, 0xdf, 0x21, 0x00, 0xc0, 0x11, 0x01, 0xc0, + 0x01, 0xff, 0x1f, 0x36, 0x00, 0xed, 0xb0, 0x21, 0xd1, 0x08, 0x0e, 0x7f, 0x06, + 0x04, 0xed, 0xb3, 0xc3, 0x93, 0x00, 0x20, 0x00, 0xc0, 0x00, 0x3f, 0x3e, 0x3f, + 0x30, 0x30, 0x38, 0x3f, 0x37, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x30, 0x0f, 0x07, 0x16, 0x3f, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf5, 0xdb, 0xbf, 0x07, 0xd2, 0x16, 0x04, 0xc5, 0xd5, 0xe5, 0xdd, + 0xe5, 0xfd, 0xe5, 0x08, 0xd9, 0xf5, 0xc5, 0xd5, 0xe5, 0x3a, 0x0b, 0xc2, 0xb7, + 0x28, 0x0e, 0xdb, 0xdd, 0xe6, 0x10, 0x21, 0x06, 0xc2, 0x4e, 0x77, 0xa9, 0xa1, + 0xc2, 0x77, 0x03, 0x3a, 0x00, 0xc2, 0x0f, 0xf5, 0xdc, 0x4d, 0x00, 0xf1, 0x0f, + 0xdc, 0x2f, 0x04, 0x0f, 0xf5, 0xdc, 0x77, 0x05, 0xcd, 0xf0, 0x04, 0xf1, 0x0f, + 0xf5, 0xdc, 0x2a, 0x0d, 0xf1, 0x0f, 0xdc, 0x5f, 0x0d, 0xcd, 0xb8, 0x05, 0xaf, + 0x32, 0x00, 0xc2, 0xe1, 0xd1, 0xc1, 0xf1, 0x08, 0xd9, 0xfd, 0xe1, 0xdd, 0xe1, + 0xe1, 0xd1, 0xc1, 0xf1, 0xfb, 0xc9, 0xd5, 0xed, 0x5b, 0x25, 0xc2, 0x16, 0x88, + 0xe7, 0x11, 0xff, 0x8a, 0xe7, 0xd1, 0xf1, 0xfb, 0xc9, 0x21, 0x00, 0xc2, 0x77, + 0x7e, 0xb7, 0x20, 0xfc, 0xc9, 0x2a, 0x03, 0xc2, 0x46, 0x23, 0x5e, 0x23, 0x56, + 0x23, 0xe7, 0x0e, 0xbe, 0xed, 0xb3, 0xc9, 0xe7, 0xdb, 0xbe, 0xc9, 0xe7, 0xdb, + 0xbe, 0x77, 0xe3, 0xe3, 0xdb, 0xbe, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf3, 0xc9, + 0x79, 0x48, 0x47, 0xc5, 0xd7, 0xeb, 0x01, 0x40, 0x00, 0x09, 0xeb, 0xc1, 0x0d, + 0x20, 0xf4, 0xc9, 0x32, 0x01, 0xc2, 0xe7, 0x7e, 0xd9, 0x01, 0xbe, 0x04, 0x67, + 0x3a, 0x01, 0xc2, 0x1f, 0x54, 0x38, 0x02, 0x16, 0x00, 0xed, 0x51, 0x10, 0xf6, + 0xd9, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xe6, 0xc9, 0x36, 0x80, 0xa0, 0x81, 0xff, + 0x82, 0xff, 0x83, 0xff, 0x84, 0xff, 0x85, 0xfb, 0x86, 0x00, 0x88, 0x00, 0x89, + 0xff, 0x8a, 0x00, 0x87, 0x10, 0xc0, 0x06, 0x04, 0xc5, 0xd5, 0xcd, 0xa5, 0x04, + 0xd1, 0x13, 0xc1, 0x10, 0xf6, 0xc9, 0x7e, 0x23, 0xb7, 0xc8, 0x47, 0x4f, 0xcb, + 0xb8, 0x7b, 0xf3, 0xd3, 0xbf, 0x7a, 0xd3, 0xbf, 0x7e, 0xd3, 0xbe, 0xfb, 0xcb, + 0x79, 0x28, 0x01, 0x23, 0x13, 0x13, 0x13, 0x13, 0x10, 0xea, 0x20, 0xe0, 0x23, + 0x18, 0xdd, 0xaf, 0x32, 0x2a, 0xc2, 0x32, 0x26, 0xc2, 0xf3, 0x21, 0x20, 0xc2, + 0x7e, 0xb7, 0xc8, 0x36, 0x00, 0x3a, 0x2a, 0xc2, 0x5f, 0x16, 0x89, 0xe7, 0x3a, + 0x26, 0xc2, 0x5f, 0x15, 0xe7, 0xc9, 0x11, 0x00, 0x78, 0x01, 0x00, 0x07, 0x2e, + 0x00, 0xef, 0xc9, 0xdb, 0xdc, 0x21, 0x07, 0xc2, 0x2f, 0x4f, 0xae, 0x71, 0x23, + 0xa1, 0x77, 0xc9, 0x3e, 0x05, 0xcd, 0x26, 0x04, 0x3a, 0x02, 0xcf, 0xb7, 0x28, + 0xf5, 0x11, 0x8a, 0x7b, 0x21, 0xe3, 0x0f, 0x01, 0x17, 0x03, 0xf3, 0xcd, 0x51, + 0x04, 0xcd, 0x4d, 0x01, 0xfb, 0x3a, 0x01, 0xcf, 0xb7, 0x28, 0xfa, 0xc9, 0x3e, + 0x03, 0x32, 0x01, 0xc2, 0x3e, 0xf0, 0x32, 0x02, 0xc2, 0x5f, 0x16, 0x88, 0xe7, + 0x2e, 0xff, 0x11, 0xc0, 0x5f, 0x01, 0x40, 0x00, 0xef, 0x11, 0x00, 0xc3, 0x3e, + 0x08, 0x21, 0x63, 0x05, 0x01, 0x04, 0x00, 0xed, 0xb0, 0x3d, 0x20, 0xf5, 0x3e, + 0xd0, 0x12, 0x1e, 0x80, 0x01, 0xff, 0x08, 0x3e, 0x04, 0xed, 0xa0, 0xed, 0xa0, + 0x3d, 0x28, 0x04, 0x2b, 0x2b, 0x18, 0xf5, 0x10, 0xf1, 0x3e, 0x01, 0xc3, 0x26, + 0x04, 0x38, 0x40, 0x48, 0x50, 0x47, 0xfe, 0x5a, 0xfe, 0x6c, 0xfe, 0x7e, 0xfe, + 0x4f, 0xff, 0x62, 0xff, 0x74, 0xff, 0x86, 0xff, 0x21, 0x01, 0xc2, 0x35, 0xc0, + 0x36, 0x02, 0x21, 0x02, 0xc2, 0x7e, 0xfe, 0x01, 0x20, 0x06, 0x3e, 0x80, 0x32, + 0x00, 0xc2, 0xc9, 0x5f, 0x16, 0x88, 0xe7, 0x34, 0x7e, 0xed, 0x44, 0xcb, 0x7f, + 0xc0, 0xfe, 0x08, 0x11, 0xe0, 0x5f, 0x38, 0x05, 0xd6, 0x08, 0x11, 0xc0, 0x5f, + 0x21, 0xaf, 0x05, 0x06, 0x00, 0x4f, 0x09, 0x6e, 0x0e, 0x20, 0xef, 0xc9, 0x00, + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xcd, 0xd2, 0x05, 0xdd, 0x21, + 0x03, 0xcf, 0x06, 0x04, 0xc5, 0xdd, 0xcb, 0x00, 0x7e, 0xc4, 0x18, 0x06, 0x11, + 0x20, 0x00, 0xdd, 0x19, 0xc1, 0x10, 0xf0, 0xc9, 0x3a, 0x00, 0xcf, 0xfe, 0x80, + 0xda, 0xb5, 0x08, 0xca, 0x12, 0x06, 0x11, 0x03, 0xcf, 0xd6, 0x81, 0x21, 0x87, + 0x0b, 0x06, 0x00, 0x87, 0x4f, 0x09, 0x7e, 0x23, 0x66, 0x6f, 0xcd, 0xb5, 0x08, + 0x46, 0x23, 0xc5, 0x01, 0x09, 0x00, 0xed, 0xb0, 0x3e, 0x20, 0x12, 0x13, 0x3e, + 0x01, 0x12, 0x13, 0xaf, 0x12, 0x13, 0x12, 0x13, 0x12, 0xe5, 0x21, 0x12, 0x00, + 0x19, 0xeb, 0xe1, 0x13, 0xc1, 0x10, 0xe1, 0x3e, 0x80, 0x32, 0x00, 0xcf, 0xc9, + 0xdd, 0x5e, 0x0c, 0xdd, 0x56, 0x0d, 0x13, 0xdd, 0x73, 0x0c, 0xdd, 0x72, 0x0d, + 0xdd, 0x6e, 0x0a, 0xdd, 0x66, 0x0b, 0xb7, 0xed, 0x52, 0xcc, 0x7e, 0x07, 0xdd, + 0x5e, 0x10, 0xdd, 0x56, 0x11, 0x7b, 0xb2, 0x20, 0x07, 0xdd, 0x36, 0x16, 0x0f, + 0xc3, 0xf0, 0x06, 0xdd, 0xcb, 0x00, 0x6e, 0x20, 0x25, 0xdd, 0x7e, 0x06, 0xb7, + 0x20, 0x14, 0xdd, 0x73, 0x12, 0xdd, 0x72, 0x13, 0xc3, 0xa9, 0x06, 0x3d, 0x4f, + 0x06, 0x00, 0x09, 0x09, 0x7e, 0x23, 0x66, 0x6f, 0xc9, 0x21, 0x85, 0x0b, 0xcd, + 0x57, 0x06, 0xcd, 0x48, 0x07, 0x18, 0x3c, 0xd5, 0xdd, 0x6e, 0x14, 0xdd, 0x66, + 0x15, 0xb7, 0xed, 0x52, 0xf5, 0x7d, 0xf2, 0x7e, 0x06, 0xed, 0x44, 0x67, 0xdd, + 0x5e, 0x0c, 0xcd, 0x67, 0x09, 0xdd, 0x5e, 0x0a, 0xcd, 0x73, 0x09, 0x5f, 0x16, + 0x00, 0xf1, 0x7b, 0xf2, 0x99, 0x06, 0xed, 0x44, 0x28, 0x02, 0x15, 0x5f, 0xe1, + 0x19, 0xeb, 0xdd, 0x73, 0x12, 0xdd, 0x72, 0x13, 0xdd, 0x7e, 0x06, 0xb7, 0xc2, + 0x62, 0x06, 0xdd, 0x7e, 0x07, 0xb7, 0x20, 0x0b, 0xdd, 0x7e, 0x08, 0x2f, 0xe6, + 0x0f, 0xdd, 0x77, 0x16, 0x18, 0x0b, 0xcb, 0xbf, 0x21, 0x6f, 0x0b, 0xcd, 0x57, + 0x06, 0xcd, 0x0e, 0x07, 0xdd, 0xcb, 0x00, 0x76, 0x20, 0x25, 0xdd, 0x7e, 0x01, + 0xe6, 0x0f, 0x4f, 0x06, 0x00, 0x21, 0x03, 0x07, 0x09, 0x4e, 0xdd, 0x7e, 0x12, + 0xe6, 0x0f, 0xb1, 0xcd, 0xad, 0x08, 0xdd, 0x7e, 0x12, 0xe6, 0xf0, 0xdd, 0xb6, + 0x13, 0x0f, 0x0f, 0x0f, 0x0f, 0xcd, 0xad, 0x08, 0xdd, 0x7e, 0x01, 0xe6, 0x0f, + 0x4f, 0x06, 0x00, 0x21, 0x07, 0x07, 0x09, 0x7e, 0xdd, 0xb6, 0x16, 0xc3, 0xad, + 0x08, 0x80, 0xa0, 0xc0, 0xc0, 0x90, 0xb0, 0xd0, 0xf0, 0xdd, 0x77, 0x0e, 0xe5, + 0xdd, 0x7e, 0x0e, 0xcb, 0x3f, 0xf5, 0x4f, 0x06, 0x00, 0x09, 0xf1, 0x7e, 0xe1, + 0x38, 0x14, 0x0f, 0x0f, 0x0f, 0x0f, 0xb7, 0x28, 0xe6, 0xfe, 0x10, 0x20, 0x05, + 0xdd, 0x35, 0x0e, 0x18, 0xe0, 0xfe, 0x20, 0x28, 0x0b, 0xdd, 0x34, 0x0e, 0xf6, + 0xf0, 0xdd, 0x86, 0x08, 0x3c, 0x38, 0x01, 0xaf, 0x2f, 0xe6, 0x0f, 0xdd, 0x77, + 0x16, 0xc9, 0xdd, 0x77, 0x0f, 0xe5, 0xdd, 0x7e, 0x0f, 0xcb, 0x3f, 0xf5, 0x4f, + 0x06, 0x00, 0x09, 0xf1, 0x7e, 0xe1, 0x38, 0x14, 0x0f, 0x0f, 0x0f, 0x0f, 0xb7, + 0xca, 0x45, 0x07, 0xfe, 0x10, 0x20, 0x08, 0xdd, 0x35, 0x0f, 0x18, 0xdf, 0xfe, + 0x20, 0xc8, 0xdd, 0x34, 0x0f, 0x2f, 0xe6, 0x0f, 0x6f, 0x26, 0x00, 0xeb, 0x19, + 0xdd, 0x75, 0x12, 0xdd, 0x74, 0x13, 0xc9, 0xdd, 0x5e, 0x03, 0xdd, 0x56, 0x04, + 0x1a, 0x13, 0xfe, 0xe0, 0xd2, 0x12, 0x08, 0xdd, 0xcb, 0x00, 0x5e, 0x20, 0x60, + 0xb7, 0xf2, 0xcd, 0x07, 0xd6, 0x80, 0x28, 0x03, 0xdd, 0x86, 0x05, 0x21, 0xd5, + 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, 0x7e, 0xdd, 0x77, 0x10, 0x23, 0x7e, 0xdd, + 0x77, 0x11, 0xdd, 0xcb, 0x00, 0x6e, 0x28, 0x58, 0x1a, 0x13, 0xd6, 0x80, 0xdd, + 0x86, 0x05, 0x21, 0xd5, 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, 0x7e, 0xdd, 0x77, + 0x14, 0x23, 0x7e, 0xdd, 0x77, 0x15, 0x1a, 0x13, 0xd5, 0x67, 0xdd, 0x5e, 0x02, + 0xcd, 0x67, 0x09, 0xd1, 0xdd, 0x75, 0x0a, 0xdd, 0x74, 0x0b, 0xaf, 0xdd, 0x77, + 0x0e, 0xdd, 0x77, 0x0f, 0xdd, 0x73, 0x03, 0xdd, 0x72, 0x04, 0xaf, 0xdd, 0x77, + 0x0c, 0xdd, 0x77, 0x0d, 0xc9, 0xdd, 0x77, 0x11, 0x1a, 0x13, 0xdd, 0x77, 0x10, + 0xdd, 0xcb, 0x00, 0x6e, 0x28, 0xcc, 0x1a, 0x13, 0xdd, 0x77, 0x15, 0x1a, 0x13, + 0xdd, 0x77, 0x14, 0x18, 0xc0, 0x1a, 0xb7, 0xf2, 0xcc, 0x07, 0x18, 0xca, 0x21, + 0x25, 0x08, 0xe5, 0xe6, 0x1f, 0x21, 0x29, 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, + 0x7e, 0x23, 0x66, 0x6f, 0xe9, 0x13, 0xc3, 0x84, 0x07, 0x8a, 0x08, 0x8f, 0x08, + 0x67, 0x08, 0x7e, 0x08, 0x3b, 0x08, 0x49, 0x08, 0x4f, 0x08, 0x83, 0x08, 0x41, + 0x08, 0xeb, 0x5e, 0x23, 0x56, 0x1b, 0xc9, 0x1a, 0xdd, 0x86, 0x05, 0xdd, 0x77, + 0x05, 0xc9, 0xdd, 0xcb, 0x00, 0xae, 0x1b, 0xc9, 0x1a, 0x13, 0xc6, 0x17, 0x4f, + 0x06, 0x00, 0xdd, 0xe5, 0xe1, 0x09, 0x7e, 0xb7, 0x20, 0x02, 0x1a, 0x77, 0x13, + 0x35, 0xc2, 0x3b, 0x08, 0x13, 0xc9, 0x1a, 0xf6, 0xe0, 0xf5, 0xcd, 0xad, 0x08, + 0xf1, 0xf6, 0xfc, 0x3c, 0x20, 0x05, 0xdd, 0xcb, 0x00, 0xb6, 0xc9, 0xdd, 0xcb, + 0x00, 0xf6, 0xc9, 0x1a, 0xdd, 0x77, 0x07, 0xc9, 0x3e, 0x80, 0x32, 0x02, 0xcf, + 0x1b, 0xc9, 0x1a, 0xdd, 0x77, 0x08, 0xc9, 0x3e, 0x80, 0x32, 0x01, 0xcf, 0xaf, + 0xdd, 0x77, 0x00, 0xcd, 0x9e, 0x08, 0xe1, 0xe1, 0xc9, 0xdd, 0x7e, 0x01, 0xe6, + 0x0f, 0x4f, 0x06, 0x00, 0x21, 0x07, 0x07, 0x09, 0x7e, 0xf6, 0x0f, 0xdd, 0xcb, + 0x00, 0x56, 0xc0, 0xd3, 0x7f, 0xc9, 0xd9, 0x21, 0x01, 0xcf, 0x11, 0x02, 0xcf, + 0x01, 0x7f, 0x00, 0x36, 0x00, 0xed, 0xb0, 0xd9, 0xd9, 0x21, 0xd1, 0x08, 0x0e, + 0x7f, 0x06, 0x04, 0xed, 0xb3, 0xaf, 0xd9, 0xc9, 0x9f, 0xbf, 0xdf, 0xff, 0x00, + 0x00, 0xff, 0x03, 0xc7, 0x03, 0x90, 0x03, 0x5d, 0x03, 0x2d, 0x03, 0xff, 0x02, + 0xd4, 0x02, 0xab, 0x02, 0x85, 0x02, 0x61, 0x02, 0x3f, 0x02, 0x1e, 0x02, 0x00, + 0x02, 0xe3, 0x01, 0xc8, 0x01, 0xaf, 0x01, 0x96, 0x01, 0x80, 0x01, 0x6a, 0x01, + 0x56, 0x01, 0x43, 0x01, 0x30, 0x01, 0x1f, 0x01, 0x0f, 0x01, 0x00, 0x01, 0xf2, + 0x00, 0xe4, 0x00, 0xd7, 0x00, 0xcb, 0x00, 0xc0, 0x00, 0xb5, 0x00, 0xab, 0x00, + 0xa1, 0x00, 0x98, 0x00, 0x90, 0x00, 0x88, 0x00, 0x80, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x6c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x5b, 0x00, 0x55, 0x00, 0x51, 0x00, + 0x4c, 0x00, 0x48, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3c, 0x00, 0x39, 0x00, 0x36, + 0x00, 0x33, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x28, 0x00, 0x26, 0x00, + 0x24, 0x00, 0x22, 0x00, 0x20, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1b, 0x00, 0x19, + 0x00, 0x18, 0x00, 0x16, 0x00, 0x15, 0x00, 0x14, 0x00, 0x13, 0x00, 0x12, 0x00, + 0x11, 0x00, 0x16, 0x00, 0x6a, 0x06, 0x08, 0x29, 0x30, 0x01, 0x19, 0x10, 0xfa, + 0xc9, 0x06, 0x08, 0xed, 0x6a, 0x7c, 0x38, 0x03, 0xbb, 0x38, 0x03, 0x93, 0x67, + 0xb7, 0x10, 0xf3, 0x7d, 0x17, 0x2f, 0xc9, 0x04, 0xa0, 0x20, 0x05, 0xc7, 0x09, + 0x05, 0x01, 0x04, 0x0d, 0xa0, 0x21, 0x05, 0xbb, 0x09, 0x05, 0x01, 0x04, 0x0d, + 0xa0, 0x22, 0x05, 0xd2, 0x09, 0x05, 0x01, 0x04, 0x0d, 0x80, 0x23, 0x05, 0xab, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0xe2, 0x04, 0xe3, 0x01, 0xe0, 0x0d, + 0x8d, 0x08, 0xe3, 0x02, 0xe0, 0x0f, 0x1c, 0xe1, 0x81, 0xa5, 0x08, 0xe5, 0x80, + 0xe7, 0x8d, 0x81, 0x10, 0x80, 0x0c, 0xe1, 0x85, 0xa9, 0x08, 0xe5, 0x80, 0x8a, + 0x8a, 0x10, 0x80, 0x08, 0xe1, 0x88, 0xac, 0x08, 0xe5, 0x80, 0x86, 0x86, 0x10, + 0x80, 0x08, 0xe1, 0x04, 0x80, 0x20, 0x05, 0x02, 0x0a, 0x00, 0x01, 0x02, 0x0e, + 0x80, 0x21, 0x05, 0x14, 0x0a, 0x00, 0x01, 0x02, 0x0f, 0x80, 0x22, 0x05, 0x27, + 0x0a, 0x00, 0x01, 0x02, 0x0e, 0x80, 0x23, 0x05, 0x3a, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x8f, 0x02, 0x02, 0x02, 0xe3, 0x04, 0x0f, 0xe3, 0x02, 0x8d, 0x03, 0x03, + 0x8f, 0xe3, 0x04, 0x91, 0x18, 0xe1, 0x9f, 0x02, 0x02, 0x02, 0xe3, 0x04, 0xa0, + 0x0f, 0xe3, 0x02, 0x9d, 0x03, 0x03, 0x9f, 0xe3, 0x04, 0xa1, 0x18, 0xe1, 0xa2, + 0x02, 0x02, 0x02, 0xe3, 0x04, 0xa4, 0x0f, 0xe3, 0x02, 0xa0, 0x03, 0x03, 0xa2, + 0xe3, 0x04, 0xa4, 0x18, 0xe1, 0xe2, 0x04, 0xe3, 0x01, 0xe0, 0x0d, 0x8d, 0x02, + 0x02, 0x02, 0xe3, 0x02, 0xe0, 0x0f, 0x0f, 0xe3, 0x01, 0xe0, 0x0d, 0x03, 0x03, + 0x03, 0xe3, 0x02, 0xe0, 0x0f, 0x18, 0xe1, 0x04, 0x80, 0x20, 0x02, 0x7b, 0x0a, + 0x00, 0x01, 0x03, 0x0b, 0x80, 0x21, 0x02, 0x7d, 0x0a, 0x00, 0x01, 0x03, 0x0c, + 0x80, 0x22, 0x02, 0xa2, 0x0a, 0x00, 0x01, 0x03, 0x0b, 0x80, 0x23, 0x02, 0xc7, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x99, 0x08, 0xa0, 0x9d, 0xa0, 0x9e, + 0x9b, 0x9d, 0x9b, 0x99, 0x9b, 0x9d, 0x9b, 0x94, 0x96, 0x94, 0x80, 0x99, 0x08, + 0xa0, 0x9d, 0xa0, 0x9e, 0x9b, 0x9d, 0x9b, 0x9d, 0x9b, 0x99, 0x98, 0x99, 0x99, + 0x99, 0x80, 0xe4, 0x7d, 0x0a, 0x8d, 0x08, 0x99, 0x8d, 0x99, 0x92, 0x9e, 0x94, + 0xa0, 0x8d, 0x94, 0x8d, 0x99, 0x88, 0x8f, 0x88, 0x94, 0x8d, 0x08, 0x99, 0x8d, + 0x99, 0x92, 0x9e, 0x94, 0xa0, 0x8d, 0x94, 0x88, 0x94, 0x8d, 0x99, 0x8d, 0x80, + 0xe4, 0xa2, 0x0a, 0xe2, 0x04, 0xe3, 0x01, 0xe0, 0x0d, 0x8d, 0x08, 0xe3, 0x02, + 0xe0, 0x0f, 0x08, 0xe3, 0x01, 0xe0, 0x0d, 0x04, 0x04, 0xe3, 0x02, 0xe0, 0x0f, + 0x08, 0xe4, 0xc9, 0x0a, 0x04, 0x80, 0x20, 0x04, 0x07, 0x0b, 0x00, 0x01, 0x02, + 0x0e, 0x80, 0x21, 0x04, 0x13, 0x0b, 0x00, 0x01, 0x02, 0x0d, 0x80, 0x22, 0x04, + 0x1f, 0x0b, 0x00, 0x01, 0x02, 0x0e, 0x80, 0x23, 0x04, 0x2b, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x9d, 0x02, 0x9b, 0x9d, 0xa0, 0x9d, 0xa0, 0xe3, 0x04, 0xa5, 0x10, + 0xe1, 0x99, 0x02, 0x98, 0x99, 0x9d, 0x99, 0x9d, 0xe3, 0x04, 0xa2, 0x10, 0xe1, + 0x8d, 0x02, 0x02, 0x02, 0x88, 0x88, 0x88, 0xe3, 0x04, 0x91, 0x10, 0xe1, 0xe2, + 0x04, 0xe3, 0x01, 0xe0, 0x0d, 0x8d, 0x04, 0xe3, 0x02, 0xe0, 0x0f, 0x04, 0xe3, + 0x01, 0xe0, 0x0d, 0x02, 0x02, 0xe3, 0x02, 0xe0, 0x0f, 0x10, 0xe1, 0xaf, 0xec, + 0xee, 0x01, 0xbc, 0xdd, 0xee, 0xff, 0xee, 0xff, 0xdd, 0xcc, 0xbb, 0xdd, 0xee, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0xfe, 0xdc, 0xbc, 0xde, + 0xfe, 0xdb, 0xab, 0xcd, 0xef, 0xed, 0xcb, 0xab, 0xcd, 0xef, 0xee, 0x01, 0xff, + 0xee, 0x00, 0x77, 0x0b, 0x79, 0x0b, 0x80, 0x0b, 0x44, 0x0b, 0xff, 0x02, 0xff, + 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x02, 0xef, 0xff, 0xff, 0xee, 0x02, 0x48, 0x0b, + 0x86, 0x09, 0xdd, 0x09, 0x56, 0x0a, 0xe2, 0x0a, 0xff, 0x3e, 0xff, 0x32, 0x0b, + 0xc2, 0x21, 0x93, 0x0d, 0x11, 0x30, 0xc2, 0x01, 0x04, 0x00, 0xed, 0xb0, 0x21, + 0xc2, 0xc9, 0x06, 0x1e, 0x36, 0x03, 0x23, 0x23, 0x10, 0xfa, 0xf3, 0x21, 0x9e, + 0x0d, 0x11, 0x64, 0x79, 0x06, 0x0a, 0xd7, 0xf3, 0x21, 0x30, 0xc2, 0x11, 0x6a, + 0x79, 0xcd, 0x76, 0x0d, 0xfb, 0x3e, 0x10, 0xcd, 0x26, 0x04, 0xdd, 0x21, 0x00, + 0xc4, 0xcd, 0x27, 0x0f, 0xdd, 0x36, 0x07, 0x08, 0xdd, 0x36, 0x0c, 0x0d, 0xdd, + 0x36, 0x04, 0x04, 0xdd, 0x21, 0x40, 0xc4, 0xcd, 0x27, 0x0f, 0xdd, 0x21, 0x20, + 0xc4, 0xcd, 0x27, 0x0f, 0xcd, 0xc1, 0x0c, 0x3e, 0x01, 0x32, 0x00, 0xc4, 0x3c, + 0x32, 0x40, 0xc4, 0x3c, 0x32, 0x20, 0xc4, 0xcd, 0x99, 0x0e, 0x01, 0x01, 0x14, + 0xcd, 0xba, 0x0c, 0x3e, 0x83, 0x32, 0x00, 0xcf, 0x3e, 0x11, 0xcd, 0x26, 0x04, + 0xcd, 0x99, 0x0e, 0x21, 0x34, 0xc2, 0x7e, 0xb7, 0x20, 0x38, 0x23, 0x7e, 0xb7, + 0x28, 0xec, 0xf3, 0x21, 0x97, 0x0d, 0x11, 0xda, 0x79, 0x06, 0x07, 0xd7, 0xfb, + 0x06, 0x00, 0xc5, 0x01, 0x80, 0x01, 0xcd, 0xba, 0x0c, 0x11, 0xdb, 0x79, 0x21, + 0x74, 0xc2, 0x34, 0xf3, 0xe7, 0x06, 0x07, 0x3a, 0x74, 0xc2, 0xe6, 0x08, 0xd3, + 0xbe, 0xf5, 0xf1, 0xdb, 0xbe, 0x10, 0xf3, 0xfb, 0xc1, 0x10, 0xdd, 0xc3, 0x77, + 0x03, 0x36, 0x00, 0x3e, 0x84, 0x32, 0x00, 0xcf, 0x01, 0x01, 0x60, 0xcd, 0xba, + 0x0c, 0x3e, 0xd0, 0x32, 0x00, 0xc3, 0x01, 0x01, 0x30, 0xcd, 0xba, 0x0c, 0x21, + 0x30, 0xc2, 0x7e, 0xc6, 0x01, 0x27, 0x77, 0x23, 0x34, 0x7e, 0xfe, 0x0d, 0x30, + 0x19, 0x5f, 0x16, 0x00, 0x21, 0xa6, 0x0d, 0x19, 0x7e, 0x2a, 0x32, 0xc2, 0x84, + 0x27, 0x30, 0x02, 0x3e, 0x99, 0x67, 0x6a, 0x22, 0x32, 0xc2, 0xc3, 0xb5, 0x0b, + 0x3e, 0x82, 0x32, 0x00, 0xcf, 0x21, 0xaa, 0x0c, 0x11, 0xd0, 0x79, 0x06, 0x10, + 0xf3, 0xd7, 0xfb, 0x01, 0x80, 0x00, 0xcd, 0xba, 0x0c, 0x01, 0x80, 0x00, 0xcd, + 0xba, 0x0c, 0xc3, 0x77, 0x03, 0x43, 0x4f, 0x4e, 0x47, 0x52, 0x41, 0x54, 0x55, + 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x21, 0x79, 0xcd, 0x26, 0x04, 0x10, + 0xfa, 0xc9, 0x3a, 0x31, 0xc2, 0x3d, 0x57, 0x87, 0x82, 0x5f, 0xaf, 0xcb, 0x1a, + 0x1f, 0x83, 0x5f, 0x21, 0xb1, 0x19, 0x19, 0x7e, 0x32, 0x08, 0xc4, 0x23, 0x7e, + 0x32, 0x48, 0xc4, 0x23, 0x7e, 0x32, 0x47, 0xc4, 0x23, 0x11, 0x00, 0xca, 0x06, + 0x80, 0xc5, 0x06, 0x04, 0x4e, 0x79, 0x3c, 0xe6, 0x03, 0xc6, 0x04, 0x12, 0x13, + 0xaf, 0x12, 0x13, 0xcb, 0x19, 0xcb, 0x19, 0x10, 0xef, 0x23, 0xc1, 0x10, 0xe7, + 0x21, 0x3e, 0xca, 0x01, 0x74, 0x10, 0x11, 0x40, 0x00, 0x71, 0x19, 0x10, 0xfc, + 0x3e, 0xff, 0x32, 0x44, 0xc2, 0x11, 0x36, 0x80, 0xe7, 0x3e, 0x08, 0xcd, 0x26, + 0x04, 0x3a, 0x44, 0xc2, 0xb7, 0x20, 0xf5, 0x11, 0x06, 0x80, 0xe7, 0x11, 0xff, + 0x8a, 0xe7, 0xc9, 0x11, 0x00, 0x88, 0xe7, 0x11, 0x37, 0x8a, 0xe7, 0x21, 0x25, + 0xc2, 0x7e, 0x35, 0x20, 0x05, 0xaf, 0x32, 0x44, 0xc2, 0xc9, 0xed, 0x44, 0x5f, + 0xe6, 0x07, 0xc0, 0x7b, 0x0f, 0x0f, 0xc6, 0xc0, 0x5f, 0x16, 0x79, 0x6f, 0x26, + 0xc9, 0x06, 0x11, 0xc5, 0x7e, 0xcf, 0x01, 0x40, 0x00, 0x09, 0xeb, 0x09, 0xeb, + 0xc1, 0x10, 0xf3, 0xc9, 0x21, 0x32, 0xc2, 0x35, 0xf0, 0x36, 0x3b, 0x23, 0x7e, + 0xd6, 0x01, 0x27, 0x77, 0x11, 0x7a, 0x79, 0x20, 0x05, 0x3d, 0x32, 0x35, 0xc2, + 0x3c, 0xe7, 0x7e, 0x1f, 0x1f, 0x1f, 0x1f, 0xe6, 0x0f, 0x28, 0x02, 0xf6, 0x30, + 0xcd, 0x8a, 0x0d, 0x7e, 0xe6, 0x0f, 0xf6, 0x30, 0xd3, 0xbe, 0xf5, 0xf1, 0x3e, + 0x08, 0xd3, 0xbe, 0xc9, 0x01, 0x01, 0x00, 0x61, 0x54, 0x49, 0x4d, 0x45, 0x20, + 0x55, 0x50, 0x52, 0x44, 0x20, 0x20, 0x20, 0x20, 0x54, 0x49, 0x4d, 0x45, 0x30, + 0x35, 0x25, 0x35, 0x35, 0x30, 0x35, 0x35, 0x35, 0x10, 0x15, 0xb9, 0x0d, 0x43, + 0x0e, 0x6f, 0x0e, 0xdd, 0xcb, 0x01, 0x7e, 0x28, 0x15, 0xdd, 0x35, 0x1f, 0x28, + 0x06, 0x2a, 0x05, 0xc4, 0xc3, 0x85, 0x0f, 0xdd, 0xcb, 0x01, 0xbe, 0x21, 0x00, + 0x00, 0x22, 0x09, 0xc4, 0xcd, 0x2c, 0x0e, 0x3a, 0x07, 0xc2, 0x0f, 0xdc, 0xf3, + 0x0d, 0x0f, 0xdc, 0x05, 0x0e, 0x0f, 0x38, 0x39, 0x0f, 0xd0, 0xcb, 0x4e, 0xc0, + 0xdd, 0x36, 0x09, 0x01, 0x21, 0x8d, 0x0e, 0x18, 0x1d, 0xe5, 0x11, 0xc0, 0xff, + 0x19, 0xcb, 0x46, 0xe1, 0xc0, 0xdd, 0x36, 0x0a, 0xff, 0x21, 0x96, 0x0e, 0x18, + 0x0a, 0xcb, 0x46, 0xc0, 0xdd, 0x36, 0x0a, 0x01, 0x21, 0x93, 0x0e, 0xf1, 0x22, + 0x05, 0xc4, 0xdd, 0x36, 0x1f, 0x08, 0xdd, 0xcb, 0x01, 0xfe, 0xc3, 0x85, 0x0f, + 0x2b, 0x2b, 0xcb, 0x4e, 0xc0, 0xdd, 0x36, 0x09, 0xff, 0x21, 0x90, 0x0e, 0x18, + 0xe4, 0x3a, 0x07, 0xc4, 0x0f, 0x0f, 0xe6, 0x3e, 0x5f, 0x3a, 0x08, 0xc4, 0xe6, + 0xf8, 0x6f, 0x26, 0x00, 0x29, 0x29, 0x29, 0x16, 0xc8, 0x19, 0xc9, 0xdd, 0xcb, + 0x01, 0x46, 0x28, 0x19, 0x2a, 0x07, 0xc4, 0x7d, 0xdd, 0xbe, 0x07, 0x20, 0x0a, + 0x7c, 0xdd, 0xbe, 0x08, 0x20, 0x04, 0x32, 0x34, 0xc2, 0xc9, 0x21, 0x87, 0x0e, + 0xc3, 0x85, 0x0f, 0xdd, 0x36, 0x0c, 0x0c, 0xdd, 0xcb, 0x01, 0xc6, 0xdd, 0x36, + 0x04, 0x1e, 0xc9, 0xdd, 0xcb, 0x01, 0x46, 0x28, 0x06, 0x21, 0x8a, 0x0e, 0xc3, + 0x85, 0x0f, 0x2a, 0x07, 0xc4, 0x22, 0x27, 0xc4, 0xdd, 0x36, 0x0c, 0x53, 0x18, + 0xdf, 0x02, 0x47, 0x0c, 0x02, 0x20, 0x53, 0x02, 0x0d, 0x0e, 0x02, 0x0f, 0x10, + 0x02, 0x11, 0x12, 0x02, 0x13, 0x14, 0x21, 0x00, 0xc3, 0x22, 0x09, 0xc2, 0xdd, + 0x21, 0x00, 0xc4, 0x06, 0x04, 0xdd, 0x7e, 0x00, 0xe6, 0x7f, 0xca, 0xc5, 0x0e, + 0xc5, 0x21, 0xb1, 0x0d, 0xcd, 0xb1, 0x0f, 0xdd, 0x7e, 0x00, 0xb7, 0xca, 0xc4, + 0x0e, 0xcd, 0x6d, 0x0f, 0xcd, 0x1d, 0x0f, 0xcd, 0xd2, 0x0e, 0xc1, 0x11, 0x20, + 0x00, 0xdd, 0x19, 0x10, 0xd9, 0x2a, 0x09, 0xc2, 0x36, 0xd0, 0xc9, 0xdd, 0x7e, + 0x00, 0xb7, 0xc8, 0xdd, 0x7e, 0x08, 0xfe, 0xc0, 0xd0, 0x2a, 0x09, 0xc2, 0x77, + 0x23, 0x08, 0xdd, 0x7e, 0x0c, 0xfe, 0x0c, 0x28, 0x12, 0x22, 0x09, 0xc2, 0x2b, + 0xcb, 0x25, 0xcb, 0xfd, 0xdd, 0x7e, 0x07, 0x77, 0x23, 0xdd, 0x7e, 0x0c, 0x77, + 0xc9, 0x08, 0x06, 0x04, 0xe5, 0xd6, 0x08, 0x77, 0x23, 0x10, 0xfa, 0x22, 0x09, + 0xc2, 0xe1, 0x2b, 0xcb, 0x25, 0xcb, 0xfd, 0x06, 0x05, 0xdd, 0x4e, 0x07, 0x08, + 0x71, 0x23, 0x77, 0x23, 0x3d, 0x10, 0xf9, 0xc9, 0xdd, 0x7e, 0x0a, 0xdd, 0x86, + 0x08, 0xdd, 0x77, 0x08, 0xc9, 0xaf, 0xdd, 0xe5, 0xe1, 0x77, 0x2c, 0x77, 0x2c, + 0x77, 0x2c, 0x36, 0x01, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, + 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, + 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, + 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, + 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x4f, 0xc9, 0x3a, 0x28, 0xc2, + 0xdd, 0x56, 0x09, 0x82, 0x57, 0xdd, 0x86, 0x07, 0xdd, 0x77, 0x07, 0xcb, 0x7a, + 0x20, 0x03, 0x38, 0xa6, 0xc9, 0x30, 0xa3, 0xc9, 0x46, 0x23, 0x50, 0xdd, 0x35, + 0x03, 0xdd, 0x7e, 0x02, 0x20, 0x0e, 0xdd, 0x5e, 0x04, 0xdd, 0x73, 0x03, 0x3c, + 0xba, 0x38, 0x01, 0xaf, 0xdd, 0x77, 0x02, 0x4f, 0x06, 0x00, 0x09, 0x7e, 0xdd, + 0x77, 0x0c, 0xc9, 0x46, 0x23, 0x50, 0xdd, 0x7e, 0x02, 0x18, 0xef, 0xe6, 0x0f, + 0x87, 0x5f, 0x16, 0x00, 0x19, 0x7e, 0x23, 0x66, 0x6f, 0xe9, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x94, 0x97, 0x98, 0x94, 0x94, 0x94, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0x00, 0xa5, 0xa6, 0xa7, + 0xa8, 0x9f, 0xa0, 0xa1, 0xa2, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0x00, 0xb7, 0xb8, 0xb9, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, + 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xc2, 0xc3, 0xc4, 0xc5, 0xcd, + 0xce, 0xcf, 0x89, 0x07, 0x1c, 0x30, 0x60, 0x41, 0xc6, 0x84, 0x88, 0xff, 0x03, + 0x00, 0x81, 0xff, 0x03, 0x00, 0x89, 0xe1, 0x27, 0x2c, 0x38, 0xf0, 0x31, 0x21, + 0x22, 0xff, 0x03, 0x00, 0x95, 0x7f, 0x80, 0x00, 0x00, 0xf8, 0x09, 0x0b, 0x0e, + 0xfc, 0x0c, 0x08, 0x08, 0x7f, 0xc0, 0x00, 0x00, 0x1f, 0x60, 0x40, 0x80, 0xfe, + 0x03, 0x02, 0x81, 0xfe, 0x03, 0x02, 0xa8, 0x03, 0x0e, 0x08, 0x18, 0x11, 0x31, + 0x22, 0x22, 0xe0, 0x39, 0x0f, 0x0e, 0xc6, 0x46, 0x22, 0x23, 0xfc, 0x86, 0x7b, + 0x8d, 0xb5, 0x8d, 0xb5, 0x7b, 0x88, 0x88, 0x84, 0xc6, 0x41, 0x60, 0x30, 0x1c, + 0xff, 0x07, 0x01, 0x00, 0xf0, 0x0c, 0x04, 0x02, 0x04, 0xe2, 0x85, 0x63, 0x62, + 0x22, 0x22, 0x3f, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, 0x81, 0xf8, 0x03, 0x18, + 0x81, 0xf8, 0x03, 0x18, 0x81, 0x8f, 0x03, 0x88, 0x81, 0x8f, 0x03, 0x88, 0x81, + 0xfe, 0x03, 0x02, 0x88, 0xe2, 0x22, 0x23, 0x23, 0x62, 0x44, 0x44, 0xc4, 0x03, + 0x88, 0x82, 0x11, 0x23, 0x03, 0x11, 0x03, 0x88, 0x84, 0xc4, 0x86, 0xfc, 0x00, + 0x03, 0x80, 0x83, 0xc0, 0x40, 0xff, 0x03, 0x80, 0x81, 0xff, 0x03, 0x80, 0x95, + 0xe2, 0x02, 0x04, 0x0c, 0xf0, 0x00, 0x01, 0x07, 0x22, 0x22, 0x21, 0x71, 0x70, + 0xd8, 0x8c, 0x07, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x03, 0x00, 0x90, 0xf8, 0x08, + 0x08, 0x0c, 0xfc, 0x0e, 0x0b, 0x09, 0x8e, 0x80, 0x40, 0x60, 0x1f, 0x00, 0x00, + 0xc0, 0x02, 0x23, 0x02, 0x22, 0x81, 0xe2, 0x03, 0x00, 0x85, 0x11, 0x10, 0x22, + 0x22, 0x23, 0x03, 0x46, 0x85, 0xc4, 0x04, 0x02, 0x02, 0xfe, 0x03, 0x00, 0x85, + 0x40, 0x60, 0x20, 0x20, 0x30, 0x03, 0x10, 0x81, 0xff, 0x07, 0x00, 0x81, 0xfc, + 0x07, 0x00, 0x81, 0x01, 0x07, 0x00, 0x81, 0xf8, 0x07, 0x00, 0x81, 0x7f, 0x07, + 0x00, 0x81, 0xf0, 0x07, 0x00, 0x81, 0x7c, 0x04, 0x3c, 0x02, 0x3e, 0x82, 0x36, + 0x1f, 0x04, 0x1e, 0x02, 0x3e, 0x81, 0x2e, 0x03, 0x01, 0x03, 0x03, 0x02, 0x06, + 0x03, 0xe0, 0x02, 0x70, 0x96, 0x78, 0x38, 0x38, 0x03, 0x0f, 0x1c, 0x18, 0x38, + 0x38, 0x3c, 0x3f, 0x90, 0xf1, 0x31, 0x1b, 0x0a, 0x08, 0x00, 0x80, 0xff, 0xff, + 0xdd, 0x05, 0x1c, 0x85, 0x87, 0xc3, 0xc3, 0x63, 0x23, 0x03, 0x03, 0x02, 0xff, + 0x82, 0x83, 0x81, 0x02, 0x80, 0x02, 0x84, 0x82, 0x1f, 0x0f, 0x03, 0x8e, 0x03, + 0x0e, 0x84, 0xf0, 0xf8, 0x3c, 0x0c, 0x03, 0x0e, 0x8d, 0x0c, 0x07, 0x1f, 0x38, + 0x30, 0x70, 0x70, 0x78, 0x7f, 0x27, 0xe3, 0x61, 0x31, 0x02, 0x10, 0x02, 0x00, + 0x82, 0xc3, 0x81, 0x02, 0xc3, 0x02, 0xe6, 0x02, 0x7c, 0x8a, 0xc3, 0x8f, 0x1c, + 0x18, 0x38, 0x38, 0x3c, 0x3f, 0x1f, 0x0f, 0x03, 0x8f, 0x02, 0x0f, 0x81, 0x0d, + 0x05, 0x07, 0x02, 0x8f, 0x82, 0x8b, 0xc0, 0x07, 0x80, 0x81, 0x36, 0x02, 0x37, + 0x04, 0x33, 0x85, 0x31, 0x2e, 0x6e, 0x6e, 0x4e, 0x03, 0xce, 0x9d, 0x8e, 0x06, + 0x06, 0x0c, 0x0f, 0x0f, 0x0c, 0x18, 0x18, 0x38, 0x3c, 0x1c, 0xfc, 0xfc, 0x1e, + 0x0e, 0x0e, 0x1f, 0x0f, 0x03, 0x00, 0x20, 0x20, 0x30, 0x18, 0xe0, 0xf0, 0xf0, + 0x78, 0x03, 0x38, 0x81, 0x70, 0x08, 0x1c, 0x08, 0x03, 0x02, 0xfc, 0x02, 0x84, + 0x02, 0x80, 0x83, 0x81, 0x83, 0x0e, 0x02, 0x0f, 0x02, 0x0e, 0x86, 0xce, 0x8e, + 0x8e, 0x3c, 0xf8, 0xf0, 0x02, 0x38, 0x02, 0x1c, 0x8d, 0x0e, 0x3f, 0x1f, 0x07, + 0x00, 0x40, 0x40, 0x60, 0x30, 0xc0, 0xe0, 0xe0, 0xf0, 0x03, 0x70, 0x81, 0xe0, + 0x08, 0x38, 0x03, 0x0d, 0x02, 0x0c, 0x87, 0xcc, 0x8c, 0x8c, 0x8b, 0xdb, 0xdb, + 0xd3, 0x03, 0xf3, 0x81, 0x63, 0x08, 0x80, 0x82, 0x31, 0x79, 0x06, 0x00, 0x82, + 0x8e, 0x9f, 0x06, 0x00, 0x82, 0x18, 0x3c, 0x06, 0x00, 0x82, 0x0e, 0x1f, 0x06, + 0x00, 0x82, 0x1f, 0x13, 0x06, 0x00, 0x82, 0xe0, 0xc0, 0x06, 0x00, 0x82, 0x1c, + 0x3e, 0x06, 0x00, 0x82, 0x03, 0x07, 0x06, 0x00, 0x02, 0xff, 0x06, 0x00, 0x82, + 0x0e, 0x1f, 0x06, 0x00, 0x82, 0x0e, 0x07, 0x0e, 0x00, 0x82, 0x3f, 0x27, 0x06, + 0x00, 0x82, 0xc0, 0x80, 0x06, 0x00, 0x82, 0x38, 0xfe, 0x06, 0x00, 0x82, 0x1f, + 0x13, 0x06, 0x00, 0x82, 0x0c, 0x1e, 0x06, 0x00, 0x82, 0x63, 0x67, 0x06, 0x00, + 0x82, 0x80, 0xc0, 0x06, 0x00, 0x00, 0x89, 0x07, 0x1c, 0x30, 0x60, 0x41, 0xc6, + 0x84, 0x88, 0xff, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, 0x89, 0xe1, 0x27, 0x2c, + 0x38, 0xf0, 0x31, 0x21, 0x22, 0xff, 0x03, 0x00, 0x95, 0x7f, 0x80, 0x00, 0x00, + 0xf8, 0x09, 0x0b, 0x0e, 0xfc, 0x0c, 0x08, 0x08, 0x7f, 0xc0, 0x00, 0x00, 0x1f, + 0x60, 0x40, 0x80, 0xfe, 0x03, 0x02, 0x81, 0xfe, 0x03, 0x02, 0xa8, 0x03, 0x0e, + 0x08, 0x18, 0x11, 0x31, 0x22, 0x22, 0xe0, 0x39, 0x0f, 0x0e, 0xc6, 0x46, 0x22, + 0x23, 0xfc, 0x86, 0x7b, 0x8d, 0xb5, 0x8d, 0xb5, 0x7b, 0x88, 0x88, 0x84, 0xc6, + 0x41, 0x60, 0x30, 0x1c, 0xff, 0x07, 0x01, 0x00, 0xf0, 0x0c, 0x04, 0x02, 0x04, + 0xe2, 0x85, 0x63, 0x62, 0x22, 0x22, 0x3f, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, + 0x81, 0xf8, 0x03, 0x18, 0x81, 0xf8, 0x03, 0x18, 0x81, 0x8f, 0x03, 0x88, 0x81, + 0x8f, 0x03, 0x88, 0x81, 0xfe, 0x03, 0x02, 0x88, 0xe2, 0x22, 0x23, 0x23, 0x62, + 0x44, 0x44, 0xc4, 0x03, 0x88, 0x82, 0x11, 0x23, 0x03, 0x11, 0x03, 0x88, 0x84, + 0xc4, 0x86, 0xfc, 0x00, 0x03, 0x80, 0x83, 0xc0, 0x40, 0xff, 0x03, 0x80, 0x81, + 0xff, 0x03, 0x80, 0x95, 0xe2, 0x02, 0x04, 0x0c, 0xf0, 0x00, 0x01, 0x07, 0x22, + 0x22, 0x21, 0x71, 0x70, 0xd8, 0x8c, 0x07, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x03, + 0x00, 0x90, 0xf8, 0x08, 0x08, 0x0c, 0xfc, 0x0e, 0x0b, 0x09, 0x8e, 0x80, 0x40, + 0x60, 0x1f, 0x00, 0x00, 0xc0, 0x02, 0x23, 0x02, 0x22, 0x81, 0xe2, 0x03, 0x00, + 0x85, 0x11, 0x10, 0x22, 0x22, 0x23, 0x03, 0x46, 0x85, 0xc4, 0x04, 0x02, 0x02, + 0xfe, 0x03, 0x00, 0x85, 0x40, 0x60, 0x20, 0x20, 0x30, 0x03, 0x10, 0x81, 0xff, + 0x07, 0x00, 0x81, 0xfc, 0x07, 0x00, 0x81, 0x01, 0x07, 0x00, 0x81, 0xf8, 0x07, + 0x00, 0x81, 0x7f, 0x07, 0x00, 0x81, 0xf0, 0x07, 0x00, 0x97, 0x80, 0x40, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, + 0x80, 0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x94, 0x10, 0x80, 0x08, + 0x00, 0x40, 0x00, 0x04, 0x10, 0x02, 0x24, 0x04, 0x04, 0x02, 0x00, 0x41, 0x00, + 0x4a, 0x20, 0x11, 0x10, 0x04, 0x00, 0x82, 0x22, 0x80, 0x04, 0x00, 0x85, 0x48, + 0x04, 0x20, 0x80, 0x40, 0x05, 0x00, 0x88, 0x04, 0x02, 0x01, 0x00, 0x00, 0x08, + 0x20, 0x90, 0x06, 0x00, 0xaa, 0x08, 0x04, 0x40, 0x12, 0x10, 0x00, 0x10, 0x12, + 0x08, 0x20, 0x04, 0x48, 0x08, 0x08, 0x04, 0x00, 0x88, 0x04, 0x92, 0x40, 0x21, + 0x20, 0x00, 0x00, 0x24, 0x42, 0x00, 0x24, 0x01, 0x18, 0x82, 0x00, 0x24, 0x50, + 0x82, 0x24, 0x04, 0x04, 0x02, 0x00, 0x20, 0x90, 0x05, 0x00, 0x81, 0x02, 0x04, + 0x00, 0x86, 0x88, 0x00, 0x00, 0x04, 0x20, 0x40, 0x06, 0x00, 0x84, 0x01, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x85, 0x02, 0x40, 0x00, 0x00, 0xa0, 0x03, 0x00, 0x90, + 0x40, 0x00, 0x08, 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x04, 0x00, 0x20, 0x00, + 0x02, 0x00, 0x10, 0x05, 0x00, 0x02, 0x10, 0x86, 0x08, 0x20, 0x00, 0x00, 0x08, + 0x80, 0x03, 0x40, 0x81, 0x88, 0x12, 0x00, 0x81, 0x08, 0x0b, 0x00, 0x8a, 0x40, + 0x00, 0x40, 0x04, 0x08, 0x40, 0x44, 0x20, 0x02, 0x10, 0x03, 0x00, 0x89, 0x01, + 0x20, 0x20, 0x10, 0x41, 0x00, 0x00, 0x10, 0x00, 0x03, 0x80, 0x82, 0x10, 0x44, + 0x0a, 0x00, 0x89, 0x01, 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x00, 0x28, 0x03, + 0x00, 0x81, 0x90, 0x08, 0x00, 0x82, 0x48, 0x84, 0x06, 0x00, 0x82, 0x11, 0x20, + 0x06, 0x00, 0x82, 0x24, 0xc2, 0x06, 0x00, 0x82, 0x11, 0x20, 0x07, 0x00, 0x81, + 0x84, 0x06, 0x00, 0x82, 0x10, 0x20, 0x06, 0x00, 0x82, 0x22, 0x41, 0x06, 0x00, + 0x82, 0x04, 0x08, 0x0e, 0x00, 0x82, 0x91, 0x20, 0x06, 0x00, 0x82, 0x01, 0x88, + 0x07, 0x00, 0x81, 0x80, 0x07, 0x00, 0x81, 0x08, 0x06, 0x00, 0x82, 0x20, 0x40, + 0x06, 0x00, 0x81, 0x44, 0x08, 0x00, 0x81, 0x04, 0x06, 0x00, 0x82, 0x92, 0x21, + 0x06, 0x00, 0x82, 0x04, 0x08, 0x06, 0x00, 0x82, 0x40, 0x20, 0x06, 0x00, 0x00, + 0x89, 0x00, 0x03, 0x0f, 0x1f, 0x3e, 0x39, 0x7b, 0x77, 0x00, 0x03, 0xff, 0x81, + 0x00, 0x03, 0xff, 0x89, 0x00, 0xc0, 0xc3, 0xc7, 0x0f, 0xce, 0xde, 0xdd, 0x00, + 0x03, 0xff, 0x95, 0x80, 0x7f, 0xff, 0xff, 0x00, 0xf0, 0xf0, 0xf1, 0x03, 0xf3, + 0xf7, 0xf7, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x9f, 0xbf, 0x7f, 0x00, 0x03, 0xfc, + 0x81, 0x00, 0x03, 0xfc, 0x82, 0x00, 0x01, 0x02, 0x07, 0x02, 0x0e, 0x02, 0x1d, + 0xa0, 0x00, 0xc0, 0xf0, 0xf1, 0x39, 0xb9, 0xdd, 0xdc, 0x00, 0x78, 0x84, 0x72, + 0x4a, 0x72, 0x4a, 0x84, 0x77, 0x77, 0x7b, 0x39, 0x3e, 0x1f, 0x0f, 0x03, 0x00, + 0xf8, 0xfe, 0xff, 0x0f, 0xf3, 0xfb, 0xfd, 0x04, 0x1d, 0x85, 0x9c, 0x9d, 0xdd, + 0xdd, 0xc0, 0x03, 0xff, 0x81, 0x00, 0x03, 0xff, 0x81, 0x07, 0x03, 0xe7, 0x81, + 0x07, 0x03, 0xe7, 0x81, 0x70, 0x03, 0x77, 0x81, 0x70, 0x03, 0x77, 0x81, 0x00, + 0x03, 0xfc, 0x81, 0x1c, 0x03, 0xdc, 0x81, 0x1d, 0x03, 0x3b, 0x03, 0x77, 0x82, + 0xee, 0xdc, 0x03, 0xee, 0x03, 0x77, 0x82, 0x3b, 0x78, 0x06, 0x00, 0x82, 0x80, + 0x00, 0x03, 0x7f, 0x81, 0x00, 0x03, 0x7f, 0x95, 0x1d, 0xfd, 0xfb, 0xf3, 0x0f, + 0xff, 0xfe, 0xf8, 0xdd, 0xdd, 0xde, 0x8e, 0x8f, 0x07, 0x03, 0x00, 0xc0, 0xff, + 0xff, 0x7f, 0x80, 0x03, 0xff, 0x90, 0x07, 0xf7, 0xf7, 0xf3, 0x03, 0xf1, 0xf0, + 0xf0, 0x71, 0x7f, 0xbf, 0x9f, 0xe0, 0xff, 0xff, 0x3f, 0x02, 0xdc, 0x02, 0xdd, + 0x81, 0x1d, 0x03, 0xff, 0x85, 0xee, 0xef, 0xdd, 0xdd, 0xdc, 0x03, 0xb9, 0x85, + 0x3b, 0xfb, 0xfd, 0xfd, 0x01, 0x03, 0xff, 0x02, 0x80, 0x03, 0xc0, 0x03, 0xe0, + 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0x00, 0x7f, 0x00, 0x7f, 0x00, + 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x55, 0x00, 0x00, 0x08, 0x00, 0x07, 0xff, + 0x81, 0xfe, 0x07, 0xff, 0x81, 0x00, 0x0f, 0xfe, 0x8f, 0x00, 0x81, 0xc3, 0xe7, + 0xff, 0xff, 0xc1, 0x81, 0x91, 0x91, 0x99, 0x81, 0xc3, 0xc3, 0x81, 0x03, 0x99, + 0x85, 0x81, 0xc3, 0xc3, 0x81, 0x99, 0x02, 0x81, 0x02, 0x99, 0x04, 0x8f, 0x02, + 0x81, 0x84, 0xff, 0x7e, 0x3c, 0x18, 0x04, 0x00, 0x81, 0x78, 0x04, 0xfc, 0x84, + 0x78, 0x2a, 0x00, 0x78, 0x04, 0xfc, 0x84, 0x78, 0x54, 0x00, 0x1e, 0x04, 0x3f, + 0x84, 0x1e, 0x54, 0x00, 0x1e, 0x04, 0x3f, 0xa3, 0x1e, 0x2a, 0x00, 0x1e, 0x7f, + 0x3f, 0x7f, 0x3f, 0x5e, 0x00, 0x00, 0x1e, 0x3f, 0x7f, 0x3f, 0x7f, 0x1e, 0x40, + 0x00, 0x00, 0x02, 0x78, 0xfe, 0xfc, 0xfe, 0xfc, 0x78, 0x00, 0x00, 0x7a, 0xfc, + 0xfe, 0xfc, 0xfe, 0x78, 0x00, 0x07, 0x00, 0x81, 0xff, 0x07, 0x00, 0x81, 0x01, + 0x07, 0x00, 0x81, 0xff, 0x0f, 0x01, 0x84, 0xff, 0x81, 0xc3, 0xe7, 0x1e, 0xff, + 0x83, 0x7e, 0x3c, 0x18, 0x04, 0x00, 0xc0, 0x78, 0xcc, 0xb5, 0xac, 0xc4, 0x78, + 0x00, 0x00, 0x78, 0xcc, 0xb4, 0xad, 0xc4, 0x78, 0x00, 0x00, 0x1e, 0x33, 0xad, + 0x35, 0x23, 0x1e, 0x00, 0x00, 0x1e, 0x33, 0x2d, 0xb5, 0x23, 0x1e, 0x00, 0x00, + 0x1e, 0x33, 0x2d, 0x25, 0x2b, 0x1e, 0x00, 0x08, 0x1e, 0x33, 0x2d, 0x25, 0x2b, + 0x1e, 0x00, 0x04, 0x20, 0x00, 0x78, 0xd4, 0xa4, 0xb4, 0xcc, 0x78, 0x10, 0x00, + 0x78, 0xd4, 0xa4, 0xb4, 0xcc, 0x78, 0x00, 0x07, 0x00, 0x21, 0xff, 0x8e, 0x81, + 0xc3, 0xe7, 0xff, 0xff, 0xc1, 0xbf, 0xf1, 0xff, 0xff, 0xe7, 0xff, 0xc3, 0xbd, + 0x03, 0xff, 0x86, 0xe7, 0xff, 0xc3, 0xbd, 0xff, 0xe7, 0x03, 0xff, 0x81, 0x8f, + 0x03, 0xff, 0x86, 0xf1, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x05, 0x00, 0xbf, 0x30, + 0x49, 0x51, 0x3b, 0x07, 0xfe, 0x00, 0x00, 0x30, 0x48, 0x51, 0x3b, 0x07, 0xfe, + 0x00, 0x00, 0x0c, 0x92, 0x8a, 0xdc, 0xe0, 0x7f, 0x00, 0x00, 0x0c, 0x12, 0x8a, + 0xdc, 0xe0, 0x7f, 0x00, 0x40, 0x4c, 0x52, 0x5a, 0x54, 0x60, 0x70, 0x38, 0x40, + 0x4c, 0x52, 0x5a, 0x54, 0x60, 0x70, 0x3c, 0x3c, 0x0e, 0x06, 0x2a, 0x5a, 0x4a, + 0x32, 0x02, 0x1c, 0x0e, 0x06, 0x2a, 0x5a, 0x4a, 0x32, 0x02, 0x00, 0x7f, 0x00, + 0x11, 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, 0x7c, 0xfc, + 0xe0, 0xf8, 0x7c, 0x1c, 0xfc, 0xf8, 0x7c, 0xfc, 0xc0, 0xf8, 0xf8, 0xc0, 0xfc, + 0x7c, 0x7c, 0xfc, 0xc0, 0xdc, 0xdc, 0xcc, 0xfc, 0x7c, 0x38, 0x38, 0x7c, 0x5c, + 0x5c, 0xce, 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x00, 0x18, 0x3e, 0x58, + 0x3c, 0x1a, 0x7c, 0x18, 0x00, 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x70, 0xc8, 0xc8, 0x70, 0x9a, 0x8c, 0x76, 0x00, 0x18, 0x18, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, + 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x18, 0x5a, 0x3c, 0x3c, 0x5a, 0x18, + 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, + 0xc0, 0x00, 0x38, 0x4c, 0xc6, 0xc6, 0xc6, 0x64, 0x38, 0x00, 0x18, 0x38, 0x18, + 0x18, 0x18, 0x18, 0x7e, 0x00, 0x7c, 0xc6, 0x0e, 0x3c, 0x78, 0xe0, 0xfe, 0x00, + 0x7e, 0x0c, 0x18, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, + 0x0c, 0x0c, 0x00, 0xfc, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x3c, 0x60, + 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, + 0x00, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, + 0x06, 0x0c, 0x78, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, + 0x0c, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, + 0x0c, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0x06, 0x1c, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0x06, 0x66, 0xd6, 0xd6, 0x7c, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, + 0xc6, 0xc6, 0x00, 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00, 0x3c, 0x66, + 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, + 0x00, 0xfe, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xfe, 0x00, 0xfe, 0xc0, 0xc0, 0xf8, + 0xc0, 0xc0, 0xc0, 0x00, 0x3e, 0x60, 0xc0, 0xce, 0xc6, 0x66, 0x3e, 0x00, 0xc6, + 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x7e, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0xc6, 0xcc, 0xd8, + 0xf0, 0xf8, 0xdc, 0xce, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, + 0xce, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xfc, 0xc6, + 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xcc, 0x76, + 0x00, 0xfc, 0xc6, 0xc6, 0xce, 0xf8, 0xdc, 0xce, 0x00, 0x78, 0xcc, 0xc0, 0x7c, + 0x06, 0xc6, 0x7c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xee, 0x7c, 0x38, + 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x44, 0x00, 0xc6, 0xee, 0x7c, + 0x38, 0x7c, 0xee, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, + 0xfe, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xfe, 0x00, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xf8, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0xf8, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x20, 0x50, 0x88, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x21, 0x00, + 0x08, 0xff, 0x00, 0x7f, 0x00, 0x29, 0x00, 0x00, 0x7f, 0x00, 0x21, 0x00, 0x08, + 0xff, 0x00, 0x02, 0xff, 0x05, 0xf0, 0x81, 0xff, 0x02, 0xf8, 0x05, 0x00, 0x81, + 0xe0, 0x02, 0xf8, 0x03, 0xfc, 0x03, 0xf6, 0x08, 0x78, 0x02, 0x1f, 0x06, 0x03, + 0x82, 0xf1, 0xf3, 0x06, 0xc3, 0x02, 0xff, 0x06, 0xc0, 0x81, 0xe7, 0x02, 0xf3, + 0x02, 0xf1, 0x03, 0xf0, 0x02, 0x80, 0x02, 0xc1, 0x02, 0xe3, 0x83, 0xf7, 0x7f, + 0xf0, 0x02, 0xe0, 0x02, 0xc0, 0x02, 0x80, 0x82, 0x00, 0xff, 0x05, 0xf0, 0x02, + 0xff, 0x81, 0xe0, 0x05, 0x00, 0x02, 0xf8, 0x03, 0xf3, 0x03, 0xf1, 0x02, 0xf0, + 0x02, 0x78, 0x81, 0x79, 0x04, 0xf9, 0x81, 0xf8, 0x02, 0x03, 0x04, 0xe3, 0x02, + 0xff, 0x07, 0xc3, 0x81, 0x81, 0x06, 0xc0, 0x02, 0xff, 0x07, 0xf0, 0x82, 0xe0, + 0x7f, 0x07, 0x3e, 0x04, 0x78, 0x02, 0x00, 0x02, 0x78, 0x08, 0x00, 0x00, 0xb8, + 0x60, 0xf0, 0x41, 0x03, 0x0d, 0x00, 0x0d, 0xc3, 0x00, 0x50, 0x8d, 0x43, 0x78, + 0x77, 0x79, 0x5d, 0x03, 0xad, 0xd1, 0x10, 0x50, 0x55, 0x64, 0x65, 0x40, 0x51, + 0x2d, 0x35, 0x24, 0x22, 0x81, 0x81, 0x43, 0x55, 0x41, 0x05, 0x75, 0xfb, 0x40, + 0x00, 0x52, 0x68, 0x8d, 0xc5, 0x22, 0x2e, 0xcd, 0x0c, 0x14, 0x94, 0x35, 0xd1, + 0x43, 0x7b, 0x51, 0x01, 0xe1, 0x56, 0x45, 0x63, 0x50, 0x6d, 0x18, 0x41, 0x8e, + 0x5b, 0x5d, 0x1e, 0x98, 0x10, 0xd4, 0x12, 0x34, 0x6e, 0x55, 0xeb, 0x48, 0x47, + 0x5b, 0x04, 0x74, 0x5b, 0x85, 0x4d, 0x83, 0xb6, 0x2d, 0xd1, 0x58, 0x6d, 0x35, + 0x92, 0x0e, 0xd8, 0x42, 0x04, 0x2d, 0x92, 0x45, 0xd7, 0x11, 0x20, 0x06, 0x41, + 0x76, 0x63, 0x8d, 0x61, 0xd4, 0x00, 0xd8, 0x36, 0x98, 0x5d, 0xdd, 0xb4, 0xbb, + 0x77, 0xa3, 0x77, 0x0f, 0x56, 0x89, 0x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0xa8, + 0xa0, 0x58, 0xf0, 0x01, 0x4d, 0x37, 0x04, 0x1d, 0x30, 0x1e, 0xad, 0x4d, 0x11, + 0x06, 0x75, 0x08, 0x4d, 0x7b, 0x57, 0x51, 0xd4, 0x75, 0x61, 0xd3, 0xba, 0x2e, + 0xae, 0xad, 0x83, 0x69, 0x4d, 0x2e, 0xd4, 0x75, 0x5b, 0x41, 0x50, 0x1d, 0xd2, + 0x78, 0x4b, 0x18, 0x56, 0x0d, 0x6e, 0x08, 0xad, 0x23, 0xbe, 0x07, 0x55, 0x35, + 0x35, 0x34, 0xd2, 0x4e, 0xd8, 0xd2, 0x56, 0x41, 0xc5, 0x06, 0x63, 0x3b, 0x11, + 0x8d, 0x5b, 0x4d, 0xb8, 0x7b, 0xbd, 0x48, 0x44, 0x01, 0x54, 0x11, 0xd4, 0x6e, + 0xd5, 0x8e, 0x55, 0x00, 0x55, 0xed, 0x2d, 0xb8, 0x18, 0x35, 0xd6, 0xd0, 0x56, + 0x61, 0xc8, 0xed, 0xed, 0xd6, 0x38, 0x15, 0x55, 0x81, 0x4d, 0x51, 0x51, 0x63, + 0xe0, 0x82, 0x59, 0x75, 0x51, 0x6c, 0x60, 0x14, 0x53, 0x03, 0xae, 0x55, 0x23, + 0x11, 0x10, 0x05, 0x56, 0x0d, 0x58, 0x21, 0x02, 0x08, 0x08, 0x00, 0x88, 0x00, + 0xa0, 0x88, 0xb8, 0x50, 0x7d, 0x37, 0x30, 0x80, 0x77, 0x77, 0x77, 0x53, 0x15, + 0xe2, 0xe0, 0x74, 0x55, 0x55, 0x61, 0xad, 0xd5, 0x5d, 0x83, 0x55, 0x55, 0x55, + 0xb4, 0x51, 0x55, 0x55, 0x40, 0x55, 0x6d, 0xe1, 0xd5, 0x55, 0x55, 0xd5, 0x6d, + 0x55, 0x35, 0x82, 0x58, 0x55, 0x55, 0x55, 0x51, 0x55, 0xd9, 0x00, 0x54, 0x55, + 0x61, 0x55, 0x6d, 0x55, 0x14, 0x00, 0x85, 0x54, 0x8d, 0x55, 0x51, 0x21, 0xd8, + 0x00, 0x02, 0x94, 0x31, 0x88, 0x63, 0x0d, 0x2e, 0x00, 0x35, 0x58, 0xed, 0x00, + 0x5e, 0x01, 0xd5, 0x00, 0x06, 0x54, 0x11, 0x00, 0x55, 0x73, 0x38, 0x00, 0x34, + 0x58, 0x6d, 0x03, 0x56, 0x55, 0x57, 0x03, 0x08, 0x55, 0x51, 0x00, 0x88, 0x55, + 0x55, 0x00, 0x34, 0xa2, 0x2d, 0x0d, 0x00, 0x56, 0x45, 0x03, 0x0b, 0x50, 0x75, + 0x05, 0x0d, 0x21, 0x82, 0x8d, 0x0d, 0xa0, 0x21, 0x02, 0x08, 0x08, 0x00, 0x02, + 0x02, 0xa0, 0xa8, 0x58, 0x38, 0xdd, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x31, 0x50, + 0x55, 0x83, 0xc3, 0x00, 0x02, 0x40, 0x04, 0x58, 0x55, 0xd0, 0x5e, 0x03, 0x00, + 0x10, 0x01, 0x50, 0x55, 0xa3, 0x65, 0xcd, 0x00, 0xd5, 0xd0, 0x6d, 0x85, 0x0c, + 0x8e, 0x56, 0x03, 0x46, 0x8b, 0x98, 0xd5, 0x36, 0x01, 0x88, 0xd0, 0x00, 0x0d, + 0x54, 0x15, 0xd8, 0x0d, 0xd0, 0x60, 0x83, 0x05, 0x51, 0xd5, 0x6d, 0x35, 0x64, + 0x53, 0x74, 0xb5, 0x54, 0x55, 0xb5, 0xd5, 0xb5, 0x14, 0x55, 0xd5, 0x55, 0x55, + 0xd5, 0x56, 0x45, 0x45, 0x6d, 0x55, 0x55, 0x55, 0x55, 0x5b, 0x81, 0x21, 0x16, + 0x88, 0x55, 0x45, 0x65, 0x55, 0x41, 0x0d, 0x08, 0x74, 0x55, 0x71, 0x15, 0x52, + 0x80, 0xf5, 0x00, 0x55, 0x55, 0x6d, 0x48, 0x07, 0x00, 0x58, 0x43, 0x55, 0x57, + 0x85, 0x8f, 0x35, 0x00, 0x60, 0x8d, 0x55, 0x55, 0x01, 0x02, 0x22, 0x00, 0x00, + 0x0a, 0x20, 0xa2, 0x40, 0xb0, 0xf0, 0x31, 0xf4, 0x3d, 0xd0, 0xd0, 0x1e, 0xd1, + 0x94, 0x4d, 0x55, 0xd8, 0x45, 0x87, 0x7b, 0x2d, 0x59, 0xb5, 0x61, 0x87, 0x11, + 0x02, 0x12, 0xd2, 0x50, 0x05, 0x1e, 0x36, 0x4e, 0x43, 0xe0, 0x84, 0x57, 0x45, + 0x0b, 0x0b, 0xc5, 0x1e, 0x44, 0xfb, 0x5a, 0x41, 0x53, 0x80, 0x12, 0x45, 0xbb, + 0x60, 0x97, 0x8d, 0xee, 0xd0, 0xd3, 0x52, 0xe0, 0x8d, 0x55, 0x4d, 0x3b, 0x6e, + 0x2e, 0x2d, 0xb4, 0xf4, 0xa2, 0x85, 0xee, 0x13, 0x78, 0x46, 0xdb, 0x18, 0x5e, + 0x35, 0x85, 0xed, 0x2d, 0x81, 0x63, 0xe4, 0x98, 0x8d, 0xd1, 0x92, 0x10, 0x8d, + 0x1d, 0xb4, 0x6d, 0x51, 0x60, 0xe3, 0x4d, 0xd1, 0x06, 0x08, 0x91, 0x6d, 0x93, + 0x50, 0xb8, 0x87, 0x7b, 0x37, 0x56, 0x7d, 0x45, 0xa4, 0xd7, 0x76, 0xac, 0x45, + 0xaf, 0x15, 0x12, 0xcd, 0x16, 0x15, 0xd1, 0x82, 0x55, 0x09, 0x20, 0x88, 0x20, + 0x82, 0x00, 0x20, 0xa2, 0xb0, 0x80, 0x68, 0x0d, 0x40, 0x0f, 0x0d, 0x11, 0x74, + 0x03, 0x50, 0x35, 0x5d, 0x75, 0x75, 0x35, 0x60, 0x01, 0xa0, 0x55, 0x55, 0x55, + 0x55, 0x75, 0x80, 0x34, 0x50, 0x55, 0x55, 0x56, 0x55, 0x18, 0xd0, 0x40, 0x97, + 0x55, 0x15, 0x58, 0x18, 0xd0, 0x21, 0x50, 0x55, 0x55, 0x08, 0x20, 0x00, 0x58, + 0xdd, 0x54, 0x95, 0x05, 0x00, 0xf4, 0x00, 0x54, 0x55, 0x65, 0x55, 0x75, 0xf7, + 0x55, 0x03, 0x55, 0x55, 0x8d, 0x55, 0x21, 0x62, 0x55, 0x41, 0x55, 0x15, 0x75, + 0x55, 0x0d, 0x80, 0x55, 0x80, 0xb5, 0x48, 0x55, 0x95, 0x05, 0x70, 0x15, 0x00, + 0x06, 0x13, 0x5a, 0x65, 0x01, 0x54, 0x05, 0x00, 0x41, 0x05, 0x6c, 0x5d, 0x0d, + 0x55, 0x01, 0xd0, 0x5e, 0x08, 0x78, 0x55, 0x05, 0x66, 0x0d, 0x54, 0x1b, 0x00, + 0x54, 0x55, 0x71, 0x83, 0x01, 0x56, 0xed, 0x00, 0x25, 0x5a, 0x21, 0x02, 0x00, + 0x20, 0x82, 0x00, 0x02, 0xa0, 0x78, 0x70, 0x78, 0x0d, 0x00, 0x38, 0x03, 0x00, + 0xe0, 0x00, 0x50, 0x35, 0x00, 0x44, 0x00, 0x00, 0x00, 0x34, 0xad, 0xd5, 0x00, + 0xb8, 0x23, 0x00, 0x40, 0x5b, 0x51, 0x15, 0x00, 0x44, 0x0d, 0x00, 0xb4, 0x54, + 0xad, 0x55, 0x03, 0xb8, 0x35, 0x00, 0x45, 0x1b, 0x52, 0x55, 0x00, 0x80, 0x14, + 0x4d, 0x81, 0x54, 0xa3, 0x55, 0x03, 0x00, 0x88, 0xb8, 0x1d, 0x18, 0x5e, 0x6d, + 0x0d, 0x37, 0x1c, 0x40, 0x08, 0x00, 0x55, 0xb5, 0x75, 0xe1, 0xd8, 0x80, 0x0d, + 0x00, 0x56, 0x55, 0x55, 0x81, 0xd7, 0x00, 0x02, 0x00, 0x55, 0x55, 0x55, 0x41, + 0x55, 0xc0, 0xdd, 0x8d, 0x55, 0x55, 0x61, 0x5d, 0xd5, 0x50, 0x55, 0xdd, 0x55, + 0x55, 0x80, 0x55, 0x59, 0x63, 0x55, 0x55, 0x58, 0x15, 0x03, 0x4a, 0x5d, 0x50, + 0x89, 0x55, 0xa3, 0x45, 0x00, 0x50, 0x58, 0x63, 0x00, 0x88, 0x50, 0x01, 0x00, + 0x00, 0x88, 0x00, 0x20, 0x00, 0xa0, 0x78, 0x48, 0xe0, 0xdd, 0x00, 0xdd, 0x40, + 0x34, 0x77, 0x03, 0x50, 0x55, 0x43, 0x55, 0x03, 0xd6, 0x16, 0x8e, 0xa4, 0x85, + 0x5d, 0x54, 0x00, 0x55, 0x01, 0x00, 0x51, 0x41, 0x15, 0x56, 0x03, 0x56, 0xd0, + 0x40, 0x57, 0x4d, 0x45, 0x88, 0x00, 0x18, 0x60, 0x53, 0x55, 0xb5, 0x50, 0x03, + 0x0c, 0xd4, 0x5d, 0x85, 0x55, 0x05, 0xd5, 0xde, 0xe1, 0x55, 0x58, 0x01, 0x56, + 0x71, 0x15, 0x88, 0x5d, 0x95, 0x63, 0x00, 0x58, 0x6d, 0xd5, 0x00, 0x56, 0x35, + 0xde, 0x10, 0x94, 0x51, 0x15, 0x00, 0x55, 0x05, 0x55, 0xe3, 0x55, 0x6d, 0xd8, + 0x8c, 0x56, 0x7b, 0x55, 0x50, 0xad, 0x15, 0xa0, 0xfb, 0x55, 0x60, 0x15, 0x54, + 0x55, 0xd5, 0x70, 0x5d, 0x88, 0x80, 0xd5, 0x58, 0x55, 0x85, 0x63, 0x15, 0x0e, + 0x00, 0x5a, 0x63, 0x58, 0x75, 0x50, 0x35, 0x78, 0x77, 0x57, 0x80, 0x57, 0x21, + 0xa0, 0x08, 0x20, 0x22, 0x22, 0x00, 0xa2, 0x58, 0xb0, 0xe8, 0x0d, 0x34, 0xb0, + 0xb7, 0xc7, 0xe0, 0xec, 0x5d, 0x35, 0xe1, 0x44, 0xd1, 0x12, 0x34, 0x51, 0x55, + 0x11, 0x10, 0xb5, 0x2e, 0xed, 0x51, 0x84, 0x55, 0x31, 0x04, 0x06, 0x75, 0x81, + 0x6d, 0xcb, 0x96, 0x1d, 0xd4, 0x51, 0x11, 0x1e, 0xb8, 0x10, 0x55, 0xc5, 0x55, + 0x60, 0x20, 0xfb, 0x40, 0x63, 0x98, 0xb5, 0x2e, 0xb4, 0x47, 0xad, 0x53, 0x51, + 0x6f, 0x45, 0x38, 0xd8, 0x62, 0xd1, 0x96, 0x20, 0x52, 0x51, 0x04, 0x6d, 0x43, + 0x24, 0xed, 0xdd, 0xa0, 0x15, 0xd0, 0xb6, 0x8d, 0x3b, 0x82, 0x1b, 0x50, 0x05, + 0x11, 0xd8, 0x42, 0x05, 0x41, 0xed, 0x6d, 0x4d, 0x04, 0x54, 0xd3, 0xbe, 0x8d, + 0x51, 0x51, 0x1d, 0x38, 0x61, 0x2d, 0xd8, 0xd2, 0x6e, 0x94, 0x05, 0x2d, 0x1e, + 0x42, 0x87, 0x14, 0x82, 0x55, 0x41, 0x40, 0x0b, 0x77, 0x35, 0x7b, 0x77, 0x59, + 0x01, 0x20, 0x02, 0x22, 0x82, 0x20, 0x22, 0xa8, 0x40, 0x40, 0xe8, 0x75, 0xd3, + 0x04, 0xc3, 0x4e, 0x37, 0x0d, 0x92, 0x21, 0x24, 0xdd, 0x2e, 0x11, 0x61, 0x38, + 0x55, 0x3d, 0x75, 0x15, 0x41, 0x44, 0x4e, 0x47, 0x58, 0x59, 0x18, 0xd6, 0xbe, + 0x11, 0x34, 0x12, 0x94, 0x2d, 0xec, 0xd5, 0xd4, 0xee, 0x49, 0xd1, 0x5d, 0x01, + 0xb8, 0x98, 0x1b, 0xb4, 0x5d, 0x84, 0x68, 0xdd, 0xed, 0x60, 0xd1, 0x48, 0x28, + 0x0d, 0x50, 0x85, 0x51, 0x83, 0x14, 0x5d, 0x43, 0xd0, 0x94, 0x71, 0xa0, 0xdd, + 0xd9, 0xb6, 0x10, 0x24, 0x61, 0x2d, 0x3d, 0x86, 0x23, 0x45, 0x2f, 0x41, 0x57, + 0x71, 0x08, 0x41, 0xd1, 0xb8, 0x35, 0x1e, 0x56, 0x2d, 0x51, 0x51, 0x20, 0xed, + 0x49, 0x4b, 0x5b, 0x75, 0x54, 0x14, 0x70, 0xb6, 0x50, 0x50, 0x94, 0x15, 0xd4, + 0xd8, 0x22, 0x49, 0x27, 0x2d, 0x58, 0x49, 0x1d, 0x6c, 0x77, 0xd0, 0xd1, 0x72, + 0x57, 0x81, 0x08, 0x02, 0x22, 0x80, 0x88, 0x20, 0xa2, 0x60, 0x60, 0xf0, 0x1d, + 0xf0, 0x4d, 0x03, 0x4d, 0x74, 0x8c, 0xa3, 0x09, 0x6d, 0x50, 0x10, 0x11, 0x2d, + 0x31, 0x50, 0xcd, 0x55, 0x2d, 0x4d, 0x5d, 0x78, 0x44, 0x97, 0x91, 0x85, 0x41, + 0x4b, 0x44, 0x23, 0x35, 0x66, 0x51, 0xf8, 0x8e, 0x1d, 0x81, 0x34, 0xe1, 0x58, + 0x2d, 0x2c, 0x45, 0x49, 0x34, 0xd5, 0x8e, 0x50, 0xd1, 0x39, 0x52, 0x38, 0x49, + 0x24, 0x0d, 0x6d, 0x85, 0xdd, 0x2d, 0x44, 0x8d, 0x3b, 0x7a, 0x91, 0xc1, 0x56, + 0x04, 0x51, 0x41, 0xc4, 0x6e, 0x6c, 0x01, 0x18, 0x79, 0x84, 0x10, 0x05, 0xb8, + 0x51, 0x4d, 0x83, 0xe0, 0x40, 0x43, 0x31, 0x0d, 0x6e, 0x11, 0xee, 0x60, 0x93, + 0x10, 0x2e, 0x76, 0x50, 0xed, 0xbb, 0x83, 0xd7, 0x8d, 0xdb, 0xe8, 0x9d, 0xb1, + 0x4c, 0x43, 0x85, 0x41, 0x20, 0x8d, 0x5b, 0xed, 0x51, 0x50, 0x35, 0x5e, 0x77, + 0xf8, 0x56, 0x89, 0x20, 0x20, 0x0a, 0x88, 0x22, 0x20, 0x28, 0x40, 0x88, 0xc0, + 0x35, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x50, 0xd5, 0x00, 0x00, 0x40, 0x35, + 0x00, 0x00, 0x54, 0x55, 0x03, 0x00, 0x50, 0xd5, 0x00, 0x00, 0x55, 0x55, 0x0d, + 0x00, 0x54, 0x55, 0x03, 0x40, 0x55, 0x55, 0x35, 0x00, 0x55, 0x55, 0x0d, 0x50, + 0x55, 0x55, 0xd5, 0x40, 0x55, 0x55, 0x35, 0x54, 0x55, 0x55, 0x55, 0x53, 0x55, + 0x55, 0xd5, 0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x05, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x58, 0x55, 0x55, 0x55, + 0x56, 0x55, 0x55, 0x00, 0x60, 0x55, 0x55, 0x55, 0x5b, 0x55, 0x15, 0x00, 0x80, + 0x55, 0x55, 0x55, 0x60, 0x55, 0x05, 0x00, 0x00, 0x56, 0x55, 0x15, 0x80, 0x55, + 0x0d, 0x00, 0x00, 0x58, 0x55, 0x05, 0x00, 0x56, 0x0d, 0x00, 0x00, 0x60, 0x55, + 0x01, 0x00, 0x58, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xa0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + }; + #endregion + + #region USA System BIOS [For Use With a ROM - Displays SEGA logo, then boots ROM] + public static readonly byte[] ROMBios = + { + 0xf3, 0xed, 0x56, 0x31, 0xf0, 0xdf, 0x18, 0x65, 0xf5, 0xe7, 0xf1, 0xd3, 0xbe, + 0xc9, 0xff, 0xff, 0xe7, 0xaf, 0x0e, 0xbe, 0xed, 0xa3, 0xf5, 0xf1, 0xed, 0x79, + 0x20, 0xf8, 0xc9, 0x11, 0xe0, 0x81, 0x7b, 0xd3, 0xbf, 0x7a, 0xd3, 0xbf, 0xc9, + 0xff, 0xe7, 0x79, 0xb7, 0x28, 0x01, 0x04, 0x7d, 0xd3, 0xbe, 0x0d, 0x20, 0xfb, + 0x10, 0xf9, 0xc9, 0xff, 0xc3, 0xb7, 0x03, 0xe7, 0x79, 0xb7, 0x28, 0x01, 0x04, + 0x78, 0x41, 0x0e, 0xbe, 0xed, 0xa3, 0x20, 0xfc, 0x3d, 0x20, 0xf9, 0xc9, 0x21, + 0x00, 0xc3, 0x11, 0x00, 0x7f, 0x01, 0xbe, 0x64, 0xe7, 0xed, 0xb3, 0x21, 0x80, + 0xc3, 0x11, 0x80, 0x7f, 0x06, 0x80, 0xe7, 0xed, 0xb3, 0xc9, 0xff, 0xed, 0x45, + 0x11, 0xa0, 0x81, 0x18, 0xb3, 0x21, 0xd1, 0x08, 0x0e, 0x7f, 0x06, 0x04, 0xed, + 0xb3, 0x21, 0x80, 0x04, 0x01, 0xbf, 0x18, 0xed, 0xb3, 0xaf, 0xd3, 0xbe, 0x21, + 0x00, 0xc0, 0x11, 0x01, 0xc0, 0x01, 0xff, 0x1f, 0x36, 0x00, 0xed, 0xb0, 0x06, + 0x0e, 0xcd, 0x66, 0x03, 0x21, 0x80, 0x04, 0x01, 0xbf, 0x18, 0xed, 0xb3, 0xaf, + 0xd3, 0xbe, 0x21, 0x94, 0x03, 0x22, 0x03, 0xc2, 0x3e, 0xd0, 0x32, 0x00, 0xc3, + 0xfb, 0x3e, 0x03, 0xcd, 0x26, 0x04, 0xf3, 0x11, 0x00, 0x40, 0x01, 0x20, 0x00, + 0xef, 0xcd, 0xe6, 0x04, 0x11, 0xe0, 0x67, 0x01, 0x20, 0x00, 0xef, 0x21, 0x04, + 0x17, 0x11, 0x60, 0x43, 0x01, 0x28, 0x02, 0x3e, 0x09, 0xcd, 0x61, 0x04, 0x21, + 0x2c, 0x19, 0x11, 0x00, 0x4c, 0xcd, 0x98, 0x04, 0xaf, 0x32, 0x02, 0xc2, 0x11, + 0x16, 0x7a, 0x21, 0xbb, 0x0f, 0x01, 0x0a, 0x04, 0xcd, 0x51, 0x04, 0x3e, 0x81, + 0x32, 0x00, 0xcf, 0x11, 0xc0, 0x4e, 0x21, 0x28, 0x10, 0xcd, 0x98, 0x04, 0x21, + 0xc5, 0x15, 0x11, 0x60, 0x40, 0xcd, 0x98, 0x04, 0xcd, 0x20, 0x05, 0xcd, 0x1d, + 0x00, 0xcd, 0xfd, 0x04, 0xf3, 0x21, 0x89, 0x02, 0x11, 0x00, 0xc7, 0x01, 0xdd, + 0x00, 0xed, 0xb0, 0xc3, 0x90, 0x0b, 0xf3, 0x3a, 0x00, 0xc0, 0xb7, 0x28, 0x1a, + 0x2a, 0x70, 0xc2, 0xed, 0x5b, 0x6a, 0xc2, 0xb7, 0xed, 0x52, 0xca, 0xd1, 0xc7, + 0xcd, 0xe6, 0x04, 0x21, 0x76, 0x01, 0x06, 0x03, 0xcd, 0x6a, 0x01, 0x18, 0xfe, + 0xcd, 0x62, 0x01, 0xfb, 0x3e, 0x80, 0xcd, 0x26, 0x04, 0x3a, 0x07, 0xc2, 0xe6, + 0x31, 0xfe, 0x31, 0xca, 0x90, 0x0b, 0x18, 0xee, 0x11, 0x54, 0x7d, 0x06, 0x0b, + 0x21, 0x57, 0x01, 0xd7, 0xc9, 0x1b, 0x20, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x31, + 0x39, 0x38, 0x36, 0xcd, 0xe6, 0x04, 0x06, 0x0c, 0x21, 0xa3, 0x01, 0xc5, 0x5e, + 0x23, 0x56, 0x23, 0x46, 0x23, 0xd7, 0xc1, 0x10, 0xf5, 0xc9, 0x84, 0x78, 0x19, + 0x4d, 0x41, 0x53, 0x54, 0x45, 0x52, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x20, 0x1b, 0x20, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x31, 0x39, 0x38, 0x36, 0x04, + 0x79, 0x0e, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x34, 0x78, 0x04, 0x56, 0x31, 0x2e, 0x33, 0x84, 0x78, 0x13, + 0x57, 0x45, 0x4c, 0x43, 0x4f, 0x4d, 0x45, 0x20, 0x54, 0x4f, 0x20, 0x54, 0x48, + 0x45, 0x20, 0x53, 0x45, 0x47, 0x41, 0x04, 0x79, 0x0e, 0x4d, 0x41, 0x53, 0x54, + 0x45, 0x52, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x2e, 0xc4, 0x79, 0x19, + 0x54, 0x4f, 0x20, 0x50, 0x4c, 0x41, 0x59, 0x2c, 0x4a, 0x55, 0x53, 0x54, 0x20, + 0x46, 0x4f, 0x4c, 0x4c, 0x4f, 0x57, 0x20, 0x54, 0x48, 0x45, 0x53, 0x45, 0x44, + 0x7a, 0x0d, 0x49, 0x4e, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x53, 0x3a, 0x04, 0x7b, 0x19, 0x31, 0x2e, 0x54, 0x55, 0x52, 0x4e, 0x20, 0x4f, + 0x46, 0x46, 0x20, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x20, 0x4f, 0x4e, 0x20, 0x50, + 0x4f, 0x57, 0x45, 0x52, 0x88, 0x7b, 0x05, 0x42, 0x41, 0x53, 0x45, 0x2e, 0x04, + 0x7c, 0x1c, 0x32, 0x2e, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, 0x20, 0x43, 0x41, + 0x52, 0x44, 0x2f, 0x43, 0x41, 0x52, 0x54, 0x52, 0x49, 0x44, 0x47, 0x45, 0x20, + 0x49, 0x4e, 0x54, 0x4f, 0x88, 0x7c, 0x07, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x2e, 0x04, 0x7d, 0x1c, 0x33, 0x2e, 0x54, 0x55, 0x52, 0x4e, 0x20, 0x50, 0x4f, + 0x57, 0x45, 0x52, 0x20, 0x42, 0x41, 0x43, 0x4b, 0x20, 0x4f, 0x4e, 0x2c, 0x41, + 0x4e, 0x44, 0x2e, 0x2e, 0x2e, 0x2e, 0x92, 0x7d, 0x0d, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x63, 0x63, 0x63, 0xd2, 0x7d, 0x0d, 0x6a, + 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x00, 0x73, 0x73, 0x73, 0xdb, + 0xdc, 0x21, 0x5e, 0xc7, 0x06, 0x03, 0x3e, 0xeb, 0xd3, 0x3e, 0x7e, 0x32, 0x00, + 0xc0, 0xd3, 0x3e, 0xd9, 0xcd, 0x36, 0xc7, 0xcd, 0x31, 0xc7, 0xcd, 0x2c, 0xc7, + 0xd9, 0x23, 0x10, 0xe8, 0xaf, 0x32, 0x00, 0xc0, 0x3e, 0xeb, 0xd3, 0x3e, 0x3e, + 0xe3, 0xd3, 0x3e, 0xc9, 0x21, 0xf0, 0x1f, 0x18, 0x08, 0x21, 0xf0, 0x3f, 0x18, + 0x03, 0x21, 0xf0, 0x7f, 0x11, 0x60, 0xc2, 0x01, 0x10, 0x00, 0xed, 0xb0, 0x21, + 0x56, 0xc7, 0x11, 0x60, 0xc2, 0x06, 0x08, 0x1a, 0xbe, 0xc0, 0x23, 0x13, 0x10, + 0xf9, 0xcd, 0x61, 0xc7, 0xf1, 0x18, 0xcd, 0x54, 0x4d, 0x52, 0x20, 0x53, 0x45, + 0x47, 0x41, 0xcb, 0xab, 0x6b, 0x11, 0x00, 0x00, 0x3a, 0x6f, 0xc2, 0x4f, 0xe6, + 0xf0, 0xfe, 0x40, 0x28, 0x08, 0x2a, 0x70, 0xc2, 0x23, 0x22, 0x6a, 0xc2, 0xc9, + 0x79, 0xd6, 0x0a, 0xe6, 0x0f, 0xf5, 0x21, 0xc4, 0xc7, 0x4f, 0x06, 0x00, 0x09, + 0x46, 0x0e, 0xf0, 0x21, 0x00, 0x00, 0xcd, 0xb6, 0xc7, 0xed, 0x53, 0x70, 0xc2, + 0xf1, 0xd6, 0x04, 0xd8, 0x4f, 0x06, 0x00, 0x21, 0xcd, 0xc7, 0x09, 0x46, 0x3e, + 0x02, 0xc5, 0x32, 0xff, 0xff, 0x3c, 0xf5, 0xcd, 0xb0, 0xc7, 0xf1, 0xc1, 0x10, + 0xf3, 0xed, 0x53, 0x70, 0xc2, 0xc9, 0x01, 0x00, 0x40, 0x21, 0x00, 0x80, 0x7b, + 0x86, 0x5f, 0x7a, 0xce, 0x00, 0x57, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf3, 0xc9, + 0x1f, 0x3f, 0x7f, 0xbf, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x02, 0x06, 0x0e, 0x1e, + 0x3e, 0xeb, 0xd3, 0x3e, 0x3a, 0x00, 0xc0, 0xd3, 0x3e, 0xc3, 0x00, 0x00, 0x11, + 0x00, 0x40, 0x1b, 0x7a, 0xb3, 0x20, 0xfb, 0x10, 0xf6, 0xc9, 0x0e, 0x0d, 0x0c, + 0x0a, 0x08, 0x06, 0xf3, 0x31, 0xf0, 0xdf, 0x21, 0x00, 0xc0, 0x11, 0x01, 0xc0, + 0x01, 0xff, 0x1f, 0x36, 0x00, 0xed, 0xb0, 0x21, 0xd1, 0x08, 0x0e, 0x7f, 0x06, + 0x04, 0xed, 0xb3, 0xc3, 0x93, 0x00, 0x20, 0x00, 0xc0, 0x00, 0x3f, 0x3e, 0x3f, + 0x30, 0x30, 0x38, 0x3f, 0x37, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x30, 0x0f, 0x07, 0x16, 0x3f, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf5, 0xdb, 0xbf, 0x07, 0xd2, 0x16, 0x04, 0xc5, 0xd5, 0xe5, 0xdd, + 0xe5, 0xfd, 0xe5, 0x08, 0xd9, 0xf5, 0xc5, 0xd5, 0xe5, 0x3a, 0x0b, 0xc2, 0xb7, + 0x28, 0x0e, 0xdb, 0xdd, 0xe6, 0x10, 0x21, 0x06, 0xc2, 0x4e, 0x77, 0xa9, 0xa1, + 0xc2, 0x77, 0x03, 0x3a, 0x00, 0xc2, 0x0f, 0xf5, 0xdc, 0x4d, 0x00, 0xf1, 0x0f, + 0xdc, 0x2f, 0x04, 0x0f, 0xf5, 0xdc, 0x77, 0x05, 0xcd, 0xf0, 0x04, 0xf1, 0x0f, + 0xf5, 0xdc, 0x2a, 0x0d, 0xf1, 0x0f, 0xdc, 0x5f, 0x0d, 0xcd, 0xb8, 0x05, 0xaf, + 0x32, 0x00, 0xc2, 0xe1, 0xd1, 0xc1, 0xf1, 0x08, 0xd9, 0xfd, 0xe1, 0xdd, 0xe1, + 0xe1, 0xd1, 0xc1, 0xf1, 0xfb, 0xc9, 0xd5, 0xed, 0x5b, 0x25, 0xc2, 0x16, 0x88, + 0xe7, 0x11, 0xff, 0x8a, 0xe7, 0xd1, 0xf1, 0xfb, 0xc9, 0x21, 0x00, 0xc2, 0x77, + 0x7e, 0xb7, 0x20, 0xfc, 0xc9, 0x2a, 0x03, 0xc2, 0x46, 0x23, 0x5e, 0x23, 0x56, + 0x23, 0xe7, 0x0e, 0xbe, 0xed, 0xb3, 0xc9, 0xe7, 0xdb, 0xbe, 0xc9, 0xe7, 0xdb, + 0xbe, 0x77, 0xe3, 0xe3, 0xdb, 0xbe, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf3, 0xc9, + 0x79, 0x48, 0x47, 0xc5, 0xd7, 0xeb, 0x01, 0x40, 0x00, 0x09, 0xeb, 0xc1, 0x0d, + 0x20, 0xf4, 0xc9, 0x32, 0x01, 0xc2, 0xe7, 0x7e, 0xd9, 0x01, 0xbe, 0x04, 0x67, + 0x3a, 0x01, 0xc2, 0x1f, 0x54, 0x38, 0x02, 0x16, 0x00, 0xed, 0x51, 0x10, 0xf6, + 0xd9, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xe6, 0xc9, 0x36, 0x80, 0xa0, 0x81, 0xff, + 0x82, 0xff, 0x83, 0xff, 0x84, 0xff, 0x85, 0xfb, 0x86, 0x00, 0x88, 0x00, 0x89, + 0xff, 0x8a, 0x00, 0x87, 0x10, 0xc0, 0x06, 0x04, 0xc5, 0xd5, 0xcd, 0xa5, 0x04, + 0xd1, 0x13, 0xc1, 0x10, 0xf6, 0xc9, 0x7e, 0x23, 0xb7, 0xc8, 0x47, 0x4f, 0xcb, + 0xb8, 0x7b, 0xf3, 0xd3, 0xbf, 0x7a, 0xd3, 0xbf, 0x7e, 0xd3, 0xbe, 0xfb, 0xcb, + 0x79, 0x28, 0x01, 0x23, 0x13, 0x13, 0x13, 0x13, 0x10, 0xea, 0x20, 0xe0, 0x23, + 0x18, 0xdd, 0xaf, 0x32, 0x2a, 0xc2, 0x32, 0x26, 0xc2, 0xf3, 0x21, 0x20, 0xc2, + 0x7e, 0xb7, 0xc8, 0x36, 0x00, 0x3a, 0x2a, 0xc2, 0x5f, 0x16, 0x89, 0xe7, 0x3a, + 0x26, 0xc2, 0x5f, 0x15, 0xe7, 0xc9, 0x11, 0x00, 0x78, 0x01, 0x00, 0x07, 0x2e, + 0x00, 0xef, 0xc9, 0xdb, 0xdc, 0x21, 0x07, 0xc2, 0x2f, 0x4f, 0xae, 0x71, 0x23, + 0xa1, 0x77, 0xc9, 0x3e, 0x05, 0xcd, 0x26, 0x04, 0x3a, 0x02, 0xcf, 0xb7, 0x28, + 0xf5, 0x11, 0x8a, 0x7b, 0x21, 0xe3, 0x0f, 0x01, 0x17, 0x03, 0xf3, 0xcd, 0x51, + 0x04, 0xcd, 0x4d, 0x01, 0xfb, 0x3a, 0x01, 0xcf, 0xb7, 0x28, 0xfa, 0xc9, 0x3e, + 0x03, 0x32, 0x01, 0xc2, 0x3e, 0xf0, 0x32, 0x02, 0xc2, 0x5f, 0x16, 0x88, 0xe7, + 0x2e, 0xff, 0x11, 0xc0, 0x5f, 0x01, 0x40, 0x00, 0xef, 0x11, 0x00, 0xc3, 0x3e, + 0x08, 0x21, 0x63, 0x05, 0x01, 0x04, 0x00, 0xed, 0xb0, 0x3d, 0x20, 0xf5, 0x3e, + 0xd0, 0x12, 0x1e, 0x80, 0x01, 0xff, 0x08, 0x3e, 0x04, 0xed, 0xa0, 0xed, 0xa0, + 0x3d, 0x28, 0x04, 0x2b, 0x2b, 0x18, 0xf5, 0x10, 0xf1, 0x3e, 0x01, 0xc3, 0x26, + 0x04, 0x38, 0x40, 0x48, 0x50, 0x47, 0xfe, 0x5a, 0xfe, 0x6c, 0xfe, 0x7e, 0xfe, + 0x4f, 0xff, 0x62, 0xff, 0x74, 0xff, 0x86, 0xff, 0x21, 0x01, 0xc2, 0x35, 0xc0, + 0x36, 0x02, 0x21, 0x02, 0xc2, 0x7e, 0xfe, 0x01, 0x20, 0x06, 0x3e, 0x80, 0x32, + 0x00, 0xc2, 0xc9, 0x5f, 0x16, 0x88, 0xe7, 0x34, 0x7e, 0xed, 0x44, 0xcb, 0x7f, + 0xc0, 0xfe, 0x08, 0x11, 0xe0, 0x5f, 0x38, 0x05, 0xd6, 0x08, 0x11, 0xc0, 0x5f, + 0x21, 0xaf, 0x05, 0x06, 0x00, 0x4f, 0x09, 0x6e, 0x0e, 0x20, 0xef, 0xc9, 0x00, + 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xcd, 0xd2, 0x05, 0xdd, 0x21, + 0x03, 0xcf, 0x06, 0x04, 0xc5, 0xdd, 0xcb, 0x00, 0x7e, 0xc4, 0x18, 0x06, 0x11, + 0x20, 0x00, 0xdd, 0x19, 0xc1, 0x10, 0xf0, 0xc9, 0x3a, 0x00, 0xcf, 0xfe, 0x80, + 0xda, 0xb5, 0x08, 0xca, 0x12, 0x06, 0x11, 0x03, 0xcf, 0xd6, 0x81, 0x21, 0x87, + 0x0b, 0x06, 0x00, 0x87, 0x4f, 0x09, 0x7e, 0x23, 0x66, 0x6f, 0xcd, 0xb5, 0x08, + 0x46, 0x23, 0xc5, 0x01, 0x09, 0x00, 0xed, 0xb0, 0x3e, 0x20, 0x12, 0x13, 0x3e, + 0x01, 0x12, 0x13, 0xaf, 0x12, 0x13, 0x12, 0x13, 0x12, 0xe5, 0x21, 0x12, 0x00, + 0x19, 0xeb, 0xe1, 0x13, 0xc1, 0x10, 0xe1, 0x3e, 0x80, 0x32, 0x00, 0xcf, 0xc9, + 0xdd, 0x5e, 0x0c, 0xdd, 0x56, 0x0d, 0x13, 0xdd, 0x73, 0x0c, 0xdd, 0x72, 0x0d, + 0xdd, 0x6e, 0x0a, 0xdd, 0x66, 0x0b, 0xb7, 0xed, 0x52, 0xcc, 0x7e, 0x07, 0xdd, + 0x5e, 0x10, 0xdd, 0x56, 0x11, 0x7b, 0xb2, 0x20, 0x07, 0xdd, 0x36, 0x16, 0x0f, + 0xc3, 0xf0, 0x06, 0xdd, 0xcb, 0x00, 0x6e, 0x20, 0x25, 0xdd, 0x7e, 0x06, 0xb7, + 0x20, 0x14, 0xdd, 0x73, 0x12, 0xdd, 0x72, 0x13, 0xc3, 0xa9, 0x06, 0x3d, 0x4f, + 0x06, 0x00, 0x09, 0x09, 0x7e, 0x23, 0x66, 0x6f, 0xc9, 0x21, 0x85, 0x0b, 0xcd, + 0x57, 0x06, 0xcd, 0x48, 0x07, 0x18, 0x3c, 0xd5, 0xdd, 0x6e, 0x14, 0xdd, 0x66, + 0x15, 0xb7, 0xed, 0x52, 0xf5, 0x7d, 0xf2, 0x7e, 0x06, 0xed, 0x44, 0x67, 0xdd, + 0x5e, 0x0c, 0xcd, 0x67, 0x09, 0xdd, 0x5e, 0x0a, 0xcd, 0x73, 0x09, 0x5f, 0x16, + 0x00, 0xf1, 0x7b, 0xf2, 0x99, 0x06, 0xed, 0x44, 0x28, 0x02, 0x15, 0x5f, 0xe1, + 0x19, 0xeb, 0xdd, 0x73, 0x12, 0xdd, 0x72, 0x13, 0xdd, 0x7e, 0x06, 0xb7, 0xc2, + 0x62, 0x06, 0xdd, 0x7e, 0x07, 0xb7, 0x20, 0x0b, 0xdd, 0x7e, 0x08, 0x2f, 0xe6, + 0x0f, 0xdd, 0x77, 0x16, 0x18, 0x0b, 0xcb, 0xbf, 0x21, 0x6f, 0x0b, 0xcd, 0x57, + 0x06, 0xcd, 0x0e, 0x07, 0xdd, 0xcb, 0x00, 0x76, 0x20, 0x25, 0xdd, 0x7e, 0x01, + 0xe6, 0x0f, 0x4f, 0x06, 0x00, 0x21, 0x03, 0x07, 0x09, 0x4e, 0xdd, 0x7e, 0x12, + 0xe6, 0x0f, 0xb1, 0xcd, 0xad, 0x08, 0xdd, 0x7e, 0x12, 0xe6, 0xf0, 0xdd, 0xb6, + 0x13, 0x0f, 0x0f, 0x0f, 0x0f, 0xcd, 0xad, 0x08, 0xdd, 0x7e, 0x01, 0xe6, 0x0f, + 0x4f, 0x06, 0x00, 0x21, 0x07, 0x07, 0x09, 0x7e, 0xdd, 0xb6, 0x16, 0xc3, 0xad, + 0x08, 0x80, 0xa0, 0xc0, 0xc0, 0x90, 0xb0, 0xd0, 0xf0, 0xdd, 0x77, 0x0e, 0xe5, + 0xdd, 0x7e, 0x0e, 0xcb, 0x3f, 0xf5, 0x4f, 0x06, 0x00, 0x09, 0xf1, 0x7e, 0xe1, + 0x38, 0x14, 0x0f, 0x0f, 0x0f, 0x0f, 0xb7, 0x28, 0xe6, 0xfe, 0x10, 0x20, 0x05, + 0xdd, 0x35, 0x0e, 0x18, 0xe0, 0xfe, 0x20, 0x28, 0x0b, 0xdd, 0x34, 0x0e, 0xf6, + 0xf0, 0xdd, 0x86, 0x08, 0x3c, 0x38, 0x01, 0xaf, 0x2f, 0xe6, 0x0f, 0xdd, 0x77, + 0x16, 0xc9, 0xdd, 0x77, 0x0f, 0xe5, 0xdd, 0x7e, 0x0f, 0xcb, 0x3f, 0xf5, 0x4f, + 0x06, 0x00, 0x09, 0xf1, 0x7e, 0xe1, 0x38, 0x14, 0x0f, 0x0f, 0x0f, 0x0f, 0xb7, + 0xca, 0x45, 0x07, 0xfe, 0x10, 0x20, 0x08, 0xdd, 0x35, 0x0f, 0x18, 0xdf, 0xfe, + 0x20, 0xc8, 0xdd, 0x34, 0x0f, 0x2f, 0xe6, 0x0f, 0x6f, 0x26, 0x00, 0xeb, 0x19, + 0xdd, 0x75, 0x12, 0xdd, 0x74, 0x13, 0xc9, 0xdd, 0x5e, 0x03, 0xdd, 0x56, 0x04, + 0x1a, 0x13, 0xfe, 0xe0, 0xd2, 0x12, 0x08, 0xdd, 0xcb, 0x00, 0x5e, 0x20, 0x60, + 0xb7, 0xf2, 0xcd, 0x07, 0xd6, 0x80, 0x28, 0x03, 0xdd, 0x86, 0x05, 0x21, 0xd5, + 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, 0x7e, 0xdd, 0x77, 0x10, 0x23, 0x7e, 0xdd, + 0x77, 0x11, 0xdd, 0xcb, 0x00, 0x6e, 0x28, 0x58, 0x1a, 0x13, 0xd6, 0x80, 0xdd, + 0x86, 0x05, 0x21, 0xd5, 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, 0x7e, 0xdd, 0x77, + 0x14, 0x23, 0x7e, 0xdd, 0x77, 0x15, 0x1a, 0x13, 0xd5, 0x67, 0xdd, 0x5e, 0x02, + 0xcd, 0x67, 0x09, 0xd1, 0xdd, 0x75, 0x0a, 0xdd, 0x74, 0x0b, 0xaf, 0xdd, 0x77, + 0x0e, 0xdd, 0x77, 0x0f, 0xdd, 0x73, 0x03, 0xdd, 0x72, 0x04, 0xaf, 0xdd, 0x77, + 0x0c, 0xdd, 0x77, 0x0d, 0xc9, 0xdd, 0x77, 0x11, 0x1a, 0x13, 0xdd, 0x77, 0x10, + 0xdd, 0xcb, 0x00, 0x6e, 0x28, 0xcc, 0x1a, 0x13, 0xdd, 0x77, 0x15, 0x1a, 0x13, + 0xdd, 0x77, 0x14, 0x18, 0xc0, 0x1a, 0xb7, 0xf2, 0xcc, 0x07, 0x18, 0xca, 0x21, + 0x25, 0x08, 0xe5, 0xe6, 0x1f, 0x21, 0x29, 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, + 0x7e, 0x23, 0x66, 0x6f, 0xe9, 0x13, 0xc3, 0x84, 0x07, 0x8a, 0x08, 0x8f, 0x08, + 0x67, 0x08, 0x7e, 0x08, 0x3b, 0x08, 0x49, 0x08, 0x4f, 0x08, 0x83, 0x08, 0x41, + 0x08, 0xeb, 0x5e, 0x23, 0x56, 0x1b, 0xc9, 0x1a, 0xdd, 0x86, 0x05, 0xdd, 0x77, + 0x05, 0xc9, 0xdd, 0xcb, 0x00, 0xae, 0x1b, 0xc9, 0x1a, 0x13, 0xc6, 0x17, 0x4f, + 0x06, 0x00, 0xdd, 0xe5, 0xe1, 0x09, 0x7e, 0xb7, 0x20, 0x02, 0x1a, 0x77, 0x13, + 0x35, 0xc2, 0x3b, 0x08, 0x13, 0xc9, 0x1a, 0xf6, 0xe0, 0xf5, 0xcd, 0xad, 0x08, + 0xf1, 0xf6, 0xfc, 0x3c, 0x20, 0x05, 0xdd, 0xcb, 0x00, 0xb6, 0xc9, 0xdd, 0xcb, + 0x00, 0xf6, 0xc9, 0x1a, 0xdd, 0x77, 0x07, 0xc9, 0x3e, 0x80, 0x32, 0x02, 0xcf, + 0x1b, 0xc9, 0x1a, 0xdd, 0x77, 0x08, 0xc9, 0x3e, 0x80, 0x32, 0x01, 0xcf, 0xaf, + 0xdd, 0x77, 0x00, 0xcd, 0x9e, 0x08, 0xe1, 0xe1, 0xc9, 0xdd, 0x7e, 0x01, 0xe6, + 0x0f, 0x4f, 0x06, 0x00, 0x21, 0x07, 0x07, 0x09, 0x7e, 0xf6, 0x0f, 0xdd, 0xcb, + 0x00, 0x56, 0xc0, 0xd3, 0x7f, 0xc9, 0xd9, 0x21, 0x01, 0xcf, 0x11, 0x02, 0xcf, + 0x01, 0x7f, 0x00, 0x36, 0x00, 0xed, 0xb0, 0xd9, 0xd9, 0x21, 0xd1, 0x08, 0x0e, + 0x7f, 0x06, 0x04, 0xed, 0xb3, 0xaf, 0xd9, 0xc9, 0x9f, 0xbf, 0xdf, 0xff, 0x00, + 0x00, 0xff, 0x03, 0xc7, 0x03, 0x90, 0x03, 0x5d, 0x03, 0x2d, 0x03, 0xff, 0x02, + 0xd4, 0x02, 0xab, 0x02, 0x85, 0x02, 0x61, 0x02, 0x3f, 0x02, 0x1e, 0x02, 0x00, + 0x02, 0xe3, 0x01, 0xc8, 0x01, 0xaf, 0x01, 0x96, 0x01, 0x80, 0x01, 0x6a, 0x01, + 0x56, 0x01, 0x43, 0x01, 0x30, 0x01, 0x1f, 0x01, 0x0f, 0x01, 0x00, 0x01, 0xf2, + 0x00, 0xe4, 0x00, 0xd7, 0x00, 0xcb, 0x00, 0xc0, 0x00, 0xb5, 0x00, 0xab, 0x00, + 0xa1, 0x00, 0x98, 0x00, 0x90, 0x00, 0x88, 0x00, 0x80, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x6c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x5b, 0x00, 0x55, 0x00, 0x51, 0x00, + 0x4c, 0x00, 0x48, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3c, 0x00, 0x39, 0x00, 0x36, + 0x00, 0x33, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x28, 0x00, 0x26, 0x00, + 0x24, 0x00, 0x22, 0x00, 0x20, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1b, 0x00, 0x19, + 0x00, 0x18, 0x00, 0x16, 0x00, 0x15, 0x00, 0x14, 0x00, 0x13, 0x00, 0x12, 0x00, + 0x11, 0x00, 0x16, 0x00, 0x6a, 0x06, 0x08, 0x29, 0x30, 0x01, 0x19, 0x10, 0xfa, + 0xc9, 0x06, 0x08, 0xed, 0x6a, 0x7c, 0x38, 0x03, 0xbb, 0x38, 0x03, 0x93, 0x67, + 0xb7, 0x10, 0xf3, 0x7d, 0x17, 0x2f, 0xc9, 0x04, 0xa0, 0x20, 0x05, 0xc7, 0x09, + 0x05, 0x01, 0x04, 0x0d, 0xa0, 0x21, 0x05, 0xbb, 0x09, 0x05, 0x01, 0x04, 0x0d, + 0xa0, 0x22, 0x05, 0xd2, 0x09, 0x05, 0x01, 0x04, 0x0d, 0x80, 0x23, 0x05, 0xab, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0xe2, 0x04, 0xe3, 0x01, 0xe0, 0x0d, + 0x8d, 0x08, 0xe3, 0x02, 0xe0, 0x0f, 0x1c, 0xe1, 0x81, 0xa5, 0x08, 0xe5, 0x80, + 0xe7, 0x8d, 0x81, 0x10, 0x80, 0x0c, 0xe1, 0x85, 0xa9, 0x08, 0xe5, 0x80, 0x8a, + 0x8a, 0x10, 0x80, 0x08, 0xe1, 0x88, 0xac, 0x08, 0xe5, 0x80, 0x86, 0x86, 0x10, + 0x80, 0x08, 0xe1, 0x04, 0x80, 0x20, 0x05, 0x02, 0x0a, 0x00, 0x01, 0x02, 0x0e, + 0x80, 0x21, 0x05, 0x14, 0x0a, 0x00, 0x01, 0x02, 0x0f, 0x80, 0x22, 0x05, 0x27, + 0x0a, 0x00, 0x01, 0x02, 0x0e, 0x80, 0x23, 0x05, 0x3a, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x8f, 0x02, 0x02, 0x02, 0xe3, 0x04, 0x0f, 0xe3, 0x02, 0x8d, 0x03, 0x03, + 0x8f, 0xe3, 0x04, 0x91, 0x18, 0xe1, 0x9f, 0x02, 0x02, 0x02, 0xe3, 0x04, 0xa0, + 0x0f, 0xe3, 0x02, 0x9d, 0x03, 0x03, 0x9f, 0xe3, 0x04, 0xa1, 0x18, 0xe1, 0xa2, + 0x02, 0x02, 0x02, 0xe3, 0x04, 0xa4, 0x0f, 0xe3, 0x02, 0xa0, 0x03, 0x03, 0xa2, + 0xe3, 0x04, 0xa4, 0x18, 0xe1, 0xe2, 0x04, 0xe3, 0x01, 0xe0, 0x0d, 0x8d, 0x02, + 0x02, 0x02, 0xe3, 0x02, 0xe0, 0x0f, 0x0f, 0xe3, 0x01, 0xe0, 0x0d, 0x03, 0x03, + 0x03, 0xe3, 0x02, 0xe0, 0x0f, 0x18, 0xe1, 0x04, 0x80, 0x20, 0x02, 0x7b, 0x0a, + 0x00, 0x01, 0x03, 0x0b, 0x80, 0x21, 0x02, 0x7d, 0x0a, 0x00, 0x01, 0x03, 0x0c, + 0x80, 0x22, 0x02, 0xa2, 0x0a, 0x00, 0x01, 0x03, 0x0b, 0x80, 0x23, 0x02, 0xc7, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x99, 0x08, 0xa0, 0x9d, 0xa0, 0x9e, + 0x9b, 0x9d, 0x9b, 0x99, 0x9b, 0x9d, 0x9b, 0x94, 0x96, 0x94, 0x80, 0x99, 0x08, + 0xa0, 0x9d, 0xa0, 0x9e, 0x9b, 0x9d, 0x9b, 0x9d, 0x9b, 0x99, 0x98, 0x99, 0x99, + 0x99, 0x80, 0xe4, 0x7d, 0x0a, 0x8d, 0x08, 0x99, 0x8d, 0x99, 0x92, 0x9e, 0x94, + 0xa0, 0x8d, 0x94, 0x8d, 0x99, 0x88, 0x8f, 0x88, 0x94, 0x8d, 0x08, 0x99, 0x8d, + 0x99, 0x92, 0x9e, 0x94, 0xa0, 0x8d, 0x94, 0x88, 0x94, 0x8d, 0x99, 0x8d, 0x80, + 0xe4, 0xa2, 0x0a, 0xe2, 0x04, 0xe3, 0x01, 0xe0, 0x0d, 0x8d, 0x08, 0xe3, 0x02, + 0xe0, 0x0f, 0x08, 0xe3, 0x01, 0xe0, 0x0d, 0x04, 0x04, 0xe3, 0x02, 0xe0, 0x0f, + 0x08, 0xe4, 0xc9, 0x0a, 0x04, 0x80, 0x20, 0x04, 0x07, 0x0b, 0x00, 0x01, 0x02, + 0x0e, 0x80, 0x21, 0x04, 0x13, 0x0b, 0x00, 0x01, 0x02, 0x0d, 0x80, 0x22, 0x04, + 0x1f, 0x0b, 0x00, 0x01, 0x02, 0x0e, 0x80, 0x23, 0x04, 0x2b, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x9d, 0x02, 0x9b, 0x9d, 0xa0, 0x9d, 0xa0, 0xe3, 0x04, 0xa5, 0x10, + 0xe1, 0x99, 0x02, 0x98, 0x99, 0x9d, 0x99, 0x9d, 0xe3, 0x04, 0xa2, 0x10, 0xe1, + 0x8d, 0x02, 0x02, 0x02, 0x88, 0x88, 0x88, 0xe3, 0x04, 0x91, 0x10, 0xe1, 0xe2, + 0x04, 0xe3, 0x01, 0xe0, 0x0d, 0x8d, 0x04, 0xe3, 0x02, 0xe0, 0x0f, 0x04, 0xe3, + 0x01, 0xe0, 0x0d, 0x02, 0x02, 0xe3, 0x02, 0xe0, 0x0f, 0x10, 0xe1, 0xaf, 0xec, + 0xee, 0x01, 0xbc, 0xdd, 0xee, 0xff, 0xee, 0xff, 0xdd, 0xcc, 0xbb, 0xdd, 0xee, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0xfe, 0xdc, 0xbc, 0xde, + 0xfe, 0xdb, 0xab, 0xcd, 0xef, 0xed, 0xcb, 0xab, 0xcd, 0xef, 0xee, 0x01, 0xff, + 0xee, 0x00, 0x77, 0x0b, 0x79, 0x0b, 0x80, 0x0b, 0x44, 0x0b, 0xff, 0x02, 0xff, + 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x02, 0xef, 0xff, 0xff, 0xee, 0x02, 0x48, 0x0b, + 0x86, 0x09, 0xdd, 0x09, 0x56, 0x0a, 0xe2, 0x0a, 0xff, 0x3e, 0xff, 0x32, 0x0b, + 0xc2, 0x21, 0x93, 0x0d, 0x11, 0x30, 0xc2, 0x01, 0x04, 0x00, 0xed, 0xb0, 0x21, + 0xc2, 0xc9, 0x06, 0x1e, 0x36, 0x03, 0x23, 0x23, 0x10, 0xfa, 0xf3, 0x21, 0x9e, + 0x0d, 0x11, 0x64, 0x79, 0x06, 0x0a, 0xd7, 0xf3, 0x21, 0x30, 0xc2, 0x11, 0x6a, + 0x79, 0xcd, 0x76, 0x0d, 0xfb, 0x3e, 0x10, 0xcd, 0x26, 0x04, 0xdd, 0x21, 0x00, + 0xc4, 0xcd, 0x27, 0x0f, 0xdd, 0x36, 0x07, 0x08, 0xdd, 0x36, 0x0c, 0x0d, 0xdd, + 0x36, 0x04, 0x04, 0xdd, 0x21, 0x40, 0xc4, 0xcd, 0x27, 0x0f, 0xdd, 0x21, 0x20, + 0xc4, 0xcd, 0x27, 0x0f, 0xcd, 0xc1, 0x0c, 0x3e, 0x01, 0x32, 0x00, 0xc4, 0x3c, + 0x32, 0x40, 0xc4, 0x3c, 0x32, 0x20, 0xc4, 0xcd, 0x99, 0x0e, 0x01, 0x01, 0x14, + 0xcd, 0xba, 0x0c, 0x3e, 0x83, 0x32, 0x00, 0xcf, 0x3e, 0x11, 0xcd, 0x26, 0x04, + 0xcd, 0x99, 0x0e, 0x21, 0x34, 0xc2, 0x7e, 0xb7, 0x20, 0x38, 0x23, 0x7e, 0xb7, + 0x28, 0xec, 0xf3, 0x21, 0x97, 0x0d, 0x11, 0xda, 0x79, 0x06, 0x07, 0xd7, 0xfb, + 0x06, 0x00, 0xc5, 0x01, 0x80, 0x01, 0xcd, 0xba, 0x0c, 0x11, 0xdb, 0x79, 0x21, + 0x74, 0xc2, 0x34, 0xf3, 0xe7, 0x06, 0x07, 0x3a, 0x74, 0xc2, 0xe6, 0x08, 0xd3, + 0xbe, 0xf5, 0xf1, 0xdb, 0xbe, 0x10, 0xf3, 0xfb, 0xc1, 0x10, 0xdd, 0xc3, 0x77, + 0x03, 0x36, 0x00, 0x3e, 0x84, 0x32, 0x00, 0xcf, 0x01, 0x01, 0x60, 0xcd, 0xba, + 0x0c, 0x3e, 0xd0, 0x32, 0x00, 0xc3, 0x01, 0x01, 0x30, 0xcd, 0xba, 0x0c, 0x21, + 0x30, 0xc2, 0x7e, 0xc6, 0x01, 0x27, 0x77, 0x23, 0x34, 0x7e, 0xfe, 0x0d, 0x30, + 0x19, 0x5f, 0x16, 0x00, 0x21, 0xa6, 0x0d, 0x19, 0x7e, 0x2a, 0x32, 0xc2, 0x84, + 0x27, 0x30, 0x02, 0x3e, 0x99, 0x67, 0x6a, 0x22, 0x32, 0xc2, 0xc3, 0xb5, 0x0b, + 0x3e, 0x82, 0x32, 0x00, 0xcf, 0x21, 0xaa, 0x0c, 0x11, 0xd0, 0x79, 0x06, 0x10, + 0xf3, 0xd7, 0xfb, 0x01, 0x80, 0x00, 0xcd, 0xba, 0x0c, 0x01, 0x80, 0x00, 0xcd, + 0xba, 0x0c, 0xc3, 0x77, 0x03, 0x43, 0x4f, 0x4e, 0x47, 0x52, 0x41, 0x54, 0x55, + 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x21, 0x79, 0xcd, 0x26, 0x04, 0x10, + 0xfa, 0xc9, 0x3a, 0x31, 0xc2, 0x3d, 0x57, 0x87, 0x82, 0x5f, 0xaf, 0xcb, 0x1a, + 0x1f, 0x83, 0x5f, 0x21, 0xb1, 0x19, 0x19, 0x7e, 0x32, 0x08, 0xc4, 0x23, 0x7e, + 0x32, 0x48, 0xc4, 0x23, 0x7e, 0x32, 0x47, 0xc4, 0x23, 0x11, 0x00, 0xca, 0x06, + 0x80, 0xc5, 0x06, 0x04, 0x4e, 0x79, 0x3c, 0xe6, 0x03, 0xc6, 0x04, 0x12, 0x13, + 0xaf, 0x12, 0x13, 0xcb, 0x19, 0xcb, 0x19, 0x10, 0xef, 0x23, 0xc1, 0x10, 0xe7, + 0x21, 0x3e, 0xca, 0x01, 0x74, 0x10, 0x11, 0x40, 0x00, 0x71, 0x19, 0x10, 0xfc, + 0x3e, 0xff, 0x32, 0x44, 0xc2, 0x11, 0x36, 0x80, 0xe7, 0x3e, 0x08, 0xcd, 0x26, + 0x04, 0x3a, 0x44, 0xc2, 0xb7, 0x20, 0xf5, 0x11, 0x06, 0x80, 0xe7, 0x11, 0xff, + 0x8a, 0xe7, 0xc9, 0x11, 0x00, 0x88, 0xe7, 0x11, 0x37, 0x8a, 0xe7, 0x21, 0x25, + 0xc2, 0x7e, 0x35, 0x20, 0x05, 0xaf, 0x32, 0x44, 0xc2, 0xc9, 0xed, 0x44, 0x5f, + 0xe6, 0x07, 0xc0, 0x7b, 0x0f, 0x0f, 0xc6, 0xc0, 0x5f, 0x16, 0x79, 0x6f, 0x26, + 0xc9, 0x06, 0x11, 0xc5, 0x7e, 0xcf, 0x01, 0x40, 0x00, 0x09, 0xeb, 0x09, 0xeb, + 0xc1, 0x10, 0xf3, 0xc9, 0x21, 0x32, 0xc2, 0x35, 0xf0, 0x36, 0x3b, 0x23, 0x7e, + 0xd6, 0x01, 0x27, 0x77, 0x11, 0x7a, 0x79, 0x20, 0x05, 0x3d, 0x32, 0x35, 0xc2, + 0x3c, 0xe7, 0x7e, 0x1f, 0x1f, 0x1f, 0x1f, 0xe6, 0x0f, 0x28, 0x02, 0xf6, 0x30, + 0xcd, 0x8a, 0x0d, 0x7e, 0xe6, 0x0f, 0xf6, 0x30, 0xd3, 0xbe, 0xf5, 0xf1, 0x3e, + 0x08, 0xd3, 0xbe, 0xc9, 0x01, 0x01, 0x00, 0x61, 0x54, 0x49, 0x4d, 0x45, 0x20, + 0x55, 0x50, 0x52, 0x44, 0x20, 0x20, 0x20, 0x20, 0x54, 0x49, 0x4d, 0x45, 0x30, + 0x35, 0x25, 0x35, 0x35, 0x30, 0x35, 0x35, 0x35, 0x10, 0x15, 0xb9, 0x0d, 0x43, + 0x0e, 0x6f, 0x0e, 0xdd, 0xcb, 0x01, 0x7e, 0x28, 0x15, 0xdd, 0x35, 0x1f, 0x28, + 0x06, 0x2a, 0x05, 0xc4, 0xc3, 0x85, 0x0f, 0xdd, 0xcb, 0x01, 0xbe, 0x21, 0x00, + 0x00, 0x22, 0x09, 0xc4, 0xcd, 0x2c, 0x0e, 0x3a, 0x07, 0xc2, 0x0f, 0xdc, 0xf3, + 0x0d, 0x0f, 0xdc, 0x05, 0x0e, 0x0f, 0x38, 0x39, 0x0f, 0xd0, 0xcb, 0x4e, 0xc0, + 0xdd, 0x36, 0x09, 0x01, 0x21, 0x8d, 0x0e, 0x18, 0x1d, 0xe5, 0x11, 0xc0, 0xff, + 0x19, 0xcb, 0x46, 0xe1, 0xc0, 0xdd, 0x36, 0x0a, 0xff, 0x21, 0x96, 0x0e, 0x18, + 0x0a, 0xcb, 0x46, 0xc0, 0xdd, 0x36, 0x0a, 0x01, 0x21, 0x93, 0x0e, 0xf1, 0x22, + 0x05, 0xc4, 0xdd, 0x36, 0x1f, 0x08, 0xdd, 0xcb, 0x01, 0xfe, 0xc3, 0x85, 0x0f, + 0x2b, 0x2b, 0xcb, 0x4e, 0xc0, 0xdd, 0x36, 0x09, 0xff, 0x21, 0x90, 0x0e, 0x18, + 0xe4, 0x3a, 0x07, 0xc4, 0x0f, 0x0f, 0xe6, 0x3e, 0x5f, 0x3a, 0x08, 0xc4, 0xe6, + 0xf8, 0x6f, 0x26, 0x00, 0x29, 0x29, 0x29, 0x16, 0xc8, 0x19, 0xc9, 0xdd, 0xcb, + 0x01, 0x46, 0x28, 0x19, 0x2a, 0x07, 0xc4, 0x7d, 0xdd, 0xbe, 0x07, 0x20, 0x0a, + 0x7c, 0xdd, 0xbe, 0x08, 0x20, 0x04, 0x32, 0x34, 0xc2, 0xc9, 0x21, 0x87, 0x0e, + 0xc3, 0x85, 0x0f, 0xdd, 0x36, 0x0c, 0x0c, 0xdd, 0xcb, 0x01, 0xc6, 0xdd, 0x36, + 0x04, 0x1e, 0xc9, 0xdd, 0xcb, 0x01, 0x46, 0x28, 0x06, 0x21, 0x8a, 0x0e, 0xc3, + 0x85, 0x0f, 0x2a, 0x07, 0xc4, 0x22, 0x27, 0xc4, 0xdd, 0x36, 0x0c, 0x53, 0x18, + 0xdf, 0x02, 0x47, 0x0c, 0x02, 0x20, 0x53, 0x02, 0x0d, 0x0e, 0x02, 0x0f, 0x10, + 0x02, 0x11, 0x12, 0x02, 0x13, 0x14, 0x21, 0x00, 0xc3, 0x22, 0x09, 0xc2, 0xdd, + 0x21, 0x00, 0xc4, 0x06, 0x04, 0xdd, 0x7e, 0x00, 0xe6, 0x7f, 0xca, 0xc5, 0x0e, + 0xc5, 0x21, 0xb1, 0x0d, 0xcd, 0xb1, 0x0f, 0xdd, 0x7e, 0x00, 0xb7, 0xca, 0xc4, + 0x0e, 0xcd, 0x6d, 0x0f, 0xcd, 0x1d, 0x0f, 0xcd, 0xd2, 0x0e, 0xc1, 0x11, 0x20, + 0x00, 0xdd, 0x19, 0x10, 0xd9, 0x2a, 0x09, 0xc2, 0x36, 0xd0, 0xc9, 0xdd, 0x7e, + 0x00, 0xb7, 0xc8, 0xdd, 0x7e, 0x08, 0xfe, 0xc0, 0xd0, 0x2a, 0x09, 0xc2, 0x77, + 0x23, 0x08, 0xdd, 0x7e, 0x0c, 0xfe, 0x0c, 0x28, 0x12, 0x22, 0x09, 0xc2, 0x2b, + 0xcb, 0x25, 0xcb, 0xfd, 0xdd, 0x7e, 0x07, 0x77, 0x23, 0xdd, 0x7e, 0x0c, 0x77, + 0xc9, 0x08, 0x06, 0x04, 0xe5, 0xd6, 0x08, 0x77, 0x23, 0x10, 0xfa, 0x22, 0x09, + 0xc2, 0xe1, 0x2b, 0xcb, 0x25, 0xcb, 0xfd, 0x06, 0x05, 0xdd, 0x4e, 0x07, 0x08, + 0x71, 0x23, 0x77, 0x23, 0x3d, 0x10, 0xf9, 0xc9, 0xdd, 0x7e, 0x0a, 0xdd, 0x86, + 0x08, 0xdd, 0x77, 0x08, 0xc9, 0xaf, 0xdd, 0xe5, 0xe1, 0x77, 0x2c, 0x77, 0x2c, + 0x77, 0x2c, 0x36, 0x01, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, + 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, + 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, + 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, + 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x2c, 0x77, 0x4f, 0xc9, 0x3a, 0x28, 0xc2, + 0xdd, 0x56, 0x09, 0x82, 0x57, 0xdd, 0x86, 0x07, 0xdd, 0x77, 0x07, 0xcb, 0x7a, + 0x20, 0x03, 0x38, 0xa6, 0xc9, 0x30, 0xa3, 0xc9, 0x46, 0x23, 0x50, 0xdd, 0x35, + 0x03, 0xdd, 0x7e, 0x02, 0x20, 0x0e, 0xdd, 0x5e, 0x04, 0xdd, 0x73, 0x03, 0x3c, + 0xba, 0x38, 0x01, 0xaf, 0xdd, 0x77, 0x02, 0x4f, 0x06, 0x00, 0x09, 0x7e, 0xdd, + 0x77, 0x0c, 0xc9, 0x46, 0x23, 0x50, 0xdd, 0x7e, 0x02, 0x18, 0xef, 0xe6, 0x0f, + 0x87, 0x5f, 0x16, 0x00, 0x19, 0x7e, 0x23, 0x66, 0x6f, 0xe9, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x94, 0x97, 0x98, 0x94, 0x94, 0x94, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0x00, 0xa5, 0xa6, 0xa7, + 0xa8, 0x9f, 0xa0, 0xa1, 0xa2, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0x00, 0xb7, 0xb8, 0xb9, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, + 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xc2, 0xc3, 0xc4, 0xc5, 0xcd, + 0xce, 0xcf, 0x89, 0x07, 0x1c, 0x30, 0x60, 0x41, 0xc6, 0x84, 0x88, 0xff, 0x03, + 0x00, 0x81, 0xff, 0x03, 0x00, 0x89, 0xe1, 0x27, 0x2c, 0x38, 0xf0, 0x31, 0x21, + 0x22, 0xff, 0x03, 0x00, 0x95, 0x7f, 0x80, 0x00, 0x00, 0xf8, 0x09, 0x0b, 0x0e, + 0xfc, 0x0c, 0x08, 0x08, 0x7f, 0xc0, 0x00, 0x00, 0x1f, 0x60, 0x40, 0x80, 0xfe, + 0x03, 0x02, 0x81, 0xfe, 0x03, 0x02, 0xa8, 0x03, 0x0e, 0x08, 0x18, 0x11, 0x31, + 0x22, 0x22, 0xe0, 0x39, 0x0f, 0x0e, 0xc6, 0x46, 0x22, 0x23, 0xfc, 0x86, 0x7b, + 0x8d, 0xb5, 0x8d, 0xb5, 0x7b, 0x88, 0x88, 0x84, 0xc6, 0x41, 0x60, 0x30, 0x1c, + 0xff, 0x07, 0x01, 0x00, 0xf0, 0x0c, 0x04, 0x02, 0x04, 0xe2, 0x85, 0x63, 0x62, + 0x22, 0x22, 0x3f, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, 0x81, 0xf8, 0x03, 0x18, + 0x81, 0xf8, 0x03, 0x18, 0x81, 0x8f, 0x03, 0x88, 0x81, 0x8f, 0x03, 0x88, 0x81, + 0xfe, 0x03, 0x02, 0x88, 0xe2, 0x22, 0x23, 0x23, 0x62, 0x44, 0x44, 0xc4, 0x03, + 0x88, 0x82, 0x11, 0x23, 0x03, 0x11, 0x03, 0x88, 0x84, 0xc4, 0x86, 0xfc, 0x00, + 0x03, 0x80, 0x83, 0xc0, 0x40, 0xff, 0x03, 0x80, 0x81, 0xff, 0x03, 0x80, 0x95, + 0xe2, 0x02, 0x04, 0x0c, 0xf0, 0x00, 0x01, 0x07, 0x22, 0x22, 0x21, 0x71, 0x70, + 0xd8, 0x8c, 0x07, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x03, 0x00, 0x90, 0xf8, 0x08, + 0x08, 0x0c, 0xfc, 0x0e, 0x0b, 0x09, 0x8e, 0x80, 0x40, 0x60, 0x1f, 0x00, 0x00, + 0xc0, 0x02, 0x23, 0x02, 0x22, 0x81, 0xe2, 0x03, 0x00, 0x85, 0x11, 0x10, 0x22, + 0x22, 0x23, 0x03, 0x46, 0x85, 0xc4, 0x04, 0x02, 0x02, 0xfe, 0x03, 0x00, 0x85, + 0x40, 0x60, 0x20, 0x20, 0x30, 0x03, 0x10, 0x81, 0xff, 0x07, 0x00, 0x81, 0xfc, + 0x07, 0x00, 0x81, 0x01, 0x07, 0x00, 0x81, 0xf8, 0x07, 0x00, 0x81, 0x7f, 0x07, + 0x00, 0x81, 0xf0, 0x07, 0x00, 0x81, 0x7c, 0x04, 0x3c, 0x02, 0x3e, 0x82, 0x36, + 0x1f, 0x04, 0x1e, 0x02, 0x3e, 0x81, 0x2e, 0x03, 0x01, 0x03, 0x03, 0x02, 0x06, + 0x03, 0xe0, 0x02, 0x70, 0x96, 0x78, 0x38, 0x38, 0x03, 0x0f, 0x1c, 0x18, 0x38, + 0x38, 0x3c, 0x3f, 0x90, 0xf1, 0x31, 0x1b, 0x0a, 0x08, 0x00, 0x80, 0xff, 0xff, + 0xdd, 0x05, 0x1c, 0x85, 0x87, 0xc3, 0xc3, 0x63, 0x23, 0x03, 0x03, 0x02, 0xff, + 0x82, 0x83, 0x81, 0x02, 0x80, 0x02, 0x84, 0x82, 0x1f, 0x0f, 0x03, 0x8e, 0x03, + 0x0e, 0x84, 0xf0, 0xf8, 0x3c, 0x0c, 0x03, 0x0e, 0x8d, 0x0c, 0x07, 0x1f, 0x38, + 0x30, 0x70, 0x70, 0x78, 0x7f, 0x27, 0xe3, 0x61, 0x31, 0x02, 0x10, 0x02, 0x00, + 0x82, 0xc3, 0x81, 0x02, 0xc3, 0x02, 0xe6, 0x02, 0x7c, 0x8a, 0xc3, 0x8f, 0x1c, + 0x18, 0x38, 0x38, 0x3c, 0x3f, 0x1f, 0x0f, 0x03, 0x8f, 0x02, 0x0f, 0x81, 0x0d, + 0x05, 0x07, 0x02, 0x8f, 0x82, 0x8b, 0xc0, 0x07, 0x80, 0x81, 0x36, 0x02, 0x37, + 0x04, 0x33, 0x85, 0x31, 0x2e, 0x6e, 0x6e, 0x4e, 0x03, 0xce, 0x9d, 0x8e, 0x06, + 0x06, 0x0c, 0x0f, 0x0f, 0x0c, 0x18, 0x18, 0x38, 0x3c, 0x1c, 0xfc, 0xfc, 0x1e, + 0x0e, 0x0e, 0x1f, 0x0f, 0x03, 0x00, 0x20, 0x20, 0x30, 0x18, 0xe0, 0xf0, 0xf0, + 0x78, 0x03, 0x38, 0x81, 0x70, 0x08, 0x1c, 0x08, 0x03, 0x02, 0xfc, 0x02, 0x84, + 0x02, 0x80, 0x83, 0x81, 0x83, 0x0e, 0x02, 0x0f, 0x02, 0x0e, 0x86, 0xce, 0x8e, + 0x8e, 0x3c, 0xf8, 0xf0, 0x02, 0x38, 0x02, 0x1c, 0x8d, 0x0e, 0x3f, 0x1f, 0x07, + 0x00, 0x40, 0x40, 0x60, 0x30, 0xc0, 0xe0, 0xe0, 0xf0, 0x03, 0x70, 0x81, 0xe0, + 0x08, 0x38, 0x03, 0x0d, 0x02, 0x0c, 0x87, 0xcc, 0x8c, 0x8c, 0x8b, 0xdb, 0xdb, + 0xd3, 0x03, 0xf3, 0x81, 0x63, 0x08, 0x80, 0x82, 0x31, 0x79, 0x06, 0x00, 0x82, + 0x8e, 0x9f, 0x06, 0x00, 0x82, 0x18, 0x3c, 0x06, 0x00, 0x82, 0x0e, 0x1f, 0x06, + 0x00, 0x82, 0x1f, 0x13, 0x06, 0x00, 0x82, 0xe0, 0xc0, 0x06, 0x00, 0x82, 0x1c, + 0x3e, 0x06, 0x00, 0x82, 0x03, 0x07, 0x06, 0x00, 0x02, 0xff, 0x06, 0x00, 0x82, + 0x0e, 0x1f, 0x06, 0x00, 0x82, 0x0e, 0x07, 0x0e, 0x00, 0x82, 0x3f, 0x27, 0x06, + 0x00, 0x82, 0xc0, 0x80, 0x06, 0x00, 0x82, 0x38, 0xfe, 0x06, 0x00, 0x82, 0x1f, + 0x13, 0x06, 0x00, 0x82, 0x0c, 0x1e, 0x06, 0x00, 0x82, 0x63, 0x67, 0x06, 0x00, + 0x82, 0x80, 0xc0, 0x06, 0x00, 0x00, 0x89, 0x07, 0x1c, 0x30, 0x60, 0x41, 0xc6, + 0x84, 0x88, 0xff, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, 0x89, 0xe1, 0x27, 0x2c, + 0x38, 0xf0, 0x31, 0x21, 0x22, 0xff, 0x03, 0x00, 0x95, 0x7f, 0x80, 0x00, 0x00, + 0xf8, 0x09, 0x0b, 0x0e, 0xfc, 0x0c, 0x08, 0x08, 0x7f, 0xc0, 0x00, 0x00, 0x1f, + 0x60, 0x40, 0x80, 0xfe, 0x03, 0x02, 0x81, 0xfe, 0x03, 0x02, 0xa8, 0x03, 0x0e, + 0x08, 0x18, 0x11, 0x31, 0x22, 0x22, 0xe0, 0x39, 0x0f, 0x0e, 0xc6, 0x46, 0x22, + 0x23, 0xfc, 0x86, 0x7b, 0x8d, 0xb5, 0x8d, 0xb5, 0x7b, 0x88, 0x88, 0x84, 0xc6, + 0x41, 0x60, 0x30, 0x1c, 0xff, 0x07, 0x01, 0x00, 0xf0, 0x0c, 0x04, 0x02, 0x04, + 0xe2, 0x85, 0x63, 0x62, 0x22, 0x22, 0x3f, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, + 0x81, 0xf8, 0x03, 0x18, 0x81, 0xf8, 0x03, 0x18, 0x81, 0x8f, 0x03, 0x88, 0x81, + 0x8f, 0x03, 0x88, 0x81, 0xfe, 0x03, 0x02, 0x88, 0xe2, 0x22, 0x23, 0x23, 0x62, + 0x44, 0x44, 0xc4, 0x03, 0x88, 0x82, 0x11, 0x23, 0x03, 0x11, 0x03, 0x88, 0x84, + 0xc4, 0x86, 0xfc, 0x00, 0x03, 0x80, 0x83, 0xc0, 0x40, 0xff, 0x03, 0x80, 0x81, + 0xff, 0x03, 0x80, 0x95, 0xe2, 0x02, 0x04, 0x0c, 0xf0, 0x00, 0x01, 0x07, 0x22, + 0x22, 0x21, 0x71, 0x70, 0xd8, 0x8c, 0x07, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x03, + 0x00, 0x90, 0xf8, 0x08, 0x08, 0x0c, 0xfc, 0x0e, 0x0b, 0x09, 0x8e, 0x80, 0x40, + 0x60, 0x1f, 0x00, 0x00, 0xc0, 0x02, 0x23, 0x02, 0x22, 0x81, 0xe2, 0x03, 0x00, + 0x85, 0x11, 0x10, 0x22, 0x22, 0x23, 0x03, 0x46, 0x85, 0xc4, 0x04, 0x02, 0x02, + 0xfe, 0x03, 0x00, 0x85, 0x40, 0x60, 0x20, 0x20, 0x30, 0x03, 0x10, 0x81, 0xff, + 0x07, 0x00, 0x81, 0xfc, 0x07, 0x00, 0x81, 0x01, 0x07, 0x00, 0x81, 0xf8, 0x07, + 0x00, 0x81, 0x7f, 0x07, 0x00, 0x81, 0xf0, 0x07, 0x00, 0x97, 0x80, 0x40, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, + 0x80, 0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x94, 0x10, 0x80, 0x08, + 0x00, 0x40, 0x00, 0x04, 0x10, 0x02, 0x24, 0x04, 0x04, 0x02, 0x00, 0x41, 0x00, + 0x4a, 0x20, 0x11, 0x10, 0x04, 0x00, 0x82, 0x22, 0x80, 0x04, 0x00, 0x85, 0x48, + 0x04, 0x20, 0x80, 0x40, 0x05, 0x00, 0x88, 0x04, 0x02, 0x01, 0x00, 0x00, 0x08, + 0x20, 0x90, 0x06, 0x00, 0xaa, 0x08, 0x04, 0x40, 0x12, 0x10, 0x00, 0x10, 0x12, + 0x08, 0x20, 0x04, 0x48, 0x08, 0x08, 0x04, 0x00, 0x88, 0x04, 0x92, 0x40, 0x21, + 0x20, 0x00, 0x00, 0x24, 0x42, 0x00, 0x24, 0x01, 0x18, 0x82, 0x00, 0x24, 0x50, + 0x82, 0x24, 0x04, 0x04, 0x02, 0x00, 0x20, 0x90, 0x05, 0x00, 0x81, 0x02, 0x04, + 0x00, 0x86, 0x88, 0x00, 0x00, 0x04, 0x20, 0x40, 0x06, 0x00, 0x84, 0x01, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x85, 0x02, 0x40, 0x00, 0x00, 0xa0, 0x03, 0x00, 0x90, + 0x40, 0x00, 0x08, 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x04, 0x00, 0x20, 0x00, + 0x02, 0x00, 0x10, 0x05, 0x00, 0x02, 0x10, 0x86, 0x08, 0x20, 0x00, 0x00, 0x08, + 0x80, 0x03, 0x40, 0x81, 0x88, 0x12, 0x00, 0x81, 0x08, 0x0b, 0x00, 0x8a, 0x40, + 0x00, 0x40, 0x04, 0x08, 0x40, 0x44, 0x20, 0x02, 0x10, 0x03, 0x00, 0x89, 0x01, + 0x20, 0x20, 0x10, 0x41, 0x00, 0x00, 0x10, 0x00, 0x03, 0x80, 0x82, 0x10, 0x44, + 0x0a, 0x00, 0x89, 0x01, 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x00, 0x28, 0x03, + 0x00, 0x81, 0x90, 0x08, 0x00, 0x82, 0x48, 0x84, 0x06, 0x00, 0x82, 0x11, 0x20, + 0x06, 0x00, 0x82, 0x24, 0xc2, 0x06, 0x00, 0x82, 0x11, 0x20, 0x07, 0x00, 0x81, + 0x84, 0x06, 0x00, 0x82, 0x10, 0x20, 0x06, 0x00, 0x82, 0x22, 0x41, 0x06, 0x00, + 0x82, 0x04, 0x08, 0x0e, 0x00, 0x82, 0x91, 0x20, 0x06, 0x00, 0x82, 0x01, 0x88, + 0x07, 0x00, 0x81, 0x80, 0x07, 0x00, 0x81, 0x08, 0x06, 0x00, 0x82, 0x20, 0x40, + 0x06, 0x00, 0x81, 0x44, 0x08, 0x00, 0x81, 0x04, 0x06, 0x00, 0x82, 0x92, 0x21, + 0x06, 0x00, 0x82, 0x04, 0x08, 0x06, 0x00, 0x82, 0x40, 0x20, 0x06, 0x00, 0x00, + 0x89, 0x00, 0x03, 0x0f, 0x1f, 0x3e, 0x39, 0x7b, 0x77, 0x00, 0x03, 0xff, 0x81, + 0x00, 0x03, 0xff, 0x89, 0x00, 0xc0, 0xc3, 0xc7, 0x0f, 0xce, 0xde, 0xdd, 0x00, + 0x03, 0xff, 0x95, 0x80, 0x7f, 0xff, 0xff, 0x00, 0xf0, 0xf0, 0xf1, 0x03, 0xf3, + 0xf7, 0xf7, 0x00, 0x3f, 0xff, 0xff, 0xe0, 0x9f, 0xbf, 0x7f, 0x00, 0x03, 0xfc, + 0x81, 0x00, 0x03, 0xfc, 0x82, 0x00, 0x01, 0x02, 0x07, 0x02, 0x0e, 0x02, 0x1d, + 0xa0, 0x00, 0xc0, 0xf0, 0xf1, 0x39, 0xb9, 0xdd, 0xdc, 0x00, 0x78, 0x84, 0x72, + 0x4a, 0x72, 0x4a, 0x84, 0x77, 0x77, 0x7b, 0x39, 0x3e, 0x1f, 0x0f, 0x03, 0x00, + 0xf8, 0xfe, 0xff, 0x0f, 0xf3, 0xfb, 0xfd, 0x04, 0x1d, 0x85, 0x9c, 0x9d, 0xdd, + 0xdd, 0xc0, 0x03, 0xff, 0x81, 0x00, 0x03, 0xff, 0x81, 0x07, 0x03, 0xe7, 0x81, + 0x07, 0x03, 0xe7, 0x81, 0x70, 0x03, 0x77, 0x81, 0x70, 0x03, 0x77, 0x81, 0x00, + 0x03, 0xfc, 0x81, 0x1c, 0x03, 0xdc, 0x81, 0x1d, 0x03, 0x3b, 0x03, 0x77, 0x82, + 0xee, 0xdc, 0x03, 0xee, 0x03, 0x77, 0x82, 0x3b, 0x78, 0x06, 0x00, 0x82, 0x80, + 0x00, 0x03, 0x7f, 0x81, 0x00, 0x03, 0x7f, 0x95, 0x1d, 0xfd, 0xfb, 0xf3, 0x0f, + 0xff, 0xfe, 0xf8, 0xdd, 0xdd, 0xde, 0x8e, 0x8f, 0x07, 0x03, 0x00, 0xc0, 0xff, + 0xff, 0x7f, 0x80, 0x03, 0xff, 0x90, 0x07, 0xf7, 0xf7, 0xf3, 0x03, 0xf1, 0xf0, + 0xf0, 0x71, 0x7f, 0xbf, 0x9f, 0xe0, 0xff, 0xff, 0x3f, 0x02, 0xdc, 0x02, 0xdd, + 0x81, 0x1d, 0x03, 0xff, 0x85, 0xee, 0xef, 0xdd, 0xdd, 0xdc, 0x03, 0xb9, 0x85, + 0x3b, 0xfb, 0xfd, 0xfd, 0x01, 0x03, 0xff, 0x02, 0x80, 0x03, 0xc0, 0x03, 0xe0, + 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0x00, 0x7f, 0x00, 0x7f, 0x00, + 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x55, 0x00, 0x00, 0x08, 0x00, 0x07, 0xff, + 0x81, 0xfe, 0x07, 0xff, 0x81, 0x00, 0x0f, 0xfe, 0x8f, 0x00, 0x81, 0xc3, 0xe7, + 0xff, 0xff, 0xc1, 0x81, 0x91, 0x91, 0x99, 0x81, 0xc3, 0xc3, 0x81, 0x03, 0x99, + 0x85, 0x81, 0xc3, 0xc3, 0x81, 0x99, 0x02, 0x81, 0x02, 0x99, 0x04, 0x8f, 0x02, + 0x81, 0x84, 0xff, 0x7e, 0x3c, 0x18, 0x04, 0x00, 0x81, 0x78, 0x04, 0xfc, 0x84, + 0x78, 0x2a, 0x00, 0x78, 0x04, 0xfc, 0x84, 0x78, 0x54, 0x00, 0x1e, 0x04, 0x3f, + 0x84, 0x1e, 0x54, 0x00, 0x1e, 0x04, 0x3f, 0xa3, 0x1e, 0x2a, 0x00, 0x1e, 0x7f, + 0x3f, 0x7f, 0x3f, 0x5e, 0x00, 0x00, 0x1e, 0x3f, 0x7f, 0x3f, 0x7f, 0x1e, 0x40, + 0x00, 0x00, 0x02, 0x78, 0xfe, 0xfc, 0xfe, 0xfc, 0x78, 0x00, 0x00, 0x7a, 0xfc, + 0xfe, 0xfc, 0xfe, 0x78, 0x00, 0x07, 0x00, 0x81, 0xff, 0x07, 0x00, 0x81, 0x01, + 0x07, 0x00, 0x81, 0xff, 0x0f, 0x01, 0x84, 0xff, 0x81, 0xc3, 0xe7, 0x1e, 0xff, + 0x83, 0x7e, 0x3c, 0x18, 0x04, 0x00, 0xc0, 0x78, 0xcc, 0xb5, 0xac, 0xc4, 0x78, + 0x00, 0x00, 0x78, 0xcc, 0xb4, 0xad, 0xc4, 0x78, 0x00, 0x00, 0x1e, 0x33, 0xad, + 0x35, 0x23, 0x1e, 0x00, 0x00, 0x1e, 0x33, 0x2d, 0xb5, 0x23, 0x1e, 0x00, 0x00, + 0x1e, 0x33, 0x2d, 0x25, 0x2b, 0x1e, 0x00, 0x08, 0x1e, 0x33, 0x2d, 0x25, 0x2b, + 0x1e, 0x00, 0x04, 0x20, 0x00, 0x78, 0xd4, 0xa4, 0xb4, 0xcc, 0x78, 0x10, 0x00, + 0x78, 0xd4, 0xa4, 0xb4, 0xcc, 0x78, 0x00, 0x07, 0x00, 0x21, 0xff, 0x8e, 0x81, + 0xc3, 0xe7, 0xff, 0xff, 0xc1, 0xbf, 0xf1, 0xff, 0xff, 0xe7, 0xff, 0xc3, 0xbd, + 0x03, 0xff, 0x86, 0xe7, 0xff, 0xc3, 0xbd, 0xff, 0xe7, 0x03, 0xff, 0x81, 0x8f, + 0x03, 0xff, 0x86, 0xf1, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x05, 0x00, 0xbf, 0x30, + 0x49, 0x51, 0x3b, 0x07, 0xfe, 0x00, 0x00, 0x30, 0x48, 0x51, 0x3b, 0x07, 0xfe, + 0x00, 0x00, 0x0c, 0x92, 0x8a, 0xdc, 0xe0, 0x7f, 0x00, 0x00, 0x0c, 0x12, 0x8a, + 0xdc, 0xe0, 0x7f, 0x00, 0x40, 0x4c, 0x52, 0x5a, 0x54, 0x60, 0x70, 0x38, 0x40, + 0x4c, 0x52, 0x5a, 0x54, 0x60, 0x70, 0x3c, 0x3c, 0x0e, 0x06, 0x2a, 0x5a, 0x4a, + 0x32, 0x02, 0x1c, 0x0e, 0x06, 0x2a, 0x5a, 0x4a, 0x32, 0x02, 0x00, 0x7f, 0x00, + 0x11, 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, 0x7c, 0xfc, + 0xe0, 0xf8, 0x7c, 0x1c, 0xfc, 0xf8, 0x7c, 0xfc, 0xc0, 0xf8, 0xf8, 0xc0, 0xfc, + 0x7c, 0x7c, 0xfc, 0xc0, 0xdc, 0xdc, 0xcc, 0xfc, 0x7c, 0x38, 0x38, 0x7c, 0x5c, + 0x5c, 0xce, 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x00, 0x18, 0x3e, 0x58, + 0x3c, 0x1a, 0x7c, 0x18, 0x00, 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x70, 0xc8, 0xc8, 0x70, 0x9a, 0x8c, 0x76, 0x00, 0x18, 0x18, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, + 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x18, 0x5a, 0x3c, 0x3c, 0x5a, 0x18, + 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, + 0xc0, 0x00, 0x38, 0x4c, 0xc6, 0xc6, 0xc6, 0x64, 0x38, 0x00, 0x18, 0x38, 0x18, + 0x18, 0x18, 0x18, 0x7e, 0x00, 0x7c, 0xc6, 0x0e, 0x3c, 0x78, 0xe0, 0xfe, 0x00, + 0x7e, 0x0c, 0x18, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, + 0x0c, 0x0c, 0x00, 0xfc, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x3c, 0x60, + 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, + 0x00, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, + 0x06, 0x0c, 0x78, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, + 0x0c, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, + 0x0c, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0x06, 0x1c, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0x06, 0x66, 0xd6, 0xd6, 0x7c, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, + 0xc6, 0xc6, 0x00, 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00, 0x3c, 0x66, + 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, + 0x00, 0xfe, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xfe, 0x00, 0xfe, 0xc0, 0xc0, 0xf8, + 0xc0, 0xc0, 0xc0, 0x00, 0x3e, 0x60, 0xc0, 0xce, 0xc6, 0x66, 0x3e, 0x00, 0xc6, + 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x7e, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0xc6, 0xcc, 0xd8, + 0xf0, 0xf8, 0xdc, 0xce, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, + 0xce, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xfc, 0xc6, + 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xcc, 0x76, + 0x00, 0xfc, 0xc6, 0xc6, 0xce, 0xf8, 0xdc, 0xce, 0x00, 0x78, 0xcc, 0xc0, 0x7c, + 0x06, 0xc6, 0x7c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xee, 0x7c, 0x38, + 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x44, 0x00, 0xc6, 0xee, 0x7c, + 0x38, 0x7c, 0xee, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, + 0xfe, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xfe, 0x00, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xf8, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0xf8, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x20, 0x50, 0x88, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x21, 0x00, + 0x08, 0xff, 0x00, 0x7f, 0x00, 0x29, 0x00, 0x00, 0x7f, 0x00, 0x21, 0x00, 0x08, + 0xff, 0x00, 0x02, 0xff, 0x05, 0xf0, 0x81, 0xff, 0x02, 0xf8, 0x05, 0x00, 0x81, + 0xe0, 0x02, 0xf8, 0x03, 0xfc, 0x03, 0xf6, 0x08, 0x78, 0x02, 0x1f, 0x06, 0x03, + 0x82, 0xf1, 0xf3, 0x06, 0xc3, 0x02, 0xff, 0x06, 0xc0, 0x81, 0xe7, 0x02, 0xf3, + 0x02, 0xf1, 0x03, 0xf0, 0x02, 0x80, 0x02, 0xc1, 0x02, 0xe3, 0x83, 0xf7, 0x7f, + 0xf0, 0x02, 0xe0, 0x02, 0xc0, 0x02, 0x80, 0x82, 0x00, 0xff, 0x05, 0xf0, 0x02, + 0xff, 0x81, 0xe0, 0x05, 0x00, 0x02, 0xf8, 0x03, 0xf3, 0x03, 0xf1, 0x02, 0xf0, + 0x02, 0x78, 0x81, 0x79, 0x04, 0xf9, 0x81, 0xf8, 0x02, 0x03, 0x04, 0xe3, 0x02, + 0xff, 0x07, 0xc3, 0x81, 0x81, 0x06, 0xc0, 0x02, 0xff, 0x07, 0xf0, 0x82, 0xe0, + 0x7f, 0x07, 0x3e, 0x04, 0x78, 0x02, 0x00, 0x02, 0x78, 0x08, 0x00, 0x00, 0xb8, + 0x60, 0xf0, 0x41, 0x03, 0x0d, 0x00, 0x0d, 0xc3, 0x00, 0x50, 0x8d, 0x43, 0x78, + 0x77, 0x79, 0x5d, 0x03, 0xad, 0xd1, 0x10, 0x50, 0x55, 0x64, 0x65, 0x40, 0x51, + 0x2d, 0x35, 0x24, 0x22, 0x81, 0x81, 0x43, 0x55, 0x41, 0x05, 0x75, 0xfb, 0x40, + 0x00, 0x52, 0x68, 0x8d, 0xc5, 0x22, 0x2e, 0xcd, 0x0c, 0x14, 0x94, 0x35, 0xd1, + 0x43, 0x7b, 0x51, 0x01, 0xe1, 0x56, 0x45, 0x63, 0x50, 0x6d, 0x18, 0x41, 0x8e, + 0x5b, 0x5d, 0x1e, 0x98, 0x10, 0xd4, 0x12, 0x34, 0x6e, 0x55, 0xeb, 0x48, 0x47, + 0x5b, 0x04, 0x74, 0x5b, 0x85, 0x4d, 0x83, 0xb6, 0x2d, 0xd1, 0x58, 0x6d, 0x35, + 0x92, 0x0e, 0xd8, 0x42, 0x04, 0x2d, 0x92, 0x45, 0xd7, 0x11, 0x20, 0x06, 0x41, + 0x76, 0x63, 0x8d, 0x61, 0xd4, 0x00, 0xd8, 0x36, 0x98, 0x5d, 0xdd, 0xb4, 0xbb, + 0x77, 0xa3, 0x77, 0x0f, 0x56, 0x89, 0x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0xa8, + 0xa0, 0x58, 0xf0, 0x01, 0x4d, 0x37, 0x04, 0x1d, 0x30, 0x1e, 0xad, 0x4d, 0x11, + 0x06, 0x75, 0x08, 0x4d, 0x7b, 0x57, 0x51, 0xd4, 0x75, 0x61, 0xd3, 0xba, 0x2e, + 0xae, 0xad, 0x83, 0x69, 0x4d, 0x2e, 0xd4, 0x75, 0x5b, 0x41, 0x50, 0x1d, 0xd2, + 0x78, 0x4b, 0x18, 0x56, 0x0d, 0x6e, 0x08, 0xad, 0x23, 0xbe, 0x07, 0x55, 0x35, + 0x35, 0x34, 0xd2, 0x4e, 0xd8, 0xd2, 0x56, 0x41, 0xc5, 0x06, 0x63, 0x3b, 0x11, + 0x8d, 0x5b, 0x4d, 0xb8, 0x7b, 0xbd, 0x48, 0x44, 0x01, 0x54, 0x11, 0xd4, 0x6e, + 0xd5, 0x8e, 0x55, 0x00, 0x55, 0xed, 0x2d, 0xb8, 0x18, 0x35, 0xd6, 0xd0, 0x56, + 0x61, 0xc8, 0xed, 0xed, 0xd6, 0x38, 0x15, 0x55, 0x81, 0x4d, 0x51, 0x51, 0x63, + 0xe0, 0x82, 0x59, 0x75, 0x51, 0x6c, 0x60, 0x14, 0x53, 0x03, 0xae, 0x55, 0x23, + 0x11, 0x10, 0x05, 0x56, 0x0d, 0x58, 0x21, 0x02, 0x08, 0x08, 0x00, 0x88, 0x00, + 0xa0, 0x88, 0xb8, 0x50, 0x7d, 0x37, 0x30, 0x80, 0x77, 0x77, 0x77, 0x53, 0x15, + 0xe2, 0xe0, 0x74, 0x55, 0x55, 0x61, 0xad, 0xd5, 0x5d, 0x83, 0x55, 0x55, 0x55, + 0xb4, 0x51, 0x55, 0x55, 0x40, 0x55, 0x6d, 0xe1, 0xd5, 0x55, 0x55, 0xd5, 0x6d, + 0x55, 0x35, 0x82, 0x58, 0x55, 0x55, 0x55, 0x51, 0x55, 0xd9, 0x00, 0x54, 0x55, + 0x61, 0x55, 0x6d, 0x55, 0x14, 0x00, 0x85, 0x54, 0x8d, 0x55, 0x51, 0x21, 0xd8, + 0x00, 0x02, 0x94, 0x31, 0x88, 0x63, 0x0d, 0x2e, 0x00, 0x35, 0x58, 0xed, 0x00, + 0x5e, 0x01, 0xd5, 0x00, 0x06, 0x54, 0x11, 0x00, 0x55, 0x73, 0x38, 0x00, 0x34, + 0x58, 0x6d, 0x03, 0x56, 0x55, 0x57, 0x03, 0x08, 0x55, 0x51, 0x00, 0x88, 0x55, + 0x55, 0x00, 0x34, 0xa2, 0x2d, 0x0d, 0x00, 0x56, 0x45, 0x03, 0x0b, 0x50, 0x75, + 0x05, 0x0d, 0x21, 0x82, 0x8d, 0x0d, 0xa0, 0x21, 0x02, 0x08, 0x08, 0x00, 0x02, + 0x02, 0xa0, 0xa8, 0x58, 0x38, 0xdd, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x31, 0x50, + 0x55, 0x83, 0xc3, 0x00, 0x02, 0x40, 0x04, 0x58, 0x55, 0xd0, 0x5e, 0x03, 0x00, + 0x10, 0x01, 0x50, 0x55, 0xa3, 0x65, 0xcd, 0x00, 0xd5, 0xd0, 0x6d, 0x85, 0x0c, + 0x8e, 0x56, 0x03, 0x46, 0x8b, 0x98, 0xd5, 0x36, 0x01, 0x88, 0xd0, 0x00, 0x0d, + 0x54, 0x15, 0xd8, 0x0d, 0xd0, 0x60, 0x83, 0x05, 0x51, 0xd5, 0x6d, 0x35, 0x64, + 0x53, 0x74, 0xb5, 0x54, 0x55, 0xb5, 0xd5, 0xb5, 0x14, 0x55, 0xd5, 0x55, 0x55, + 0xd5, 0x56, 0x45, 0x45, 0x6d, 0x55, 0x55, 0x55, 0x55, 0x5b, 0x81, 0x21, 0x16, + 0x88, 0x55, 0x45, 0x65, 0x55, 0x41, 0x0d, 0x08, 0x74, 0x55, 0x71, 0x15, 0x52, + 0x80, 0xf5, 0x00, 0x55, 0x55, 0x6d, 0x48, 0x07, 0x00, 0x58, 0x43, 0x55, 0x57, + 0x85, 0x8f, 0x35, 0x00, 0x60, 0x8d, 0x55, 0x55, 0x01, 0x02, 0x22, 0x00, 0x00, + 0x0a, 0x20, 0xa2, 0x40, 0xb0, 0xf0, 0x31, 0xf4, 0x3d, 0xd0, 0xd0, 0x1e, 0xd1, + 0x94, 0x4d, 0x55, 0xd8, 0x45, 0x87, 0x7b, 0x2d, 0x59, 0xb5, 0x61, 0x87, 0x11, + 0x02, 0x12, 0xd2, 0x50, 0x05, 0x1e, 0x36, 0x4e, 0x43, 0xe0, 0x84, 0x57, 0x45, + 0x0b, 0x0b, 0xc5, 0x1e, 0x44, 0xfb, 0x5a, 0x41, 0x53, 0x80, 0x12, 0x45, 0xbb, + 0x60, 0x97, 0x8d, 0xee, 0xd0, 0xd3, 0x52, 0xe0, 0x8d, 0x55, 0x4d, 0x3b, 0x6e, + 0x2e, 0x2d, 0xb4, 0xf4, 0xa2, 0x85, 0xee, 0x13, 0x78, 0x46, 0xdb, 0x18, 0x5e, + 0x35, 0x85, 0xed, 0x2d, 0x81, 0x63, 0xe4, 0x98, 0x8d, 0xd1, 0x92, 0x10, 0x8d, + 0x1d, 0xb4, 0x6d, 0x51, 0x60, 0xe3, 0x4d, 0xd1, 0x06, 0x08, 0x91, 0x6d, 0x93, + 0x50, 0xb8, 0x87, 0x7b, 0x37, 0x56, 0x7d, 0x45, 0xa4, 0xd7, 0x76, 0xac, 0x45, + 0xaf, 0x15, 0x12, 0xcd, 0x16, 0x15, 0xd1, 0x82, 0x55, 0x09, 0x20, 0x88, 0x20, + 0x82, 0x00, 0x20, 0xa2, 0xb0, 0x80, 0x68, 0x0d, 0x40, 0x0f, 0x0d, 0x11, 0x74, + 0x03, 0x50, 0x35, 0x5d, 0x75, 0x75, 0x35, 0x60, 0x01, 0xa0, 0x55, 0x55, 0x55, + 0x55, 0x75, 0x80, 0x34, 0x50, 0x55, 0x55, 0x56, 0x55, 0x18, 0xd0, 0x40, 0x97, + 0x55, 0x15, 0x58, 0x18, 0xd0, 0x21, 0x50, 0x55, 0x55, 0x08, 0x20, 0x00, 0x58, + 0xdd, 0x54, 0x95, 0x05, 0x00, 0xf4, 0x00, 0x54, 0x55, 0x65, 0x55, 0x75, 0xf7, + 0x55, 0x03, 0x55, 0x55, 0x8d, 0x55, 0x21, 0x62, 0x55, 0x41, 0x55, 0x15, 0x75, + 0x55, 0x0d, 0x80, 0x55, 0x80, 0xb5, 0x48, 0x55, 0x95, 0x05, 0x70, 0x15, 0x00, + 0x06, 0x13, 0x5a, 0x65, 0x01, 0x54, 0x05, 0x00, 0x41, 0x05, 0x6c, 0x5d, 0x0d, + 0x55, 0x01, 0xd0, 0x5e, 0x08, 0x78, 0x55, 0x05, 0x66, 0x0d, 0x54, 0x1b, 0x00, + 0x54, 0x55, 0x71, 0x83, 0x01, 0x56, 0xed, 0x00, 0x25, 0x5a, 0x21, 0x02, 0x00, + 0x20, 0x82, 0x00, 0x02, 0xa0, 0x78, 0x70, 0x78, 0x0d, 0x00, 0x38, 0x03, 0x00, + 0xe0, 0x00, 0x50, 0x35, 0x00, 0x44, 0x00, 0x00, 0x00, 0x34, 0xad, 0xd5, 0x00, + 0xb8, 0x23, 0x00, 0x40, 0x5b, 0x51, 0x15, 0x00, 0x44, 0x0d, 0x00, 0xb4, 0x54, + 0xad, 0x55, 0x03, 0xb8, 0x35, 0x00, 0x45, 0x1b, 0x52, 0x55, 0x00, 0x80, 0x14, + 0x4d, 0x81, 0x54, 0xa3, 0x55, 0x03, 0x00, 0x88, 0xb8, 0x1d, 0x18, 0x5e, 0x6d, + 0x0d, 0x37, 0x1c, 0x40, 0x08, 0x00, 0x55, 0xb5, 0x75, 0xe1, 0xd8, 0x80, 0x0d, + 0x00, 0x56, 0x55, 0x55, 0x81, 0xd7, 0x00, 0x02, 0x00, 0x55, 0x55, 0x55, 0x41, + 0x55, 0xc0, 0xdd, 0x8d, 0x55, 0x55, 0x61, 0x5d, 0xd5, 0x50, 0x55, 0xdd, 0x55, + 0x55, 0x80, 0x55, 0x59, 0x63, 0x55, 0x55, 0x58, 0x15, 0x03, 0x4a, 0x5d, 0x50, + 0x89, 0x55, 0xa3, 0x45, 0x00, 0x50, 0x58, 0x63, 0x00, 0x88, 0x50, 0x01, 0x00, + 0x00, 0x88, 0x00, 0x20, 0x00, 0xa0, 0x78, 0x48, 0xe0, 0xdd, 0x00, 0xdd, 0x40, + 0x34, 0x77, 0x03, 0x50, 0x55, 0x43, 0x55, 0x03, 0xd6, 0x16, 0x8e, 0xa4, 0x85, + 0x5d, 0x54, 0x00, 0x55, 0x01, 0x00, 0x51, 0x41, 0x15, 0x56, 0x03, 0x56, 0xd0, + 0x40, 0x57, 0x4d, 0x45, 0x88, 0x00, 0x18, 0x60, 0x53, 0x55, 0xb5, 0x50, 0x03, + 0x0c, 0xd4, 0x5d, 0x85, 0x55, 0x05, 0xd5, 0xde, 0xe1, 0x55, 0x58, 0x01, 0x56, + 0x71, 0x15, 0x88, 0x5d, 0x95, 0x63, 0x00, 0x58, 0x6d, 0xd5, 0x00, 0x56, 0x35, + 0xde, 0x10, 0x94, 0x51, 0x15, 0x00, 0x55, 0x05, 0x55, 0xe3, 0x55, 0x6d, 0xd8, + 0x8c, 0x56, 0x7b, 0x55, 0x50, 0xad, 0x15, 0xa0, 0xfb, 0x55, 0x60, 0x15, 0x54, + 0x55, 0xd5, 0x70, 0x5d, 0x88, 0x80, 0xd5, 0x58, 0x55, 0x85, 0x63, 0x15, 0x0e, + 0x00, 0x5a, 0x63, 0x58, 0x75, 0x50, 0x35, 0x78, 0x77, 0x57, 0x80, 0x57, 0x21, + 0xa0, 0x08, 0x20, 0x22, 0x22, 0x00, 0xa2, 0x58, 0xb0, 0xe8, 0x0d, 0x34, 0xb0, + 0xb7, 0xc7, 0xe0, 0xec, 0x5d, 0x35, 0xe1, 0x44, 0xd1, 0x12, 0x34, 0x51, 0x55, + 0x11, 0x10, 0xb5, 0x2e, 0xed, 0x51, 0x84, 0x55, 0x31, 0x04, 0x06, 0x75, 0x81, + 0x6d, 0xcb, 0x96, 0x1d, 0xd4, 0x51, 0x11, 0x1e, 0xb8, 0x10, 0x55, 0xc5, 0x55, + 0x60, 0x20, 0xfb, 0x40, 0x63, 0x98, 0xb5, 0x2e, 0xb4, 0x47, 0xad, 0x53, 0x51, + 0x6f, 0x45, 0x38, 0xd8, 0x62, 0xd1, 0x96, 0x20, 0x52, 0x51, 0x04, 0x6d, 0x43, + 0x24, 0xed, 0xdd, 0xa0, 0x15, 0xd0, 0xb6, 0x8d, 0x3b, 0x82, 0x1b, 0x50, 0x05, + 0x11, 0xd8, 0x42, 0x05, 0x41, 0xed, 0x6d, 0x4d, 0x04, 0x54, 0xd3, 0xbe, 0x8d, + 0x51, 0x51, 0x1d, 0x38, 0x61, 0x2d, 0xd8, 0xd2, 0x6e, 0x94, 0x05, 0x2d, 0x1e, + 0x42, 0x87, 0x14, 0x82, 0x55, 0x41, 0x40, 0x0b, 0x77, 0x35, 0x7b, 0x77, 0x59, + 0x01, 0x20, 0x02, 0x22, 0x82, 0x20, 0x22, 0xa8, 0x40, 0x40, 0xe8, 0x75, 0xd3, + 0x04, 0xc3, 0x4e, 0x37, 0x0d, 0x92, 0x21, 0x24, 0xdd, 0x2e, 0x11, 0x61, 0x38, + 0x55, 0x3d, 0x75, 0x15, 0x41, 0x44, 0x4e, 0x47, 0x58, 0x59, 0x18, 0xd6, 0xbe, + 0x11, 0x34, 0x12, 0x94, 0x2d, 0xec, 0xd5, 0xd4, 0xee, 0x49, 0xd1, 0x5d, 0x01, + 0xb8, 0x98, 0x1b, 0xb4, 0x5d, 0x84, 0x68, 0xdd, 0xed, 0x60, 0xd1, 0x48, 0x28, + 0x0d, 0x50, 0x85, 0x51, 0x83, 0x14, 0x5d, 0x43, 0xd0, 0x94, 0x71, 0xa0, 0xdd, + 0xd9, 0xb6, 0x10, 0x24, 0x61, 0x2d, 0x3d, 0x86, 0x23, 0x45, 0x2f, 0x41, 0x57, + 0x71, 0x08, 0x41, 0xd1, 0xb8, 0x35, 0x1e, 0x56, 0x2d, 0x51, 0x51, 0x20, 0xed, + 0x49, 0x4b, 0x5b, 0x75, 0x54, 0x14, 0x70, 0xb6, 0x50, 0x50, 0x94, 0x15, 0xd4, + 0xd8, 0x22, 0x49, 0x27, 0x2d, 0x58, 0x49, 0x1d, 0x6c, 0x77, 0xd0, 0xd1, 0x72, + 0x57, 0x81, 0x08, 0x02, 0x22, 0x80, 0x88, 0x20, 0xa2, 0x60, 0x60, 0xf0, 0x1d, + 0xf0, 0x4d, 0x03, 0x4d, 0x74, 0x8c, 0xa3, 0x09, 0x6d, 0x50, 0x10, 0x11, 0x2d, + 0x31, 0x50, 0xcd, 0x55, 0x2d, 0x4d, 0x5d, 0x78, 0x44, 0x97, 0x91, 0x85, 0x41, + 0x4b, 0x44, 0x23, 0x35, 0x66, 0x51, 0xf8, 0x8e, 0x1d, 0x81, 0x34, 0xe1, 0x58, + 0x2d, 0x2c, 0x45, 0x49, 0x34, 0xd5, 0x8e, 0x50, 0xd1, 0x39, 0x52, 0x38, 0x49, + 0x24, 0x0d, 0x6d, 0x85, 0xdd, 0x2d, 0x44, 0x8d, 0x3b, 0x7a, 0x91, 0xc1, 0x56, + 0x04, 0x51, 0x41, 0xc4, 0x6e, 0x6c, 0x01, 0x18, 0x79, 0x84, 0x10, 0x05, 0xb8, + 0x51, 0x4d, 0x83, 0xe0, 0x40, 0x43, 0x31, 0x0d, 0x6e, 0x11, 0xee, 0x60, 0x93, + 0x10, 0x2e, 0x76, 0x50, 0xed, 0xbb, 0x83, 0xd7, 0x8d, 0xdb, 0xe8, 0x9d, 0xb1, + 0x4c, 0x43, 0x85, 0x41, 0x20, 0x8d, 0x5b, 0xed, 0x51, 0x50, 0x35, 0x5e, 0x77, + 0xf8, 0x56, 0x89, 0x20, 0x20, 0x0a, 0x88, 0x22, 0x20, 0x28, 0x40, 0x88, 0xc0, + 0x35, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x50, 0xd5, 0x00, 0x00, 0x40, 0x35, + 0x00, 0x00, 0x54, 0x55, 0x03, 0x00, 0x50, 0xd5, 0x00, 0x00, 0x55, 0x55, 0x0d, + 0x00, 0x54, 0x55, 0x03, 0x40, 0x55, 0x55, 0x35, 0x00, 0x55, 0x55, 0x0d, 0x50, + 0x55, 0x55, 0xd5, 0x40, 0x55, 0x55, 0x35, 0x54, 0x55, 0x55, 0x55, 0x53, 0x55, + 0x55, 0xd5, 0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x05, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x58, 0x55, 0x55, 0x55, + 0x56, 0x55, 0x55, 0x00, 0x60, 0x55, 0x55, 0x55, 0x5b, 0x55, 0x15, 0x00, 0x80, + 0x55, 0x55, 0x55, 0x60, 0x55, 0x05, 0x00, 0x00, 0x56, 0x55, 0x15, 0x80, 0x55, + 0x0d, 0x00, 0x00, 0x58, 0x55, 0x05, 0x00, 0x56, 0x0d, 0x00, 0x00, 0x60, 0x55, + 0x01, 0x00, 0x58, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xa0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff + }; + #endregion + + #region Japanese Mark III System BIOS [No Cartridge Present] + public static readonly byte[] Mk3Bios = + { + 0xf3, 0xed, 0x56, 0x31, 0xef, 0xdf, 0x18, 0x60, 0xe7, 0x01, 0xbe, 0x00, 0x1e, + 0x02, 0xed, 0xb3, 0xed, 0xb3, 0xed, 0xb3, 0x1d, 0x20, 0xf7, 0xc9, 0xe5, 0xe1, + 0xc9, 0xff, 0xff, 0x11, 0xe0, 0x81, 0x7b, 0xd3, 0xbf, 0x7a, 0xd3, 0xbf, 0xc9, + 0xff, 0x4f, 0x06, 0x00, 0x09, 0x09, 0x7e, 0x23, 0x66, 0x6f, 0xc9, 0x06, 0x06, + 0xc3, 0x2e, 0x01, 0xff, 0xf5, 0xdb, 0xbf, 0xc5, 0xd5, 0xe5, 0x08, 0xf5, 0xdb, + 0xdd, 0xe6, 0x10, 0x21, 0x04, 0xc1, 0x4e, 0x77, 0xa9, 0xa1, 0x20, 0x5d, 0xcd, + 0xdd, 0x01, 0x21, 0x00, 0xc1, 0x7e, 0x36, 0x00, 0x1f, 0xdc, 0xf5, 0x01, 0xcd, + 0xa8, 0x0a, 0xf1, 0x08, 0xe1, 0xd1, 0xc1, 0xf1, 0xfb, 0xc9, 0xff, 0xed, 0x45, + 0xf3, 0xcd, 0x32, 0x00, 0x21, 0xf2, 0x00, 0x11, 0x00, 0xc7, 0x01, 0x3c, 0x00, + 0xed, 0xb0, 0xcd, 0x00, 0xc7, 0x21, 0x00, 0xc0, 0x11, 0x01, 0xc0, 0x01, 0xfe, + 0x1f, 0x36, 0x00, 0xed, 0xb0, 0x21, 0xd9, 0x1d, 0xcd, 0x39, 0x01, 0x21, 0x00, + 0xc8, 0x01, 0x06, 0x00, 0x7e, 0x23, 0xfe, 0x03, 0x30, 0x02, 0x36, 0x00, 0x23, + 0x10, 0xf5, 0x0d, 0x20, 0xf2, 0x06, 0x01, 0xcd, 0x2e, 0x01, 0x3e, 0x03, 0xd3, + 0xf2, 0x31, 0xef, 0xdf, 0xcd, 0x69, 0x01, 0x3e, 0x01, 0x32, 0x40, 0xc1, 0x3e, + 0xd0, 0x32, 0x00, 0xc3, 0xfb, 0x3e, 0x01, 0xcd, 0x60, 0x01, 0xf3, 0x11, 0x00, + 0x40, 0x01, 0x20, 0x00, 0xcd, 0xce, 0x01, 0x21, 0x97, 0x14, 0x11, 0x20, 0x40, + 0xcd, 0x91, 0x01, 0x21, 0x00, 0xc8, 0x11, 0x00, 0x78, 0xcf, 0xcd, 0x1d, 0x00, + 0xfb, 0x3e, 0x81, 0x32, 0x03, 0xde, 0x3e, 0x01, 0xcd, 0x60, 0x01, 0x3e, 0x02, + 0x32, 0x40, 0xc1, 0xcd, 0xae, 0x02, 0x18, 0xf1, 0xdb, 0xdc, 0x21, 0x39, 0xc7, + 0x06, 0x03, 0x3e, 0xeb, 0xd3, 0x3e, 0x7e, 0x32, 0x00, 0xc0, 0xd3, 0x3e, 0xd9, + 0xcd, 0x26, 0xc7, 0xd9, 0x23, 0x10, 0xee, 0xaf, 0x32, 0x00, 0xc0, 0x3e, 0xeb, + 0xd3, 0x3e, 0x3e, 0xe3, 0xd3, 0x3e, 0xc9, 0x21, 0x00, 0x00, 0x01, 0x3c, 0x00, + 0x7e, 0xa1, 0x5f, 0x7e, 0x2c, 0xa1, 0xbb, 0xc2, 0x00, 0x00, 0x10, 0xf7, 0xc9, + 0xcb, 0xab, 0x6b, 0x11, 0x00, 0x40, 0x1b, 0x7a, 0xb3, 0x20, 0xfb, 0x10, 0xf6, + 0xc9, 0x11, 0x00, 0xc8, 0xd5, 0xcd, 0x42, 0x01, 0xd1, 0x13, 0x7e, 0x23, 0xb7, + 0xc8, 0xf2, 0x56, 0x01, 0xe6, 0x7f, 0x4f, 0x06, 0x00, 0xed, 0xa0, 0x13, 0xea, + 0x4e, 0x01, 0x18, 0xec, 0x47, 0x7e, 0x23, 0x12, 0x13, 0x13, 0x10, 0xfb, 0x18, + 0xe2, 0x21, 0x00, 0xc1, 0x77, 0x7e, 0xb7, 0x20, 0xfc, 0xc9, 0x11, 0x10, 0xc0, + 0xe7, 0xaf, 0xd3, 0xbe, 0x21, 0x7b, 0x01, 0x01, 0xbf, 0x16, 0xed, 0xb3, 0xc3, + 0xc0, 0x0e, 0x06, 0x80, 0xa0, 0x81, 0xff, 0x82, 0xff, 0x83, 0xff, 0x84, 0xff, + 0x85, 0xfb, 0x86, 0x00, 0x88, 0x00, 0x89, 0xff, 0x8a, 0x00, 0x87, 0x06, 0x04, + 0xc5, 0xd5, 0xcd, 0x9e, 0x01, 0xd1, 0xc1, 0x13, 0x10, 0xf6, 0xc9, 0xe7, 0x0e, + 0xbe, 0x7e, 0x23, 0xb7, 0xc8, 0xfa, 0xb8, 0x01, 0x47, 0x56, 0x23, 0xed, 0x51, + 0xdb, 0xbe, 0xdb, 0xbe, 0xdb, 0xbe, 0x10, 0xf6, 0xc3, 0xa1, 0x01, 0xe6, 0x7f, + 0x47, 0xed, 0xa3, 0xdb, 0xbe, 0xdb, 0xbe, 0xdb, 0xbe, 0xc2, 0xbb, 0x01, 0xc3, + 0xa1, 0x01, 0x11, 0xa0, 0x81, 0xe7, 0xc9, 0xe7, 0x79, 0xb7, 0x28, 0x01, 0x04, + 0x7d, 0xd3, 0xbe, 0x0d, 0x20, 0xfb, 0x10, 0xf9, 0xc9, 0x21, 0x00, 0xc3, 0x11, + 0x00, 0x7f, 0x01, 0xbe, 0x64, 0xe7, 0xed, 0xb3, 0x21, 0x80, 0xc3, 0x11, 0x80, + 0x7f, 0x06, 0x80, 0xe7, 0xed, 0xb3, 0xc9, 0x3a, 0x40, 0xc1, 0x3d, 0xf8, 0x20, + 0x0d, 0x21, 0x7f, 0x14, 0x11, 0x00, 0xc0, 0x01, 0xbe, 0x18, 0xe7, 0xed, 0xb3, + 0xc9, 0xcd, 0x55, 0x02, 0x21, 0x47, 0xc1, 0x11, 0x04, 0xc0, 0xcd, 0x1b, 0x02, + 0x21, 0x4a, 0xc1, 0x11, 0x06, 0xc0, 0x7e, 0x3d, 0xf8, 0x2c, 0x35, 0xc0, 0x36, + 0x05, 0x2c, 0x4e, 0x34, 0xb7, 0x79, 0x28, 0x10, 0xfe, 0x06, 0x30, 0x10, 0x06, + 0x00, 0x21, 0x47, 0x02, 0x09, 0x09, 0x01, 0xbe, 0x02, 0x18, 0xcb, 0xfe, 0x02, + 0x38, 0xf0, 0x2d, 0x2d, 0x36, 0x00, 0x21, 0x47, 0x02, 0x18, 0xee, 0x38, 0x00, + 0x3f, 0x38, 0x3f, 0x38, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x38, 0x3f, 0x38, 0x21, + 0x42, 0xc1, 0x35, 0xf0, 0x3a, 0x05, 0xde, 0x3c, 0x77, 0x2c, 0x7e, 0x3d, 0xf2, + 0x67, 0x02, 0x3e, 0x07, 0x77, 0x5f, 0x2c, 0x35, 0x20, 0x03, 0x2c, 0x34, 0x2d, + 0x2c, 0x4e, 0x79, 0xe6, 0x0f, 0x4f, 0x21, 0x9e, 0x02, 0x09, 0x4e, 0x50, 0x21, + 0x8e, 0x02, 0x19, 0x11, 0x08, 0xc0, 0xe7, 0x06, 0x08, 0x7e, 0xb1, 0xd3, 0xbe, + 0x23, 0x10, 0xf9, 0xc9, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x08, + 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x00, 0x01, 0x02, 0x03, 0x13, 0x12, + 0x11, 0x10, 0x30, 0x31, 0x32, 0x33, 0x23, 0x22, 0x21, 0x20, 0x21, 0xd0, 0xd0, + 0x22, 0x00, 0xc3, 0xcd, 0x8b, 0x03, 0xcd, 0x07, 0x03, 0x3a, 0x82, 0xc1, 0x3d, + 0xf8, 0x28, 0x2f, 0x2a, 0x87, 0xc1, 0x11, 0x00, 0xfe, 0x19, 0x30, 0x1e, 0x22, + 0x87, 0xc1, 0x11, 0x04, 0x00, 0x2a, 0x85, 0xc1, 0x19, 0x22, 0x85, 0xc1, 0xed, + 0x5b, 0x89, 0xc1, 0x19, 0x22, 0x89, 0xc1, 0x7c, 0x32, 0x00, 0xc3, 0x3c, 0xfe, + 0x90, 0x38, 0x14, 0xaf, 0x32, 0x82, 0xc1, 0x32, 0x86, 0xc1, 0xc9, 0x21, 0x8c, + 0xc1, 0x35, 0x28, 0xf2, 0x3a, 0x8a, 0xc1, 0x32, 0x00, 0xc3, 0x2a, 0x88, 0xc1, + 0x3a, 0x8b, 0xc1, 0x67, 0x22, 0x80, 0xc3, 0xc9, 0x21, 0x80, 0xc1, 0x35, 0xc0, + 0x36, 0x80, 0xed, 0x5f, 0x1f, 0xd8, 0x2c, 0x34, 0x7e, 0xe6, 0x1f, 0x87, 0x5f, + 0x16, 0x00, 0x21, 0x4b, 0x03, 0x19, 0x7e, 0xe6, 0xf8, 0x3d, 0x32, 0x8a, 0xc1, + 0x7e, 0x87, 0x87, 0x87, 0x87, 0xe6, 0x07, 0x32, 0x85, 0xc1, 0x23, 0x7e, 0xe6, + 0xf8, 0x32, 0x88, 0xc1, 0x7e, 0xe6, 0x01, 0x3c, 0x32, 0x8b, 0xc1, 0x7e, 0xe6, + 0x02, 0x3c, 0x32, 0x82, 0xc1, 0x3e, 0x1e, 0x32, 0x8c, 0xc1, 0xc9, 0x50, 0x21, + 0x50, 0xa8, 0x12, 0x4a, 0x10, 0xc0, 0x78, 0xa8, 0x18, 0x21, 0x58, 0x62, 0x70, + 0x18, 0x49, 0xe3, 0x40, 0x50, 0x28, 0x80, 0x40, 0xc8, 0x10, 0xe1, 0x00, 0x93, + 0x10, 0x41, 0x00, 0x38, 0x40, 0xab, 0x40, 0x10, 0x10, 0x08, 0x78, 0x41, 0x00, + 0x70, 0x0a, 0xbb, 0x40, 0x69, 0x68, 0x11, 0x50, 0xc1, 0x00, 0xda, 0x00, 0xa8, + 0x08, 0x20, 0x40, 0x39, 0x20, 0xd2, 0x60, 0xe0, 0x20, 0xa8, 0x21, 0x04, 0xde, + 0x7e, 0x3d, 0xf8, 0x36, 0x00, 0x20, 0x0e, 0x3c, 0x21, 0x46, 0xc1, 0x34, 0xcb, + 0x46, 0x21, 0x47, 0xc1, 0x28, 0x0b, 0x18, 0x07, 0x3c, 0x21, 0x47, 0xc1, 0xcd, + 0xac, 0x03, 0x2e, 0x4a, 0x77, 0x2c, 0x36, 0x01, 0x2c, 0x36, 0x00, 0xc9, 0xff, + 0x03, 0xf5, 0x80, 0x10, 0xe0, 0xff, 0x00, 0xf8, 0x45, 0x06, 0xf5, 0x80, 0x40, + 0xe2, 0xff, 0x01, 0xf8, 0xf8, 0x06, 0xac, 0x1e, 0xae, 0x03, 0xaf, 0xb0, 0xb1, + 0xb2, 0xb3, 0xb4, 0xb5, 0xf5, 0x80, 0x40, 0xff, 0x01, 0xfb, 0x0c, 0xf8, 0xf8, + 0x06, 0xac, 0x36, 0xfb, 0xf4, 0xf5, 0x80, 0x60, 0xff, 0x03, 0xf8, 0x28, 0x08, + 0xf5, 0x80, 0x40, 0xff, 0x01, 0xf8, 0xf8, 0x06, 0xac, 0x36, 0xf6, 0xb6, 0x03, + 0xf5, 0x80, 0x10, 0xe0, 0xf8, 0x7d, 0x06, 0xf5, 0x80, 0xc0, 0xe2, 0xfb, 0x0c, + 0xf8, 0x5f, 0x07, 0xfb, 0xf4, 0xf5, 0x80, 0xc0, 0xe2, 0xfb, 0x0c, 0xf8, 0x5f, + 0x07, 0xfb, 0xf4, 0xf5, 0x80, 0x60, 0xfb, 0x0c, 0xf8, 0x10, 0x09, 0xfb, 0xf4, + 0xf5, 0x80, 0xc0, 0xfb, 0x0c, 0xf8, 0x5f, 0x07, 0xfb, 0xf4, 0xf6, 0xf6, 0x03, + 0xf5, 0x80, 0x10, 0xe0, 0xf8, 0xb2, 0x06, 0xf5, 0x80, 0xc0, 0xe2, 0xfb, 0x0c, + 0xf8, 0xba, 0x07, 0xfb, 0xf4, 0xf5, 0x80, 0xc0, 0xe2, 0xfb, 0x0c, 0xf8, 0xba, + 0x07, 0xfb, 0xf4, 0xf5, 0x80, 0x60, 0xfb, 0x0c, 0xf8, 0x7e, 0x09, 0xfb, 0xf4, + 0xf5, 0x80, 0xc0, 0xfb, 0x0c, 0xf8, 0xba, 0x07, 0xfb, 0xf4, 0xf6, 0x2a, 0x04, + 0x80, 0x60, 0xf7, 0x00, 0x08, 0x5e, 0x04, 0x80, 0x60, 0xf7, 0x00, 0x10, 0x65, + 0x04, 0x80, 0x60, 0xf7, 0x00, 0x10, 0x6c, 0x04, 0x80, 0x60, 0xf7, 0x00, 0x08, + 0x73, 0x04, 0xf5, 0x80, 0x43, 0xe4, 0xba, 0x12, 0xe3, 0xfd, 0xba, 0xe2, 0xfd, + 0xba, 0xe1, 0xb1, 0x06, 0xb3, 0xb5, 0xb8, 0xb5, 0xb3, 0xb1, 0xe4, 0xb1, 0x12, + 0xe3, 0xfd, 0xb1, 0xe2, 0xfd, 0xb1, 0xe1, 0xb8, 0x06, 0xae, 0xb1, 0xb5, 0xae, + 0xb1, 0xb3, 0xe4, 0xb3, 0x18, 0xe3, 0xfd, 0xb3, 0x12, 0xe2, 0xfd, 0xb3, 0xe1, + 0xb1, 0x0c, 0xb0, 0xb1, 0xf5, 0x80, 0x40, 0xb0, 0x03, 0x80, 0xae, 0x80, 0xac, + 0x80, 0xae, 0x80, 0x4b, 0xf7, 0x00, 0x02, 0x7a, 0x04, 0x80, 0x60, 0xf7, 0x00, + 0x10, 0xc2, 0x04, 0xf6, 0x5e, 0x04, 0x80, 0x60, 0xf7, 0x00, 0x07, 0xcc, 0x04, + 0x12, 0xfc, 0x01, 0xf5, 0x80, 0x53, 0xaa, 0x05, 0xf0, 0x03, 0xa5, 0x05, 0xf0, + 0x03, 0xa2, 0x05, 0xf8, 0x06, 0x80, 0x00, 0x00, 0x1e, 0xaa, 0x05, 0xf0, 0x03, + 0xaa, 0x05, 0xf0, 0x03, 0xaa, 0x05, 0xf0, 0x03, 0xaa, 0x05, 0xf0, 0x03, 0xa5, + 0x05, 0xf0, 0x03, 0xa5, 0x05, 0xf0, 0x03, 0xa5, 0x05, 0xf0, 0x03, 0xa5, 0x05, + 0xf0, 0x03, 0xa2, 0x05, 0xf8, 0x03, 0xa2, 0x05, 0xf8, 0x03, 0xa2, 0x05, 0xf8, + 0x03, 0xa2, 0x05, 0xf8, 0x03, 0xfc, 0x00, 0xf5, 0x80, 0x40, 0x80, 0x30, 0xf7, + 0x00, 0x1f, 0x1e, 0x05, 0x18, 0xfc, 0x01, 0xf5, 0x80, 0x53, 0xad, 0x05, 0xf0, + 0x03, 0xad, 0x05, 0xf0, 0x03, 0xad, 0x05, 0xf0, 0x03, 0xad, 0x05, 0xf0, 0x03, + 0xad, 0x05, 0xf0, 0x03, 0xa8, 0x05, 0xf0, 0x03, 0xa8, 0x05, 0xf0, 0x03, 0xa5, + 0x05, 0xf8, 0x03, 0xfc, 0x00, 0xf5, 0x80, 0x40, 0x80, 0x30, 0xf7, 0x00, 0x1f, + 0x50, 0x05, 0xfc, 0x01, 0xf5, 0x80, 0x53, 0xac, 0x05, 0xf0, 0x04, 0xac, 0x05, + 0xf0, 0x04, 0xa7, 0x05, 0xf0, 0x04, 0xac, 0x05, 0xf0, 0x04, 0xac, 0x05, 0xf0, + 0x04, 0xa7, 0x05, 0xf0, 0x04, 0xac, 0x05, 0xf0, 0x03, 0xac, 0x05, 0xf0, 0x03, + 0xac, 0x05, 0xf0, 0x03, 0xa7, 0x05, 0xf0, 0x03, 0xa7, 0x05, 0xf0, 0x03, 0xa7, + 0x05, 0xf0, 0x03, 0xa4, 0x05, 0xf8, 0x03, 0xa4, 0x05, 0xf8, 0x03, 0xfc, 0x00, + 0xf5, 0x80, 0x40, 0x80, 0x60, 0xf7, 0x00, 0x08, 0x99, 0x05, 0xfe, 0x00, 0xfb, + 0x0c, 0xf8, 0xd4, 0x05, 0x80, 0x30, 0xf8, 0xd4, 0x05, 0x80, 0x24, 0xfc, 0x01, + 0xf5, 0x80, 0x53, 0x9f, 0x05, 0xf0, 0x03, 0x9f, 0x05, 0xf0, 0x03, 0x9a, 0x05, + 0xf0, 0x03, 0x97, 0x05, 0xf8, 0x03, 0xfc, 0x00, 0xf5, 0x80, 0x40, 0xfb, 0xf4, + 0x80, 0x60, 0xf7, 0x00, 0x10, 0xca, 0x05, 0xf6, 0xcc, 0x04, 0xf5, 0x80, 0x43, + 0xe5, 0xba, 0x12, 0xe4, 0xfd, 0xba, 0xe3, 0xfd, 0xba, 0xe2, 0xb1, 0x06, 0xb3, + 0xb5, 0xb8, 0xb5, 0xb3, 0xb1, 0xe5, 0xb1, 0x12, 0xe4, 0xfd, 0xb1, 0xe3, 0xfd, + 0xb1, 0xe2, 0xb8, 0x06, 0xae, 0xb1, 0xb5, 0xae, 0xb1, 0xb3, 0xe5, 0xb3, 0x18, + 0xe4, 0xfd, 0xb3, 0x12, 0xe3, 0xfd, 0xb3, 0xe2, 0xb1, 0x0c, 0xb0, 0xb1, 0xf5, + 0x80, 0x40, 0xb0, 0x03, 0x80, 0xae, 0x80, 0xac, 0x80, 0xae, 0x80, 0x1b, 0xf9, + 0xf8, 0xe3, 0x06, 0xf8, 0x12, 0x0a, 0x88, 0x06, 0x94, 0x89, 0x95, 0x8a, 0x96, + 0x8c, 0x98, 0xf8, 0x12, 0x0a, 0x88, 0x06, 0x94, 0x88, 0x94, 0x88, 0x94, 0x88, + 0x94, 0xf8, 0x6a, 0x0a, 0xf8, 0x12, 0x0a, 0x88, 0x06, 0x94, 0x88, 0x94, 0x88, + 0x94, 0x88, 0x94, 0xf6, 0x18, 0x06, 0xfb, 0x0c, 0xa5, 0x24, 0x06, 0x36, 0x1e, + 0x06, 0x80, 0xa5, 0x36, 0x24, 0x06, 0x36, 0x1e, 0x06, 0x80, 0xa5, 0x36, 0x24, + 0x06, 0x36, 0x1e, 0xb1, 0x06, 0x80, 0xb1, 0x36, 0x24, 0x06, 0x36, 0xf1, 0x01, + 0xb3, 0x06, 0xf1, 0x01, 0xb3, 0xf1, 0x01, 0xb3, 0x80, 0x0c, 0xf1, 0x01, 0xb3, + 0x06, 0x80, 0xf1, 0x02, 0xb1, 0xfb, 0xf4, 0x80, 0x30, 0xf9, 0xfb, 0x0c, 0xa0, + 0x24, 0x06, 0xa2, 0x36, 0xa1, 0x1e, 0xa1, 0x06, 0x80, 0xa0, 0x36, 0x24, 0x06, + 0xa2, 0x36, 0xa1, 0x1e, 0x06, 0x80, 0xa0, 0x36, 0x24, 0x06, 0xae, 0x36, 0xad, + 0x1e, 0x06, 0x80, 0xac, 0x36, 0x24, 0x06, 0xae, 0x36, 0xad, 0x06, 0xad, 0xad, + 0x80, 0x0c, 0xad, 0x06, 0x80, 0xac, 0xfb, 0xf4, 0x80, 0x30, 0xf9, 0xfb, 0x0c, + 0x9d, 0x24, 0x06, 0x9e, 0x36, 0x1e, 0x06, 0x80, 0x9d, 0x36, 0x24, 0x06, 0x9e, + 0x36, 0x1e, 0x06, 0x80, 0x9d, 0x36, 0xa9, 0x24, 0x06, 0xaa, 0x36, 0x1e, 0x06, + 0x80, 0xa9, 0x36, 0x24, 0x06, 0xaa, 0x36, 0x06, 0xaa, 0xaa, 0x80, 0x0c, 0xaa, + 0x06, 0x80, 0xa9, 0xfb, 0xf4, 0x80, 0x30, 0xf9, 0x81, 0x06, 0x8d, 0xf7, 0x00, + 0x38, 0xe3, 0x06, 0x81, 0x06, 0x81, 0x81, 0x80, 0x0c, 0x81, 0x06, 0x80, 0x81, + 0x80, 0x30, 0xf9, 0xaa, 0x12, 0xa9, 0x06, 0x30, 0xa0, 0x0c, 0xa2, 0xaa, 0x12, + 0xa9, 0x06, 0x3c, 0x80, 0x0c, 0xaa, 0x12, 0xa9, 0x06, 0x30, 0xa7, 0x0c, 0xa9, + 0xaa, 0x30, 0xad, 0x12, 0xac, 0xaa, 0x0c, 0xf7, 0x00, 0x02, 0xf8, 0x06, 0xff, + 0x02, 0xa9, 0x3c, 0x9d, 0x0c, 0xa0, 0xa7, 0xa6, 0x24, 0xa3, 0x0c, 0xa2, 0x20, + 0xa0, 0x08, 0x9e, 0x9d, 0x0c, 0x9e, 0x06, 0x9b, 0x30, 0x06, 0x9d, 0x9e, 0x0c, + 0xa0, 0x06, 0xa2, 0x24, 0xa1, 0x0c, 0xaa, 0x18, 0xa7, 0xa9, 0x3c, 0x9d, 0x0c, + 0xa0, 0xa7, 0xa6, 0x36, 0xa9, 0x06, 0xa6, 0xa3, 0xa2, 0xa0, 0x9e, 0x9d, 0x9b, + 0x24, 0x9d, 0x0c, 0x9e, 0x08, 0x9d, 0x9e, 0xa0, 0x9e, 0xa0, 0xa2, 0x24, 0xa0, + 0x06, 0xf9, 0xa0, 0x12, 0x06, 0x80, 0x0c, 0xa0, 0x12, 0x06, 0x80, 0x0c, 0xa0, + 0x06, 0xa0, 0x80, 0x0c, 0xa0, 0x12, 0x06, 0x80, 0x0c, 0xa0, 0x12, 0x06, 0x80, + 0x0c, 0xa0, 0x06, 0xa0, 0x80, 0x0c, 0xa2, 0x12, 0x06, 0x80, 0x0c, 0xa2, 0x12, + 0x06, 0x80, 0x0c, 0xa2, 0xa2, 0x9e, 0x18, 0x80, 0x06, 0xa2, 0x12, 0xa1, 0x18, + 0x9e, 0x0c, 0x9e, 0xf7, 0x00, 0x02, 0x5f, 0x07, 0xa0, 0x60, 0x9d, 0x30, 0x9d, + 0x18, 0x0c, 0x9d, 0x9e, 0x60, 0x9e, 0x30, 0xa1, 0x18, 0xa1, 0xa0, 0x60, 0x9d, + 0x30, 0x18, 0x0c, 0x9d, 0x9e, 0x60, 0x9e, 0x24, 0x9e, 0x06, 0xa0, 0x2a, 0x80, + 0x0c, 0xf9, 0xa5, 0x12, 0xa4, 0x06, 0x80, 0x0c, 0xa7, 0x12, 0xa5, 0x06, 0x80, + 0x0c, 0xa4, 0x06, 0xa5, 0x80, 0x0c, 0xa5, 0x12, 0xa3, 0x06, 0x80, 0x0c, 0xa7, + 0x12, 0xa5, 0x06, 0x80, 0x0c, 0xa3, 0x06, 0xa5, 0x80, 0x0c, 0xa5, 0x12, 0xa4, + 0x06, 0x80, 0x0c, 0xa7, 0x12, 0xa5, 0x06, 0x80, 0x0c, 0xa4, 0xa5, 0xa5, 0x18, + 0x80, 0x06, 0xa7, 0xa9, 0xa7, 0x1e, 0xa5, 0x0c, 0xa7, 0xf7, 0x00, 0x02, 0xba, + 0x07, 0xa9, 0x54, 0xa7, 0x0c, 0xa6, 0x30, 0xa3, 0x18, 0xa2, 0x0c, 0xa0, 0xa7, + 0x30, 0xa5, 0x18, 0xa7, 0xa5, 0x30, 0xa7, 0x18, 0xaa, 0xa9, 0x54, 0xa7, 0x0c, + 0xa6, 0x30, 0xa3, 0x18, 0xa2, 0x0c, 0xa0, 0xa7, 0x30, 0xa5, 0x18, 0xa7, 0xa5, + 0x24, 0xa5, 0x06, 0xac, 0x2a, 0x80, 0x0c, 0xf9, 0xf1, 0x01, 0xb1, 0x03, 0x80, + 0xf1, 0x01, 0xb1, 0x80, 0xf1, 0x01, 0xb0, 0x80, 0xf1, 0x01, 0xb1, 0x80, 0x80, + 0x18, 0x80, 0x12, 0xae, 0x03, 0x80, 0xb0, 0x80, 0xb1, 0x06, 0x80, 0x0c, 0xf1, + 0x01, 0xb1, 0x03, 0x80, 0xf1, 0x01, 0xb1, 0x80, 0xf1, 0x01, 0xb0, 0x80, 0xf1, + 0x01, 0xb1, 0x80, 0x80, 0x18, 0x80, 0x12, 0xae, 0x03, 0x80, 0xb0, 0x80, 0xb1, + 0x06, 0x80, 0x0c, 0xf1, 0x01, 0xb3, 0x03, 0x80, 0xf1, 0x01, 0xb3, 0x80, 0xf1, + 0x01, 0xb1, 0x80, 0xf1, 0x01, 0xb3, 0x80, 0x80, 0x18, 0x80, 0x12, 0xb0, 0x03, + 0x80, 0x03, 0xb1, 0x03, 0x80, 0x03, 0xb3, 0x06, 0x80, 0x0c, 0xf1, 0x01, 0xb1, + 0x03, 0x80, 0xf1, 0x01, 0xb1, 0x80, 0xf1, 0x01, 0xb0, 0x80, 0xf1, 0x01, 0xb1, + 0x80, 0x80, 0x18, 0x80, 0x30, 0xf7, 0x00, 0x02, 0x28, 0x08, 0xff, 0x04, 0xf8, + 0xc1, 0x08, 0x80, 0x30, 0xf8, 0xc1, 0x08, 0x80, 0x06, 0xf1, 0x02, 0xb6, 0x03, + 0x80, 0xf1, 0x02, 0xb6, 0x80, 0x09, 0xf1, 0x01, 0xb8, 0x03, 0x80, 0xf1, 0x02, + 0xb8, 0x06, 0x80, 0x0c, 0xf9, 0xf1, 0x01, 0xb5, 0x03, 0x80, 0xf1, 0x01, 0xb5, + 0x80, 0xf1, 0x01, 0xb3, 0x80, 0xf1, 0x02, 0xb5, 0x80, 0x80, 0x48, 0xf1, 0x01, + 0xb5, 0x03, 0x80, 0xf1, 0x01, 0xb5, 0x80, 0xf1, 0x01, 0xb3, 0x80, 0xf1, 0x02, + 0xb5, 0x80, 0x4b, 0xf1, 0x01, 0xb3, 0x03, 0x80, 0xf1, 0x01, 0xb3, 0x80, 0xf1, + 0x02, 0xb1, 0x80, 0xf1, 0x02, 0xb3, 0x80, 0x1b, 0x80, 0x0c, 0xb1, 0xb0, 0xb1, + 0xf1, 0x01, 0xb1, 0x03, 0x80, 0xf1, 0x01, 0xb1, 0x80, 0xf1, 0x02, 0xb0, 0x80, + 0xf1, 0x02, 0xb1, 0x80, 0x1b, 0xf9, 0xae, 0x03, 0x80, 0xae, 0x80, 0xac, 0x80, + 0xae, 0x80, 0x4b, 0xae, 0x03, 0x80, 0xae, 0x80, 0xac, 0x80, 0xae, 0x80, 0x4b, + 0xb0, 0x03, 0x80, 0xb0, 0x80, 0xae, 0x80, 0xb0, 0x80, 0x4b, 0xae, 0x03, 0x80, + 0xae, 0x80, 0xac, 0x80, 0xae, 0x80, 0x4b, 0xf7, 0x00, 0x02, 0x10, 0x09, 0xf8, + 0x55, 0x09, 0x80, 0x30, 0xf8, 0x55, 0x09, 0x80, 0x06, 0xae, 0x03, 0x80, 0xae, + 0x80, 0x09, 0xb0, 0x03, 0x80, 0xb0, 0x06, 0x80, 0x0c, 0xf9, 0xb1, 0x03, 0x80, + 0xb1, 0x80, 0xb0, 0x80, 0xb1, 0x80, 0x4b, 0xb1, 0x03, 0x80, 0xb1, 0x80, 0xb0, + 0x80, 0xb1, 0x80, 0x4b, 0xb0, 0x03, 0x80, 0xb0, 0x80, 0xae, 0x80, 0xb0, 0x80, + 0x4b, 0xae, 0x03, 0x80, 0xae, 0x80, 0xac, 0x80, 0xae, 0x80, 0x1b, 0xf9, 0xa9, + 0x03, 0x80, 0xa9, 0x80, 0xa7, 0x80, 0xa9, 0x80, 0x1b, 0x80, 0x12, 0xa9, 0x03, + 0x80, 0xa9, 0x80, 0xa9, 0x06, 0x80, 0x0c, 0xaa, 0x03, 0x80, 0xaa, 0x80, 0xa9, + 0x80, 0xaa, 0x80, 0x1b, 0x80, 0x12, 0xaa, 0x03, 0x80, 0xaa, 0x80, 0xaa, 0x06, + 0x80, 0x0c, 0xac, 0x03, 0x80, 0xac, 0x80, 0xaa, 0x80, 0xac, 0x80, 0x1b, 0x80, + 0x12, 0xac, 0x03, 0x80, 0xac, 0x80, 0xac, 0x06, 0x80, 0x0c, 0xa9, 0x03, 0x80, + 0xa9, 0x80, 0xa7, 0x80, 0xa9, 0x80, 0x4b, 0xf7, 0x00, 0x02, 0x7e, 0x09, 0xf8, + 0xe4, 0x09, 0x80, 0x30, 0xf8, 0xe4, 0x09, 0x80, 0x06, 0xaa, 0x03, 0x80, 0xaa, + 0x80, 0x09, 0xac, 0x03, 0x80, 0xac, 0x06, 0x80, 0x0c, 0xf9, 0xae, 0x03, 0x80, + 0xae, 0x80, 0xac, 0x80, 0xae, 0x80, 0x4b, 0xae, 0x03, 0x80, 0xae, 0x80, 0xac, + 0x80, 0xae, 0x80, 0x4b, 0xac, 0x03, 0x80, 0xac, 0x80, 0xaa, 0x80, 0xac, 0x80, + 0x1b, 0x80, 0x0c, 0xac, 0xac, 0xac, 0xa9, 0x03, 0x80, 0xa9, 0x80, 0xa7, 0x80, + 0xa9, 0x80, 0x1b, 0xf9, 0xf8, 0x61, 0x0a, 0xfb, 0x0a, 0xf8, 0x61, 0x0a, 0xfb, + 0xff, 0xf8, 0x61, 0x0a, 0xfb, 0xfc, 0xf8, 0x61, 0x0a, 0xfb, 0xfb, 0xf7, 0x00, + 0x02, 0x12, 0x0a, 0xf8, 0x3b, 0x0a, 0x86, 0x06, 0x92, 0x86, 0x92, 0x86, 0x92, + 0x86, 0x92, 0xf8, 0x3b, 0x0a, 0xf9, 0xfb, 0x04, 0xf8, 0x61, 0x0a, 0xfb, 0x05, + 0xf8, 0x61, 0x0a, 0xfb, 0xf9, 0xf8, 0x56, 0x0a, 0xfb, 0xfe, 0x86, 0x06, 0x92, + 0x86, 0x92, 0x86, 0x92, 0x86, 0x92, 0xf9, 0x81, 0x06, 0x8d, 0x03, 0x03, 0xf7, + 0x01, 0x08, 0x56, 0x0a, 0xf9, 0x81, 0x06, 0x8d, 0xf7, 0x01, 0x08, 0x61, 0x0a, + 0xf9, 0xfb, 0x09, 0xf8, 0x56, 0x0a, 0xfb, 0xfc, 0xf8, 0x56, 0x0a, 0xfb, 0x02, + 0xf8, 0x56, 0x0a, 0xfb, 0x02, 0xf8, 0x56, 0x0a, 0xfb, 0xf7, 0xf7, 0x00, 0x03, + 0x6a, 0x0a, 0xfb, 0x09, 0xf8, 0x56, 0x0a, 0xfb, 0xfc, 0xf8, 0x56, 0x0a, 0xfb, + 0x02, 0xf8, 0x56, 0x0a, 0xfb, 0xf9, 0x8a, 0x06, 0x96, 0x8a, 0x96, 0x8a, 0x96, + 0x8a, 0x96, 0x80, 0x86, 0x86, 0x80, 0x88, 0x88, 0x80, 0x0c, 0xf9, 0x21, 0x0c, + 0xde, 0xd9, 0xcd, 0x16, 0x0b, 0xcd, 0x24, 0x0b, 0x3e, 0x01, 0x32, 0x00, 0xde, + 0xb7, 0x08, 0xcd, 0xc5, 0x0a, 0xaf, 0x32, 0x00, 0xde, 0xb7, 0x08, 0xc3, 0xed, + 0x0a, 0xdd, 0x21, 0x0d, 0xde, 0x06, 0x07, 0xc5, 0x78, 0x32, 0x06, 0xde, 0xfe, + 0x01, 0x28, 0x10, 0xdd, 0xcb, 0x00, 0x7e, 0xc4, 0xed, 0x0b, 0x11, 0x20, 0x00, + 0xdd, 0x19, 0xc1, 0x10, 0xe8, 0xc9, 0xdd, 0xcb, 0x00, 0x7e, 0xc4, 0x99, 0x0b, + 0x18, 0xee, 0xdd, 0x21, 0xed, 0xde, 0x06, 0x04, 0xc5, 0x78, 0x3c, 0x32, 0x06, + 0xde, 0xfe, 0x02, 0x28, 0x10, 0xdd, 0xcb, 0x00, 0x7e, 0xc4, 0x8a, 0x0f, 0x11, + 0x20, 0x00, 0xdd, 0x19, 0xc1, 0x10, 0xe7, 0xc9, 0xdd, 0xcb, 0x00, 0x7e, 0xc4, + 0xef, 0x0e, 0x18, 0xee, 0x21, 0x03, 0xde, 0x7e, 0xb7, 0xf2, 0x21, 0x0b, 0x32, + 0x02, 0xde, 0xaf, 0x77, 0xc9, 0x3a, 0x02, 0xde, 0xfe, 0x81, 0xc0, 0x01, 0x66, + 0x11, 0xc3, 0x30, 0x0b, 0xc5, 0xcd, 0xc0, 0x0e, 0xc1, 0xcd, 0x3e, 0x0b, 0x11, + 0x0d, 0xde, 0xc3, 0x64, 0x0b, 0xc5, 0x06, 0x12, 0x21, 0x52, 0x0b, 0x0e, 0xf0, + 0xed, 0xa3, 0xdf, 0x0e, 0xf1, 0xed, 0xa3, 0xdf, 0x20, 0xf4, 0xc1, 0xc9, 0x16, + 0x20, 0x17, 0xb0, 0x18, 0x01, 0x26, 0x05, 0x27, 0x01, 0x28, 0x01, 0x36, 0x00, + 0x37, 0x50, 0x38, 0x03, 0x08, 0x60, 0x69, 0x46, 0x23, 0xc5, 0xe5, 0xdd, 0xe1, + 0x01, 0x09, 0x00, 0xed, 0xb0, 0x3e, 0x20, 0x12, 0x13, 0x3e, 0x01, 0x12, 0x13, + 0xaf, 0x12, 0x13, 0x12, 0x13, 0x12, 0xeb, 0x0e, 0x12, 0x09, 0xeb, 0x13, 0x08, + 0xf5, 0xcd, 0xa9, 0x0c, 0xcd, 0x4c, 0x10, 0xf1, 0x08, 0xc1, 0x10, 0xd6, 0x3e, + 0x80, 0x32, 0x02, 0xde, 0xc9, 0xdd, 0x34, 0x0b, 0xdd, 0x7e, 0x0a, 0xdd, 0x96, + 0x0b, 0x20, 0x0f, 0xcd, 0xbf, 0x0b, 0x3e, 0x0e, 0xd3, 0xf0, 0xdd, 0x7e, 0x10, + 0xf6, 0x20, 0xd3, 0xf1, 0xc9, 0xfe, 0x02, 0xc0, 0x3e, 0x0e, 0xd3, 0xf0, 0xdf, + 0xaf, 0xd3, 0xf1, 0xc9, 0xdd, 0x5e, 0x03, 0xdd, 0x56, 0x04, 0x1a, 0x13, 0xfe, + 0xe0, 0xd2, 0xe3, 0x0b, 0xfe, 0x7f, 0xda, 0x67, 0x0d, 0xcb, 0x6f, 0x28, 0x02, + 0xf6, 0x01, 0xcb, 0x67, 0x28, 0x02, 0xf6, 0x10, 0xdd, 0x77, 0x10, 0xc3, 0x59, + 0x0d, 0x21, 0xe9, 0x0b, 0xc3, 0xaa, 0x0d, 0x13, 0xc3, 0xc5, 0x0b, 0xdd, 0x34, + 0x0b, 0xdd, 0x7e, 0x0a, 0xdd, 0x96, 0x0b, 0xcc, 0x13, 0x0d, 0x32, 0x0c, 0xde, + 0xfe, 0x80, 0xca, 0x36, 0x0c, 0xdd, 0xcb, 0x00, 0x6e, 0xca, 0x36, 0x0c, 0xd9, + 0x36, 0x80, 0xd9, 0xdd, 0x7e, 0x11, 0xb7, 0xf2, 0x21, 0x0c, 0xdd, 0x86, 0x0e, + 0x38, 0x1b, 0xdd, 0x35, 0x0f, 0xdd, 0x35, 0x0f, 0xc3, 0x2f, 0x0c, 0xdd, 0x86, + 0x0e, 0x30, 0x0d, 0xdd, 0x34, 0x0f, 0xdd, 0x34, 0x0f, 0xc3, 0x2f, 0x0c, 0xdd, + 0xcb, 0x07, 0xce, 0xdd, 0x77, 0x0e, 0xdd, 0x7e, 0x13, 0xfe, 0x1f, 0xc8, 0x3a, + 0x0c, 0xde, 0xdd, 0xcb, 0x07, 0x46, 0x20, 0x05, 0xfe, 0x02, 0xda, 0xbf, 0x0c, + 0xb7, 0xfa, 0x5b, 0x0c, 0xdd, 0xcb, 0x14, 0x7e, 0xc0, 0xdd, 0x7e, 0x06, 0x3d, + 0xf2, 0x5f, 0x0c, 0xc9, 0xdd, 0x7e, 0x06, 0x3d, 0xdd, 0x6e, 0x0e, 0xdd, 0x66, + 0x0f, 0xfa, 0x70, 0x0c, 0xeb, 0x21, 0x2e, 0x14, 0xef, 0xcd, 0xd6, 0x0c, 0xdd, + 0xcb, 0x00, 0x46, 0xc0, 0x7d, 0xb4, 0xca, 0xbf, 0x0c, 0x0e, 0xf1, 0xdd, 0x7e, + 0x01, 0xd3, 0xf0, 0xc6, 0x10, 0xdf, 0xed, 0x69, 0xdf, 0xd9, 0xcb, 0x7e, 0xd9, + 0xd3, 0xf0, 0x20, 0x0f, 0xdd, 0xcb, 0x07, 0x46, 0x28, 0x09, 0xdd, 0xcb, 0x07, + 0x4e, 0xc8, 0xdd, 0xcb, 0x07, 0x8e, 0xdd, 0xcb, 0x07, 0x56, 0x28, 0x02, 0xcb, + 0xec, 0xed, 0x61, 0xc9, 0xdd, 0x7e, 0x01, 0xc6, 0x20, 0xd3, 0xf0, 0xdd, 0x7e, + 0x07, 0xe6, 0xf0, 0x4f, 0xdd, 0x7e, 0x08, 0xe6, 0x0f, 0xb1, 0xd3, 0xf1, 0xc9, + 0xaf, 0x32, 0x04, 0xde, 0xdd, 0x7e, 0x01, 0xc6, 0x10, 0xd3, 0xf0, 0xdf, 0xdd, + 0x36, 0x13, 0x1f, 0xaf, 0xd3, 0xf1, 0xc9, 0xdd, 0x77, 0x0d, 0xdd, 0x7e, 0x0d, + 0x85, 0x4f, 0x8c, 0x91, 0x47, 0x0a, 0xb7, 0xf2, 0xf8, 0x0c, 0xfe, 0x83, 0x28, + 0x0a, 0xfe, 0x80, 0x28, 0x0a, 0xdd, 0x36, 0x14, 0xff, 0xe1, 0xc9, 0x03, 0x0a, + 0x18, 0xde, 0xaf, 0x18, 0xdb, 0xdd, 0x34, 0x0d, 0x6f, 0x26, 0x00, 0x19, 0x3a, + 0x00, 0xde, 0xb7, 0x28, 0x0a, 0x7c, 0xdd, 0xbe, 0x10, 0x28, 0x04, 0xdd, 0xcb, + 0x07, 0xce, 0xdd, 0x77, 0x10, 0xc9, 0xdd, 0x7e, 0x08, 0xb7, 0xf2, 0x25, 0x0d, + 0x3c, 0xcb, 0x77, 0x20, 0x01, 0x3c, 0xe6, 0x3f, 0xdd, 0x77, 0x08, 0xdd, 0x5e, + 0x03, 0xdd, 0x56, 0x04, 0x1a, 0x13, 0xfe, 0xe0, 0xd2, 0xa7, 0x0d, 0xfe, 0x80, + 0xda, 0x67, 0x0d, 0xcd, 0x90, 0x0d, 0x7e, 0xdd, 0x77, 0x0e, 0x23, 0x7e, 0xdd, + 0x77, 0x0f, 0xdd, 0xcb, 0x00, 0x6e, 0xca, 0x59, 0x0d, 0x1a, 0x13, 0xdd, 0x77, + 0x12, 0xdd, 0x77, 0x11, 0xdd, 0x77, 0x11, 0x13, 0x1a, 0x18, 0x0d, 0x1a, 0xb7, + 0xf2, 0x66, 0x0d, 0xdd, 0x7e, 0x15, 0xdd, 0x77, 0x0a, 0x18, 0x11, 0x13, 0xdd, + 0x46, 0x02, 0x05, 0x28, 0x04, 0x4f, 0x81, 0x10, 0xfd, 0xdd, 0x77, 0x0a, 0xdd, + 0x77, 0x15, 0xaf, 0xdd, 0x77, 0x0c, 0xdd, 0x77, 0x0d, 0xdd, 0x77, 0x0b, 0xdd, + 0x77, 0x13, 0xdd, 0x77, 0x14, 0xdd, 0x73, 0x03, 0xdd, 0x72, 0x04, 0x3e, 0x80, + 0xc9, 0xd6, 0x80, 0x28, 0x03, 0xdd, 0x86, 0x05, 0x21, 0x59, 0x10, 0x08, 0x28, + 0x03, 0x21, 0xd3, 0x10, 0x08, 0x4f, 0x06, 0x00, 0x09, 0x09, 0xc9, 0x21, 0xbd, + 0x0d, 0xe5, 0xd6, 0xf0, 0xda, 0x22, 0x0e, 0x21, 0xcd, 0x0d, 0x87, 0x4f, 0x06, + 0x00, 0x09, 0x4e, 0x23, 0x66, 0x69, 0xe9, 0x21, 0x06, 0xde, 0xcb, 0x46, 0x28, + 0x05, 0x3e, 0x01, 0x32, 0x04, 0xde, 0x13, 0xc3, 0x2b, 0x0d, 0x02, 0x0e, 0xfd, + 0x0d, 0x7a, 0x0e, 0x35, 0x0e, 0x60, 0x0e, 0x49, 0x0e, 0x65, 0x0e, 0xa8, 0x0e, + 0x7a, 0x0e, 0x95, 0x0e, 0x22, 0x0e, 0x1a, 0x0e, 0x6b, 0x0e, 0xee, 0x0d, 0xed, + 0x0d, 0xf8, 0x0d, 0xc9, 0xdd, 0xcb, 0x00, 0xc6, 0xdd, 0xcb, 0x07, 0xc6, 0x1b, + 0xc9, 0x1a, 0x32, 0x05, 0xde, 0xc9, 0x1a, 0x32, 0x04, 0xde, 0xc9, 0x1b, 0xdd, + 0x7e, 0x08, 0xe6, 0x0f, 0xb7, 0xc8, 0x3d, 0x20, 0x04, 0xf6, 0x40, 0x18, 0x01, + 0x3d, 0xf6, 0x80, 0xdd, 0x77, 0x08, 0xc3, 0x32, 0x0e, 0x1a, 0xdd, 0x86, 0x05, + 0xdd, 0x77, 0x05, 0xc9, 0x1b, 0x08, 0x20, 0x02, 0x08, 0xc9, 0x08, 0xe6, 0x0f, + 0xdd, 0x77, 0x08, 0xdd, 0xcb, 0x00, 0x86, 0xc3, 0xa9, 0x0c, 0x1a, 0xf6, 0xe0, + 0xd3, 0x7f, 0xf6, 0xfc, 0x3c, 0x20, 0x05, 0xdd, 0xcb, 0x00, 0xb6, 0xc9, 0xdd, + 0xcb, 0x00, 0xf6, 0xc9, 0x08, 0x20, 0x0a, 0x08, 0x1a, 0x13, 0xfe, 0x80, 0xc8, + 0xdd, 0x77, 0x07, 0xc9, 0x08, 0x13, 0x1a, 0xfe, 0x04, 0xc8, 0xdd, 0x77, 0x07, + 0xc9, 0x1a, 0xdd, 0x77, 0x06, 0xc9, 0xeb, 0x5e, 0x23, 0x56, 0x1b, 0xc9, 0x1a, + 0xfe, 0x01, 0x20, 0x05, 0xdd, 0xcb, 0x00, 0xee, 0xc9, 0xdd, 0xcb, 0x00, 0xae, + 0xc9, 0x1a, 0x4f, 0x13, 0x1a, 0x47, 0xc5, 0xdd, 0xe5, 0xe1, 0xdd, 0x35, 0x09, + 0xdd, 0x4e, 0x09, 0xdd, 0x35, 0x09, 0x06, 0x00, 0x09, 0x72, 0x2b, 0x73, 0xd1, + 0x1b, 0xc9, 0xdd, 0xe5, 0xe1, 0xdd, 0x4e, 0x09, 0x06, 0x00, 0x09, 0x5e, 0x23, + 0x56, 0xdd, 0x34, 0x09, 0xdd, 0x34, 0x09, 0xc9, 0x1a, 0x13, 0xc6, 0x16, 0x4f, + 0x06, 0x00, 0xdd, 0xe5, 0xe1, 0x09, 0x7e, 0xb7, 0x20, 0x02, 0x1a, 0x77, 0x13, + 0x35, 0xc2, 0x65, 0x0e, 0x13, 0xc9, 0x21, 0x02, 0xde, 0x11, 0x03, 0xde, 0x01, + 0x63, 0x01, 0x36, 0x00, 0xed, 0xb0, 0x21, 0xe6, 0x0e, 0x01, 0x7f, 0x09, 0xed, + 0xb3, 0xaf, 0x01, 0xf0, 0x60, 0x16, 0x20, 0xaf, 0xed, 0x51, 0x14, 0xdf, 0xd3, + 0xf1, 0xdf, 0x10, 0xf7, 0xc9, 0x80, 0x00, 0xa0, 0x00, 0xc0, 0x00, 0xe0, 0x00, + 0xff, 0xdd, 0x34, 0x0b, 0xdd, 0x7e, 0x0a, 0xdd, 0x96, 0x0b, 0xcc, 0x11, 0x0f, + 0xdd, 0xcb, 0x13, 0x66, 0xc0, 0xdd, 0x7e, 0x07, 0x3d, 0xf8, 0x21, 0xd6, 0x13, + 0xef, 0xcd, 0x14, 0x10, 0xf6, 0xf0, 0xd3, 0x7f, 0xc9, 0xdd, 0x5e, 0x03, 0xdd, + 0x56, 0x04, 0x1a, 0x13, 0xfe, 0xe0, 0xd2, 0x3b, 0x0f, 0xfe, 0x80, 0xda, 0x67, + 0x0d, 0xcd, 0x45, 0x0f, 0x1a, 0x13, 0xfe, 0x80, 0xda, 0x67, 0x0d, 0x1b, 0xdd, + 0x7e, 0x15, 0xdd, 0x77, 0x0a, 0xc3, 0x77, 0x0d, 0x1b, 0xc3, 0x77, 0x0d, 0x21, + 0x41, 0x0f, 0xc3, 0xaa, 0x0d, 0x13, 0xc3, 0x17, 0x0f, 0xcb, 0x5f, 0x20, 0x19, + 0xcb, 0x6f, 0x20, 0x1c, 0xcb, 0x4f, 0x20, 0x18, 0xcb, 0x47, 0x20, 0x22, 0xcb, + 0x57, 0x20, 0x1e, 0xdd, 0x36, 0x07, 0x00, 0x3e, 0xff, 0xd3, 0x7f, 0xc9, 0x08, + 0x3e, 0x02, 0x06, 0x03, 0x18, 0x13, 0x0e, 0x04, 0xcb, 0x47, 0x20, 0x02, 0x0e, + 0x03, 0x08, 0x79, 0x06, 0x05, 0x18, 0x05, 0x08, 0x3e, 0x01, 0x06, 0x06, 0xdd, + 0x77, 0x07, 0x08, 0xcb, 0x57, 0x28, 0x02, 0x05, 0x05, 0xdd, 0x70, 0x08, 0xc9, + 0xdd, 0x34, 0x0b, 0xdd, 0x7e, 0x0a, 0xdd, 0x96, 0x0b, 0xcc, 0x13, 0x0d, 0x32, + 0x0c, 0xde, 0xfe, 0x80, 0xdd, 0x7e, 0x13, 0xfe, 0x1f, 0xc8, 0x18, 0x0b, 0x3e, + 0x1f, 0xdd, 0x77, 0x13, 0xdd, 0x86, 0x01, 0xd3, 0x7f, 0xc9, 0xfe, 0xff, 0xca, + 0xc8, 0x0f, 0xdd, 0x7e, 0x07, 0x3d, 0xfa, 0xc8, 0x0f, 0x21, 0xd6, 0x13, 0xef, + 0xcd, 0x14, 0x10, 0xdd, 0xb6, 0x01, 0xc6, 0x10, 0xd3, 0x7f, 0x3a, 0x0c, 0xde, + 0xb7, 0xfa, 0xdc, 0x0f, 0xdd, 0xcb, 0x14, 0x7e, 0xc8, 0xdd, 0x7e, 0x06, 0x3d, + 0xf2, 0xe0, 0x0f, 0xc9, 0xdd, 0x7e, 0x06, 0x3d, 0xdd, 0x6e, 0x0e, 0xdd, 0x66, + 0x0f, 0xfa, 0xf1, 0x0f, 0xeb, 0x21, 0x2e, 0x14, 0xef, 0xcd, 0xd6, 0x0c, 0xdd, + 0xcb, 0x00, 0x76, 0xc0, 0xdd, 0x7e, 0x01, 0xfe, 0xe0, 0x20, 0x02, 0x3e, 0xc0, + 0x4f, 0x7d, 0xe6, 0x0f, 0xb1, 0xd3, 0x7f, 0x7d, 0xe6, 0xf0, 0xb4, 0x0f, 0x0f, + 0x0f, 0x0f, 0xd3, 0x7f, 0xc9, 0xdd, 0x77, 0x0c, 0xe5, 0xdd, 0x4e, 0x0c, 0x06, + 0x00, 0x09, 0x4d, 0x44, 0xe1, 0x0a, 0xcb, 0x7f, 0x28, 0x1d, 0xfe, 0x82, 0x28, + 0x0c, 0xfe, 0x81, 0x28, 0x0f, 0xfe, 0x80, 0x28, 0x08, 0x03, 0x0a, 0x18, 0xde, + 0xe1, 0xc3, 0xa3, 0x0f, 0xaf, 0x18, 0xd7, 0xdd, 0x36, 0x13, 0xff, 0x0b, 0x0a, + 0xdd, 0x34, 0x0c, 0xdd, 0x86, 0x08, 0xcb, 0x67, 0xc8, 0x3e, 0x0f, 0xc9, 0xdd, + 0x7e, 0x08, 0xe6, 0x0f, 0xdd, 0xb6, 0x01, 0xc6, 0x10, 0xd3, 0x7f, 0xc9, 0x00, + 0x00, 0xff, 0x03, 0xc7, 0x03, 0x90, 0x03, 0x5d, 0x03, 0x2d, 0x03, 0xff, 0x02, + 0xd4, 0x02, 0xab, 0x02, 0x85, 0x02, 0x61, 0x02, 0x3f, 0x02, 0x1e, 0x02, 0x00, + 0x02, 0xe3, 0x01, 0xc8, 0x01, 0xaf, 0x01, 0x96, 0x01, 0x80, 0x01, 0x6a, 0x01, + 0x56, 0x01, 0x43, 0x01, 0x30, 0x01, 0x1f, 0x01, 0x0f, 0x01, 0x00, 0x01, 0xf2, + 0x00, 0xe4, 0x00, 0xd7, 0x00, 0xcb, 0x00, 0xc0, 0x00, 0xb5, 0x00, 0xab, 0x00, + 0xa1, 0x00, 0x98, 0x00, 0x90, 0x00, 0x88, 0x00, 0x80, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x6c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x5b, 0x00, 0x55, 0x00, 0x51, 0x00, + 0x4c, 0x00, 0x48, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3c, 0x00, 0x39, 0x00, 0x36, + 0x00, 0x33, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x28, 0x00, 0x26, 0x00, + 0x24, 0x00, 0x22, 0x00, 0x00, 0x00, 0x57, 0x11, 0x6b, 0x11, 0x81, 0x11, 0x98, + 0x11, 0xb0, 0x11, 0xca, 0x11, 0xe5, 0x11, 0x01, 0x13, 0x10, 0x13, 0x20, 0x13, + 0x31, 0x13, 0x43, 0x13, 0x57, 0x13, 0x6b, 0x13, 0x81, 0x13, 0x98, 0x13, 0xb0, + 0x13, 0xca, 0x13, 0xe5, 0x13, 0x01, 0x15, 0x10, 0x15, 0x20, 0x15, 0x31, 0x15, + 0x43, 0x15, 0x57, 0x15, 0x6b, 0x15, 0x81, 0x15, 0x98, 0x15, 0xb0, 0x15, 0xca, + 0x15, 0xe5, 0x15, 0x01, 0x17, 0x10, 0x17, 0x20, 0x17, 0x31, 0x17, 0x43, 0x17, + 0x57, 0x17, 0x6b, 0x17, 0x81, 0x17, 0x98, 0x17, 0xb0, 0x17, 0xca, 0x17, 0xe5, + 0x17, 0x01, 0x19, 0x10, 0x19, 0x20, 0x19, 0x31, 0x19, 0x43, 0x19, 0x57, 0x19, + 0x6b, 0x19, 0x81, 0x19, 0x98, 0x19, 0xb0, 0x19, 0xca, 0x19, 0xe5, 0x19, 0x01, + 0x1b, 0x10, 0x1b, 0x20, 0x1b, 0x31, 0x1b, 0x43, 0x1b, 0x57, 0x1b, 0x6b, 0x1b, + 0x81, 0x1b, 0x98, 0x1b, 0xb0, 0x1b, 0xca, 0x1b, 0xe5, 0x1b, 0x01, 0x1d, 0x10, + 0x1d, 0x20, 0x1d, 0x31, 0x1d, 0x43, 0x1d, 0xff, 0x0b, 0x80, 0x10, 0x02, 0xb6, + 0x03, 0x00, 0x01, 0x70, 0x02, 0x80, 0x11, 0x02, 0x18, 0x06, 0x00, 0x02, 0xe0, + 0x02, 0x80, 0x12, 0x02, 0xf6, 0x03, 0x00, 0x01, 0x10, 0x00, 0x80, 0x13, 0x02, + 0x2a, 0x04, 0x00, 0x01, 0x10, 0x00, 0x80, 0x14, 0x02, 0x5e, 0x04, 0x00, 0x00, + 0x40, 0x02, 0x80, 0x15, 0x02, 0xcc, 0x04, 0x00, 0x00, 0x40, 0x02, 0x80, 0x00, + 0x02, 0xea, 0x11, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x02, 0xb6, 0x03, 0xf7, + 0x00, 0x06, 0x02, 0x80, 0xa0, 0x02, 0x18, 0x06, 0x03, 0x02, 0x04, 0x04, 0x80, + 0xc0, 0x02, 0xb5, 0x03, 0xf7, 0x01, 0x05, 0x04, 0x80, 0xe0, 0x02, 0xea, 0x11, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x85, 0x06, 0x81, 0x03, 0x81, 0x8d, 0x06, 0x81, + 0x03, 0x03, 0x85, 0x06, 0x81, 0x03, 0x81, 0x8f, 0x06, 0x81, 0x03, 0x03, 0xf7, + 0x00, 0x08, 0xcb, 0x11, 0xf8, 0x17, 0x12, 0xf6, 0xef, 0x11, 0xf3, 0x04, 0xf8, + 0x07, 0x12, 0xf8, 0x65, 0x12, 0xf8, 0xeb, 0x12, 0xf8, 0x65, 0x12, 0xf8, 0xeb, + 0x12, 0xf8, 0x33, 0x13, 0xf8, 0x65, 0x12, 0xf8, 0xeb, 0x12, 0xf6, 0xcb, 0x11, + 0x84, 0x0c, 0xf7, 0x00, 0x1c, 0x07, 0x12, 0x86, 0x86, 0x86, 0x06, 0x84, 0x03, + 0x84, 0xae, 0x0c, 0x85, 0x06, 0x81, 0x03, 0x81, 0x89, 0x06, 0x81, 0x03, 0x03, + 0x85, 0x06, 0x81, 0x03, 0x81, 0x8b, 0x06, 0x81, 0x03, 0x03, 0xf7, 0x00, 0x04, + 0x17, 0x12, 0x85, 0x06, 0x81, 0x03, 0x81, 0x8d, 0x06, 0x81, 0x03, 0x03, 0x85, + 0x06, 0x81, 0x03, 0x81, 0x8f, 0x06, 0x81, 0x03, 0x03, 0xf7, 0x00, 0x02, 0x30, + 0x12, 0x89, 0x06, 0x89, 0x89, 0x85, 0x03, 0x84, 0x81, 0x06, 0x8d, 0x81, 0xae, + 0x83, 0x0c, 0x85, 0x03, 0x89, 0x89, 0x85, 0x85, 0x89, 0x89, 0x85, 0x85, 0x89, + 0x8d, 0xae, 0xf9, 0xf8, 0x84, 0x12, 0x85, 0x06, 0x83, 0x8d, 0x83, 0x85, 0x85, + 0x03, 0x85, 0xaa, 0x06, 0x81, 0xf8, 0x84, 0x12, 0x85, 0x06, 0x89, 0x89, 0x85, + 0x85, 0x89, 0x03, 0x89, 0x85, 0x06, 0xaa, 0xf9, 0x85, 0x06, 0x03, 0x81, 0x89, + 0x06, 0x85, 0x03, 0x81, 0x81, 0x06, 0x85, 0x03, 0x81, 0x89, 0x06, 0x81, 0x03, + 0x81, 0x85, 0x06, 0x03, 0x81, 0x89, 0x06, 0x85, 0x03, 0x81, 0x81, 0x06, 0x85, + 0x03, 0x81, 0xaa, 0x06, 0x81, 0x03, 0x81, 0xf7, 0x00, 0x02, 0x84, 0x12, 0x85, + 0x06, 0x03, 0x81, 0x89, 0x06, 0x85, 0x03, 0x81, 0x81, 0x06, 0x85, 0x03, 0x81, + 0x89, 0x06, 0x81, 0x03, 0x81, 0x85, 0x06, 0x81, 0x03, 0x81, 0x89, 0x06, 0x81, + 0x03, 0x81, 0x85, 0x06, 0x85, 0x03, 0x81, 0x89, 0x06, 0x81, 0x03, 0x81, 0x85, + 0x06, 0x81, 0x03, 0x81, 0x89, 0x06, 0x85, 0x03, 0x81, 0x85, 0x06, 0x85, 0x03, + 0x81, 0x89, 0x06, 0x81, 0x03, 0x81, 0xf9, 0xf8, 0x0a, 0x13, 0x89, 0x04, 0x89, + 0x85, 0x89, 0x89, 0x84, 0x89, 0x06, 0x89, 0x89, 0x84, 0xf8, 0x0a, 0x13, 0x85, + 0x06, 0x89, 0x85, 0x89, 0x85, 0x89, 0x03, 0x85, 0x89, 0x06, 0xae, 0xf9, 0x85, + 0x06, 0x81, 0x03, 0x85, 0x89, 0x06, 0x81, 0x03, 0x81, 0xf7, 0x00, 0x07, 0x0a, + 0x13, 0x85, 0x06, 0x81, 0x03, 0x85, 0x89, 0x06, 0x81, 0x03, 0xae, 0x85, 0x06, + 0x81, 0x03, 0x85, 0x89, 0x06, 0x81, 0x03, 0x81, 0xf7, 0x00, 0x06, 0x23, 0x13, + 0xf9, 0xf8, 0x80, 0x13, 0x89, 0x03, 0x89, 0x85, 0x85, 0x89, 0x89, 0x85, 0x85, + 0x89, 0x89, 0x85, 0x85, 0x85, 0x89, 0x89, 0xaa, 0xf8, 0x80, 0x13, 0x85, 0x03, + 0x85, 0x85, 0x85, 0x89, 0x85, 0x85, 0x85, 0xae, 0x06, 0x85, 0x03, 0x85, 0x89, + 0x89, 0x89, 0xaa, 0xf8, 0x80, 0x13, 0x89, 0x03, 0x89, 0x85, 0x85, 0x89, 0x89, + 0x85, 0x85, 0x89, 0x89, 0x85, 0x85, 0x85, 0x89, 0x89, 0xaa, 0xf8, 0x80, 0x13, + 0x85, 0x06, 0x89, 0x89, 0x81, 0x8d, 0xae, 0x89, 0x03, 0x89, 0x8d, 0xae, 0xf9, + 0xf8, 0x9b, 0x13, 0x85, 0x06, 0x85, 0x03, 0x81, 0x89, 0x06, 0x85, 0x03, 0x81, + 0x81, 0x06, 0x85, 0x03, 0x85, 0xaa, 0x06, 0x85, 0x03, 0x85, 0xf8, 0x9b, 0x13, + 0xf9, 0x85, 0x06, 0x85, 0x03, 0x81, 0x81, 0x06, 0x8d, 0x03, 0x81, 0x81, 0x06, + 0x03, 0x85, 0x89, 0x06, 0x81, 0x03, 0x81, 0x85, 0x06, 0x85, 0x03, 0x81, 0x88, + 0x06, 0xae, 0x03, 0x81, 0x81, 0x06, 0x03, 0x85, 0x89, 0x06, 0x81, 0x03, 0x81, + 0x85, 0x06, 0x85, 0x03, 0x81, 0x81, 0x06, 0x8d, 0x03, 0x81, 0x81, 0x06, 0x03, + 0x85, 0x89, 0x06, 0x81, 0x03, 0x81, 0xf9, 0xff, 0xe2, 0x13, 0xe5, 0x13, 0xf2, + 0x13, 0xfb, 0x13, 0x04, 0x14, 0x0f, 0x14, 0x00, 0x02, 0x82, 0x00, 0x00, 0x01, + 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x82, 0x01, 0x00, 0x01, + 0x01, 0x03, 0x04, 0x07, 0x0a, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x82, 0x02, 0x01, 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x81, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x08, 0x81, 0x32, 0x14, 0x48, 0x14, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x01, 0x02, 0x03, 0x03, 0x02, + 0x01, 0x00, 0x00, 0x01, 0x02, 0x03, 0x03, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x04, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x03, 0x02, 0x01, + 0x00, 0x01, 0x01, 0x83, 0x28, 0x01, 0x01, 0x81, 0x00, 0x3f, 0x30, 0x34, 0x38, + 0x00, 0x38, 0x00, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x38, 0x3f, 0x0f, 0x03, 0x00, 0x83, 0x02, 0x05, 0x02, 0x03, + 0x00, 0x83, 0x10, 0x28, 0x10, 0x04, 0x00, 0x89, 0x07, 0x1c, 0x30, 0x60, 0x41, + 0xc6, 0x84, 0x88, 0xff, 0x03, 0x00, 0x81, 0xff, 0x03, 0x00, 0x89, 0xe1, 0x27, + 0x2c, 0x38, 0xf0, 0x31, 0x21, 0x22, 0xff, 0x03, 0x00, 0x8a, 0x7f, 0x80, 0x00, + 0x00, 0xf8, 0x09, 0x0b, 0x0e, 0xfc, 0x0c, 0x02, 0x08, 0x02, 0x88, 0x8e, 0x84, + 0xc6, 0x41, 0x60, 0x30, 0x0c, 0xff, 0x07, 0x01, 0x00, 0xf0, 0x0c, 0x04, 0x02, + 0x04, 0xe2, 0x85, 0x63, 0x62, 0x22, 0x22, 0x3f, 0x03, 0x00, 0x81, 0xff, 0x03, + 0x00, 0x81, 0xf8, 0x03, 0x18, 0x81, 0xf8, 0x03, 0x18, 0x81, 0xff, 0x03, 0x80, + 0x81, 0xff, 0x03, 0x80, 0x95, 0xe2, 0x02, 0x04, 0x0c, 0xf0, 0x00, 0x01, 0x07, + 0x22, 0x22, 0x21, 0x71, 0x70, 0xd8, 0x8c, 0x07, 0x3f, 0x00, 0x00, 0x80, 0x7f, + 0x03, 0x00, 0x89, 0xf8, 0x08, 0x08, 0x0c, 0xfc, 0x0e, 0x0b, 0x09, 0xff, 0x07, + 0x00, 0x81, 0xf8, 0x07, 0x00, 0x83, 0x11, 0x28, 0x10, 0x05, 0x00, 0x82, 0xfc, + 0x7c, 0x02, 0x3c, 0x04, 0x3e, 0x02, 0x1f, 0x02, 0x1e, 0x04, 0x3e, 0x82, 0x81, + 0x01, 0x03, 0x03, 0x03, 0x07, 0x02, 0xe0, 0x89, 0xf0, 0xf2, 0xf5, 0x7a, 0x78, + 0x78, 0x07, 0x1f, 0x1e, 0x03, 0x3c, 0x8a, 0x3e, 0x3f, 0xd1, 0xf9, 0x7b, 0x3b, + 0x1b, 0x08, 0x00, 0x80, 0x03, 0xff, 0x81, 0x9c, 0x04, 0x1c, 0x85, 0xcf, 0xc7, + 0xe3, 0xe3, 0x63, 0x03, 0x03, 0x02, 0xff, 0x88, 0x87, 0x83, 0x81, 0x80, 0x82, + 0x86, 0x3f, 0x9f, 0x03, 0x8e, 0x03, 0x0e, 0x86, 0xf8, 0xfc, 0x7c, 0x1e, 0x1e, + 0x0e, 0x02, 0x1e, 0x04, 0x37, 0x04, 0x33, 0x03, 0x6e, 0x81, 0xee, 0x04, 0xce, + 0x81, 0x06, 0x02, 0x0e, 0x02, 0x0f, 0x02, 0x1c, 0x81, 0x18, 0x03, 0x3c, 0x89, + 0xfc, 0xfe, 0x1e, 0x1e, 0x0e, 0x1f, 0x0f, 0x03, 0x00, 0x02, 0x30, 0x02, 0x38, + 0x82, 0xe0, 0xf0, 0x02, 0xf8, 0x03, 0x78, 0x81, 0xf8, 0x08, 0x1c, 0x83, 0x13, + 0x2b, 0x13, 0x05, 0x03, 0x02, 0xfe, 0x87, 0x86, 0x82, 0x80, 0x80, 0x81, 0x83, + 0x0e, 0x02, 0x0f, 0x02, 0x0e, 0x02, 0xce, 0x8b, 0x8e, 0x7c, 0xfc, 0xfc, 0x78, + 0x7c, 0x3c, 0x1e, 0x1e, 0x79, 0xfd, 0x06, 0x00, 0x82, 0x9f, 0xbf, 0x06, 0x00, + 0x82, 0x3c, 0xfe, 0x06, 0x00, 0x82, 0x1f, 0x3f, 0x06, 0x00, 0x82, 0x1f, 0x97, + 0x06, 0x00, 0x82, 0xf0, 0xe0, 0x06, 0x00, 0x82, 0x3e, 0x7f, 0x06, 0x00, 0x82, + 0x07, 0x0f, 0x06, 0x00, 0x02, 0xff, 0x06, 0x00, 0x82, 0x9f, 0x3f, 0x06, 0x00, + 0x82, 0x0f, 0x8f, 0x03, 0x00, 0xb7, 0x08, 0x14, 0x08, 0x00, 0x3f, 0x00, 0x7f, + 0x40, 0x5e, 0x40, 0x1e, 0x00, 0xfe, 0x80, 0xff, 0x81, 0xbd, 0x81, 0xbc, 0x20, + 0x13, 0x0a, 0x02, 0x42, 0x22, 0x12, 0x02, 0x00, 0xff, 0x10, 0x20, 0xfe, 0x82, + 0x82, 0xfe, 0x02, 0x01, 0x02, 0x3f, 0x04, 0x08, 0x13, 0x1c, 0x00, 0x00, 0x60, + 0x80, 0x00, 0x00, 0x04, 0x8c, 0x00, 0x00, 0x38, 0x44, 0x04, 0x82, 0x02, 0x00, + 0x82, 0x7f, 0x21, 0x03, 0x20, 0x89, 0x22, 0x00, 0x00, 0x40, 0x22, 0x21, 0x20, + 0x20, 0x40, 0x03, 0x00, 0x8b, 0x78, 0x80, 0x00, 0x20, 0x50, 0x00, 0x1f, 0x10, + 0x1f, 0x10, 0x1f, 0x03, 0x00, 0x88, 0xfc, 0x84, 0xfc, 0x84, 0xfd, 0x81, 0x7e, + 0x02, 0x02, 0x0a, 0x02, 0x12, 0x94, 0x24, 0x25, 0x40, 0x82, 0x82, 0xfe, 0x10, + 0x92, 0x91, 0x11, 0x30, 0x20, 0x41, 0x02, 0x04, 0x08, 0x08, 0x07, 0x00, 0xf0, + 0x03, 0x80, 0x02, 0x00, 0x82, 0xf0, 0x00, 0x05, 0x82, 0x85, 0x44, 0x38, 0x00, + 0x3e, 0x22, 0x04, 0x20, 0x8b, 0x70, 0x00, 0x40, 0x42, 0x52, 0x52, 0x61, 0x20, + 0x20, 0x00, 0x20, 0x04, 0x00, 0x8c, 0xfc, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, + 0x1f, 0x60, 0x40, 0x80, 0xfe, 0x03, 0x02, 0x81, 0xfe, 0x03, 0x02, 0x99, 0x03, + 0x0e, 0x08, 0x18, 0x11, 0x31, 0x22, 0x22, 0xe0, 0x3d, 0x0f, 0x0e, 0xc6, 0x46, + 0x22, 0x23, 0x78, 0x86, 0x7a, 0x8d, 0xb5, 0x8d, 0xb5, 0x7a, 0x8f, 0x03, 0x88, + 0x81, 0x8f, 0x03, 0x88, 0x81, 0xfe, 0x03, 0x02, 0x88, 0xe2, 0x22, 0x23, 0x23, + 0x62, 0x44, 0x44, 0xc4, 0x03, 0x88, 0x82, 0x11, 0x23, 0x03, 0x11, 0x03, 0x88, + 0x91, 0xc4, 0x86, 0x78, 0x00, 0x80, 0x80, 0x82, 0xc5, 0x42, 0x8e, 0x80, 0x40, + 0x60, 0x1f, 0x00, 0x00, 0xc0, 0x02, 0x23, 0x02, 0x22, 0x81, 0xe0, 0x03, 0x00, + 0x85, 0x11, 0x10, 0x20, 0x20, 0x3f, 0x03, 0x60, 0x85, 0xc4, 0x04, 0x02, 0x02, + 0xfe, 0x03, 0x00, 0x02, 0x40, 0x81, 0x60, 0x05, 0x20, 0x81, 0x7f, 0x03, 0x00, + 0x85, 0x10, 0x28, 0x10, 0x00, 0xe0, 0x07, 0x00, 0x83, 0x0f, 0x3f, 0x3c, 0x03, + 0x78, 0x8b, 0x7c, 0x7f, 0xa7, 0xf7, 0xf3, 0x71, 0x31, 0x10, 0x00, 0x00, 0xc7, + 0x02, 0xc3, 0x02, 0xe7, 0x02, 0xfe, 0x84, 0x7c, 0xe7, 0xdf, 0x9e, 0x03, 0x3c, + 0x84, 0x3e, 0x3f, 0x3f, 0x9f, 0x03, 0x8f, 0x03, 0x0f, 0x04, 0x07, 0x04, 0x8f, + 0x82, 0xe0, 0xc0, 0x06, 0x80, 0x91, 0x3f, 0x1f, 0x07, 0x01, 0x60, 0x60, 0x70, + 0x71, 0xc0, 0xe0, 0xf0, 0xf0, 0xf1, 0xf2, 0xf1, 0xf0, 0x7c, 0x04, 0x38, 0x81, + 0xb8, 0x02, 0x38, 0x04, 0x0d, 0x84, 0x0c, 0xcc, 0xcc, 0x8c, 0x03, 0xdb, 0x81, + 0xfb, 0x04, 0xf3, 0x08, 0x80, 0x82, 0x00, 0x80, 0x06, 0x00, 0x82, 0x3f, 0x2f, + 0x06, 0x00, 0x82, 0xe0, 0xc0, 0x06, 0x00, 0x82, 0x7c, 0xfe, 0x06, 0x00, 0x82, + 0x1f, 0x17, 0x06, 0x00, 0x82, 0x9e, 0x3f, 0x06, 0x00, 0x82, 0x67, 0x6f, 0x06, + 0x00, 0x82, 0xc0, 0xe0, 0x06, 0x00, 0x82, 0x40, 0x30, 0x06, 0x20, 0x03, 0x00, + 0x82, 0x08, 0x07, 0x05, 0x00, 0x84, 0x1f, 0xe6, 0x08, 0x10, 0x02, 0x20, 0x02, + 0x00, 0x81, 0xc0, 0x05, 0x00, 0x05, 0x20, 0x82, 0x11, 0x0e, 0x02, 0x00, 0x02, + 0x10, 0x83, 0x20, 0x40, 0x80, 0x02, 0x00, 0x04, 0x40, 0x82, 0x20, 0x1f, 0x06, + 0x00, 0x02, 0x18, 0x82, 0x08, 0x10, 0x04, 0x00, 0x83, 0x08, 0x06, 0x02, 0x04, + 0x00, 0x81, 0x0c, 0x03, 0x04, 0x81, 0x08, 0x03, 0x00, 0x82, 0x20, 0x1f, 0x06, + 0x00, 0x81, 0xf0, 0x02, 0x10, 0x02, 0x20, 0x82, 0x00, 0x40, 0x04, 0x20, 0x8c, + 0x38, 0x24, 0x00, 0x01, 0x02, 0x3f, 0x04, 0x08, 0x13, 0x1c, 0x00, 0x0f, 0x05, + 0x00, 0x82, 0x01, 0x00, 0x06, 0x80, 0x89, 0x40, 0x00, 0x18, 0x08, 0x08, 0x0c, + 0x79, 0x0a, 0x1c, 0x03, 0x00, 0x82, 0x70, 0x88, 0x03, 0x08, 0x05, 0x00, 0x89, + 0x01, 0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x40, 0x80, 0x05, 0x00, 0x83, 0x01, + 0x02, 0x0c, 0x02, 0x00, 0x02, 0x40, 0x87, 0x80, 0x04, 0x0a, 0x04, 0x00, 0x00, + 0x22, 0x06, 0x20, 0x88, 0x00, 0x41, 0xa2, 0x42, 0x04, 0x08, 0x10, 0x20, 0x02, + 0x40, 0x02, 0x20, 0x86, 0x10, 0x08, 0x04, 0x02, 0x01, 0x18, 0x02, 0x28, 0x02, + 0x48, 0x83, 0x18, 0x08, 0x00, 0x05, 0x08, 0xa7, 0x04, 0x00, 0x00, 0x3c, 0x42, + 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, 0x3f, 0x7f, 0x60, 0x7e, 0x3f, 0x03, 0x7f, + 0x7e, 0x7f, 0x7f, 0x60, 0x7e, 0x7e, 0x60, 0x7f, 0x7f, 0x3f, 0x7f, 0x60, 0x6f, + 0x6f, 0x63, 0x7f, 0x3f, 0x1c, 0x3e, 0x77, 0x63, 0x02, 0x7f, 0x02, 0x63, 0x07, + 0x00, 0x81, 0xff, 0x07, 0x00, 0x81, 0xff, 0x07, 0x00, 0x82, 0xff, 0x00, 0x02, + 0xff, 0x02, 0x00, 0x02, 0xff, 0x02, 0x00, 0x02, 0xff, 0x02, 0x00, 0x02, 0xff, + 0x02, 0x00, 0x02, 0xff, 0x02, 0x00, 0x02, 0xff, 0x02, 0x00, 0x02, 0xff, 0x02, + 0x00, 0x02, 0xff, 0x03, 0x00, 0x03, 0xff, 0x05, 0x00, 0x03, 0xff, 0x05, 0x00, + 0x03, 0xff, 0x05, 0x00, 0x03, 0xff, 0x05, 0x00, 0x03, 0xff, 0x04, 0x00, 0x04, + 0xff, 0x04, 0x00, 0x04, 0xff, 0x04, 0x00, 0x04, 0xff, 0x04, 0x00, 0x04, 0xff, + 0x04, 0x00, 0x04, 0xff, 0x05, 0x00, 0x06, 0xff, 0x02, 0x00, 0x06, 0xff, 0x02, + 0x00, 0x06, 0xff, 0x02, 0x00, 0x06, 0xff, 0x02, 0x00, 0x06, 0xff, 0x07, 0x00, + 0x81, 0xff, 0x07, 0x00, 0x81, 0xff, 0x07, 0x00, 0x81, 0xff, 0x07, 0x00, 0x81, + 0xff, 0x07, 0x00, 0x29, 0xff, 0x03, 0x00, 0x83, 0x47, 0x38, 0x00, 0x02, 0x01, + 0x02, 0x00, 0x90, 0xfe, 0x30, 0x40, 0x80, 0x02, 0x05, 0x01, 0x00, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x10, 0x00, 0x80, 0x03, 0x00, 0x81, 0x03, 0x03, 0x00, 0x95, + 0x60, 0x20, 0x20, 0x38, 0xc3, 0x44, 0x41, 0x20, 0x90, 0x40, 0x00, 0x01, 0xc0, + 0x80, 0x00, 0x00, 0x18, 0x08, 0x08, 0x0b, 0xfc, 0x02, 0x02, 0x03, 0x00, 0x81, + 0xc2, 0x03, 0x01, 0x81, 0x02, 0x05, 0x00, 0x81, 0x80, 0x02, 0x40, 0x04, 0x02, + 0x81, 0x01, 0x03, 0x00, 0x81, 0x02, 0x04, 0x00, 0x87, 0xf8, 0x00, 0x00, 0x10, + 0x08, 0x04, 0x02, 0x02, 0x01, 0x05, 0x00, 0x02, 0x01, 0x82, 0x02, 0x82, 0x03, + 0x80, 0x84, 0x88, 0x08, 0x08, 0x07, 0x07, 0x00, 0x85, 0xe0, 0x00, 0x00, 0x01, + 0x7f, 0x03, 0x80, 0x84, 0x40, 0x3f, 0x00, 0x02, 0x02, 0x82, 0x03, 0x01, 0x03, + 0x00, 0x02, 0x20, 0x02, 0x40, 0x83, 0x80, 0xc0, 0x00, 0x03, 0x20, 0x84, 0x01, + 0x02, 0x02, 0x01, 0x04, 0x00, 0x86, 0x80, 0x40, 0x40, 0x80, 0x00, 0x78, 0x05, + 0x38, 0x83, 0x7c, 0x00, 0x7c, 0x03, 0xce, 0x90, 0x7e, 0x0e, 0x7c, 0x00, 0x7c, + 0xce, 0xce, 0x7c, 0xce, 0xce, 0x7c, 0x00, 0xfe, 0xc6, 0xce, 0x1c, 0x03, 0x18, + 0x81, 0x00, 0x04, 0xc6, 0x85, 0x6c, 0x38, 0x10, 0x00, 0x03, 0x02, 0x06, 0x02, + 0x00, 0x84, 0x03, 0x07, 0x00, 0xe0, 0x03, 0x70, 0x85, 0xe0, 0x03, 0xf3, 0x00, + 0x3e, 0x05, 0x67, 0x82, 0x3e, 0x00, 0x00, 0x09, 0x00, 0x83, 0x10, 0x38, 0x10, + 0x05, 0x00, 0x88, 0x03, 0x0f, 0x1f, 0x3e, 0x39, 0x7b, 0x77, 0x00, 0x03, 0xff, + 0x81, 0x00, 0x03, 0xff, 0x89, 0x00, 0xc0, 0xc3, 0xc7, 0x0f, 0xce, 0xde, 0xdd, + 0x00, 0x03, 0xff, 0x8a, 0x80, 0x7f, 0xff, 0xff, 0x00, 0xf0, 0xf0, 0xf1, 0x03, + 0xf3, 0x02, 0xf7, 0x02, 0x77, 0x8e, 0x7b, 0x39, 0x3e, 0x1f, 0x0f, 0x03, 0x00, + 0xf8, 0xfe, 0xff, 0x0f, 0xf3, 0xfb, 0xfd, 0x04, 0x1d, 0x85, 0x9c, 0x9d, 0xdd, + 0xdd, 0xc0, 0x03, 0xff, 0x81, 0x00, 0x03, 0xff, 0x81, 0x07, 0x03, 0xe7, 0x81, + 0x07, 0x03, 0xe7, 0x81, 0x00, 0x03, 0x7f, 0x81, 0x00, 0x03, 0x7f, 0x95, 0x1d, + 0xfd, 0xfb, 0xf3, 0x0f, 0xff, 0xfe, 0xf8, 0xdd, 0xdd, 0xde, 0x8e, 0x8f, 0x07, + 0x03, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x80, 0x03, 0xff, 0x86, 0x07, 0xf7, 0xf7, + 0xf3, 0x03, 0xf1, 0x02, 0xf0, 0x18, 0x00, 0xad, 0x80, 0x40, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x80, 0x00, + 0x02, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x10, 0x02, 0x87, 0x0a, 0x00, + 0x40, 0x04, 0x10, 0x02, 0x24, 0x04, 0x04, 0x02, 0x00, 0x41, 0x08, 0x42, 0x20, + 0x11, 0x05, 0x00, 0x82, 0x22, 0x80, 0x04, 0x00, 0x85, 0x48, 0x04, 0x20, 0x80, + 0x40, 0x05, 0x00, 0x88, 0x04, 0x02, 0x01, 0x00, 0x00, 0x04, 0x20, 0x90, 0x06, + 0x00, 0x8c, 0x08, 0x04, 0x40, 0x12, 0x10, 0x00, 0x10, 0x12, 0x01, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x85, 0x02, 0x40, 0x00, 0x00, 0xa0, 0x03, 0x00, 0x90, 0x40, + 0x00, 0x08, 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, + 0x00, 0x10, 0x05, 0x00, 0x02, 0x10, 0x86, 0x08, 0x28, 0x00, 0x00, 0x08, 0x80, + 0x03, 0x40, 0x81, 0x88, 0x12, 0x00, 0x81, 0x04, 0x0b, 0x00, 0x8c, 0x40, 0x00, + 0x40, 0x00, 0x04, 0x48, 0x44, 0x20, 0x02, 0x10, 0x48, 0x84, 0x06, 0x00, 0x82, + 0x11, 0x20, 0x06, 0x00, 0x82, 0x24, 0xc2, 0x06, 0x00, 0x82, 0x11, 0x20, 0x07, + 0x00, 0x81, 0x84, 0x06, 0x00, 0x82, 0x10, 0x20, 0x06, 0x00, 0x82, 0x22, 0x41, + 0x06, 0x00, 0x82, 0x04, 0x08, 0x0e, 0x00, 0x82, 0x91, 0x20, 0x06, 0x00, 0x82, + 0x01, 0x88, 0x54, 0x00, 0x82, 0x20, 0x70, 0x48, 0x00, 0x81, 0x20, 0x08, 0x00, + 0x88, 0x3f, 0xff, 0xff, 0xe0, 0x9f, 0xbf, 0x7f, 0x00, 0x03, 0xfc, 0x81, 0x00, + 0x03, 0xfc, 0x82, 0x00, 0x01, 0x02, 0x07, 0x02, 0x0e, 0x02, 0x1d, 0x91, 0x00, + 0xc0, 0xf0, 0xf1, 0x39, 0xb9, 0xdd, 0xdc, 0x00, 0x78, 0x84, 0x72, 0x4a, 0x72, + 0x4a, 0x84, 0x70, 0x03, 0x77, 0x81, 0x70, 0x03, 0x77, 0x81, 0x00, 0x03, 0xfc, + 0x81, 0x1c, 0x03, 0xdc, 0x81, 0x1d, 0x03, 0x3b, 0x03, 0x77, 0x82, 0xee, 0xdc, + 0x03, 0xee, 0x03, 0x77, 0x82, 0x3b, 0x78, 0x04, 0x00, 0x8b, 0x02, 0x07, 0x82, + 0x71, 0x7f, 0xbf, 0x9f, 0xe0, 0xff, 0xff, 0x3f, 0x02, 0xdc, 0x02, 0xdd, 0x81, + 0x1f, 0x03, 0xff, 0x85, 0xee, 0xef, 0xdf, 0xdf, 0xc0, 0x03, 0x9f, 0x85, 0x3b, + 0xfb, 0xfd, 0xfd, 0x01, 0x03, 0xff, 0x03, 0x80, 0x05, 0xc0, 0x04, 0x00, 0x83, + 0x10, 0x38, 0x10, 0x09, 0x00, 0x8d, 0x08, 0x20, 0x04, 0x48, 0x08, 0x08, 0x04, + 0x00, 0x80, 0x14, 0x82, 0x40, 0x21, 0x03, 0x00, 0x92, 0x04, 0x42, 0x00, 0x24, + 0x01, 0x18, 0x82, 0x00, 0x24, 0x50, 0x82, 0x24, 0x04, 0x04, 0x02, 0x00, 0x20, + 0x90, 0x05, 0x00, 0x81, 0x02, 0x04, 0x00, 0x86, 0x88, 0x00, 0x00, 0x04, 0x20, + 0x40, 0x09, 0x00, 0x8e, 0x01, 0x20, 0x20, 0x10, 0x51, 0x00, 0x00, 0x10, 0x00, + 0x81, 0x83, 0x81, 0x10, 0x44, 0x04, 0x00, 0x81, 0x80, 0x05, 0x00, 0x89, 0x01, + 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x00, 0x28, 0x03, 0x00, 0x81, 0x90, 0x09, + 0x00, 0x81, 0x80, 0x07, 0x00, 0x81, 0x08, 0x06, 0x00, 0x82, 0x20, 0x40, 0x06, + 0x00, 0x81, 0x44, 0x08, 0x00, 0x81, 0x04, 0x06, 0x00, 0x82, 0x92, 0x21, 0x06, + 0x00, 0x82, 0x04, 0x08, 0x06, 0x00, 0x82, 0x40, 0x20, 0x7f, 0x00, 0x3f, 0x00, + 0x83, 0x40, 0xe0, 0x40, 0x1d, 0x00, 0xa4, 0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, + 0x42, 0x3c, 0x3f, 0x7f, 0x60, 0x7e, 0x3f, 0x03, 0x7f, 0x7e, 0x7f, 0x7f, 0x60, + 0x7e, 0x7e, 0x60, 0x7f, 0x7f, 0x3f, 0x7f, 0x60, 0x6f, 0x6f, 0x63, 0x7f, 0x3f, + 0x1c, 0x3e, 0x77, 0x63, 0x02, 0x7f, 0x02, 0x63, 0x18, 0x00, 0x03, 0xff, 0x04, + 0x00, 0x04, 0xff, 0x04, 0x00, 0x04, 0xff, 0x04, 0x00, 0x04, 0xff, 0x04, 0x00, + 0x06, 0xff, 0x03, 0x00, 0x05, 0xff, 0x03, 0x00, 0x05, 0xff, 0x03, 0x00, 0x05, + 0xff, 0x03, 0x00, 0x05, 0xff, 0x08, 0x00, 0x03, 0xff, 0x05, 0x00, 0x03, 0xff, + 0x05, 0x00, 0x03, 0xff, 0x05, 0x00, 0x03, 0xff, 0x05, 0x00, 0x2b, 0xff, 0x7f, + 0x00, 0x71, 0x00, 0x81, 0x78, 0x05, 0x38, 0x83, 0x7c, 0x00, 0x7c, 0x03, 0xce, + 0x90, 0x7e, 0x0e, 0x7c, 0x00, 0x7c, 0xce, 0xce, 0x7c, 0xce, 0xce, 0x7c, 0x00, + 0xfe, 0xc6, 0xce, 0x1c, 0x03, 0x18, 0x81, 0x00, 0x04, 0xc6, 0x85, 0x6c, 0x38, + 0x10, 0x00, 0x03, 0x02, 0x06, 0x02, 0x00, 0x84, 0x03, 0x07, 0x00, 0xe0, 0x03, + 0x70, 0x85, 0xe0, 0x03, 0xf3, 0x00, 0x3e, 0x05, 0x67, 0x82, 0x3e, 0x00, 0x00, + 0x03, 0x00, 0x83, 0x02, 0x07, 0x02, 0x03, 0x00, 0x83, 0x10, 0x38, 0x10, 0x7f, + 0x00, 0x0d, 0x00, 0x83, 0x10, 0x38, 0x10, 0x20, 0x00, 0x83, 0x02, 0x07, 0x02, + 0x72, 0x00, 0x83, 0x10, 0x38, 0x10, 0x72, 0x00, 0x83, 0x08, 0x1c, 0x08, 0x4e, + 0x00, 0x82, 0x20, 0x70, 0x48, 0x00, 0x81, 0x20, 0x54, 0x00, 0x83, 0x02, 0x07, + 0x02, 0x2c, 0x00, 0x83, 0x10, 0x38, 0x10, 0x4d, 0x00, 0x83, 0x01, 0x03, 0x01, + 0x06, 0x00, 0x81, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x07, 0x00, 0x83, 0x04, 0x0e, + 0x04, 0x0a, 0x00, 0x83, 0x40, 0xe0, 0x40, 0x53, 0x00, 0x82, 0x3f, 0xff, 0x06, + 0x00, 0x82, 0xc0, 0x80, 0x03, 0x00, 0x05, 0xff, 0x03, 0x00, 0x88, 0xff, 0xfc, + 0xf0, 0xc0, 0x00, 0x03, 0x0f, 0x3f, 0x05, 0x00, 0x88, 0xff, 0xfe, 0xfc, 0x07, + 0x0f, 0x1f, 0x3f, 0x7f, 0x05, 0xff, 0x03, 0x00, 0x04, 0xff, 0x87, 0xfc, 0x0f, + 0x3f, 0xff, 0xfc, 0xf0, 0xc0, 0x02, 0x00, 0x03, 0xff, 0x05, 0x00, 0x03, 0xff, + 0x88, 0x00, 0x01, 0x03, 0x07, 0x0f, 0xe0, 0xc0, 0x80, 0x0c, 0x00, 0x87, 0x03, + 0x0f, 0x3f, 0xff, 0x03, 0x0f, 0x3f, 0x0e, 0xff, 0x87, 0xfe, 0xfc, 0xf8, 0xf0, + 0xe0, 0xc0, 0x80, 0x0c, 0x00, 0x87, 0x03, 0x0f, 0x3f, 0xff, 0x03, 0x0f, 0x3f, + 0x0e, 0xff, 0x87, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x0c, 0xff, 0x87, + 0xfc, 0xf0, 0xc0, 0x00, 0xfc, 0xf0, 0xc0, 0x0e, 0x00, 0x87, 0x01, 0x03, 0x07, + 0x0f, 0x1f, 0x3f, 0x7f, 0x0c, 0xff, 0x87, 0xfc, 0xf0, 0xc0, 0x00, 0xfc, 0xf0, + 0xc0, 0x0e, 0x00, 0x87, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0x0e, 0x00, + 0x82, 0x02, 0x07, 0x40, 0x00, 0x81, 0x02, 0x7f, 0x00, 0x10, 0x00, 0x00, 0x7f, + 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, + 0x7f, 0x00, 0x7f, 0x00, 0x07, 0x00, 0x02, 0xff, 0x06, 0x00, 0x02, 0xff, 0x06, + 0x00, 0x7f, 0xff, 0x6b, 0xff, 0x7f, 0x00, 0x61, 0x00, 0x00, 0x81, 0x01, 0x06, + 0x00, 0x84, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x81, 0x01, 0x03, 0x00, 0x84, + 0x02, 0x00, 0x00, 0x01, 0x05, 0x00, 0x81, 0x01, 0x06, 0x00, 0x83, 0x02, 0x00, + 0x01, 0x06, 0x00, 0x8d, 0x03, 0x04, 0x05, 0x06, 0x07, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x00, 0x00, 0x02, 0x09, 0x00, 0x81, 0x01, 0x06, 0x00, 0x8d, 0x02, 0x01, + 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x03, 0x00, + 0x81, 0x01, 0x03, 0x00, 0x81, 0x02, 0x07, 0x00, 0x83, 0x02, 0x00, 0x01, 0x04, + 0x00, 0x8d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x54, 0x55, 0x56, 0x57, 0x58, 0x00, + 0x00, 0x01, 0x08, 0x00, 0x81, 0x02, 0x09, 0x00, 0x87, 0x02, 0x12, 0x13, 0x14, + 0x12, 0x13, 0x59, 0x03, 0x12, 0x82, 0x5a, 0x01, 0x03, 0x00, 0x82, 0x02, 0x01, + 0x08, 0x00, 0x9c, 0x01, 0x00, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x01, 0x5b, 0x5c, 0x5d, 0x5e, 0x1a, 0x1b, 0x1c, 0x1d, 0x5f, + 0x60, 0x61, 0x00, 0x00, 0x02, 0x03, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x20, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x00, 0x62, 0x63, 0x64, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x65, 0x66, 0x67, 0x09, 0x00, 0x99, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x30, 0x31, 0x32, 0x33, 0x6d, 0x6e, 0x6f, 0x00, 0x01, 0x04, 0x00, 0x81, + 0x01, 0x04, 0x00, 0x87, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x07, 0x00, + 0x81, 0x02, 0x03, 0x00, 0x81, 0x01, 0x0b, 0x00, 0x8f, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x3b, 0x3c, 0x3d, 0x3d, 0x3e, 0x3f, 0x70, 0x71, 0x72, 0x73, 0x08, 0x00, + 0x81, 0x02, 0x07, 0x00, 0x95, 0x02, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x47, 0x48, 0x49, 0x74, 0x75, 0x76, 0x77, 0x00, 0x01, 0x00, 0x00, 0x02, + 0x07, 0x00, 0x81, 0x01, 0x0b, 0x00, 0x81, 0x01, 0x18, 0x00, 0x98, 0x78, 0x79, + 0x7a, 0x7b, 0x7c, 0x7d, 0x3b, 0x7e, 0x7f, 0x80, 0x81, 0xb0, 0xb1, 0xb2, 0xb3, + 0xb4, 0xb5, 0xb6, 0xb7, 0x82, 0xb8, 0x00, 0x00, 0x01, 0x05, 0x00, 0x99, 0x02, + 0x00, 0x00, 0x82, 0x83, 0x84, 0x85, 0x86, 0x44, 0x45, 0x87, 0x88, 0x89, 0x8a, + 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0x08, 0x00, + 0x81, 0x01, 0x24, 0x00, 0x8e, 0x02, 0x00, 0x8b, 0x00, 0x8c, 0x8d, 0x8e, 0x8f, + 0x00, 0xc4, 0xc5, 0xc6, 0xc7, 0x01, 0x03, 0x00, 0x85, 0x02, 0xc8, 0xc9, 0xca, + 0xc4, 0x22, 0x00, 0x0e, 0x90, 0x84, 0x91, 0x92, 0x92, 0x91, 0x0e, 0x90, 0x0c, + 0x93, 0x88, 0x94, 0x95, 0x96, 0x93, 0x93, 0x96, 0x95, 0x94, 0x0c, 0x93, 0x0a, + 0x97, 0x84, 0x98, 0x99, 0x9a, 0x9b, 0x04, 0x97, 0x84, 0x9b, 0x9a, 0x99, 0x98, + 0x0a, 0x97, 0x08, 0x9c, 0x85, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0x06, 0x9c, 0x85, + 0xa0, 0x9f, 0x9f, 0x9e, 0x9d, 0x08, 0x9c, 0x06, 0xa1, 0x82, 0xa2, 0xa3, 0x03, + 0xa4, 0x81, 0xa5, 0x08, 0xa1, 0x81, 0xa5, 0x03, 0xa4, 0x82, 0xa3, 0xa2, 0x06, + 0xa1, 0x04, 0xa6, 0x82, 0xa7, 0xa8, 0x04, 0xa9, 0x81, 0xaa, 0x0a, 0xa6, 0x81, + 0xaa, 0x04, 0xa9, 0x82, 0xa8, 0xa7, 0x04, 0xa6, 0x02, 0xab, 0x82, 0xac, 0xad, + 0x05, 0xae, 0x81, 0xaf, 0x0c, 0xab, 0x81, 0xaf, 0x05, 0xae, 0x82, 0xad, 0xac, + 0x02, 0xab, 0x00, 0x41, 0x10, 0x81, 0x16, 0x06, 0x10, 0x81, 0x16, 0x7f, 0x10, + 0x7f, 0x10, 0x7f, 0x10, 0x6a, 0x10, 0x02, 0x12, 0x1f, 0x10, 0x03, 0x12, 0x1e, + 0x10, 0x82, 0x12, 0x10, 0x02, 0x12, 0x1d, 0x10, 0x81, 0x12, 0x02, 0x10, 0x02, + 0x12, 0x1c, 0x10, 0x81, 0x12, 0x03, 0x10, 0x02, 0x12, 0x1b, 0x10, 0x81, 0x12, + 0x04, 0x10, 0x02, 0x12, 0x1a, 0x10, 0x81, 0x12, 0x05, 0x10, 0x02, 0x12, 0x02, + 0x10, 0x00, 0x00 + }; + #endregion + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/Compat.txt b/BizHawk.Emulation/Consoles/Sega/SMS/Compat.txt new file mode 100644 index 0000000000..6d81384a38 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/SMS/Compat.txt @@ -0,0 +1,20 @@ +======= Sega MasterSystem Compatibility Issues ======= + +* CodeMasters games don't work: + + CodeMasters games use a custom mapper (implemented now). + + CodeMasters games use alternate video mode, not implemented. + + Games are: Cosmic Spacehead, Fantastic Dizzy, Micro Machines + +* F16 Fighting Falcon uses old SG-1000 video mode, and doesn't work on a GG/Genesis either. + +That said.. I will fix CodeMasters games and F16 Fighting Falcon eventually, and add full +SG-1000 support, it's just not the high priority currently. + +* Raster effects are sometimes on the wrong line... but it's correct 99% of the time... :| + Update: I think this is a timing issue resulting in latching/rendering at the wrong part + of a scanline. I should play with this timing. + +======= Game Gear compatibility issues ======= + +* Axe Battler is broken. +* "SEGA" logo audio sample plays at low rate in Sonic & Tails. \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/Input.cs b/BizHawk.Emulation/Consoles/Sega/SMS/Input.cs new file mode 100644 index 0000000000..76e19a97b3 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/SMS/Input.cs @@ -0,0 +1,77 @@ +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class SMS + { + public static readonly ControllerDefinition SmsController = new ControllerDefinition + { + Name = "SMS Controller", + BoolButtons = + { + "Reset", "Pause", + "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 B1", "P1 B2", + "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 B1", "P2 B2" + } + }; + + public ControllerDefinition ControllerDefinition { get { return SmsController; } } + public IController Controller { get; set; } + + private byte ReadControls1() + { + byte value = 0xFF; + + if (Controller["P1 Up"]) value &= 0xFE; + if (Controller["P1 Down"]) value &= 0xFD; + if (Controller["P1 Left"]) value &= 0xFB; + if (Controller["P1 Right"]) value &= 0xF7; + if (Controller["P1 B1"]) value &= 0xEF; + if (Controller["P1 B2"]) value &= 0xDF; + + if (Controller["P2 Up"]) value &= 0xBF; + if (Controller["P2 Down"]) value &= 0x7F; + + return value; + } + + private byte ReadControls2() + { + byte value = 0xFF; + + if (Controller["P2 Left"]) value &= 0xFE; + if (Controller["P2 Right"]) value &= 0xFD; + if (Controller["P2 B1"]) value &= 0xFB; + if (Controller["P2 B2"]) value &= 0xF7; + + if (Controller["Reset"]) value &= 0xEF; + + if ((Port3F & 0x0F) == 5) + { + if (region == "Japan") + { + value &= 0x3F; + } + else // US / Europe + { + if (Port3F >> 4 == 0x0F) + value |= 0xC0; + else + value &= 0x3F; + } + } + + return value; + } + + private byte ReadPort0() + { + if (IsGameGear == false) + return 0xFF; + byte value = 0xFF; + if (Controller["Pause"]) + value ^= 0x80; + if (Region == "US") + value ^= 0x40; + return value; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.CodeMasters.cs b/BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.CodeMasters.cs new file mode 100644 index 0000000000..3f000f70f6 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.CodeMasters.cs @@ -0,0 +1,40 @@ +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class SMS + { + // The CodeMasters mapper has 3 banks of 16kb, like the Sega mapper. + // The differences are that the paging control addresses are different, and the first 1K of ROM is not protected. + // Bank 0: Control Address $0000 - Maps $0000 - $3FFF + // Bank 1: Control Address $4000 - Maps $4000 - $7FFF + // Bank 2: Control Address $8000 - Maps $8000 - $BFFF + // System RAM is at $C000+ as in the Sega mapper. + + private byte ReadMemoryCM(ushort address) + { + if (address < BankSize * 1) return RomData[(RomBank0 * BankSize) + address]; + if (address < BankSize * 2) return RomData[(RomBank1 * BankSize) + (address & BankSizeMask)]; + if (address < BankSize * 3) return RomData[(RomBank2 * BankSize) + (address & BankSizeMask)]; + + return SystemRam[address & RamSizeMask]; + } + + private void WriteMemoryCM(ushort address, byte value) + { + if (address >= 0xC000) + SystemRam[address & RamSizeMask] = value; + + else if (address == 0x0000) RomBank0 = (byte)(value % RomBanks); + else if (address == 0x4000) RomBank1 = (byte)(value % RomBanks); + else if (address == 0x8000) RomBank2 = (byte)(value % RomBanks); + } + + private void InitCodeMastersMapper() + { + Cpu.ReadMemory = ReadMemoryCM; + Cpu.WriteMemory = WriteMemoryCM; + WriteMemoryCM(0x0000, 0); + WriteMemoryCM(0x4000, 1); + WriteMemoryCM(0x8000, 2); + } + } +} diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.Sega.cs b/BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.Sega.cs new file mode 100644 index 0000000000..022f897b85 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/SMS/MemoryMap.Sega.cs @@ -0,0 +1,81 @@ +namespace BizHawk.Emulation.Consoles.Sega +{ + public partial class SMS + { + // The Sega memory mapper layout looks like so: + // $0000-$03FF - ROM (unpaged) + // $0400-$3FFF - ROM mapper slot 0 + // $4000-$7FFF - ROM mapper slot 1 + // $8000-$BFFF - ROM mapper slot 2 - OR - SaveRAM + // $C000-$DFFF - System RAM + // $E000-$FFFF - System RAM (mirror) + // $FFFC - SaveRAM mapper control + // $FFFD - Mapper slot 0 control + // $FFFE - Mapper slot 1 control + // $FFFF - Mapper slot 2 control + + private const ushort BankSizeMask = 0x3FFF; + private const ushort RamSizeMask = 0x1FFF; + + private byte ReadMemory(ushort address) + { + if (address < 1024) + return RomData[address]; + if (address < BankSize) + return RomData[(RomBank0*BankSize) + address]; + if (address < BankSize * 2) + return RomData[(RomBank1*BankSize) + (address & BankSizeMask)]; + if (address < BankSize * 3) + { + switch (SaveRamBank) + { + case 0: return RomData[(RomBank2*BankSize) + (address & BankSizeMask)]; + case 1: return SaveRAM[address & BankSizeMask]; + case 2: return SaveRAM[BankSize + (address & BankSizeMask)]; + } + } + return SystemRam[address & RamSizeMask]; + } + + private void WriteMemory(ushort address, byte value) + { + if (address >= 0xC000) + SystemRam[address & RamSizeMask] = value; + + else if (address >= 0x8000) + { + SaveRamModified = true; + switch (SaveRamBank) + { + case 1: SaveRAM[address & BankSizeMask] = value; return; + case 2: SaveRAM[BankSize + (address & BankSizeMask)] = value; return; + } + } + + if (address >= 0xFFFC) + { + if (address == 0xFFFC) + { + if ((value & 8) != 0) + SaveRamBank = (byte)((value & 4) == 0 ? 1 : 2); // SaveRAM selected + else + SaveRamBank = 0; // ROM bank selected + } + else if (address == 0xFFFD) RomBank0 = (byte)(value % RomBanks); + else if (address == 0xFFFE) RomBank1 = (byte)(value % RomBanks); + else if (address == 0xFFFF) RomBank2 = (byte)(value % RomBanks); + return; + } + } + + private void InitSegaMapper() + { + Cpu.ReadMemory = ReadMemory; + Cpu.WriteMemory = WriteMemory; + WriteMemory(0xFFFC, 0); + WriteMemory(0xFFFD, 0); + WriteMemory(0xFFFE, 1); + WriteMemory(0xFFFF, 2); + } + } +} diff --git a/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs new file mode 100644 index 0000000000..3f8b4a3990 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/SMS/SMS.cs @@ -0,0 +1,398 @@ +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using BizHawk.Emulation.CPUs.Z80; +using BizHawk.Emulation.Sound; + +/***************************************************** + + VDP: + + Double Size Sprites + + HCounter + + Possibly work on VDP tests, but they don't really affect games. + - Other video modes / CodeMasters 224 lines / old SG-1000 video modes. + + GENERAL: + + Debug some GameGear game issues. + + Port 3F emulation (Japanese BIOS) + + Try to clean up the organization of the source code. + +**********************************************************/ + +namespace BizHawk.Emulation.Consoles.Sega +{ + public enum DisplayType { NTSC, PAL } + + public sealed partial class SMS : IEmulator + { + // Constants + public const int BankSize = 16384; + + // ROM + public byte[] RomData; + public byte RomBank0, RomBank1, RomBank2; + public byte RomBanks; + public string[] Options; + + // SaveRAM + public byte[] SaveRAM = new byte[BankSize*2]; + public byte SaveRamBank; + + public byte[] SaveRam { get { return SaveRAM; } } + public bool SaveRamModified { get; set; } + + // Machine resources + public Z80A Cpu; + public byte[] SystemRam; + public VDP Vdp; + public SN76489 PSG; + public YM2413 YM2413; + public SoundMixer SoundMixer; + public bool IsGameGear = false; + + public bool HasYM2413 = false; + public int IPeriod = 228; + + public int Frame { get; set; } + private byte Port01 = 0xFF; + private byte Port02 = 0xFF; + private byte Port3F = 0xFF; + + private int framesPerSecond; + private int scanlinesPerFrame; + + private DisplayType displayType; + public DisplayType DisplayType + { + get { return displayType; } + set + { + displayType = value; + if (displayType == DisplayType.NTSC) + { + framesPerSecond = 60; + scanlinesPerFrame = 262; + } else // PAL + { + framesPerSecond = 50; + scanlinesPerFrame = 313; + } + } + } + + public bool DeterministicEmulation { get; set; } + + public void Init() + { + DisplayType = DisplayType.NTSC; + if (Controller == null) + Controller = NullController.GetNullController(); + + Cpu = new Z80A(); + Cpu.ReadHardware = ReadPort; + Cpu.WriteHardware = WritePort; + + Vdp = new VDP(IsGameGear ? VdpMode.GameGear : VdpMode.SMS); + PSG = new SN76489(); + YM2413 = new YM2413(); + SoundMixer = new SoundMixer(PSG, YM2413); + + ActiveSoundProvider = PSG; + HardReset(); + //PSG.StereoPanning = 0xDA; + } + + public void HardReset() + { + Cpu.Reset(); + Cpu.RegisterSP = 0xDFF0; + Vdp = new VDP(Vdp.VdpMode); + PSG.Reset(); + YM2413.Reset(); + SystemRam = new byte[0x2000]; + + if (Options.Contains("CMMapper") == false) + InitSegaMapper(); + else + InitCodeMastersMapper(); + } + + public void LoadGame(IGame game) + { + RomData = game.GetRomData(); + RomBanks = (byte)(RomData.Length/BankSize); + Options = game.GetOptions(); + foreach (string option in Options) + { + var args = option.Split('='); + if (option == "FM") HasYM2413 = true; + else if (args[0] == "IPeriod") IPeriod = int.Parse(args[1]); + else if (args[0] == "Japan") Region = "Japan"; + } + + Init(); + + // In Outrun FM mode, when you start a race, the PSG noise channel is left on until a "wheel squeeling" + // sound effect occurs, and this happens again every "extended play" checkpoint. Every emulator I have tested + // does this; if it's a bug, it is a bug that no emulator gets right. + // In any case, it is annoying, so this turns it off. + // My view is that because I believe it to be a game bug (not an emulation bug), this doesn't count as a game-specific hack :) + + if (HasYM2413 && game.Name.StartsWith("OutRun", StringComparison.InvariantCultureIgnoreCase)) + SoundMixer.DisableSource(PSG); + + // TODO: at some point we need a proper Game Library construct with various metadata about emulation hints and options for games and roms. + } + + public byte ReadPort(ushort port) + { + switch (port & 0xFF) + { + case 0x00: return ReadPort0(); + case 0x01: return Port01; + case 0x02: return Port02; + case 0x03: return 0x00; + case 0x04: return 0xFF; + case 0x05: return 0x00; + case 0x06: return 0xFF; + case 0x7E: return Vdp.ReadVLineCounter(); + case 0x7F: break; // hline counter TODO + case 0xBE: return Vdp.ReadVram(); + case 0xBF: Cpu.Interrupt = false; return Vdp.ReadVdpStatus(); + case 0xC0: + case 0xDC: return ReadControls1(); + case 0xC1: + case 0xDD: return ReadControls2(); + case 0xF2: + if (HasYM2413) + { + ActiveSoundProvider = SoundMixer; + return YM2413.DetectionValue; + } + break; + } + return 0xFF; + } + + public void WritePort(ushort port, byte value) + { + switch (port & 0xFF) + { + case 0x01: Port01 = value; break; + case 0x02: Port02 = value; break; + case 0x06: PSG.StereoPanning = value; break; + case 0x3F: Port3F = value; break; + case 0x7E: + case 0x7F: PSG.WritePsgData(value, Cpu.TotalExecutedCycles); break; + case 0xBE: Vdp.WriteVdpData(value); break; + case 0xBD: + case 0xBF: Vdp.WriteVdpRegister(value); break; + case 0xF0: if (HasYM2413) YM2413.RegisterLatch = value; break; + case 0xF1: if (HasYM2413) YM2413.Write(value); break; + case 0xF2: if (HasYM2413) YM2413.DetectionValue = value; break; + } + } + + private int lineIntLinesRemaining; + + private void ProcessFrameInterrupt() + { + if (Vdp.ScanLine == 193) + Vdp.StatusByte |= 0x80; + + if ((Vdp.StatusByte & 0x80) != 0 && Vdp.EnableFrameInterrupts) + Cpu.Interrupt = true; + } + + private void ProcessLineInterrupt() + { + if (Vdp.ScanLine <= 192) + { + if (lineIntLinesRemaining-- <= 0) + { + if (Vdp.EnableLineInterrupts) + { + Cpu.Interrupt = true; + } + lineIntLinesRemaining = Vdp.Registers[0x0A]; + } + return; + } + // else we're outside the active display period + lineIntLinesRemaining = Vdp.Registers[0x0A]; + } + + public void FrameAdvance(bool render) + { + Controller.FrameNumber = Frame++; + PSG.BeginFrame(Cpu.TotalExecutedCycles); + + if (IsGameGear == false) + Cpu.NonMaskableInterrupt = Controller["Pause"]; + + for (Vdp.ScanLine = 0; Vdp.ScanLine < scanlinesPerFrame; Vdp.ScanLine++) + { + ProcessFrameInterrupt(); + ProcessLineInterrupt(); + + if (Vdp.ScanLine < 192) + Vdp.RenderCurrentScanline(render); + + Cpu.ExecuteCycles(IPeriod); + + if (Vdp.ScanLine == 192) + Vdp.RenderBlankingRegions(); + } + PSG.EndFrame(Cpu.TotalExecutedCycles); + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[SMS]\n"); + Cpu.SaveStateText(writer); + PSG.SaveStateText(writer); + Vdp.SaveStateText(writer); + + writer.WriteLine("Frame {0}", Frame); + writer.WriteLine("Bank0 {0}", RomBank0); + writer.WriteLine("Bank1 {0}", RomBank1); + writer.WriteLine("Bank2 {0}", RomBank2); + writer.Write("RAM "); + SystemRam.SaveAsHex(writer); + writer.WriteLine("Port01 {0:X2}", Port01); + writer.WriteLine("Port02 {0:X2}", Port02); + writer.WriteLine("Port3F {0:X2}", Port3F); + int SaveRamLen = Util.SaveRamBytesUsed(SaveRAM); + if (SaveRamLen > 0) + { + writer.Write("SaveRAM "); + SaveRAM.SaveAsHex(writer, SaveRamLen); + } + if (HasYM2413) + { + writer.Write("FMRegs " ); + YM2413.opll.reg.SaveAsHex(writer); + } + writer.WriteLine("[/SMS]"); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[SMS]") continue; + if (args[0] == "[/SMS]") break; + if (args[0] == "Bank0") + RomBank0 = byte.Parse(args[1]); + else if (args[0] == "Bank1") + RomBank1 = byte.Parse(args[1]); + else if (args[0] == "Bank2") + RomBank2 = byte.Parse(args[1]); + else if (args[0] == "Frame") + Frame = int.Parse(args[1]); + else if (args[0] == "RAM") + SystemRam.ReadFromHex(args[1]); + else if (args[0] == "SaveRAM") + { + for (int i = 0; i < SaveRAM.Length; i++) SaveRAM[i] = 0; + SaveRAM.ReadFromHex(args[1]); + } + else if (args[0] == "FMRegs") + { + byte[] regs = new byte[YM2413.opll.reg.Length]; + regs.ReadFromHex(args[1]); + for (byte i=0; i + /// Emulates the Texas Instruments TMS9918 VDP. + /// + public sealed class VDP : IVideoProvider + { + // VDP State + public byte[] VRAM = new byte[0x4000]; //16kb video RAM + public byte[] CRAM; // SMS = 32 bytes, GG = 64 bytes CRAM + public byte[] Registers = new byte[] { 0x06, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }; + public byte StatusByte; + + private bool vdpWaitingForLatchByte = true; + private byte vdpLatch; + private byte vdpBuffer; + private ushort vdpAddress; + private VdpCommand vdpCommand; + private ushort vdpAddressClamp; + + private VdpMode mode; + public VdpMode VdpMode { get { return mode; } } + + public int ScanLine; + + public int[] FrameBuffer = new int[256*192]; + public int[] GameGearFrameBuffer = new int[160*144]; + + // preprocessed state assist stuff. + public int[] Palette = new int[32]; + + private static readonly byte[] SMSPalXlatTable = { 0, 85, 170, 255 }; + private static readonly byte[] GGPalXlatTable = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 }; + + public bool ShiftSpritesLeft8Pixels { get { return (Registers[0] & 8) > 0; } } + public bool EnableLineInterrupts { get { return (Registers[0] & 16) > 0; } } + public bool LeftBlanking { get { return (Registers[0] & 32) > 0; } } + public bool HorizScrollLock { get { return (Registers[0] & 64) > 0; } } + public bool VerticalScrollLock { get { return (Registers[0] & 128) > 0; } } + public bool DisplayOn { get { return (Registers[1] & 64) > 0; } } + public bool EnableFrameInterrupts { get { return (Registers[1] & 32) > 0; } } + public bool Enable8x16Sprites { get { return (Registers[1] & 2) > 0; } } + public byte BackdropColor { get { return (byte) (16 + (Registers[7] & 15)); } } + public int NameTableBase { get { return 1024 * (Registers[2] & 0x0E); } } + public int SpriteAttributeTableBase { get { return ((Registers[5] >> 1) << 8) & 0x3FFF; } } + public int SpriteTileBase { get { return (Registers[6] & 4) > 0 ? 256: 0; } } + + private readonly byte[] VLineCounterTable = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, + }; + + public byte[] PatternBuffer = new byte[0x8000]; + + private byte[] ScanlinePriorityBuffer = new byte[256]; + private byte[] SpriteCollisionBuffer = new byte[256]; + + public VDP(VdpMode mode) + { + this.mode = mode; + if (mode == VdpMode.SMS) CRAM = new byte[32]; + if (mode == VdpMode.GameGear) CRAM = new byte[64]; + } + + public byte ReadVram() + { + vdpWaitingForLatchByte = true; + byte value = vdpBuffer; + vdpBuffer = VRAM[vdpAddress & vdpAddressClamp]; + vdpAddress++; + return value; + } + + public byte ReadVdpStatus() + { + vdpWaitingForLatchByte = true; + byte returnValue = StatusByte; + StatusByte &= 0x1F; + return returnValue; + } + + public byte ReadVLineCounter() + { + return VLineCounterTable[ScanLine]; + } + + public void WriteVdpRegister(byte value) + { + if (vdpWaitingForLatchByte) + { + vdpLatch = value; + vdpWaitingForLatchByte = false; + vdpAddress = (ushort)((vdpAddress & 0xFF00) | value); + return; + } + + vdpWaitingForLatchByte = true; + switch (value & 0xC0) + { + case 0x00: // read VRAM + vdpCommand = VdpCommand.VramRead; + vdpAddressClamp = 0x3FFF; + vdpAddress = (ushort)(((value & 63) << 8) | vdpLatch); + vdpBuffer = VRAM[vdpAddress & vdpAddressClamp]; + vdpAddress++; + break; + case 0x40: // write VRAM + vdpCommand = VdpCommand.VramWrite; + vdpAddressClamp = 0x3FFF; + vdpAddress = (ushort)(((value & 63) << 8) | vdpLatch); + break; + case 0x80: // VDP register write + Registers[value & 0x0F] = vdpLatch; + break; + case 0xC0: // write CRAM / modify palette + vdpCommand = VdpCommand.CramWrite; + vdpAddressClamp = (byte) (mode == VdpMode.SMS ? 0x1F : 0x3F); + vdpAddress = (ushort)(((value & 63) << 8) | vdpLatch); + break; + } + } + + public void WriteVdpData(byte value) + { + vdpWaitingForLatchByte = true; + vdpBuffer = value; + if (vdpCommand == VdpCommand.CramWrite) + { + // Write Palette / CRAM + CRAM[vdpAddress & vdpAddressClamp] = value; + vdpAddress++; + UpdatePrecomputedPalette(); + } + else + { + // Write VRAM and update pre-computed pattern buffer. + UpdatePatternBuffer((ushort)(vdpAddress & vdpAddressClamp), value); + VRAM[vdpAddress & vdpAddressClamp] = value; + vdpAddress++; + } + } + + public void UpdatePrecomputedPalette() + { + if (mode == VdpMode.SMS) + { + for (int i=0; i<32; i++) + { + byte value = CRAM[i]; + byte r = SMSPalXlatTable[(value & 0x03)]; + byte g = SMSPalXlatTable[(value & 0x0C) >> 2]; + byte b = SMSPalXlatTable[(value & 0x30) >> 4]; + Palette[i] = Colors.ARGB(r, g, b); + } + } else // GameGear + { + for (int i=0; i<32; i++) + { + ushort value = (ushort) ((CRAM[(i*2) + 1] << 8) | CRAM[(i*2) + 0]); + byte r = GGPalXlatTable[(value & 0x000F)]; + byte g = GGPalXlatTable[(value & 0x00F0) >> 4]; + byte b = GGPalXlatTable[(value & 0x0F00) >> 8]; + Palette[i] = Colors.ARGB(r, g, b); + } + } + } + + private static readonly byte[] pow2 = {1, 2, 4, 8, 16, 32, 64, 128}; + + private void UpdatePatternBuffer(ushort address, byte value) + { + // writing one byte affects 8 pixels due to stupid planar storage. + for (int i=0; i<8; i++) + { + byte colorBit = pow2[address%4]; + byte sourceBit = pow2[7 - i]; + ushort dest = (ushort) (((address & 0xFFFC)*2) + i); + if ((value & sourceBit) > 0) // setting bit + PatternBuffer[dest] |= colorBit; + else // clearing bit + PatternBuffer[dest] &= (byte)~colorBit; + } + } + + internal void RenderCurrentScanline(bool render) + { + // TODO: make frameskip actually skip rendering + RenderBackgroundCurrentLine(); + RenderSpritesCurrentLine(); + } + + internal void RenderBackgroundCurrentLine() + { + if (DisplayOn == false) + { + for (int x = 0; x < 256; x++) + FrameBuffer[(ScanLine*256) + x] = BackdropColor; + return; + } + + // Clear the priority buffer for this scanline + for (int p = 0; p < 256; p++) + ScanlinePriorityBuffer[p] = 0; + + int mapBase = NameTableBase; + + int vertOffset = ScanLine + Registers[9]; + if (vertOffset >= 224) + vertOffset -= 224; + byte horzOffset = (HorizScrollLock && ScanLine < 16) ? (byte) 0 : Registers[8]; + + int yTile = vertOffset/8; + + for (int xTile = 0; xTile<32; xTile++) + { + if (xTile == 24 && VerticalScrollLock) + { + vertOffset = ScanLine; + yTile = vertOffset/8; + } + + byte PaletteBase = 0; + int tileInfo = VRAM[mapBase+((yTile*32) + xTile)*2] | (VRAM[mapBase+(((yTile*32) + xTile)*2) + 1]<<8); + int tileNo = tileInfo & 0x01FF; + if ((tileInfo & 0x800) != 0) + PaletteBase = 16; + bool Priority = (tileInfo & 0x1000) != 0; + bool VFlip = (tileInfo & 0x400) != 0; + bool HFlip = (tileInfo & 0x200) != 0; + + int yOfs = vertOffset & 7; + if (VFlip) + yOfs = 7 - yOfs; + + if (HFlip == false) + { + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 0] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 1] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 2] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 3] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 4] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 5] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 6] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 7] + PaletteBase]; + + if (Priority) + { + horzOffset -= 8; + for (int k = 0; k < 8; k++) + { + if (PatternBuffer[(tileNo * 64) + (yOfs * 8) + k] != 0) + ScanlinePriorityBuffer[horzOffset] = 1; + horzOffset++; + } + } + } + else // Flipped Horizontally + { + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 7] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 6] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 5] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 4] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 3] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 2] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 1] + PaletteBase]; + FrameBuffer[(ScanLine * 256) + horzOffset++] = Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 0] + PaletteBase]; + + if (Priority) + { + horzOffset -= 8; + for (int k = 7; k >= 0; k--) + { + if (PatternBuffer[(tileNo * 64) + (yOfs * 8) + k] != 0) + ScanlinePriorityBuffer[horzOffset] = 1; + horzOffset++; + } + } + } + } + } + + internal void RenderSpritesCurrentLine() + { + if (DisplayOn == false) return; + int SpriteBase = SpriteAttributeTableBase; + int SpriteHeight = Enable8x16Sprites ? 16 : 8; + + // Clear the sprite collision buffer for this scanline + for (int c = 0; c < 256; c++) + SpriteCollisionBuffer[c] = 0; + + // 208 is a special terminator sprite. Lets find it... + int TerminalSprite = 64; + for (int i = 0; i < 64; i++) + { + if (VRAM[SpriteBase + i] == 208) + { + TerminalSprite = i; + break; + } + } + + // Loop through these sprites and render the current scanline + int SpritesDrawnThisScanline = 0; + for (int i = TerminalSprite - 1; i >= 0; i--) + { + if (SpritesDrawnThisScanline >= 8) + StatusByte |= 0x40; // Set Overflow bit + + int x = VRAM[SpriteBase + 0x80 + (i*2)]; + if (ShiftSpritesLeft8Pixels) + x -= 8; + + int y = VRAM[SpriteBase + i] + 1; + if (y >= (Enable8x16Sprites ? 240 : 248)) y -= 256; + + if (y+SpriteHeight<=ScanLine || y > ScanLine) + continue; + + int tileNo = VRAM[SpriteBase + 0x80 + (i*2) + 1]; + if (Enable8x16Sprites) + tileNo &= 0xFE; + tileNo += SpriteTileBase; + + int ys = ScanLine - y; + + for (int xs = 0; xs<8 && x+xs < 256; xs++) + { + byte color = PatternBuffer[(tileNo*64) + (ys*8) + xs]; + if (color != 0 && x+xs >= 0 && ScanlinePriorityBuffer[x + xs] == 0) + { + FrameBuffer[(ys + y)*256 + x + xs] = Palette[(color + 16)]; + if (SpriteCollisionBuffer[x + xs] != 0) + StatusByte |= 0x20; // Set Collision bit + SpriteCollisionBuffer[x + xs] = 1; + } + } + SpritesDrawnThisScanline++; + } + } + + /// + /// Performs render buffer blanking. This includes the left-column blanking as well as Game Gear blanking if requested. + /// Should be called at the end of the frame. + /// + public void RenderBlankingRegions() + { + int blankingColor = Palette[BackdropColor]; + + if (LeftBlanking) + { + for (int y=0; y<192; y++) + { + for (int x=0; x<8; x++) + FrameBuffer[(y*256) + x] = blankingColor; + } + } + + if (mode == VdpMode.GameGear) + { + for (int y = 0; y < 144; y++) + for (int x = 0; x < 160; x++) + GameGearFrameBuffer[(y*160) + x] = FrameBuffer[((y + 24)*256) + x + 48]; + } + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[VDP]"); + writer.WriteLine("Mode " + Enum.GetName(typeof(VdpMode), VdpMode)); + writer.WriteLine("StatusByte {0:X2}", StatusByte); + writer.WriteLine("WaitingForLatchByte {0}", vdpWaitingForLatchByte); + writer.WriteLine("Latch {0:X2}", vdpLatch); + writer.WriteLine("ReadBuffer {0:X2}", vdpBuffer); + writer.WriteLine("VdpAddress {0:X4}", vdpAddress); + writer.WriteLine("VdpAddressMask {0:X2}", vdpAddressClamp); + writer.WriteLine("Command " + Enum.GetName(typeof(VdpCommand), vdpCommand)); + + writer.Write("Registers "); + Registers.SaveAsHex(writer); + writer.Write("CRAM "); + CRAM.SaveAsHex(writer); + writer.Write("VRAM "); + VRAM.SaveAsHex(writer); + + writer.WriteLine("[/VDP]"); + writer.WriteLine(); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/VDP]") break; + if (args[0] == "StatusByte") + StatusByte = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "WaitingForLatchByte") + vdpWaitingForLatchByte = bool.Parse(args[1]); + else if (args[0] == "Latch") + vdpLatch = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "ReadBuffer") + vdpBuffer = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "VdpAddress") + vdpAddress = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "VdpAddressMask") + vdpAddressClamp = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Command") + vdpCommand = (VdpCommand) Enum.Parse(typeof (VdpCommand), args[1]); + else if (args[0] == "Registers") + Registers.ReadFromHex(args[1]); + else if (args[0] == "CRAM") + { + CRAM.ReadFromHex(args[1]); + UpdatePrecomputedPalette(); + } + else if (args[0] == "VRAM") + { + VRAM.ReadFromHex(args[1]); + for (ushort i=0; i 0; --j) + { + if ((crc & 1) == 1) + crc = ((crc >> 1) ^ 0xEDB88320); + else + crc >>= 1; + } + CRC32Table[i] = crc; + } + //} + } + + public static int Calculate(byte[] data) + { + //unchecked { + uint Result = 0xFFFFFFFF; + foreach (var b in data) + Result = (((Result) >> 8) ^ CRC32Table[b ^ ((Result) & 0xFF)]); + return (int)~Result; + //} + } + } +} diff --git a/BizHawk.Emulation/Database/Database.cs b/BizHawk.Emulation/Database/Database.cs new file mode 100644 index 0000000000..16bf58a806 --- /dev/null +++ b/BizHawk.Emulation/Database/Database.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; + +namespace BizHawk +{ + public class GameInfo + { + public string Name; + public string System; + public string MetaData; + public int CRC32; + + public string[] GetOptions() + { + if (string.IsNullOrEmpty(MetaData)) + return new string[0]; + return MetaData.Split(';').Where(opt => string.IsNullOrEmpty(opt) == false).ToArray(); + } + } + + public static class Database + { + private static Dictionary db = new Dictionary(); + + public static void LoadDatabase(string path) + { + using (var reader = new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) + { + reader.ReadLine(); // Skip header row + + while (reader.EndOfStream == false) + { + string line = reader.ReadLine(); + if (line.Trim().Length == 0) continue; + string[] items = line.Split('\t'); + + var Game = new GameInfo(); + Game.CRC32 = Int32.Parse(items[0], NumberStyles.HexNumber); + Game.Name = items[2]; + Game.System = items[3]; + Game.MetaData = items.Length >= 6 ? items[5] : null; + db[Game.CRC32] = Game; + } + } + } + + public static GameInfo GetGameInfo(byte[] RomData, string fileName) + { + int crc = CRC32.Calculate(RomData); + if (db.ContainsKey(crc)) + return db[crc]; + + // rom is not in database. make some best-guesses + var Game = new GameInfo(); + Game.CRC32 = crc; + Game.MetaData = "NotInDatabase"; + + string ext = Path.GetExtension(fileName).ToUpperInvariant(); + + switch (ext) + { + case ".SMS": Game.System = "SMS"; break; + case ".GG" : Game.System = "GG"; break; + case ".SG" : Game.System = "SG"; break; + case ".PCE": Game.System = "PCE"; break; + case ".SGX": Game.System = "SGX"; break; + case ".GB" : Game.System = "GB"; break; + case ".BIN": + case ".SMD": Game.System = "GEN"; break; + case ".NES": Game.System = "NES"; break; + } + + Game.Name = Path.GetFileNameWithoutExtension(fileName).Replace('_', ' '); + // If filename is all-caps, then attempt to proper-case the title. + if (Game.Name == Game.Name.ToUpperInvariant()) + Game.Name = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(Game.Name.ToLower()); + + return Game; + } + } +} diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/Game.cs b/BizHawk.Emulation/Interfaces/Base Implementations/Game.cs new file mode 100644 index 0000000000..330f0ad5f9 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/Base Implementations/Game.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; + +namespace BizHawk +{ + public sealed class Game : IGame + { + public byte[] RomData; + private string name; + private string[] options; + private const int BankSize = 4096; + + public Game(string path, params string[] options) + { + name = Path.GetFileNameWithoutExtension(path).Replace('_',' '); + this.options = options; + if (this.options == null) + this.options = new string[0]; + + this.options = options; + + using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) + { + int length = (int)stream.Length; + + stream.Position = 0; + if (length % BankSize == 512) // 512-byte ROM header is present + { + stream.Position += 512; + length -= 512; + } + if (length % BankSize == 64) // 64-byte ROM header is present + { + stream.Position += 64; + length -= 64; + } + + if (length % BankSize != 0) + throw new Exception("Not a valid ROM."); + RomData = new byte[length]; + stream.Read(RomData, 0, length); + } + } + + public void Patch(string patch) + { + using (var stream = new FileStream(patch, FileMode.Open, FileAccess.Read)) + { + IPS.Patch(RomData, stream); + } + } + + public byte[] GetRomData() + { + return RomData; + } + + public string[] GetOptions() + { + return options; + } + + public string Name + { + get { return name; } + set { name = value; } + } + } +} diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/IPS.cs b/BizHawk.Emulation/Interfaces/Base Implementations/IPS.cs new file mode 100644 index 0000000000..7dcc23c578 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/Base Implementations/IPS.cs @@ -0,0 +1,64 @@ +using System; +using System.IO; + +namespace BizHawk +{ + public static class IPS + { + public static void Patch(byte[] rom, Stream patch) + { + var ipsHeader = new byte[5]; + patch.Read(ipsHeader, 0, 5); + + string header = "PATCH"; + for (int i = 0; i < 5; i++) + { + if (ipsHeader[i] != header[i]) + { + Console.WriteLine("Patch file specified is invalid."); + return; + } + } + + // header verified, loop over patch entries + uint EOF = ('E' * 0x10000 + 'O' * 0x100 + 'F'); + + while (true) + { + uint offset = Read24(patch); + if (offset == EOF) return; + ushort size = Read16(patch); + + if (size != 0) // non-RLE patch + { + var patchData = new byte[size]; + patch.Read(patchData, 0, size); + for (int i = 0; i < size; i++) + rom[offset++] = patchData[i]; + } + else // RLE patch + { + size = Read16(patch); + byte value = (byte)patch.ReadByte(); + for (int i = 0; i < size; i++) + rom[offset++] = value; + } + } + } + + private static ushort Read16(Stream patch) + { + int Upper = patch.ReadByte(); + int Lower = patch.ReadByte(); + return (ushort)(Upper * 0x100 + Lower); + } + + private static uint Read24(Stream patch) + { + int Upper = patch.ReadByte(); + int Middle = patch.ReadByte(); + int Lower = patch.ReadByte(); + return (uint)(Upper * 0x10000 + Middle * 0x100 + Lower); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/Movies.cs b/BizHawk.Emulation/Interfaces/Base Implementations/Movies.cs new file mode 100644 index 0000000000..98b7d10ead --- /dev/null +++ b/BizHawk.Emulation/Interfaces/Base Implementations/Movies.cs @@ -0,0 +1,125 @@ +using System.IO; + +namespace BizHawk +{ + public class InputRecorder : IController + { + private IController baseController; + private BinaryWriter writer; + + public InputRecorder(IController baseController, BinaryWriter writer) + { + this.baseController = baseController; + this.writer = writer; + } + + public void CloseMovie() + { + writer.Close(); + } + + public ControllerDefinition Type + { + get { return baseController.Type; } + } + + public bool this[string name] + { + get { return baseController[name]; } + } + + public bool IsPressed(string name) + { + return baseController[name]; + } + + public float GetFloat(string name) + { + return baseController.GetFloat(name); + } + + public void UnpressButton(string name) + { + baseController.UnpressButton(name); + } + + private int frame; + public int FrameNumber + { + get { return frame; } + set + { + if (frame != value) + { + frame = value; + RecordFrame(); + } + baseController.FrameNumber = value; + } + } + + private void RecordFrame() + { + int encodedValue = 0; + for (int i=0; i= input.Length) + return false; + + for (int i = 0; i < def.BoolButtons.Count; i++) + { + if (def.BoolButtons[i] == name) + { + return (input[FrameNumber] & (1 << i)) != 0; + } + } + return false; + } + + public float GetFloat(string name) + { + throw new System.NotImplementedException(); + } + + public void UnpressButton(string name) {} + public int FrameNumber { get; set; } + + public bool MovieEnded { get { return FrameNumber >= input.Length; } } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/NullController.cs b/BizHawk.Emulation/Interfaces/Base Implementations/NullController.cs new file mode 100644 index 0000000000..821c07bc9a --- /dev/null +++ b/BizHawk.Emulation/Interfaces/Base Implementations/NullController.cs @@ -0,0 +1,15 @@ +namespace BizHawk +{ + public class NullController : IController + { + public ControllerDefinition Type { get { return null; } } + public bool this[string name] { get { return false; } } + public bool IsPressed(string name) { return false; } + public float GetFloat(string name) { return 0f; } + public void UnpressButton(string name) { } + public int FrameNumber { get; set; } + + private static NullController nullController = new NullController(); + public static NullController GetNullController() { return nullController; } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs b/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs new file mode 100644 index 0000000000..d73d6126b6 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/Base Implementations/NullEmulator.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; + +namespace BizHawk +{ + public class NullEmulator : IEmulator, IVideoProvider, ISoundProvider + { + private int[] frameBuffer = new int[256 * 192]; + private Random rand = new Random(); + public IVideoProvider VideoProvider { get { return this; } } + public ISoundProvider SoundProvider { get { return this; } } + public void LoadGame(IGame game) { } + public void FrameAdvance(bool render) + { + if (render == false) return; + for (int i = 0; i < 256 * 192; i++) + frameBuffer[i] = Colors.Luminosity((byte)rand.Next()); + } + public void HardReset() { } + public ControllerDefinition ControllerDefinition { get { return null; } } + public IController Controller { get; set; } + public int Frame { get; set; } + public byte[] SaveRam { get { return new byte[0]; } } + public bool DeterministicEmulation { get; set; } + public bool SaveRamModified { get; set; } + public void SaveStateText(TextWriter writer) { } + public void LoadStateText(TextReader reader) { } + public void SaveStateBinary(BinaryWriter writer) { } + public void LoadStateBinary(BinaryReader reader) { } + public byte[] SaveStateBinary() { return new byte[1]; } + public int[] GetVideoBuffer() { return frameBuffer; } + public int BufferWidth { get { return 256; } } + public int BufferHeight { get { return 192; } } + public int BackgroundColor { get { return 0; } } + public void GetSamples(short[] samples) { } + } +} diff --git a/BizHawk.Emulation/Interfaces/Base Implementations/SmdGame.cs b/BizHawk.Emulation/Interfaces/Base Implementations/SmdGame.cs new file mode 100644 index 0000000000..06c17a6dfe --- /dev/null +++ b/BizHawk.Emulation/Interfaces/Base Implementations/SmdGame.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; + +namespace BizHawk +{ + /// + /// Loader for .SMD Genesis ROM format (Super Magic Drive) + /// + public sealed class SmdGame : IGame + { + public byte[] RomData; + private string name; + private string[] options; + + private const int BankSize = 16384; + + // TODO we need a consistent interface for these ROM loader implementations, that easily supports loading direct files, or from Content. + // TODO also should support Name-set, and some other crap. + // TODO we should inject a way to support IPS patches, because the patch needs to be applied before de-interlacing (I assume). + public SmdGame(string path, params string[] options) + { + name = Path.GetFileNameWithoutExtension(path).Replace('_', ' '); + this.options = options; + if (this.options == null) + this.options = new string[0]; + + using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) + { + int length = (int)stream.Length; + + stream.Position = 0; + if (length % BankSize == 512) // 512-byte ROM header is present + { + stream.Position += 512; + length -= 512; + } + + if (length % BankSize != 0) + throw new Exception("Not a valid ROM."); + var rawRomData = new byte[length]; + stream.Read(rawRomData, 0, length); + RomData = DeInterleave(rawRomData); + } + } + + public byte[] DeInterleave(byte[] source) + { + // SMD files are interleaved in pages of 16k, with the first 8k containing all + // odd bytes and the second 8k containing all even bytes. + + int size = source.Length; + if (size > 0x400000) size = 0x400000; + int pages = size / 0x4000; + byte[] output = new byte[size]; + + for (int page = 0; page < pages; page++) + { + for (int i = 0; i < 0x2000; i++) + { + output[(page * 0x4000) + (i * 2) + 0] = source[(page * 0x4000) + 0x2000 + i]; + output[(page * 0x4000) + (i * 2) + 1] = source[(page * 0x4000) + 0x0000 + i]; + } + } + return output; + } + + public byte[] GetRomData() + { + return RomData; + } + + public string[] GetOptions() + { + return options; + } + + public string Name + { + get { return name; } + set { name = value; } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/IController.cs b/BizHawk.Emulation/Interfaces/IController.cs new file mode 100644 index 0000000000..a4a4fe64a0 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/IController.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace BizHawk +{ + public class ControllerDefinition + { + public string Name; + public List BoolButtons = new List(); + public List FloatControls = new List(); + } + + public interface IController + { + ControllerDefinition Type { get; } + + bool this[string name] { get; } + bool IsPressed(string name); + float GetFloat(string name); + void UnpressButton(string name); + + int FrameNumber { get; set; } + } +} diff --git a/BizHawk.Emulation/Interfaces/IEmulator.cs b/BizHawk.Emulation/Interfaces/IEmulator.cs new file mode 100644 index 0000000000..1839ca43d3 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/IEmulator.cs @@ -0,0 +1,32 @@ +using System.IO; + +namespace BizHawk +{ + public interface IEmulator + { + IVideoProvider VideoProvider { get; } + ISoundProvider SoundProvider { get; } + + ControllerDefinition ControllerDefinition { get; } + IController Controller { get; set; } + + void LoadGame(IGame game); + void FrameAdvance(bool render); + void HardReset(); + + int Frame { get; } + bool DeterministicEmulation { get; set; } + + byte[] SaveRam { get; } + bool SaveRamModified { get; set; } + + // TODO: should IEmulator expose a way of enumerating the Options it understands? + // (the answer is yes) + + void SaveStateText(TextWriter writer); + void LoadStateText(TextReader reader); + void SaveStateBinary(BinaryWriter writer); + void LoadStateBinary(BinaryReader reader); + byte[] SaveStateBinary(); + } +} diff --git a/BizHawk.Emulation/Interfaces/IGame.cs b/BizHawk.Emulation/Interfaces/IGame.cs new file mode 100644 index 0000000000..0c03f0b799 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/IGame.cs @@ -0,0 +1,9 @@ +namespace BizHawk +{ + public interface IGame + { + byte[] GetRomData(); + string[] GetOptions(); + string Name { get; } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Interfaces/ISoundProvider.cs b/BizHawk.Emulation/Interfaces/ISoundProvider.cs new file mode 100644 index 0000000000..8ba96ee142 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/ISoundProvider.cs @@ -0,0 +1,7 @@ +namespace BizHawk +{ + public interface ISoundProvider + { + void GetSamples(short[] samples); + } +} diff --git a/BizHawk.Emulation/Interfaces/IVideoProvider.cs b/BizHawk.Emulation/Interfaces/IVideoProvider.cs new file mode 100644 index 0000000000..2826e2e198 --- /dev/null +++ b/BizHawk.Emulation/Interfaces/IVideoProvider.cs @@ -0,0 +1,11 @@ +namespace BizHawk +{ + public interface IVideoProvider + { + int[] GetVideoBuffer(); + + int BufferWidth { get; } + int BufferHeight { get; } + int BackgroundColor { get; } + } +} diff --git a/BizHawk.Emulation/Log.cs b/BizHawk.Emulation/Log.cs new file mode 100644 index 0000000000..ecff2e5e89 --- /dev/null +++ b/BizHawk.Emulation/Log.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace BizHawk +{ + public static class Log + { + static Log() + { + // You can set current desired logging settings here. + // Production builds should be done with all logging disabled. + //LogToConsole = true; + //LogToFile = true; + //LogFilename = "d:/bizhawk.log"; + //EnableDomain("CPU"); + //EnableDomain("VDC"); + //EnableDomain("MEM"); + } + + // ============== Logging Domain Configuration ============== + + private static List EnabledLogDomains = new List(); + + public static void EnableDomain(string domain) + { + if (EnabledLogDomains.Contains(domain) == false) + EnabledLogDomains.Add(domain); + } + + public static void DisableDomain(string domain) + { + if (EnabledLogDomains.Contains(domain)) + EnabledLogDomains.Remove(domain); + } + + // ============== Logging Action Configuration ============== + + public static Action LogAction = DefaultLogger; + + // NOTEs are only logged if the domain is enabled. + // ERRORs are logged regardless. + + public static void Note(string domain, string msg, params object[] vals) + { + if (EnabledLogDomains.Contains(domain)) + LogAction(String.Format(msg, vals)); + } + + public static void Error(string domain, string msg, params object[] vals) + { + LogAction(String.Format(msg, vals)); + } + + // ============== Default Logger Action ============== + + private static bool LogToConsole; + private static bool LogToFile; + + private static string LogFilename = "bizhawk.txt"; + private static StreamWriter writer; + + private static void DefaultLogger(string message) + { + if (LogToConsole) + Console.WriteLine(message); + + if (LogToFile && writer == null) + writer = new StreamWriter(LogFilename); + + if (LogToFile) + writer.WriteLine(message); + } + } +} diff --git a/BizHawk.Emulation/Notes.txt b/BizHawk.Emulation/Notes.txt new file mode 100644 index 0000000000..2be6504090 --- /dev/null +++ b/BizHawk.Emulation/Notes.txt @@ -0,0 +1,64 @@ +------------------------------- +BizHawk.Emulation Project Notes +------------------------------- + +1) Please keep this project free of non-portable external references. + Windows.Forms should not be referenced, nor System.Windows.Drawing, nor XNA, nor SlimDX, etc. + This project should be very close to vanilla C# consisting primarily of basic data manipulation. + +2) If you want to include ie Winforms code for something such as a debugger, this should be placed in + a separate project. That project does not yet exist at the time of this writing. If you are creating + a debugger, please talk to me (vecna) and we'll figure out the right place to put it. + +3) The current plan is that all actual emulation cores go in this assembly. + At least one reason for this is that .NET will not inline calls across assemblies. + At this time, please do not separate emulation into multiple assemblies - this is negotiable, but + for now this is the plan. + +4) IEmulator exposes a DeterministicEmulation property. When enabled, a well-behaving core must + use strictly deterministic (TAS-safe, not having de-syncs) emulation, regardless of the performance cost. + When disabled, the core is free to take whatever shortcuts it deems reasonable for performance. + + Note that in many cases, frameskipping will not be possible in Deterministic mode. In that case the + client should still be free to request a frameskip, but the core will ignore this request and do a full + frame execution. + + Deterministic means exactly that, no more, no less; it's not a synonym for 'max emulation quality'. + +5) Classes should default sealed. Make unsealed only if the class is _designed for inheritance_. + +6) For GENERATED CPUs, DO NOT UPDATE THE GENERATED FILES DIRECTLY!!!!!!!!!!!!!! + Open the CpuCoreGenerator solution and make your changes there. Run the program to regenerate your cpus. + CpuCoreGenerator is a separate solution and it may not be obvious that it is there. + +--------------- +Emulation Notes +--------------- + +1) I'm not super happy with the IController interfaces. If someone has suggestions on how they could be + improved, I'm all for it. Although API changes would break all emulators, controls are typically pretty + simple to update. + +2) Various improvements to ISoundProvider, IVideoProvider, and IEmulator are under consideration. + Feedback is appreciated. + + ISoundProvider: + * A means of controlling overall volume for the SoundProvider would be beneficial + when it comes to mixing multiple ISoundProviders. + * Current implementations generate garbage on each frame, although the API does not _require_ + garbage to be created, it encourages it because you cannot provide a large buffer and specify + a smaller number of samples to fill. Also the BufferAsync generates garbage and probably the + SoundMixer. It's not really clear to me how much of a problem generating garbage is on PC. + + IVideoProvider: + * Some hints about different aspect ratios and non-square pixels could be useful. + * For some arcades, screen rotations could be important, but we could assign this to be + the responsibility of the emulator/video provider rather than the blitter. + * I suppose NTSC/PAL (ie: target fps) could be useful also. + + IEmulator: + * The LoadGame(IGame) is potentially problematic. Perhaps we simply remove this. Most likely + the constructor would then take an IGame as a requirement (or ICDImage or IRomSet or IFileSystem...) + * IEmulator should provide metadata about what Options it recognizes. + * Possibly, a lot of the metadata type functions should be removed from IEmulator and added to new + interface (such as IConsole, IArcade, IComputer, whatever) diff --git a/BizHawk.Emulation/Properties/AssemblyInfo.cs b/BizHawk.Emulation/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..4f418bc55b --- /dev/null +++ b/BizHawk.Emulation/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("BizHawk.Emulation")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("BizHawk.Emulation")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("38dc7bf9-d86c-4217-acd8-36dc09f8ba57")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BizHawk.Emulation/Sound/HuC6280PSG.cs b/BizHawk.Emulation/Sound/HuC6280PSG.cs new file mode 100644 index 0000000000..fbe19022f2 --- /dev/null +++ b/BizHawk.Emulation/Sound/HuC6280PSG.cs @@ -0,0 +1,341 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; + +namespace BizHawk.Emulation.Sound +{ + // Emulates PSG audio unit of a PC Engine / Turbografx-16 / SuperGrafx. + // It is embedded on the CPU and doesn't have its own part number. None the less, it is emulated separately from the 6280 CPU. + + public sealed class HuC6280PSG : ISoundProvider + { + public class PSGChannel + { + public ushort Frequency; + public byte Panning; + public byte Volume; + public bool Enabled; + public bool NoiseChannel; + public bool DDA; + public ushort NoiseFreq; + public short DDAValue; + public short[] Wave = new short[32]; + public float SampleOffset; + } + + public PSGChannel[] Channels = new PSGChannel[8]; + + public byte VoiceLatch; + private byte WaveTableWriteOffset; + + private Queue commands = new Queue(256); + private int frameStartTime, frameStopTime; + + private const int SampleRate = 44100; + private const int PsgBase = 3580000; + private static byte[] LogScale = { 0, 0, 10, 10, 13, 13, 16, 16, 20, 20, 26, 26, 32, 32, 40, 40, 51, 51, 64, 64, 81, 81, 102, 102, 128, 128, 161, 161, 203, 203, 255, 255 }; + + public byte MainVolumeLeft; + public byte MainVolumeRight; + + public HuC6280PSG() + { + for (int i=0; i<8; i++) + Channels[i] = new PSGChannel(); + } + + public void BeginFrame(int cycles) + { + while (commands.Count > 0) + { + var cmd = commands.Dequeue(); + WritePSGImmediate(cmd.Register, cmd.Value); + } + frameStartTime = cycles; + } + + public void EndFrame(int cycles) + { + frameStopTime = cycles; + } + + public void WritePSG(ushort register, byte value, int cycles) + { + commands.Enqueue(new QueuedCommand { Register = register, Value = value, Time = cycles-frameStartTime }); + } + + public void WritePSGImmediate(ushort register, byte value) + { + switch (register) + { + case 0x800: // Set Voice Latch + VoiceLatch = (byte) (value & 7); + break; + case 0x801: // Global Volume select; + MainVolumeLeft = (byte) ((value >> 4) & 0x0F); + MainVolumeRight = (byte) (value & 0x0F); + break; + case 0x802: // Frequency LSB + Channels[VoiceLatch].Frequency &= 0xFF00; + Channels[VoiceLatch].Frequency |= value; + break; + case 0x803: // Frequency MSB + Channels[VoiceLatch].Frequency &= 0x00FF; + Channels[VoiceLatch].Frequency |= (ushort)(value << 8); + Channels[VoiceLatch].Frequency &= 0x0FFF; + break; + case 0x804: // Voice Volume + Channels[VoiceLatch].Volume = (byte) (value & 0x1F); + Channels[VoiceLatch].Enabled = (value & 0x80) != 0; + Channels[VoiceLatch].DDA = (value & 0x40) != 0; + if (Channels[VoiceLatch].Enabled == false && Channels[VoiceLatch].DDA) + WaveTableWriteOffset = 0; + break; + case 0x805: // Panning + Channels[VoiceLatch].Panning = value; + break; + case 0x806: // Wave data + if (Channels[VoiceLatch].DDA == false) + { + Channels[VoiceLatch].Wave[WaveTableWriteOffset++] = (short) ((value*2047) - 32767); + WaveTableWriteOffset &= 31; + } else { + Channels[VoiceLatch].DDAValue = (short)((value * 2047) - 32767); + } + break; + case 0x807: // Noise + Channels[VoiceLatch].NoiseChannel = ((value & 0x80) != 0) && VoiceLatch >= 4; + if ((value & 0x1F) == 0x1F) + value &= 0xFE; + Channels[VoiceLatch].NoiseFreq = (ushort) (PsgBase/(64*(0x1F - (value & 0x1F)))); + break; + case 0x0808: // LFO + // TODO: implement LFO + break; + case 0x809: // LFO Control + if ((value & 0x80) == 0 && (value & 3) != 0) + { + Channels[1].Enabled = false; + } else + { + Channels[1].Enabled = true; + } + break; + } + } + + public void GetSamples(short[] samples) + { + int elapsedCycles = frameStopTime - frameStartTime; + int start = 0; + while (commands.Count > 0) + { + var cmd = commands.Dequeue(); + int pos = ((cmd.Time * samples.Length) / elapsedCycles) & ~1; + MixSamples(samples, start, pos - start); + start = pos; + WritePSGImmediate(cmd.Register, cmd.Value); + } + MixSamples(samples, start, samples.Length - start); + } + + private void MixSamples(short[] samples, int start, int len) + { + for (int i = 0; i < 6; i++) + MixChannel(samples, start, len, Channels[i]); + } + + private void MixChannel(short[] samples, int start, int len, PSGChannel channel) + { + if (channel.Enabled == false) return; + if (channel.DDA == false && (channel.Frequency == 0 || channel.Volume == 0)) return; + + int freq = PsgBase / (32 * (channel.DDA ? 1 : (int)channel.Frequency)); + int leftVol = channel.Panning >> 4; + int rightVol = channel.Panning & 15; + leftVol *= MainVolumeLeft; + rightVol *= MainVolumeRight; + leftVol /= 16; + rightVol /= 16; + + short[] wave = channel.Wave; + if (channel.NoiseChannel) + { + wave = Waves.NoiseWave; + freq = channel.NoiseFreq; + leftVol /= 2; + rightVol /= 2; + } + + float adjustedWaveLengthInSamples = SampleRate / (channel.NoiseChannel ? freq/512f : freq); + float moveThroughWaveRate = wave.Length / adjustedWaveLengthInSamples; + + int end = start + len; + for (int i=start; i32768f || left <-32768f) Console.WriteLine("HEY BAD THINGS"); + samples[i++] += (short) left; + samples[i++] += (short)((value * LogScale[channel.Volume] / 255f / 6f) * (rightVol / 15f)); + + channel.SampleOffset += moveThroughWaveRate; + channel.SampleOffset %= wave.Length; + } + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[PSG]"); + + writer.WriteLine("MainVolumeLeft {0:X2}", MainVolumeLeft); + writer.WriteLine("MainVolumeRight {0:X2}", MainVolumeRight); + writer.WriteLine("VoiceLatch {0}", VoiceLatch); + writer.WriteLine("WaveTableWriteOffset {0:X2}", WaveTableWriteOffset); + writer.WriteLine(); + + for (int i = 0; i<6; i++) + { + writer.WriteLine("[Channel{0}]",i+1); + writer.WriteLine("Frequency {0:X4}", Channels[i].Frequency); + writer.WriteLine("Panning {0:X2}", Channels[i].Panning); + writer.WriteLine("Volume {0:X2}", Channels[i].Volume); + writer.WriteLine("Enabled {0}", Channels[i].Enabled); + if (i.In(4,5)) + { + writer.WriteLine("NoiseChannel {0}", Channels[i].NoiseChannel); + writer.WriteLine("NoiseFreq {0:X4}", Channels[i].NoiseFreq); + } + writer.WriteLine("DDA {0}",Channels[i].DDA); + writer.WriteLine("DDAValue {0:X4}", Channels[i].DDAValue); + writer.WriteLine("SampleOffset {0}", Channels[i].SampleOffset); + writer.Write("Wave "); + Channels[i].Wave.SaveAsHex(writer); + writer.WriteLine("[/Channel{0}]\n",i+1); + } + + writer.WriteLine("[/PSG]\n"); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/PSG]") break; + if (args[0] == "MainVolumeLeft") + MainVolumeLeft = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "MainVolumeRight") + MainVolumeRight = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "VoiceLatch") + VoiceLatch = byte.Parse(args[1]); + else if (args[0] == "WaveTableWriteOffset") + WaveTableWriteOffset = byte.Parse(args[1]); + else if (args[0] == "[Channel1]") + LoadChannelStateText(reader, 0); + else if (args[0] == "[Channel2]") + LoadChannelStateText(reader, 1); + else if (args[0] == "[Channel3]") + LoadChannelStateText(reader, 2); + else if (args[0] == "[Channel4]") + LoadChannelStateText(reader, 3); + else if (args[0] == "[Channel5]") + LoadChannelStateText(reader, 4); + else if (args[0] == "[Channel6]") + LoadChannelStateText(reader, 5); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + private void LoadChannelStateText(TextReader reader, int channel) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/Channel"+(channel+1)+"]") break; + if (args[0] == "Frequency") + Channels[channel].Frequency = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Panning") + Channels[channel].Panning = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Volume") + Channels[channel].Volume = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Enabled") + Channels[channel].Enabled = bool.Parse(args[1]); + else if (args[0] == "NoiseChannel") + Channels[channel].NoiseChannel = bool.Parse(args[1]); + else if (args[0] == "NoiseFreq") + Channels[channel].NoiseFreq = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "DDA") + Channels[channel].DDA = bool.Parse(args[1]); + else if (args[0] == "DDAValue") + Channels[channel].DDAValue = short.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "SampleOffset") + Channels[channel].SampleOffset = float.Parse(args[1]); + else if (args[0] == "Wave") + Channels[channel].Wave.ReadFromHex(args[1]); + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(MainVolumeLeft); + writer.Write(MainVolumeRight); + writer.Write(VoiceLatch); + writer.Write(WaveTableWriteOffset); + + for (int i = 0; i < 6; i++) + { + writer.Write(Channels[i].Frequency); + writer.Write(Channels[i].Panning); + writer.Write(Channels[i].Volume); + writer.Write(Channels[i].Enabled); + writer.Write(Channels[i].NoiseChannel); + writer.Write(Channels[i].NoiseFreq); + writer.Write(Channels[i].DDA); + writer.Write(Channels[i].DDAValue); + writer.Write(Channels[i].SampleOffset); + for (int j = 0; j < 32; j++) + writer.Write(Channels[i].Wave[j]); + } + } + + public void LoadStateBinary(BinaryReader reader) + { + MainVolumeLeft = reader.ReadByte(); + MainVolumeRight = reader.ReadByte(); + VoiceLatch = reader.ReadByte(); + WaveTableWriteOffset = reader.ReadByte(); + + for (int i=0; i<6; i++) + { + Channels[i].Frequency = reader.ReadUInt16(); + Channels[i].Panning = reader.ReadByte(); + Channels[i].Volume = reader.ReadByte(); + Channels[i].Enabled = reader.ReadBoolean(); + Channels[i].NoiseChannel = reader.ReadBoolean(); + Channels[i].NoiseFreq = reader.ReadUInt16(); + Channels[i].DDA = reader.ReadBoolean(); + Channels[i].DDAValue = reader.ReadInt16(); + Channels[i].SampleOffset = reader.ReadSingle(); + for (int j = 0; j < 32; j++) + Channels[i].Wave[j] = reader.ReadInt16(); + } + } + + class QueuedCommand + { + public ushort Register; + public byte Value; + public int Time; + } + } +} diff --git a/BizHawk.Emulation/Sound/SN76489.cs b/BizHawk.Emulation/Sound/SN76489.cs new file mode 100644 index 0000000000..bb87d3664e --- /dev/null +++ b/BizHawk.Emulation/Sound/SN76489.cs @@ -0,0 +1,440 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; + +// Emulates a Texas Instruments SN76489. This is found in: +// + Sega 8-bit consoles (SMS/MarkIII/Game Gear/SG-1000/SC-3000/etc) +// + In the Genesis/MegaDrive as a 2ndary sound source +// + Some arcade hardware + +// The Game Gear version is enhanced to support stereo output. +// TODO at this time, I dont know if some arcades need a different PsgBase value or if it is constant. +// TODO the noise channel emulation is not perfect. +// TODO the freq->note translation should be moved to a separate utility class. + +namespace BizHawk.Emulation.Sound +{ + public sealed class SN76489 : ISoundProvider + { + public sealed class Channel + { + public ushort Frequency; + public byte Volume; + public short[] Wave; + public bool Noise; + public byte NoiseType; + public float WaveOffset; + public bool Left = true; + public bool Right = true; + + private const int SampleRate = 44100; + private static byte[] LogScale = { 0, 10, 13, 16, 20, 26, 32, 40, 51, 64, 81, 102, 128, 161, 203, 255 }; + + public void Mix(short[] samples, int start, int len) + { + if (Volume == 0) return; + + float adjustedWaveLengthInSamples = SampleRate / (Noise ? (Frequency / 512f) : Frequency); + float moveThroughWaveRate = Wave.Length / adjustedWaveLengthInSamples; + + int end = start + len; + for (int i = start; i < end; ) + { + short value = Wave[(int)WaveOffset]; + + samples[i++] += (short)(Left ? (value / 4 * LogScale[Volume] / 0x1FF) : 0); + samples[i++] += (short)(Right ? (value / 4 * LogScale[Volume] / 0x1FF) : 0); + WaveOffset += moveThroughWaveRate; + if (WaveOffset >= Wave.Length) + WaveOffset %= Wave.Length; + } + } + } + + public Channel[] Channels = new Channel[4]; + public byte PsgLatch; + + private Queue commands = new Queue(256); + private int frameStartTime, frameStopTime; + + private const int PsgBase = 111861; + + public SN76489() + { + for (int i=0; i<4; i++) + { + Channels[i] = new Channel(); + switch (i) + { + case 0: + case 1: + case 2: + Channels[i].Wave = Waves.ImperfectSquareWave; + break; + case 3: + Channels[i].Wave = Waves.NoiseWave; + Channels[i].Noise = true; + break; + } + } + } + + public void Reset() + { + PsgLatch = 0; + foreach (var channel in Channels) + { + channel.Frequency = 0; + channel.Volume = 0; + channel.NoiseType = 0; + channel.WaveOffset = 0f; + } + } + + public void BeginFrame(int cycles) + { + while (commands.Count > 0) + { + var cmd = commands.Dequeue(); + WritePsgDataImmediate(cmd.Value); + } + frameStartTime = cycles; + } + + public void EndFrame(int cycles) + { + frameStopTime = cycles; + } + + public void WritePsgData(byte value, int cycles) + { + commands.Enqueue(new QueuedCommand {Value = value, Time = cycles-frameStartTime}); + } + + public void WritePsgDataImmediate(byte value) + { + switch (value & 0xF0) + { + case 0x80: + case 0xA0: + case 0xC0: + PsgLatch = value; + break; + case 0xE0: + PsgLatch = value; + Channels[3].NoiseType = (byte) (value & 0x03); + switch (Channels[3].NoiseType) + { + case 0: Channels[3].Frequency = PsgBase/16; break; + case 1: Channels[3].Frequency = PsgBase/32; break; + case 2: Channels[3].Frequency = PsgBase/64; break; + case 3: Channels[3].Frequency = Channels[2].Frequency; break; + } + break; + case 0x90: + Channels[0].Volume = (byte)(~value & 15); + PsgLatch = value; + break; + case 0xB0: + Channels[1].Volume = (byte)(~value & 15); + PsgLatch = value; + break; + case 0xD0: + Channels[2].Volume = (byte)(~value & 15); + PsgLatch = value; + break; + case 0xF0: + Channels[3].Volume = (byte)(~value & 15); + PsgLatch = value; + break; + default: + byte channel = (byte) ((PsgLatch & 0x60) >> 5); + if ((PsgLatch & 16) == 0) // Tone latched + { + int f = PsgBase/(((value & 0x03F)*16) + (PsgLatch & 0x0F) + 1); + if (f > 15000) + f = 0; // upper bound of playable frequency + Channels[channel].Frequency = (ushort) f; + if (Channels[3].NoiseType == 3 && channel == 2) + Channels[3].Frequency = (ushort) f; + } else { // volume latched + Channels[channel].Volume = (byte)(~value & 15); + } + break; + } + } + + public byte StereoPanning + { + get + { + byte value = 0; + if (Channels[0].Left) value |= 0x10; + if (Channels[0].Right) value |= 0x01; + if (Channels[1].Left) value |= 0x20; + if (Channels[1].Right) value |= 0x02; + if (Channels[2].Left) value |= 0x40; + if (Channels[2].Right) value |= 0x04; + if (Channels[3].Left) value |= 0x80; + if (Channels[3].Right) value |= 0x08; + return value; + } + set + { + Channels[0].Left = (value & 0x10) != 0; + Channels[0].Right = (value & 0x01) != 0; + Channels[1].Left = (value & 0x20) != 0; + Channels[1].Right = (value & 0x02) != 0; + Channels[2].Left = (value & 0x40) != 0; + Channels[2].Right = (value & 0x04) != 0; + Channels[3].Left = (value & 0x80) != 0; + Channels[3].Right = (value & 0x08) != 0; + } + } + + public void SaveStateText(TextWriter writer) + { + writer.WriteLine("[PSG]"); + writer.WriteLine("Volume0 {0:X2}", Channels[0].Volume); + writer.WriteLine("Volume1 {0:X2}", Channels[1].Volume); + writer.WriteLine("Volume2 {0:X2}", Channels[2].Volume); + writer.WriteLine("Volume3 {0:X2}", Channels[3].Volume); + writer.WriteLine("Freq0 {0:X4}", Channels[0].Frequency); + writer.WriteLine("Freq1 {0:X4}", Channels[1].Frequency); + writer.WriteLine("Freq2 {0:X4}", Channels[2].Frequency); + writer.WriteLine("Freq3 {0:X4}", Channels[3].Frequency); + writer.WriteLine("NoiseType {0:X}", Channels[3].NoiseType); + writer.WriteLine("PsgLatch {0:X2}", PsgLatch); + writer.WriteLine("Panning {0:X2}", StereoPanning); + writer.WriteLine("[/PSG]"); + writer.WriteLine(); + } + + public void LoadStateText(TextReader reader) + { + while (true) + { + string[] args = reader.ReadLine().Split(' '); + if (args[0].Trim() == "") continue; + if (args[0] == "[/PSG]") break; + if (args[0] == "Volume0") + Channels[0].Volume = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Volume1") + Channels[1].Volume = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Volume2") + Channels[2].Volume = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Volume3") + Channels[3].Volume = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Freq0") + Channels[0].Frequency = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Freq1") + Channels[1].Frequency = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Freq2") + Channels[2].Frequency = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Freq3") + Channels[3].Frequency = ushort.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "NoiseType") + Channels[3].NoiseType = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "PsgLatch") + PsgLatch = byte.Parse(args[1], NumberStyles.HexNumber); + else if (args[0] == "Panning") + StereoPanning = byte.Parse(args[1], NumberStyles.HexNumber); + + else + Console.WriteLine("Skipping unrecognized identifier " + args[0]); + } + } + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(Channels[0].Volume); + writer.Write(Channels[1].Volume); + writer.Write(Channels[2].Volume); + writer.Write(Channels[3].Volume); + writer.Write(Channels[0].Frequency); + writer.Write(Channels[1].Frequency); + writer.Write(Channels[2].Frequency); + writer.Write(Channels[3].Frequency); + writer.Write(Channels[3].NoiseType); + writer.Write(PsgLatch); + writer.Write(StereoPanning); + } + + public void LoadStateBinary(BinaryReader reader) + { + Channels[0].Volume = reader.ReadByte(); + Channels[1].Volume = reader.ReadByte(); + Channels[2].Volume = reader.ReadByte(); + Channels[3].Volume = reader.ReadByte(); + Channels[0].Frequency = reader.ReadUInt16(); + Channels[1].Frequency = reader.ReadUInt16(); + Channels[2].Frequency = reader.ReadUInt16(); + Channels[3].Frequency = reader.ReadUInt16(); + Channels[3].NoiseType = reader.ReadByte(); + PsgLatch = reader.ReadByte(); + StereoPanning = reader.ReadByte(); + } + + #region Frequency -> Note Conversion (for interested humans) + + public static string GetNote(int freq) + { + if (freq < 26) return "LOW"; + if (freq > 4435) return "HIGH"; + + for (int i = 0; i < frequencies.Length - 1; i++) + { + if (freq >= frequencies[i + 1]) continue; + int nextNoteDistance = frequencies[i + 1] - frequencies[i]; + int distance = freq - frequencies[i]; + if (distance < nextNoteDistance / 2) + { + // note identified + return notes[i]; + } + } + return "?"; + } + + // For the curious, A4 = 440hz. Every octave is a doubling, so A5=880, A3=220 + // Each next step is a factor of the 12-root of 2. So to go up a step you multiply by 1.0594630943592952645618252949463 + // Next step from A4 is A#4. A#4 = (440.00 * 1.05946...) = 466.163... + // Note that because frequencies must be integers, SMS games will be slightly out of pitch to a normally tuned instrument, especially at the low end. + + private static readonly int[] frequencies = + { + 27, // A0 + 29, // A#0 + 31, // B0 + 33, // C1 + 35, // C#1 + 37, // D1 + 39, // D#1 + 41, // E1 + 44, // F1 + 46, // F#1 + 49, // G1 + 52, // G#1 + 55, // A1 + 58, // A#1 + 62, // B1 + 65, // C2 + 69, // C#2 + 73, // D2 + 78, // D#2 + 82, // E2 + 87, // F2 + 92, // F#2 + 98, // G2 + 104, // G#2 + 110, // A2 + 117, // A#2 + 123, // B2 + 131, // C3 + 139, // C#3 + 147, // D3 + 156, // D#3 + 165, // E3 + 175, // F3 + 185, // F#3 + 196, // G3 + 208, // G#3 + 220, // A3 + 233, // A#3 + 247, // B3 + 262, // C4 + 277, // C#4 + 294, // D4 + 311, // D#4 + 330, // E4 + 349, // F4 + 370, // F#4 + 392, // G4 + 415, // G#4 + 440, // A4 + 466, // A#4 + 494, // B4 + 523, // C5 + 554, // C#5 + 587, // D5 + 622, // D#5 + 659, // E5 + 698, // F5 + 740, // F#5 + 784, // G5 + 831, // G#5 + 880, // A5 + 932, // A#5 + 988, // B5 + 1046, // C6 + 1109, // C#6 + 1175, // D6 + 1245, // D#6 + 1319, // E6 + 1397, // F6 + 1480, // F#6 + 1568, // G6 + 1661, // G#6 + 1760, // A6 + 1865, // A#6 + 1976, // B6 + 2093, // C7 + 2217, // C#7 + 2349, // D7 + 2489, // D#7 + 2637, // E7 + 2794, // F7 + 2960, // F#7 + 3136, // G7 + 3322, // G#7 + 3520, // A7 + 3729, // A#7 + 3951, // B7 + 4186, // C8 + 4435 // C#8 + }; + + private static readonly string[] notes = + { + "A0","A#0","B0", + "C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1", + "C2","C#2","D2","D#2","E2","F2","F#2","G2","G#2","A2","A#2","B2", + "C3","C#3","D3","D#3","E3","F3","F#3","G3","G#3","A3","A#3","B3", + "C4","C#4","D4","D#4","E4","F4","F#4","G4","G#4","A4","A#4","B4", + "C5","C#5","D5","D#5","E5","F5","F#5","G5","G#5","A5","A#5","B5", + "C6","C#6","D6","D#6","E6","F6","F#6","G6","G#6","A6","A#6","B6", + "C7","C#7","D7","D#7","E7","F7","F#7","G7","G#7","A7","A#7","B7", + "C8","HIGH" + }; + + #endregion + + public void GetSamples(short[] samples) + { + int elapsedCycles = frameStopTime - frameStartTime; + int start = 0; + while (commands.Count > 0) + { + var cmd = commands.Dequeue(); + int pos = ((cmd.Time*samples.Length)/elapsedCycles) & ~1; + GetSamplesImmediate(samples, start, pos-start); + start = pos; + WritePsgDataImmediate(cmd.Value); + } + GetSamplesImmediate(samples, start, samples.Length - start); + } + + public void GetSamplesImmediate(short[] samples, int start, int len) + { + for (int i = 0; i < 4; i++) + Channels[i].Mix(samples, start, len); + } + + class QueuedCommand + { + public byte Value; + public int Time; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Sound/Utilities/BufferedAsync.cs b/BizHawk.Emulation/Sound/Utilities/BufferedAsync.cs new file mode 100644 index 0000000000..d3d28442f2 --- /dev/null +++ b/BizHawk.Emulation/Sound/Utilities/BufferedAsync.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; + +namespace BizHawk.Emulation.Sound +{ + // Generates SEMI-synchronous sound, or "buffered asynchronous" sound. + + // This class will try as hard as it can to request the correct number of samples on each frame and then + // send them out to the sound card as it needs them. + + // However, it has minimum/maximum buffer targets and will request smaller or larger frames if it has to. + // The ultimate goal of this strategy is to make MOST frames 100% correct, and if errors must occur, + // concentrate it on a single frame, rather than distribute small errors across most frames, as + // distributing error to most frames tends to result in persistently distorted audio, especially when + // sample playback is involved. + + public sealed class BufferedAsync : ISoundProvider + { + public ISoundProvider BaseSoundProvider; + + private Queue buffer = new Queue(4096); + + private const int SamplesInOneFrame = 1470; + private const int TargetExtraSamples = 882; + private const int MaxExcessSamples = 4096; + + public void GetSamples(short[] samples) + { + int samplesToGenerate = SamplesInOneFrame; + if (buffer.Count > samples.Length + MaxExcessSamples) + samplesToGenerate = 0; + if (buffer.Count - samples.Length < TargetExtraSamples) + samplesToGenerate += SamplesInOneFrame; + if (samplesToGenerate + buffer.Count < samples.Length) + samplesToGenerate = samples.Length - buffer.Count; + + var mySamples = new short[samplesToGenerate]; + + BaseSoundProvider.GetSamples(mySamples); + + for (int i = 0; i < mySamples.Length; i++) + buffer.Enqueue(mySamples[i]); + + for (int i = 0; i < samples.Length; i++) + samples[i] = buffer.Dequeue(); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Sound/Utilities/Metaspu.cs b/BizHawk.Emulation/Sound/Utilities/Metaspu.cs new file mode 100644 index 0000000000..180a0d1f1e --- /dev/null +++ b/BizHawk.Emulation/Sound/Utilities/Metaspu.cs @@ -0,0 +1,486 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.Emulation.Sound +{ + public class MetaspuSoundProvider : ISoundProvider + { + public ISynchronizingAudioBuffer buffer = Metaspu.metaspu_construct(ESynchMethod.ESynchMethod_Z); + public MetaspuSoundProvider() + { + } + + public void GetSamples(short[] samples) + { + buffer.output_samples(samples, samples.Length / 2); + } + } + + public interface ISynchronizingAudioBuffer + { + void enqueue_samples(short[] buf, int samples_provided); + + //returns the number of samples actually supplied, which may not match the number requested + int output_samples(short[] buf, int samples_requested); + }; + + public enum ESynchMethod + { + ESynchMethod_N, //nitsuja's + ESynchMethod_Z, //zero's + //ESynchMethod_P, //PCSX2 spu2-x //ohno! not available yet in c# + }; + + public static class Metaspu + { + public static ISynchronizingAudioBuffer metaspu_construct(ESynchMethod method) + { + switch (method) + { + case ESynchMethod.ESynchMethod_Z: + return new ZeromusSynchronizer(); + case ESynchMethod.ESynchMethod_N: + return new NitsujaSynchronizer(); + default: + return new NitsujaSynchronizer(); + } + } + } + + + class ZeromusSynchronizer : ISynchronizingAudioBuffer + { + public ZeromusSynchronizer() + { + //#ifdef NDEBUG + adjustobuf = new Adjustobuf(200, 1000); + //#else + //adjustobuf = new Adjustobuf(22000, 44000); + //#endif + + } + + //adjustobuf(200,1000) + bool mixqueue_go = false; + + public void enqueue_samples(short[] buf, int samples_provided) + { + int ctr = 0; + for (int i = 0; i < samples_provided; i++) + { + short left = buf[ctr++]; + short right = buf[ctr++]; + adjustobuf.enqueue(left, right); + } + } + + //returns the number of samples actually supplied, which may not match the number requested + public int output_samples(short[] buf, int samples_requested) + { + int ctr=0; + int done = 0; + if (!mixqueue_go) + { + if (adjustobuf.size > 200) + mixqueue_go = true; + } + else + { + for (int i = 0; i < samples_requested; i++) + { + if (adjustobuf.size == 0) + { + mixqueue_go = false; + break; + } + done++; + short left, right; + adjustobuf.dequeue(out left, out right); + buf[ctr++] = left; + buf[ctr++] = right; + } + } + + return done; + } + + Adjustobuf adjustobuf; + class Adjustobuf + { + public Adjustobuf(int _minLatency, int _maxLatency) + { + minLatency = _minLatency; + maxLatency = _maxLatency; + rollingTotalSize = 0; + targetLatency = (maxLatency + minLatency)/2; + rate = 1.0f; + cursor = 0.0f; + curr[0] = curr[1] = 0; + kAverageSize = 80000; + } + + float rate, cursor; + int minLatency, targetLatency, maxLatency; + Queue buffer = new Queue(); + Queue statsHistory = new Queue(); + public int size = 0; + short[] curr = new short[2]; + + public void enqueue(short left, short right) + { + buffer.Enqueue(left); + buffer.Enqueue(right); + size++; + } + + long rollingTotalSize; + + uint kAverageSize; + + void addStatistic() + { + statsHistory.Enqueue(size); + rollingTotalSize += size; + if (statsHistory.Count > kAverageSize) + { + rollingTotalSize -= statsHistory.Peek(); + statsHistory.Dequeue(); + + float averageSize = (float)(rollingTotalSize / kAverageSize); + //static int ctr=0; ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate); + { + float targetRate; + if(averageSize < targetLatency) + { + targetRate = 1.0f - (targetLatency-averageSize)/kAverageSize; + } + else if(averageSize > targetLatency) { + targetRate = 1.0f + (averageSize-targetLatency)/kAverageSize; + } else targetRate = 1.0f; + + //rate = moveValueTowards(rate,targetRate,0.001f); + rate = targetRate; + } + + } + + + } + + public void dequeue(out short left, out short right) + { + left = right = 0; + addStatistic(); + if(size==0) { return; } + cursor += rate; + while(cursor>1.0f) { + cursor -= 1.0f; + if(size>0) { + curr[0] = buffer.Dequeue(); + curr[1] = buffer.Dequeue(); + size--; + } + } + left = curr[0]; + right = curr[1]; + } + } + } + + class NitsujaSynchronizer : ISynchronizingAudioBuffer + { + struct ssamp + { + public short l, r; + public ssamp(short ll, short rr) { l = ll; r = rr; } + }; + + List sampleQueue = new List(); + + // returns values going between 0 and y-1 in a saw wave pattern, based on x + static int pingpong(int x, int y) + { + x %= 2*y; + if(x >= y) + x = 2*y - x - 1; + return x; + + // in case we want to switch to odd buffer sizes for more sharpness + //x %= 2*(y-1); + //if(x >= y) + // x = 2*(y-1) - x; + //return x; + } + + static ssamp crossfade (ssamp lhs, ssamp rhs, int cur, int start, int end) + { + if(cur <= start) + return lhs; + if(cur >= end) + return rhs; + + // in case we want sine wave interpolation instead of linear here + //float ang = 3.14159f * (float)(cur - start) / (float)(end - start); + //cur = start + (int)((1-cosf(ang))*0.5f * (end - start)); + + int inNum = cur - start; + int outNum = end - cur; + int denom = end - start; + + int lrv = ((int)lhs.l * outNum + (int)rhs.l * inNum) / denom; + int rrv = ((int)lhs.r * outNum + (int)rhs.r * inNum) / denom; + + return new ssamp((short)lrv,(short)rrv); + } + + static void emit_sample(short[] outbuf, ref int cursor, ssamp sample) + { + outbuf[cursor++] = sample.l; + outbuf[cursor++] = sample.r; + } + + static void emit_samples(short[] outbuf, ref int outcursor, ssamp[] samplebuf, int incursor, int samples) + { + for(int i=0;i 0x200 && audiosize > 0) // is there any work to do? + { + // are we going at normal speed? + // or more precisely, are the input and output queues/buffers of similar size? + if(queued > 900 || audiosize > queued * 2) + { + // not normal speed. we have to resample it somehow in this case. + if(audiosize <= queued) + { + // fast forward speed + // this is the easy case, just crossfade it and it sounds ok + for(int i = 0; i < audiosize; i++) + { + int j = i + queued - audiosize; + ssamp outsamp = crossfade(sampleQueue[i],sampleQueue[j], i,0,audiosize); + emit_sample(buf,ref bufcursor,outsamp); + } + } + else + { + // slow motion speed + // here we take a very different approach, + // instead of crossfading it, we select a single sample from the queue + // and make sure that the index we use to select a sample is constantly moving + // and that it starts at the first sample in the queue and ends on the last one. + // + // hopefully the index doesn't move discontinuously or we'll get slight crackling + // (there might still be a minor bug here that causes this occasionally) + // + // here's a diagram of how the index we sample from moves: + // + // queued (this axis represents the index we sample from. the top means the end of the queue) + // ^ + // | --> audiosize (this axis represents the output index we write to, right meaning forward in output time/position) + // | A C C end + // A A B C C C + // A A A B C C C + // A A A B C C + // A A C + // start + // + // yes, this means we are spending some stretches of time playing the sound backwards, + // but the stretches are short enough that this doesn't sound weird. + // this lets us avoid most crackling problems due to the endpoints matching up. + + // first calculate a shorter-than-full window + // that has minimal slope at the endpoints + // (to further reduce crackling, especially in sine waves) + int beststart = 0, extraAtEnd = 0; + { + int bestend = queued; + const int worstdiff = 99999999; + int beststartdiff = worstdiff; + int bestenddiff = worstdiff; + for(int i = 0; i < 128; i+=2) + { + int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r); + if(diff < beststartdiff) + { + beststartdiff = diff; + beststart = i; + } + } + for(int i = queued-3; i > queued-3-128; i-=2) + { + int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r); + if(diff < bestenddiff) + { + bestenddiff = diff; + bestend = i+1; + } + } + + extraAtEnd = queued - bestend; + queued = bestend - beststart; + + int oksize = queued; + while(oksize + queued*2 + beststart + extraAtEnd <= samples_requested) + oksize += queued*2; + audiosize = oksize; + + for(int x = 0; x < beststart; x++) + { + emit_sample(buf,ref bufcursor,sampleQueue[x]); + } + //sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart); + sampleQueue.RemoveRange(0, beststart); + //zero 08-nov-2010: did i do this right? + } + + + int midpointX = audiosize >> 1; + int midpointY = queued >> 1; + + // all we need to do here is calculate the X position of the leftmost "B" in the above diagram. + // TODO: we should calculate it with a simple equation like + // midpointXOffset = min(something,somethingElse); + // but it's a little difficult to work it out exactly + // so here's a stupid search for the value for now: + + int prevA = 999999; + int midpointXOffset = queued/2; + while(true) + { + int a = abs(pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset; + if(((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999) + { + if(((a + prevA)&1)!=0) // there's some sort of off-by-one problem with this search since we're moving diagonally... + midpointXOffset++; // but this fixes it most of the time... + break; // found it + } + prevA = a; + midpointXOffset--; + if(midpointXOffset < 0) + { + midpointXOffset = 0; + break; // failed to find it. the two sides probably meet exactly in the center. + } + } + + int leftMidpointX = midpointX - midpointXOffset; + int rightMidpointX = midpointX + midpointXOffset; + int leftMidpointY = pingpong(leftMidpointX, queued); + int rightMidpointY = (queued-1) - pingpong((int)audiosize-1 - rightMidpointX + queued*2, queued); + + // output the left almost-half of the sound (section "A") + for(int x = 0; x < leftMidpointX; x++) + { + int i = pingpong(x, queued); + emit_sample(buf,ref bufcursor,sampleQueue[i]); + } + + // output the middle stretch (section "B") + int y = leftMidpointY; + int dyMidLeft = (leftMidpointY < midpointY) ? 1 : -1; + int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1; + for(int x = leftMidpointX; x < midpointX; x++, y+=dyMidLeft) + emit_sample(buf,ref bufcursor,sampleQueue[y]); + for(int x = midpointX; x < rightMidpointX; x++, y+=dyMidRight) + emit_sample(buf, ref bufcursor, sampleQueue[y]); + + // output the end of the queued sound (section "C") + for(int x = rightMidpointX; x < audiosize; x++) + { + int i = (queued-1) - pingpong((int)audiosize-1 - x + queued*2, queued); + emit_sample(buf,ref bufcursor,sampleQueue[i]); + } + + for(int x = 0; x < extraAtEnd; x++) + { + int i = queued + x; + emit_sample(buf,ref bufcursor,sampleQueue[i]); + } + queued += extraAtEnd; + audiosize += beststart + extraAtEnd; + } //end else + + //sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); + sampleQueue.RemoveRange(0, queued); + //zero 08-nov-2010: did i do this right? + return audiosize; + } + else + { + // normal speed + // just output the samples straightforwardly. + // + // at almost-full speeds (like 50/60 FPS) + // what will happen is that we rapidly fluctuate between entering this branch + // and entering the "slow motion speed" branch above. + // but that's ok! because all of these branches sound similar enough that we can get away with it. + // so the two cases actually complement each other. + + if(audiosize >= queued) + { + emit_samples(buf,ref bufcursor, sampleQueue.ToArray(),0,queued); + //sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); + sampleQueue.RemoveRange(0, queued); + //zero 08-nov-2010: did i do this right? + return queued; + } + else + { + emit_samples(buf,ref bufcursor, sampleQueue.ToArray(),0,audiosize); + //sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize); + sampleQueue.RemoveRange(0, audiosize); + //zero 08-nov-2010: did i do this right? + return audiosize; + } + + } //end normal speed + + } //end if there is any work to do + else + { + return 0; + } + + } //output_samples + + +}; //NitsujaSynchronizer + +} \ No newline at end of file diff --git a/BizHawk.Emulation/Sound/Utilities/SoundMixer.cs b/BizHawk.Emulation/Sound/Utilities/SoundMixer.cs new file mode 100644 index 0000000000..46cfaaeb1f --- /dev/null +++ b/BizHawk.Emulation/Sound/Utilities/SoundMixer.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using BizHawk.Emulation.Sound; + +namespace BizHawk.Emulation.Sound +{ + // This is a straightforward class to mix/chain multiple ISoundProvider sources. + // TODO: Fine-tuned volume control would be a good thing. + + public sealed class SoundMixer : ISoundProvider + { + private List SoundProviders; + + public SoundMixer(params ISoundProvider[] soundProviders) + { + SoundProviders = new List(soundProviders); + } + + public void AddSource(ISoundProvider source) + { + SoundProviders.Add(source); + } + + public void DisableSource(ISoundProvider source) + { + SoundProviders.Remove(source); + } + + public void GetSamples(short[] samples) + { + foreach (var soundSource in SoundProviders) + soundSource.GetSamples(samples); + } + } +} diff --git a/BizHawk.Emulation/Sound/Utilities/Waves.cs b/BizHawk.Emulation/Sound/Utilities/Waves.cs new file mode 100644 index 0000000000..66c96687ed --- /dev/null +++ b/BizHawk.Emulation/Sound/Utilities/Waves.cs @@ -0,0 +1,77 @@ +namespace BizHawk.Emulation.Sound +{ + public static class Waves + { + public static readonly short[] SquareWave = + { + -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767 + }; + + public static readonly short[] ImperfectSquareWave = + { + -32768,-30145,-27852,-26213,-24902,-23592,-22282,-20971,-19988,-19005,-18350,-17694,-17366,-17039,-16711,-16711, + 32767, 30145, 27852, 26213, 24902, 23592, 22282, 20971, 19988, 19005, 18350, 17694, 17366, 17039, 16711, 16711 + }; + + public static readonly short[] NoiseWave = + { + 32767, 32767, 32767,-32768,-32768,-32768, 32767,-32768, 32767, 32767, 32767, 32767,-32768,-32768,-32768,-32768, 32767, 32767,-32768,-32768, 32767, 32767,-32768,-32768, 32767, 32767,-32768,-32768, 32767, 32767,-32768,-32768, 32767,-32768,-32768, + 32767, 32767,-32768,-32768, 32767, 32767,-32768,-32768, 32767, 32767,-32768, 32767, 32767,-32768, 32767, 32767, 32767,-32768,-32768, 32767, 32767,-32768,-32768, 32767,-32768,-32768,-32768, 32767,-32768,-32768,-32768,-32768, 32767,-32768, 32767, + 32767, 32767,-32768,-32768,-32768,-32768,-32768, 32767,-32768,-32768, 32767,-32768, 32767,-32768, 32767,-32768, 32767, 32767,-32768,-32768,-32768, 32767,-32768, 32767,-32768,-32768, 32767, 32767,-32768, 32767,-32768,-32768,-32768, 32767,-32768, + 32767, 32767, 32767, 32767, 32767, 32767, 32767,-32768, 32767, 32767,-32768, 32767, 32767, 32767,-32768,-32768,-32768, 32767,-32768,-32768, 32767,-32768, 32767,-32768, 32767,-32768,-32768,-32768, 32767,-32768, 32767,-32768,-32768, 32767,-32768, + -32768, 32767, 32767, 32767,-32768, 32767,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 32767,-32768, 32767,-32768, 32767,-32768,-32768, 32767, 32767, 32767,-32768, 32767, 32767,-32768,-32768, 32767, 32767, 32767,-32768, 32767, 32767, 32767, + -32768,-32768, 32767, 32767, 32767,-32768,-32768,-32768,-32768,-32768, 32767, 32767,-32768,-32768,-32768, 32767,-32768,-32768, 32767, 32767, 32767,-32768,-32768,-32768,-32768,-32768, 32767, 32767, 32767,-32768,-32768,-32768, 32767,-32768, 32767, + 32767,-32768, 32767, 32767, 32767, 32767, 32767, 32767, 32767,-32768,-32768, 32767, 32767,-32768, 32767,-32768, 32767, 32767,-32768, 32767,-32768,-32768, 32767, 32767, 32767,-32768, 32767,-32768,-32768, 32767, 32767, 32767, 32767, 32767,-32768, + 32767, 32767,-32768, 32767,-32768,-32768,-32768, 32767,-32768, 32767, 32767, 32767, 32767,-32768, 32767,-32768, 32767, 32767, 32767,-32768, 32767, 32767, 32767,-32768,-32768, 32767,-32768,-32768, 32767, 32767, 32767,-32768, 32767, 32767, 32767, + -32768,-32768,-32768, 32767, 32767, 32767,-32768, 32767,-32768,-32768, 32767, 32767,-32768,-32768, 32767,-32768,-32768,-32768, 32767, 32767,-32768,-32768,-32768, 32767, 32767, 32767, 32767,-32768, 32767, 32767, 32767, 32767, 32767,-32768, 32767, + 32767,-32768,-32768, 32767,-32768,-32768,-32768,-32768, 32767,-32768, 32767, 32767,-32768, 32767, 32767,-32768, 32767,-32768,-32768,-32768,-32768, 32767,-32768, 32767,-32768, 32767, 32767,-32768,-32768, 32767, 32767, 32767, 32767,-32768, 32767, + -32768, 32767, 32767, 32767,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 32767, 32767, 32767, 32767,-32768, 32767, 32767,-32768,-32768, 32767, 32767, 32767,-32768, 32767, 32767, 32767,-32768,-32768,-32768, 32767, 32767,-32768, + -32768,-32768,-32768,-32768, 32767, 32767,-32768,-32768, 32767,-32768,-32768, 32767, 32767,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 32767,-32768, 32767, 32767, 32767,-32768,-32768,-32768,-32768,-32768,-32768, 32767, 32767,-32768,-32768, + 32767,-32768, 32767,-32768, 32767, 32767,-32768,-32768, 32767,-32768,-32768,-32768, 32767,-32768, 32767,-32768, 32767, 32767,-32768,-32768,-32768,-32768, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,-32768,-32768,-32768, 32767, 32767, + -32768, 32767,-32768, 32767, 32767,-32768,-32768, 32767,-32768,-32768,-32768,-32768, 32767,-32768,-32768, 32767,-32768,-32768,-32768,-32768, 32767,-32768,-32768,-32768,-32768, 32767, 32767,-32768, 32767, 32767,-32768,-32768,-32768, 32767, 32767, + 32767,-32768,-32768, 32767,-32768,-32768,-32768,-32768, 32767,-32768, 32767,-32768,-32768, 32767, 32767, 32767,-32768,-32768,-32768,-32768,-32768, 32767 + }; + + public static readonly short[] TriangleWave = + { + -32768,-32513,-32257,-32001,-31745,-31489,-31233,-30977,-30721,-30465,-30209,-29953,-29697,-29441,-29185,-28929,-28673,-28417,-28161,-27905,-27649,-27393,-27137,-26881,-26625,-26369,-26113,-25857,-25601,-25345,-25089,-24833,-24577,-24321,-24065, + -23809,-23553,-23297,-23041,-22785,-22529,-22273,-22017,-21761,-21505,-21249,-20993,-20737,-20481,-20225,-19969,-19713,-19457,-19201,-18945,-18689,-18433,-18177,-17921,-17665,-17409,-17153,-16897,-16641,-16385,-16129,-15873,-15617,-15361,-15105, + -14849,-14593,-14337,-14081,-13825,-13569,-13313,-13057,-12801,-12545,-12289,-12033,-11777,-11521,-11265,-11009,-10753,-10497,-10241,-9985,-9729,-9473,-9217,-8961,-8705,-8449,-8193,-7937,-7681,-7425,-7169,-6913,-6657,-6401,-6145,-5889,-5633,-5377, + -5121,-4865,-4609,-4353,-4097,-3841,-3585,-3329,-3073,-2817,-2561,-2305,-2049,-1793,-1537,-1281,-1025,-769,-513,-257,-1,255,511,767,1023,1279,1535,1791,2047,2303,2559,2815,3071,3327,3583,3839,4095,4351,4607,4863,5119,5375,5631,5887,6143,6399, + 6655,6911,7167,7423,7679,7935,8191,8447,8703,8959,9215,9471,9727,9983,10239,10495,10751,11007,11263,11519,11775,12031,12287,12543,12799,13055,13311,13567,13823,14079,14335,14591,14847,15103,15359,15615,15871,16127,16383,16639,16895, + 17151,17407,17663,17919,18175,18431,18687,18943,19199,19455,19711,19967,20223,20479,20735,20991,21247,21503,21759,22015,22271,22527,22783,23039,23295,23551,23807,24063,24319,24575,24831,25087,25343,25599,25855,26111,26367,26623, + 26879,27135,27391,27647,27903,28159,28415,28671,28927,29183,29439,29695,29951,30207,30463,30719,30975,31231,31487,31743,31999,32255,32511,32767,32511,32255,31999,31743,31487,31231,30975,30719,30463,30207,29951,29695,29439,29183, + 28927,28671,28415,28159,27903,27647,27391,27135,26879,26623,26367,26111,25855,25599,25343,25087,24831,24575,24319,24063,23807,23551,23295,23039,22783,22527,22271,22015,21759,21503,21247,20991,20735,20479,20223,19967,19711,19455, + 19199,18943,18687,18431,18175,17919,17663,17407,17151,16895,16639,16383,16127,15871,15615,15359,15103,14847,14591,14335,14079,13823,13567,13311,13055,12799,12543,12287,12031,11775,11519,11263,11007,10751,10495,10239,9983,9727,9471, + 9215,8959,8703,8447,8191,7935,7679,7423,7167,6911,6655,6399,6143,5887,5631,5375,5119,4863,4607,4351,4095,3839,3583,3327,3071,2815,2559,2303,2047,1791,1535,1279,1023,767,511,255,-1,-257,-513,-769,-1025,-1281,-1537,-1793,-2049,-2305,-2561, + -2817,-3073,-3329,-3585,-3841,-4097,-4353,-4609,-4865,-5121,-5377,-5633,-5889,-6145,-6401,-6657,-6913,-7169,-7425,-7681,-7937,-8193,-8449,-8705,-8961,-9217,-9473,-9729,-9985,-10241,-10497,-10753,-11009,-11265,-11521,-11777,-12033,-12289,-12545, + -12801,-13057,-13313,-13569,-13825,-14081,-14337,-14593,-14849,-15105,-15361,-15617,-15873,-16129,-16385,-16641,-16897,-17153,-17409,-17665,-17921,-18177,-18433,-18689,-18945,-19201,-19457,-19713,-19969,-20225,-20481,-20737,-20993,-21249,-21505, + -21761,-22017,-22273,-22529,-22785,-23041,-23297,-23553,-23809,-24065,-24321,-24577,-24833,-25089,-25345,-25601,-25857,-26113,-26369,-26625,-26881,-27137,-27393,-27649,-27905,-28161,-28417,-28673,-28929,-29185,-29441,-29697,-29953,-30209,-30465, + -30721,-30977,-31233,-31489,-31745,-32001,-32257,-32513 + }; + + /*public static short[] SineWave; + public static short[] SawWave; + + public static void InitWaves() + { + TriangleWave = new short[512]; + for (int i = 0; i < 256; i++) + TriangleWave[i] = (short)((ushort.MaxValue*i/256)-short.MinValue); + for (int i = 0; i < 256; i++) + TriangleWave[256+i] = TriangleWave[256-i]; + TriangleWave[256] = short.MaxValue; + + SawWave = new short[512]; + for (int i = 0; i < 512; i++) + SawWave[i] = (short)((ushort.MaxValue * i / 512) - short.MinValue); + + SineWave = new short[1024]; + for (int i=0; i<1024; i++) + { + SineWave[i] = (short) (Math.Sin(i*Math.PI*2/1024d)*32767); + } + }*/ + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Sound/YM2413.cs b/BizHawk.Emulation/Sound/YM2413.cs new file mode 100644 index 0000000000..719a9c939e --- /dev/null +++ b/BizHawk.Emulation/Sound/YM2413.cs @@ -0,0 +1,1815 @@ +using System; + +// Credits: +// Original emulator written by Mitsutaka Okazaki 2001. +// Original conversion to C# by Ben Ryves. + +// TODO The savestate support here is very simplistic and incomplete. However, this does not result in desyncs as the YM2413 is write-only. +// TODO This should eventually be replaced, due to 1) uncertain licensing terms 2) This is not a native C# implementation, but a naive port. + +namespace BizHawk.Emulation.Sound +{ + public sealed class YM2413 : ISoundProvider + { + public byte DetectionValue; + public byte RegisterLatch; + + public OPLL opll; + + public YM2413() + { + opll = OPLL_new(3579545, 44100); + } + + public void Reset() + { + OPLL_reset(opll); + DetectionValue = 0; + RegisterLatch = 0; + } + + public void Write(byte value) + { + OPLL_writeReg(opll, RegisterLatch, value); + } + + public void Write(byte register, byte value) + { + OPLL_writeReg(opll, register, value); + } + + public void GetSamples(short[] samples) + { + for (int i=0; i> (b)); } + + /* Leave the lower b bit(s). */ + static int LOWBITS(int c, int b) { return ((c) & ((1 << (b)) - 1)); } + + /* Expand x which is s bits to d bits. */ + static int EXPAND_BITS(int x, int s, int d) { return ((x) << ((d) - (s))); } + + /* Expand x which is s bits to d bits and fill expanded bits '1' */ + static int EXPAND_BITS_X(int x, int s, int d) { return (((x) << ((d) - (s))) | ((1 << ((d) - (s))) - 1)); } + + /* Adjust envelope speed which depends on sampling rate. */ + static uint RATE_ADJUST(double x) { return (rate == 49716 ? (uint)x : (uint)((double)(x) * clk / 72 / rate + 0.5)); } /* added 0.5 to round the value*/ + + static OPLL_SLOT MOD(OPLL o, int x) { return ((o).slot[(x) << 1]); } + static OPLL_SLOT CAR(OPLL o, int x) { return ((o).slot[((x) << 1) | 1]); } + + static bool BIT(uint s, int b) { return (((s) >> (b)) & 1) != 0; } + static bool BIT(int s, int b) { return (((s) >> (b)) & 1) != 0; } + + /* Input clock */ + static uint clk = 844451141; + /* Sampling rate */ + static uint rate = 3354932; + + /* WaveTable for each envelope amp */ + static short[] fullsintable = new short[PG_WIDTH]; + static short[] halfsintable = new short[PG_WIDTH]; + + static short[][] waveform = new short[2][] { fullsintable, halfsintable }; + + /* LFO Table */ + static int[] pmtable = new int[PM_PG_WIDTH]; + static int[] amtable = new int[AM_PG_WIDTH]; + + /* Phase delta for LFO */ + static uint pm_dphase; + static uint am_dphase; + + /* dB to Liner table */ + static short[] DB2LIN_TABLE = new short[(DB_MUTE + DB_MUTE) * 2]; + + /* Liner to Log curve conversion table (for Attack rate). */ + static short[] AR_ADJUST_TABLE = new short[1 << EG_BITS]; + + /* Empty voice data */ + //static OPLL_PATCH null_patch = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + /* Basic voice Data */ + static OPLL_PATCH[,] default_patch = new OPLL_PATCH[OPLL_TONE_NUM, (16 + 3) * 2]; + + /* Definition of envelope mode */ + public enum OPLL_EG_STATE { READY, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, SETTLE, FINISH }; + + /* Phase incr table for Attack */ + static uint[,] dphaseARTable = new uint[16, 16]; + /* Phase incr table for Decay and Release */ + static uint[,] dphaseDRTable = new uint[16, 16]; + + /* KSL + TL Table */ + static uint[, , ,] tllTable = new uint[16, 8, 1 << TL_BITS, 4]; + static int[, ,] rksTable = new int[2, 8, 2]; + + /* Phase incr table for PG */ + static uint[, ,] dphaseTable = new uint[512, 8, 16]; + + /*************************************************** + + Create tables + + ****************************************************/ + static int Min(int i, int j) + { + if (i < j) + return i; + else + return j; + } + + /* Table for AR to LogCurve. */ + static void makeAdjustTable() + { + AR_ADJUST_TABLE[0] = (1 << EG_BITS) - 1; + for (int i = 1; i < (1 << EG_BITS); i++) + AR_ADJUST_TABLE[i] = (short)((double)(1 << EG_BITS) - 1 - ((1 << EG_BITS) - 1) * Math.Log(i) / Math.Log10(127)); + } + + + /* Table for dB(0 -- (1<= DB_MUTE) DB2LIN_TABLE[i] = 0; + DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (short)(-DB2LIN_TABLE[i]); + } + } + + /* Liner(+0.0 - +1.0) to dB((1<> (20 - DP_BITS)); + } + + static double dB2(double x) { return ((x) * 2); } + + static void makeTllTable() + { + double[] kltable = new double[] { + dB2 (0.000), dB2 (9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625), + dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000) + }; + + int tmp; + int fnum, block, TL, KL; + + for (fnum = 0; fnum < 16; fnum++) + for (block = 0; block < 8; block++) + for (TL = 0; TL < 64; TL++) + for (KL = 0; KL < 4; KL++) + { + if (KL == 0) + { + tllTable[fnum, block, TL, KL] = TL2EG((uint)TL); + } + else + { + tmp = (int)(kltable[fnum] - dB2(3.000) * (7 - block)); + if (tmp <= 0) + tllTable[fnum, block, TL, KL] = TL2EG((uint)TL); + else + tllTable[fnum, block, TL, KL] = (uint)((tmp >> (3 - KL)) / EG_STEP) + TL2EG((uint)TL); + } + } + } + + /* Rate Table for Attack */ + static void makeDphaseARTable() + { + int AR, Rks, RM, RL; + + for (AR = 0; AR < 16; AR++) + for (Rks = 0; Rks < 16; Rks++) + { + RM = AR + (Rks >> 2); + RL = Rks & 3; + if (RM > 15) + RM = 15; + switch (AR) + { + case 0: + dphaseARTable[AR, Rks] = 0; + break; + case 15: + dphaseARTable[AR, Rks] = 0;/*EG_DP_WIDTH;*/ + break; + default: + dphaseARTable[AR, Rks] = RATE_ADJUST((uint)((3 * (RL + 4) << (RM + 1)))); + break; + } + } + } + + /* Rate Table for Decay and Release */ + static void makeDphaseDRTable() + { + int DR, Rks, RM, RL; + + for (DR = 0; DR < 16; DR++) + for (Rks = 0; Rks < 16; Rks++) + { + RM = DR + (Rks >> 2); + RL = Rks & 3; + if (RM > 15) + RM = 15; + switch (DR) + { + case 0: + dphaseDRTable[DR, Rks] = 0; + break; + default: + dphaseDRTable[DR, Rks] = RATE_ADJUST((uint)((RL + 4) << (RM - 1))); + break; + } + } + } + + static void makeRksTable() + { + int fnum8, block, KR; + + for (fnum8 = 0; fnum8 < 2; fnum8++) + for (block = 0; block < 8; block++) + for (KR = 0; KR < 2; KR++) + { + if (KR != 0) + rksTable[fnum8, block, KR] = (block << 1) + fnum8; + else + rksTable[fnum8, block, KR] = block >> 1; + } + } + + static void OPLL_dump2patch(byte[] dump, OPLL_PATCH[] patch) + { + patch[0].am = (uint)(dump[0] >> 7) & 1; + patch[1].am = (uint)(dump[1] >> 7) & 1; + patch[0].pm = (uint)(dump[0] >> 6) & 1; + patch[1].pm = (uint)(dump[1] >> 6) & 1; + patch[0].eg = (uint)(dump[0] >> 5) & 1; + patch[1].eg = (uint)(dump[1] >> 5) & 1; + patch[0].kr = (uint)(dump[0] >> 4) & 1; + patch[1].kr = (uint)(dump[1] >> 4) & 1; + patch[0].ml = (uint)(dump[0]) & 15; + patch[1].ml = (uint)(dump[1]) & 15; + patch[0].kl = (uint)(dump[2] >> 6) & 3; + patch[1].kl = (uint)(dump[3] >> 6) & 3; + patch[0].tl = (uint)(dump[2]) & 63; + patch[0].fb = (uint)(dump[3]) & 7; + patch[0].wf = (uint)(dump[3] >> 3) & 1; + patch[1].wf = (uint)(dump[3] >> 4) & 1; + patch[0].ar = (uint)(dump[4] >> 4) & 15; + patch[1].ar = (uint)(dump[5] >> 4) & 15; + patch[0].dr = (uint)(dump[4]) & 15; + patch[1].dr = (uint)(dump[5]) & 15; + patch[0].sl = (uint)(dump[6] >> 4) & 15; + patch[1].sl = (uint)(dump[7] >> 4) & 15; + patch[0].rr = (uint)(dump[6]) & 15; + patch[1].rr = (uint)(dump[7]) & 15; + } + + static void + OPLL_getDefaultPatch(int type, int num, OPLL_PATCH[] patch) + { + byte[] r = new byte[8]; + Array.Copy(default_inst[type], num * 16, r, 0, r.Length); + OPLL_dump2patch(r, patch); + } + + static void makeDefaultPatch() + { + for (int i = 0; i < OPLL_TONE_NUM; i++) + { + for (int j = 0; j < 19; j++) + { + default_patch[i, j * 2 + 0] = new OPLL_PATCH(); + default_patch[i, j * 2 + 1] = new OPLL_PATCH(); + OPLL_getDefaultPatch(i, j, new[] { default_patch[i, j * 2 + 0], default_patch[i, j * 2 + 1] }); + } + } + } + + /************************************************************ + + Calc Parameters + + ************************************************************/ + + static uint calc_eg_dphase(OPLL_SLOT slot) + { + switch (slot.eg_mode) + { + case OPLL_EG_STATE.ATTACK: + return dphaseARTable[slot.patch.ar, slot.rks]; + + case OPLL_EG_STATE.DECAY: + return dphaseDRTable[slot.patch.dr, slot.rks]; + + case OPLL_EG_STATE.SUSHOLD: + return 0; + + case OPLL_EG_STATE.SUSTINE: + return dphaseDRTable[slot.patch.rr, slot.rks]; + + case OPLL_EG_STATE.RELEASE: + if (slot.sustine != 0) + return dphaseDRTable[5, slot.rks]; + else if (slot.patch.eg != 0) + return dphaseDRTable[slot.patch.rr, slot.rks]; + else + return dphaseDRTable[7, slot.rks]; + + case OPLL_EG_STATE.SETTLE: + return dphaseDRTable[15, 0]; + + case OPLL_EG_STATE.FINISH: + return 0; + + default: + return 0; + } + } + + /************************************************************* + + OPLL public interfaces + + *************************************************************/ + + const int SLOT_BD1 = 12; + const int SLOT_BD2 = 13; + const int SLOT_HH = 14; + const int SLOT_SD = 15; + const int SLOT_TOM = 16; + const int SLOT_CYM = 17; + + static void UPDATE_PG(OPLL_SLOT S) { (S).dphase = dphaseTable[(S).fnum, (S).block, (S).patch.ml]; } + static void UPDATE_TLL(OPLL_SLOT S) + { + if (S.type == 0) + { + (S).tll = tllTable[((S).fnum) >> 5, (S).block, (S).patch.tl, (S).patch.kl]; + } + else + { + (S).tll = tllTable[((S).fnum) >> 5, (S).block, (S).volume, (S).patch.kl]; + } + } + static void UPDATE_RKS(OPLL_SLOT S) { (S).rks = (uint)rksTable[((S).fnum) >> 8, (S).block, (S).patch.kr]; } + static void UPDATE_WF(OPLL_SLOT S) { (S).sintbl = waveform[(S).patch.wf]; } + static void UPDATE_EG(OPLL_SLOT S) { (S).eg_dphase = calc_eg_dphase(S); } + static void UPDATE_ALL(OPLL_SLOT S) + { + UPDATE_PG(S); + UPDATE_TLL(S); + UPDATE_RKS(S); + UPDATE_WF(S); + UPDATE_EG(S); /* EG should be updated last. */ + } + + /* Slot key on */ + static void slotOn(OPLL_SLOT slot) + { + slot.eg_mode = OPLL_EG_STATE.ATTACK; + slot.eg_phase = 0; + slot.phase = 0; + UPDATE_EG(slot); + } + + /* Slot key on without reseting the phase */ + static void slotOn2(OPLL_SLOT slot) + { + slot.eg_mode = OPLL_EG_STATE.ATTACK; + slot.eg_phase = 0; + UPDATE_EG(slot); + } + + /* Slot key off */ + static void slotOff(OPLL_SLOT slot) + { + if (slot.eg_mode == OPLL_EG_STATE.ATTACK) + slot.eg_phase = (uint)EXPAND_BITS(AR_ADJUST_TABLE[HIGHBITS(slot.eg_phase, EG_DP_BITS - EG_BITS)], EG_BITS, EG_DP_BITS); + slot.eg_mode = OPLL_EG_STATE.RELEASE; + UPDATE_EG(slot); + } + + /* Channel key on */ + static void keyOn(OPLL opll, int i) + { + if (opll.slot_on_flag[i * 2] == 0) + slotOn(MOD(opll, i)); + if (opll.slot_on_flag[i * 2 + 1] == 0) + slotOn(CAR(opll, i)); + opll.key_status[i] = 1; + } + + /* Channel key off */ + static void keyOff(OPLL opll, int i) + { + if (opll.slot_on_flag[i * 2 + 1] != 0) + slotOff(CAR(opll, i)); + opll.key_status[i] = 0; + } + + static void keyOn_BD(OPLL opll) + { + keyOn(opll, 6); + } + + static void keyOn_SD(OPLL opll) + { + if (opll.slot_on_flag[SLOT_SD] == 0) + slotOn(CAR(opll, 7)); + } + + static void keyOn_TOM(OPLL opll) + { + if (opll.slot_on_flag[SLOT_TOM] == 0) + slotOn(MOD(opll, 8)); + } + + static void keyOn_HH(OPLL opll) + { + if (opll.slot_on_flag[SLOT_HH] == 0) + slotOn2(MOD(opll, 7)); + } + + static void keyOn_CYM(OPLL opll) + { + if (opll.slot_on_flag[SLOT_CYM] == 0) + slotOn2(CAR(opll, 8)); + } + + /* Drum key off */ + static void keyOff_BD(OPLL opll) + { + keyOff(opll, 6); + } + + static void keyOff_SD(OPLL opll) + { + if (opll.slot_on_flag[SLOT_SD] == 0) + slotOff(CAR(opll, 7)); + } + + static void keyOff_TOM(OPLL opll) + { + if (opll.slot_on_flag[SLOT_TOM] != 0) + slotOff(MOD(opll, 8)); + } + + static void keyOff_HH(OPLL opll) + { + if (opll.slot_on_flag[SLOT_HH] != 0) + slotOff(MOD(opll, 7)); + } + + static void keyOff_CYM(OPLL opll) + { + if (opll.slot_on_flag[SLOT_CYM] != 0) + slotOff(CAR(opll, 8)); + } + + /* Change a voice */ + static void setPatch(OPLL opll, int i, int num) + { + opll.patch_number[i] = num; + MOD(opll, i).patch = opll.patch[num * 2 + 0]; + CAR(opll, i).patch = opll.patch[num * 2 + 1]; + } + + /* Change a rhythm voice */ + static void setSlotPatch(OPLL_SLOT slot, OPLL_PATCH patch) + { + slot.patch = patch; + } + + /* Set sustine parameter */ + static void setSustine(OPLL opll, int c, int sustine) + { + CAR(opll, c).sustine = sustine; + if (MOD(opll, c).type != 0) + MOD(opll, c).sustine = sustine; + } + + /* Volume : 6bit ( Volume register << 2 ) */ + static void setVolume(OPLL opll, int c, int volume) + { + CAR(opll, c).volume = volume; + } + + static void setSlotVolume(OPLL_SLOT slot, int volume) + { + slot.volume = volume; + } + + /* Set F-Number ( fnum : 9bit ) */ + static void setFnumber(OPLL opll, int c, int fnum) + { + CAR(opll, c).fnum = fnum; + MOD(opll, c).fnum = fnum; + } + + /* Set Block data (block : 3bit ) */ + static void setBlock(OPLL opll, int c, int block) + { + CAR(opll, c).block = block; + MOD(opll, c).block = block; + } + + /* Change Rhythm Mode */ + static void update_rhythm_mode(OPLL opll) + { + if ((opll.patch_number[6] & 0x10) != 0) + { + if ((opll.slot_on_flag[SLOT_BD2] | (opll.reg[0x0e] & 32)) == 0) + { + opll.slot[SLOT_BD1].eg_mode = OPLL_EG_STATE.FINISH; + opll.slot[SLOT_BD2].eg_mode = OPLL_EG_STATE.FINISH; + setPatch(opll, 6, opll.reg[0x36] >> 4); + } + } + else if ((opll.reg[0x0e] & 32) != 0) + { + opll.patch_number[6] = 16; + opll.slot[SLOT_BD1].eg_mode = OPLL_EG_STATE.FINISH; + opll.slot[SLOT_BD2].eg_mode = OPLL_EG_STATE.FINISH; + setSlotPatch(opll.slot[SLOT_BD1], opll.patch[16 * 2 + 0]); + setSlotPatch(opll.slot[SLOT_BD2], opll.patch[16 * 2 + 1]); + } + + if ((opll.patch_number[7] & 0x10) != 0) + { + if (!((opll.slot_on_flag[SLOT_HH] != 0 && opll.slot_on_flag[SLOT_SD] != 0) | ((opll.reg[0x0e] & 32) != 0))) + { + opll.slot[SLOT_HH].type = 0; + opll.slot[SLOT_HH].eg_mode = OPLL_EG_STATE.FINISH; + opll.slot[SLOT_SD].eg_mode = OPLL_EG_STATE.FINISH; + setPatch(opll, 7, opll.reg[0x37] >> 4); + } + } + else if ((opll.reg[0x0e] & 32) != 0) + { + opll.patch_number[7] = 17; + opll.slot[SLOT_HH].type = 1; + opll.slot[SLOT_HH].eg_mode = OPLL_EG_STATE.FINISH; + opll.slot[SLOT_SD].eg_mode = OPLL_EG_STATE.FINISH; + setSlotPatch(opll.slot[SLOT_HH], opll.patch[17 * 2 + 0]); + setSlotPatch(opll.slot[SLOT_SD], opll.patch[17 * 2 + 1]); + } + + if ((opll.patch_number[8] & 0x10) != 0) + { + if (!((opll.slot_on_flag[SLOT_CYM] != 0 && opll.slot_on_flag[SLOT_TOM] != 0) | ((opll.reg[0x0e] & 32) != 0))) + { + opll.slot[SLOT_TOM].type = 0; + opll.slot[SLOT_TOM].eg_mode = OPLL_EG_STATE.FINISH; + opll.slot[SLOT_CYM].eg_mode = OPLL_EG_STATE.FINISH; + setPatch(opll, 8, opll.reg[0x38] >> 4); + } + } + else if ((opll.reg[0x0e] & 32) != 0) + { + opll.patch_number[8] = 18; + opll.slot[SLOT_TOM].type = 1; + opll.slot[SLOT_TOM].eg_mode = OPLL_EG_STATE.FINISH; + opll.slot[SLOT_CYM].eg_mode = OPLL_EG_STATE.FINISH; + setSlotPatch(opll.slot[SLOT_TOM], opll.patch[18 * 2 + 0]); + setSlotPatch(opll.slot[SLOT_CYM], opll.patch[18 * 2 + 1]); + } + } + + static void update_key_status(OPLL opll) + { + int ch; + + for (ch = 0; ch < 9; ch++) + opll.slot_on_flag[ch * 2] = opll.slot_on_flag[ch * 2 + 1] = (opll.reg[0x20 + ch]) & 0x10; + + if ((opll.reg[0x0e] & 32) != 0) + { + opll.slot_on_flag[SLOT_BD1] |= (opll.reg[0x0e] & 0x10); + opll.slot_on_flag[SLOT_BD2] |= (opll.reg[0x0e] & 0x10); + opll.slot_on_flag[SLOT_SD] |= (opll.reg[0x0e] & 0x08); + opll.slot_on_flag[SLOT_HH] |= (opll.reg[0x0e] & 0x01); + opll.slot_on_flag[SLOT_TOM] |= (opll.reg[0x0e] & 0x04); + opll.slot_on_flag[SLOT_CYM] |= (opll.reg[0x0e] & 0x02); + } + } + + void OPLL_copyPatch(OPLL opll, int num, OPLL_PATCH patch) + { + opll.patch[num] = (OPLL_PATCH)patch.Clone(); + } + + /*********************************************************** + + Initializing + + ***********************************************************/ + + static void OPLL_SLOT_reset(OPLL_SLOT slot, int type) + { + slot.type = type; + slot.sintbl = waveform[0]; + slot.phase = 0; + slot.dphase = 0; + slot.output[0] = 0; + slot.output[1] = 0; + slot.feedback = 0; + slot.eg_mode = OPLL_EG_STATE.FINISH; + slot.eg_phase = EG_DP_WIDTH; + slot.eg_dphase = 0; + slot.rks = 0; + slot.tll = 0; + slot.sustine = 0; + slot.fnum = 0; + slot.block = 0; + slot.volume = 0; + slot.pgout = 0; + slot.egout = 0; + slot.patch = new OPLL_PATCH(); + } + + static void public_refresh() + { + makeDphaseTable(); + makeDphaseARTable(); + makeDphaseDRTable(); + pm_dphase = (uint)RATE_ADJUST(PM_SPEED * PM_DP_WIDTH / (clk / 72)); + am_dphase = (uint)RATE_ADJUST(AM_SPEED * AM_DP_WIDTH / (clk / 72)); + } + + static void maketables(uint c, uint r) + { + if (c != clk) + { + clk = c; + makePmTable(); + makeAmTable(); + makeDB2LinTable(); + makeAdjustTable(); + makeTllTable(); + makeRksTable(); + makeSinTable(); + makeDefaultPatch(); + } + + if (r != rate) + { + rate = r; + public_refresh(); + } + } + + OPLL OPLL_new(uint clk, uint rate) + { + OPLL opll = new OPLL(); + int i; + + maketables(clk, rate); + + for (i = 0; i < 19 * 2; i++) + opll.patch[i] = new OPLL_PATCH(); + + opll.mask = 0; + + OPLL_reset(opll); + OPLL_reset_patch(opll, 0); + + return opll; + } + + /* Reset patch datas by system default. */ + void OPLL_reset_patch(OPLL opll, int type) + { + int i; + + for (i = 0; i < 19 * 2; i++) + OPLL_copyPatch(opll, i, default_patch[type % OPLL_TONE_NUM, i]); + } + + /* Reset whole of OPLL except patch datas. */ + void OPLL_reset(OPLL opll) + { + int i; + + opll.adr = 0; + opll.output = 0; + + opll.pm_phase = 0; + opll.am_phase = 0; + + opll.noise_seed = 0xffff; + opll.mask = 0; + + for (i = 0; i < 18; i++) + OPLL_SLOT_reset(opll.slot[i], i % 2); + + for (i = 0; i < 9; i++) + { + opll.key_status[i] = 0; + setPatch(opll, i, 0); + } + + for (i = 0; i < 0x40; i++) + OPLL_writeReg(opll, (uint)i, 0); + + opll.realstep = (uint)((1 << 31) / rate); + opll.opllstep = (uint)((1 << 31) / (clk / 72)); + opll.oplltime = 0; + for (i = 0; i < 14; i++) + opll.pan[i] = 3; + opll.sprev[0] = opll.sprev[1] = 0; + opll.snext[0] = opll.snext[1] = 0; + + } + + /* Force Refresh (When external program changes some parameters). */ + void OPLL_forceRefresh(OPLL opll) + { + int i; + + if (opll == null) + return; + + for (i = 0; i < 9; i++) + setPatch(opll, i, opll.patch_number[i]); + + for (i = 0; i < 18; i++) + { + UPDATE_PG(opll.slot[i]); + UPDATE_RKS(opll.slot[i]); + UPDATE_TLL(opll.slot[i]); + UPDATE_WF(opll.slot[i]); + UPDATE_EG(opll.slot[i]); + } + } + + void OPLL_set_rate(OPLL opll, uint r) + { + if (opll.quality) + rate = 49716; + else + rate = r; + public_refresh(); + rate = r; + } + + void OPLL_set_quality(OPLL opll, bool q) + { + opll.quality = q; + OPLL_set_rate(opll, rate); + } + + /********************************************************* + + Generate wave data + + *********************************************************/ + + /* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */ + static int wave2_2pi(int e) + { + return ((SLOT_AMP_BITS - PG_BITS) > 0) ? + ((e) >> (SLOT_AMP_BITS - PG_BITS)) : + ((e) << (PG_BITS - SLOT_AMP_BITS)); + } + + /* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */ + static int wave2_4pi(int e) + { + return ((e) << (1 + PG_BITS - SLOT_AMP_BITS)); + /*if ((SLOT_AMP_BITS - PG_BITS - 1) == 0) { + return (e); + } else if ((SLOT_AMP_BITS - PG_BITS - 1) > 0) { + return ((e) >> (SLOT_AMP_BITS - PG_BITS - 1)); + } else { + return ((e) << (1 + PG_BITS - SLOT_AMP_BITS)); + }*/ + } + /* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */ + static int wave2_8pi(int e) + { + return ((e) << (2 + PG_BITS - SLOT_AMP_BITS)); + /* + if ((SLOT_AMP_BITS - PG_BITS - 2) == 0) { + return (e); + } else if ((SLOT_AMP_BITS - PG_BITS - 2) > 0) { + return ((e) >> (SLOT_AMP_BITS - PG_BITS - 2)); + } else { + return ((e) << (2 + PG_BITS - SLOT_AMP_BITS)); + } + */ + } + /* Update AM, PM unit */ + static void update_ampm(OPLL opll) + { + opll.pm_phase = (uint)((opll.pm_phase + pm_dphase) & (PM_DP_WIDTH - 1)); + opll.am_phase = (int)((opll.am_phase + am_dphase) & (AM_DP_WIDTH - 1)); + opll.lfo_am = amtable[HIGHBITS((uint)opll.am_phase, AM_DP_BITS - AM_PG_BITS)]; + opll.lfo_pm = pmtable[HIGHBITS(opll.pm_phase, PM_DP_BITS - PM_PG_BITS)]; + } + + /* PG */ + static void calc_phase(OPLL_SLOT slot, int lfo) + { + if (slot.patch.pm != 0) + slot.phase += (uint)((slot.dphase * lfo) >> PM_AMP_BITS); + else + slot.phase += slot.dphase; + + slot.phase &= unchecked((uint)(DP_WIDTH - 1)); + + slot.pgout = HIGHBITS(slot.phase, DP_BASE_BITS); + } + + /* Update Noise unit */ + static void update_noise(OPLL opll) + { + if ((opll.noise_seed & 1) != 0) opll.noise_seed ^= 0x8003020; + opll.noise_seed >>= 1; + } + + /* EG */ + static uint S2E(double x) { return (SL2EG((uint)(x / SL_STEP)) << (EG_DP_BITS - EG_BITS)); } + static uint[] SL = new[] { + S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0), + S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0) + }; + + static void calc_envelope(OPLL_SLOT slot, int lfo) + { + uint egout; + + switch (slot.eg_mode) + { + case OPLL_EG_STATE.ATTACK: + egout = (uint)AR_ADJUST_TABLE[HIGHBITS(slot.eg_phase, EG_DP_BITS - EG_BITS)]; + slot.eg_phase += slot.eg_dphase; + if ((EG_DP_WIDTH & slot.eg_phase) != 0 || (slot.patch.ar == 15)) + { + egout = 0; + slot.eg_phase = 0; + slot.eg_mode = OPLL_EG_STATE.DECAY; + UPDATE_EG(slot); + } + break; + + case OPLL_EG_STATE.DECAY: + egout = HIGHBITS(slot.eg_phase, EG_DP_BITS - EG_BITS); + slot.eg_phase += slot.eg_dphase; + if (slot.eg_phase >= SL[slot.patch.sl]) + { + if (slot.patch.eg != 0) + { + slot.eg_phase = SL[slot.patch.sl]; + slot.eg_mode = OPLL_EG_STATE.SUSHOLD; + UPDATE_EG(slot); + } + else + { + slot.eg_phase = SL[slot.patch.sl]; + slot.eg_mode = OPLL_EG_STATE.SUSTINE; + UPDATE_EG(slot); + } + } + break; + + case OPLL_EG_STATE.SUSHOLD: + egout = HIGHBITS(slot.eg_phase, EG_DP_BITS - EG_BITS); + if (slot.patch.eg == 0) + { + slot.eg_mode = OPLL_EG_STATE.SUSTINE; + UPDATE_EG(slot); + } + break; + + case OPLL_EG_STATE.SUSTINE: + case OPLL_EG_STATE.RELEASE: + egout = HIGHBITS(slot.eg_phase, EG_DP_BITS - EG_BITS); + slot.eg_phase += slot.eg_dphase; + if (egout >= (1 << EG_BITS)) + { + slot.eg_mode = OPLL_EG_STATE.FINISH; + egout = (1 << EG_BITS) - 1; + } + break; + + case OPLL_EG_STATE.SETTLE: + egout = HIGHBITS(slot.eg_phase, EG_DP_BITS - EG_BITS); + slot.eg_phase += slot.eg_dphase; + if (egout >= (1 << EG_BITS)) + { + slot.eg_mode = OPLL_EG_STATE.ATTACK; + egout = (1 << EG_BITS) - 1; + UPDATE_EG(slot); + } + break; + + case OPLL_EG_STATE.FINISH: + egout = (1 << EG_BITS) - 1; + break; + + default: + egout = (1 << EG_BITS) - 1; + break; + } + + if (slot.patch.am != 0) + egout = (uint)(EG2DB(egout + slot.tll) + lfo); + else + egout = EG2DB(egout + slot.tll); + + if (egout >= DB_MUTE) + egout = unchecked((uint)DB_MUTE - 1); + + slot.egout = egout | 3; + } + + /* CARRIOR */ + static int calc_slot_car(OPLL_SLOT slot, int fm) + { + if (slot.egout + 1 >= DB_MUTE) + { + slot.output[0] = 0; + } + else + { + slot.output[0] = DB2LIN_TABLE[slot.sintbl[(slot.pgout + wave2_8pi(fm)) & (PG_WIDTH - 1)] + slot.egout]; + } + slot.output[1] = (slot.output[1] + slot.output[0]) >> 1; + return slot.output[1]; + } + + /* MODULATOR */ + static int calc_slot_mod(OPLL_SLOT slot) + { + int fm; + + slot.output[1] = slot.output[0]; + + if (slot.egout + 1 >= DB_MUTE) + { + slot.output[0] = 0; + } + else if (slot.patch.fb != 0) + { + fm = wave2_4pi(slot.feedback) >> (int)(7 - slot.patch.fb); + slot.output[0] = DB2LIN_TABLE[slot.sintbl[(slot.pgout + fm) & (PG_WIDTH - 1)] + slot.egout]; + } + else + { + slot.output[0] = DB2LIN_TABLE[slot.sintbl[slot.pgout] + slot.egout]; + } + + slot.feedback = (slot.output[1] + slot.output[0]) >> 1; + + return slot.feedback; + } + + /* TOM */ + static int calc_slot_tom(OPLL_SLOT slot) + { + if (slot.egout + 1 >= DB_MUTE) + return 0; + + return DB2LIN_TABLE[slot.sintbl[slot.pgout] + slot.egout]; + } + + /* SNARE */ + static int calc_slot_snare(OPLL_SLOT slot, uint noise) + { + if (slot.egout + 1 >= DB_MUTE) + return 0; + + if (BIT(slot.pgout, 7)) + return DB2LIN_TABLE[(noise != 0 ? DB_POS(0.0) : DB_POS(15.0)) + slot.egout]; + else + return DB2LIN_TABLE[(noise != 0 ? DB_NEG(0.0) : DB_NEG(15.0)) + slot.egout]; + } + + /* + TOP-CYM + */ + static int calc_slot_cym(OPLL_SLOT slot, uint pgout_hh) + { + uint dbout; + if (slot.egout + 1 >= DB_MUTE) + return 0; + else if ( + /* the same as fmopl.c */ + ((BIT(pgout_hh, PG_BITS - 8) ^ BIT(pgout_hh, PG_BITS - 1)) | BIT(pgout_hh, PG_BITS - 7)) ^ + /* different from fmopl.c */ + (BIT(slot.pgout, PG_BITS - 7) & !BIT(slot.pgout, PG_BITS - 5)) + ) + dbout = DB_NEG(3.0); + else + dbout = DB_POS(3.0); + + return DB2LIN_TABLE[dbout + slot.egout]; + } + + /* + HI-HAT + */ + static int calc_slot_hat(OPLL_SLOT slot, int pgout_cym, uint noise) + { + uint dbout; + + if (slot.egout + 1 >= DB_MUTE) + return 0; + else if ( + /* the same as fmopl.c */ + ((BIT(slot.pgout, PG_BITS - 8) ^ BIT(slot.pgout, PG_BITS - 1)) | BIT(slot.pgout, PG_BITS - 7)) ^ + /* different from fmopl.c */ + (BIT(pgout_cym, PG_BITS - 7) & !BIT(pgout_cym, PG_BITS - 5)) + ) + { + if (noise != 0) + dbout = DB_NEG(12.0); + else + dbout = DB_NEG(24.0); + } + else + { + if (noise != 0) + dbout = DB_POS(12.0); + else + dbout = DB_POS(24.0); + } + + return DB2LIN_TABLE[dbout + slot.egout]; + } + + static short calc(OPLL opll) + { + int inst = 0, perc = 0, output = 0; + int i; + + update_ampm(opll); + update_noise(opll); + + for (i = 0; i < 18; i++) + { + calc_phase(opll.slot[i], opll.lfo_pm); + calc_envelope(opll.slot[i], opll.lfo_am); + } + + for (i = 0; i < 6; i++) + if ((opll.mask & OPLL_MASK_CH(i)) == 0 && (CAR(opll, i).eg_mode != OPLL_EG_STATE.FINISH)) + inst += calc_slot_car(CAR(opll, i), calc_slot_mod(MOD(opll, i))); + + /* CH6 */ + if (opll.patch_number[6] <= 15) + { + if ((opll.mask & OPLL_MASK_CH(6)) == 0 && (CAR(opll, 6).eg_mode != OPLL_EG_STATE.FINISH)) + inst += calc_slot_car(CAR(opll, 6), calc_slot_mod(MOD(opll, 6))); + } + else + { + if ((opll.mask & OPLL_MASK_BD) == 0 && (CAR(opll, 6).eg_mode != OPLL_EG_STATE.FINISH)) + perc += calc_slot_car(CAR(opll, 6), calc_slot_mod(MOD(opll, 6))); + } + + /* CH7 */ + if (opll.patch_number[7] <= 15) + { + if ((opll.mask & OPLL_MASK_CH(7)) == 0 && (CAR(opll, 7).eg_mode != OPLL_EG_STATE.FINISH)) + inst += calc_slot_car(CAR(opll, 7), calc_slot_mod(MOD(opll, 7))); + } + else + { + if ((opll.mask & OPLL_MASK_HH) == 0 && (MOD(opll, 7).eg_mode != OPLL_EG_STATE.FINISH)) + perc += calc_slot_hat(MOD(opll, 7), (int)CAR(opll, 8).pgout, opll.noise_seed & 1); + if ((opll.mask & OPLL_MASK_SD) == 0 && (CAR(opll, 7).eg_mode != OPLL_EG_STATE.FINISH)) + perc -= calc_slot_snare(CAR(opll, 7), opll.noise_seed & 1); + } + + /* CH8 */ + if (opll.patch_number[8] <= 15) + { + if ((opll.mask & OPLL_MASK_CH(8)) == 0 && (CAR(opll, 8).eg_mode != OPLL_EG_STATE.FINISH)) + inst += calc_slot_car(CAR(opll, 8), calc_slot_mod(MOD(opll, 8))); + } + else + { + if ((opll.mask & OPLL_MASK_TOM) == 0 && (MOD(opll, 8).eg_mode != OPLL_EG_STATE.FINISH)) + perc += calc_slot_tom(MOD(opll, 8)); + if ((opll.mask & OPLL_MASK_CYM) == 0 && (CAR(opll, 8).eg_mode != OPLL_EG_STATE.FINISH)) + perc -= calc_slot_cym(CAR(opll, 8), MOD(opll, 7).pgout); + } + + output = inst + (perc << 1); + return (short)(output << 3); + } + + short OPLL_calc(OPLL opll) + { + if (!opll.quality) + return calc(opll); + + while (opll.realstep > opll.oplltime) + { + opll.oplltime += opll.opllstep; + opll.prev = opll.next; + opll.next = calc(opll); + } + + opll.oplltime -= opll.realstep; + opll.output = (short)(((double)opll.next * (opll.opllstep - opll.oplltime) + + (double)opll.prev * opll.oplltime) / opll.opllstep); + return (short)opll.output; + } + + uint OPLL_setMask(OPLL opll, uint mask) + { + uint ret; + + if (opll != null) + { + ret = opll.mask; + opll.mask = mask; + return ret; + } + else + return 0; + } + + uint OPLL_toggleMask(OPLL opll, uint mask) + { + uint ret; + + if (opll != null) + { + ret = opll.mask; + opll.mask ^= mask; + return ret; + } + else + return 0; + } + + /**************************************************** + + I/O Ctrl + + *****************************************************/ + + void OPLL_writeReg(OPLL opll, uint reg, uint data) + { + int i, v, ch; + + data = data & 0xff; + reg = reg & 0x3f; + opll.reg[reg] = (byte)data; + + switch (reg) + { + case 0x00: + opll.patch[0].am = (data >> 7) & 1; + opll.patch[0].pm = (data >> 6) & 1; + opll.patch[0].eg = (data >> 5) & 1; + opll.patch[0].kr = (data >> 4) & 1; + opll.patch[0].ml = (data) & 15; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_PG(MOD(opll, i)); + UPDATE_RKS(MOD(opll, i)); + UPDATE_EG(MOD(opll, i)); + } + } + break; + + case 0x01: + opll.patch[1].am = (data >> 7) & 1; + opll.patch[1].pm = (data >> 6) & 1; + opll.patch[1].eg = (data >> 5) & 1; + opll.patch[1].kr = (data >> 4) & 1; + opll.patch[1].ml = (data) & 15; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_PG(CAR(opll, i)); + UPDATE_RKS(CAR(opll, i)); + UPDATE_EG(CAR(opll, i)); + } + } + break; + + case 0x02: + opll.patch[0].kl = (data >> 6) & 3; + opll.patch[0].tl = (data) & 63; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_TLL(MOD(opll, i)); + } + } + break; + + case 0x03: + opll.patch[1].kl = (data >> 6) & 3; + opll.patch[1].wf = (data >> 4) & 1; + opll.patch[0].wf = (data >> 3) & 1; + opll.patch[0].fb = (data) & 7; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_WF(MOD(opll, i)); + UPDATE_WF(CAR(opll, i)); + } + } + break; + + case 0x04: + opll.patch[0].ar = (data >> 4) & 15; + opll.patch[0].dr = (data) & 15; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_EG(MOD(opll, i)); + } + } + break; + + case 0x05: + opll.patch[1].ar = (data >> 4) & 15; + opll.patch[1].dr = (data) & 15; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_EG(CAR(opll, i)); + } + } + break; + + case 0x06: + opll.patch[0].sl = (data >> 4) & 15; + opll.patch[0].rr = (data) & 15; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_EG(MOD(opll, i)); + } + } + break; + + case 0x07: + opll.patch[1].sl = (data >> 4) & 15; + opll.patch[1].rr = (data) & 15; + for (i = 0; i < 9; i++) + { + if (opll.patch_number[i] == 0) + { + UPDATE_EG(CAR(opll, i)); + } + } + break; + + case 0x0e: + update_rhythm_mode(opll); + if ((data & 32) != 0) + { + if ((data & 0x10) != 0) + keyOn_BD(opll); + else + keyOff_BD(opll); + if ((data & 0x8) != 0) + keyOn_SD(opll); + else + keyOff_SD(opll); + if ((data & 0x4) != 0) + keyOn_TOM(opll); + else + keyOff_TOM(opll); + if ((data & 0x2) != 0) + keyOn_CYM(opll); + else + keyOff_CYM(opll); + if ((data & 0x1) != 0) + keyOn_HH(opll); + else + keyOff_HH(opll); + } + update_key_status(opll); + + UPDATE_ALL(MOD(opll, 6)); + UPDATE_ALL(CAR(opll, 6)); + UPDATE_ALL(MOD(opll, 7)); + UPDATE_ALL(CAR(opll, 7)); + UPDATE_ALL(MOD(opll, 8)); + UPDATE_ALL(CAR(opll, 8)); + + break; + + case 0x0f: + break; + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + ch = (int)(reg - 0x10); + setFnumber(opll, ch, (int)data + ((opll.reg[0x20 + ch] & 1) << 8)); + UPDATE_ALL(MOD(opll, ch)); + UPDATE_ALL(CAR(opll, ch)); + break; + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + ch = (int)(reg - 0x20); + setFnumber(opll, ch, (int)((data & 1) << 8) + opll.reg[0x10 + ch]); + setBlock(opll, ch, (int)(data >> 1) & 7); + setSustine(opll, ch, (int)(data >> 5) & 1); + if ((data & 0x10) != 0) + keyOn(opll, ch); + else + keyOff(opll, ch); + UPDATE_ALL(MOD(opll, ch)); + UPDATE_ALL(CAR(opll, ch)); + update_key_status(opll); + update_rhythm_mode(opll); + break; + + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + i = (int)((data >> 4) & 15); + v = (int)(data & 15); + if ((opll.reg[0x0e] & 32) != 0 && (reg >= 0x36)) + { + switch (reg) + { + case 0x37: + setSlotVolume(MOD(opll, 7), i << 2); + break; + case 0x38: + setSlotVolume(MOD(opll, 8), i << 2); + break; + default: + break; + } + } + else + { + setPatch(opll, (int)(reg - 0x30), i); + } + setVolume(opll, (int)(reg - 0x30), v << 2); + UPDATE_ALL(MOD(opll, (int)(reg - 0x30))); + UPDATE_ALL(CAR(opll, (int)(reg - 0x30))); + break; + + default: + break; + + } + } + + void OPLL_writeIO(OPLL opll, uint adr, uint val) + { + if ((adr & 1) != 0) + OPLL_writeReg(opll, opll.adr, val); + else + opll.adr = val; + } + + /* STEREO MODE (OPT) */ + void OPLL_set_pan(OPLL opll, uint ch, uint pan) + { + opll.pan[ch & 15] = pan & 3; + } + + static void calc_stereo(OPLL opll, int[] output) + { + int[] b = new[] { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */ + int[] r = new[] { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */ + int i; + + update_ampm(opll); + update_noise(opll); + + for (i = 0; i < 18; i++) + { + calc_phase(opll.slot[i], opll.lfo_pm); + calc_envelope(opll.slot[i], opll.lfo_am); + } + + for (i = 0; i < 6; i++) + if ((opll.mask & OPLL_MASK_CH(i)) == 0 && (CAR(opll, i).eg_mode != OPLL_EG_STATE.FINISH)) + b[opll.pan[i]] += calc_slot_car(CAR(opll, i), calc_slot_mod(MOD(opll, i))); + + + if (opll.patch_number[6] <= 15) + { + if ((opll.mask & OPLL_MASK_CH(6)) == 0 && (CAR(opll, 6).eg_mode != OPLL_EG_STATE.FINISH)) + b[opll.pan[6]] += calc_slot_car(CAR(opll, 6), calc_slot_mod(MOD(opll, 6))); + } + else + { + if ((opll.mask & OPLL_MASK_BD) == 0 && (CAR(opll, 6).eg_mode != OPLL_EG_STATE.FINISH)) + r[opll.pan[9]] += calc_slot_car(CAR(opll, 6), calc_slot_mod(MOD(opll, 6))); + } + + if (opll.patch_number[7] <= 15) + { + if ((opll.mask & OPLL_MASK_CH(7)) == 0 && (CAR(opll, 7).eg_mode != OPLL_EG_STATE.FINISH)) + b[opll.pan[7]] += calc_slot_car(CAR(opll, 7), calc_slot_mod(MOD(opll, 7))); + } + else + { + if ((opll.mask & OPLL_MASK_HH) == 0 && (MOD(opll, 7).eg_mode != OPLL_EG_STATE.FINISH)) + r[opll.pan[10]] += calc_slot_hat(MOD(opll, 7), (int)CAR(opll, 8).pgout, opll.noise_seed & 1); + if ((opll.mask & OPLL_MASK_SD) == 0 && (CAR(opll, 7).eg_mode != OPLL_EG_STATE.FINISH)) + r[opll.pan[11]] -= calc_slot_snare(CAR(opll, 7), opll.noise_seed & 1); + } + + if (opll.patch_number[8] <= 15) + { + if ((opll.mask & OPLL_MASK_CH(8)) == 0 && (CAR(opll, 8).eg_mode != OPLL_EG_STATE.FINISH)) + b[opll.pan[8]] += calc_slot_car(CAR(opll, 8), calc_slot_mod(MOD(opll, 8))); + } + else + { + if ((opll.mask & OPLL_MASK_TOM) == 0 && (MOD(opll, 8).eg_mode != OPLL_EG_STATE.FINISH)) + r[opll.pan[12]] += calc_slot_tom(MOD(opll, 8)); + if ((opll.mask & OPLL_MASK_CYM) == 0 && (CAR(opll, 8).eg_mode != OPLL_EG_STATE.FINISH)) + r[opll.pan[13]] -= calc_slot_cym(CAR(opll, 8), MOD(opll, 7).pgout); + } + + output[1] = (b[1] + b[3] + ((r[1] + r[3]) << 1)) << 3; + output[0] = (b[2] + b[3] + ((r[2] + r[3]) << 1)) << 3; + } + + void OPLL_calc_stereo(OPLL opll, int[] output) + { + if (!opll.quality) + { + calc_stereo(opll, output); + return; + } + + while (opll.realstep > opll.oplltime) + { + opll.oplltime += opll.opllstep; + opll.sprev[0] = opll.snext[0]; + opll.sprev[1] = opll.snext[1]; + calc_stereo(opll, opll.snext); + } + + opll.oplltime -= opll.realstep; + output[0] = (short)(((double)opll.snext[0] * (opll.opllstep - opll.oplltime) + + (double)opll.sprev[0] * opll.oplltime) / opll.opllstep); + output[1] = (short)(((double)opll.snext[1] * (opll.opllstep - opll.oplltime) + + (double)opll.sprev[1] * opll.oplltime) / opll.opllstep); + } + + /* voice data */ + public sealed class OPLL_PATCH : ICloneable + { + public uint tl, fb, eg, ml, ar, dr, sl, rr, kr, kl, am, pm, wf; + + public object Clone() + { + OPLL_PATCH o = new OPLL_PATCH(); + o.tl = this.tl; o.fb = this.fb; o.eg = this.eg; o.ml = this.ml; o.ar = this.ar; o.dr = this.dr; o.sl = this.sl; o.rr = this.rr; o.kr = this.kr; o.kl = this.kl; o.am = this.am; o.pm = this.pm; o.wf = this.wf; + return o; + } + } + + /* slot */ + public sealed class OPLL_SLOT + { + public OPLL_PATCH patch; + + public int type; /* 0 : modulator 1 : carrier */ + + /* OUTPUT */ + public int feedback; + + public int[] output = new int[2]; /* Output value of slot */ + + /* for Phase Generator (PG) */ + public short[] sintbl; /* Wavetable */ + public uint phase; /* Phase */ + public uint dphase; /* Phase increment amount */ + public uint pgout; /* output */ + + /* for Envelope Generator (EG) */ + public int fnum; /* F-Number */ + public int block; /* Block */ + public int volume; /* Current volume */ + public int sustine; /* Sustine 1 = ON, 0 = OFF */ + public uint tll; /* Total Level + Key scale level*/ + public uint rks; /* Key scale offset (Rks) */ + public OPLL_EG_STATE eg_mode; /* Current state */ + public uint eg_phase; /* Phase */ + public uint eg_dphase; /* Phase increment amount */ + public uint egout; /* output */ + + } + + public sealed class OPLL + { + public uint adr; + public int output; + + public uint realstep; + public uint oplltime; + public uint opllstep; + public int prev, next; + public int[] sprev = new int[2], snext = new int[2]; + public uint[] pan = new uint[16]; + + /* Register */ + public byte[] reg = new byte[0x40]; + public int[] slot_on_flag = new int[18]; + + /* Pitch Modulator */ + public uint pm_phase; + public int lfo_pm; + + /* Amp Modulator */ + public int am_phase; + public int lfo_am; + + public bool quality; + + /* Noise Generator */ + public uint noise_seed; + + /* Channel Data */ + public int[] patch_number = new int[9]; + public int[] key_status = new int[9]; + + /* Slot */ + public OPLL_SLOT[] slot = new OPLL_SLOT[18]; + + /* Voice Data */ + public OPLL_PATCH[] patch = new OPLL_PATCH[19 * 2]; + public int[] patch_update = new int[2]; /* flag for check patch update */ + + public uint mask; + + public OPLL() + { + for (int i = 0; i < this.slot.Length; ++i) this.slot[i] = new OPLL_SLOT(); + for (int i = 0; i < this.patch.Length; i++) this.patch[i] = new OPLL_PATCH(); + } + + } + + #endregion + } +} diff --git a/BizHawk.Emulation/Sound/YM2612.cs b/BizHawk.Emulation/Sound/YM2612.cs new file mode 100644 index 0000000000..ca6f4bb3b5 --- /dev/null +++ b/BizHawk.Emulation/Sound/YM2612.cs @@ -0,0 +1,25 @@ +namespace BizHawk.Emulation.Sound +{ + public sealed class YM2612 : ISoundProvider + { + public byte ReadStatus() + { + // default status: not BUSY, both timers tripped + return 3; + } + + public void Write(int addr, byte value) + { + + } + + public void Reset() + { + } + + public void GetSamples(short[] samples) + { + // TODO + } + } +} diff --git a/BizHawk.Emulation/Util.cs b/BizHawk.Emulation/Util.cs new file mode 100644 index 0000000000..96660cb879 --- /dev/null +++ b/BizHawk.Emulation/Util.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; + +namespace BizHawk +{ + public struct Tuple : IEquatable> + { + private readonly T1 first; + private readonly T2 second; + public T1 First { get { return first; } } + public T2 Second { get { return second; } } + + public Tuple(T1 o1, T2 o2) + { + first = o1; + second = o2; + } + + public bool Equals(Tuple other) + { + return first.Equals(other.first) && + second.Equals(other.second); + } + + public override bool Equals(object obj) + { + if (obj is Tuple) + return this.Equals((Tuple)obj); + else + return false; + } + + public override int GetHashCode() + { + return first.GetHashCode() ^ second.GetHashCode(); + } + } + + public static class Extensions + { + public static bool IsBinary(this string str) + { + for (int i = 0; i < str.Length; i++) + { + char c = str[i]; + if (c == '0' || c == '1') + continue; + return false; + } + return true; + } + + public static bool In(this string str, params string[] options) + { + foreach (string opt in options) + { + if (opt.Equals(str, StringComparison.CurrentCultureIgnoreCase)) return true; + } + return false; + } + + public static bool In(this string str, IEnumerable options) + { + foreach (string opt in options) + { + if (opt.Equals(str,StringComparison.CurrentCultureIgnoreCase)) return true; + } + return false; + } + + public static bool In(this string str, IEnumerable options, Func eval) + { + foreach (T opt in options) + { + if (eval(opt, str) == true) + return true; + } + return false; + } + + public static bool NotIn(this string str, params string[] options) + { + foreach (string opt in options) + { + if (opt.ToLower() == str.ToLower()) return false; + } + return true; + } + + public static bool NotIn(this string str, IEnumerable options) + { + foreach (string opt in options) + { + if (opt.ToLower() == str.ToLower()) return false; + } + return true; + } + + public static bool In(this int i, params int[] options) + { + foreach (int j in options) + { + if (i == j) return true; + } + return false; + } + + public static bool In(this int i, IEnumerable options) + { + foreach (int j in options) + { + if (i == j) return true; + } + return false; + } + + public static bool IsValidRomExtentsion(this string str, params string[] romExtensions) + { + string strUpper = str.ToUpper(); + foreach (string ext in romExtensions) + { + if (strUpper.EndsWith(ext.ToUpper())) return true; + } + return false; + } + + public static string ToCommaSeparated(this List list) + { + var sb = new StringBuilder(); + for (int i = 0; i < list.Count; i++) + { + if (i > 0) sb.Append(","); + sb.Append(list[i]); + } + return sb.ToString(); + } + + public static void SaveAsHex(this byte[] buffer, TextWriter writer) + { + for (int i=0; i= 0; j--) + if (SaveRAM[j] != 0) + return j + 1; + return 0; + } + } +} diff --git a/BizHawk.MultiClient/BizHawk.MultiClient.csproj b/BizHawk.MultiClient/BizHawk.MultiClient.csproj new file mode 100644 index 0000000000..4680f61f88 --- /dev/null +++ b/BizHawk.MultiClient/BizHawk.MultiClient.csproj @@ -0,0 +1,133 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {DD448B37-BA3F-4544-9754-5406E8094723} + Exe + Properties + BizHawk.MultiClient + BizHawk.MultiClient + v3.5 + 512 + + + + + true + full + false + output\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + output\ + TRACE + prompt + 4 + x86 + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + False + ..\SlimDX.dll + + + + + + + + + + + + + Form + + + MainForm.cs + + + + Form + + + NameStateForm.cs + + + + + MainForm.cs + + + NameStateForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + Form + + + + + + + + {197D4314-8A9F-49BA-977D-54ACEFAEB6BA} + BizHawk.Emulation + + + {EE135301-08B3-4EFC-A61C-1C53E1C65CB9} + BizHawk.Util + + + + + + \ No newline at end of file diff --git a/BizHawk.MultiClient/Config.cs b/BizHawk.MultiClient/Config.cs new file mode 100644 index 0000000000..39232a6bf9 --- /dev/null +++ b/BizHawk.MultiClient/Config.cs @@ -0,0 +1,53 @@ +namespace BizHawk.MultiClient +{ + public class Config + { + // General Client Settings + public bool SoundEnabled = true; + public string LastRomPath = "."; + + // Client Hotkey Bindings + public string HardResetBinding = "LeftShift+Tab"; + public string FastForwardBinding = "J1 B6"; + public string RewindBinding = "J1 B5"; + public string EmulatorPauseBinding = "LeftControl+Space"; + public string FrameAdvanceBinding = "F"; + public string ScreenshotBinding = "F12"; + + // SMS / GameGear Settings + public string SmsReset = "Tab"; + public string SmsPause = "J1 B10, Space"; + public string SmsP1Up = "J1 Up, UpArrow"; + public string SmsP1Left = "J1 Left, LeftArrow"; + public string SmsP1Right = "J1 Right, RightArrow"; + public string SmsP1Down = "J1 Down, DownArrow"; + public string SmsP1B1 = "J1 B1, Z"; + public string SmsP1B2 = "J1 B2, X"; + public string SmsP2Up = "J2 Up"; + public string SmsP2Left = "J2 Left"; + public string SmsP2Right = "J2 Right"; + public string SmsP2Down = "J2 Down"; + public string SmsP2B1 = "J2 B1"; + public string SmsP2B2 = "J2 B2"; + + // PCEngine Settings + public string PCEUp = "J1 Up, UpArrow"; + public string PCEDown = "J1 Down, DownArrow"; + public string PCELeft = "J1 Left, LeftArrow"; + public string PCERight = "J1 Right, RightArrow"; + public string PCEBII = "J1 B1, Z"; + public string PCEBI = "J1 B2, X"; + public string PCESelect = "J1 B9, Space"; + public string PCERun = "J1 B10, Return"; + + // Genesis Settings + public string GenP1Up = "J1 Up, UpArrow"; + public string GenP1Down = "J1 Down, DownArrow"; + public string GenP1Left = "J1 Left, LeftArrow"; + public string GenP1Right = "J1 Right, RightArrow"; + public string GenP1A = "J1 B1, Z"; + public string GenP1B = "J1 B2, X"; + public string GenP1C = "J1 B9, C"; + public string GenP1Start = "J1 B10, Return"; + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/ConfigService.cs b/BizHawk.MultiClient/ConfigService.cs new file mode 100644 index 0000000000..0c3f23f3a1 --- /dev/null +++ b/BizHawk.MultiClient/ConfigService.cs @@ -0,0 +1,77 @@ +using System; +using System.IO; + +namespace BizHawk.MultiClient +{ + public static class ConfigService + { + public static T Load(string filepath) where T : new() + { + T config = new T(); + + try + { + var file = new FileInfo(filepath); + var reader = file.OpenText(); + var type = config.GetType(); + + while (reader.EndOfStream == false) + { + try + { + string line = reader.ReadLine(); + if (string.IsNullOrEmpty(line)) + continue; + + int seperatorIndex = line.IndexOf(' '); + string name = line.Substring(0, seperatorIndex); + string value = line.Substring(seperatorIndex).Trim(); + + var field = type.GetField(name); + if (field == null) // look at properties instead of fields? or just abort. + continue; + + Type fieldType = field.FieldType; + if (fieldType == typeof(string)) + field.SetValue(config, value); + else if (fieldType == typeof(int)) + field.SetValue(config, int.Parse(value)); + else if (fieldType == typeof(long)) + field.SetValue(config, long.Parse(value)); + else if (fieldType == typeof(byte)) + field.SetValue(config, byte.Parse(value)); + else if (fieldType == typeof(short)) + field.SetValue(config, short.Parse(value)); + else if (fieldType == typeof(float)) + field.SetValue(config, Single.Parse(value)); + else if (fieldType == typeof(double)) + field.SetValue(config, Double.Parse(value)); + else if (fieldType == typeof(bool)) + field.SetValue(config, bool.Parse(value)); + else if (fieldType == typeof(char)) + field.SetValue(config, char.Parse(value)); + } + catch { } // If anything fails to parse, just move on / use defaults, don't crash. + } + reader.Close(); + } + catch { } + return config; + } + + public static void Save(string filepath, object config) + { + var file = new FileInfo(filepath); + var writer = file.CreateText(); + + var type = config.GetType(); + var fields = type.GetFields(); + + foreach (var field in fields) + { + writer.WriteLine("{0} {1}", field.Name, field.GetValue(config)); + } + writer.Close(); + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/Global.cs b/BizHawk.MultiClient/Global.cs new file mode 100644 index 0000000000..ce0a6aaab6 --- /dev/null +++ b/BizHawk.MultiClient/Global.cs @@ -0,0 +1,21 @@ +using SlimDX.Direct3D9; +using SlimDX.DirectSound; + +namespace BizHawk.MultiClient +{ + public static class Global + { + public static MainForm MainForm; + public static DirectSound DSound; + public static Direct3D Direct3D; + public static Sound Sound; + public static IRenderer RenderPanel; + public static Config Config; + public static IEmulator Emulator; + public static RomGame Game; + public static IController ClientControls; + public static IController SMSControls; + public static IController PCEControls; + public static IController GenControls; + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/HawkFile.cs b/BizHawk.MultiClient/HawkFile.cs new file mode 100644 index 0000000000..7764d5245e --- /dev/null +++ b/BizHawk.MultiClient/HawkFile.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; + +namespace BizHawk.MultiClient +{ + public class HawkFile : IDisposable + { + private bool zipped; + public bool Zipped { get { return zipped; } } + + private bool exists; + public bool Exists { get { return exists; } } + + private string extension; + public string Extension { get { return extension; } } + + public string Directory { get { return Path.GetDirectoryName(rawFileName); } } + + private string rawFileName; + private string name; + public string Name { get { return name; } } + public string FullName { get { return name + "." + extension; } } + + private IDisposable thingToDispose; + private Stream zippedStream; + + public HawkFile(string path) : this(path,"SMS","PCE","SGX","GG","SG","BIN","SMD","GB","IPS") {} + + public HawkFile(string path, params string[] recognizedExtensions) + { + var file = new FileInfo(path); + + exists = file.Exists; + if (file.Exists == false) + return; + + if (file.Extension.ToLower().In(".zip",".rar",".7z")) + { + LoadZipFile(path, recognizedExtensions); + return; + } + + zipped = false; + extension = file.Extension.Substring(1).ToUpperInvariant(); + rawFileName = path; + name = Path.GetFileNameWithoutExtension(path); + } + + private void LoadZipFile(string path, string[] recognizedExtensions) + { + zipped = true; + rawFileName = path; + + using (var extractor = new SevenZip.SevenZipExtractor(path)) + { + thingToDispose = extractor; + foreach (var e in extractor.ArchiveFileData) + { + extension = Path.GetExtension(e.FileName).Substring(1).ToUpperInvariant(); + + if (extension.In(recognizedExtensions)) + { + // we found our match. + name = Path.GetFileNameWithoutExtension(e.FileName); + zippedStream = new MemoryStream(); + //e.Extract(zippedStream); + extractor.ExtractFile(e.Index,zippedStream); + thingToDispose = zippedStream; + return; + } + } + exists = false; + } + } + + public Stream GetStream() + { + if (zipped == false) + { + var stream = new FileStream(rawFileName, FileMode.Open, FileAccess.Read); + thingToDispose = stream; + return stream; + } + + return zippedStream; + } + + public void Dispose() + { + if (thingToDispose != null) + thingToDispose.Dispose(); + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/Input/ControllerBinding.cs b/BizHawk.MultiClient/Input/ControllerBinding.cs new file mode 100644 index 0000000000..d4da2747a4 --- /dev/null +++ b/BizHawk.MultiClient/Input/ControllerBinding.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.MultiClient +{ + public class Controller : IController + { + private ControllerDefinition type; + private Dictionary> bindings = new Dictionary>(); + private List unpressedButtons = new List(); + + public Controller(ControllerDefinition definition) + { + type = definition; + + foreach (var b in type.BoolButtons) + bindings[b] = new List(); + + foreach (var f in type.FloatControls) + bindings[f] = new List(); + } + + public void BindButton(string button, string control) + { + bindings[button].Add(control); + } + + public void BindMulti(string button, string controlString) + { + string[] controlbindings = controlString.Split(','); + foreach (string control in controlbindings) + bindings[button].Add(control.Trim()); + } + + public ControllerDefinition Type + { + get { return type; } + } + + public bool this[string name] + { + get { return IsPressed(name); } + } + + public bool IsPressed(string name) + { + if (unpressedButtons.Contains(name)) + { + if (IsPressedActually(name) == false) + unpressedButtons.Remove(name); + + return false; + } + + return IsPressedActually(name); + } + + private bool IsPressedActually(string name) + { + foreach (var control in bindings[name]) + if (Input.IsPressed(control)) + return true; + + return false; + } + + public float GetFloat(string name) + { + throw new NotImplementedException(); + } + + public void UnpressButton(string name) + { + unpressedButtons.Add(name); + } + + private int frameNumber; + public int FrameNumber + { + get + { + return frameNumber; + } + set + { + if (value != frameNumber) + { + // update + unpressedButtons.RemoveAll(button => IsPressedActually(button) == false); + } + frameNumber = value; + } + } + } +} diff --git a/BizHawk.MultiClient/Input/GamePad.cs b/BizHawk.MultiClient/Input/GamePad.cs new file mode 100644 index 0000000000..ca60076fdf --- /dev/null +++ b/BizHawk.MultiClient/Input/GamePad.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using SlimDX; +using SlimDX.DirectInput; + +namespace BizHawk.MultiClient +{ + public class GamePad + { + // ********************************** Static interface ********************************** + + private static DirectInput dinput; + public static List Devices; + + public static void Initialize() + { + if (dinput == null) + dinput = new DirectInput(); + + Devices = new List(); + + foreach (DeviceInstance device in dinput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly)) + { + var joystick = new Joystick(dinput, device.InstanceGuid); + joystick.SetCooperativeLevel(Global.MainForm.Handle, CooperativeLevel.Background | CooperativeLevel.Nonexclusive); + foreach (DeviceObjectInstance deviceObject in joystick.GetObjects()) + { + if ((deviceObject.ObjectType & ObjectDeviceType.Axis) != 0) + joystick.GetObjectPropertiesById((int)deviceObject.ObjectType).SetRange(-1000, 1000); + } + joystick.Acquire(); + + GamePad p = new GamePad(device.InstanceName, device.InstanceGuid, joystick); + Devices.Add(p); + } + } + + public static void UpdateAll() + { + foreach (var device in Devices) + device.Update(); + } + + // ********************************** Instance Members ********************************** + + private readonly string name; + private readonly Guid guid; + private readonly Joystick joystick; + private JoystickState state = new JoystickState(); + private bool[] buttons; + private int[] pov; + + private GamePad(string name, Guid guid, Joystick joystick) + { + this.name = name; + this.guid = guid; + this.joystick = joystick; + Update(); + } + + public void Update() + { + if (joystick.Acquire().IsFailure) + return; + if (joystick.Poll().IsFailure) + return; + + state = joystick.GetCurrentState(); + if (Result.Last.IsFailure) + return; + + buttons = state.GetButtons(); + pov = state.GetPointOfViewControllers(); + } + + public string Name { get { return name; } } + public Guid Guid { get { return guid; } } + + public float X { get { return state.X / 1000f; } } + public float Y { get { return state.Y / 1000f; } } + public float Z { get { return state.Z / 1000f; } } + + public bool[] Buttons { get { return buttons; } } + + public bool Up + { + get + { + if (state.Y < -250 || state.RotationY < -250) + return true; + foreach (int p in pov) + if (p.In(0, 4500, 31500)) + return true; + return false; + } + } + + public bool Down + { + get + { + if (state.Y > 250 || state.RotationY > 250) + return true; + foreach (int p in pov) + if (p.In(13500, 18000, 22500)) + return true; + return false; + } + } + + public bool Left + { + get + { + if (state.X < -250 || state.RotationX < -250) + return true; + foreach (int p in pov) + if (p.In(22500, 27000, 31500)) + return true; + return false; + } + } + + public bool Right + { + get + { + if (state.X > 250 || state.RotationX > 250) + return true; + foreach (int p in pov) + if (p.In(4500, 9000, 13500)) + return true; + return false; + } + } + + /// + /// Note that this does not appear to work at this time. I probably need to have more infos. + /// + public void SetVibration(int left, int right) + { + int[] temp1, temp2; + // my first clue that it doesnt work is that LEFT and RIGHT _ARENT USED_ + // I should just look for C++ examples instead of trying to look for SlimDX examples + + var parameters = new EffectParameters(); + parameters.Duration = 0x2710; + parameters.Gain = 0x2710; + parameters.SamplePeriod = 0; + parameters.TriggerButton = 0; + parameters.TriggerRepeatInterval = 0x2710; + parameters.Flags = EffectFlags.None; + parameters.GetAxes(out temp1, out temp2); + parameters.SetAxes(temp1, temp2); + var effect = new Effect(joystick, EffectGuid.ConstantForce); + effect.SetParameters(parameters); + effect.Start(1); + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/Input/Input.cs b/BizHawk.MultiClient/Input/Input.cs new file mode 100644 index 0000000000..78f1de95f2 --- /dev/null +++ b/BizHawk.MultiClient/Input/Input.cs @@ -0,0 +1,69 @@ +using System; +using SlimDX.DirectInput; + +namespace BizHawk.MultiClient +{ + public static class Input + { + public static void Initialize() + { + KeyInput.Initialize(); + GamePad.Initialize(); + } + + public static void Update() + { + KeyInput.Update(); + GamePad.UpdateAll(); + } + + public static bool IsPressed(string control) + { + string[] controls = control.Split('+'); + for (int i=0; i= GamePad.Devices.Count) + return false; + + if (control == "Up") return GamePad.Devices[index].Up; + if (control == "Down") return GamePad.Devices[index].Down; + if (control == "Left") return GamePad.Devices[index].Left; + if (control == "Right") return GamePad.Devices[index].Right; + + if (control.StartsWith("B")) + { + int buttonIndex = int.Parse(control.Substring(1)) - 1; + if (buttonIndex >= GamePad.Devices[index].Buttons.Length) + return false; + return GamePad.Devices[index].Buttons[buttonIndex]; + } + + return false; + } + + public static string GetPressedKey() + { + //for (int j = 0; j < GamePad.Devices.Count; j++) + return null; + } + } +} diff --git a/BizHawk.MultiClient/Input/Keyboard.cs b/BizHawk.MultiClient/Input/Keyboard.cs new file mode 100644 index 0000000000..e5b1d80028 --- /dev/null +++ b/BizHawk.MultiClient/Input/Keyboard.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using SlimDX; +using SlimDX.DirectInput; + +namespace BizHawk.MultiClient +{ + public static class KeyInput + { + private static DirectInput dinput; + private static Keyboard keyboard; + private static KeyboardState state = new KeyboardState(); + private static List unpressedKeys = new List(); + + public static void Initialize() + { + if (dinput == null) + dinput = new DirectInput(); + + if (keyboard == null || keyboard.Disposed) + keyboard = new Keyboard(dinput); + + keyboard.SetCooperativeLevel(Global.MainForm.Handle, CooperativeLevel.Foreground | CooperativeLevel.Nonexclusive); + } + + public static void Update() + { + if (keyboard.Acquire().IsFailure) + return; + if (keyboard.Poll().IsFailure) + return; + + state = keyboard.GetCurrentState(); + if (Result.Last.IsFailure) + return; + + unpressedKeys.RemoveAll(key => state.IsReleased(key)); + } + + public static KeyboardState State { get { return state; } } + + public static void Unpress(Key key) + { + if (unpressedKeys.Contains(key)) + return; + unpressedKeys.Add(key); + } + + public static bool IsPressed(Key key) + { + if (unpressedKeys.Contains(key)) + return false; + if (state.IsPressed(key)) + return true; + if (key == Key.UpArrow && state.IsPressed(Key.NumberPad8)) + return true; + if (key == Key.DownArrow && state.IsPressed(Key.NumberPad2)) + return true; + if (key == Key.LeftArrow && state.IsPressed(Key.NumberPad4)) + return true; + if (key == Key.RightArrow && state.IsPressed(Key.NumberPad6)) + return true; + return false; + } + + public static Key? GetPressedKey() + { + // TODO uhh this will return the same key over and over though. + if (state.PressedKeys.Count == 0) + return null; + if (state.PressedKeys[0] == Key.NumberPad8) + return Key.UpArrow; + if (state.PressedKeys[0] == Key.NumberPad2) + return Key.DownArrow; + if (state.PressedKeys[0] == Key.NumberPad4) + return Key.LeftArrow; + if (state.PressedKeys[0] == Key.NumberPad6) + return Key.RightArrow; + return state.PressedKeys[0]; + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/MainForm.Designer.cs b/BizHawk.MultiClient/MainForm.Designer.cs new file mode 100644 index 0000000000..30d5488d6a --- /dev/null +++ b/BizHawk.MultiClient/MainForm.Designer.cs @@ -0,0 +1,383 @@ +namespace BizHawk.MultiClient +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openROMToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.advancedLoadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.saveStateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripMenuItem(); + this.loadStateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem18 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem19 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem20 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem21 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem22 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem23 = new System.Windows.Forms.ToolStripMenuItem(); + this.saveNamedStateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.loadNamedStateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.menuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(932, 24); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.openROMToolStripMenuItem, + this.advancedLoadToolStripMenuItem, + this.toolStripMenuItem1, + this.saveStateToolStripMenuItem, + this.loadStateToolStripMenuItem, + this.saveNamedStateToolStripMenuItem, + this.loadNamedStateToolStripMenuItem, + this.toolStripMenuItem2, + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // openROMToolStripMenuItem + // + this.openROMToolStripMenuItem.Name = "openROMToolStripMenuItem"; + this.openROMToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.openROMToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.openROMToolStripMenuItem.Text = "Open ROM"; + this.openROMToolStripMenuItem.Click += new System.EventHandler(this.openROMToolStripMenuItem_Click); + // + // advancedLoadToolStripMenuItem + // + this.advancedLoadToolStripMenuItem.Name = "advancedLoadToolStripMenuItem"; + this.advancedLoadToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.advancedLoadToolStripMenuItem.Text = "Advanced Load"; + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(208, 6); + // + // saveStateToolStripMenuItem + // + this.saveStateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem4, + this.toolStripMenuItem5, + this.toolStripMenuItem6, + this.toolStripMenuItem7, + this.toolStripMenuItem8, + this.toolStripMenuItem9, + this.toolStripMenuItem10, + this.toolStripMenuItem11, + this.toolStripMenuItem12, + this.toolStripMenuItem13}); + this.saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem"; + this.saveStateToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.saveStateToolStripMenuItem.Text = "Save State"; + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F1))); + this.toolStripMenuItem4.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem4.Text = "1"; + this.toolStripMenuItem4.Click += new System.EventHandler(this.toolStripMenuItem4_Click); + // + // toolStripMenuItem5 + // + this.toolStripMenuItem5.Name = "toolStripMenuItem5"; + this.toolStripMenuItem5.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F2))); + this.toolStripMenuItem5.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem5.Text = "2"; + this.toolStripMenuItem5.Click += new System.EventHandler(this.toolStripMenuItem5_Click); + // + // toolStripMenuItem6 + // + this.toolStripMenuItem6.Name = "toolStripMenuItem6"; + this.toolStripMenuItem6.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F3))); + this.toolStripMenuItem6.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem6.Text = "3"; + this.toolStripMenuItem6.Click += new System.EventHandler(this.toolStripMenuItem6_Click); + // + // toolStripMenuItem7 + // + this.toolStripMenuItem7.Name = "toolStripMenuItem7"; + this.toolStripMenuItem7.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F4))); + this.toolStripMenuItem7.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem7.Text = "4"; + this.toolStripMenuItem7.Click += new System.EventHandler(this.toolStripMenuItem7_Click); + // + // toolStripMenuItem8 + // + this.toolStripMenuItem8.Name = "toolStripMenuItem8"; + this.toolStripMenuItem8.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F5))); + this.toolStripMenuItem8.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem8.Text = "5"; + this.toolStripMenuItem8.Click += new System.EventHandler(this.toolStripMenuItem8_Click); + // + // toolStripMenuItem9 + // + this.toolStripMenuItem9.Name = "toolStripMenuItem9"; + this.toolStripMenuItem9.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F6))); + this.toolStripMenuItem9.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem9.Text = "6"; + this.toolStripMenuItem9.Click += new System.EventHandler(this.toolStripMenuItem9_Click); + // + // toolStripMenuItem10 + // + this.toolStripMenuItem10.Name = "toolStripMenuItem10"; + this.toolStripMenuItem10.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F7))); + this.toolStripMenuItem10.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem10.Text = "7"; + this.toolStripMenuItem10.Click += new System.EventHandler(this.toolStripMenuItem10_Click); + // + // toolStripMenuItem11 + // + this.toolStripMenuItem11.Name = "toolStripMenuItem11"; + this.toolStripMenuItem11.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F8))); + this.toolStripMenuItem11.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem11.Text = "8"; + this.toolStripMenuItem11.Click += new System.EventHandler(this.toolStripMenuItem11_Click); + // + // toolStripMenuItem12 + // + this.toolStripMenuItem12.Name = "toolStripMenuItem12"; + this.toolStripMenuItem12.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F9))); + this.toolStripMenuItem12.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem12.Text = "9"; + this.toolStripMenuItem12.Click += new System.EventHandler(this.toolStripMenuItem12_Click); + // + // toolStripMenuItem13 + // + this.toolStripMenuItem13.Name = "toolStripMenuItem13"; + this.toolStripMenuItem13.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.F10))); + this.toolStripMenuItem13.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem13.Text = "0"; + this.toolStripMenuItem13.Click += new System.EventHandler(this.toolStripMenuItem13_Click); + // + // loadStateToolStripMenuItem + // + this.loadStateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem14, + this.toolStripMenuItem15, + this.toolStripMenuItem16, + this.toolStripMenuItem17, + this.toolStripMenuItem18, + this.toolStripMenuItem19, + this.toolStripMenuItem20, + this.toolStripMenuItem21, + this.toolStripMenuItem22, + this.toolStripMenuItem23}); + this.loadStateToolStripMenuItem.Name = "loadStateToolStripMenuItem"; + this.loadStateToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.loadStateToolStripMenuItem.Text = "Load State"; + // + // toolStripMenuItem14 + // + this.toolStripMenuItem14.Name = "toolStripMenuItem14"; + this.toolStripMenuItem14.ShortcutKeys = System.Windows.Forms.Keys.F1; + this.toolStripMenuItem14.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem14.Text = "1"; + this.toolStripMenuItem14.Click += new System.EventHandler(this.toolStripMenuItem14_Click); + // + // toolStripMenuItem15 + // + this.toolStripMenuItem15.Name = "toolStripMenuItem15"; + this.toolStripMenuItem15.ShortcutKeys = System.Windows.Forms.Keys.F2; + this.toolStripMenuItem15.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem15.Text = "2"; + this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click); + // + // toolStripMenuItem16 + // + this.toolStripMenuItem16.Name = "toolStripMenuItem16"; + this.toolStripMenuItem16.ShortcutKeys = System.Windows.Forms.Keys.F3; + this.toolStripMenuItem16.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem16.Text = "3"; + this.toolStripMenuItem16.Click += new System.EventHandler(this.toolStripMenuItem16_Click); + // + // toolStripMenuItem17 + // + this.toolStripMenuItem17.Name = "toolStripMenuItem17"; + this.toolStripMenuItem17.ShortcutKeys = System.Windows.Forms.Keys.F4; + this.toolStripMenuItem17.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem17.Text = "4"; + this.toolStripMenuItem17.Click += new System.EventHandler(this.toolStripMenuItem17_Click); + // + // toolStripMenuItem18 + // + this.toolStripMenuItem18.Name = "toolStripMenuItem18"; + this.toolStripMenuItem18.ShortcutKeys = System.Windows.Forms.Keys.F5; + this.toolStripMenuItem18.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem18.Text = "5"; + this.toolStripMenuItem18.Click += new System.EventHandler(this.toolStripMenuItem18_Click); + // + // toolStripMenuItem19 + // + this.toolStripMenuItem19.Name = "toolStripMenuItem19"; + this.toolStripMenuItem19.ShortcutKeys = System.Windows.Forms.Keys.F6; + this.toolStripMenuItem19.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem19.Text = "6"; + this.toolStripMenuItem19.Click += new System.EventHandler(this.toolStripMenuItem19_Click); + // + // toolStripMenuItem20 + // + this.toolStripMenuItem20.Name = "toolStripMenuItem20"; + this.toolStripMenuItem20.ShortcutKeys = System.Windows.Forms.Keys.F7; + this.toolStripMenuItem20.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem20.Text = "7"; + this.toolStripMenuItem20.Click += new System.EventHandler(this.toolStripMenuItem20_Click); + // + // toolStripMenuItem21 + // + this.toolStripMenuItem21.Name = "toolStripMenuItem21"; + this.toolStripMenuItem21.ShortcutKeys = System.Windows.Forms.Keys.F8; + this.toolStripMenuItem21.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem21.Text = "8"; + this.toolStripMenuItem21.Click += new System.EventHandler(this.toolStripMenuItem21_Click); + // + // toolStripMenuItem22 + // + this.toolStripMenuItem22.Name = "toolStripMenuItem22"; + this.toolStripMenuItem22.ShortcutKeys = System.Windows.Forms.Keys.F9; + this.toolStripMenuItem22.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem22.Text = "9"; + this.toolStripMenuItem22.Click += new System.EventHandler(this.toolStripMenuItem22_Click); + // + // toolStripMenuItem23 + // + this.toolStripMenuItem23.Name = "toolStripMenuItem23"; + this.toolStripMenuItem23.ShortcutKeys = System.Windows.Forms.Keys.F10; + this.toolStripMenuItem23.Size = new System.Drawing.Size(105, 22); + this.toolStripMenuItem23.Text = "0"; + this.toolStripMenuItem23.Click += new System.EventHandler(this.toolStripMenuItem23_Click); + // + // saveNamedStateToolStripMenuItem + // + this.saveNamedStateToolStripMenuItem.Name = "saveNamedStateToolStripMenuItem"; + this.saveNamedStateToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.saveNamedStateToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.saveNamedStateToolStripMenuItem.Text = "Save Named State"; + this.saveNamedStateToolStripMenuItem.Click += new System.EventHandler(this.saveStateToolStripMenuItem_Click); + // + // loadNamedStateToolStripMenuItem + // + this.loadNamedStateToolStripMenuItem.Name = "loadNamedStateToolStripMenuItem"; + this.loadNamedStateToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L))); + this.loadNamedStateToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.loadNamedStateToolStripMenuItem.Text = "Load Named State"; + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(208, 6); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(211, 22); + this.exitToolStripMenuItem.Text = "Exit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(932, 561); + this.Controls.Add(this.menuStrip1); + this.MainMenuStrip = this.menuStrip1; + this.Name = "MainForm"; + this.Text = "BizHawk MultiClient"; + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openROMToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem advancedLoadToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem saveStateToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem6; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem7; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem8; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem10; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13; + private System.Windows.Forms.ToolStripMenuItem loadStateToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem16; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem17; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem18; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem19; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem20; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem21; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem22; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem23; + private System.Windows.Forms.ToolStripMenuItem saveNamedStateToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem loadNamedStateToolStripMenuItem; + } +} + diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs new file mode 100644 index 0000000000..e13c6392f7 --- /dev/null +++ b/BizHawk.MultiClient/MainForm.cs @@ -0,0 +1,389 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using BizHawk.Core; +using BizHawk.Emulation.Consoles.Sega; +using BizHawk.Emulation.Consoles.TurboGrafx; + +namespace BizHawk.MultiClient +{ + public partial class MainForm : Form + { + private Control renderTarget; + private RetainedViewportPanel retainedPanel; + + private bool EmulatorPaused = false; + + public MainForm(string[] args) + { + Global.MainForm = this; + Global.Config = ConfigService.Load("config.ini"); + + InitializeComponent(); + + if (Global.Direct3D != null) + renderTarget = new ViewportPanel(); + else renderTarget = retainedPanel = new RetainedViewportPanel(); + + renderTarget.Dock = DockStyle.Fill; + renderTarget.BackColor = Color.Black; + Controls.Add(renderTarget); + Database.LoadDatabase("d:/gamedb.txt"); + + if (Global.Direct3D != null) + { + Global.RenderPanel = new Direct3DRenderPanel(Global.Direct3D, renderTarget); + } + else + { + Global.RenderPanel = new SysdrawingRenderPanel(retainedPanel); + } + + Load += (o, e) => + { + AllowDrop = true; + DragEnter += FormDragEnter; + DragDrop += FormDragDrop; + }; + + Closing += (o, e) => + { + CloseGame(); + ConfigService.Save("config.ini", Global.Config); + }; + + ResizeBegin += (o, e) => + { + if (Global.Sound != null) Global.Sound.StopSound(); + }; + + ResizeEnd += (o, e) => + { + if (Global.RenderPanel != null) Global.RenderPanel.Resized = true; + if (Global.Sound != null) Global.Sound.StartSound(); + }; + + InitControls(); + Global.Emulator = new NullEmulator(); + Global.Sound = new Sound(Handle, Global.DSound); + Global.Sound.StartSound(); + + Application.Idle += Application_Idle; + + if(args.Length != 0) + LoadRom(args[0]); + } + + public static ControllerDefinition ClientControlsDef = new ControllerDefinition + { + Name = "Emulator Frontend Controls", + BoolButtons = { "Fast Forward", "Rewind", "Hard Reset", "Mode Flip", "Quick Save State", "Quick Load State", "Save Named State", "Load Named State", "Emulator Pause", "Frame Advance", "Screenshot" } + }; + + private void InitControls() + { + Input.Initialize(); + var controls = new Controller(ClientControlsDef); + controls.BindMulti("Fast Forward", Global.Config.FastForwardBinding); + controls.BindMulti("Rewind", Global.Config.RewindBinding); + controls.BindMulti("Hard Reset", Global.Config.HardResetBinding); + controls.BindMulti("Emulator Pause", Global.Config.EmulatorPauseBinding); + controls.BindMulti("Frame Advance", Global.Config.FrameAdvanceBinding); + controls.BindMulti("Screenshot", Global.Config.ScreenshotBinding); + Global.ClientControls = controls; + + var smsControls = new Controller(SMS.SmsController); + smsControls.BindMulti("Reset", Global.Config.SmsReset); + smsControls.BindMulti("Pause", Global.Config.SmsPause); + + smsControls.BindMulti("P1 Up", Global.Config.SmsP1Up); + smsControls.BindMulti("P1 Left", Global.Config.SmsP1Left); + smsControls.BindMulti("P1 Right", Global.Config.SmsP1Right); + smsControls.BindMulti("P1 Down", Global.Config.SmsP1Down); + smsControls.BindMulti("P1 B1", Global.Config.SmsP1B1); + smsControls.BindMulti("P1 B2", Global.Config.SmsP1B2); + + smsControls.BindMulti("P2 Up", Global.Config.SmsP2Up); + smsControls.BindMulti("P2 Left", Global.Config.SmsP2Left); + smsControls.BindMulti("P2 Right", Global.Config.SmsP2Right); + smsControls.BindMulti("P2 Down", Global.Config.SmsP2Down); + smsControls.BindMulti("P2 B1", Global.Config.SmsP2B1); + smsControls.BindMulti("P2 B2", Global.Config.SmsP2B2); + Global.SMSControls = smsControls; + + var pceControls = new Controller(PCEngine.PCEngineController); + pceControls.BindMulti("Up", Global.Config.PCEUp); + pceControls.BindMulti("Down", Global.Config.PCEDown); + pceControls.BindMulti("Left", Global.Config.PCELeft); + pceControls.BindMulti("Right", Global.Config.PCERight); + + pceControls.BindMulti("II", Global.Config.PCEBII); + pceControls.BindMulti("I", Global.Config.PCEBI); + pceControls.BindMulti("Select", Global.Config.PCESelect); + pceControls.BindMulti("Run", Global.Config.PCERun); + Global.PCEControls = pceControls; + + var genControls = new Controller(Genesis.GenesisController); + genControls.BindMulti("P1 Up", Global.Config.GenP1Up); + genControls.BindMulti("P1 Left", Global.Config.GenP1Left); + genControls.BindMulti("P1 Right", Global.Config.GenP1Right); + genControls.BindMulti("P1 Down", Global.Config.GenP1Down); + genControls.BindMulti("P1 A", Global.Config.GenP1A); + genControls.BindMulti("P1 B", Global.Config.GenP1B); + genControls.BindMulti("P1 C", Global.Config.GenP1C); + genControls.BindMulti("P1 Start", Global.Config.GenP1Start); + Global.GenControls = genControls; + } + + private static void FormDragEnter(object sender, DragEventArgs e) + { + e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None; + } + + private void FormDragDrop(object sender, DragEventArgs e) + { + string[] filePaths = (string[]) e.Data.GetData(DataFormats.FileDrop); + LoadRom(filePaths[0]); + } + + private void LoadRom(string path) + { + var file = new FileInfo(path); + if (file.Exists == false) return; + + CloseGame(); + + var game = new RomGame(path); + Global.Game = game; + + switch(game.System) + { + case "SMS": + Global.Emulator = new SMS(); + Global.Emulator.Controller = Global.SMSControls; + break; + case "GG": + Global.Emulator = new SMS { IsGameGear = true }; + Global.Emulator.Controller = Global.SMSControls; + break; + case "PCE": + Global.Emulator = new PCEngine(NecSystemType.TurboGrafx); + Global.Emulator.Controller = Global.PCEControls; + break; + case "SGX": + Global.Emulator = new PCEngine(NecSystemType.SuperGrafx); + Global.Emulator.Controller = Global.PCEControls; + break; + case "GEN": + Global.Emulator = new Genesis(false);//TODO + Global.Emulator.Controller = Global.GenControls; + break; + } + + Global.Emulator.LoadGame(game); + Text = game.Name; + ResetRewindBuffer(); + + if (File.Exists(game.SaveRamPath)) + LoadSaveRam(); + } + + private void LoadSaveRam() + { + using (var reader = new BinaryReader(new FileStream(Global.Game.SaveRamPath, FileMode.Open, FileAccess.Read))) + reader.Read(Global.Emulator.SaveRam, 0, Global.Emulator.SaveRam.Length); + } + + private void CloseGame() + { + if (Global.Emulator.SaveRamModified) + { + string path = Global.Game.SaveRamPath; + + var f = new FileInfo(path); + if (f.Directory.Exists == false) + f.Directory.Create(); + + var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write)); + int len = Util.SaveRamBytesUsed(Global.Emulator.SaveRam); + writer.Write(Global.Emulator.SaveRam, 0, len); + writer.Close(); + } + } + + [System.Security.SuppressUnmanagedCodeSecurity, DllImport("User32.dll", CharSet = CharSet.Auto)] + public static extern bool PeekMessage(out Message msg, IntPtr hWnd, UInt32 msgFilterMin, UInt32 msgFilterMax, UInt32 flags); + + public void GameTick() + { + Input.Update(); + if (ActiveForm != null) + ScreenSaver.ResetTimerPeriodically(); + + if (/*Global.Config.RewindEnabled && */Global.ClientControls["Rewind"]) + { + Rewind(); + return; + } + + if (Global.ClientControls["Hard Reset"]) + { + Global.ClientControls.UnpressButton("Hard Reset"); + Global.Emulator.HardReset(); + } + + if (Global.ClientControls["Fast Forward"]) + { + Global.Emulator.FrameAdvance(false); + Global.Emulator.FrameAdvance(false); + Global.Emulator.FrameAdvance(false); + } + + if (Global.ClientControls["Screenshot"]) + { + Global.ClientControls.UnpressButton("Screenshot"); + TakeScreenshot(); + } + + if (Global.ClientControls["Emulator Pause"]) + { + Global.ClientControls.UnpressButton("Emulator Pause"); + EmulatorPaused = !EmulatorPaused; + } + + if (EmulatorPaused == false || Global.ClientControls["Frame Advance"]) + { + CaptureRewindState(); + Global.Emulator.FrameAdvance(true); + if (EmulatorPaused) + Global.ClientControls.UnpressButton("Frame Advance"); + } + Global.Sound.UpdateSound(Global.Emulator.SoundProvider); + Global.RenderPanel.Render(Global.Emulator.VideoProvider); + } + + private bool wasMaximized = false; + + private void Application_Idle(object sender, EventArgs e) + { + if (wasMaximized != (WindowState == FormWindowState.Maximized)) + { + wasMaximized = (WindowState == FormWindowState.Maximized); + Global.RenderPanel.Resized = true; + } + + Message msg; + while (!PeekMessage(out msg, IntPtr.Zero, 0, 0, 0)) + { + GameTick(); + } + } + + private void TakeScreenshot() + { + var video = Global.Emulator.VideoProvider; + var image = new Bitmap(video.BufferWidth, video.BufferHeight, PixelFormat.Format32bppArgb); + + for (int y=0; yis@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/BizHawk.MultiClient/MruStack.cs b/BizHawk.MultiClient/MruStack.cs new file mode 100644 index 0000000000..9a60db6a74 --- /dev/null +++ b/BizHawk.MultiClient/MruStack.cs @@ -0,0 +1,53 @@ +namespace BizHawk.MultiClient +{ + public class MruStack + { + private T[] store; + private int count; + private int head; + + public int Count { get { return count; } } + + public MruStack(int capacity) + { + store = new T[capacity]; + Clear(); + } + + public void Clear() + { + head = 0; + count = 0; + for (int i = 0; i < store.Length; i++) + store[i] = default(T); + } + + public void Push(T value) + { + store[head] = value; + head = (head + 1) % store.Length; + + if (count < store.Length) + count++; + } + + public T Pop() + { + if (count == 0) + return default(T); + + head--; + if (head < 0) + head = store.Length - 1; + count--; + T value = store[head]; + store[head] = default(T); + return value; + } + + public bool HasElements() + { + return count > 0; + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/NameStateForm.Designer.cs b/BizHawk.MultiClient/NameStateForm.Designer.cs new file mode 100644 index 0000000000..31258b6240 --- /dev/null +++ b/BizHawk.MultiClient/NameStateForm.Designer.cs @@ -0,0 +1,98 @@ +namespace BizHawk.MultiClient +{ + partial class NameStateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.cancelButton = new System.Windows.Forms.Button(); + this.saveButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.stateLabelTextBox = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // cancelButton + // + this.cancelButton.Location = new System.Drawing.Point(199, 51); + this.cancelButton.Name = "cancelButton"; + this.cancelButton.Size = new System.Drawing.Size(75, 23); + this.cancelButton.TabIndex = 0; + this.cancelButton.Text = "Cancel"; + this.cancelButton.UseVisualStyleBackColor = true; + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // saveButton + // + this.saveButton.Location = new System.Drawing.Point(118, 51); + this.saveButton.Name = "saveButton"; + this.saveButton.Size = new System.Drawing.Size(75, 23); + this.saveButton.TabIndex = 1; + this.saveButton.Text = "Save"; + this.saveButton.UseVisualStyleBackColor = true; + this.saveButton.Click += new System.EventHandler(this.saveButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(181, 13); + this.label1.TabIndex = 2; + this.label1.Text = "Enter a short label for this save state:"; + // + // stateLabelTextBox + // + this.stateLabelTextBox.Location = new System.Drawing.Point(15, 25); + this.stateLabelTextBox.Name = "stateLabelTextBox"; + this.stateLabelTextBox.Size = new System.Drawing.Size(167, 20); + this.stateLabelTextBox.TabIndex = 3; + // + // NameStateForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(278, 81); + this.Controls.Add(this.stateLabelTextBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.saveButton); + this.Controls.Add(this.cancelButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Name = "NameStateForm"; + this.Text = "Label Save State"; + this.Shown += new System.EventHandler(this.NameStateForm_Shown); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button saveButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox stateLabelTextBox; + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/NameStateForm.cs b/BizHawk.MultiClient/NameStateForm.cs new file mode 100644 index 0000000000..cba7d2c04b --- /dev/null +++ b/BizHawk.MultiClient/NameStateForm.cs @@ -0,0 +1,38 @@ +using System; +using System.Windows.Forms; + +namespace BizHawk.MultiClient +{ + public partial class NameStateForm : Form + { + public string Result; + public bool OK; + + public NameStateForm() + { + InitializeComponent(); + AcceptButton = saveButton; + CancelButton = cancelButton; + } + + private void cancelButton_Click(object sender, EventArgs e) + { + Close(); + } + + private void saveButton_Click(object sender, EventArgs e) + { + if (stateLabelTextBox.Text.Length != 0) + { + Result = stateLabelTextBox.Text; + OK = true; + Close(); + } + } + + private void NameStateForm_Shown(object sender, EventArgs e) + { + stateLabelTextBox.Focus(); + } + } +} diff --git a/BizHawk.MultiClient/NameStateForm.resources b/BizHawk.MultiClient/NameStateForm.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BizHawk.MultiClient/Program.cs b/BizHawk.MultiClient/Program.cs new file mode 100644 index 0000000000..d7596e6284 --- /dev/null +++ b/BizHawk.MultiClient/Program.cs @@ -0,0 +1,39 @@ +using System; +using System.Windows.Forms; +using SlimDX.Direct3D9; +using SlimDX.DirectSound; + +namespace BizHawk.MultiClient +{ + static class Program + { + [STAThread] + static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + try { Global.DSound = new DirectSound(); } + catch { + MessageBox.Show("Couldn't initialize DirectSound!"); + return; + } + + try { Global.Direct3D = new Direct3D(); } + catch { + //can fallback to GDI rendering + } + + try { + Application.Run(new MainForm(args)); + } catch (Exception e) { + MessageBox.Show(e.ToString(), "Oh, no, a terrible thing happened!"); + } finally { + if (Global.DSound != null && Global.DSound.Disposed == false) + Global.DSound.Dispose(); + if (Global.Direct3D != null && Global.Direct3D.Disposed == false) + Global.Direct3D.Dispose(); + } + } + } +} diff --git a/BizHawk.MultiClient/Properties/AssemblyInfo.cs b/BizHawk.MultiClient/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a15f908be2 --- /dev/null +++ b/BizHawk.MultiClient/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("BizHawk.MultiClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("BizHawk.MultiClient")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c282f0e2-86cb-4a6b-b83e-ad74f90ebe83")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BizHawk.MultiClient/Properties/Resources.Designer.cs b/BizHawk.MultiClient/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..5bbb7cd048 --- /dev/null +++ b/BizHawk.MultiClient/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4952 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace BizHawk.MultiClient.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BizHawk.MultiClient.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/BizHawk.MultiClient/Properties/Resources.resources b/BizHawk.MultiClient/Properties/Resources.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BizHawk.MultiClient/Properties/Settings.Designer.cs b/BizHawk.MultiClient/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..0236e1285c --- /dev/null +++ b/BizHawk.MultiClient/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4952 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace BizHawk.MultiClient.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/BizHawk.MultiClient/Properties/Settings.settings b/BizHawk.MultiClient/Properties/Settings.settings new file mode 100644 index 0000000000..abf36c5d3d --- /dev/null +++ b/BizHawk.MultiClient/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/BizHawk.MultiClient/RenderPanel.cs b/BizHawk.MultiClient/RenderPanel.cs new file mode 100644 index 0000000000..b3cb6e0a6f --- /dev/null +++ b/BizHawk.MultiClient/RenderPanel.cs @@ -0,0 +1,287 @@ +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Windows.Forms; +using SlimDX; +using SlimDX.Direct3D9; +using Font = SlimDX.Direct3D9.Font; +using BizHawk.Core; + +namespace BizHawk.MultiClient +{ + public class ImageTexture : IDisposable + { + public Device GraphicsDevice; + public Texture Texture; + + private int imageWidth; + public int ImageWidth { get { return imageWidth; } } + + private int imageHeight; + public int ImageHeight { get { return imageHeight; } } + + private int textureWidth; + public int TextureWidth { get { return textureWidth; } } + + private int textureHeight; + public int TextureHeight { get { return textureHeight; } } + + public ImageTexture(Device graphicsDevice) + { + GraphicsDevice = graphicsDevice; + } + + public void SetImage(int[] data, int width, int height) + { + bool needsRecreating = false; + if (Texture == null) + { + needsRecreating = true; + } + else + { + var currentTextureSize = Texture.GetLevelDescription(0); + if (imageWidth != width || imageHeight != height) + { + needsRecreating = true; + } + } + // If we need to recreate the texture, do so. + if (needsRecreating) + { + if (Texture != null) + { + Texture.Dispose(); + Texture = null; + } + // Copy the width/height to member fields. + imageWidth = width; + imageHeight = height; + // Round up the width/height to the nearest power of two. + textureWidth = 32; textureHeight = 32; + while (textureWidth < imageWidth) textureWidth <<= 1; + while (textureHeight < imageHeight) textureHeight <<= 1; + // Create a new texture instance. + Texture = new Texture(GraphicsDevice, textureWidth, textureHeight, 1, Usage.Dynamic, Format.X8R8G8B8, Pool.Default); + } + // Copy the image data to the texture. + using (var Data = Texture.LockRectangle(0, new Rectangle(0, 0, imageWidth, imageHeight), LockFlags.None).Data) + { + if (imageWidth == textureWidth) + { + // Widths are the same, just dump the data across (easy!) + Data.WriteRange(data, 0, imageWidth * imageHeight); + } + else + { + // Widths are different, need a bit of additional magic here to make them fit: + long RowSeekOffset = 4 * (textureWidth - imageWidth); + for (int r = 0, s = 0; r < imageHeight; ++r, s += imageWidth) + { + Data.WriteRange(data, s, imageWidth); + Data.Seek(RowSeekOffset, SeekOrigin.Current); + } + } + Texture.UnlockRectangle(0); + } + } + + private bool disposed; + + public void Dispose() + { + if (!disposed) + { + disposed = true; + if (Texture != null) + Texture.Dispose(); + Texture = null; + GC.SuppressFinalize(this); + } + } + } + + public interface IRenderer : IDisposable + { + void Render(IVideoProvider video); + bool Resized { get; set; } + void AddMessage(string msg); + } + + public class SysdrawingRenderPanel : IRenderer + { + public bool Resized { get; set; } + public void Dispose() { } + public void Render(IVideoProvider video) + { + Color BackgroundColor = Color.FromArgb(video.BackgroundColor); + + int[] data = video.GetVideoBuffer(); + + Bitmap bmp = new Bitmap(video.BufferWidth, video.BufferHeight, PixelFormat.Format32bppArgb); + BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + + //TODO - this is not very intelligent. no handling of pitch, for instance + Marshal.Copy(data, 0, bmpdata.Scan0, bmp.Width * bmp.Height); + + bmp.UnlockBits(bmpdata); + + backingControl.SetBitmap(bmp); + } + public SysdrawingRenderPanel(RetainedViewportPanel control) + { + backingControl = control; + } + RetainedViewportPanel backingControl; + public void AddMessage(string msg) { } + } + + + public class Direct3DRenderPanel : IRenderer + { + public Color BackgroundColor { get; set; } + public bool Resized { get; set; } + + private Direct3D d3d; + private Device Device; + private Control backingControl; + public ImageTexture Texture; + private Sprite Sprite; + private Font MessageFont; + + public Direct3DRenderPanel(Direct3D direct3D, Control control) + { + d3d = direct3D; + backingControl = control; + } + + private void DestroyDevice() + { + if (Texture != null) + { + Texture.Dispose(); + Texture = null; + } + if (Sprite != null) + { + Sprite.Dispose(); + Sprite = null; + } + if (MessageFont != null) + { + MessageFont.Dispose(); + MessageFont = null; + } + } + + public void CreateDevice() + { + DestroyDevice(); + Device = new Device(d3d, 0, DeviceType.Hardware, backingControl.Handle, CreateFlags.HardwareVertexProcessing, + new PresentParameters + { + BackBufferWidth = Math.Max(1, backingControl.ClientSize.Width), + BackBufferHeight = Math.Max(1, backingControl.ClientSize.Height), + DeviceWindowHandle = backingControl.Handle, + PresentationInterval = PresentInterval.One + }); + Sprite = new Sprite(Device); + Texture = new ImageTexture(Device); + MessageFont = new Font(Device, 16, 0, FontWeight.Bold, 1, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Arial"); + } + + public void Render() + { + if (Device == null || Resized) + CreateDevice(); + + Resized = false; + Device.Clear(ClearFlags.Target, BackgroundColor, 1.0f, 0); + Device.Present(Present.DoNotWait); + } + + public void Render(IVideoProvider video) + { + if (video == null) + { + Render(); + return; + } + + if (Device == null || Resized) + CreateDevice(); + Resized = false; + + BackgroundColor = Color.FromArgb(video.BackgroundColor); + + int[] data = video.GetVideoBuffer(); + Texture.SetImage(data, video.BufferWidth, video.BufferHeight); + + Device.Clear(ClearFlags.Target, BackgroundColor, 1.0f, 0); + + // figure out scaling factor + int widthScale = backingControl.Size.Width / video.BufferWidth; + int heightScale = backingControl.Size.Height / video.BufferHeight; + int finalScale = Math.Min(widthScale, heightScale); + + // center position + int xpos = (backingControl.Size.Width / 2) - (video.BufferWidth / 2); + int ypos = (backingControl.Size.Height / 2) - (video.BufferHeight / 2); + + Device.BeginScene(); + + Sprite.Begin(SpriteFlags.None); + Device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Point); + Device.SetSamplerState(1, SamplerState.MagFilter, TextureFilter.Point); + Sprite.Transform = Matrix.Scaling(finalScale, finalScale, 0f); + Sprite.Draw(Texture.Texture, new Rectangle(0, 0, video.BufferWidth, video.BufferHeight), new Vector3(video.BufferWidth / 2f, video.BufferHeight / 2f, 0), new Vector3(backingControl.Size.Width / 2f / finalScale, backingControl.Size.Height / 2f / finalScale, 0), Color.White); + Sprite.End(); + + DrawMessages(); + + Device.EndScene(); + Device.Present(Present.DoNotWait); + } + + private List messages = new List(5); + + public void AddMessage(string message) + { + messages.Add(new UIMessage {Message = message, ExpireAt = DateTime.Now + TimeSpan.FromSeconds(2)}); + } + + private void DrawMessages() + { + messages.RemoveAll(m => DateTime.Now > m.ExpireAt); + + int line = 1; + for (int i=messages.Count - 1; i>=0; i--, line++) + { + int x = 3; + int y = backingControl.Size.Height - (line*18); + MessageFont.DrawString(null, messages[i].Message, x+2, y+2, new Color4(Color.Black)); + MessageFont.DrawString(null, messages[i].Message, x, y, new Color4(Color.White)); + } + } + + private bool disposed; + + public void Dispose() + { + if (disposed == false) + { + disposed = true; + DestroyDevice(); + } + } + } + + class UIMessage + { + public string Message; + public DateTime ExpireAt; + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/Rewind.cs b/BizHawk.MultiClient/Rewind.cs new file mode 100644 index 0000000000..d5f38c14fa --- /dev/null +++ b/BizHawk.MultiClient/Rewind.cs @@ -0,0 +1,171 @@ +using System.IO; + +namespace BizHawk.MultiClient +{ + public partial class MainForm + { + private MruStack RewindBuf = new MruStack(15000); + private byte[] LastState; + + private void CaptureRewindState() + { + if (LastState == null) + { + // This is the first frame. Capture the state, and put it in LastState for future deltas to be compared against. + LastState = Global.Emulator.SaveStateBinary(); + //System.Console.WriteLine(LastState.Length); + return; + } + + // Otherwise, it's not the first frame, so build a delta. + if (LastState.Length <= 0x10000) + CaptureRewindState64K(); + else + CaptureRewindStateLarge(); + } + + /// + /// Builds a delta for states that are <= 64K in size. + /// + private void CaptureRewindState64K() + { + byte[] CurrentState = Global.Emulator.SaveStateBinary(); + int beginChangeSequence = -1; + bool inChangeSequence = false; + var ms = new MemoryStream(); + var writer = new BinaryWriter(ms); + for (int i = 0; i < CurrentState.Length; i++) + { + if (inChangeSequence == false) + { + if (CurrentState[i] == LastState[i]) + continue; + + inChangeSequence = true; + beginChangeSequence = i; + continue; + } + + if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1) + { + writer.Write((byte)(i - beginChangeSequence + 1)); + writer.Write((ushort)beginChangeSequence); + writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1); + inChangeSequence = false; + continue; + } + + if (CurrentState[i] == LastState[i]) + { + writer.Write((byte)(i - beginChangeSequence)); + writer.Write((ushort)beginChangeSequence); + writer.Write(LastState, beginChangeSequence, i - beginChangeSequence); + inChangeSequence = false; + } + } + LastState = CurrentState; + ms.Position = 0; + RewindBuf.Push(ms); + } + + /// + /// Builds a delta for states that are > 64K in size. + /// + private void CaptureRewindStateLarge() + { + byte[] CurrentState = Global.Emulator.SaveStateBinary(); + int beginChangeSequence = -1; + bool inChangeSequence = false; + var ms = new MemoryStream(); + var writer = new BinaryWriter(ms); + for (int i = 0; i < CurrentState.Length; i++) + { + if (inChangeSequence == false) + { + if (CurrentState[i] == LastState[i]) + continue; + + inChangeSequence = true; + beginChangeSequence = i; + continue; + } + + if (i - beginChangeSequence == 254 || i == CurrentState.Length - 1) + { + writer.Write((byte)(i - beginChangeSequence + 1)); + writer.Write(beginChangeSequence); + writer.Write(LastState, beginChangeSequence, i - beginChangeSequence + 1); + inChangeSequence = false; + continue; + } + + if (CurrentState[i] == LastState[i]) + { + writer.Write((byte)(i - beginChangeSequence)); + writer.Write(beginChangeSequence); + writer.Write(LastState, beginChangeSequence, i - beginChangeSequence); + inChangeSequence = false; + } + } + LastState = CurrentState; + ms.Position = 0; + RewindBuf.Push(ms); + } + + private void Rewind64K() + { + var ms = RewindBuf.Pop(); + var reader = new BinaryReader(ms); + var output = new MemoryStream(LastState); + while (ms.Position < ms.Length - 1) + { + byte len = reader.ReadByte(); + ushort offset = reader.ReadUInt16(); + output.Position = offset; + output.Write(ms.GetBuffer(), (int)ms.Position, len); + ms.Position += len; + } + reader.Close(); + output.Position = 0; + Global.Emulator.LoadStateBinary(new BinaryReader(output)); + } + + private void RewindLarge() + { + var ms = RewindBuf.Pop(); + var reader = new BinaryReader(ms); + var output = new MemoryStream(LastState); + while (ms.Position < ms.Length - 1) + { + byte len = reader.ReadByte(); + int offset = reader.ReadInt32(); + output.Position = offset; + output.Write(ms.GetBuffer(), (int)ms.Position, len); + ms.Position += len; + } + reader.Close(); + output.Position = 0; + Global.Emulator.LoadStateBinary(new BinaryReader(output)); + } + + private void Rewind() + { + if (RewindBuf.Count == 0) + return; + if (LastState.Length < 0x10000) + Rewind64K(); + else + RewindLarge(); + + Global.Emulator.FrameAdvance(true); + Global.Sound.UpdateSound(Global.Emulator.SoundProvider); + Global.RenderPanel.Render(Global.Emulator.VideoProvider); + } + + public void ResetRewindBuffer() + { + RewindBuf.Clear(); + LastState = null; + } + } +} diff --git a/BizHawk.MultiClient/RomGame.cs b/BizHawk.MultiClient/RomGame.cs new file mode 100644 index 0000000000..c8d69bf491 --- /dev/null +++ b/BizHawk.MultiClient/RomGame.cs @@ -0,0 +1,144 @@ +using System; + +namespace BizHawk.MultiClient +{ + public class RomGame : IGame + { + public byte[] RomData; + public string System; + + private string name; + private string[] options = new string[0]; + private const int BankSize = 4096; + + public RomGame(string path) : this(path, null){} + + public RomGame(string path, string patch) + { + using (var file = new HawkFile(path)) + { + if (!file.Exists) + throw new Exception("The file needs to exist, yo."); + + var stream = file.GetStream(); + + int header = (int) (stream.Length%BankSize); + stream.Position = header; + int length = (int) stream.Length - header; + + RomData = new byte[length]; + stream.Read(RomData, 0, length); + + if (file.Extension == "SMD") + RomData = DeInterleaveSMD(RomData); + + var info = Database.GetGameInfo(RomData, file.FullName); + name = info.Name; + System = info.System; + options = info.GetOptions(); + } + + if (patch != null) + { + using (var stream = new HawkFile(patch).GetStream()) + { + IPS.Patch(RomData, stream); + } + } + } + + private byte[] DeInterleaveSMD(byte[] source) + { + // SMD files are interleaved in pages of 16k, with the first 8k containing all + // odd bytes and the second 8k containing all even bytes. + + int size = source.Length; + if (size > 0x400000) size = 0x400000; + int pages = size / 0x4000; + byte[] output = new byte[size]; + + for (int page = 0; page < pages; page++) + { + for (int i = 0; i < 0x2000; i++) + { + output[(page * 0x4000) + (i * 2) + 0] = source[(page * 0x4000) + 0x2000 + i]; + output[(page * 0x4000) + (i * 2) + 1] = source[(page * 0x4000) + 0x0000 + i]; + } + } + return output; + } + + public byte[] GetRomData() { return RomData; } + public string[] GetOptions() { return options; } + public string Name { get { return name; } } + + public string SaveRamPath + { + get + { + switch (System) + { + case "SMS": return "SMS/SaveRAM/" + Name + ".SaveRAM"; + case "GG": return "Game Gear/SaveRAM/" + Name + ".SaveRAM"; + case "PCE": return "TurboGrafx/SaveRAM/" + Name + ".SaveRAM"; + case "GB": return "Gameboy/SaveRAM/" + Name + ".SaveRAM"; + case "GEN": return "Genesis/SaveRAM/" + Name + ".SaveRAM"; + case "NES": return "NES/SaveRAM/" + Name + ".SaveRAM"; + default: return ""; + } + } + } + + public string SaveStatePrefix + { + get + { + switch (System) + { + case "SMS": return "SMS/State/" + Name; + case "GG": return "Game Gear/State/" + Name; + case "PCE": return "TurboGrafx/State/" + Name; + case "GB": return "Gameboy/State/" + Name; + case "GEN": return "Genesis/State/" + Name; + case "NES": return "NES/State/" + Name; + default: return ""; + } + + } + } + + public string MoviePrefix + { + get + { + switch (System) + { + case "SMS": return "SMS/Movie/" + Name; + case "GG": return "Game Gear/Movie/" + Name; + case "PCE": return "TurboGrafx/Movie/" + Name; + case "GB": return "Gameboy/Movie/" + Name; + case "GEN": return "Genesis/Movie/" + Name; + case "NES": return "NES/Movie/" + Name; + default: return ""; + } + } + } + + public string ScreenshotPrefix + { + get + { + switch (System) + { + case "SMS": return "SMS/Screenshot/" + Name; + case "GG": return "Game Gear/Screenshot/" + Name; + case "PCE": return "TurboGrafx/Screenshot/" + Name; + case "GB": return "Gameboy/Screenshot/" + Name; + case "GEN": return "Genesis/Screenshot/" + Name; + case "NES": return "NES/Screenshot/" + Name; + default: return ""; + } + } + } + } +} diff --git a/BizHawk.MultiClient/ScreenSaver.cs b/BizHawk.MultiClient/ScreenSaver.cs new file mode 100644 index 0000000000..ca729b3b65 --- /dev/null +++ b/BizHawk.MultiClient/ScreenSaver.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.InteropServices; + +namespace BizHawk.MultiClient +{ + // Derived from http://www.codeproject.com/KB/cs/ScreenSaverControl.aspx + public static class ScreenSaver + { + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags); + + private const int SPI_GETSCREENSAVERTIMEOUT = 14; + private const int SPI_SETSCREENSAVERTIMEOUT = 15; + private const int SPIF_SENDWININICHANGE = 2; + + public static void ResetTimerImmediate() + { + SetScreenSaverTimeout(GetScreenSaverTimeout()); + } + + private static int ctr; + public static void ResetTimerPeriodically() + { + ctr++; + if (ctr == 120) + { + SetScreenSaverTimeout(GetScreenSaverTimeout()); + ctr = 0; + } + } + + // Returns the screen saver timeout setting, in seconds + private static Int32 GetScreenSaverTimeout() + { + Int32 value = 0; + SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0); + return value; + } + + // Pass in the number of seconds to set the screen saver timeout value. + private static void SetScreenSaverTimeout(Int32 Value) + { + int nullVar = 0; + SystemParametersInfo(SPI_SETSCREENSAVERTIMEOUT, Value, ref nullVar, SPIF_SENDWININICHANGE); + } + } +} diff --git a/BizHawk.MultiClient/Sound.cs b/BizHawk.MultiClient/Sound.cs new file mode 100644 index 0000000000..0888526a40 --- /dev/null +++ b/BizHawk.MultiClient/Sound.cs @@ -0,0 +1,110 @@ +using System; +using BizHawk.Emulation.Sound; +using SlimDX.DirectSound; +using SlimDX.Multimedia; + +namespace BizHawk.MultiClient +{ + public class Sound : IDisposable + { + public bool SoundEnabled = true; + public bool Muted = false; + private bool disposed = false; + + private SecondarySoundBuffer DSoundBuffer; + private byte[] SoundBuffer; + private const int BufferSize = 4410 * 2 * 2; // 1/10th of a second, 2 bytes per sample, 2 channels; + private int SoundBufferPosition; + + private BufferedAsync semisync = new BufferedAsync(); + + public Sound(IntPtr handle, DirectSound device) + { + device.SetCooperativeLevel(handle, CooperativeLevel.Priority); + + var format = new WaveFormat(); + format.SamplesPerSecond = 44100; + format.BitsPerSample = 16; + format.Channels = 2; + format.FormatTag = WaveFormatTag.Pcm; + format.BlockAlignment = 4; + format.AverageBytesPerSecond = format.SamplesPerSecond * format.Channels * (format.BitsPerSample / 8); + + var desc = new SoundBufferDescription(); + desc.Format = format; + desc.Flags = BufferFlags.GlobalFocus | BufferFlags.Software | BufferFlags.GetCurrentPosition2; + desc.SizeInBytes = BufferSize; + + DSoundBuffer = new SecondarySoundBuffer(device, desc); + SoundBuffer = new byte[BufferSize]; + + disposed = false; + } + + public void StartSound() + { + if (disposed) throw new ObjectDisposedException("Sound"); + if (SoundEnabled == false) return; + + DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer); + + DSoundBuffer.CurrentPlayPosition = 0; + DSoundBuffer.Play(0, PlayFlags.Looping); + } + + public void StopSound() + { + for (int i = 0; i < SoundBuffer.Length; i++) + SoundBuffer[i] = 0; + DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer); + DSoundBuffer.Stop(); + } + + public void Dispose() + { + if (disposed) return; + if (DSoundBuffer != null && DSoundBuffer.Disposed == false) + { + DSoundBuffer.Dispose(); + DSoundBuffer = null; + } + } + + public void UpdateSound(ISoundProvider soundProvider) + { + if (SoundEnabled == false || disposed) + return; + + int PlayPos = DSoundBuffer.CurrentPlayPosition / 2; + int WritePos = SoundBufferPosition / 2; + int TargetPos = PlayPos + 2204; + + int samplesNeeded = TargetPos - WritePos; + if (samplesNeeded < 0) + samplesNeeded += 8820; + + if (samplesNeeded >= 8820) + samplesNeeded -= 8820; + + short[] samples = new short[samplesNeeded]; + + if (soundProvider != null && Muted == false) + { + semisync.BaseSoundProvider = soundProvider; + semisync.GetSamples(samples); + } + + for (int i = 0; i < samples.Length; i++) + { + short s = samples[i]; + SoundBuffer[SoundBufferPosition++] = (byte)(s & 0xFF); + SoundBuffer[SoundBufferPosition++] = (byte)(s >> 8); + + if (SoundBufferPosition >= SoundBuffer.Length) + SoundBufferPosition = 0; + } + + DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer); + } + } +} \ No newline at end of file diff --git a/BizHawk.MultiClient/output/7z.dll b/BizHawk.MultiClient/output/7z.dll new file mode 100644 index 0000000000000000000000000000000000000000..f08706fef8898d54e69590ed0b65e715985df039 GIT binary patch literal 878592 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

3rGaM0IZYP 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ⅇ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℘k)*@Zu4UPIk^NVLdh|TkY~wSmV2A|%SZQc9 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%0D1&3h`Ho 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�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 z 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 z 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 Bo>c$< literal 0 HcmV?d00001 diff --git a/BizHawk.MultiClient/output/config.ini b/BizHawk.MultiClient/output/config.ini new file mode 100644 index 0000000000..8564416733 --- /dev/null +++ b/BizHawk.MultiClient/output/config.ini @@ -0,0 +1,38 @@ +SoundEnabled True +LastRomPath D:\lib\roms\Turbografx16 +HardResetBinding LeftShift+Tab +FastForwardBinding J1 B6 +RewindBinding J1 B5 +EmulatorPauseBinding Pause +FrameAdvanceBinding F +ScreenshotBinding F12 +SmsReset Tab +SmsPause J1 B10, Space +SmsP1Up J1 Up, UpArrow +SmsP1Left J1 Left, LeftArrow +SmsP1Right J1 Right, RightArrow +SmsP1Down J1 Down, DownArrow +SmsP1B1 J1 B2, Z +SmsP1B2 J1 B3, X +SmsP2Up J2 Up +SmsP2Left J2 Left +SmsP2Right J2 Right +SmsP2Down J2 Down +SmsP2B1 J2 B1 +SmsP2B2 J2 B2 +PCEUp J1 Up, UpArrow +PCEDown J1 Down, DownArrow +PCELeft J1 Left, LeftArrow +PCERight J1 Right, RightArrow +PCEBII J1 B2, Z +PCEBI J1 B3, X +PCESelect J1 B9, Space +PCERun J1 B10, Return +GenP1Up J1 Up, UpArrow +GenP1Down J1 Down, DownArrow +GenP1Left J1 Left, LeftArrow +GenP1Right J1 Right, RightArrow +GenP1A J1 B1, Z +GenP1B J1 B2, X +GenP1C J1 B9, C +GenP1Start J1 B10, Return diff --git a/BizHawk.Util/7z.dll b/BizHawk.Util/7z.dll new file mode 100644 index 0000000000000000000000000000000000000000..f08706fef8898d54e69590ed0b65e715985df039 GIT binary patch literal 878592 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

3rGaM0IZYP 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ⅇ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℘k)*@Zu4UPIk^NVLdh|TkY~wSmV2A|%SZQc9 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%0D1&3h`Ho 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�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 z zLmp`3&~7+7;MRt|FF@0^83fzM>jG*7&>Y7bZw1_I{<-FW+W89T<^nyQ_ly~HQ?*DGjkdIy%A74ulJcBWIC^#Is)nsivsGP#gJEF zADEpN|5bgvR^IC?Mba?hE|p zuK~3Ukneo|3%J930d-j-;J)*%zf29{drv@JhxYN$0k!Qf0ks~e*9}oW8!gVuSK~JY)SS)fT=kmJxckU_b=j`@YADd0 zN4>^pROG8ou-EVTH;>9!m58}$V?e!y_BXVRi1X%8-aMWFOa6=f!o0MIXM5<(fO+LsC;$GjC^(I^nCR?ke{pdICwvuGcjKsT%Vca38$QX zEZ^tpYviff`Rcl=eD(F=`DzmUy*UOp0_N~{qyKF4eVCT`1D2ca!T`xrle zYXS1vLg(y2#-Gda-ZtZ;e0L7?n&Nwg>9=F;8SAlB75rvBs^JAGP6xP&p=r)XSi8Yt z1*&?hf{by#j(1Axsm%K_?acY5o!QTJ&YVmguMzg|LoQset-!5c%vU!9xmM=`Th`>O zOMzUgO~9YfxMz)eAm3fDe*r$ymandSJm3Aiz2c#K^(d~tT^Hx8`xfP^$I-ZtehK{L zrF{H95AeVbqv>4CI`+el?z7f??+#AYjMw=%z~J$NR0u6Naggdh7Y$fF`L{oRV{Y0{h`vrAgrEC^e;N=i zo31X4PMv|6wFBExS835DEV`&gmq5M)<;i$ai%wa5_F3#A7Q2v7$7?o(X68p(0IR0H9Jx61a0GDV@c*vlk z`NIN*d0XUenS-D3SZebB*KErzbMpq{mmhvxxBrcwb0n~axz4+>uaHICN(2{1TV z1wX~Ljn;~O94&}zunzhV8~UZ_SK~a0rqJ&LH`;}3pY5;cqtP$-Z2YZi73SUzzuW`r zK8Nlfu+4=}v=Gr5tV)5EXw_(H6Krz^<6S1s(Yk*He+%pbkR{N%(c+LrfURgzv{Ljd ze}Vsk!78#5dBR5&=;n@mLmWc@JRtX!YBUFZ=FUB(G7om>2Z8vlvQ%y%#O>QEom+4y z;-l}+EdiO%ts6NwLy#k6I=>M5&S3bJ{1p6#aBk*TxlLw%k*zcH3qc=7ZmB)@1LVAI zy5G7z_fF8gHl1(M`BQQGKD*Uc zD&ueh1*)_<9LLU#+tZ*yx~|b1QPb4pfr(QQ|w3CdLc)1zJm^}6s`43thIl^FV`C|-h-Be40}`f z8^rz!>-lS32WV01(GqB-f5$oo(oZX}8vPKEe!@WdiL4Vp|4jQSMZEv%bGd#FGVy&+?%A8OEV*Uvr#t-Z)eUE!{@nw&Z+_#Rqo<7jaf{CK z!~g5AU!OMUnBr$vUvT*+*PVUVW6!;HWW~1^|9t#6`#yR7ho{VZC{nuW&a#JR{pY1K zK3=fTH9d#j{Lw4V{xbE_1HZcB;FfbP{9)}u@Be$;u(pm}7Eg+Px$VUB=dHMLc>n(I zHU0U6g1_%k^QX6Od;E#9=MBDg_eD=1wRGdZM%{X7c->BY!CUf9efO@D9=zj`t~ci# zS6y^d_X~4p{ObmtN4Y|9+#VH8k)VJ?4VO ziBo6JxF9%n#sw!_cT=sX^a>(HPd_2VBS(eYVpN$>2%gbl{Q1j@t6=&`@ zeNx?jr-uutWuLj@@0xJX@;Le=0 zZrOU}oPEn)y}t0&#+_dcT@RNhO7B#M4v})Cbi+XN7X61LUKeTGAHIEjST~?9Y z`{~(@$8|jwo$^WZPgk8h>F}0IUf;L9V^m)BjT_H+`G;ZMuOD;QlOIhw|E)nY_SmCn z&d@)Ns@ip@(Hk$RIANPDs!o}F#n2008hX)Hqu+exra2We?|!uR_H{aQK+4+w*6*YCtF35dj{?D6NM!szbw*BX^pH_a~bouM70gt%*uXA*J z=}~-PGsk^IegU6rsnY#}k4^U%;QW5+hwk)#wrg^E-UNR{eQ=FMd@|a$h^#dK zo*nr4qT9#O_RJ$3^m1qhvQN}@#k*$4Gwl|OU7OeunNM(EFL(MP-@G)auk`s0qOapM z`*gJDL0>V67Z>aR(vJS)7P~It_W&9HJL&&N?0KCzBeIXPaFSP-5+Lo%fP5aQ0J64Y zL{H>(O*x+q$YX!3=!<~Nmp($4ctPQDTrC#fH1I%i8pMAika^7#d&cRs*hdVWGcx=5 z+YDa0g%=YZa|l{^Yrq4=`PlFqw(xrmUb}_2(TJb0@YKm({9>S<52q~q_$v)wxrH~u z-~}zbT8SU_T_>C`eek^2=c5UIop02q({{X08jL(TExfS7b9T!<{)Gmw+`?-&ctHzq zg~4mG@Dc{E)xzsBcpVmAzwo#|`z*Y|Q@r(21l08|-93AK%7sV2H5T4j@jJor+hpO_ z8h%?Xyaw^xX!uQ7_{|2d-@;pL@JdHzAAi)~)mV6|g~vLDEWA$exSqQWzpWPj2H_X% zm;Js&f8`cEbLv2h_5tGbLdJDKPI-CuIuuOy@>W32ueI>Y!Q=H>DSTe@%@%%*!HZgW zQ-sH7#ZC(^1Rf~PbwI|x705B(1>}8gF_8D5CxN_=JqP4{?ax4tkI$}Edt|T2TJS(| z{syG~Z-DgwZy^0Ur+WT}0qK7`puXNB7QYn+FJ|FY8@z4{Z?f<>wt_u}y17;XnW8>8 zPxauj9|CebO@fqhJU9FLtR2TiZqVlsB4-=?e1=&2->l0z*bcNV!;tHG#Ru?D-^_a< z^3uFs3$NYasl77CPhULfZ-v3Dvhdalk8@rJ9_tYD@##8|MYp7N7>G1K*xRsJm6_7bp`|@H=92?_y`}{!U)L!T1#p_z_?Tx<% zNS!{+c#|dG6v630#<I9CBpKF7gpjPdJyej#$6!v7KEc$s@d;1;BsO229Sn>XA1&At2*4 z0U0YSI2Xt{xf{sq?m-~0?Il1y8!Q)m8mPwsaq3MreHZMTSqJJ5$N!ntb*&mePY(Tc zz^~@jS$N$Bui3)uH+WGCPt~U5c3ODl2G7~=x8u~~s5W@z7GACJI0r!suK_&zzFKgO z;lJ5p*JALZ7GBigby|3<4W6@q_VITbymAX~oxuxQc+MH#{P22f0*`CA#m6_-BWtA( zE$7-~qb)Hm_U84L@cDcQ|Nj}()X|PU*C($9XN-5fRRdE5oalIzl_GD(Di_=j$hkfQ z$gzwUoCq}Sc7O|lACOrOh}?tutO1XmwSrxOJ%Z~5HwbP7>ir;O@vF}Cc+9oM z!Yc!h@%Irv>)T=BPcV3W7Ty%_=qq}l{k|Qy=$U)*fkRdQ0CB1yXC2)2k8{Rq0RmD7 z>#I8<$>%ztDQ66QZ;ATsX*)COtt-xLx5OzpD0`fU#AyN2cdIWRV=-suTk7)zk+U5C zuV1g5AoS!l`*>#l%O&0l!PkL|@h*^YJ_ee6jzd2`w)*@+<=lkt9bkOso{;$6KA!fc zk#;;98E>h?TQ0Z~$g#f;=TX1M* zo#>MX{gxWMN(*m{!K=0KY7Ac3!kc37+AX}0@Hl4)3vV`f9MgOtYrPQ2S}hiP{ya#H z&0dG7*vACpf*pbh!A}Lh6#Q232f<%}tUK3Q*b+~j?d4l6SPG;a*LMtd97CVap7RB< zdyD~}oUwuvfQ&g&`jdes-(24XhyAt=|4yXWVbuV72Bp7x_+_3&=+{|zv%sUxZGv|K zIUn~+{}CYP^hxReUhqXAYw#M7&v5Sm`T437$T|E{|Np%N$o!d0>EXYv1H|q)$AHK4u?9bA;Rl6ZD}48Qx9~%T-*)iGkNNm| z{xmWl9^|qme0=I2#&_6oeC}^4jr06A0jbl6=`Vsj=&M!m86elu^U_}__$H9|>GuWy z3grBJA(#|gFZdIXep`TMJpEf#)J1%GLFBCKPOroG0D5xhukhUTJod^s`+a;JS0inC zFgC}is=c~!eevfA>p*NkCqkX9%7TsSCZGC>tA!sicpVmAoA9`v`@rK^3y#bjm$^>x z$5%4e4f)KSSn9Kb$m#sqTQ~F{gr2;5AJ6o^#^OKhv!nm*H>THRbO1d$^xrMxWUif( zN3V~s^Uz3J9?Y4|nUGl*iYDWGiMSqk%~eA0j?c%-@Hf?4PX&To16i9Lfn1X#fF|F( z?}mMTL3cjM!T0INbr~H%PY(T!fnW06@mqK`;L+w3;d49%NBwr(tpJwpruieKt^Qi!zoH3Ss;y!!Oou9V# z^5Ht`lQ_l4WFL2p#0d)4`r>iy%-J2k&kw{-C%$(}kE;%P)+_Aend733KD3;^*=S2_ z7kjhzF`v)F@cmw(rjC=)XC8b8=>?a5%4@QZyGh0y7Mu&@SnmdMybl6d!zDnSC%W#t z3GNN_U+wcx{a}3m81tY$G=QEQ`dbdaEWF7Eui3(@H+WGCZlXPp*a1UwF^1;~1| ziXG=z9p|mrN+3D<;P~~qiCRuSYwP|-!S}?OzSg48dEk7ufJ=XIpN)=3 zySR+wEg<8305tXHb=v9kL;K_R^5T(KaJ(0<6iA&uOn*H-|K@nBe0H>dNBomlKY*Sb z`tOHdz3w9xUg0!v-nIwo^%}SED-2$*g;#Cx)Wpp3Ge;iGbF%QbPO8A;xN3cT^2p~= z4?Z~|peZ-kM961PyIOolAIHZyttl8<269 z3O)~HO;-xO4m9n|pVt(em^n`RJ?>zy9?YX^06jVM*9pHo?-uL@GLJqWueE+b=K_yc zAc!x(a_h}|NsGmQneZ!sti>3?!-4dFG?3#wQLq-Mua`cH-v)zMe9~{n50~!vW($uo zsx7=0@M!ZGka<1}WF1}*d&k5h!tbrc4lb%^`y$b;BD>cJ-`1Z0dRAm=$Oaw6{;l$&Z^DQQ`4@LmhbZANTRiJn5U`TMavM*9fi^>=Nt|Tqn3e za3hdDcxb=$$9E!pAHwrqiO)XYjZoI_%jwlgnfu?n=ySZxsr=;Z^-(jt_{Bi-Iqq8U z86)Pi)A>Q=RDe&;7$9Se1#(^|0C{aq6g&;cxjYBRy^w2atp7`-~}zb6$Y=#!b=#uRtvAk;B{Dd{RXek!Yiy#kGFVo z_PUe`k8@US;f(>0^K!Vs4_Wv@@Hi!B37>1B)xr;n|0W>kGAwpH@3h!0G9@(}7b0ghzE@XYf9(=K=HqF9 z8fnLaKG_mJK6S(K-Mo5TJEvtI|3>6X9&<0Z@YIFgyzK;J%-w+;|Gq#Sr`}>eL3o_+ z2zd0-?&F)|s|DZelh1g>xX%tEr~YzpysUMf_%A&@bKIuC2KcA1SwQ-oE&WDcT-Jqi zNN$zSA4JaLnd$kfA3#qI#r&s%}IUM&{>a^W$zICzYo@bUF{G}1p0a@l%)eCqCN z^z!9;FRu0c27%P+!}PZndC*sv;MYLT;lF^a&5uBnZ?5-xpI`bv@S60xY#BgL4*eBe zlwOx{3$Fw`+Kd7+&;6u-h}cu+oRK*`ig+;2M1xmu;nf+upoP~cJkDDac#Pld<1?;~ zPt*swY^^>%^`mc2*DW!Co*epJDDgQr{Sv?U%*^rY__S#UpE09AQ_lQ3&(u}=>>+Y~ zH#@zK>YyjD#m6)Kt(G`z1V0AS|K~vF`Zdtxo9ig*^9#Cj3%*;M*AesVmiT=>p7y7a zc08CXTfteGb)oJb;+OiW0rce1U*KYIeKLNXg;xw7ZAJ>8ej^rsmGD@b7Ukjv8AEv)L_@}RWApM4b%&iH?c?(Ow8ED#> z&*dSXf0#L4`2KR{!F{Mz^62#OOn-~vpLw(ana5JW=Yh;)CD7!X>!;7>7j);JcX{#Y zv-IrD@l(%({u1!3_v;!9ugBnpEWC}vW6mw$aV#+(-y8??(1(^YXEr_0-D1zazGnM; zK6iW|^SOUF^mYA9&yjTi)Uk*<9?we}y!w|3js`N;fk2MsaG=RI>mTy@rN1@!K6=Jy z&aDzZ>f>pD8fnKvkH5pmr*3b2w>|xG{q+x^Cx`x~NWQZLrwKL)HVV!Hrsn_L%=*w5 z5Bh5n9%~Y^@Rou{o8^Kl4ZC)WT|)Su0y+M##g6ssw%BbHyTO-u<6wTOF8er2zyrl8 z12Rs9*l|8c1{4|&K{rt9 zS|ncF$1~$~Nt_-a$G*-IuhZv;@eaY?QqXlTIM3T}%7N7B!;Gh8L@n3#V|<MaY_Vt2eQ7Sft<4gfxOla2b%W0 zukaqnIDNi25IHa4Z%ydyy7c_adQi`U{(|sJ9(~nVc+wo2CsBl_VI5tcr_NDx-318kcC%f@LDXqDuWld z@Fp6(UJI|z;He9;kGD~HoVzLuZ$5aO$NLSx^%nk8gBP*z;zs18ge;|~e$0`f2Sa@99b>MN$H~IKn->eaj3h>Q7`K&Q9;3zO$06jVMw-$bR-X(E*fQ-8isQ01D`t0>^F86rMr`EzN z0*`S@fXul}`W0f&`#_7ueuD5P3QiWB0_2*T0b~xBiTrB8n*|pD^>~~MvyZ1$c&tG= zc+9oR$Jg_q5ft|zmo4byQ<=cujA4Ad%(Is`uea-5$4InKWWO+MEG z*BEUQKEDt--)~H>2j?PhT%|zj^kMqjAaOVP;;=5vgK?^S_VlxAQ~ElsA3#qI!CK|j- z3$M=L)mnIs!eh9gtH4J;zh;eTVEE?Dxrd`+)Ge?`9@J@JwHG{HU7)8kH1m!W!-DQW9%j$U+2Yqo56SI z7|48D1eX9!9>>o$>~eknAa+I5vT;e8tJnc^-?Re<=^!oVJT_=9YDGp^HcO3b$ zKK!2UYVgQ+F3;qfao2)RPM3_g2gtR(PH+Q|n8;a={gXtAVV;8tJbU>;md_8MDOe6CQnZgU9^U%vk>JiivmWNUEcf|?ne%u2Z8+w~xvYhral<~I>8}$0X?KXk8}Ex}?!PTQKeT(R zJbj&Z44@~6@g~Esu3MjlS1&xqExsbNUi8I-{$_#4^VQD&ObuPcko98MZ%u|P+H;r1s zTCoLveCikA?<&$S=Q%8X+kHIKUxnmzAdtBq4m9=VJ`wl%VZ86grT2-x0rce1Ur@%& zyo;~S949$E$eU*Hsx7=GgI90i%@-c8rwDkA-{IpkF5~lP1)rRDAnOs8eq1mHH2LQB z)a~<2e|Maiu8(TUKJK;f%XwqHt1P@;@aVTs^63{lUVkBrUEwvJ-S$9^Z#N*vw?B|^ zX&;3>WeJ}jbG%Te4lSoYHrf*V#h!hRhq8ieGRJ-a{%$A4spD$&Q{xAhHbI|_jz^O@lsr@|$YY>n%Kho*c$m0l%y_?*;7^UPAKd1hU56K<3a3 z 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 Bo>c$< literal 0 HcmV?d00001 diff --git a/BizHawk.Util/7z/ArchiveEmulationStreamProxy.cs b/BizHawk.Util/7z/ArchiveEmulationStreamProxy.cs new file mode 100644 index 0000000000..c0bdaed292 --- /dev/null +++ b/BizHawk.Util/7z/ArchiveEmulationStreamProxy.cs @@ -0,0 +1,101 @@ +using System.IO; +using System; + +namespace SevenZip +{ + ///

+ /// The Stream extension class to emulate the archive part of a stream. + /// + internal class ArchiveEmulationStreamProxy : Stream, IDisposable + { + /// + /// Gets the file offset. + /// + public int Offset { get; private set; } + + /// + /// The source wrapped stream. + /// + public Stream Source { get; private set; } + + /// + /// Initializes a new instance of the ArchiveEmulationStream class. + /// + /// The stream to wrap. + /// The stream offset. + public ArchiveEmulationStreamProxy(Stream stream, int offset) + { + Source = stream; + Offset = offset; + Source.Position = offset; + } + + public override bool CanRead + { + get { return Source.CanRead; } + } + + public override bool CanSeek + { + get { return Source.CanSeek; } + } + + public override bool CanWrite + { + get { return Source.CanWrite; } + } + + public override void Flush() + { + Source.Flush(); + } + + public override long Length + { + get { return Source.Length - Offset; } + } + + public override long Position + { + get + { + return Source.Position - Offset; + } + set + { + Source.Position = value; + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + return Source.Read(buffer, offset, count); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return Source.Seek(origin == SeekOrigin.Begin ? offset + Offset : offset, + origin) - Offset; + } + + public override void SetLength(long value) + { + Source.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + Source.Write(buffer, offset, count); + } + + public new void Dispose() + { + Source.Dispose(); + } + + public override void Close() + { + Source.Close(); + } + } +} diff --git a/BizHawk.Util/7z/ArchiveExtractCallback.cs b/BizHawk.Util/7z/ArchiveExtractCallback.cs new file mode 100644 index 0000000000..d9aedc0f7a --- /dev/null +++ b/BizHawk.Util/7z/ArchiveExtractCallback.cs @@ -0,0 +1,602 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +#if MONO +using SevenZip.Mono.COM; +using System.Runtime.InteropServices; +#endif + +namespace SevenZip +{ +#if UNMANAGED + /// + /// Archive extraction callback to handle the process of unpacking files + /// + internal sealed class ArchiveExtractCallback : CallbackBase, IArchiveExtractCallback, ICryptoGetTextPassword, + IDisposable + { + private List _actualIndexes; + private IInArchive _archive; + + /// + /// For Compressing event. + /// + private long _bytesCount; + + private long _bytesWritten; + private long _bytesWrittenOld; + private string _directory; + + /// + /// Rate of the done work from [0, 1]. + /// + private float _doneRate; + + private SevenZipExtractor _extractor; + private FakeOutStreamWrapper _fakeStream; + private uint? _fileIndex; + private int _filesCount; + private OutStreamWrapper _fileStream; + private bool _directoryStructure; + private int _currentIndex; +#if !WINCE + const int MEMORY_PRESSURE = 64 * 1024 * 1024; //64mb seems to be the maximum value +#endif + #region Constructors + + /// + /// Initializes a new instance of the ArchiveExtractCallback class + /// + /// IInArchive interface for the archive + /// Directory where files are to be unpacked to + /// The archive files count' + /// The owner of the callback + /// The list of actual indexes (solid archives support) + /// The value indicating whether to preserve directory structure of extracted files. + public ArchiveExtractCallback(IInArchive archive, string directory, int filesCount, bool directoryStructure, + List actualIndexes, SevenZipExtractor extractor) + { + Init(archive, directory, filesCount, directoryStructure, actualIndexes, extractor); + } + + /// + /// Initializes a new instance of the ArchiveExtractCallback class + /// + /// IInArchive interface for the archive + /// Directory where files are to be unpacked to + /// The archive files count + /// Password for the archive + /// The owner of the callback + /// The list of actual indexes (solid archives support) + /// The value indicating whether to preserve directory structure of extracted files. + public ArchiveExtractCallback(IInArchive archive, string directory, int filesCount, bool directoryStructure, + List actualIndexes, string password, SevenZipExtractor extractor) + : base(password) + { + Init(archive, directory, filesCount, directoryStructure, actualIndexes, extractor); + } + + /// + /// Initializes a new instance of the ArchiveExtractCallback class + /// + /// IInArchive interface for the archive + /// The stream where files are to be unpacked to + /// The archive files count + /// The file index for the stream + /// The owner of the callback + public ArchiveExtractCallback(IInArchive archive, Stream stream, int filesCount, uint fileIndex, + SevenZipExtractor extractor) + { + Init(archive, stream, filesCount, fileIndex, extractor); + } + + /// + /// Initializes a new instance of the ArchiveExtractCallback class + /// + /// IInArchive interface for the archive + /// The stream where files are to be unpacked to + /// The archive files count + /// The file index for the stream + /// Password for the archive + /// The owner of the callback + public ArchiveExtractCallback(IInArchive archive, Stream stream, int filesCount, uint fileIndex, string password, + SevenZipExtractor extractor) + : base(password) + { + Init(archive, stream, filesCount, fileIndex, extractor); + } + + private void Init(IInArchive archive, string directory, int filesCount, bool directoryStructure, + List actualIndexes, SevenZipExtractor extractor) + { + CommonInit(archive, filesCount, extractor); + _directory = directory; + _actualIndexes = actualIndexes; + _directoryStructure = directoryStructure; + if (!directory.EndsWith("" + Path.DirectorySeparatorChar, StringComparison.CurrentCulture)) + { + _directory += Path.DirectorySeparatorChar; + } + } + + private void Init(IInArchive archive, Stream stream, int filesCount, uint fileIndex, SevenZipExtractor extractor) + { + CommonInit(archive, filesCount, extractor); + _fileStream = new OutStreamWrapper(stream, false); + _fileStream.BytesWritten += IntEventArgsHandler; + _fileIndex = fileIndex; + } + + private void CommonInit(IInArchive archive, int filesCount, SevenZipExtractor extractor) + { + _archive = archive; + _filesCount = filesCount; + _fakeStream = new FakeOutStreamWrapper(); + _fakeStream.BytesWritten += IntEventArgsHandler; + _extractor = extractor; +#if !WINCE + GC.AddMemoryPressure(MEMORY_PRESSURE); +#endif + } + #endregion + + #region Events + + /// + /// Occurs when a new file is going to be unpacked + /// + /// Occurs when 7-zip engine requests for an output stream for a new file to unpack in + public event EventHandler FileExtractionStarted; + + /// + /// Occurs when a file has been successfully unpacked + /// + public event EventHandler FileExtractionFinished; + + /// + /// Occurs when the archive is opened and 7-zip sends the size of unpacked data + /// + public event EventHandler Open; + + /// + /// Occurs when the extraction is performed + /// + public event EventHandler Extracting; + + /// + /// Occurs during the extraction when a file already exists + /// + public event EventHandler FileExists; + + private void OnFileExists(FileOverwriteEventArgs e) + { + if (FileExists != null) + { + FileExists(this, e); + } + } + + private void OnOpen(OpenEventArgs e) + { + if (Open != null) + { + Open(this, e); + } + } + + private void OnFileExtractionStarted(FileInfoEventArgs e) + { + if (FileExtractionStarted != null) + { + FileExtractionStarted(this, e); + } + } + + private void OnFileExtractionFinished(FileInfoEventArgs e) + { + if (FileExtractionFinished != null) + { + FileExtractionFinished(this, e); + } + } + + private void OnExtracting(ProgressEventArgs e) + { + if (Extracting != null) + { + Extracting(this, e); + } + } + + private void IntEventArgsHandler(object sender, IntEventArgs e) + { + var pold = (int)((_bytesWrittenOld * 100) / _bytesCount); + _bytesWritten += e.Value; + var pnow = (int)((_bytesWritten * 100) / _bytesCount); + if (pnow > pold) + { + if (pnow > 100) + { + pold = pnow = 0; + } + _bytesWrittenOld = _bytesWritten; + OnExtracting(new ProgressEventArgs((byte)pnow, (byte)(pnow - pold))); + } + } + + #endregion + + #region IArchiveExtractCallback Members + + /// + /// Gives the size of the unpacked archive files + /// + /// Size of the unpacked archive files (in bytes) + public void SetTotal(ulong total) + { + _bytesCount = (long)total; + OnOpen(new OpenEventArgs(total)); + } + + public void SetCompleted(ref ulong completeValue) { } + + /// + /// Sets output stream for writing unpacked data + /// + /// Current file index + /// Output stream pointer + /// Extraction mode + /// 0 if OK + public int GetStream(uint index, out +#if !MONO + ISequentialOutStream +#else + HandleRef +#endif + outStream, AskMode askExtractMode) + { +#if !MONO + outStream = null; +#else + outStream = new System.Runtime.InteropServices.HandleRef(null, IntPtr.Zero); +#endif + if (Canceled) + { + return -1; + } + _currentIndex = (int)index; + if (askExtractMode == AskMode.Extract) + { + var fileName = _directory; + if (!_fileIndex.HasValue) + { + #region Extraction to a file + + if (_actualIndexes == null || _actualIndexes.Contains(index)) + { + var data = new PropVariant(); + _archive.GetProperty(index, ItemPropId.Path, ref data); + string entryName = NativeMethods.SafeCast(data, ""); + + #region Get entryName + + if (String.IsNullOrEmpty(entryName)) + { + if (_filesCount == 1) + { + var archName = Path.GetFileName(_extractor.FileName); + archName = archName.Substring(0, archName.LastIndexOf('.')); + if (!archName.EndsWith(".tar", StringComparison.OrdinalIgnoreCase)) + { + archName += ".tar"; + } + entryName = archName; + } + else + { + entryName = "[no name] " + index.ToString(CultureInfo.InvariantCulture); + } + } + + #endregion + + fileName = Path.Combine(_directory, _directoryStructure? entryName : Path.GetFileName(entryName)); + _archive.GetProperty(index, ItemPropId.IsDirectory, ref data); + try + { + fileName = ValidateFileName(fileName); + } + catch (Exception e) + { + AddException(e); + goto FileExtractionStartedLabel; + } + if (!NativeMethods.SafeCast(data, false)) + { + #region Branch + + _archive.GetProperty(index, ItemPropId.LastWriteTime, ref data); + var time = NativeMethods.SafeCast(data, DateTime.MinValue); + if (File.Exists(fileName)) + { + var fnea = new FileOverwriteEventArgs(fileName); + OnFileExists(fnea); + if (fnea.Cancel) + { + Canceled = true; + return -1; + } + if (String.IsNullOrEmpty(fnea.FileName)) + { +#if !MONO + outStream = _fakeStream; +#else + outStream = _fakeStream.Handle; +#endif + goto FileExtractionStartedLabel; + } + fileName = fnea.FileName; + } + try + { + _fileStream = new OutStreamWrapper(File.Create(fileName), fileName, time, true); + } + catch (Exception e) + { + if (e is FileNotFoundException) + { + AddException( + new IOException("The file \"" + fileName + + "\" was not extracted due to the File.Create fail.")); + } + else + { + AddException(e); + } + outStream = _fakeStream; + goto FileExtractionStartedLabel; + } + _fileStream.BytesWritten += IntEventArgsHandler; + outStream = _fileStream; + + #endregion + } + else + { + #region Branch + + if (!Directory.Exists(fileName)) + { + try + { + Directory.CreateDirectory(fileName); + } + catch (Exception e) + { + AddException(e); + } + outStream = _fakeStream; + } + + #endregion + } + } + else + { + outStream = _fakeStream; + } + + #endregion + } + else + { + #region Extraction to a stream + + if (index == _fileIndex) + { + outStream = _fileStream; + _fileIndex = null; + } + else + { + outStream = _fakeStream; + } + + #endregion + } + + FileExtractionStartedLabel: + _doneRate += 1.0f / _filesCount; + var iea = new FileInfoEventArgs( + _extractor.ArchiveFileData[(int)index], PercentDoneEventArgs.ProducePercentDone(_doneRate)); + OnFileExtractionStarted(iea); + if (iea.Cancel) + { + if (!String.IsNullOrEmpty(fileName)) + { + _fileStream.Dispose(); + if (File.Exists(fileName)) + { + try + { + File.Delete(fileName); + } + catch (Exception e) + { + AddException(e); + } + } + } + Canceled = true; + return -1; + } + } + return 0; + } + + public void PrepareOperation(AskMode askExtractMode) { } + + /// + /// Called when the archive was extracted + /// + /// + public void SetOperationResult(OperationResult operationResult) + { + if (operationResult != OperationResult.Ok && ReportErrors) + { + switch (operationResult) + { + case OperationResult.CrcError: + AddException(new ExtractionFailedException("File is corrupted. Crc check has failed.")); + break; + case OperationResult.DataError: + AddException(new ExtractionFailedException("File is corrupted. Data error has occured.")); + break; + case OperationResult.UnsupportedMethod: + AddException(new ExtractionFailedException("Unsupported method error has occured.")); + break; + } + } + else + { + if (_fileStream != null && !_fileIndex.HasValue) + { + try + { + _fileStream.BytesWritten -= IntEventArgsHandler; + _fileStream.Dispose(); + } + catch (ObjectDisposedException) { } + _fileStream = null; + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + var iea = new FileInfoEventArgs( + _extractor.ArchiveFileData[_currentIndex], PercentDoneEventArgs.ProducePercentDone(_doneRate)); + OnFileExtractionFinished(iea); + if (iea.Cancel) + { + Canceled = true; + } + } + } + + #endregion + + #region ICryptoGetTextPassword Members + + /// + /// Sets password for the archive + /// + /// Password for the archive + /// Zero if everything is OK + public int CryptoGetTextPassword(out string password) + { + password = Password; + return 0; + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { +#if !WINCE + GC.RemoveMemoryPressure(MEMORY_PRESSURE); +#endif + if (_fileStream != null) + { + try + { + _fileStream.Dispose(); + } + catch (ObjectDisposedException) { } + _fileStream = null; + } + if (_fakeStream != null) + { + try + { + _fakeStream.Dispose(); + } + catch (ObjectDisposedException) { } + _fakeStream = null; + } + } + + #endregion + + /// + /// Validates the file name and ensures that the directory to the file name is valid and creates intermediate directories if necessary + /// + /// File name + /// The valid file name + private static string ValidateFileName(string fileName) + { + if (String.IsNullOrEmpty(fileName)) + { + throw new SevenZipArchiveException("some archive name is null or empty."); + } + var splittedFileName = new List(fileName.Split(Path.DirectorySeparatorChar)); +#if !WINCE + foreach (char chr in Path.GetInvalidFileNameChars()) + { + for (int i = 0; i < splittedFileName.Count; i++) + { + if (chr == ':' && i == 0) + { + continue; + } + if (String.IsNullOrEmpty(splittedFileName[i])) + { + continue; + } + while (splittedFileName[i].IndexOf(chr) > -1) + { + splittedFileName[i] = splittedFileName[i].Replace(chr, '_'); + } + } + } +#endif + if (fileName.StartsWith(new string(Path.DirectorySeparatorChar, 2), + StringComparison.CurrentCultureIgnoreCase)) + { + splittedFileName.RemoveAt(0); + splittedFileName.RemoveAt(0); + splittedFileName[0] = new string(Path.DirectorySeparatorChar, 2) + splittedFileName[0]; + } + if (splittedFileName.Count > 2) + { + string tfn = splittedFileName[0]; + for (int i = 1; i < splittedFileName.Count - 1; i++) + { + tfn += Path.DirectorySeparatorChar + splittedFileName[i]; + if (!Directory.Exists(tfn)) + { + Directory.CreateDirectory(tfn); + } + } + } + return String.Join(new string(Path.DirectorySeparatorChar, 1), splittedFileName.ToArray()); + } + } +#endif +} diff --git a/BizHawk.Util/7z/ArchiveOpenCallback.cs b/BizHawk.Util/7z/ArchiveOpenCallback.cs new file mode 100644 index 0000000000..d870be30bb --- /dev/null +++ b/BizHawk.Util/7z/ArchiveOpenCallback.cs @@ -0,0 +1,192 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +#if MONO +using SevenZip.Mono; +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ + #if UNMANAGED + /// + /// Callback to handle the archive opening + /// + internal sealed class ArchiveOpenCallback : CallbackBase, IArchiveOpenCallback, IArchiveOpenVolumeCallback, + ICryptoGetTextPassword, IDisposable + { + private FileInfo _fileInfo; + private Dictionary _wrappers = + new Dictionary(); + public readonly List VolumeFileNames = new List(); + + /// + /// Performs the common initialization. + /// + /// Volume file name. + private void Init(string fileName) + { + if (!String.IsNullOrEmpty(fileName)) + { + _fileInfo = new FileInfo(fileName); + VolumeFileNames.Add(fileName); + } + } + + /// + /// Initializes a new instance of the ArchiveOpenCallback class. + /// + /// The archive file name. + public ArchiveOpenCallback(string fileName) + { + Init(fileName); + } + + /// + /// Initializes a new instance of the ArchiveOpenCallback class. + /// + /// The archive file name. + /// Password for the archive. + public ArchiveOpenCallback(string fileName, string password) : base(password) + { + Init(fileName); + } + + #region IArchiveOpenCallback Members + + public void SetTotal(IntPtr files, IntPtr bytes) {} + + public void SetCompleted(IntPtr files, IntPtr bytes) {} + + #endregion + + #region IArchiveOpenVolumeCallback Members + + public int GetProperty(ItemPropId propId, ref PropVariant value) + { + switch (propId) + { + case ItemPropId.Name: + value.VarType = VarEnum.VT_BSTR; + value.Value = Marshal.StringToBSTR(_fileInfo.FullName); + break; + case ItemPropId.IsDirectory: + value.VarType = VarEnum.VT_BOOL; + value.UInt64Value = (byte) (_fileInfo.Attributes & FileAttributes.Directory); + break; + case ItemPropId.Size: + value.VarType = VarEnum.VT_UI8; + value.UInt64Value = (UInt64) _fileInfo.Length; + break; + case ItemPropId.Attributes: + value.VarType = VarEnum.VT_UI4; + value.UInt32Value = (uint) _fileInfo.Attributes; + break; + case ItemPropId.CreationTime: + value.VarType = VarEnum.VT_FILETIME; + value.Int64Value = _fileInfo.CreationTime.ToFileTime(); + break; + case ItemPropId.LastAccessTime: + value.VarType = VarEnum.VT_FILETIME; + value.Int64Value = _fileInfo.LastAccessTime.ToFileTime(); + break; + case ItemPropId.LastWriteTime: + value.VarType = VarEnum.VT_FILETIME; + value.Int64Value = _fileInfo.LastWriteTime.ToFileTime(); + break; + } + return 0; + } + + public int GetStream(string name, out IInStream inStream) + { + if (!File.Exists(name)) + { + name = Path.Combine(Path.GetDirectoryName(_fileInfo.FullName), name); + if (!File.Exists(name)) + { + inStream = null; + AddException(new FileNotFoundException("The volume \"" + name + "\" was not found. Extraction can be impossible.")); + return 1; + } + } + VolumeFileNames.Add(name); + if (_wrappers.ContainsKey(name)) + { + inStream = _wrappers[name]; + } + else + { + try + { + var wrapper = new InStreamWrapper( + new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), true); + _wrappers.Add(name, wrapper); + inStream = wrapper; + } + catch (Exception) + { + AddException(new FileNotFoundException("Failed to open the volume \"" + name + "\". Extraction is impossible.")); + inStream = null; + return 1; + } + } + return 0; + } + + #endregion + + #region ICryptoGetTextPassword Members + + /// + /// Sets password for the archive + /// + /// Password for the archive + /// Zero if everything is OK + public int CryptoGetTextPassword(out string password) + { + password = Password; + return 0; + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + if (_wrappers != null) + { + foreach (InStreamWrapper wrap in _wrappers.Values) + { + wrap.Dispose(); + } + _wrappers = null; + } +#if MONO + libp7zInvokerRaw.FreeObject(Handle); +#endif + GC.SuppressFinalize(this); + } + + #endregion + } +#endif +} diff --git a/BizHawk.Util/7z/ArchiveUpdateCallback.cs b/BizHawk.Util/7z/ArchiveUpdateCallback.cs new file mode 100644 index 0000000000..9e8be21990 --- /dev/null +++ b/BizHawk.Util/7z/ArchiveUpdateCallback.cs @@ -0,0 +1,806 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ +#if UNMANAGED +#if COMPRESS + /// + /// Archive update callback to handle the process of packing files + /// + internal sealed class ArchiveUpdateCallback : CallbackBase, IArchiveUpdateCallback, ICryptoGetTextPassword2, + IDisposable + { + #region Fields + /// + /// _files.Count if do not count directories + /// + private int _actualFilesCount; + + /// + /// For Compressing event. + /// + private long _bytesCount; + + private long _bytesWritten; + private long _bytesWrittenOld; + private SevenZipCompressor _compressor; + + /// + /// No directories. + /// + private bool _directoryStructure; + + /// + /// Rate of the done work from [0, 1] + /// + private float _doneRate; + + /// + /// The names of the archive entries + /// + private string[] _entries; + + /// + /// Array of files to pack + /// + private FileInfo[] _files; + + private InStreamWrapper _fileStream; + + private uint _indexInArchive; + private uint _indexOffset; + + /// + /// Common root of file names length. + /// + private int _rootLength; + + /// + /// Input streams to be compressed. + /// + private Stream[] _streams; + + private UpdateData _updateData; + private List _wrappersToDispose; + + /// + /// Gets or sets the default item name used in MemoryStream compression. + /// + public string DefaultItemName { private get; set; } + + /// + /// Gets or sets the value indicating whether to compress as fast as possible, without calling events. + /// + public bool FastCompression { private get; set; } +#if !WINCE + private int _memoryPressure; +#endif + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the ArchiveUpdateCallback class + /// + /// Array of files to pack + /// Common file names root length + /// The owner of the callback + /// The compression parameters. + /// Preserve directory structure. + public ArchiveUpdateCallback( + FileInfo[] files, int rootLength, + SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + { + Init(files, rootLength, compressor, updateData, directoryStructure); + } + + /// + /// Initializes a new instance of the ArchiveUpdateCallback class + /// + /// Array of files to pack + /// Common file names root length + /// The archive password + /// The owner of the callback + /// The compression parameters. + /// Preserve directory structure. + public ArchiveUpdateCallback( + FileInfo[] files, int rootLength, string password, + SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + : base(password) + { + Init(files, rootLength, compressor, updateData, directoryStructure); + } + + /// + /// Initializes a new instance of the ArchiveUpdateCallback class + /// + /// The input stream + /// The owner of the callback + /// The compression parameters. + /// Preserve directory structure. + public ArchiveUpdateCallback( + Stream stream, SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + { + Init(stream, compressor, updateData, directoryStructure); + } + + /// + /// Initializes a new instance of the ArchiveUpdateCallback class + /// + /// The input stream + /// The archive password + /// The owner of the callback + /// The compression parameters. + /// Preserve directory structure. + public ArchiveUpdateCallback( + Stream stream, string password, SevenZipCompressor compressor, UpdateData updateData, + bool directoryStructure) + : base(password) + { + Init(stream, compressor, updateData, directoryStructure); + } + + /// + /// Initializes a new instance of the ArchiveUpdateCallback class + /// + /// Dictionary<file stream, name of the archive entry> + /// The owner of the callback + /// The compression parameters. + /// Preserve directory structure. + public ArchiveUpdateCallback( + Dictionary streamDict, + SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + { + Init(streamDict, compressor, updateData, directoryStructure); + } + + /// + /// Initializes a new instance of the ArchiveUpdateCallback class + /// + /// Dictionary<file stream, name of the archive entry> + /// The archive password + /// The owner of the callback + /// The compression parameters. + /// Preserve directory structure. + public ArchiveUpdateCallback( + Dictionary streamDict, string password, + SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + : base(password) + { + Init(streamDict, compressor, updateData, directoryStructure); + } + + private void CommonInit(SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + { + _compressor = compressor; + _indexInArchive = updateData.FilesCount; + _indexOffset = updateData.Mode != InternalCompressionMode.Append ? 0 : _indexInArchive; + if (_compressor.ArchiveFormat == OutArchiveFormat.Zip) + { + _wrappersToDispose = new List(); + } + _updateData = updateData; + _directoryStructure = directoryStructure; + DefaultItemName = "default"; + } + + private void Init( + FileInfo[] files, int rootLength, SevenZipCompressor compressor, + UpdateData updateData, bool directoryStructure) + { + _files = files; + _rootLength = rootLength; + if (files != null) + { + foreach (var fi in files) + { + if (fi.Exists) + { + _bytesCount += fi.Length; + if ((fi.Attributes & FileAttributes.Directory) == 0) + { + _actualFilesCount++; + } + } + } + } + CommonInit(compressor, updateData, directoryStructure); + } + + private void Init( + Stream stream, SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + { + _fileStream = new InStreamWrapper(stream, false); + _fileStream.BytesRead += IntEventArgsHandler; + _actualFilesCount = 1; + try + { + _bytesCount = stream.Length; + } + catch (NotSupportedException) + { + _bytesCount = -1; + } + try + { + stream.Seek(0, SeekOrigin.Begin); + } + catch (NotSupportedException) + { + _bytesCount = -1; + } + CommonInit(compressor, updateData, directoryStructure); + } + + private void Init( + Dictionary streamDict, + SevenZipCompressor compressor, UpdateData updateData, bool directoryStructure) + { + _streams = new Stream[streamDict.Count]; + streamDict.Values.CopyTo(_streams, 0); + _entries = new string[streamDict.Count]; + streamDict.Keys.CopyTo(_entries, 0); + _actualFilesCount = streamDict.Count; + foreach (Stream str in _streams) + { + if (str != null) + { + _bytesCount += str.Length; + } + } + CommonInit(compressor, updateData, directoryStructure); + } + + #endregion + + /// + /// Gets or sets the dictionary size. + /// + public float DictionarySize + { + set + { +#if !WINCE + _memoryPressure = (int)(value * 1024 * 1024); + GC.AddMemoryPressure(_memoryPressure); +#endif + } + } + + /// + /// Raises events for the GetStream method. + /// + /// The current item index. + /// True if not cancelled; otherwise, false. + private bool EventsForGetStream(uint index) + { + if (!FastCompression) + { + if (_fileStream != null) + { + _fileStream.BytesRead += IntEventArgsHandler; + } + _doneRate += 1.0f / _actualFilesCount; + var fiea = new FileNameEventArgs(_files != null? _files[index].Name : _entries[index], + PercentDoneEventArgs.ProducePercentDone(_doneRate)); + OnFileCompression(fiea); + if (fiea.Cancel) + { + Canceled = true; + return false; + } + } + return true; + } + + #region Events + + /// + /// Occurs when the next file is going to be packed. + /// + /// Occurs when 7-zip engine requests for an input stream for the next file to pack it + public event EventHandler FileCompressionStarted; + + /// + /// Occurs when data are being compressed. + /// + public event EventHandler Compressing; + + /// + /// Occurs when the current file was compressed. + /// + public event EventHandler FileCompressionFinished; + + private void OnFileCompression(FileNameEventArgs e) + { + if (FileCompressionStarted != null) + { + FileCompressionStarted(this, e); + } + } + + private void OnCompressing(ProgressEventArgs e) + { + if (Compressing != null) + { + Compressing(this, e); + } + } + + private void OnFileCompressionFinished(EventArgs e) + { + if (FileCompressionFinished != null) + { + FileCompressionFinished(this, e); + } + } + + #endregion + + #region IArchiveUpdateCallback Members + + public void SetTotal(ulong total) {} + + public void SetCompleted(ref ulong completeValue) {} + + public int GetUpdateItemInfo(uint index, ref int newData, ref int newProperties, ref uint indexInArchive) + { + switch (_updateData.Mode) + { + case InternalCompressionMode.Create: + newData = 1; + newProperties = 1; + indexInArchive = UInt32.MaxValue; + break; + case InternalCompressionMode.Append: + if (index < _indexInArchive) + { + newData = 0; + newProperties = 0; + indexInArchive = index; + } + else + { + newData = 1; + newProperties = 1; + indexInArchive = UInt32.MaxValue; + } + break; + case InternalCompressionMode.Modify: + newData = 0; + newProperties = Convert.ToInt32(_updateData.FileNamesToModify.ContainsKey((int)index) + && _updateData.FileNamesToModify[(int)index] != null); + if (_updateData.FileNamesToModify.ContainsKey((int)index) + && _updateData.FileNamesToModify[(int)index] == null) + { + indexInArchive = (UInt32)_updateData.ArchiveFileData.Count; + foreach (KeyValuePair pairModification in _updateData.FileNamesToModify) + if ((pairModification.Key <= index) && (pairModification.Value == null)) + { + do + { + indexInArchive--; + } + while ((indexInArchive > 0) && _updateData.FileNamesToModify.ContainsKey((Int32)indexInArchive) + && (_updateData.FileNamesToModify[(Int32)indexInArchive] == null)); + } + } + else + { + indexInArchive = index; + } + break; + } + return 0; + } + + public int GetProperty(uint index, ItemPropId propID, ref PropVariant value) + { + index -= _indexOffset; + try + { + switch (propID) + { + case ItemPropId.IsAnti: + value.VarType = VarEnum.VT_BOOL; + value.UInt64Value = 0; + break; + case ItemPropId.Path: + #region Path + + value.VarType = VarEnum.VT_BSTR; + string val = DefaultItemName; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + if (_files == null) + { + if (_entries != null) + { + val = _entries[index]; + } + } + else + { + if (_directoryStructure) + { + if (_rootLength > 0) + { + val = _files[index].FullName.Substring(_rootLength); + } + else + { + val = _files[index].FullName[0] + _files[index].FullName.Substring(2); + } + } + else + { + val = _files[index].Name; + } + } + } + else + { + val = _updateData.FileNamesToModify[(int) index]; + } + value.Value = Marshal.StringToBSTR(val); + #endregion + break; + case ItemPropId.IsDirectory: + value.VarType = VarEnum.VT_BOOL; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + if (_files == null) + { + if (_streams == null) + { + value.UInt64Value = 0; + } + else + { + value.UInt64Value = (ulong)(_streams[index] == null ? 1 : 0); + } + } + else + { + value.UInt64Value = (byte)(_files[index].Attributes & FileAttributes.Directory); + } + } + else + { + value.UInt64Value = Convert.ToUInt64(_updateData.ArchiveFileData[(int) index].IsDirectory); + } + break; + case ItemPropId.Size: + #region Size + + value.VarType = VarEnum.VT_UI8; + UInt64 size; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + if (_files == null) + { + if (_streams == null) + { + size = _bytesCount > 0 ? (ulong) _bytesCount : 0; + } + else + { + size = (ulong) (_streams[index] == null? 0 : _streams[index].Length); + } + } + else + { + size = (_files[index].Attributes & FileAttributes.Directory) == 0 + ? (ulong) _files[index].Length + : 0; + } + } + else + { + size = _updateData.ArchiveFileData[(int) index].Size; + } + value.UInt64Value = size; + + #endregion + break; + case ItemPropId.Attributes: + value.VarType = VarEnum.VT_UI4; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + if (_files == null) + { + if (_streams == null) + { + value.UInt32Value = (uint)FileAttributes.Normal; + } + else + { + value.UInt32Value = (uint)(_streams[index] == null ? FileAttributes.Directory : FileAttributes.Normal); + } + } + else + { + value.UInt32Value = (uint) _files[index].Attributes; + } + } + else + { + value.UInt32Value = _updateData.ArchiveFileData[(int) index].Attributes; + } + break; + #region Times + case ItemPropId.CreationTime: + value.VarType = VarEnum.VT_FILETIME; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + value.Int64Value = _files == null + ? DateTime.Now.ToFileTime() + : _files[index].CreationTime.ToFileTime(); + } + else + { + value.Int64Value = _updateData.ArchiveFileData[(int) index].CreationTime.ToFileTime(); + } + break; + case ItemPropId.LastAccessTime: + value.VarType = VarEnum.VT_FILETIME; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + value.Int64Value = _files == null + ? DateTime.Now.ToFileTime() + : _files[index].LastAccessTime.ToFileTime(); + } + else + { + value.Int64Value = _updateData.ArchiveFileData[(int) index].LastAccessTime.ToFileTime(); + } + break; + case ItemPropId.LastWriteTime: + value.VarType = VarEnum.VT_FILETIME; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + value.Int64Value = _files == null + ? DateTime.Now.ToFileTime() + : _files[index].LastWriteTime.ToFileTime(); + } + else + { + value.Int64Value = _updateData.ArchiveFileData[(int) index].LastWriteTime.ToFileTime(); + } + break; + #endregion + case ItemPropId.Extension: + #region Extension + + value.VarType = VarEnum.VT_BSTR; + if (_updateData.Mode != InternalCompressionMode.Modify) + { + try + { + val = _files != null + ? _files[index].Extension.Substring(1) + : _entries == null + ? "" + : Path.GetExtension(_entries[index]); + value.Value = Marshal.StringToBSTR(val); + } + catch (ArgumentException) + { + value.Value = Marshal.StringToBSTR(""); + } + } + else + { + val = Path.GetExtension(_updateData.ArchiveFileData[(int) index].FileName); + value.Value = Marshal.StringToBSTR(val); + } + + #endregion + break; + } + } + catch (Exception e) + { + AddException(e); + } + return 0; + } + + /// + /// Gets the stream for 7-zip library. + /// + /// File index + /// Input file stream + /// Zero if Ok + public int GetStream(uint index, out +#if !MONO + ISequentialInStream +#else + HandleRef +#endif + inStream) + { + index -= _indexOffset; + if (_files != null) + { + _fileStream = null; + try + { + if (File.Exists(_files[index].FullName)) + { + _fileStream = new InStreamWrapper( + new FileStream(_files[index].FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), + true); + } + } + catch (Exception e) + { + AddException(e); + inStream = null; + return -1; + } + inStream = _fileStream; + if (!EventsForGetStream(index)) + { + return -1; + } + } + else + { + if (_streams == null) + { + inStream = _fileStream; + } + else + { + _fileStream = new InStreamWrapper(_streams[index], true); + inStream = _fileStream; + if (!EventsForGetStream(index)) + { + return -1; + } + } + } + return 0; + } + + public long EnumProperties(IntPtr enumerator) + { + //Not implemented HRESULT + return 0x80004001L; + } + + public void SetOperationResult(OperationResult operationResult) + { + if (operationResult != OperationResult.Ok && ReportErrors) + { + switch (operationResult) + { + case OperationResult.CrcError: + AddException(new ExtractionFailedException("File is corrupted. Crc check has failed.")); + break; + case OperationResult.DataError: + AddException(new ExtractionFailedException("File is corrupted. Data error has occured.")); + break; + case OperationResult.UnsupportedMethod: + AddException(new ExtractionFailedException("Unsupported method error has occured.")); + break; + } + } + if (_fileStream != null) + { + + _fileStream.BytesRead -= IntEventArgsHandler; + //Specific Zip implementation - can not Dispose files for Zip. + if (_compressor.ArchiveFormat != OutArchiveFormat.Zip) + { + try + { + _fileStream.Dispose(); + } + catch (ObjectDisposedException) {} + } + else + { + _wrappersToDispose.Add(_fileStream); + } + _fileStream = null; + GC.Collect(); + // Issue #6987 + //GC.WaitForPendingFinalizers(); + } + OnFileCompressionFinished(EventArgs.Empty); + } + + #endregion + + #region ICryptoGetTextPassword2 Members + + public int CryptoGetTextPassword2(ref int passwordIsDefined, out string password) + { + passwordIsDefined = String.IsNullOrEmpty(Password) ? 0 : 1; + password = Password; + return 0; + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { +#if !WINCE + GC.RemoveMemoryPressure(_memoryPressure); +#endif + if (_fileStream != null) + { + try + { + _fileStream.Dispose(); + } + catch (ObjectDisposedException) {} + } + if (_wrappersToDispose != null) + { + foreach (var wrapper in _wrappersToDispose) + { + try + { + wrapper.Dispose(); + } + catch (ObjectDisposedException) {} + } + } + GC.SuppressFinalize(this); + } + + #endregion + + private void IntEventArgsHandler(object sender, IntEventArgs e) + { + lock (this) + { + var pold = (byte) ((_bytesWrittenOld*100)/_bytesCount); + _bytesWritten += e.Value; + byte pnow; + if (_bytesCount < _bytesWritten) //Holy shit, this check for ZIP is golden + { + pnow = 100; + } + else + { + pnow = (byte)((_bytesWritten * 100) / _bytesCount); + } + if (pnow > pold) + { + _bytesWrittenOld = _bytesWritten; + OnCompressing(new ProgressEventArgs(pnow, (byte) (pnow - pold))); + } + } + } + } +#endif +#endif +} diff --git a/BizHawk.Util/7z/COM.cs b/BizHawk.Util/7z/COM.cs new file mode 100644 index 0000000000..31d2a4d863 --- /dev/null +++ b/BizHawk.Util/7z/COM.cs @@ -0,0 +1,1244 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General public License for more details. + + You should have received a copy of the GNU Lesser General public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; +using System.Security.Permissions; +#if !WINCE +using FILETIME=System.Runtime.InteropServices.ComTypes.FILETIME; +#elif WINCE +using FILETIME=OpenNETCF.Runtime.InteropServices.ComTypes.FILETIME; +#endif + +namespace SevenZip +{ + #if UNMANAGED + + /// + /// The structure to fix x64 and x32 variant size mismatch. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct PropArray + { + uint _cElems; + IntPtr _pElems; + } + + /// + /// COM VARIANT structure with special interface routines. + /// + [StructLayout(LayoutKind.Explicit)] + internal struct PropVariant + { + [FieldOffset(0)] private ushort _vt; + + /// + /// IntPtr variant value. + /// + [FieldOffset(8)] private IntPtr _value; + + /*/// + /// Byte variant value. + /// + [FieldOffset(8)] + private byte _ByteValue;*/ + + /// + /// Signed int variant value. + /// + [FieldOffset(8)] + private Int32 _int32Value; + + /// + /// Unsigned int variant value. + /// + [FieldOffset(8)] private UInt32 _uInt32Value; + + /// + /// Long variant value. + /// + [FieldOffset(8)] private Int64 _int64Value; + + /// + /// Unsigned long variant value. + /// + [FieldOffset(8)] private UInt64 _uInt64Value; + + /// + /// FILETIME variant value. + /// + [FieldOffset(8)] private FILETIME _fileTime; + + /// + /// The PropArray instance to fix the variant size on x64 bit systems. + /// + [FieldOffset(8)] + private PropArray _propArray; + + /// + /// Gets or sets variant type. + /// + public VarEnum VarType + { + private get + { + return (VarEnum) _vt; + } + + set + { + _vt = (ushort) value; + } + } + + /// + /// Gets or sets the pointer value of the COM variant + /// + public IntPtr Value + { + private get + { + return _value; + } + + set + { + _value = value; + } + } + + /* + /// + /// Gets or sets the byte value of the COM variant + /// + public byte ByteValue + { + get + { + return _ByteValue; + } + + set + { + _ByteValue = value; + } + } +*/ + + /// + /// Gets or sets the UInt32 value of the COM variant. + /// + public UInt32 UInt32Value + { + private get + { + return _uInt32Value; + } + set + { + _uInt32Value = value; + } + } + + /// + /// Gets or sets the UInt32 value of the COM variant. + /// + public Int32 Int32Value + { + private get + { + return _int32Value; + } + set + { + _int32Value = value; + } + } + + /// + /// Gets or sets the Int64 value of the COM variant + /// + public Int64 Int64Value + { + private get + { + return _int64Value; + } + + set + { + _int64Value = value; + } + } + + /// + /// Gets or sets the UInt64 value of the COM variant + /// + public UInt64 UInt64Value + { + private get + { + return _uInt64Value; + } + set + { + _uInt64Value = value; + } + } + + /* + /// + /// Gets or sets the FILETIME value of the COM variant + /// + public System.Runtime.InteropServices.ComTypes.FILETIME FileTime + { + get + { + return _fileTime; + } + + set + { + _fileTime = value; + } + } +*/ + + /*/// + /// Gets or sets variant type (ushort). + /// + public ushort VarTypeNative + { + get + { + return _vt; + } + + set + { + _vt = value; + } + }*/ + + /*/// + /// Clears variant + /// + public void Clear() + { + switch (VarType) + { + case VarEnum.VT_EMPTY: + break; + case VarEnum.VT_NULL: + case VarEnum.VT_I2: + case VarEnum.VT_I4: + case VarEnum.VT_R4: + case VarEnum.VT_R8: + case VarEnum.VT_CY: + case VarEnum.VT_DATE: + case VarEnum.VT_ERROR: + case VarEnum.VT_BOOL: + case VarEnum.VT_I1: + case VarEnum.VT_UI1: + case VarEnum.VT_UI2: + case VarEnum.VT_UI4: + case VarEnum.VT_I8: + case VarEnum.VT_UI8: + case VarEnum.VT_INT: + case VarEnum.VT_UINT: + case VarEnum.VT_HRESULT: + case VarEnum.VT_FILETIME: + _vt = 0; + break; + default: + if (NativeMethods.PropVariantClear(ref this) != (int)OperationResult.Ok) + { + throw new ArgumentException("PropVariantClear has failed for some reason."); + } + break; + } + }*/ + + /// + /// Gets the object for this PropVariant. + /// + /// + public object Object + { + get + { +#if !WINCE + var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + sp.Demand(); +#endif + switch (VarType) + { + case VarEnum.VT_EMPTY: + return null; + case VarEnum.VT_FILETIME: + try + { + return DateTime.FromFileTime(Int64Value); + } + catch (ArgumentOutOfRangeException) + { + return DateTime.MinValue; + } + default: + GCHandle propHandle = GCHandle.Alloc(this, GCHandleType.Pinned); + try + { + return Marshal.GetObjectForNativeVariant(propHandle.AddrOfPinnedObject()); + } +#if WINCE + catch (NotSupportedException) + { + switch (VarType) + { + case VarEnum.VT_UI8: + return UInt64Value; + case VarEnum.VT_UI4: + return UInt32Value; + case VarEnum.VT_I8: + return Int64Value; + case VarEnum.VT_I4: + return Int32Value; + default: + return 0; + } + } +#endif + finally + { + propHandle.Free(); + } + } + } + } + + /// + /// Determines whether the specified System.Object is equal to the current PropVariant. + /// + /// The System.Object to compare with the current PropVariant. + /// true if the specified System.Object is equal to the current PropVariant; otherwise, false. + public override bool Equals(object obj) + { + return (obj is PropVariant) ? Equals((PropVariant) obj) : false; + } + + /// + /// Determines whether the specified PropVariant is equal to the current PropVariant. + /// + /// The PropVariant to compare with the current PropVariant. + /// true if the specified PropVariant is equal to the current PropVariant; otherwise, false. + private bool Equals(PropVariant afi) + { + if (afi.VarType != VarType) + { + return false; + } + if (VarType != VarEnum.VT_BSTR) + { + return afi.Int64Value == Int64Value; + } + return afi.Value == Value; + } + + /// + /// Serves as a hash function for a particular type. + /// + /// A hash code for the current PropVariant. + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + /// + /// Returns a System.String that represents the current PropVariant. + /// + /// A System.String that represents the current PropVariant. + public override string ToString() + { + return "[" + Value + "] " + Int64Value.ToString(CultureInfo.CurrentCulture); + } + + /// + /// Determines whether the specified PropVariant instances are considered equal. + /// + /// The first PropVariant to compare. + /// The second PropVariant to compare. + /// true if the specified PropVariant instances are considered equal; otherwise, false. + public static bool operator ==(PropVariant afi1, PropVariant afi2) + { + return afi1.Equals(afi2); + } + + /// + /// Determines whether the specified PropVariant instances are not considered equal. + /// + /// The first PropVariant to compare. + /// The second PropVariant to compare. + /// true if the specified PropVariant instances are not considered equal; otherwise, false. + public static bool operator !=(PropVariant afi1, PropVariant afi2) + { + return !afi1.Equals(afi2); + } + } + + /// + /// Stores file extraction modes. + /// + internal enum AskMode + { + /// + /// Extraction mode + /// + Extract = 0, + /// + /// Test mode + /// + Test, + /// + /// Skip mode + /// + Skip + } + + /// + /// Stores operation result values + /// + public enum OperationResult + { + /// + /// Success + /// + Ok = 0, + /// + /// Method is unsupported + /// + UnsupportedMethod, + /// + /// Data error has occured + /// + DataError, + /// + /// CrcError has occured + /// + CrcError + } + + /// + /// Codes of item properities + /// + internal enum ItemPropId : uint + { + /// + /// No property + /// + NoProperty = 0, + /// + /// Handler item index + /// + HandlerItemIndex = 2, + /// + /// Item path + /// + Path, + /// + /// Item name + /// + Name, + /// + /// Item extension + /// + Extension, + /// + /// true if the item is a folder; otherwise, false + /// + IsDirectory, + /// + /// Item size + /// + Size, + /// + /// Item packed sise; usually absent + /// + PackedSize, + /// + /// Item attributes; usually absent + /// + Attributes, + /// + /// Item creation time; usually absent + /// + CreationTime, + /// + /// Item last access time; usually absent + /// + LastAccessTime, + /// + /// Item last write time + /// + LastWriteTime, + /// + /// true if the item is solid; otherwise, false + /// + Solid, + /// + /// true if the item is commented; otherwise, false + /// + Commented, + /// + /// true if the item is encrypted; otherwise, false + /// + Encrypted, + /// + /// (?) + /// + SplitBefore, + /// + /// (?) + /// + SplitAfter, + /// + /// Dictionary size(?) + /// + DictionarySize, + /// + /// Item CRC checksum + /// + Crc, + /// + /// Item type(?) + /// + Type, + /// + /// (?) + /// + IsAnti, + /// + /// Compression method + /// + Method, + /// + /// (?); usually absent + /// + HostOS, + /// + /// Item file system; usually absent + /// + FileSystem, + /// + /// Item user(?); usually absent + /// + User, + /// + /// Item group(?); usually absent + /// + Group, + /// + /// Bloack size(?) + /// + Block, + /// + /// Item comment; usually absent + /// + Comment, + /// + /// Item position + /// + Position, + /// + /// Item prefix(?) + /// + Prefix, + /// + /// Number of subdirectories + /// + NumSubDirs, + /// + /// Numbers of subfiles + /// + NumSubFiles, + /// + /// The archive legacy unpacker version + /// + UnpackVersion, + /// + /// Volume(?) + /// + Volume, + /// + /// Is a volume + /// + IsVolume, + /// + /// Offset value(?) + /// + Offset, + /// + /// Links(?) + /// + Links, + /// + /// Number of blocks + /// + NumBlocks, + /// + /// Number of volumes(?) + /// + NumVolumes, + /// + /// Time type(?) + /// + TimeType, + /// + /// 64-bit(?) + /// + Bit64, + /// + /// BigEndian + /// + BigEndian, + /// + /// Cpu(?) + /// + Cpu, + /// + /// Physical archive size + /// + PhysicalSize, + /// + /// Headers size + /// + HeadersSize, + /// + /// Archive checksum + /// + Checksum, + /// + /// (?) + /// + TotalSize = 0x1100, + /// + /// (?) + /// + FreeSpace, + /// + /// Cluster size(?) + /// + ClusterSize, + /// + /// Volume name(?) + /// + VolumeName, + /// + /// Local item name(?); usually absent + /// + LocalName = 0x1200, + /// + /// (?) + /// + Provider, + /// + /// User defined property; usually absent + /// + UserDefined = 0x10000 + } + + /*/// + /// Codes of archive properties or modes. + /// + internal enum ArchivePropId : uint + { + Name = 0, + ClassID, + Extension, + AddExtension, + Update, + KeepName, + StartSignature, + FinishSignature, + Associate + }*/ + + /// + /// PropId string names dictionary wrapper. + /// + internal static class PropIdToName + { + /// + /// PropId string names + /// + public static readonly Dictionary PropIdNames = + #region Initialization + new Dictionary(46) + { + {ItemPropId.Path, "Path"}, + {ItemPropId.Name, "Name"}, + {ItemPropId.IsDirectory, "Folder"}, + {ItemPropId.Size, "Size"}, + {ItemPropId.PackedSize, "Packed Size"}, + {ItemPropId.Attributes, "Attributes"}, + {ItemPropId.CreationTime, "Created"}, + {ItemPropId.LastAccessTime, "Accessed"}, + {ItemPropId.LastWriteTime, "Modified"}, + {ItemPropId.Solid, "Solid"}, + {ItemPropId.Commented, "Commented"}, + {ItemPropId.Encrypted, "Encrypted"}, + {ItemPropId.SplitBefore, "Split Before"}, + {ItemPropId.SplitAfter, "Split After"}, + { + ItemPropId.DictionarySize, + "Dictionary Size" + }, + {ItemPropId.Crc, "CRC"}, + {ItemPropId.Type, "Type"}, + {ItemPropId.IsAnti, "Anti"}, + {ItemPropId.Method, "Method"}, + {ItemPropId.HostOS, "Host OS"}, + {ItemPropId.FileSystem, "File System"}, + {ItemPropId.User, "User"}, + {ItemPropId.Group, "Group"}, + {ItemPropId.Block, "Block"}, + {ItemPropId.Comment, "Comment"}, + {ItemPropId.Position, "Position"}, + {ItemPropId.Prefix, "Prefix"}, + { + ItemPropId.NumSubDirs, + "Number of subdirectories" + }, + { + ItemPropId.NumSubFiles, + "Number of subfiles" + }, + { + ItemPropId.UnpackVersion, + "Unpacker version" + }, + {ItemPropId.Volume, "Volume"}, + {ItemPropId.IsVolume, "IsVolume"}, + {ItemPropId.Offset, "Offset"}, + {ItemPropId.Links, "Links"}, + { + ItemPropId.NumBlocks, + "Number of blocks" + }, + { + ItemPropId.NumVolumes, + "Number of volumes" + }, + {ItemPropId.TimeType, "Time type"}, + {ItemPropId.Bit64, "64-bit"}, + {ItemPropId.BigEndian, "Big endian"}, + {ItemPropId.Cpu, "CPU"}, + { + ItemPropId.PhysicalSize, + "Physical Size" + }, + {ItemPropId.HeadersSize, "Headers Size"}, + {ItemPropId.Checksum, "Checksum"}, + {ItemPropId.FreeSpace, "Free Space"}, + {ItemPropId.ClusterSize, "Cluster Size"} + }; + #endregion + } + + /// + /// 7-zip IArchiveOpenCallback imported interface to handle the opening of an archive. + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600100000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IArchiveOpenCallback + { + // ref ulong replaced with IntPtr because handlers often pass null value + // read actual value with Marshal.ReadInt64 + /// + /// Sets total data size + /// + /// Files pointer + /// Total size in bytes + void SetTotal( + IntPtr files, + IntPtr bytes); + + /// + /// Sets completed size + /// + /// Files pointer + /// Completed size in bytes + void SetCompleted( + IntPtr files, + IntPtr bytes); + } + + /// + /// 7-zip ICryptoGetTextPassword imported interface to get the archive password. + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000500100000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ICryptoGetTextPassword + { + /// + /// Gets password for the archive + /// + /// Password for the archive + /// Zero if everything is OK + [PreserveSig] + int CryptoGetTextPassword( + [MarshalAs(UnmanagedType.BStr)] out string password); + } + + /// + /// 7-zip ICryptoGetTextPassword2 imported interface for setting the archive password. + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000500110000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ICryptoGetTextPassword2 + { + /// + /// Sets password for the archive + /// + /// Specifies whether archive has a password or not (0 if not) + /// Password for the archive + /// Zero if everything is OK + [PreserveSig] + int CryptoGetTextPassword2( + ref int passwordIsDefined, + [MarshalAs(UnmanagedType.BStr)] out string password); + } + + /// + /// 7-zip IArchiveExtractCallback imported interface. + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600200000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IArchiveExtractCallback + { + /// + /// Gives the size of the unpacked archive files + /// + /// Size of the unpacked archive files (in bytes) + void SetTotal(ulong total); + + /// + /// SetCompleted 7-zip function + /// + /// + void SetCompleted([In] ref ulong completeValue); + + /// + /// Gets the stream for file extraction + /// + /// File index in the archive file table + /// Pointer to the stream + /// Extraction mode + /// S_OK - OK, S_FALSE - skip this file + [PreserveSig] + int GetStream( + uint index, + [Out, MarshalAs(UnmanagedType.Interface)] out ISequentialOutStream outStream, + AskMode askExtractMode); + + /// + /// PrepareOperation 7-zip function + /// + /// Ask mode + void PrepareOperation(AskMode askExtractMode); + + /// + /// Sets the operaton result + /// + /// The operation result + void SetOperationResult(OperationResult operationResult); + } + + /// + /// 7-zip IArchiveUpdateCallback imported interface. + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600800000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IArchiveUpdateCallback + { + /// + /// Gives the size of the unpacked archive files. + /// + /// Size of the unpacked archive files (in bytes) + void SetTotal(ulong total); + + /// + /// SetCompleted 7-zip internal function. + /// + /// + void SetCompleted([In] ref ulong completeValue); + + /// + /// Gets archive update mode. + /// + /// File index + /// 1 if new, 0 if not + /// 1 if new, 0 if not + /// -1 if doesn't matter + /// + [PreserveSig] + int GetUpdateItemInfo( + uint index, ref int newData, + ref int newProperties, ref uint indexInArchive); + + /// + /// Gets the archive item property data. + /// + /// Item index + /// Property identificator + /// Property value + /// Zero if Ok + [PreserveSig] + int GetProperty(uint index, ItemPropId propId, ref PropVariant value); + + /// + /// Gets the stream for reading. + /// + /// The item index. + /// The ISequentialInStream pointer for reading. + /// Zero if Ok + [PreserveSig] + int GetStream( + uint index, + [Out, MarshalAs(UnmanagedType.Interface)] out ISequentialInStream inStream); + + /// + /// Sets the result for currently performed operation. + /// + /// The result value. + void SetOperationResult(OperationResult operationResult); + + /// + /// EnumProperties 7-zip internal function. + /// + /// The enumerator pointer. + /// + long EnumProperties(IntPtr enumerator); + } + + /// + /// 7-zip IArchiveOpenVolumeCallback imported interface to handle archive volumes. + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600300000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IArchiveOpenVolumeCallback + { + /// + /// Gets the archive property data. + /// + /// The property identificator. + /// The property value. + [PreserveSig] + int GetProperty( + ItemPropId propId, ref PropVariant value); + + /// + /// Gets the stream for reading the volume. + /// + /// The volume file name. + /// The IInStream pointer for reading. + /// Zero if Ok + [PreserveSig] + int GetStream( + [MarshalAs(UnmanagedType.LPWStr)] string name, + [Out, MarshalAs(UnmanagedType.Interface)] out IInStream inStream); + } + + /// + /// 7-zip ISequentialInStream imported interface + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000300010000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ISequentialInStream + { + /// + /// Writes data to 7-zip packer + /// + /// Array of bytes available for writing + /// Array size + /// S_OK if success + /// If (size > 0) and there are bytes in stream, + /// this function must read at least 1 byte. + /// This function is allowed to read less than "size" bytes. + /// You must call Read function in loop, if you need exact amount of data. + /// + int Read( + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data, + uint size); + } + + /// + /// 7-zip ISequentialOutStream imported interface + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000300020000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ISequentialOutStream + { + /// + /// Writes data to unpacked file stream + /// + /// Array of bytes available for reading + /// Array size + /// Processed data size + /// S_OK if success + /// If size != 0, return value is S_OK and (*processedSize == 0), + /// then there are no more bytes in stream. + /// If (size > 0) and there are bytes in stream, + /// this function must read at least 1 byte. + /// This function is allowed to rwrite less than "size" bytes. + /// You must call Write function in loop, if you need exact amount of data. + /// + [PreserveSig] + int Write( + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data, + uint size, IntPtr processedSize); + } + + /// + /// 7-zip IInStream imported interface + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000300030000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IInStream + { + /// + /// Read routine + /// + /// Array of bytes to set + /// Array size + /// Zero if Ok + int Read( + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data, + uint size); + + /// + /// Seek routine + /// + /// Offset value + /// Seek origin value + /// New position pointer + void Seek( + long offset, SeekOrigin seekOrigin, IntPtr newPosition); + } + + /// + /// 7-zip IOutStream imported interface + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000300040000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IOutStream + { + /// + /// Write routine + /// + /// Array of bytes to get + /// Array size + /// Processed size + /// Zero if Ok + [PreserveSig] + int Write( + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data, + uint size, + IntPtr processedSize); + + /// + /// Seek routine + /// + /// Offset value + /// Seek origin value + /// New position pointer + void Seek( + long offset, SeekOrigin seekOrigin, IntPtr newPosition); + + /// + /// Set size routine + /// + /// New size value + /// Zero if Ok + [PreserveSig] + int SetSize(long newSize); + } + + /// + /// 7-zip essential in archive interface + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600600000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IInArchive + { + /// + /// Opens archive for reading. + /// + /// Archive file stream + /// Maximum start position for checking + /// Callback for opening archive + /// + [PreserveSig] + int Open( + IInStream stream, + [In] ref ulong maxCheckStartPosition, + [MarshalAs(UnmanagedType.Interface)] IArchiveOpenCallback openArchiveCallback); + + /// + /// Closes the archive. + /// + void Close(); + + /// + /// Gets the number of files in the archive file table . + /// + /// The number of files in the archive + uint GetNumberOfItems(); + + /// + /// Retrieves specific property data. + /// + /// File index in the archive file table + /// Property code + /// Property variant value + void GetProperty( + uint index, + ItemPropId propId, + ref PropVariant value); // PropVariant + + /// + /// Extracts files from the opened archive. + /// + /// indexes of files to be extracted (must be sorted) + /// 0xFFFFFFFF means all files + /// testMode != 0 means "test files operation" + /// IArchiveExtractCallback for operations handling + /// 0 if success + [PreserveSig] + int Extract( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] indexes, + uint numItems, + int testMode, + [MarshalAs(UnmanagedType.Interface)] IArchiveExtractCallback extractCallback); + + /// + /// Gets archive property data + /// + /// Archive property identificator + /// Archive property value + void GetArchiveProperty( + ItemPropId propId, // PROPID + ref PropVariant value); // PropVariant + + /// + /// Gets the number of properties + /// + /// The number of properties + uint GetNumberOfProperties(); + + /// + /// Gets property information + /// + /// Item index + /// Name + /// Property identificator + /// Variant type + void GetPropertyInfo( + uint index, + [MarshalAs(UnmanagedType.BStr)] out string name, + out ItemPropId propId, // PROPID + out ushort varType); //VARTYPE + + /// + /// Gets the number of archive properties + /// + /// The number of archive properties + uint GetNumberOfArchiveProperties(); + + /// + /// Gets the archive property information + /// + /// Item index + /// Name + /// Property identificator + /// Variant type + void GetArchivePropertyInfo( + uint index, + [MarshalAs(UnmanagedType.BStr)] out string name, + out ItemPropId propId, // PROPID + out ushort varType); //VARTYPE + } + + /// + /// 7-zip essential out archive interface + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600A00000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IOutArchive + { + /// + /// Updates archive items + /// + /// The ISequentialOutStream pointer for writing the archive data + /// Number of archive items + /// The IArchiveUpdateCallback pointer + /// Zero if Ok + [PreserveSig] + int UpdateItems( + [MarshalAs(UnmanagedType.Interface)] ISequentialOutStream outStream, + uint numItems, + [MarshalAs(UnmanagedType.Interface)] IArchiveUpdateCallback updateCallback); + + /// + /// Gets file time type(?) + /// + /// Type pointer + void GetFileTimeType(IntPtr type); + } + + /// + /// 7-zip ISetProperties interface for setting various archive properties + /// + [ComImport] + [Guid("23170F69-40C1-278A-0000-000600030000")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ISetProperties + { + /// + /// Sets the archive properties + /// + /// The names of the properties + /// The values of the properties + /// The properties count + /// + int SetProperties(IntPtr names, IntPtr values, int numProperties); + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/Common.cs b/BizHawk.Util/7z/Common.cs new file mode 100644 index 0000000000..dd88cfbf2c --- /dev/null +++ b/BizHawk.Util/7z/Common.cs @@ -0,0 +1,833 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +#if !WINCE +using System.Runtime.Remoting.Messaging; +#endif +#if DOTNET20 +using System.Threading; +#else +using System.Windows.Threading; +#endif +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ +#if UNMANAGED + + /// + /// The way of the event synchronization. + /// + public enum EventSynchronizationStrategy + { + /// + /// Events are called synchronously if user can do some action; that is, cancel the execution process for example. + /// + Default, + /// + /// Always call events asynchronously. + /// + AlwaysAsynchronous, + /// + /// Always call events synchronously. + /// + AlwaysSynchronous + } + + /// + /// SevenZip Extractor/Compressor base class. Implements Password string, ReportErrors flag. + /// + public class SevenZipBase : MarshalByRefObject + { + private readonly string _password; + private readonly bool _reportErrors; + private readonly int _uniqueID; + private static readonly List Identificators = new List(); +#if !WINCE + internal static readonly AsyncCallback AsyncCallbackImplementation = AsyncCallbackMethod; + + /// + /// True if the instance of the class needs to be recreated in new thread context; otherwise, false. + /// + protected internal bool NeedsToBeRecreated; + + /// + /// AsyncCallback implementation used in asynchronous invocations. + /// + /// IAsyncResult instance. + internal static void AsyncCallbackMethod(IAsyncResult ar) + { + var result = (AsyncResult) ar; + result.AsyncDelegate.GetType().GetMethod("EndInvoke").Invoke(result.AsyncDelegate, new[] { ar }); + ((SevenZipBase)ar.AsyncState).ReleaseContext(); + } + + virtual internal void SaveContext( +#if !DOTNET20 + DispatcherPriority priority = DispatcherPriority.Normal +#endif + ) + { +#if !DOTNET20 + Dispatcher = Dispatcher.CurrentDispatcher; + Priority = priority; +#else + Context = SynchronizationContext.Current; +#endif + NeedsToBeRecreated = true; + } + + internal void ReleaseContext() + { +#if !DOTNET20 + Dispatcher = null; +#else + Context = null; +#endif + NeedsToBeRecreated = true; + } + + private delegate void EventHandlerDelegate(EventHandler handler, T e) where T : EventArgs; + + internal void OnEvent(EventHandler handler, T e, bool synchronous) where T: EventArgs + { + try + { + if (handler != null) + { + switch (EventSynchronization) + { + case EventSynchronizationStrategy.AlwaysAsynchronous: + synchronous = false; + break; + case EventSynchronizationStrategy.AlwaysSynchronous: + synchronous = true; + break; + } + if ( +#if !DOTNET20 + Dispatcher == null +#else + Context == null +#endif +) + { + // Usual synchronous call + handler(this, e); + } + else + { +#if !DOTNET20 + var eventHandlerDelegate = new EventHandlerDelegate((h, ee) => h(this, ee)); + if (synchronous) + { + // Could be just handler(this, e); + Dispatcher.Invoke(eventHandlerDelegate, Priority, handler, e); + } + else + { + Dispatcher.BeginInvoke(eventHandlerDelegate, Priority, handler, e); + } +#else + var callback = new SendOrPostCallback((obj) => + { + var array = (object[])obj; + ((EventHandler)array[0])(array[1], (T)array[2]); + }); + if (synchronous) + { + // Could be just handler(this, e); + this.Context.Send(callback, new object[] { handler, this, e }); + } + else + { + this.Context.Post(callback, new object[] { handler, this, e }); + } +#endif + } + } + } + catch (Exception ex) + { + AddException(ex); + } + } + +#if !DOTNET20 + /// + /// Gets or sets the Dispatcher object for this instance. + /// It will be used to fire events in the user context. + /// + internal Dispatcher Dispatcher { get; set; } + + /// + /// Gets or sets the Dispatcher priority of calling user events. + /// + internal DispatcherPriority Priority { get; set; } +#else + internal SynchronizationContext Context { get; set; } +#endif + /// + /// Gets or sets the event synchronization strategy. + /// + public EventSynchronizationStrategy EventSynchronization { get; set; } +#else // WINCE + internal void OnEvent(EventHandler handler, T e, bool synchronous) where T : System.EventArgs + { + try + { + handler(this, e); + } + catch (Exception ex) + { + AddException(ex); + } + } +#endif + /// + /// Gets the unique identificator of this SevenZipBase instance. + /// + public int UniqueID + { + get + { + return _uniqueID; + } + } + + /// + /// User exceptions thrown during the requested operations, for example, in events. + /// + private readonly List _exceptions = new List(); + + private static int GetUniqueID() + { + int id; + var rnd = new Random(DateTime.Now.Millisecond); + do + { + id = rnd.Next(Int32.MaxValue); + } + while (Identificators.Contains(id)); + Identificators.Add(id); + return id; + } + + #region Constructors + /// + /// Initializes a new instance of the SevenZipBase class. + /// + protected SevenZipBase() + { + _password = ""; + _reportErrors = true; + _uniqueID = GetUniqueID(); + } + + /// + /// Initializes a new instance of the SevenZipBase class + /// + /// The archive password. + protected SevenZipBase(string password) + { + if (String.IsNullOrEmpty(password)) + { + throw new SevenZipException("Empty password was specified."); + } + _password = password; + _reportErrors = true; + _uniqueID = GetUniqueID(); + } + #endregion + + /// + /// Removes the UniqueID from the list. + /// + ~SevenZipBase() + { + Identificators.Remove(_uniqueID); + } + + /// + /// Gets or sets the archive password + /// + public string Password + { + get + { + return _password; + } + } + + /// + /// Gets or sets throw exceptions on archive errors flag + /// + internal bool ReportErrors + { + get + { + return _reportErrors; + } + } + + /// + /// Gets the user exceptions thrown during the requested operations, for example, in events. + /// + internal ReadOnlyCollection Exceptions + { + get + { + return new ReadOnlyCollection(_exceptions); + } + } + + internal void AddException(Exception e) + { + _exceptions.Add(e); + } + + internal void ClearExceptions() + { + _exceptions.Clear(); + } + + internal bool HasExceptions + { + get + { + return _exceptions.Count > 0; + } + } + + /// + /// Throws the specified exception when is able to. + /// + /// The exception to throw. + /// The handler responsible for the exception. + internal bool ThrowException(CallbackBase handler, params Exception[] e) + { + if (_reportErrors && (handler == null || !handler.Canceled)) + { + throw e[0]; + } + return false; + } + + internal void ThrowUserException() + { + if (HasExceptions) + { + throw new SevenZipException(SevenZipException.USER_EXCEPTION_MESSAGE); + } + } + + /// + /// Throws exception if HRESULT != 0. + /// + /// Result code to check. + /// Exception message. + /// The class responsible for the callback. + internal void CheckedExecute(int hresult, string message, CallbackBase handler) + { + if (hresult != (int) OperationResult.Ok || handler.HasExceptions) + { + if (!handler.HasExceptions) + { + if (hresult < -2000000000) + { + ThrowException(handler, + new SevenZipException( + "The execution has failed due to the bug in the SevenZipSharp.\n" + + "Please report about it to http://sevenzipsharp.codeplex.com/WorkItem/List.aspx, post the release number and attach the archive.")); + } + else + { + ThrowException(handler, + new SevenZipException(message + hresult.ToString(CultureInfo.InvariantCulture) + + '.')); + } + } + else + { + ThrowException(handler, handler.Exceptions[0]); + } + } + } + +#if !WINCE && !MONO + /// + /// Changes the path to the 7-zip native library. + /// + /// The path to the 7-zip native library. + public static void SetLibraryPath(string libraryPath) + { + SevenZipLibraryManager.SetLibraryPath(libraryPath); + } +#endif + /// + /// Gets the current library features. + /// + public static LibraryFeature CurrentLibraryFeatures + { + get + { + return SevenZipLibraryManager.CurrentLibraryFeatures; + } + } + + /// + /// Determines whether the specified System.Object is equal to the current SevenZipBase. + /// + /// The System.Object to compare with the current SevenZipBase. + /// true if the specified System.Object is equal to the current SevenZipBase; otherwise, false. + public override bool Equals(object obj) + { + var inst = obj as SevenZipBase; + if (inst == null) + { + return false; + } + return _uniqueID == inst._uniqueID; + } + + /// + /// Serves as a hash function for a particular type. + /// + /// A hash code for the current SevenZipBase. + public override int GetHashCode() + { + return _uniqueID; + } + + /// + /// Returns a System.String that represents the current SevenZipBase. + /// + /// A System.String that represents the current SevenZipBase. + public override string ToString() + { + var type = "SevenZipBase"; + if (this is SevenZipExtractor) + { + type = "SevenZipExtractor"; + } + if (this is SevenZipCompressor) + { + type = "SevenZipCompressor"; + } + return string.Format("{0} [{1}]", type, _uniqueID); + } + } + + internal class CallbackBase : MarshalByRefObject + { + private readonly string _password; + private readonly bool _reportErrors; + /// + /// User exceptions thrown during the requested operations, for example, in events. + /// + private readonly List _exceptions = new List(); + + #region Constructors + /// + /// Initializes a new instance of the CallbackBase class. + /// + protected CallbackBase() + { + _password = ""; + _reportErrors = true; + } + + /// + /// Initializes a new instance of the CallbackBase class. + /// + /// The archive password. + protected CallbackBase(string password) + { + if (String.IsNullOrEmpty(password)) + { + throw new SevenZipException("Empty password was specified."); + } + _password = password; + _reportErrors = true; + } + #endregion + + /// + /// Gets or sets the archive password + /// + public string Password + { + get + { + return _password; + } + } + + /// + /// Gets or sets the value indicating whether the current procedure was cancelled. + /// + public bool Canceled { get; set; } + + /// + /// Gets or sets throw exceptions on archive errors flag + /// + public bool ReportErrors + { + get + { + return _reportErrors; + } + } + + /// + /// Gets the user exceptions thrown during the requested operations, for example, in events. + /// + public ReadOnlyCollection Exceptions + { + get + { + return new ReadOnlyCollection(_exceptions); + } + } + + public void AddException(Exception e) + { + _exceptions.Add(e); + } + + public void ClearExceptions() + { + _exceptions.Clear(); + } + + public bool HasExceptions + { + get + { + return _exceptions.Count > 0; + } + } + + /// + /// Throws the specified exception when is able to. + /// + /// The exception to throw. + /// The handler responsible for the exception. + public bool ThrowException(CallbackBase handler, params Exception[] e) + { + if (_reportErrors && (handler == null || !handler.Canceled)) + { + throw e[0]; + } + return false; + } + + /// + /// Throws the first exception in the list if any exists. + /// + /// True means no exceptions. + public bool ThrowException() + { + if (HasExceptions && _reportErrors) + { + throw _exceptions[0]; + } + return true; + } + + public void ThrowUserException() + { + if (HasExceptions) + { + throw new SevenZipException(SevenZipException.USER_EXCEPTION_MESSAGE); + } + } + } + + /// + /// Struct for storing information about files in the 7-zip archive. + /// + public struct ArchiveFileInfo + { + /// + /// Gets or sets index of the file in the archive file table. + /// + public int Index { get; set; } + + /// + /// Gets or sets file name + /// + public string FileName { get; set; } + + /// + /// Gets or sets the file last write time. + /// + public DateTime LastWriteTime { get; set; } + + /// + /// Gets or sets the file creation time. + /// + public DateTime CreationTime { get; set; } + + /// + /// Gets or sets the file creation time. + /// + public DateTime LastAccessTime { get; set; } + + /// + /// Gets or sets size of the file (unpacked). + /// + public ulong Size { get; set; } + + /// + /// Gets or sets CRC checksum of the file. + /// + public uint Crc { get; set; } + + /// + /// Gets or sets file attributes. + /// + public uint Attributes { get; set; } + + /// + /// Gets or sets being a directory. + /// + public bool IsDirectory { get; set; } + + /// + /// Gets or sets being encrypted. + /// + public bool Encrypted { get; set; } + + /// + /// Gets or sets comment for the file. + /// + public string Comment { get; set; } + + /// + /// Determines whether the specified System.Object is equal to the current ArchiveFileInfo. + /// + /// The System.Object to compare with the current ArchiveFileInfo. + /// true if the specified System.Object is equal to the current ArchiveFileInfo; otherwise, false. + public override bool Equals(object obj) + { + return (obj is ArchiveFileInfo) ? Equals((ArchiveFileInfo) obj) : false; + } + + /// + /// Determines whether the specified ArchiveFileInfo is equal to the current ArchiveFileInfo. + /// + /// The ArchiveFileInfo to compare with the current ArchiveFileInfo. + /// true if the specified ArchiveFileInfo is equal to the current ArchiveFileInfo; otherwise, false. + public bool Equals(ArchiveFileInfo afi) + { + return afi.Index == Index && afi.FileName == FileName; + } + + /// + /// Serves as a hash function for a particular type. + /// + /// A hash code for the current ArchiveFileInfo. + public override int GetHashCode() + { + return FileName.GetHashCode() ^ Index; + } + + /// + /// Returns a System.String that represents the current ArchiveFileInfo. + /// + /// A System.String that represents the current ArchiveFileInfo. + public override string ToString() + { + return "[" + Index.ToString(CultureInfo.CurrentCulture) + "] " + FileName; + } + + /// + /// Determines whether the specified ArchiveFileInfo instances are considered equal. + /// + /// The first ArchiveFileInfo to compare. + /// The second ArchiveFileInfo to compare. + /// true if the specified ArchiveFileInfo instances are considered equal; otherwise, false. + public static bool operator ==(ArchiveFileInfo afi1, ArchiveFileInfo afi2) + { + return afi1.Equals(afi2); + } + + /// + /// Determines whether the specified ArchiveFileInfo instances are not considered equal. + /// + /// The first ArchiveFileInfo to compare. + /// The second ArchiveFileInfo to compare. + /// true if the specified ArchiveFileInfo instances are not considered equal; otherwise, false. + public static bool operator !=(ArchiveFileInfo afi1, ArchiveFileInfo afi2) + { + return !afi1.Equals(afi2); + } + } + + /// + /// Archive property struct. + /// + public struct ArchiveProperty + { + /// + /// Gets the name of the archive property. + /// + public string Name { get; internal set; } + + /// + /// Gets the value of the archive property. + /// + public object Value { get; internal set; } + + /// + /// Determines whether the specified System.Object is equal to the current ArchiveProperty. + /// + /// The System.Object to compare with the current ArchiveProperty. + /// true if the specified System.Object is equal to the current ArchiveProperty; otherwise, false. + public override bool Equals(object obj) + { + return (obj is ArchiveProperty) ? Equals((ArchiveProperty) obj) : false; + } + + /// + /// Determines whether the specified ArchiveProperty is equal to the current ArchiveProperty. + /// + /// The ArchiveProperty to compare with the current ArchiveProperty. + /// true if the specified ArchiveProperty is equal to the current ArchiveProperty; otherwise, false. + public bool Equals(ArchiveProperty afi) + { + return afi.Name == Name && afi.Value == Value; + } + + /// + /// Serves as a hash function for a particular type. + /// + /// A hash code for the current ArchiveProperty. + public override int GetHashCode() + { + return Name.GetHashCode() ^ Value.GetHashCode(); + } + + /// + /// Returns a System.String that represents the current ArchiveProperty. + /// + /// A System.String that represents the current ArchiveProperty. + public override string ToString() + { + return Name + " = " + Value; + } + + /// + /// Determines whether the specified ArchiveProperty instances are considered equal. + /// + /// The first ArchiveProperty to compare. + /// The second ArchiveProperty to compare. + /// true if the specified ArchiveProperty instances are considered equal; otherwise, false. + public static bool operator ==(ArchiveProperty afi1, ArchiveProperty afi2) + { + return afi1.Equals(afi2); + } + + /// + /// Determines whether the specified ArchiveProperty instances are not considered equal. + /// + /// The first ArchiveProperty to compare. + /// The second ArchiveProperty to compare. + /// true if the specified ArchiveProperty instances are not considered equal; otherwise, false. + public static bool operator !=(ArchiveProperty afi1, ArchiveProperty afi2) + { + return !afi1.Equals(afi2); + } + } + +#if COMPRESS + + /// + /// Archive compression mode. + /// + public enum CompressionMode + { + /// + /// Create a new archive; overwrite the existing one. + /// + Create, + /// + /// Add data to the archive. + /// + Append, + } + + internal enum InternalCompressionMode + { + /// + /// Create a new archive; overwrite the existing one. + /// + Create, + /// + /// Add data to the archive. + /// + Append, + /// + /// Modify archive data. + /// + Modify + } + + /// + /// Zip encryption method enum. + /// + public enum ZipEncryptionMethod + { + /// + /// ZipCrypto encryption method. + /// + ZipCrypto, + /// + /// AES 128 bit encryption method. + /// + Aes128, + /// + /// AES 192 bit encryption method. + /// + Aes192, + /// + /// AES 256 bit encryption method. + /// + Aes256 + } + + /// + /// Archive update data for UpdateCallback. + /// + internal struct UpdateData + { + public uint FilesCount; + public InternalCompressionMode Mode; + + public Dictionary FileNamesToModify { get; set; } + + public List ArchiveFileData { get; set; } + } +#endif +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/EventArgs.cs b/BizHawk.Util/7z/EventArgs.cs new file mode 100644 index 0000000000..8f3928b295 --- /dev/null +++ b/BizHawk.Util/7z/EventArgs.cs @@ -0,0 +1,383 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; + +namespace SevenZip +{ + /// + /// EventArgs for storing PercentDone property. + /// + public class PercentDoneEventArgs : EventArgs + { + private readonly byte _percentDone; + + /// + /// Initializes a new instance of the PercentDoneEventArgs class. + /// + /// The percent of finished work. + /// + public PercentDoneEventArgs(byte percentDone) + { + if (percentDone > 100 || percentDone < 0) + { + throw new ArgumentOutOfRangeException("percentDone", + "The percent of finished work must be between 0 and 100."); + } + _percentDone = percentDone; + } + + /// + /// Gets the percent of finished work. + /// + public byte PercentDone + { + get + { + return _percentDone; + } + } + + /// + /// Gets or sets whether to stop the current archive operation. + /// + public bool Cancel { get; set; } + + /// + /// Converts a [0, 1] rate to its percent equivalent. + /// + /// The rate of the done work. + /// Percent integer equivalent. + /// + internal static byte ProducePercentDone(float doneRate) + { +#if !WINCE + return (byte) Math.Round(Math.Min(100*doneRate, 100), MidpointRounding.AwayFromZero); +#else + return (byte) Math.Round(Math.Min(100*doneRate, 100)); +#endif + } + } + + /// + /// The EventArgs class for accurate progress handling. + /// + public sealed class ProgressEventArgs : PercentDoneEventArgs + { + private readonly byte _delta; + + /// + /// Initializes a new instance of the ProgressEventArgs class. + /// + /// The percent of finished work. + /// The percent of work done after the previous event. + public ProgressEventArgs(byte percentDone, byte percentDelta) + : base(percentDone) + { + _delta = percentDelta; + } + + /// + /// Gets the change in done work percentage. + /// + public byte PercentDelta + { + get + { + return _delta; + } + } + } + +#if UNMANAGED + /// + /// EventArgs used to report the file information which is going to be packed. + /// + public sealed class FileInfoEventArgs : PercentDoneEventArgs + { + private readonly ArchiveFileInfo _fileInfo; + + /// + /// Initializes a new instance of the FileInfoEventArgs class. + /// + /// The current ArchiveFileInfo. + /// The percent of finished work. + public FileInfoEventArgs(ArchiveFileInfo fileInfo, byte percentDone) + : base(percentDone) + { + _fileInfo = fileInfo; + } + + /// + /// Gets the corresponding FileInfo to the event. + /// + public ArchiveFileInfo FileInfo + { + get + { + return _fileInfo; + } + } + } + + /// + /// EventArgs used to report the size of unpacked archive data + /// + public sealed class OpenEventArgs : EventArgs + { + private readonly ulong _totalSize; + + /// + /// Initializes a new instance of the OpenEventArgs class + /// + /// Size of unpacked archive data + public OpenEventArgs(ulong totalSize) + { + _totalSize = totalSize; + } + + /// + /// Gets the size of unpacked archive data + /// + public ulong TotalSize + { + get + { + return _totalSize; + } + } + } + + /// + /// Stores an int number + /// + public sealed class IntEventArgs : EventArgs + { + private readonly int _value; + + /// + /// Initializes a new instance of the IntEventArgs class + /// + /// Useful data carried by the IntEventArgs class + public IntEventArgs(int value) + { + _value = value; + } + + /// + /// Gets the value of the IntEventArgs class + /// + public int Value + { + get + { + return _value; + } + } + } + + /// + /// EventArgs class which stores the file name. + /// + public sealed class FileNameEventArgs : PercentDoneEventArgs + { + private readonly string _fileName; + + /// + /// Initializes a new instance of the FileNameEventArgs class. + /// + /// The file name. + /// The percent of finished work + public FileNameEventArgs(string fileName, byte percentDone) : + base(percentDone) + { + _fileName = fileName; + } + + /// + /// Gets the file name. + /// + public string FileName + { + get + { + return _fileName; + } + } + } + + /// + /// EventArgs for FileExists event, stores the file name and asks whether to overwrite it in case it already exists. + /// + public sealed class FileOverwriteEventArgs : EventArgs + { + /// + /// Initializes a new instance of the FileOverwriteEventArgs class + /// + /// The file name. + public FileOverwriteEventArgs(string fileName) + { + FileName = fileName; + } + + /// + /// Gets or sets the value indicating whether to cancel the extraction. + /// + public bool Cancel { get; set; } + + /// + /// Gets or sets the file name to extract to. Null means skip. + /// + public string FileName { get; set; } + } + + /// + /// The reason for calling . + /// + public enum ExtractFileCallbackReason + { + /// + /// is called the first time for a file. + /// + Start, + + /// + /// All data has been written to the target without any exceptions. + /// + Done, + + /// + /// An exception occured during extraction of the file. + /// + Failure + } + + /// + /// The arguments passed to . + /// + /// + /// For each file, is first called with + /// set to . If the callback chooses to extract the + /// file data by setting or , the callback + /// will be called a second time with set to + /// or + /// to allow for any cleanup task like closing the stream. + /// + public class ExtractFileCallbackArgs : EventArgs + { + private readonly ArchiveFileInfo _archiveFileInfo; + private Stream _extractToStream; + + /// + /// Initializes a new instance of the class. + /// + /// The information about file in the archive. + public ExtractFileCallbackArgs(ArchiveFileInfo archiveFileInfo) + { + Reason = ExtractFileCallbackReason.Start; + _archiveFileInfo = archiveFileInfo; + } + + /// + /// Information about file in the archive. + /// + /// Information about file in the archive. + public ArchiveFileInfo ArchiveFileInfo + { + get + { + return _archiveFileInfo; + } + } + + /// + /// The reason for calling . + /// + /// + /// If neither nor is set, + /// will not be called after . + /// + /// The reason. + public ExtractFileCallbackReason Reason { get; internal set; } + + /// + /// The exception that occurred during extraction. + /// + /// The _Exception. + /// + /// If the callback is called with set to , + /// this member contains the _Exception that occurred. + /// The default behavior is to rethrow the _Exception after return of the callback. + /// However the callback can set to null to swallow the _Exception + /// and continue extraction with the next file. + /// + public Exception Exception { get; set; } + + /// + /// Gets or sets a value indicating whether to cancel the extraction. + /// + /// true to cancel the extraction; false to continue. The default is false. + public bool CancelExtraction { get; set; } + + /// + /// Gets or sets whether and where to extract the file. + /// + /// The path where to extract the file to. + /// + /// If is set, this mmember will be ignored. + /// + public string ExtractToFile { get; set; } + + /// + /// Gets or sets whether and where to extract the file. + /// + /// The the extracted data is written to. + /// + /// If both this member and are null (the defualt), the file + /// will not be extracted and the callback will be be executed a second time with the + /// set to or . + /// + public Stream ExtractToStream + { + get + { + return _extractToStream; + } + set + { + if (_extractToStream != null && !_extractToStream.CanWrite) + { + throw new ExtractionFailedException("The specified stream is not writable!"); + } + _extractToStream = value; + } + } + + /// + /// Gets or sets any data that will be preserved between the callback call + /// and the or calls. + /// + /// The data. + public object ObjectData { get; set; } + } + + /// + /// Callback delegate for . + /// + public delegate void ExtractFileCallback(ExtractFileCallbackArgs extractFileCallbackArgs); +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/Exceptions.cs b/BizHawk.Util/7z/Exceptions.cs new file mode 100644 index 0000000000..8a8410e0d8 --- /dev/null +++ b/BizHawk.Util/7z/Exceptions.cs @@ -0,0 +1,464 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +#if !WINCE +using System.Runtime.Serialization; +#endif + +namespace SevenZip +{ + /// + /// Base SevenZip exception class. + /// + [Serializable] + public class SevenZipException : Exception + { + /// + /// The message for thrown user exceptions. + /// + internal const string USER_EXCEPTION_MESSAGE = "The extraction was successful but" + + "some exceptions were thrown in your events. Check UserExceptions for details."; + + /// + /// Initializes a new instance of the SevenZipException class + /// + public SevenZipException() : base("SevenZip unknown exception.") {} + + /// + /// Initializes a new instance of the SevenZipException class + /// + /// Default exception message + public SevenZipException(string defaultMessage) + : base(defaultMessage) {} + + /// + /// Initializes a new instance of the SevenZipException class + /// + /// Default exception message + /// Additional detailed message + public SevenZipException(string defaultMessage, string message) + : base(defaultMessage + " Message: " + message) {} + + /// + /// Initializes a new instance of the SevenZipException class + /// + /// Default exception message + /// Additional detailed message + /// Inner exception occured + public SevenZipException(string defaultMessage, string message, Exception inner) + : base( + defaultMessage + (defaultMessage.EndsWith(" ", StringComparison.CurrentCulture) ? "" : " Message: ") + + message, inner) {} + + /// + /// Initializes a new instance of the SevenZipException class + /// + /// Default exception message + /// Inner exception occured + public SevenZipException(string defaultMessage, Exception inner) + : base(defaultMessage, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } + +#if UNMANAGED + + /// + /// Exception class for ArchiveExtractCallback. + /// + [Serializable] + public class ExtractionFailedException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "Could not extract files!"; + + /// + /// Initializes a new instance of the ExtractionFailedException class + /// + public ExtractionFailedException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the ExtractionFailedException class + /// + /// Additional detailed message + public ExtractionFailedException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the ExtractionFailedException class + /// + /// Additional detailed message + /// Inner exception occured + public ExtractionFailedException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the ExtractionFailedException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected ExtractionFailedException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } + +#if COMPRESS + + /// + /// Exception class for ArchiveUpdateCallback. + /// + [Serializable] + public class CompressionFailedException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "Could not pack files!"; + + /// + /// Initializes a new instance of the CompressionFailedException class + /// + public CompressionFailedException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the CompressionFailedException class + /// + /// Additional detailed message + public CompressionFailedException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the CompressionFailedException class + /// + /// Additional detailed message + /// Inner exception occured + public CompressionFailedException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the CompressionFailedException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected CompressionFailedException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } +#endif +#endif + + /// + /// Exception class for LZMA operations. + /// + [Serializable] + public class LzmaException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "Specified stream is not a valid LZMA compressed stream!"; + + /// + /// Initializes a new instance of the LzmaException class + /// + public LzmaException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the LzmaException class + /// + /// Additional detailed message + public LzmaException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the LzmaException class + /// + /// Additional detailed message + /// Inner exception occured + public LzmaException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the LzmaException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected LzmaException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } + +#if UNMANAGED + + /// + /// Exception class for 7-zip archive open or read operations. + /// + [Serializable] + public class SevenZipArchiveException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = + "Invalid archive: open/read error! Is it encrypted and a wrong password was provided?\n" + + "If your archive is an exotic one, it is possible that SevenZipSharp has no signature for "+ + "its format and thus decided it is TAR by mistake."; + + /// + /// Initializes a new instance of the SevenZipArchiveException class + /// + public SevenZipArchiveException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the SevenZipArchiveException class + /// + /// Additional detailed message + public SevenZipArchiveException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the SevenZipArchiveException class + /// + /// Additional detailed message + /// Inner exception occured + public SevenZipArchiveException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipArchiveException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipArchiveException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } + + /// + /// Exception class for empty common root if file name array in SevenZipCompressor. + /// + [Serializable] + public class SevenZipInvalidFileNamesException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "Invalid file names have been specified: "; + + /// + /// Initializes a new instance of the SevenZipInvalidFileNamesException class + /// + public SevenZipInvalidFileNamesException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the SevenZipInvalidFileNamesException class + /// + /// Additional detailed message + public SevenZipInvalidFileNamesException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the SevenZipInvalidFileNamesException class + /// + /// Additional detailed message + /// Inner exception occured + public SevenZipInvalidFileNamesException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipInvalidFileNamesException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipInvalidFileNamesException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } + +#if COMPRESS + + /// + /// Exception class for fail to create an archive in SevenZipCompressor. + /// + [Serializable] + public class SevenZipCompressionFailedException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "The compression has failed for an unknown reason with code "; + + /// + /// Initializes a new instance of the SevenZipCompressionFailedException class + /// + public SevenZipCompressionFailedException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the SevenZipCompressionFailedException class + /// + /// Additional detailed message + public SevenZipCompressionFailedException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the SevenZipCompressionFailedException class + /// + /// Additional detailed message + /// Inner exception occured + public SevenZipCompressionFailedException(string message, Exception inner) + : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipCompressionFailedException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipCompressionFailedException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } +#endif + + /// + /// Exception class for fail to extract an archive in SevenZipExtractor. + /// + [Serializable] + public class SevenZipExtractionFailedException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "The extraction has failed for an unknown reason with code "; + + /// + /// Initializes a new instance of the SevenZipExtractionFailedException class + /// + public SevenZipExtractionFailedException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the SevenZipExtractionFailedException class + /// + /// Additional detailed message + public SevenZipExtractionFailedException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the SevenZipExtractionFailedException class + /// + /// Additional detailed message + /// Inner exception occured + public SevenZipExtractionFailedException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipExtractionFailedException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipExtractionFailedException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } + + /// + /// Exception class for 7-zip library operations. + /// + [Serializable] + public class SevenZipLibraryException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public const string DEFAULT_MESSAGE = "Can not load 7-zip library or internal COM error!"; + + /// + /// Initializes a new instance of the SevenZipLibraryException class + /// + public SevenZipLibraryException() : base(DEFAULT_MESSAGE) {} + + /// + /// Initializes a new instance of the SevenZipLibraryException class + /// + /// Additional detailed message + public SevenZipLibraryException(string message) : base(DEFAULT_MESSAGE, message) {} + + /// + /// Initializes a new instance of the SevenZipLibraryException class + /// + /// Additional detailed message + /// Inner exception occured + public SevenZipLibraryException(string message, Exception inner) : base(DEFAULT_MESSAGE, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipLibraryException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipLibraryException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } +#endif + +#if SFX + + /// + /// Exception class for 7-zip sfx settings validation. + /// + [Serializable] + public class SevenZipSfxValidationException : SevenZipException + { + /// + /// Exception dafault message which is displayed if no extra information is specified + /// + public static readonly string DefaultMessage = "Sfx settings validation failed."; + + /// + /// Initializes a new instance of the SevenZipSfxValidationException class + /// + public SevenZipSfxValidationException() : base(DefaultMessage) {} + + /// + /// Initializes a new instance of the SevenZipSfxValidationException class + /// + /// Additional detailed message + public SevenZipSfxValidationException(string message) : base(DefaultMessage, message) {} + + /// + /// Initializes a new instance of the SevenZipSfxValidationException class + /// + /// Additional detailed message + /// Inner exception occured + public SevenZipSfxValidationException(string message, Exception inner) : base(DefaultMessage, message, inner) {} +#if !WINCE + /// + /// Initializes a new instance of the SevenZipSfxValidationException class + /// + /// All data needed for serialization or deserialization + /// Serialized stream descriptor + protected SevenZipSfxValidationException( + SerializationInfo info, StreamingContext context) + : base(info, context) {} +#endif + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/FileSignatureChecker.cs b/BizHawk.Util/7z/FileSignatureChecker.cs new file mode 100644 index 0000000000..294cdc95d6 --- /dev/null +++ b/BizHawk.Util/7z/FileSignatureChecker.cs @@ -0,0 +1,240 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; + +namespace SevenZip +{ +#if UNMANAGED + /// + /// The signature checker class. Original code by Siddharth Uppal, adapted by Markhor. + /// + /// Based on the code at http://blog.somecreativity.com/2008/04/08/how-to-check-if-a-file-is-compressed-in-c/# + internal static class FileChecker + { + private const int SIGNATURE_SIZE = 16; + private const int SFX_SCAN_LENGTH = 256 * 1024; + + private static bool SpecialDetect(Stream stream, int offset, InArchiveFormat expectedFormat) + { + if (stream.Length > offset + SIGNATURE_SIZE) + { + var signature = new byte[SIGNATURE_SIZE]; + int bytesRequired = SIGNATURE_SIZE; + int index = 0; + stream.Seek(offset, SeekOrigin.Begin); + while (bytesRequired > 0) + { + int bytesRead = stream.Read(signature, index, bytesRequired); + bytesRequired -= bytesRead; + index += bytesRead; + } + string actualSignature = BitConverter.ToString(signature); + foreach (string expectedSignature in Formats.InSignatureFormats.Keys) + { + if (Formats.InSignatureFormats[expectedSignature] != expectedFormat) + { + continue; + } + if (actualSignature.StartsWith(expectedSignature, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + } + return false; + } + + /// + /// Gets the InArchiveFormat for a specific extension. + /// + /// The stream to identify. + /// The archive beginning offset. + /// True if the original format of the stream is PE; otherwise, false. + /// Corresponding InArchiveFormat. + public static InArchiveFormat CheckSignature(Stream stream, out int offset, out bool isExecutable) + { + offset = 0; + if (!stream.CanRead) + { + throw new ArgumentException("The stream must be readable."); + } + if (stream.Length < SIGNATURE_SIZE) + { + throw new ArgumentException("The stream is invalid."); + } + + #region Get file signature + + var signature = new byte[SIGNATURE_SIZE]; + int bytesRequired = SIGNATURE_SIZE; + int index = 0; + stream.Seek(0, SeekOrigin.Begin); + while (bytesRequired > 0) + { + int bytesRead = stream.Read(signature, index, bytesRequired); + bytesRequired -= bytesRead; + index += bytesRead; + } + string actualSignature = BitConverter.ToString(signature); + + #endregion + + InArchiveFormat suspectedFormat = InArchiveFormat.XZ; // any except PE and Cab + isExecutable = false; + + foreach (string expectedSignature in Formats.InSignatureFormats.Keys) + { + if (actualSignature.StartsWith(expectedSignature, StringComparison.OrdinalIgnoreCase) || + actualSignature.Substring(6).StartsWith(expectedSignature, StringComparison.OrdinalIgnoreCase) && + Formats.InSignatureFormats[expectedSignature] == InArchiveFormat.Lzh) + { + if (Formats.InSignatureFormats[expectedSignature] == InArchiveFormat.PE) + { + suspectedFormat = InArchiveFormat.PE; + isExecutable = true; + } + else + { + return Formats.InSignatureFormats[expectedSignature]; + } + } + } + + // Many Microsoft formats + if (actualSignature.StartsWith("D0-CF-11-E0-A1-B1-1A-E1", StringComparison.OrdinalIgnoreCase)) + { + suspectedFormat = InArchiveFormat.Cab; // != InArchiveFormat.XZ + } + + #region SpecialDetect + try + { + SpecialDetect(stream, 257, InArchiveFormat.Tar); + } + catch (ArgumentException) {} + if (SpecialDetect(stream, 0x8001, InArchiveFormat.Iso)) + { + return InArchiveFormat.Iso; + } + if (SpecialDetect(stream, 0x8801, InArchiveFormat.Iso)) + { + return InArchiveFormat.Iso; + } + if (SpecialDetect(stream, 0x9001, InArchiveFormat.Iso)) + { + return InArchiveFormat.Iso; + } + if (SpecialDetect(stream, 0x9001, InArchiveFormat.Iso)) + { + return InArchiveFormat.Iso; + } + if (SpecialDetect(stream, 0x400, InArchiveFormat.Hfs)) + { + return InArchiveFormat.Hfs; + } + #region Last resort for tar - can mistake + if (stream.Length >= 1024) + { + stream.Seek(-1024, SeekOrigin.End); + byte[] buf = new byte[1024]; + stream.Read(buf, 0, 1024); + bool istar = true; + for (int i = 0; i < 1024; i++) + { + istar = istar && buf[i] == 0; + } + if (istar) + { + return InArchiveFormat.Tar; + } + } + #endregion + #endregion + + #region Check if it is an SFX archive or a file with an embedded archive. + if (suspectedFormat != InArchiveFormat.XZ) + { + #region Get first Min(stream.Length, SFX_SCAN_LENGTH) bytes + var scanLength = Math.Min(stream.Length, SFX_SCAN_LENGTH); + signature = new byte[scanLength]; + bytesRequired = (int)scanLength; + index = 0; + stream.Seek(0, SeekOrigin.Begin); + while (bytesRequired > 0) + { + int bytesRead = stream.Read(signature, index, bytesRequired); + bytesRequired -= bytesRead; + index += bytesRead; + } + actualSignature = BitConverter.ToString(signature); + #endregion + + foreach (var format in new InArchiveFormat[] + { + InArchiveFormat.Zip, + InArchiveFormat.SevenZip, + InArchiveFormat.Rar, + InArchiveFormat.Cab, + InArchiveFormat.Arj + }) + { + int pos = actualSignature.IndexOf(Formats.InSignatureFormatsReversed[format]); + if (pos > -1) + { + offset = pos / 3; + return format; + } + } + // Nothing + if (suspectedFormat == InArchiveFormat.PE) + { + return InArchiveFormat.PE; + } + } + #endregion + + throw new ArgumentException("The stream is invalid or no corresponding signature was found."); + } + + /// + /// Gets the InArchiveFormat for a specific file name. + /// + /// The archive file name. + /// The archive beginning offset. + /// True if the original format of the file is PE; otherwise, false. + /// Corresponding InArchiveFormat. + /// + public static InArchiveFormat CheckSignature(string fileName, out int offset, out bool isExecutable) + { + using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + try + { + return CheckSignature(fs, out offset, out isExecutable); + } + catch (ArgumentException) + { + offset = 0; + isExecutable = false; + return Formats.FormatByFileName(fileName, true); + } + } + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/Formats.cs b/BizHawk.Util/7z/Formats.cs new file mode 100644 index 0000000000..3c7acb859e --- /dev/null +++ b/BizHawk.Util/7z/Formats.cs @@ -0,0 +1,529 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.IO; + +namespace SevenZip +{ +#if UNMANAGED + /// + /// Readable archive format enumeration. + /// + public enum InArchiveFormat + { + /// + /// Open 7-zip archive format. + /// + /// Wikipedia information + SevenZip, + /// + /// Proprietary Arj archive format. + /// + /// Wikipedia information + Arj, + /// + /// Open Bzip2 archive format. + /// + /// Wikipedia information + BZip2, + /// + /// Microsoft cabinet archive format. + /// + /// Wikipedia information + Cab, + /// + /// Microsoft Compiled HTML Help file format. + /// + /// Wikipedia information + Chm, + /// + /// Microsoft Compound file format. + /// + /// Wikipedia information + Compound, + /// + /// Open Cpio archive format. + /// + /// Wikipedia information + Cpio, + /// + /// Open Debian software package format. + /// + /// Wikipedia information + Deb, + /// + /// Open Gzip archive format. + /// + /// Wikipedia information + GZip, + /// + /// Open ISO disk image format. + /// + /// Wikipedia information + Iso, + /// + /// Open Lzh archive format. + /// + /// Wikipedia information + Lzh, + /// + /// Open core 7-zip Lzma raw archive format. + /// + /// Wikipedia information + Lzma, + /// + /// Nullsoft installation package format. + /// + /// Wikipedia information + Nsis, + /// + /// RarLab Rar archive format. + /// + /// Wikipedia information + Rar, + /// + /// Open Rpm software package format. + /// + /// Wikipedia information + Rpm, + /// + /// Open split file format. + /// + /// Wikipedia information + Split, + /// + /// Open Tar archive format. + /// + /// Wikipedia information + Tar, + /// + /// Microsoft Windows Imaging disk image format. + /// + /// Wikipedia information + Wim, + /// + /// Open LZW archive format; implemented in "compress" program; also known as "Z" archive format. + /// + /// Wikipedia information + Lzw, + /// + /// Open Zip archive format. + /// + /// Wikipedia information + Zip, + /// + /// Open Udf disk image format. + /// + Udf, + /// + /// Xar open source archive format. + /// + /// Wikipedia information + Xar, + /// + /// Mub + /// + Mub, + /// + /// Macintosh Disk Image on CD. + /// + /// Wikipedia information + Hfs, + /// + /// Apple Mac OS X Disk Copy Disk Image format. + /// + Dmg, + /// + /// Open Xz archive format. + /// + /// Wikipedia information + XZ, + /// + /// MSLZ archive format. + /// + Mslz, + /// + /// Flash video format. + /// + /// Wikipedia information + Flv, + /// + /// Shockwave Flash format. + /// + /// Wikipedia information + Swf, + /// + /// Windows PE executable format. + /// + /// Wikipedia information + PE, + /// + /// Linux executable Elf format. + /// + /// Wikipedia information + Elf, + /// + /// Windows Installer Database. + /// + /// Wikipedia information + Msi, + /// + /// Microsoft virtual hard disk file format. + /// + /// Wikipedia information + Vhd + } + +#if COMPRESS + /// + /// Writable archive format enumeration. + /// + public enum OutArchiveFormat + { + /// + /// Open 7-zip archive format. + /// + /// Wikipedia information + SevenZip, + /// + /// Open Zip archive format. + /// + /// Wikipedia information + Zip, + /// + /// Open Gzip archive format. + /// + /// Wikipedia information + GZip, + /// + /// Open Bzip2 archive format. + /// + /// Wikipedia information + BZip2, + /// + /// Open Tar archive format. + /// + /// Wikipedia information + Tar, + /// + /// Open Xz archive format. + /// + /// Wikipedia information + XZ + } + + /// + /// Compression level enumeration + /// + public enum CompressionLevel + { + /// + /// No compression + /// + None, + /// + /// Very low compression level + /// + Fast, + /// + /// Low compression level + /// + Low, + /// + /// Normal compression level (default) + /// + Normal, + /// + /// High compression level + /// + High, + /// + /// The best compression level (slow) + /// + Ultra + } + + /// + /// Compression method enumeration. + /// + /// Some methods are applicable only to Zip format, some - only to 7-zip. + public enum CompressionMethod + { + /// + /// Zip or 7-zip|no compression method. + /// + Copy, + /// + /// Zip|Deflate method. + /// + Deflate, + /// + /// Zip|Deflate64 method. + /// + Deflate64, + /// + /// Zip or 7-zip|Bzip2 method. + /// + /// Wikipedia information + BZip2, + /// + /// Zip or 7-zip|LZMA method based on Lempel-Ziv algorithm, it is default for 7-zip. + /// + Lzma, + /// + /// 7-zip|LZMA version 2, LZMA with improved multithreading and usually slight archive size decrease. + /// + Lzma2, + /// + /// Zip or 7-zip|PPMd method based on Dmitry Shkarin's PPMdH source code, very efficient for compressing texts. + /// + /// Wikipedia information + Ppmd, + /// + /// No method change. + /// + Default + } +#endif + + /// + /// Archive format routines + /// + public static class Formats + { + /*/// + /// Gets the max value of the specified enum type. + /// + /// Type of the enum + /// Max value + internal static int GetMaxValue(Type type) + { + List enumList = new List((IEnumerable)Enum.GetValues(type)); + enumList.Sort(); + return enumList[enumList.Count - 1]; + }*/ + + /// + /// List of readable archive format interface guids for 7-zip COM interop. + /// + internal static readonly Dictionary InFormatGuids = + new Dictionary(20) + #region InFormatGuids initialization + + { + {InArchiveFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000")}, + {InArchiveFormat.Arj, new Guid("23170f69-40c1-278a-1000-000110040000")}, + {InArchiveFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000")}, + {InArchiveFormat.Cab, new Guid("23170f69-40c1-278a-1000-000110080000")}, + {InArchiveFormat.Chm, new Guid("23170f69-40c1-278a-1000-000110e90000")}, + {InArchiveFormat.Compound, new Guid("23170f69-40c1-278a-1000-000110e50000")}, + {InArchiveFormat.Cpio, new Guid("23170f69-40c1-278a-1000-000110ed0000")}, + {InArchiveFormat.Deb, new Guid("23170f69-40c1-278a-1000-000110ec0000")}, + {InArchiveFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000")}, + {InArchiveFormat.Iso, new Guid("23170f69-40c1-278a-1000-000110e70000")}, + {InArchiveFormat.Lzh, new Guid("23170f69-40c1-278a-1000-000110060000")}, + {InArchiveFormat.Lzma, new Guid("23170f69-40c1-278a-1000-0001100a0000")}, + {InArchiveFormat.Nsis, new Guid("23170f69-40c1-278a-1000-000110090000")}, + {InArchiveFormat.Rar, new Guid("23170f69-40c1-278a-1000-000110030000")}, + {InArchiveFormat.Rpm, new Guid("23170f69-40c1-278a-1000-000110eb0000")}, + {InArchiveFormat.Split, new Guid("23170f69-40c1-278a-1000-000110ea0000")}, + {InArchiveFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000")}, + {InArchiveFormat.Wim, new Guid("23170f69-40c1-278a-1000-000110e60000")}, + {InArchiveFormat.Lzw, new Guid("23170f69-40c1-278a-1000-000110050000")}, + {InArchiveFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000")}, + {InArchiveFormat.Udf, new Guid("23170f69-40c1-278a-1000-000110E00000")}, + {InArchiveFormat.Xar, new Guid("23170f69-40c1-278a-1000-000110E10000")}, + {InArchiveFormat.Mub, new Guid("23170f69-40c1-278a-1000-000110E20000")}, + {InArchiveFormat.Hfs, new Guid("23170f69-40c1-278a-1000-000110E30000")}, + {InArchiveFormat.Dmg, new Guid("23170f69-40c1-278a-1000-000110E40000")}, + {InArchiveFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000")}, + {InArchiveFormat.Mslz, new Guid("23170f69-40c1-278a-1000-000110D50000")}, + {InArchiveFormat.PE, new Guid("23170f69-40c1-278a-1000-000110DD0000")}, + {InArchiveFormat.Elf, new Guid("23170f69-40c1-278a-1000-000110DE0000")}, + {InArchiveFormat.Swf, new Guid("23170f69-40c1-278a-1000-000110D70000")}, + {InArchiveFormat.Vhd, new Guid("23170f69-40c1-278a-1000-000110DC0000")} + }; + + #endregion + +#if COMPRESS + /// + /// List of writable archive format interface guids for 7-zip COM interop. + /// + internal static readonly Dictionary OutFormatGuids = + new Dictionary(2) + #region OutFormatGuids initialization + + { + {OutArchiveFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000")}, + {OutArchiveFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000")}, + {OutArchiveFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000")}, + {OutArchiveFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000")}, + {OutArchiveFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000")}, + {OutArchiveFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000")}, + }; + + #endregion + + internal static readonly Dictionary MethodNames = + new Dictionary(6) + #region MethodNames initialization + + { + {CompressionMethod.Copy, "Copy"}, + {CompressionMethod.Deflate, "Deflate"}, + {CompressionMethod.Deflate64, "Deflate64"}, + {CompressionMethod.Lzma, "LZMA"}, + {CompressionMethod.Lzma2, "LZMA2"}, + {CompressionMethod.Ppmd, "PPMd"}, + {CompressionMethod.BZip2, "BZip2"} + }; + + #endregion + + internal static readonly Dictionary InForOutFormats = + new Dictionary(6) + #region InForOutFormats initialization + + { + {OutArchiveFormat.SevenZip, InArchiveFormat.SevenZip}, + {OutArchiveFormat.GZip, InArchiveFormat.GZip}, + {OutArchiveFormat.BZip2, InArchiveFormat.BZip2}, + {OutArchiveFormat.Tar, InArchiveFormat.Tar}, + {OutArchiveFormat.XZ, InArchiveFormat.XZ}, + {OutArchiveFormat.Zip, InArchiveFormat.Zip} + }; + + #endregion + +#endif + + /// + /// List of archive formats corresponding to specific extensions + /// + private static readonly Dictionary InExtensionFormats = + new Dictionary + #region InExtensionFormats initialization + + {{"7z", InArchiveFormat.SevenZip}, + {"gz", InArchiveFormat.GZip}, + {"tar", InArchiveFormat.Tar}, + {"rar", InArchiveFormat.Rar}, + {"zip", InArchiveFormat.Zip}, + {"lzma", InArchiveFormat.Lzma}, + {"lzh", InArchiveFormat.Lzh}, + {"arj", InArchiveFormat.Arj}, + {"bz2", InArchiveFormat.BZip2}, + {"cab", InArchiveFormat.Cab}, + {"chm", InArchiveFormat.Chm}, + {"deb", InArchiveFormat.Deb}, + {"iso", InArchiveFormat.Iso}, + {"rpm", InArchiveFormat.Rpm}, + {"wim", InArchiveFormat.Wim}, + {"udf", InArchiveFormat.Udf}, + {"mub", InArchiveFormat.Mub}, + {"xar", InArchiveFormat.Xar}, + {"hfs", InArchiveFormat.Hfs}, + {"dmg", InArchiveFormat.Dmg}, + {"Z", InArchiveFormat.Lzw}, + {"xz", InArchiveFormat.XZ}, + {"flv", InArchiveFormat.Flv}, + {"swf", InArchiveFormat.Swf}, + {"exe", InArchiveFormat.PE}, + {"dll", InArchiveFormat.PE}, + {"vhd", InArchiveFormat.Vhd} + }; + + #endregion + + /// + /// List of archive formats corresponding to specific signatures + /// + /// Based on the information at this site. + internal static readonly Dictionary InSignatureFormats = + new Dictionary + #region InSignatureFormats initialization + + {{"37-7A-BC-AF-27-1C", InArchiveFormat.SevenZip}, + {"1F-8B-08", InArchiveFormat.GZip}, + {"75-73-74-61-72", InArchiveFormat.Tar}, + //257 byte offset + {"52-61-72-21-1A-07-00", InArchiveFormat.Rar}, + {"50-4B-03-04", InArchiveFormat.Zip}, + {"5D-00-00-40-00", InArchiveFormat.Lzma}, + {"2D-6C-68", InArchiveFormat.Lzh}, + //^ 2 byte offset + {"1F-9D-90", InArchiveFormat.Lzw}, + {"60-EA", InArchiveFormat.Arj}, + {"42-5A-68", InArchiveFormat.BZip2}, + {"4D-53-43-46", InArchiveFormat.Cab}, + {"49-54-53-46", InArchiveFormat.Chm}, + {"21-3C-61-72-63-68-3E-0A-64-65-62-69-61-6E-2D-62-69-6E-61-72-79", InArchiveFormat.Deb}, + {"43-44-30-30-31", InArchiveFormat.Iso}, + //^ 0x8001, 0x8801 or 0x9001 byte offset + {"ED-AB-EE-DB", InArchiveFormat.Rpm}, + {"4D-53-57-49-4D-00-00-00", InArchiveFormat.Wim}, + {"udf", InArchiveFormat.Udf}, + {"mub", InArchiveFormat.Mub}, + {"78-61-72-21", InArchiveFormat.Xar}, + //0x400 byte offset + {"48-2B", InArchiveFormat.Hfs}, + {"FD-37-7A-58-5A", InArchiveFormat.XZ}, + {"46-4C-56", InArchiveFormat.Flv}, + {"46-57-53", InArchiveFormat.Swf}, + {"4D-5A", InArchiveFormat.PE}, + {"7F-45-4C-46", InArchiveFormat.Elf}, + {"78", InArchiveFormat.Dmg}, + {"63-6F-6E-65-63-74-69-78", InArchiveFormat.Vhd}}; + #endregion + + internal static Dictionary InSignatureFormatsReversed; + + static Formats() + { + InSignatureFormatsReversed = new Dictionary(InSignatureFormats.Count); + foreach (var pair in InSignatureFormats) + { + InSignatureFormatsReversed.Add(pair.Value, pair.Key); + } + } + + /// + /// Gets InArchiveFormat for specified archive file name + /// + /// Archive file name + /// Indicates whether to throw exceptions + /// InArchiveFormat recognized by the file name extension + /// + public static InArchiveFormat FormatByFileName(string fileName, bool reportErrors) + { + if (String.IsNullOrEmpty(fileName) && reportErrors) + { + throw new ArgumentException("File name is null or empty string!"); + } + string extension = Path.GetExtension(fileName).Substring(1); + if (!InExtensionFormats.ContainsKey(extension) && reportErrors) + { + throw new ArgumentException("Extension \"" + extension + + "\" is not a supported archive file name extension."); + } + return InExtensionFormats[extension]; + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/LibraryFeature.cs b/BizHawk.Util/7z/LibraryFeature.cs new file mode 100644 index 0000000000..fdc1d5a3bf --- /dev/null +++ b/BizHawk.Util/7z/LibraryFeature.cs @@ -0,0 +1,112 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; + +namespace SevenZip +{ + /// + /// The set of features supported by the library. + /// + [Flags] + public enum LibraryFeature : uint + { + /// + /// Default feature. + /// + None = 0, + /// + /// The library can extract 7zip archives compressed with LZMA method. + /// + Extract7z = 0x1, + /// + /// The library can extract 7zip archives compressed with LZMA2 method. + /// + Extract7zLZMA2 = 0x2, + /// + /// The library can extract 7z archives compressed with all known methods. + /// + Extract7zAll = Extract7z|Extract7zLZMA2|0x4, + /// + /// The library can extract zip archives. + /// + ExtractZip = 0x8, + /// + /// The library can extract rar archives. + /// + ExtractRar = 0x10, + /// + /// The library can extract gzip archives. + /// + ExtractGzip = 0x20, + /// + /// The library can extract bzip2 archives. + /// + ExtractBzip2 = 0x40, + /// + /// The library can extract tar archives. + /// + ExtractTar = 0x80, + /// + /// The library can extract xz archives. + /// + ExtractXz = 0x100, + /// + /// The library can extract all types of archives supported. + /// + ExtractAll = Extract7zAll|ExtractZip|ExtractRar|ExtractGzip|ExtractBzip2|ExtractTar|ExtractXz, + /// + /// The library can compress data to 7zip archives with LZMA method. + /// + Compress7z = 0x200, + /// + /// The library can compress data to 7zip archives with LZMA2 method. + /// + Compress7zLZMA2 = 0x400, + /// + /// The library can compress data to 7zip archives with all methods known. + /// + Compress7zAll = Compress7z|Compress7zLZMA2|0x800, + /// + /// The library can compress data to tar archives. + /// + CompressTar = 0x1000, + /// + /// The library can compress data to gzip archives. + /// + CompressGzip = 0x2000, + /// + /// The library can compress data to bzip2 archives. + /// + CompressBzip2 = 0x4000, + /// + /// The library can compress data to xz archives. + /// + CompressXz = 0x8000, + /// + /// The library can compress data to zip archives. + /// + CompressZip = 0x10000, + /// + /// The library can compress data to all types of archives supported. + /// + CompressAll = Compress7zAll|CompressTar|CompressGzip|CompressBzip2|CompressXz|CompressZip, + /// + /// The library can modify archives. + /// + Modify = 0x20000 + } +} diff --git a/BizHawk.Util/7z/LibraryManager.cs b/BizHawk.Util/7z/LibraryManager.cs new file mode 100644 index 0000000000..dbf1aece9b --- /dev/null +++ b/BizHawk.Util/7z/LibraryManager.cs @@ -0,0 +1,563 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +#if !WINCE && !MONO +using System.Configuration; +using System.Diagnostics; +using System.Security.Permissions; +#endif +#if WINCE +using OpenNETCF.Diagnostics; +#endif +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ +#if UNMANAGED + /// + /// 7-zip library low-level wrapper. + /// + internal static class SevenZipLibraryManager + { +#if !WINCE && !MONO + /// + /// Path to the 7-zip dll. + /// + /// 7zxa.dll supports only decoding from .7z archives. + /// Features of 7za.dll: + /// - Supporting 7z format; + /// - Built encoders: LZMA, PPMD, BCJ, BCJ2, COPY, AES-256 Encryption. + /// - Built decoders: LZMA, PPMD, BCJ, BCJ2, COPY, AES-256 Encryption, BZip2, Deflate. + /// 7z.dll (from the 7-zip distribution) supports every InArchiveFormat for encoding and decoding. + /// + //private static string _libraryFileName = ConfigurationManager.AppSettings["7zLocation"] ?? Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "7z.dll"); + private static string _libraryFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "7z.dll"); +#endif +#if WINCE + private static string _libraryFileName = + Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase), "7z.dll"); +#endif + /// + /// 7-zip library handle. + /// + private static IntPtr _modulePtr; + + /// + /// 7-zip library features. + /// + private static LibraryFeature? _features; + + private static Dictionary> _inArchives; +#if COMPRESS + private static Dictionary> _outArchives; +#endif + private static int _totalUsers; + + // private static string _LibraryVersion; + private static bool? _modifyCapabale; + + private static void InitUserInFormat(object user, InArchiveFormat format) + { + if (!_inArchives.ContainsKey(user)) + { + _inArchives.Add(user, new Dictionary()); + } + if (!_inArchives[user].ContainsKey(format)) + { + _inArchives[user].Add(format, null); + _totalUsers++; + } + } + +#if COMPRESS + private static void InitUserOutFormat(object user, OutArchiveFormat format) + { + if (!_outArchives.ContainsKey(user)) + { + _outArchives.Add(user, new Dictionary()); + } + if (!_outArchives[user].ContainsKey(format)) + { + _outArchives[user].Add(format, null); + _totalUsers++; + } + } +#endif + + private static void Init() + { + _inArchives = new Dictionary>(); +#if COMPRESS + _outArchives = new Dictionary>(); +#endif + } + + /// + /// Loads the 7-zip library if necessary and adds user to the reference list + /// + /// Caller of the function + /// Archive format + public static void LoadLibrary(object user, Enum format) + { + if (_inArchives == null +#if COMPRESS + || _outArchives == null +#endif + ) + { + Init(); + } +#if !WINCE && !MONO + if (_modulePtr == IntPtr.Zero) + { + if (!File.Exists(_libraryFileName)) + { + throw new SevenZipLibraryException("DLL file does not exist."); + } + if ((_modulePtr = NativeMethods.LoadLibrary(_libraryFileName)) == IntPtr.Zero) + { + throw new SevenZipLibraryException("failed to load library."); + } + if (NativeMethods.GetProcAddress(_modulePtr, "GetHandlerProperty") == IntPtr.Zero) + { + NativeMethods.FreeLibrary(_modulePtr); + throw new SevenZipLibraryException("library is invalid."); + } + } +#endif + if (format is InArchiveFormat) + { + InitUserInFormat(user, (InArchiveFormat) format); + return; + } +#if COMPRESS + if (format is OutArchiveFormat) + { + InitUserOutFormat(user, (OutArchiveFormat) format); + return; + } +#endif + throw new ArgumentException( + "Enum " + format + " is not a valid archive format attribute!"); + } + + /*/// + /// Gets the native 7zip library version string. + /// + public static string LibraryVersion + { + get + { + if (String.IsNullOrEmpty(_LibraryVersion)) + { + FileVersionInfo dllVersionInfo = FileVersionInfo.GetVersionInfo(_libraryFileName); + _LibraryVersion = String.Format( + System.Globalization.CultureInfo.CurrentCulture, + "{0}.{1}", + dllVersionInfo.FileMajorPart, dllVersionInfo.FileMinorPart); + } + return _LibraryVersion; + } + }*/ + + /// + /// Gets the value indicating whether the library supports modifying archives. + /// + public static bool ModifyCapable + { + get + { + if (!_modifyCapabale.HasValue) + { +#if !WINCE && !MONO + FileVersionInfo dllVersionInfo = FileVersionInfo.GetVersionInfo(_libraryFileName); + _modifyCapabale = dllVersionInfo.FileMajorPart >= 9; +#else + _modifyCapabale = true; +#endif + } + return _modifyCapabale.Value; + } + } + + static readonly string Namespace = Assembly.GetExecutingAssembly().GetManifestResourceNames()[0].Split('.')[0]; + + private static string GetResourceString(string str) + { + return Namespace + ".arch." + str; + } + + private static bool ExtractionBenchmark(string archiveFileName, Stream outStream, + ref LibraryFeature? features, LibraryFeature testedFeature) + { + var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream( + GetResourceString(archiveFileName)); + try + { + using (var extr = new SevenZipExtractor(stream)) + { + extr.ExtractFile(0, outStream); + } + } + catch(Exception) + { + return false; + } + features |= testedFeature; + return true; + } + + private static bool CompressionBenchmark(Stream inStream, Stream outStream, + OutArchiveFormat format, CompressionMethod method, + ref LibraryFeature? features, LibraryFeature testedFeature) + { + try + { + var compr = new SevenZipCompressor {ArchiveFormat = format, CompressionMethod = method}; + compr.CompressStream(inStream, outStream); + } + catch (Exception) + { + return false; + } + features |= testedFeature; + return true; + } + + public static LibraryFeature CurrentLibraryFeatures + { + get + { + if (_features != null && _features.HasValue) + { + return _features.Value; + } + _features = LibraryFeature.None; + #region Benchmark + #region Extraction features + using (var outStream = new MemoryStream()) + { + ExtractionBenchmark("Test.lzma.7z", outStream, ref _features, LibraryFeature.Extract7z); + ExtractionBenchmark("Test.lzma2.7z", outStream, ref _features, LibraryFeature.Extract7zLZMA2); + int i = 0; + if (ExtractionBenchmark("Test.bzip2.7z", outStream, ref _features, _features.Value)) + { + i++; + } + if (ExtractionBenchmark("Test.ppmd.7z", outStream, ref _features, _features.Value)) + { + i++; + if (i == 2 && (_features & LibraryFeature.Extract7z) != 0 && + (_features & LibraryFeature.Extract7zLZMA2) != 0) + { + _features |= LibraryFeature.Extract7zAll; + } + } + ExtractionBenchmark("Test.rar", outStream, ref _features, LibraryFeature.ExtractRar); + ExtractionBenchmark("Test.tar", outStream, ref _features, LibraryFeature.ExtractTar); + ExtractionBenchmark("Test.txt.bz2", outStream, ref _features, LibraryFeature.ExtractBzip2); + ExtractionBenchmark("Test.txt.gz", outStream, ref _features, LibraryFeature.ExtractGzip); + ExtractionBenchmark("Test.txt.xz", outStream, ref _features, LibraryFeature.ExtractXz); + ExtractionBenchmark("Test.zip", outStream, ref _features, LibraryFeature.ExtractZip); + } + #endregion + #region Compression features + using (var inStream = new MemoryStream()) + { + inStream.Write(Encoding.UTF8.GetBytes("Test"), 0, 4); + using (var outStream = new MemoryStream()) + { + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.SevenZip, CompressionMethod.Lzma, + ref _features, LibraryFeature.Compress7z); + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.SevenZip, CompressionMethod.Lzma2, + ref _features, LibraryFeature.Compress7zLZMA2); + int i = 0; + if (CompressionBenchmark(inStream, outStream, + OutArchiveFormat.SevenZip, CompressionMethod.BZip2, + ref _features, _features.Value)) + { + i++; + } + if (CompressionBenchmark(inStream, outStream, + OutArchiveFormat.SevenZip, CompressionMethod.Ppmd, + ref _features, _features.Value)) + { + i++; + if (i == 2 && (_features & LibraryFeature.Compress7z) != 0 && + (_features & LibraryFeature.Compress7zLZMA2) != 0) + { + _features |= LibraryFeature.Compress7zAll; + } + } + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.Zip, CompressionMethod.Default, + ref _features, LibraryFeature.CompressZip); + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.BZip2, CompressionMethod.Default, + ref _features, LibraryFeature.CompressBzip2); + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.GZip, CompressionMethod.Default, + ref _features, LibraryFeature.CompressGzip); + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.Tar, CompressionMethod.Default, + ref _features, LibraryFeature.CompressTar); + CompressionBenchmark(inStream, outStream, + OutArchiveFormat.XZ, CompressionMethod.Default, + ref _features, LibraryFeature.CompressXz); + } + } + #endregion + #endregion + if (ModifyCapable && (_features.Value & LibraryFeature.Compress7z) != 0) + { + _features |= LibraryFeature.Modify; + } + return _features.Value; + } + } + + /// + /// Removes user from reference list and frees the 7-zip library if it becomes empty + /// + /// Caller of the function + /// Archive format + public static void FreeLibrary(object user, Enum format) + { +#if !WINCE && !MONO + var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + sp.Demand(); +#endif + if (_modulePtr != IntPtr.Zero) + { + if (format is InArchiveFormat) + { + if (_inArchives != null && _inArchives.ContainsKey(user) && + _inArchives[user].ContainsKey((InArchiveFormat) format) && + _inArchives[user][(InArchiveFormat) format] != null) + { + try + { + Marshal.ReleaseComObject(_inArchives[user][(InArchiveFormat) format]); + } + catch (InvalidComObjectException) {} + _inArchives[user].Remove((InArchiveFormat) format); + _totalUsers--; + if (_inArchives[user].Count == 0) + { + _inArchives.Remove(user); + } + } + } +#if COMPRESS + if (format is OutArchiveFormat) + { + if (_outArchives != null && _outArchives.ContainsKey(user) && + _outArchives[user].ContainsKey((OutArchiveFormat) format) && + _outArchives[user][(OutArchiveFormat) format] != null) + { + try + { + Marshal.ReleaseComObject(_outArchives[user][(OutArchiveFormat) format]); + } + catch (InvalidComObjectException) {} + _outArchives[user].Remove((OutArchiveFormat) format); + _totalUsers--; + if (_outArchives[user].Count == 0) + { + _outArchives.Remove(user); + } + } + } +#endif + if ((_inArchives == null || _inArchives.Count == 0) +#if COMPRESS + && (_outArchives == null || _outArchives.Count == 0) +#endif + ) + { + _inArchives = null; +#if COMPRESS + _outArchives = null; +#endif + if (_totalUsers == 0) + { +#if !WINCE && !MONO + NativeMethods.FreeLibrary(_modulePtr); + +#endif + _modulePtr = IntPtr.Zero; + } + } + } + } + + /// + /// Gets IInArchive interface to extract 7-zip archives. + /// + /// Archive format. + /// Archive format user. + public static IInArchive InArchive(InArchiveFormat format, object user) + { +#if !WINCE && !MONO + lock (_libraryFileName) + { +#endif + if (_inArchives[user][format] == null) + { +#if !WINCE && !MONO + var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + sp.Demand(); + + if (_modulePtr == IntPtr.Zero) + { + LoadLibrary(user, format); + if (_modulePtr == IntPtr.Zero) + { + throw new SevenZipLibraryException(); + } + } + var createObject = (NativeMethods.CreateObjectDelegate) + Marshal.GetDelegateForFunctionPointer( + NativeMethods.GetProcAddress(_modulePtr, "CreateObject"), + typeof(NativeMethods.CreateObjectDelegate)); + if (createObject == null) + { + throw new SevenZipLibraryException(); + } +#endif + object result; + Guid interfaceId = +#if !WINCE && !MONO + typeof(IInArchive).GUID; +#else + new Guid(((GuidAttribute)typeof(IInArchive).GetCustomAttributes(typeof(GuidAttribute), false)[0]).Value); +#endif + Guid classID = Formats.InFormatGuids[format]; + try + { +#if !WINCE && !MONO + createObject(ref classID, ref interfaceId, out result); +#elif !MONO + NativeMethods.CreateCOMObject(ref classID, ref interfaceId, out result); +#else + result = SevenZip.Mono.Factory.CreateInterface(user, classID, interfaceId); +#endif + } + catch (Exception) + { + throw new SevenZipLibraryException("Your 7-zip library does not support this archive type."); + } + InitUserInFormat(user, format); + _inArchives[user][format] = result as IInArchive; + } +#if !WINCE && !MONO + } +#endif + return _inArchives[user][format]; + } + +#if COMPRESS + /// + /// Gets IOutArchive interface to pack 7-zip archives. + /// + /// Archive format. + /// Archive format user. + public static IOutArchive OutArchive(OutArchiveFormat format, object user) + { +#if !WINCE && !MONO + lock (_libraryFileName) + { +#endif + if (_outArchives[user][format] == null) + { +#if !WINCE && !MONO + var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + sp.Demand(); + if (_modulePtr == IntPtr.Zero) + { + throw new SevenZipLibraryException(); + } + var createObject = (NativeMethods.CreateObjectDelegate) + Marshal.GetDelegateForFunctionPointer( + NativeMethods.GetProcAddress(_modulePtr, "CreateObject"), + typeof(NativeMethods.CreateObjectDelegate)); + if (createObject == null) + { + throw new SevenZipLibraryException(); + } +#endif + object result; + Guid interfaceId = +#if !WINCE && !MONO + typeof(IOutArchive).GUID; +#else + new Guid(((GuidAttribute)typeof(IOutArchive).GetCustomAttributes(typeof(GuidAttribute), false)[0]).Value); +#endif + Guid classID = Formats.OutFormatGuids[format]; + try + { +#if !WINCE && !MONO + createObject(ref classID, ref interfaceId, out result); +#elif !MONO + NativeMethods.CreateCOMObject(ref classID, ref interfaceId, out result); +#else + result = SevenZip.Mono.Factory.CreateInterface(classID, interfaceId, user); +#endif + } + catch (Exception) + { + throw new SevenZipLibraryException("Your 7-zip library does not support this archive type."); + } + InitUserOutFormat(user, format); + _outArchives[user][format] = result as IOutArchive; + } +#if !WINCE && !MONO + } +#endif + return _outArchives[user][format]; + } +#endif +#if !WINCE && !MONO + public static void SetLibraryPath(string libraryPath) + { + if (_modulePtr != IntPtr.Zero && !Path.GetFullPath(libraryPath).Equals( + Path.GetFullPath(_libraryFileName), StringComparison.OrdinalIgnoreCase)) + { + throw new SevenZipLibraryException( + "can not change the library path while the library \"" + _libraryFileName + "\" is being used."); + } + if (!File.Exists(libraryPath)) + { + throw new SevenZipLibraryException( + "can not change the library path because the file \"" + libraryPath + "\" does not exist."); + } + _libraryFileName = libraryPath; + _features = null; + } +#endif + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/LzmaDecodeStream.cs b/BizHawk.Util/7z/LzmaDecodeStream.cs new file mode 100644 index 0000000000..16946d5a1a --- /dev/null +++ b/BizHawk.Util/7z/LzmaDecodeStream.cs @@ -0,0 +1,240 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; +using SevenZip.Sdk.Compression.Lzma; + +namespace SevenZip +{ +#if LZMA_STREAM + /// + /// The stream which decompresses data with LZMA on the fly. + /// + public class LzmaDecodeStream : Stream + { + private readonly MemoryStream _buffer = new MemoryStream(); + private readonly Decoder _decoder = new Decoder(); + private readonly Stream _input; + private byte[] _commonProperties; + private bool _error; + private bool _firstChunkRead; + + /// + /// Initializes a new instance of the LzmaDecodeStream class. + /// + /// A compressed stream. + public LzmaDecodeStream(Stream encodedStream) + { + if (!encodedStream.CanRead) + { + throw new ArgumentException("The specified stream can not read.", "encodedStream"); + } + _input = encodedStream; + } + + /// + /// Gets the chunk size. + /// + public int ChunkSize + { + get + { + return (int) _buffer.Length; + } + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get + { + return true; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get + { + return false; + } + } + + /// + /// Gets the length in bytes of the output stream. + /// + public override long Length + { + get + { + if (_input.CanSeek) + { + return _input.Length; + } + return _buffer.Length; + } + } + + /// + /// Gets or sets the position within the output stream. + /// + public override long Position + { + get + { + if (_input.CanSeek) + { + return _input.Position; + } + return _buffer.Position; + } + set + { + throw new NotSupportedException(); + } + } + + private void ReadChunk() + { + long size; + byte[] properties; + try + { + properties = SevenZipExtractor.GetLzmaProperties(_input, out size); + } + catch (LzmaException) + { + _error = true; + return; + } + if (!_firstChunkRead) + { + _commonProperties = properties; + } + if (_commonProperties[0] != properties[0] || + _commonProperties[1] != properties[1] || + _commonProperties[2] != properties[2] || + _commonProperties[3] != properties[3] || + _commonProperties[4] != properties[4]) + { + _error = true; + return; + } + if (_buffer.Capacity < (int) size) + { + _buffer.Capacity = (int) size; + } + _buffer.SetLength(size); + _decoder.SetDecoderProperties(properties); + _buffer.Position = 0; + _decoder.Code( + _input, _buffer, 0, size, null); + _buffer.Position = 0; + } + + /// + /// Does nothing. + /// + public override void Flush() {} + + /// + /// Reads a sequence of bytes from the current stream and decompresses data if necessary. + /// + /// An array of bytes. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// The total number of bytes read into the buffer. + public override int Read(byte[] buffer, int offset, int count) + { + if (_error) + { + return 0; + } + + if (!_firstChunkRead) + { + ReadChunk(); + _firstChunkRead = true; + } + int readCount = 0; + while (count > _buffer.Length - _buffer.Position && !_error) + { + var buf = new byte[_buffer.Length - _buffer.Position]; + _buffer.Read(buf, 0, buf.Length); + buf.CopyTo(buffer, offset); + offset += buf.Length; + count -= buf.Length; + readCount += buf.Length; + ReadChunk(); + } + if (!_error) + { + _buffer.Read(buffer, offset, count); + readCount += count; + } + return readCount; + } + + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position. + /// The new position within the current stream. + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// Writes a sequence of bytes to the current stream. + /// + /// An array of bytes. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/LzmaEncodeStream.cs b/BizHawk.Util/7z/LzmaEncodeStream.cs new file mode 100644 index 0000000000..bc9165e39f --- /dev/null +++ b/BizHawk.Util/7z/LzmaEncodeStream.cs @@ -0,0 +1,304 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; +using SevenZip.Sdk.Compression.Lzma; + +namespace SevenZip +{ +#if LZMA_STREAM +#if COMPRESS + /// + /// The stream which compresses data with LZMA on the fly. + /// + public class LzmaEncodeStream : Stream + { + private const int MAX_BUFFER_CAPACITY = 1 << 30; //1 Gb + private readonly MemoryStream _buffer = new MemoryStream(); + private readonly int _bufferCapacity = 1 << 18; //256 kb + private readonly bool _ownOutput; + private bool _disposed; + private Encoder _lzmaEncoder; + private Stream _output; + + /// + /// Initializes a new instance of the LzmaEncodeStream class. + /// + public LzmaEncodeStream() + { + _output = new MemoryStream(); + _ownOutput = true; + Init(); + } + + /// + /// Initializes a new instance of the LzmaEncodeStream class. + /// + /// The buffer size. The bigger size, the better compression. + public LzmaEncodeStream(int bufferCapacity) + { + _output = new MemoryStream(); + _ownOutput = true; + if (bufferCapacity > MAX_BUFFER_CAPACITY) + { + throw new ArgumentException("Too large capacity.", "bufferCapacity"); + } + _bufferCapacity = bufferCapacity; + Init(); + } + + /// + /// Initializes a new instance of the LzmaEncodeStream class. + /// + /// An output stream which supports writing. + public LzmaEncodeStream(Stream outputStream) + { + if (!outputStream.CanWrite) + { + throw new ArgumentException("The specified stream can not write.", "outputStream"); + } + _output = outputStream; + Init(); + } + + /// + /// Initializes a new instance of the LzmaEncodeStream class. + /// + /// An output stream which supports writing. + /// A buffer size. The bigger size, the better compression. + public LzmaEncodeStream(Stream outputStream, int bufferCapacity) + { + if (!outputStream.CanWrite) + { + throw new ArgumentException("The specified stream can not write.", "outputStream"); + } + _output = outputStream; + if (bufferCapacity > 1 << 30) + { + throw new ArgumentException("Too large capacity.", "bufferCapacity"); + } + _bufferCapacity = bufferCapacity; + Init(); + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get + { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get + { + DisposedCheck(); + return _buffer.CanWrite; + } + } + + /// + /// Gets the length in bytes of the output stream. + /// + public override long Length + { + get + { + DisposedCheck(); + if (_output.CanSeek) + { + return _output.Length; + } + return _buffer.Position; + } + } + + /// + /// Gets or sets the position within the output stream. + /// + public override long Position + { + get + { + DisposedCheck(); + if (_output.CanSeek) + { + return _output.Position; + } + return _buffer.Position; + } + set + { + throw new NotSupportedException(); + } + } + + private void Init() + { + _buffer.Capacity = _bufferCapacity; + SevenZipCompressor.LzmaDictionarySize = _bufferCapacity; + _lzmaEncoder = new Encoder(); + SevenZipCompressor.WriteLzmaProperties(_lzmaEncoder); + } + + /// + /// Checked whether the class was disposed. + /// + /// + private void DisposedCheck() + { + if (_disposed) + { + throw new ObjectDisposedException("SevenZipExtractor"); + } + } + + private void WriteChunk() + { + _lzmaEncoder.WriteCoderProperties(_output); + long streamSize = _buffer.Position; + if (_buffer.Length != _buffer.Position) + { + _buffer.SetLength(_buffer.Position); + } + _buffer.Position = 0; + for (int i = 0; i < 8; i++) + { + _output.WriteByte((byte) (streamSize >> (8*i))); + } + _lzmaEncoder.Code(_buffer, _output, -1, -1, null); + _buffer.Position = 0; + } + + /// + /// Converts the LzmaEncodeStream to the LzmaDecodeStream to read data. + /// + /// + public LzmaDecodeStream ToDecodeStream() + { + DisposedCheck(); + Flush(); + return new LzmaDecodeStream(_output); + } + + /// + /// Clears all buffers for this stream and causes any buffered data to be compressed and written. + /// + public override void Flush() + { + DisposedCheck(); + WriteChunk(); + } + + /// + /// Releases all unmanaged resources used by LzmaEncodeStream. + /// + protected override void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + Flush(); + _buffer.Close(); + if (_ownOutput) + { + _output.Dispose(); + } + _output = null; + } + _disposed = true; + } + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// The total number of bytes read into the buffer. + public override int Read(byte[] buffer, int offset, int count) + { + DisposedCheck(); + throw new NotSupportedException(); + } + + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position. + /// The new position within the current stream. + public override long Seek(long offset, SeekOrigin origin) + { + DisposedCheck(); + throw new NotSupportedException(); + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + public override void SetLength(long value) + { + DisposedCheck(); + throw new NotSupportedException(); + } + + /// + /// Writes a sequence of bytes to the current stream and compresses it if necessary. + /// + /// An array of bytes. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + public override void Write(byte[] buffer, int offset, int count) + { + DisposedCheck(); + int dataLength = Math.Min(buffer.Length - offset, count); + while (_buffer.Position + dataLength >= _bufferCapacity) + { + int length = _bufferCapacity - (int) _buffer.Position; + _buffer.Write(buffer, offset, length); + offset = length + offset; + dataLength -= length; + WriteChunk(); + } + _buffer.Write(buffer, offset, dataLength); + } + } +#endif +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/LzmaProgressCallback.cs b/BizHawk.Util/7z/LzmaProgressCallback.cs new file mode 100644 index 0000000000..fee8c7abad --- /dev/null +++ b/BizHawk.Util/7z/LzmaProgressCallback.cs @@ -0,0 +1,72 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using SevenZip.Sdk; + +namespace SevenZip +{ + /// + /// Callback to implement the ICodeProgress interface + /// + internal sealed class LzmaProgressCallback : ICodeProgress + { + private readonly long _inSize; + private float _oldPercentDone; + + /// + /// Initializes a new instance of the LzmaProgressCallback class + /// + /// The input size + /// Progress event handler + public LzmaProgressCallback(long inSize, EventHandler working) + { + _inSize = inSize; + Working += working; + } + + #region ICodeProgress Members + + /// + /// Sets the progress + /// + /// The processed input size + /// The processed output size + public void SetProgress(long inSize, long outSize) + { + if (Working != null) + { + float newPercentDone = (inSize + 0.0f) / _inSize; + float delta = newPercentDone - _oldPercentDone; + if (delta * 100 < 1.0) + { + delta = 0; + } + else + { + _oldPercentDone = newPercentDone; + } + Working(this, new ProgressEventArgs( + PercentDoneEventArgs.ProducePercentDone(newPercentDone), + delta > 0 ? PercentDoneEventArgs.ProducePercentDone(delta) : (byte)0)); + } + } + + #endregion + + public event EventHandler Working; + } +} diff --git a/BizHawk.Util/7z/NativeMethods.cs b/BizHawk.Util/7z/NativeMethods.cs new file mode 100644 index 0000000000..02ef5e7eb4 --- /dev/null +++ b/BizHawk.Util/7z/NativeMethods.cs @@ -0,0 +1,77 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Runtime.InteropServices; +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ +#if UNMANAGED + internal static class NativeMethods + { + #if !WINCE && !MONO + #region Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate int CreateObjectDelegate( + [In] ref Guid classID, + [In] ref Guid interfaceID, + [MarshalAs(UnmanagedType.Interface)] out object outObject); + + #endregion + + [DllImport("kernel32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true)] + public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string fileName); + + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FreeLibrary(IntPtr hModule); + + [DllImport("kernel32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true)] + public static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName); + #endif + + #if WINCE + [DllImport("7z.dll", EntryPoint="CreateObject")] + public static extern int CreateCOMObject( + [In] ref Guid classID, + [In] ref Guid interfaceID, + [MarshalAs(UnmanagedType.Interface)] out object outObject); + #endif + + public static T SafeCast(PropVariant var, T def) + { + object obj; + try + { + obj = var.Object; + } + catch (Exception) + { + return def; + } + if (obj != null && obj is T) + { + return (T) obj; + } + return def; + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/SevenZipCompressor.cs b/BizHawk.Util/7z/SevenZipCompressor.cs new file mode 100644 index 0000000000..2227150f97 --- /dev/null +++ b/BizHawk.Util/7z/SevenZipCompressor.cs @@ -0,0 +1,2048 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +#if DOTNET20 +using System.Threading; +#else +using System.Linq; +#endif +using System.Runtime.InteropServices; +#if !WINCE +using System.Security.Permissions; +#endif +using SevenZip.Sdk; +using SevenZip.Sdk.Compression.Lzma; +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ +#if COMPRESS + /// + /// Class for packing files into 7-zip archives + /// + public sealed partial class SevenZipCompressor +#if UNMANAGED + : SevenZipBase +#endif + { +#if UNMANAGED + #region Fields + private bool _compressingFilesOnDisk; + /// + /// Gets or sets the archiving compression level. + /// + public CompressionLevel CompressionLevel { get; set; } + private OutArchiveFormat _archiveFormat = OutArchiveFormat.SevenZip; + private CompressionMethod _compressionMethod = CompressionMethod.Default; + /// + /// Gets the custom compression parameters - for advanced users only. + /// + public Dictionary CustomParameters { get; private set; } + private int _volumeSize; + private string _archiveName; + /// + /// Gets or sets the value indicating whether to include empty directories to archives. Default is true. + /// + public bool IncludeEmptyDirectories { get; set; } + /// + /// Gets or sets the value indicating whether to preserve the directory root for CompressDirectory. + /// + public bool PreserveDirectoryRoot { get; set; } + /// + /// Gets or sets the value indicating whether to preserve the directory structure. + /// + public bool DirectoryStructure { get; set; } + private bool _directoryCompress; + /// + /// Gets or sets the compression mode. + /// + public CompressionMode CompressionMode { get; set; } + private UpdateData _updateData; + private uint _oldFilesCount; + /// + /// Gets or sets the value indicating whether to encrypt 7-Zip archive headers. + /// + public bool EncryptHeaders { get; set; } + /// + /// Gets or sets the value indicating whether to compress files only open for writing. + /// + public bool ScanOnlyWritable { get; set; } + /// + /// Gets or sets the encryption method for zip archives. + /// + public ZipEncryptionMethod ZipEncryptionMethod { get; set; } + /// + /// Gets or sets the temporary folder path. + /// + public string TempFolderPath { get; set; } + /// + /// Gets or sets the default archive item name used when an item to be compressed has no name, + /// for example, when you compress a MemoryStream instance. + /// + public string DefaultItemName { get; set; } + /// + /// Gets or sets the value indicating whether to compress as fast as possible, without calling events. + /// + public bool FastCompression { get; set; } + #endregion +#endif + private static int _lzmaDictionarySize = 1 << 22; + +#if UNMANAGED + + private void CommonInit() + { + DirectoryStructure = true; + IncludeEmptyDirectories = true; + CompressionLevel = CompressionLevel.Normal; + CompressionMode = CompressionMode.Create; + ZipEncryptionMethod = ZipEncryptionMethod.ZipCrypto; + CustomParameters = new Dictionary(); + _updateData = new UpdateData(); + DefaultItemName = "default"; + } + + /// + /// Initializes a new instance of the SevenZipCompressor class. + /// + public SevenZipCompressor() + { + try + { +#if !WINCE + TempFolderPath = Path.GetTempPath(); + //TempFolderPath = Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.User); +#else + TempFolderPath = "Temp"; +#endif + } + catch (System.Security.SecurityException) // Registry access is not allowed, etc. + { + /*throw new SevenZipCompressionFailedException( + "Attempted to get TEMP environment variable but registry access was not allowed (security settings on your machine). You must call SevenZipCompressor constructor overload with your own temporary path."); + */ + throw new SevenZipCompressionFailedException( + "Path.GetTempPath() threw a System.Security.SecurityException. You must call SevenZipCompressor constructor overload with your own temporary path."); + } + CommonInit(); + } + + /// + /// Initializes a new instance of the SevenZipCompressor class. + /// + /// Your own temporary path (default is set in the parameterless constructor overload.) + public SevenZipCompressor(string temporaryPath) + { + TempFolderPath = temporaryPath; + if (!Directory.Exists(TempFolderPath)) + { + try + { + Directory.CreateDirectory(TempFolderPath); + } + catch (Exception) + { + throw new SevenZipCompressionFailedException("The specified temporary path is invalid."); + } + } + CommonInit(); + } +#endif + + /// + /// Checks if the specified stream supports compression. + /// + /// The stream to check. + private static void ValidateStream(Stream stream) + { + if (!stream.CanWrite || !stream.CanSeek) + { + throw new ArgumentException("The specified stream can not seek or is not writable.", "stream"); + } + } + +#if UNMANAGED + + #region Private functions + + private IOutArchive MakeOutArchive(IInStream inArchiveStream) + { + IInArchive inArchive = SevenZipLibraryManager.InArchive( + Formats.InForOutFormats[_archiveFormat], this); + using (ArchiveOpenCallback openCallback = GetArchiveOpenCallback()) + { + ulong checkPos = 1 << 15; + if (inArchive.Open(inArchiveStream, ref checkPos, openCallback) != (int) OperationResult.Ok) + { + if ( + !ThrowException(null, new SevenZipArchiveException("Can not update the archive: Open() failed."))) + { + return null; + } + } + _oldFilesCount = inArchive.GetNumberOfItems(); + } + return (IOutArchive) inArchive; + } + + /// + /// Guaranties the correct work of the SetCompressionProperties function + /// + /// The compression method to check + /// The value indicating whether the specified method is valid for the current ArchiveFormat + private bool MethodIsValid(CompressionMethod method) + { + if (method == CompressionMethod.Default) + { + return true; + } + switch (_archiveFormat) + { + case OutArchiveFormat.Zip: + return method != CompressionMethod.Ppmd; + case OutArchiveFormat.GZip: + return method == CompressionMethod.Deflate; + case OutArchiveFormat.BZip2: + return method == CompressionMethod.BZip2; + case OutArchiveFormat.SevenZip: + return method != CompressionMethod.Deflate && method != CompressionMethod.Deflate64; + case OutArchiveFormat.Tar: + return method == CompressionMethod.Copy; + default: + return true; + } + } + + private bool SwitchIsInCustomParameters(string name) + { + return CustomParameters.ContainsKey(name); + } + + /// + /// Sets the compression properties + /// + private void SetCompressionProperties() + { + switch (_archiveFormat) + { + case OutArchiveFormat.Tar: + break; + default: + ISetProperties setter = CompressionMode == CompressionMode.Create && _updateData.FileNamesToModify == null + ? (ISetProperties) SevenZipLibraryManager.OutArchive( + _archiveFormat, this) + : (ISetProperties) SevenZipLibraryManager.InArchive( + Formats.InForOutFormats[_archiveFormat], this); + if (setter == null) + { + if (!ThrowException(null, + new CompressionFailedException( + "The specified archive format is unsupported."))) + { + return; + } + } + if (_volumeSize > 0 && ArchiveFormat != OutArchiveFormat.SevenZip) + { + throw new CompressionFailedException("Unfortunately, the creation of multivolume non-7Zip archives is not implemented. It will be one day, though."); + } + if (CustomParameters.ContainsKey("x") || CustomParameters.ContainsKey("m")) + { + if ( + !ThrowException(null, + new CompressionFailedException( + "The specified compression parameters are invalid."))) + { + return; + } + } + var names = new List(2 + CustomParameters.Count); + var values = new List(2 + CustomParameters.Count); +#if !WINCE + var sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + sp.Demand(); +#endif + #region Initialize compression properties + + if (_compressionMethod == CompressionMethod.Default) + { + names.Add(Marshal.StringToBSTR("x")); + values.Add(new PropVariant()); + foreach (var pair in CustomParameters) + { + names.Add(Marshal.StringToBSTR(pair.Key)); + var pv = new PropVariant(); + if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d") + { + pv.VarType = VarEnum.VT_UI4; + pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture); + } + else + { + pv.VarType = VarEnum.VT_BSTR; + pv.Value = Marshal.StringToBSTR(pair.Value); + } + values.Add(pv); + } + } + else + { + names.Add(Marshal.StringToBSTR("x")); + names.Add(_archiveFormat == OutArchiveFormat.Zip + ? Marshal.StringToBSTR("m") + : Marshal.StringToBSTR("0")); + values.Add(new PropVariant()); + var pv = new PropVariant + { + VarType = VarEnum.VT_BSTR, + Value = Marshal.StringToBSTR(Formats.MethodNames[_compressionMethod]) + }; + values.Add(pv); + foreach (var pair in CustomParameters) + { + names.Add(Marshal.StringToBSTR(pair.Key)); + pv = new PropVariant(); + if (pair.Key == "fb" || pair.Key == "pass" || pair.Key == "d") + { + pv.VarType = VarEnum.VT_UI4; + pv.UInt32Value = Convert.ToUInt32(pair.Value, CultureInfo.InvariantCulture); + } + else + { + pv.VarType = VarEnum.VT_BSTR; + pv.Value = Marshal.StringToBSTR(pair.Value); + } + values.Add(pv); + } + } + + #endregion + + #region Set compression level + + PropVariant clpv = values[0]; + clpv.VarType = VarEnum.VT_UI4; + switch (CompressionLevel) + { + case CompressionLevel.None: + clpv.UInt32Value = 0; + break; + case CompressionLevel.Fast: + clpv.UInt32Value = 1; + break; + case CompressionLevel.Low: + clpv.UInt32Value = 3; + break; + case CompressionLevel.Normal: + clpv.UInt32Value = 5; + break; + case CompressionLevel.High: + clpv.UInt32Value = 7; + break; + case CompressionLevel.Ultra: + clpv.UInt32Value = 9; + break; + } + values[0] = clpv; + + #endregion + + #region Encrypt headers + + if (EncryptHeaders && _archiveFormat == OutArchiveFormat.SevenZip && + !SwitchIsInCustomParameters("he")) + { + names.Add(Marshal.StringToBSTR("he")); + var tmp = new PropVariant {VarType = VarEnum.VT_BSTR, Value = Marshal.StringToBSTR("on")}; + values.Add(tmp); + } + + #endregion + + #region Zip Encryption + + if (_archiveFormat == OutArchiveFormat.Zip && ZipEncryptionMethod != ZipEncryptionMethod.ZipCrypto && + !SwitchIsInCustomParameters("em")) + { + names.Add(Marshal.StringToBSTR("em")); + var tmp = new PropVariant + { + VarType = VarEnum.VT_BSTR, + Value = Marshal.StringToBSTR( +#if !WINCE + Enum.GetName(typeof (ZipEncryptionMethod), ZipEncryptionMethod)) +#else + OpenNETCF.Enum2.GetName(typeof (ZipEncryptionMethod), ZipEncryptionMethod)) +#endif + }; + values.Add(tmp); + } + + #endregion + + var namesHandle = GCHandle.Alloc(names.ToArray(), GCHandleType.Pinned); + var valuesHandle = GCHandle.Alloc(values.ToArray(), GCHandleType.Pinned); + try + { + if (setter != null) //ReSharper + setter.SetProperties(namesHandle.AddrOfPinnedObject(), valuesHandle.AddrOfPinnedObject(), + names.Count); + } + finally + { + namesHandle.Free(); + valuesHandle.Free(); + } + break; + } + } + + /// + /// Finds the common root of file names + /// + /// Array of file names + /// Common root + private static int CommonRoot(ICollection files) + { + var splittedFileNames = new List(files.Count); +#if CS4 + splittedFileNames.AddRange(files.Select(fn => fn.Split(Path.DirectorySeparatorChar))); +#else + foreach (string fn in files) + { + splittedFileNames.Add(fn.Split(Path.DirectorySeparatorChar)); + } +#endif + int minSplitLength = splittedFileNames[0].Length - 1; + if (files.Count > 1) + { + for (int i = 1; i < files.Count; i++) + { + if (minSplitLength > splittedFileNames[i].Length) + { + minSplitLength = splittedFileNames[i].Length; + } + } + } + string res = ""; + for (int i = 0; i < minSplitLength; i++) + { + bool common = true; + for (int j = 1; j < files.Count; j++) + { + if (!(common &= splittedFileNames[j - 1][i] == splittedFileNames[j][i])) + { + break; + } + } + if (common) + { + res += splittedFileNames[0][i] + Path.DirectorySeparatorChar; + } + else + { + break; + } + } + return res.Length; + } + + /// + /// Validates the common root + /// + /// The length of the common root of the file names. + /// Array of file names + private static void CheckCommonRoot(string[] files, ref int commonRootLength) + { + string commonRoot; + try + { + commonRoot = files[0].Substring(0, commonRootLength); + } + catch (ArgumentOutOfRangeException) + { + throw new SevenZipInvalidFileNamesException("invalid common root."); + } + if (commonRoot.EndsWith(new string(Path.DirectorySeparatorChar, 1), StringComparison.CurrentCulture)) + { + commonRoot = commonRoot.Substring(0, commonRootLength - 1); + commonRootLength--; + } +#if CS4 + if (files.Any(fn => !fn.StartsWith(commonRoot, StringComparison.CurrentCulture))) + { + throw new SevenZipInvalidFileNamesException("invalid common root."); + } +#else + foreach (string fn in files) + { + if (!fn.StartsWith(commonRoot, StringComparison.CurrentCulture)) + { + throw new SevenZipInvalidFileNamesException("invalid common root."); + } + } +#endif + } + + /// + /// Ensures that directory directory is not empty + /// + /// Directory name + /// False if is not empty + private static bool RecursiveDirectoryEmptyCheck(string directory) + { + var di = new DirectoryInfo(directory); + if (di.GetFiles().Length > 0) + { + return false; + } + bool empty = true; + foreach (DirectoryInfo cdi in di.GetDirectories()) + { + empty &= RecursiveDirectoryEmptyCheck(cdi.FullName); + if (!empty) + { + return false; + } + } + return true; + } + + /// + /// Makes special FileInfo array for the archive file table. + /// + /// Array of files to pack. + /// The length of the common root of file names + /// The value indicating whether to produce the array for files in a particular directory or just for an array of files. + /// Preserve directory structure. + /// Special FileInfo array for the archive file table. + private static FileInfo[] ProduceFileInfoArray( + string[] files, int commonRootLength, + bool directoryCompress, bool directoryStructure) + { + var fis = new List(files.Length); + string commonRoot = files[0].Substring(0, commonRootLength); + if (directoryCompress) + { +#if CS4 + fis.AddRange(files.Select(fn => new FileInfo(fn))); +#else + foreach (string fn in files) + { + fis.Add(new FileInfo(fn)); + } +#endif + } + else + { + if (!directoryStructure) + { +#if CS4 + fis.AddRange(from fn in files where !Directory.Exists(fn) select new FileInfo(fn)); +#else + foreach (string fn in files) + { + if (!Directory.Exists(fn)) + { + fis.Add(new FileInfo(fn)); + } + } +#endif + } + else + { + var fns = new List(files.Length); + CheckCommonRoot(files, ref commonRootLength); + if (commonRootLength > 0) + { + commonRootLength++; + foreach (string f in files) + { + string[] splittedAfn = f.Substring(commonRootLength).Split(Path.DirectorySeparatorChar); + string cfn = commonRoot; + foreach (string t in splittedAfn) { + cfn += Path.DirectorySeparatorChar + t; + if (!fns.Contains(cfn)) + { + fis.Add(new FileInfo(cfn)); + fns.Add(cfn); + } + } + } + } + else + { + foreach (string f in files) + { + string[] splittedAfn = f.Substring(commonRootLength).Split(Path.DirectorySeparatorChar); + string cfn = splittedAfn[0]; + for (int i = 1; i < splittedAfn.Length; i++) + { + cfn += Path.DirectorySeparatorChar + splittedAfn[i]; + if (!fns.Contains(cfn)) + { + fis.Add(new FileInfo(cfn)); + fns.Add(cfn); + } + } + } + } + } + } + return fis.ToArray(); + } + + /// + /// Recursive function for adding files in directory + /// + /// Directory directory + /// List of files + /// Search string, such as "*.txt" + private void AddFilesFromDirectory(string directory, ICollection files, string searchPattern) + { + var di = new DirectoryInfo(directory); + foreach (FileInfo fi in di.GetFiles(searchPattern)) + { + if (!ScanOnlyWritable) + { + files.Add(fi.FullName); + } + else + { + try + { + using (fi.OpenWrite()) {} + files.Add(fi.FullName); + } + catch (IOException) {} + } + } + foreach (DirectoryInfo cdi in di.GetDirectories()) + { + if (IncludeEmptyDirectories) + { + files.Add(cdi.FullName); + } + AddFilesFromDirectory(cdi.FullName, files, searchPattern); + } + } + + #endregion + + #region GetArchiveUpdateCallback overloads + + /// + /// Performs the common ArchiveUpdateCallback initialization. + /// + /// The ArchiveUpdateCallback instance to initialize. + private void CommonUpdateCallbackInit(ArchiveUpdateCallback auc) + { + auc.FileCompressionStarted += FileCompressionStartedEventProxy; + auc.Compressing += CompressingEventProxy; + auc.FileCompressionFinished += FileCompressionFinishedEventProxy; + auc.DefaultItemName = DefaultItemName; + auc.FastCompression = FastCompression; + } + + private float GetDictionarySize() + { + float dictionarySize = 0.001f; + switch (_compressionMethod) + { + case CompressionMethod.Default: + case CompressionMethod.Lzma: + case CompressionMethod.Lzma2: + switch (CompressionLevel) + { + case CompressionLevel.None: + dictionarySize = 0.001f; + break; + case CompressionLevel.Fast: + dictionarySize = 1.0f / 16 * 7.5f + 4; + break; + case CompressionLevel.Low: + dictionarySize = 7.5f * 11.5f + 4; + break; + case CompressionLevel.Normal: + dictionarySize = 16 * 11.5f + 4; + break; + case CompressionLevel.High: + dictionarySize = 32 * 11.5f + 4; + break; + case CompressionLevel.Ultra: + dictionarySize = 64 * 11.5f + 4; + break; + } + break; + case CompressionMethod.BZip2: + switch (CompressionLevel) + { + case CompressionLevel.None: + dictionarySize = 0; + break; + case CompressionLevel.Fast: + dictionarySize = 0.095f; + break; + case CompressionLevel.Low: + dictionarySize = 0.477f; + break; + case CompressionLevel.Normal: + case CompressionLevel.High: + case CompressionLevel.Ultra: + dictionarySize = 0.858f; + break; + } + break; + case CompressionMethod.Deflate: + case CompressionMethod.Deflate64: + dictionarySize = 32; + break; + case CompressionMethod.Ppmd: + dictionarySize = 16; + break; + } + return dictionarySize; + } + + /// + /// Produces a new instance of ArchiveUpdateCallback class. + /// + /// Array of FileInfo - files to pack + /// Length of the common root of file names + /// The archive password + /// + private ArchiveUpdateCallback GetArchiveUpdateCallback( + FileInfo[] files, int rootLength, string password) + { + SetCompressionProperties(); + var auc = (String.IsNullOrEmpty(password)) + ? new ArchiveUpdateCallback(files, rootLength, this, GetUpdateData(), DirectoryStructure) + { DictionarySize = GetDictionarySize() } + : new ArchiveUpdateCallback(files, rootLength, password, this, GetUpdateData(), DirectoryStructure) + { DictionarySize = GetDictionarySize() }; + CommonUpdateCallbackInit(auc); + return auc; + } + + /// + /// Produces a new instance of ArchiveUpdateCallback class. + /// + /// The archive input stream. + /// The archive password. + /// + private ArchiveUpdateCallback GetArchiveUpdateCallback(Stream inStream, string password) + { + SetCompressionProperties(); + var auc = (String.IsNullOrEmpty(password)) + ? new ArchiveUpdateCallback(inStream, this, GetUpdateData(), DirectoryStructure) + { DictionarySize = GetDictionarySize() } + : new ArchiveUpdateCallback(inStream, password, this, GetUpdateData(), DirectoryStructure) + { DictionarySize = GetDictionarySize() }; + CommonUpdateCallbackInit(auc); + return auc; + } + + /// + /// Produces a new instance of ArchiveUpdateCallback class. + /// + /// Dictionary<name of the archive entry, stream>. + /// The archive password + /// + private ArchiveUpdateCallback GetArchiveUpdateCallback( + Dictionary streamDict, string password) + { + SetCompressionProperties(); + var auc = (String.IsNullOrEmpty(password)) + ? new ArchiveUpdateCallback(streamDict, this, GetUpdateData(), DirectoryStructure) + { DictionarySize = GetDictionarySize() } + : new ArchiveUpdateCallback(streamDict, password, this, GetUpdateData(), DirectoryStructure) + { DictionarySize = GetDictionarySize() }; + CommonUpdateCallbackInit(auc); + return auc; + } + + #endregion + + #region Service "Get" functions + + private void FreeCompressionCallback(ArchiveUpdateCallback callback) + { + callback.FileCompressionStarted -= FileCompressionStartedEventProxy; + callback.Compressing -= CompressingEventProxy; + callback.FileCompressionFinished -= FileCompressionFinishedEventProxy; + } + + private string GetTempArchiveFileName(string archiveName) + { + return Path.Combine(TempFolderPath, Path.GetFileName(archiveName) + ".~"); + } + + private FileStream GetArchiveFileStream(string archiveName) + { + if ((CompressionMode != CompressionMode.Create || _updateData.FileNamesToModify != null) && !File.Exists(archiveName)) + { + if ( + !ThrowException(null, new CompressionFailedException("file \"" + archiveName + "\" does not exist."))) + { + return null; + } + } + return _volumeSize == 0 + ? CompressionMode == CompressionMode.Create && _updateData.FileNamesToModify == null + ? File.Create(archiveName) + : File.Create(GetTempArchiveFileName(archiveName)) + : null; + } + + private void FinalizeUpdate() + { + if (_volumeSize == 0 && (CompressionMode != CompressionMode.Create || _updateData.FileNamesToModify != null)) + { + File.Move(GetTempArchiveFileName(_archiveName), _archiveName); + } + } + + private UpdateData GetUpdateData() + { + if (_updateData.FileNamesToModify == null) + { + var updateData = new UpdateData {Mode = (InternalCompressionMode) ((int) CompressionMode)}; + switch (CompressionMode) + { + case CompressionMode.Create: + updateData.FilesCount = UInt32.MaxValue; + break; + case CompressionMode.Append: + updateData.FilesCount = _oldFilesCount; + break; + } + return updateData; + } + return _updateData; + } + + private ISequentialOutStream GetOutStream(Stream outStream) + { + if (!_compressingFilesOnDisk) + { + return new OutStreamWrapper(outStream, false); + } + if (_volumeSize == 0 || CompressionMode != CompressionMode.Create || _updateData.FileNamesToModify != null) + { + return new OutStreamWrapper(outStream, true); + } + return new OutMultiStreamWrapper(_archiveName, _volumeSize); + } + + private IInStream GetInStream() + { + return File.Exists(_archiveName) && + (CompressionMode != CompressionMode.Create && _compressingFilesOnDisk || _updateData.FileNamesToModify != null) + ? + new InStreamWrapper( + new FileStream(_archiveName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), + true) + : null; + } + + private ArchiveOpenCallback GetArchiveOpenCallback() + { + return String.IsNullOrEmpty(Password) + ? + new ArchiveOpenCallback(_archiveName) + : + new ArchiveOpenCallback(_archiveName, Password); + } + + #endregion + + #region Core public Members + + #region Events + + /// + /// Occurs when the next file is going to be packed. + /// + /// Occurs when 7-zip engine requests for an input stream for the next file to pack it + public event EventHandler FileCompressionStarted; + + /// + /// Occurs when the current file was compressed. + /// + public event EventHandler FileCompressionFinished; + + /// + /// Occurs when data are being compressed + /// + /// Use this event for accurate progress handling and various ProgressBar.StepBy(e.PercentDelta) routines + public event EventHandler Compressing; + + /// + /// Occurs when all files information was determined and SevenZipCompressor is about to start to compress them. + /// + /// The incoming int value indicates the number of scanned files. + public event EventHandler FilesFound; + + /// + /// Occurs when the compression procedure is finished + /// + public event EventHandler CompressionFinished; + + #region Event proxies + /// + /// Event proxy for FileCompressionStarted. + /// + /// The sender of the event. + /// The event arguments. + private void FileCompressionStartedEventProxy(object sender, FileNameEventArgs e) + { + OnEvent(FileCompressionStarted, e, false); + } + + /// + /// Event proxy for FileCompressionFinished. + /// + /// The sender of the event. + /// The event arguments. + private void FileCompressionFinishedEventProxy(object sender, EventArgs e) + { + OnEvent(FileCompressionFinished, e, false); + } + + /// + /// Event proxy for Compressing. + /// + /// The sender of the event. + /// The event arguments. + private void CompressingEventProxy(object sender, ProgressEventArgs e) + { + OnEvent(Compressing, e, false); + } + + /// + /// Event proxy for FilesFound. + /// + /// The sender of the event. + /// The event arguments. + private void FilesFoundEventProxy(object sender, IntEventArgs e) + { + OnEvent(FilesFound, e, false); + } + #endregion + #endregion + + #region Properties + + /// + /// Gets or sets the archive format + /// + public OutArchiveFormat ArchiveFormat + { + get + { + return _archiveFormat; + } + + set + { + _archiveFormat = value; + if (!MethodIsValid(_compressionMethod)) + { + _compressionMethod = CompressionMethod.Default; + } + } + } + + /// + /// Gets or sets the compression method + /// + public CompressionMethod CompressionMethod + { + get + { + return _compressionMethod; + } + + set + { + _compressionMethod = !MethodIsValid(value) ? CompressionMethod.Default : value; + } + } + + /// + /// Gets or sets the size in bytes of an archive volume (0 for no volumes). + /// + public int VolumeSize + { + get + { + return _volumeSize; + } + + set + { + _volumeSize = value > 0 ? value : 0; + } + } + #endregion + + #region CompressFiles overloads + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The archive file name. + public void CompressFiles( + string archiveName, params string[] fileFullNames) + { + CompressFilesEncrypted(archiveName, "", fileFullNames); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles(string archiveName ... ) overloads for archiving to disk. + public void CompressFiles( + Stream archiveStream, params string[] fileFullNames) + { + CompressFilesEncrypted(archiveStream, "", fileFullNames); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive file name. + public void CompressFiles( + string archiveName, int commonRootLength, params string[] fileFullNames) + { + CompressFilesEncrypted(archiveName, commonRootLength, "", fileFullNames); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive output stream. + /// Use CompressFiles(string archiveName, ... ) overloads for archiving to disk. + public void CompressFiles( + Stream archiveStream, int commonRootLength, params string[] fileFullNames) + { + CompressFilesEncrypted(archiveStream, commonRootLength, "", fileFullNames); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The archive file name. + /// The archive password. + public void CompressFilesEncrypted( + string archiveName, string password, params string[] fileFullNames) + { + CompressFilesEncrypted(archiveName, CommonRoot(fileFullNames), password, fileFullNames); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressFilesEncrypted( + Stream archiveStream, string password, params string[] fileFullNames) + { + CompressFilesEncrypted(archiveStream, CommonRoot(fileFullNames), password, fileFullNames); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive file name. + /// The archive password. + public void CompressFilesEncrypted( + string archiveName, int commonRootLength, string password, params string[] fileFullNames) + { + _compressingFilesOnDisk = true; + _archiveName = archiveName; + using (FileStream fs = GetArchiveFileStream(archiveName)) + { + if (fs == null) + { + return; + } + CompressFilesEncrypted(fs, commonRootLength, password, fileFullNames); + } + FinalizeUpdate(); + } + + /// + /// Packs files into the archive. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive output stream. + /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressFilesEncrypted( + Stream archiveStream, int commonRootLength, string password, params string[] fileFullNames) + { + ClearExceptions(); + if (fileFullNames.Length > 1 && + (_archiveFormat == OutArchiveFormat.BZip2 || _archiveFormat == OutArchiveFormat.GZip || + _archiveFormat == OutArchiveFormat.XZ)) + { + if (!ThrowException(null, + new CompressionFailedException("Can not compress more than one file in this format."))) + { + return; + } + } + if (_volumeSize == 0 || !_compressingFilesOnDisk) + { + ValidateStream(archiveStream); + } + FileInfo[] files = null; + try + { + files = ProduceFileInfoArray(fileFullNames, commonRootLength, _directoryCompress, DirectoryStructure); + } + catch (Exception e) + { + if (!ThrowException(null, e)) + { + return; + } + } + _directoryCompress = false; + if (FilesFound != null) + { + FilesFound(this, new IntEventArgs(fileFullNames.Length)); + } + try + { + ISequentialOutStream sequentialArchiveStream; + using ((sequentialArchiveStream = GetOutStream(archiveStream)) as IDisposable) + { + IInStream inArchiveStream; + using ((inArchiveStream = GetInStream()) as IDisposable) + { + IOutArchive outArchive; + if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk) + { + SevenZipLibraryManager.LoadLibrary(this, _archiveFormat); + outArchive = SevenZipLibraryManager.OutArchive(_archiveFormat, this); + } + else + { + // Create IInArchive, read it and convert to IOutArchive + SevenZipLibraryManager.LoadLibrary( + this, Formats.InForOutFormats[_archiveFormat]); + if ((outArchive = MakeOutArchive(inArchiveStream)) == null) + { + return; + } + } + using (var auc = GetArchiveUpdateCallback(files, commonRootLength, password)) + { + try + { + if (files != null) //ReSharper + CheckedExecute( + outArchive.UpdateItems( + sequentialArchiveStream, (uint) files.Length + _oldFilesCount, auc), + SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc); + } + finally + { + FreeCompressionCallback(auc); + } + } + } + } + } + finally + { + if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk) + { + SevenZipLibraryManager.FreeLibrary(this, _archiveFormat); + } + else + { + SevenZipLibraryManager.FreeLibrary(this, Formats.InForOutFormats[_archiveFormat]); + File.Delete(_archiveName); + } + _compressingFilesOnDisk = false; + OnEvent(CompressionFinished, EventArgs.Empty, false); + } + ThrowUserException(); + } + + #endregion + + #region CompressDirectory overloads + +#if !CS4 + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + public void CompressDirectory( + string directory, string archiveName) + { + CompressDirectory(directory, archiveName, "", "*", true); + } + + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + public void CompressDirectory( + string directory, Stream archiveStream) + { + CompressDirectory(directory, archiveStream, "", "*", true); + } + + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. + public void CompressDirectory( + string directory, string archiveName, string password) + { + CompressDirectory(directory, archiveName, password, "*", true); + } + + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressDirectory( + string directory, Stream archiveStream, string password) + { + CompressDirectory(directory, archiveStream, password, "*", true); + } + + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, string archiveName, bool recursion) + { + CompressDirectory(directory, archiveName, "", "*", recursion); + } + + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, Stream archiveStream, bool recursion) + { + CompressDirectory(directory, archiveStream, "", "*", recursion); + } + + /// + /// Packs all files found by the specified pattern in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, string archiveName, + string searchPattern, bool recursion) + { + CompressDirectory(directory, archiveName, "", searchPattern, recursion); + } + + /// + /// Packs all files found by the specified pattern in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, Stream archiveStream, + string searchPattern, bool recursion) + { + CompressDirectory(directory, archiveStream, "", searchPattern, recursion); + } + + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// If true, files will be searched for recursively; otherwise, not. + /// The archive password. + public void CompressDirectory( + string directory, string archiveName, + bool recursion, string password) + { + CompressDirectory(directory, archiveName, password, "*", recursion); + } + + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// If true, files will be searched for recursively; otherwise, not. + /// The archive password. + public void CompressDirectory( + string directory, Stream archiveStream, + bool recursion, string password) + { + CompressDirectory(directory, archiveStream, password, "*", recursion); + } +#endif + +#if !CS4 + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, string archiveName, + string password, string searchPattern, bool recursion) +#else + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, string archiveName, + string password = "", string searchPattern = "*", bool recursion = true) +#endif + { + _compressingFilesOnDisk = true; + _archiveName = archiveName; + using (FileStream fs = GetArchiveFileStream(archiveName)) + { + if (fs == null && _volumeSize == 0) + { + return; + } + CompressDirectory(directory, fs, password, searchPattern, recursion); + } + FinalizeUpdate(); + } + +#if !CS4 + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, Stream archiveStream, + string password, string searchPattern, bool recursion) +#else + /// + /// Packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + public void CompressDirectory( + string directory, Stream archiveStream, + string password = "", string searchPattern = "*", bool recursion = true) +#endif + { + var files = new List(); + if (!Directory.Exists(directory)) + { + throw new ArgumentException("Directory \"" + directory + "\" does not exist!"); + } + if (RecursiveDirectoryEmptyCheck(directory)) + { + throw new SevenZipInvalidFileNamesException("the specified directory is empty!"); + } + if (recursion) + { + AddFilesFromDirectory(directory, files, searchPattern); + } + else + { +#if CS4 + files.AddRange((new DirectoryInfo(directory)).GetFiles(searchPattern).Select(fi => fi.FullName)); +#else + foreach (FileInfo fi in (new DirectoryInfo(directory)).GetFiles(searchPattern)) + { + files.Add(fi.FullName); + } +#endif + } + int commonRootLength = directory.Length; + if (directory.EndsWith("\\", StringComparison.OrdinalIgnoreCase)) + { + directory = directory.Substring(0, directory.Length - 1); + } + else + { + commonRootLength++; + } + if (PreserveDirectoryRoot) + { + var upperRoot = Path.GetDirectoryName(directory); + commonRootLength = upperRoot.Length + + (upperRoot.EndsWith("\\", StringComparison.OrdinalIgnoreCase) ? 0 : 1); + } + _directoryCompress = true; + CompressFilesEncrypted(archiveStream, commonRootLength, password, files.ToArray()); + } + + #endregion + + #region CompressFileDictionary overloads + +#if !CS4 + /// + /// Packs the specified file dictionary. + /// + /// Dictionary<name of the archive entry, file name>. + /// If a file name is null, the corresponding archive entry becomes a directory. + /// The archive file name. + public void CompressFileDictionary( + Dictionary fileDictionary, string archiveName) + { + CompressFileDictionary(fileDictionary, archiveName, ""); + } + + /// + /// Packs the specified file dictionary. + /// + /// Dictionary<name of the archive entry, file name>. + /// If a file name is null, the corresponding archive entry becomes a directory. + /// The archive output stream. + /// Use CompressFileDictionary( ... string archiveName ... ) overloads for archiving to disk. + public void CompressFileDictionary( + Dictionary fileDictionary, Stream archiveStream) + { + CompressFileDictionary(fileDictionary, archiveStream, ""); + } +#endif + +#if !CS4 + /// + /// Packs the specified file dictionary. + /// + /// Dictionary<name of the archive entry, file name>. + /// If a file name is null, the corresponding archive entry becomes a directory. + /// The archive file name. + /// The archive password. + public void CompressFileDictionary( + Dictionary fileDictionary, string archiveName, string password) +#else + /// + /// Packs the specified file dictionary. + /// + /// Dictionary<name of the archive entry, file name>. + /// If a file name is null, the corresponding archive entry becomes a directory. + /// The archive file name. + /// The archive password. + public void CompressFileDictionary( + Dictionary fileDictionary, string archiveName, string password = "") +#endif + { + _compressingFilesOnDisk = true; + _archiveName = archiveName; + using (FileStream fs = GetArchiveFileStream(archiveName)) + { + if (fs == null) + { + return; + } + CompressFileDictionary(fileDictionary, fs, password); + } + FinalizeUpdate(); + } + +#if !CS4 + /// + /// Packs the specified file dictionary. + /// + /// Dictionary<name of the archive entry, file name>. + /// If a file name is null, the corresponding archive entry becomes a directory. + /// The archive output stream. + /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressFileDictionary( + Dictionary fileDictionary, Stream archiveStream, string password) +#else + /// + /// Packs the specified file dictionary. + /// + /// Dictionary<name of the archive entry, file name>. + /// If a file name is null, the corresponding archive entry becomes a directory. + /// The archive output stream. + /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressFileDictionary( + Dictionary fileDictionary, Stream archiveStream, string password = "") +#endif + { + var streamDict = new Dictionary(fileDictionary.Count); + foreach (var pair in fileDictionary) + { + if (pair.Value == null) + { + streamDict.Add(pair.Key, null); + } + else + { + if (!File.Exists(pair.Value)) + { + throw new CompressionFailedException("The file corresponding to the archive entry \"" + pair.Key + "\" does not exist."); + } + streamDict.Add( + pair.Key, + new FileStream(pair.Value, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); + } + } + //The created streams will be automatically disposed inside. + CompressStreamDictionary(streamDict, archiveStream, password); + } + + #endregion + + #region CompressStreamDictionary overloads +#if !CS4 + /// + /// Packs the specified stream dictionary. + /// + /// Dictionary<name of the archive entry, stream>. + /// If a stream is null, the corresponding string becomes a directory name. + /// The archive file name. + public void CompressStreamDictionary( + Dictionary streamDictionary, string archiveName) + { + CompressStreamDictionary(streamDictionary, archiveName, ""); + } + + /// + /// Packs the specified stream dictionary. + /// + /// Dictionary<name of the archive entry, stream>. + /// If a stream is null, the corresponding string becomes a directory name. + /// The archive output stream. + /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk. + public void CompressStreamDictionary( + Dictionary streamDictionary, Stream archiveStream) + { + CompressStreamDictionary(streamDictionary, archiveStream, ""); + } +#endif + +#if !CS4 + /// + /// Packs the specified stream dictionary. + /// + /// Dictionary<name of the archive entry, stream>. + /// If a stream is null, the corresponding string becomes a directory name. + /// The archive file name. + /// The archive password. + public void CompressStreamDictionary( + Dictionary streamDictionary, string archiveName, string password) +#else + /// + /// Packs the specified stream dictionary. + /// + /// Dictionary<name of the archive entry, stream>. + /// If a stream is null, the corresponding string becomes a directory name. + /// The archive file name. + /// The archive password. + public void CompressStreamDictionary( + Dictionary streamDictionary, string archiveName, string password = "") +#endif + { + _compressingFilesOnDisk = true; + _archiveName = archiveName; + using (FileStream fs = GetArchiveFileStream(archiveName)) + { + if (fs == null) + { + return; + } + CompressStreamDictionary(streamDictionary, fs, password); + } + FinalizeUpdate(); + } + +#if !CS4 + /// + /// Packs the specified stream dictionary. + /// + /// Dictionary<name of the archive entry, stream>. + /// If a stream is null, the corresponding string becomes a directory name. + /// The archive output stream. + /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressStreamDictionary( + Dictionary streamDictionary, Stream archiveStream, string password) +#else + /// + /// Packs the specified stream dictionary. + /// + /// Dictionary<name of the archive entry, stream>. + /// If a stream is null, the corresponding string becomes a directory name. + /// The archive output stream. + /// Use CompressStreamDictionary( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + public void CompressStreamDictionary( + Dictionary streamDictionary, Stream archiveStream, string password = "") +#endif + { + ClearExceptions(); + if (streamDictionary.Count > 1 && + (_archiveFormat == OutArchiveFormat.BZip2 || _archiveFormat == OutArchiveFormat.GZip || + _archiveFormat == OutArchiveFormat.XZ)) + { + if (!ThrowException(null, + new CompressionFailedException("Can not compress more than one file/stream in this format."))) + { + return; + } + } + if (_volumeSize == 0 || !_compressingFilesOnDisk) + { + ValidateStream(archiveStream); + } +#if CS4 + if (streamDictionary.Where( + pair => pair.Value != null && (!pair.Value.CanSeek || !pair.Value.CanRead)).Any( + pair => !ThrowException(null, + new ArgumentException("The specified stream dictionary contains an invalid stream corresponding to the archive entry \"" + + pair.Key + "\".", "streamDictionary")))) { + return; + } +#else + foreach (var pair in streamDictionary) + { + if (pair.Value != null && (!pair.Value.CanSeek || !pair.Value.CanRead)) + { + if (!ThrowException(null, new ArgumentException( + "The specified stream dictionary contains an invalid stream corresponding to the archive entry \"" + pair.Key + "\".", + "streamDictionary"))) + { + return; + } + } + } +#endif + try + { + ISequentialOutStream sequentialArchiveStream; + using ((sequentialArchiveStream = GetOutStream(archiveStream)) as IDisposable) + { + IInStream inArchiveStream; + using ((inArchiveStream = GetInStream()) as IDisposable) + { + IOutArchive outArchive; + if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk) + { + SevenZipLibraryManager.LoadLibrary(this, _archiveFormat); + outArchive = SevenZipLibraryManager.OutArchive(_archiveFormat, this); + } + else + { + // Create IInArchive, read it and convert to IOutArchive + SevenZipLibraryManager.LoadLibrary( + this, Formats.InForOutFormats[_archiveFormat]); + if ((outArchive = MakeOutArchive(inArchiveStream)) == null) + { + return; + } + } + using (ArchiveUpdateCallback auc = GetArchiveUpdateCallback( + streamDictionary, password)) + { + try + { + CheckedExecute(outArchive.UpdateItems(sequentialArchiveStream, + (uint)streamDictionary.Count + _oldFilesCount, auc), + SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc); + } + finally + { + FreeCompressionCallback(auc); + } + } + } + } + } + finally + { + if (CompressionMode == CompressionMode.Create || !_compressingFilesOnDisk) + { + SevenZipLibraryManager.FreeLibrary(this, _archiveFormat); + } + else + { + SevenZipLibraryManager.FreeLibrary(this, Formats.InForOutFormats[_archiveFormat]); + File.Delete(_archiveName); + } + _compressingFilesOnDisk = false; + OnEvent(CompressionFinished, EventArgs.Empty, false); + } + ThrowUserException(); + } + + #endregion + + #region CompressStream overloads + +#if !CS4 + /// + /// Compresses the specified stream. + /// + /// The source uncompressed stream. + /// The destination compressed stream. + /// ArgumentException: at least one of the specified streams is invalid. + public void CompressStream(Stream inStream, Stream outStream) + { + CompressStream(inStream, outStream, ""); + } +#endif + /// + /// Compresses the specified stream. + /// + /// The source uncompressed stream. + /// The destination compressed stream. + /// The archive password. + /// ArgumentException: at least one of the specified streams is invalid. + public void CompressStream(Stream inStream, Stream outStream, string password +#if CS4 + = "" +#endif + ) + { + ClearExceptions(); + if (!inStream.CanSeek || !inStream.CanRead || !outStream.CanWrite) + { + if (!ThrowException(null, new ArgumentException("The specified streams are invalid."))) + { + return; + } + } + try + { + SevenZipLibraryManager.LoadLibrary(this, _archiveFormat); + ISequentialOutStream sequentialArchiveStream; + using ((sequentialArchiveStream = GetOutStream(outStream)) as IDisposable) + { + using (ArchiveUpdateCallback auc = GetArchiveUpdateCallback(inStream, password)) + { + try + { + CheckedExecute( + SevenZipLibraryManager.OutArchive(_archiveFormat, this).UpdateItems( + sequentialArchiveStream, 1, auc), + SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc); + } + finally + { + FreeCompressionCallback(auc); + } + } + } + } + finally + { + SevenZipLibraryManager.FreeLibrary(this, _archiveFormat); + OnEvent(CompressionFinished, EventArgs.Empty, false); + } + ThrowUserException(); + } + + #endregion + + #region ModifyArchive overloads +#if !CS4 + /// + /// Modifies the existing archive (renames files or deletes them). + /// + /// The archive file name. + /// New file names. Null value to delete the corresponding index. + public void ModifyArchive(string archiveName, Dictionary newFileNames) + { + ModifyArchive(archiveName, newFileNames, ""); + } +#endif + + /// + /// Modifies the existing archive (renames files or deletes them). + /// + /// The archive file name. + /// New file names. Null value to delete the corresponding index. + /// The archive password. + public void ModifyArchive(string archiveName, Dictionary newFileNames, string password +#if CS4 + = "" +#endif + ) + { + ClearExceptions(); + if (!SevenZipLibraryManager.ModifyCapable) + { + throw new SevenZipLibraryException("The specified 7zip native library does not support this method."); + } + if (!File.Exists(archiveName)) + { + if (!ThrowException(null, new ArgumentException("The specified archive does not exist.", "archiveName"))) + { + return; + } + } + if (newFileNames == null || newFileNames.Count == 0) + { + if (!ThrowException(null, new ArgumentException("Invalid new file names.", "newFileNames"))) + { + return; + } + } + try + { + using (var extr = new SevenZipExtractor(archiveName)) + { + _updateData = new UpdateData(); + var archiveData = new ArchiveFileInfo[extr.ArchiveFileData.Count]; + extr.ArchiveFileData.CopyTo(archiveData, 0); + _updateData.ArchiveFileData = new List(archiveData); + } + _updateData.FileNamesToModify = newFileNames; + _updateData.Mode = InternalCompressionMode.Modify; + } + catch (SevenZipException e) + { + if (!ThrowException(null, e)) + { + return; + } + } + try + { + ISequentialOutStream sequentialArchiveStream; + _compressingFilesOnDisk = true; + using ((sequentialArchiveStream = GetOutStream(GetArchiveFileStream(archiveName))) as IDisposable) + { + IInStream inArchiveStream; + _archiveName = archiveName; + using ((inArchiveStream = GetInStream()) as IDisposable) + { + IOutArchive outArchive; + // Create IInArchive, read it and convert to IOutArchive + SevenZipLibraryManager.LoadLibrary( + this, Formats.InForOutFormats[_archiveFormat]); + if ((outArchive = MakeOutArchive(inArchiveStream)) == null) + { + return; + } + using (ArchiveUpdateCallback auc = GetArchiveUpdateCallback(null, 0, password)) + { + UInt32 deleteCount = 0; + if (_updateData.FileNamesToModify != null) + { +#if CS4 // System.Linq of C# 4 is great + deleteCount = (UInt32)_updateData.FileNamesToModify.Sum( + pairDeleted => pairDeleted.Value == null ? 1 : 0); +#else + foreach(var pairDeleted in _updateData.FileNamesToModify) + { + if (pairDeleted.Value == null) + { + deleteCount++; + } + } +#endif + } + try + { + CheckedExecute( + outArchive.UpdateItems( + sequentialArchiveStream, _oldFilesCount - deleteCount, auc), + SevenZipCompressionFailedException.DEFAULT_MESSAGE, auc); + } + finally + { + FreeCompressionCallback(auc); + } + } + } + } + } + finally + { + SevenZipLibraryManager.FreeLibrary(this, Formats.InForOutFormats[_archiveFormat]); + File.Delete(archiveName); + FinalizeUpdate(); + _compressingFilesOnDisk = false; + _updateData.FileNamesToModify = null; + _updateData.ArchiveFileData = null; + OnEvent(CompressionFinished, EventArgs.Empty, false); + } + ThrowUserException(); + } + #endregion + + #endregion + +#endif + + /// + /// Gets or sets the dictionary size for the managed LZMA algorithm. + /// + public static int LzmaDictionarySize + { + get + { + return _lzmaDictionarySize; + } + set + { + _lzmaDictionarySize = value; + } + } + + internal static void WriteLzmaProperties(Encoder encoder) + { + #region LZMA properties definition + + CoderPropId[] propIDs = + { + CoderPropId.DictionarySize, + CoderPropId.PosStateBits, + CoderPropId.LitContextBits, + CoderPropId.LitPosBits, + CoderPropId.Algorithm, + CoderPropId.NumFastBytes, + CoderPropId.MatchFinder, + CoderPropId.EndMarker + }; + object[] properties = + { + _lzmaDictionarySize, + 2, + 3, + 0, + 2, + 256, + "bt4", + false + }; + + #endregion + + encoder.SetCoderProperties(propIDs, properties); + } + + /// + /// Compresses the specified stream with LZMA algorithm (C# inside) + /// + /// The source uncompressed stream + /// The destination compressed stream + /// The length of uncompressed data (null for inStream.Length) + /// The event for handling the code progress + public static void CompressStream(Stream inStream, Stream outStream, int? inLength, + EventHandler codeProgressEvent) + { + if (!inStream.CanRead || !outStream.CanWrite) + { + throw new ArgumentException("The specified streams are invalid."); + } + var encoder = new Encoder(); + WriteLzmaProperties(encoder); + encoder.WriteCoderProperties(outStream); + long streamSize = inLength.HasValue ? inLength.Value : inStream.Length; + for (int i = 0; i < 8; i++) + { + outStream.WriteByte((byte) (streamSize >> (8*i))); + } + encoder.Code(inStream, outStream, -1, -1, new LzmaProgressCallback(streamSize, codeProgressEvent)); + } + + /// + /// Compresses byte array with LZMA algorithm (C# inside) + /// + /// Byte array to compress + /// Compressed byte array + public static byte[] CompressBytes(byte[] data) + { + using (var inStream = new MemoryStream(data)) + { + using (var outStream = new MemoryStream()) + { + var encoder = new Encoder(); + WriteLzmaProperties(encoder); + encoder.WriteCoderProperties(outStream); + long streamSize = inStream.Length; + for (int i = 0; i < 8; i++) + outStream.WriteByte((byte) (streamSize >> (8*i))); + encoder.Code(inStream, outStream, -1, -1, null); + return outStream.ToArray(); + } + } + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/SevenZipCompressorAsynchronous.cs b/BizHawk.Util/7z/SevenZipCompressorAsynchronous.cs new file mode 100644 index 0000000000..11af46cf73 --- /dev/null +++ b/BizHawk.Util/7z/SevenZipCompressorAsynchronous.cs @@ -0,0 +1,689 @@ +namespace SevenZip +{ + using System.Collections.Generic; + using System.IO; +#if DOTNET20 + using System.Threading; +#else + using System.Windows.Threading; +#endif + + partial class SevenZipCompressor + { + #region Delegates + private delegate void CompressFiles1Delegate(string archiveName, string[] fileFullNames); + private delegate void CompressFiles2Delegate(Stream archiveStream, string[] fileFullNames); + private delegate void CompressFiles3Delegate(string archiveName, int commonRootLength, string[] fileFullNames); + private delegate void CompressFiles4Delegate(Stream archiveStream, int commonRootLength, string[] fileFullNames); + + private delegate void CompressFilesEncrypted1Delegate(string archiveName, string password, string[] fileFullNames); + private delegate void CompressFilesEncrypted2Delegate(Stream archiveStream, string password, string[] fileFullNames); + private delegate void CompressFilesEncrypted3Delegate(string archiveName, int commonRootLength, string password, string[] fileFullNames); + private delegate void CompressFilesEncrypted4Delegate(Stream archiveStream, int commonRootLength, string password, string[] fileFullNames); + + private delegate void CompressDirectory1Delegate(string directory, string archiveName); + private delegate void CompressDirectory2Delegate(string directory, Stream archiveStream); + private delegate void CompressDirectory3Delegate(string directory, string archiveName, string password); + private delegate void CompressDirectory4Delegate(string directory, Stream archiveStream, string password); + private delegate void CompressDirectory5Delegate(string directory, string archiveName, + string password, string searchPattern, bool recursion); + private delegate void CompressDirectory6Delegate(string directory, Stream archiveStream, + string password, string searchPattern, bool recursion); + + private delegate void CompressStream1Delegate(Stream inStream, Stream outStream); + private delegate void CompressStream2Delegate(Stream inStream, Stream outStream, string password); + + private delegate void ModifyArchive1Delegate(string archiveName, Dictionary newFileNames); + private delegate void ModifyArchive2Delegate(string archiveName, Dictionary newFileNames, + string password); + #endregion + + #region CompressFiles overloads +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive file name. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive file name. +#endif + public void BeginCompressFiles( + string archiveName +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFiles1Delegate(CompressFiles)).BeginInvoke(archiveName, fileFullNames, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles(string archiveName ... ) overloads for archiving to disk. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles(string archiveName ... ) overloads for archiving to disk. +#endif + public void BeginCompressFiles( + Stream archiveStream +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFiles2Delegate(CompressFiles)).BeginInvoke(archiveStream, fileFullNames, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive file name. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive file name. +#endif + public void BeginCompressFiles( + string archiveName, int commonRootLength +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFiles3Delegate(CompressFiles)).BeginInvoke(archiveName, commonRootLength, fileFullNames, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive output stream. + /// Use CompressFiles(string archiveName, ... ) overloads for archiving to disk. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The length of the common root of the file names. + /// The archive output stream. + /// Use CompressFiles(string archiveName, ... ) overloads for archiving to disk. +#endif + public void BeginCompressFiles( + Stream archiveStream, int commonRootLength +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFiles4Delegate(CompressFiles)).BeginInvoke(archiveStream, commonRootLength, fileFullNames, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive file name + /// The archive password. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive file name + /// The archive password. +#endif + public void BeginCompressFilesEncrypted( + string archiveName, string password +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFilesEncrypted1Delegate(CompressFilesEncrypted)).BeginInvoke(archiveName, password, fileFullNames, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. +#endif + public void BeginCompressFilesEncrypted( + Stream archiveStream, string password +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFilesEncrypted2Delegate(CompressFilesEncrypted)).BeginInvoke(archiveStream, password, fileFullNames, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive file name + /// The archive password. + /// The length of the common root of the file names. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive file name + /// The archive password. + /// The length of the common root of the file names. +#endif + public void BeginCompressFilesEncrypted( + string archiveName, int commonRootLength, string password +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFilesEncrypted3Delegate(CompressFilesEncrypted)).BeginInvoke(archiveName, commonRootLength, password, + fileFullNames, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// The length of the common root of the file names. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs files into the archive asynchronously. + /// + /// Array of file names to pack. + /// The archive output stream. + /// Use CompressFiles( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// The length of the common root of the file names. +#endif + public void BeginCompressFilesEncrypted( + Stream archiveStream, int commonRootLength, string password +#if !DOTNET20 +, DispatcherPriority eventPriority +#endif + , params string[] fileFullNames + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressFilesEncrypted4Delegate(CompressFilesEncrypted)).BeginInvoke(archiveStream, commonRootLength, password, + fileFullNames, AsyncCallbackImplementation, this); + } + #endregion + + #region BeginCompressDirectory overloads + +#if !CS4 +#if !DOTNET20 + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. +#endif + public void BeginCompressDirectory( + string directory, string archiveName +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressDirectory1Delegate(CompressDirectory)).BeginInvoke(directory, archiveName, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. +#endif + public void BeginCompressDirectory( + string directory, Stream archiveStream +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressDirectory2Delegate(CompressDirectory)).BeginInvoke(directory, archiveStream, + AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. +#endif + public void BeginCompressDirectory( + string directory, string archiveName, string password +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressDirectory3Delegate(CompressDirectory)).BeginInvoke(directory, archiveName, + password, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Recursively packs all files in the specified directory. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. +#endif + public void BeginCompressDirectory( + string directory, Stream archiveStream, string password +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressDirectory4Delegate(CompressDirectory)).BeginInvoke(directory, archiveStream, + password, AsyncCallbackImplementation, this); + } +#endif + +#if !DOTNET20 + /// + /// Packs all files in the specified directory asynchronously. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs all files in the specified directory asynchronously. + /// + /// The directory to compress. + /// The archive file name. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. +#endif + public void BeginCompressDirectory(string directory, string archiveName, + string password +#if CS4 + = "" +#endif + , string searchPattern +#if CS4 + = "*" +#endif + , bool recursion +#if CS4 + = true +#endif +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif +) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressDirectory5Delegate(CompressDirectory)).BeginInvoke(directory, archiveName, + password, searchPattern, recursion, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Packs all files in the specified directory asynchronously. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Packs all files in the specified directory asynchronously. + /// + /// The directory to compress. + /// The archive output stream. + /// Use CompressDirectory( ... string archiveName ... ) overloads for archiving to disk. + /// The archive password. + /// Search string, such as "*.txt". + /// If true, files will be searched for recursively; otherwise, not. +#endif + public void BeginCompressDirectory(string directory, Stream archiveStream, + string password +#if CS4 + = "" +#endif + , string searchPattern +#if CS4 + = "*" +#endif + , bool recursion +#if CS4 + = true +#endif +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressDirectory6Delegate(CompressDirectory)).BeginInvoke(directory, archiveStream, + password, searchPattern, recursion, AsyncCallbackImplementation, this); + } +#endregion + + #region BeginCompressStream overloads +#if !CS4 +#if !DOTNET20 + /// + /// Compresses the specified stream. + /// + /// The source uncompressed stream. + /// The destination compressed stream. + /// ArgumentException: at least one of the specified streams is invalid. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Compresses the specified stream. + /// + /// The source uncompressed stream. + /// The destination compressed stream. + /// ArgumentException: at least one of the specified streams is invalid. +#endif + public void BeginCompressStream(Stream inStream, Stream outStream +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressStream1Delegate(CompressStream)).BeginInvoke(inStream, outStream, AsyncCallbackImplementation, this); + } +#endif + +#if !DOTNET20 + /// + /// Compresses the specified stream. + /// + /// The source uncompressed stream. + /// The destination compressed stream. + /// The archive password. + /// ArgumentException: at least one of the specified streams is invalid. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Compresses the specified stream. + /// + /// The source uncompressed stream. + /// The destination compressed stream. + /// The archive password. + /// ArgumentException: at least one of the specified streams is invalid. +#endif + public void BeginCompressStream(Stream inStream, Stream outStream, string password +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new CompressStream2Delegate(CompressStream)).BeginInvoke(inStream, outStream, password, AsyncCallbackImplementation, this); + + } + #endregion + + #region BeginModifyArchive overloads +#if !CS4 +#if !DOTNET20 + /// + /// Modifies the existing archive asynchronously (renames files or deletes them). + /// + /// The archive file name. + /// New file names. Null value to delete the corresponding index. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Modifies the existing archive asynchronously (renames files or deletes them). + /// + /// The archive file name. + /// New file names. Null value to delete the corresponding index. +#endif + public void BeginModifyArchive(string archiveName, Dictionary newFileNames +#if !DOTNET20 + , DispatcherPriority eventPriority +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ModifyArchive1Delegate(ModifyArchive)).BeginInvoke(archiveName, newFileNames, AsyncCallbackImplementation, this); + } +#endif + +#if !DOTNET20 + /// + /// Modifies the existing archive asynchronously (renames files or deletes them). + /// + /// The archive file name. + /// New file names. Null value to delete the corresponding index. + /// The archive password. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Modifies the existing archive asynchronously (renames files or deletes them). + /// + /// The archive file name. + /// New file names. Null value to delete the corresponding index. + /// The archive password. +#endif + public void BeginModifyArchive(string archiveName, Dictionary newFileNames, + string password +#if CS4 + = "" +#endif +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif + ) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ModifyArchive2Delegate(ModifyArchive)).BeginInvoke(archiveName, newFileNames, password, AsyncCallbackImplementation, this); + } + #endregion + } +} diff --git a/BizHawk.Util/7z/SevenZipExtractor.cs b/BizHawk.Util/7z/SevenZipExtractor.cs new file mode 100644 index 0000000000..90562496b9 --- /dev/null +++ b/BizHawk.Util/7z/SevenZipExtractor.cs @@ -0,0 +1,1374 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +#if DOTNET20 +using System.Threading; +#else +using System.Linq; +#endif +using SevenZip.Sdk.Compression.Lzma; +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ + /// + /// Class for extracting and getting information about 7-zip archives + /// + public sealed partial class SevenZipExtractor +#if UNMANAGED + : SevenZipBase, IDisposable +#endif + { +#if UNMANAGED + private List _archiveFileData; + private IInArchive _archive; + private IInStream _archiveStream; + private int _offset; + private ArchiveOpenCallback _openCallback; + private string _fileName; + private Stream _inStream; + private long? _packedSize; + private long? _unpackedSize; + private uint? _filesCount; + private bool? _isSolid; + private bool _opened; + private bool _disposed; + private InArchiveFormat _format; + private ReadOnlyCollection _archiveFileInfoCollection; + private ReadOnlyCollection _archiveProperties; + private ReadOnlyCollection _volumeFileNames; + + #region Constructors + /// + /// General initialization function. + /// + /// The archive file name. + private void Init(string archiveFullName) + { + _fileName = archiveFullName; + bool isExecutable; + _format = FileChecker.CheckSignature(archiveFullName, out _offset, out isExecutable); + PreserveDirectoryStructure = true; + SevenZipLibraryManager.LoadLibrary(this, _format); + try + { + _archive = SevenZipLibraryManager.InArchive(_format, this); + } + catch (SevenZipLibraryException) + { + SevenZipLibraryManager.FreeLibrary(this, _format); + throw; + } + if (isExecutable && _format != InArchiveFormat.PE) + { + if (!Check()) + { + CommonDispose(); + _format = InArchiveFormat.PE; + SevenZipLibraryManager.LoadLibrary(this, _format); + try + { + _archive = SevenZipLibraryManager.InArchive(_format, this); + } + catch (SevenZipLibraryException) + { + SevenZipLibraryManager.FreeLibrary(this, _format); + throw; + } + } + } + } + + /// + /// General initialization function. + /// + /// The stream to read the archive from. + private void Init(Stream stream) + { + ValidateStream(stream); + bool isExecutable; + _format = FileChecker.CheckSignature(stream, out _offset, out isExecutable); + PreserveDirectoryStructure = true; + SevenZipLibraryManager.LoadLibrary(this, _format); + try + { + _inStream = new ArchiveEmulationStreamProxy(stream, _offset); + _packedSize = stream.Length; + _archive = SevenZipLibraryManager.InArchive(_format, this); + } + catch (SevenZipLibraryException) + { + SevenZipLibraryManager.FreeLibrary(this, _format); + throw; + } + if (isExecutable && _format != InArchiveFormat.PE) + { + if (!Check()) + { + CommonDispose(); + _format = InArchiveFormat.PE; + try + { + _inStream = new ArchiveEmulationStreamProxy(stream, _offset); + _packedSize = stream.Length; + _archive = SevenZipLibraryManager.InArchive(_format, this); + } + catch (SevenZipLibraryException) + { + SevenZipLibraryManager.FreeLibrary(this, _format); + throw; + } + } + } + } + + /// + /// Initializes a new instance of SevenZipExtractor class. + /// + /// The stream to read the archive from. + /// Use SevenZipExtractor(string) to extract from disk, though it is not necessary. + /// The archive format is guessed by the signature. + public SevenZipExtractor(Stream archiveStream) + { + Init(archiveStream); + } + + /// + /// Initializes a new instance of SevenZipExtractor class + /// + /// The archive full file name + public SevenZipExtractor(string archiveFullName) + { + Init(archiveFullName); + } + + /// + /// Initializes a new instance of SevenZipExtractor class. + /// + /// The archive full file name. + /// Password for an encrypted archive. + public SevenZipExtractor(string archiveFullName, string password) + : base(password) + { + Init(archiveFullName); + } + + /// + /// Initializes a new instance of SevenZipExtractor class. + /// + /// The stream to read the archive from. + /// Password for an encrypted archive. + /// The archive format is guessed by the signature. + public SevenZipExtractor( + Stream archiveStream, string password) + : base(password) + { + Init(archiveStream); + } + + #endregion + + #region Properties + + /// + /// Gets or sets archive full file name + /// + public string FileName + { + get + { + DisposedCheck(); + return _fileName; + } + } + + /// + /// Gets the size of the archive file + /// + public long PackedSize + { + get + { + DisposedCheck(); + return _packedSize.HasValue + ? + _packedSize.Value + : + _fileName != null + ? + (new FileInfo(_fileName)).Length + : + -1; + } + } + + /// + /// Gets the size of unpacked archive data + /// + public long UnpackedSize + { + get + { + DisposedCheck(); + if (!_unpackedSize.HasValue) + { + return -1; + } + return _unpackedSize.Value; + } + } + + /// + /// Gets a value indicating whether the archive is solid + /// + public bool IsSolid + { + get + { + DisposedCheck(); + if (!_isSolid.HasValue) + { + GetArchiveInfo(true); + } + if (_isSolid != null) + { + return _isSolid.Value; + } + throw new SevenZipException("_isSolid == null"); + } + } + + /// + /// Gets the number of files in the archive + /// + public uint FilesCount + { + get + { + DisposedCheck(); + if (!_filesCount.HasValue) + { + GetArchiveInfo(true); + } + if (_filesCount != null) + { + return _filesCount.Value; + } + throw new SevenZipException("_filesCount == null"); + } + } + + /// + /// Gets archive format + /// + public InArchiveFormat Format + { + get + { + DisposedCheck(); + return _format; + } + } + + /// + /// Gets or sets the value indicatin whether to preserve the directory structure of extracted files. + /// + public bool PreserveDirectoryStructure { get; set; } + #endregion + + /// + /// Checked whether the class was disposed. + /// + /// + private void DisposedCheck() + { + if (_disposed) + { + throw new ObjectDisposedException("SevenZipExtractor"); + } +#if !WINCE + RecreateInstanceIfNeeded(); +#endif + } + + #region Core private functions + + private ArchiveOpenCallback GetArchiveOpenCallback() + { + return _openCallback ?? (_openCallback = String.IsNullOrEmpty(Password) + ? new ArchiveOpenCallback(_fileName) + : new ArchiveOpenCallback(_fileName, Password)); + } + + /// + /// Gets the archive input stream. + /// + /// The archive input wrapper stream. + private IInStream GetArchiveStream(bool dispose) + { + if (_archiveStream != null) + { + if (_archiveStream is DisposeVariableWrapper) + { + (_archiveStream as DisposeVariableWrapper).DisposeStream = dispose; + } + return _archiveStream; + } + + if (_inStream != null) + { + _inStream.Seek(0, SeekOrigin.Begin); + _archiveStream = new InStreamWrapper(_inStream, false); + } + else + { + if (!_fileName.EndsWith(".001", StringComparison.OrdinalIgnoreCase)) + { + _archiveStream = new InStreamWrapper( + new ArchiveEmulationStreamProxy(new FileStream( + _fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), + _offset), + dispose); + } + else + { + _archiveStream = new InMultiStreamWrapper(_fileName, dispose); + _packedSize = (_archiveStream as InMultiStreamWrapper).Length; + } + } + return _archiveStream; + } + + /// + /// Opens the archive and throws exceptions or returns OperationResult.DataError if any error occurs. + /// + /// The IInStream compliant class instance, that is, the input stream. + /// The ArchiveOpenCallback instance. + /// OperationResult.Ok if Open() succeeds. + private OperationResult OpenArchiveInner(IInStream archiveStream, + IArchiveOpenCallback openCallback) + { + ulong checkPos = 1 << 15; + int res = _archive.Open(archiveStream, ref checkPos, openCallback); + return (OperationResult)res; + } + + /// + /// Opens the archive and throws exceptions or returns OperationResult.DataError if any error occurs. + /// + /// The IInStream compliant class instance, that is, the input stream. + /// The ArchiveOpenCallback instance. + /// True if Open() succeeds; otherwise, false. + private bool OpenArchive(IInStream archiveStream, + ArchiveOpenCallback openCallback) + { + if (!_opened) + { + if (OpenArchiveInner(archiveStream, openCallback) != OperationResult.Ok) + { + if (!ThrowException(null, new SevenZipArchiveException())) + { + return false; + } + } + _volumeFileNames = new ReadOnlyCollection(openCallback.VolumeFileNames); + _opened = true; + } + return true; + } + + /// + /// Retrieves all information about the archive. + /// + /// + private void GetArchiveInfo(bool disposeStream) + { + if (_archive == null) + { + if (!ThrowException(null, new SevenZipArchiveException())) + { + return; + } + } + else + { + IInStream archiveStream; + using ((archiveStream = GetArchiveStream(disposeStream)) as IDisposable) + { + var openCallback = GetArchiveOpenCallback(); + if (!_opened) + { + if (!OpenArchive(archiveStream, openCallback)) + { + return; + } + _opened = !disposeStream; + } + _filesCount = _archive.GetNumberOfItems(); + _archiveFileData = new List((int)_filesCount); + if (_filesCount != 0) + { + var data = new PropVariant(); + try + { + #region Getting archive items data + + for (uint i = 0; i < _filesCount; i++) + { + try + { + var fileInfo = new ArchiveFileInfo { Index = (int)i }; + _archive.GetProperty(i, ItemPropId.Path, ref data); + fileInfo.FileName = NativeMethods.SafeCast(data, "[no name]"); + _archive.GetProperty(i, ItemPropId.LastWriteTime, ref data); + fileInfo.LastWriteTime = NativeMethods.SafeCast(data, DateTime.Now); + _archive.GetProperty(i, ItemPropId.CreationTime, ref data); + fileInfo.CreationTime = NativeMethods.SafeCast(data, DateTime.Now); + _archive.GetProperty(i, ItemPropId.LastAccessTime, ref data); + fileInfo.LastAccessTime = NativeMethods.SafeCast(data, DateTime.Now); + _archive.GetProperty(i, ItemPropId.Size, ref data); + fileInfo.Size = NativeMethods.SafeCast(data, 0); + if (fileInfo.Size == 0) + { + fileInfo.Size = NativeMethods.SafeCast(data, 0); + } + _archive.GetProperty(i, ItemPropId.Attributes, ref data); + fileInfo.Attributes = NativeMethods.SafeCast(data, 0); + _archive.GetProperty(i, ItemPropId.IsDirectory, ref data); + fileInfo.IsDirectory = NativeMethods.SafeCast(data, false); + _archive.GetProperty(i, ItemPropId.Encrypted, ref data); + fileInfo.Encrypted = NativeMethods.SafeCast(data, false); + _archive.GetProperty(i, ItemPropId.Crc, ref data); + fileInfo.Crc = NativeMethods.SafeCast(data, 0); + _archive.GetProperty(i, ItemPropId.Comment, ref data); + fileInfo.Comment = NativeMethods.SafeCast(data, ""); + _archiveFileData.Add(fileInfo); + } + catch (InvalidCastException) + { + ThrowException(null, new SevenZipArchiveException("probably archive is corrupted.")); + } + } + + #endregion + + #region Getting archive properties + + uint numProps = _archive.GetNumberOfArchiveProperties(); + var archProps = new List((int)numProps); + for (uint i = 0; i < numProps; i++) + { + string propName; + ItemPropId propId; + ushort varType; + _archive.GetArchivePropertyInfo(i, out propName, out propId, out varType); + _archive.GetArchiveProperty(propId, ref data); + if (propId == ItemPropId.Solid) + { + _isSolid = NativeMethods.SafeCast(data, true); + } + // TODO Add more archive properties + if (PropIdToName.PropIdNames.ContainsKey(propId)) + { + archProps.Add(new ArchiveProperty + { + Name = PropIdToName.PropIdNames[propId], + Value = data.Object + }); + } + else + { + Debug.WriteLine( + "An unknown archive property encountered (code " + + ((int)propId).ToString(CultureInfo.InvariantCulture) + ')'); + } + } + _archiveProperties = new ReadOnlyCollection(archProps); + if (!_isSolid.HasValue && _format == InArchiveFormat.Zip) + { + _isSolid = false; + } + if (!_isSolid.HasValue) + { + _isSolid = true; + } + + #endregion + } + catch (Exception) + { + if (openCallback.ThrowException()) + { + throw; + } + } + } + } + if (disposeStream) + { + _archive.Close(); + _archiveStream = null; + } + _archiveFileInfoCollection = new ReadOnlyCollection(_archiveFileData); + } + } + + /// + /// Ensure that _archiveFileData is loaded. + /// + /// Dispose the archive stream after this operation. + private void InitArchiveFileData(bool disposeStream) + { + if (_archiveFileData == null) + { + GetArchiveInfo(disposeStream); + } + } + + /// + /// Produces an array of indexes from 0 to the maximum value in the specified array + /// + /// The source array + /// The array of indexes from 0 to the maximum value in the specified array + private static uint[] SolidIndexes(uint[] indexes) + { +#if CS4 + int max = indexes.Aggregate(0, (current, i) => Math.Max(current, (int) i)); +#else + int max = 0; + foreach (uint i in indexes) + { + max = Math.Max(max, (int)i); + } +#endif + if (max > 0) + { + max++; + var res = new uint[max]; + for (int i = 0; i < max; i++) + { + res[i] = (uint)i; + } + return res; + } + return indexes; + } + + /// + /// Checkes whether all the indexes are valid. + /// + /// The indexes to check. + /// True is valid; otherwise, false. + private static bool CheckIndexes(params int[] indexes) + { +#if CS4 // Wow, C# 4 is great! + return indexes.All(i => i >= 0); +#else + bool res = true; + foreach (int i in indexes) + { + if (i < 0) + { + res = false; + break; + } + } + return res; +#endif + } + + private void ArchiveExtractCallbackCommonInit(ArchiveExtractCallback aec) + { + aec.Open += ((s, e) => { _unpackedSize = (long)e.TotalSize; }); + aec.FileExtractionStarted += FileExtractionStartedEventProxy; + aec.FileExtractionFinished += FileExtractionFinishedEventProxy; + aec.Extracting += ExtractingEventProxy; + aec.FileExists += FileExistsEventProxy; + } + + /// + /// Gets the IArchiveExtractCallback callback + /// + /// The directory where extract the files + /// The number of files to be extracted + /// The list of actual indexes (solid archives support) + /// The ArchiveExtractCallback callback + private ArchiveExtractCallback GetArchiveExtractCallback(string directory, int filesCount, + List actualIndexes) + { + var aec = String.IsNullOrEmpty(Password) + ? new ArchiveExtractCallback(_archive, directory, filesCount, PreserveDirectoryStructure, actualIndexes, this) + : new ArchiveExtractCallback(_archive, directory, filesCount, PreserveDirectoryStructure, actualIndexes, Password, this); + ArchiveExtractCallbackCommonInit(aec); + return aec; + } + + /// + /// Gets the IArchiveExtractCallback callback + /// + /// The stream where extract the file + /// The file index + /// The number of files to be extracted + /// The ArchiveExtractCallback callback + private ArchiveExtractCallback GetArchiveExtractCallback(Stream stream, uint index, int filesCount) + { + var aec = String.IsNullOrEmpty(Password) + ? new ArchiveExtractCallback(_archive, stream, filesCount, index, this) + : new ArchiveExtractCallback(_archive, stream, filesCount, index, Password, this); + ArchiveExtractCallbackCommonInit(aec); + return aec; + } + + private void FreeArchiveExtractCallback(ArchiveExtractCallback callback) + { + callback.Open -= ((s, e) => { _unpackedSize = (long)e.TotalSize; }); + callback.FileExtractionStarted -= FileExtractionStartedEventProxy; + callback.FileExtractionFinished -= FileExtractionFinishedEventProxy; + callback.Extracting -= ExtractingEventProxy; + callback.FileExists -= FileExistsEventProxy; + } + #endregion +#endif + + /// + /// Checks if the specified stream supports extraction. + /// + /// The stream to check. + private static void ValidateStream(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + if (!stream.CanSeek || !stream.CanRead) + { + throw new ArgumentException("The specified stream can not seek or read.", "stream"); + } + if (stream.Length == 0) + { + throw new ArgumentException("The specified stream has zero length.", "stream"); + } + } + +#if UNMANAGED + + #region IDisposable Members + + private void CommonDispose() + { + if (_opened) + { + try + { + if (_archive != null) + { + _archive.Close(); + } + } + catch (Exception) { } + } + _archive = null; + _archiveFileData = null; + _archiveProperties = null; + _archiveFileInfoCollection = null; + _inStream = null; + if (_openCallback != null) + { + try + { + _openCallback.Dispose(); + } + catch (ObjectDisposedException) { } + _openCallback = null; + } + if (_archiveStream != null) + { + if (_archiveStream is IDisposable) + { + try + { + if (_archiveStream is DisposeVariableWrapper) + { + (_archiveStream as DisposeVariableWrapper).DisposeStream = true; + } + (_archiveStream as IDisposable).Dispose(); + } + catch (ObjectDisposedException) { } + _archiveStream = null; + } + } + SevenZipLibraryManager.FreeLibrary(this, _format); + } + + /// + /// Releases the unmanaged resources used by SevenZipExtractor. + /// + public void Dispose() + { + if (!_disposed) + { + CommonDispose(); + } + _disposed = true; + GC.SuppressFinalize(this); + } + + #endregion + + #region Core public Members + + #region Events + + /// + /// Occurs when a new file is going to be unpacked. + /// + /// Occurs when 7-zip engine requests for an output stream for a new file to unpack in. + public event EventHandler FileExtractionStarted; + + /// + /// Occurs when a file has been successfully unpacked. + /// + public event EventHandler FileExtractionFinished; + + /// + /// Occurs when the archive has been unpacked. + /// + public event EventHandler ExtractionFinished; + + /// + /// Occurs when data are being extracted. + /// + /// Use this event for accurate progress handling and various ProgressBar.StepBy(e.PercentDelta) routines. + public event EventHandler Extracting; + + /// + /// Occurs during the extraction when a file already exists. + /// + public event EventHandler FileExists; + + #region Event proxies + /// + /// Event proxy for FileExtractionStarted. + /// + /// The sender of the event. + /// The event arguments. + private void FileExtractionStartedEventProxy(object sender, FileInfoEventArgs e) + { + OnEvent(FileExtractionStarted, e, true); + } + + /// + /// Event proxy for FileExtractionFinished. + /// + /// The sender of the event. + /// The event arguments. + private void FileExtractionFinishedEventProxy(object sender, FileInfoEventArgs e) + { + OnEvent(FileExtractionFinished, e, true); + } + + /// + /// Event proxy for Extractng. + /// + /// The sender of the event. + /// The event arguments. + private void ExtractingEventProxy(object sender, ProgressEventArgs e) + { + OnEvent(Extracting, e, false); + } + + /// + /// Event proxy for FileExists. + /// + /// The sender of the event. + /// The event arguments. + private void FileExistsEventProxy(object sender, FileOverwriteEventArgs e) + { + OnEvent(FileExists, e, true); + } + #endregion + #endregion + + #region Properties + /// + /// Gets the collection of ArchiveFileInfo with all information about files in the archive + /// + public ReadOnlyCollection ArchiveFileData + { + get + { + DisposedCheck(); + InitArchiveFileData(true); + return _archiveFileInfoCollection; + } + } + + /// + /// Gets the properties for the current archive + /// + public ReadOnlyCollection ArchiveProperties + { + get + { + DisposedCheck(); + InitArchiveFileData(true); + return _archiveProperties; + } + } + + /// + /// Gets the collection of all file names contained in the archive. + /// + /// + /// Each get recreates the collection + /// + public ReadOnlyCollection ArchiveFileNames + { + get + { + DisposedCheck(); + InitArchiveFileData(true); + var fileNames = new List(_archiveFileData.Count); +#if CS4 + fileNames.AddRange(_archiveFileData.Select(afi => afi.FileName)); +#else + foreach (var afi in _archiveFileData) + { + fileNames.Add(afi.FileName); + } +#endif + return new ReadOnlyCollection(fileNames); + } + } + + /// + /// Gets the list of archive volume file names. + /// + public ReadOnlyCollection VolumeFileNames + { + get + { + DisposedCheck(); + InitArchiveFileData(true); + return _volumeFileNames; + } + } + #endregion + + /// + /// Performs the archive integrity test. + /// + /// True is the archive is ok; otherwise, false. + public bool Check() + { + DisposedCheck(); + try + { + InitArchiveFileData(false); + var archiveStream = GetArchiveStream(true); + var openCallback = GetArchiveOpenCallback(); + if (!OpenArchive(archiveStream, openCallback)) + { + return false; + } + using (var aec = GetArchiveExtractCallback("", (int)_filesCount, null)) + { + try + { + CheckedExecute( + _archive.Extract(null, UInt32.MaxValue, 1, aec), + SevenZipExtractionFailedException.DEFAULT_MESSAGE, aec); + } + finally + { + FreeArchiveExtractCallback(aec); + } + } + } + catch (Exception) + { + return false; + } + finally + { + if (_archive != null) + { + _archive.Close(); + } + _archiveStream = null; + _opened = false; + } + return true; + } + + #region ExtractFile overloads + /// + /// Unpacks the file by its name to the specified stream. + /// + /// The file full name in the archive file table. + /// The stream where the file is to be unpacked. + public void ExtractFile(string fileName, Stream stream) + { + DisposedCheck(); + InitArchiveFileData(false); + int index = -1; + foreach (ArchiveFileInfo afi in _archiveFileData) + { + if (afi.FileName == fileName && !afi.IsDirectory) + { + index = afi.Index; + break; + } + } + if (index == -1) + { + if (!ThrowException(null, new ArgumentOutOfRangeException( + "fileName", + "The specified file name was not found in the archive file table."))) + { + return; + } + } + else + { + ExtractFile(index, stream); + } + } + + /// + /// Unpacks the file by its index to the specified stream. + /// + /// Index in the archive file table. + /// The stream where the file is to be unpacked. + public void ExtractFile(int index, Stream stream) + { + DisposedCheck(); + ClearExceptions(); + if (!CheckIndexes(index)) + { + if (!ThrowException(null, new ArgumentException("The index must be more or equal to zero.", "index"))) + { + return; + } + } + if (!stream.CanWrite) + { + if (!ThrowException(null, new ArgumentException("The specified stream can not be written.", "stream"))) + { + return; + } + } + InitArchiveFileData(false); + if (index > _filesCount - 1) + { + if (!ThrowException(null, new ArgumentOutOfRangeException( + "index", "The specified index is greater than the archive files count."))) + { + return; + } + } + var indexes = new[] {(uint) index}; + if (_isSolid.Value) + { + indexes = SolidIndexes(indexes); + } + var archiveStream = GetArchiveStream(false); + var openCallback = GetArchiveOpenCallback(); + if (!OpenArchive(archiveStream, openCallback)) + { + return; + } + try + { + using (var aec = GetArchiveExtractCallback(stream, (uint) index, indexes.Length)) + { + try + { + CheckedExecute( + _archive.Extract(indexes, (uint) indexes.Length, 0, aec), + SevenZipExtractionFailedException.DEFAULT_MESSAGE, aec); + } + finally + { + FreeArchiveExtractCallback(aec); + } + } + } + catch (Exception) + { + if (openCallback.ThrowException()) + { + throw; + } + } + OnEvent(ExtractionFinished, EventArgs.Empty, false); + ThrowUserException(); + } + #endregion + + #region ExtractFiles overloads + /// + /// Unpacks files by their indices to the specified directory. + /// + /// indexes of the files in the archive file table. + /// Directory where the files are to be unpacked. + public void ExtractFiles(string directory, params int[] indexes) + { + DisposedCheck(); + ClearExceptions(); + if (!CheckIndexes(indexes)) + { + if ( + !ThrowException(null, new ArgumentException("The indexes must be more or equal to zero.", "indexes"))) + { + return; + } + } + InitArchiveFileData(false); + + #region Indexes stuff + + var uindexes = new uint[indexes.Length]; + for (int i = 0; i < indexes.Length; i++) + { + uindexes[i] = (uint) indexes[i]; + } +#if CS4 + if (uindexes.Where(i => i >= _filesCount).Any( + i => !ThrowException(null, + new ArgumentOutOfRangeException("indexes", + "Index must be less than " + + _filesCount.Value.ToString( + CultureInfo.InvariantCulture) + "!")))) + { + return; + } +#else + foreach (uint i in uindexes) + { + if (i >= _filesCount) + { + if (!ThrowException(null, + new ArgumentOutOfRangeException("indexes", + "Index must be less than " + + _filesCount.Value.ToString( + CultureInfo.InvariantCulture) + "!"))) + { + return; + } + } + } +#endif + var origIndexes = new List(uindexes); + origIndexes.Sort(); + uindexes = origIndexes.ToArray(); + if (_isSolid.Value) + { + uindexes = SolidIndexes(uindexes); + } + + #endregion + + try + { + IInStream archiveStream; + using ((archiveStream = GetArchiveStream(origIndexes.Count != 1)) as IDisposable) + { + var openCallback = GetArchiveOpenCallback(); + if (!OpenArchive(archiveStream, openCallback)) + { + return; + } + try + { + using (var aec = GetArchiveExtractCallback(directory, (int) _filesCount, origIndexes)) + { + try + { + CheckedExecute( + _archive.Extract(uindexes, (uint) uindexes.Length, 0, aec), + SevenZipExtractionFailedException.DEFAULT_MESSAGE, aec); + } + finally + { + FreeArchiveExtractCallback(aec); + } + } + } + catch (Exception) + { + if (openCallback.ThrowException()) + { + throw; + } + } + } + OnEvent(ExtractionFinished, EventArgs.Empty, false); + } + finally + { + if (origIndexes.Count > 1) + { + if (_archive != null) + { + _archive.Close(); + } + _archiveStream = null; + _opened = false; + } + } + ThrowUserException(); + } + + /// + /// Unpacks files by their full names to the specified directory. + /// + /// Full file names in the archive file table. + /// Directory where the files are to be unpacked. + public void ExtractFiles(string directory, params string[] fileNames) + { + DisposedCheck(); + InitArchiveFileData(false); + var indexes = new List(fileNames.Length); + var archiveFileNames = new List(ArchiveFileNames); + foreach (string fn in fileNames) + { + if (!archiveFileNames.Contains(fn)) + { + if ( + !ThrowException(null, + new ArgumentOutOfRangeException("fileNames", + "File \"" + fn + + "\" was not found in the archive file table."))) + { + return; + } + } + else + { + foreach (ArchiveFileInfo afi in _archiveFileData) + { + if (afi.FileName == fn && !afi.IsDirectory) + { + indexes.Add(afi.Index); + break; + } + } + } + } + ExtractFiles(directory, indexes.ToArray()); + } + + /// + /// Extracts files from the archive, giving a callback the choice what + /// to do with each file. The order of the files is given by the archive. + /// 7-Zip (and any other solid) archives are NOT supported. + /// + /// The callback to call for each file in the archive. + public void ExtractFiles(ExtractFileCallback extractFileCallback) + { + DisposedCheck(); + InitArchiveFileData(false); + if (IsSolid) + { + // solid strategy + } + else + { + foreach (ArchiveFileInfo archiveFileInfo in ArchiveFileData) + { + var extractFileCallbackArgs = new ExtractFileCallbackArgs(archiveFileInfo); + extractFileCallback(extractFileCallbackArgs); + if (extractFileCallbackArgs.CancelExtraction) + { + break; + } + if (extractFileCallbackArgs.ExtractToStream != null || extractFileCallbackArgs.ExtractToFile != null) + { + bool callDone = false; + try + { + if (extractFileCallbackArgs.ExtractToStream != null) + { + ExtractFile(archiveFileInfo.Index, extractFileCallbackArgs.ExtractToStream); + } + else + { + using (var file = new FileStream(extractFileCallbackArgs.ExtractToFile, FileMode.CreateNew, + FileAccess.Write, FileShare.None, 8192)) + { + ExtractFile(archiveFileInfo.Index, file); + } + } + callDone = true; + } + catch (Exception ex) + { + extractFileCallbackArgs.Exception = ex; + extractFileCallbackArgs.Reason = ExtractFileCallbackReason.Failure; + extractFileCallback(extractFileCallbackArgs); + if (!ThrowException(null, ex)) + { + return; + } + } + if (callDone) + { + extractFileCallbackArgs.Reason = ExtractFileCallbackReason.Done; + extractFileCallback(extractFileCallbackArgs); + } + } + } + } + } + #endregion + + /// + /// Unpacks the whole archive to the specified directory. + /// + /// The directory where the files are to be unpacked. + public void ExtractArchive(string directory) + { + DisposedCheck(); + ClearExceptions(); + InitArchiveFileData(false); + try + { + IInStream archiveStream; + using ((archiveStream = GetArchiveStream(true)) as IDisposable) + { + var openCallback = GetArchiveOpenCallback(); + if (!OpenArchive(archiveStream, openCallback)) + { + return; + } + try + { + using (var aec = GetArchiveExtractCallback(directory, (int) _filesCount, null)) + { + try + { + CheckedExecute( + _archive.Extract(null, UInt32.MaxValue, 0, aec), + SevenZipExtractionFailedException.DEFAULT_MESSAGE, aec); + OnEvent(ExtractionFinished, EventArgs.Empty, false); + } + finally + { + FreeArchiveExtractCallback(aec); + } + } + } + catch (Exception) + { + if (openCallback.ThrowException()) + { + throw; + } + } + } + } + finally + { + if (_archive != null) + { + _archive.Close(); + } + _archiveStream = null; + _opened = false; + } + ThrowUserException(); + } + #endregion + +#endif + + #region LZMA SDK functions + + internal static byte[] GetLzmaProperties(Stream inStream, out long outSize) + { + var lzmAproperties = new byte[5]; + if (inStream.Read(lzmAproperties, 0, 5) != 5) + { + throw new LzmaException(); + } + outSize = 0; + for (int i = 0; i < 8; i++) + { + int b = inStream.ReadByte(); + if (b < 0) + { + throw new LzmaException(); + } + outSize |= ((long) (byte) b) << (i << 3); + } + return lzmAproperties; + } + + /// + /// Decompress the specified stream (C# inside) + /// + /// The source compressed stream + /// The destination uncompressed stream + /// The length of compressed data (null for inStream.Length) + /// The event for handling the code progress + public static void DecompressStream(Stream inStream, Stream outStream, int? inLength, + EventHandler codeProgressEvent) + { + if (!inStream.CanRead || !outStream.CanWrite) + { + throw new ArgumentException("The specified streams are invalid."); + } + var decoder = new Decoder(); + long outSize, inSize = (inLength.HasValue ? inLength.Value : inStream.Length) - inStream.Position; + decoder.SetDecoderProperties(GetLzmaProperties(inStream, out outSize)); + decoder.Code( + inStream, outStream, inSize, outSize, + new LzmaProgressCallback(inSize, codeProgressEvent)); + } + + /// + /// Decompress byte array compressed with LZMA algorithm (C# inside) + /// + /// Byte array to decompress + /// Decompressed byte array + public static byte[] ExtractBytes(byte[] data) + { + using (var inStream = new MemoryStream(data)) + { + var decoder = new Decoder(); + inStream.Seek(0, 0); + using (var outStream = new MemoryStream()) + { + long outSize; + decoder.SetDecoderProperties(GetLzmaProperties(inStream, out outSize)); + decoder.Code(inStream, outStream, inStream.Length - inStream.Position, outSize, null); + return outStream.ToArray(); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/SevenZipExtractorAsynchronous.cs b/BizHawk.Util/7z/SevenZipExtractorAsynchronous.cs new file mode 100644 index 0000000000..bffc19cc5e --- /dev/null +++ b/BizHawk.Util/7z/SevenZipExtractorAsynchronous.cs @@ -0,0 +1,294 @@ +namespace SevenZip +{ + using System; + using System.IO; +#if DOTNET20 + using System.Threading; +#else + using System.Windows.Threading; +#endif + + partial class SevenZipExtractor + { + #region Asynchronous core methods + + /// + /// Recreates the instance of the SevenZipExtractor class. + /// Used in asynchronous methods. + /// + private void RecreateInstanceIfNeeded() + { + if (NeedsToBeRecreated) + { + NeedsToBeRecreated = false; + Stream backupStream = null; + string backupFileName = null; + if (String.IsNullOrEmpty(_fileName)) + { + backupStream = _inStream; + } + else + { + backupFileName = _fileName; + } + CommonDispose(); + if (backupStream == null) + { + Init(backupFileName); + } + else + { + Init(backupStream); + } + } + } + + internal override void SaveContext( +#if !DOTNET20 + DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif +) + { + DisposedCheck(); + base.SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + + } + + #endregion + + #region Delegates + /// + /// The delegate to use in BeginExtractArchive. + /// + /// The directory where the files are to be unpacked. + private delegate void ExtractArchiveDelegate(string directory); + + /// + /// The delegate to use in BeginExtractFile (by file name). + /// + /// The file full name in the archive file table. + /// The stream where the file is to be unpacked. + private delegate void ExtractFileByFileNameDelegate(string fileName, Stream stream); + + /// + /// The delegate to use in BeginExtractFile (by index). + /// + /// Index in the archive file table. + /// The stream where the file is to be unpacked. + private delegate void ExtractFileByIndexDelegate(int index, Stream stream); + + /// + /// The delegate to use in BeginExtractFiles(string directory, params int[] indexes). + /// + /// indexes of the files in the archive file table. + /// Directory where the files are to be unpacked. + private delegate void ExtractFiles1Delegate(string directory, int[] indexes); + + /// + /// The delegate to use in BeginExtractFiles(string directory, params string[] fileNames). + /// + /// Full file names in the archive file table. + /// Directory where the files are to be unpacked. + private delegate void ExtractFiles2Delegate(string directory, string[] fileNames); + + /// + /// The delegate to use in BeginExtractFiles(ExtractFileCallback extractFileCallback). + /// + /// The callback to call for each file in the archive. + private delegate void ExtractFiles3Delegate(ExtractFileCallback extractFileCallback); + #endregion + +#if !DOTNET20 + /// + /// Unpacks the whole archive asynchronously to the specified directory name at the specified priority. + /// + /// The directory where the files are to be unpacked. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Unpacks the whole archive asynchronously to the specified directory name at the specified priority. + /// + /// The directory where the files are to be unpacked. +#endif + public void BeginExtractArchive(string directory +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif +) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ExtractArchiveDelegate(ExtractArchive)).BeginInvoke(directory, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Unpacks the file asynchronously by its name to the specified stream. + /// + /// The file full name in the archive file table. + /// The stream where the file is to be unpacked. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Unpacks the file asynchronously by its name to the specified stream. + /// + /// The file full name in the archive file table. + /// The stream where the file is to be unpacked. +#endif + public void BeginExtractFile(string fileName, Stream stream +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif +) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ExtractFileByFileNameDelegate(ExtractFile)).BeginInvoke(fileName, stream, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Unpacks the file asynchronously by its index to the specified stream. + /// + /// Index in the archive file table. + /// The stream where the file is to be unpacked. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Unpacks the file asynchronously by its index to the specified stream. + /// + /// Index in the archive file table. + /// The stream where the file is to be unpacked. +#endif + public void BeginExtractFile(int index, Stream stream +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif +) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ExtractFileByIndexDelegate(ExtractFile)).BeginInvoke(index, stream, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Unpacks files asynchronously by their indices to the specified directory. + /// + /// indexes of the files in the archive file table. + /// Directory where the files are to be unpacked. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Unpacks files asynchronously by their indices to the specified directory. + /// + /// indexes of the files in the archive file table. + /// Directory where the files are to be unpacked. +#endif + public void BeginExtractFiles(string directory +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif + , params int[] indexes) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ExtractFiles1Delegate(ExtractFiles)).BeginInvoke(directory, indexes, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Unpacks files asynchronously by their full names to the specified directory. + /// + /// Full file names in the archive file table. + /// Directory where the files are to be unpacked. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Unpacks files asynchronously by their full names to the specified directory. + /// + /// Full file names in the archive file table. + /// Directory where the files are to be unpacked. +#endif + public void BeginExtractFiles(string directory +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif + , params string[] fileNames) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ExtractFiles2Delegate(ExtractFiles)).BeginInvoke(directory, fileNames, AsyncCallbackImplementation, this); + } + +#if !DOTNET20 + /// + /// Extracts files from the archive asynchronously, giving a callback the choice what + /// to do with each file. The order of the files is given by the archive. + /// 7-Zip (and any other solid) archives are NOT supported. + /// + /// The callback to call for each file in the archive. + /// The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked. +#else + /// + /// Extracts files from the archive asynchronously, giving a callback the choice what + /// to do with each file. The order of the files is given by the archive. + /// 7-Zip (and any other solid) archives are NOT supported. + /// + /// The callback to call for each file in the archive. +#endif + public void BeginExtractFiles(ExtractFileCallback extractFileCallback +#if !DOTNET20 + , DispatcherPriority eventPriority +#if CS4 + = DispatcherPriority.Normal +#endif +#endif +) + { + SaveContext( +#if !DOTNET20 + eventPriority +#endif + ); + (new ExtractFiles3Delegate(ExtractFiles)).BeginInvoke(extractFileCallback, AsyncCallbackImplementation, this); + } + } +} diff --git a/BizHawk.Util/7z/SevenZipSfx.cs b/BizHawk.Util/7z/SevenZipSfx.cs new file mode 100644 index 0000000000..c02d279fd9 --- /dev/null +++ b/BizHawk.Util/7z/SevenZipSfx.cs @@ -0,0 +1,499 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Text; +using System.Xml; +using System.Xml.Schema; + +namespace SevenZip +{ +#if SFX + using SfxSettings = Dictionary; + + /// + /// Sfx module choice enumeration + /// + public enum SfxModule + { + /// + /// Default module (leave this if unsure) + /// + Default, + /// + /// The simple sfx module by Igor Pavlov with no adjustable parameters + /// + Simple, + /// + /// The installer sfx module by Igor Pavlov + /// + Installer, + /// + /// The extended installer sfx module by Oleg Scherbakov + /// + Extended, + /// + /// The custom sfx module. First you must specify the module file name. + /// + Custom + } + + /// + /// The class for making 7-zip based self-extracting archives. + /// + public class SevenZipSfx + { + private static readonly Dictionary> SfxSupportedModuleNames = + new Dictionary>(3) + { + {SfxModule.Default, new List(1) {"7zxSD_All.sfx"}}, + {SfxModule.Simple, new List(2) {"7z.sfx", "7zCon.sfx"}}, + {SfxModule.Installer, new List(2) {"7zS.sfx", "7zSD.sfx"}}, + { + SfxModule.Extended, + new List(4) {"7zxSD_All.sfx", "7zxSD_Deflate", "7zxSD_LZMA", "7zxSD_PPMd"} + } + }; + + private SfxModule _module = SfxModule.Default; + private string _moduleFileName; + private Dictionary> _sfxCommands; + + /// + /// Initializes a new instance of the SevenZipSfx class. + /// + public SevenZipSfx() + { + _module = SfxModule.Default; + CommonInit(); + } + + /// + /// Initializes a new instance of the SevenZipSfx class. + /// + /// The sfx module to use as a front-end. + public SevenZipSfx(SfxModule module) + { + if (module == SfxModule.Custom) + { + throw new ArgumentException("You must specify the custom module executable.", "module"); + } + _module = module; + CommonInit(); + } + + /// + /// Initializes a new instance of the SevenZipSfx class. + /// + /// + public SevenZipSfx(string moduleFileName) + { + _module = SfxModule.Custom; + ModuleFileName = moduleFileName; + CommonInit(); + } + + /// + /// Gets the sfx module type. + /// + public SfxModule SfxModule + { + get + { + return _module; + } + } + + /// + /// Gets or sets the custom sfx module file name + /// + public string ModuleFileName + { + get + { + return _moduleFileName; + } + + set + { + if (!File.Exists(value)) + { + throw new ArgumentException("The specified file does not exist."); + } + _moduleFileName = value; + _module = SfxModule.Custom; + string sfxName = Path.GetFileName(value); + foreach (SfxModule mod in SfxSupportedModuleNames.Keys) + { + if (SfxSupportedModuleNames[mod].Contains(sfxName)) + { + _module = mod; + } + } + } + } + + private void CommonInit() + { + LoadCommandsFromResource("Configs"); + } + + private static string GetResourceString(string str) + { +#if !WINCE + return "SevenZip.sfx." + str; +#else + return "SevenZipSharpMobile.sfx." + str; +#endif + } + + /// + /// Gets the sfx module enum by the list of supported modules + /// + /// + /// + private static SfxModule GetModuleByName(string name) + { + if (name.IndexOf("7z.sfx", StringComparison.Ordinal) > -1) + { + return SfxModule.Simple; + } + if (name.IndexOf("7zS.sfx", StringComparison.Ordinal) > -1) + { + return SfxModule.Installer; + } + if (name.IndexOf("7zxSD_All.sfx", StringComparison.Ordinal) > -1) + { + return SfxModule.Extended; + } + throw new SevenZipSfxValidationException("The specified configuration is unsupported."); + } + + /// + /// Loads the commands for each supported sfx module configuration + /// + /// The resource name for xml definitions + private void LoadCommandsFromResource(string xmlDefinitions) + { + using (Stream cfg = Assembly.GetExecutingAssembly().GetManifestResourceStream( + GetResourceString(xmlDefinitions + ".xml"))) + { + if (cfg == null) + { + throw new SevenZipSfxValidationException("The configuration \"" + xmlDefinitions + + "\" does not exist."); + } + using (Stream schm = Assembly.GetExecutingAssembly().GetManifestResourceStream( + GetResourceString(xmlDefinitions + ".xsd"))) + { + if (schm == null) + { + throw new SevenZipSfxValidationException("The configuration schema \"" + xmlDefinitions + + "\" does not exist."); + } + var sc = new XmlSchemaSet(); + using (XmlReader scr = XmlReader.Create(schm)) + { + sc.Add(null, scr); + var settings = new XmlReaderSettings {ValidationType = ValidationType.Schema, Schemas = sc}; + string validationErrors = ""; + settings.ValidationEventHandler += + ((s, t) => + { + validationErrors += String.Format(CultureInfo.InvariantCulture, "[{0}]: {1}\n", + t.Severity.ToString(), t.Message); + }); + using (XmlReader rdr = XmlReader.Create(cfg, settings)) + { + _sfxCommands = new Dictionary>(); + rdr.Read(); + rdr.Read(); + rdr.Read(); + rdr.Read(); + rdr.Read(); + rdr.ReadStartElement("sfxConfigs"); + rdr.Read(); + do + { + SfxModule mod = GetModuleByName(rdr["modules"]); + rdr.ReadStartElement("config"); + rdr.Read(); + if (rdr.Name == "id") + { + var cmds = new List(); + _sfxCommands.Add(mod, cmds); + do + { + cmds.Add(rdr["command"]); + rdr.Read(); + rdr.Read(); + } while (rdr.Name == "id"); + rdr.ReadEndElement(); + rdr.Read(); + } + else + { + _sfxCommands.Add(mod, null); + } + } while (rdr.Name == "config"); + } + if (!String.IsNullOrEmpty(validationErrors)) + { + throw new SevenZipSfxValidationException( + "\n" + validationErrors.Substring(0, validationErrors.Length - 1)); + } + _sfxCommands.Add(SfxModule.Default, _sfxCommands[SfxModule.Extended]); + } + } + } + } + + /// + /// Validates the sfx scenario commands. + /// + /// The sfx settings dictionary to validate. + private void ValidateSettings(SfxSettings settings) + { + if (_module == SfxModule.Custom) + { + return; + } + List commands = _sfxCommands[_module]; + if (commands == null) + { + return; + } + var invalidCommands = new List(); + foreach (string command in settings.Keys) + { + if (!commands.Contains(command)) + { + invalidCommands.Add(command); + } + } + if (invalidCommands.Count > 0) + { + var invalidText = new StringBuilder("\nInvalid commands:\n"); + foreach (string str in invalidCommands) + { + invalidText.Append(str); + } + throw new SevenZipSfxValidationException(invalidText.ToString()); + } + } + + /// + /// Gets the stream containing the sfx settings. + /// + /// The sfx settings dictionary. + /// + private static Stream GetSettingsStream(SfxSettings settings) + { + var ms = new MemoryStream(); + byte[] buf = Encoding.UTF8.GetBytes(@";!@Install@!UTF-8!" + '\n'); + ms.Write(buf, 0, buf.Length); + foreach (string command in settings.Keys) + { + buf = + Encoding.UTF8.GetBytes(String.Format(CultureInfo.InvariantCulture, "{0}=\"{1}\"\n", command, + settings[command])); + ms.Write(buf, 0, buf.Length); + } + buf = Encoding.UTF8.GetBytes(@";!@InstallEnd@!"); + ms.Write(buf, 0, buf.Length); + return ms; + } + + private SfxSettings GetDefaultSettings() + { + switch (_module) + { + default: + return null; + case SfxModule.Installer: + var settings = new Dictionary {{"Title", "7-Zip self-extracting archive"}}; + return settings; + case SfxModule.Default: + case SfxModule.Extended: + settings = new Dictionary + { + {"GUIMode", "0"}, + {"InstallPath", "."}, + {"GUIFlags", "128+8"}, + {"ExtractPathTitle", "7-Zip self-extracting archive"}, + {"ExtractPathText", "Specify the path where to extract the files:"} + }; + return settings; + } + } + + /// + /// Writes the whole to the other one. + /// + /// The source stream to read from. + /// The destination stream to wrie to. + private static void WriteStream(Stream src, Stream dest) + { + src.Seek(0, SeekOrigin.Begin); + var buf = new byte[32768]; + int bytesRead; + while ((bytesRead = src.Read(buf, 0, buf.Length)) > 0) + { + dest.Write(buf, 0, bytesRead); + } + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive stream. + /// The name of the self-extracting executable. + public void MakeSfx(Stream archive, string sfxFileName) + { + using (Stream sfxStream = File.Create(sfxFileName)) + { + MakeSfx(archive, GetDefaultSettings(), sfxStream); + } + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive stream. + /// The stream to write the self-extracting executable to. + public void MakeSfx(Stream archive, Stream sfxStream) + { + MakeSfx(archive, GetDefaultSettings(), sfxStream); + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive stream. + /// The sfx settings. + /// The name of the self-extracting executable. + public void MakeSfx(Stream archive, SfxSettings settings, string sfxFileName) + { + using (Stream sfxStream = File.Create(sfxFileName)) + { + MakeSfx(archive, settings, sfxStream); + } + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive stream. + /// The sfx settings. + /// The stream to write the self-extracting executable to. + public void MakeSfx(Stream archive, SfxSettings settings, Stream sfxStream) + { + if (!sfxStream.CanWrite) + { + throw new ArgumentException("The specified output stream can not write.", "sfxStream"); + } + ValidateSettings(settings); + using (Stream sfx = _module == SfxModule.Default + ? Assembly.GetExecutingAssembly().GetManifestResourceStream( + GetResourceString(SfxSupportedModuleNames[_module][0])) + : new FileStream(_moduleFileName, FileMode.Open, FileAccess.Read, + FileShare.ReadWrite)) + { + WriteStream(sfx, sfxStream); + } + if (_module == SfxModule.Custom || _sfxCommands[_module] != null) + { + using (Stream set = GetSettingsStream(settings)) + { + WriteStream(set, sfxStream); + } + } + WriteStream(archive, sfxStream); + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive file name. + /// The name of the self-extracting executable. + public void MakeSfx(string archiveFileName, string sfxFileName) + { + using (Stream sfxStream = File.Create(sfxFileName)) + { + using ( + Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + ) + { + MakeSfx(archive, GetDefaultSettings(), sfxStream); + } + } + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive file name. + /// The stream to write the self-extracting executable to. + public void MakeSfx(string archiveFileName, Stream sfxStream) + { + using (Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + ) + { + MakeSfx(archive, GetDefaultSettings(), sfxStream); + } + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive file name. + /// The sfx settings. + /// The name of the self-extracting executable. + public void MakeSfx(string archiveFileName, SfxSettings settings, string sfxFileName) + { + using (Stream sfxStream = File.Create(sfxFileName)) + { + using ( + Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + ) + { + MakeSfx(archive, settings, sfxStream); + } + } + } + + /// + /// Makes the self-extracting archive. + /// + /// The archive file name. + /// The sfx settings. + /// The stream to write the self-extracting executable to. + public void MakeSfx(string archiveFileName, SfxSettings settings, Stream sfxStream) + { + using (Stream archive = new FileStream(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + ) + { + MakeSfx(archive, settings, sfxStream); + } + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/StreamWrappers.cs b/BizHawk.Util/7z/StreamWrappers.cs new file mode 100644 index 0000000000..55821d3e17 --- /dev/null +++ b/BizHawk.Util/7z/StreamWrappers.cs @@ -0,0 +1,545 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; +#if MONO +using SevenZip.Mono.COM; +#endif + +namespace SevenZip +{ +#if UNMANAGED + + /// + /// A class that has DisposeStream property. + /// + internal class DisposeVariableWrapper + { + public bool DisposeStream { protected get; set; } + + protected DisposeVariableWrapper(bool disposeStream) { DisposeStream = disposeStream; } + } + + /// + /// Stream wrapper used in InStreamWrapper + /// + internal class StreamWrapper : DisposeVariableWrapper, IDisposable + { + /// + /// File name associated with the stream (for date fix) + /// + private readonly string _fileName; + + private readonly DateTime _fileTime; + + /// + /// Worker stream for reading, writing and seeking. + /// + private Stream _baseStream; + + /// + /// Initializes a new instance of the StreamWrapper class + /// + /// Worker stream for reading, writing and seeking + /// File name associated with the stream (for attributes fix) + /// File last write time (for attributes fix) + /// Indicates whether to dispose the baseStream + protected StreamWrapper(Stream baseStream, string fileName, DateTime time, bool disposeStream) + : base(disposeStream) + { + _baseStream = baseStream; + _fileName = fileName; + _fileTime = time; + } + + /// + /// Initializes a new instance of the StreamWrapper class + /// + /// Worker stream for reading, writing and seeking + /// Indicates whether to dispose the baseStream + protected StreamWrapper(Stream baseStream, bool disposeStream) + : base(disposeStream) + { + _baseStream = baseStream; + } + + /// + /// Gets the worker stream for reading, writing and seeking. + /// + protected Stream BaseStream + { + get + { + return _baseStream; + } + } + + #region IDisposable Members + + /// + /// Cleans up any resources used and fixes file attributes. + /// + public void Dispose() + { + if (_baseStream != null && DisposeStream) + { + try + { + _baseStream.Dispose(); + } + catch (ObjectDisposedException) { } + _baseStream = null; + } + if (!String.IsNullOrEmpty(_fileName) && File.Exists(_fileName)) + { + try + { +#if !WINCE + + File.SetLastWriteTime(_fileName, _fileTime); + File.SetLastAccessTime(_fileName, _fileTime); + File.SetCreationTime(_fileName, _fileTime); +#elif WINCE + OpenNETCF.IO.FileHelper.SetLastWriteTime(_fileName, _fileTime); + OpenNETCF.IO.FileHelper.SetLastAccessTime(_fileName, _fileTime); + OpenNETCF.IO.FileHelper.SetCreationTime(_fileName, _fileTime); +#endif + //TODO: time support for Windows Phone + } + catch (ArgumentOutOfRangeException) {} + } + GC.SuppressFinalize(this); + } + + #endregion + + public virtual void Seek(long offset, SeekOrigin seekOrigin, IntPtr newPosition) + { + if (BaseStream != null) + { + long position = BaseStream.Seek(offset, seekOrigin); + if (newPosition != IntPtr.Zero) + { + Marshal.WriteInt64(newPosition, position); + } + } + } + } + + /// + /// IInStream wrapper used in stream read operations. + /// + internal sealed class InStreamWrapper : StreamWrapper, ISequentialInStream, IInStream + { + /// + /// Initializes a new instance of the InStreamWrapper class. + /// + /// Stream for writing data + /// Indicates whether to dispose the baseStream + public InStreamWrapper(Stream baseStream, bool disposeStream) : base(baseStream, disposeStream) { } + + #region ISequentialInStream Members + + /// + /// Reads data from the stream. + /// + /// A data array. + /// The array size. + /// The read bytes count. + public int Read(byte[] data, uint size) + { + int readCount = 0; + if (BaseStream != null) + { + readCount = BaseStream.Read(data, 0, (int) size); + if (readCount > 0) + { + OnBytesRead(new IntEventArgs(readCount)); + } + } + return readCount; + } + + #endregion + + /// + /// Occurs when IntEventArgs.Value bytes were read from the source. + /// + public event EventHandler BytesRead; + + private void OnBytesRead(IntEventArgs e) + { + if (BytesRead != null) + { + BytesRead(this, e); + } + } + } + + /// + /// IOutStream wrapper used in stream write operations. + /// + internal sealed class OutStreamWrapper : StreamWrapper, ISequentialOutStream, IOutStream + { + /// + /// Initializes a new instance of the OutStreamWrapper class + /// + /// Stream for writing data + /// File name (for attributes fix) + /// Time of the file creation (for attributes fix) + /// Indicates whether to dispose the baseStream + public OutStreamWrapper(Stream baseStream, string fileName, DateTime time, bool disposeStream) : + base(baseStream, fileName, time, disposeStream) {} + + /// + /// Initializes a new instance of the OutStreamWrapper class + /// + /// Stream for writing data + /// Indicates whether to dispose the baseStream + public OutStreamWrapper(Stream baseStream, bool disposeStream) : + base(baseStream, disposeStream) {} + + #region IOutStream Members + + public int SetSize(long newSize) + { + BaseStream.SetLength(newSize); + return 0; + } + + #endregion + + #region ISequentialOutStream Members + + /// + /// Writes data to the stream + /// + /// Data array + /// Array size + /// Count of written bytes + /// Zero if Ok + public int Write(byte[] data, uint size, IntPtr processedSize) + { + BaseStream.Write(data, 0, (int) size); + if (processedSize != IntPtr.Zero) + { + Marshal.WriteInt32(processedSize, (int) size); + } + OnBytesWritten(new IntEventArgs((int) size)); + return 0; + } + + #endregion + + /// + /// Occurs when IntEventArgs.Value bytes were written. + /// + public event EventHandler BytesWritten; + + private void OnBytesWritten(IntEventArgs e) + { + if (BytesWritten != null) + { + BytesWritten(this, e); + } + } + } + + /// + /// Base multi volume stream wrapper class. + /// + internal class MultiStreamWrapper : DisposeVariableWrapper, IDisposable + { + protected readonly Dictionary> StreamOffsets = + new Dictionary>(); + + protected readonly List Streams = new List(); + protected int CurrentStream; + protected long Position; + protected long StreamLength; + + /// + /// Initializes a new instance of the MultiStreamWrapper class. + /// + /// Perform Dispose() if requested to. + protected MultiStreamWrapper(bool dispose) : base(dispose) {} + + /// + /// Gets the total length of input data. + /// + public long Length + { + get + { + return StreamLength; + } + } + + #region IDisposable Members + + /// + /// Cleans up any resources used and fixes file attributes. + /// + public virtual void Dispose() + { + if (DisposeStream) + { + foreach (Stream stream in Streams) + { + try + { + stream.Dispose(); + } + catch (ObjectDisposedException) {} + } + Streams.Clear(); + } + GC.SuppressFinalize(this); + } + + #endregion + + protected static string VolumeNumber(int num) + { + if (num < 10) + { + return ".00" + num.ToString(CultureInfo.InvariantCulture); + } + if (num > 9 && num < 100) + { + return ".0" + num.ToString(CultureInfo.InvariantCulture); + } + if (num > 99 && num < 1000) + { + return "." + num.ToString(CultureInfo.InvariantCulture); + } + return String.Empty; + } + + private int StreamNumberByOffset(long offset) + { + foreach (int number in StreamOffsets.Keys) + { + if (StreamOffsets[number].Key <= offset && + StreamOffsets[number].Value >= offset) + { + return number; + } + } + return -1; + } + + public void Seek(long offset, SeekOrigin seekOrigin, IntPtr newPosition) + { + long absolutePosition = (seekOrigin == SeekOrigin.Current) + ? Position + offset + : offset; + CurrentStream = StreamNumberByOffset(absolutePosition); + long delta = Streams[CurrentStream].Seek( + absolutePosition - StreamOffsets[CurrentStream].Key, SeekOrigin.Begin); + Position = StreamOffsets[CurrentStream].Key + delta; + if (newPosition != IntPtr.Zero) + { + Marshal.WriteInt64(newPosition, Position); + } + } + } + + /// + /// IInStream wrapper used in stream multi volume read operations. + /// + internal sealed class InMultiStreamWrapper : MultiStreamWrapper, ISequentialInStream, IInStream + { + /// + /// Initializes a new instance of the InMultiStreamWrapper class. + /// + /// The archive file name. + /// Perform Dispose() if requested to. + public InMultiStreamWrapper(string fileName, bool dispose) : + base(dispose) + { + string baseName = fileName.Substring(0, fileName.Length - 4); + int i = 0; + while (File.Exists(fileName)) + { + Streams.Add(new FileStream(fileName, FileMode.Open)); + long length = Streams[i].Length; + StreamOffsets.Add(i++, new KeyValuePair(StreamLength, StreamLength + length)); + StreamLength += length; + fileName = baseName + VolumeNumber(i + 1); + } + } + + #region ISequentialInStream Members + + /// + /// Reads data from the stream. + /// + /// A data array. + /// The array size. + /// The read bytes count. + public int Read(byte[] data, uint size) + { + var readSize = (int) size; + int readCount = Streams[CurrentStream].Read(data, 0, readSize); + readSize -= readCount; + Position += readCount; + while (readCount < (int) size) + { + if (CurrentStream == Streams.Count - 1) + { + return readCount; + } + CurrentStream++; + Streams[CurrentStream].Seek(0, SeekOrigin.Begin); + int count = Streams[CurrentStream].Read(data, readCount, readSize); + readCount += count; + readSize -= count; + Position += count; + } + return readCount; + } + + #endregion + } + +#if COMPRESS + /// + /// IOutStream wrapper used in multi volume stream write operations. + /// + internal sealed class OutMultiStreamWrapper : MultiStreamWrapper, ISequentialOutStream, IOutStream + { + private readonly string _archiveName; + private readonly int _volumeSize; + private long _overallLength; + + /// + /// Initializes a new instance of the OutMultiStreamWrapper class. + /// + /// The archive name. + /// The volume size. + public OutMultiStreamWrapper(string archiveName, int volumeSize) : + base(true) + { + _archiveName = archiveName; + _volumeSize = volumeSize; + CurrentStream = -1; + NewVolumeStream(); + } + + #region IOutStream Members + + public int SetSize(long newSize) + { + return 0; + } + + #endregion + + #region ISequentialOutStream Members + + public int Write(byte[] data, uint size, IntPtr processedSize) + { + int offset = 0; + var originalSize = (int) size; + Position += size; + _overallLength = Math.Max(Position + 1, _overallLength); + while (size > _volumeSize - Streams[CurrentStream].Position) + { + var count = (int) (_volumeSize - Streams[CurrentStream].Position); + Streams[CurrentStream].Write(data, offset, count); + size -= (uint) count; + offset += count; + NewVolumeStream(); + } + Streams[CurrentStream].Write(data, offset, (int) size); + if (processedSize != IntPtr.Zero) + { + Marshal.WriteInt32(processedSize, originalSize); + } + return 0; + } + + #endregion + + public override void Dispose() + { + int lastIndex = Streams.Count - 1; + Streams[lastIndex].SetLength(lastIndex > 0? Streams[lastIndex].Position : _overallLength); + base.Dispose(); + } + + private void NewVolumeStream() + { + CurrentStream++; + Streams.Add(File.Create(_archiveName + VolumeNumber(CurrentStream + 1))); + Streams[CurrentStream].SetLength(_volumeSize); + StreamOffsets.Add(CurrentStream, new KeyValuePair(0, _volumeSize - 1)); + } + } +#endif + + internal sealed class FakeOutStreamWrapper : ISequentialOutStream, IDisposable + { + #region IDisposable Members + + public void Dispose() + { + GC.SuppressFinalize(this); + } + + #endregion + + #region ISequentialOutStream Members + + /// + /// Does nothing except calling the BytesWritten event + /// + /// Data array + /// Array size + /// Count of written bytes + /// Zero if Ok + public int Write(byte[] data, uint size, IntPtr processedSize) + { + OnBytesWritten(new IntEventArgs((int) size)); + if (processedSize != IntPtr.Zero) + { + Marshal.WriteInt32(processedSize, (int) size); + } + return 0; + } + + #endregion + + /// + /// Occurs when IntEventArgs.Value bytes were written + /// + public event EventHandler BytesWritten; + + private void OnBytesWritten(IntEventArgs e) + { + if (BytesWritten != null) + { + BytesWritten(this, e); + } + } + } +#endif +} \ No newline at end of file diff --git a/BizHawk.Util/7z/arch/Test.bzip2.7z b/BizHawk.Util/7z/arch/Test.bzip2.7z new file mode 100644 index 0000000000000000000000000000000000000000..cb39ab1b4c9263a0357da544ae2fb6c5bcb16ed1 GIT binary patch literal 149 zcmXr7+Ou9=hJpFV2X8@b1_E&2@^(urzdxR11#0nba8zlwfXPVPIn5VNhUD zY~wMw<9cVJpNNWC#G-HqMiw>(Mow)8c5X%nMrIZ!CLR_B4lYKci@p^M46KZT!VDn{ ksSL#oB@B8%Tmi%k3?f{N4BQJP!}qK{#VE?g2s9N004iY{>2KTSK4Z|5^h(bzuxMapVPjzAE`#=qKpj8A*sbB42&#n42+x{4D8&D42+73j2t{H z3>;jHMi+f67#LU?1%(+x7*ZLE8A=%RfVcvP85l&k7#X-1N`~)QeTq?(jgdhCY%T!z CE)eBc2a1_%g%(&m}D9SkADaqA}EU|?WmVPjzA4!afx0@ UMG3=)?z$`x=ZI}Jg9AGQ09^tSBLDyZ literal 0 HcmV?d00001 diff --git a/BizHawk.Util/7z/arch/Test.tar b/BizHawk.Util/7z/arch/Test.tar new file mode 100644 index 0000000000000000000000000000000000000000..b61b52eab46fbe4612ecbb67f979a5dde114c605 GIT binary patch literal 2048 zcmWGZEiTb3sVHHfAuu#BFgG_>U{C-712h^eXrf?fXl!h1WMFP;ZU_`HH8nR@U@)Me dn?{X>gg^)|{zt=NGz3ONU^E0qLtx~E008Z{4Nw38 literal 0 HcmV?d00001 diff --git a/BizHawk.Util/7z/arch/Test.txt b/BizHawk.Util/7z/arch/Test.txt new file mode 100644 index 0000000000..8318c86b35 --- /dev/null +++ b/BizHawk.Util/7z/arch/Test.txt @@ -0,0 +1 @@ +Test \ No newline at end of file diff --git a/BizHawk.Util/7z/arch/Test.txt.bz2 b/BizHawk.Util/7z/arch/Test.txt.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..142ed3f74e9a84ca054e678bf8cafac98cbb40f9 GIT binary patch literal 43 ycmZ>Y%CIzaj8qGbyqVM)%fP_E+`z)X#K6O#z@XU1V{pgy&O|>E6|;y%;SK=vVhe8o literal 0 HcmV?d00001 diff --git a/BizHawk.Util/7z/arch/Test.txt.gz b/BizHawk.Util/7z/arch/Test.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..f6f5f3346011519dd3228c077a4df0e43fbd2181 GIT binary patch literal 33 ocmb2|=HRI0FZE_(2uUq2(JQGaVc_=E)njBZy69WM!oa`)0E|}$uK)l5 literal 0 HcmV?d00001 diff --git a/BizHawk.Util/7z/arch/Test.txt.xz b/BizHawk.Util/7z/arch/Test.txt.xz new file mode 100644 index 0000000000000000000000000000000000000000..f928831802e4a4a09dcc264d0d820cc3e805115c GIT binary patch literal 56 zcmexsUKJ6=z`&TPbkB^5L6K30fq_Bbe8d?>2Ii2|;t~d. +*/ + +namespace SevenZip.Sdk +{ + internal class CRC + { + public static readonly uint[] Table; + + private uint _value = 0xFFFFFFFF; + + static CRC() + { + Table = new uint[256]; + const uint kPoly = 0xEDB88320; + for (uint i = 0; i < 256; i++) + { + uint r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >> 1) ^ kPoly; + else + r >>= 1; + Table[i] = r; + } + } + + public void Init() + { + _value = 0xFFFFFFFF; + } + + public void UpdateByte(byte b) + { + _value = Table[(((byte) (_value)) ^ b)] ^ (_value >> 8); + } + + public void Update(byte[] data, uint offset, uint size) + { + for (uint i = 0; i < size; i++) + _value = Table[(((byte) (_value)) ^ data[offset + i])] ^ (_value >> 8); + } + + public uint GetDigest() + { + return _value ^ 0xFFFFFFFF; + } + + private static uint CalculateDigest(byte[] data, uint offset, uint size) + { + var crc = new CRC(); + // crc.Init(); + crc.Update(data, offset, size); + return crc.GetDigest(); + } + + private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) + { + return (CalculateDigest(data, offset, size) == digest); + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Common/InBuffer.cs b/BizHawk.Util/7z/sdk/Common/InBuffer.cs new file mode 100644 index 0000000000..26f3ae4104 --- /dev/null +++ b/BizHawk.Util/7z/sdk/Common/InBuffer.cs @@ -0,0 +1,119 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System.IO; + +namespace SevenZip.Sdk.Buffer +{ + /// + /// Implements the input buffer work + /// + internal class InBuffer + { + private readonly byte[] m_Buffer; + private readonly uint m_BufferSize; + private uint m_Limit; + private uint m_Pos; + private ulong m_ProcessedSize; + private Stream m_Stream; + private bool m_StreamWasExhausted; + + /// + /// Initializes the input buffer + /// + /// + private InBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + /// + /// Initializes the class + /// + /// + private void Init(Stream stream) + { + m_Stream = stream; + m_ProcessedSize = 0; + m_Limit = 0; + m_Pos = 0; + m_StreamWasExhausted = false; + } + + /// + /// Reads the whole block + /// + /// + private bool ReadBlock() + { + if (m_StreamWasExhausted) + return false; + m_ProcessedSize += m_Pos; + int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int) m_BufferSize); + m_Pos = 0; + m_Limit = (uint) aNumProcessedBytes; + m_StreamWasExhausted = (aNumProcessedBytes == 0); + return (!m_StreamWasExhausted); + } + + /// + /// Releases the stream + /// + private void ReleaseStream() + { + // m_Stream.Close(); + m_Stream = null; + } + + /// + /// Reads the byte to check it + /// + /// + /// + private bool ReadByte(out byte b) + { + b = 0; + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return false; + b = m_Buffer[m_Pos++]; + return true; + } + + /// + /// Reads the next byte + /// + /// + private byte ReadByte() + { + // return (byte)m_Stream.ReadByte(); + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return 0xFF; + return m_Buffer[m_Pos++]; + } + + /// + /// Gets processed size + /// + /// + private ulong GetProcessedSize() + { + return m_ProcessedSize + m_Pos; + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Common/OutBuffer.cs b/BizHawk.Util/7z/sdk/Common/OutBuffer.cs new file mode 100644 index 0000000000..85117e038d --- /dev/null +++ b/BizHawk.Util/7z/sdk/Common/OutBuffer.cs @@ -0,0 +1,85 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System.IO; + +namespace SevenZip.Sdk.Buffer +{ + internal class OutBuffer + { + private readonly byte[] m_Buffer; + private readonly uint m_BufferSize; + private uint m_Pos; + private ulong m_ProcessedSize; + private Stream m_Stream; + + /// + /// Initializes a new instance of the OutBuffer class + /// + /// + public OutBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void SetStream(Stream stream) + { + m_Stream = stream; + } + + public void FlushStream() + { + m_Stream.Flush(); + } + + public void CloseStream() + { + m_Stream.Close(); + } + + public void ReleaseStream() + { + m_Stream = null; + } + + public void Init() + { + m_ProcessedSize = 0; + m_Pos = 0; + } + + public void WriteByte(byte b) + { + m_Buffer[m_Pos++] = b; + if (m_Pos >= m_BufferSize) + FlushData(); + } + + public void FlushData() + { + if (m_Pos == 0) + return; + m_Stream.Write(m_Buffer, 0, (int) m_Pos); + m_Pos = 0; + } + + public ulong GetProcessedSize() + { + return m_ProcessedSize + m_Pos; + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZ/IMatchFinder.cs b/BizHawk.Util/7z/sdk/Compress/LZ/IMatchFinder.cs new file mode 100644 index 0000000000..d7a792c91e --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZ/IMatchFinder.cs @@ -0,0 +1,40 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; + +namespace SevenZip.Sdk.Compression.LZ +{ + internal interface IInWindowStream + { + void SetStream(Stream inStream); + void Init(); + void ReleaseStream(); + Byte GetIndexByte(Int32 index); + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); + UInt32 GetNumAvailableBytes(); + } + + internal interface IMatchFinder : IInWindowStream + { + void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + + UInt32 GetMatches(UInt32[] distances); + void Skip(UInt32 num); + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZ/LzBinTree.cs b/BizHawk.Util/7z/sdk/Compress/LZ/LzBinTree.cs new file mode 100644 index 0000000000..6669a5b2d5 --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZ/LzBinTree.cs @@ -0,0 +1,405 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; + +namespace SevenZip.Sdk.Compression.LZ +{ + internal class BinTree : InWindow, IMatchFinder + { + private const UInt32 kBT2HashSize = 1 << 16; + private const UInt32 kEmptyHashValue = 0; + private const UInt32 kHash2Size = 1 << 10; + private const UInt32 kHash3Offset = kHash2Size; + private const UInt32 kHash3Size = 1 << 16; + private const UInt32 kMaxValForNormalize = ((UInt32) 1 << 31) - 1; + private const UInt32 kStartMaxLen = 1; + private UInt32 _cutValue = 0xFF; + private UInt32 _cyclicBufferPos; + private UInt32 _cyclicBufferSize; + private UInt32[] _hash; + + private UInt32 _hashMask; + private UInt32 _hashSizeSum; + private UInt32 _matchMaxLen; + + private UInt32[] _son; + + private bool HASH_ARRAY = true; + + private UInt32 kFixHashSize = kHash2Size + kHash3Size; + private UInt32 kMinMatchCheck = 4; + private UInt32 kNumHashDirectBytes; + + #region IMatchFinder Members + + public new void SetStream(Stream stream) + { + base.SetStream(stream); + } + + public new void ReleaseStream() + { + base.ReleaseStream(); + } + + public new void Init() + { + base.Init(); + for (UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public new Byte GetIndexByte(Int32 index) + { + return base.GetIndexByte(index); + } + + public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { + return base.GetMatchLen(index, distance, limit); + } + + public new UInt32 GetNumAvailableBytes() + { + return base.GetNumAvailableBytes(); + } + + public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) + { + if (historySize + 256 > kMaxValForNormalize) + { + throw new ArgumentException("historySize + 256 > kMaxValForNormalize", "historySize"); + } + _cutValue = 16 + (matchMaxLen >> 1); + + UInt32 windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter)/2 + 256; + + base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + UInt32 cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize)*2]; + + UInt32 hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new UInt32[_hashSizeSum = hs]; + } + + public UInt32 GetMatches(UInt32[] distances) + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + UInt32 offset = 0; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + UInt32 hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + hash2Value = (temp & (((int) kHash2Size) - 1)); + temp ^= (uint) ((_bufferBase[cur + 2]) << 8); + hash3Value = (temp & (((int) kHash3Size) - 1)); + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32) (_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + UInt32 curMatch2 = _hash[hash2Value]; + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + UInt32 count = _cutValue; + + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) + ? + (_cyclicBufferPos - delta) + : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(UInt32 num) + { + do + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + + UInt32 hashValue; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + UInt32 hash2Value = (temp & (((int) kHash2Size) - 1)); + _hash[hash2Value] = _pos; + temp ^= ((UInt32) (_bufferBase[cur + 2]) << 8); + UInt32 hash3Value = (temp & (((int) kHash3Size) - 1)); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32) (_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + UInt32 count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) + ? + (_cyclicBufferPos - delta) + : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } while (--num != 0); + } + + #endregion + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + public new void MovePos() + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + base.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + private static void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) + { + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + private void Normalize() + { + UInt32 subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize*2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets((Int32) subValue); + } + + //public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZ/LzInWindow.cs b/BizHawk.Util/7z/sdk/Compress/LZ/LzInWindow.cs new file mode 100644 index 0000000000..8cb05038da --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZ/LzInWindow.cs @@ -0,0 +1,197 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ +using System; +using System.IO; + +namespace SevenZip.Sdk.Compression.LZ +{ + /// + /// Input window class + /// + internal class InWindow + { + /// + /// Size of Allocated memory block + /// + public UInt32 _blockSize; + + /// + /// The pointer to buffer with data + /// + public Byte[] _bufferBase; + + /// + /// Buffer offset value + /// + public UInt32 _bufferOffset; + + /// + /// How many BYTEs must be kept buffer after _pos + /// + private UInt32 _keepSizeAfter; + + /// + /// How many BYTEs must be kept in buffer before _pos + /// + private UInt32 _keepSizeBefore; + + private UInt32 _pointerToLastSafePosition; + + /// + /// Offset (from _buffer) of curent byte + /// + public UInt32 _pos; + + private UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + private Stream _stream; + private bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + /// + /// Offset (from _buffer) of first not read byte from Stream + /// + public UInt32 _streamPos; + + public void MoveBlock() + { + UInt32 offset = (_bufferOffset) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + UInt32 numBytes = (_bufferOffset) + _streamPos - offset; + + // check negative offset ???? + for (UInt32 i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public virtual void ReadBlock() + { + if (_streamEndWasReached) + return; + while (true) + { + var size = (int) ((0 - _bufferOffset) + _blockSize - _streamPos); + if (size == 0) + return; + int numReadBytes = _stream.Read(_bufferBase, (int) (_bufferOffset + _streamPos), size); + if (numReadBytes == 0) + { + _posLimit = _streamPos; + UInt32 pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = (_pointerToLastSafePosition - _bufferOffset); + + _streamEndWasReached = true; + return; + } + _streamPos += (UInt32) numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + private void Free() + { + _bufferBase = null; + } + + public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new Byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(Stream stream) + { + _stream = stream; + } + + public void ReleaseStream() + { + _stream = null; + } + + public void Init() + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() + { + _pos++; + if (_pos > _posLimit) + { + UInt32 pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public Byte GetIndexByte(Int32 index) + { + return _bufferBase[_bufferOffset + _pos + index]; + } + + /// + /// index + limit have not to exceed _keepSizeAfter + /// + /// + /// + /// + /// + public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (UInt32) (_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + UInt32 pby = _bufferOffset + _pos + (UInt32) index; + + UInt32 i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++) ; + return i; + } + + public UInt32 GetNumAvailableBytes() + { + return _streamPos - _pos; + } + + public void ReduceOffsets(Int32 subValue) + { + _bufferOffset += (UInt32) subValue; + _posLimit -= (UInt32) subValue; + _pos -= (UInt32) subValue; + _streamPos -= (UInt32) subValue; + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZ/LzOutWindow.cs b/BizHawk.Util/7z/sdk/Compress/LZ/LzOutWindow.cs new file mode 100644 index 0000000000..6cf788ad06 --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZ/LzOutWindow.cs @@ -0,0 +1,125 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System.IO; + +namespace SevenZip.Sdk.Compression.LZ +{ + internal class OutWindow + { + private byte[] _buffer; + private uint _pos; + private Stream _stream; + private uint _streamPos; + private uint _windowSize; + public uint TrainSize; + + public void Create(uint windowSize) + { + if (_windowSize != windowSize) + { + // System.GC.Collect(); + _buffer = new byte[windowSize]; + } + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void Init(Stream stream, bool solid) + { + ReleaseStream(); + _stream = stream; + if (!solid) + { + _streamPos = 0; + _pos = 0; + TrainSize = 0; + } + } + + public bool Train(Stream stream) + { + long len = stream.Length; + uint size = (len < _windowSize) ? (uint) len : _windowSize; + TrainSize = size; + stream.Position = len - size; + _streamPos = _pos = 0; + while (size > 0) + { + uint curSize = _windowSize - _pos; + if (size < curSize) + curSize = size; + int numReadBytes = stream.Read(_buffer, (int) _pos, (int) curSize); + if (numReadBytes == 0) + return false; + size -= (uint) numReadBytes; + _pos += (uint) numReadBytes; + _streamPos += (uint) numReadBytes; + if (_pos == _windowSize) + _streamPos = _pos = 0; + } + return true; + } + + public void ReleaseStream() + { + Flush(); + _stream = null; + } + + public void Flush() + { + uint size = _pos - _streamPos; + if (size == 0) + return; + _stream.Write(_buffer, (int) _streamPos, (int) size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(uint distance, uint len) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + for (; len > 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(uint distance) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaBase.cs b/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaBase.cs new file mode 100644 index 0000000000..cba427c016 --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaBase.cs @@ -0,0 +1,108 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +namespace SevenZip.Sdk.Compression.Lzma +{ + internal abstract class Base + { + public const uint kAlignMask = (kAlignTableSize - 1); + public const uint kAlignTableSize = 1 << kNumAlignBits; + public const int kDicLogSizeMin = 0; + public const uint kEndPosModelIndex = 14; + public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; + // public const int kDicLogSizeMax = 30; + // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; + + public const uint kMatchMinLen = 2; + + public const int kNumAlignBits = 4; + + public const uint kNumFullDistances = 1 << ((int) kEndPosModelIndex/2); + public const int kNumHighLenBits = 8; + + public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + + public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + public const int kNumLenToPosStatesBits = 2; // it's for speed optimization + + public const uint kNumLitContextBitsMax = 8; + public const uint kNumLitPosStatesBitsEncodingMax = 4; + + public const int kNumLowLenBits = 3; + public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; + public const int kNumMidLenBits = 3; + public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; + public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + public const int kNumPosSlotBits = 6; + public const int kNumPosStatesBitsEncodingMax = 4; + public const int kNumPosStatesBitsMax = 4; + public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public const uint kNumRepDistances = 4; + public const uint kNumStates = 12; + public const uint kStartPosModelIndex = 4; + + public static uint GetLenToPosState(uint len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (kNumLenToPosStates - 1); + } + + #region Nested type: State + + public struct State + { + public uint Index; + + public void Init() + { + Index = 0; + } + + public void UpdateChar() + { + if (Index < 4) Index = 0; + else if (Index < 10) Index -= 3; + else Index -= 6; + } + + public void UpdateMatch() + { + Index = (uint) (Index < 7 ? 7 : 10); + } + + public void UpdateRep() + { + Index = (uint) (Index < 7 ? 8 : 11); + } + + public void UpdateShortRep() + { + Index = (uint) (Index < 7 ? 9 : 11); + } + + public bool IsCharState() + { + return Index < 7; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaDecoder.cs b/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaDecoder.cs new file mode 100644 index 0000000000..f3f993d488 --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaDecoder.cs @@ -0,0 +1,480 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; +using SevenZip.Sdk.Compression.LZ; +using SevenZip.Sdk.Compression.RangeCoder; + +namespace SevenZip.Sdk.Compression.Lzma +{ + /// + /// The LZMA decoder class + /// + public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream + { + private readonly BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + private readonly BitDecoder[] m_IsRep0LongDecoders = + new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + private readonly BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; + private readonly BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; + private readonly BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; + private readonly BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; + + private readonly LenDecoder m_LenDecoder = new LenDecoder(); + + private readonly LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + private readonly OutWindow m_OutWindow = new OutWindow(); + private readonly BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + private readonly BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + private readonly RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); + private readonly LenDecoder m_RepLenDecoder = new LenDecoder(); + private bool _solid; + + private uint m_DictionarySize; + private uint m_DictionarySizeCheck; + private BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + private uint m_PosStateMask; + + /// + /// Initializes the Lzma Decoder class. + /// + public Decoder() + { + m_DictionarySize = 0xFFFFFFFF; + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + #region ICoder Members + + /// + /// Codes a stream with LZMA algorithm to an output stream + /// + /// The input stream + /// The input size + /// The output size + /// The output stream + /// Progress interface + public void Code(Stream inStream, Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + Init(inStream, outStream); + + var state = new Base.State(); + state.Init(); + uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + UInt64 nowPos64 = 0; + var outSize64 = (UInt64) outSize; + if (nowPos64 < outSize64) + { + if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) + throw new DataErrorException(); + state.UpdateChar(); + byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); + m_OutWindow.PutByte(b); + nowPos64++; + } + while (nowPos64 < outSize64) + { + // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); + // while(nowPos64 < next) + { + uint posState = (uint) nowPos64 & m_PosStateMask; + if ( + m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == + 0) + { + byte b; + byte prevByte = m_OutWindow.GetByte(0); + if (!state.IsCharState()) + b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, + (uint) nowPos64, prevByte, + m_OutWindow.GetByte(rep0)); + else + b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint) nowPos64, prevByte); + m_OutWindow.PutByte(b); + state.UpdateChar(); + nowPos64++; + } + else + { + uint len; + if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) + { + if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + if ( + m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode( + m_RangeDecoder) == 0) + { + state.UpdateShortRep(); + m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); + nowPos64++; + continue; + } + } + else + { + UInt32 distance; + if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + distance = rep1; + } + else + { + if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state.UpdateRep(); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state.UpdateMatch(); + uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + var numDirectBits = (int) ((posSlot >> 1) - 1); + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, + numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + } + } + else + rep0 = posSlot; + } + if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) + { + if (rep0 == 0xFFFFFFFF) + break; + throw new DataErrorException(); + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + } + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + } + + #endregion + + #region ISetDecoderProperties Members + + /// + /// Sets decoder properties + /// + /// Array of byte properties + public void SetDecoderProperties(byte[] properties) + { + if (properties.Length < 5) + throw new InvalidParamException(); + int lc = properties[0]%9; + int remainder = properties[0]/9; + int lp = remainder%5; + int pb = remainder/5; + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + UInt32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UInt32) (properties[1 + i])) << (i*8); + SetDictionarySize(dictionarySize); + SetLiteralProperties(lp, lc); + SetPosBitsProperties(pb); + } + + #endregion + + private void SetDictionarySize(uint dictionarySize) + { + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); + uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); + m_OutWindow.Create(blockSize); + } + } + + private void SetLiteralProperties(int lp, int lc) + { + if (lp > 8) + throw new InvalidParamException(); + if (lc > 8) + throw new InvalidParamException(); + m_LiteralDecoder.Create(lp, lc); + } + + private void SetPosBitsProperties(int pb) + { + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + uint numPosStates = (uint) 1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + } + + private void Init(Stream inStream, Stream outStream) + { + m_RangeDecoder.Init(inStream); + m_OutWindow.Init(outStream, _solid); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= m_PosStateMask; j++) + { + uint index = (i << Base.kNumPosStatesBitsMax) + j; + m_IsMatchDecoders[index].Init(); + m_IsRep0LongDecoders[index].Init(); + } + m_IsRepDecoders[i].Init(); + m_IsRepG0Decoders[i].Init(); + m_IsRepG1Decoders[i].Init(); + m_IsRepG2Decoders[i].Init(); + } + + m_LiteralDecoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + // m_PosSpecDecoder.Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + m_PosDecoders[i].Init(); + + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + } + + /// + /// Trains a stream + /// + /// The stream to train. + /// true if Ok; otherwise, false. + public bool Train(Stream stream) + { + _solid = true; + return m_OutWindow.Train(stream); + } + + #region Nested type: LenDecoder + + private class LenDecoder + { + private readonly BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + private readonly BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + private BitDecoder m_Choice; + private BitDecoder m_Choice2; + private BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + private uint m_NumPosStates; + + internal void Create(uint numPosStates) + { + for (uint posState = m_NumPosStates; posState < numPosStates; posState++) + { + m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); + } + m_NumPosStates = numPosStates; + } + + internal void Init() + { + m_Choice.Init(); + for (uint posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_Choice2.Init(); + m_HighCoder.Init(); + } + + /// + /// Decodes the stream + /// + /// The specified RangeCoder + /// The position state + /// + public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) + { + if (m_Choice.Decode(rangeDecoder) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + else + { + uint symbol = Base.kNumLowLenSymbols; + if (m_Choice2.Decode(rangeDecoder) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + { + symbol += Base.kNumMidLenSymbols; + symbol += m_HighCoder.Decode(rangeDecoder); + } + return symbol; + } + } + } + + #endregion + + #region Nested type: LiteralDecoder + + private class LiteralDecoder + { + private Decoder2[] m_Coders; + private int m_NumPosBits; + private int m_NumPrevBits; + private uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && + m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint) 1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint) 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint) 1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + private uint GetState(uint pos, byte prevByte) + { + return ((pos & m_PosMask) << m_NumPrevBits) + (uint) (prevByte >> (8 - m_NumPrevBits)); + } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) + { + return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); + } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) + { + return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); + } + + #region Nested type: Decoder2 + + private struct Decoder2 + { + private BitDecoder[] m_Decoders; + + public void Create() + { + m_Decoders = new BitDecoder[0x300]; + } + + public void Init() + { + for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); + } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) + { + uint symbol = 1; + do + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); + return (byte) symbol; + } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) + { + uint symbol = 1; + do + { + uint matchBit = (uint) (matchByte >> 7) & 1; + matchByte <<= 1; + uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + break; + } + } while (symbol < 0x100); + return (byte) symbol; + } + } + + #endregion + } ; + + #endregion + + /* + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return true; }} + public override bool CanSeek { get { return true; }} + public override long Length { get { return 0; }} + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + public override void Write(byte[] buffer, int offset, int count) + { + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + return 0; + } + public override void SetLength(long value) {} + */ + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaEncoder.cs b/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaEncoder.cs new file mode 100644 index 0000000000..cf3e528e91 --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/LZMA/LzmaEncoder.cs @@ -0,0 +1,1587 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.Globalization; +using System.IO; +using SevenZip.Sdk.Compression.LZ; +using SevenZip.Sdk.Compression.RangeCoder; + +namespace SevenZip.Sdk.Compression.Lzma +{ + /// + /// The LZMA encoder class + /// + public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + { + private const int kDefaultDictionaryLogSize = 22; + private const UInt32 kIfinityPrice = 0xFFFFFFF; + private const UInt32 kNumFastBytesDefault = 0x20; + + private const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + private const UInt32 kNumOpts = 1 << 12; + private const int kPropSize = 5; + private static readonly Byte[] g_FastPos = new Byte[1 << 11]; + + private static readonly string[] kMatchFinderIDs = + { + "BT2", + "BT4", + }; + + private readonly UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; + private readonly UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; + + private readonly BitEncoder[] _isMatch = new BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + private readonly BitEncoder[] _isRep = new BitEncoder[Base.kNumStates]; + private readonly BitEncoder[] _isRep0Long = new BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + private readonly BitEncoder[] _isRepG0 = new BitEncoder[Base.kNumStates]; + private readonly BitEncoder[] _isRepG1 = new BitEncoder[Base.kNumStates]; + private readonly BitEncoder[] _isRepG2 = new BitEncoder[Base.kNumStates]; + + private readonly LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); + + private readonly LiteralEncoder _literalEncoder = new LiteralEncoder(); + + private readonly UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen*2 + 2]; + private readonly Optimal[] _optimum = new Optimal[kNumOpts]; + private readonly BitEncoder[] _posEncoders = new BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + private readonly BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; + + private readonly UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; + private readonly RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); + private readonly UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; + private readonly LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); + private readonly Byte[] properties = new Byte[kPropSize]; + private readonly UInt32[] repLens = new UInt32[Base.kNumRepDistances]; + private readonly UInt32[] reps = new UInt32[Base.kNumRepDistances]; + private readonly UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; + private UInt32 _additionalOffset; + private UInt32 _alignPriceCount; + + private UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); + private UInt32 _dictionarySizePrev = 0xFFFFFFFF; + private UInt32 _distTableSize = (kDefaultDictionaryLogSize*2); + private bool _finished; + private Stream _inStream; + private UInt32 _longestMatchLength; + private bool _longestMatchWasFound; + private IMatchFinder _matchFinder; + + private EMatchFinderType _matchFinderType = EMatchFinderType.BT4; + private UInt32 _matchPriceCount; + + private bool _needReleaseMFStream; + private UInt32 _numDistancePairs; + private UInt32 _numFastBytes = kNumFastBytesDefault; + private UInt32 _numFastBytesPrev = 0xFFFFFFFF; + private int _numLiteralContextBits = 3; + private int _numLiteralPosStateBits; + private UInt32 _optimumCurrentIndex; + private UInt32 _optimumEndIndex; + private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); + private int _posStateBits = 2; + private UInt32 _posStateMask = (4 - 1); + private Byte _previousByte; + private Base.State _state; + private uint _trainSize; + private bool _writeEndMark; + private Int64 nowPos64; + + static Encoder() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = ((UInt32) 1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } + + /// + /// Initializes a new instance of the Encoder class + /// + public Encoder() + { + for (int i = 0; i < kNumOpts; i++) + _optimum[i] = new Optimal(); + for (int i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); + } + + #region ICoder Members + + /// + /// Codes the specified stream + /// + /// The input stream + /// The input size + /// The output size + /// The output stream + /// The progress callback + public void Code(Stream inStream, Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream /*, inSize, outSize*/); + while (true) + { + Int64 processedInSize; + Int64 processedOutSize; + bool finished; + CodeOneBlock(out processedInSize, out processedOutSize, out finished); + if (finished) + return; + if (progress != null) + { + progress.SetProgress(processedInSize, processedOutSize); + } + } + } + finally + { + ReleaseStreams(); + } + } + + #endregion + + #region ISetCoderProperties Members + + /// + /// Sets the coder properties + /// + /// The property identificators + /// The array of properties + public void SetCoderProperties(CoderPropId[] propIDs, object[] properties) + { + for (UInt32 i = 0; i < properties.Length; i++) + { + object prop = properties[i]; + switch (propIDs[i]) + { + case CoderPropId.NumFastBytes: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + var numFastBytes = (Int32) prop; + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + throw new InvalidParamException(); + _numFastBytes = (UInt32) numFastBytes; + break; + } + case CoderPropId.Algorithm: + { + /* + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 maximize = (Int32)prop; + _fastMode = (maximize == 0); + _maxMode = (maximize >= 2); + */ + break; + } + case CoderPropId.MatchFinder: + { + if (!(prop is String)) + throw new InvalidParamException(); + EMatchFinderType matchFinderIndexPrev = _matchFinderType; + int m = FindMatchFinder(((string) prop).ToUpper(CultureInfo.CurrentCulture)); + if (m < 0) + throw new InvalidParamException(); + _matchFinderType = (EMatchFinderType) m; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = 0xFFFFFFFF; + _matchFinder = null; + } + break; + } + case CoderPropId.DictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (!(prop is Int32)) + throw new InvalidParamException(); + ; + var dictionarySize = (Int32) prop; + if (dictionarySize < (UInt32) (1 << Base.kDicLogSizeMin) || + dictionarySize > (UInt32) (1 << kDicLogSizeMaxCompress)) + throw new InvalidParamException(); + _dictionarySize = (UInt32) dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dicLogSize < (UInt32) kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= ((UInt32) (1) << dicLogSize)) + break; + _distTableSize = (UInt32) dicLogSize*2; + break; + } + case CoderPropId.PosStateBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + var v = (Int32) prop; + if (v < 0 || v > (UInt32) Base.kNumPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _posStateBits = v; + _posStateMask = (((UInt32) 1) << _posStateBits) - 1; + break; + } + case CoderPropId.LitPosBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + var v = (Int32) prop; + if (v < 0 || v > Base.kNumLitPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _numLiteralPosStateBits = v; + break; + } + case CoderPropId.LitContextBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + var v = (Int32) prop; + if (v < 0 || v > Base.kNumLitContextBitsMax) + throw new InvalidParamException(); + ; + _numLiteralContextBits = v; + break; + } + case CoderPropId.EndMarker: + { + if (!(prop is Boolean)) + throw new InvalidParamException(); + SetWriteEndMarkerMode((Boolean) prop); + break; + } + default: + throw new InvalidParamException(); + } + } + } + + #endregion + + #region IWriteCoderProperties Members + + /// + /// Writes the coder properties + /// + /// The output stream to write the properties to. + public void WriteCoderProperties(Stream outStream) + { + properties[0] = (Byte) ((_posStateBits*5 + _numLiteralPosStateBits)*9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (Byte) (_dictionarySize >> (8*i)); + outStream.Write(properties, 0, kPropSize); + } + + #endregion + + private static UInt32 GetPosSlot(UInt32 pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (UInt32) (g_FastPos[pos >> 10] + 20); + return (UInt32) (g_FastPos[pos >> 20] + 40); + } + + private static UInt32 GetPosSlot2(UInt32 pos) + { + if (pos < (1 << 17)) + return (UInt32) (g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (UInt32) (g_FastPos[pos >> 16] + 32); + return (UInt32) (g_FastPos[pos >> 26] + 52); + } + + private void BaseInit() + { + _state.Init(); + _previousByte = 0; + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + private void Create() + { + if (_matchFinder == null) + { + var bt = new BinTree(); + int numHashBytes = 4; + if (_matchFinderType == EMatchFinderType.BT2) + numHashBytes = 2; + bt.SetType(numHashBytes); + _matchFinder = bt; + } + _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return; + _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + } + + private void SetWriteEndMarkerMode(bool writeEndMarker) + { + _writeEndMark = writeEndMarker; + } + + private void Init() + { + BaseInit(); + _rangeEncoder.Init(); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= _posStateMask; j++) + { + uint complexState = (i << Base.kNumPosStatesBitsMax) + j; + _isMatch[complexState].Init(); + _isRep0Long[complexState].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + _literalEncoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + _posEncoders[i].Init(); + + _lenEncoder.Init((UInt32) 1 << _posStateBits); + _repMatchLenEncoder.Init((UInt32) 1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + } + + private void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) + { + lenRes = 0; + numDistancePairs = _matchFinder.GetMatches(_matchDistances); + if (numDistancePairs > 0) + { + lenRes = _matchDistances[numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int) lenRes - 1, _matchDistances[numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + } + + + private void MovePos(UInt32 num) + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + private UInt32 GetRepLen1Price(Base.State state, UInt32 posState) + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); + } + + private UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) + { + UInt32 price; + if (repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + + private UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) + { + UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + private UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) + { + UInt32 price; + UInt32 lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState*Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + private UInt32 Backward(out UInt32 backRes, UInt32 cur) + { + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + + private UInt32 GetOptimum(UInt32 position, out UInt32 backRes) + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + ReadMatchDistances(out lenMain, out numDistancePairs); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = 0xFFFFFFFF; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + UInt32 repMaxIndex = 0; + + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + UInt32 lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + Byte currentByte = _matchFinder.GetIndexByte(0 - 1); + Byte matchByte = _matchFinder.GetIndexByte((Int32) (0 - _repDistances[0] - 1 - 1)); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = 0xFFFFFFFF; + return 1; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), + matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if (matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; while (len >= 2); + + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } while (--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (;; len++) + { + UInt32 distance = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(out backRes, cur); + UInt32 newLen; + ReadMatchDistances(out newLen, out numDistancePairs); + if (newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(out backRes, cur); + } + position++; + UInt32 posPrev = _optimum[cur].PosPrev; + Base.State state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state.UpdateRep(); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + UInt32 curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte((Int32) (0 - reps[0] - 1 - 1)); + + posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!state.IsCharState(), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.Min(((int) kNumOpts) - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext]. + GetPrice1() + + _isRep[state2.Index].GetPrice1(); + { + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + + for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + UInt32 lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32) lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32) lenTest - 1 - 1)).GetPrice + (true, + _matchFinder.GetIndexByte(((Int32) lenTest - 1 - (Int32) (reps[repIndex] + 1))), + _matchFinder.GetIndexByte((Int32) lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext] + .GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (UInt32 lenTest = startLen;; lenTest++) + { + UInt32 curBack = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32) lenTest, curBack, t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[ + (state2.Index << Base.kNumPosStatesBitsMax) + + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte( + (Int32) lenTest - 1 - 1)) + . + GetPrice(true, + _matchFinder.GetIndexByte((Int32) lenTest - + (Int32) + (curBack + 1) - 1), + _matchFinder.GetIndexByte((Int32) lenTest - + 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + + _isMatch[ + (state2.Index << Base.kNumPosStatesBitsMax) + + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + UInt32 offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + /*static bool ChangePair(UInt32 smallDist, UInt32 bigDist) + { + const int kDif = 7; + return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); + }*/ + + private void WriteEndMarker(UInt32 posState) + { + if (!_writeEndMark) + return; + + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + UInt32 posReduced = (((UInt32) 1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + private void Flush(UInt32 nowPos) + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + internal void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) + { + inSize = 0; + outSize = 0; + finished = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + if (_trainSize > 0) + _matchFinder.Skip(_trainSize); + } + + if (_finished) + return; + _finished = true; + + + Int64 progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32) nowPos64); + return; + } + UInt32 len, numDistancePairs; // it's not used + ReadMatchDistances(out len, out numDistancePairs); + UInt32 posState = (UInt32) (nowPos64) & _posStateMask; + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder.GetIndexByte((Int32) (0 - _additionalOffset)); + _literalEncoder.GetSubCoder((UInt32) (nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32) nowPos64); + return; + } + while (true) + { + UInt32 pos; + UInt32 len = GetOptimum((UInt32) nowPos64, out pos); + + UInt32 posState = ((UInt32) nowPos64) & _posStateMask; + UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[complexState].Encode(_rangeEncoder, 0); + Byte curByte = _matchFinder.GetIndexByte((Int32) (0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32) nowPos64, _previousByte); + if (!_state.IsCharState()) + { + Byte matchByte = + _matchFinder.GetIndexByte((Int32) (0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state.UpdateChar(); + } + else + { + _isMatch[complexState].Encode(_rangeEncoder, 1); + if (pos < Base.kNumRepDistances) + { + _isRep[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 0) + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 0); + if (len == 1) + _isRep0Long[complexState].Encode(_rangeEncoder, 0); + else + _isRep0Long[complexState].Encode(_rangeEncoder, 1); + } + else + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); + } + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state.UpdateRep(); + } + UInt32 distance = _repDistances[pos]; + if (pos != 0) + { + for (UInt32 i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + var footerBits = (int) ((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, + posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, + footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + UInt32 distance = pos; + for (Int32 i = ((int) Base.kNumRepDistances) - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte((Int32) (len - 1 - _additionalOffset)); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize = nowPos64; + outSize = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32) nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished = false; + return; + } + } + } + } + + private void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + private void SetOutStream(Stream outStream) + { + _rangeEncoder.SetStream(outStream); + } + + private void ReleaseOutStream() + { + _rangeEncoder.ReleaseStream(); + } + + private void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + private void SetStreams(Stream inStream, Stream outStream /*, + Int64 inSize, Int64 outSize*/) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables((UInt32) 1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables((UInt32) 1 << _posStateBits); + + nowPos64 = 0; + } + + private void FillDistancesPrices() + { + for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + var footerBits = (int) ((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + UInt32 st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << + BitEncoder.kNumBitPriceShiftBits); + + UInt32 st2 = lenToPosState*Base.kNumFullDistances; + UInt32 i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + private void FillAlignPrices() + { + for (UInt32 i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + private static int FindMatchFinder(string s) + { + for (int m = 0; m < kMatchFinderIDs.Length; m++) + if (s == kMatchFinderIDs[m]) + return m; + return -1; + } + + #region Nested type: EMatchFinderType + + private enum EMatchFinderType + { + BT2, + BT4, + } ; + + #endregion + + #region Nested type: LenEncoder + + private class LenEncoder + { + private readonly BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + private readonly BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + private BitEncoder _choice; + private BitEncoder _choice2; + private BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); + + public LenEncoder() + { + for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(UInt32 numPosStates) + { + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + if (symbol < Base.kNumLowLenSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + _choice.Encode(rangeEncoder, 1); + if (symbol < Base.kNumMidLenSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) + { + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + } ; + + #endregion + + #region Nested type: LenPriceTableEncoder + + private class LenPriceTableEncoder : LenEncoder + { + private readonly UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; + private readonly UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; + private UInt32 _tableSize; + + public void SetTableSize(UInt32 tableSize) + { + _tableSize = tableSize; + } + + public UInt32 GetPrice(UInt32 symbol, UInt32 posState) + { + return _prices[posState*Base.kNumLenSymbols + symbol]; + } + + private void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices, posState*Base.kNumLenSymbols); + _counters[posState] = _tableSize; + } + + public void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + + public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + base.Encode(rangeEncoder, symbol, posState); + if (--_counters[posState] == 0) + UpdateTable(posState); + } + } + + #endregion + + #region Nested type: LiteralEncoder + + private class LiteralEncoder + { + private Encoder2[] m_Coders; + private int m_NumPosBits; + private int m_NumPrevBits; + private uint m_PosMask; + + internal void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint) 1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint) 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + internal void Init() + { + uint numStates = (uint) 1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + internal Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) + { + return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint) (prevByte >> (8 - m_NumPrevBits))]; + } + + #region Nested type: Encoder2 + + public struct Encoder2 + { + private BitEncoder[] m_Encoders; + + public void Create() + { + m_Encoders = new BitEncoder[0x300]; + } + + public void Init() + { + for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); + } + + public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) + { + uint context = 1; + for (int i = 7; i >= 0; i--) + { + var bit = (uint) ((symbol >> i) & 1); + m_Encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) + { + uint context = 1; + bool same = true; + for (int i = 7; i >= 0; i--) + { + var bit = (uint) ((symbol >> i) & 1); + uint state = context; + if (same) + { + var matchBit = (uint) ((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + m_Encoders[state].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public uint GetPrice(bool matchMode, byte matchByte, byte symbol) + { + uint price = 0; + uint context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + uint matchBit = (uint) (matchByte >> i) & 1; + uint bit = (uint) (symbol >> i) & 1; + price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + uint bit = (uint) (symbol >> i) & 1; + price += m_Encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; + } + } + + #endregion + } + + #endregion + + #region Nested type: Optimal + + private class Optimal + { + public UInt32 BackPrev; + public UInt32 BackPrev2; + + public UInt32 Backs0; + public UInt32 Backs1; + public UInt32 Backs2; + public UInt32 Backs3; + public UInt32 PosPrev; + public UInt32 PosPrev2; + public bool Prev1IsChar; + public bool Prev2; + public UInt32 Price; + public Base.State State; + + public void MakeAsChar() + { + BackPrev = 0xFFFFFFFF; + Prev1IsChar = false; + } + + public void MakeAsShortRep() + { + BackPrev = 0; + ; + Prev1IsChar = false; + } + + public bool IsShortRep() + { + return (BackPrev == 0); + } + } ; + + #endregion + + internal void SetTrainSize(uint trainSize) + { + _trainSize = trainSize; + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoder.cs b/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoder.cs new file mode 100644 index 0000000000..b371fe34ce --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoder.cs @@ -0,0 +1,249 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; + +namespace SevenZip.Sdk.Compression.RangeCoder +{ + internal class Encoder + { + public const uint kTopValue = (1 << 24); + private byte _cache; + private uint _cacheSize; + + public UInt64 Low; + public uint Range; + + private long StartPosition; + private Stream Stream; + + public void SetStream(Stream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + StartPosition = Stream.Position; + + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() + { + Stream.Flush(); + } + + /*public void CloseStream() + { + Stream.Close(); + }*/ + + /*public void Encode(uint start, uint size, uint total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + }*/ + + public void ShiftLow() + { + if ((uint) Low < 0xFF000000 || (uint) (Low >> 32) == 1) + { + byte temp = _cache; + do + { + Stream.WriteByte((byte) (temp + (Low >> 32))); + temp = 0xFF; + } while (--_cacheSize != 0); + _cache = (byte) (((uint) Low) >> 24); + } + _cacheSize++; + Low = ((uint) Low) << 8; + } + + public void EncodeDirectBits(uint v, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((v >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + /*public void EncodeBit(uint size0, int numTotalBits, uint symbol) + { + uint newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + }*/ + + public long GetProcessedSizeAdd() + { + return _cacheSize + + Stream.Position - StartPosition + 4; + // (long)Stream.GetProcessedSize(); + } + } + + internal class Decoder + { + public const uint kTopValue = (1 << 24); + public uint Code; + public uint Range; + // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); + public Stream Stream; + + public void Init(Stream stream) + { + // Stream.Init(stream); + Stream = stream; + + Code = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | (byte) Stream.ReadByte(); + } + + public void ReleaseStream() + { + // Stream.ReleaseStream(); + Stream = null; + } + + /*public void CloseStream() + { + Stream.Close(); + }*/ + + /*public void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + }*/ + + /*public void Normalize2() + { + if (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + }*/ + + /*public uint GetThreshold(uint total) + { + return Code / (Range /= total); + }*/ + + /*public void Decode(uint start, uint size, uint total) + { + Code -= start * Range; + Range *= size; + Normalize(); + }*/ + + public uint DecodeDirectBits(int numTotalBits) + { + uint range = Range; + uint code = Code; + uint result = 0; + for (int i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + uint t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | (byte) Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + /*public uint DecodeBit(uint size0, int numTotalBits) + { + uint newBound = (Range >> numTotalBits) * size0; + uint symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + }*/ + + // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBit.cs b/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBit.cs new file mode 100644 index 0000000000..48fa6db98f --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBit.cs @@ -0,0 +1,146 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; + +namespace SevenZip.Sdk.Compression.RangeCoder +{ + internal struct BitEncoder + { + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + public const int kNumBitModelTotalBits = 11; + public const int kNumBitPriceShiftBits = 6; + private const int kNumMoveBits = 5; + private const int kNumMoveReducingBits = 2; + private static readonly UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; + + private uint Prob; + + static BitEncoder() + { + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = (UInt32) 1 << (kNumBits - i - 1); + UInt32 end = (UInt32) 1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = ((UInt32) i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + } + + public void Init() + { + Prob = kBitModelTotal >> 1; + } + + /*public void UpdateModel(uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + else + Prob -= (Prob) >> kNumMoveBits; + }*/ + + public void Encode(Encoder encoder, uint symbol) + { + // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); + // UpdateModel(symbol); + uint newBound = (encoder.Range >> kNumBitModelTotalBits)*Prob; + if (symbol == 0) + { + encoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + } + else + { + encoder.Low += newBound; + encoder.Range -= newBound; + Prob -= (Prob) >> kNumMoveBits; + } + if (encoder.Range < Encoder.kTopValue) + { + encoder.Range <<= 8; + encoder.ShiftLow(); + } + } + + public uint GetPrice(uint symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-(int) symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + + public uint GetPrice0() + { + return ProbPrices[Prob >> kNumMoveReducingBits]; + } + + public uint GetPrice1() + { + return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; + } + } + + internal struct BitDecoder + { + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + public const int kNumBitModelTotalBits = 11; + private const int kNumMoveBits = 5; + + private uint Prob; + + /*public void UpdateModel(int numMoveBits, uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + }*/ + + public void Init() + { + Prob = kBitModelTotal >> 1; + } + + public uint Decode(Decoder rangeDecoder) + { + uint newBound = (rangeDecoder.Range >> kNumBitModelTotalBits)*Prob; + if (rangeDecoder.Code < newBound) + { + rangeDecoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte) rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 0; + } + else + { + rangeDecoder.Range -= newBound; + rangeDecoder.Code -= newBound; + Prob -= (Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte) rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 1; + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBitTree.cs b/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBitTree.cs new file mode 100644 index 0000000000..2e3bd4d18b --- /dev/null +++ b/BizHawk.Util/7z/sdk/Compress/RangeCoder/RangeCoderBitTree.cs @@ -0,0 +1,173 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; + +namespace SevenZip.Sdk.Compression.RangeCoder +{ + internal struct BitTreeEncoder + { + private readonly BitEncoder[] Models; + private readonly int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitEncoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public void Encode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0;) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (UInt32 i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public UInt32 GetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0;) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + price += Models[m].GetPrice(bit); + m = (m << 1) + bit; + } + return price; + } + + public UInt32 ReverseGetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, + int NumBitLevels, UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[startIndex + m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, + Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) + { + UInt32 m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[startIndex + m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + } + + internal struct BitTreeDecoder + { + private readonly BitDecoder[] Models; + private readonly int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitDecoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public uint Decode(Decoder rangeDecoder) + { + uint m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + m = (m << 1) + Models[m].Decode(rangeDecoder); + return m - ((uint) 1 << NumBitLevels); + } + + public uint ReverseDecode(Decoder rangeDecoder) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, + Decoder rangeDecoder, int NumBitLevels) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[startIndex + m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/7z/sdk/ICoder.cs b/BizHawk.Util/7z/sdk/ICoder.cs new file mode 100644 index 0000000000..a87019e2df --- /dev/null +++ b/BizHawk.Util/7z/sdk/ICoder.cs @@ -0,0 +1,191 @@ +/* This file is part of SevenZipSharp. + + SevenZipSharp is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SevenZipSharp 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with SevenZipSharp. If not, see . +*/ + +using System; +using System.IO; + +namespace SevenZip.Sdk +{ + /// + /// The exception that is thrown when an error in input stream occurs during decoding. + /// + [Serializable] + internal class DataErrorException : ApplicationException + { + public DataErrorException() : base("Data Error") {} + } + + /// + /// The exception that is thrown when the value of an argument is outside the allowable range. + /// + internal class InvalidParamException : ApplicationException + { + public InvalidParamException() : base("Invalid Parameter") {} + } + + /// + /// Callback progress interface. + /// + public interface ICodeProgress + { + /// + /// Callback progress. + /// + /// + /// Processed input size. -1 if unknown. + /// + /// + /// Processed output size. -1 if unknown. + /// + void SetProgress(Int64 inSize, Int64 outSize); + } ; + + /// + /// Stream coder interface + /// + public interface ICoder + { + /// + /// Codes streams. + /// + /// + /// input Stream. + /// + /// + /// output Stream. + /// + /// + /// input Size. -1 if unknown. + /// + /// + /// output Size. -1 if unknown. + /// + /// + /// callback progress reference. + /// + /// + /// if input stream is not valid + /// + void Code(Stream inStream, Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress); + } ; + + /* + public interface ICoder2 + { + void Code(ISequentialInStream []inStreams, + const UInt64 []inSizes, + ISequentialOutStream []outStreams, + UInt64 []outSizes, + ICodeProgress progress); + }; + */ + + /// + /// Provides the fields that represent properties idenitifiers for compressing. + /// + public enum CoderPropId + { + /// + /// Specifies default property. + /// + DefaultProp = 0, + /// + /// Specifies size of dictionary. + /// + DictionarySize, + /// + /// Specifies size of memory for PPM*. + /// + UsedMemorySize, + /// + /// Specifies order for PPM methods. + /// + Order, + /// + /// Specifies Block Size. + /// + BlockSize, + /// + /// Specifies number of postion state bits for LZMA (0 <= x <= 4). + /// + PosStateBits, + /// + /// Specifies number of literal context bits for LZMA (0 <= x <= 8). + /// + LitContextBits, + /// + /// Specifies number of literal position bits for LZMA (0 <= x <= 4). + /// + LitPosBits, + /// + /// Specifies number of fast bytes for LZ*. + /// + NumFastBytes, + /// + /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". + /// + MatchFinder, + /// + /// Specifies the number of match finder cyckes. + /// + MatchFinderCycles, + /// + /// Specifies number of passes. + /// + NumPasses, + /// + /// Specifies number of algorithm. + /// + Algorithm, + /// + /// Specifies the number of threads. + /// + NumThreads, + /// + /// Specifies mode with end marker. + /// + EndMarker = 0x490 + } ; + + /// + /// The ISetCoderProperties interface + /// + internal interface ISetCoderProperties + { + void SetCoderProperties(CoderPropId[] propIDs, object[] properties); + } ; + + /// + /// The IWriteCoderProperties interface + /// + internal interface IWriteCoderProperties + { + void WriteCoderProperties(Stream outStream); + } + + /// + /// The ISetDecoderPropertiesinterface + /// + internal interface ISetDecoderProperties + { + /// + /// Sets decoder properties + /// + /// Array of byte properties + void SetDecoderProperties(byte[] properties); + } +} \ No newline at end of file diff --git a/BizHawk.Util/BizHawk.Util.csproj b/BizHawk.Util/BizHawk.Util.csproj new file mode 100644 index 0000000000..1824b8e56e --- /dev/null +++ b/BizHawk.Util/BizHawk.Util.csproj @@ -0,0 +1,128 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {EE135301-08B3-4EFC-A61C-1C53E1C65CB9} + Library + Properties + BizHawk.Util + BizHawk.Util + v3.5 + 512 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;DOTNET20;UNMANAGED;COMPRESS + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE;DOTNET20;UNMANAGED;COMPRESS + prompt + 4 + x86 + + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + + + Component + + + Component + + + Component + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BizHawk.Util/Dictionaries.cs b/BizHawk.Util/Dictionaries.cs new file mode 100644 index 0000000000..dc1f2bdb19 --- /dev/null +++ b/BizHawk.Util/Dictionaries.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace BizHawk +{ + /// + /// a Dictionary-of-lists with key K and values List<V> + /// + [Serializable] + public class Bag : BagBase>, List> { } + + /// + /// a Dictionary-of-lists with key K and values List<V> + /// + [Serializable] + public class SortedBag : BagBase>, List> { } + + /// + /// A dictionary that creates new values on the fly as necessary so that any key you need will be defined. + /// + /// dictionary keys + /// dictionary values + public class WorkingDictionary : Dictionary where V : new() { + public new V this[K key] { + get { + V temp; + if(!TryGetValue(key, out temp)) + temp = this[key] = new V(); + return temp; + } + set { base[key] = value; } + } + } + + /// + /// base class for Bag and SortedBag + /// + /// dictionary keys + /// list values + /// dictionary type + /// list type + [Serializable] + public class BagBase : IEnumerable + where D : IDictionary, new() + where L : IList, IEnumerable, new() { + D dictionary = new D(); + public void Add(K key, V val) { + this[key].Add(val); + } + + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + public IEnumerator GetEnumerator() { + foreach(L lv in dictionary.Values) + foreach(V v in lv) + yield return v; + } + + public IEnumerable KeyValuePairEnumerator { get { return dictionary; } } + + /// + /// the list of keys contained herein + /// + public IList Keys { get { return new List(dictionary.Keys); } } + + + + public L this[K key] { + get { + L slot; + if(!dictionary.TryGetValue(key, out slot)) + dictionary[key] = slot = new L(); + return slot; + } + set { + dictionary[key] = value; + } + } + } + +} \ No newline at end of file diff --git a/BizHawk.Util/InputConfigBase.cs b/BizHawk.Util/InputConfigBase.cs new file mode 100644 index 0000000000..913382bea5 --- /dev/null +++ b/BizHawk.Util/InputConfigBase.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace BizHawk +{ + public class InputConfigBase : Form + { + public void CheckDups() + { + Dictionary dups = new Dictionary(); + foreach (Control c in Controls) + { + SmartTextBoxControl stbc = c as SmartTextBoxControl; + if (stbc == null) continue; + if (dups.ContainsKey(stbc.Text)) + { + MessageBox.Show("DUP!"); + return; + } + dups[stbc.Text] = true; + } + } + + } +} \ No newline at end of file diff --git a/BizHawk.Util/KeyTurbo.cs b/BizHawk.Util/KeyTurbo.cs new file mode 100644 index 0000000000..24f9515435 --- /dev/null +++ b/BizHawk.Util/KeyTurbo.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections; +using System.Windows.Forms; + +namespace BizHawk +{ + public class TurboKey + { + public void Reset(int downTime, int upTime) + { + value = false; + timer = 0; + this.upTime = upTime; + this.downTime = downTime; + } + + public void Tick(bool down) + { + if (!down) + { + Reset(downTime, upTime); + return; + } + + timer++; + + value = true; + if (timer > downTime) + value = false; + if(timer > (upTime+downTime)) + { + timer = 0; + value = true; + } + } + + public bool value; + int upTime, downTime; + int timer; + } +} \ No newline at end of file diff --git a/BizHawk.Util/Properties/AssemblyInfo.cs b/BizHawk.Util/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..00e6900702 --- /dev/null +++ b/BizHawk.Util/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("BizHawk.Util")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("BizHawk.Util")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("53c04c97-2bac-4fa9-af11-2540b483674f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/BizHawk.Util/SmartTextBoxControl.cs b/BizHawk.Util/SmartTextBoxControl.cs new file mode 100644 index 0000000000..34d8b7b35a --- /dev/null +++ b/BizHawk.Util/SmartTextBoxControl.cs @@ -0,0 +1,34 @@ +using System; +using System.Windows.Forms; + +namespace BizHawk +{ + public class SmartTextBoxControl : TextBox + { + public SmartTextBoxControl() + { + ReadOnly = true; + } + protected override void OnKeyDown(KeyEventArgs e) + { + base.Text = e.KeyCode.ToString(); + OnTextChanged(new EventArgs()); + } + + protected override void OnKeyPress(KeyPressEventArgs e) + { + + } + + protected override void OnKeyUp(KeyEventArgs e) + { + } + + public override string Text + { + get { return base.Text; } + set { } + } + + } +} \ No newline at end of file diff --git a/BizHawk.Util/TextDebugView.cs b/BizHawk.Util/TextDebugView.cs new file mode 100644 index 0000000000..41bda99f0f --- /dev/null +++ b/BizHawk.Util/TextDebugView.cs @@ -0,0 +1,59 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace BizHawk +{ + public class TextDebugView : Control + { + public TextDebugView() + { + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.Opaque, true); + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + } + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + e.Graphics.Clear(SystemColors.Control); + Font font = new Font(new FontFamily("Courier New"), 8); + e.Graphics.DrawString(Text, font, Brushes.Black,0,0); + font.Dispose(); + } + + public override string Text + { + get + { + return base.Text; + } + set + { + base.Text = value; + Invalidate(); + } + } + } + + public class TextDebugForm : Form + { + public TextDebugView view = new TextDebugView(); + public TextDebugForm() + { + view.Dock = DockStyle.Fill; + Controls.Add(view); + } + + public override string Text + { + get + { + return view.Text; + } + set + { + view.Text = value; + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Util/ViewportPanel.cs b/BizHawk.Util/ViewportPanel.cs new file mode 100644 index 0000000000..2c17cb39b8 --- /dev/null +++ b/BizHawk.Util/ViewportPanel.cs @@ -0,0 +1,115 @@ +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Windows.Forms; + +namespace BizHawk.Core +{ + /// + /// A programmatic PictureBox, really, which will paint itself using the last bitmap that was provided + /// + public class RetainedViewportPanel : Control + { + public RetainedViewportPanel() + { + CreateHandle(); + + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.DoubleBuffer, true); + SetStyle(ControlStyles.Opaque, true); + SetStyle(ControlStyles.UserMouse, true); + } + + //Size logicalSize; + ////int pitch; + //public void SetLogicalSize(int w, int h) + //{ + // if (bmp != null) bmp.Dispose(); + // bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); + // logicalSize = new Size(w, h); + //} + + /// + /// Takes ownership of the provided bitmap and will use it for future painting + /// + public void SetBitmap(Bitmap newbmp) + { + if (bmp != null) bmp.Dispose(); + bmp = newbmp; + Refresh(); + } + + Bitmap bmp; + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + if(bmp != null) + e.Graphics.DrawImage(bmp, 0, 0, Width, Height); + } + + } + + /// + /// A dumb panel which functions as a placeholder for framebuffer painting + /// + public class ViewportPanel : Control + { + public ViewportPanel() + { + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.DoubleBuffer, true); + SetStyle(ControlStyles.Opaque, true); + SetStyle(ControlStyles.UserMouse, true); + } + } + + /// + /// A ViewportPanel with a vertical scroll bar + /// + public class ScrollableViewportPanel : UserControl + { + TableLayoutPanel table; + ViewportPanel view; + VScrollBar scroll; + + public ViewportPanel View { get { return view; } } + public VScrollBar Scrollbar { get { return scroll; } } + + public int ScrollMax { get { return Scrollbar.Maximum; } set { Scrollbar.Maximum = value; } } + public int ScrollLargeChange { get { return Scrollbar.LargeChange; } set { Scrollbar.LargeChange = value; } } + + public ScrollableViewportPanel() + { + InitializeComponent(); + } + + public void InitializeComponent() + { + table = new TableLayoutPanel(); + view = new ViewportPanel(); + scroll = new VScrollBar(); + + scroll.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom; + view.Dock = DockStyle.Fill; + + table.Dock = DockStyle.Fill; + table.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); + table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); + table.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize, 0)); + table.RowCount = 1; + table.ColumnCount = 2; + table.Controls.Add(view); + table.Controls.Add(scroll); + table.SetColumn(view, 0); + table.SetColumn(scroll, 1); + + scroll.Scroll += (sender, e) => OnScroll(e); + view.Paint += (sender, e) => OnPaint(e); + + Controls.Add(table); + } + } +} \ No newline at end of file diff --git a/BizHawk.sln b/BizHawk.sln new file mode 100644 index 0000000000..06187e112b --- /dev/null +++ b/BizHawk.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Emulation", "BizHawk.Emulation\BizHawk.Emulation.csproj", "{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Util", "BizHawk.Util\BizHawk.Util.csproj", "{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.MultiClient", "BizHawk.MultiClient\BizHawk.MultiClient.csproj", "{DD448B37-BA3F-4544-9754-5406E8094723}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Any CPU.Build.0 = Release|Any CPU + {EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Any CPU.Build.0 = Release|Any CPU + {DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD448B37-BA3F-4544-9754-5406E8094723}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD448B37-BA3F-4544-9754-5406E8094723}.Release|Any CPU.Build.0 = Release|Any CPU + {C43F8BCA-CB5F-47CF-A0BD-B32ED49423BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43F8BCA-CB5F-47CF-A0BD-B32ED49423BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43F8BCA-CB5F-47CF-A0BD-B32ED49423BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43F8BCA-CB5F-47CF-A0BD-B32ED49423BA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = BizHawk.MultiClient\BizHawk.MultiClient.csproj + EndGlobalSection +EndGlobal diff --git a/CpuCoreGenerator.sln b/CpuCoreGenerator.sln new file mode 100644 index 0000000000..748b09ba2e --- /dev/null +++ b/CpuCoreGenerator.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CpuCoreGenerator", "CpuCoreGenerator\CpuCoreGenerator.csproj", "{ED25C59A-0A09-49ED-8CC1-9363576A83A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CpuCoreGenerator/CpuCoreGenerator.csproj b/CpuCoreGenerator/CpuCoreGenerator.csproj new file mode 100644 index 0000000000..7529ece5cd --- /dev/null +++ b/CpuCoreGenerator/CpuCoreGenerator.csproj @@ -0,0 +1,52 @@ + + + Debug + AnyCPU + {ED25C59A-0A09-49ED-8CC1-9363576A83A7} + 9.0.21022 + 2.0 + Exe + false + CpuCoreGenerator + v3.5 + 512 + CpuCoreGenerator + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CpuCoreGenerator/HuC6280/CoreGenerator.cs b/CpuCoreGenerator/HuC6280/CoreGenerator.cs new file mode 100644 index 0000000000..0824df12d5 --- /dev/null +++ b/CpuCoreGenerator/HuC6280/CoreGenerator.cs @@ -0,0 +1,823 @@ +using System; +using System.IO; + +namespace HuC6280 +{ + public enum AddrMode + { + Implicit, + Accumulator, + Immediate, + ZeroPage, + ZeroPageX, + ZeroPageY, + ZeroPageR, + Absolute, + AbsoluteX, + AbsoluteY, + AbsoluteIndirect, + AbsoluteIndirectX, + Indirect, + IndirectX, + IndirectY, + Relative, + BlockMove, + ImmZeroPage, + ImmZeroPageX, + ImmAbsolute, + ImmAbsoluteX + } + + public class OpcodeInfo + { + public string Instruction; + public AddrMode AddressMode; + public int Cycles; + + public int Size + { + get + { + switch (AddressMode) + { + case AddrMode.Implicit: return 1; + case AddrMode.Accumulator: return 1; + case AddrMode.Immediate: return 2; + case AddrMode.ZeroPage: return 2; + case AddrMode.ZeroPageX: return 2; + case AddrMode.ZeroPageY: return 2; + case AddrMode.ZeroPageR: return 3; + case AddrMode.Absolute: return 3; + case AddrMode.AbsoluteX: return 3; + case AddrMode.AbsoluteY: return 3; + case AddrMode.Indirect: return 2; + case AddrMode.IndirectX: return 2; + case AddrMode.IndirectY: return 2; + case AddrMode.Relative: return 2; + case AddrMode.BlockMove: return 7; + case AddrMode.ImmZeroPage: return 3; + case AddrMode.ImmZeroPageX:return 3; + case AddrMode.ImmAbsolute: return 4; + case AddrMode.ImmAbsoluteX:return 4; + case AddrMode.AbsoluteIndirect: return 3; + case AddrMode.AbsoluteIndirectX: return 3; + default: + return -1; + } + } + } + + public override string ToString() + { + switch (AddressMode) + { + case AddrMode.Implicit: return Instruction; + case AddrMode.Accumulator: return Instruction + " A"; + case AddrMode.Immediate: return Instruction + " #nn"; + case AddrMode.ZeroPage: return Instruction + " zp"; + case AddrMode.ZeroPageX: return Instruction + " zp,X"; + case AddrMode.ZeroPageY: return Instruction + " zp,Y"; + case AddrMode.Absolute: return Instruction + " addr"; + case AddrMode.AbsoluteX: return Instruction + " addr,X"; + case AddrMode.AbsoluteY: return Instruction + " addr,Y"; + case AddrMode.Indirect: return Instruction + " (addr)"; + case AddrMode.IndirectX: return Instruction + " (addr,X)"; + case AddrMode.IndirectY: return Instruction + " (addr),Y"; + case AddrMode.Relative: return Instruction + " +/-rel"; + case AddrMode.BlockMove: return Instruction + " src, dest, len"; + default: return Instruction; + } + } + } + + public partial class CoreGenerator + { + public OpcodeInfo[] Opcodes = new OpcodeInfo[256]; + + public void InitOpcodeTable() + { + // Add with Carry + Set(0x69, "ADC", AddrMode.Immediate, 2); + Set(0x65, "ADC", AddrMode.ZeroPage, 4); + Set(0x75, "ADC", AddrMode.ZeroPageX, 4); + Set(0x6D, "ADC", AddrMode.Absolute, 5); + Set(0x7D, "ADC", AddrMode.AbsoluteX, 5); + Set(0x79, "ADC", AddrMode.AbsoluteY, 5); + Set(0x72, "ADC", AddrMode.Indirect, 7); + Set(0x61, "ADC", AddrMode.IndirectX, 7); + Set(0x71, "ADC", AddrMode.IndirectY, 7); + + // AND + Set(0x29, "AND", AddrMode.Immediate, 2); + Set(0x25, "AND", AddrMode.ZeroPage, 4); + Set(0x35, "AND", AddrMode.ZeroPageX, 4); + Set(0x2D, "AND", AddrMode.Absolute, 5); + Set(0x3D, "AND", AddrMode.AbsoluteX, 5); + Set(0x39, "AND", AddrMode.AbsoluteY, 5); + Set(0x32, "AND", AddrMode.Indirect, 7); + Set(0x21, "AND", AddrMode.IndirectX, 7); + Set(0x31, "AND", AddrMode.IndirectY, 7); + + // Arithmatic Shift Left + Set(0x06, "ASL", AddrMode.ZeroPage, 6); + Set(0x16, "ASL", AddrMode.ZeroPageX, 6); + Set(0x0E, "ASL", AddrMode.Absolute, 7); + Set(0x1E, "ASL", AddrMode.AbsoluteX, 7); + Set(0x0A, "ASL", AddrMode.Accumulator, 2); + + // Branch on Bit Reset + Set(0x0F, "BBR0", AddrMode.ZeroPageR, 6); + Set(0x1F, "BBR1", AddrMode.ZeroPageR, 6); + Set(0x2F, "BBR2", AddrMode.ZeroPageR, 6); + Set(0x3F, "BBR3", AddrMode.ZeroPageR, 6); + Set(0x4F, "BBR4", AddrMode.ZeroPageR, 6); + Set(0x5F, "BBR5", AddrMode.ZeroPageR, 6); + Set(0x6F, "BBR6", AddrMode.ZeroPageR, 6); + Set(0x7F, "BBR7", AddrMode.ZeroPageR, 6); + + // Branch on Bit Set + Set(0x8F, "BBS0", AddrMode.ZeroPageR, 6); + Set(0x9F, "BBS1", AddrMode.ZeroPageR, 6); + Set(0xAF, "BBS2", AddrMode.ZeroPageR, 6); + Set(0xBF, "BBS3", AddrMode.ZeroPageR, 6); + Set(0xCF, "BBS4", AddrMode.ZeroPageR, 6); + Set(0xDF, "BBS5", AddrMode.ZeroPageR, 6); + Set(0xEF, "BBS6", AddrMode.ZeroPageR, 6); + Set(0xFF, "BBS7", AddrMode.ZeroPageR, 6); + + // BIT + Set(0x89, "BIT", AddrMode.Immediate, 2); + Set(0x24, "BIT", AddrMode.ZeroPage, 4); + Set(0x34, "BIT", AddrMode.ZeroPageX, 4); + Set(0x2C, "BIT", AddrMode.Absolute, 5); + Set(0x3C, "BIT", AddrMode.AbsoluteX, 5); + + // Branch instructions + Set(0x10, "BPL", AddrMode.Relative, 2); // Branch on Plus + Set(0x30, "BMI", AddrMode.Relative, 2); // Branch on Minus + Set(0x50, "BVC", AddrMode.Relative, 2); // Branch on Overflow Clear + Set(0x70, "BVS", AddrMode.Relative, 2); // Branch on Overflow Set + Set(0x90, "BCC", AddrMode.Relative, 2); // Branch on Carry Clear + Set(0xB0, "BCS", AddrMode.Relative, 2); // Branch on Carry Set + Set(0xD0, "BNE", AddrMode.Relative, 2); // Branch on Not Equal + Set(0xF0, "BEQ", AddrMode.Relative, 2); // Branch on Equal + Set(0x80, "BRA", AddrMode.Relative, 4); // Branch Always + Set(0x44, "BSR", AddrMode.Relative, 8); // Branch to Subroutine + + // CPU Break + Set(0x00, "BRK", AddrMode.Implicit, 7); + + // Compare accumulator + Set(0xC9, "CMP", AddrMode.Immediate, 2); + Set(0xC5, "CMP", AddrMode.ZeroPage, 4); + Set(0xD5, "CMP", AddrMode.ZeroPageX, 4); + Set(0xD2, "CMP", AddrMode.Indirect, 7); + Set(0xC1, "CMP", AddrMode.IndirectX, 7); + Set(0xD1, "CMP", AddrMode.IndirectY, 7); + Set(0xCD, "CMP", AddrMode.Absolute, 5); + Set(0xDD, "CMP", AddrMode.AbsoluteX, 5); + Set(0xD9, "CMP", AddrMode.AbsoluteY, 5); + + // Compare X register + Set(0xE0, "CPX", AddrMode.Immediate, 2); + Set(0xE4, "CPX", AddrMode.ZeroPage, 4); + Set(0xEC, "CPX", AddrMode.Absolute, 5); + + // Compare Y register + Set(0xC0, "CPY", AddrMode.Immediate, 2); + Set(0xC4, "CPY", AddrMode.ZeroPage, 4); + Set(0xCC, "CPY", AddrMode.Absolute, 5); + + // DEC + Set(0xC6, "DEC", AddrMode.ZeroPage, 6); + Set(0xD6, "DEC", AddrMode.ZeroPageX, 6); + Set(0xCE, "DEC", AddrMode.Absolute, 7); + Set(0xDE, "DEC", AddrMode.AbsoluteX, 7); + Set(0x3A, "DEC", AddrMode.Accumulator, 2); + + // Exclusive OR + Set(0x49, "EOR", AddrMode.Immediate, 2); + Set(0x45, "EOR", AddrMode.ZeroPage, 4); + Set(0x55, "EOR", AddrMode.ZeroPageX, 4); + Set(0x52, "EOR", AddrMode.Indirect, 7); + Set(0x41, "EOR", AddrMode.IndirectX, 7); + Set(0x51, "EOR", AddrMode.IndirectY, 7); + Set(0x4D, "EOR", AddrMode.Absolute, 5); + Set(0x5D, "EOR", AddrMode.AbsoluteX, 5); + Set(0x59, "EOR", AddrMode.AbsoluteY, 5); + + // Flag Instructions + Set(0x18, "CLC", AddrMode.Implicit, 2); // Clear Carry + Set(0x38, "SEC", AddrMode.Implicit, 2); // Set Carry + Set(0x58, "CLI", AddrMode.Implicit, 2); // Clear Interrupt + Set(0x78, "SEI", AddrMode.Implicit, 2); // Set Interrupt + Set(0xB8, "CLV", AddrMode.Implicit, 2); // Clear Overflow + Set(0xD8, "CLD", AddrMode.Implicit, 2); // Clear Decimal + Set(0xF8, "SED", AddrMode.Implicit, 2); // Set Decimal + Set(0xF4, "SET", AddrMode.Implicit, 2); // Set T flag + + // Additional clear instructions + Set(0x62, "CLA", AddrMode.Implicit, 2); + Set(0x82, "CLX", AddrMode.Implicit, 2); + Set(0xC2, "CLY", AddrMode.Implicit, 2); + + // INC + Set(0xE6, "INC", AddrMode.ZeroPage, 6); + Set(0xF6, "INC", AddrMode.ZeroPageX, 6); + Set(0xEE, "INC", AddrMode.Absolute, 7); + Set(0xFE, "INC", AddrMode.AbsoluteX, 7); + Set(0x1A, "INC", AddrMode.Accumulator, 2); + + // Jump + Set(0x4C, "JMP", AddrMode.Absolute, 4); + Set(0x6C, "JMP", AddrMode.AbsoluteIndirect, 7); + Set(0x7C, "JMP", AddrMode.AbsoluteIndirectX, 7); + + // Jump to Subroutine + Set(0x20, "JSR", AddrMode.Absolute, 6); + + // Load Accumulator + Set(0xA9, "LDA", AddrMode.Immediate, 2); + Set(0xA5, "LDA", AddrMode.ZeroPage, 4); + Set(0xB5, "LDA", AddrMode.ZeroPageX, 4); + Set(0xB2, "LDA", AddrMode.Indirect, 7); + Set(0xA1, "LDA", AddrMode.IndirectX, 7); + Set(0xB1, "LDA", AddrMode.IndirectY, 7); + Set(0xAD, "LDA", AddrMode.Absolute, 5); + Set(0xBD, "LDA", AddrMode.AbsoluteX, 5); + Set(0xB9, "LDA", AddrMode.AbsoluteY, 5); + + // Load X register + Set(0xA2, "LDX", AddrMode.Immediate, 2); + Set(0xA6, "LDX", AddrMode.ZeroPage, 4); + Set(0xB6, "LDX", AddrMode.ZeroPageY, 4); + Set(0xAE, "LDX", AddrMode.Absolute, 5); + Set(0xBE, "LDX", AddrMode.AbsoluteY, 5); + + // Load Y register + Set(0xA0, "LDY", AddrMode.Immediate, 2); + Set(0xA4, "LDY", AddrMode.ZeroPage, 4); + Set(0xB4, "LDY", AddrMode.ZeroPageX, 4); + Set(0xAC, "LDY", AddrMode.Absolute, 5); + Set(0xBC, "LDY", AddrMode.AbsoluteX, 5); + + // Logical Shift Right + Set(0x46, "LSR", AddrMode.ZeroPage, 6); + Set(0x56, "LSR", AddrMode.ZeroPageX, 6); + Set(0x4E, "LSR", AddrMode.Absolute, 7); + Set(0x5E, "LSR", AddrMode.AbsoluteX, 7); + Set(0x4A, "LSR", AddrMode.Accumulator, 2); + + // No Operation + Set(0xEA, "NOP", AddrMode.Implicit, 2); + + // Bitwise OR with Accumulator + Set(0x09, "ORA", AddrMode.Immediate, 2); + Set(0x05, "ORA", AddrMode.ZeroPage, 4); + Set(0x15, "ORA", AddrMode.ZeroPageX, 4); + Set(0x12, "ORA", AddrMode.Indirect, 7); + Set(0x01, "ORA", AddrMode.IndirectX, 7); + Set(0x11, "ORA", AddrMode.IndirectY, 7); + Set(0x0D, "ORA", AddrMode.Absolute, 5); + Set(0x1D, "ORA", AddrMode.AbsoluteX, 5); + Set(0x19, "ORA", AddrMode.AbsoluteY, 5); + + // Register instructions + Set(0xCA, "DEX", AddrMode.Implicit, 2); // DEC X + Set(0x88, "DEY", AddrMode.Implicit, 2); // DEC Y + Set(0xE8, "INX", AddrMode.Implicit, 2); // INC X + Set(0xC8, "INY", AddrMode.Implicit, 2); // INC Y + Set(0x22, "SAX", AddrMode.Implicit, 3); // Swap A and X + Set(0x42, "SAY", AddrMode.Implicit, 3); // Swap A and Y + Set(0x02, "SXY", AddrMode.Implicit, 3); // Swap X and Y + Set(0xAA, "TAX", AddrMode.Implicit, 2); // Transfer A to X + Set(0x8A, "TXA", AddrMode.Implicit, 2); // Transfer X to A + Set(0xA8, "TAY", AddrMode.Implicit, 2); // Transfer A to Y + Set(0x98, "TYA", AddrMode.Implicit, 2); // Transfer Y to A + + // Rotate Left + Set(0x26, "ROL", AddrMode.ZeroPage, 6); + Set(0x36, "ROL", AddrMode.ZeroPageX, 6); + Set(0x2E, "ROL", AddrMode.Absolute, 7); + Set(0x3E, "ROL", AddrMode.AbsoluteX, 7); + Set(0x2A, "ROL", AddrMode.Accumulator, 2); + + // Rotate Right + Set(0x66, "ROR", AddrMode.ZeroPage, 6); + Set(0x76, "ROR", AddrMode.ZeroPageX, 6); + Set(0x6E, "ROR", AddrMode.Absolute, 7); + Set(0x7E, "ROR", AddrMode.AbsoluteX, 7); + Set(0x6A, "ROR", AddrMode.Accumulator, 2); + + // Return from Interrupt + Set(0x40, "RTI", AddrMode.Implicit, 7); + + // Return from Subroutine + Set(0x60, "RTS", AddrMode.Implicit, 7); + + // Subtract with Carry + Set(0xE9, "SBC", AddrMode.Immediate, 2); + Set(0xE5, "SBC", AddrMode.ZeroPage, 4); + Set(0xF5, "SBC", AddrMode.ZeroPageX, 4); + Set(0xF2, "SBC", AddrMode.Indirect, 7); + Set(0xE1, "SBC", AddrMode.IndirectX, 7); + Set(0xF1, "SBC", AddrMode.IndirectY, 7); + Set(0xED, "SBC", AddrMode.Absolute, 5); + Set(0xFD, "SBC", AddrMode.AbsoluteX, 5); + Set(0xF9, "SBC", AddrMode.AbsoluteY, 5); + + // Store Accumulator + Set(0x85, "STA", AddrMode.ZeroPage, 4); + Set(0x95, "STA", AddrMode.ZeroPageX, 4); + Set(0x92, "STA", AddrMode.Indirect, 7); + Set(0x81, "STA", AddrMode.IndirectX, 7); + Set(0x91, "STA", AddrMode.IndirectY, 7); + Set(0x8D, "STA", AddrMode.Absolute, 5); + Set(0x9D, "STA", AddrMode.AbsoluteX, 5); + Set(0x99, "STA", AddrMode.AbsoluteY, 5); + + // Stack instructions + Set(0x9A, "TXS", AddrMode.Implicit, 2); // Transfer X to Stack + Set(0xBA, "TSX", AddrMode.Implicit, 2); // Transfer Stack to X + Set(0x48, "PHA", AddrMode.Implicit, 3); // Push A + Set(0x68, "PLA", AddrMode.Implicit, 4); // Pull A + Set(0x08, "PHP", AddrMode.Implicit, 3); // Push P + Set(0x28, "PLP", AddrMode.Implicit, 4); // Pull P + Set(0xDA, "PHX", AddrMode.Implicit, 3); // Push X + Set(0xFA, "PLX", AddrMode.Implicit, 4); // Pull X + Set(0x5A, "PHY", AddrMode.Implicit, 3); // Push Y + Set(0x7A, "PLY", AddrMode.Implicit, 4); // Pull Y + + // Store X register + Set(0x86, "STX", AddrMode.ZeroPage, 4); + Set(0x96, "STX", AddrMode.ZeroPageY, 4); + Set(0x8E, "STX", AddrMode.Absolute, 5); + + // Store Y register + Set(0x84, "STY", AddrMode.ZeroPage, 4); + Set(0x94, "STY", AddrMode.ZeroPageX, 4); + Set(0x8C, "STY", AddrMode.Absolute, 5); + + // Memory Paging Register instructions + Set(0x53, "TAM", AddrMode.Immediate, 5); + Set(0x43, "TMA", AddrMode.Immediate, 4); + + // VDC I/O instructions + Set(0x03, "ST0", AddrMode.Immediate, 4); + Set(0x13, "ST1", AddrMode.Immediate, 4); + Set(0x23, "ST2", AddrMode.Immediate, 4); + + // Store Memory To Zero + Set(0x64, "STZ", AddrMode.ZeroPage, 4); + Set(0x74, "STZ", AddrMode.ZeroPageX, 4); + Set(0x9C, "STZ", AddrMode.Absolute, 5); + Set(0x9E, "STZ", AddrMode.AbsoluteX, 5); + + // Reset Memory Bit i + Set(0x07, "RMB0", AddrMode.ZeroPage, 7); + Set(0x17, "RMB1", AddrMode.ZeroPage, 7); + Set(0x27, "RMB2", AddrMode.ZeroPage, 7); + Set(0x37, "RMB3", AddrMode.ZeroPage, 7); + Set(0x47, "RMB4", AddrMode.ZeroPage, 7); + Set(0x57, "RMB5", AddrMode.ZeroPage, 7); + Set(0x67, "RMB6", AddrMode.ZeroPage, 7); + Set(0x77, "RMB7", AddrMode.ZeroPage, 7); + + // Set Memory Bit i + Set(0x87, "SMB0", AddrMode.ZeroPage, 7); + Set(0x97, "SMB1", AddrMode.ZeroPage, 7); + Set(0xA7, "SMB2", AddrMode.ZeroPage, 7); + Set(0xB7, "SMB3", AddrMode.ZeroPage, 7); + Set(0xC7, "SMB4", AddrMode.ZeroPage, 7); + Set(0xD7, "SMB5", AddrMode.ZeroPage, 7); + Set(0xE7, "SMB6", AddrMode.ZeroPage, 7); + Set(0xF7, "SMB7", AddrMode.ZeroPage, 7); + + // Test and Reset Memory Bit Against Accumulator + Set(0x14, "TRB", AddrMode.ZeroPage, 6); + Set(0x1C, "TRB", AddrMode.Absolute, 7); + + // Test and Set Memory Bit Against Accumulator + Set(0x04, "TSB", AddrMode.ZeroPage, 6); + Set(0x0C, "TSB", AddrMode.Absolute, 7); + + // Test and Reset Memory Bits + Set(0x83, "TST", AddrMode.ImmZeroPage, 7); + Set(0xA3, "TST", AddrMode.ImmZeroPageX, 7); + Set(0x93, "TST", AddrMode.ImmAbsolute, 8); + Set(0xB3, "TST", AddrMode.ImmAbsoluteX, 8); + + // Cpu Speed instructions + Set(0xD4, "CSH", AddrMode.Implicit, 2); + Set(0x54, "CSL", AddrMode.Implicit, 2); + + // Block Memory Transfer instructions + Set(0xF3, "TAI", AddrMode.BlockMove, 17); // Transfer Alternate Increment + Set(0xE3, "TIA", AddrMode.BlockMove, 17); // Transfer Increment Alternate + Set(0x73, "TII", AddrMode.BlockMove, 17); // Transfer Increment Increment + Set(0xD3, "TIN", AddrMode.BlockMove, 17); // Transfer Increment None + Set(0xC3, "TDD", AddrMode.BlockMove, 17); // Transfer Decrement Decrement + } + + private void Set(byte value, string instr, AddrMode addressMode, int cycles) + { + var op = new OpcodeInfo(); + op.Instruction = instr; + op.AddressMode = addressMode; + op.Cycles = cycles; + if (Opcodes[value] != null) + throw new Exception("opcode " + value + " already assigned"); + Opcodes[value] = op; + } + + public void GenerateExecutor(string file) + { + var w = new StreamWriter(file, false); + w.WriteLine("using System;"); + w.WriteLine(); + w.WriteLine("// Do not modify this file directly! This is GENERATED code."); + w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there."); + w.WriteLine(); + w.WriteLine("namespace BizHawk.Emulation.CPUs.H6280"); + w.WriteLine("{"); + w.WriteLine(" public partial class HuC6280"); + w.WriteLine(" {"); + w.WriteLine(" public void Execute(int cycles)"); + w.WriteLine(" {"); + w.WriteLine(" sbyte rel8;"); + w.WriteLine(" byte value8, temp8, source8;"); + w.WriteLine(" ushort value16, temp16;"); + w.WriteLine(" ushort from, to, len;"); + w.WriteLine(" int temp, lo, hi;"); + w.WriteLine(); + w.WriteLine(" PendingCycles += cycles;"); + w.WriteLine(" while (PendingCycles > 0)"); + w.WriteLine(" {"); + w.WriteLine(" int lastCycles = PendingCycles;"); + w.WriteLine(); + w.WriteLine(" if (IRQ1Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ1Selector) == 0)"); + w.WriteLine(" {"); + w.WriteLine(" FlagB = false;"); + w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));"); + w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)PC);"); + w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), P);"); + w.WriteLine(" FlagD = false;"); + w.WriteLine(" FlagI = true;"); + w.WriteLine(" PC = ReadWord(IRQ1Vector);"); + w.WriteLine(" PendingCycles -= 7;"); + w.WriteLine(" //Log.Note(\"CPU\", \"ENTERING IRQ1 INTERRUPT\");"); + w.WriteLine(" }"); + w.WriteLine(); + w.WriteLine(" if (TimerAssert && FlagI == false && LagIFlag == false && (IRQControlByte & TimerSelector) == 0)"); + w.WriteLine(" {"); + w.WriteLine(" FlagB = false;"); + w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));"); + w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)PC);"); + w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), P);"); + w.WriteLine(" FlagD = false;"); + w.WriteLine(" FlagI = true;"); + w.WriteLine(" PC = ReadWord(TimerVector);"); + w.WriteLine(" PendingCycles -= 7;"); + w.WriteLine(" //Log.Note(\"CPU\", \"ENTERING __TIMER__ INTERRUPT\");"); + w.WriteLine(" }"); + w.WriteLine(); + w.WriteLine(" IRQControlByte = IRQNextControlByte;"); + w.WriteLine(" LagIFlag = FlagI;"); + w.WriteLine(); + + // TODO halt state, shit like that + w.WriteLine("//if (debug) Log.Note(\"CPU\", State());"); + + w.WriteLine(" byte opcode = ReadMemory(PC++);"); + w.WriteLine(" switch (opcode)"); + w.WriteLine(" {"); + + for (int i = 0; i < 256; i++) + { + if (Opcodes[i] != null) + EmulateOpcode(w, i); + } + + w.WriteLine(" default:"); + w.WriteLine(" throw new Exception(String.Format(\"Unhandled opcode: {0:X2}\", opcode));"); + w.WriteLine(" }"); + w.WriteLine(); + w.WriteLine(" P &= 0xDF; // Clear T flag"); + w.WriteLine(" AfterClearTFlag: // SET command jumps here"); + w.WriteLine(" int delta = lastCycles - PendingCycles;"); + w.WriteLine(" TotalExecutedCycles += delta;"); + w.WriteLine(); + w.WriteLine(" if (TimerEnabled)"); + w.WriteLine(" {"); + w.WriteLine(" TimerTickCounter += delta;"); + w.WriteLine(" if (TimerTickCounter >= 1024)"); + w.WriteLine(" {"); + w.WriteLine(" TimerValue--;"); + w.WriteLine(" TimerTickCounter &= 1023;"); + w.WriteLine(" if (TimerValue == 0xFF)"); + w.WriteLine(" {"); + w.WriteLine(" TimerValue = TimerReloadValue;"); + w.WriteLine(" TimerAssert = true;"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine("}"); + w.Close(); + } + + const string Spaces = " "; + + private void EmulateOpcode(TextWriter w, int opcode) + { + var op = Opcodes[opcode]; + w.WriteLine(" case 0x{0:X2}: // {1}", opcode, op); + switch (op.Instruction) + { + case "ADC": ADC(op, w); break; + case "AND": AND(op, w); break; + case "ASL": ASL(op, w); break; + case "BBR0": BB(op, w, 0, false); break; + case "BBR1": BB(op, w, 1, false); break; + case "BBR2": BB(op, w, 2, false); break; + case "BBR3": BB(op, w, 3, false); break; + case "BBR4": BB(op, w, 4, false); break; + case "BBR5": BB(op, w, 5, false); break; + case "BBR6": BB(op, w, 6, false); break; + case "BBR7": BB(op, w, 7, false); break; + case "BBS0": BB(op, w, 0, true); break; + case "BBS1": BB(op, w, 1, true); break; + case "BBS2": BB(op, w, 2, true); break; + case "BBS3": BB(op, w, 3, true); break; + case "BBS4": BB(op, w, 4, true); break; + case "BBS5": BB(op, w, 5, true); break; + case "BBS6": BB(op, w, 6, true); break; + case "BBS7": BB(op, w, 7, true); break; + case "BCC": Branch(op, w, "C", false); break; + case "BCS": Branch(op, w, "C", true); break; + case "BEQ": Branch(op, w, "Z", true); break; + case "BIT": BIT(op, w); break; + case "BMI": Branch(op, w, "N", true); break; + case "BNE": Branch(op, w, "Z", false); break; + case "BPL": Branch(op, w, "N", false); break; + case "BRA": BRA(op, w); break; + case "BRK": w.WriteLine("throw new Exception(\"break\");"); break; + case "BSR": BSR(op, w); break; + case "BVC": Branch(op, w, "V", false); break; + case "BVS": Branch(op, w, "V", true); break; + case "CLA": CLreg(op, w, "A"); break; + case "CLC": CLC(op, w); break; + case "CLD": CLD(op, w); break; + case "CLI": CLI(op, w); break; + case "CLV": CLV(op, w); break; + case "CLX": CLreg(op, w, "X"); break; + case "CLY": CLreg(op, w, "Y"); break; + case "CMP": CMP_reg(op, w, "A"); break; + case "CPX": CMP_reg(op, w, "X"); break; + case "CPY": CMP_reg(op, w, "Y"); break; + case "CSH": NOP(op, w); break; // TODO fixme + case "CSL": NOP(op, w); break; // TODO fixme + case "DEC": DEC(op, w); break; + case "DEX": DEX(op, w); break; + case "DEY": DEY(op, w); break; + case "EOR": EOR(op, w); break; + case "INC": INC(op, w); break; + case "INX": INX(op, w); break; + case "INY": INY(op, w); break; + case "JMP": JMP(op, w); break; + case "JSR": JSR(op, w); break; + case "LDA": LDA(op, w); break; + case "LDX": LDX(op, w); break; + case "LDY": LDY(op, w); break; + case "LSR": LSR(op, w); break; + case "NOP": NOP(op, w); break; + case "ORA": ORA(op, w); break; + case "PHA": PushReg(op, w, "A"); break; + case "PHP": PushReg(op, w, "P"); break; + case "PHX": PushReg(op, w, "X"); break; + case "PHY": PushReg(op, w, "Y"); break; + case "PLA": PullReg(op, w, "A"); break; + case "PLP": PLP(op, w); break; + case "PLX": PullReg(op, w, "X"); break; + case "PLY": PullReg(op, w, "Y"); break; + case "ROL": ROL(op, w); break; + case "ROR": ROR(op, w); break; + case "RTI": RTI(op, w); break; + case "RTS": RTS(op, w); break; + case "SAX": SAX(op, w); break; + case "SAY": SAY(op, w); break; + case "SBC": SBC(op, w); break; + case "SEC": SEC(op, w); break; + case "SED": SED(op, w); break; + case "SEI": SEI(op, w); break; + case "SET": SET(op, w); break; + case "SXY": SXY(op, w); break; + case "ST0": ST0(op, w); break; + case "ST1": ST1(op, w); break; + case "ST2": ST2(op, w); break; + case "STA": STA(op, w); break; + case "STX": STX(op, w); break; + case "STY": STY(op, w); break; + case "STZ": STZ(op, w); break; + case "TAI": TAI(op, w); break; + case "TAM": TAM(op, w); break; + case "TAX": TAX(op, w); break; + case "TAY": TAY(op, w); break; + case "TDD": TDD(op, w); break; + case "TIA": TIA(op, w); break; + case "TII": TII(op, w); break; + case "TIN": TIN(op, w); break; + case "TMA": TMA(op, w); break; + case "TRB": TRB(op, w); break; + case "TSB": TSB(op, w); break; + case "TST": TST(op, w); break; + case "TSX": TSX(op, w); break; + case "TXA": TXA(op, w); break; + case "TYA": TYA(op, w); break; + case "TXS": TXS(op, w); break; + case "RMB0": RMB(op, w, 0); break; + case "RMB1": RMB(op, w, 1); break; + case "RMB2": RMB(op, w, 2); break; + case "RMB3": RMB(op, w, 3); break; + case "RMB4": RMB(op, w, 4); break; + case "RMB5": RMB(op, w, 5); break; + case "RMB6": RMB(op, w, 6); break; + case "RMB7": RMB(op, w, 7); break; + case "SMB0": SMB(op, w, 0); break; + case "SMB1": SMB(op, w, 1); break; + case "SMB2": SMB(op, w, 2); break; + case "SMB3": SMB(op, w, 3); break; + case "SMB4": SMB(op, w, 4); break; + case "SMB5": SMB(op, w, 5); break; + case "SMB6": SMB(op, w, 6); break; + case "SMB7": SMB(op, w, 7); break; + default: + w.WriteLine("throw new Exception(\"unsupported opcode {0:X2}\");",opcode); + break; + } + if (op.Instruction != "SET") + w.WriteLine(Spaces + "break;"); + } + + private void GetValue8(OpcodeInfo op, TextWriter w, string dest) + { + // TODO it APPEARS that the +1 opcode penalty applies to all AbsoluteX, AbsoluteY, and IndirectY + // but this is not completely clear. the doc has some exceptions, but are they real? + switch (op.AddressMode) + { + case AddrMode.Immediate: + w.WriteLine(Spaces + dest + " = ReadMemory(PC++);"); break; + case AddrMode.ImmZeroPage: + case AddrMode.ZeroPage: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadMemory(PC++)+0x2000));"); break; + case AddrMode.ImmZeroPageX: + case AddrMode.ZeroPageX: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000));"); break; + case AddrMode.ZeroPageY: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(((ReadMemory(PC++)+Y)&0xFF)+0x2000));"); break; + case AddrMode.ImmAbsolute: + case AddrMode.Absolute: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadWord(PC)); PC += 2;"); break; + case AddrMode.ImmAbsoluteX: + case AddrMode.AbsoluteX: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+X));"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.AbsoluteY: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+Y));"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.Indirect: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)));"); break; + case AddrMode.IndirectX: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000)));"); break; + case AddrMode.IndirectY: + w.WriteLine(Spaces + "temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000));"); + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));"); + w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " PendingCycles--;"); + break; + default: + throw new Exception("p"+op.Instruction); + + } + } + + private void GetAddress(OpcodeInfo op, TextWriter w, string dest) + { + // TODO it APPEARS that the +1 opcode penalty applies to all AbsoluteX, AbsoluteY, and IndirectY + // but this is not completely clear. the doc has some exceptions, but are they real? + switch (op.AddressMode) + { + case AddrMode.ZeroPage: + w.WriteLine(Spaces + dest + " = (ushort)(ReadMemory(PC++)+0x2000);"); break; + case AddrMode.ZeroPageX: + w.WriteLine(Spaces + dest + " = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000);"); break; + case AddrMode.ZeroPageY: + w.WriteLine(Spaces + dest + " = (ushort)(((ReadMemory(PC++)+Y)&0xFF)+0x2000);"); break; + case AddrMode.Absolute: + w.WriteLine(Spaces + dest + " = ReadWord(PC); PC += 2;"); break; + case AddrMode.AbsoluteX: + w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+X);"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.AbsoluteY: + w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+Y);"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.Indirect: + w.WriteLine(Spaces + dest + " = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000));"); break; + case AddrMode.IndirectX: + w.WriteLine(Spaces + dest + " = ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000));"); break; + case AddrMode.IndirectY: + w.WriteLine(Spaces + "temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000));"); + w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);"); + w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " PendingCycles--;"); + break; + case AddrMode.Relative: + w.WriteLine(Spaces + "rel8 = (sbyte)ReadMemory(PC++);"); + w.WriteLine(Spaces + dest + " = (ushort)(PC+rel8);"); + break; + } + } + + public void GenerateDisassembler(string file) + { + var w = new StreamWriter(file, false); + w.WriteLine("namespace BizHawk.Emulation.CPUs.H6280"); + w.WriteLine(); + w.WriteLine("// Do not modify this file directly! This is GENERATED code."); + w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there."); + w.WriteLine(); + w.WriteLine("{"); + w.WriteLine(" public partial class HuC6280"); + w.WriteLine(" {"); + w.WriteLine(" public string Disassemble(ushort pc, out int bytesToAdvance)"); + w.WriteLine(" {"); + w.WriteLine(" byte op = ReadMemory(pc);"); + w.WriteLine(" switch (op)"); + w.WriteLine(" {"); + + for (int i = 0; i < 256; i++) + { + if (Opcodes[i] != null) + DisassembleOpcode(w, i); + } + + w.WriteLine(" }"); + w.WriteLine(" bytesToAdvance = 1;"); + w.WriteLine(" return \"???\";"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine("}"); + w.Close(); + } + + private void DisassembleOpcode(TextWriter w, int i) + { + var op = Opcodes[i]; + w.Write(" case 0x{0:X2}: ", i); + + string mstr; + switch (op.AddressMode) + { + case AddrMode.Implicit: mstr = "\"" + op.Instruction + "\""; break; + case AddrMode.Accumulator: mstr = "\"" + op.Instruction + " A\""; break; + case AddrMode.Immediate: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPage: mstr = "string.Format(\"" + op.Instruction + " ${0:X2}\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPageX: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},X\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPageY: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},Y\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPageR: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},{1}\", ReadMemory(++pc), (sbyte)ReadMemory(++pc))"; break; + case AddrMode.Absolute: mstr = "string.Format(\"" + op.Instruction + " ${0:X4}\", ReadWord(++pc))"; break; + case AddrMode.AbsoluteX: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},X\", ReadWord(++pc))"; break; + case AddrMode.AbsoluteY: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},Y\", ReadWord(++pc))"; break; + case AddrMode.Indirect: mstr = "string.Format(\"" + op.Instruction + " (${0:X2})\", ReadMemory(++pc))"; break; + case AddrMode.IndirectX: mstr = "string.Format(\"" + op.Instruction + " (${0:X2},X)\", ReadMemory(++pc))"; break; + case AddrMode.IndirectY: mstr = "string.Format(\"" + op.Instruction + " (${0:X2}),Y\", ReadMemory(++pc))"; break; + case AddrMode.Relative: mstr = "string.Format(\"" + op.Instruction + " {0}\", (sbyte)ReadMemory(++pc))"; break; + case AddrMode.BlockMove: mstr = "string.Format(\"" + op.Instruction + " {0:X4},{1:X4},{2:X4}\", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5)))"; break; + case AddrMode.ImmZeroPage: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X2}\", ReadMemory(++pc), ReadMemory(++pc))"; break; + case AddrMode.ImmZeroPageX: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X2},X\", ReadMemory(++pc), ReadMemory(++pc))"; break; + case AddrMode.ImmAbsolute: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X4}\", ReadMemory(++pc), ReadWord(++pc))"; break; + case AddrMode.ImmAbsoluteX: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X4},X\", ReadMemory(++pc), ReadWord(++pc))"; break; + case AddrMode.AbsoluteIndirect: mstr = "string.Format(\"" + op.Instruction + " (${0:X4})\", ReadWord(++pc))"; break; + case AddrMode.AbsoluteIndirectX: mstr = "string.Format(\"" + op.Instruction + " (${0:X4},X)\", ReadWord(++pc))"; break; + default: mstr = @"""?"""; break; + } + + w.Write("bytesToAdvance = {0}; ", op.Size); + w.WriteLine("return " + mstr + ";"); + } + } +} \ No newline at end of file diff --git a/CpuCoreGenerator/HuC6280/Instructions.cs b/CpuCoreGenerator/HuC6280/Instructions.cs new file mode 100644 index 0000000000..45638c0f39 --- /dev/null +++ b/CpuCoreGenerator/HuC6280/Instructions.cs @@ -0,0 +1,698 @@ +using System.IO; + +namespace HuC6280 +{ + public partial class CoreGenerator + { + private string SetNZ(string val) + { + return "P = (byte)((P & 0x5D) | TableNZ[" + val + "]);"; + } + + private void ADC(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A;"); + w.WriteLine(); + w.WriteLine(Spaces + "if ((P & 0x08) != 0) {"); + w.WriteLine(Spaces + " lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0);"); + w.WriteLine(Spaces + " hi = (source8 & 0xF0) + (value8 & 0xF0);"); + w.WriteLine(Spaces + " if (lo > 0x09) {"); + w.WriteLine(Spaces + " hi += 0x10;"); + w.WriteLine(Spaces + " lo += 0x06;"); + w.WriteLine(Spaces + " }"); + w.WriteLine(Spaces + " if (hi > 0x90) hi += 0x60;"); + w.WriteLine(Spaces + " FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0;"); + w.WriteLine(Spaces + " FlagC = (hi & 0xFF00) != 0;"); + w.WriteLine(Spaces + " source8 = (byte) ((lo & 0x0F) | (hi & 0xF0));"); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + "} else {"); + w.WriteLine(Spaces + " temp = value8 + source8 + (FlagC ? 1 : 0);"); + w.WriteLine(Spaces + " FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0;"); + w.WriteLine(Spaces + " FlagC = temp > 0xFF;"); + w.WriteLine(Spaces + " source8 = (byte)temp;"); + w.WriteLine(Spaces + "}"); + + w.WriteLine(Spaces + "if (FlagT == false)"); + w.WriteLine(Spaces + " A = source8;"); + w.WriteLine(Spaces + "else { "); + w.WriteLine(Spaces + " WriteMemory((ushort)(0x2000 + X), source8);"); + w.WriteLine(Spaces + " PendingCycles -= 3;"); + w.WriteLine(Spaces + "}"); + w.WriteLine(Spaces + SetNZ("source8")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void AND(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "A &= value8;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void ASL(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "FlagC = (A & 0x80) != 0;"); + w.WriteLine(Spaces + "A = (byte) (A << 1);"); + w.WriteLine(Spaces + SetNZ("A")); + } + else + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "FlagC = (value8 & 0x80) != 0;"); + w.WriteLine(Spaces + "value8 = (byte)(value8 << 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void BB(OpcodeInfo op, TextWriter w, int bit, bool set) + { + string filter = ""; + switch (bit) + { + case 0: filter = "0x01"; break; + case 1: filter = "0x02"; break; + case 2: filter = "0x04"; break; + case 3: filter = "0x08"; break; + case 4: filter = "0x10"; break; + case 5: filter = "0x20"; break; + case 6: filter = "0x40"; break; + case 7: filter = "0x80"; break; + } + string cond = set ? "!=" : "=="; + + w.WriteLine(Spaces + "value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000));"); + w.WriteLine(Spaces + "rel8 = (sbyte) ReadMemory(PC++);"); + w.WriteLine(Spaces + "if ((value8 & "+filter+") "+cond+" 0) {"); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + " PC = (ushort)(PC+rel8);"); + w.WriteLine(Spaces + "}"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void Branch(OpcodeInfo op, TextWriter w, string flag, bool cond) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "if (Flag" + flag + " == " + cond.ToString().ToLower() + ") {"); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + " PC = value16;"); + w.WriteLine(Spaces + "}"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void BRA(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "PC"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void BSR(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "temp16 = (ushort)(PC-1);"); + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)(temp16 >> 8));"); + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)temp16);"); + w.WriteLine(Spaces + "PC = value16;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void BIT(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;"); + w.WriteLine(Spaces + "FlagZ = (A & value8) == 0;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void CLC(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagC = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void CLD(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagD = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void CLI(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagI = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void CLV(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagV = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void CLreg(OpcodeInfo op, TextWriter w, string reg) + { + w.WriteLine(Spaces + "{0} = 0;",reg); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void CMP_reg(OpcodeInfo op, TextWriter w, string reg) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "value16 = (ushort) (" + reg + " - value8);"); + w.WriteLine(Spaces + "FlagC = (" + reg + " >= value8);"); + w.WriteLine(Spaces + SetNZ("(byte)value16")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void DEC(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode != AddrMode.Accumulator) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) - 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + } else { + w.WriteLine(Spaces + SetNZ("--A")); + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void DEX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("--X")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void DEY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("--Y")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void EOR(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "if (FlagT == false) { "); + w.WriteLine(Spaces + " A ^= value8;"); + w.WriteLine(Spaces + " "+SetNZ("A")); + w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles); + w.WriteLine(Spaces + "} else {"); + w.WriteLine(Spaces + " temp8 = ReadMemory((ushort)(0x2000 + X));"); + w.WriteLine(Spaces + " temp8 ^= value8;"); + w.WriteLine(Spaces + " " + SetNZ("temp8")); + w.WriteLine(Spaces + " WriteMemory((ushort)(0x2000 + X), temp8);"); + w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles+3); + w.WriteLine(Spaces + "}"); + } + + private void INC(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode != AddrMode.Accumulator) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) + 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + } else { + w.WriteLine(Spaces + SetNZ("++A")); + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void INX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("++X")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void INY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("++Y")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void JMP(OpcodeInfo op, TextWriter w) + { + switch (op.AddressMode) + { + case AddrMode.Absolute: w.WriteLine(Spaces + "PC = ReadWord(PC);"); break; + case AddrMode.AbsoluteIndirect: w.WriteLine(Spaces + "PC = ReadWord(ReadWord(PC));"); break; + case AddrMode.AbsoluteIndirectX: w.WriteLine(Spaces + "PC = ReadWord((ushort)(ReadWord(PC)+X));"); break; + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void JSR(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "temp16 = (ushort)(PC+1);"); + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)(temp16 >> 8));"); + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)temp16);"); + w.WriteLine(Spaces + "PC = ReadWord(PC);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void LDA(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "A"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void LDX(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "X"); + w.WriteLine(Spaces + SetNZ("X")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void LDY(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "Y"); + w.WriteLine(Spaces + SetNZ("Y")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void LSR(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "FlagC = (A & 1) != 0;"); + w.WriteLine(Spaces + "A = (byte) (A >> 1);"); + w.WriteLine(Spaces + SetNZ("A")); + } + else + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "FlagC = (value8 & 1) != 0;"); + w.WriteLine(Spaces + "value8 = (byte)(value8 >> 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void NOP(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void ORA(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "A |= value8;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void PushReg(OpcodeInfo op, TextWriter w, string reg) + { + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), {0});", reg); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void PullReg(OpcodeInfo op, TextWriter w, string reg) + { + w.WriteLine(Spaces + "{0} = ReadMemory((ushort)(++S + 0x2100));", reg); + w.WriteLine(Spaces + SetNZ(reg)); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + + private void PLP(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x2100));"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void ROL(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "temp8 = A;"); + w.WriteLine(Spaces + "A = (byte)((A << 1) | (P & 1));"); + w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;"); + w.WriteLine(Spaces + SetNZ("A")); + } + else + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "value8 = (byte)((value8 << 1) | (P & 1));"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void ROR(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "temp8 = A;"); + w.WriteLine(Spaces + "A = (byte)((A >> 1) | ((P & 1)<<7));"); + w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;"); + w.WriteLine(Spaces + SetNZ("A")); + } + else + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "value8 = (byte)((value8 >> 1) | ((P & 1)<<7));"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void RTI(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x2100));"); + w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x2100));"); + w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x2100)) << 8);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void RTS(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x2100));"); + w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x2100)) << 8);"); + w.WriteLine(Spaces + "PC++;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SAX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "temp8 = A;"); + w.WriteLine(Spaces + "A = X;"); + w.WriteLine(Spaces + "X = temp8;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SAY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "temp8 = A;"); + w.WriteLine(Spaces + "A = Y;"); + w.WriteLine(Spaces + "Y = temp8;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SXY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "temp8 = X;"); + w.WriteLine(Spaces + "X = Y;"); + w.WriteLine(Spaces + "Y = temp8;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SBC(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "temp = A - value8 - (FlagC ? 0 : 1);"); + w.WriteLine(Spaces + "if ((P & 0x08) != 0) {"); + w.WriteLine(Spaces + " lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1);"); + w.WriteLine(Spaces + " hi = (A & 0xF0) - (value8 & 0xF0);"); + w.WriteLine(Spaces + " if ((lo & 0xF0) != 0) lo -= 0x06;"); + w.WriteLine(Spaces + " if ((lo & 0x80) != 0) hi -= 0x10;"); + w.WriteLine(Spaces + " if ((hi & 0x0F00) != 0) hi -= 0x60;"); + w.WriteLine(Spaces + " FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;"); + w.WriteLine(Spaces + " FlagC = (hi & 0xFF00) == 0;"); + w.WriteLine(Spaces + " A = (byte) ((lo & 0x0F) | (hi & 0xF0));"); + w.WriteLine(Spaces + " PendingCycles--;"); + w.WriteLine(Spaces + "} else {"); + w.WriteLine(Spaces + " FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;"); + w.WriteLine(Spaces + " FlagC = temp >= 0;"); + w.WriteLine(Spaces + " A = (byte)temp;"); + w.WriteLine(Spaces + "}"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SEC(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagC = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SED(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagD = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SEI(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagI = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SET(OpcodeInfo op, TextWriter w) + { + w.WriteLine(" int a; // TODO remove these extra checks"); // TODO remove these extra checks + w.WriteLine(" string b = Disassemble(PC, out a);"); + w.WriteLine(" if (b.StartsWith(\"ADC\") == false && b.StartsWith(\"EOR\") == false)"); + w.WriteLine(" Console.WriteLine(\"SETTING T FLAG, NEXT INSTRUCTION IS UNHANDLED: {0}\", b);"); + w.WriteLine(Spaces + "FlagT = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + w.WriteLine(Spaces + "goto AfterClearTFlag;"); + } + + private void ST0(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "WriteVDC(0,value8);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void ST1(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "WriteVDC(2,value8);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void ST2(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "WriteVDC(3,value8);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void STA(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, A);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void STX(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, X);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void STY(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, Y);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void STZ(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, 0);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TAM(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "for (byte reg=0; reg<8; reg++)"); + w.WriteLine(Spaces + "{"); + w.WriteLine(Spaces + " if ((value8 & (1 << reg)) != 0)"); + w.WriteLine(Spaces + " MPR[reg] = A;"); + w.WriteLine(Spaces + "}"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TAX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "X = A;"); + w.WriteLine(Spaces + SetNZ("X")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TAY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "Y = A;"); + w.WriteLine(Spaces + SetNZ("Y")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TMA(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + " if ((value8 & 0x01) != 0) A = MPR[0];"); + w.WriteLine(Spaces + "else if ((value8 & 0x02) != 0) A = MPR[1];"); + w.WriteLine(Spaces + "else if ((value8 & 0x04) != 0) A = MPR[2];"); + w.WriteLine(Spaces + "else if ((value8 & 0x08) != 0) A = MPR[3];"); + w.WriteLine(Spaces + "else if ((value8 & 0x10) != 0) A = MPR[4];"); + w.WriteLine(Spaces + "else if ((value8 & 0x20) != 0) A = MPR[5];"); + w.WriteLine(Spaces + "else if ((value8 & 0x40) != 0) A = MPR[6];"); + w.WriteLine(Spaces + "else if ((value8 & 0x80) != 0) A = MPR[7];"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TRB(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "WriteMemory(value16, (byte)(value8 & ~A));"); + w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;"); + w.WriteLine(Spaces + "FlagZ = (A & value8) == 0;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TSB(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "WriteMemory(value16, (byte)(value8 | A));"); + w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;"); + w.WriteLine(Spaces + "FlagZ = (A | value8) == 0;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TST(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "value8 = ReadMemory(PC++);"); + GetValue8(op, w, "temp8"); + w.WriteLine(Spaces + "FlagN = (temp8 & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagV = (temp8 & 0x40) != 0;"); + w.WriteLine(Spaces + "FlagZ = (temp8 & value8) == 0;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TSX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "X = S;"); + w.WriteLine(Spaces + SetNZ("X")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TXA(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "A = X;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TXS(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "S = X;"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void TYA(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "A = Y;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void RMB(OpcodeInfo op, TextWriter w, int bit) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "value8 &= 0x{0:X2};", (byte)(~(1 << bit))); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void SMB(OpcodeInfo op, TextWriter w, int bit) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "value8 |= 0x{0:X2};",(1< 0)"); + w.WriteLine(" {"); + + w.WriteLine("Console.WriteLine(State());"); + + // TODO interrupts, halt state, shit like that + + w.WriteLine(" byte opcode = ReadMemory(PC++);"); + w.WriteLine(" switch (opcode)"); + w.WriteLine(" {"); + + for (int i = 0; i < 256; i++) + { + if (Opcodes[i] != null) + EmulateOpcode(w, i); + } + + w.WriteLine(" default:"); + w.WriteLine(" throw new Exception(String.Format(\"Unhandled opcode: {0:X2}\", opcode));"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine("}"); + w.Close(); + } + + const string Spaces = " "; + + private void EmulateOpcode(TextWriter w, int opcode) + { + var op = Opcodes[opcode]; + w.WriteLine(" case 0x{0:X2}: // {1}", opcode, op); + switch (op.Instruction) + { + case "ADC": ADC(op, w); break; + case "AND": AND(op, w); break; + case "ASL": ASL(op, w); break; + case "BCC": Branch(op, w, "C", false); break; + case "BCS": Branch(op, w, "C", true); break; + case "BEQ": Branch(op, w, "Z", true); break; + case "BIT": BIT(op, w); break; + case "BMI": Branch(op, w, "N", true); break; + case "BNE": Branch(op, w, "Z", false); break; + case "BPL": Branch(op, w, "N", false); break; + case "BRK": w.WriteLine("throw new Exception(\"break\");"); break; + case "BVC": Branch(op, w, "V", false); break; + case "BVS": Branch(op, w, "V", true); break; + case "CLC": CLC(op, w); break; + case "CLD": CLD(op, w); break; + case "CLI": CLI(op, w); break; + case "CLV": CLV(op, w); break; + case "CMP": CMP_reg(op, w, "A"); break; + case "CPX": CMP_reg(op, w, "X"); break; + case "CPY": CMP_reg(op, w, "Y"); break; + case "DEC": DEC(op, w); break; + case "DEX": DEX(op, w); break; + case "DEY": DEY(op, w); break; + case "EOR": EOR(op, w); break; + case "INC": INC(op, w); break; + case "INX": INX(op, w); break; + case "INY": INY(op, w); break; + case "JMP": JMP(op, w); break; + case "JSR": JSR(op, w); break; + case "LDA": LDA(op, w); break; + case "LDX": LDX(op, w); break; + case "LDY": LDY(op, w); break; + case "LSR": LSR(op, w); break; + case "NOP": NOP(op, w); break; + case "ORA": ORA(op, w); break; + case "PHA": PHA(op, w); break; + case "PHP": PHP(op, w); break; + case "PLA": PLA(op, w); break; + case "PLP": PLP(op, w); break; + case "ROL": ROL(op, w); break; + case "ROR": ROR(op, w); break; + case "RTI": RTI(op, w); break; + case "RTS": RTS(op, w); break; + case "SBC": SBC(op, w); break; + case "SEC": SEC(op, w); break; + case "SED": SED(op, w); break; + case "SEI": SEI(op, w); break; + case "STA": STA(op, w); break; + case "STX": STX(op, w); break; + case "STY": STY(op, w); break; + case "TAX": TAX(op, w); break; + case "TAY": TAY(op, w); break; + case "TSX": TSX(op, w); break; + case "TXA": TXA(op, w); break; + case "TYA": TYA(op, w); break; + case "TXS": TXS(op, w); break; + } + w.WriteLine(Spaces+"break;"); + } + + private void GetValue8(OpcodeInfo op, TextWriter w, string dest) + { + // TODO it APPEARS that the +1 opcode penalty applies to all AbsoluteX, AbsoluteY, and IndirectY + // but this is not completely clear. the doc has some exceptions, but are they real? + switch (op.AddressMode) + { + case AddrMode.Immediate: + w.WriteLine(Spaces + dest + " = ReadMemory(PC++);"); break; + case AddrMode.ZeroPage: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadMemory(PC++));"); break; + case AddrMode.ZeroPageX: + w.WriteLine(Spaces + dest + " = ReadMemory((byte)(ReadMemory(PC++)+X));"); break; + case AddrMode.ZeroPageY: + w.WriteLine(Spaces + dest + " = ReadMemory((byte)(ReadMemory(PC++)+Y));"); break; + case AddrMode.Absolute: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadWord(PC)); PC += 2;"); break; + case AddrMode.AbsoluteX: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+X));"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.AbsoluteY: + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+Y));"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.IndirectX: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X)));"); break; + case AddrMode.IndirectY: + w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));"); + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));"); + w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + break; + } + } + + private void GetAddress(OpcodeInfo op, TextWriter w, string dest) + { + // TODO it APPEARS that the +1 opcode penalty applies to all AbsoluteX, AbsoluteY, and IndirectY + // but this is not completely clear. the doc has some exceptions, but are they real? + switch (op.AddressMode) + { + case AddrMode.ZeroPage: + w.WriteLine(Spaces + dest + " = ReadMemory(PC++);"); break; + case AddrMode.ZeroPageX: + w.WriteLine(Spaces + dest + " = (byte)(ReadMemory(PC++)+X);"); break; + case AddrMode.ZeroPageY: + w.WriteLine(Spaces + dest + " = (byte)(ReadMemory(PC++)+Y);"); break; + case AddrMode.Absolute: + w.WriteLine(Spaces + dest + " = ReadWord(PC); PC += 2;"); break; + case AddrMode.AbsoluteX: + w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+X);"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.AbsoluteY: + w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+Y);"); + w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.IndirectX: + w.WriteLine(Spaces + dest + " = ReadWordPageWrap((byte)(ReadMemory(PC++)+X));"); break; + case AddrMode.IndirectY: + w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));"); + w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);"); + w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + break; + case AddrMode.Relative: + w.WriteLine(Spaces + "rel8 = (sbyte)ReadMemory(PC++);"); + w.WriteLine(Spaces + dest +" = (ushort)(PC+rel8);"); + break; + } + } + + public void GenerateDisassembler(string file) + { + var w = new StreamWriter(file, false); + w.WriteLine("using System;"); + w.WriteLine(); + w.WriteLine("// Do not modify this file directly! This is GENERATED code."); + w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there."); + w.WriteLine(); + w.WriteLine("namespace BizHawk.Emulation.CPUs.M6502"); + w.WriteLine("{"); + w.WriteLine(" public partial class MOS6502"); + w.WriteLine(" {"); + w.WriteLine(" public string Disassemble(ushort pc, out int bytesToAdvance)"); + w.WriteLine(" {"); + w.WriteLine(" byte op = ReadMemory(pc);"); + w.WriteLine(" switch (op)"); + w.WriteLine(" {"); + + for (int i = 0; i < 256; i++) + { + if (Opcodes[i] != null) + DisassembleOpcode(w,i); + } + + w.WriteLine(" }"); + w.WriteLine(" bytesToAdvance = 1;"); + w.WriteLine(" return \"???\";"); + w.WriteLine(" }"); + w.WriteLine(" }"); + w.WriteLine("}"); + w.Close(); + } + + private void DisassembleOpcode(TextWriter w, int i) + { + var op = Opcodes[i]; + w.Write(" case 0x{0:X2}: ", i); + + string mstr; + switch (op.AddressMode) + { + case AddrMode.Implicit: mstr = "\""+op.Instruction+"\""; break; + case AddrMode.Accumulator: mstr = "\"" + op.Instruction + " A\""; break; + case AddrMode.Immediate: mstr = "string.Format(\""+op.Instruction+" #${0:X2}\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPage: mstr = "string.Format(\"" + op.Instruction + " ${0:X2}\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPageX: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},X\", ReadMemory(++pc))"; break; + case AddrMode.ZeroPageY: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},Y\", ReadMemory(++pc))"; break; + case AddrMode.Absolute: mstr = "string.Format(\"" + op.Instruction + " ${0:X4}\", ReadWord(++pc))"; break; + case AddrMode.AbsoluteX: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},X\", ReadWord(++pc))"; break; + case AddrMode.AbsoluteY: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},Y\", ReadWord(++pc))"; break; + case AddrMode.Indirect: mstr = "string.Format(\"" + op.Instruction + " (${0:X4})\", ReadWord(++pc))"; break; + case AddrMode.IndirectX: mstr = "string.Format(\"" + op.Instruction + " (${0:X2},X)\", ReadMemory(++pc))"; break; + case AddrMode.IndirectY: mstr = "string.Format(\"" + op.Instruction + " (${0:X2}),Y\", ReadMemory(++pc))"; break; + case AddrMode.Relative: mstr = "string.Format(\"" + op.Instruction + " {0}\", (sbyte)ReadMemory(++pc))"; break; + default: mstr = @"""?"""; break; + } + + w.Write("bytesToAdvance = {0}; ", op.Size); + w.WriteLine("return " + mstr + ";"); + } + } +} \ No newline at end of file diff --git a/CpuCoreGenerator/MOS 6502/Instructions.cs b/CpuCoreGenerator/MOS 6502/Instructions.cs new file mode 100644 index 0000000000..d53bd4f31a --- /dev/null +++ b/CpuCoreGenerator/MOS 6502/Instructions.cs @@ -0,0 +1,401 @@ +using System.IO; + +namespace M6502 +{ + public partial class CoreGenerator + { + private string SetNZ(string val) + { + return "P = (byte)((P & 0x7D) | TableNZ[" + val + "]);"; // NES version + //return "P = (byte)((P & 0x5D) | TableNZ[" + val + "]);"; // PCE version + } + + private void ADC(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "temp = value8 + A + (FlagC ? 1 : 0);"); + w.WriteLine(Spaces + "FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagC = temp > 0xFF;"); + w.WriteLine(Spaces + "A = (byte)temp;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void AND(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "A &= value8;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void ASL(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "FlagC = (A & 0x80) != 0;"); + w.WriteLine(Spaces + "A = (byte) (A << 1);"); + w.WriteLine(Spaces + SetNZ("A")); + } else { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "FlagC = (value8 & 0x80) != 0;"); + w.WriteLine(Spaces + "value8 = (byte)(value8 << 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void Branch(OpcodeInfo op, TextWriter w, string flag, bool cond) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "if (Flag"+flag+" == "+cond.ToString().ToLower()+") {"); + w.WriteLine(Spaces + " PendingCycles--; TotalExecutedCycles++;"); + w.WriteLine(Spaces + " if ((PC & 0xFF00) != (value16 & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + w.WriteLine(Spaces + " PC = value16;"); + w.WriteLine(Spaces + "}"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void BIT(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;"); + w.WriteLine(Spaces + "FlagZ = (A & value8) == 0;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void CLC(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagC = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void CLD(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagD = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void CLI(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagI = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void CLV(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagV = false;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void CMP_reg(OpcodeInfo op, TextWriter w, string reg) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "value16 = (ushort) (" + reg + " - value8);"); + w.WriteLine(Spaces + "FlagC = (" + reg + " >= value8);"); + w.WriteLine(Spaces + SetNZ("(byte)value16")); + w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles); + } + + private void DEC(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) - 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void DEX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("--X")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void DEY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("--Y")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void EOR(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "A ^= value8;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void INC(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) + 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void INX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("++X")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void INY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + SetNZ("++Y")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void JMP(OpcodeInfo op, TextWriter w) + { + switch (op.AddressMode) + { + case AddrMode.Absolute: w.WriteLine(Spaces+"PC = ReadWord(PC);"); break; + case AddrMode.Indirect: w.WriteLine(Spaces+"PC = ReadWordPageWrap(ReadWord(PC));"); break; + } + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void JSR(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "temp16 = (ushort)(PC+1);"); + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), (byte)(temp16 >> 8));"); + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), (byte)temp16);"); + w.WriteLine(Spaces + "PC = ReadWord(PC);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void LDA(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "A"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void LDX(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "X"); + w.WriteLine(Spaces + SetNZ("X")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void LDY(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "Y"); + w.WriteLine(Spaces + SetNZ("Y")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void LSR(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "FlagC = (A & 1) != 0;"); + w.WriteLine(Spaces + "A = (byte) (A >> 1);"); + w.WriteLine(Spaces + SetNZ("A")); + } else { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "FlagC = (value8 & 1) != 0;"); + w.WriteLine(Spaces + "value8 = (byte)(value8 >> 1);"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void NOP(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces+"PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void ORA(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "A |= value8;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void PHA(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), A);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void PHP(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), P);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void PLA(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "A = ReadMemory((ushort)(++S + 0x100));"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void PLP(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x100));"); +w.WriteLine("FlagT = true;//this seems wrong");//this seems wrong + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void ROL(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "temp8 = A;"); + w.WriteLine(Spaces + "A = (byte)((A << 1) | (P & 1));"); + w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;"); + w.WriteLine(Spaces + SetNZ("A")); + } + else + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "value8 = (byte)((value8 << 1) | (P & 1));"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void ROR(OpcodeInfo op, TextWriter w) + { + if (op.AddressMode == AddrMode.Accumulator) + { + w.WriteLine(Spaces + "temp8 = A;"); + w.WriteLine(Spaces + "A = (byte)((A >> 1) | ((P & 1)<<7));"); + w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;"); + w.WriteLine(Spaces + SetNZ("A")); + } + else + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);"); + w.WriteLine(Spaces + "value8 = (byte)((value8 >> 1) | ((P & 1)<<7));"); + w.WriteLine(Spaces + "WriteMemory(value16, value8);"); + w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;"); + w.WriteLine(Spaces + SetNZ("value8")); + } + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void RTI(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x100));"); +w.WriteLine("FlagT = true;// this seems wrong");//this seems wrong + w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x100));"); + w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void RTS(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x100));"); + w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8);"); + w.WriteLine(Spaces + "PC++;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void SBC(OpcodeInfo op, TextWriter w) + { + GetValue8(op, w, "value8"); + w.WriteLine(Spaces + "temp = A - value8 - (FlagC?0:1);"); + w.WriteLine(Spaces + "FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;"); + w.WriteLine(Spaces + "FlagC = temp >= 0;"); + w.WriteLine(Spaces + "A = (byte)temp;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void SEC(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagC = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void SED(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagD = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void SEI(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "FlagI = true;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void STA(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, A);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void STX(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, X);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void STY(OpcodeInfo op, TextWriter w) + { + GetAddress(op, w, "value16"); + w.WriteLine(Spaces + "WriteMemory(value16, Y);"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void TAX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "X = A;"); + w.WriteLine(Spaces + SetNZ("X")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void TAY(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "Y = A;"); + w.WriteLine(Spaces + SetNZ("Y")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void TSX(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "X = S;"); + w.WriteLine(Spaces + SetNZ("X")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void TXA(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "A = X;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void TXS(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "S = X;"); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + + private void TYA(OpcodeInfo op, TextWriter w) + { + w.WriteLine(Spaces + "A = Y;"); + w.WriteLine(Spaces + SetNZ("A")); + w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles); + } + } +} diff --git a/CpuCoreGenerator/Program.cs b/CpuCoreGenerator/Program.cs new file mode 100644 index 0000000000..8d95b3b855 --- /dev/null +++ b/CpuCoreGenerator/Program.cs @@ -0,0 +1,15 @@ +class Program +{ + static void Main() + { + var x = new M6502.CoreGenerator(); + x.InitOpcodeTable(); + x.GenerateDisassembler("../../../BizHawk.Emulation/CPUs/MOS 6502/Disassembler.cs"); + x.GenerateExecutor("../../../BizHawk.Emulation/CPUs/MOS 6502/Execute.cs"); + + var y = new HuC6280.CoreGenerator(); + y.InitOpcodeTable(); + y.GenerateDisassembler("../../../BizHawk.Emulation/CPUs/HuC6280/Disassembler.cs"); + y.GenerateExecutor("../../../BizHawk.Emulation/CPUs/HuC6280/Execute.cs"); + } +} diff --git a/CpuCoreGenerator/Properties/AssemblyInfo.cs b/CpuCoreGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a7058b8685 --- /dev/null +++ b/CpuCoreGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("M6502CoreGenerator")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("M6502CoreGenerator")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ab5eef8f-50f4-4c39-af46-8c5ba9404c6b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SlimDX.dll b/SlimDX.dll new file mode 100644 index 0000000000000000000000000000000000000000..b14c6f9adcb0180a656c6fe9c564f8c96a151349 GIT binary patch literal 3335680 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 z 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�AiMYJ+l*sbcQCpkg1S{Y3GTxHZX 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

d)+*2yI&%j0ii9 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%0Ax+$u#}_QNLQ6iF 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

+Rd~*Hz7> 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