diff --git a/VBA.vcproj b/VBA.vcproj
index 88c3a3c9..861b63ea 100644
--- a/VBA.vcproj
+++ b/VBA.vcproj
@@ -51,7 +51,7 @@
-
-
-
-
@@ -683,16 +675,40 @@
>
+
+
+
+
+
+
+
+
+
+
+
@@ -1002,6 +1022,14 @@
RelativePath=".\src\win32\RomInfo.cpp"
>
+
+
+
+
@@ -1014,10 +1042,6 @@
RelativePath=".\src\win32\TileView.cpp"
>
-
-
@@ -1106,6 +1130,10 @@
RelativePath=".\src\win32\DirectSound.cpp"
>
+
+
@@ -1155,6 +1183,130 @@
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/src/2xSaI.cpp b/src/2xSaI.cpp
index 61eb116b..1aacc0a8 100644
--- a/src/2xSaI.cpp
+++ b/src/2xSaI.cpp
@@ -1,6 +1,8 @@
#include "System.h"
#include "Port.h"
+extern int RGB_LOW_BITS_MASK;
+
extern "C"
{
@@ -48,6 +50,7 @@ int Init_2xSaI(u32 BitFormat)
greenMask = 0x7E0;
qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0xF7DEF7DE;
hq2x_init(16);
+ RGB_LOW_BITS_MASK = 0x0821;
} else if (BitFormat == 555) {
colorMask = 0x7BDE7BDE;
lowPixelMask = 0x04210421;
@@ -57,6 +60,7 @@ int Init_2xSaI(u32 BitFormat)
greenMask = 0x3E0;
qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0x7BDE7BDE;
hq2x_init(15);
+ RGB_LOW_BITS_MASK = 0x0421;
} else {
return 0;
}
@@ -67,6 +71,7 @@ int Init_2xSaI(u32 BitFormat)
qlowpixelMask = 0x030303;
qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0xfefefe;
hq2x_init(32);
+ RGB_LOW_BITS_MASK = 0x010101;
} else
return 0;
diff --git a/src/AutoBuild.h b/src/AutoBuild.h
new file mode 100644
index 00000000..425c57b0
--- /dev/null
+++ b/src/AutoBuild.h
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef __AUTOBUILD_H__
+#define __AUTOBUILD_H__
+#ifndef VERSION
+#define VERSION "1.8.0"
+#endif
+//change the FALSE to TRUE for autoincrement of build number
+#define INCREMENT_VERSION FALSE
+#define FILEVER 1,8,0,600
+#define PRODUCTVER 1,8,0,600
+#define STRFILEVER "1, 8, 0, 600\0"
+#define STRPRODUCTVER "1, 8, 0, 600\0"
+#endif //__AUTOBUILD_H__
diff --git a/src/Cheats.cpp b/src/Cheats.cpp
index 2eeae9b1..c8290495 100644
--- a/src/Cheats.cpp
+++ b/src/Cheats.cpp
@@ -1,2770 +1,2895 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-#include
-#include
-
-#include "GBA.h"
-#include "GBAinline.h"
-#include "Cheats.h"
-#include "Globals.h"
-#include "NLS.h"
-#include "Util.h"
-
-/**
- * Gameshark code types: (based on AR v1.0)
- *
- * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
- * DEADFACE XXXXXXXX - changes decryption seeds // Not supported by VBA.
- * 0AAAAAAA 000000YY - 8-bit constant write
- * 1AAAAAAA 0000YYYY - 16-bit constant write
- * 2AAAAAAA YYYYYYYY - 32-bit constant write
- * 30XXAAAA YYYYYYYY - 32bit Group Write, 8/16/32bit Sub/Add (depending on the XX value).
- * 6AAAAAAA Z000YYYY - 16-bit ROM Patch (address >> 1). Z selects the Rom Patching register.
- * - AR v1/2 hardware only supports Z=0.
- * - AR v3 hardware should support Z=0,1,2 or 3.
- * 8A1AAAAA 000000YY - 8-bit button write
- * 8A2AAAAA 0000YYYY - 16-bit button write
- * 8A4AAAAA YYYYYYYY - 32-bit button write // BUGGY ! Only writes 00000000 on the AR v1.0.
- * 80F00000 0000YYYY - button slow motion
- * DAAAAAAA 00Z0YYYY - Z = 0 : if 16-bit value at address != YYYY skip next line
- * - Z = 1 : if 16-bit value at address == YYYY skip next line
- * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip next line
- * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip next line
- * E0CCYYYY ZAAAAAAA - Z = 0 : if 16-bit value at address != YYYY skip CC lines
- * - Z = 1 : if 16-bit value at address == YYYY skip CC lines
- * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip CC lines
- * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip CC lines
- * FAAAAAAA 0000YYYY - Master code function
- *
- *
- *
- * CodeBreaker codes types: (based on the CBA clone "Cheatcode S" v1.1)
- *
- * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
- * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
- * + 0x08000100))
- * 2AAAAAAA YYYY - 16-bit or
- * 3AAAAAAA YYYY - 8-bit constant write
- * 4AAAAAAA YYYY - Slide code
- * XXXXCCCC IIII (C is count and I is address increment, X is value incr.)
- * 5AAAAAAA CCCC - Super code (Write bytes to address, 2*CCCC is count)
- * BBBBBBBB BBBB
- * 6AAAAAAA YYYY - 16-bit and
- * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
- * 8AAAAAAA YYYY - 16-bit constant write
- * 9AAAAAAA YYYY - change decryption (when first code only?)
- * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
- * BAAAAAAA YYYY - if 16-bit value at address <= YYYY skip next code
- * CAAAAAAA YYYY - if 16-bit value at address >= YYYY skip next code
- * D00000X0 YYYY - if button keys ... enable next code (else skip next code)
- * EAAAAAAA YYYY - increase 16/32bit value stored in address
- * FAAAAAAA YYYY - if 16-bit value at address AND YYYY = 0 then skip next code
- **/
-
-#define UNKNOWN_CODE -1
-#define INT_8_BIT_WRITE 0
-#define INT_16_BIT_WRITE 1
-#define INT_32_BIT_WRITE 2
-#define GSA_16_BIT_ROM_PATCH 3
-#define GSA_8_BIT_GS_WRITE 4
-#define GSA_16_BIT_GS_WRITE 5
-#define GSA_32_BIT_GS_WRITE 6
-#define CBA_IF_KEYS_PRESSED 7
-#define CBA_IF_TRUE 8
-#define CBA_SLIDE_CODE 9
-#define CBA_IF_FALSE 10
-#define CBA_AND 11
-#define GSA_8_BIT_GS_WRITE2 12
-#define GSA_16_BIT_GS_WRITE2 13
-#define GSA_32_BIT_GS_WRITE2 14
-#define GSA_16_BIT_ROM_PATCH2C 15
-#define GSA_8_BIT_SLIDE 16
-#define GSA_16_BIT_SLIDE 17
-#define GSA_32_BIT_SLIDE 18
-#define GSA_8_BIT_IF_TRUE 19
-#define GSA_32_BIT_IF_TRUE 20
-#define GSA_8_BIT_IF_FALSE 21
-#define GSA_32_BIT_IF_FALSE 22
-#define GSA_8_BIT_FILL 23
-#define GSA_16_BIT_FILL 24
-#define GSA_8_BIT_IF_TRUE2 25
-#define GSA_16_BIT_IF_TRUE2 26
-#define GSA_32_BIT_IF_TRUE2 27
-#define GSA_8_BIT_IF_FALSE2 28
-#define GSA_16_BIT_IF_FALSE2 29
-#define GSA_32_BIT_IF_FALSE2 30
-#define GSA_SLOWDOWN 31
-#define CBA_ADD 32
-#define CBA_OR 33
-#define CBA_LT 34
-#define CBA_GT 35
-#define CBA_SUPER 36
-#define GSA_8_BIT_POINTER 37
-#define GSA_16_BIT_POINTER 38
-#define GSA_32_BIT_POINTER 39
-#define GSA_8_BIT_ADD 40
-#define GSA_16_BIT_ADD 41
-#define GSA_32_BIT_ADD 42
-#define GSA_8_BIT_IF_LOWER_U 43
-#define GSA_16_BIT_IF_LOWER_U 44
-#define GSA_32_BIT_IF_LOWER_U 45
-#define GSA_8_BIT_IF_HIGHER_U 46
-#define GSA_16_BIT_IF_HIGHER_U 47
-#define GSA_32_BIT_IF_HIGHER_U 48
-#define GSA_8_BIT_IF_AND 49
-#define GSA_16_BIT_IF_AND 50
-#define GSA_32_BIT_IF_AND 51
-#define GSA_8_BIT_IF_LOWER_U2 52
-#define GSA_16_BIT_IF_LOWER_U2 53
-#define GSA_32_BIT_IF_LOWER_U2 54
-#define GSA_8_BIT_IF_HIGHER_U2 55
-#define GSA_16_BIT_IF_HIGHER_U2 56
-#define GSA_32_BIT_IF_HIGHER_U2 57
-#define GSA_8_BIT_IF_AND2 58
-#define GSA_16_BIT_IF_AND2 59
-#define GSA_32_BIT_IF_AND2 60
-#define GSA_ALWAYS 61
-#define GSA_ALWAYS2 62
-#define GSA_8_BIT_IF_LOWER_S 63
-#define GSA_16_BIT_IF_LOWER_S 64
-#define GSA_32_BIT_IF_LOWER_S 65
-#define GSA_8_BIT_IF_HIGHER_S 66
-#define GSA_16_BIT_IF_HIGHER_S 67
-#define GSA_32_BIT_IF_HIGHER_S 68
-#define GSA_8_BIT_IF_LOWER_S2 69
-#define GSA_16_BIT_IF_LOWER_S2 70
-#define GSA_32_BIT_IF_LOWER_S2 71
-#define GSA_8_BIT_IF_HIGHER_S2 72
-#define GSA_16_BIT_IF_HIGHER_S2 73
-#define GSA_32_BIT_IF_HIGHER_S2 74
-#define GSA_16_BIT_WRITE_IOREGS 75
-#define GSA_32_BIT_WRITE_IOREGS 76
-#define GSA_CODES_ON 77
-#define GSA_8_BIT_IF_TRUE3 78
-#define GSA_16_BIT_IF_TRUE3 79
-#define GSA_32_BIT_IF_TRUE3 80
-#define GSA_8_BIT_IF_FALSE3 81
-#define GSA_16_BIT_IF_FALSE3 82
-#define GSA_32_BIT_IF_FALSE3 83
-#define GSA_8_BIT_IF_LOWER_S3 84
-#define GSA_16_BIT_IF_LOWER_S3 85
-#define GSA_32_BIT_IF_LOWER_S3 86
-#define GSA_8_BIT_IF_HIGHER_S3 87
-#define GSA_16_BIT_IF_HIGHER_S3 88
-#define GSA_32_BIT_IF_HIGHER_S3 89
-#define GSA_8_BIT_IF_LOWER_U3 90
-#define GSA_16_BIT_IF_LOWER_U3 91
-#define GSA_32_BIT_IF_LOWER_U3 92
-#define GSA_8_BIT_IF_HIGHER_U3 93
-#define GSA_16_BIT_IF_HIGHER_U3 94
-#define GSA_32_BIT_IF_HIGHER_U3 95
-#define GSA_8_BIT_IF_AND3 96
-#define GSA_16_BIT_IF_AND3 97
-#define GSA_32_BIT_IF_AND3 98
-#define GSA_ALWAYS3 99
-#define GSA_16_BIT_ROM_PATCH2D 100
-#define GSA_16_BIT_ROM_PATCH2E 101
-#define GSA_16_BIT_ROM_PATCH2F 102
-#define GSA_GROUP_WRITE 103
-#define GSA_32_BIT_ADD2 104
-#define GSA_32_BIT_SUB2 105
-#define GSA_16_BIT_IF_LOWER_OR_EQ_U 106
-#define GSA_16_BIT_IF_HIGHER_OR_EQ_U 107
-#define GSA_16_BIT_MIF_TRUE 108
-#define GSA_16_BIT_MIF_FALSE 109
-#define GSA_16_BIT_MIF_LOWER_OR_EQ_U 110
-#define GSA_16_BIT_MIF_HIGHER_OR_EQ_U 111
-
-CheatsData cheatsList[100];
-int cheatsNumber = 0;
-u32 rompatch2addr [4];
-u16 rompatch2val [4];
-u16 rompatch2oldval [4];
-
-u8 cheatsCBASeedBuffer[0x30];
-u32 cheatsCBASeed[4];
-u32 cheatsCBATemporaryValue = 0;
-u16 cheatsCBATable[256];
-bool cheatsCBATableGenerated = false;
-u16 super = 0;
-
-u8 cheatsCBACurrentSeed[12] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-u32 seeds_v1[4];
-u32 seeds_v3[4];
-
-u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2);
-
-//seed tables for AR v1
-u8 v1_deadtable1[256] = {
- 0x31, 0x1C, 0x23, 0xE5, 0x89, 0x8E, 0xA1, 0x37, 0x74, 0x6D, 0x67, 0xFC, 0x1F, 0xC0, 0xB1, 0x94,
- 0x3B, 0x05, 0x56, 0x86, 0x00, 0x24, 0xF0, 0x17, 0x72, 0xA2, 0x3D, 0x1B, 0xE3, 0x17, 0xC5, 0x0B,
- 0xB9, 0xE2, 0xBD, 0x58, 0x71, 0x1B, 0x2C, 0xFF, 0xE4, 0xC9, 0x4C, 0x5E, 0xC9, 0x55, 0x33, 0x45,
- 0x7C, 0x3F, 0xB2, 0x51, 0xFE, 0x10, 0x7E, 0x75, 0x3C, 0x90, 0x8D, 0xDA, 0x94, 0x38, 0xC3, 0xE9,
- 0x95, 0xEA, 0xCE, 0xA6, 0x06, 0xE0, 0x4F, 0x3F, 0x2A, 0xE3, 0x3A, 0xE4, 0x43, 0xBD, 0x7F, 0xDA,
- 0x55, 0xF0, 0xEA, 0xCB, 0x2C, 0xA8, 0x47, 0x61, 0xA0, 0xEF, 0xCB, 0x13, 0x18, 0x20, 0xAF, 0x3E,
- 0x4D, 0x9E, 0x1E, 0x77, 0x51, 0xC5, 0x51, 0x20, 0xCF, 0x21, 0xF9, 0x39, 0x94, 0xDE, 0xDD, 0x79,
- 0x4E, 0x80, 0xC4, 0x9D, 0x94, 0xD5, 0x95, 0x01, 0x27, 0x27, 0xBD, 0x6D, 0x78, 0xB5, 0xD1, 0x31,
- 0x6A, 0x65, 0x74, 0x74, 0x58, 0xB3, 0x7C, 0xC9, 0x5A, 0xED, 0x50, 0x03, 0xC4, 0xA2, 0x94, 0x4B,
- 0xF0, 0x58, 0x09, 0x6F, 0x3E, 0x7D, 0xAE, 0x7D, 0x58, 0xA0, 0x2C, 0x91, 0xBB, 0xE1, 0x70, 0xEB,
- 0x73, 0xA6, 0x9A, 0x44, 0x25, 0x90, 0x16, 0x62, 0x53, 0xAE, 0x08, 0xEB, 0xDC, 0xF0, 0xEE, 0x77,
- 0xC2, 0xDE, 0x81, 0xE8, 0x30, 0x89, 0xDB, 0xFE, 0xBC, 0xC2, 0xDF, 0x26, 0xE9, 0x8B, 0xD6, 0x93,
- 0xF0, 0xCB, 0x56, 0x90, 0xC0, 0x46, 0x68, 0x15, 0x43, 0xCB, 0xE9, 0x98, 0xE3, 0xAF, 0x31, 0x25,
- 0x4D, 0x7B, 0xF3, 0xB1, 0x74, 0xE2, 0x64, 0xAC, 0xD9, 0xF6, 0xA0, 0xD5, 0x0B, 0x9B, 0x49, 0x52,
- 0x69, 0x3B, 0x71, 0x00, 0x2F, 0xBB, 0xBA, 0x08, 0xB1, 0xAE, 0xBB, 0xB3, 0xE1, 0xC9, 0xA6, 0x7F,
- 0x17, 0x97, 0x28, 0x72, 0x12, 0x6E, 0x91, 0xAE, 0x3A, 0xA2, 0x35, 0x46, 0x27, 0xF8, 0x12, 0x50
-};
-u8 v1_deadtable2[256] = {
- 0xD8, 0x65, 0x04, 0xC2, 0x65, 0xD5, 0xB0, 0x0C, 0xDF, 0x9D, 0xF0, 0xC3, 0x9A, 0x17, 0xC9, 0xA6,
- 0xE1, 0xAC, 0x0D, 0x14, 0x2F, 0x3C, 0x2C, 0x87, 0xA2, 0xBF, 0x4D, 0x5F, 0xAC, 0x2D, 0x9D, 0xE1,
- 0x0C, 0x9C, 0xE7, 0x7F, 0xFC, 0xA8, 0x66, 0x59, 0xAC, 0x18, 0xD7, 0x05, 0xF0, 0xBF, 0xD1, 0x8B,
- 0x35, 0x9F, 0x59, 0xB4, 0xBA, 0x55, 0xB2, 0x85, 0xFD, 0xB1, 0x72, 0x06, 0x73, 0xA4, 0xDB, 0x48,
- 0x7B, 0x5F, 0x67, 0xA5, 0x95, 0xB9, 0xA5, 0x4A, 0xCF, 0xD1, 0x44, 0xF3, 0x81, 0xF5, 0x6D, 0xF6,
- 0x3A, 0xC3, 0x57, 0x83, 0xFA, 0x8E, 0x15, 0x2A, 0xA2, 0x04, 0xB2, 0x9D, 0xA8, 0x0D, 0x7F, 0xB8,
- 0x0F, 0xF6, 0xAC, 0xBE, 0x97, 0xCE, 0x16, 0xE6, 0x31, 0x10, 0x60, 0x16, 0xB5, 0x83, 0x45, 0xEE,
- 0xD7, 0x5F, 0x2C, 0x08, 0x58, 0xB1, 0xFD, 0x7E, 0x79, 0x00, 0x34, 0xAD, 0xB5, 0x31, 0x34, 0x39,
- 0xAF, 0xA8, 0xDD, 0x52, 0x6A, 0xB0, 0x60, 0x35, 0xB8, 0x1D, 0x52, 0xF5, 0xF5, 0x30, 0x00, 0x7B,
- 0xF4, 0xBA, 0x03, 0xCB, 0x3A, 0x84, 0x14, 0x8A, 0x6A, 0xEF, 0x21, 0xBD, 0x01, 0xD8, 0xA0, 0xD4,
- 0x43, 0xBE, 0x23, 0xE7, 0x76, 0x27, 0x2C, 0x3F, 0x4D, 0x3F, 0x43, 0x18, 0xA7, 0xC3, 0x47, 0xA5,
- 0x7A, 0x1D, 0x02, 0x55, 0x09, 0xD1, 0xFF, 0x55, 0x5E, 0x17, 0xA0, 0x56, 0xF4, 0xC9, 0x6B, 0x90,
- 0xB4, 0x80, 0xA5, 0x07, 0x22, 0xFB, 0x22, 0x0D, 0xD9, 0xC0, 0x5B, 0x08, 0x35, 0x05, 0xC1, 0x75,
- 0x4F, 0xD0, 0x51, 0x2D, 0x2E, 0x5E, 0x69, 0xE7, 0x3B, 0xC2, 0xDA, 0xFF, 0xF6, 0xCE, 0x3E, 0x76,
- 0xE8, 0x36, 0x8C, 0x39, 0xD8, 0xF3, 0xE9, 0xA6, 0x42, 0xE6, 0xC1, 0x4C, 0x05, 0xBE, 0x17, 0xF2,
- 0x5C, 0x1B, 0x19, 0xDB, 0x0F, 0xF3, 0xF8, 0x49, 0xEB, 0x36, 0xF6, 0x40, 0x6F, 0xAD, 0xC1, 0x8C
-};
-
-//seed tables for AR v3
-u8 v3_deadtable1[256] = {
- 0xD0, 0xFF, 0xBA, 0xE5, 0xC1, 0xC7, 0xDB, 0x5B, 0x16, 0xE3, 0x6E, 0x26, 0x62, 0x31, 0x2E, 0x2A,
- 0xD1, 0xBB, 0x4A, 0xE6, 0xAE, 0x2F, 0x0A, 0x90, 0x29, 0x90, 0xB6, 0x67, 0x58, 0x2A, 0xB4, 0x45,
- 0x7B, 0xCB, 0xF0, 0x73, 0x84, 0x30, 0x81, 0xC2, 0xD7, 0xBE, 0x89, 0xD7, 0x4E, 0x73, 0x5C, 0xC7,
- 0x80, 0x1B, 0xE5, 0xE4, 0x43, 0xC7, 0x46, 0xD6, 0x6F, 0x7B, 0xBF, 0xED, 0xE5, 0x27, 0xD1, 0xB5,
- 0xD0, 0xD8, 0xA3, 0xCB, 0x2B, 0x30, 0xA4, 0xF0, 0x84, 0x14, 0x72, 0x5C, 0xFF, 0xA4, 0xFB, 0x54,
- 0x9D, 0x70, 0xE2, 0xFF, 0xBE, 0xE8, 0x24, 0x76, 0xE5, 0x15, 0xFB, 0x1A, 0xBC, 0x87, 0x02, 0x2A,
- 0x58, 0x8F, 0x9A, 0x95, 0xBD, 0xAE, 0x8D, 0x0C, 0xA5, 0x4C, 0xF2, 0x5C, 0x7D, 0xAD, 0x51, 0xFB,
- 0xB1, 0x22, 0x07, 0xE0, 0x29, 0x7C, 0xEB, 0x98, 0x14, 0xC6, 0x31, 0x97, 0xE4, 0x34, 0x8F, 0xCC,
- 0x99, 0x56, 0x9F, 0x78, 0x43, 0x91, 0x85, 0x3F, 0xC2, 0xD0, 0xD1, 0x80, 0xD1, 0x77, 0xA7, 0xE2,
- 0x43, 0x99, 0x1D, 0x2F, 0x8B, 0x6A, 0xE4, 0x66, 0x82, 0xF7, 0x2B, 0x0B, 0x65, 0x14, 0xC0, 0xC2,
- 0x1D, 0x96, 0x78, 0x1C, 0xC4, 0xC3, 0xD2, 0xB1, 0x64, 0x07, 0xD7, 0x6F, 0x02, 0xE9, 0x44, 0x31,
- 0xDB, 0x3C, 0xEB, 0x93, 0xED, 0x9A, 0x57, 0x05, 0xB9, 0x0E, 0xAF, 0x1F, 0x48, 0x11, 0xDC, 0x35,
- 0x6C, 0xB8, 0xEE, 0x2A, 0x48, 0x2B, 0xBC, 0x89, 0x12, 0x59, 0xCB, 0xD1, 0x18, 0xEA, 0x72, 0x11,
- 0x01, 0x75, 0x3B, 0xB5, 0x56, 0xF4, 0x8B, 0xA0, 0x41, 0x75, 0x86, 0x7B, 0x94, 0x12, 0x2D, 0x4C,
- 0x0C, 0x22, 0xC9, 0x4A, 0xD8, 0xB1, 0x8D, 0xF0, 0x55, 0x2E, 0x77, 0x50, 0x1C, 0x64, 0x77, 0xAA,
- 0x3E, 0xAC, 0xD3, 0x3D, 0xCE, 0x60, 0xCA, 0x5D, 0xA0, 0x92, 0x78, 0xC6, 0x51, 0xFE, 0xF9, 0x30
-};
-u8 v3_deadtable2[256] = {
- 0xAA, 0xAF, 0xF0, 0x72, 0x90, 0xF7, 0x71, 0x27, 0x06, 0x11, 0xEB, 0x9C, 0x37, 0x12, 0x72, 0xAA,
- 0x65, 0xBC, 0x0D, 0x4A, 0x76, 0xF6, 0x5C, 0xAA, 0xB0, 0x7A, 0x7D, 0x81, 0xC1, 0xCE, 0x2F, 0x9F,
- 0x02, 0x75, 0x38, 0xC8, 0xFC, 0x66, 0x05, 0xC2, 0x2C, 0xBD, 0x91, 0xAD, 0x03, 0xB1, 0x88, 0x93,
- 0x31, 0xC6, 0xAB, 0x40, 0x23, 0x43, 0x76, 0x54, 0xCA, 0xE7, 0x00, 0x96, 0x9F, 0xD8, 0x24, 0x8B,
- 0xE4, 0xDC, 0xDE, 0x48, 0x2C, 0xCB, 0xF7, 0x84, 0x1D, 0x45, 0xE5, 0xF1, 0x75, 0xA0, 0xED, 0xCD,
- 0x4B, 0x24, 0x8A, 0xB3, 0x98, 0x7B, 0x12, 0xB8, 0xF5, 0x63, 0x97, 0xB3, 0xA6, 0xA6, 0x0B, 0xDC,
- 0xD8, 0x4C, 0xA8, 0x99, 0x27, 0x0F, 0x8F, 0x94, 0x63, 0x0F, 0xB0, 0x11, 0x94, 0xC7, 0xE9, 0x7F,
- 0x3B, 0x40, 0x72, 0x4C, 0xDB, 0x84, 0x78, 0xFE, 0xB8, 0x56, 0x08, 0x80, 0xDF, 0x20, 0x2F, 0xB9,
- 0x66, 0x2D, 0x60, 0x63, 0xF5, 0x18, 0x15, 0x1B, 0x86, 0x85, 0xB9, 0xB4, 0x68, 0x0E, 0xC6, 0xD1,
- 0x8A, 0x81, 0x2B, 0xB3, 0xF6, 0x48, 0xF0, 0x4F, 0x9C, 0x28, 0x1C, 0xA4, 0x51, 0x2F, 0xD7, 0x4B,
- 0x17, 0xE7, 0xCC, 0x50, 0x9F, 0xD0, 0xD1, 0x40, 0x0C, 0x0D, 0xCA, 0x83, 0xFA, 0x5E, 0xCA, 0xEC,
- 0xBF, 0x4E, 0x7C, 0x8F, 0xF0, 0xAE, 0xC2, 0xD3, 0x28, 0x41, 0x9B, 0xC8, 0x04, 0xB9, 0x4A, 0xBA,
- 0x72, 0xE2, 0xB5, 0x06, 0x2C, 0x1E, 0x0B, 0x2C, 0x7F, 0x11, 0xA9, 0x26, 0x51, 0x9D, 0x3F, 0xF8,
- 0x62, 0x11, 0x2E, 0x89, 0xD2, 0x9D, 0x35, 0xB1, 0xE4, 0x0A, 0x4D, 0x93, 0x01, 0xA7, 0xD1, 0x2D,
- 0x00, 0x87, 0xE2, 0x2D, 0xA4, 0xE9, 0x0A, 0x06, 0x66, 0xF8, 0x1F, 0x44, 0x75, 0xB5, 0x6B, 0x1C,
- 0xFC, 0x31, 0x09, 0x48, 0xA3, 0xFF, 0x92, 0x12, 0x58, 0xE9, 0xFA, 0xAE, 0x4F, 0xE2, 0xB4, 0xCC
-};
-
-#define debuggerReadMemory(addr) \
- READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-#define debuggerReadHalfWord(addr) \
- READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-#define debuggerReadByte(addr) \
- map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
-
-#define debuggerWriteMemory(addr, value) \
- WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
-
-#define debuggerWriteHalfWord(addr, value) \
- WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
-
-#define debuggerWriteByte(addr, value) \
- map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
-
-
-#define CHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9'))
-
-#define CHEAT_PATCH_ROM_16BIT(a,v) \
- WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v);
-
-static bool isMultilineWithData(int i)
-{
- // we consider it a multiline code if it has more than one line of data
- // otherwise, it can still be considered a single code
- // (Only CBA codes can be true multilines !!!)
- if(i < cheatsNumber && i >= 0)
- switch(cheatsList[i].size) {
- case INT_8_BIT_WRITE:
- case INT_16_BIT_WRITE:
- case INT_32_BIT_WRITE:
- case GSA_16_BIT_ROM_PATCH:
- case GSA_8_BIT_GS_WRITE:
- case GSA_16_BIT_GS_WRITE:
- case GSA_32_BIT_GS_WRITE:
- case CBA_AND:
- case CBA_IF_KEYS_PRESSED:
- case CBA_IF_TRUE:
- case CBA_IF_FALSE:
- case GSA_8_BIT_IF_TRUE:
- case GSA_32_BIT_IF_TRUE:
- case GSA_8_BIT_IF_FALSE:
- case GSA_32_BIT_IF_FALSE:
- case GSA_8_BIT_FILL:
- case GSA_16_BIT_FILL:
- case GSA_8_BIT_IF_TRUE2:
- case GSA_16_BIT_IF_TRUE2:
- case GSA_32_BIT_IF_TRUE2:
- case GSA_8_BIT_IF_FALSE2:
- case GSA_16_BIT_IF_FALSE2:
- case GSA_32_BIT_IF_FALSE2:
- case GSA_SLOWDOWN:
- case CBA_ADD:
- case CBA_OR:
- case CBA_LT:
- case CBA_GT:
- case GSA_8_BIT_POINTER:
- case GSA_16_BIT_POINTER:
- case GSA_32_BIT_POINTER:
- case GSA_8_BIT_ADD:
- case GSA_16_BIT_ADD:
- case GSA_32_BIT_ADD:
- case GSA_8_BIT_IF_LOWER_U:
- case GSA_16_BIT_IF_LOWER_U:
- case GSA_32_BIT_IF_LOWER_U:
- case GSA_8_BIT_IF_HIGHER_U:
- case GSA_16_BIT_IF_HIGHER_U:
- case GSA_32_BIT_IF_HIGHER_U:
- case GSA_8_BIT_IF_AND:
- case GSA_16_BIT_IF_AND:
- case GSA_32_BIT_IF_AND:
- case GSA_8_BIT_IF_LOWER_U2:
- case GSA_16_BIT_IF_LOWER_U2:
- case GSA_32_BIT_IF_LOWER_U2:
- case GSA_8_BIT_IF_HIGHER_U2:
- case GSA_16_BIT_IF_HIGHER_U2:
- case GSA_32_BIT_IF_HIGHER_U2:
- case GSA_8_BIT_IF_AND2:
- case GSA_16_BIT_IF_AND2:
- case GSA_32_BIT_IF_AND2:
- case GSA_ALWAYS:
- case GSA_ALWAYS2:
- case GSA_8_BIT_IF_LOWER_S:
- case GSA_16_BIT_IF_LOWER_S:
- case GSA_32_BIT_IF_LOWER_S:
- case GSA_8_BIT_IF_HIGHER_S:
- case GSA_16_BIT_IF_HIGHER_S:
- case GSA_32_BIT_IF_HIGHER_S:
- case GSA_8_BIT_IF_LOWER_S2:
- case GSA_16_BIT_IF_LOWER_S2:
- case GSA_32_BIT_IF_LOWER_S2:
- case GSA_8_BIT_IF_HIGHER_S2:
- case GSA_16_BIT_IF_HIGHER_S2:
- case GSA_32_BIT_IF_HIGHER_S2:
- case GSA_16_BIT_WRITE_IOREGS:
- case GSA_32_BIT_WRITE_IOREGS:
- case GSA_CODES_ON:
- case GSA_8_BIT_IF_TRUE3:
- case GSA_16_BIT_IF_TRUE3:
- case GSA_32_BIT_IF_TRUE3:
- case GSA_8_BIT_IF_FALSE3:
- case GSA_16_BIT_IF_FALSE3:
- case GSA_32_BIT_IF_FALSE3:
- case GSA_8_BIT_IF_LOWER_S3:
- case GSA_16_BIT_IF_LOWER_S3:
- case GSA_32_BIT_IF_LOWER_S3:
- case GSA_8_BIT_IF_HIGHER_S3:
- case GSA_16_BIT_IF_HIGHER_S3:
- case GSA_32_BIT_IF_HIGHER_S3:
- case GSA_8_BIT_IF_LOWER_U3:
- case GSA_16_BIT_IF_LOWER_U3:
- case GSA_32_BIT_IF_LOWER_U3:
- case GSA_8_BIT_IF_HIGHER_U3:
- case GSA_16_BIT_IF_HIGHER_U3:
- case GSA_32_BIT_IF_HIGHER_U3:
- case GSA_8_BIT_IF_AND3:
- case GSA_16_BIT_IF_AND3:
- case GSA_32_BIT_IF_AND3:
- case GSA_ALWAYS3:
- case GSA_8_BIT_GS_WRITE2:
- case GSA_16_BIT_GS_WRITE2:
- case GSA_32_BIT_GS_WRITE2:
- case GSA_16_BIT_ROM_PATCH2C:
- case GSA_16_BIT_ROM_PATCH2D:
- case GSA_16_BIT_ROM_PATCH2E:
- case GSA_16_BIT_ROM_PATCH2F:
- case GSA_8_BIT_SLIDE:
- case GSA_16_BIT_SLIDE:
- case GSA_32_BIT_SLIDE:
- case GSA_GROUP_WRITE:
- case GSA_32_BIT_ADD2:
- case GSA_32_BIT_SUB2:
- case GSA_16_BIT_IF_LOWER_OR_EQ_U:
- case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
- case GSA_16_BIT_MIF_TRUE:
- case GSA_16_BIT_MIF_FALSE:
- case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
- case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
- return false;
- // the codes below have two lines of data
- case CBA_SLIDE_CODE:
- case CBA_SUPER:
- return true;
- }
- return false;
-}
-
-static int getCodeLength(int num)
-{
- if(num >= cheatsNumber || num < 0)
- return 1;
-
- // this is for all the codes that are true multiline
- switch(cheatsList[num].size) {
- case INT_8_BIT_WRITE:
- case INT_16_BIT_WRITE:
- case INT_32_BIT_WRITE:
- case GSA_16_BIT_ROM_PATCH:
- case GSA_8_BIT_GS_WRITE:
- case GSA_16_BIT_GS_WRITE:
- case GSA_32_BIT_GS_WRITE:
- case CBA_AND:
- case GSA_8_BIT_FILL:
- case GSA_16_BIT_FILL:
- case GSA_SLOWDOWN:
- case CBA_ADD:
- case CBA_OR:
- case GSA_8_BIT_POINTER:
- case GSA_16_BIT_POINTER:
- case GSA_32_BIT_POINTER:
- case GSA_8_BIT_ADD:
- case GSA_16_BIT_ADD:
- case GSA_32_BIT_ADD:
- case GSA_CODES_ON:
- case GSA_8_BIT_IF_TRUE3:
- case GSA_16_BIT_IF_TRUE3:
- case GSA_32_BIT_IF_TRUE3:
- case GSA_8_BIT_IF_FALSE3:
- case GSA_16_BIT_IF_FALSE3:
- case GSA_32_BIT_IF_FALSE3:
- case GSA_8_BIT_IF_LOWER_S3:
- case GSA_16_BIT_IF_LOWER_S3:
- case GSA_32_BIT_IF_LOWER_S3:
- case GSA_8_BIT_IF_HIGHER_S3:
- case GSA_16_BIT_IF_HIGHER_S3:
- case GSA_32_BIT_IF_HIGHER_S3:
- case GSA_8_BIT_IF_LOWER_U3:
- case GSA_16_BIT_IF_LOWER_U3:
- case GSA_32_BIT_IF_LOWER_U3:
- case GSA_8_BIT_IF_HIGHER_U3:
- case GSA_16_BIT_IF_HIGHER_U3:
- case GSA_32_BIT_IF_HIGHER_U3:
- case GSA_8_BIT_IF_AND3:
- case GSA_16_BIT_IF_AND3:
- case GSA_32_BIT_IF_AND3:
- case GSA_8_BIT_IF_LOWER_U:
- case GSA_16_BIT_IF_LOWER_U:
- case GSA_32_BIT_IF_LOWER_U:
- case GSA_8_BIT_IF_HIGHER_U:
- case GSA_16_BIT_IF_HIGHER_U:
- case GSA_32_BIT_IF_HIGHER_U:
- case GSA_8_BIT_IF_AND:
- case GSA_16_BIT_IF_AND:
- case GSA_32_BIT_IF_AND:
- case GSA_ALWAYS:
- case GSA_8_BIT_IF_LOWER_S:
- case GSA_16_BIT_IF_LOWER_S:
- case GSA_32_BIT_IF_LOWER_S:
- case GSA_8_BIT_IF_HIGHER_S:
- case GSA_16_BIT_IF_HIGHER_S:
- case GSA_32_BIT_IF_HIGHER_S:
- case GSA_16_BIT_WRITE_IOREGS:
- case GSA_32_BIT_WRITE_IOREGS:
- case GSA_8_BIT_GS_WRITE2:
- case GSA_16_BIT_GS_WRITE2:
- case GSA_32_BIT_GS_WRITE2:
- case GSA_16_BIT_ROM_PATCH2C:
- case GSA_16_BIT_ROM_PATCH2D:
- case GSA_16_BIT_ROM_PATCH2E:
- case GSA_16_BIT_ROM_PATCH2F:
- case GSA_8_BIT_SLIDE:
- case GSA_16_BIT_SLIDE:
- case GSA_32_BIT_SLIDE:
- case GSA_8_BIT_IF_TRUE:
- case GSA_32_BIT_IF_TRUE:
- case GSA_8_BIT_IF_FALSE:
- case GSA_32_BIT_IF_FALSE:
- case CBA_LT:
- case CBA_GT:
- case CBA_IF_TRUE:
- case CBA_IF_FALSE:
- case GSA_8_BIT_IF_TRUE2:
- case GSA_16_BIT_IF_TRUE2:
- case GSA_32_BIT_IF_TRUE2:
- case GSA_8_BIT_IF_FALSE2:
- case GSA_16_BIT_IF_FALSE2:
- case GSA_32_BIT_IF_FALSE2:
- case GSA_8_BIT_IF_LOWER_U2:
- case GSA_16_BIT_IF_LOWER_U2:
- case GSA_32_BIT_IF_LOWER_U2:
- case GSA_8_BIT_IF_HIGHER_U2:
- case GSA_16_BIT_IF_HIGHER_U2:
- case GSA_32_BIT_IF_HIGHER_U2:
- case GSA_8_BIT_IF_AND2:
- case GSA_16_BIT_IF_AND2:
- case GSA_32_BIT_IF_AND2:
- case GSA_ALWAYS2:
- case GSA_8_BIT_IF_LOWER_S2:
- case GSA_16_BIT_IF_LOWER_S2:
- case GSA_32_BIT_IF_LOWER_S2:
- case GSA_8_BIT_IF_HIGHER_S2:
- case GSA_16_BIT_IF_HIGHER_S2:
- case GSA_32_BIT_IF_HIGHER_S2:
- case GSA_GROUP_WRITE:
- case GSA_32_BIT_ADD2:
- case GSA_32_BIT_SUB2:
- case GSA_16_BIT_IF_LOWER_OR_EQ_U:
- case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
- case GSA_16_BIT_MIF_TRUE:
- case GSA_16_BIT_MIF_FALSE:
- case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
- case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
- return 1;
- case CBA_IF_KEYS_PRESSED:
- case CBA_SLIDE_CODE:
- return 2;
- case CBA_SUPER:
- return ((((cheatsList[num].value-1) & 0xFFFF)/3) + 1);
- }
- return 1;
-}
-
-int cheatsCheckKeys(u32 keys, u32 extended)
-{
- bool onoff = true;
- int ticks = 1;
- int i;
- for (i = 0; i<4; i++)
- if (rompatch2addr [i] != 0) {
- CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2oldval [i]);
- rompatch2addr [i] = 0;
- }
-
- for (i = 0; i < cheatsNumber; i++) {
- if(!cheatsList[i].enabled) {
- // make sure we skip other lines in this code
- i += getCodeLength(i)-1;
- continue;
- }
- switch(cheatsList[i].size) {
- case GSA_CODES_ON:
- onoff = true;
- break;
- case GSA_SLOWDOWN:
- // check if button was pressed and released, if so toggle our state
- if((cheatsList[i].status & 4) && !(extended & 4))
- cheatsList[i].status ^= 1;
- if(extended & 4)
- cheatsList[i].status |= 4;
- else
- cheatsList[i].status &= ~4;
-
- if(cheatsList[i].status & 1)
- ticks += ((cheatsList[i].value & 0xFFFF) * 7);
- break;
- case GSA_8_BIT_SLIDE:
- i++;
- if(i < cheatsNumber) {
- u32 addr = cheatsList[i-1].value;
- u8 value = cheatsList[i].rawaddress;
- int vinc = (cheatsList[i].value >> 24) & 255;
- int count = (cheatsList[i].value >> 16) & 255;
- int ainc = (cheatsList[i].value & 0xffff);
- while(count > 0) {
- CPUWriteByte(addr, value);
- value += vinc;
- addr += ainc;
- count--;
- }
- }
- i++;
- break;
- case GSA_16_BIT_SLIDE:
- i++;
- if(i < cheatsNumber) {
- u32 addr = cheatsList[i-1].value;
- u16 value = cheatsList[i].rawaddress;
- int vinc = (cheatsList[i].value >> 24) & 255;
- int count = (cheatsList[i].value >> 16) & 255;
- int ainc = (cheatsList[i].value & 0xffff)*2;
- while(count > 0) {
- CPUWriteHalfWord(addr, value);
- value += vinc;
- addr += ainc;
- count--;
- }
- }
- i++;
- break;
- case GSA_32_BIT_SLIDE:
- i++;
- if(i < cheatsNumber) {
- u32 addr = cheatsList[i-1].value;
- u32 value = cheatsList[i].rawaddress;
- int vinc = (cheatsList[i].value >> 24) & 255;
- int count = (cheatsList[i].value >> 16) & 255;
- int ainc = (cheatsList[i].value & 0xffff)*4;
- while(count > 0) {
- CPUWriteMemory(addr, value);
- value += vinc;
- addr += ainc;
- count--;
- }
- }
- i++;
- break;
- case GSA_8_BIT_GS_WRITE2:
- i++;
- if(i < cheatsNumber) {
- if(extended & 4) {
- CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
- }
- }
- break;
- case GSA_16_BIT_GS_WRITE2:
- i++;
- if(i < cheatsNumber) {
- if(extended & 4) {
- CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
- }
- }
- break;
- case GSA_32_BIT_GS_WRITE2:
- i++;
- if(i < cheatsNumber) {
- if(extended & 4) {
- CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
- }
- }
- break;
- case GSA_16_BIT_ROM_PATCH2C:
- i++;
- if((i < cheatsNumber) && (cheatsList[i].status & 1) == 0) {
- rompatch2addr [0] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
- rompatch2oldval [0] = CPUReadHalfWord(rompatch2addr [0]);
- rompatch2val [0] = cheatsList[i].rawaddress & 0xFFFF;
- }
- i++;
- break;
- case GSA_16_BIT_ROM_PATCH2D:
- i++;
- if((i < cheatsNumber) && (cheatsList[i].status & 1) == 0) {
- rompatch2addr [1] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
- rompatch2oldval [1] = CPUReadHalfWord(rompatch2addr [1]);
- rompatch2val [1] = cheatsList[i].rawaddress & 0xFFFF;
- }
- i++;
- break;
- case GSA_16_BIT_ROM_PATCH2E:
- i++;
- if((i < cheatsNumber) && (cheatsList[i].status & 1) == 0) {
- rompatch2addr [2] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
- rompatch2oldval [2] = CPUReadHalfWord(rompatch2addr [2]);
- rompatch2val [2] = cheatsList[i].rawaddress & 0xFFFF;
- }
- i++;
- break;
- case GSA_16_BIT_ROM_PATCH2F:
- i++;
- if((i < cheatsNumber) && (cheatsList[i].status & 1) == 0) {
- rompatch2addr [3] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
- rompatch2oldval [3] = CPUReadHalfWord(rompatch2addr [3]);
- rompatch2val [3] = cheatsList[i].rawaddress & 0xFFFF;
- }
- i++;
- break;
- }
- if (onoff) {
- switch(cheatsList[i].size) {
- case INT_8_BIT_WRITE:
- CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
- break;
- case INT_16_BIT_WRITE:
- CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
- break;
- case INT_32_BIT_WRITE:
- CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
- break;
- case GSA_16_BIT_ROM_PATCH:
- if((cheatsList[i].status & 1) == 0) {
- if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
- cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
- cheatsList[i].status |= 1;
- CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
- }
- }
- break;
- case GSA_8_BIT_GS_WRITE:
- if(extended & 4) {
- CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
- }
- break;
- case GSA_16_BIT_GS_WRITE:
- if(extended & 4) {
- CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
- }
- break;
- case GSA_32_BIT_GS_WRITE:
- if(extended & 4) {
- CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
- }
- break;
- case CBA_IF_KEYS_PRESSED:
- {
- u16 value = cheatsList[i].value;
- u32 addr = cheatsList[i].address;
- if((addr & 0xF0) == 0x20) {
- if((keys & value) == 0) {
- i++;
- }
- } else if((addr & 0xF0) == 0x10) {
- if((keys & value) == value) {
- i++;
- }
- } else if((addr & 0xF0) == 0x00) {
- if(((~keys) & 0x3FF) == value) {
- i++;
- }
- }
- }
- break;
- case CBA_IF_TRUE:
- if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
- i++;
- }
- break;
- case CBA_SLIDE_CODE:
- {
- u32 address = cheatsList[i].address;
- u16 value = cheatsList[i].value;
- i++;
- if(i < cheatsNumber) {
- int count = ((cheatsList[i].address - 1) & 0xFFFF);
- u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
- int inc = cheatsList[i].value;
- for(int x = 0; x <= count ; x++) {
- CPUWriteHalfWord(address, value);
- address += inc;
- value += vinc;
- }
- }
- }
- break;
- case CBA_IF_FALSE:
- if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value){
- i++;
- }
- break;
- case CBA_AND:
- CPUWriteHalfWord(cheatsList[i].address,
- CPUReadHalfWord(cheatsList[i].address) &
- cheatsList[i].value);
- break;
- case GSA_8_BIT_IF_TRUE:
- if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_TRUE:
- if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
- i++;
- }
- break;
- case GSA_8_BIT_IF_FALSE:
- if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_FALSE:
- if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
- i++;
- }
- break;
- case GSA_8_BIT_FILL:
- {
- u32 addr = cheatsList[i].address;
- u8 v = cheatsList[i].value & 0xff;
- u32 end = addr + (cheatsList[i].value >> 8);
- do {
- CPUWriteByte(addr, v);
- addr++;
- } while (addr <= end);
- }
- break;
- case GSA_16_BIT_FILL:
- {
- u32 addr = cheatsList[i].address;
- u16 v = cheatsList[i].value & 0xffff;
- u32 end = addr + ((cheatsList[i].value >> 16) << 1);
- do {
- CPUWriteHalfWord(addr, v);
- addr+=2;
- } while (addr <= end);
- }
- break;
- case GSA_8_BIT_IF_TRUE2:
- if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_TRUE2:
- if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_TRUE2:
- if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
- i+=2;
- }
- break;
- case GSA_8_BIT_IF_FALSE2:
- if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_FALSE2:
- if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_FALSE2:
- if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
- i+=2;
- }
- break;
- case CBA_ADD:
- if ((cheatsList[i].address & 1) == 0) {
- CPUWriteHalfWord(cheatsList[i].address,
- CPUReadHalfWord(cheatsList[i].address) +
- cheatsList[i].value);
- } else {
- CPUWriteMemory(cheatsList[i].address & 0x0FFFFFFE,
- CPUReadMemory(cheatsList[i].address & 0x0FFFFFFE) +
- cheatsList[i].value);
- }
- break;
- case CBA_OR:
- CPUWriteHalfWord(cheatsList[i].address,
- CPUReadHalfWord(cheatsList[i].address) |
- cheatsList[i].value);
- break;
- case CBA_GT:
- if (!(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value)){
- i++;
- }
- break;
- case CBA_LT:
- if (!(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value)){
- i++;
- }
- break;
- case CBA_SUPER:
- {
- int count = 2*((cheatsList[i].value -1) & 0xFFFF)+1;
- u32 address = cheatsList[i].address;
- for(int x = 0; x <= count; x++) {
- u8 b;
- int res = x % 6;
- if (res==0)
- i++;
- if(res < 4)
- b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
- else
- b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0xFF;
- CPUWriteByte(address, b);
- address++;
- }
- }
- break;
- case GSA_8_BIT_POINTER :
- if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
- (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
- {
- CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8),
- cheatsList[i].value & 0xFF);
- }
- break;
- case GSA_16_BIT_POINTER :
- if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
- (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
- {
- CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15),
- cheatsList[i].value & 0xFFFF);
- }
- break;
- case GSA_32_BIT_POINTER :
- if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
- (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
- {
- CPUWriteMemory(CPUReadMemory(cheatsList[i].address),
- cheatsList[i].value);
- }
- break;
- case GSA_8_BIT_ADD :
- CPUWriteByte(cheatsList[i].address,
- (cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address) & 0xFF);
- break;
- case GSA_16_BIT_ADD :
- CPUWriteHalfWord(cheatsList[i].address,
- (cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address) & 0xFFFF);
- break;
- case GSA_32_BIT_ADD :
- CPUWriteMemory(cheatsList[i].address ,
- cheatsList[i].value + CPUReadMemory(cheatsList[i].address) & 0xFFFFFFFF);
- break;
- case GSA_8_BIT_IF_LOWER_U:
- if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
- i++;
- }
- break;
- case GSA_16_BIT_IF_LOWER_U:
- if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_LOWER_U:
- if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
- i++;
- }
- break;
- case GSA_8_BIT_IF_HIGHER_U:
- if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
- i++;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_U:
- if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_HIGHER_U:
- if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
- i++;
- }
- break;
- case GSA_8_BIT_IF_AND:
- if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
- i++;
- }
- break;
- case GSA_16_BIT_IF_AND:
- if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_AND:
- if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
- i++;
- }
- break;
- case GSA_8_BIT_IF_LOWER_U2:
- if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_LOWER_U2:
- if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_LOWER_U2:
- if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
- i+=2;
- }
- break;
- case GSA_8_BIT_IF_HIGHER_U2:
- if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_U2:
- if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_HIGHER_U2:
- if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
- i+=2;
- }
- break;
- case GSA_8_BIT_IF_AND2:
- if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_AND2:
- if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_AND2:
- if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
- i+=2;
- }
- break;
- case GSA_ALWAYS:
- i++;
- break;
- case GSA_ALWAYS2:
- i+=2;
- break;
- case GSA_8_BIT_IF_LOWER_S:
- if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
- i++;
- }
- break;
- case GSA_16_BIT_IF_LOWER_S:
- if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_LOWER_S:
- if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
- i++;
- }
- break;
- case GSA_8_BIT_IF_HIGHER_S:
- if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
- i++;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_S:
- if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
- i++;
- }
- break;
- case GSA_32_BIT_IF_HIGHER_S:
- if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
- i++;
- }
- break;
- case GSA_8_BIT_IF_LOWER_S2:
- if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_LOWER_S2:
- if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_LOWER_S2:
- if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
- i+=2;
- }
- break;
- case GSA_8_BIT_IF_HIGHER_S2:
- if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
- i+=2;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_S2:
- if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
- i+=2;
- }
- break;
- case GSA_32_BIT_IF_HIGHER_S2:
- if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
- i+=2;
- }
- break;
- case GSA_16_BIT_WRITE_IOREGS:
- if ((cheatsList[i].address <= 0x3FF) && (cheatsList[i].address != 0x6) &&
- (cheatsList[i].address != 0x130))
- ioMem[cheatsList[i].address & 0x3FE]=cheatsList[i].value & 0xFFFF;
- break;
- case GSA_32_BIT_WRITE_IOREGS:
- if (cheatsList[i].address<=0x3FF)
- {
- if (((cheatsList[i].address & 0x3FC) != 0x6) && ((cheatsList[i].address & 0x3FC) != 0x130))
- ioMem[cheatsList[i].address & 0x3FC]= (cheatsList[i].value & 0xFFFF);
- if ((((cheatsList[i].address & 0x3FC)+2) != 0x6) && ((cheatsList[i].address & 0x3FC) +2) != 0x130)
- ioMem[(cheatsList[i].address & 0x3FC) + 2 ]= ((cheatsList[i].value>>16 ) & 0xFFFF);
- }
- break;
- case GSA_8_BIT_IF_TRUE3:
- if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_TRUE3:
- if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_TRUE3:
- if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
- onoff=false;
- }
- break;
- case GSA_8_BIT_IF_FALSE3:
- if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_FALSE3:
- if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_FALSE3:
- if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
- onoff=false;
- }
- break;
- case GSA_8_BIT_IF_LOWER_S3:
- if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_LOWER_S3:
- if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_LOWER_S3:
- if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
- onoff=false;
- }
- break;
- case GSA_8_BIT_IF_HIGHER_S3:
- if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_S3:
- if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_HIGHER_S3:
- if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
- onoff=false;
- }
- break;
- case GSA_8_BIT_IF_LOWER_U3:
- if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_LOWER_U3:
- if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_LOWER_U3:
- if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
- onoff=false;
- }
- break;
- case GSA_8_BIT_IF_HIGHER_U3:
- if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_U3:
- if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_HIGHER_U3:
- if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
- onoff=false;
- }
- break;
- case GSA_8_BIT_IF_AND3:
- if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
- onoff=false;
- }
- break;
- case GSA_16_BIT_IF_AND3:
- if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
- onoff=false;
- }
- break;
- case GSA_32_BIT_IF_AND3:
- if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
- onoff=false;
- }
- break;
- case GSA_ALWAYS3:
- if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
- onoff=false;
- }
- break;
- case GSA_GROUP_WRITE:
- {
- int count = ((cheatsList[i].address) & 0xFFFE) +1;
- u32 value = cheatsList[i].value;
- if (count==0)
- i++;
- else
- for (int x = 1; x <= count; x++) {
- if ((x % 2) ==0){
- if (x cheatsList[i].value) {
- i++;
- }
- break;
- case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
- if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
- i++;
- }
- break;
- case GSA_16_BIT_MIF_TRUE:
- if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
- i+=((cheatsList[i].rawaddress >> 0x10) & 0xFF);
- }
- break;
- case GSA_16_BIT_MIF_FALSE:
- if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
- i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
- }
- break;
- case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
- if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) {
- i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
- }
- break;
- case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
- if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
- i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
- }
- break;
- }
- }
- }
- for (i = 0; i<4; i++)
- if (rompatch2addr [i] != 0)
- CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2val [i]);
- return ticks;
-}
-
-void cheatsAdd(const char *codeStr,
- const char *desc,
- u32 rawaddress,
- u32 address,
- u32 value,
- int code,
- int size)
-{
- if(cheatsNumber < 100) {
- int x = cheatsNumber;
- cheatsList[x].code = code;
- cheatsList[x].size = size;
- cheatsList[x].rawaddress = rawaddress;
- cheatsList[x].address = address;
- cheatsList[x].value = value;
- strcpy(cheatsList[x].codestring, codeStr);
- strcpy(cheatsList[x].desc, desc);
- cheatsList[x].enabled = true;
- cheatsList[x].status = 0;
-
- // we only store the old value for this simple codes. ROM patching
- // is taken care when it actually patches the ROM
- switch(cheatsList[x].size) {
- case INT_8_BIT_WRITE:
- cheatsList[x].oldValue = CPUReadByte(address);
- break;
- case INT_16_BIT_WRITE:
- cheatsList[x].oldValue = CPUReadHalfWord(address);
- break;
- case INT_32_BIT_WRITE:
- cheatsList[x].oldValue = CPUReadMemory(address);
- break;
- }
- cheatsNumber++;
- }
-}
-
-void cheatsDelete(int number, bool restore)
-{
- if(number < cheatsNumber && number >= 0) {
- int x = number;
-
- if(restore) {
- switch(cheatsList[x].size) {
- case INT_8_BIT_WRITE:
- CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
- break;
- case INT_16_BIT_WRITE:
- CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
- break;
- case INT_32_BIT_WRITE:
- CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
- break;
- case GSA_16_BIT_ROM_PATCH:
- if(cheatsList[x].status & 1) {
- cheatsList[x].status &= ~1;
- CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
- cheatsList[x].oldValue);
- }
- break;
- case GSA_16_BIT_ROM_PATCH2C:
- case GSA_16_BIT_ROM_PATCH2D:
- case GSA_16_BIT_ROM_PATCH2E:
- case GSA_16_BIT_ROM_PATCH2F:
- if(cheatsList[x].status & 1) {
- cheatsList[x].status &= ~1;
- }
- break;
- }
- }
- if((x+1) < cheatsNumber) {
- memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
- (cheatsNumber-x-1));
- }
- cheatsNumber--;
- }
-}
-
-void cheatsDeleteAll(bool restore)
-{
- for(int i = cheatsNumber-1; i >= 0; i--) {
- cheatsDelete(i, restore);
- }
-}
-
-void cheatsEnable(int i)
-{
- if(i >= 0 && i < cheatsNumber) {
- cheatsList[i].enabled = true;
- }
-}
-
-void cheatsDisable(int i)
-{
- if(i >= 0 && i < cheatsNumber) {
- switch(cheatsList[i].size) {
- case GSA_16_BIT_ROM_PATCH:
- if(cheatsList[i].status & 1) {
- cheatsList[i].status &= ~1;
- CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
- cheatsList[i].oldValue);
- }
- break;
- case GSA_16_BIT_ROM_PATCH2C:
- case GSA_16_BIT_ROM_PATCH2D:
- case GSA_16_BIT_ROM_PATCH2E:
- case GSA_16_BIT_ROM_PATCH2F:
- if(cheatsList[i].status & 1) {
- cheatsList[i].status &= ~1;
- }
- break;
- }
- cheatsList[i].enabled = false;
- }
-}
-
-bool cheatsVerifyCheatCode(const char *code, const char *desc)
-{
- int len = strlen(code);
- if(len != 11 && len != 13 && len != 17) {
- systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
- return false;
- }
-
- if(code[8] != ':') {
- systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
- return false;
- }
-
- int i;
- for(i = 0; i < 8; i++) {
- if(!CHEAT_IS_HEX(code[i])) {
- // wrong cheat
- systemMessage(MSG_INVALID_CHEAT_CODE,
- N_("Invalid cheat code '%s'"), code);
- return false;
- }
- }
- for(i = 9; i < len; i++) {
- if(!CHEAT_IS_HEX(code[i])) {
- // wrong cheat
- systemMessage(MSG_INVALID_CHEAT_CODE,
- N_("Invalid cheat code '%s'"), code);
- return false;
- }
- }
-
- u32 address = 0;
- u32 value = 0;
-
- char buffer[10];
- strncpy(buffer, code, 8);
- buffer[8] = 0;
- sscanf(buffer, "%x", &address);
-
- switch(address >> 24) {
- case 2:
- case 3:
- break;
- default:
- systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS,
- N_("Invalid cheat code address: %08x"),
- address);
- return false;
- }
-
- strncpy(buffer, &code[9], 8);
- sscanf(buffer, "%x", &value);
- int type = 0;
- if(len == 13)
- type = 1;
- if(len == 17)
- type = 2;
- cheatsAdd(code, desc, address, address, value, type, type);
- return true;
-}
-
-void cheatsAddCheatCode(const char *code, const char *desc)
-{
- cheatsVerifyCheatCode(code, desc);
-}
-
-u16 cheatsGSAGetDeadface(bool v3)
-{
- for(int i = cheatsNumber-1; i >= 0; i--)
- if ((cheatsList[i].address == 0xDEADFACE) && (cheatsList[i].code == (v3 ? 257 : 256)))
- return cheatsList[i].value & 0xFFFF;
- return 0;
-}
-
-void cheatsGSAChangeEncryption(u16 value, bool v3) {
- int i;
- u8 *deadtable1, *deadtable2;
-
- if (v3) {
- deadtable1 = (u8*)(&v3_deadtable1);
- deadtable2 = (u8*)(&v3_deadtable2);
- for (i = 0; i < 4; i++)
- seeds_v3[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
- }
- else {
- deadtable1 = (u8*)(&v1_deadtable1);
- deadtable2 = (u8*)(&v1_deadtable2);
- for (i = 0; i < 4; i++){
- seeds_v1[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
- }
- }
-}
-
-u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2) {
- int i;
- u32 newseed = 0;
-
- for (i = 0; i < 4; i++)
- newseed = ((newseed << 8) | ((deadtable1[(i + upper) & 0xFF] + deadtable2[seed]) & 0xFF));
-
- return newseed;
-}
-
-void cheatsDecryptGSACode(u32& address, u32& value, bool v3)
-{
- u32 rollingseed = 0xC6EF3720;
- u32 *seeds = v3 ? seeds_v3 : seeds_v1;
-
- int bitsleft = 32;
- while (bitsleft > 0) {
- value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
- ((address >> 5) + seeds[3]));
- address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
- ((value >> 5) + seeds[1]));
- rollingseed -= 0x9E3779B9;
- bitsleft--;
- }
-}
-
-void cheatsAddGSACode(const char *code, const char *desc, bool v3)
-{
- if(strlen(code) != 16) {
- // wrong cheat
- systemMessage(MSG_INVALID_GSA_CODE,
- N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
- return;
- }
-
- int i;
- for(i = 0; i < 16; i++) {
- if(!CHEAT_IS_HEX(code[i])) {
- // wrong cheat
- systemMessage(MSG_INVALID_GSA_CODE,
- N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
- return;
- }
- }
-
- char buffer[10];
- strncpy(buffer, code, 8);
- buffer[8] = 0;
- u32 address;
- sscanf(buffer, "%x", &address);
- strncpy(buffer, &code[8], 8);
- buffer[8] = 0;
- u32 value;
- sscanf(buffer, "%x", &value);
- cheatsGSAChangeEncryption(cheatsGSAGetDeadface (v3), v3);
- cheatsDecryptGSACode(address, value, v3);
-
- if(value == 0x1DC0DE) {
- u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
- if(gamecode != address) {
- char buffer[5];
- *((u32 *)buffer) = address;
- buffer[4] = 0;
- char buffer2[5];
- *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
- buffer2[4] = 0;
- systemMessage(MSG_GBA_CODE_WARNING, N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."),
- buffer, buffer2);
- }
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, v3 ? 257 : 256,
- UNKNOWN_CODE);
- return;
- }
- if(isMultilineWithData(cheatsNumber-1)) {
- cheatsAdd(code, desc, address, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
- return;
- }
- if(v3) {
- int type = ((address >> 25) & 127) | ((address >> 17) & 0x80);
- u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
- switch(type) {
- case 0x00:
- if(address == 0) {
- type = (value >> 25) & 127;
- addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
- switch(type) {
- case 0x04:
- cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
- break;
- case 0x08:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
- break;
- case 0x09:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
- break;
- case 0x0a:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
- break;
- case 0x0c:
- cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2C);
- break;
- case 0x0d:
- cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2D);
- break;
- case 0x0e:
- cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2E);
- break;
- case 0x0f:
- cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2F);
- break;
- case 0x20:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_CODES_ON);
- break;
- case 0x40:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_SLIDE);
- break;
- case 0x41:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_SLIDE);
- break;
- case 0x42:
- cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_SLIDE);
- break;
- default:
- cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
- break;
- }
- } else
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_FILL);
- break;
- case 0x01:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_FILL);
- break;
- case 0x02:
- cheatsAdd(code, desc, address, addr, value, 257, INT_32_BIT_WRITE);
- break;
- case 0x04:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE);
- break;
- case 0x05:
- cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_TRUE);
- break;
- case 0x06:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE);
- break;
- case 0x07:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS);
- break;
- case 0x08:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE);
- break;
- case 0x09:
- cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_FALSE);
- break;
- case 0x0a:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE);
- break;
- case 0xc:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S);
- break;
- case 0xd:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S);
- break;
- case 0xe:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S);
- break;
- case 0x10:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S);
- break;
- case 0x11:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S);
- break;
- case 0x12:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S);
- break;
- case 0x14:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U);
- break;
- case 0x15:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U);
- break;
- case 0x16:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U);
- break;
- case 0x18:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U);
- break;
- case 0x19:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U);
- break;
- case 0x1A:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U);
- break;
- case 0x1C:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND);
- break;
- case 0x1D:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND);
- break;
- case 0x1E:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND);
- break;
- case 0x20:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_POINTER);
- break;
- case 0x21:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_POINTER);
- break;
- case 0x22:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_POINTER);
- break;
- case 0x24:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE2);
- break;
- case 0x25:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE2);
- break;
- case 0x26:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE2);
- break;
- case 0x27:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS2);
- break;
- case 0x28:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE2);
- break;
- case 0x29:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE2);
- break;
- case 0x2a:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE2);
- break;
- case 0x2c:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S2);
- break;
- case 0x2d:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S2);
- break;
- case 0x2e:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S2);
- break;
- case 0x30:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S2);
- break;
- case 0x31:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S2);
- break;
- case 0x32:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S2);
- break;
- case 0x34:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U2);
- break;
- case 0x35:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U2);
- break;
- case 0x36:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U2);
- break;
- case 0x38:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U2);
- break;
- case 0x39:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U2);
- break;
- case 0x3A:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U2);
- break;
- case 0x3C:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND2);
- break;
- case 0x3D:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND2);
- break;
- case 0x3E:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND2);
- break;
- case 0x40:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_ADD);
- break;
- case 0x41:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_ADD);
- break;
- case 0x42:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_ADD);
- break;
- case 0x44:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE3);
- break;
- case 0x45:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE3);
- break;
- case 0x46:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE3);
- break;
- case 0x47:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS3);
- break;
- case 0x48:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE3);
- break;
- case 0x49:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE3);
- break;
- case 0x4a:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE3);
- break;
- case 0x4c:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S3);
- break;
- case 0x4d:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S3);
- break;
- case 0x4e:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S3);
- break;
- case 0x50:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S3);
- break;
- case 0x51:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S3);
- break;
- case 0x52:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S3);
- break;
- case 0x54:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U3);
- break;
- case 0x55:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U3);
- break;
- case 0x56:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U3);
- break;
- case 0x58:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U3);
- break;
- case 0x59:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U3);
- break;
- case 0x5a:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U3);
- break;
- case 0x5c:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND3);
- break;
- case 0x5d:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND3);
- break;
- case 0x5e:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND3);
- break;
- case 0x63:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_WRITE_IOREGS);
- break;
- case 0xE3:
- cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_WRITE_IOREGS);
- break;
- default:
- cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
- break;
- }
- } else {
- int type = (address >> 28) & 15;
- switch(type) {
- case 0:
- case 1:
- case 2:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, type);
- break;
- case 3:
- switch ((address >> 0x10) & 0xFF){
- case 0x00:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_GROUP_WRITE);
- break;
- case 0x10:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFF, 256, GSA_32_BIT_ADD );
- break;
- case 0x20:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFF)+1), 256, GSA_32_BIT_ADD );
- break;
- case 0x30:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, GSA_32_BIT_ADD );
- break;
- case 0x40:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFFFF)+1), 256, GSA_32_BIT_ADD );
- break;
- case 0x50:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_ADD2);
- break;
- case 0x60:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_SUB2);
- break;
- default:
- // unsupported code
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- }
- break;
- case 6:
- address <<= 1;
- type = (value >> 24) & 0xFF;
- if(type == 0x00) {
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
- GSA_16_BIT_ROM_PATCH);
- break;
- }
- // unsupported code
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- case 8:
- switch((address >> 20) & 15) {
- case 1:
- cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
- GSA_8_BIT_GS_WRITE);
- break;
- case 2:
- cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
- GSA_16_BIT_GS_WRITE);
- break;
- case 4:
- // This code is buggy : the value is always set to 0 !
- cheatsAdd(code, desc, address, address & 0x0F0FFFFF, 0, 256,
- GSA_32_BIT_GS_WRITE);
- break;
- case 15:
- cheatsAdd(code, desc, address, 0, value & 0xFFFF, 256, GSA_SLOWDOWN);
- break;
- default:
- // unsupported code
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- }
- break;
- case 0x0d:
- if(address != 0xDEADFACE) {
- switch((value >> 20) & 0xF) {
- case 0:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
- CBA_IF_TRUE);
- break;
- case 1:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
- CBA_IF_FALSE);
- break;
- case 2:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
- GSA_16_BIT_IF_LOWER_OR_EQ_U);
- break;
- case 3:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
- GSA_16_BIT_IF_HIGHER_OR_EQ_U);
- break;
- default:
- // unsupported code
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- }
- } else
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- case 0x0e:
- switch((value >> 28) & 0xF) {
- case 0:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
- GSA_16_BIT_MIF_TRUE);
- break;
- case 1:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
- GSA_16_BIT_MIF_FALSE);
- break;
- case 2:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
- GSA_16_BIT_MIF_LOWER_OR_EQ_U);
- break;
- case 3:
- cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
- GSA_16_BIT_MIF_HIGHER_OR_EQ_U);
- break;
- default:
- // unsupported code
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- }
- break;
- default:
- // unsupported code
- cheatsAdd(code, desc, address, address, value, 256,
- UNKNOWN_CODE);
- break;
- }
- }
-}
-
-bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
-{
- FILE *f = fopen(name, "rb");
- if(!f)
- return false;
-
- int games = 0;
- int len = 0;
- fseek(f, 0x1e, SEEK_CUR);
- fread(&games, 1, 4, f);
- bool found = false;
- int g = 0;
- while(games > 0) {
- if(g == game) {
- found = true;
- break;
- }
- fread(&len, 1, 4, f);
- fseek(f,len,SEEK_CUR);
- int codes = 0;
- fread(&codes, 1, 4, f);
- while(codes > 0) {
- fread(&len, 1, 4, f);
- fseek(f, len, SEEK_CUR);
- fseek(f, 8, SEEK_CUR);
- fread(&len, 1, 4, f);
- fseek(f, len*12, SEEK_CUR);
- codes--;
- }
- games--;
- g++;
- }
- if(found) {
- char desc[256];
- char code[17];
- fread(&len, 1, 4, f);
- fseek(f, len, SEEK_CUR);
- int codes = 0;
- fread(&codes, 1, 4, f);
- while(codes > 0) {
- fread(&len, 1, 4, f);
- fread(desc, 1, len, f);
- desc[len] =0;
- desc[31] = 0;
- fread(&len, 1, 4, f);
- fseek(f, len, SEEK_CUR);
- fseek(f, 4, SEEK_CUR);
- fread(&len, 1, 4, f);
- while(len) {
- fseek(f, 4, SEEK_CUR);
- fread(code, 1, 8, f);
- fseek(f, 4, SEEK_CUR);
- fread(&code[8], 1, 8, f);
- code[16] = 0;
- cheatsAddGSACode(code, desc, v3);
- len -= 2;
- }
- codes--;
- }
- }
- fclose(f);
- return false;
-}
-
-void cheatsCBAReverseArray(u8 *array, u8 *dest)
-{
- dest[0] = array[3];
- dest[1] = array[2];
- dest[2] = array[1];
- dest[3] = array[0];
- dest[4] = array[5];
- dest[5] = array[4];
-}
-
-void chatsCBAScramble(u8 *array, int count, u8 b)
-{
- u8 *x = array + (count >> 3);
- u8 *y = array + (b >> 3);
- u32 z = *x & (1 << (count & 7));
- u32 x0 = (*x & (~(1 << (count & 7))));
- if (z != 0)
- z = 1;
- if ((*y & (1 << (b & 7))) != 0)
- x0 |= (1 << (count & 7));
- *x = x0;
- u32 temp = *y & (~(1 << (b & 7)));
- if (z != 0)
- temp |= (1 << (b & 7));
- *y = temp;
-}
-
-u32 cheatsCBAGetValue(u8 *array)
-{
- return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
-}
-
-u16 cheatsCBAGetData(u8 *array)
-{
- return array[4] | array[5]<<8;
-}
-
-void cheatsCBAArrayToValue(u8 *array, u8 *dest)
-{
- dest[0] = array[3];
- dest[1] = array[2];
- dest[2] = array[1];
- dest[3] = array[0];
- dest[4] = array[5];
- dest[5] = array[4];
-}
-
-void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
-{
- array[0] = 1;
- array[1] = value & 0xFF;
- array[2] = (address >> 0x10) & 0xFF;
- array[3] = (value >> 8) & 0xFF;
- array[4] = (address >> 0x18) & 0x0F;
- array[5] = address & 0xFFFF;
- array[6] = address;
- array[7] = value;
-}
-
-u32 cheatsCBAEncWorker()
-{
- u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
- u32 y = (x * 0x41c64e6d) + 0x3039;
- u32 z = x >> 0x10;
- x = ((y >> 0x10) & 0x7fff) << 0x0f;
- z = (z << 0x1e) | x;
- x = (y * 0x41c64e6d) + 0x3039;
- cheatsCBATemporaryValue = x;
- return z | ((x >> 0x10) & 0x7fff);
-}
-
-#define ROR(v, s) \
- (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
-
-u32 cheatsCBACalcIndex(u32 x, u32 y)
-{
- if(y != 0) {
- if(y == 1)
- x = 0;
- else if(x == y)
- x = 0;
- if(y < 1)
- return x;
- else if(x < y)
- return x;
- u32 x0 = 1;
-
- while(y < 0x10000000) {
- if(y < x) {
- y = y << 4;
- x0 = x0 << 4;
- } else break;
- }
-
- while(y < 0x80000000) {
- if(y < x) {
- y = y << 1;
- x0 = x0 << 1;
- } else break;
- }
-
- loop:
- u32 z = 0;
- if(x >= y)
- x -= y;
- if(x >= (y >> 1)) {
- x -= (y >> 1);
- z |= ROR(x0, 1);
- }
- if(x >= (y >> 2)) {
- x -= (y >> 2);
- z |= ROR(x0, 2);
- }
- if(x >= (y >> 3)) {
- x -= (y >> 3);
- z |= ROR(x0, 3);
- }
-
- u32 temp = x0;
-
- if(x != 0) {
- x0 = x0 >> 4;
- if(x0 != 0) {
- y = y >> 4;
- goto loop;
- }
- }
-
- z = z & 0xe0000000;
-
- if(z != 0) {
- if((temp & 7) == 0)
- return x;
- } else
- return x;
-
- if((z & ROR(temp, 3)) != 0)
- x += y >> 3;
- if((z & ROR(temp, 2)) != 0)
- x += y >> 2;
- if((z & ROR(temp, 1)) != 0)
- x += y >> 1;
- return x;
- } else {
- }
- // should not happen in the current code
- return 0;
-}
-
-void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
-{
- int i;
- for(i = 0; i < count; i++)
- buffer[i] = i;
- for(i = 0; (u32)i < a; i++) {
- u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
- u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
- u32 t = buffer[a];
- buffer[a] = buffer[b];
- buffer[b] = t;
- }
-}
-
-void cheatsCBAChangeEncryption(u32 *seed)
-{
- int i;
-
- cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
- cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
- cheatsCBATemporaryValue = 0x4efad1c3;
-
- for(i = 0; (u32)i < seed[4]; i++) {
- cheatsCBATemporaryValue = cheatsCBAEncWorker();
- }
- cheatsCBASeed[2] = cheatsCBAEncWorker();
- cheatsCBASeed[3] = cheatsCBAEncWorker();
-
- cheatsCBATemporaryValue = seed[3] ^ 0xf254;
-
- for(i = 0; (u32)i < seed[3]; i++) {
- cheatsCBATemporaryValue = cheatsCBAEncWorker();
- }
-
- cheatsCBASeed[0] = cheatsCBAEncWorker();
- cheatsCBASeed[1] = cheatsCBAEncWorker();
-
- *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
- *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
- *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
-}
-
-u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
-{
- y <<= 0x10;
- z <<= 0x10;
- x <<= 0x18;
- u32 x0 = (int)y >> 0x10;
- z = (int)z >> 0x10;
- x = (int)x >> 0x10;
- for(int i = 0; i < 8; i++) {
- u32 temp = z ^ x;
- if ((int)temp >= 0) {
- temp = z << 0x11;
- }
- else {
- temp = z << 0x01;
- temp ^= x0;
- temp = temp << 0x10;
- }
- z = (int)temp >> 0x10;
- temp = x << 0x11;
- x = (int)temp >> 0x10;
- }
- return z & 0xffff;
-}
-
-void cheatsCBAGenTable() {
- for (int i = 0; i < 0x100; i++) {
- cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
- }
- cheatsCBATableGenerated = true;
-}
-
-u16 cheatsCBACalcCRC(u8 *rom, int count)
-{
- u32 crc = 0xffffffff;
-
- if (count & 3) {
- // 0x08000EAE
- } else {
- count = (count >> 2) - 1;
- if(count != -1) {
- while(count != -1) {
- crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
- ^ *rom++]) << 0x10) >> 0x10;
- crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
- ^ *rom++]) << 0x10) >> 0x10;
- crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
- ^ *rom++]) << 0x10) >> 0x10;
- crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
- ^ *rom++]) << 0x10) >> 0x10;
- count--;
- }
- }
- }
- return crc & 0xffff;
-}
-
-void cheatsCBADecrypt(u8 *decrypt)
-{
- u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- u8 *array = &buffer[1];
-
- cheatsCBAReverseArray(decrypt, array);
-
- for(int count = 0x2f; count >= 0; count--) {
- chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
- }
- cheatsCBAArrayToValue(array, decrypt);
- *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
- cheatsCBASeed[0];
- *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
- cheatsCBASeed[1]) & 0xffff;
-
- cheatsCBAReverseArray(decrypt, array);
-
- u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
- for(int i = 0; i <= 4; i++) {
- array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
- }
-
- array[5] = (cs >> 8) ^ array[5];
-
- for(int j = 5; j >=0; j--) {
- array[j] = (cs ^ array[j-1]) ^ array[j];
- }
-
- cheatsCBAArrayToValue(array, decrypt);
-
- *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
- ^ cheatsCBASeed[2];
- *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
- ^ cheatsCBASeed[3]) & 0xffff;
-}
-
-int cheatsCBAGetCount()
-{
- int count = 0;
- for(int i = 0; i < cheatsNumber; i++) {
- if(cheatsList[i].code == 512)
- count++;
- }
- return count;
-}
-
-bool cheatsCBAShouldDecrypt()
-{
- for(int i = 0; i < cheatsNumber; i++) {
- if(cheatsList[i].code == 512) {
- return (cheatsList[i].codestring[0] == '9');
- }
- }
- return false;
-}
-
-void cheatsAddCBACode(const char *code, const char *desc)
-{
- if(strlen(code) != 13) {
- // wrong cheat
- systemMessage(MSG_INVALID_CBA_CODE,
- N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
- return;
- }
-
- int i;
- for(i = 0; i < 8; i++) {
- if(!CHEAT_IS_HEX(code[i])) {
- // wrong cheat
- systemMessage(MSG_INVALID_CBA_CODE,
- N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
- return;
- }
- }
-
- if(code[8] != ' ') {
- systemMessage(MSG_INVALID_CBA_CODE,
- N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
- return;
- }
-
- for(i = 9; i < 13; i++) {
- if(!CHEAT_IS_HEX(code[i])) {
- // wrong cheat
- systemMessage(MSG_INVALID_CBA_CODE,
- N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
- return;
- }
- }
-
- char buffer[10];
- strncpy(buffer, code, 8);
- buffer[8] = 0;
- u32 address;
- sscanf(buffer, "%x", &address);
- strncpy(buffer, &code[9], 4);
- buffer[4] = 0;
- u32 value;
- sscanf(buffer, "%x", &value);
-
- u8 array[8] = {
- address & 255,
- (address >> 8) & 255,
- (address >> 16) & 255,
- (address >> 24) & 255,
- (value & 255),
- (value >> 8) & 255,
- 0,
- 0
- };
-
- if(cheatsCBAGetCount() == 0 &&
- (address >> 28) == 9) {
- u32 seed[8];
- cheatsCBAParseSeedCode(address, value, seed);
- cheatsCBAChangeEncryption(seed);
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
- } else {
- if(cheatsCBAShouldDecrypt())
- cheatsCBADecrypt(array);
-
- address = READ32LE(((u32 *)array));
- value = READ16LE(((u16 *)&array[4]));
-
- int type = (address >> 28) & 15;
-
- if(isMultilineWithData(cheatsNumber-1) || (super>0)) {
- cheatsAdd(code, desc, address, address, value, 512, UNKNOWN_CODE);
- if (super>0)
- super-= 1;
- return;
- }
-
- switch(type) {
- case 0x00:
- {
- if(!cheatsCBATableGenerated)
- cheatsCBAGenTable();
- u32 crc = cheatsCBACalcCRC(rom, 0x10000);
- if(crc != address) {
- systemMessage(MSG_CBA_CODE_WARNING,
- N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly."));
- }
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
- UNKNOWN_CODE);
- }
- break;
- case 0x02:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_OR);
- break;
- case 0x03:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
- INT_8_BIT_WRITE);
- break;
- case 0x04:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_SLIDE_CODE);
- break;
- case 0x05:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_SUPER);
- super = getCodeLength(cheatsNumber-1);
- break;
- case 0x06:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_AND);
- break;
- case 0x07:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_IF_TRUE);
- break;
- case 0x08:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- INT_16_BIT_WRITE);
- break;
- case 0x0a:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_IF_FALSE);
- break;
- case 0x0b:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_GT);
- break;
- case 0x0c:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- CBA_LT);
- break;
- case 0x0d:
- if ((address & 0xF0)<0x30)
- cheatsAdd(code, desc, address, address & 0xF0, value, 512,
- CBA_IF_KEYS_PRESSED);
- break;
- case 0x0e:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0x8000 ? value | 0xFFFF0000 : value, 512,
- CBA_ADD);
- break;
- case 0x0f:
- cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
- GSA_16_BIT_IF_AND);
- break;
- default:
- // unsupported code
- cheatsAdd(code, desc, address, address & 0xFFFFFFFF, value, 512,
- UNKNOWN_CODE);
- break;
- }
- }
-}
-
-void cheatsSaveGame(gzFile file)
-{
- utilWriteInt(file, cheatsNumber);
-
- utilGzWrite(file, cheatsList, sizeof(cheatsList));
-}
-
-void cheatsReadGame(gzFile file)
-{
- cheatsNumber = 0;
-
- cheatsNumber = utilReadInt(file);
-
- utilGzRead(file, cheatsList, sizeof(cheatsList));
-
- bool firstCodeBreaker = true;
-
- for(int i = 0; i < cheatsNumber; i++) {
- cheatsList[i].status = 0;
- if(!cheatsList[i].codestring[0]) {
- switch(cheatsList[i].size) {
- case 0:
- sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
- cheatsList[i].value);
- break;
- case 1:
- sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
- cheatsList[i].value);
- break;
- case 2:
- sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
- cheatsList[i].value);
- break;
- }
- }
-
- if(cheatsList[i].enabled) {
- cheatsEnable(i);
- }
-
- if(cheatsList[i].code == 512 && firstCodeBreaker) {
- firstCodeBreaker = false;
- char buffer[10];
- strncpy(buffer, cheatsList[i].codestring, 8);
- buffer[8] = 0;
- u32 address;
- sscanf(buffer, "%x", &address);
- if((address >> 28) == 9) {
- strncpy(buffer, &cheatsList[i].codestring[9], 4);
- buffer[4] = 0;
- u32 value;
- sscanf(buffer, "%x", &value);
-
- u32 seed[8];
- cheatsCBAParseSeedCode(address, value, seed);
- cheatsCBAChangeEncryption(seed);
- }
- }
- }
-}
-
-void cheatsSaveCheatList(const char *file)
-{
- if(cheatsNumber == 0)
- return;
- FILE *f = fopen(file, "wb");
- if(f == NULL)
- return;
- int version = 1;
- fwrite(&version, 1, sizeof(version), f);
- int type = 0;
- fwrite(&type, 1, sizeof(type), f);
- fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
- fwrite(cheatsList, 1, sizeof(cheatsList), f);
- fclose(f);
-}
-
-bool cheatsLoadCheatList(const char *file)
-{
- cheatsNumber = 0;
-
- int count = 0;
-
- FILE *f = fopen(file, "rb");
-
- if(f == NULL)
- return false;
-
- int version = 0;
-
- if(fread(&version, 1, sizeof(version), f) != sizeof(version)) {
- fclose(f);
- return false;
- }
-
- if(version != 1) {
- systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
- N_("Unsupported cheat list version %d"), version);
- fclose(f);
- return false;
- }
-
- int type = 0;
- if(fread(&type, 1, sizeof(type), f) != sizeof(type)) {
- fclose(f);
- return false;
- }
-
- if(type != 0) {
- systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
- N_("Unsupported cheat list type %d"), type);
- fclose(f);
- return false;
- }
-
- if(fread(&count, 1, sizeof(count), f) != sizeof(count)) {
- fclose(f);
- return false;
- }
-
- if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) {
- fclose(f);
- return false;
- }
-
- bool firstCodeBreaker = true;
-
- for(int i = 0; i < count; i++) {
- cheatsList[i].status = 0; // remove old status as it is not used
- if(!cheatsList[i].codestring[0]) {
- switch(cheatsList[i].size) {
- case 0:
- sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
- cheatsList[i].value);
- break;
- case 1:
- sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
- cheatsList[i].value);
- break;
- case 2:
- sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
- cheatsList[i].value);
- break;
- }
- }
-
- if(cheatsList[i].code == 512 && firstCodeBreaker) {
- firstCodeBreaker = false;
- char buffer[10];
- strncpy(buffer, cheatsList[i].codestring, 8);
- buffer[8] = 0;
- u32 address;
- sscanf(buffer, "%x", &address);
- if((address >> 28) == 9) {
- strncpy(buffer, &cheatsList[i].codestring[9], 4);
- buffer[4] = 0;
- u32 value;
- sscanf(buffer, "%x", &value);
-
- u32 seed[8];
- cheatsCBAParseSeedCode(address, value, seed);
- cheatsCBAChangeEncryption(seed);
- }
- }
- }
- cheatsNumber = count;
- fclose(f);
- return true;
-}
-
-extern int cpuNextEvent;
-
-extern void debuggerBreakOnWrite(u32 , u32, u32, int, int);
-
-static u8 cheatsGetType(u32 address)
-{
- switch(address >> 24) {
- case 2:
- return freezeWorkRAM[address & 0x3FFFF];
- case 3:
- return freezeInternalRAM[address & 0x7FFF];
- }
- return 0;
-}
-
-void cheatsWriteMemory(u32 address, u32 value)
-{
-#ifdef BKPT_SUPPORT
-#ifdef SDL
- if(cheatsNumber == 0) {
- int type = cheatsGetType(address);
- u32 oldValue = debuggerReadMemory(address);
- if(type == 1 || (type == 2 && oldValue != value)) {
- debuggerBreakOnWrite(address, oldValue, value, 2, type);
- cpuNextEvent = 0;
- }
- debuggerWriteMemory(address, value);
- }
-#endif
-#endif
-}
-
-void cheatsWriteHalfWord(u32 address, u16 value)
-{
-#ifdef BKPT_SUPPORT
-#ifdef SDL
- if(cheatsNumber == 0) {
- int type = cheatsGetType(address);
- u16 oldValue = debuggerReadHalfWord(address);
- if(type == 1 || (type == 2 && oldValue != value)) {
- debuggerBreakOnWrite(address, oldValue, value, 1, type);
- cpuNextEvent = 0;
- }
- debuggerWriteHalfWord(address, value);
- }
-#endif
-#endif
-}
-
-#if defined BKPT_SUPPORT && defined SDL
-void cheatsWriteByte(u32 address, u8 value)
-#else
-void cheatsWriteByte(u32, u8)
-#endif
-{
-#ifdef BKPT_SUPPORT
-#ifdef SDL
- if(cheatsNumber == 0) {
- int type = cheatsGetType(address);
- u8 oldValue = debuggerReadByte(address);
- if(type == 1 || (type == 2 && oldValue != value)) {
- debuggerBreakOnWrite(address, oldValue, value, 0, type);
- cpuNextEvent = 0;
- }
- debuggerWriteByte(address, value);
- }
-#endif
-#endif
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+#include
+#include
+
+#include "GBA.h"
+#include "GBAinline.h"
+#include "Cheats.h"
+#include "Globals.h"
+#include "NLS.h"
+#include "Util.h"
+
+/**
+ * Gameshark code types: (based on AR v1.0)
+ *
+ * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
+ * DEADFACE XXXXXXXX - changes decryption seeds // Not supported by VBA.
+ * 0AAAAAAA 000000YY - 8-bit constant write
+ * 1AAAAAAA 0000YYYY - 16-bit constant write
+ * 2AAAAAAA YYYYYYYY - 32-bit constant write
+ * 30XXAAAA YYYYYYYY - 32bit Group Write, 8/16/32bit Sub/Add (depending on the XX value).
+ * 6AAAAAAA Z000YYYY - 16-bit ROM Patch (address >> 1). Z selects the Rom Patching register.
+ * - AR v1/2 hardware only supports Z=0.
+ * - AR v3 hardware should support Z=0,1,2 or 3.
+ * 8A1AAAAA 000000YY - 8-bit button write
+ * 8A2AAAAA 0000YYYY - 16-bit button write
+ * 8A4AAAAA YYYYYYYY - 32-bit button write // BUGGY ! Only writes 00000000 on the AR v1.0.
+ * 80F00000 0000YYYY - button slow motion
+ * DAAAAAAA 00Z0YYYY - Z = 0 : if 16-bit value at address != YYYY skip next line
+ * - Z = 1 : if 16-bit value at address == YYYY skip next line
+ * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip next line
+ * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip next line
+ * E0CCYYYY ZAAAAAAA - Z = 0 : if 16-bit value at address != YYYY skip CC lines
+ * - Z = 1 : if 16-bit value at address == YYYY skip CC lines
+ * - Z = 2 : if 16-bit value at address > YYYY (Unsigned) skip CC lines
+ * - Z = 3 : if 16-bit value at address < YYYY (Unsigned) skip CC lines
+ * FAAAAAAA 0000YYYY - Master code function
+ *
+ *
+ *
+ * CodeBreaker codes types: (based on the CBA clone "Cheatcode S" v1.1)
+ *
+ * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
+ * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
+ * + 0x08000100))
+ * 2AAAAAAA YYYY - 16-bit or
+ * 3AAAAAAA YYYY - 8-bit constant write
+ * 4AAAAAAA YYYY - Slide code
+ * XXXXCCCC IIII (C is count and I is address increment, X is value incr.)
+ * 5AAAAAAA CCCC - Super code (Write bytes to address, 2*CCCC is count)
+ * BBBBBBBB BBBB
+ * 6AAAAAAA YYYY - 16-bit and
+ * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
+ * 8AAAAAAA YYYY - 16-bit constant write
+ * 9AAAAAAA YYYY - change decryption (when first code only?)
+ * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
+ * BAAAAAAA YYYY - if 16-bit value at address <= YYYY skip next code
+ * CAAAAAAA YYYY - if 16-bit value at address >= YYYY skip next code
+ * D00000X0 YYYY - if button keys ... enable next code (else skip next code)
+ * EAAAAAAA YYYY - increase 16/32bit value stored in address
+ * FAAAAAAA YYYY - if 16-bit value at address AND YYYY = 0 then skip next code
+ **/
+
+#define UNKNOWN_CODE -1
+#define INT_8_BIT_WRITE 0
+#define INT_16_BIT_WRITE 1
+#define INT_32_BIT_WRITE 2
+#define GSA_16_BIT_ROM_PATCH 3
+#define GSA_8_BIT_GS_WRITE 4
+#define GSA_16_BIT_GS_WRITE 5
+#define GSA_32_BIT_GS_WRITE 6
+#define CBA_IF_KEYS_PRESSED 7
+#define CBA_IF_TRUE 8
+#define CBA_SLIDE_CODE 9
+#define CBA_IF_FALSE 10
+#define CBA_AND 11
+#define GSA_8_BIT_GS_WRITE2 12
+#define GSA_16_BIT_GS_WRITE2 13
+#define GSA_32_BIT_GS_WRITE2 14
+#define GSA_16_BIT_ROM_PATCH2C 15
+#define GSA_8_BIT_SLIDE 16
+#define GSA_16_BIT_SLIDE 17
+#define GSA_32_BIT_SLIDE 18
+#define GSA_8_BIT_IF_TRUE 19
+#define GSA_32_BIT_IF_TRUE 20
+#define GSA_8_BIT_IF_FALSE 21
+#define GSA_32_BIT_IF_FALSE 22
+#define GSA_8_BIT_FILL 23
+#define GSA_16_BIT_FILL 24
+#define GSA_8_BIT_IF_TRUE2 25
+#define GSA_16_BIT_IF_TRUE2 26
+#define GSA_32_BIT_IF_TRUE2 27
+#define GSA_8_BIT_IF_FALSE2 28
+#define GSA_16_BIT_IF_FALSE2 29
+#define GSA_32_BIT_IF_FALSE2 30
+#define GSA_SLOWDOWN 31
+#define CBA_ADD 32
+#define CBA_OR 33
+#define CBA_LT 34
+#define CBA_GT 35
+#define CBA_SUPER 36
+#define GSA_8_BIT_POINTER 37
+#define GSA_16_BIT_POINTER 38
+#define GSA_32_BIT_POINTER 39
+#define GSA_8_BIT_ADD 40
+#define GSA_16_BIT_ADD 41
+#define GSA_32_BIT_ADD 42
+#define GSA_8_BIT_IF_LOWER_U 43
+#define GSA_16_BIT_IF_LOWER_U 44
+#define GSA_32_BIT_IF_LOWER_U 45
+#define GSA_8_BIT_IF_HIGHER_U 46
+#define GSA_16_BIT_IF_HIGHER_U 47
+#define GSA_32_BIT_IF_HIGHER_U 48
+#define GSA_8_BIT_IF_AND 49
+#define GSA_16_BIT_IF_AND 50
+#define GSA_32_BIT_IF_AND 51
+#define GSA_8_BIT_IF_LOWER_U2 52
+#define GSA_16_BIT_IF_LOWER_U2 53
+#define GSA_32_BIT_IF_LOWER_U2 54
+#define GSA_8_BIT_IF_HIGHER_U2 55
+#define GSA_16_BIT_IF_HIGHER_U2 56
+#define GSA_32_BIT_IF_HIGHER_U2 57
+#define GSA_8_BIT_IF_AND2 58
+#define GSA_16_BIT_IF_AND2 59
+#define GSA_32_BIT_IF_AND2 60
+#define GSA_ALWAYS 61
+#define GSA_ALWAYS2 62
+#define GSA_8_BIT_IF_LOWER_S 63
+#define GSA_16_BIT_IF_LOWER_S 64
+#define GSA_32_BIT_IF_LOWER_S 65
+#define GSA_8_BIT_IF_HIGHER_S 66
+#define GSA_16_BIT_IF_HIGHER_S 67
+#define GSA_32_BIT_IF_HIGHER_S 68
+#define GSA_8_BIT_IF_LOWER_S2 69
+#define GSA_16_BIT_IF_LOWER_S2 70
+#define GSA_32_BIT_IF_LOWER_S2 71
+#define GSA_8_BIT_IF_HIGHER_S2 72
+#define GSA_16_BIT_IF_HIGHER_S2 73
+#define GSA_32_BIT_IF_HIGHER_S2 74
+#define GSA_16_BIT_WRITE_IOREGS 75
+#define GSA_32_BIT_WRITE_IOREGS 76
+#define GSA_CODES_ON 77
+#define GSA_8_BIT_IF_TRUE3 78
+#define GSA_16_BIT_IF_TRUE3 79
+#define GSA_32_BIT_IF_TRUE3 80
+#define GSA_8_BIT_IF_FALSE3 81
+#define GSA_16_BIT_IF_FALSE3 82
+#define GSA_32_BIT_IF_FALSE3 83
+#define GSA_8_BIT_IF_LOWER_S3 84
+#define GSA_16_BIT_IF_LOWER_S3 85
+#define GSA_32_BIT_IF_LOWER_S3 86
+#define GSA_8_BIT_IF_HIGHER_S3 87
+#define GSA_16_BIT_IF_HIGHER_S3 88
+#define GSA_32_BIT_IF_HIGHER_S3 89
+#define GSA_8_BIT_IF_LOWER_U3 90
+#define GSA_16_BIT_IF_LOWER_U3 91
+#define GSA_32_BIT_IF_LOWER_U3 92
+#define GSA_8_BIT_IF_HIGHER_U3 93
+#define GSA_16_BIT_IF_HIGHER_U3 94
+#define GSA_32_BIT_IF_HIGHER_U3 95
+#define GSA_8_BIT_IF_AND3 96
+#define GSA_16_BIT_IF_AND3 97
+#define GSA_32_BIT_IF_AND3 98
+#define GSA_ALWAYS3 99
+#define GSA_16_BIT_ROM_PATCH2D 100
+#define GSA_16_BIT_ROM_PATCH2E 101
+#define GSA_16_BIT_ROM_PATCH2F 102
+#define GSA_GROUP_WRITE 103
+#define GSA_32_BIT_ADD2 104
+#define GSA_32_BIT_SUB2 105
+#define GSA_16_BIT_IF_LOWER_OR_EQ_U 106
+#define GSA_16_BIT_IF_HIGHER_OR_EQ_U 107
+#define GSA_16_BIT_MIF_TRUE 108
+#define GSA_16_BIT_MIF_FALSE 109
+#define GSA_16_BIT_MIF_LOWER_OR_EQ_U 110
+#define GSA_16_BIT_MIF_HIGHER_OR_EQ_U 111
+#define MASTER_CODE 112
+#define CHEATS_16_BIT_WRITE 114
+#define CHEATS_32_BIT_WRITE 115
+
+CheatsData cheatsList[100];
+int cheatsNumber = 0;
+u32 rompatch2addr [4];
+u16 rompatch2val [4];
+u16 rompatch2oldval [4];
+
+u8 cheatsCBASeedBuffer[0x30];
+u32 cheatsCBASeed[4];
+u32 cheatsCBATemporaryValue = 0;
+u16 cheatsCBATable[256];
+bool cheatsCBATableGenerated = false;
+u16 super = 0;
+extern u32 mastercode;
+
+u8 cheatsCBACurrentSeed[12] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+u32 seeds_v1[4];
+u32 seeds_v3[4];
+
+u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2);
+
+//seed tables for AR v1
+u8 v1_deadtable1[256] = {
+ 0x31, 0x1C, 0x23, 0xE5, 0x89, 0x8E, 0xA1, 0x37, 0x74, 0x6D, 0x67, 0xFC, 0x1F, 0xC0, 0xB1, 0x94,
+ 0x3B, 0x05, 0x56, 0x86, 0x00, 0x24, 0xF0, 0x17, 0x72, 0xA2, 0x3D, 0x1B, 0xE3, 0x17, 0xC5, 0x0B,
+ 0xB9, 0xE2, 0xBD, 0x58, 0x71, 0x1B, 0x2C, 0xFF, 0xE4, 0xC9, 0x4C, 0x5E, 0xC9, 0x55, 0x33, 0x45,
+ 0x7C, 0x3F, 0xB2, 0x51, 0xFE, 0x10, 0x7E, 0x75, 0x3C, 0x90, 0x8D, 0xDA, 0x94, 0x38, 0xC3, 0xE9,
+ 0x95, 0xEA, 0xCE, 0xA6, 0x06, 0xE0, 0x4F, 0x3F, 0x2A, 0xE3, 0x3A, 0xE4, 0x43, 0xBD, 0x7F, 0xDA,
+ 0x55, 0xF0, 0xEA, 0xCB, 0x2C, 0xA8, 0x47, 0x61, 0xA0, 0xEF, 0xCB, 0x13, 0x18, 0x20, 0xAF, 0x3E,
+ 0x4D, 0x9E, 0x1E, 0x77, 0x51, 0xC5, 0x51, 0x20, 0xCF, 0x21, 0xF9, 0x39, 0x94, 0xDE, 0xDD, 0x79,
+ 0x4E, 0x80, 0xC4, 0x9D, 0x94, 0xD5, 0x95, 0x01, 0x27, 0x27, 0xBD, 0x6D, 0x78, 0xB5, 0xD1, 0x31,
+ 0x6A, 0x65, 0x74, 0x74, 0x58, 0xB3, 0x7C, 0xC9, 0x5A, 0xED, 0x50, 0x03, 0xC4, 0xA2, 0x94, 0x4B,
+ 0xF0, 0x58, 0x09, 0x6F, 0x3E, 0x7D, 0xAE, 0x7D, 0x58, 0xA0, 0x2C, 0x91, 0xBB, 0xE1, 0x70, 0xEB,
+ 0x73, 0xA6, 0x9A, 0x44, 0x25, 0x90, 0x16, 0x62, 0x53, 0xAE, 0x08, 0xEB, 0xDC, 0xF0, 0xEE, 0x77,
+ 0xC2, 0xDE, 0x81, 0xE8, 0x30, 0x89, 0xDB, 0xFE, 0xBC, 0xC2, 0xDF, 0x26, 0xE9, 0x8B, 0xD6, 0x93,
+ 0xF0, 0xCB, 0x56, 0x90, 0xC0, 0x46, 0x68, 0x15, 0x43, 0xCB, 0xE9, 0x98, 0xE3, 0xAF, 0x31, 0x25,
+ 0x4D, 0x7B, 0xF3, 0xB1, 0x74, 0xE2, 0x64, 0xAC, 0xD9, 0xF6, 0xA0, 0xD5, 0x0B, 0x9B, 0x49, 0x52,
+ 0x69, 0x3B, 0x71, 0x00, 0x2F, 0xBB, 0xBA, 0x08, 0xB1, 0xAE, 0xBB, 0xB3, 0xE1, 0xC9, 0xA6, 0x7F,
+ 0x17, 0x97, 0x28, 0x72, 0x12, 0x6E, 0x91, 0xAE, 0x3A, 0xA2, 0x35, 0x46, 0x27, 0xF8, 0x12, 0x50
+};
+u8 v1_deadtable2[256] = {
+ 0xD8, 0x65, 0x04, 0xC2, 0x65, 0xD5, 0xB0, 0x0C, 0xDF, 0x9D, 0xF0, 0xC3, 0x9A, 0x17, 0xC9, 0xA6,
+ 0xE1, 0xAC, 0x0D, 0x14, 0x2F, 0x3C, 0x2C, 0x87, 0xA2, 0xBF, 0x4D, 0x5F, 0xAC, 0x2D, 0x9D, 0xE1,
+ 0x0C, 0x9C, 0xE7, 0x7F, 0xFC, 0xA8, 0x66, 0x59, 0xAC, 0x18, 0xD7, 0x05, 0xF0, 0xBF, 0xD1, 0x8B,
+ 0x35, 0x9F, 0x59, 0xB4, 0xBA, 0x55, 0xB2, 0x85, 0xFD, 0xB1, 0x72, 0x06, 0x73, 0xA4, 0xDB, 0x48,
+ 0x7B, 0x5F, 0x67, 0xA5, 0x95, 0xB9, 0xA5, 0x4A, 0xCF, 0xD1, 0x44, 0xF3, 0x81, 0xF5, 0x6D, 0xF6,
+ 0x3A, 0xC3, 0x57, 0x83, 0xFA, 0x8E, 0x15, 0x2A, 0xA2, 0x04, 0xB2, 0x9D, 0xA8, 0x0D, 0x7F, 0xB8,
+ 0x0F, 0xF6, 0xAC, 0xBE, 0x97, 0xCE, 0x16, 0xE6, 0x31, 0x10, 0x60, 0x16, 0xB5, 0x83, 0x45, 0xEE,
+ 0xD7, 0x5F, 0x2C, 0x08, 0x58, 0xB1, 0xFD, 0x7E, 0x79, 0x00, 0x34, 0xAD, 0xB5, 0x31, 0x34, 0x39,
+ 0xAF, 0xA8, 0xDD, 0x52, 0x6A, 0xB0, 0x60, 0x35, 0xB8, 0x1D, 0x52, 0xF5, 0xF5, 0x30, 0x00, 0x7B,
+ 0xF4, 0xBA, 0x03, 0xCB, 0x3A, 0x84, 0x14, 0x8A, 0x6A, 0xEF, 0x21, 0xBD, 0x01, 0xD8, 0xA0, 0xD4,
+ 0x43, 0xBE, 0x23, 0xE7, 0x76, 0x27, 0x2C, 0x3F, 0x4D, 0x3F, 0x43, 0x18, 0xA7, 0xC3, 0x47, 0xA5,
+ 0x7A, 0x1D, 0x02, 0x55, 0x09, 0xD1, 0xFF, 0x55, 0x5E, 0x17, 0xA0, 0x56, 0xF4, 0xC9, 0x6B, 0x90,
+ 0xB4, 0x80, 0xA5, 0x07, 0x22, 0xFB, 0x22, 0x0D, 0xD9, 0xC0, 0x5B, 0x08, 0x35, 0x05, 0xC1, 0x75,
+ 0x4F, 0xD0, 0x51, 0x2D, 0x2E, 0x5E, 0x69, 0xE7, 0x3B, 0xC2, 0xDA, 0xFF, 0xF6, 0xCE, 0x3E, 0x76,
+ 0xE8, 0x36, 0x8C, 0x39, 0xD8, 0xF3, 0xE9, 0xA6, 0x42, 0xE6, 0xC1, 0x4C, 0x05, 0xBE, 0x17, 0xF2,
+ 0x5C, 0x1B, 0x19, 0xDB, 0x0F, 0xF3, 0xF8, 0x49, 0xEB, 0x36, 0xF6, 0x40, 0x6F, 0xAD, 0xC1, 0x8C
+};
+
+//seed tables for AR v3
+u8 v3_deadtable1[256] = {
+ 0xD0, 0xFF, 0xBA, 0xE5, 0xC1, 0xC7, 0xDB, 0x5B, 0x16, 0xE3, 0x6E, 0x26, 0x62, 0x31, 0x2E, 0x2A,
+ 0xD1, 0xBB, 0x4A, 0xE6, 0xAE, 0x2F, 0x0A, 0x90, 0x29, 0x90, 0xB6, 0x67, 0x58, 0x2A, 0xB4, 0x45,
+ 0x7B, 0xCB, 0xF0, 0x73, 0x84, 0x30, 0x81, 0xC2, 0xD7, 0xBE, 0x89, 0xD7, 0x4E, 0x73, 0x5C, 0xC7,
+ 0x80, 0x1B, 0xE5, 0xE4, 0x43, 0xC7, 0x46, 0xD6, 0x6F, 0x7B, 0xBF, 0xED, 0xE5, 0x27, 0xD1, 0xB5,
+ 0xD0, 0xD8, 0xA3, 0xCB, 0x2B, 0x30, 0xA4, 0xF0, 0x84, 0x14, 0x72, 0x5C, 0xFF, 0xA4, 0xFB, 0x54,
+ 0x9D, 0x70, 0xE2, 0xFF, 0xBE, 0xE8, 0x24, 0x76, 0xE5, 0x15, 0xFB, 0x1A, 0xBC, 0x87, 0x02, 0x2A,
+ 0x58, 0x8F, 0x9A, 0x95, 0xBD, 0xAE, 0x8D, 0x0C, 0xA5, 0x4C, 0xF2, 0x5C, 0x7D, 0xAD, 0x51, 0xFB,
+ 0xB1, 0x22, 0x07, 0xE0, 0x29, 0x7C, 0xEB, 0x98, 0x14, 0xC6, 0x31, 0x97, 0xE4, 0x34, 0x8F, 0xCC,
+ 0x99, 0x56, 0x9F, 0x78, 0x43, 0x91, 0x85, 0x3F, 0xC2, 0xD0, 0xD1, 0x80, 0xD1, 0x77, 0xA7, 0xE2,
+ 0x43, 0x99, 0x1D, 0x2F, 0x8B, 0x6A, 0xE4, 0x66, 0x82, 0xF7, 0x2B, 0x0B, 0x65, 0x14, 0xC0, 0xC2,
+ 0x1D, 0x96, 0x78, 0x1C, 0xC4, 0xC3, 0xD2, 0xB1, 0x64, 0x07, 0xD7, 0x6F, 0x02, 0xE9, 0x44, 0x31,
+ 0xDB, 0x3C, 0xEB, 0x93, 0xED, 0x9A, 0x57, 0x05, 0xB9, 0x0E, 0xAF, 0x1F, 0x48, 0x11, 0xDC, 0x35,
+ 0x6C, 0xB8, 0xEE, 0x2A, 0x48, 0x2B, 0xBC, 0x89, 0x12, 0x59, 0xCB, 0xD1, 0x18, 0xEA, 0x72, 0x11,
+ 0x01, 0x75, 0x3B, 0xB5, 0x56, 0xF4, 0x8B, 0xA0, 0x41, 0x75, 0x86, 0x7B, 0x94, 0x12, 0x2D, 0x4C,
+ 0x0C, 0x22, 0xC9, 0x4A, 0xD8, 0xB1, 0x8D, 0xF0, 0x55, 0x2E, 0x77, 0x50, 0x1C, 0x64, 0x77, 0xAA,
+ 0x3E, 0xAC, 0xD3, 0x3D, 0xCE, 0x60, 0xCA, 0x5D, 0xA0, 0x92, 0x78, 0xC6, 0x51, 0xFE, 0xF9, 0x30
+};
+u8 v3_deadtable2[256] = {
+ 0xAA, 0xAF, 0xF0, 0x72, 0x90, 0xF7, 0x71, 0x27, 0x06, 0x11, 0xEB, 0x9C, 0x37, 0x12, 0x72, 0xAA,
+ 0x65, 0xBC, 0x0D, 0x4A, 0x76, 0xF6, 0x5C, 0xAA, 0xB0, 0x7A, 0x7D, 0x81, 0xC1, 0xCE, 0x2F, 0x9F,
+ 0x02, 0x75, 0x38, 0xC8, 0xFC, 0x66, 0x05, 0xC2, 0x2C, 0xBD, 0x91, 0xAD, 0x03, 0xB1, 0x88, 0x93,
+ 0x31, 0xC6, 0xAB, 0x40, 0x23, 0x43, 0x76, 0x54, 0xCA, 0xE7, 0x00, 0x96, 0x9F, 0xD8, 0x24, 0x8B,
+ 0xE4, 0xDC, 0xDE, 0x48, 0x2C, 0xCB, 0xF7, 0x84, 0x1D, 0x45, 0xE5, 0xF1, 0x75, 0xA0, 0xED, 0xCD,
+ 0x4B, 0x24, 0x8A, 0xB3, 0x98, 0x7B, 0x12, 0xB8, 0xF5, 0x63, 0x97, 0xB3, 0xA6, 0xA6, 0x0B, 0xDC,
+ 0xD8, 0x4C, 0xA8, 0x99, 0x27, 0x0F, 0x8F, 0x94, 0x63, 0x0F, 0xB0, 0x11, 0x94, 0xC7, 0xE9, 0x7F,
+ 0x3B, 0x40, 0x72, 0x4C, 0xDB, 0x84, 0x78, 0xFE, 0xB8, 0x56, 0x08, 0x80, 0xDF, 0x20, 0x2F, 0xB9,
+ 0x66, 0x2D, 0x60, 0x63, 0xF5, 0x18, 0x15, 0x1B, 0x86, 0x85, 0xB9, 0xB4, 0x68, 0x0E, 0xC6, 0xD1,
+ 0x8A, 0x81, 0x2B, 0xB3, 0xF6, 0x48, 0xF0, 0x4F, 0x9C, 0x28, 0x1C, 0xA4, 0x51, 0x2F, 0xD7, 0x4B,
+ 0x17, 0xE7, 0xCC, 0x50, 0x9F, 0xD0, 0xD1, 0x40, 0x0C, 0x0D, 0xCA, 0x83, 0xFA, 0x5E, 0xCA, 0xEC,
+ 0xBF, 0x4E, 0x7C, 0x8F, 0xF0, 0xAE, 0xC2, 0xD3, 0x28, 0x41, 0x9B, 0xC8, 0x04, 0xB9, 0x4A, 0xBA,
+ 0x72, 0xE2, 0xB5, 0x06, 0x2C, 0x1E, 0x0B, 0x2C, 0x7F, 0x11, 0xA9, 0x26, 0x51, 0x9D, 0x3F, 0xF8,
+ 0x62, 0x11, 0x2E, 0x89, 0xD2, 0x9D, 0x35, 0xB1, 0xE4, 0x0A, 0x4D, 0x93, 0x01, 0xA7, 0xD1, 0x2D,
+ 0x00, 0x87, 0xE2, 0x2D, 0xA4, 0xE9, 0x0A, 0x06, 0x66, 0xF8, 0x1F, 0x44, 0x75, 0xB5, 0x6B, 0x1C,
+ 0xFC, 0x31, 0x09, 0x48, 0xA3, 0xFF, 0x92, 0x12, 0x58, 0xE9, 0xFA, 0xAE, 0x4F, 0xE2, 0xB4, 0xCC
+};
+
+#define debuggerReadMemory(addr) \
+ READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
+
+#define debuggerReadHalfWord(addr) \
+ READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
+
+#define debuggerReadByte(addr) \
+ map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
+
+#define debuggerWriteMemory(addr, value) \
+ WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
+
+#define debuggerWriteHalfWord(addr, value) \
+ WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
+
+#define debuggerWriteByte(addr, value) \
+ map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
+
+
+#define CHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9'))
+
+#define CHEAT_PATCH_ROM_16BIT(a,v) \
+ WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v);
+
+#define CHEAT_PATCH_ROM_32BIT(a,v) \
+ WRITE32LE(((u32 *)&rom[(a) & 0x1ffffff]), v);
+
+static bool isMultilineWithData(int i)
+{
+ // we consider it a multiline code if it has more than one line of data
+ // otherwise, it can still be considered a single code
+ // (Only CBA codes can be true multilines !!!)
+ if(i < cheatsNumber && i >= 0)
+ switch(cheatsList[i].size) {
+ case INT_8_BIT_WRITE:
+ case INT_16_BIT_WRITE:
+ case INT_32_BIT_WRITE:
+ case GSA_16_BIT_ROM_PATCH:
+ case GSA_8_BIT_GS_WRITE:
+ case GSA_16_BIT_GS_WRITE:
+ case GSA_32_BIT_GS_WRITE:
+ case CBA_AND:
+ case CBA_IF_KEYS_PRESSED:
+ case CBA_IF_TRUE:
+ case CBA_IF_FALSE:
+ case GSA_8_BIT_IF_TRUE:
+ case GSA_32_BIT_IF_TRUE:
+ case GSA_8_BIT_IF_FALSE:
+ case GSA_32_BIT_IF_FALSE:
+ case GSA_8_BIT_FILL:
+ case GSA_16_BIT_FILL:
+ case GSA_8_BIT_IF_TRUE2:
+ case GSA_16_BIT_IF_TRUE2:
+ case GSA_32_BIT_IF_TRUE2:
+ case GSA_8_BIT_IF_FALSE2:
+ case GSA_16_BIT_IF_FALSE2:
+ case GSA_32_BIT_IF_FALSE2:
+ case GSA_SLOWDOWN:
+ case CBA_ADD:
+ case CBA_OR:
+ case CBA_LT:
+ case CBA_GT:
+ case GSA_8_BIT_POINTER:
+ case GSA_16_BIT_POINTER:
+ case GSA_32_BIT_POINTER:
+ case GSA_8_BIT_ADD:
+ case GSA_16_BIT_ADD:
+ case GSA_32_BIT_ADD:
+ case GSA_8_BIT_IF_LOWER_U:
+ case GSA_16_BIT_IF_LOWER_U:
+ case GSA_32_BIT_IF_LOWER_U:
+ case GSA_8_BIT_IF_HIGHER_U:
+ case GSA_16_BIT_IF_HIGHER_U:
+ case GSA_32_BIT_IF_HIGHER_U:
+ case GSA_8_BIT_IF_AND:
+ case GSA_16_BIT_IF_AND:
+ case GSA_32_BIT_IF_AND:
+ case GSA_8_BIT_IF_LOWER_U2:
+ case GSA_16_BIT_IF_LOWER_U2:
+ case GSA_32_BIT_IF_LOWER_U2:
+ case GSA_8_BIT_IF_HIGHER_U2:
+ case GSA_16_BIT_IF_HIGHER_U2:
+ case GSA_32_BIT_IF_HIGHER_U2:
+ case GSA_8_BIT_IF_AND2:
+ case GSA_16_BIT_IF_AND2:
+ case GSA_32_BIT_IF_AND2:
+ case GSA_ALWAYS:
+ case GSA_ALWAYS2:
+ case GSA_8_BIT_IF_LOWER_S:
+ case GSA_16_BIT_IF_LOWER_S:
+ case GSA_32_BIT_IF_LOWER_S:
+ case GSA_8_BIT_IF_HIGHER_S:
+ case GSA_16_BIT_IF_HIGHER_S:
+ case GSA_32_BIT_IF_HIGHER_S:
+ case GSA_8_BIT_IF_LOWER_S2:
+ case GSA_16_BIT_IF_LOWER_S2:
+ case GSA_32_BIT_IF_LOWER_S2:
+ case GSA_8_BIT_IF_HIGHER_S2:
+ case GSA_16_BIT_IF_HIGHER_S2:
+ case GSA_32_BIT_IF_HIGHER_S2:
+ case GSA_16_BIT_WRITE_IOREGS:
+ case GSA_32_BIT_WRITE_IOREGS:
+ case GSA_CODES_ON:
+ case GSA_8_BIT_IF_TRUE3:
+ case GSA_16_BIT_IF_TRUE3:
+ case GSA_32_BIT_IF_TRUE3:
+ case GSA_8_BIT_IF_FALSE3:
+ case GSA_16_BIT_IF_FALSE3:
+ case GSA_32_BIT_IF_FALSE3:
+ case GSA_8_BIT_IF_LOWER_S3:
+ case GSA_16_BIT_IF_LOWER_S3:
+ case GSA_32_BIT_IF_LOWER_S3:
+ case GSA_8_BIT_IF_HIGHER_S3:
+ case GSA_16_BIT_IF_HIGHER_S3:
+ case GSA_32_BIT_IF_HIGHER_S3:
+ case GSA_8_BIT_IF_LOWER_U3:
+ case GSA_16_BIT_IF_LOWER_U3:
+ case GSA_32_BIT_IF_LOWER_U3:
+ case GSA_8_BIT_IF_HIGHER_U3:
+ case GSA_16_BIT_IF_HIGHER_U3:
+ case GSA_32_BIT_IF_HIGHER_U3:
+ case GSA_8_BIT_IF_AND3:
+ case GSA_16_BIT_IF_AND3:
+ case GSA_32_BIT_IF_AND3:
+ case GSA_ALWAYS3:
+ case GSA_8_BIT_GS_WRITE2:
+ case GSA_16_BIT_GS_WRITE2:
+ case GSA_32_BIT_GS_WRITE2:
+ case GSA_16_BIT_ROM_PATCH2C:
+ case GSA_16_BIT_ROM_PATCH2D:
+ case GSA_16_BIT_ROM_PATCH2E:
+ case GSA_16_BIT_ROM_PATCH2F:
+ case GSA_8_BIT_SLIDE:
+ case GSA_16_BIT_SLIDE:
+ case GSA_32_BIT_SLIDE:
+ case GSA_GROUP_WRITE:
+ case GSA_32_BIT_ADD2:
+ case GSA_32_BIT_SUB2:
+ case GSA_16_BIT_IF_LOWER_OR_EQ_U:
+ case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
+ case GSA_16_BIT_MIF_TRUE:
+ case GSA_16_BIT_MIF_FALSE:
+ case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
+ case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
+ case MASTER_CODE:
+ case CHEATS_16_BIT_WRITE:
+ case CHEATS_32_BIT_WRITE:
+ return false;
+ // the codes below have two lines of data
+ case CBA_SLIDE_CODE:
+ case CBA_SUPER:
+ return true;
+ }
+ return false;
+}
+
+static int getCodeLength(int num)
+{
+ if(num >= cheatsNumber || num < 0)
+ return 1;
+
+ // this is for all the codes that are true multiline
+ switch(cheatsList[num].size) {
+ case INT_8_BIT_WRITE:
+ case INT_16_BIT_WRITE:
+ case INT_32_BIT_WRITE:
+ case GSA_16_BIT_ROM_PATCH:
+ case GSA_8_BIT_GS_WRITE:
+ case GSA_16_BIT_GS_WRITE:
+ case GSA_32_BIT_GS_WRITE:
+ case CBA_AND:
+ case GSA_8_BIT_FILL:
+ case GSA_16_BIT_FILL:
+ case GSA_SLOWDOWN:
+ case CBA_ADD:
+ case CBA_OR:
+ case GSA_8_BIT_POINTER:
+ case GSA_16_BIT_POINTER:
+ case GSA_32_BIT_POINTER:
+ case GSA_8_BIT_ADD:
+ case GSA_16_BIT_ADD:
+ case GSA_32_BIT_ADD:
+ case GSA_CODES_ON:
+ case GSA_8_BIT_IF_TRUE3:
+ case GSA_16_BIT_IF_TRUE3:
+ case GSA_32_BIT_IF_TRUE3:
+ case GSA_8_BIT_IF_FALSE3:
+ case GSA_16_BIT_IF_FALSE3:
+ case GSA_32_BIT_IF_FALSE3:
+ case GSA_8_BIT_IF_LOWER_S3:
+ case GSA_16_BIT_IF_LOWER_S3:
+ case GSA_32_BIT_IF_LOWER_S3:
+ case GSA_8_BIT_IF_HIGHER_S3:
+ case GSA_16_BIT_IF_HIGHER_S3:
+ case GSA_32_BIT_IF_HIGHER_S3:
+ case GSA_8_BIT_IF_LOWER_U3:
+ case GSA_16_BIT_IF_LOWER_U3:
+ case GSA_32_BIT_IF_LOWER_U3:
+ case GSA_8_BIT_IF_HIGHER_U3:
+ case GSA_16_BIT_IF_HIGHER_U3:
+ case GSA_32_BIT_IF_HIGHER_U3:
+ case GSA_8_BIT_IF_AND3:
+ case GSA_16_BIT_IF_AND3:
+ case GSA_32_BIT_IF_AND3:
+ case GSA_8_BIT_IF_LOWER_U:
+ case GSA_16_BIT_IF_LOWER_U:
+ case GSA_32_BIT_IF_LOWER_U:
+ case GSA_8_BIT_IF_HIGHER_U:
+ case GSA_16_BIT_IF_HIGHER_U:
+ case GSA_32_BIT_IF_HIGHER_U:
+ case GSA_8_BIT_IF_AND:
+ case GSA_16_BIT_IF_AND:
+ case GSA_32_BIT_IF_AND:
+ case GSA_ALWAYS:
+ case GSA_8_BIT_IF_LOWER_S:
+ case GSA_16_BIT_IF_LOWER_S:
+ case GSA_32_BIT_IF_LOWER_S:
+ case GSA_8_BIT_IF_HIGHER_S:
+ case GSA_16_BIT_IF_HIGHER_S:
+ case GSA_32_BIT_IF_HIGHER_S:
+ case GSA_16_BIT_WRITE_IOREGS:
+ case GSA_32_BIT_WRITE_IOREGS:
+ case GSA_8_BIT_GS_WRITE2:
+ case GSA_16_BIT_GS_WRITE2:
+ case GSA_32_BIT_GS_WRITE2:
+ case GSA_16_BIT_ROM_PATCH2C:
+ case GSA_16_BIT_ROM_PATCH2D:
+ case GSA_16_BIT_ROM_PATCH2E:
+ case GSA_16_BIT_ROM_PATCH2F:
+ case GSA_8_BIT_SLIDE:
+ case GSA_16_BIT_SLIDE:
+ case GSA_32_BIT_SLIDE:
+ case GSA_8_BIT_IF_TRUE:
+ case GSA_32_BIT_IF_TRUE:
+ case GSA_8_BIT_IF_FALSE:
+ case GSA_32_BIT_IF_FALSE:
+ case CBA_LT:
+ case CBA_GT:
+ case CBA_IF_TRUE:
+ case CBA_IF_FALSE:
+ case GSA_8_BIT_IF_TRUE2:
+ case GSA_16_BIT_IF_TRUE2:
+ case GSA_32_BIT_IF_TRUE2:
+ case GSA_8_BIT_IF_FALSE2:
+ case GSA_16_BIT_IF_FALSE2:
+ case GSA_32_BIT_IF_FALSE2:
+ case GSA_8_BIT_IF_LOWER_U2:
+ case GSA_16_BIT_IF_LOWER_U2:
+ case GSA_32_BIT_IF_LOWER_U2:
+ case GSA_8_BIT_IF_HIGHER_U2:
+ case GSA_16_BIT_IF_HIGHER_U2:
+ case GSA_32_BIT_IF_HIGHER_U2:
+ case GSA_8_BIT_IF_AND2:
+ case GSA_16_BIT_IF_AND2:
+ case GSA_32_BIT_IF_AND2:
+ case GSA_ALWAYS2:
+ case GSA_8_BIT_IF_LOWER_S2:
+ case GSA_16_BIT_IF_LOWER_S2:
+ case GSA_32_BIT_IF_LOWER_S2:
+ case GSA_8_BIT_IF_HIGHER_S2:
+ case GSA_16_BIT_IF_HIGHER_S2:
+ case GSA_32_BIT_IF_HIGHER_S2:
+ case GSA_GROUP_WRITE:
+ case GSA_32_BIT_ADD2:
+ case GSA_32_BIT_SUB2:
+ case GSA_16_BIT_IF_LOWER_OR_EQ_U:
+ case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
+ case GSA_16_BIT_MIF_TRUE:
+ case GSA_16_BIT_MIF_FALSE:
+ case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
+ case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
+ case MASTER_CODE:
+ case CHEATS_16_BIT_WRITE:
+ case CHEATS_32_BIT_WRITE:
+ case UNKNOWN_CODE:
+ return 1;
+ case CBA_IF_KEYS_PRESSED:
+ case CBA_SLIDE_CODE:
+ return 2;
+ case CBA_SUPER:
+ return ((((cheatsList[num].value-1) & 0xFFFF)/3) + 1);
+ }
+ return 1;
+}
+
+int cheatsCheckKeys(u32 keys, u32 extended)
+{
+ bool onoff = true;
+ int ticks = 0;
+ int i;
+ mastercode = 0;
+
+ for (i = 0; i<4; i++)
+ if (rompatch2addr [i] != 0) {
+ CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2oldval [i]);
+ rompatch2addr [i] = 0;
+ }
+
+ for (i = 0; i < cheatsNumber; i++) {
+ if(!cheatsList[i].enabled) {
+ // make sure we skip other lines in this code
+ i += getCodeLength(i)-1;
+ continue;
+ }
+ switch(cheatsList[i].size) {
+ case GSA_CODES_ON:
+ onoff = true;
+ break;
+ case GSA_SLOWDOWN:
+ // check if button was pressed and released, if so toggle our state
+ if((cheatsList[i].status & 4) && !(extended & 4))
+ cheatsList[i].status ^= 1;
+ if(extended & 4)
+ cheatsList[i].status |= 4;
+ else
+ cheatsList[i].status &= ~4;
+
+ if(cheatsList[i].status & 1)
+ ticks += ((cheatsList[i].value & 0xFFFF) * 7);
+ break;
+ case GSA_8_BIT_SLIDE:
+ i++;
+ if(i < cheatsNumber) {
+ u32 addr = cheatsList[i-1].value;
+ u8 value = cheatsList[i].rawaddress;
+ int vinc = (cheatsList[i].value >> 24) & 255;
+ int count = (cheatsList[i].value >> 16) & 255;
+ int ainc = (cheatsList[i].value & 0xffff);
+ while(count > 0) {
+ CPUWriteByte(addr, value);
+ value += vinc;
+ addr += ainc;
+ count--;
+ }
+ }
+ break;
+ case GSA_16_BIT_SLIDE:
+ i++;
+ if(i < cheatsNumber) {
+ u32 addr = cheatsList[i-1].value;
+ u16 value = cheatsList[i].rawaddress;
+ int vinc = (cheatsList[i].value >> 24) & 255;
+ int count = (cheatsList[i].value >> 16) & 255;
+ int ainc = (cheatsList[i].value & 0xffff)*2;
+ while(count > 0) {
+ CPUWriteHalfWord(addr, value);
+ value += vinc;
+ addr += ainc;
+ count--;
+ }
+ }
+ break;
+ case GSA_32_BIT_SLIDE:
+ i++;
+ if(i < cheatsNumber) {
+ u32 addr = cheatsList[i-1].value;
+ u32 value = cheatsList[i].rawaddress;
+ int vinc = (cheatsList[i].value >> 24) & 255;
+ int count = (cheatsList[i].value >> 16) & 255;
+ int ainc = (cheatsList[i].value & 0xffff)*4;
+ while(count > 0) {
+ CPUWriteMemory(addr, value);
+ value += vinc;
+ addr += ainc;
+ count--;
+ }
+ }
+ break;
+ case GSA_8_BIT_GS_WRITE2:
+ i++;
+ if(i < cheatsNumber) {
+ if(extended & 4) {
+ CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
+ }
+ }
+ break;
+ case GSA_16_BIT_GS_WRITE2:
+ i++;
+ if(i < cheatsNumber) {
+ if(extended & 4) {
+ CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
+ }
+ }
+ break;
+ case GSA_32_BIT_GS_WRITE2:
+ i++;
+ if(i < cheatsNumber) {
+ if(extended & 4) {
+ CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
+ }
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH:
+ if((cheatsList[i].status & 1) == 0) {
+ if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
+ cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
+ cheatsList[i].status |= 1;
+ CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
+ }
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH2C:
+ i++;
+ if(i < cheatsNumber) {
+ rompatch2addr [0] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
+ rompatch2oldval [0] = CPUReadHalfWord(rompatch2addr [0]);
+ rompatch2val [0] = cheatsList[i].rawaddress & 0xFFFF;
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH2D:
+ i++;
+ if(i < cheatsNumber) {
+ rompatch2addr [1] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
+ rompatch2oldval [1] = CPUReadHalfWord(rompatch2addr [1]);
+ rompatch2val [1] = cheatsList[i].rawaddress & 0xFFFF;
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH2E:
+ i++;
+ if(i < cheatsNumber) {
+ rompatch2addr [2] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
+ rompatch2oldval [2] = CPUReadHalfWord(rompatch2addr [2]);
+ rompatch2val [2] = cheatsList[i].rawaddress & 0xFFFF;
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH2F:
+ i++;
+ if(i < cheatsNumber) {
+ rompatch2addr [3] = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
+ rompatch2oldval [3] = CPUReadHalfWord(rompatch2addr [3]);
+ rompatch2val [3] = cheatsList[i].rawaddress & 0xFFFF;
+ }
+ break;
+ case MASTER_CODE:
+ mastercode = cheatsList[i].address;
+ break;
+ }
+ if (onoff) {
+ switch(cheatsList[i].size) {
+ case INT_8_BIT_WRITE:
+ CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
+ break;
+ case INT_16_BIT_WRITE:
+ CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
+ break;
+ case INT_32_BIT_WRITE:
+ CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
+ break;
+ case GSA_8_BIT_GS_WRITE:
+ if(extended & 4) {
+ CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
+ }
+ break;
+ case GSA_16_BIT_GS_WRITE:
+ if(extended & 4) {
+ CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
+ }
+ break;
+ case GSA_32_BIT_GS_WRITE:
+ if(extended & 4) {
+ CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
+ }
+ break;
+ case CBA_IF_KEYS_PRESSED:
+ {
+ u16 value = cheatsList[i].value;
+ u32 addr = cheatsList[i].address;
+ if((addr & 0xF0) == 0x20) {
+ if((keys & value) == 0) {
+ i++;
+ }
+ } else if((addr & 0xF0) == 0x10) {
+ if((keys & value) == value) {
+ i++;
+ }
+ } else if((addr & 0xF0) == 0x00) {
+ if(((~keys) & 0x3FF) == value) {
+ i++;
+ }
+ }
+ }
+ break;
+ case CBA_IF_TRUE:
+ if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case CBA_SLIDE_CODE:
+ {
+ u32 address = cheatsList[i].address;
+ u16 value = cheatsList[i].value;
+ i++;
+ if(i < cheatsNumber) {
+ int count = ((cheatsList[i].address - 1) & 0xFFFF);
+ u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
+ int inc = cheatsList[i].value;
+ for(int x = 0; x <= count ; x++) {
+ CPUWriteHalfWord(address, value);
+ address += inc;
+ value += vinc;
+ }
+ }
+ }
+ break;
+ case CBA_IF_FALSE:
+ if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value){
+ i++;
+ }
+ break;
+ case CBA_AND:
+ CPUWriteHalfWord(cheatsList[i].address,
+ CPUReadHalfWord(cheatsList[i].address) &
+ cheatsList[i].value);
+ break;
+ case GSA_8_BIT_IF_TRUE:
+ if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_TRUE:
+ if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_IF_FALSE:
+ if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_FALSE:
+ if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_FILL:
+ {
+ u32 addr = cheatsList[i].address;
+ u8 v = cheatsList[i].value & 0xff;
+ u32 end = addr + (cheatsList[i].value >> 8);
+ do {
+ CPUWriteByte(addr, v);
+ addr++;
+ } while (addr <= end);
+ }
+ break;
+ case GSA_16_BIT_FILL:
+ {
+ u32 addr = cheatsList[i].address;
+ u16 v = cheatsList[i].value & 0xffff;
+ u32 end = addr + ((cheatsList[i].value >> 16) << 1);
+ do {
+ CPUWriteHalfWord(addr, v);
+ addr+=2;
+ } while (addr <= end);
+ }
+ break;
+ case GSA_8_BIT_IF_TRUE2:
+ if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_TRUE2:
+ if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_TRUE2:
+ if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
+ i+=2;
+ }
+ break;
+ case GSA_8_BIT_IF_FALSE2:
+ if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_FALSE2:
+ if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_FALSE2:
+ if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
+ i+=2;
+ }
+ break;
+ case CBA_ADD:
+ if ((cheatsList[i].address & 1) == 0) {
+ CPUWriteHalfWord(cheatsList[i].address,
+ CPUReadHalfWord(cheatsList[i].address) +
+ cheatsList[i].value);
+ } else {
+ CPUWriteMemory(cheatsList[i].address & 0x0FFFFFFE,
+ CPUReadMemory(cheatsList[i].address & 0x0FFFFFFE) +
+ cheatsList[i].value);
+ }
+ break;
+ case CBA_OR:
+ CPUWriteHalfWord(cheatsList[i].address,
+ CPUReadHalfWord(cheatsList[i].address) |
+ cheatsList[i].value);
+ break;
+ case CBA_GT:
+ if (!(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value)){
+ i++;
+ }
+ break;
+ case CBA_LT:
+ if (!(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value)){
+ i++;
+ }
+ break;
+ case CBA_SUPER:
+ {
+ int count = 2*((cheatsList[i].value -1) & 0xFFFF)+1;
+ u32 address = cheatsList[i].address;
+ for(int x = 0; x <= count; x++) {
+ u8 b;
+ int res = x % 6;
+ if (res==0)
+ i++;
+ if(res < 4)
+ b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
+ else
+ b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0xFF;
+ CPUWriteByte(address, b);
+ address++;
+ }
+ }
+ break;
+ case GSA_8_BIT_POINTER :
+ if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
+ (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
+ {
+ CPUWriteByte(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFFFF00) >> 8),
+ cheatsList[i].value & 0xFF);
+ }
+ break;
+ case GSA_16_BIT_POINTER :
+ if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
+ (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
+ {
+ CPUWriteHalfWord(CPUReadMemory(cheatsList[i].address)+((cheatsList[i].value & 0xFFFF0000) >> 15),
+ cheatsList[i].value & 0xFFFF);
+ }
+ break;
+ case GSA_32_BIT_POINTER :
+ if ((CPUReadMemory(cheatsList[i].address)>=0x02000000) && (CPUReadMemory(cheatsList[i].address)<0x02040000) ||
+ (CPUReadMemory(cheatsList[i].address)>=0x03000000) && (CPUReadMemory(cheatsList[i].address)<0x03008000))
+ {
+ CPUWriteMemory(CPUReadMemory(cheatsList[i].address),
+ cheatsList[i].value);
+ }
+ break;
+ case GSA_8_BIT_ADD :
+ CPUWriteByte(cheatsList[i].address,
+ (cheatsList[i].value & 0xFF) + CPUReadMemory(cheatsList[i].address) & 0xFF);
+ break;
+ case GSA_16_BIT_ADD :
+ CPUWriteHalfWord(cheatsList[i].address,
+ (cheatsList[i].value & 0xFFFF) + CPUReadMemory(cheatsList[i].address) & 0xFFFF);
+ break;
+ case GSA_32_BIT_ADD :
+ CPUWriteMemory(cheatsList[i].address ,
+ cheatsList[i].value + CPUReadMemory(cheatsList[i].address) & 0xFFFFFFFF);
+ break;
+ case GSA_8_BIT_IF_LOWER_U:
+ if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_IF_LOWER_U:
+ if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_LOWER_U:
+ if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_IF_HIGHER_U:
+ if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_U:
+ if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_HIGHER_U:
+ if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_IF_AND:
+ if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_IF_AND:
+ if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_AND:
+ if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_IF_LOWER_U2:
+ if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_LOWER_U2:
+ if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_LOWER_U2:
+ if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
+ i+=2;
+ }
+ break;
+ case GSA_8_BIT_IF_HIGHER_U2:
+ if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_U2:
+ if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_HIGHER_U2:
+ if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
+ i+=2;
+ }
+ break;
+ case GSA_8_BIT_IF_AND2:
+ if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_AND2:
+ if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_AND2:
+ if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
+ i+=2;
+ }
+ break;
+ case GSA_ALWAYS:
+ i++;
+ break;
+ case GSA_ALWAYS2:
+ i+=2;
+ break;
+ case GSA_8_BIT_IF_LOWER_S:
+ if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_IF_LOWER_S:
+ if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_LOWER_S:
+ if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_IF_HIGHER_S:
+ if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_S:
+ if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
+ i++;
+ }
+ break;
+ case GSA_32_BIT_IF_HIGHER_S:
+ if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
+ i++;
+ }
+ break;
+ case GSA_8_BIT_IF_LOWER_S2:
+ if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_LOWER_S2:
+ if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_LOWER_S2:
+ if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
+ i+=2;
+ }
+ break;
+ case GSA_8_BIT_IF_HIGHER_S2:
+ if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_S2:
+ if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
+ i+=2;
+ }
+ break;
+ case GSA_32_BIT_IF_HIGHER_S2:
+ if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
+ i+=2;
+ }
+ break;
+ case GSA_16_BIT_WRITE_IOREGS:
+ if ((cheatsList[i].address <= 0x3FF) && (cheatsList[i].address != 0x6) &&
+ (cheatsList[i].address != 0x130))
+ ioMem[cheatsList[i].address & 0x3FE]=cheatsList[i].value & 0xFFFF;
+ break;
+ case GSA_32_BIT_WRITE_IOREGS:
+ if (cheatsList[i].address<=0x3FF)
+ {
+ if (((cheatsList[i].address & 0x3FC) != 0x6) && ((cheatsList[i].address & 0x3FC) != 0x130))
+ ioMem[cheatsList[i].address & 0x3FC]= (cheatsList[i].value & 0xFFFF);
+ if ((((cheatsList[i].address & 0x3FC)+2) != 0x6) && ((cheatsList[i].address & 0x3FC) +2) != 0x130)
+ ioMem[(cheatsList[i].address & 0x3FC) + 2 ]= ((cheatsList[i].value>>16 ) & 0xFFFF);
+ }
+ break;
+ case GSA_8_BIT_IF_TRUE3:
+ if(CPUReadByte(cheatsList[i].address) != cheatsList[i].value) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_TRUE3:
+ if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_TRUE3:
+ if(CPUReadMemory(cheatsList[i].address) != cheatsList[i].value) {
+ onoff=false;
+ }
+ break;
+ case GSA_8_BIT_IF_FALSE3:
+ if(CPUReadByte(cheatsList[i].address) == cheatsList[i].value) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_FALSE3:
+ if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_FALSE3:
+ if(CPUReadMemory(cheatsList[i].address) == cheatsList[i].value) {
+ onoff=false;
+ }
+ break;
+ case GSA_8_BIT_IF_LOWER_S3:
+ if (!((s8)CPUReadByte(cheatsList[i].address) < ((s8)cheatsList[i].value & 0xFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_LOWER_S3:
+ if (!((s16)CPUReadHalfWord(cheatsList[i].address) < ((s16)cheatsList[i].value & 0xFFFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_LOWER_S3:
+ if (!((s32)CPUReadMemory(cheatsList[i].address) < (s32)cheatsList[i].value)) {
+ onoff=false;
+ }
+ break;
+ case GSA_8_BIT_IF_HIGHER_S3:
+ if (!((s8)CPUReadByte(cheatsList[i].address) > ((s8)cheatsList[i].value & 0xFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_S3:
+ if (!((s16)CPUReadHalfWord(cheatsList[i].address) > ((s16)cheatsList[i].value & 0xFFFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_HIGHER_S3:
+ if (!((s32)CPUReadMemory(cheatsList[i].address) > (s32)cheatsList[i].value)) {
+ onoff=false;
+ }
+ break;
+ case GSA_8_BIT_IF_LOWER_U3:
+ if (!(CPUReadByte(cheatsList[i].address) < (cheatsList[i].value & 0xFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_LOWER_U3:
+ if (!(CPUReadHalfWord(cheatsList[i].address) < (cheatsList[i].value & 0xFFFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_LOWER_U3:
+ if (!(CPUReadMemory(cheatsList[i].address) < cheatsList[i].value)) {
+ onoff=false;
+ }
+ break;
+ case GSA_8_BIT_IF_HIGHER_U3:
+ if (!(CPUReadByte(cheatsList[i].address) > (cheatsList[i].value & 0xFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_U3:
+ if (!(CPUReadHalfWord(cheatsList[i].address) > (cheatsList[i].value & 0xFFFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_HIGHER_U3:
+ if (!(CPUReadMemory(cheatsList[i].address) > cheatsList[i].value)) {
+ onoff=false;
+ }
+ break;
+ case GSA_8_BIT_IF_AND3:
+ if (!(CPUReadByte(cheatsList[i].address) & (cheatsList[i].value & 0xFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_16_BIT_IF_AND3:
+ if (!(CPUReadHalfWord(cheatsList[i].address) & (cheatsList[i].value & 0xFFFF))) {
+ onoff=false;
+ }
+ break;
+ case GSA_32_BIT_IF_AND3:
+ if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
+ onoff=false;
+ }
+ break;
+ case GSA_ALWAYS3:
+ if (!(CPUReadMemory(cheatsList[i].address) & cheatsList[i].value)) {
+ onoff=false;
+ }
+ break;
+ case GSA_GROUP_WRITE:
+ {
+ int count = ((cheatsList[i].address) & 0xFFFE) +1;
+ u32 value = cheatsList[i].value;
+ if (count==0)
+ i++;
+ else
+ for (int x = 1; x <= count; x++) {
+ if ((x % 2) ==0){
+ if (x cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_IF_HIGHER_OR_EQ_U:
+ if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
+ i++;
+ }
+ break;
+ case GSA_16_BIT_MIF_TRUE:
+ if(CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value) {
+ i+=((cheatsList[i].rawaddress >> 0x10) & 0xFF);
+ }
+ break;
+ case GSA_16_BIT_MIF_FALSE:
+ if(CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value) {
+ i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
+ }
+ break;
+ case GSA_16_BIT_MIF_LOWER_OR_EQ_U:
+ if(CPUReadHalfWord(cheatsList[i].address) > cheatsList[i].value) {
+ i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
+ }
+ break;
+ case GSA_16_BIT_MIF_HIGHER_OR_EQ_U:
+ if(CPUReadHalfWord(cheatsList[i].address) < cheatsList[i].value) {
+ i+=(cheatsList[i].rawaddress >> 0x10) & 0xFF;
+ }
+ break;
+ case CHEATS_16_BIT_WRITE:
+ if ((cheatsList[i].address>>24)>=0x08) {
+ CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
+ } else {
+ CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
+ }
+ break;
+ case CHEATS_32_BIT_WRITE:
+ if ((cheatsList[i].address>>24)>=0x08) {
+ CHEAT_PATCH_ROM_32BIT(cheatsList[i].address, cheatsList[i].value);
+ } else {
+ CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
+ }
+ break;
+ }
+ }
+ }
+ for (i = 0; i<4; i++)
+ if (rompatch2addr [i] != 0)
+ CHEAT_PATCH_ROM_16BIT(rompatch2addr [i],rompatch2val [i]);
+ return ticks;
+}
+
+void cheatsAdd(const char *codeStr,
+ const char *desc,
+ u32 rawaddress,
+ u32 address,
+ u32 value,
+ int code,
+ int size)
+{
+ if(cheatsNumber < 100) {
+ int x = cheatsNumber;
+ cheatsList[x].code = code;
+ cheatsList[x].size = size;
+ cheatsList[x].rawaddress = rawaddress;
+ cheatsList[x].address = address;
+ cheatsList[x].value = value;
+ strcpy(cheatsList[x].codestring, codeStr);
+ strcpy(cheatsList[x].desc, desc);
+ cheatsList[x].enabled = true;
+ cheatsList[x].status = 0;
+
+ // we only store the old value for this simple codes. ROM patching
+ // is taken care when it actually patches the ROM
+ switch(cheatsList[x].size) {
+ case INT_8_BIT_WRITE:
+ cheatsList[x].oldValue = CPUReadByte(address);
+ break;
+ case INT_16_BIT_WRITE:
+ cheatsList[x].oldValue = CPUReadHalfWord(address);
+ break;
+ case INT_32_BIT_WRITE:
+ cheatsList[x].oldValue = CPUReadMemory(address);
+ break;
+ case CHEATS_16_BIT_WRITE:
+ cheatsList[x].oldValue = CPUReadHalfWord(address);
+ break;
+ case CHEATS_32_BIT_WRITE:
+ cheatsList[x].oldValue = CPUReadMemory(address);
+ break;
+ }
+ cheatsNumber++;
+ }
+}
+
+void cheatsDelete(int number, bool restore)
+{
+ if(number < cheatsNumber && number >= 0) {
+ int x = number;
+
+ if(restore) {
+ switch(cheatsList[x].size) {
+ case INT_8_BIT_WRITE:
+ CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
+ break;
+ case INT_16_BIT_WRITE:
+ CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
+ break;
+ case INT_32_BIT_WRITE:
+ CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
+ break;
+ case CHEATS_16_BIT_WRITE:
+ if ((cheatsList[x].address>>24)>=0x08) {
+ CHEAT_PATCH_ROM_16BIT(cheatsList[x].address, cheatsList[x].oldValue);
+ } else {
+ CPUWriteHalfWord(cheatsList[x].address, cheatsList[x].oldValue);
+ }
+ break;
+ case CHEATS_32_BIT_WRITE:
+ if ((cheatsList[x].address>>24)>=0x08) {
+ CHEAT_PATCH_ROM_32BIT(cheatsList[x].address, cheatsList[x].oldValue);
+ } else {
+ CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
+ }
+ case GSA_16_BIT_ROM_PATCH:
+ if(cheatsList[x].status & 1) {
+ cheatsList[x].status &= ~1;
+ CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
+ cheatsList[x].oldValue);
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH2C:
+ case GSA_16_BIT_ROM_PATCH2D:
+ case GSA_16_BIT_ROM_PATCH2E:
+ case GSA_16_BIT_ROM_PATCH2F:
+ if(cheatsList[x].status & 1) {
+ cheatsList[x].status &= ~1;
+ }
+ break;
+ case MASTER_CODE:
+ mastercode=0;
+ break;
+ }
+ }
+ if((x+1) < cheatsNumber) {
+ memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
+ (cheatsNumber-x-1));
+ }
+ cheatsNumber--;
+ }
+}
+
+void cheatsDeleteAll(bool restore)
+{
+ for(int i = cheatsNumber-1; i >= 0; i--) {
+ cheatsDelete(i, restore);
+ }
+}
+
+void cheatsEnable(int i)
+{
+ if(i >= 0 && i < cheatsNumber) {
+ cheatsList[i].enabled = true;
+ mastercode = 0;
+ }
+}
+
+void cheatsDisable(int i)
+{
+ if(i >= 0 && i < cheatsNumber) {
+ switch(cheatsList[i].size) {
+ case GSA_16_BIT_ROM_PATCH:
+ if(cheatsList[i].status & 1) {
+ cheatsList[i].status &= ~1;
+ CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
+ cheatsList[i].oldValue);
+ }
+ break;
+ case GSA_16_BIT_ROM_PATCH2C:
+ case GSA_16_BIT_ROM_PATCH2D:
+ case GSA_16_BIT_ROM_PATCH2E:
+ case GSA_16_BIT_ROM_PATCH2F:
+ if(cheatsList[i].status & 1) {
+ cheatsList[i].status &= ~1;
+ }
+ break;
+ case MASTER_CODE:
+ mastercode=0;
+ break;
+ }
+ cheatsList[i].enabled = false;
+ }
+}
+
+bool cheatsVerifyCheatCode(const char *code, const char *desc)
+{
+ size_t len = strlen(code);
+ if(len != 11 && len != 13 && len != 17) {
+ systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
+ return false;
+ }
+
+ if(code[8] != ':') {
+ systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
+ return false;
+ }
+
+ size_t i;
+ for(i = 0; i < 8; i++) {
+ if(!CHEAT_IS_HEX(code[i])) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_CHEAT_CODE,
+ N_("Invalid cheat code '%s'"), code);
+ return false;
+ }
+ }
+ for(i = 9; i < len; i++) {
+ if(!CHEAT_IS_HEX(code[i])) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_CHEAT_CODE,
+ N_("Invalid cheat code '%s'"), code);
+ return false;
+ }
+ }
+
+ u32 address = 0;
+ u32 value = 0;
+
+ char buffer[10];
+ strncpy(buffer, code, 8);
+ buffer[8] = 0;
+ sscanf(buffer, "%x", &address);
+
+ switch(address >> 24) {
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ break;
+ default:
+ systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS,
+ N_("Invalid cheat code address: %08x"),
+ address);
+ return false;
+ }
+
+ strncpy(buffer, &code[9], 8);
+ sscanf(buffer, "%x", &value);
+ int type = 0;
+ if(len == 13)
+ type = 114;
+ if(len == 17)
+ type = 115;
+ cheatsAdd(code, desc, address, address, value, type, type);
+ return true;
+}
+
+void cheatsAddCheatCode(const char *code, const char *desc)
+{
+ cheatsVerifyCheatCode(code, desc);
+}
+
+u16 cheatsGSAGetDeadface(bool v3)
+{
+ for(int i = cheatsNumber-1; i >= 0; i--)
+ if ((cheatsList[i].address == 0xDEADFACE) && (cheatsList[i].code == (v3 ? 257 : 256)))
+ return cheatsList[i].value & 0xFFFF;
+ return 0;
+}
+
+void cheatsGSAChangeEncryption(u16 value, bool v3) {
+ int i;
+ u8 *deadtable1, *deadtable2;
+
+ if (v3) {
+ deadtable1 = (u8*)(&v3_deadtable1);
+ deadtable2 = (u8*)(&v3_deadtable2);
+ for (i = 0; i < 4; i++)
+ seeds_v3[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
+ }
+ else {
+ deadtable1 = (u8*)(&v1_deadtable1);
+ deadtable2 = (u8*)(&v1_deadtable2);
+ for (i = 0; i < 4; i++){
+ seeds_v1[i] = seed_gen(((value & 0xFF00) >> 8), (value & 0xFF) + i, deadtable1, deadtable2);
+ }
+ }
+}
+
+u32 seed_gen(u8 upper, u8 seed, u8 *deadtable1, u8 *deadtable2) {
+ int i;
+ u32 newseed = 0;
+
+ for (i = 0; i < 4; i++)
+ newseed = ((newseed << 8) | ((deadtable1[(i + upper) & 0xFF] + deadtable2[seed]) & 0xFF));
+
+ return newseed;
+}
+
+void cheatsDecryptGSACode(u32& address, u32& value, bool v3)
+{
+ u32 rollingseed = 0xC6EF3720;
+ u32 *seeds = v3 ? seeds_v3 : seeds_v1;
+
+ int bitsleft = 32;
+ while (bitsleft > 0) {
+ value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
+ ((address >> 5) + seeds[3]));
+ address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
+ ((value >> 5) + seeds[1]));
+ rollingseed -= 0x9E3779B9;
+ bitsleft--;
+ }
+}
+
+void cheatsAddGSACode(const char *code, const char *desc, bool v3)
+{
+ if(strlen(code) != 16) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_GSA_CODE,
+ N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
+ return;
+ }
+
+ int i;
+ for(i = 0; i < 16; i++) {
+ if(!CHEAT_IS_HEX(code[i])) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_GSA_CODE,
+ N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
+ return;
+ }
+ }
+
+ char buffer[10];
+ strncpy(buffer, code, 8);
+ buffer[8] = 0;
+ u32 address;
+ sscanf(buffer, "%x", &address);
+ strncpy(buffer, &code[8], 8);
+ buffer[8] = 0;
+ u32 value;
+ sscanf(buffer, "%x", &value);
+ cheatsGSAChangeEncryption(cheatsGSAGetDeadface (v3), v3);
+ cheatsDecryptGSACode(address, value, v3);
+
+ if(value == 0x1DC0DE) {
+ u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
+ if(gamecode != address) {
+ char buffer[5];
+ *((u32 *)buffer) = address;
+ buffer[4] = 0;
+ char buffer2[5];
+ *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
+ buffer2[4] = 0;
+ systemMessage(MSG_GBA_CODE_WARNING, N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."),
+ buffer, buffer2);
+ }
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, v3 ? 257 : 256,
+ UNKNOWN_CODE);
+ return;
+ }
+ if(isMultilineWithData(cheatsNumber-1)) {
+ cheatsAdd(code, desc, address, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
+ return;
+ }
+ if(v3) {
+ int type = ((address >> 25) & 127) | ((address >> 17) & 0x80);
+ u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
+ u16 mcode = (address>>24 & 0xFF);
+
+ if ((mcode & 0xFE) == 0xC4)
+ {
+ cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | (0x08000000),
+ value, 257, MASTER_CODE);
+ mastercode = (address & 0x1FFFFFF) | (0x08000000);
+ }
+ else
+ switch(type) {
+ case 0x00:
+ if(address == 0) {
+ type = (value >> 25) & 127;
+ addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
+ switch(type) {
+ case 0x04:
+ cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
+ break;
+ case 0x08:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
+ break;
+ case 0x09:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
+ break;
+ case 0x0a:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
+ break;
+ case 0x0c:
+ cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2C);
+ break;
+ case 0x0d:
+ cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2D);
+ break;
+ case 0x0e:
+ cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2E);
+ break;
+ case 0x0f:
+ cheatsAdd(code, desc, address, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2F);
+ break;
+ case 0x20:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_CODES_ON);
+ break;
+ case 0x40:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_8_BIT_SLIDE);
+ break;
+ case 0x41:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_16_BIT_SLIDE);
+ break;
+ case 0x42:
+ cheatsAdd(code, desc, address, 0, addr, 257, GSA_32_BIT_SLIDE);
+ break;
+ default:
+ cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
+ break;
+ }
+ } else
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_FILL);
+ break;
+ case 0x01:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_FILL);
+ break;
+ case 0x02:
+ cheatsAdd(code, desc, address, addr, value, 257, INT_32_BIT_WRITE);
+ break;
+ case 0x04:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE);
+ break;
+ case 0x05:
+ cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_TRUE);
+ break;
+ case 0x06:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE);
+ break;
+ case 0x07:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS);
+ break;
+ case 0x08:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE);
+ break;
+ case 0x09:
+ cheatsAdd(code, desc, address, addr, value, 257, CBA_IF_FALSE);
+ break;
+ case 0x0a:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE);
+ break;
+ case 0xc:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S);
+ break;
+ case 0xd:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S);
+ break;
+ case 0xe:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S);
+ break;
+ case 0x10:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S);
+ break;
+ case 0x11:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S);
+ break;
+ case 0x12:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S);
+ break;
+ case 0x14:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U);
+ break;
+ case 0x15:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U);
+ break;
+ case 0x16:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U);
+ break;
+ case 0x18:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U);
+ break;
+ case 0x19:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U);
+ break;
+ case 0x1A:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U);
+ break;
+ case 0x1C:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND);
+ break;
+ case 0x1D:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND);
+ break;
+ case 0x1E:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND);
+ break;
+ case 0x20:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_POINTER);
+ break;
+ case 0x21:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_POINTER);
+ break;
+ case 0x22:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_POINTER);
+ break;
+ case 0x24:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE2);
+ break;
+ case 0x25:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE2);
+ break;
+ case 0x26:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE2);
+ break;
+ case 0x27:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS2);
+ break;
+ case 0x28:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE2);
+ break;
+ case 0x29:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE2);
+ break;
+ case 0x2a:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE2);
+ break;
+ case 0x2c:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S2);
+ break;
+ case 0x2d:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S2);
+ break;
+ case 0x2e:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S2);
+ break;
+ case 0x30:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S2);
+ break;
+ case 0x31:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S2);
+ break;
+ case 0x32:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S2);
+ break;
+ case 0x34:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U2);
+ break;
+ case 0x35:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U2);
+ break;
+ case 0x36:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U2);
+ break;
+ case 0x38:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U2);
+ break;
+ case 0x39:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U2);
+ break;
+ case 0x3A:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U2);
+ break;
+ case 0x3C:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND2);
+ break;
+ case 0x3D:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND2);
+ break;
+ case 0x3E:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND2);
+ break;
+ case 0x40:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_ADD);
+ break;
+ case 0x41:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_ADD);
+ break;
+ case 0x42:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_ADD);
+ break;
+ case 0x44:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_TRUE3);
+ break;
+ case 0x45:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_TRUE3);
+ break;
+ case 0x46:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_TRUE3);
+ break;
+ case 0x47:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_ALWAYS3);
+ break;
+ case 0x48:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_FALSE3);
+ break;
+ case 0x49:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_FALSE3);
+ break;
+ case 0x4a:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_FALSE3);
+ break;
+ case 0x4c:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_S3);
+ break;
+ case 0x4d:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_S3);
+ break;
+ case 0x4e:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_S3);
+ break;
+ case 0x50:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_S3);
+ break;
+ case 0x51:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_S3);
+ break;
+ case 0x52:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_S3);
+ break;
+ case 0x54:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_LOWER_U3);
+ break;
+ case 0x55:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_LOWER_U3);
+ break;
+ case 0x56:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_LOWER_U3);
+ break;
+ case 0x58:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_HIGHER_U3);
+ break;
+ case 0x59:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_HIGHER_U3);
+ break;
+ case 0x5a:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_HIGHER_U3);
+ break;
+ case 0x5c:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_8_BIT_IF_AND3);
+ break;
+ case 0x5d:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_IF_AND3);
+ break;
+ case 0x5e:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_IF_AND3);
+ break;
+ case 0x63:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_16_BIT_WRITE_IOREGS);
+ break;
+ case 0xE3:
+ cheatsAdd(code, desc, address, addr, value, 257, GSA_32_BIT_WRITE_IOREGS);
+ break;
+ default:
+ cheatsAdd(code, desc, address, address, value, 257, UNKNOWN_CODE);
+ break;
+ }
+ } else {
+ int type = (address >> 28) & 15;
+ switch(type) {
+ case 0:
+ case 1:
+ case 2:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, type);
+ break;
+ case 3:
+ switch ((address >> 0x10) & 0xFF){
+ case 0x00:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_GROUP_WRITE);
+ break;
+ case 0x10:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFF, 256, GSA_32_BIT_ADD );
+ break;
+ case 0x20:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFF)+1), 256, GSA_32_BIT_ADD );
+ break;
+ case 0x30:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256, GSA_32_BIT_ADD );
+ break;
+ case 0x40:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, (~(address & 0xFFFF)+1), 256, GSA_32_BIT_ADD );
+ break;
+ case 0x50:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_ADD2);
+ break;
+ case 0x60:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 256, GSA_32_BIT_SUB2);
+ break;
+ default:
+ // unsupported code
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ }
+ break;
+ case 6:
+ address <<= 1;
+ type = (value >> 24) & 0xFF;
+ if(type == 0x00) {
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
+ GSA_16_BIT_ROM_PATCH);
+ break;
+ }
+ // unsupported code
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ case 8:
+ switch((address >> 20) & 15) {
+ case 1:
+ cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
+ GSA_8_BIT_GS_WRITE);
+ break;
+ case 2:
+ cheatsAdd(code, desc, address, address & 0x0F0FFFFF, value, 256,
+ GSA_16_BIT_GS_WRITE);
+ break;
+ case 4:
+ // This code is buggy : the value is always set to 0 !
+ cheatsAdd(code, desc, address, address & 0x0F0FFFFF, 0, 256,
+ GSA_32_BIT_GS_WRITE);
+ break;
+ case 15:
+ cheatsAdd(code, desc, address, 0, value & 0xFFFF, 256, GSA_SLOWDOWN);
+ break;
+ default:
+ // unsupported code
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ }
+ break;
+ case 0x0d:
+ if(address != 0xDEADFACE) {
+ switch((value >> 20) & 0xF) {
+ case 0:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
+ CBA_IF_TRUE);
+ break;
+ case 1:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
+ CBA_IF_FALSE);
+ break;
+ case 2:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
+ GSA_16_BIT_IF_LOWER_OR_EQ_U);
+ break;
+ case 3:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0xFFFF, 256,
+ GSA_16_BIT_IF_HIGHER_OR_EQ_U);
+ break;
+ default:
+ // unsupported code
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ }
+ } else
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ case 0x0e:
+ switch((value >> 28) & 0xF) {
+ case 0:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
+ GSA_16_BIT_MIF_TRUE);
+ break;
+ case 1:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
+ GSA_16_BIT_MIF_FALSE);
+ break;
+ case 2:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
+ GSA_16_BIT_MIF_LOWER_OR_EQ_U);
+ break;
+ case 3:
+ cheatsAdd(code, desc, address, value & 0x0FFFFFFF, address & 0xFFFF, 256,
+ GSA_16_BIT_MIF_HIGHER_OR_EQ_U);
+ break;
+ default:
+ // unsupported code
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ }
+ break;
+ case 0x0f:
+ cheatsAdd(code, desc, address, (address & 0xFFFFFFF), value, 256, MASTER_CODE);
+ mastercode = (address & 0xFFFFFFF);
+ break;
+ default:
+ // unsupported code
+ cheatsAdd(code, desc, address, address, value, 256,
+ UNKNOWN_CODE);
+ break;
+ }
+ }
+}
+
+bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
+{
+ FILE *f = fopen(name, "rb");
+ if(!f)
+ return false;
+
+ int games = 0;
+ int len = 0;
+ fseek(f, 0x1e, SEEK_CUR);
+ fread(&games, 1, 4, f);
+ bool found = false;
+ int g = 0;
+ while(games > 0) {
+ if(g == game) {
+ found = true;
+ break;
+ }
+ fread(&len, 1, 4, f);
+ fseek(f,len,SEEK_CUR);
+ int codes = 0;
+ fread(&codes, 1, 4, f);
+ while(codes > 0) {
+ fread(&len, 1, 4, f);
+ fseek(f, len, SEEK_CUR);
+ fseek(f, 8, SEEK_CUR);
+ fread(&len, 1, 4, f);
+ fseek(f, len*12, SEEK_CUR);
+ codes--;
+ }
+ games--;
+ g++;
+ }
+ if(found) {
+ char desc[256];
+ char code[17];
+ fread(&len, 1, 4, f);
+ fseek(f, len, SEEK_CUR);
+ int codes = 0;
+ fread(&codes, 1, 4, f);
+ while(codes > 0) {
+ fread(&len, 1, 4, f);
+ fread(desc, 1, len, f);
+ desc[len] =0;
+ desc[31] = 0;
+ fread(&len, 1, 4, f);
+ fseek(f, len, SEEK_CUR);
+ fseek(f, 4, SEEK_CUR);
+ fread(&len, 1, 4, f);
+ while(len) {
+ fseek(f, 4, SEEK_CUR);
+ fread(code, 1, 8, f);
+ fseek(f, 4, SEEK_CUR);
+ fread(&code[8], 1, 8, f);
+ code[16] = 0;
+ cheatsAddGSACode(code, desc, v3);
+ len -= 2;
+ }
+ codes--;
+ }
+ }
+ fclose(f);
+ return false;
+}
+
+void cheatsCBAReverseArray(u8 *array, u8 *dest)
+{
+ dest[0] = array[3];
+ dest[1] = array[2];
+ dest[2] = array[1];
+ dest[3] = array[0];
+ dest[4] = array[5];
+ dest[5] = array[4];
+}
+
+void chatsCBAScramble(u8 *array, int count, u8 b)
+{
+ u8 *x = array + (count >> 3);
+ u8 *y = array + (b >> 3);
+ u32 z = *x & (1 << (count & 7));
+ u32 x0 = (*x & (~(1 << (count & 7))));
+ if (z != 0)
+ z = 1;
+ if ((*y & (1 << (b & 7))) != 0)
+ x0 |= (1 << (count & 7));
+ *x = x0;
+ u32 temp = *y & (~(1 << (b & 7)));
+ if (z != 0)
+ temp |= (1 << (b & 7));
+ *y = temp;
+}
+
+u32 cheatsCBAGetValue(u8 *array)
+{
+ return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
+}
+
+u16 cheatsCBAGetData(u8 *array)
+{
+ return array[4] | array[5]<<8;
+}
+
+void cheatsCBAArrayToValue(u8 *array, u8 *dest)
+{
+ dest[0] = array[3];
+ dest[1] = array[2];
+ dest[2] = array[1];
+ dest[3] = array[0];
+ dest[4] = array[5];
+ dest[5] = array[4];
+}
+
+void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
+{
+ array[0] = 1;
+ array[1] = value & 0xFF;
+ array[2] = (address >> 0x10) & 0xFF;
+ array[3] = (value >> 8) & 0xFF;
+ array[4] = (address >> 0x18) & 0x0F;
+ array[5] = address & 0xFFFF;
+ array[6] = address;
+ array[7] = value;
+}
+
+u32 cheatsCBAEncWorker()
+{
+ u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
+ u32 y = (x * 0x41c64e6d) + 0x3039;
+ u32 z = x >> 0x10;
+ x = ((y >> 0x10) & 0x7fff) << 0x0f;
+ z = (z << 0x1e) | x;
+ x = (y * 0x41c64e6d) + 0x3039;
+ cheatsCBATemporaryValue = x;
+ return z | ((x >> 0x10) & 0x7fff);
+}
+
+#define ROR(v, s) \
+ (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
+
+u32 cheatsCBACalcIndex(u32 x, u32 y)
+{
+ if(y != 0) {
+ if(y == 1)
+ x = 0;
+ else if(x == y)
+ x = 0;
+ if(y < 1)
+ return x;
+ else if(x < y)
+ return x;
+ u32 x0 = 1;
+
+ while(y < 0x10000000) {
+ if(y < x) {
+ y = y << 4;
+ x0 = x0 << 4;
+ } else break;
+ }
+
+ while(y < 0x80000000) {
+ if(y < x) {
+ y = y << 1;
+ x0 = x0 << 1;
+ } else break;
+ }
+
+ loop:
+ u32 z = 0;
+ if(x >= y)
+ x -= y;
+ if(x >= (y >> 1)) {
+ x -= (y >> 1);
+ z |= ROR(x0, 1);
+ }
+ if(x >= (y >> 2)) {
+ x -= (y >> 2);
+ z |= ROR(x0, 2);
+ }
+ if(x >= (y >> 3)) {
+ x -= (y >> 3);
+ z |= ROR(x0, 3);
+ }
+
+ u32 temp = x0;
+
+ if(x != 0) {
+ x0 = x0 >> 4;
+ if(x0 != 0) {
+ y = y >> 4;
+ goto loop;
+ }
+ }
+
+ z = z & 0xe0000000;
+
+ if(z != 0) {
+ if((temp & 7) == 0)
+ return x;
+ } else
+ return x;
+
+ if((z & ROR(temp, 3)) != 0)
+ x += y >> 3;
+ if((z & ROR(temp, 2)) != 0)
+ x += y >> 2;
+ if((z & ROR(temp, 1)) != 0)
+ x += y >> 1;
+ return x;
+ } else {
+ }
+ // should not happen in the current code
+ return 0;
+}
+
+void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
+{
+ int i;
+ for(i = 0; i < count; i++)
+ buffer[i] = i;
+ for(i = 0; (u32)i < a; i++) {
+ u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
+ u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
+ u32 t = buffer[a];
+ buffer[a] = buffer[b];
+ buffer[b] = t;
+ }
+}
+
+void cheatsCBAChangeEncryption(u32 *seed)
+{
+ int i;
+
+ cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
+ cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
+ cheatsCBATemporaryValue = 0x4efad1c3;
+
+ for(i = 0; (u32)i < seed[4]; i++) {
+ cheatsCBATemporaryValue = cheatsCBAEncWorker();
+ }
+ cheatsCBASeed[2] = cheatsCBAEncWorker();
+ cheatsCBASeed[3] = cheatsCBAEncWorker();
+
+ cheatsCBATemporaryValue = seed[3] ^ 0xf254;
+
+ for(i = 0; (u32)i < seed[3]; i++) {
+ cheatsCBATemporaryValue = cheatsCBAEncWorker();
+ }
+
+ cheatsCBASeed[0] = cheatsCBAEncWorker();
+ cheatsCBASeed[1] = cheatsCBAEncWorker();
+
+ *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
+ *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
+ *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
+}
+
+u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
+{
+ y <<= 0x10;
+ z <<= 0x10;
+ x <<= 0x18;
+ u32 x0 = (int)y >> 0x10;
+ z = (int)z >> 0x10;
+ x = (int)x >> 0x10;
+ for(int i = 0; i < 8; i++) {
+ u32 temp = z ^ x;
+ if ((int)temp >= 0) {
+ temp = z << 0x11;
+ }
+ else {
+ temp = z << 0x01;
+ temp ^= x0;
+ temp = temp << 0x10;
+ }
+ z = (int)temp >> 0x10;
+ temp = x << 0x11;
+ x = (int)temp >> 0x10;
+ }
+ return z & 0xffff;
+}
+
+void cheatsCBAGenTable() {
+ for (int i = 0; i < 0x100; i++) {
+ cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
+ }
+ cheatsCBATableGenerated = true;
+}
+
+u16 cheatsCBACalcCRC(u8 *rom, int count)
+{
+ u32 crc = 0xffffffff;
+
+ if (count & 3) {
+ // 0x08000EAE
+ } else {
+ count = (count >> 2) - 1;
+ if(count != -1) {
+ while(count != -1) {
+ crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
+ ^ *rom++]) << 0x10) >> 0x10;
+ crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
+ ^ *rom++]) << 0x10) >> 0x10;
+ crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
+ ^ *rom++]) << 0x10) >> 0x10;
+ crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
+ ^ *rom++]) << 0x10) >> 0x10;
+ count--;
+ }
+ }
+ }
+ return crc & 0xffff;
+}
+
+void cheatsCBADecrypt(u8 *decrypt)
+{
+ u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ u8 *array = &buffer[1];
+
+ cheatsCBAReverseArray(decrypt, array);
+
+ for(int count = 0x2f; count >= 0; count--) {
+ chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
+ }
+ cheatsCBAArrayToValue(array, decrypt);
+ *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
+ cheatsCBASeed[0];
+ *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
+ cheatsCBASeed[1]) & 0xffff;
+
+ cheatsCBAReverseArray(decrypt, array);
+
+ u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
+ for(int i = 0; i <= 4; i++) {
+ array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
+ }
+
+ array[5] = (cs >> 8) ^ array[5];
+
+ for(int j = 5; j >=0; j--) {
+ array[j] = (cs ^ array[j-1]) ^ array[j];
+ }
+
+ cheatsCBAArrayToValue(array, decrypt);
+
+ *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
+ ^ cheatsCBASeed[2];
+ *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
+ ^ cheatsCBASeed[3]) & 0xffff;
+}
+
+int cheatsCBAGetCount()
+{
+ int count = 0;
+ for(int i = 0; i < cheatsNumber; i++) {
+ if(cheatsList[i].code == 512)
+ count++;
+ }
+ return count;
+}
+
+bool cheatsCBAShouldDecrypt()
+{
+ for(int i = 0; i < cheatsNumber; i++) {
+ if(cheatsList[i].code == 512) {
+ return (cheatsList[i].codestring[0] == '9');
+ }
+ }
+ return false;
+}
+
+void cheatsAddCBACode(const char *code, const char *desc)
+{
+ if(strlen(code) != 13) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_CBA_CODE,
+ N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
+ return;
+ }
+
+ int i;
+ for(i = 0; i < 8; i++) {
+ if(!CHEAT_IS_HEX(code[i])) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_CBA_CODE,
+ N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
+ return;
+ }
+ }
+
+ if(code[8] != ' ') {
+ systemMessage(MSG_INVALID_CBA_CODE,
+ N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
+ return;
+ }
+
+ for(i = 9; i < 13; i++) {
+ if(!CHEAT_IS_HEX(code[i])) {
+ // wrong cheat
+ systemMessage(MSG_INVALID_CBA_CODE,
+ N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
+ return;
+ }
+ }
+
+ char buffer[10];
+ strncpy(buffer, code, 8);
+ buffer[8] = 0;
+ u32 address;
+ sscanf(buffer, "%x", &address);
+ strncpy(buffer, &code[9], 4);
+ buffer[4] = 0;
+ u32 value;
+ sscanf(buffer, "%x", &value);
+
+ u8 array[8] = {
+ address & 255,
+ (address >> 8) & 255,
+ (address >> 16) & 255,
+ (address >> 24) & 255,
+ (value & 255),
+ (value >> 8) & 255,
+ 0,
+ 0
+ };
+
+ if(cheatsCBAGetCount() == 0 &&
+ (address >> 28) == 9) {
+ u32 seed[8];
+ cheatsCBAParseSeedCode(address, value, seed);
+ cheatsCBAChangeEncryption(seed);
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
+ } else {
+ if(cheatsCBAShouldDecrypt())
+ cheatsCBADecrypt(array);
+
+ address = READ32LE(((u32 *)array));
+ value = READ16LE(((u16 *)&array[4]));
+
+ int type = (address >> 28) & 15;
+
+ if(isMultilineWithData(cheatsNumber-1) || (super>0)) {
+ cheatsAdd(code, desc, address, address, value, 512, UNKNOWN_CODE);
+ if (super>0)
+ super-= 1;
+ return;
+ }
+
+ switch(type) {
+ case 0x00:
+ {
+ if(!cheatsCBATableGenerated)
+ cheatsCBAGenTable();
+ u32 crc = cheatsCBACalcCRC(rom, 0x10000);
+ if(crc != address) {
+ systemMessage(MSG_CBA_CODE_WARNING,
+ N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly."));
+ }
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
+ UNKNOWN_CODE);
+ }
+ break;
+ case 0x01:
+ cheatsAdd(code, desc, address, (address & 0x1FFFFFF) | 0x08000000, value, 512, MASTER_CODE);
+ mastercode = (address & 0x1FFFFFF) | 0x08000000;
+ break;
+ case 0x02:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_OR);
+ break;
+ case 0x03:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value, 512,
+ INT_8_BIT_WRITE);
+ break;
+ case 0x04:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_SLIDE_CODE);
+ break;
+ case 0x05:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_SUPER);
+ super = getCodeLength(cheatsNumber-1);
+ break;
+ case 0x06:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_AND);
+ break;
+ case 0x07:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_IF_TRUE);
+ break;
+ case 0x08:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ INT_16_BIT_WRITE);
+ break;
+ case 0x0a:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_IF_FALSE);
+ break;
+ case 0x0b:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_GT);
+ break;
+ case 0x0c:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ CBA_LT);
+ break;
+ case 0x0d:
+ if ((address & 0xF0)<0x30)
+ cheatsAdd(code, desc, address, address & 0xF0, value, 512,
+ CBA_IF_KEYS_PRESSED);
+ break;
+ case 0x0e:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFF, value & 0x8000 ? value | 0xFFFF0000 : value, 512,
+ CBA_ADD);
+ break;
+ case 0x0f:
+ cheatsAdd(code, desc, address, address & 0x0FFFFFFE, value, 512,
+ GSA_16_BIT_IF_AND);
+ break;
+ default:
+ // unsupported code
+ cheatsAdd(code, desc, address, address & 0xFFFFFFFF, value, 512,
+ UNKNOWN_CODE);
+ break;
+ }
+ }
+}
+
+void cheatsSaveGame(gzFile file)
+{
+ utilWriteInt(file, cheatsNumber);
+
+ utilGzWrite(file, cheatsList, sizeof(cheatsList));
+}
+
+void cheatsReadGame(gzFile file, int version)
+{
+ cheatsNumber = 0;
+
+ cheatsNumber = utilReadInt(file);
+
+ if (version > 8)
+ utilGzRead(file, cheatsList, sizeof(cheatsList));
+
+
+ bool firstCodeBreaker = true;
+
+ for(int i = 0; i < cheatsNumber; i++) {
+ if (version <9)
+ {
+ cheatsList[i].code = utilReadInt(file);
+ cheatsList[i].size = utilReadInt(file);
+ cheatsList[i].status = utilReadInt(file);
+ cheatsList[i].enabled = utilReadInt(file) ? true : false;
+ utilGzRead(file, &cheatsList[i].address, sizeof(u32));
+ cheatsList[i].rawaddress = cheatsList[i].address;
+ utilGzRead(file, &cheatsList[i].value, sizeof(u32));
+ utilGzRead(file, &cheatsList[i].oldValue, sizeof(u32));
+ utilGzRead(file, &cheatsList[i].codestring, 20*sizeof(char));
+ utilGzRead(file, &cheatsList[i].desc, 32*sizeof(char));
+ }
+
+ cheatsList[i].status = 0;
+ if(!cheatsList[i].codestring[0]) {
+ switch(cheatsList[i].size) {
+ case 0:
+ sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
+ cheatsList[i].value);
+ break;
+ case 1:
+ sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
+ cheatsList[i].value);
+ break;
+ case 2:
+ sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
+ cheatsList[i].value);
+ break;
+ }
+ }
+
+ if(cheatsList[i].enabled) {
+ cheatsEnable(i);
+ }
+
+ if(cheatsList[i].code == 512 && firstCodeBreaker) {
+ firstCodeBreaker = false;
+ char buffer[10];
+ strncpy(buffer, cheatsList[i].codestring, 8);
+ buffer[8] = 0;
+ u32 address;
+ sscanf(buffer, "%x", &address);
+ if((address >> 28) == 9) {
+ strncpy(buffer, &cheatsList[i].codestring[9], 4);
+ buffer[4] = 0;
+ u32 value;
+ sscanf(buffer, "%x", &value);
+
+ u32 seed[8];
+ cheatsCBAParseSeedCode(address, value, seed);
+ cheatsCBAChangeEncryption(seed);
+ }
+ }
+ }
+}
+
+void cheatsSaveCheatList(const char *file)
+{
+ if(cheatsNumber == 0)
+ return;
+ FILE *f = fopen(file, "wb");
+ if(f == NULL)
+ return;
+ int version = 1;
+ fwrite(&version, 1, sizeof(version), f);
+ int type = 1;
+ fwrite(&type, 1, sizeof(type), f);
+ fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
+ fwrite(cheatsList, 1, sizeof(cheatsList), f);
+ fclose(f);
+}
+
+bool cheatsLoadCheatList(const char *file)
+{
+
+ int count = 0;
+
+ FILE *f = fopen(file, "rb");
+
+ if(f == NULL)
+ return false;
+
+ int version = 0;
+
+ if(fread(&version, 1, sizeof(version), f) != sizeof(version)) {
+ fclose(f);
+ return false;
+ }
+
+ if(version != 1) {
+ systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
+ N_("Unsupported cheat list version %d"), version);
+ fclose(f);
+ return false;
+ }
+
+ int type = 0;
+ if(fread(&type, 1, sizeof(type), f) != sizeof(type)) {
+ fclose(f);
+ return false;
+ }
+
+
+ if((type != 0) && (type != 1)) {
+ systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
+ N_("Unsupported cheat list type %d"), type);
+ fclose(f);
+ return false;
+ }
+
+ if(fread(&count, 1, sizeof(count), f) != sizeof(count)) {
+ fclose(f);
+ return false;
+ }
+ if (type == 1)
+ {
+ if(fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList)) {
+ fclose(f);
+ return false;
+ }
+ }
+ else if (type == 0)
+ {
+ for(int i = 0; i < count; i++) {
+ fread(&cheatsList[i].code, 1, sizeof(int),f);
+ fread(&cheatsList[i].size, 1, sizeof(int),f);
+ fread(&cheatsList[i].status, 1, sizeof(int),f);
+ fread(&cheatsList[i].enabled, 1, sizeof(int),f);
+ cheatsList[i].enabled = cheatsList[i].enabled ? true : false;
+ fread(&cheatsList[i].address, 1, sizeof(u32),f);
+ cheatsList[i].rawaddress = cheatsList[i].address;
+ fread(&cheatsList[i].value, 1, sizeof(u32),f);
+ fread(&cheatsList[i].oldValue, 1, sizeof(u32),f);
+ fread(&cheatsList[i].codestring, 1, 20*sizeof(char),f);
+ if(fread(&cheatsList[i].desc, 1, 32*sizeof(char),f) != 32*sizeof(char)) {
+ fclose(f);
+ return false;
+ }
+ }
+ }
+
+ bool firstCodeBreaker = true;
+
+ for(int i = 0; i < count; i++) {
+ cheatsList[i].status = 0; // remove old status as it is not used
+ if(!cheatsList[i].codestring[0]) {
+ switch(cheatsList[i].size) {
+ case 0:
+ sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
+ cheatsList[i].value);
+ break;
+ case 1:
+ sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
+ cheatsList[i].value);
+ break;
+ case 2:
+ sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
+ cheatsList[i].value);
+ break;
+ }
+ }
+
+ if(cheatsList[i].code == 512 && firstCodeBreaker) {
+ firstCodeBreaker = false;
+ char buffer[10];
+ strncpy(buffer, cheatsList[i].codestring, 8);
+ buffer[8] = 0;
+ u32 address;
+ sscanf(buffer, "%x", &address);
+ if((address >> 28) == 9) {
+ strncpy(buffer, &cheatsList[i].codestring[9], 4);
+ buffer[4] = 0;
+ u32 value;
+ sscanf(buffer, "%x", &value);
+
+ u32 seed[8];
+ cheatsCBAParseSeedCode(address, value, seed);
+ cheatsCBAChangeEncryption(seed);
+ }
+ }
+ }
+ cheatsNumber = count;
+ fclose(f);
+ return true;
+}
+
+extern int cpuNextEvent;
+
+extern void debuggerBreakOnWrite(u32 , u32, u32, int, int);
+
+static u8 cheatsGetType(u32 address)
+{
+ switch(address >> 24) {
+ case 2:
+ return freezeWorkRAM[address & 0x3FFFF];
+ case 3:
+ return freezeInternalRAM[address & 0x7FFF];
+ case 5:
+ return freezePRAM[address & 0x3FC];
+ case 6:
+ if (address > 0x06010000)
+ return freezeVRAM[address & 0x17FFF];
+ else
+ return freezeVRAM[address & 0x1FFFF];
+ case 7:
+ return freezeOAM[address & 0x3FC];
+ }
+ return 0;
+}
+
+void cheatsWriteMemory(u32 address, u32 value)
+{
+#ifdef BKPT_SUPPORT
+#ifdef SDL
+ if(cheatsNumber == 0) {
+ int type = cheatsGetType(address);
+ u32 oldValue = debuggerReadMemory(address);
+ if(type == 1 || (type == 2 && oldValue != value)) {
+ debuggerBreakOnWrite(address, oldValue, value, 2, type);
+ cpuNextEvent = 0;
+ }
+ debuggerWriteMemory(address, value);
+ }
+#endif
+#endif
+}
+
+void cheatsWriteHalfWord(u32 address, u16 value)
+{
+#ifdef BKPT_SUPPORT
+#ifdef SDL
+ if(cheatsNumber == 0) {
+ int type = cheatsGetType(address);
+ u16 oldValue = debuggerReadHalfWord(address);
+ if(type == 1 || (type == 2 && oldValue != value)) {
+ debuggerBreakOnWrite(address, oldValue, value, 1, type);
+ cpuNextEvent = 0;
+ }
+ debuggerWriteHalfWord(address, value);
+ }
+#endif
+#endif
+}
+
+#if defined BKPT_SUPPORT && defined SDL
+void cheatsWriteByte(u32 address, u8 value)
+#else
+void cheatsWriteByte(u32, u8)
+#endif
+{
+#ifdef BKPT_SUPPORT
+#ifdef SDL
+ if(cheatsNumber == 0) {
+ int type = cheatsGetType(address);
+ u8 oldValue = debuggerReadByte(address);
+ if(type == 1 || (type == 2 && oldValue != value)) {
+ debuggerBreakOnWrite(address, oldValue, value, 0, type);
+ cpuNextEvent = 0;
+ }
+ debuggerWriteByte(address, value);
+ }
+#endif
+#endif
+}
diff --git a/src/Cheats.h b/src/Cheats.h
index ed828ee5..ce966872 100644
--- a/src/Cheats.h
+++ b/src/Cheats.h
@@ -1,55 +1,55 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef GBA_CHEATS_H
-#define GBA_CHEATS_H
-
-struct CheatsData {
- int code;
- int size;
- int status;
- bool enabled;
- u32 rawaddress;
- u32 address;
- u32 value;
- u32 oldValue;
- char codestring[20];
- char desc[32];
-};
-
-extern void cheatsAdd(const char *,const char *,u32, u32,u32,int,int);
-extern void cheatsAddCheatCode(const char *code, const char *desc);
-extern void cheatsAddGSACode(const char *code, const char *desc, bool v3);
-extern void cheatsAddCBACode(const char *code, const char *desc);
-extern bool cheatsImportGSACodeFile(const char *name, int game, bool v3);
-extern void cheatsDelete(int number, bool restore);
-extern void cheatsDeleteAll(bool restore);
-extern void cheatsEnable(int number);
-extern void cheatsDisable(int number);
-extern void cheatsSaveGame(gzFile file);
-extern void cheatsReadGame(gzFile file);
-extern void cheatsSaveCheatList(const char *file);
-extern bool cheatsLoadCheatList(const char *file);
-extern void cheatsWriteMemory(u32, u32);
-extern void cheatsWriteHalfWord(u32, u16);
-extern void cheatsWriteByte(u32, u8);
-extern int cheatsCheckKeys(u32,u32);
-extern int cheatsNumber;
-extern CheatsData cheatsList[100];
-#endif // GBA_CHEATS_H
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef GBA_CHEATS_H
+#define GBA_CHEATS_H
+
+struct CheatsData {
+ int code;
+ int size;
+ int status;
+ bool enabled;
+ u32 rawaddress;
+ u32 address;
+ u32 value;
+ u32 oldValue;
+ char codestring[20];
+ char desc[32];
+};
+
+extern void cheatsAdd(const char *,const char *,u32, u32,u32,int,int);
+extern void cheatsAddCheatCode(const char *code, const char *desc);
+extern void cheatsAddGSACode(const char *code, const char *desc, bool v3);
+extern void cheatsAddCBACode(const char *code, const char *desc);
+extern bool cheatsImportGSACodeFile(const char *name, int game, bool v3);
+extern void cheatsDelete(int number, bool restore);
+extern void cheatsDeleteAll(bool restore);
+extern void cheatsEnable(int number);
+extern void cheatsDisable(int number);
+extern void cheatsSaveGame(gzFile file);
+extern void cheatsReadGame(gzFile file, int version);
+extern void cheatsSaveCheatList(const char *file);
+extern bool cheatsLoadCheatList(const char *file);
+extern void cheatsWriteMemory(u32, u32);
+extern void cheatsWriteHalfWord(u32, u16);
+extern void cheatsWriteByte(u32, u8);
+extern int cheatsCheckKeys(u32,u32);
+extern int cheatsNumber;
+extern CheatsData cheatsList[100];
+#endif // GBA_CHEATS_H
diff --git a/src/EEprom.cpp b/src/EEprom.cpp
index 0992ae66..0e456c08 100644
--- a/src/EEprom.cpp
+++ b/src/EEprom.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include
#include "GBA.h"
#include "EEprom.h"
#include "Util.h"
@@ -42,6 +43,11 @@ variable_desc eepromSaveData[] = {
{ NULL, 0 }
};
+void eepromInit()
+{
+ memset(eepromData, 255, sizeof(eepromData));
+}
+
void eepromReset()
{
eepromMode = EEPROM_IDLE;
diff --git a/src/EEprom.h b/src/EEprom.h
index 4bf23afc..3418ec4a 100644
--- a/src/EEprom.h
+++ b/src/EEprom.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -20,10 +20,11 @@
#ifndef VBA_EEPROM_H
#define VBA_EEPROM_H
-extern void eepromSaveGame(gzFile gzFile);
-extern void eepromReadGame(gzFile gzFile, int version);
+extern void eepromSaveGame(gzFile _gzFile);
+extern void eepromReadGame(gzFile _gzFile, int version);
extern int eepromRead(u32 address);
extern void eepromWrite(u32 address, u8 value);
+extern void eepromInit();
extern void eepromReset();
extern u8 eepromData[0x2000];
extern bool eepromInUse;
diff --git a/src/Flash.cpp b/src/Flash.cpp
index 0e9958a6..a04adc4a 100644
--- a/src/Flash.cpp
+++ b/src/Flash.cpp
@@ -1,259 +1,263 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-#include "GBA.h"
-#include "Globals.h"
-#include "Flash.h"
-#include "Sram.h"
-#include "Util.h"
-
-#define FLASH_READ_ARRAY 0
-#define FLASH_CMD_1 1
-#define FLASH_CMD_2 2
-#define FLASH_AUTOSELECT 3
-#define FLASH_CMD_3 4
-#define FLASH_CMD_4 5
-#define FLASH_CMD_5 6
-#define FLASH_ERASE_COMPLETE 7
-#define FLASH_PROGRAM 8
-#define FLASH_SETBANK 9
-
-u8 flashSaveMemory[0x20000];
-int flashState = FLASH_READ_ARRAY;
-int flashReadState = FLASH_READ_ARRAY;
-int flashSize = 0x10000;
-int flashDeviceID = 0x1b;
-int flashManufacturerID = 0x32;
-int flashBank = 0;
-
-static variable_desc flashSaveData[] = {
- { &flashState, sizeof(int) },
- { &flashReadState, sizeof(int) },
- { &flashSaveMemory[0], 0x10000 },
- { NULL, 0 }
-};
-
-static variable_desc flashSaveData2[] = {
- { &flashState, sizeof(int) },
- { &flashReadState, sizeof(int) },
- { &flashSize, sizeof(int) },
- { &flashSaveMemory[0], 0x20000 },
- { NULL, 0 }
-};
-
-static variable_desc flashSaveData3[] = {
- { &flashState, sizeof(int) },
- { &flashReadState, sizeof(int) },
- { &flashSize, sizeof(int) },
- { &flashBank, sizeof(int) },
- { &flashSaveMemory[0], 0x20000 },
- { NULL, 0 }
-};
-
-void flashInit()
-{
- memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
-}
-
-void flashReset()
-{
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- flashBank = 0;
-}
-
-void flashSaveGame(gzFile gzFile)
-{
- utilWriteData(gzFile, flashSaveData3);
-}
-
-void flashReadGame(gzFile gzFile, int version)
-{
- if(version < SAVE_GAME_VERSION_5)
- utilReadData(gzFile, flashSaveData);
- else if(version < SAVE_GAME_VERSION_7) {
- utilReadData(gzFile, flashSaveData2);
- flashBank = 0;
- flashSetSize(flashSize);
- } else {
- utilReadData(gzFile, flashSaveData3);
- }
-}
-
-void flashSetSize(int size)
-{
- // log("Setting flash size to %d\n", size);
- flashSize = size;
- if(size == 0x10000) {
- flashDeviceID = 0x1b;
- flashManufacturerID = 0x32;
- } else {
- flashDeviceID = 0x13; //0x09;
- flashManufacturerID = 0x62; //0xc2;
- }
-}
-
-u8 flashRead(u32 address)
-{
- // log("Reading %08x from %08x\n", address, reg[15].I);
- // log("Current read state is %d\n", flashReadState);
- address &= 0xFFFF;
-
- switch(flashReadState) {
- case FLASH_READ_ARRAY:
- return flashSaveMemory[(flashBank << 16) + address];
- case FLASH_AUTOSELECT:
- switch(address & 0xFF) {
- case 0:
- // manufacturer ID
- return flashManufacturerID;
- case 1:
- // device ID
- return flashDeviceID;
- }
- break;
- case FLASH_ERASE_COMPLETE:
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- return 0xFF;
- };
- return 0;
-}
-
-void flashSaveDecide(u32 address, u8 byte)
-{
- // log("Deciding save type %08x\n", address);
- if(address == 0x0e005555) {
- saveType = 2;
- cpuSaveGameFunc = flashWrite;
- } else {
- saveType = 1;
- cpuSaveGameFunc = sramWrite;
- }
-
- (*cpuSaveGameFunc)(address, byte);
-}
-
-void flashDelayedWrite(u32 address, u8 byte)
-{
- saveType = 2;
- cpuSaveGameFunc = flashWrite;
- flashWrite(address, byte);
-}
-
-void flashWrite(u32 address, u8 byte)
-{
- // log("Writing %02x at %08x\n", byte, address);
- // log("Current state is %d\n", flashState);
- address &= 0xFFFF;
- switch(flashState) {
- case FLASH_READ_ARRAY:
- if(address == 0x5555 && byte == 0xAA)
- flashState = FLASH_CMD_1;
- break;
- case FLASH_CMD_1:
- if(address == 0x2AAA && byte == 0x55)
- flashState = FLASH_CMD_2;
- else
- flashState = FLASH_READ_ARRAY;
- break;
- case FLASH_CMD_2:
- if(address == 0x5555) {
- if(byte == 0x90) {
- flashState = FLASH_AUTOSELECT;
- flashReadState = FLASH_AUTOSELECT;
- } else if(byte == 0x80) {
- flashState = FLASH_CMD_3;
- } else if(byte == 0xF0) {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- } else if(byte == 0xA0) {
- flashState = FLASH_PROGRAM;
- } else if(byte == 0xB0 && flashSize == 0x20000) {
- flashState = FLASH_SETBANK;
- } else {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- }
- } else {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- }
- break;
- case FLASH_CMD_3:
- if(address == 0x5555 && byte == 0xAA) {
- flashState = FLASH_CMD_4;
- } else {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- }
- break;
- case FLASH_CMD_4:
- if(address == 0x2AAA && byte == 0x55) {
- flashState = FLASH_CMD_5;
- } else {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- }
- break;
- case FLASH_CMD_5:
- if(byte == 0x30) {
- // SECTOR ERASE
- memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)],
- 0,
- 0x1000);
- systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
- flashReadState = FLASH_ERASE_COMPLETE;
- } else if(byte == 0x10) {
- // CHIP ERASE
- memset(flashSaveMemory, 0, flashSize);
- systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
- flashReadState = FLASH_ERASE_COMPLETE;
- } else {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- }
- break;
- case FLASH_AUTOSELECT:
- if(byte == 0xF0) {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- } else if(address == 0x5555 && byte == 0xAA)
- flashState = FLASH_CMD_1;
- else {
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- }
- break;
- case FLASH_PROGRAM:
- flashSaveMemory[(flashBank<<16)+address] = byte;
- systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- break;
- case FLASH_SETBANK:
- if(address == 0) {
- flashBank = (byte & 1);
- }
- flashState = FLASH_READ_ARRAY;
- flashReadState = FLASH_READ_ARRAY;
- break;
- }
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+#include "GBA.h"
+#include "Globals.h"
+#include "Flash.h"
+#include "Sram.h"
+#include "Util.h"
+
+#define FLASH_READ_ARRAY 0
+#define FLASH_CMD_1 1
+#define FLASH_CMD_2 2
+#define FLASH_AUTOSELECT 3
+#define FLASH_CMD_3 4
+#define FLASH_CMD_4 5
+#define FLASH_CMD_5 6
+#define FLASH_ERASE_COMPLETE 7
+#define FLASH_PROGRAM 8
+#define FLASH_SETBANK 9
+
+u8 flashSaveMemory[0x20000];
+int flashState = FLASH_READ_ARRAY;
+int flashReadState = FLASH_READ_ARRAY;
+int flashSize = 0x10000;
+int flashDeviceID = 0x1b;
+int flashManufacturerID = 0x32;
+int flashBank = 0;
+
+static variable_desc flashSaveData[] = {
+ { &flashState, sizeof(int) },
+ { &flashReadState, sizeof(int) },
+ { &flashSaveMemory[0], 0x10000 },
+ { NULL, 0 }
+};
+
+static variable_desc flashSaveData2[] = {
+ { &flashState, sizeof(int) },
+ { &flashReadState, sizeof(int) },
+ { &flashSize, sizeof(int) },
+ { &flashSaveMemory[0], 0x20000 },
+ { NULL, 0 }
+};
+
+static variable_desc flashSaveData3[] = {
+ { &flashState, sizeof(int) },
+ { &flashReadState, sizeof(int) },
+ { &flashSize, sizeof(int) },
+ { &flashBank, sizeof(int) },
+ { &flashSaveMemory[0], 0x20000 },
+ { NULL, 0 }
+};
+
+void flashInit()
+{
+ memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
+}
+
+void flashReset()
+{
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ flashBank = 0;
+}
+
+void flashSaveGame(gzFile gzFile)
+{
+ utilWriteData(gzFile, flashSaveData3);
+}
+
+void flashReadGame(gzFile gzFile, int version)
+{
+ if(version < SAVE_GAME_VERSION_5)
+ utilReadData(gzFile, flashSaveData);
+ else if(version < SAVE_GAME_VERSION_7) {
+ utilReadData(gzFile, flashSaveData2);
+ flashBank = 0;
+ flashSetSize(flashSize);
+ } else {
+ utilReadData(gzFile, flashSaveData3);
+ }
+}
+
+void flashSetSize(int size)
+{
+ // log("Setting flash size to %d\n", size);
+ if(size == 0x10000) {
+ flashDeviceID = 0x1b;
+ flashManufacturerID = 0x32;
+ } else {
+ flashDeviceID = 0x13; //0x09;
+ flashManufacturerID = 0x62; //0xc2;
+ }
+ // Added to make 64k saves compatible with 128k ones
+ // (allow wrongfuly set 64k saves to work for Pokemon games)
+ if ((size == 0x20000) && (flashSize == 0x10000))
+ memcpy((u8 *)(flashSaveMemory+0x10000), (u8 *)(flashSaveMemory), 0x10000);
+ flashSize = size;
+}
+
+u8 flashRead(u32 address)
+{
+ // log("Reading %08x from %08x\n", address, reg[15].I);
+ // log("Current read state is %d\n", flashReadState);
+ address &= 0xFFFF;
+
+ switch(flashReadState) {
+ case FLASH_READ_ARRAY:
+ return flashSaveMemory[(flashBank << 16) + address];
+ case FLASH_AUTOSELECT:
+ switch(address & 0xFF) {
+ case 0:
+ // manufacturer ID
+ return flashManufacturerID;
+ case 1:
+ // device ID
+ return flashDeviceID;
+ }
+ break;
+ case FLASH_ERASE_COMPLETE:
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ return 0xFF;
+ };
+ return 0;
+}
+
+void flashSaveDecide(u32 address, u8 byte)
+{
+ // log("Deciding save type %08x\n", address);
+ if(address == 0x0e005555) {
+ saveType = 2;
+ cpuSaveGameFunc = flashWrite;
+ } else {
+ saveType = 1;
+ cpuSaveGameFunc = sramWrite;
+ }
+
+ (*cpuSaveGameFunc)(address, byte);
+}
+
+void flashDelayedWrite(u32 address, u8 byte)
+{
+ saveType = 2;
+ cpuSaveGameFunc = flashWrite;
+ flashWrite(address, byte);
+}
+
+void flashWrite(u32 address, u8 byte)
+{
+ // log("Writing %02x at %08x\n", byte, address);
+ // log("Current state is %d\n", flashState);
+ address &= 0xFFFF;
+ switch(flashState) {
+ case FLASH_READ_ARRAY:
+ if(address == 0x5555 && byte == 0xAA)
+ flashState = FLASH_CMD_1;
+ break;
+ case FLASH_CMD_1:
+ if(address == 0x2AAA && byte == 0x55)
+ flashState = FLASH_CMD_2;
+ else
+ flashState = FLASH_READ_ARRAY;
+ break;
+ case FLASH_CMD_2:
+ if(address == 0x5555) {
+ if(byte == 0x90) {
+ flashState = FLASH_AUTOSELECT;
+ flashReadState = FLASH_AUTOSELECT;
+ } else if(byte == 0x80) {
+ flashState = FLASH_CMD_3;
+ } else if(byte == 0xF0) {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ } else if(byte == 0xA0) {
+ flashState = FLASH_PROGRAM;
+ } else if(byte == 0xB0 && flashSize == 0x20000) {
+ flashState = FLASH_SETBANK;
+ } else {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ }
+ } else {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ }
+ break;
+ case FLASH_CMD_3:
+ if(address == 0x5555 && byte == 0xAA) {
+ flashState = FLASH_CMD_4;
+ } else {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ }
+ break;
+ case FLASH_CMD_4:
+ if(address == 0x2AAA && byte == 0x55) {
+ flashState = FLASH_CMD_5;
+ } else {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ }
+ break;
+ case FLASH_CMD_5:
+ if(byte == 0x30) {
+ // SECTOR ERASE
+ memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)],
+ 0,
+ 0x1000);
+ systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
+ flashReadState = FLASH_ERASE_COMPLETE;
+ } else if(byte == 0x10) {
+ // CHIP ERASE
+ memset(flashSaveMemory, 0, flashSize);
+ systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
+ flashReadState = FLASH_ERASE_COMPLETE;
+ } else {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ }
+ break;
+ case FLASH_AUTOSELECT:
+ if(byte == 0xF0) {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ } else if(address == 0x5555 && byte == 0xAA)
+ flashState = FLASH_CMD_1;
+ else {
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ }
+ break;
+ case FLASH_PROGRAM:
+ flashSaveMemory[(flashBank<<16)+address] = byte;
+ systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ break;
+ case FLASH_SETBANK:
+ if(address == 0) {
+ flashBank = (byte & 1);
+ }
+ flashState = FLASH_READ_ARRAY;
+ flashReadState = FLASH_READ_ARRAY;
+ break;
+ }
+}
diff --git a/src/Flash.h b/src/Flash.h
index bde63997..debda734 100644
--- a/src/Flash.h
+++ b/src/Flash.h
@@ -1,35 +1,35 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_FLASH_H
-#define VBA_FLASH_H
-
-extern void flashSaveGame(gzFile gzFile);
-extern void flashReadGame(gzFile gzFile, int version);
-extern u8 flashRead(u32 address);
-extern void flashWrite(u32 address, u8 byte);
-extern void flashDelayedWrite(u32 address, u8 byte);
-extern u8 flashSaveMemory[0x20000];
-extern void flashSaveDecide(u32 address, u8 byte);
-extern void flashReset();
-extern void flashSetSize(int size);
-extern void flashInit();
-
-extern int flashSize;
-#endif // VBA_FLASH_H
\ No newline at end of file
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_FLASH_H
+#define VBA_FLASH_H
+
+extern void flashSaveGame(gzFile _gzFile);
+extern void flashReadGame(gzFile _gzFile, int version);
+extern u8 flashRead(u32 address);
+extern void flashWrite(u32 address, u8 byte);
+extern void flashDelayedWrite(u32 address, u8 byte);
+extern u8 flashSaveMemory[0x20000];
+extern void flashSaveDecide(u32 address, u8 byte);
+extern void flashReset();
+extern void flashSetSize(int size);
+extern void flashInit();
+
+extern int flashSize;
+#endif // VBA_FLASH_H
diff --git a/src/GBA.cpp b/src/GBA.cpp
index 3268bc11..3ca1113a 100644
--- a/src/GBA.cpp
+++ b/src/GBA.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -42,31 +42,51 @@
#include "prof/prof.h"
#endif
-#define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value)
+#define UPDATE_REG(address, value)\
+ {\
+ WRITE16LE(((u16 *)&ioMem[address]),value);\
+ }\
+
+#define ARM_PREFETCH \
+ {\
+ cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);\
+ cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);\
+ }
+
+#define THUMB_PREFETCH \
+ {\
+ cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);\
+ cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);\
+ }
+
+#define ARM_PREFETCH_NEXT \
+ cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);
+
+#define THUMB_PREFETCH_NEXT\
+ cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);
#ifdef __GNUC__
#define _stricmp strcasecmp
#endif
-extern int emulating;
-extern int linktime;
-extern void StartLink(u16);
-extern void StartJOYLink(u16);
-extern void StartGPLink(u16);
-extern void LinkSSend(u16);
-extern void LinkUpdate(int);
-extern int linktime2;
+extern int emulating;
+int SWITicks = 0;
+int IRQTicks = 0;
+
+u32 mastercode = 0;
+int layerEnableDelay = 0;
+bool busPrefetch = false;
+bool busPrefetchEnable = false;
+u32 busPrefetchCount = 0;
int cpuDmaTicksToUpdate = 0;
int cpuDmaCount = 0;
bool cpuDmaHack = false;
-bool cpuDmaHack2 = false;
u32 cpuDmaLast = 0;
int dummyAddress = 0;
-bool cpuBreakLoop = true;
+bool cpuBreakLoop = false;
int cpuNextEvent = 0;
-int cpuTotalTicks = 0;
int gbaSaveType = 0; // used to remember the save type on reset
bool intState = false;
@@ -78,29 +98,40 @@ bool cpuFlashEnabled = true;
bool cpuEEPROMEnabled = true;
bool cpuEEPROMSensorEnabled = false;
+u32 cpuPrefetch[2];
+
+int cpuTotalTicks = 0;
#ifdef PROFILING
int profilingTicks = 0;
int profilingTicksReload = 0;
-static char *profilBuffer = NULL;
-static int profilSize = 0;
-static u32 profilLowPC = 0;
-static int profilScale = 0;
+static profile_segment *profilSegment = NULL;
#endif
+
u8 freezeWorkRAM[0x40000];
u8 freezeInternalRAM[0x8000];
-int lcdTicks = 960;
+u8 freezeVRAM[0x18000];
+u8 freezePRAM[0x400];
+u8 freezeOAM[0x400];
+bool debugger_last;
+
+int lcdTicks = (useBios && !skipBios) ? 1008 : 208;
+u8 timerOnOffDelay = 0;
+u16 timer0Value = 0;
bool timer0On = false;
int timer0Ticks = 0;
int timer0Reload = 0;
int timer0ClockReload = 0;
+u16 timer1Value = 0;
bool timer1On = false;
int timer1Ticks = 0;
int timer1Reload = 0;
int timer1ClockReload = 0;
+u16 timer2Value = 0;
bool timer2On = false;
int timer2Ticks = 0;
int timer2Reload = 0;
int timer2ClockReload = 0;
+u16 timer3Value = 0;
bool timer3On = false;
int timer3Ticks = 0;
int timer3Reload = 0;
@@ -128,62 +159,38 @@ int capturePrevious = 0;
int captureNumber = 0;
const int TIMER_TICKS[4] = {
- 1,
- 64,
- 256,
- 1024
+ 0,
+ 6,
+ 8,
+ 10
};
-const int thumbCycles[] = {
-// 0 1 2 3 4 5 6 7 8 9 a b c d e f
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
- 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 4
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 5
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 6
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 7
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 8
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 9
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // a
- 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, // b
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, // d
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // e
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // f
-};
+const u32 objTilesAddress [3] = {0x010000, 0x014000, 0x014000};
+const u8 gamepakRamWaitState[4] = { 4, 3, 2, 8 };
+const u8 gamepakWaitState[4] = { 4, 3, 2, 8 };
+const u8 gamepakWaitState0[2] = { 2, 1 };
+const u8 gamepakWaitState1[2] = { 4, 1 };
+const u8 gamepakWaitState2[2] = { 8, 1 };
+const bool isInRom [16]=
+ { false, false, false, false, false, false, false, false,
+ true, true, true, true, true, true, false, false };
-const int gamepakRamWaitState[4] = { 4, 3, 2, 8 };
-const int gamepakWaitState[8] = { 4, 3, 2, 8, 4, 3, 2, 8 };
-const int gamepakWaitState0[8] = { 2, 2, 2, 2, 1, 1, 1, 1 };
-const int gamepakWaitState1[8] = { 4, 4, 4, 4, 1, 1, 1, 1 };
-const int gamepakWaitState2[8] = { 8, 8, 8, 8, 1, 1, 1, 1 };
-
-int memoryWait[16] =
+u8 memoryWait[16] =
{ 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 };
-int memoryWait32[16] =
- { 0, 0, 9, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 0 };
-int memoryWaitSeq[16] =
+u8 memoryWait32[16] =
+ { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 };
+u8 memoryWaitSeq[16] =
{ 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 };
-int memoryWaitSeq32[16] =
- { 2, 0, 3, 0, 0, 2, 2, 0, 4, 4, 8, 8, 16, 16, 8, 0 };
-int memoryWaitFetch[16] =
- { 3, 0, 3, 0, 0, 1, 1, 0, 4, 4, 4, 4, 4, 4, 4, 0 };
-int memoryWaitFetch32[16] =
- { 6, 0, 6, 0, 0, 2, 2, 0, 8, 8, 8, 8, 8, 8, 8, 0 };
+u8 memoryWaitSeq32[16] =
+ { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 };
+
+// The videoMemoryWait constants are used to add some waitstates
+// if the opcode access video memory data outside of vblank/hblank
+// It seems to happen on only one ticks for each pixel.
+// Not used for now (too problematic with current code).
+//const u8 videoMemoryWait[16] =
+// {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-const int cpuMemoryWait[16] = {
- 0, 0, 2, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 0, 0
-};
-const int cpuMemoryWait32[16] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
- 3, 3, 3, 3, 3, 3, 0, 0
-};
-
-const bool memory32[16] =
- { true, false, false, true, true, false, false, true, false, false, false, false, false, false, true, false};
u8 biosProtected[4];
@@ -489,12 +496,9 @@ variable_desc saveGameStruct[] = {
static int romSize = 0x2000000;
#ifdef PROFILING
-void cpuProfil(char *buf, int size, u32 lowPC, int scale)
+void cpuProfil(profile_segment *seg)
{
- profilBuffer = buf;
- profilSize = size;
- profilLowPC = lowPC;
- profilScale = scale;
+ profilSegment = seg;
}
void cpuEnableProfiling(int hz)
@@ -506,26 +510,211 @@ void cpuEnableProfiling(int hz)
}
#endif
-inline int CPUUpdateTicksAccess32(u32 address)
+
+// Waitstates when accessing data
+inline int dataTicksAccess16(u32 address) // DATA 8/16bits NON SEQ
{
- return memoryWait32[(address>>24)&15];
+ int addr = (address>>24)&15;
+ int value = memoryWait[addr];
+
+ if ((addr>=0x08) || (addr < 0x02))
+ {
+ busPrefetchCount=0;
+ busPrefetch=false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((++busPrefetchCount)<>24)&15];
+ int addr = (address>>24)&15;
+ int value = memoryWait32[addr];
+
+ if ((addr>=0x08) || (addr < 0x02))
+ {
+ busPrefetchCount=0;
+ busPrefetch=false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((++busPrefetchCount)<>24)&15];
+ int addr = (address>>24)&15;
+ int value = memoryWaitSeq[addr];
+
+ if ((addr>=0x08) || (addr < 0x02))
+ {
+ busPrefetchCount=0;
+ busPrefetch=false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((++busPrefetchCount)<>24)&15];
+ int addr = (address>>24)&15;
+ int value = memoryWaitSeq32[addr];
+
+ if ((addr>=0x08) || (addr < 0x02))
+ {
+ busPrefetchCount=0;
+ busPrefetch=false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((++busPrefetchCount)<>24)&15;
+
+ if ((addr>=0x08) && (addr<=0x0D))
+ {
+ if (busPrefetchCount&0x1)
+ {
+ if (busPrefetchCount&0x2)
+ {
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
+ return 0;
+ }
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
+ return memoryWaitSeq[addr]-1;
+ }
+ else
+ {
+ busPrefetchCount=0;
+ return memoryWait[addr];
+ }
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait[addr];
+ }
+}
+
+inline int codeTicksAccess32(u32 address) // ARM NON SEQ
+{
+ int addr = (address>>24)&15;
+
+ if ((addr>=0x08) && (addr<=0x0D))
+ {
+ if (busPrefetchCount&0x1)
+ {
+ if (busPrefetchCount&0x2)
+ {
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
+ return 0;
+ }
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
+ return memoryWaitSeq[addr] - 1;
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait32[addr];
+ }
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait32[addr];
+ }
+}
+
+inline int codeTicksAccessSeq16(u32 address) // THUMB SEQ
+{
+ int addr = (address>>24)&15;
+
+ if ((addr>=0x08) && (addr<=0x0D))
+ {
+ if (busPrefetchCount&0x1)
+ {
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
+ return 0;
+ }
+ else
+ if (busPrefetchCount>0xFF)
+ {
+ busPrefetchCount=0;
+ return memoryWait[addr];
+ }
+ else
+ return memoryWaitSeq[addr];
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWaitSeq[addr];
+ }
+}
+
+inline int codeTicksAccessSeq32(u32 address) // ARM SEQ
+{
+ int addr = (address>>24)&15;
+
+ if ((addr>=0x08) && (addr<=0x0D))
+ {
+ if (busPrefetchCount&0x1)
+ {
+ if (busPrefetchCount&0x2)
+ {
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
+ return 0;
+ }
+ busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
+ return memoryWaitSeq[addr];
+ }
+ else
+ if (busPrefetchCount>0xFF)
+ {
+ busPrefetchCount=0;
+ return memoryWait32[addr];
+ }
+ else
+ return memoryWaitSeq32[addr];
+ }
+ else
+ {
+ return memoryWaitSeq32[addr];
+ }
+}
+
+
inline int CPUUpdateTicks()
{
int cpuLoopTicks = lcdTicks;
@@ -533,7 +722,7 @@ inline int CPUUpdateTicks()
if(soundTicks < cpuLoopTicks)
cpuLoopTicks = soundTicks;
- if(timer0On && !(TM0CNT & 4) && (timer0Ticks < cpuLoopTicks)) {
+ if(timer0On && (timer0Ticks < cpuLoopTicks)) {
cpuLoopTicks = timer0Ticks;
}
if(timer1On && !(TM1CNT & 4) && (timer1Ticks < cpuLoopTicks)) {
@@ -553,6 +742,16 @@ inline int CPUUpdateTicks()
}
#endif
+ if (SWITicks) {
+ if (SWITicks < cpuLoopTicks)
+ cpuLoopTicks = SWITicks;
+ }
+
+ if (IRQTicks) {
+ if (IRQTicks < cpuLoopTicks)
+ cpuLoopTicks = IRQTicks;
+ }
+
return cpuLoopTicks;
}
@@ -632,7 +831,7 @@ static bool CPUWriteState(gzFile gzFile)
// new to version 0.7.1
utilWriteInt(gzFile, stopState);
// new to version 0.8
- utilWriteInt(gzFile, intState);
+ utilWriteInt(gzFile, IRQTicks);
utilGzWrite(gzFile, internalRAM, 0x8000);
utilGzWrite(gzFile, paletteRAM, 0x400);
@@ -640,9 +839,6 @@ static bool CPUWriteState(gzFile gzFile)
utilGzWrite(gzFile, vram, 0x20000);
utilGzWrite(gzFile, oam, 0x400);
utilGzWrite(gzFile, pix, 4*241*162);
-
- for (int i = NR10; i <= 0x9F; i++) ioMem[i] = soundRead(i);
-
utilGzWrite(gzFile, ioMem, 0x400);
eepromSaveGame(gzFile);
@@ -739,9 +935,21 @@ static bool CPUReadState(gzFile gzFile)
stopState = utilReadInt(gzFile) ? true : false;
if(version < SAVE_GAME_VERSION_4)
+ {
+ IRQTicks = 0;
intState = false;
+ }
else
- intState = utilReadInt(gzFile) ? true : false;
+ {
+ IRQTicks = utilReadInt(gzFile);
+ if (IRQTicks>0)
+ intState = true;
+ else
+ {
+ intState = false;
+ IRQTicks = 0;
+ }
+ }
utilGzRead(gzFile, internalRAM, 0x8000);
utilGzRead(gzFile, paletteRAM, 0x400);
@@ -759,7 +967,7 @@ static bool CPUReadState(gzFile gzFile)
soundReadGame(gzFile, version);
if(version > SAVE_GAME_VERSION_1) {
- cheatsReadGame(gzFile);
+ cheatsReadGame(gzFile, version);
}
if(version > SAVE_GAME_VERSION_6) {
rtcReadGame(gzFile);
@@ -783,6 +991,19 @@ static bool CPUReadState(gzFile gzFile)
SWAP(dma3Dest, DM3DAD_H, DM3DAD_L);
}
+ if(version <= SAVE_GAME_VERSION_8) {
+ timer0ClockReload = TIMER_TICKS[TM0CNT & 3];
+ timer1ClockReload = TIMER_TICKS[TM1CNT & 3];
+ timer2ClockReload = TIMER_TICKS[TM2CNT & 3];
+ timer3ClockReload = TIMER_TICKS[TM3CNT & 3];
+
+ timer0Ticks = ((0x10000 - TM0D) << timer0ClockReload) - timer0Ticks;
+ timer1Ticks = ((0x10000 - TM1D) << timer1ClockReload) - timer1Ticks;
+ timer2Ticks = ((0x10000 - TM2D) << timer2ClockReload) - timer2Ticks;
+ timer3Ticks = ((0x10000 - TM3D) << timer3ClockReload) - timer3Ticks;
+ interp_rate();
+ }
+
// set pointers!
layerEnable = layerSettings & DISPCNT;
@@ -803,6 +1024,11 @@ static bool CPUReadState(gzFile gzFile)
cpuSaveGameFunc = flashWrite;
gbaSaveType = 2;
break;
+ case 3:
+ break;
+ case 5:
+ gbaSaveType = 5;
+ break;
default:
systemMessage(MSG_UNSUPPORTED_SAVE_TYPE,
N_("Unsupported save type %d"), saveType);
@@ -812,6 +1038,13 @@ static bool CPUReadState(gzFile gzFile)
gbaSaveType = 3;
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+ if(armState) {
+ ARM_PREFETCH;
+ } else {
+ THUMB_PREFETCH;
+ }
+
+ CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
return true;
}
@@ -881,7 +1114,7 @@ bool CPUWriteBatteryFile(const char *fileName)
}
}
- if(gbaSaveType) {
+ if((gbaSaveType) && (gbaSaveType!=5)) {
FILE *file = fopen(fileName, "wb");
if(!file) {
@@ -998,13 +1231,13 @@ bool CPUWriteGSASnapshot(const char *fileName,
fwrite("SharkPortSave", 1, 0x0d, file);
utilPutDword(buffer, 0x000f0000);
fwrite(buffer, 1, 4, file); // save type 0x000f0000 = GBA save
- utilPutDword(buffer, strlen(title));
+ utilPutDword(buffer, (u32)strlen(title));
fwrite(buffer, 1, 4, file); // title length
fwrite(title, 1, strlen(title), file);
- utilPutDword(buffer, strlen(desc));
+ utilPutDword(buffer, (u32)strlen(desc));
fwrite(buffer, 1, 4, file); // desc length
fwrite(desc, 1, strlen(desc), file);
- utilPutDword(buffer, strlen(notes));
+ utilPutDword(buffer, (u32)strlen(notes));
fwrite(buffer, 1, 4, file); // notes length
fwrite(notes, 1, strlen(notes), file);
int saveSize = 0x10000;
@@ -1131,7 +1364,7 @@ bool CPUWriteBMPFile(const char *fileName)
bool CPUIsZipFile(const char * file)
{
if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
+ const char * p = strrchr(file,'.');
if(p != NULL) {
if(_stricmp(p, ".zip") == 0)
@@ -1146,7 +1379,7 @@ bool CPUIsGBAImage(const char * file)
{
cpuIsMultiBoot = false;
if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
+ const char * p = strrchr(file,'.');
if(p != NULL) {
if(_stricmp(p, ".gba") == 0)
@@ -1170,7 +1403,7 @@ bool CPUIsGBAImage(const char * file)
bool CPUIsGBABios(const char * file)
{
if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
+ const char * p = strrchr(file,'.');
if(p != NULL) {
if(_stricmp(p, ".gba") == 0)
@@ -1190,7 +1423,7 @@ bool CPUIsGBABios(const char * file)
bool CPUIsELF(const char *file)
{
if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
+ const char * p = strrchr(file,'.');
if(p != NULL) {
if(_stricmp(p, ".elf") == 0)
@@ -1263,7 +1496,6 @@ void CPUCleanUp()
int CPULoadRom(const char *szFile)
{
romSize = 0x2000000;
-
if(rom != NULL) {
CPUCleanUp();
}
@@ -1376,12 +1608,30 @@ int CPULoadRom(const char *szFile)
}
flashInit();
+ eepromInit();
CPUUpdateRenderBuffers(true);
return romSize;
}
+void doMirroring (bool b)
+{
+ u32 mirroredRomSize = (((romSize)>>20) & 0x3F)<<20;
+ u32 mirroredRomAddress = romSize;
+ if ((mirroredRomSize <=0x800000) && (b))
+ {
+ mirroredRomAddress = mirroredRomSize;
+ if (mirroredRomSize==0)
+ mirroredRomSize=0x100000;
+ while (mirroredRomAddress<0x01000000)
+ {
+ memcpy ((u16 *)(rom+mirroredRomAddress), (u16 *)(rom), mirroredRomSize);
+ mirroredRomAddress+=mirroredRomSize;
+ }
+ }
+}
+
void CPUUpdateRender()
{
switch(DISPCNT & 7) {
@@ -1473,9 +1723,8 @@ void CPUUpdateFlags(bool breakLoop)
armState = (CPSR & 0x20) ? false : true;
armIrqEnable = (CPSR & 0x80) ? false : true;
if(breakLoop) {
- if(armIrqEnable && (IF & IE) && (IME & 1)) {
- cpuNextEvent = 0;
- }
+ if (armIrqEnable && (IF & IE) && (IME & 1))
+ cpuNextEvent = cpuTotalTicks;
}
}
@@ -1629,6 +1878,7 @@ void CPUUndefinedException()
armState = true;
armIrqEnable = false;
armNextPC = 0x04;
+ ARM_PREFETCH;
reg[15].I += 4;
}
@@ -1642,6 +1892,7 @@ void CPUSoftwareInterrupt()
armState = true;
armIrqEnable = false;
armNextPC = 0x08;
+ ARM_PREFETCH;
reg[15].I += 4;
}
@@ -1681,7 +1932,7 @@ void CPUSoftwareInterrupt(int comment)
#ifdef SDL
if(comment == 0xf9) {
emulating = 0;
- cpuNextEvent = 0;
+ cpuNextEvent = cpuTotalTicks;
cpuBreakLoop = true;
return;
}
@@ -1708,6 +1959,7 @@ void CPUSoftwareInterrupt(int comment)
switch(comment) {
case 0x00:
BIOS_SoftReset();
+ ARM_PREFETCH;
break;
case 0x01:
BIOS_RegisterRamReset();
@@ -1721,7 +1973,7 @@ void CPUSoftwareInterrupt(int comment)
#endif
holdState = true;
holdType = -1;
- cpuNextEvent = 0;
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x03:
#ifdef DEV_VERSION
@@ -1733,7 +1985,7 @@ void CPUSoftwareInterrupt(int comment)
holdState = true;
holdType = -1;
stopState = true;
- cpuNextEvent = 0;
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x04:
#ifdef DEV_VERSION
@@ -1771,11 +2023,52 @@ void CPUSoftwareInterrupt(int comment)
BIOS_ArcTan2();
break;
case 0x0B:
+ {
+ int len = (reg[2].I & 0x1FFFFF) >>1;
+ if (!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + len) & 0xe000000) == 0))
+ {
+ if ((reg[2].I >> 24) & 1)
+ {
+ if ((reg[2].I >> 26) & 1)
+ SWITicks = (7 + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1);
+ else
+ SWITicks = (8 + memoryWait[(reg[1].I>>24) & 0xF]) * (len);
+ }
+ else
+ {
+ if ((reg[2].I >> 26) & 1)
+ SWITicks = (10 + memoryWait32[(reg[0].I>>24) & 0xF] +
+ memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1);
+ else
+ SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] +
+ memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
+ }
+ }
BIOS_CpuSet();
break;
case 0x0C:
+ {
+ int len = (reg[2].I & 0x1FFFFF) >>5;
+ if (!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + len) & 0xe000000) == 0))
+ {
+ if ((reg[2].I >> 24) & 1)
+ SWITicks = (6 + memoryWait32[(reg[1].I>>24) & 0xF] +
+ 7 * (memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 1)) * len;
+ else
+ SWITicks = (9 + memoryWait32[(reg[0].I>>24) & 0xF] +
+ memoryWait32[(reg[1].I>>24) & 0xF] +
+ 7 * (memoryWaitSeq32[(reg[0].I>>24) & 0xF] +
+ memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 2)) * len;
+ }
+ }
BIOS_CpuFastSet();
break;
+ case 0x0D:
+ BIOS_GetBiosChecksum();
+ break;
case 0x0E:
BIOS_BgAffineSet();
break;
@@ -1783,30 +2076,89 @@ void CPUSoftwareInterrupt(int comment)
BIOS_ObjAffineSet();
break;
case 0x10:
+ {
+ int len = CPUReadHalfWord(reg[2].I);
+ if (!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + len) & 0xe000000) == 0))
+ SWITicks = (32 + memoryWait[(reg[0].I>>24) & 0xF]) * len;
+ }
BIOS_BitUnPack();
break;
case 0x11:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 8;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (9 + memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_LZ77UnCompWram();
break;
case 0x12:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 8;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (19 + memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_LZ77UnCompVram();
break;
case 0x13:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 8;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (29 + (memoryWait[(reg[0].I>>24) & 0xF]<<1)) * len;
+ }
BIOS_HuffUnComp();
break;
case 0x14:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 8;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] +
+ memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_RLUnCompWram();
break;
case 0x15:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 9;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (34 + (memoryWait[(reg[0].I>>24) & 0xF] << 1) +
+ memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_RLUnCompVram();
break;
case 0x16:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 8;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] +
+ memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_Diff8bitUnFilterWram();
break;
case 0x17:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 9;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (39 + (memoryWait[(reg[0].I>>24) & 0xF]<<1) +
+ memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_Diff8bitUnFilterVram();
break;
case 0x18:
+ {
+ u32 len = CPUReadMemory(reg[0].I) >> 9;
+ if(!(((reg[0].I & 0xe000000) == 0) ||
+ ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
+ SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] +
+ memoryWait[(reg[1].I>>24) & 0xF]) * len;
+ }
BIOS_Diff16bitUnFilter();
break;
case 0x19:
@@ -1865,17 +2217,33 @@ void CPUCompareVCOUNT()
DISPSTAT &= 0xFFFB;
UPDATE_REG(0x4, DISPSTAT);
}
+ if (layerEnableDelay>0)
+ {
+ layerEnableDelay--;
+ if (layerEnableDelay==1)
+ layerEnable = layerSettings & DISPCNT;
+ }
+
}
void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
{
int sm = s >> 24;
int dm = d >> 24;
-
+ int sw = 0;
+ int dw = 0;
int sc = c;
cpuDmaCount = c;
+ // This is done to get the correct waitstates.
+ if (sm>15)
+ sm=15;
+ if (dm>15)
+ dm=15;
+ //if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07))
+ // blank = (((DISPSTAT | ((DISPSTAT>>1)&1))==1) ? true : false);
+
if(transfer32) {
s &= 0xFFFFFFFC;
if(s < 0x02000000 && (reg[15].I >> 24)) {
@@ -1900,7 +2268,6 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
if(s < 0x02000000 && (reg[15].I >> 24)) {
while(c != 0) {
CPUWriteHalfWord(d, 0);
- cpuDmaLast |= (cpuDmaLast<<16);
d += di;
c--;
}
@@ -1908,6 +2275,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
while(c != 0) {
cpuDmaLast = CPUReadHalfWord(s);
CPUWriteHalfWord(d, cpuDmaLast);
+ cpuDmaLast |= (cpuDmaLast<<16);
d += di;
s += si;
c--;
@@ -1917,33 +2285,31 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
cpuDmaCount = 0;
- int sw = 1+memoryWaitSeq[sm & 15];
- int dw = 1+memoryWaitSeq[dm & 15];
-
int totalTicks = 0;
if(transfer32) {
- if(!memory32[sm & 15])
- sw <<= 1;
- if(!memory32[dm & 15])
- dw <<= 1;
+ sw =1+memoryWaitSeq32[sm & 15];
+ dw =1+memoryWaitSeq32[dm & 15];
+ totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] +
+ memoryWaitSeq32[dm & 15];
+ }
+ else
+ {
+ sw = 1+memoryWaitSeq[sm & 15];
+ dw = 1+memoryWaitSeq[dm & 15];
+ totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] +
+ memoryWaitSeq[dm & 15];
}
-
- totalTicks = (sw+dw)*sc;
cpuDmaTicksToUpdate += totalTicks;
- cpuNextEvent = 0;
}
-bool CPUCheckDMA(int reason, int dmamask)
+void CPUCheckDMA(int reason, int dmamask)
{
- bool res = false;
- cpuDmaHack = 0;
// DMA 0
if((DM0CNT_H & 0x8000) && (dmamask & 1)) {
if(((DM0CNT_H >> 12) & 3) == reason) {
- res = true;
u32 sourceIncrement = 4;
u32 destIncrement = 4;
switch((DM0CNT_H >> 7) & 3) {
@@ -1980,9 +2346,11 @@ bool CPUCheckDMA(int reason, int dmamask)
DM0CNT_L ? DM0CNT_L : 0x4000,
DM0CNT_H & 0x0400);
cpuDmaHack = true;
+
if(DM0CNT_H & 0x4000) {
IF |= 0x0100;
UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
}
if(((DM0CNT_H >> 5) & 3) == 3) {
@@ -1999,7 +2367,6 @@ bool CPUCheckDMA(int reason, int dmamask)
// DMA 1
if((DM1CNT_H & 0x8000) && (dmamask & 2)) {
if(((DM1CNT_H >> 12) & 3) == reason) {
- res = true;
u32 sourceIncrement = 4;
u32 destIncrement = 4;
switch((DM1CNT_H >> 7) & 3) {
@@ -2048,10 +2415,11 @@ bool CPUCheckDMA(int reason, int dmamask)
DM1CNT_H & 0x0400);
}
cpuDmaHack = true;
-
+
if(DM1CNT_H & 0x4000) {
IF |= 0x0200;
UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
}
if(((DM1CNT_H >> 5) & 3) == 3) {
@@ -2068,7 +2436,6 @@ bool CPUCheckDMA(int reason, int dmamask)
// DMA 2
if((DM2CNT_H & 0x8000) && (dmamask & 4)) {
if(((DM2CNT_H >> 12) & 3) == reason) {
- res = true;
u32 sourceIncrement = 4;
u32 destIncrement = 4;
switch((DM2CNT_H >> 7) & 3) {
@@ -2118,9 +2485,11 @@ bool CPUCheckDMA(int reason, int dmamask)
DM2CNT_H & 0x0400);
}
cpuDmaHack = true;
+
if(DM2CNT_H & 0x4000) {
IF |= 0x0400;
UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
}
if(((DM2CNT_H >> 5) & 3) == 3) {
@@ -2137,7 +2506,6 @@ bool CPUCheckDMA(int reason, int dmamask)
// DMA 3
if((DM3CNT_H & 0x8000) && (dmamask & 8)) {
if(((DM3CNT_H >> 12) & 3) == reason) {
- res = true;
u32 sourceIncrement = 4;
u32 destIncrement = 4;
switch((DM3CNT_H >> 7) & 3) {
@@ -2176,6 +2544,7 @@ bool CPUCheckDMA(int reason, int dmamask)
if(DM3CNT_H & 0x4000) {
IF |= 0x0800;
UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
}
if(((DM3CNT_H >> 5) & 3) == 3) {
@@ -2188,8 +2557,6 @@ bool CPUCheckDMA(int reason, int dmamask)
}
}
}
- cpuDmaHack = false;
- return res;
}
void CPUUpdateRegister(u32 address, u16 value)
@@ -2197,15 +2564,27 @@ void CPUUpdateRegister(u32 address, u16 value)
switch(address) {
case 0x00:
{
+ if ((value & 7) >5)
+ DISPCNT = (value &7);
bool change = ((DISPCNT ^ value) & 0x80) ? true : false;
bool changeBG = ((DISPCNT ^ value) & 0x0F00) ? true : false;
+ u16 changeBGon = (((~DISPCNT) & value) & 0x0F00);
DISPCNT = (value & 0xFFF7);
UPDATE_REG(0x00, DISPCNT);
- layerEnable = layerSettings & value;
+
+ if (changeBGon)
+ {
+ layerEnableDelay=4;
+ layerEnable = layerSettings & value & (~changeBGon);
+ }
+ else
+ layerEnable = layerSettings & value;
+ // CPUUpdateTicks();
+
windowOn = (layerEnable & 0x6000) ? true : false;
if(change && !((value & 0x80))) {
if(!(DISPSTAT & 1)) {
- lcdTicks = 960;
+ lcdTicks = 1008;
// VCOUNT = 0;
// UPDATE_REG(0x06, VCOUNT);
DISPSTAT &= 0xFFFC;
@@ -2218,7 +2597,6 @@ void CPUUpdateRegister(u32 address, u16 value)
// we only care about changes in BG0-BG3
if(changeBG)
CPUUpdateRenderBuffers(false);
- // CPUUpdateTicks();
}
break;
case 0x04:
@@ -2566,89 +2944,41 @@ void CPUUpdateRegister(u32 address, u16 value)
}
}
break;
- case 0x100:
+ case 0x100:
timer0Reload = value;
interp_rate();
- break;
+ break;
case 0x102:
- timer0Ticks = timer0ClockReload = TIMER_TICKS[value & 3];
- if(!timer0On && (value & 0x80)) {
- // reload the counter
- TM0D = timer0Reload;
- if(timer0ClockReload == 1)
- timer0Ticks = 0x10000 - TM0D;
- UPDATE_REG(0x100, TM0D);
- int event = cpuTotalTicks + timer0Ticks;
- if(event < cpuNextEvent)
- cpuNextEvent = event;
- }
- timer0On = value & 0x80 ? true : false;
- TM0CNT = value & 0xC7;
- UPDATE_REG(0x102, TM0CNT);
- interp_rate();
- // CPUUpdateTicks();
+ timer0Value = value;
+ timerOnOffDelay|=1;
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x104:
timer1Reload = value;
interp_rate();
- break;
+ break;
case 0x106:
- timer1Ticks = timer1ClockReload = TIMER_TICKS[value & 3];
- if(!timer1On && (value & 0x80)) {
- // reload the counter
- TM1D = timer1Reload;
- if(timer1ClockReload == 1)
- timer1Ticks = 0x10000 - TM1D;
- UPDATE_REG(0x104, TM1D);
- int event = cpuTotalTicks + timer1Ticks;
- if(event < cpuNextEvent)
- cpuNextEvent = event;
- }
- timer1On = value & 0x80 ? true : false;
- TM1CNT = value & 0xC7;
- UPDATE_REG(0x106, TM1CNT);
- interp_rate();
- break;
+ timer1Value = value;
+ timerOnOffDelay|=2;
+ cpuNextEvent = cpuTotalTicks;
+ break;
case 0x108:
timer2Reload = value;
break;
case 0x10A:
- timer2Ticks = timer2ClockReload = TIMER_TICKS[value & 3];
- if(!timer2On && (value & 0x80)) {
- // reload the counter
- TM2D = timer2Reload;
- if(timer2ClockReload == 1)
- timer2Ticks = 0x10000 - TM2D;
- UPDATE_REG(0x108, TM2D);
- int event = cpuTotalTicks + timer2Ticks;
- if(event < cpuNextEvent)
- cpuNextEvent = event;
- }
- timer2On = value & 0x80 ? true : false;
- TM2CNT = value & 0xC7;
- UPDATE_REG(0x10A, TM2CNT);
+ timer2Value = value;
+ timerOnOffDelay|=4;
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x10C:
timer3Reload = value;
break;
case 0x10E:
- timer3Ticks = timer3ClockReload = TIMER_TICKS[value & 3];
- if(!timer3On && (value & 0x80)) {
- // reload the counter
- TM3D = timer3Reload;
- if(timer3ClockReload == 1)
- timer3Ticks = 0x10000 - TM3D;
- UPDATE_REG(0x10C, TM3D);
- int event = cpuTotalTicks + timer3Ticks;
- if(event < cpuNextEvent)
- cpuNextEvent = event;
- }
- timer3On = value & 0x80 ? true : false;
- TM3CNT = value & 0xC7;
- UPDATE_REG(0x10E, TM3CNT);
+ timer3Value = value;
+ timerOnOffDelay|=8;
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x128:
- StartLink(value); // Link
if(value & 0x80) {
value &= 0xff7f;
if(value & 1 && (value & 0x4000)) {
@@ -2660,14 +2990,6 @@ void CPUUpdateRegister(u32 address, u16 value)
}
UPDATE_REG(0x128, value);
break;
-/* Link
-------------------------------*/
- case 0x12a:
- if(lspeed)
- LinkSSend(value);
- UPDATE_REG(0x12a, value);
- break;
-/* --------------------------- */
case 0x130:
P1 |= (value & 0x3FF);
UPDATE_REG(0x130, P1);
@@ -2675,18 +2997,11 @@ void CPUUpdateRegister(u32 address, u16 value)
case 0x132:
UPDATE_REG(0x132, value & 0xC3FF);
break;
- case 0x134:
- StartGPLink(value);
- break;
- case 0x140:
- StartJOYLink(value);
- break;
case 0x200:
IE = value & 0x3FFF;
UPDATE_REG(0x200, IE);
- if((IME & 1) && (IF & IE) && armIrqEnable) {
- cpuNextEvent = 0;
- }
+ if ((IME & 1) && (IF & IE) && armIrqEnable)
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x202:
IF ^= (value & IF);
@@ -2694,54 +3009,54 @@ void CPUUpdateRegister(u32 address, u16 value)
break;
case 0x204:
{
- int i;
memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3];
if(!speedHack) {
- memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 7];
+ memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3];
memoryWaitSeq[0x08] = memoryWaitSeq[0x09] =
- gamepakWaitState0[(value >> 2) & 7];
+ gamepakWaitState0[(value >> 4) & 1];
- memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 7];
+ memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3];
memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] =
- gamepakWaitState1[(value >> 5) & 7];
+ gamepakWaitState1[(value >> 7) & 1];
- memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 7];
+ memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3];
memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] =
- gamepakWaitState2[(value >> 8) & 7];
+ gamepakWaitState2[(value >> 10) & 1];
} else {
- memoryWait[0x08] = memoryWait[0x09] = 4;
- memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 2;
+ memoryWait[0x08] = memoryWait[0x09] = 3;
+ memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1;
- memoryWait[0x0a] = memoryWait[0x0b] = 4;
- memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 4;
+ memoryWait[0x0a] = memoryWait[0x0b] = 3;
+ memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1;
- memoryWait[0x0c] = memoryWait[0x0d] = 4;
- memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 8;
+ memoryWait[0x0c] = memoryWait[0x0d] = 3;
+ memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1;
}
- for(i = 0; i < 16; i++) {
- memoryWaitFetch32[i] = memoryWait32[i] = memoryWait[i] *
- (memory32[i] ? 1 : 2);
- memoryWaitFetch[i] = memoryWait[i];
+
+ for(int i = 8; i < 15; i++) {
+ memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1;
+ memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1;
}
- memoryWaitFetch32[3] += 1;
- memoryWaitFetch32[2] += 3;
-
- if(value & 0x4000) {
- for(i = 8; i < 16; i++) {
- memoryWaitFetch32[i] = cpuMemoryWait32[i];
- memoryWaitFetch[i] = cpuMemoryWait[i];
- }
+
+ if((value & 0x4000) == 0x4000) {
+ busPrefetchEnable = true;
+ busPrefetch = false;
+ busPrefetchCount = 0;
+ } else {
+ busPrefetchEnable = false;
+ busPrefetch = false;
+ busPrefetchCount = 0;
}
- UPDATE_REG(0x204, value);
+ UPDATE_REG(0x204, value & 0x7FFF);
+
}
break;
case 0x208:
IME = value & 1;
UPDATE_REG(0x208, IME);
- if((IME & 1) && (IF & IE) && armIrqEnable) {
- cpuNextEvent = 0;
- }
+ if ((IME & 1) && (IF & IE) && armIrqEnable)
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x300:
if(value != 0)
@@ -2754,6 +3069,67 @@ void CPUUpdateRegister(u32 address, u16 value)
}
}
+void applyTimer ()
+{
+ if (timerOnOffDelay & 1)
+ {
+ timer0ClockReload = TIMER_TICKS[timer0Value & 3];
+ if(!timer0On && (timer0Value & 0x80)) {
+ // reload the counter
+ TM0D = timer0Reload;
+ timer0Ticks = (0x10000 - TM0D) << timer0ClockReload;
+ UPDATE_REG(0x100, TM0D);
+ }
+ timer0On = timer0Value & 0x80 ? true : false;
+ TM0CNT = timer0Value & 0xC7;
+ interp_rate();
+ UPDATE_REG(0x102, TM0CNT);
+ // CPUUpdateTicks();
+ }
+ if (timerOnOffDelay & 2)
+ {
+ timer1ClockReload = TIMER_TICKS[timer1Value & 3];
+ if(!timer1On && (timer1Value & 0x80)) {
+ // reload the counter
+ TM1D = timer1Reload;
+ timer1Ticks = (0x10000 - TM1D) << timer1ClockReload;
+ UPDATE_REG(0x104, TM1D);
+ }
+ timer1On = timer1Value & 0x80 ? true : false;
+ TM1CNT = timer1Value & 0xC7;
+ interp_rate();
+ UPDATE_REG(0x106, TM1CNT);
+ }
+ if (timerOnOffDelay & 4)
+ {
+ timer2ClockReload = TIMER_TICKS[timer2Value & 3];
+ if(!timer2On && (timer2Value & 0x80)) {
+ // reload the counter
+ TM2D = timer2Reload;
+ timer2Ticks = (0x10000 - TM2D) << timer2ClockReload;
+ UPDATE_REG(0x108, TM2D);
+ }
+ timer2On = timer2Value & 0x80 ? true : false;
+ TM2CNT = timer2Value & 0xC7;
+ UPDATE_REG(0x10A, TM2CNT);
+ }
+ if (timerOnOffDelay & 8)
+ {
+ timer3ClockReload = TIMER_TICKS[timer3Value & 3];
+ if(!timer3On && (timer3Value & 0x80)) {
+ // reload the counter
+ TM3D = timer3Reload;
+ timer3Ticks = (0x10000 - TM3D) << timer3ClockReload;
+ UPDATE_REG(0x10C, TM3D);
+ }
+ timer3On = timer3Value & 0x80 ? true : false;
+ TM3CNT = timer3Value & 0xC7;
+ UPDATE_REG(0x10E, TM3CNT);
+ }
+ cpuNextEvent = CPUUpdateTicks();
+ timerOnOffDelay = 0;
+}
+
void CPUWriteHalfWord(u32 address, u16 value)
{
#ifdef DEV_VERSION
@@ -2769,7 +3145,7 @@ void CPUWriteHalfWord(u32 address, u16 value)
switch(address >> 24) {
case 2:
-#ifdef SDL
+#ifdef BKPT_SUPPORT
if(*((u16 *)&freezeWorkRAM[address & 0x3FFFE]))
cheatsWriteHalfWord(address & 0x203FFFE,
value);
@@ -2778,7 +3154,7 @@ void CPUWriteHalfWord(u32 address, u16 value)
WRITE16LE(((u16 *)&workRAM[address & 0x3FFFE]),value);
break;
case 3:
-#ifdef SDL
+#ifdef BKPT_SUPPORT
if(*((u16 *)&freezeInternalRAM[address & 0x7ffe]))
cheatsWriteHalfWord(address & 0x3007ffe,
value);
@@ -2792,15 +3168,35 @@ void CPUWriteHalfWord(u32 address, u16 value)
else goto unwritable;
break;
case 5:
+#ifdef BKPT_SUPPORT
+ if(*((u16 *)&freezePRAM[address & 0x03fe]))
+ cheatsWriteHalfWord(address & 0x70003fe,
+ value);
+ else
+#endif
WRITE16LE(((u16 *)&paletteRAM[address & 0x3fe]), value);
break;
case 6:
- if(address & 0x10000)
- WRITE16LE(((u16 *)&vram[address & 0x17ffe]), value);
+ address = (address & 0x1fffe);
+ if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
+ return;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+#ifdef BKPT_SUPPORT
+ if(*((u16 *)&freezeVRAM[address]))
+ cheatsWriteHalfWord(address + 0x06000000,
+ value);
else
- WRITE16LE(((u16 *)&vram[address & 0x1fffe]), value);
+#endif
+ WRITE16LE(((u16 *)&vram[address]), value);
break;
case 7:
+#ifdef BKPT_SUPPORT
+ if(*((u16 *)&freezeOAM[address & 0x03fe]))
+ cheatsWriteHalfWord(address & 0x70003fe,
+ value);
+ else
+#endif
WRITE16LE(((u16 *)&oam[address & 0x3fe]), value);
break;
case 8:
@@ -2840,7 +3236,7 @@ void CPUWriteByte(u32 address, u8 b)
{
switch(address >> 24) {
case 2:
-#ifdef SDL
+#ifdef BKPT_SUPPORT
if(freezeWorkRAM[address & 0x3FFFF])
cheatsWriteByte(address & 0x203FFFF, b);
else
@@ -2848,7 +3244,7 @@ void CPUWriteByte(u32 address, u8 b)
workRAM[address & 0x3FFFF] = b;
break;
case 3:
-#ifdef SDL
+#ifdef BKPT_SUPPORT
if(freezeInternalRAM[address & 0x7fff])
cheatsWriteByte(address & 0x3007fff, b);
else
@@ -2863,7 +3259,7 @@ void CPUWriteByte(u32 address, u8 b)
stopState = true;
holdState = 1;
holdType = -1;
- cpuNextEvent = 0;
+ cpuNextEvent = cpuTotalTicks;
break;
case 0x60:
case 0x61:
@@ -2925,12 +3321,23 @@ void CPUWriteByte(u32 address, u8 b)
*((u16 *)&paletteRAM[address & 0x3FE]) = (b << 8) | b;
break;
case 6:
+ address = (address & 0x1fffe);
+ if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
+ return;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+
// no need to switch
// byte writes to OBJ VRAM are ignored
- if(!(address & 0x10000))
- // *((u16 *)&vram[address & 0x17FFE]) = (b << 8) | b;
- // else
- *((u16 *)&vram[address & 0xFFFE]) = (b << 8) | b;
+ if ((address) < objTilesAddress[((DISPCNT&7)+1)>>2])
+ {
+#ifdef BKPT_SUPPORT
+ if(freezeVRAM[address])
+ cheatsWriteByte(address + 0x06000000, b);
+ else
+#endif
+ *((u16 *)&vram[address]) = (b << 8) | b;
+ }
break;
case 7:
// no need to switch
@@ -2944,8 +3351,11 @@ void CPUWriteByte(u32 address, u8 b)
}
goto unwritable;
case 14:
- if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
- (*cpuSaveGameFunc)(address, b);
+ if (!(saveType == 5) && (!eepromInUse | cpuSramEnabled | cpuFlashEnabled)) {
+
+ //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) {
+
+ (*cpuSaveGameFunc)(address, b);
break;
}
// default
@@ -2962,6 +3372,7 @@ void CPUWriteByte(u32 address, u8 b)
break;
}
}
+
u8 cpuBitsSet[256];
u8 cpuLowestBitSet[256];
@@ -3077,7 +3488,7 @@ void CPUReset()
}
}
rtcReset();
- // clen registers
+ // clean registers
memset(®[0], 0, sizeof(reg));
// clean OAM
memset(oam, 0, 0x400);
@@ -3092,7 +3503,7 @@ void CPUReset()
DISPCNT = 0x0080;
DISPSTAT = 0x0000;
- VCOUNT = 0x0000;
+ VCOUNT = (useBios && !skipBios) ? 0 :0x007E;
BG0CNT = 0x0000;
BG1CNT = 0x0000;
BG2CNT = 0x0000;
@@ -3194,6 +3605,7 @@ void CPUReset()
armState = true;
C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
UPDATE_REG(0x00, DISPCNT);
+ UPDATE_REG(0x06, VCOUNT);
UPDATE_REG(0x20, BG2PA);
UPDATE_REG(0x26, BG2PD);
UPDATE_REG(0x30, BG3PA);
@@ -3218,7 +3630,7 @@ void CPUReset()
biosProtected[2] = 0x29;
biosProtected[3] = 0xe1;
- lcdTicks = 960;
+ lcdTicks = (useBios && !skipBios) ? 1008 : 208;
timer0On = false;
timer0Ticks = 0;
timer0Reload = 0;
@@ -3308,12 +3720,14 @@ void CPUReset()
cpuFlashEnabled = true;
cpuEEPROMEnabled = true;
cpuEEPROMSensorEnabled = false;
+ saveType = gbaSaveType = 0;
break;
case 1: // EEPROM
cpuSramEnabled = false;
cpuFlashEnabled = false;
cpuEEPROMEnabled = true;
cpuEEPROMSensorEnabled = false;
+ saveType = gbaSaveType = 3;
// EEPROM usage is automatically detected
break;
case 2: // SRAM
@@ -3322,6 +3736,7 @@ void CPUReset()
cpuEEPROMEnabled = false;
cpuEEPROMSensorEnabled = false;
cpuSaveGameFunc = sramDelayedWrite; // to insure we detect the write
+ saveType = gbaSaveType = 1;
break;
case 3: // FLASH
cpuSramEnabled = false;
@@ -3329,6 +3744,7 @@ void CPUReset()
cpuEEPROMEnabled = false;
cpuEEPROMSensorEnabled = false;
cpuSaveGameFunc = flashDelayedWrite; // to insure we detect the write
+ saveType = gbaSaveType = 2;
break;
case 4: // EEPROM+Sensor
cpuSramEnabled = false;
@@ -3336,6 +3752,7 @@ void CPUReset()
cpuEEPROMEnabled = true;
cpuEEPROMSensorEnabled = true;
// EEPROM usage is automatically detected
+ saveType = gbaSaveType = 3;
break;
case 5: // NONE
cpuSramEnabled = false;
@@ -3343,14 +3760,19 @@ void CPUReset()
cpuEEPROMEnabled = false;
cpuEEPROMSensorEnabled = false;
// no save at all
+ saveType = gbaSaveType = 5;
break;
}
+ ARM_PREFETCH;
+
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
- cpuDmaHack2 = false;
-
+ cpuDmaHack = false;
+
lastTime = systemGetClock();
+
+ SWITicks = 0;
}
void CPUInterrupt()
@@ -3367,6 +3789,7 @@ void CPUInterrupt()
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
// if(!holdState)
biosProtected[0] = 0x02;
@@ -3399,25 +3822,30 @@ extern void winlog(const char *, ...);
void CPULoop(int ticks)
{
int clockTicks;
- int totalTicks = 0;
int timerOverflow = 0;
- // variables used by the CPU core
- cpuNextEvent = CPUUpdateTicks();
- if(cpuNextEvent > ticks) {
- cpuNextEvent = ticks;
- }
-
- if(intState) {
- cpuNextEvent = 5;
- }
- if(cpuDmaHack2)
- cpuNextEvent = 1;
+ // variable used by the CPU core
+ cpuTotalTicks = 0;
cpuBreakLoop = false;
+ cpuNextEvent = CPUUpdateTicks();
+ if(cpuNextEvent > ticks)
+ cpuNextEvent = ticks;
+
+
for(;;) {
#ifndef FINAL_VERSION
if(systemDebug) {
if(systemDebug >= 10 && !holdState) {
CPUUpdateCPSR();
+#ifdef BKPT_SUPPORT
+ if (debugger_last)
+ {
+ sprintf(buffer, "R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n",
+ oldreg[0], oldreg[1], oldreg[2], oldreg[3], oldreg[4], oldreg[5],
+ oldreg[6], oldreg[7], oldreg[8], oldreg[9], oldreg[10], oldreg[11],
+ oldreg[12], oldreg[13], oldreg[14], oldreg[15], oldreg[16],
+ oldreg[17]);
+ }
+#endif
sprintf(buffer, "R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n",
reg[0].I, reg[1].I, reg[2].I, reg[3].I, reg[4].I, reg[5].I,
reg[6].I, reg[7].I, reg[8].I, reg[9].I, reg[10].I, reg[11].I,
@@ -3437,67 +3865,72 @@ void CPULoop(int ticks)
#endif
}
}
-#endif
+#endif /* FINAL_VERSION */
+
+ if(!holdState && !SWITicks) {
+
+ // Emulates the Cheat System (m) code
+ if((cheatsEnabled) && (mastercode) && (mastercode == armNextPC))
+ {
+ u32 joy = 0;
+ if(systemReadJoypads())
+ joy = systemReadJoypad(-1);
+ u32 ext = (joy >> 10);
+ cpuTotalTicks += cheatsCheckKeys(P1^0x3FF, ext);
+ }
+
+ if ((armNextPC & 0x0803FFFF) == 0x08020000)
+ busPrefetchCount=0x100;
- if(!holdState) {
if(armState) {
#include "arm-new.h"
} else {
#include "thumb.h"
}
- } else {
- clockTicks = lcdTicks;
+ } else
+ clockTicks = CPUUpdateTicks();
- if(soundTicks < clockTicks)
- clockTicks = soundTicks;
-
- if(timer0On && (timer0Ticks < clockTicks)) {
- clockTicks = timer0Ticks;
+ cpuTotalTicks += clockTicks;
+
+
+ if(cpuTotalTicks >= cpuNextEvent) {
+ int remainingTicks = cpuTotalTicks - cpuNextEvent;
+
+ if (SWITicks)
+ {
+ SWITicks-=clockTicks;
+ if (SWITicks<0)
+ SWITicks = 0;
}
- if(timer1On && !(TM1CNT & 4) && (timer1Ticks < clockTicks)) {
- clockTicks = timer1Ticks;
- }
- if(timer2On && !(TM2CNT & 4) && (timer2Ticks < clockTicks)) {
- clockTicks = timer2Ticks;
- }
- if(timer3On && !(TM3CNT & 4) && (timer3Ticks < clockTicks)) {
- clockTicks = timer3Ticks;
- }
-#ifdef PROFILING
- if(profilingTicksReload != 0) {
- if(profilingTicks < clockTicks) {
- clockTicks = profilingTicks;
- }
- }
-#endif
- // if((clockTicks+totalTicks) > cpuNextEvent) {
- // clockTicks = cpuNextEvent - totalTicks;
- // }
- }
- totalTicks += clockTicks;
- cpuTotalTicks = totalTicks;
- if(totalTicks >= cpuNextEvent) {
- cpuDmaHack2 = false;
- int remainingTicks = totalTicks - cpuNextEvent;
+
clockTicks = cpuNextEvent;
- int oldTotalTicks = totalTicks;
- cpuTotalTicks = totalTicks = 0;
-
+ cpuTotalTicks = 0;
+ cpuDmaHack = false;
+
updateLoop:
+
+ if (IRQTicks)
+ {
+ IRQTicks -= clockTicks;
+ if (IRQTicks<0)
+ IRQTicks = 0;
+ }
+
lcdTicks -= clockTicks;
+
if(lcdTicks <= 0) {
if(DISPSTAT & 1) { // V-BLANK
// if in V-Blank mode, keep computing...
if(DISPSTAT & 2) {
- lcdTicks += 960;
+ lcdTicks += 1008;
VCOUNT++;
UPDATE_REG(0x06, VCOUNT);
DISPSTAT &= 0xFFFD;
UPDATE_REG(0x04, DISPSTAT);
CPUCompareVCOUNT();
} else {
- lcdTicks += 272;
+ lcdTicks += 224;
DISPSTAT |= 2;
UPDATE_REG(0x04, DISPSTAT);
if(DISPSTAT & 16) {
@@ -3506,7 +3939,7 @@ void CPULoop(int ticks)
}
}
- if(VCOUNT >= 228) {
+ if(VCOUNT >= 228) { //Reaching last line
DISPSTAT &= 0xFFFC;
UPDATE_REG(0x04, DISPSTAT);
VCOUNT = 0;
@@ -3522,8 +3955,8 @@ void CPULoop(int ticks)
// if in H-Blank, leave it and move to drawing mode
VCOUNT++;
UPDATE_REG(0x06, VCOUNT);
-
- lcdTicks += (960);
+
+ lcdTicks += 1008;
DISPSTAT &= 0xFFFD;
if(VCOUNT == 160) {
count++;
@@ -3571,7 +4004,8 @@ void CPULoop(int ticks)
}
u32 ext = (joy >> 10);
- if(cheatsEnabled)
+ // If no (m) code is enabled, apply the cheats at each LCDline
+ if((cheatsEnabled) && (mastercode==0))
remainingTicks += cheatsCheckKeys(P1^0x3FF, ext);
speedup = (ext & 1) ? true : false;
capture = (ext & 2) ? true : false;
@@ -3581,7 +4015,7 @@ void CPULoop(int ticks)
systemScreenCapture(captureNumber);
}
capturePrevious = capture;
-
+
DISPSTAT |= 1;
DISPSTAT &= 0xFFFD;
UPDATE_REG(0x04, DISPSTAT);
@@ -3589,7 +4023,7 @@ void CPULoop(int ticks)
IF |= 1;
UPDATE_REG(0x202, IF);
}
- cpuDmaHack2 = CPUCheckDMA(1, 0x0f);
+ CPUCheckDMA(1, 0x0f);
if(frameCount >= framesToSkip) {
systemDrawScreen();
frameCount = 0;
@@ -3600,14 +4034,14 @@ void CPULoop(int ticks)
}
UPDATE_REG(0x04, DISPSTAT);
-
- CPUCompareVCOUNT();
+ CPUCompareVCOUNT();
+
} else {
- if(frameCount >= framesToSkip) {
- (*renderLine)();
-
+ if(frameCount >= framesToSkip)
+ {
+ (*renderLine)();
switch(systemColorDepth) {
- case 16:
+ case 16:
{
u16 *dest = (u16 *)pix + 242 * (VCOUNT+1);
for(int x = 0; x < 240;) {
@@ -3635,7 +4069,7 @@ void CPULoop(int ticks)
*dest++ = 0;
}
break;
- case 24:
+ case 24:
{
u8 *dest = (u8 *)pix + 240 * VCOUNT * 3;
for(int x = 0; x < 240;) {
@@ -3677,7 +4111,7 @@ void CPULoop(int ticks)
}
}
break;
- case 32:
+ case 32:
{
u32 *dest = (u32 *)pix + 241 * (VCOUNT+1);
for(int x = 0; x < 240; ) {
@@ -3685,7 +4119,7 @@ void CPULoop(int ticks)
*dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
*dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
*dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
-
+
*dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
*dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
*dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
@@ -3708,8 +4142,8 @@ void CPULoop(int ticks)
// entering H-Blank
DISPSTAT |= 2;
UPDATE_REG(0x04, DISPSTAT);
- lcdTicks += 272;
- cpuDmaHack2 = CPUCheckDMA(2, 0x0f);
+ lcdTicks += 224;
+ CPUCheckDMA(2, 0x0f);
if(DISPSTAT & 16) {
IF |= 2;
UPDATE_REG(0x202, IF);
@@ -3720,39 +4154,18 @@ void CPULoop(int ticks)
if(!stopState) {
if(timer0On) {
- if(timer0ClockReload == 1) {
- u32 tm0d = TM0D + clockTicks;
- if(tm0d > 0xffff) {
- tm0d += timer0Reload;
- timerOverflow |= 1;
- soundTimerOverflow(0);
- if(TM0CNT & 0x40) {
- IF |= 0x08;
- UPDATE_REG(0x202, IF);
- }
- }
- TM0D = tm0d;
- if(TM0D < timer0Reload)
- TM0D = timer0Reload;
- timer0Ticks = 0x10000 - TM0D;
- UPDATE_REG(0x100, TM0D);
- } else {
- timer0Ticks -= clockTicks;
- if(timer0Ticks <= 0) {
- timer0Ticks += timer0ClockReload;
- TM0D++;
- if(TM0D == 0) {
- TM0D = timer0Reload;
- timerOverflow |= 1;
- soundTimerOverflow(0);
- if(TM0CNT & 0x40) {
- IF |= 0x08;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x100, TM0D);
+ timer0Ticks -= clockTicks;
+ if(timer0Ticks <= 0) {
+ timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload;
+ timerOverflow |= 1;
+ soundTimerOverflow(0);
+ if(TM0CNT & 0x40) {
+ IF |= 0x08;
+ UPDATE_REG(0x202, IF);
}
}
+ TM0D = 0xFFFF - (timer0Ticks >> timer0ClockReload);
+ UPDATE_REG(0x100, TM0D);
}
if(timer1On) {
@@ -3771,40 +4184,18 @@ void CPULoop(int ticks)
UPDATE_REG(0x104, TM1D);
}
} else {
- if(timer1ClockReload == 1) {
- u32 tm1d = TM1D + clockTicks;
- if(tm1d > 0xffff) {
- tm1d += timer1Reload;
- timerOverflow |= 2;
- soundTimerOverflow(1);
- if(TM1CNT & 0x40) {
- IF |= 0x10;
- UPDATE_REG(0x202, IF);
- }
- }
- TM1D = tm1d;
- if(TM1D < timer1Reload)
- TM1D = timer1Reload;
- timer1Ticks = 0x10000 - TM1D;
- UPDATE_REG(0x104, TM1D);
- } else {
- timer1Ticks -= clockTicks;
- if(timer1Ticks <= 0) {
- timer1Ticks += timer1ClockReload;
- TM1D++;
-
- if(TM1D == 0) {
- TM1D = timer1Reload;
- timerOverflow |= 2;
- soundTimerOverflow(1);
- if(TM1CNT & 0x40) {
- IF |= 0x10;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x104, TM1D);
+ timer1Ticks -= clockTicks;
+ if(timer1Ticks <= 0) {
+ timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload;
+ timerOverflow |= 2;
+ soundTimerOverflow(1);
+ if(TM1CNT & 0x40) {
+ IF |= 0x10;
+ UPDATE_REG(0x202, IF);
}
}
+ TM1D = 0xFFFF - (timer1Ticks >> timer1ClockReload);
+ UPDATE_REG(0x104, TM1D);
}
}
@@ -3823,38 +4214,17 @@ void CPULoop(int ticks)
UPDATE_REG(0x108, TM2D);
}
} else {
- if(timer2ClockReload == 1) {
- u32 tm2d = TM2D + clockTicks;
- if(tm2d > 0xffff) {
- tm2d += timer2Reload;
- timerOverflow |= 4;
- if(TM2CNT & 0x40) {
- IF |= 0x20;
- UPDATE_REG(0x202, IF);
- }
- }
- TM2D = tm2d;
- if(TM2D < timer2Reload)
- TM2D = timer2Reload;
- timer2Ticks = 0x10000 - TM2D;
- UPDATE_REG(0x108, TM2D);
- } else {
- timer2Ticks -= clockTicks;
- if(timer2Ticks <= 0) {
- timer2Ticks += timer2ClockReload;
- TM2D++;
-
- if(TM2D == 0) {
- TM2D = timer2Reload;
- timerOverflow |= 4;
- if(TM2CNT & 0x40) {
- IF |= 0x20;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x108, TM2D);
+ timer2Ticks -= clockTicks;
+ if(timer2Ticks <= 0) {
+ timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload;
+ timerOverflow |= 4;
+ if(TM2CNT & 0x40) {
+ IF |= 0x20;
+ UPDATE_REG(0x202, IF);
}
}
+ TM2D = 0xFFFF - (timer2Ticks >> timer2ClockReload);
+ UPDATE_REG(0x108, TM2D);
}
}
@@ -3869,43 +4239,26 @@ void CPULoop(int ticks)
UPDATE_REG(0x202, IF);
}
}
- UPDATE_REG(0x10c, TM3D);
+ UPDATE_REG(0x10C, TM3D);
}
} else {
- if(timer3ClockReload == 1) {
- u32 tm3d = TM3D + clockTicks;
- if(tm3d > 0xffff) {
- tm3d += timer3Reload;
- if(TM3CNT & 0x40) {
- IF |= 0x40;
- UPDATE_REG(0x202, IF);
- }
- }
- TM3D = tm3d;
- if(TM3D < timer3Reload)
- TM3D = timer3Reload;
- timer3Ticks = 0x10000 - TM3D;
- UPDATE_REG(0x10C, TM3D);
- } else {
- timer3Ticks -= clockTicks;
- if(timer3Ticks <= 0) {
- timer3Ticks += timer3ClockReload;
- TM3D++;
-
- if(TM3D == 0) {
- TM3D = timer3Reload;
- if(TM3CNT & 0x40) {
- IF |= 0x40;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x10C, TM3D);
+ timer3Ticks -= clockTicks;
+ if(timer3Ticks <= 0) {
+ timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload;
+ if(TM3CNT & 0x40) {
+ IF |= 0x40;
+ UPDATE_REG(0x202, IF);
}
}
+ TM3D = 0xFFFF - (timer3Ticks >> timer3ClockReload);
+ UPDATE_REG(0x10C, TM3D);
}
}
}
- // we shouldn't be doing sound in stop state, but we lose synchronization
+
+ timerOverflow = 0;
+
+ // we shouldn't be doing sound in stop state, but we loose synchronization
// if sound is disabled, so in stop state, soundTick will just produce
// mute sound
soundTicks -= clockTicks;
@@ -3913,88 +4266,110 @@ void CPULoop(int ticks)
psoundTickfn();
soundTicks += SOUND_CLOCK_TICKS;
}
- timerOverflow = 0;
#ifdef PROFILING
profilingTicks -= clockTicks;
if(profilingTicks <= 0) {
profilingTicks += profilingTicksReload;
- if(profilBuffer && profilSize) {
- u16 *b = (u16 *)profilBuffer;
- int pc = ((reg[15].I - profilLowPC) * profilScale)/0x10000;
- if(pc >= 0 && pc < profilSize) {
+ if(profilSegment) {
+ profile_segment *seg = profilSegment;
+ do {
+ u16 *b = (u16 *)seg->sbuf;
+ int pc = ((reg[15].I - seg->s_lowpc) * seg->s_scale)/0x10000;
+ if(pc >= 0 && pc < seg->ssiz) {
b[pc]++;
+ break;
}
+
+ seg = seg->next;
+ } while(seg);
}
}
#endif
ticks -= clockTicks;
-
-
-/* Link
-----------------------------------*/
- LinkUpdate(clockTicks);
-/* ----------------------------- */
cpuNextEvent = CPUUpdateTicks();
if(cpuDmaTicksToUpdate > 0) {
- if(cpuDmaTicksToUpdate < cpuNextEvent)
- cpuNextEvent = cpuDmaTicksToUpdate;
- cpuDmaTicksToUpdate -= cpuNextEvent;
- clockTicks = cpuNextEvent;
+ if(cpuDmaTicksToUpdate > cpuNextEvent)
+ clockTicks = cpuNextEvent;
+ else
+ clockTicks = cpuDmaTicksToUpdate;
+ cpuDmaTicksToUpdate -= clockTicks;
if(cpuDmaTicksToUpdate < 0)
cpuDmaTicksToUpdate = 0;
+ cpuDmaHack = true;
goto updateLoop;
}
-
- if(cpuDmaHack2)
- cpuNextEvent = 1;
if(IF && (IME & 1) && armIrqEnable) {
int res = IF & IE;
if(stopState)
res &= 0x3080;
if(res) {
- if(intState) {
- CPUInterrupt();
- intState = false;
- if(holdState) {
+ if (intState)
+ {
+ if (!IRQTicks)
+ {
+ CPUInterrupt();
+ intState = false;
holdState = false;
stopState = false;
- }
- } else {
- if(!holdState) {
- intState = true;
- cpuNextEvent = 5;
- } else {
- CPUInterrupt();
- if(holdState) {
- holdState = false;
- stopState = false;
- }
+ holdType = 0;
}
}
+ else
+ {
+ if (!holdState)
+ {
+ intState = true;
+ IRQTicks=7;
+ if (cpuNextEvent> IRQTicks)
+ cpuNextEvent = IRQTicks;
+ }
+ else
+ {
+ CPUInterrupt();
+ holdState = false;
+ stopState = false;
+ holdType = 0;
+ }
+ }
+
+ // Stops the SWI Ticks emulation if an IRQ is executed
+ //(to avoid problems with nested IRQ/SWI)
+ if (SWITicks)
+ SWITicks = 0;
}
}
-
+
if(remainingTicks > 0) {
- if(remainingTicks < cpuNextEvent)
- cpuNextEvent = remainingTicks;
- remainingTicks -= cpuNextEvent;
- clockTicks = cpuNextEvent;
+ if(remainingTicks > cpuNextEvent)
+ clockTicks = cpuNextEvent;
+ else
+ clockTicks = remainingTicks;
+ remainingTicks -= clockTicks;
if(remainingTicks < 0)
remainingTicks = 0;
goto updateLoop;
}
-
+
+ if (timerOnOffDelay)
+ applyTimer();
+
+ if(cpuNextEvent > ticks)
+ cpuNextEvent = ticks;
+
if(ticks <= 0 || cpuBreakLoop)
break;
+
}
}
}
+
+
struct EmulatedSystem GBASystem = {
// emuMain
CPULoop,
@@ -4008,7 +4383,7 @@ struct EmulatedSystem GBASystem = {
CPUWriteBatteryFile,
// emuReadState
CPUReadState,
- // emuWriteState
+ // emuWriteState
CPUWriteState,
// emuReadMemState
CPUReadMemState,
diff --git a/src/GBA.h b/src/GBA.h
index d6b8fa39..a79603b2 100644
--- a/src/GBA.h
+++ b/src/GBA.h
@@ -1,147 +1,158 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_GBA_H
-#define VBA_GBA_H
-
-#include "System.h"
-
-#define SAVE_GAME_VERSION_1 1
-#define SAVE_GAME_VERSION_2 2
-#define SAVE_GAME_VERSION_3 3
-#define SAVE_GAME_VERSION_4 4
-#define SAVE_GAME_VERSION_5 5
-#define SAVE_GAME_VERSION_6 6
-#define SAVE_GAME_VERSION_7 7
-#define SAVE_GAME_VERSION_8 8
-#define SAVE_GAME_VERSION SAVE_GAME_VERSION_8
-
-typedef struct {
- u8 *address;
- u32 mask;
-} memoryMap;
-
-typedef union {
- struct {
-#ifdef WORDS_BIGENDIAN
- u8 B3;
- u8 B2;
- u8 B1;
- u8 B0;
-#else
- u8 B0;
- u8 B1;
- u8 B2;
- u8 B3;
-#endif
- } B;
- struct {
-#ifdef WORDS_BIGENDIAN
- u16 W1;
- u16 W0;
-#else
- u16 W0;
- u16 W1;
-#endif
- } W;
-#ifdef WORDS_BIGENDIAN
- volatile u32 I;
-#else
- u32 I;
-#endif
-} reg_pair;
-
-#ifndef NO_GBA_MAP
-extern memoryMap map[256];
-#endif
-
-extern reg_pair reg[45];
-extern u8 biosProtected[4];
-
-extern bool N_FLAG;
-extern bool Z_FLAG;
-extern bool C_FLAG;
-extern bool V_FLAG;
-extern bool armIrqEnable;
-extern bool armState;
-extern int armMode;
-extern void (*cpuSaveGameFunc)(u32,u8);
-
-extern u8 freezeWorkRAM[0x40000];
-extern u8 freezeInternalRAM[0x8000];
-extern bool CPUReadGSASnapshot(const char *);
-extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *);
-extern bool CPUWriteBatteryFile(const char *);
-extern bool CPUReadBatteryFile(const char *);
-extern bool CPUExportEepromFile(const char *);
-extern bool CPUImportEepromFile(const char *);
-extern bool CPUWritePNGFile(const char *);
-extern bool CPUWriteBMPFile(const char *);
-extern void CPUCleanUp();
-extern void CPUUpdateRender();
-extern bool CPUReadMemState(char *, int);
-extern bool CPUReadState(const char *);
-extern bool CPUWriteMemState(char *, int);
-extern bool CPUWriteState(const char *);
-extern int CPULoadRom(const char *);
-extern void CPUUpdateRegister(u32, u16);
-extern void CPUWriteHalfWord(u32, u16);
-extern void CPUWriteByte(u32, u8);
-extern void CPUInit(const char *,bool);
-extern void CPUReset();
-extern void CPULoop(int);
-extern bool CPUCheckDMA(int,int);
-extern bool CPUIsGBAImage(const char *);
-extern bool CPUIsZipFile(const char *);
-#ifdef PROFILING
-extern void cpuProfil(char *buffer, int, u32, int);
-extern void cpuEnableProfiling(int hz);
-#endif
-
-extern struct EmulatedSystem GBASystem;
-
-#define R13_IRQ 18
-#define R14_IRQ 19
-#define SPSR_IRQ 20
-#define R13_USR 26
-#define R14_USR 27
-#define R13_SVC 28
-#define R14_SVC 29
-#define SPSR_SVC 30
-#define R13_ABT 31
-#define R14_ABT 32
-#define SPSR_ABT 33
-#define R13_UND 34
-#define R14_UND 35
-#define SPSR_UND 36
-#define R8_FIQ 37
-#define R9_FIQ 38
-#define R10_FIQ 39
-#define R11_FIQ 40
-#define R12_FIQ 41
-#define R13_FIQ 42
-#define R14_FIQ 43
-#define SPSR_FIQ 44
-
-#include "Cheats.h"
-#include "Globals.h"
-#include "EEprom.h"
-#include "Flash.h"
-
-#endif //VBA_GBA_H
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_GBA_H
+#define VBA_GBA_H
+
+#include "System.h"
+
+#define SAVE_GAME_VERSION_1 1
+#define SAVE_GAME_VERSION_2 2
+#define SAVE_GAME_VERSION_3 3
+#define SAVE_GAME_VERSION_4 4
+#define SAVE_GAME_VERSION_5 5
+#define SAVE_GAME_VERSION_6 6
+#define SAVE_GAME_VERSION_7 7
+#define SAVE_GAME_VERSION_8 8
+#define SAVE_GAME_VERSION_9 9
+#define SAVE_GAME_VERSION SAVE_GAME_VERSION_9
+
+typedef struct {
+ u8 *address;
+ u32 mask;
+} memoryMap;
+
+typedef union {
+ struct {
+#ifdef WORDS_BIGENDIAN
+ u8 B3;
+ u8 B2;
+ u8 B1;
+ u8 B0;
+#else
+ u8 B0;
+ u8 B1;
+ u8 B2;
+ u8 B3;
+#endif
+ } B;
+ struct {
+#ifdef WORDS_BIGENDIAN
+ u16 W1;
+ u16 W0;
+#else
+ u16 W0;
+ u16 W1;
+#endif
+ } W;
+#ifdef WORDS_BIGENDIAN
+ volatile u32 I;
+#else
+ u32 I;
+#endif
+} reg_pair;
+
+#ifndef NO_GBA_MAP
+extern memoryMap map[256];
+#endif
+
+extern reg_pair reg[45];
+extern u8 biosProtected[4];
+
+extern bool N_FLAG;
+extern bool Z_FLAG;
+extern bool C_FLAG;
+extern bool V_FLAG;
+extern bool armIrqEnable;
+extern bool armState;
+extern int armMode;
+extern void (*cpuSaveGameFunc)(u32,u8);
+
+extern u8 freezeWorkRAM[0x40000];
+extern u8 freezeInternalRAM[0x8000];
+extern u8 freezeVRAM[0x18000];
+extern u8 freezeOAM[0x400];
+extern u8 freezePRAM[0x400];
+extern bool debugger_last;
+extern int oldreg[17];
+extern char oldbuffer[10];
+
+extern bool CPUReadGSASnapshot(const char *);
+extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *);
+extern bool CPUWriteBatteryFile(const char *);
+extern bool CPUReadBatteryFile(const char *);
+extern bool CPUExportEepromFile(const char *);
+extern bool CPUImportEepromFile(const char *);
+extern bool CPUWritePNGFile(const char *);
+extern bool CPUWriteBMPFile(const char *);
+extern void CPUCleanUp();
+extern void CPUUpdateRender();
+extern bool CPUReadMemState(char *, int);
+extern bool CPUReadState(const char *);
+extern bool CPUWriteMemState(char *, int);
+extern bool CPUWriteState(const char *);
+extern int CPULoadRom(const char *);
+extern void doMirroring(bool);
+extern void CPUUpdateRegister(u32, u16);
+extern void applyTimer ();
+extern void CPUWriteHalfWord(u32, u16);
+extern void CPUWriteByte(u32, u8);
+extern void CPUInit(const char *,bool);
+extern void CPUReset();
+extern void CPULoop(int);
+extern void CPUCheckDMA(int,int);
+extern bool CPUIsGBAImage(const char *);
+extern bool CPUIsZipFile(const char *);
+#ifdef PROFILING
+#include "prof/prof.h"
+extern void cpuProfil(profile_segment *seg);
+extern void cpuEnableProfiling(int hz);
+#endif
+
+extern struct EmulatedSystem GBASystem;
+
+#define R13_IRQ 18
+#define R14_IRQ 19
+#define SPSR_IRQ 20
+#define R13_USR 26
+#define R14_USR 27
+#define R13_SVC 28
+#define R14_SVC 29
+#define SPSR_SVC 30
+#define R13_ABT 31
+#define R14_ABT 32
+#define SPSR_ABT 33
+#define R13_UND 34
+#define R14_UND 35
+#define SPSR_UND 36
+#define R8_FIQ 37
+#define R9_FIQ 38
+#define R10_FIQ 39
+#define R11_FIQ 40
+#define R12_FIQ 41
+#define R13_FIQ 42
+#define R14_FIQ 43
+#define SPSR_FIQ 44
+
+#include "Cheats.h"
+#include "Globals.h"
+#include "EEprom.h"
+#include "Flash.h"
+
+#endif //VBA_GBA_H
diff --git a/src/GBAinline.h b/src/GBAinline.h
index 1c482c85..7221763c 100644
--- a/src/GBAinline.h
+++ b/src/GBAinline.h
@@ -1,427 +1,488 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_GBAinline_H
-#define VBA_GBAinline_H
-
-#include "System.h"
-#include "Port.h"
-#include "RTC.h"
-#include "Sound.h"
-
-extern bool cpuSramEnabled;
-extern bool cpuFlashEnabled;
-extern bool cpuEEPROMEnabled;
-extern bool cpuEEPROMSensorEnabled;
-extern bool cpuDmaHack;
-extern bool cpuDmaHack2;
-extern u32 cpuDmaLast;
-
-extern int lspeed;
-extern void LinkSStop(void);
-
-#define CPUReadByteQuick(addr) \
- map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
-
-#define CPUReadHalfWordQuick(addr) \
- READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-#define CPUReadMemoryQuick(addr) \
- READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-inline u32 CPUReadMemory(u32 address)
-{
-
-#ifdef DEV_VERSION
- if(address & 3) {
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned word read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
- }
-#endif
-
- u32 value;
- switch(address >> 24) {
- case 0:
- if(reg[15].I >> 24) {
- if(address < 0x4000) {
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal word read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
-
- value = READ32LE(((u32 *)&biosProtected));
- }
- else goto unreadable;
- } else
- value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
- break;
- case 2:
- value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
- break;
- case 3:
- value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
- break;
- case 4:
- if((address>=0x4000120||address<=0x4000126)&&lspeed)
- LinkSStop();
- if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
- if(ioReadable[(address & 0x3fc) + 2])
- value = soundRead32(address & 0x3fC);
- else
- value = soundRead16(address & 0x3fc);
- } else goto unreadable;
- break;
- case 5:
- value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
- break;
- case 6:
- value = READ32LE(((u32 *)&vram[address & 0x1fffc]));
- break;
- case 7:
- value = READ32LE(((u32 *)&oam[address & 0x3FC]));
- break;
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
- break;
- case 13:
- if(cpuEEPROMEnabled)
- // no need to swap this
- return eepromRead(address);
- goto unreadable;
- case 14:
- if(cpuFlashEnabled | cpuSramEnabled)
- // no need to swap this
- return flashRead(address);
- // default
- default:
- unreadable:
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal word read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
-
- if(cpuDmaHack || cpuDmaHack2) {
- value = cpuDmaLast;
- } else {
- if(armState) {
- value = CPUReadMemoryQuick(reg[15].I);
- } else {
- value = CPUReadHalfWordQuick(reg[15].I) |
- CPUReadHalfWordQuick(reg[15].I) << 16;
- }
- }
- }
-
- if(address & 3) {
-#ifdef C_CORE
- int shift = (address & 3) << 3;
- value = (value >> shift) | (value << (32 - shift));
-#else
-#ifdef __GNUC__
- asm("and $3, %%ecx;"
- "shl $3 ,%%ecx;"
- "ror %%cl, %0"
- : "=r" (value)
- : "r" (value), "c" (address));
-#else
- __asm {
- mov ecx, address;
- and ecx, 3;
- shl ecx, 3;
- ror [dword ptr value], cl;
- }
-#endif
-#endif
- }
- return value;
-}
-
-extern u32 myROM[];
-
-inline u32 CPUReadHalfWord(u32 address)
-{
-#ifdef DEV_VERSION
- if(address & 1) {
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
- }
-#endif
-
- u32 value;
-
- switch(address >> 24) {
- case 0:
- if (reg[15].I >> 24) {
- if(address < 0x4000) {
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal halfword read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- value = READ16LE(((u16 *)&biosProtected[address&2]));
- } else goto unreadable;
- } else
- value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
- break;
- case 2:
- value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
- break;
- case 3:
- value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
- break;
- case 4:
-if((address>=0x4000120||address<=0x4000126)&&lspeed)
- LinkSStop();
- if((address < 0x4000400) && ioReadable[address & 0x3fe])
- value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
- else goto unreadable;
- break;
- case 5:
- value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
- break;
- case 6:
- value = READ16LE(((u16 *)&vram[address & 0x1fffe]));
- break;
- case 7:
- value = READ16LE(((u16 *)&oam[address & 0x3fe]));
- break;
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
- value = rtcRead(address);
- else
- value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
- break;
- case 13:
- if(cpuEEPROMEnabled)
- // no need to swap this
- return eepromRead(address);
- goto unreadable;
- case 14:
- if(cpuFlashEnabled | cpuSramEnabled)
- // no need to swap this
- return flashRead(address);
- // default
- default:
- unreadable:
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal halfword read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- if(cpuDmaHack2 || cpuDmaHack) {
- value = cpuDmaLast & 0xFFFF;
- } else {
- if(armState) {
- value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
- } else {
- value = CPUReadHalfWordQuick(reg[15].I);
- }
- }
- break;
- }
-
- if(address & 1) {
- value = (value >> 8) | (value << 24);
- }
-
- return value;
-}
-
-inline u16 CPUReadHalfWordSigned(u32 address)
-{
- u16 value = CPUReadHalfWord(address);
- if((address & 1))
- value = (s8)value;
- return value;
-}
-
-inline u8 CPUReadByte(u32 address)
-{
- switch(address >> 24) {
- case 0:
- if (reg[15].I >> 24) {
- if(address < 0x4000) {
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal byte read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- return biosProtected[address & 3];
- } else goto unreadable;
- }
- return bios[address & 0x3FFF];
- case 2:
- return workRAM[address & 0x3FFFF];
- case 3:
- return internalRAM[address & 0x7fff];
- case 4:
- if((address>=0x4000120||address<=0x4000126)&&lspeed)
- LinkSStop();
- if((address < 0x4000400) && ioReadable[address & 0x3ff])
- return soundRead(address & 0x3ff);
- else goto unreadable;
- case 5:
- return paletteRAM[address & 0x3ff];
- case 6:
- return vram[address & 0x1ffff];
- case 7:
- return oam[address & 0x3ff];
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- return rom[address & 0x1FFFFFF];
- case 13:
- if(cpuEEPROMEnabled)
- return eepromRead(address);
- goto unreadable;
- case 14:
- if(cpuSramEnabled | cpuFlashEnabled)
- return flashRead(address);
- if(cpuEEPROMSensorEnabled) {
- switch(address & 0x00008f00) {
- case 0x8200:
- return systemGetSensorX() & 255;
- case 0x8300:
- return (systemGetSensorX() >> 8)|0x80;
- case 0x8400:
- return systemGetSensorY() & 255;
- case 0x8500:
- return systemGetSensorY() >> 8;
- }
- }
- // default
- default:
- unreadable:
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal byte read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- if(cpuDmaHack || cpuDmaHack2) {
- return cpuDmaLast & 0xFF;
- } else {
- if(armState) {
- return CPUReadByteQuick(reg[15].I+(address & 3));
- } else {
- return CPUReadByteQuick(reg[15].I+(address & 1));
- }
- }
- break;
- }
-}
-
-inline void CPUWriteMemory(u32 address, u32 value)
-{
-#ifdef DEV_VERSION
- if(address & 3) {
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaliagned word write: %08x to %08x from %08x\n",
- value,
- address,
- armMode ? armNextPC - 4 : armNextPC - 2);
- }
- }
-#endif
-
- switch(address >> 24) {
- case 0x02:
-#ifdef SDL
- if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
- cheatsWriteMemory(address & 0x203FFFC,
- value);
- else
-#endif
- WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
- break;
- case 0x03:
-#ifdef SDL
- if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
- cheatsWriteMemory(address & 0x3007FFC,
- value);
- else
-#endif
- WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
- break;
- case 0x04:
- if(address < 0x4000400) {
- CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
- CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
- } else goto unwritable;
- break;
- case 0x05:
- WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
- break;
- case 0x06:
- if(address & 0x10000)
- WRITE32LE(((u32 *)&vram[address & 0x17ffc]), value);
- else
- WRITE32LE(((u32 *)&vram[address & 0x1fffc]), value);
- break;
- case 0x07:
- WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
- break;
- case 0x0D:
- if(cpuEEPROMEnabled) {
- eepromWrite(address, value);
- break;
- }
- goto unwritable;
- case 0x0E:
- if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
- (*cpuSaveGameFunc)(address, (u8)value);
- break;
- }
- // default
- default:
- unwritable:
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
- log("Illegal word write: %08x to %08x from %08x\n",
- value,
- address,
- armMode ? armNextPC - 4 : armNextPC - 2);
- }
-#endif
- break;
- }
-}
-
-#endif //VBA_GBAinline_H
\ No newline at end of file
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_GBAinline_H
+#define VBA_GBAinline_H
+
+#include "System.h"
+#include "Port.h"
+#include "RTC.h"
+
+extern bool cpuSramEnabled;
+extern bool cpuFlashEnabled;
+extern bool cpuEEPROMEnabled;
+extern bool cpuEEPROMSensorEnabled;
+extern bool cpuDmaHack;
+extern u32 cpuDmaLast;
+extern bool timer0On;
+extern int timer0Ticks;
+extern int timer0ClockReload;
+extern bool timer1On;
+extern int timer1Ticks;
+extern int timer1ClockReload;
+extern bool timer2On;
+extern int timer2Ticks;
+extern int timer2ClockReload;
+extern bool timer3On;
+extern int timer3Ticks;
+extern int timer3ClockReload;
+extern int cpuTotalTicks;
+
+#define CPUReadByteQuick(addr) \
+ map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
+
+#define CPUReadHalfWordQuick(addr) \
+ READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
+
+#define CPUReadMemoryQuick(addr) \
+ READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
+
+static inline u32 CPUReadMemory(u32 address)
+{
+
+#ifdef DEV_VERSION
+ if(address & 3) {
+ if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
+ log("Unaligned word read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+ }
+#endif
+
+ u32 value;
+ switch(address >> 24) {
+ case 0:
+ if(reg[15].I >> 24) {
+ if(address < 0x4000) {
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_READ) {
+ log("Illegal word read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+
+ value = READ32LE(((u32 *)&biosProtected));
+ }
+ else goto unreadable;
+ } else
+ value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
+ break;
+ case 2:
+ value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
+ break;
+ case 3:
+ value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
+ break;
+ case 4:
+ if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
+ if(ioReadable[(address & 0x3fc) + 2])
+ value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
+ else
+ value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
+ } else goto unreadable;
+ break;
+ case 5:
+ value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
+ break;
+ case 6:
+ address = (address & 0x1fffc);
+ if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
+ {
+ value = 0;
+ break;
+ }
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ value = READ32LE(((u32 *)&vram[address]));
+ break;
+ case 7:
+ value = READ32LE(((u32 *)&oam[address & 0x3FC]));
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
+ break;
+ case 13:
+ if(cpuEEPROMEnabled)
+ // no need to swap this
+ return eepromRead(address);
+ goto unreadable;
+ case 14:
+ if(cpuFlashEnabled | cpuSramEnabled)
+ // no need to swap this
+ return flashRead(address);
+ // default
+ default:
+ unreadable:
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_READ) {
+ log("Illegal word read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+
+ if(cpuDmaHack) {
+ value = cpuDmaLast;
+ } else {
+ if(armState) {
+ value = CPUReadMemoryQuick(reg[15].I);
+ } else {
+ value = CPUReadHalfWordQuick(reg[15].I) |
+ CPUReadHalfWordQuick(reg[15].I) << 16;
+ }
+ }
+ }
+
+ if(address & 3) {
+#ifdef C_CORE
+ int shift = (address & 3) << 3;
+ value = (value >> shift) | (value << (32 - shift));
+#else
+#ifdef __GNUC__
+ asm("and $3, %%ecx;"
+ "shl $3 ,%%ecx;"
+ "ror %%cl, %0"
+ : "=r" (value)
+ : "r" (value), "c" (address));
+#else
+ __asm {
+ mov ecx, address;
+ and ecx, 3;
+ shl ecx, 3;
+ ror [dword ptr value], cl;
+ }
+#endif
+#endif
+ }
+ return value;
+}
+
+extern u32 myROM[];
+
+static inline u32 CPUReadHalfWord(u32 address)
+{
+#ifdef DEV_VERSION
+ if(address & 1) {
+ if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
+ log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+ }
+#endif
+
+ u32 value;
+
+ switch(address >> 24) {
+ case 0:
+ if (reg[15].I >> 24) {
+ if(address < 0x4000) {
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_READ) {
+ log("Illegal halfword read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+ value = READ16LE(((u16 *)&biosProtected[address&2]));
+ } else goto unreadable;
+ } else
+ value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
+ break;
+ case 2:
+ value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
+ break;
+ case 3:
+ value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
+ break;
+ case 4:
+ if((address < 0x4000400) && ioReadable[address & 0x3fe])
+ {
+ value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
+ if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
+ {
+ if (((address & 0x3fe) == 0x100) && timer0On)
+ value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
+ else
+ if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4))
+ value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
+ else
+ if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4))
+ value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
+ else
+ if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4))
+ value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
+ }
+ }
+ else goto unreadable;
+ break;
+ case 5:
+ value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
+ break;
+ case 6:
+ address = (address & 0x1fffe);
+ if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
+ {
+ value = 0;
+ break;
+ }
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ value = READ16LE(((u16 *)&vram[address]));
+ break;
+ case 7:
+ value = READ16LE(((u16 *)&oam[address & 0x3fe]));
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
+ value = rtcRead(address);
+ else
+ value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
+ break;
+ case 13:
+ if(cpuEEPROMEnabled)
+ // no need to swap this
+ return eepromRead(address);
+ goto unreadable;
+ case 14:
+ if(cpuFlashEnabled | cpuSramEnabled)
+ // no need to swap this
+ return flashRead(address);
+ // default
+ default:
+ unreadable:
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_READ) {
+ log("Illegal halfword read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+ if(cpuDmaHack) {
+ value = cpuDmaLast & 0xFFFF;
+ } else {
+ if(armState) {
+ value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
+ } else {
+ value = CPUReadHalfWordQuick(reg[15].I);
+ }
+ }
+ break;
+ }
+
+ if(address & 1) {
+ value = (value >> 8) | (value << 24);
+ }
+
+ return value;
+}
+
+static inline u16 CPUReadHalfWordSigned(u32 address)
+{
+ u16 value = CPUReadHalfWord(address);
+ if((address & 1))
+ value = (s8)value;
+ return value;
+}
+
+static inline u8 CPUReadByte(u32 address)
+{
+ switch(address >> 24) {
+ case 0:
+ if (reg[15].I >> 24) {
+ if(address < 0x4000) {
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_READ) {
+ log("Illegal byte read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+ return biosProtected[address & 3];
+ } else goto unreadable;
+ }
+ return bios[address & 0x3FFF];
+ case 2:
+ return workRAM[address & 0x3FFFF];
+ case 3:
+ return internalRAM[address & 0x7fff];
+ case 4:
+ if((address < 0x4000400) && ioReadable[address & 0x3ff])
+ return ioMem[address & 0x3ff];
+ else goto unreadable;
+ case 5:
+ return paletteRAM[address & 0x3ff];
+ case 6:
+ address = (address & 0x1ffff);
+ if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
+ return 0;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ return vram[address];
+ case 7:
+ return oam[address & 0x3ff];
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ return rom[address & 0x1FFFFFF];
+ case 13:
+ if(cpuEEPROMEnabled)
+ return eepromRead(address);
+ goto unreadable;
+ case 14:
+ if(cpuSramEnabled | cpuFlashEnabled)
+ return flashRead(address);
+ if(cpuEEPROMSensorEnabled) {
+ switch(address & 0x00008f00) {
+ case 0x8200:
+ return systemGetSensorX() & 255;
+ case 0x8300:
+ return (systemGetSensorX() >> 8)|0x80;
+ case 0x8400:
+ return systemGetSensorY() & 255;
+ case 0x8500:
+ return systemGetSensorY() >> 8;
+ }
+ }
+ // default
+ default:
+ unreadable:
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_READ) {
+ log("Illegal byte read: %08x at %08x\n", address, armMode ?
+ armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+ if(cpuDmaHack) {
+ return cpuDmaLast & 0xFF;
+ } else {
+ if(armState) {
+ return CPUReadByteQuick(reg[15].I+(address & 3));
+ } else {
+ return CPUReadByteQuick(reg[15].I+(address & 1));
+ }
+ }
+ break;
+ }
+}
+
+static inline void CPUWriteMemory(u32 address, u32 value)
+{
+
+#ifdef DEV_VERSION
+ if(address & 3) {
+ if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
+ log("Unaligned word write: %08x to %08x from %08x\n",
+ value,
+ address,
+ armMode ? armNextPC - 4 : armNextPC - 2);
+ }
+ }
+#endif
+
+ switch(address >> 24) {
+ case 0x02:
+#ifdef BKPT_SUPPORT
+ if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
+ cheatsWriteMemory(address & 0x203FFFC,
+ value);
+ else
+#endif
+ WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
+ break;
+ case 0x03:
+#ifdef BKPT_SUPPORT
+ if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
+ cheatsWriteMemory(address & 0x3007FFC,
+ value);
+ else
+#endif
+ WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
+ break;
+ case 0x04:
+ if(address < 0x4000400) {
+ CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
+ CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
+ } else goto unwritable;
+ break;
+ case 0x05:
+#ifdef BKPT_SUPPORT
+ if(*((u32 *)&freezePRAM[address & 0x3fc]))
+ cheatsWriteMemory(address & 0x70003FC,
+ value);
+ else
+#endif
+ WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
+ break;
+ case 0x06:
+ address = (address & 0x1fffc);
+ if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
+ return;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+
+#ifdef BKPT_SUPPORT
+ if(*((u32 *)&freezeVRAM[address]))
+ cheatsWriteMemory(address + 0x06000000, value);
+ else
+#endif
+
+ WRITE32LE(((u32 *)&vram[address]), value);
+ break;
+ case 0x07:
+#ifdef BKPT_SUPPORT
+ if(*((u32 *)&freezeOAM[address & 0x3fc]))
+ cheatsWriteMemory(address & 0x70003FC,
+ value);
+ else
+#endif
+ WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
+ break;
+ case 0x0D:
+ if(cpuEEPROMEnabled) {
+ eepromWrite(address, value);
+ break;
+ }
+ goto unwritable;
+ case 0x0E:
+ if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
+ (*cpuSaveGameFunc)(address, (u8)value);
+ break;
+ }
+ // default
+ default:
+ unwritable:
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
+ log("Illegal word write: %08x to %08x from %08x\n",
+ value,
+ address,
+ armMode ? armNextPC - 4 : armNextPC - 2);
+ }
+#endif
+ break;
+ }
+}
+
+#endif //VBA_GBAinline_H
diff --git a/src/Gfx.cpp b/src/Gfx.cpp
index 26c15691..7dc47ef4 100644
--- a/src/Gfx.cpp
+++ b/src/Gfx.cpp
@@ -22,7 +22,6 @@ int coeff[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
-
u32 line0[240];
u32 line1[240];
u32 line2[240];
@@ -32,6 +31,7 @@ u32 lineOBJWin[240];
u32 lineMix[240];
bool gfxInWin0[240];
bool gfxInWin1[240];
+int lineOBJpixleft[128];
int gfxBG2Changed = 0;
int gfxBG3Changed = 0;
diff --git a/src/Gfx.h b/src/Gfx.h
index 40abe485..2e9625bc 100644
--- a/src/Gfx.h
+++ b/src/Gfx.h
@@ -1,1581 +1,1654 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_GFX_H
-#define VBA_GFX_H
-
-#include "GBA.h"
-#include "Gfx.h"
-#include "Globals.h"
-
-#include "Port.h"
-
-//#define SPRITE_DEBUG
-
-void gfxDrawTextScreen(u16, u16, u16, u32 *);
-void gfxDrawRotScreen(u16,
- u16, u16,
- u16, u16,
- u16, u16,
- u16, u16,
- int&, int&,
- int,
- u32*);
-void gfxDrawRotScreen16Bit(u16,
- u16, u16,
- u16, u16,
- u16, u16,
- u16, u16,
- int&, int&,
- int,
- u32*);
-void gfxDrawRotScreen256(u16,
- u16, u16,
- u16, u16,
- u16, u16,
- u16, u16,
- int&, int&,
- int,
- u32*);
-void gfxDrawRotScreen16Bit160(u16,
- u16, u16,
- u16, u16,
- u16, u16,
- u16, u16,
- int&, int&,
- int,
- u32*);
-void gfxDrawSprites(u32 *);
-void gfxIncreaseBrightness(u32 *line, int coeff);
-void gfxDecreaseBrightness(u32 *line, int coeff);
-void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb);
-
-void mode0RenderLine();
-void mode0RenderLineNoWindow();
-void mode0RenderLineAll();
-
-void mode1RenderLine();
-void mode1RenderLineNoWindow();
-void mode1RenderLineAll();
-
-void mode2RenderLine();
-void mode2RenderLineNoWindow();
-void mode2RenderLineAll();
-
-void mode3RenderLine();
-void mode3RenderLineNoWindow();
-void mode3RenderLineAll();
-
-void mode4RenderLine();
-void mode4RenderLineNoWindow();
-void mode4RenderLineAll();
-
-void mode5RenderLine();
-void mode5RenderLineNoWindow();
-void mode5RenderLineAll();
-
-extern int coeff[32];
-extern u32 line0[240];
-extern u32 line1[240];
-extern u32 line2[240];
-extern u32 line3[240];
-extern u32 lineOBJ[240];
-extern u32 lineOBJWin[240];
-extern u32 lineMix[240];
-extern bool gfxInWin0[240];
-extern bool gfxInWin1[240];
-
-extern int gfxBG2Changed;
-extern int gfxBG3Changed;
-
-extern int gfxBG2X;
-extern int gfxBG2Y;
-extern int gfxBG2LastX;
-extern int gfxBG2LastY;
-extern int gfxBG3X;
-extern int gfxBG3Y;
-extern int gfxBG3LastX;
-extern int gfxBG3LastY;
-extern int gfxLastVCOUNT;
-
-inline void gfxClearArray(u32 *array)
-{
- for(int i = 0; i < 240; i++) {
- *array++ = 0x80000000;
- }
-}
-
-inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
- u32 *line)
-{
- u16 *palette = (u16 *)paletteRAM;
- u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
- u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
- u32 prio = ((control & 3)<<25) + 0x1000000;
- int sizeX = 256;
- int sizeY = 256;
- switch((control >> 14) & 3) {
- case 0:
- break;
- case 1:
- sizeX = 512;
- break;
- case 2:
- sizeY = 512;
- break;
- case 3:
- sizeX = 512;
- sizeY = 512;
- break;
- }
-
- int maskX = sizeX-1;
- int maskY = sizeY-1;
-
- bool mosaicOn = (control & 0x40) ? true : false;
-
- int xxx = hofs & maskX;
- int yyy = (vofs + VCOUNT) & maskY;
- int mosaicX = (MOSAIC & 0x000F)+1;
- int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
-
- if(mosaicOn) {
- if((VCOUNT % mosaicY) != 0) {
- mosaicY = (VCOUNT / mosaicY) * mosaicY;
- yyy = (vofs + mosaicY) & maskY;
- }
- }
-
- if(yyy > 255 && sizeY > 256) {
- yyy &= 255;
- screenBase += 0x400;
- if(sizeX > 256)
- screenBase += 0x400;
- }
-
- int yshift = ((yyy>>3)<<5);
- if((control) & 0x80) {
- u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
- for(int x = 0; x < 240; x++) {
- u16 data = READ16LE(screenSource);
-
- int tile = data & 0x3FF;
- int tileX = (xxx & 7);
- int tileY = yyy & 7;
-
- if(data & 0x0400)
- tileX = 7 - tileX;
- if(data & 0x0800)
- tileY = 7 - tileY;
-
- u8 color = charBase[tile * 64 + tileY * 8 + tileX];
-
- line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
-
- if(data & 0x0400) {
- if(tileX == 0)
- screenSource++;
- } else if(tileX == 7)
- screenSource++;
- xxx++;
- if(xxx == 256) {
- if(sizeX > 256)
- screenSource = screenBase + 0x400 + yshift;
- else {
- screenSource = screenBase + yshift;
- xxx = 0;
- }
- } else if(xxx >= sizeX) {
- xxx = 0;
- screenSource = screenBase + yshift;
- }
- }
- } else {
- u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
- yshift;
- for(int x = 0; x < 240; x++) {
- u16 data = READ16LE(screenSource);
-
- int tile = data & 0x3FF;
- int tileX = (xxx & 7);
- int tileY = yyy & 7;
-
- if(data & 0x0400)
- tileX = 7 - tileX;
- if(data & 0x0800)
- tileY = 7 - tileY;
-
- u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
-
- if(tileX & 1) {
- color = (color >> 4);
- } else {
- color &= 0x0F;
- }
-
- int pal = (READ16LE(screenSource)>>8) & 0xF0;
- line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
-
- if(data & 0x0400) {
- if(tileX == 0)
- screenSource++;
- } else if(tileX == 7)
- screenSource++;
- xxx++;
- if(xxx == 256) {
- if(sizeX > 256)
- screenSource = screenBase + 0x400 + yshift;
- else {
- screenSource = screenBase + yshift;
- xxx = 0;
- }
- } else if(xxx >= sizeX) {
- xxx = 0;
- screenSource = screenBase + yshift;
- }
- }
- }
- if(mosaicOn) {
- if(mosaicX > 1) {
- int m = 1;
- for(int i = 0; i < 239; i++) {
- line[i+1] = line[i];
- m++;
- if(m == mosaicX) {
- m = 1;
- i++;
- }
- }
- }
- }
-}
-
-inline void gfxDrawRotScreen(u16 control,
- u16 x_l, u16 x_h,
- u16 y_l, u16 y_h,
- u16 pa, u16 pb,
- u16 pc, u16 pd,
- int& currentX, int& currentY,
- int changed,
- u32 *line)
-{
- u16 *palette = (u16 *)paletteRAM;
- u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
- u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
- int prio = ((control & 3) << 25) + 0x1000000;
-
- int sizeX = 128;
- int sizeY = 128;
- switch((control >> 14) & 3) {
- case 0:
- break;
- case 1:
- sizeX = sizeY = 256;
- break;
- case 2:
- sizeX = sizeY = 512;
- break;
- case 3:
- sizeX = sizeY = 1024;
- break;
- }
-
- int dx = pa & 0x7FFF;
- if(pa & 0x8000)
- dx |= 0xFFFF8000;
- int dmx = pb & 0x7FFF;
- if(pb & 0x8000)
- dmx |= 0xFFFF8000;
- int dy = pc & 0x7FFF;
- if(pc & 0x8000)
- dy |= 0xFFFF8000;
- int dmy = pd & 0x7FFFF;
- if(pd & 0x8000)
- dmy |= 0xFFFF8000;
-
- if(VCOUNT == 0)
- changed = 3;
-
- if(changed & 1) {
- currentX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- currentX |= 0xF8000000;
- } else {
- currentX += dmx;
- }
-
- if(changed & 2) {
- currentY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- currentY |= 0xF8000000;
- } else {
- currentY += dmy;
- }
-
- int realX = currentX;
- int realY = currentY;
-
- if(control & 0x40) {
- int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
- int y = (VCOUNT % mosaicY);
- realX -= y*dmx;
- realY -= y*dmy;
- }
-
- int xxx = (realX >> 8);
- int yyy = (realY >> 8);
-
- if(control & 0x2000) {
- xxx %= sizeX;
- yyy %= sizeY;
- if(xxx < 0)
- xxx += sizeX;
- if(yyy < 0)
- yyy += sizeY;
- }
-
- if(control & 0x80) {
- for(int x = 0; x < 240; x++) {
- if(xxx < 0 ||
- yyy < 0 ||
- xxx >= sizeX ||
- yyy >= sizeY) {
- line[x] = 0x80000000;
- } else {
- int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
-
- int tileX = (xxx & 7);
- int tileY = yyy & 7;
-
- u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
-
- line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
- }
- realX += dx;
- realY += dy;
-
- xxx = (realX >> 8);
- yyy = (realY >> 8);
-
- if(control & 0x2000) {
- xxx %= sizeX;
- yyy %= sizeY;
- if(xxx < 0)
- xxx += sizeX;
- if(yyy < 0)
- yyy += sizeY;
- }
- }
- } else {
- for(int x = 0; x < 240; x++) {
- if(xxx < 0 ||
- yyy < 0 ||
- xxx >= sizeX ||
- yyy >= sizeY) {
- line[x] = 0x80000000;
- } else {
- int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
-
- int tileX = (xxx & 7);
- int tileY = yyy & 7;
-
- u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
-
- line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
- }
- realX += dx;
- realY += dy;
-
- xxx = (realX >> 8);
- yyy = (realY >> 8);
-
- if(control & 0x2000) {
- xxx %= sizeX;
- yyy %= sizeY;
- if(xxx < 0)
- xxx += sizeX;
- if(yyy < 0)
- yyy += sizeY;
- }
- }
- }
-
- if(control & 0x40) {
- int mosaicX = (MOSAIC & 0xF) + 1;
- if(mosaicX > 1) {
- int m = 1;
- for(int i = 0; i < 239; i++) {
- line[i+1] = line[i];
- m++;
- if(m == mosaicX) {
- m = 1;
- i++;
- }
- }
- }
- }
-}
-
-inline void gfxDrawRotScreen16Bit(u16 control,
- u16 x_l, u16 x_h,
- u16 y_l, u16 y_h,
- u16 pa, u16 pb,
- u16 pc, u16 pd,
- int& currentX, int& currentY,
- int changed,
- u32 *line)
-{
- u16 *screenBase = (u16 *)&vram[0];
- int prio = ((control & 3) << 25) + 0x1000000;
- int sizeX = 240;
- int sizeY = 160;
-
- int startX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- startX |= 0xF8000000;
- int startY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- startY |= 0xF8000000;
-
- int dx = pa & 0x7FFF;
- if(pa & 0x8000)
- dx |= 0xFFFF8000;
- int dmx = pb & 0x7FFF;
- if(pb & 0x8000)
- dmx |= 0xFFFF8000;
- int dy = pc & 0x7FFF;
- if(pc & 0x8000)
- dy |= 0xFFFF8000;
- int dmy = pd & 0x7FFFF;
- if(pd & 0x8000)
- dmy |= 0xFFFF8000;
-
- if(VCOUNT == 0)
- changed = 3;
-
- if(changed & 1) {
- currentX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- currentX |= 0xF8000000;
- } else
- currentX += dmx;
-
- if(changed & 2) {
- currentY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- currentY |= 0xF8000000;
- } else {
- currentY += dmy;
- }
-
- int realX = currentX;
- int realY = currentY;
-
- if(control & 0x40) {
- int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
- int y = (VCOUNT % mosaicY);
- realX -= y*dmx;
- realY -= y*dmy;
- }
-
- int xxx = (realX >> 8);
- int yyy = (realY >> 8);
-
- for(int x = 0; x < 240; x++) {
- if(xxx < 0 ||
- yyy < 0 ||
- xxx >= sizeX ||
- yyy >= sizeY) {
- line[x] = 0x80000000;
- } else {
- line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
- }
- realX += dx;
- realY += dy;
-
- xxx = (realX >> 8);
- yyy = (realY >> 8);
- }
-
- if(control & 0x40) {
- int mosaicX = (MOSAIC & 0xF) + 1;
- if(mosaicX > 1) {
- int m = 1;
- for(int i = 0; i < 239; i++) {
- line[i+1] = line[i];
- m++;
- if(m == mosaicX) {
- m = 1;
- i++;
- }
- }
- }
- }
-}
-
-inline void gfxDrawRotScreen256(u16 control,
- u16 x_l, u16 x_h,
- u16 y_l, u16 y_h,
- u16 pa, u16 pb,
- u16 pc, u16 pd,
- int ¤tX, int& currentY,
- int changed,
- u32 *line)
-{
- u16 *palette = (u16 *)paletteRAM;
- u8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000];
- int prio = ((control & 3) << 25) + 0x1000000;
- int sizeX = 240;
- int sizeY = 160;
-
- int startX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- startX |= 0xF8000000;
- int startY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- startY |= 0xF8000000;
-
- int dx = pa & 0x7FFF;
- if(pa & 0x8000)
- dx |= 0xFFFF8000;
- int dmx = pb & 0x7FFF;
- if(pb & 0x8000)
- dmx |= 0xFFFF8000;
- int dy = pc & 0x7FFF;
- if(pc & 0x8000)
- dy |= 0xFFFF8000;
- int dmy = pd & 0x7FFFF;
- if(pd & 0x8000)
- dmy |= 0xFFFF8000;
-
- if(VCOUNT == 0)
- changed = 3;
-
- if(changed & 1) {
- currentX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- currentX |= 0xF8000000;
- } else {
- currentX += dmx;
- }
-
- if(changed & 2) {
- currentY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- currentY |= 0xF8000000;
- } else {
- currentY += dmy;
- }
-
- int realX = currentX;
- int realY = currentY;
-
- if(control & 0x40) {
- int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
- int y = (VCOUNT / mosaicY) * mosaicY;
- realX = startX + y*dmx;
- realY = startY + y*dmy;
- }
-
- int xxx = (realX >> 8);
- int yyy = (realY >> 8);
-
- for(int x = 0; x < 240; x++) {
- if(xxx < 0 ||
- yyy < 0 ||
- xxx >= sizeX ||
- yyy >= sizeY) {
- line[x] = 0x80000000;
- } else {
- u8 color = screenBase[yyy * 240 + xxx];
-
- line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
- }
- realX += dx;
- realY += dy;
-
- xxx = (realX >> 8);
- yyy = (realY >> 8);
- }
-
- if(control & 0x40) {
- int mosaicX = (MOSAIC & 0xF) + 1;
- if(mosaicX > 1) {
- int m = 1;
- for(int i = 0; i < 239; i++) {
- line[i+1] = line[i];
- m++;
- if(m == mosaicX) {
- m = 1;
- i++;
- }
- }
- }
- }
-}
-
-inline void gfxDrawRotScreen16Bit160(u16 control,
- u16 x_l, u16 x_h,
- u16 y_l, u16 y_h,
- u16 pa, u16 pb,
- u16 pc, u16 pd,
- int& currentX, int& currentY,
- int changed,
- u32 *line)
-{
- u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] :
- (u16 *)&vram[0];
- int prio = ((control & 3) << 25) + 0x1000000;
- int sizeX = 160;
- int sizeY = 128;
-
- int startX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- startX |= 0xF8000000;
- int startY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- startY |= 0xF8000000;
-
- int dx = pa & 0x7FFF;
- if(pa & 0x8000)
- dx |= 0xFFFF8000;
- int dmx = pb & 0x7FFF;
- if(pb & 0x8000)
- dmx |= 0xFFFF8000;
- int dy = pc & 0x7FFF;
- if(pc & 0x8000)
- dy |= 0xFFFF8000;
- int dmy = pd & 0x7FFFF;
- if(pd & 0x8000)
- dmy |= 0xFFFF8000;
-
- if(VCOUNT == 0)
- changed = 3;
-
- if(changed & 1) {
- currentX = (x_l) | ((x_h & 0x07FF)<<16);
- if(x_h & 0x0800)
- currentX |= 0xF8000000;
- } else {
- currentX += dmx;
- }
-
- if(changed & 2) {
- currentY = (y_l) | ((y_h & 0x07FF)<<16);
- if(y_h & 0x0800)
- currentY |= 0xF8000000;
- } else {
- currentY += dmy;
- }
-
- int realX = currentX;
- int realY = currentY;
-
- if(control & 0x40) {
- int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
- int y = (VCOUNT / mosaicY) * mosaicY;
- realX = startX + y*dmx;
- realY = startY + y*dmy;
- }
-
- int xxx = (realX >> 8);
- int yyy = (realY >> 8);
-
- for(int x = 0; x < 240; x++) {
- if(xxx < 0 ||
- yyy < 0 ||
- xxx >= sizeX ||
- yyy >= sizeY) {
- line[x] = 0x80000000;
- } else {
- line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
- }
- realX += dx;
- realY += dy;
-
- xxx = (realX >> 8);
- yyy = (realY >> 8);
- }
-
- if(control & 0x40) {
- int mosaicX = (MOSAIC & 0xF) + 1;
- if(mosaicX > 1) {
- int m = 1;
- for(int i = 0; i < 239; i++) {
- line[i+1] = line[i];
- m++;
- if(m == mosaicX) {
- m = 1;
- i++;
- }
- }
- }
- }
-}
-
-inline void gfxDrawSprites(u32 *lineOBJ)
-{
- int m=0;
- gfxClearArray(lineOBJ);
- if(layerEnable & 0x1000) {
- u16 *sprites = (u16 *)oam;
- u16 *spritePalette = &((u16 *)paletteRAM)[256];
- int mosaicY = ((MOSAIC & 0xF000)>>12) + 1;
- int mosaicX = ((MOSAIC & 0xF00)>>8) + 1;
- for(int x = 0; x < 128 ; x++) {
- u16 a0 = READ16LE(sprites++);
- u16 a1 = READ16LE(sprites++);
- u16 a2 = READ16LE(sprites++);
- sprites++;
-
- // ignore OBJ-WIN
- if((a0 & 0x0c00) == 0x0800)
- continue;
-
- int sizeY = 8;
- int sizeX = 8;
-
- switch(((a0 >>12) & 0x0c)|(a1>>14)) {
- case 0:
- break;
- case 1:
- sizeX = sizeY = 16;
- break;
- case 2:
- sizeX = sizeY = 32;
- break;
- case 3:
- sizeX = sizeY = 64;
- break;
- case 4:
- sizeX = 16;
- break;
- case 5:
- sizeX = 32;
- break;
- case 6:
- sizeX = 32;
- sizeY = 16;
- break;
- case 7:
- sizeX = 64;
- sizeY = 32;
- break;
- case 8:
- sizeY = 16;
- break;
- case 9:
- sizeY = 32;
- break;
- case 10:
- sizeX = 16;
- sizeY = 32;
- break;
- case 11:
- sizeX = 32;
- sizeY = 64;
- break;
- default:
- continue;
- }
-
-#ifdef SPRITE_DEBUG
- int maskX = sizeX-1;
- int maskY = sizeY-1;
-#endif
-
- int sy = (a0 & 255);
-
- if(sy > 160)
- sy -= 256;
-
- if(a0 & 0x0100) {
- int fieldX = sizeX;
- int fieldY = sizeY;
- if(a0 & 0x0200) {
- fieldX <<= 1;
- fieldY <<= 1;
- }
-
- int t = VCOUNT - sy;
- if((t >= 0) && (t < fieldY)) {
- int sx = (a1 & 0x1FF);
- if((sx < 240) || (((sx + fieldX) & 511) < 240)) {
- // int t2 = t - (fieldY >> 1);
- int rot = (a1 >> 9) & 0x1F;
- u16 *OAM = (u16 *)oam;
- int dx = READ16LE(&OAM[3 + (rot << 4)]);
- if(dx & 0x8000)
- dx |= 0xFFFF8000;
- int dmx = READ16LE(&OAM[7 + (rot << 4)]);
- if(dmx & 0x8000)
- dmx |= 0xFFFF8000;
- int dy = READ16LE(&OAM[11 + (rot << 4)]);
- if(dy & 0x8000)
- dy |= 0xFFFF8000;
- int dmy = READ16LE(&OAM[15 + (rot << 4)]);
- if(dmy & 0x8000)
- dmy |= 0xFFFF8000;
-
- if(a0 & 0x1000) {
- t -= (t % mosaicY);
- }
-
- int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
- + t * dmx;
- int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
- + t * dmy;
-
- u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
-
- if(a0 & 0x2000) {
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
- int inc = 32;
- if(DISPCNT & 0x40)
- inc = sizeX >> 2;
- else
- c &= 0x3FE;
- for(int x = 0; x < fieldX; x++) {
- int xxx = realX >> 8;
- int yyy = realY >> 8;
-
- if(xxx < 0 || xxx >= sizeX ||
- yyy < 0 || yyy >= sizeY ||
- sx >= 240);
- else {
- u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
- + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
- (xxx & 7))&0x7FFF)];
- if ((color==0) && (((prio >> 25)&3) <
- ((lineOBJ[sx]>>25)&3))) {
- lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
- lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- }
-
- if (a0 & 0x1000) {
- m++;
- if (m==mosaicX)
- m=0;
- }
-#ifdef SPRITE_DEBUG
- if(t == 0 || t == maskY || x == 0 || x == maskX)
- lineOBJ[sx] = 0x001F;
-#endif
- }
- sx = (sx+1)&511;;
- realX += dx;
- realY += dy;
- }
- } else {
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
-
- int inc = 32;
- if(DISPCNT & 0x40)
- inc = sizeX >> 3;
- int palette = (a2 >> 8) & 0xF0;
- for(int x = 0; x < fieldX; x++) {
- int xxx = realX >> 8;
- int yyy = realY >> 8;
- if(xxx < 0 || xxx >= sizeX ||
- yyy < 0 || yyy >= sizeY ||
- sx >= 240);
- else {
- u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
- + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
- ((xxx & 7)>>1))&0x7FFF)];
- if(xxx & 1)
- color >>= 4;
- else
- color &= 0x0F;
-
- if ((color==0) && (((prio >> 25)&3) <
- ((lineOBJ[sx]>>25)&3))) {
- lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
- lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- }
- }
- if((a0 & 0x1000) && m) {
- m++;
- if (m==mosaicX)
- m=0;
- }
-
-#ifdef SPRITE_DEBUG
- if(t == 0 || t == maskY || x == 0 || x == maskX)
- lineOBJ[sx] = 0x001F;
-#endif
- sx = (sx+1)&511;;
- realX += dx;
- realY += dy;
-
- }
- }
- }
- }
- } else {
- int t = VCOUNT - sy;
- if((t >= 0) && (t < sizeY)) {
- int sx = (a1 & 0x1FF);
- if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) {
- if(a0 & 0x2000) {
- if(a1 & 0x2000)
- t = sizeY - t - 1;
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
-
- int inc = 32;
- if(DISPCNT & 0x40) {
- inc = sizeX >> 2;
- } else {
- c &= 0x3FE;
- }
- int xxx = 0;
- if(a1 & 0x1000)
- xxx = sizeX-1;
-
- if(a0 & 0x1000) {
- t -= (t % mosaicY);
- }
-
- int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
- + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
-
- if(a1 & 0x1000)
- xxx = 7;
- u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
-
- for(int xx = 0; xx < sizeX; xx++) {
- if(sx < 240) {
- u8 color = vram[address];
- if ((color==0) && (((prio >> 25)&3) <
- ((lineOBJ[sx]>>25)&3))) {
- lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
- lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- }
-
- if (a0 & 0x1000) {
- m++;
- if (m==mosaicX)
- m=0;
- }
-
-#ifdef SPRITE_DEBUG
- if(t == 0 || t == maskY || xx == 0 || xx == maskX)
- lineOBJ[sx] = 0x001F;
-#endif
- }
-
- sx = (sx+1) & 511;
- if(a1 & 0x1000) {
- xxx--;
- address--;
- if(xxx == -1) {
- address -= 56;
- xxx = 7;
- }
- if(address < 0x10000)
- address += 0x8000;
- } else {
- xxx++;
- address++;
- if(xxx == 8) {
- address += 56;
- xxx = 0;
- }
- if(address > 0x17fff)
- address -= 0x8000;
- }
- }
- } else {
- if(a1 & 0x2000)
- t = sizeY - t - 1;
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
-
- int inc = 32;
- if(DISPCNT & 0x40) {
- inc = sizeX >> 3;
- }
- int xxx = 0;
- if(a1 & 0x1000)
- xxx = sizeX - 1;
-
- if(a0 & 0x1000) {
- t -= (t % mosaicY);
- }
-
- int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
- + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
- u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
- int palette = (a2 >> 8) & 0xF0;
- if(a1 & 0x1000) {
- xxx = 7;
- for(int xx = sizeX - 1; xx >= 0; xx--) {
- if(sx < 240) {
- u8 color = vram[address];
- if(xx & 1) {
- color = (color >> 4);
- } else
- color &= 0x0F;
-
- if ((color==0) && (((prio >> 25)&3) <
- ((lineOBJ[sx]>>25)&3))) {
- lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
- lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- }
- }
- if (a0 & 0x1000) {
- m++;
- if (m==mosaicX)
- m=0;
- }
-#ifdef SPRITE_DEBUG
- if(t == 0 || t == maskY || xx == 0 || xx == maskX)
- lineOBJ[sx] = 0x001F;
-#endif
- sx = (sx+1) & 511;
- xxx--;
- if(!(xx & 1))
- address--;
- if(xxx == -1) {
- xxx = 7;
- address -= 28;
- }
- if(address < 0x10000)
- address += 0x8000;
- }
- } else {
- for(int xx = 0; xx < sizeX; xx++) {
- if(sx < 240) {
- u8 color = vram[address];
- if(xx & 1) {
- color = (color >> 4);
- } else
- color &= 0x0F;
-
- if ((color==0) && (((prio >> 25)&3) <
- ((lineOBJ[sx]>>25)&3))) {
- lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
- } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
- lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
- if((a0 & 0x1000) && m)
- lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
-
- }
- }
- if (a0 & 0x1000) {
- m++;
- if (m==mosaicX)
- m=0;
- }
-#ifdef SPRITE_DEBUG
- if(t == 0 || t == maskY || xx == 0 || xx == maskX)
- lineOBJ[sx] = 0x001F;
-#endif
- sx = (sx+1) & 511;
- xxx++;
- if(xx & 1)
- address++;
- if(xxx == 8) {
- address += 28;
- xxx = 0;
- }
- if(address > 0x17fff)
- address -= 0x8000;
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-inline void gfxDrawOBJWin(u32 *lineOBJWin)
-{
- gfxClearArray(lineOBJWin);
- if(layerEnable & 0x8000) {
- u16 *sprites = (u16 *)oam;
- // u16 *spritePalette = &((u16 *)paletteRAM)[256];
- for(int x = 0; x < 128 ; x++) {
- u16 a0 = READ16LE(sprites++);
- u16 a1 = READ16LE(sprites++);
- u16 a2 = READ16LE(sprites++);
- sprites++;
-
- // ignore non OBJ-WIN
- if((a0 & 0x0c00) != 0x0800)
- continue;
-
- int sizeY = 8;
- int sizeX = 8;
-
- switch(((a0 >>12) & 0x0c)|(a1>>14)) {
- case 0:
- break;
- case 1:
- sizeX = sizeY = 16;
- break;
- case 2:
- sizeX = sizeY = 32;
- break;
- case 3:
- sizeX = sizeY = 64;
- break;
- case 4:
- sizeX = 16;
- break;
- case 5:
- sizeX = 32;
- break;
- case 6:
- sizeX = 32;
- sizeY = 16;
- break;
- case 7:
- sizeX = 64;
- sizeY = 32;
- break;
- case 8:
- sizeY = 16;
- break;
- case 9:
- sizeY = 32;
- break;
- case 10:
- sizeX = 16;
- sizeY = 32;
- break;
- case 11:
- sizeX = 32;
- sizeY = 64;
- break;
- default:
- continue;
- }
-
- int sy = (a0 & 255);
-
- if(sy > 160)
- sy -= 256;
-
- if(a0 & 0x0100) {
- int fieldX = sizeX;
- int fieldY = sizeY;
- if(a0 & 0x0200) {
- fieldX <<= 1;
- fieldY <<= 1;
- }
-
- int t = VCOUNT - sy;
- if((t >= 0) && (t < fieldY)) {
- int sx = (a1 & 0x1FF);
- if((sx < 240) || (((sx + fieldX) & 511) < 240)) {
- // int t2 = t - (fieldY >> 1);
- int rot = (a1 >> 9) & 0x1F;
- u16 *OAM = (u16 *)oam;
- int dx = READ16LE(&OAM[3 + (rot << 4)]);
- if(dx & 0x8000)
- dx |= 0xFFFF8000;
- int dmx = READ16LE(&OAM[7 + (rot << 4)]);
- if(dmx & 0x8000)
- dmx |= 0xFFFF8000;
- int dy = READ16LE(&OAM[11 + (rot << 4)]);
- if(dy & 0x8000)
- dy |= 0xFFFF8000;
- int dmy = READ16LE(&OAM[15 + (rot << 4)]);
- if(dmy & 0x8000)
- dmy |= 0xFFFF8000;
-
- int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
- + t * dmx;
- int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
- + t * dmy;
-
- // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
-
- if(a0 & 0x2000) {
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
- int inc = 32;
- if(DISPCNT & 0x40)
- inc = sizeX >> 2;
- else
- c &= 0x3FE;
- for(int x = 0; x < fieldX; x++) {
- int xxx = realX >> 8;
- int yyy = realY >> 8;
-
- if(xxx < 0 || xxx >= sizeX ||
- yyy < 0 || yyy >= sizeY ||
- sx >= 240) {
- } else {
- u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
- + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
- (xxx & 7))&0x7fff)];
- if(color) {
- lineOBJWin[sx] = 1;
- }
- }
- sx = (sx+1)&511;;
- realX += dx;
- realY += dy;
- }
- } else {
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
-
- int inc = 32;
- if(DISPCNT & 0x40)
- inc = sizeX >> 3;
- // int palette = (a2 >> 8) & 0xF0;
- for(int x = 0; x < fieldX; x++) {
- int xxx = realX >> 8;
- int yyy = realY >> 8;
-
- // if(x == 0 || x == (sizeX-1) ||
- // t == 0 || t == (sizeY-1)) {
- // lineOBJ[sx] = 0x001F | prio;
- // } else {
- if(xxx < 0 || xxx >= sizeX ||
- yyy < 0 || yyy >= sizeY ||
- sx >= 240){
- } else {
- u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
- + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
- ((xxx & 7)>>1))&0x7fff)];
- if(xxx & 1)
- color >>= 4;
- else
- color &= 0x0F;
-
- if(color) {
- lineOBJWin[sx] = 1;
- }
- }
- // }
- sx = (sx+1)&511;;
- realX += dx;
- realY += dy;
- }
- }
- }
- }
- } else {
- int t = VCOUNT - sy;
- if((t >= 0) && (t < sizeY)) {
- int sx = (a1 & 0x1FF);
- if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) {
- if(a0 & 0x2000) {
- if(a1 & 0x2000)
- t = sizeY - t - 1;
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
-
- int inc = 32;
- if(DISPCNT & 0x40) {
- inc = sizeX >> 2;
- } else {
- c &= 0x3FE;
- }
- int xxx = 0;
- if(a1 & 0x1000)
- xxx = sizeX-1;
- int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
- + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
- if(a1 & 0x1000)
- xxx = 7;
- // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
- for(int xx = 0; xx < sizeX; xx++) {
- if(sx < 240) {
- u8 color = vram[address];
- if(color) {
- lineOBJWin[sx] = 1;
- }
- }
-
- sx = (sx+1) & 511;
- if(a1 & 0x1000) {
- xxx--;
- address--;
- if(xxx == -1) {
- address -= 56;
- xxx = 7;
- }
- if(address < 0x10000)
- address += 0x8000;
- } else {
- xxx++;
- address++;
- if(xxx == 8) {
- address += 56;
- xxx = 0;
- }
- if(address > 0x17fff)
- address -= 0x8000;
- }
- }
- } else {
- if(a1 & 0x2000)
- t = sizeY - t - 1;
- int c = (a2 & 0x3FF);
- if((DISPCNT & 7) > 2 && (c < 512))
- continue;
-
- int inc = 32;
- if(DISPCNT & 0x40) {
- inc = sizeX >> 3;
- }
- int xxx = 0;
- if(a1 & 0x1000)
- xxx = sizeX - 1;
- int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
- + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
- // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
- // int palette = (a2 >> 8) & 0xF0;
- if(a1 & 0x1000) {
- xxx = 7;
- for(int xx = sizeX - 1; xx >= 0; xx--) {
- if(sx < 240) {
- u8 color = vram[address];
- if(xx & 1) {
- color = (color >> 4);
- } else
- color &= 0x0F;
-
- if(color) {
- lineOBJWin[sx] = 1;
- }
- }
- sx = (sx+1) & 511;
- xxx--;
- if(!(xx & 1))
- address--;
- if(xxx == -1) {
- xxx = 7;
- address -= 28;
- }
- if(address < 0x10000)
- address += 0x8000;
- }
- } else {
- for(int xx = 0; xx < sizeX; xx++) {
- if(sx < 240) {
- u8 color = vram[address];
- if(xx & 1) {
- color = (color >> 4);
- } else
- color &= 0x0F;
-
- if(color) {
- lineOBJWin[sx] = 1;
- }
- }
- sx = (sx+1) & 511;
- xxx++;
- if(xx & 1)
- address++;
- if(xxx == 8) {
- address += 28;
- xxx = 0;
- }
- if(address > 0x17fff)
- address -= 0x8000;
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-inline u32 gfxIncreaseBrightness(u32 color, int coeff)
-{
- int r = (color & 0x1F);
- int g = ((color >> 5) & 0x1F);
- int b = ((color >> 10) & 0x1F);
-
- r = r + (((31 - r) * coeff) >> 4);
- g = g + (((31 - g) * coeff) >> 4);
- b = b + (((31 - b) * coeff) >> 4);
- if(r > 31)
- r = 31;
- if(g > 31)
- g = 31;
- if(b > 31)
- b = 31;
- color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
- return color;
-}
-
-inline void gfxIncreaseBrightness(u32 *line, int coeff)
-{
- for(int x = 0; x < 240; x++) {
- u32 color = *line;
- int r = (color & 0x1F);
- int g = ((color >> 5) & 0x1F);
- int b = ((color >> 10) & 0x1F);
-
- r = r + (((31 - r) * coeff) >> 4);
- g = g + (((31 - g) * coeff) >> 4);
- b = b + (((31 - b) * coeff) >> 4);
- if(r > 31)
- r = 31;
- if(g > 31)
- g = 31;
- if(b > 31)
- b = 31;
- *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
- }
-}
-
-inline u32 gfxDecreaseBrightness(u32 color, int coeff)
-{
- int r = (color & 0x1F);
- int g = ((color >> 5) & 0x1F);
- int b = ((color >> 10) & 0x1F);
-
- r = r - ((r * coeff) >> 4);
- g = g - ((g * coeff) >> 4);
- b = b - ((b * coeff) >> 4);
- if(r < 0)
- r = 0;
- if(g < 0)
- g = 0;
- if(b < 0)
- b = 0;
- color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
-
- return color;
-}
-
-inline void gfxDecreaseBrightness(u32 *line, int coeff)
-{
- for(int x = 0; x < 240; x++) {
- u32 color = *line;
- int r = (color & 0x1F);
- int g = ((color >> 5) & 0x1F);
- int b = ((color >> 10) & 0x1F);
-
- r = r - ((r * coeff) >> 4);
- g = g - ((g * coeff) >> 4);
- b = b - ((b * coeff) >> 4);
- if(r < 0)
- r = 0;
- if(g < 0)
- g = 0;
- if(b < 0)
- b = 0;
- *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
- }
-}
-
-inline u32 gfxAlphaBlend(u32 color, u32 color2, int ca, int cb)
-{
- if(color < 0x80000000) {
- int r = (color & 0x1F);
- int g = ((color >> 5) & 0x1F);
- int b = ((color >> 10) & 0x1F);
- int r0 = (color2 & 0x1F);
- int g0 = ((color2 >> 5) & 0x1F);
- int b0 = ((color2 >> 10) & 0x1F);
-
- r = ((r * ca) >> 4) + ((r0 * cb) >> 4);
- g = ((g * ca) >> 4) + ((g0 * cb) >> 4);
- b = ((b * ca) >> 4) + ((b0 * cb) >> 4);
-
- if(r > 31)
- r = 31;
- if(g > 31)
- g = 31;
- if(b > 31)
- b = 31;
-
- return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
- }
- return color;
-}
-
-inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb)
-{
- for(int x = 0; x < 240; x++) {
- u32 color = *ta;
- if(color < 0x80000000) {
- int r = (color & 0x1F);
- int g = ((color >> 5) & 0x1F);
- int b = ((color >> 10) & 0x1F);
- u32 color2 = (*tb++);
- int r0 = (color2 & 0x1F);
- int g0 = ((color2 >> 5) & 0x1F);
- int b0 = ((color2 >> 10) & 0x1F);
-
- r = ((r * ca) >> 4) + ((r0 * cb) >> 4);
- g = ((g * ca) >> 4) + ((g0 * cb) >> 4);
- b = ((b * ca) >> 4) + ((b0 * cb) >> 4);
-
- if(r > 31)
- r = 31;
- if(g > 31)
- g = 31;
- if(b > 31)
- b = 31;
-
- *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
- } else {
- ta++;
- tb++;
- }
- }
-}
-
-#endif // VBA_GFX_H
\ No newline at end of file
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_GFX_H
+#define VBA_GFX_H
+
+#include "GBA.h"
+#include "Gfx.h"
+#include "Globals.h"
+
+#include "Port.h"
+
+//#define SPRITE_DEBUG
+
+static void gfxDrawTextScreen(u16, u16, u16, u32 *);
+static void gfxDrawRotScreen(u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ int&, int&,
+ int,
+ u32*);
+static void gfxDrawRotScreen16Bit(u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ int&, int&,
+ int,
+ u32*);
+static void gfxDrawRotScreen256(u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ int&, int&,
+ int,
+ u32*);
+static void gfxDrawRotScreen16Bit160(u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ u16, u16,
+ int&, int&,
+ int,
+ u32*);
+static void gfxDrawSprites(u32 *);
+static void gfxIncreaseBrightness(u32 *line, int coeff);
+static void gfxDecreaseBrightness(u32 *line, int coeff);
+static void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb);
+
+void mode0RenderLine();
+void mode0RenderLineNoWindow();
+void mode0RenderLineAll();
+
+void mode1RenderLine();
+void mode1RenderLineNoWindow();
+void mode1RenderLineAll();
+
+void mode2RenderLine();
+void mode2RenderLineNoWindow();
+void mode2RenderLineAll();
+
+void mode3RenderLine();
+void mode3RenderLineNoWindow();
+void mode3RenderLineAll();
+
+void mode4RenderLine();
+void mode4RenderLineNoWindow();
+void mode4RenderLineAll();
+
+void mode5RenderLine();
+void mode5RenderLineNoWindow();
+void mode5RenderLineAll();
+
+extern int coeff[32];
+extern u32 line0[240];
+extern u32 line1[240];
+extern u32 line2[240];
+extern u32 line3[240];
+extern u32 lineOBJ[240];
+extern u32 lineOBJWin[240];
+extern u32 lineMix[240];
+extern bool gfxInWin0[240];
+extern bool gfxInWin1[240];
+extern int lineOBJpixleft[128];
+
+extern int gfxBG2Changed;
+extern int gfxBG3Changed;
+
+extern int gfxBG2X;
+extern int gfxBG2Y;
+extern int gfxBG2LastX;
+extern int gfxBG2LastY;
+extern int gfxBG3X;
+extern int gfxBG3Y;
+extern int gfxBG3LastX;
+extern int gfxBG3LastY;
+extern int gfxLastVCOUNT;
+
+static inline void gfxClearArray(u32 *array)
+{
+ for(int i = 0; i < 240; i++) {
+ *array++ = 0x80000000;
+ }
+}
+
+static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
+ u32 *line)
+{
+ u16 *palette = (u16 *)paletteRAM;
+ u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
+ u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
+ u32 prio = ((control & 3)<<25) + 0x1000000;
+ int sizeX = 256;
+ int sizeY = 256;
+ switch((control >> 14) & 3) {
+ case 0:
+ break;
+ case 1:
+ sizeX = 512;
+ break;
+ case 2:
+ sizeY = 512;
+ break;
+ case 3:
+ sizeX = 512;
+ sizeY = 512;
+ break;
+ }
+
+ int maskX = sizeX-1;
+ int maskY = sizeY-1;
+
+ bool mosaicOn = (control & 0x40) ? true : false;
+
+ int xxx = hofs & maskX;
+ int yyy = (vofs + VCOUNT) & maskY;
+ int mosaicX = (MOSAIC & 0x000F)+1;
+ int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
+
+ if(mosaicOn) {
+ if((VCOUNT % mosaicY) != 0) {
+ mosaicY = (VCOUNT / mosaicY) * mosaicY;
+ yyy = (vofs + mosaicY) & maskY;
+ }
+ }
+
+ if(yyy > 255 && sizeY > 256) {
+ yyy &= 255;
+ screenBase += 0x400;
+ if(sizeX > 256)
+ screenBase += 0x400;
+ }
+
+ int yshift = ((yyy>>3)<<5);
+ if((control) & 0x80) {
+ u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
+ for(int x = 0; x < 240; x++) {
+ u16 data = READ16LE(screenSource);
+
+ int tile = data & 0x3FF;
+ int tileX = (xxx & 7);
+ int tileY = yyy & 7;
+
+ if(data & 0x0400)
+ tileX = 7 - tileX;
+ if(data & 0x0800)
+ tileY = 7 - tileY;
+
+ u8 color = charBase[tile * 64 + tileY * 8 + tileX];
+
+ line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
+
+ if(data & 0x0400) {
+ if(tileX == 0)
+ screenSource++;
+ } else if(tileX == 7)
+ screenSource++;
+ xxx++;
+ if(xxx == 256) {
+ if(sizeX > 256)
+ screenSource = screenBase + 0x400 + yshift;
+ else {
+ screenSource = screenBase + yshift;
+ xxx = 0;
+ }
+ } else if(xxx >= sizeX) {
+ xxx = 0;
+ screenSource = screenBase + yshift;
+ }
+ }
+ } else {
+ u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
+ yshift;
+ for(int x = 0; x < 240; x++) {
+ u16 data = READ16LE(screenSource);
+
+ int tile = data & 0x3FF;
+ int tileX = (xxx & 7);
+ int tileY = yyy & 7;
+
+ if(data & 0x0400)
+ tileX = 7 - tileX;
+ if(data & 0x0800)
+ tileY = 7 - tileY;
+
+ u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
+
+ if(tileX & 1) {
+ color = (color >> 4);
+ } else {
+ color &= 0x0F;
+ }
+
+ int pal = (READ16LE(screenSource)>>8) & 0xF0;
+ line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
+
+ if(data & 0x0400) {
+ if(tileX == 0)
+ screenSource++;
+ } else if(tileX == 7)
+ screenSource++;
+ xxx++;
+ if(xxx == 256) {
+ if(sizeX > 256)
+ screenSource = screenBase + 0x400 + yshift;
+ else {
+ screenSource = screenBase + yshift;
+ xxx = 0;
+ }
+ } else if(xxx >= sizeX) {
+ xxx = 0;
+ screenSource = screenBase + yshift;
+ }
+ }
+ }
+ if(mosaicOn) {
+ if(mosaicX > 1) {
+ int m = 1;
+ for(int i = 0; i < 239; i++) {
+ line[i+1] = line[i];
+ m++;
+ if(m == mosaicX) {
+ m = 1;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+static inline void gfxDrawRotScreen(u16 control,
+ u16 x_l, u16 x_h,
+ u16 y_l, u16 y_h,
+ u16 pa, u16 pb,
+ u16 pc, u16 pd,
+ int& currentX, int& currentY,
+ int changed,
+ u32 *line)
+{
+ u16 *palette = (u16 *)paletteRAM;
+ u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
+ u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) * 0x800];
+ int prio = ((control & 3) << 25) + 0x1000000;
+
+ int sizeX = 128;
+ int sizeY = 128;
+ switch((control >> 14) & 3) {
+ case 0:
+ break;
+ case 1:
+ sizeX = sizeY = 256;
+ break;
+ case 2:
+ sizeX = sizeY = 512;
+ break;
+ case 3:
+ sizeX = sizeY = 1024;
+ break;
+ }
+
+ int dx = pa & 0x7FFF;
+ if(pa & 0x8000)
+ dx |= 0xFFFF8000;
+ int dmx = pb & 0x7FFF;
+ if(pb & 0x8000)
+ dmx |= 0xFFFF8000;
+ int dy = pc & 0x7FFF;
+ if(pc & 0x8000)
+ dy |= 0xFFFF8000;
+ int dmy = pd & 0x7FFF;
+ if(pd & 0x8000)
+ dmy |= 0xFFFF8000;
+
+ if(VCOUNT == 0)
+ changed = 3;
+
+ if(changed & 1) {
+ currentX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ currentX |= 0xF8000000;
+ } else {
+ currentX += dmx;
+ }
+
+ if(changed & 2) {
+ currentY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ currentY |= 0xF8000000;
+ } else {
+ currentY += dmy;
+ }
+
+ int realX = currentX;
+ int realY = currentY;
+
+ if(control & 0x40) {
+ int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
+ int y = (VCOUNT % mosaicY);
+ realX -= y*dmx;
+ realY -= y*dmy;
+ }
+
+ int xxx = (realX >> 8);
+ int yyy = (realY >> 8);
+
+ if(control & 0x2000) {
+ xxx %= sizeX;
+ yyy %= sizeY;
+ if(xxx < 0)
+ xxx += sizeX;
+ if(yyy < 0)
+ yyy += sizeY;
+ }
+
+ if(control & 0x80) {
+ for(int x = 0; x < 240; x++) {
+ if(xxx < 0 ||
+ yyy < 0 ||
+ xxx >= sizeX ||
+ yyy >= sizeY) {
+ line[x] = 0x80000000;
+ } else {
+ int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
+
+ int tileX = (xxx & 7);
+ int tileY = yyy & 7;
+
+ u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
+
+ line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
+ }
+ realX += dx;
+ realY += dy;
+
+ xxx = (realX >> 8);
+ yyy = (realY >> 8);
+
+ if(control & 0x2000) {
+ xxx %= sizeX;
+ yyy %= sizeY;
+ if(xxx < 0)
+ xxx += sizeX;
+ if(yyy < 0)
+ yyy += sizeY;
+ }
+ }
+ } else {
+ for(int x = 0; x < 240; x++) {
+ if(xxx < 0 ||
+ yyy < 0 ||
+ xxx >= sizeX ||
+ yyy >= sizeY) {
+ line[x] = 0x80000000;
+ } else {
+ int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)];
+
+ int tileX = (xxx & 7);
+ int tileY = yyy & 7;
+
+ u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
+
+ line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
+ }
+ realX += dx;
+ realY += dy;
+
+ xxx = (realX >> 8);
+ yyy = (realY >> 8);
+
+ if(control & 0x2000) {
+ xxx %= sizeX;
+ yyy %= sizeY;
+ if(xxx < 0)
+ xxx += sizeX;
+ if(yyy < 0)
+ yyy += sizeY;
+ }
+ }
+ }
+
+ if(control & 0x40) {
+ int mosaicX = (MOSAIC & 0xF) + 1;
+ if(mosaicX > 1) {
+ int m = 1;
+ for(int i = 0; i < 239; i++) {
+ line[i+1] = line[i];
+ m++;
+ if(m == mosaicX) {
+ m = 1;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+static inline void gfxDrawRotScreen16Bit(u16 control,
+ u16 x_l, u16 x_h,
+ u16 y_l, u16 y_h,
+ u16 pa, u16 pb,
+ u16 pc, u16 pd,
+ int& currentX, int& currentY,
+ int changed,
+ u32 *line)
+{
+ u16 *screenBase = (u16 *)&vram[0];
+ int prio = ((control & 3) << 25) + 0x1000000;
+ int sizeX = 240;
+ int sizeY = 160;
+
+ int startX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ startX |= 0xF8000000;
+ int startY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ startY |= 0xF8000000;
+
+ int dx = pa & 0x7FFF;
+ if(pa & 0x8000)
+ dx |= 0xFFFF8000;
+ int dmx = pb & 0x7FFF;
+ if(pb & 0x8000)
+ dmx |= 0xFFFF8000;
+ int dy = pc & 0x7FFF;
+ if(pc & 0x8000)
+ dy |= 0xFFFF8000;
+ int dmy = pd & 0x7FFF;
+ if(pd & 0x8000)
+ dmy |= 0xFFFF8000;
+
+ if(VCOUNT == 0)
+ changed = 3;
+
+ if(changed & 1) {
+ currentX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ currentX |= 0xF8000000;
+ } else
+ currentX += dmx;
+
+ if(changed & 2) {
+ currentY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ currentY |= 0xF8000000;
+ } else {
+ currentY += dmy;
+ }
+
+ int realX = currentX;
+ int realY = currentY;
+
+ if(control & 0x40) {
+ int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
+ int y = (VCOUNT % mosaicY);
+ realX -= y*dmx;
+ realY -= y*dmy;
+ }
+
+ int xxx = (realX >> 8);
+ int yyy = (realY >> 8);
+
+ for(int x = 0; x < 240; x++) {
+ if(xxx < 0 ||
+ yyy < 0 ||
+ xxx >= sizeX ||
+ yyy >= sizeY) {
+ line[x] = 0x80000000;
+ } else {
+ line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
+ }
+ realX += dx;
+ realY += dy;
+
+ xxx = (realX >> 8);
+ yyy = (realY >> 8);
+ }
+
+ if(control & 0x40) {
+ int mosaicX = (MOSAIC & 0xF) + 1;
+ if(mosaicX > 1) {
+ int m = 1;
+ for(int i = 0; i < 239; i++) {
+ line[i+1] = line[i];
+ m++;
+ if(m == mosaicX) {
+ m = 1;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+static inline void gfxDrawRotScreen256(u16 control,
+ u16 x_l, u16 x_h,
+ u16 y_l, u16 y_h,
+ u16 pa, u16 pb,
+ u16 pc, u16 pd,
+ int ¤tX, int& currentY,
+ int changed,
+ u32 *line)
+{
+ u16 *palette = (u16 *)paletteRAM;
+ u8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000];
+ int prio = ((control & 3) << 25) + 0x1000000;
+ int sizeX = 240;
+ int sizeY = 160;
+
+ int startX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ startX |= 0xF8000000;
+ int startY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ startY |= 0xF8000000;
+
+ int dx = pa & 0x7FFF;
+ if(pa & 0x8000)
+ dx |= 0xFFFF8000;
+ int dmx = pb & 0x7FFF;
+ if(pb & 0x8000)
+ dmx |= 0xFFFF8000;
+ int dy = pc & 0x7FFF;
+ if(pc & 0x8000)
+ dy |= 0xFFFF8000;
+ int dmy = pd & 0x7FFF;
+ if(pd & 0x8000)
+ dmy |= 0xFFFF8000;
+
+ if(VCOUNT == 0)
+ changed = 3;
+
+ if(changed & 1) {
+ currentX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ currentX |= 0xF8000000;
+ } else {
+ currentX += dmx;
+ }
+
+ if(changed & 2) {
+ currentY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ currentY |= 0xF8000000;
+ } else {
+ currentY += dmy;
+ }
+
+ int realX = currentX;
+ int realY = currentY;
+
+ if(control & 0x40) {
+ int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
+ int y = (VCOUNT / mosaicY) * mosaicY;
+ realX = startX + y*dmx;
+ realY = startY + y*dmy;
+ }
+
+ int xxx = (realX >> 8);
+ int yyy = (realY >> 8);
+
+ for(int x = 0; x < 240; x++) {
+ if(xxx < 0 ||
+ yyy < 0 ||
+ xxx >= sizeX ||
+ yyy >= sizeY) {
+ line[x] = 0x80000000;
+ } else {
+ u8 color = screenBase[yyy * 240 + xxx];
+
+ line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000;
+ }
+ realX += dx;
+ realY += dy;
+
+ xxx = (realX >> 8);
+ yyy = (realY >> 8);
+ }
+
+ if(control & 0x40) {
+ int mosaicX = (MOSAIC & 0xF) + 1;
+ if(mosaicX > 1) {
+ int m = 1;
+ for(int i = 0; i < 239; i++) {
+ line[i+1] = line[i];
+ m++;
+ if(m == mosaicX) {
+ m = 1;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+static inline void gfxDrawRotScreen16Bit160(u16 control,
+ u16 x_l, u16 x_h,
+ u16 y_l, u16 y_h,
+ u16 pa, u16 pb,
+ u16 pc, u16 pd,
+ int& currentX, int& currentY,
+ int changed,
+ u32 *line)
+{
+ u16 *screenBase = (DISPCNT & 0x0010) ? (u16 *)&vram[0xa000] :
+ (u16 *)&vram[0];
+ int prio = ((control & 3) << 25) + 0x1000000;
+ int sizeX = 160;
+ int sizeY = 128;
+
+ int startX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ startX |= 0xF8000000;
+ int startY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ startY |= 0xF8000000;
+
+ int dx = pa & 0x7FFF;
+ if(pa & 0x8000)
+ dx |= 0xFFFF8000;
+ int dmx = pb & 0x7FFF;
+ if(pb & 0x8000)
+ dmx |= 0xFFFF8000;
+ int dy = pc & 0x7FFF;
+ if(pc & 0x8000)
+ dy |= 0xFFFF8000;
+ int dmy = pd & 0x7FFF;
+ if(pd & 0x8000)
+ dmy |= 0xFFFF8000;
+
+ if(VCOUNT == 0)
+ changed = 3;
+
+ if(changed & 1) {
+ currentX = (x_l) | ((x_h & 0x07FF)<<16);
+ if(x_h & 0x0800)
+ currentX |= 0xF8000000;
+ } else {
+ currentX += dmx;
+ }
+
+ if(changed & 2) {
+ currentY = (y_l) | ((y_h & 0x07FF)<<16);
+ if(y_h & 0x0800)
+ currentY |= 0xF8000000;
+ } else {
+ currentY += dmy;
+ }
+
+ int realX = currentX;
+ int realY = currentY;
+
+ if(control & 0x40) {
+ int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
+ int y = (VCOUNT / mosaicY) * mosaicY;
+ realX = startX + y*dmx;
+ realY = startY + y*dmy;
+ }
+
+ int xxx = (realX >> 8);
+ int yyy = (realY >> 8);
+
+ for(int x = 0; x < 240; x++) {
+ if(xxx < 0 ||
+ yyy < 0 ||
+ xxx >= sizeX ||
+ yyy >= sizeY) {
+ line[x] = 0x80000000;
+ } else {
+ line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
+ }
+ realX += dx;
+ realY += dy;
+
+ xxx = (realX >> 8);
+ yyy = (realY >> 8);
+ }
+
+ if(control & 0x40) {
+ int mosaicX = (MOSAIC & 0xF) + 1;
+ if(mosaicX > 1) {
+ int m = 1;
+ for(int i = 0; i < 239; i++) {
+ line[i+1] = line[i];
+ m++;
+ if(m == mosaicX) {
+ m = 1;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+static inline void gfxDrawSprites(u32 *lineOBJ)
+{
+ // lineOBJpix is used to keep track of the drawn OBJs
+ // and to stop drawing them if the 'maximum number of OBJ per line'
+ // has been reached.
+ int lineOBJpix = (DISPCNT & 0x20) ? 954 : 1226;
+ int m=0;
+ gfxClearArray(lineOBJ);
+ if(layerEnable & 0x1000) {
+ u16 *sprites = (u16 *)oam;
+ u16 *spritePalette = &((u16 *)paletteRAM)[256];
+ int mosaicY = ((MOSAIC & 0xF000)>>12) + 1;
+ int mosaicX = ((MOSAIC & 0xF00)>>8) + 1;
+ for(int x = 0; x < 128 ; x++) {
+ u16 a0 = READ16LE(sprites++);
+ u16 a1 = READ16LE(sprites++);
+ u16 a2 = READ16LE(sprites++);
+ sprites++;
+
+ lineOBJpixleft[x]=lineOBJpix;
+
+ lineOBJpix-=2;
+ if (lineOBJpix<=0)
+ continue;
+
+ if ((a0 & 0x0c00) == 0x0c00)
+ a0 &=0xF3FF;
+
+ if ((a0>>14) == 3)
+ {
+ a0 &= 0x3FFF;
+ a1 &= 0x3FFF;
+ }
+
+ int sizeX = 8<<(a1>>14);
+ int sizeY = sizeX;
+
+ if ((a0>>14) & 1)
+ {
+ if (sizeX<32)
+ sizeX<<=1;
+ if (sizeY>8)
+ sizeY>>=1;
+ }
+ else if ((a0>>14) & 2)
+ {
+ if (sizeX>8)
+ sizeX>>=1;
+ if (sizeY<32)
+ sizeY<<=1;
+ }
+
+#ifdef SPRITE_DEBUG
+ int maskX = sizeX-1;
+ int maskY = sizeY-1;
+#endif
+
+ int sy = (a0 & 255);
+ int sx = (a1 & 0x1FF);
+
+ // computes ticks used by OBJ-WIN if OBJWIN is enabled
+ if (((a0 & 0x0c00) == 0x0800) && (layerEnable & 0x8000))
+ {
+ if ((a0 & 0x0300) == 0x0300)
+ {
+ sizeX<<=1;
+ sizeY<<=1;
+ }
+ if((sy+sizeY) > 256)
+ sy -= 256;
+ if ((sx+sizeX)> 512)
+ sx-=512;
+ if (sx<0)
+ {
+ sizeX+=sx;
+ sx = 0;
+ }
+ else if ((sx+sizeX)>240)
+ sizeX=240-sx;
+ if ((VCOUNT>=sy) && (VCOUNT 256)
+ sy -= 256;
+ int t = VCOUNT - sy;
+ if((t >= 0) && (t < fieldY)) {
+ int startpix = 0;
+ if ((sx+fieldX)> 512)
+ {
+ startpix=512-sx;
+ }
+ if (lineOBJpix>0)
+ if((sx < 240) || startpix) {
+ lineOBJpix-=8;
+ // int t2 = t - (fieldY >> 1);
+ int rot = (a1 >> 9) & 0x1F;
+ u16 *OAM = (u16 *)oam;
+ int dx = READ16LE(&OAM[3 + (rot << 4)]);
+ if(dx & 0x8000)
+ dx |= 0xFFFF8000;
+ int dmx = READ16LE(&OAM[7 + (rot << 4)]);
+ if(dmx & 0x8000)
+ dmx |= 0xFFFF8000;
+ int dy = READ16LE(&OAM[11 + (rot << 4)]);
+ if(dy & 0x8000)
+ dy |= 0xFFFF8000;
+ int dmy = READ16LE(&OAM[15 + (rot << 4)]);
+ if(dmy & 0x8000)
+ dmy |= 0xFFFF8000;
+
+ if(a0 & 0x1000) {
+ t -= (t % mosaicY);
+ }
+
+ int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
+ + t * dmx;
+ int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
+ + t * dmy;
+
+ u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
+
+ if(a0 & 0x2000) {
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+ int inc = 32;
+ if(DISPCNT & 0x40)
+ inc = sizeX >> 2;
+ else
+ c &= 0x3FE;
+ for(int x = 0; x < fieldX; x++) {
+ if (x >= startpix)
+ lineOBJpix-=2;
+ if (lineOBJpix<0)
+ continue;
+ int xxx = realX >> 8;
+ int yyy = realY >> 8;
+
+ if(xxx < 0 || xxx >= sizeX ||
+ yyy < 0 || yyy >= sizeY ||
+ sx >= 240);
+ else {
+ u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
+ + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
+ (xxx & 7))&0x7FFF)];
+ if ((color==0) && (((prio >> 25)&3) <
+ ((lineOBJ[sx]>>25)&3))) {
+ lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
+ lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ }
+
+ if (a0 & 0x1000) {
+ m++;
+ if (m==mosaicX)
+ m=0;
+ }
+#ifdef SPRITE_DEBUG
+ if(t == 0 || t == maskY || x == 0 || x == maskX)
+ lineOBJ[sx] = 0x001F;
+#endif
+ }
+ sx = (sx+1)&511;
+ realX += dx;
+ realY += dy;
+ }
+ } else {
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+
+ int inc = 32;
+ if(DISPCNT & 0x40)
+ inc = sizeX >> 3;
+ int palette = (a2 >> 8) & 0xF0;
+ for(int x = 0; x < fieldX; x++) {
+ if (x >= startpix)
+ lineOBJpix-=2;
+ if (lineOBJpix<0)
+ continue;
+ int xxx = realX >> 8;
+ int yyy = realY >> 8;
+ if(xxx < 0 || xxx >= sizeX ||
+ yyy < 0 || yyy >= sizeY ||
+ sx >= 240);
+ else {
+ u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
+ + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
+ ((xxx & 7)>>1))&0x7FFF)];
+ if(xxx & 1)
+ color >>= 4;
+ else
+ color &= 0x0F;
+
+ if ((color==0) && (((prio >> 25)&3) <
+ ((lineOBJ[sx]>>25)&3))) {
+ lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
+ lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ }
+ }
+ if((a0 & 0x1000) && m) {
+ m++;
+ if (m==mosaicX)
+ m=0;
+ }
+
+#ifdef SPRITE_DEBUG
+ if(t == 0 || t == maskY || x == 0 || x == maskX)
+ lineOBJ[sx] = 0x001F;
+#endif
+ sx = (sx+1)&511;
+ realX += dx;
+ realY += dy;
+
+ }
+ }
+ }
+ }
+ } else {
+ if(sy+sizeY > 256)
+ sy -= 256;
+ int t = VCOUNT - sy;
+ if((t >= 0) && (t < sizeY)) {
+ int startpix = 0;
+ if ((sx+sizeX)> 512)
+ {
+ startpix=512-sx;
+ }
+ if((sx < 240) || startpix) {
+ lineOBJpix+=2;
+ if(a0 & 0x2000) {
+ if(a1 & 0x2000)
+ t = sizeY - t - 1;
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+
+ int inc = 32;
+ if(DISPCNT & 0x40) {
+ inc = sizeX >> 2;
+ } else {
+ c &= 0x3FE;
+ }
+ int xxx = 0;
+ if(a1 & 0x1000)
+ xxx = sizeX-1;
+
+ if(a0 & 0x1000) {
+ t -= (t % mosaicY);
+ }
+
+ int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
+ + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
+
+ if(a1 & 0x1000)
+ xxx = 7;
+ u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
+
+ for(int xx = 0; xx < sizeX; xx++) {
+ if (xx >= startpix)
+ lineOBJpix--;
+ if (lineOBJpix<0)
+ continue;
+ if(sx < 240) {
+ u8 color = vram[address];
+ if ((color==0) && (((prio >> 25)&3) <
+ ((lineOBJ[sx]>>25)&3))) {
+ lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
+ lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ }
+
+ if (a0 & 0x1000) {
+ m++;
+ if (m==mosaicX)
+ m=0;
+ }
+
+#ifdef SPRITE_DEBUG
+ if(t == 0 || t == maskY || xx == 0 || xx == maskX)
+ lineOBJ[sx] = 0x001F;
+#endif
+ }
+
+ sx = (sx+1) & 511;
+ if(a1 & 0x1000) {
+ xxx--;
+ address--;
+ if(xxx == -1) {
+ address -= 56;
+ xxx = 7;
+ }
+ if(address < 0x10000)
+ address += 0x8000;
+ } else {
+ xxx++;
+ address++;
+ if(xxx == 8) {
+ address += 56;
+ xxx = 0;
+ }
+ if(address > 0x17fff)
+ address -= 0x8000;
+ }
+ }
+ } else {
+ if(a1 & 0x2000)
+ t = sizeY - t - 1;
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+
+ int inc = 32;
+ if(DISPCNT & 0x40) {
+ inc = sizeX >> 3;
+ }
+ int xxx = 0;
+ if(a1 & 0x1000)
+ xxx = sizeX - 1;
+
+ if(a0 & 0x1000) {
+ t -= (t % mosaicY);
+ }
+
+ int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
+ + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
+ u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
+ int palette = (a2 >> 8) & 0xF0;
+ if(a1 & 0x1000) {
+ xxx = 7;
+ for(int xx = sizeX - 1; xx >= 0; xx--) {
+ if (xx >= startpix)
+ lineOBJpix--;
+ if (lineOBJpix<0)
+ continue;
+ if(sx < 240) {
+ u8 color = vram[address];
+ if(xx & 1) {
+ color = (color >> 4);
+ } else
+ color &= 0x0F;
+
+ if ((color==0) && (((prio >> 25)&3) <
+ ((lineOBJ[sx]>>25)&3))) {
+ lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
+ lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ }
+ }
+ if (a0 & 0x1000) {
+ m++;
+ if (m==mosaicX)
+ m=0;
+ }
+#ifdef SPRITE_DEBUG
+ if(t == 0 || t == maskY || xx == 0 || xx == maskX)
+ lineOBJ[sx] = 0x001F;
+#endif
+ sx = (sx+1) & 511;
+ xxx--;
+ if(!(xx & 1))
+ address--;
+ if(xxx == -1) {
+ xxx = 7;
+ address -= 28;
+ }
+ if(address < 0x10000)
+ address += 0x8000;
+ }
+ } else {
+ for(int xx = 0; xx < sizeX; xx++) {
+ if (xx >= startpix)
+ lineOBJpix--;
+ if (lineOBJpix<0)
+ continue;
+ if(sx < 240) {
+ u8 color = vram[address];
+ if(xx & 1) {
+ color = (color >> 4);
+ } else
+ color &= 0x0F;
+
+ if ((color==0) && (((prio >> 25)&3) <
+ ((lineOBJ[sx]>>25)&3))) {
+ lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+ } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) {
+ lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio;
+ if((a0 & 0x1000) && m)
+ lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio;
+
+ }
+ }
+ if (a0 & 0x1000) {
+ m++;
+ if (m==mosaicX)
+ m=0;
+ }
+#ifdef SPRITE_DEBUG
+ if(t == 0 || t == maskY || xx == 0 || xx == maskX)
+ lineOBJ[sx] = 0x001F;
+#endif
+ sx = (sx+1) & 511;
+ xxx++;
+ if(xx & 1)
+ address++;
+ if(xxx == 8) {
+ address += 28;
+ xxx = 0;
+ }
+ if(address > 0x17fff)
+ address -= 0x8000;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static inline void gfxDrawOBJWin(u32 *lineOBJWin)
+{
+ gfxClearArray(lineOBJWin);
+ if((layerEnable & 0x9000) == 0x9000) {
+ u16 *sprites = (u16 *)oam;
+ // u16 *spritePalette = &((u16 *)paletteRAM)[256];
+ for(int x = 0; x < 128 ; x++) {
+ int lineOBJpix = lineOBJpixleft[x];
+ u16 a0 = READ16LE(sprites++);
+ u16 a1 = READ16LE(sprites++);
+ u16 a2 = READ16LE(sprites++);
+ sprites++;
+
+ if (lineOBJpix<=0)
+ continue;
+
+ // ignores non OBJ-WIN and disabled OBJ-WIN
+ if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200))
+ continue;
+
+ if ((a0 & 0x0c00) == 0x0c00)
+ a0 &=0xF3FF;
+
+ if ((a0>>14) == 3)
+ {
+ a0 &= 0x3FFF;
+ a1 &= 0x3FFF;
+ }
+
+ int sizeX = 8<<(a1>>14);
+ int sizeY = sizeX;
+
+ if ((a0>>14) & 1)
+ {
+ if (sizeX<32)
+ sizeX<<=1;
+ if (sizeY>8)
+ sizeY>>=1;
+ }
+ else if ((a0>>14) & 2)
+ {
+ if (sizeX>8)
+ sizeX>>=1;
+ if (sizeY<32)
+ sizeY<<=1;
+ }
+
+ int sy = (a0 & 255);
+
+ if(a0 & 0x0100) {
+ int fieldX = sizeX;
+ int fieldY = sizeY;
+ if(a0 & 0x0200) {
+ fieldX <<= 1;
+ fieldY <<= 1;
+ }
+ if((sy+fieldY) > 256)
+ sy -= 256;
+ int t = VCOUNT - sy;
+ if((t >= 0) && (t < fieldY)) {
+ int sx = (a1 & 0x1FF);
+ int startpix = 0;
+ if ((sx+fieldX)> 512)
+ {
+ startpix=512-sx;
+ }
+ if((sx < 240) || startpix) {
+ lineOBJpix-=8;
+ // int t2 = t - (fieldY >> 1);
+ int rot = (a1 >> 9) & 0x1F;
+ u16 *OAM = (u16 *)oam;
+ int dx = READ16LE(&OAM[3 + (rot << 4)]);
+ if(dx & 0x8000)
+ dx |= 0xFFFF8000;
+ int dmx = READ16LE(&OAM[7 + (rot << 4)]);
+ if(dmx & 0x8000)
+ dmx |= 0xFFFF8000;
+ int dy = READ16LE(&OAM[11 + (rot << 4)]);
+ if(dy & 0x8000)
+ dy |= 0xFFFF8000;
+ int dmy = READ16LE(&OAM[15 + (rot << 4)]);
+ if(dmy & 0x8000)
+ dmy |= 0xFFFF8000;
+
+ int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
+ + t * dmx;
+ int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
+ + t * dmy;
+
+ // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
+
+ if(a0 & 0x2000) {
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+ int inc = 32;
+ if(DISPCNT & 0x40)
+ inc = sizeX >> 2;
+ else
+ c &= 0x3FE;
+ for(int x = 0; x < fieldX; x++) {
+ if (x >= startpix)
+ lineOBJpix-=2;
+ if (lineOBJpix<0)
+ continue;
+ int xxx = realX >> 8;
+ int yyy = realY >> 8;
+
+ if(xxx < 0 || xxx >= sizeX ||
+ yyy < 0 || yyy >= sizeY ||
+ sx >= 240) {
+ } else {
+ u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
+ + ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
+ (xxx & 7))&0x7fff)];
+ if(color) {
+ lineOBJWin[sx] = 1;
+ }
+ }
+ sx = (sx+1)&511;
+ realX += dx;
+ realY += dy;
+ }
+ } else {
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+
+ int inc = 32;
+ if(DISPCNT & 0x40)
+ inc = sizeX >> 3;
+ // int palette = (a2 >> 8) & 0xF0;
+ for(int x = 0; x < fieldX; x++) {
+ if (x >= startpix)
+ lineOBJpix-=2;
+ if (lineOBJpix<0)
+ continue;
+ int xxx = realX >> 8;
+ int yyy = realY >> 8;
+
+ // if(x == 0 || x == (sizeX-1) ||
+ // t == 0 || t == (sizeY-1)) {
+ // lineOBJ[sx] = 0x001F | prio;
+ // } else {
+ if(xxx < 0 || xxx >= sizeX ||
+ yyy < 0 || yyy >= sizeY ||
+ sx >= 240) {
+ } else {
+ u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
+ + ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
+ ((xxx & 7)>>1))&0x7fff)];
+ if(xxx & 1)
+ color >>= 4;
+ else
+ color &= 0x0F;
+
+ if(color) {
+ lineOBJWin[sx] = 1;
+ }
+ }
+ // }
+ sx = (sx+1)&511;
+ realX += dx;
+ realY += dy;
+ }
+ }
+ }
+ }
+ } else {
+ if((sy+sizeY) > 256)
+ sy -= 256;
+ int t = VCOUNT - sy;
+ if((t >= 0) && (t < sizeY)) {
+ int sx = (a1 & 0x1FF);
+ int startpix = 0;
+ if ((sx+sizeX)> 512)
+ {
+ startpix=512-sx;
+ }
+ if((sx < 240) || startpix) {
+ lineOBJpix+=2;
+ if(a0 & 0x2000) {
+ if(a1 & 0x2000)
+ t = sizeY - t - 1;
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+
+ int inc = 32;
+ if(DISPCNT & 0x40) {
+ inc = sizeX >> 2;
+ } else {
+ c &= 0x3FE;
+ }
+ int xxx = 0;
+ if(a1 & 0x1000)
+ xxx = sizeX-1;
+ int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
+ + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
+ if(a1 & 0x1000)
+ xxx = 7;
+ // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
+ for(int xx = 0; xx < sizeX; xx++) {
+ if (xx >= startpix)
+ lineOBJpix--;
+ if (lineOBJpix<0)
+ continue;
+ if(sx < 240) {
+ u8 color = vram[address];
+ if(color) {
+ lineOBJWin[sx] = 1;
+ }
+ }
+
+ sx = (sx+1) & 511;
+ if(a1 & 0x1000) {
+ xxx--;
+ address--;
+ if(xxx == -1) {
+ address -= 56;
+ xxx = 7;
+ }
+ if(address < 0x10000)
+ address += 0x8000;
+ } else {
+ xxx++;
+ address++;
+ if(xxx == 8) {
+ address += 56;
+ xxx = 0;
+ }
+ if(address > 0x17fff)
+ address -= 0x8000;
+ }
+ }
+ } else {
+ if(a1 & 0x2000)
+ t = sizeY - t - 1;
+ int c = (a2 & 0x3FF);
+ if((DISPCNT & 7) > 2 && (c < 512))
+ continue;
+
+ int inc = 32;
+ if(DISPCNT & 0x40) {
+ inc = sizeX >> 3;
+ }
+ int xxx = 0;
+ if(a1 & 0x1000)
+ xxx = sizeX - 1;
+ int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
+ + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
+ // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
+ // int palette = (a2 >> 8) & 0xF0;
+ if(a1 & 0x1000) {
+ xxx = 7;
+ for(int xx = sizeX - 1; xx >= 0; xx--) {
+ if (xx >= startpix)
+ lineOBJpix--;
+ if (lineOBJpix<0)
+ continue;
+ if(sx < 240) {
+ u8 color = vram[address];
+ if(xx & 1) {
+ color = (color >> 4);
+ } else
+ color &= 0x0F;
+
+ if(color) {
+ lineOBJWin[sx] = 1;
+ }
+ }
+ sx = (sx+1) & 511;
+ xxx--;
+ if(!(xx & 1))
+ address--;
+ if(xxx == -1) {
+ xxx = 7;
+ address -= 28;
+ }
+ if(address < 0x10000)
+ address += 0x8000;
+ }
+ } else {
+ for(int xx = 0; xx < sizeX; xx++) {
+ if (xx >= startpix)
+ lineOBJpix--;
+ if (lineOBJpix<0)
+ continue;
+ if(sx < 240) {
+ u8 color = vram[address];
+ if(xx & 1) {
+ color = (color >> 4);
+ } else
+ color &= 0x0F;
+
+ if(color) {
+ lineOBJWin[sx] = 1;
+ }
+ }
+ sx = (sx+1) & 511;
+ xxx++;
+ if(xx & 1)
+ address++;
+ if(xxx == 8) {
+ address += 28;
+ xxx = 0;
+ }
+ if(address > 0x17fff)
+ address -= 0x8000;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static inline u32 gfxIncreaseBrightness(u32 color, int coeff)
+{
+ int r = (color & 0x1F);
+ int g = ((color >> 5) & 0x1F);
+ int b = ((color >> 10) & 0x1F);
+
+ r = r + (((31 - r) * coeff) >> 4);
+ g = g + (((31 - g) * coeff) >> 4);
+ b = b + (((31 - b) * coeff) >> 4);
+ if(r > 31)
+ r = 31;
+ if(g > 31)
+ g = 31;
+ if(b > 31)
+ b = 31;
+ color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
+ return color;
+}
+
+static inline void gfxIncreaseBrightness(u32 *line, int coeff)
+{
+ for(int x = 0; x < 240; x++) {
+ u32 color = *line;
+ int r = (color & 0x1F);
+ int g = ((color >> 5) & 0x1F);
+ int b = ((color >> 10) & 0x1F);
+
+ r = r + (((31 - r) * coeff) >> 4);
+ g = g + (((31 - g) * coeff) >> 4);
+ b = b + (((31 - b) * coeff) >> 4);
+ if(r > 31)
+ r = 31;
+ if(g > 31)
+ g = 31;
+ if(b > 31)
+ b = 31;
+ *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
+ }
+}
+
+static inline u32 gfxDecreaseBrightness(u32 color, int coeff)
+{
+ int r = (color & 0x1F);
+ int g = ((color >> 5) & 0x1F);
+ int b = ((color >> 10) & 0x1F);
+
+ r = r - ((r * coeff) >> 4);
+ g = g - ((g * coeff) >> 4);
+ b = b - ((b * coeff) >> 4);
+ if(r < 0)
+ r = 0;
+ if(g < 0)
+ g = 0;
+ if(b < 0)
+ b = 0;
+ color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
+
+ return color;
+}
+
+static inline void gfxDecreaseBrightness(u32 *line, int coeff)
+{
+ for(int x = 0; x < 240; x++) {
+ u32 color = *line;
+ int r = (color & 0x1F);
+ int g = ((color >> 5) & 0x1F);
+ int b = ((color >> 10) & 0x1F);
+
+ r = r - ((r * coeff) >> 4);
+ g = g - ((g * coeff) >> 4);
+ b = b - ((b * coeff) >> 4);
+ if(r < 0)
+ r = 0;
+ if(g < 0)
+ g = 0;
+ if(b < 0)
+ b = 0;
+ *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
+ }
+}
+
+static inline u32 gfxAlphaBlend(u32 color, u32 color2, int ca, int cb)
+{
+ if(color < 0x80000000) {
+ int r = (color & 0x1F);
+ int g = ((color >> 5) & 0x1F);
+ int b = ((color >> 10) & 0x1F);
+ int r0 = (color2 & 0x1F);
+ int g0 = ((color2 >> 5) & 0x1F);
+ int b0 = ((color2 >> 10) & 0x1F);
+
+ r = ((r * ca) + (r0 * cb)) >> 4;
+ g = ((g * ca) + (g0 * cb)) >> 4;
+ b = ((b * ca) + (b0 * cb)) >> 4;
+
+ if(r > 31)
+ r = 31;
+ if(g > 31)
+ g = 31;
+ if(b > 31)
+ b = 31;
+
+ return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
+ }
+ return color;
+}
+
+static inline void gfxAlphaBlend(u32 *ta, u32 *tb, int ca, int cb)
+{
+ for(int x = 0; x < 240; x++) {
+ u32 color = *ta;
+ if(color < 0x80000000) {
+ int r = (color & 0x1F);
+ int g = ((color >> 5) & 0x1F);
+ int b = ((color >> 10) & 0x1F);
+ u32 color2 = (*tb++);
+ int r0 = (color2 & 0x1F);
+ int g0 = ((color2 >> 5) & 0x1F);
+ int b0 = ((color2 >> 10) & 0x1F);
+
+ r = ((r * ca) + (r0 * cb)) >> 4;
+ g = ((g * ca) + (g0 * cb)) >> 4;
+ b = ((b * ca) + (b0 * cb)) >> 4;
+
+ if(r > 31)
+ r = 31;
+ if(g > 31)
+ g = 31;
+ if(b > 31)
+ b = 31;
+
+ *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
+ } else {
+ ta++;
+ tb++;
+ }
+ }
+}
+
+#endif // VBA_GFX_H
diff --git a/src/Globals.cpp b/src/Globals.cpp
index cb863c32..a256ce37 100644
--- a/src/Globals.cpp
+++ b/src/Globals.cpp
@@ -16,7 +16,12 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#include "Globals.h"
+#include "GBA.h"
+
+#ifdef BKPT_SUPPORT
+int oldreg[17];
+char oldbuffer[10];
+#endif
reg_pair reg[45];
memoryMap map[256];
@@ -43,8 +48,8 @@ int layerSettings = 0xff00;
int layerEnable = 0xff00;
bool speedHack = false;
int cpuSaveType = 0;
-bool cpuEnhancedDetection = true;
bool cheatsEnabled = true;
+bool mirroringEnable = false;
u8 *bios = NULL;
u8 *rom = NULL;
diff --git a/src/Globals.h b/src/Globals.h
index 2466a3f2..34d76b88 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -57,8 +57,8 @@ extern int layerSettings;
extern int layerEnable;
extern bool speedHack;
extern int cpuSaveType;
-extern bool cpuEnhancedDetection;
extern bool cheatsEnabled;
+extern bool mirroringEnable;
extern u8 *bios;
extern u8 *rom;
diff --git a/src/NLS.h b/src/NLS.h
index d243a863..92b24eb3 100644
--- a/src/NLS.h
+++ b/src/NLS.h
@@ -1,62 +1,64 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#define N_(String) (String)
-
-#define MSG_UNSUPPORTED_VBA_SGM 1
-#define MSG_CANNOT_LOAD_SGM 2
-#define MSG_SAVE_GAME_NOT_USING_BIOS 3
-#define MSG_SAVE_GAME_USING_BIOS 4
-#define MSG_UNSUPPORTED_SAVE_TYPE 5
-#define MSG_CANNOT_OPEN_FILE 6
-#define MSG_BAD_ARCHIVE_FILE 7
-#define MSG_NO_IMAGE_ON_ARCHIVE 8
-#define MSG_ERROR_OPENING_IMAGE 9
-#define MSG_ERROR_READING_IMAGE 10
-#define MSG_UNSUPPORTED_BIOS_FUNCTION 11
-#define MSG_INVALID_BIOS_FILE_SIZE 12
-#define MSG_INVALID_CHEAT_CODE 13
-#define MSG_UNKNOWN_ARM_OPCODE 14
-#define MSG_UNKNOWN_THUMB_OPCODE 15
-#define MSG_ERROR_CREATING_FILE 16
-#define MSG_FAILED_TO_READ_SGM 17
-#define MSG_FAILED_TO_READ_RTC 18
-#define MSG_UNSUPPORTED_VB_SGM 19
-#define MSG_CANNOT_LOAD_SGM_FOR 20
-#define MSG_ERROR_OPENING_IMAGE_FROM 21
-#define MSG_ERROR_READING_IMAGE_FROM 22
-#define MSG_UNSUPPORTED_ROM_SIZE 23
-#define MSG_UNSUPPORTED_RAM_SIZE 24
-#define MSG_UNKNOWN_CARTRIDGE_TYPE 25
-#define MSG_MAXIMUM_NUMBER_OF_CHEATS 26
-#define MSG_INVALID_GAMESHARK_CODE 27
-#define MSG_INVALID_GAMEGENIE_CODE 28
-#define MSG_INVALID_CHEAT_TO_REMOVE 29
-#define MSG_INVALID_CHEAT_CODE_ADDRESS 30
-#define MSG_UNSUPPORTED_CHEAT_LIST_VERSION 31
-#define MSG_UNSUPPORTED_CHEAT_LIST_TYPE 32
-#define MSG_INVALID_GSA_CODE 33
-#define MSG_CANNOT_IMPORT_SNAPSHOT_FOR 34
-#define MSG_UNSUPPORTED_SNAPSHOT_FILE 35
-#define MSG_UNSUPPORTED_ARM_MODE 36
-#define MSG_UNSUPPORTED_CODE_FILE 37
-#define MSG_GBA_CODE_WARNING 38
-#define MSG_INVALID_CBA_CODE 39
-#define MSG_CBA_CODE_WARNING 40
-#define MSG_OUT_OF_MEMORY 41
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#define N_(String) (String)
+
+#define MSG_UNSUPPORTED_VBA_SGM 1
+#define MSG_CANNOT_LOAD_SGM 2
+#define MSG_SAVE_GAME_NOT_USING_BIOS 3
+#define MSG_SAVE_GAME_USING_BIOS 4
+#define MSG_UNSUPPORTED_SAVE_TYPE 5
+#define MSG_CANNOT_OPEN_FILE 6
+#define MSG_BAD_ZIP_FILE 7
+#define MSG_NO_IMAGE_ON_ZIP 8
+#define MSG_ERROR_OPENING_IMAGE 9
+#define MSG_ERROR_READING_IMAGE 10
+#define MSG_UNSUPPORTED_BIOS_FUNCTION 11
+#define MSG_INVALID_BIOS_FILE_SIZE 12
+#define MSG_INVALID_CHEAT_CODE 13
+#define MSG_UNKNOWN_ARM_OPCODE 14
+#define MSG_UNKNOWN_THUMB_OPCODE 15
+#define MSG_ERROR_CREATING_FILE 16
+#define MSG_FAILED_TO_READ_SGM 17
+#define MSG_FAILED_TO_READ_RTC 18
+#define MSG_UNSUPPORTED_VB_SGM 19
+#define MSG_CANNOT_LOAD_SGM_FOR 20
+#define MSG_ERROR_OPENING_IMAGE_FROM 21
+#define MSG_ERROR_READING_IMAGE_FROM 22
+#define MSG_UNSUPPORTED_ROM_SIZE 23
+#define MSG_UNSUPPORTED_RAM_SIZE 24
+#define MSG_UNKNOWN_CARTRIDGE_TYPE 25
+#define MSG_MAXIMUM_NUMBER_OF_CHEATS 26
+#define MSG_INVALID_GAMESHARK_CODE 27
+#define MSG_INVALID_GAMEGENIE_CODE 28
+#define MSG_INVALID_CHEAT_TO_REMOVE 29
+#define MSG_INVALID_CHEAT_CODE_ADDRESS 30
+#define MSG_UNSUPPORTED_CHEAT_LIST_VERSION 31
+#define MSG_UNSUPPORTED_CHEAT_LIST_TYPE 32
+#define MSG_INVALID_GSA_CODE 33
+#define MSG_CANNOT_IMPORT_SNAPSHOT_FOR 34
+#define MSG_UNSUPPORTED_SNAPSHOT_FILE 35
+#define MSG_UNSUPPORTED_ARM_MODE 36
+#define MSG_UNSUPPORTED_CODE_FILE 37
+#define MSG_GBA_CODE_WARNING 38
+#define MSG_INVALID_CBA_CODE 39
+#define MSG_CBA_CODE_WARNING 40
+#define MSG_OUT_OF_MEMORY 41
+#define MSG_WRONG_GAMESHARK_CODE 42
+#define MSG_UNSUPPORTED_GAMESHARK_CODE 43
diff --git a/src/RTC.cpp b/src/RTC.cpp
index 9a5b3098..9a69ecc5 100644
--- a/src/RTC.cpp
+++ b/src/RTC.cpp
@@ -1,220 +1,222 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "System.h"
-#include "GBA.h"
-#include "Globals.h"
-#include "Port.h"
-#include "Util.h"
-#include "NLS.h"
-
-#include
-#include
-
-enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
-
-typedef struct {
- u8 byte0;
- u8 byte1;
- u8 byte2;
- u8 command;
- int dataLen;
- int bits;
- RTCSTATE state;
- u8 data[12];
- // reserved variables for future
- u8 reserved[12];
- bool reserved2;
- u32 reserved3;
-} RTCCLOCKDATA;
-
-static RTCCLOCKDATA rtcClockData;
-static bool rtcEnabled = false;
-
-void rtcEnable(bool e)
-{
- rtcEnabled = e;
-}
-
-bool rtcIsEnabled()
-{
- return rtcEnabled;
-}
-
-u16 rtcRead(u32 address)
-{
- if(rtcEnabled) {
- if(address == 0x80000c8)
- return rtcClockData.byte2;
- else if(address == 0x80000c6)
- return rtcClockData.byte1;
- else if(address == 0x80000c4) {
- return rtcClockData.byte0;
- }
- }
-
- return READ16LE((&rom[address & 0x1FFFFFE]));
-}
-
-static u8 toBCD(u8 value)
-{
- value = value % 100;
- int l = value % 10;
- int h = value / 10;
- return h * 16 + l;
-}
-
-bool rtcWrite(u32 address, u16 value)
-{
- if(!rtcEnabled)
- return false;
-
- if(address == 0x80000c8) {
- rtcClockData.byte2 = (u8)value; // enable ?
- } else if(address == 0x80000c6) {
- rtcClockData.byte1 = (u8)value; // read/write
- } else if(address == 0x80000c4) {
- if(rtcClockData.byte2 & 1) {
- if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) {
- rtcClockData.state = COMMAND;
- rtcClockData.bits = 0;
- rtcClockData.command = 0;
- } else if(!(rtcClockData.byte0 & 1) && (value & 1)) { // bit transfer
- rtcClockData.byte0 = (u8)value;
- switch(rtcClockData.state) {
- case COMMAND:
- rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
- rtcClockData.bits++;
- if(rtcClockData.bits == 8) {
- rtcClockData.bits = 0;
- switch(rtcClockData.command) {
- case 0x60:
- // not sure what this command does but it doesn't take parameters
- // maybe it is a reset or stop
- rtcClockData.state = IDLE;
- rtcClockData.bits = 0;
- break;
- case 0x62:
- // this sets the control state but not sure what those values are
- rtcClockData.state = READDATA;
- rtcClockData.dataLen = 1;
- break;
- case 0x63:
- rtcClockData.dataLen = 1;
- rtcClockData.data[0] = 0x40;
- rtcClockData.state = DATA;
- break;
- case 0x65:
- {
- struct tm *newtime;
- time_t long_time;
-
- time( &long_time ); /* Get time as long integer. */
- newtime = localtime( &long_time ); /* Convert to local time. */
-
- rtcClockData.dataLen = 7;
- rtcClockData.data[0] = toBCD(newtime->tm_year);
- rtcClockData.data[1] = toBCD(newtime->tm_mon+1);
- rtcClockData.data[2] = toBCD(newtime->tm_mday);
- rtcClockData.data[3] = toBCD(newtime->tm_wday);
- rtcClockData.data[4] = toBCD(newtime->tm_hour);
- rtcClockData.data[5] = toBCD(newtime->tm_min);
- rtcClockData.data[6] = toBCD(newtime->tm_sec);
- rtcClockData.state = DATA;
- }
- break;
- case 0x67:
- {
- struct tm *newtime;
- time_t long_time;
-
- time( &long_time ); /* Get time as long integer. */
- newtime = localtime( &long_time ); /* Convert to local time. */
-
- rtcClockData.dataLen = 3;
- rtcClockData.data[0] = toBCD(newtime->tm_hour);
- rtcClockData.data[1] = toBCD(newtime->tm_min);
- rtcClockData.data[2] = toBCD(newtime->tm_sec);
- rtcClockData.state = DATA;
- }
- break;
- default:
- systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command);
- rtcClockData.state = IDLE;
- break;
- }
- }
- break;
- case DATA:
- if(rtcClockData.byte1 & 2) {
- } else {
- rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
- ((rtcClockData.data[rtcClockData.bits >> 3] >>
- (rtcClockData.bits & 7)) & 1)*2;
- rtcClockData.bits++;
- if(rtcClockData.bits == 8*rtcClockData.dataLen) {
- rtcClockData.bits = 0;
- rtcClockData.state = IDLE;
- }
- }
- break;
- case READDATA:
- if(!(rtcClockData.byte1 & 2)) {
- } else {
- rtcClockData.data[rtcClockData.bits >> 3] =
- (rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
- ((value << 6) & 128);
- rtcClockData.bits++;
- if(rtcClockData.bits == 8*rtcClockData.dataLen) {
- rtcClockData.bits = 0;
- rtcClockData.state = IDLE;
- }
- }
- break;
- default:
- break;
- }
- } else
- rtcClockData.byte0 = (u8)value;
- }
- }
- return true;
-}
-
-void rtcReset()
-{
- memset(&rtcClockData, 0, sizeof(rtcClockData));
-
- rtcClockData.byte0 = 0;
- rtcClockData.byte1 = 0;
- rtcClockData.byte2 = 0;
- rtcClockData.command = 0;
- rtcClockData.dataLen = 0;
- rtcClockData.bits = 0;
- rtcClockData.state = IDLE;
-}
-
-void rtcSaveGame(gzFile gzFile)
-{
- utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
-}
-
-void rtcReadGame(gzFile gzFile)
-{
- utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "System.h"
+#include "GBA.h"
+#include "Globals.h"
+#include "Port.h"
+#include "Util.h"
+#include "NLS.h"
+
+#include
+#include
+
+enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
+
+typedef struct {
+ u8 byte0;
+ u8 byte1;
+ u8 byte2;
+ u8 command;
+ int dataLen;
+ int bits;
+ RTCSTATE state;
+ u8 data[12];
+ // reserved variables for future
+ u8 reserved[12];
+ bool reserved2;
+ u32 reserved3;
+} RTCCLOCKDATA;
+
+static RTCCLOCKDATA rtcClockData;
+static bool rtcEnabled = false;
+
+void rtcEnable(bool e)
+{
+ rtcEnabled = e;
+}
+
+bool rtcIsEnabled()
+{
+ return rtcEnabled;
+}
+
+u16 rtcRead(u32 address)
+{
+ if(rtcEnabled) {
+ if(address == 0x80000c8)
+ return rtcClockData.byte2;
+ else if(address == 0x80000c6)
+ return rtcClockData.byte1;
+ else if(address == 0x80000c4) {
+ return rtcClockData.byte0;
+ }
+ }
+
+ return READ16LE((&rom[address & 0x1FFFFFE]));
+}
+
+static u8 toBCD(u8 value)
+{
+ value = value % 100;
+ int l = value % 10;
+ int h = value / 10;
+ return h * 16 + l;
+}
+
+bool rtcWrite(u32 address, u16 value)
+{
+ if(!rtcEnabled)
+ return false;
+
+ if(address == 0x80000c8) {
+ rtcClockData.byte2 = (u8)value; // enable ?
+ } else if(address == 0x80000c6) {
+ rtcClockData.byte1 = (u8)value; // read/write
+ } else if(address == 0x80000c4) {
+ if(rtcClockData.byte2 & 1) {
+ if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) {
+ rtcClockData.state = COMMAND;
+ rtcClockData.bits = 0;
+ rtcClockData.command = 0;
+ } else if(!(rtcClockData.byte0 & 1) && (value & 1)) { // bit transfer
+ rtcClockData.byte0 = (u8)value;
+ switch(rtcClockData.state) {
+ case COMMAND:
+ rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
+ rtcClockData.bits++;
+ if(rtcClockData.bits == 8) {
+ rtcClockData.bits = 0;
+ switch(rtcClockData.command) {
+ case 0x60:
+ // not sure what this command does but it doesn't take parameters
+ // maybe it is a reset or stop
+ rtcClockData.state = IDLE;
+ rtcClockData.bits = 0;
+ break;
+ case 0x62:
+ // this sets the control state but not sure what those values are
+ rtcClockData.state = READDATA;
+ rtcClockData.dataLen = 1;
+ break;
+ case 0x63:
+ rtcClockData.dataLen = 1;
+ rtcClockData.data[0] = 0x40;
+ rtcClockData.state = DATA;
+ break;
+ case 0x64:
+ break;
+ case 0x65:
+ {
+ struct tm *newtime;
+ time_t long_time;
+
+ time( &long_time ); /* Get time as long integer. */
+ newtime = localtime( &long_time ); /* Convert to local time. */
+
+ rtcClockData.dataLen = 7;
+ rtcClockData.data[0] = toBCD(newtime->tm_year);
+ rtcClockData.data[1] = toBCD(newtime->tm_mon+1);
+ rtcClockData.data[2] = toBCD(newtime->tm_mday);
+ rtcClockData.data[3] = toBCD(newtime->tm_wday);
+ rtcClockData.data[4] = toBCD(newtime->tm_hour);
+ rtcClockData.data[5] = toBCD(newtime->tm_min);
+ rtcClockData.data[6] = toBCD(newtime->tm_sec);
+ rtcClockData.state = DATA;
+ }
+ break;
+ case 0x67:
+ {
+ struct tm *newtime;
+ time_t long_time;
+
+ time( &long_time ); /* Get time as long integer. */
+ newtime = localtime( &long_time ); /* Convert to local time. */
+
+ rtcClockData.dataLen = 3;
+ rtcClockData.data[0] = toBCD(newtime->tm_hour);
+ rtcClockData.data[1] = toBCD(newtime->tm_min);
+ rtcClockData.data[2] = toBCD(newtime->tm_sec);
+ rtcClockData.state = DATA;
+ }
+ break;
+ default:
+ systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command);
+ rtcClockData.state = IDLE;
+ break;
+ }
+ }
+ break;
+ case DATA:
+ if(rtcClockData.byte1 & 2) {
+ } else {
+ rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
+ ((rtcClockData.data[rtcClockData.bits >> 3] >>
+ (rtcClockData.bits & 7)) & 1)*2;
+ rtcClockData.bits++;
+ if(rtcClockData.bits == 8*rtcClockData.dataLen) {
+ rtcClockData.bits = 0;
+ rtcClockData.state = IDLE;
+ }
+ }
+ break;
+ case READDATA:
+ if(!(rtcClockData.byte1 & 2)) {
+ } else {
+ rtcClockData.data[rtcClockData.bits >> 3] =
+ (rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
+ ((value << 6) & 128);
+ rtcClockData.bits++;
+ if(rtcClockData.bits == 8*rtcClockData.dataLen) {
+ rtcClockData.bits = 0;
+ rtcClockData.state = IDLE;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } else
+ rtcClockData.byte0 = (u8)value;
+ }
+ }
+ return true;
+}
+
+void rtcReset()
+{
+ memset(&rtcClockData, 0, sizeof(rtcClockData));
+
+ rtcClockData.byte0 = 0;
+ rtcClockData.byte1 = 0;
+ rtcClockData.byte2 = 0;
+ rtcClockData.command = 0;
+ rtcClockData.dataLen = 0;
+ rtcClockData.bits = 0;
+ rtcClockData.state = IDLE;
+}
+
+void rtcSaveGame(gzFile gzFile)
+{
+ utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
+}
+
+void rtcReadGame(gzFile gzFile)
+{
+ utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
+}
diff --git a/src/Sound.cpp b/src/Sound.cpp
index ec623c8a..178dc82b 100644
--- a/src/Sound.cpp
+++ b/src/Sound.cpp
@@ -659,40 +659,17 @@ void soundChannel4()
{
}
-#include
-
inline void soundDirectSoundA()
{
-#ifdef ENHANCED_RATE
- double cr = calc_rate(soundDSATimer);
- static int cnt = 0;
- static double lastcr = 0;
- static FILE *fp = NULL;
-
- if (fp==NULL)
- fp=fopen("C:\\cr.txt", "at");
- if (cr!=lastcr)
- {
- fprintf(fp, "%f %d\n", lastcr, cnt);
- cnt=0;
- lastcr=cr;
- }
- else
- cnt++;
-
- directBuffer[0][soundIndex] = interp_pop(0, calc_rate(soundDSATimer)); //soundDSAValue;
-#else
directBuffer[0][soundIndex] = interp_pop(0); //soundDSAValue;
-#endif
-
}
void soundDirectSoundATimer()
{
if(soundDSAEnabled) {
if(soundDSFifoACount <= 16) {
- cpuDmaHack2 = CPUCheckDMA(3, 2);
+ CPUCheckDMA(3, 2);
if(soundDSFifoACount <= 16) {
soundEvent(FIFOA_L, (u16)0);
soundEvent(FIFOA_H, (u16)0);
@@ -714,18 +691,15 @@ void soundDirectSoundATimer()
inline void soundDirectSoundB()
{
-#ifdef ENHANCED_RATE
- directBuffer[1][soundIndex] = interp_pop(1, calc_rate(soundDSBTimer)); //soundDSBValue;
-#else
directBuffer[1][soundIndex] = interp_pop(1); //soundDSBValue;
-#endif
}
void soundDirectSoundBTimer()
{
if(soundDSBEnabled) {
if(soundDSFifoBCount <= 16) {
- cpuDmaHack2 = CPUCheckDMA(3, 4);
+ //cpuDmaHack2 =
+ CPUCheckDMA(3, 4);
if(soundDSFifoBCount <= 16) {
soundEvent(FIFOB_L, (u16)0);
soundEvent(FIFOB_H, (u16)0);
diff --git a/src/Sound.h b/src/Sound.h
index d02d3838..ee808a34 100644
--- a/src/Sound.h
+++ b/src/Sound.h
@@ -2,6 +2,7 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2004-2006 VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -95,7 +96,6 @@ extern Multi_Buffer * apu_out;
extern Gb_Apu * apu;
extern const BOOST::uint8_t sound_data [Gb_Apu::register_count];
-
extern void interp_rate();
diff --git a/src/Sram.cpp b/src/Sram.cpp
index df582240..46e7108b 100644
--- a/src/Sram.cpp
+++ b/src/Sram.cpp
@@ -1,39 +1,39 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "GBA.h"
-#include "Globals.h"
-#include "Flash.h"
-#include "Sram.h"
-
-u8 sramRead(u32 address)
-{
- return flashSaveMemory[address & 0xFFFF];
-}
-void sramDelayedWrite(u32 address, u8 byte)
-{
- saveType = 1;
- cpuSaveGameFunc = sramWrite;
- sramWrite(address, byte);
-}
-
-void sramWrite(u32 address, u8 byte)
-{
- flashSaveMemory[address & 0xFFFF] = byte;
- systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "GBA.h"
+#include "Globals.h"
+#include "Flash.h"
+#include "Sram.h"
+
+u8 sramRead(u32 address)
+{
+ return flashSaveMemory[address & 0xFFFF];
+}
+void sramDelayedWrite(u32 address, u8 byte)
+{
+ saveType = 1;
+ cpuSaveGameFunc = sramWrite;
+ sramWrite(address, byte);
+}
+
+void sramWrite(u32 address, u8 byte)
+{
+ flashSaveMemory[address & 0xFFFF] = byte;
+ systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
+}
diff --git a/src/Sram.h b/src/Sram.h
index c8a90192..c4c7d257 100644
--- a/src/Sram.h
+++ b/src/Sram.h
@@ -1,27 +1,27 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_SRAM_H
-#define VBA_SRAM_H
-
-extern u8 sramRead(u32 address);
-extern void sramWrite(u32 address, u8 byte);
-extern void sramDelayedWrite(u32 address, u8 byte);
-
-#endif // VBA_SRAM_H
\ No newline at end of file
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_SRAM_H
+#define VBA_SRAM_H
+
+extern u8 sramRead(u32 address);
+extern void sramWrite(u32 address, u8 byte);
+extern void sramDelayedWrite(u32 address, u8 byte);
+
+#endif // VBA_SRAM_H
diff --git a/src/System.h b/src/System.h
index 2cc6d495..21dc21cc 100644
--- a/src/System.h
+++ b/src/System.h
@@ -106,6 +106,12 @@ extern void system10Frames(int);
extern void systemFrame();
extern void systemGbBorderOn();
+extern void Sm60FPS_Init();
+extern bool Sm60FPS_CanSkipFrame();
+extern void Sm60FPS_Sleep();
+extern void DbgMsg(const char *msg, ...);
+extern void winlog(const char *,...);
+
extern bool systemSoundOn;
extern u16 systemColorMap16[0x10000];
extern u32 systemColorMap32[0x10000];
@@ -118,6 +124,7 @@ extern int systemDebug;
extern int systemVerbose;
extern int systemFrameSkip;
extern int systemSaveUpdateCounter;
+extern int systemSpeed;
#define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0
diff --git a/src/Util.cpp b/src/Util.cpp
index 328ed142..9e3b7d91 100644
--- a/src/Util.cpp
+++ b/src/Util.cpp
@@ -1,1115 +1,1102 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-#include
-#include
-
-extern "C" {
-#include
-}
-
-#if 0
-#include "unrarlib.h"
-#endif
-
-#include "System.h"
-#include "NLS.h"
-#include "Util.h"
-#include "Flash.h"
-#include "GBA.h"
-#include "Globals.h"
-#include "RTC.h"
-#include "Port.h"
-#include "memgzio.h"
-#include "gbafilter.h"
-
-#ifndef _MSC_VER
-#define _stricmp strcasecmp
-#endif // ! _MSC_VER
-
-extern int systemColorDepth;
-extern int systemRedShift;
-extern int systemGreenShift;
-extern int systemBlueShift;
-
-extern u16 systemColorMap16[0x10000];
-extern u32 systemColorMap32[0x10000];
-
-static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
-static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
-static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
-
-bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
-{
- u8 writeBuffer[512 * 3];
-
- FILE *fp = fopen(fileName,"wb");
-
- if(!fp) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
- return false;
- }
-
- png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
- NULL,
- NULL,
- NULL);
- if(!png_ptr) {
- fclose(fp);
- return false;
- }
-
- png_infop info_ptr = png_create_info_struct(png_ptr);
-
- if(!info_ptr) {
- png_destroy_write_struct(&png_ptr,NULL);
- fclose(fp);
- return false;
- }
-
- if(setjmp(png_ptr->jmpbuf)) {
- png_destroy_write_struct(&png_ptr,NULL);
- fclose(fp);
- return false;
- }
-
- png_init_io(png_ptr,fp);
-
- png_set_IHDR(png_ptr,
- info_ptr,
- w,
- h,
- 8,
- PNG_COLOR_TYPE_RGB,
- PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
-
- png_write_info(png_ptr,info_ptr);
-
- u8 *b = writeBuffer;
-
- int sizeX = w;
- int sizeY = h;
-
- switch(systemColorDepth) {
- case 16:
- {
- u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- u16 v = *p++;
-
- *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
- *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
- *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
- }
- p++; // skip black pixel for filters
- p++; // skip black pixel for filters
- png_write_row(png_ptr,writeBuffer);
-
- b = writeBuffer;
- }
- }
- break;
- case 24:
- {
- u8 *pixU8 = (u8 *)pix;
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- if(systemRedShift < systemBlueShift) {
- *b++ = *pixU8++; // R
- *b++ = *pixU8++; // G
- *b++ = *pixU8++; // B
- } else {
- int blue = *pixU8++;
- int green = *pixU8++;
- int red = *pixU8++;
-
- *b++ = red;
- *b++ = green;
- *b++ = blue;
- }
- }
- png_write_row(png_ptr,writeBuffer);
-
- b = writeBuffer;
- }
- }
- break;
- case 32:
- {
- u32 *pixU32 = (u32 *)(pix+4*(w+1));
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- u32 v = *pixU32++;
-
- *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
- *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
- *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
- }
- pixU32++;
-
- png_write_row(png_ptr,writeBuffer);
-
- b = writeBuffer;
- }
- }
- break;
- }
-
- png_write_end(png_ptr, info_ptr);
-
- png_destroy_write_struct(&png_ptr, &info_ptr);
-
- fclose(fp);
-
- return true;
-}
-
-void utilPutDword(u8 *p, u32 value)
-{
- *p++ = value & 255;
- *p++ = (value >> 8) & 255;
- *p++ = (value >> 16) & 255;
- *p = (value >> 24) & 255;
-}
-
-void utilPutWord(u8 *p, u16 value)
-{
- *p++ = value & 255;
- *p = (value >> 8) & 255;
-}
-
-void utilWriteBMP(char *buf, int w, int h, u8 *pix)
-{
- u8 *b = (u8 *)buf;
-
- int sizeX = w;
- int sizeY = h;
-
- switch(systemColorDepth) {
- case 16:
- {
- u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- u16 v = *p++;
-
- *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
- *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
- *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
- }
- p++; // skip black pixel for filters
- p++; // skip black pixel for filters
- p -= 2*(w+2);
- }
- }
- break;
- case 24:
- {
- u8 *pixU8 = (u8 *)pix+3*w*(h-1);
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- if(systemRedShift > systemBlueShift) {
- *b++ = *pixU8++; // B
- *b++ = *pixU8++; // G
- *b++ = *pixU8++; // R
- } else {
- int red = *pixU8++;
- int green = *pixU8++;
- int blue = *pixU8++;
-
- *b++ = blue;
- *b++ = green;
- *b++ = red;
- }
- }
- pixU8 -= 2*3*w;
- }
- }
- break;
- case 32:
- {
- u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- u32 v = *pixU32++;
-
- *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
- *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
- *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
- }
- pixU32++;
- pixU32 -= 2*(w+1);
- }
- }
- break;
- }
-}
-
-bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
-{
- u8 writeBuffer[512 * 3];
-
- FILE *fp = fopen(fileName,"wb");
-
- if(!fp) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
- return false;
- }
-
- struct {
- u8 ident[2];
- u8 filesize[4];
- u8 reserved[4];
- u8 dataoffset[4];
- u8 headersize[4];
- u8 width[4];
- u8 height[4];
- u8 planes[2];
- u8 bitsperpixel[2];
- u8 compression[4];
- u8 datasize[4];
- u8 hres[4];
- u8 vres[4];
- u8 colors[4];
- u8 importantcolors[4];
- // u8 pad[2];
- } bmpheader;
- memset(&bmpheader, 0, sizeof(bmpheader));
-
- bmpheader.ident[0] = 'B';
- bmpheader.ident[1] = 'M';
-
- u32 fsz = sizeof(bmpheader) + w*h*3;
- utilPutDword(bmpheader.filesize, fsz);
- utilPutDword(bmpheader.dataoffset, 0x36);
- utilPutDword(bmpheader.headersize, 0x28);
- utilPutDword(bmpheader.width, w);
- utilPutDword(bmpheader.height, h);
- utilPutDword(bmpheader.planes, 1);
- utilPutDword(bmpheader.bitsperpixel, 24);
- utilPutDword(bmpheader.datasize, 3*w*h);
-
- fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
-
- u8 *b = writeBuffer;
-
- int sizeX = w;
- int sizeY = h;
-
- switch(systemColorDepth) {
- case 16:
- {
- u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- u16 v = *p++;
-
- *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
- *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
- *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
- }
- p++; // skip black pixel for filters
- p++; // skip black pixel for filters
- p -= 2*(w+2);
- fwrite(writeBuffer, 1, 3*w, fp);
-
- b = writeBuffer;
- }
- }
- break;
- case 24:
- {
- u8 *pixU8 = (u8 *)pix+3*w*(h-1);
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- if(systemRedShift > systemBlueShift) {
- *b++ = *pixU8++; // B
- *b++ = *pixU8++; // G
- *b++ = *pixU8++; // R
- } else {
- int red = *pixU8++;
- int green = *pixU8++;
- int blue = *pixU8++;
-
- *b++ = blue;
- *b++ = green;
- *b++ = red;
- }
- }
- pixU8 -= 2*3*w;
- fwrite(writeBuffer, 1, 3*w, fp);
-
- b = writeBuffer;
- }
- }
- break;
- case 32:
- {
- u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
- for(int y = 0; y < sizeY; y++) {
- for(int x = 0; x < sizeX; x++) {
- u32 v = *pixU32++;
-
- *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
- *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
- *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
- }
- pixU32++;
- pixU32 -= 2*(w+1);
-
- fwrite(writeBuffer, 1, 3*w, fp);
-
- b = writeBuffer;
- }
- }
- break;
- }
-
- fclose(fp);
-
- return true;
-}
-
-static int utilReadInt2(FILE *f)
-{
- int res = 0;
- int c = fgetc(f);
- if(c == EOF)
- return -1;
- res = c;
- c = fgetc(f);
- if(c == EOF)
- return -1;
- return c + (res<<8);
-}
-
-static int utilReadInt3(FILE *f)
-{
- int res = 0;
- int c = fgetc(f);
- if(c == EOF)
- return -1;
- res = c;
- c = fgetc(f);
- if(c == EOF)
- return -1;
- res = c + (res<<8);
- c = fgetc(f);
- if(c == EOF)
- return -1;
- return c + (res<<8);
-}
-
-void utilApplyIPS(const char *ips, u8 **r, int *s)
-{
- // from the IPS spec at http://zerosoft.zophar.net/ips.htm
- FILE *f = fopen(ips, "rb");
- if(!f)
- return;
- u8 *rom = *r;
- int size = *s;
- if(fgetc(f) == 'P' &&
- fgetc(f) == 'A' &&
- fgetc(f) == 'T' &&
- fgetc(f) == 'C' &&
- fgetc(f) == 'H') {
- int b;
- int offset;
- int len;
- for(;;) {
- // read offset
- offset = utilReadInt3(f);
- // if offset == EOF, end of patch
- if(offset == 0x454f46)
- break;
- // read length
- len = utilReadInt2(f);
- if(!len) {
- // len == 0, RLE block
- len = utilReadInt2(f);
- // byte to fill
- int c = fgetc(f);
- if(c == -1)
- break;
- b = (u8)c;
- } else
- b= -1;
- // check if we need to reallocate our ROM
- if((offset + len) >= size) {
- size *= 2;
- rom = (u8 *)realloc(rom, size);
- *r = rom;
- *s = size;
- }
- if(b == -1) {
- // normal block, just read the data
- if(fread(&rom[offset], 1, len, f) != (size_t)len)
- break;
- } else {
- // fill the region with the given byte
- while(len--) {
- rom[offset++] = b;
- }
- }
- }
- }
- // close the file
- fclose(f);
-}
-
-extern bool cpuIsMultiBoot;
-
-bool utilIsGBAImage(const char * file)
-{
- cpuIsMultiBoot = false;
- if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".gba") == 0)
- return true;
- if(_stricmp(p, ".agb") == 0)
- return true;
- if(_stricmp(p, ".bin") == 0)
- return true;
- if(_stricmp(p, ".elf") == 0)
- return true;
- if(_stricmp(p, ".mb") == 0) {
- cpuIsMultiBoot = true;
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool utilIsGBImage(const char * file)
-{
- if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".gb") == 0)
- return true;
- if(_stricmp(p, ".gbc") == 0)
- return true;
- if(_stricmp(p, ".cgb") == 0)
- return true;
- if(_stricmp(p, ".sgb") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-bool utilIsZipFile(const char *file)
-{
- if(strlen(file) > 4) {
- char * p = (char *)strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".zip") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-#if 0
-bool utilIsRarFile(const char *file)
-{
- if(strlen(file) > 4) {
- const char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".rar") == 0)
- return true;
- }
- }
-
- return false;
-}
-#endif
-
-bool utilIs7ZipFile(const char *file)
-{
- if(strlen(file) > 3) {
- const char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".7z") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-bool utilIsGzipFile(const char *file)
-{
- if(strlen(file) > 3) {
- char * p = (char *)strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".gz") == 0)
- return true;
- if(_stricmp(p, ".z") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-void utilGetBaseName(const char *file, char *buffer)
-{
- strcpy(buffer, file);
-
- if(utilIsGzipFile(file)) {
- char *p = strrchr(buffer, '.');
-
- if(p)
- *p = 0;
- }
-}
-
-IMAGE_TYPE utilFindType(const char *file)
-{
- char buffer[2048];
-
- if(utilIsZipFile(file)) {
- unzFile unz = unzOpen(file);
-
- if(unz == NULL) {
- systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
- return IMAGE_UNKNOWN;
- }
-
- int r = unzGoToFirstFile(unz);
-
- if(r != UNZ_OK) {
- unzClose(unz);
- systemMessage(MSG_BAD_ARCHIVE_FILE, N_("Bad ZIP file %s"), file);
- return IMAGE_UNKNOWN;
- }
-
- IMAGE_TYPE found = IMAGE_UNKNOWN;
-
- unz_file_info info;
-
- while(true) {
- r = unzGetCurrentFileInfo(unz,
- &info,
- buffer,
- sizeof(buffer),
- NULL,
- 0,
- NULL,
- 0);
-
- if(r != UNZ_OK) {
- unzClose(unz);
- systemMessage(MSG_BAD_ARCHIVE_FILE, N_("Bad ZIP file %s"), file);
- return IMAGE_UNKNOWN;
- }
-
- if(utilIsGBAImage(buffer)) {
- found = IMAGE_GBA;
- break;
- }
-
- if(utilIsGBImage(buffer)) {
- found = IMAGE_GB;
- break;
- }
-
- r = unzGoToNextFile(unz);
-
- if(r != UNZ_OK)
- break;
- }
- unzClose(unz);
-
- if(found == IMAGE_UNKNOWN) {
- systemMessage(MSG_NO_IMAGE_ON_ARCHIVE,
- N_("No image found on ZIP file %s"), file);
- return found;
- }
- return found;
-#if 0
- } else if(utilIsRarFile(file)) {
- IMAGE_TYPE found = IMAGE_UNKNOWN;
-
- ArchiveList_struct *rarList = NULL;
- if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
- ArchiveList_struct *p = rarList;
-
- while(p) {
- if(utilIsGBAImage(p->item.Name)) {
- found = IMAGE_GBA;
- break;
- }
-
- if(utilIsGBImage(p->item.Name)) {
- found = IMAGE_GB;
- break;
- }
- p = p->next;
- }
-
- urarlib_freelist(rarList);
- }
- return found;
-#endif
- } else {
- if(utilIsGzipFile(file))
- utilGetBaseName(file, buffer);
- else
- strcpy(buffer, file);
-
- if(utilIsGBAImage(buffer))
- return IMAGE_GBA;
- if(utilIsGBImage(buffer))
- return IMAGE_GB;
- }
- return IMAGE_UNKNOWN;
-}
-
-static int utilGetSize(int size)
-{
- int res = 1;
- while(res < size)
- res <<= 1;
- return res;
-}
-
-static u8 *utilLoadFromZip(const char *file,
- bool (*accept)(const char *),
- u8 *data,
- int &size)
-{
- char buffer[2048];
-
- unzFile unz = unzOpen(file);
-
- if(unz == NULL) {
- systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
- return NULL;
- }
- int r = unzGoToFirstFile(unz);
-
- if(r != UNZ_OK) {
- unzClose(unz);
- systemMessage(MSG_BAD_ARCHIVE_FILE, N_("Bad ZIP file %s"), file);
- return NULL;
- }
-
- bool found = false;
-
- unz_file_info info;
-
- while(true) {
- r = unzGetCurrentFileInfo(unz,
- &info,
- buffer,
- sizeof(buffer),
- NULL,
- 0,
- NULL,
- 0);
-
- if(r != UNZ_OK) {
- unzClose(unz);
- systemMessage(MSG_BAD_ARCHIVE_FILE, N_("Bad ZIP file %s"), file);
- return NULL;
- }
-
- if(accept(buffer)) {
- found = true;
- break;
- }
-
- r = unzGoToNextFile(unz);
-
- if(r != UNZ_OK)
- break;
- }
-
- if(!found) {
- unzClose(unz);
- systemMessage(MSG_NO_IMAGE_ON_ARCHIVE,
- N_("No image found on ZIP file %s"), file);
- return NULL;
- }
-
- int fileSize = info.uncompressed_size;
- if(size == 0)
- size = fileSize;
- r = unzOpenCurrentFile(unz);
-
- if(r != UNZ_OK) {
- unzClose(unz);
- systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
- return NULL;
- }
-
- u8 *image = data;
-
- if(image == NULL) {
- image = (u8 *)malloc(utilGetSize(size));
- if(image == NULL) {
- unzCloseCurrentFile(unz);
- unzClose(unz);
- systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "data");
- return NULL;
- }
- size = fileSize;
- }
- int read = fileSize <= size ? fileSize : size;
- r = unzReadCurrentFile(unz,
- image,
- read);
-
- unzCloseCurrentFile(unz);
- unzClose(unz);
-
- if(r != (int)read) {
- systemMessage(MSG_ERROR_READING_IMAGE,
- N_("Error reading image %s"), buffer);
- if(data == NULL)
- free(image);
- return NULL;
- }
-
- size = fileSize;
-
- return image;
-}
-
-static u8 *utilLoadGzipFile(const char *file,
- bool (*accept)(const char *),
- u8 *data,
- int &size)
-{
- FILE *f = fopen(file, "rb");
-
- if(f == NULL) {
- systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
- return NULL;
- }
-
- fseek(f, -4, SEEK_END);
- int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
- fclose(f);
- if(size == 0)
- size = fileSize;
-
- gzFile gz = gzopen(file, "rb");
-
- if(gz == NULL) {
- // should not happen, but who knows?
- systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
- return NULL;
- }
-
- u8 *image = data;
-
- if(image == NULL) {
- image = (u8 *)malloc(utilGetSize(size));
- if(image == NULL) {
- systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "data");
- fclose(f);
- return NULL;
- }
- size = fileSize;
- }
- int read = fileSize <= size ? fileSize : size;
- int r = gzread(gz, image, read);
- gzclose(gz);
-
- if(r != (int)read) {
- systemMessage(MSG_ERROR_READING_IMAGE,
- N_("Error reading image %s"), file);
- if(data == NULL)
- free(image);
- return NULL;
- }
-
- size = fileSize;
-
- return image;
-}
-
-#if 0
-static u8 *utilLoadRarFile(const char *file,
- bool (*accept)(const char *),
- u8 *data,
- int &size)
-{
- char buffer[2048];
-
- ArchiveList_struct *rarList = NULL;
- if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
- ArchiveList_struct *p = rarList;
-
- bool found = false;
- while(p) {
- if(accept(p->item.Name)) {
- strcpy(buffer, p->item.Name);
- found = true;
- break;
- }
- p = p->next;
- }
- if(found) {
- void *memory = NULL;
- unsigned long lsize = 0;
- size = p->item.UnpSize;
- int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
- if(!r) {
- systemMessage(MSG_ERROR_READING_IMAGE,
- N_("Error reading image %s"), buffer);
- urarlib_freelist(rarList);
- return NULL;
- }
- u8 *image = (u8 *)memory;
- if(data != NULL) {
- memcpy(image, data, size);
- }
- urarlib_freelist(rarList);
- return image;
- }
- systemMessage(MSG_NO_IMAGE_ON_ZIP,
- N_("No image found on RAR file %s"), file);
- urarlib_freelist(rarList);
- return NULL;
- }
- // nothing found
- return NULL;
-}
-#endif
-
-u8 *utilLoad(const char *file,
- bool (*accept)(const char *),
- u8 *data,
- int &size)
-{
- if(utilIsZipFile(file)) {
- return utilLoadFromZip(file, accept, data, size);
- }
- if(utilIsGzipFile(file)) {
- return utilLoadGzipFile(file, accept, data, size);
- }
-#if 0
- if(utilIsRarFile(file)) {
- return utilLoadRarFile(file, accept, data, size);
- }
-#endif
-
- u8 *image = data;
-
- FILE *f = fopen(file, "rb");
-
- if(!f) {
- systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
- return NULL;
- }
-
- fseek(f,0,SEEK_END);
- int fileSize = ftell(f);
- fseek(f,0,SEEK_SET);
- if(size == 0)
- size = fileSize;
-
- if(image == NULL) {
- image = (u8 *)malloc(utilGetSize(size));
- if(image == NULL) {
- systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "data");
- fclose(f);
- return NULL;
- }
- size = fileSize;
- }
- int read = fileSize <= size ? fileSize : size;
- int r = fread(image, 1, read, f);
- fclose(f);
-
- if(r != (int)read) {
- systemMessage(MSG_ERROR_READING_IMAGE,
- N_("Error reading image %s"), file);
- if(data == NULL)
- free(image);
- return NULL;
- }
-
- size = fileSize;
-
- return image;
-}
-
-void utilWriteInt(gzFile gzFile, int i)
-{
- utilGzWrite(gzFile, &i, sizeof(int));
-}
-
-int utilReadInt(gzFile gzFile)
-{
- int i = 0;
- utilGzRead(gzFile, &i, sizeof(int));
- return i;
-}
-
-void utilReadData(gzFile gzFile, variable_desc* data)
-{
- while(data->address) {
- utilGzRead(gzFile, data->address, data->size);
- data++;
- }
-}
-
-void utilWriteData(gzFile gzFile, variable_desc *data)
-{
- while(data->address) {
- utilGzWrite(gzFile, data->address, data->size);
- data++;
- }
-}
-
-gzFile utilGzOpen(const char *file, const char *mode)
-{
- utilGzWriteFunc = (int (ZEXPORT *)(void *,void * const, unsigned int))gzwrite;
- utilGzReadFunc = gzread;
- utilGzCloseFunc = gzclose;
-
- return gzopen(file, mode);
-}
-
-gzFile utilMemGzOpen(char *memory, int available, char *mode)
-{
- utilGzWriteFunc = memgzwrite;
- utilGzReadFunc = memgzread;
- utilGzCloseFunc = memgzclose;
-
- return memgzopen(memory, available, mode);
-}
-
-int utilGzWrite(gzFile file, const voidp buffer, unsigned int len)
-{
- return utilGzWriteFunc(file, buffer, len);
-}
-
-int utilGzRead(gzFile file, voidp buffer, unsigned int len)
-{
- return utilGzReadFunc(file, buffer, len);
-}
-
-int utilGzClose(gzFile file)
-{
- return utilGzCloseFunc(file);
-}
-
-long utilGzMemTell(gzFile file)
-{
- return memtell(file);
-}
-
-void utilGBAFindSave(const u8 *data, const int size)
-{
- u32 *p = (u32 *)data;
- u32 *end = (u32 *)(data + size);
- int saveType = 0;
- int flashSize = 0x10000;
- bool rtcFound = false;
-
- while(p < end) {
- u32 d = READ32LE(p);
-
- if(d == 0x52504545) {
- if(memcmp(p, "EEPROM_", 7) == 0) {
- if(saveType == 0)
- saveType = 1;
- }
- } else if (d == 0x4D415253) {
- if(memcmp(p, "SRAM_", 5) == 0) {
- if(saveType == 0)
- saveType = 2;
- }
- } else if (d == 0x53414C46) {
- if(memcmp(p, "FLASH1M_", 8) == 0) {
- if(saveType == 0) {
- saveType = 3;
- flashSize = 0x20000;
- }
- } else if(memcmp(p, "FLASH", 5) == 0) {
- if(saveType == 0) {
- saveType = 3;
- flashSize = 0x10000;
- }
- }
- } else if (d == 0x52494953) {
- if(memcmp(p, "SIIRTC_V", 8) == 0)
- rtcFound = true;
- }
- p++;
- }
- // if no matches found, then set it to NONE
- if(saveType == 0) {
- saveType = 5;
- }
- rtcEnable(rtcFound);
- cpuSaveType = saveType;
- flashSetSize(flashSize);
-}
-
-void utilUpdateSystemColorMaps(int lcd)
-{
- switch(systemColorDepth) {
- case 16:
- {
- for(int i = 0; i < 0x10000; i++) {
- systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
- (((i & 0x3e0) >> 5) << systemGreenShift) |
- (((i & 0x7c00) >> 10) << systemBlueShift);
- }
- if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000);
- }
- break;
- case 24:
- case 32:
- {
- for(int i = 0; i < 0x10000; i++) {
- systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
- (((i & 0x3e0) >> 5) << systemGreenShift) |
- (((i & 0x7c00) >> 10) << systemBlueShift);
- }
- if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000);
- }
- break;
- }
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+#include
+#include
+
+extern "C" {
+#include
+}
+
+#if 0
+#include "unrarlib.h"
+#endif
+
+#include "System.h"
+#include "NLS.h"
+#include "Util.h"
+#include "Flash.h"
+#include "GBA.h"
+#include "Globals.h"
+#include "RTC.h"
+#include "Port.h"
+
+
+extern "C" {
+#include "memgzio.h"
+}
+
+#ifndef _MSC_VER
+#define _stricmp strcasecmp
+#endif // ! _MSC_VER
+
+extern int systemColorDepth;
+extern int systemRedShift;
+extern int systemGreenShift;
+extern int systemBlueShift;
+
+extern u16 systemColorMap16[0x10000];
+extern u32 systemColorMap32[0x10000];
+
+static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
+static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
+static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
+
+bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
+{
+ u8 writeBuffer[512 * 3];
+
+ FILE *fp = fopen(fileName,"wb");
+
+ if(!fp) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
+ return false;
+ }
+
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL,
+ NULL,
+ NULL);
+ if(!png_ptr) {
+ fclose(fp);
+ return false;
+ }
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+
+ if(!info_ptr) {
+ png_destroy_write_struct(&png_ptr,NULL);
+ fclose(fp);
+ return false;
+ }
+
+ if(setjmp(png_ptr->jmpbuf)) {
+ png_destroy_write_struct(&png_ptr,NULL);
+ fclose(fp);
+ return false;
+ }
+
+ png_init_io(png_ptr,fp);
+
+ png_set_IHDR(png_ptr,
+ info_ptr,
+ w,
+ h,
+ 8,
+ PNG_COLOR_TYPE_RGB,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+ png_write_info(png_ptr,info_ptr);
+
+ u8 *b = writeBuffer;
+
+ int sizeX = w;
+ int sizeY = h;
+
+ switch(systemColorDepth) {
+ case 16:
+ {
+ u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ u16 v = *p++;
+
+ *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
+ *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
+ *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
+ }
+ p++; // skip black pixel for filters
+ p++; // skip black pixel for filters
+ png_write_row(png_ptr,writeBuffer);
+
+ b = writeBuffer;
+ }
+ }
+ break;
+ case 24:
+ {
+ u8 *pixU8 = (u8 *)pix;
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ if(systemRedShift < systemBlueShift) {
+ *b++ = *pixU8++; // R
+ *b++ = *pixU8++; // G
+ *b++ = *pixU8++; // B
+ } else {
+ int blue = *pixU8++;
+ int green = *pixU8++;
+ int red = *pixU8++;
+
+ *b++ = red;
+ *b++ = green;
+ *b++ = blue;
+ }
+ }
+ png_write_row(png_ptr,writeBuffer);
+
+ b = writeBuffer;
+ }
+ }
+ break;
+ case 32:
+ {
+ u32 *pixU32 = (u32 *)(pix+4*(w+1));
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ u32 v = *pixU32++;
+
+ *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
+ *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
+ *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
+ }
+ pixU32++;
+
+ png_write_row(png_ptr,writeBuffer);
+
+ b = writeBuffer;
+ }
+ }
+ break;
+ }
+
+ png_write_end(png_ptr, info_ptr);
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ fclose(fp);
+
+ return true;
+}
+
+void utilPutDword(u8 *p, u32 value)
+{
+ *p++ = value & 255;
+ *p++ = (value >> 8) & 255;
+ *p++ = (value >> 16) & 255;
+ *p = (value >> 24) & 255;
+}
+
+void utilPutWord(u8 *p, u16 value)
+{
+ *p++ = value & 255;
+ *p = (value >> 8) & 255;
+}
+
+void utilWriteBMP(char *buf, int w, int h, u8 *pix)
+{
+ u8 *b = (u8 *)buf;
+
+ int sizeX = w;
+ int sizeY = h;
+
+ switch(systemColorDepth) {
+ case 16:
+ {
+ u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ u16 v = *p++;
+
+ *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
+ *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
+ *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
+ }
+ p++; // skip black pixel for filters
+ p++; // skip black pixel for filters
+ p -= 2*(w+2);
+ }
+ }
+ break;
+ case 24:
+ {
+ u8 *pixU8 = (u8 *)pix+3*w*(h-1);
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ if(systemRedShift > systemBlueShift) {
+ *b++ = *pixU8++; // B
+ *b++ = *pixU8++; // G
+ *b++ = *pixU8++; // R
+ } else {
+ int red = *pixU8++;
+ int green = *pixU8++;
+ int blue = *pixU8++;
+
+ *b++ = blue;
+ *b++ = green;
+ *b++ = red;
+ }
+ }
+ pixU8 -= 2*3*w;
+ }
+ }
+ break;
+ case 32:
+ {
+ u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ u32 v = *pixU32++;
+
+ *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
+ *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
+ *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
+ }
+ pixU32++;
+ pixU32 -= 2*(w+1);
+ }
+ }
+ break;
+ }
+}
+
+bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
+{
+ u8 writeBuffer[512 * 3];
+
+ FILE *fp = fopen(fileName,"wb");
+
+ if(!fp) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
+ return false;
+ }
+
+ struct {
+ u8 ident[2];
+ u8 filesize[4];
+ u8 reserved[4];
+ u8 dataoffset[4];
+ u8 headersize[4];
+ u8 width[4];
+ u8 height[4];
+ u8 planes[2];
+ u8 bitsperpixel[2];
+ u8 compression[4];
+ u8 datasize[4];
+ u8 hres[4];
+ u8 vres[4];
+ u8 colors[4];
+ u8 importantcolors[4];
+ // u8 pad[2];
+ } bmpheader;
+ memset(&bmpheader, 0, sizeof(bmpheader));
+
+ bmpheader.ident[0] = 'B';
+ bmpheader.ident[1] = 'M';
+
+ u32 fsz = sizeof(bmpheader) + w*h*3;
+ utilPutDword(bmpheader.filesize, fsz);
+ utilPutDword(bmpheader.dataoffset, 0x36);
+ utilPutDword(bmpheader.headersize, 0x28);
+ utilPutDword(bmpheader.width, w);
+ utilPutDword(bmpheader.height, h);
+ utilPutDword(bmpheader.planes, 1);
+ utilPutDword(bmpheader.bitsperpixel, 24);
+ utilPutDword(bmpheader.datasize, 3*w*h);
+
+ fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
+
+ u8 *b = writeBuffer;
+
+ int sizeX = w;
+ int sizeY = h;
+
+ switch(systemColorDepth) {
+ case 16:
+ {
+ u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ u16 v = *p++;
+
+ *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
+ *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
+ *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
+ }
+ p++; // skip black pixel for filters
+ p++; // skip black pixel for filters
+ p -= 2*(w+2);
+ fwrite(writeBuffer, 1, 3*w, fp);
+
+ b = writeBuffer;
+ }
+ }
+ break;
+ case 24:
+ {
+ u8 *pixU8 = (u8 *)pix+3*w*(h-1);
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ if(systemRedShift > systemBlueShift) {
+ *b++ = *pixU8++; // B
+ *b++ = *pixU8++; // G
+ *b++ = *pixU8++; // R
+ } else {
+ int red = *pixU8++;
+ int green = *pixU8++;
+ int blue = *pixU8++;
+
+ *b++ = blue;
+ *b++ = green;
+ *b++ = red;
+ }
+ }
+ pixU8 -= 2*3*w;
+ fwrite(writeBuffer, 1, 3*w, fp);
+
+ b = writeBuffer;
+ }
+ }
+ break;
+ case 32:
+ {
+ u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
+ for(int y = 0; y < sizeY; y++) {
+ for(int x = 0; x < sizeX; x++) {
+ u32 v = *pixU32++;
+
+ *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
+ *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
+ *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
+ }
+ pixU32++;
+ pixU32 -= 2*(w+1);
+
+ fwrite(writeBuffer, 1, 3*w, fp);
+
+ b = writeBuffer;
+ }
+ }
+ break;
+ }
+
+ fclose(fp);
+
+ return true;
+}
+
+static int utilReadInt2(FILE *f)
+{
+ int res = 0;
+ int c = fgetc(f);
+ if(c == EOF)
+ return -1;
+ res = c;
+ c = fgetc(f);
+ if(c == EOF)
+ return -1;
+ return c + (res<<8);
+}
+
+static int utilReadInt3(FILE *f)
+{
+ int res = 0;
+ int c = fgetc(f);
+ if(c == EOF)
+ return -1;
+ res = c;
+ c = fgetc(f);
+ if(c == EOF)
+ return -1;
+ res = c + (res<<8);
+ c = fgetc(f);
+ if(c == EOF)
+ return -1;
+ return c + (res<<8);
+}
+
+void utilApplyIPS(const char *ips, u8 **r, int *s)
+{
+ // from the IPS spec at http://zerosoft.zophar.net/ips.htm
+ FILE *f = fopen(ips, "rb");
+ if(!f)
+ return;
+ u8 *rom = *r;
+ int size = *s;
+ if(fgetc(f) == 'P' &&
+ fgetc(f) == 'A' &&
+ fgetc(f) == 'T' &&
+ fgetc(f) == 'C' &&
+ fgetc(f) == 'H') {
+ int b;
+ int offset;
+ int len;
+ for(;;) {
+ // read offset
+ offset = utilReadInt3(f);
+ // if offset == EOF, end of patch
+ if(offset == 0x454f46)
+ break;
+ // read length
+ len = utilReadInt2(f);
+ if(!len) {
+ // len == 0, RLE block
+ len = utilReadInt2(f);
+ // byte to fill
+ int c = fgetc(f);
+ if(c == -1)
+ break;
+ b = (u8)c;
+ } else
+ b= -1;
+ // check if we need to reallocate our ROM
+ if((offset + len) >= size) {
+ size *= 2;
+ rom = (u8 *)realloc(rom, size);
+ *r = rom;
+ *s = size;
+ }
+ if(b == -1) {
+ // normal block, just read the data
+ if(fread(&rom[offset], 1, len, f) != (size_t)len)
+ break;
+ } else {
+ // fill the region with the given byte
+ while(len--) {
+ rom[offset++] = b;
+ }
+ }
+ }
+ }
+ // close the file
+ fclose(f);
+}
+
+extern bool cpuIsMultiBoot;
+
+bool utilIsGBAImage(const char * file)
+{
+ cpuIsMultiBoot = false;
+ if(strlen(file) > 4) {
+ const char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".gba") == 0)
+ return true;
+ if(_stricmp(p, ".agb") == 0)
+ return true;
+ if(_stricmp(p, ".bin") == 0)
+ return true;
+ if(_stricmp(p, ".elf") == 0)
+ return true;
+ if(_stricmp(p, ".mb") == 0) {
+ cpuIsMultiBoot = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool utilIsGBImage(const char * file)
+{
+ if(strlen(file) > 4) {
+ const char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".gb") == 0)
+ return true;
+ if(_stricmp(p, ".gbc") == 0)
+ return true;
+ if(_stricmp(p, ".cgb") == 0)
+ return true;
+ if(_stricmp(p, ".sgb") == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool utilIsZipFile(const char *file)
+{
+ if(strlen(file) > 4) {
+ const char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".zip") == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#if 0
+bool utilIsRarFile(const char *file)
+{
+ if(strlen(file) > 4) {
+ char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".rar") == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
+bool utilIsGzipFile(const char *file)
+{
+ if(strlen(file) > 3) {
+ const char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".gz") == 0)
+ return true;
+ if(_stricmp(p, ".z") == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void utilGetBaseName(const char *file, char *buffer)
+{
+ strcpy(buffer, file);
+
+ if(utilIsGzipFile(file)) {
+ char *p = strrchr(buffer, '.');
+
+ if(p)
+ *p = 0;
+ }
+}
+
+IMAGE_TYPE utilFindType(const char *file)
+{
+ char buffer[2048];
+
+ if(utilIsZipFile(file)) {
+ unzFile unz = unzOpen(file);
+
+ if(unz == NULL) {
+ systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
+ return IMAGE_UNKNOWN;
+ }
+
+ int r = unzGoToFirstFile(unz);
+
+ if(r != UNZ_OK) {
+ unzClose(unz);
+ systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
+ return IMAGE_UNKNOWN;
+ }
+
+ IMAGE_TYPE found = IMAGE_UNKNOWN;
+
+ unz_file_info info;
+
+ while(true) {
+ r = unzGetCurrentFileInfo(unz,
+ &info,
+ buffer,
+ sizeof(buffer),
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ if(r != UNZ_OK) {
+ unzClose(unz);
+ systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
+ return IMAGE_UNKNOWN;
+ }
+
+ if(utilIsGBAImage(buffer)) {
+ found = IMAGE_GBA;
+ break;
+ }
+
+ if(utilIsGBImage(buffer)) {
+ found = IMAGE_GB;
+ break;
+ }
+
+ r = unzGoToNextFile(unz);
+
+ if(r != UNZ_OK)
+ break;
+ }
+ unzClose(unz);
+
+ if(found == IMAGE_UNKNOWN) {
+ systemMessage(MSG_NO_IMAGE_ON_ZIP,
+ N_("No image found on ZIP file %s"), file);
+ return found;
+ }
+ return found;
+#if 0
+ } else if(utilIsRarFile(file)) {
+ IMAGE_TYPE found = IMAGE_UNKNOWN;
+
+ ArchiveList_struct *rarList = NULL;
+ if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
+ ArchiveList_struct *p = rarList;
+
+ while(p) {
+ if(utilIsGBAImage(p->item.Name)) {
+ found = IMAGE_GBA;
+ break;
+ }
+
+ if(utilIsGBImage(p->item.Name)) {
+ found = IMAGE_GB;
+ break;
+ }
+ p = p->next;
+ }
+
+ urarlib_freelist(rarList);
+ }
+ return found;
+#endif
+ } else {
+ if(utilIsGzipFile(file))
+ utilGetBaseName(file, buffer);
+ else
+ strcpy(buffer, file);
+
+ if(utilIsGBAImage(buffer))
+ return IMAGE_GBA;
+ if(utilIsGBImage(buffer))
+ return IMAGE_GB;
+ }
+ return IMAGE_UNKNOWN;
+}
+
+static int utilGetSize(int size)
+{
+ int res = 1;
+ while(res < size)
+ res <<= 1;
+ return res;
+}
+
+static u8 *utilLoadFromZip(const char *file,
+ bool (*accept)(const char *),
+ u8 *data,
+ int &size)
+{
+ char buffer[2048];
+
+ unzFile unz = unzOpen(file);
+
+ if(unz == NULL) {
+ systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
+ return NULL;
+ }
+ int r = unzGoToFirstFile(unz);
+
+ if(r != UNZ_OK) {
+ unzClose(unz);
+ systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
+ return NULL;
+ }
+
+ bool found = false;
+
+ unz_file_info info;
+
+ while(true) {
+ r = unzGetCurrentFileInfo(unz,
+ &info,
+ buffer,
+ sizeof(buffer),
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ if(r != UNZ_OK) {
+ unzClose(unz);
+ systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
+ return NULL;
+ }
+
+ if(accept(buffer)) {
+ found = true;
+ break;
+ }
+
+ r = unzGoToNextFile(unz);
+
+ if(r != UNZ_OK)
+ break;
+ }
+
+ if(!found) {
+ unzClose(unz);
+ systemMessage(MSG_NO_IMAGE_ON_ZIP,
+ N_("No image found on ZIP file %s"), file);
+ return NULL;
+ }
+
+ int fileSize = info.uncompressed_size;
+ if(size == 0)
+ size = fileSize;
+ r = unzOpenCurrentFile(unz);
+
+ if(r != UNZ_OK) {
+ unzClose(unz);
+ systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
+ return NULL;
+ }
+
+ u8 *image = data;
+
+ if(image == NULL) {
+ image = (u8 *)malloc(utilGetSize(size));
+ if(image == NULL) {
+ unzCloseCurrentFile(unz);
+ unzClose(unz);
+ systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
+ "data");
+ return NULL;
+ }
+ size = fileSize;
+ }
+ int read = fileSize <= size ? fileSize : size;
+ r = unzReadCurrentFile(unz,
+ image,
+ read);
+
+ unzCloseCurrentFile(unz);
+ unzClose(unz);
+
+ if(r != (int)read) {
+ systemMessage(MSG_ERROR_READING_IMAGE,
+ N_("Error reading image %s"), buffer);
+ if(data == NULL)
+ free(image);
+ return NULL;
+ }
+
+ size = fileSize;
+
+ return image;
+}
+
+static u8 *utilLoadGzipFile(const char *file,
+ bool (*accept)(const char *),
+ u8 *data,
+ int &size)
+{
+ FILE *f = fopen(file, "rb");
+
+ if(f == NULL) {
+ systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
+ return NULL;
+ }
+
+ fseek(f, -4, SEEK_END);
+ int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
+ fclose(f);
+ if(size == 0)
+ size = fileSize;
+
+ gzFile gz = gzopen(file, "rb");
+
+ if(gz == NULL) {
+ // should not happen, but who knows?
+ systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
+ return NULL;
+ }
+
+ u8 *image = data;
+
+ if(image == NULL) {
+ image = (u8 *)malloc(utilGetSize(size));
+ if(image == NULL) {
+ systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
+ "data");
+ fclose(f);
+ return NULL;
+ }
+ size = fileSize;
+ }
+ int read = fileSize <= size ? fileSize : size;
+ int r = gzread(gz, image, read);
+ gzclose(gz);
+
+ if(r != (int)read) {
+ systemMessage(MSG_ERROR_READING_IMAGE,
+ N_("Error reading image %s"), file);
+ if(data == NULL)
+ free(image);
+ return NULL;
+ }
+
+ size = fileSize;
+
+ return image;
+}
+
+#if 0
+static u8 *utilLoadRarFile(const char *file,
+ bool (*accept)(const char *),
+ u8 *data,
+ int &size)
+{
+ char buffer[2048];
+
+ ArchiveList_struct *rarList = NULL;
+ if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
+ ArchiveList_struct *p = rarList;
+
+ bool found = false;
+ while(p) {
+ if(accept(p->item.Name)) {
+ strcpy(buffer, p->item.Name);
+ found = true;
+ break;
+ }
+ p = p->next;
+ }
+ if(found) {
+ void *memory = NULL;
+ unsigned long lsize = 0;
+ size = p->item.UnpSize;
+ int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
+ if(!r) {
+ systemMessage(MSG_ERROR_READING_IMAGE,
+ N_("Error reading image %s"), buffer);
+ urarlib_freelist(rarList);
+ return NULL;
+ }
+ u8 *image = (u8 *)memory;
+ if(data != NULL) {
+ memcpy(image, data, size);
+ }
+ urarlib_freelist(rarList);
+ return image;
+ }
+ systemMessage(MSG_NO_IMAGE_ON_ZIP,
+ N_("No image found on RAR file %s"), file);
+ urarlib_freelist(rarList);
+ return NULL;
+ }
+ // nothing found
+ return NULL;
+}
+#endif
+
+u8 *utilLoad(const char *file,
+ bool (*accept)(const char *),
+ u8 *data,
+ int &size)
+{
+ if(utilIsZipFile(file)) {
+ return utilLoadFromZip(file, accept, data, size);
+ }
+ if(utilIsGzipFile(file)) {
+ return utilLoadGzipFile(file, accept, data, size);
+ }
+#if 0
+ if(utilIsRarFile(file)) {
+ return utilLoadRarFile(file, accept, data, size);
+ }
+#endif
+
+ u8 *image = data;
+
+ FILE *f = fopen(file, "rb");
+
+ if(!f) {
+ systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
+ return NULL;
+ }
+
+ fseek(f,0,SEEK_END);
+ int fileSize = ftell(f);
+ fseek(f,0,SEEK_SET);
+ if(size == 0)
+ size = fileSize;
+
+ if(image == NULL) {
+ image = (u8 *)malloc(utilGetSize(size));
+ if(image == NULL) {
+ systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
+ "data");
+ fclose(f);
+ return NULL;
+ }
+ size = fileSize;
+ }
+ size_t read = fileSize <= size ? fileSize : size;
+ size_t r = fread(image, 1, read, f);
+ fclose(f);
+
+ if(r != read) {
+ systemMessage(MSG_ERROR_READING_IMAGE,
+ N_("Error reading image %s"), file);
+ if(data == NULL)
+ free(image);
+ return NULL;
+ }
+
+ size = fileSize;
+
+ return image;
+}
+
+void utilWriteInt(gzFile gzFile, int i)
+{
+ utilGzWrite(gzFile, &i, sizeof(int));
+}
+
+int utilReadInt(gzFile gzFile)
+{
+ int i = 0;
+ utilGzRead(gzFile, &i, sizeof(int));
+ return i;
+}
+
+void utilReadData(gzFile gzFile, variable_desc* data)
+{
+ while(data->address) {
+ utilGzRead(gzFile, data->address, data->size);
+ data++;
+ }
+}
+
+void utilWriteData(gzFile gzFile, variable_desc *data)
+{
+ while(data->address) {
+ utilGzWrite(gzFile, data->address, data->size);
+ data++;
+ }
+}
+
+gzFile utilGzOpen(const char *file, const char *mode)
+{
+ utilGzWriteFunc = (int (ZEXPORT *)(void *,void * const, unsigned int))gzwrite;
+ utilGzReadFunc = gzread;
+ utilGzCloseFunc = gzclose;
+
+ return gzopen(file, mode);
+}
+
+gzFile utilMemGzOpen(char *memory, int available, char *mode)
+{
+ utilGzWriteFunc = memgzwrite;
+ utilGzReadFunc = memgzread;
+ utilGzCloseFunc = memgzclose;
+
+ return memgzopen(memory, available, mode);
+}
+
+int utilGzWrite(gzFile file, const voidp buffer, unsigned int len)
+{
+ return utilGzWriteFunc(file, buffer, len);
+}
+
+int utilGzRead(gzFile file, voidp buffer, unsigned int len)
+{
+ return utilGzReadFunc(file, buffer, len);
+}
+
+int utilGzClose(gzFile file)
+{
+ return utilGzCloseFunc(file);
+}
+
+long utilGzMemTell(gzFile file)
+{
+ return memtell(file);
+}
+
+void utilGBAFindSave(const u8 *data, const int size)
+{
+ u32 *p = (u32 *)data;
+ u32 *end = (u32 *)(data + size);
+ int saveType = 0;
+ int flashSize = 0x10000;
+ bool rtcFound = false;
+
+ while(p < end) {
+ u32 d = READ32LE(p);
+
+ if(d == 0x52504545) {
+ if(memcmp(p, "EEPROM_", 7) == 0) {
+ if(saveType == 0)
+ saveType = 3;
+ }
+ } else if (d == 0x4D415253) {
+ if(memcmp(p, "SRAM_", 5) == 0) {
+ if(saveType == 0)
+ saveType = 1;
+ }
+ } else if (d == 0x53414C46) {
+ if(memcmp(p, "FLASH1M_", 8) == 0) {
+ if(saveType == 0) {
+ saveType = 2;
+ flashSize = 0x20000;
+ }
+ } else if(memcmp(p, "FLASH", 5) == 0) {
+ if(saveType == 0) {
+ saveType = 2;
+ flashSize = 0x10000;
+ }
+ }
+ } else if (d == 0x52494953) {
+ if(memcmp(p, "SIIRTC_V", 8) == 0)
+ rtcFound = true;
+ }
+ p++;
+ }
+ // if no matches found, then set it to NONE
+ if(saveType == 0) {
+ saveType = 5;
+ }
+ rtcEnable(rtcFound);
+ cpuSaveType = saveType;
+ flashSetSize(flashSize);
+}
+
+void utilUpdateSystemColorMaps()
+{
+ switch(systemColorDepth) {
+ case 16:
+ {
+ for(int i = 0; i < 0x10000; i++) {
+ systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
+ (((i & 0x3e0) >> 5) << systemGreenShift) |
+ (((i & 0x7c00) >> 10) << systemBlueShift);
+ }
+ }
+ break;
+ case 24:
+ case 32:
+ {
+ for(int i = 0; i < 0x10000; i++) {
+ systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
+ (((i & 0x3e0) >> 5) << systemGreenShift) |
+ (((i & 0x7c00) >> 10) << systemBlueShift);
+ }
+ }
+ break;
+ }
+}
diff --git a/src/Util.h b/src/Util.h
index 37fa1f6a..1197dfb6 100644
--- a/src/Util.h
+++ b/src/Util.h
@@ -1,65 +1,65 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_UTIL_H
-#define VBA_UTIL_H
-enum IMAGE_TYPE {
- IMAGE_UNKNOWN = -1,
- IMAGE_GBA = 0,
- IMAGE_GB = 1
-};
-
-// save game
-
-typedef struct {
- void *address;
- int size;
-} variable_desc;
-
-extern bool utilWritePNGFile(const char *, int, int, u8 *);
-extern bool utilWriteBMPFile(const char *, int, int, u8 *);
-extern void utilApplyIPS(const char *ips, u8 **rom, int *size);
-extern void utilWriteBMP(char *, int, int, u8 *);
-extern bool utilIsGBAImage(const char *);
-extern bool utilIsGBImage(const char *);
-extern bool utilIsZipFile(const char *);
-extern bool utilIsGzipFile(const char *);
-extern bool utilIsRarFile(const char *);
-extern void utilGetBaseName(const char *, char *);
-extern IMAGE_TYPE utilFindType(const char *);
-extern u8 *utilLoad(const char *,
- bool (*)(const char*),
- u8 *,
- int &);
-
-extern void utilPutDword(u8 *, u32);
-extern void utilPutWord(u8 *, u16);
-extern void utilWriteData(gzFile, variable_desc *);
-extern void utilReadData(gzFile, variable_desc *);
-extern int utilReadInt(gzFile);
-extern void utilWriteInt(gzFile, int);
-extern gzFile utilGzOpen(const char *file, const char *mode);
-extern gzFile utilMemGzOpen(char *memory, int available, char *mode);
-extern int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
-extern int utilGzRead(gzFile file, voidp buffer, unsigned int len);
-extern int utilGzClose(gzFile file);
-extern long utilGzMemTell(gzFile file);
-extern void utilGBAFindSave(const u8 *, const int);
-extern void utilUpdateSystemColorMaps(int lcd);
-#endif
\ No newline at end of file
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_UTIL_H
+#define VBA_UTIL_H
+enum IMAGE_TYPE {
+ IMAGE_UNKNOWN = -1,
+ IMAGE_GBA = 0,
+ IMAGE_GB = 1
+};
+
+// save game
+
+typedef struct {
+ void *address;
+ int size;
+} variable_desc;
+
+extern bool utilWritePNGFile(const char *, int, int, u8 *);
+extern bool utilWriteBMPFile(const char *, int, int, u8 *);
+extern void utilApplyIPS(const char *ips, u8 **rom, int *size);
+extern void utilWriteBMP(char *, int, int, u8 *);
+extern bool utilIsGBAImage(const char *);
+extern bool utilIsGBImage(const char *);
+extern bool utilIsZipFile(const char *);
+extern bool utilIsGzipFile(const char *);
+extern bool utilIsRarFile(const char *);
+extern void utilGetBaseName(const char *, char *);
+extern IMAGE_TYPE utilFindType(const char *);
+extern u8 *utilLoad(const char *,
+ bool (*)(const char*),
+ u8 *,
+ int &);
+
+extern void utilPutDword(u8 *, u32);
+extern void utilPutWord(u8 *, u16);
+extern void utilWriteData(gzFile, variable_desc *);
+extern void utilReadData(gzFile, variable_desc *);
+extern int utilReadInt(gzFile);
+extern void utilWriteInt(gzFile, int);
+extern gzFile utilGzOpen(const char *file, const char *mode);
+extern gzFile utilMemGzOpen(char *memory, int available, char *mode);
+extern int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
+extern int utilGzRead(gzFile file, voidp buffer, unsigned int len);
+extern int utilGzClose(gzFile file);
+extern long utilGzMemTell(gzFile file);
+extern void utilGBAFindSave(const u8 *, const int);
+extern void utilUpdateSystemColorMaps();
+#endif
diff --git a/src/arm-new.h b/src/arm-new.h
index 8c87f87c..0a1daaff 100644
--- a/src/arm-new.h
+++ b/src/arm-new.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -1113,27 +1113,34 @@
bool C_OUT = C_FLAG;\
u32 value;\
\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_LSL_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1149,7 +1156,12 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_LSR_REG\
} else {\
@@ -1158,20 +1170,22 @@
}\
\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1187,7 +1201,12 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_ASR_REG\
} else {\
@@ -1201,20 +1220,22 @@
}\
\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1230,27 +1251,34 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_ROR_REG\
} else {\
LOGICAL_RRX_REG\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1260,12 +1288,17 @@
case BASE+1:\
{\
/* OP Rd,Rb,Rm LSL Rs */\
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
if(shift == 32) {\
value = 0;\
@@ -1280,20 +1313,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1303,12 +1338,17 @@
case BASE+3:\
{\
/* OP Rd,Rb,Rm LSR Rs */ \
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
if(shift == 32) {\
value = 0;\
@@ -1323,20 +1363,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1346,12 +1388,17 @@
case BASE+5:\
{\
/* OP Rd,Rb,Rm ASR Rs */ \
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift < 32) {\
if(shift) {\
LOGICAL_ASR_REG\
@@ -1368,20 +1415,22 @@
}\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1391,12 +1440,17 @@
case BASE+7:\
{\
/* OP Rd,Rb,Rm ROR Rs */\
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
shift &= 0x1f;\
if(shift) {\
@@ -1410,20 +1464,22 @@
C_OUT = (value & 0x80000000 ? true : false);\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1452,27 +1508,34 @@
int dest = (opcode >> 12) & 0x0F;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_ROR_IMM\
} else {\
value = opcode & 0xff;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1489,7 +1552,12 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
\
if(shift) {\
LOGICAL_LSL_REG\
@@ -1497,20 +1565,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1525,7 +1595,12 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_LSR_REG\
} else {\
@@ -1534,20 +1609,22 @@
}\
\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1562,7 +1639,12 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_ASR_REG\
} else {\
@@ -1576,20 +1658,22 @@
}\
\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1604,27 +1688,34 @@
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_ROR_REG\
} else {\
LOGICAL_RRX_REG\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1634,11 +1725,16 @@
case BASE+1:\
{\
/* OP Rd,Rb,Rm LSL Rs */\
- clockTicks+=2;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
if(shift == 32) {\
value = 0;\
@@ -1653,20 +1749,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1676,11 +1774,16 @@
case BASE+3:\
{\
/* OP Rd,Rb,Rm LSR Rs */ \
- clockTicks+=2;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
if(shift == 32) {\
value = 0;\
@@ -1695,20 +1798,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1718,11 +1823,16 @@
case BASE+5:\
{\
/* OP Rd,Rb,Rm ASR Rs */ \
- clockTicks+=2;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift < 32) {\
if(shift) {\
LOGICAL_ASR_REG\
@@ -1739,20 +1849,22 @@
}\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1762,11 +1874,16 @@
case BASE+7:\
{\
/* OP Rd,Rb,Rm ROR Rs */\
- clockTicks+=2;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
bool C_OUT = C_FLAG;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
shift &= 0x1f;\
if(shift) {\
@@ -1780,20 +1897,22 @@
C_OUT = (value & 0x80000000 ? true : false);\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1821,27 +1940,34 @@
int dest = (opcode >> 12) & 0x0F;\
bool C_OUT = C_FLAG;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
LOGICAL_ROR_IMM\
} else {\
value = opcode & 0xff;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1858,27 +1984,34 @@
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
ARITHMETIC_LSL_REG\
} else {\
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1893,27 +2026,34 @@
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
ARITHMETIC_LSR_REG\
} else {\
value = 0;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1928,7 +2068,12 @@
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
ARITHMETIC_ASR_REG\
} else {\
@@ -1937,20 +2082,22 @@
} else value = 0;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1965,27 +2112,34 @@
int shift = (opcode >> 7) & 0x1F;\
int dest = (opcode>>12) & 15;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
ARITHMETIC_ROR_REG\
} else {\
ARITHMETIC_RRX_REG\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -1995,12 +2149,16 @@
case BASE+1:\
{\
/* OP Rd,Rb,Rm LSL Rs */\
- clockTicks++;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
if(shift == 32) {\
value = 0;\
@@ -2011,20 +2169,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -2034,11 +2194,16 @@
case BASE+3:\
{\
/* OP Rd,Rb,Rm LSR Rs */\
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
if(shift == 32) {\
value = 0;\
@@ -2049,20 +2214,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -2072,11 +2239,16 @@
case BASE+5:\
{\
/* OP Rd,Rb,Rm ASR Rs */\
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift < 32) {\
if(shift) {\
ARITHMETIC_ASR_REG\
@@ -2089,20 +2261,22 @@
} else value = 0;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -2112,11 +2286,16 @@
case BASE+7:\
{\
/* OP Rd,Rb,Rm ROR Rs */\
- clockTicks+=2;\
int base = (opcode >> 16) & 0x0F;\
int shift = reg[(opcode >> 8)&15].B.B0;\
int dest = (opcode>>12) & 15;\
u32 value;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
if(shift) {\
shift &= 0x1f;\
if(shift) {\
@@ -2128,20 +2307,22 @@
value = reg[opcode & 0x0F].I;\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -2169,25 +2350,32 @@
int base = (opcode >> 16) & 0x0F;\
int dest = (opcode >> 12) & 0x0F;\
u32 value;\
- clockTicks++;\
+ if ((dest == 15)||((opcode & 0x02000010)==0x10))\
+ {\
+ clockTicks = 1+codeTicksAccess32(armNextPC);\
+ if ((opcode & 0x02000010)==0x10)\
+ clockTicks++;\
+ }\
{\
ARITHMETIC_ROR_IMM\
}\
if(dest == 15) {\
+ clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\
OPCODE2\
/* todo */\
if(opcode & 0x00100000) {\
- clockTicks++;\
CPUSwitchMode(reg[17].I & 0x1f, false);\
}\
if(armState) {\
reg[15].I &= 0xFFFFFFFC;\
armNextPC = reg[15].I;\
reg[15].I += 4;\
+ ARM_PREFETCH;\
} else {\
reg[15].I &= 0xFFFFFFFE;\
armNextPC = reg[15].I;\
reg[15].I += 2;\
+ THUMB_PREFETCH;\
}\
} else {\
OPCODE \
@@ -2195,9 +2383,16 @@
}\
break;
- u32 opcode = CPUReadMemoryQuick(armNextPC);
+ u32 opcode = cpuPrefetch[0];
+ cpuPrefetch[0] = cpuPrefetch[1];
- clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15];
+ busPrefetch = false;
+ if (busPrefetchCount & 0xFFFFFE00)
+ busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF);
+
+
+ clockTicks = 0;//codeTicksAccessSeq32(armNextPC)+1;
+ int oldArmNextPC = armNextPC;
#ifndef FINAL_VERSION
if(armNextPC == stop) {
@@ -2207,6 +2402,8 @@
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH_NEXT;
+
int cond = opcode >> 28;
// suggested optimization for frequent cases
bool cond_res;
@@ -2276,18 +2473,23 @@ if(cond_res) {
// MUL Rd, Rm, Rs
int dest = (opcode >> 16) & 0x0F;
int mult = (opcode & 0x0F);
+ clockTicks = 1;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs;
if(((s32)rs)<0)
- rs = ~rs;
+ rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 2;
+ clockTicks += 0;
else if ((rs & 0xFFFF0000) == 0)
- clockTicks += 3;
+ clockTicks += 1;
else if ((rs & 0xFF000000) == 0)
- clockTicks += 4;
+ clockTicks += 2;
else
- clockTicks += 5;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 16) & 0x0F;
int mult = (opcode & 0x0F);
+ clockTicks = 1;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs;
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
@@ -2302,24 +2505,30 @@ if(cond_res) {
if(((s32)rs)<0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 2;
+ clockTicks += 0;
else if ((rs & 0xFFFF0000) == 0)
- clockTicks += 3;
+ clockTicks += 1;
else if ((rs & 0xFF000000) == 0)
- clockTicks += 4;
+ clockTicks += 2;
else
- clockTicks += 5;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
address -= offset;
reg[base].I = address;
@@ -2329,11 +2538,14 @@ if(cond_res) {
case 0x06b:
{
// STRH Rd, [Rn], #-offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address)
+ + codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
address -= offset;
reg[base].I = address;
@@ -2343,11 +2555,14 @@ if(cond_res) {
case 0x0ab:
{
// STRH Rd, [Rn], Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
address += offset;
reg[base].I = address;
@@ -2357,11 +2572,14 @@ if(cond_res) {
case 0x0eb:
{
// STRH Rd, [Rn], #offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
address += offset;
reg[base].I = address;
@@ -2370,20 +2588,26 @@ if(cond_res) {
case 0x10b:
{
// STRH Rd, [Rn, -Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x12b:
{
// STRH Rd, [Rn, -Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
@@ -2391,20 +2615,26 @@ if(cond_res) {
case 0x14b:
{
// STRH Rd, [Rn, -#offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x16b:
{
// STRH Rd, [Rn, -#offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
@@ -2412,20 +2642,26 @@ if(cond_res) {
case 0x18b:
{
// STRH Rd, [Rn, Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x1ab:
{
// STRH Rd, [Rn, Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
@@ -2433,20 +2669,26 @@ if(cond_res) {
case 0x1cb:
{
// STRH Rd, [Rn, #offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
}
break;
case 0x1eb:
{
// STRH Rd, [Rn, #offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 4 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
CPUWriteHalfWord(address, reg[dest].W.W0);
reg[base].I = address;
}
@@ -2455,456 +2697,852 @@ if(cond_res) {
case 0x03b:
{
// LDRH Rd, [Rn], -Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base) {
address -= offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x05b:
case 0x07b:
{
// LDRH Rd, [Rn], #-offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base) {
address -= offset;
reg[base].I = address;
}
+ clockTicks=0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x09b:
case 0x0bb:
{
// LDRH Rd, [Rn], Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base) {
address += offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x0db:
case 0x0fb:
{
// LDRH Rd, [Rn], #offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base) {
address += offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x11b:
{
// LDRH Rd, [Rn, -Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x13b:
{
// LDRH Rd, [Rn, -Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x15b:
{
// LDRH Rd, [Rn, -#offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x17b:
{
// LDRH Rd, [Rn, -#offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x19b:
{
// LDRH Rd, [Rn, Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1bb:
{
// LDRH Rd, [Rn, Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1db:
{
// LDRH Rd, [Rn, #offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1fb:
{
// LDRH Rd, [Rn, #offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = CPUReadHalfWord(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x01d:
case 0x03d:
{
// LDRSB Rd, [Rn], -Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base) {
address -= offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x05d:
case 0x07d:
{
// LDRSB Rd, [Rn], #-offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base) {
address -= offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x09d:
case 0x0bd:
{
// LDRSB Rd, [Rn], Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base) {
address += offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x0dd:
case 0x0fd:
{
// LDRSB Rd, [Rn], #offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base) {
address += offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x11d:
{
// LDRSB Rd, [Rn, -Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x13d:
{
// LDRSB Rd, [Rn, -Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x15d:
{
// LDRSB Rd, [Rn, -#offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x17d:
{
// LDRSB Rd, [Rn, -#offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x19d:
{
// LDRSB Rd, [Rn, Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1bd:
{
// LDRSB Rd, [Rn, Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1dd:
{
// LDRSB Rd, [Rn, #offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1fd:
{
// LDRSB Rd, [Rn, #offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s8)CPUReadByte(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x01f:
case 0x03f:
{
// LDRSH Rd, [Rn], -Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base) {
address -= offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x05f:
case 0x07f:
{
// LDRSH Rd, [Rn], #-offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base) {
address -= offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x09f:
case 0x0bf:
{
// LDRSH Rd, [Rn], Rm
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base) {
address += offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x0df:
case 0x0ff:
{
// LDRSH Rd, [Rn], #offset
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I;
int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base) {
address += offset;
reg[base].I = address;
}
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x11f:
{
// LDRSH Rd, [Rn, -Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x13f:
{
// LDRSH Rd, [Rn, -Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x15f:
{
// LDRSH Rd, [Rn, -#offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x17f:
{
// LDRSH Rd, [Rn, -#offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x19f:
{
// LDRSH Rd, [Rn, Rm]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1bf:
{
// LDRSH Rd, [Rn, Rm]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + reg[opcode & 0x0F].I;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1df:
{
// LDRSH Rd, [Rn, #offset]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x1ff:
{
// LDRSH Rd, [Rn, #offset]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode >> 16) & 0x0F;
int dest = (opcode >> 12) & 0x0F;
u32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0));
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
reg[dest].I = (s16)CPUReadHalfWordSigned(address);
if(dest != base)
reg[base].I = address;
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020);
@@ -2912,25 +3550,28 @@ if(cond_res) {
case 0x029:
{
// MLA Rd, Rm, Rs, Rn
+ clockTicks = 2;
int dest = (opcode >> 16) & 0x0F;
int mult = (opcode & 0x0F);
u32 rs = reg[(opcode >> 8) & 0x0F].I;
reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I;
- if(((s32)rs)<0)
- rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 3;
+ clockTicks += 0;
else if ((rs & 0xFFFF0000) == 0)
- clockTicks += 4;
+ clockTicks += 1;
else if ((rs & 0xFF000000) == 0)
- clockTicks += 5;
+ clockTicks += 2;
else
- clockTicks += 6;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 16) & 0x0F;
int mult = (opcode & 0x0F);
u32 rs = reg[(opcode >> 8) & 0x0F].I;
@@ -2940,13 +3581,16 @@ if(cond_res) {
if(((s32)rs)<0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 3;
+ clockTicks += 0;
else if ((rs & 0xFFFF0000) == 0)
- clockTicks += 4;
+ clockTicks += 1;
else if ((rs & 0xFF000000) == 0)
- clockTicks += 5;
+ clockTicks += 2;
else
- clockTicks += 6;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u64 uTemp = ((u64)umult)*((u64)usource);
- reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
+ reg[destLo].I = (u32)uTemp;
reg[destHi].I = (u32)(uTemp >> 32);
if ((usource & 0xFFFFFF00) == 0)
- clockTicks += 2;
+ clockTicks += 0;
else if ((usource & 0xFFFF0000) == 0)
- clockTicks += 3;
+ clockTicks += 1;
else if ((usource & 0xFF000000) == 0)
- clockTicks += 4;
+ clockTicks += 2;
else
- clockTicks += 5;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
@@ -2988,13 +3637,16 @@ if(cond_res) {
Z_FLAG = (uTemp) ? false : true;
N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
if ((usource & 0xFFFFFF00) == 0)
- clockTicks += 2;
+ clockTicks += 0;
else if ((usource & 0xFFFF0000) == 0)
- clockTicks += 3;
+ clockTicks += 1;
else if ((usource & 0xFF000000) == 0)
- clockTicks += 4;
+ clockTicks += 2;
else
- clockTicks += 5;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
@@ -3013,18 +3666,22 @@ if(cond_res) {
reg[destLo].I = (u32)uTemp;
reg[destHi].I = (u32)(uTemp >> 32);
if ((usource & 0xFFFFFF00) == 0)
- clockTicks += 3;
+ clockTicks += 0;
else if ((usource & 0xFFFF0000) == 0)
- clockTicks += 4;
+ clockTicks += 1;
else if ((usource & 0xFF000000) == 0)
- clockTicks += 5;
+ clockTicks += 2;
else
- clockTicks += 6;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 8) & 0x0F].I;
int destLo = (opcode >> 12) & 0x0F;
@@ -3038,13 +3695,16 @@ if(cond_res) {
Z_FLAG = (uTemp) ? false : true;
N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
if ((usource & 0xFFFFFF00) == 0)
- clockTicks += 3;
+ clockTicks += 0;
else if ((usource & 0xFFFF0000) == 0)
- clockTicks += 4;
+ clockTicks += 1;
else if ((usource & 0xFF000000) == 0)
- clockTicks += 5;
+ clockTicks += 2;
else
- clockTicks += 6;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
@@ -3063,18 +3724,22 @@ if(cond_res) {
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 2;
+ clockTicks += 0;
else if((rs & 0xFFFF0000) == 0)
- clockTicks += 3;
+ clockTicks += 1;
else if((rs & 0xFF000000) == 0)
- clockTicks += 4;
+ clockTicks += 2;
else
- clockTicks += 5;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
@@ -3088,13 +3753,16 @@ if(cond_res) {
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 2;
+ clockTicks += 0;
else if((rs & 0xFFFF0000) == 0)
- clockTicks += 3;
+ clockTicks += 1;
else if((rs & 0xFF000000) == 0)
- clockTicks += 4;
+ clockTicks += 2;
else
- clockTicks += 5;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
@@ -3116,18 +3785,21 @@ if(cond_res) {
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 3;
+ clockTicks += 0;
else if((rs & 0xFFFF0000) == 0)
- clockTicks += 4;
+ clockTicks += 1;
else if((rs & 0xFF000000) == 0)
- clockTicks += 5;
+ clockTicks += 2;
else
- clockTicks += 6;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F;
int destHi = (opcode >> 16) & 0x0F;
u32 rs = reg[(opcode >> 8) & 0x0F].I;
@@ -3144,20 +3816,21 @@ if(cond_res) {
if(((s32)rs) < 0)
rs = ~rs;
if((rs & 0xFFFFFF00) == 0)
- clockTicks += 3;
+ clockTicks += 0;
else if((rs & 0xFFFF0000) == 0)
- clockTicks += 4;
+ clockTicks += 1;
else if((rs & 0xFF000000) == 0)
- clockTicks += 5;
+ clockTicks += 2;
else
- clockTicks += 6;
+ clockTicks += 3;
+ if (!busPrefetchCount)
+ busPrefetchCount = ((++busPrefetchCount)<> 12) & 0x0F].I = reg[16].I;
break;
@@ -3168,7 +3841,8 @@ if(cond_res) {
u32 temp = CPUReadMemory(address);
CPUWriteMemory(address, reg[opcode&15].I);
reg[(opcode >> 12) & 15].I = temp;
- clockTicks++;
+ clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130);
@@ -3192,24 +3866,33 @@ if(cond_res) {
CPUSwitchMode(newValue & 0x1f, false);
reg[16].I = newValue;
CPUUpdateFlags();
- clockTicks++;
+ if(!armState) { // this should not be allowed, but it seems to work
+ THUMB_PREFETCH;
+ reg[15].I = armNextPC + 2;
+ }
}
break;
case 0x121:
{
// BX Rm
// TODO: check if right instruction...
- clockTicks += 3;
int base = opcode & 0x0F;
+ busPrefetchCount=0;
armState = reg[base].I & 1 ? false : true;
if(armState) {
reg[15].I = reg[base].I & 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks = codeTicksAccessSeq32(armNextPC) +
+ codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
} else {
reg[15].I = reg[base].I & 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC) +
+ codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
}
}
break;
@@ -3218,7 +3901,6 @@ if(cond_res) {
// MRS Rd, SPSR
// TODO: check if right instruction...
reg[(opcode >> 12) & 0x0F].I = reg[17].I;
- clockTicks++;
break;
case 0x149:
{
@@ -3227,7 +3909,8 @@ if(cond_res) {
u32 temp = CPUReadByte(address);
CPUWriteByte(address, reg[opcode&15].B.B0);
reg[(opcode>>12)&15].I = temp;
- clockTicks++;
+ clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170);
@@ -3245,7 +3928,6 @@ if(cond_res) {
if(opcode & 0x00080000)
reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
}
- clockTicks++;
}
break;
LOGICAL_DATA_OPCODE (OP_ORR, OP_ORR, 0x180);
@@ -3306,7 +3988,10 @@ if(cond_res) {
CPUSwitchMode(newValue & 0x1f, false);
reg[16].I = newValue;
CPUUpdateFlags();
- clockTicks++;
+ if(!armState) { // this should not be allowed, but it seems to work
+ THUMB_PREFETCH;
+ reg[15].I = armNextPC + 2;
+ }
}
break;
case 0x360:
@@ -3342,7 +4027,6 @@ if(cond_res) {
if(opcode & 0x00080000)
reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
}
- clockTicks++;
}
break;
CASE_16(0x400)
@@ -3350,13 +4034,16 @@ if(cond_res) {
CASE_16(0x420)
{
// STR Rd, [Rn], -#
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x480)
@@ -3364,64 +4051,81 @@ if(cond_res) {
CASE_16(0x4a0)
{
// STR Rd, [Rn], #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x500)
{
// STR Rd, [Rn, -#]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x520)
{
// STR Rd, [Rn, -#]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x580)
{
// STR Rd, [Rn, #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x5a0)
{
// STR Rd, [Rn, #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x410)
{
// LDR Rd, [Rn], -#
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3429,18 +4133,23 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I -= offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x430)
{
// LDRT Rd, [Rn], -#
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3448,12 +4157,23 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I -= offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x490)
{
// LDR Rd, [Rn], #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3461,18 +4181,23 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I += offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x4b0)
{
// LDRT Rd, [Rn], #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3480,29 +4205,45 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I += offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x510)
{
// LDR Rd, [Rn, -#]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x530)
{
// LDR Rd, [Rn, -#]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3510,35 +4251,45 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
- }
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
+ }
break;
CASE_16(0x590)
{
// LDR Rd, [Rn, #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x5b0)
{
// LDR Rd, [Rn, #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3546,13 +4297,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x440)
@@ -3560,73 +4314,91 @@ if(cond_res) {
CASE_16(0x460)
{
// STRB Rd, [Rn], -#
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x4c0)
// T versions shouldn't be different on GBA
CASE_16(0x4e0)
- // STRB Rd, [Rn], #
{
+ // STRB Rd, [Rn], #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x540)
{
// STRB Rd, [Rn, -#]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x560)
{
// STRB Rd, [Rn, -#]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x5c0)
{
// STRB Rd, [Rn, #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x5e0)
{
// STRB Rd, [Rn, #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x450)
@@ -3634,6 +4406,8 @@ if(cond_res) {
CASE_16(0x470)
{
// LDRB Rd, [Rn], -#
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3641,13 +4415,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I -= offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x4d0)
CASE_16(0x4f0) // T versions should not be different
{
// LDRB Rd, [Rn], #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3655,23 +4440,45 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I += offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x550)
{
// LDRB Rd, [Rn, -#]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x570)
{
// LDRB Rd, [Rn, -#]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3679,23 +4486,45 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x5d0)
{
// LDRB Rd, [Rn, #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x5f0)
{
// LDRB Rd, [Rn, #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = opcode & 0xFFF;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -3703,7 +4532,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x600:
@@ -3713,13 +4551,16 @@ if(cond_res) {
case 0x628:
{
// STR Rd, [Rn], -Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x602:
@@ -3729,6 +4570,8 @@ if(cond_res) {
case 0x62a:
{
// STR Rd, [Rn], -Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -3736,7 +4579,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x604:
@@ -3746,6 +4590,8 @@ if(cond_res) {
case 0x62c:
{
// STR Rd, [Rn], -Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -3759,7 +4605,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x606:
@@ -3769,6 +4616,8 @@ if(cond_res) {
case 0x62e:
{
// STR Rd, [Rn], -Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -3781,7 +4630,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address - value;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x680:
@@ -3791,13 +4641,16 @@ if(cond_res) {
case 0x6a8:
{
// STR Rd, [Rn], Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x682:
@@ -3807,6 +4660,8 @@ if(cond_res) {
case 0x6aa:
{
// STR Rd, [Rn], Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -3814,7 +4669,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x684:
@@ -3824,6 +4680,8 @@ if(cond_res) {
case 0x6ac:
{
// STR Rd, [Rn], Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -3837,7 +4695,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x686:
@@ -3847,6 +4706,8 @@ if(cond_res) {
case 0x6ae:
{
// STR Rd, [Rn], Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -3859,38 +4720,47 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteMemory(address, reg[dest].I);
reg[base].I = address + value;
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x700:
case 0x708:
{
// STR Rd, [Rn, -Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x702:
case 0x70a:
{
// STR Rd, [Rn, -Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x704:
case 0x70c:
{
// STR Rd, [Rn, -Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -3903,13 +4773,16 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x706:
case 0x70e:
{
// STR Rd, [Rn, -Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -3921,26 +4794,32 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x720:
case 0x728:
{
// STR Rd, [Rn, -Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x722:
case 0x72a:
{
// STR Rd, [Rn, -Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -3948,13 +4827,16 @@ if(cond_res) {
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x724:
case 0x72c:
{
// STR Rd, [Rn, -Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -3968,13 +4850,16 @@ if(cond_res) {
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x726:
case 0x72e:
{
// STR Rd, [Rn, -Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -3987,38 +4872,47 @@ if(cond_res) {
u32 address = reg[base].I - value;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x780:
case 0x788:
{
// STR Rd, [Rn, Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x782:
case 0x78a:
{
// STR Rd, [Rn, Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x784:
case 0x78c:
{
// STR Rd, [Rn, Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4031,13 +4925,16 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x786:
case 0x78e:
{
// STR Rd, [Rn, Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4049,26 +4946,32 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7a0:
case 0x7a8:
{
// STR Rd, [Rn, Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7a2:
case 0x7aa:
{
// STR Rd, [Rn, Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4076,13 +4979,16 @@ if(cond_res) {
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7a4:
case 0x7ac:
{
// STR Rd, [Rn, Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4096,13 +5002,16 @@ if(cond_res) {
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7a6:
case 0x7ae:
{
// STR Rd, [Rn, Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4115,7 +5024,8 @@ if(cond_res) {
u32 address = reg[base].I + value;
reg[base].I = address;
CPUWriteMemory(address, reg[dest].I);
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks = 2 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x610:
@@ -4125,6 +5035,8 @@ if(cond_res) {
case 0x638:
{
// LDR Rd, [Rn], -Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -4132,13 +5044,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x612:
@@ -4148,6 +5063,8 @@ if(cond_res) {
case 0x63a:
{
// LDR Rd, [Rn], -Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4156,13 +5073,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x614:
@@ -4172,6 +5092,8 @@ if(cond_res) {
case 0x63c:
{
// LDR Rd, [Rn], -Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4186,13 +5108,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x616:
@@ -4202,6 +5127,8 @@ if(cond_res) {
case 0x63e:
{
// LDR Rd, [Rn], -Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4215,13 +5142,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address - value;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x690:
@@ -4231,6 +5161,8 @@ if(cond_res) {
case 0x6b8:
{
// LDR Rd, [Rn], Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -4238,13 +5170,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x692:
@@ -4254,6 +5189,8 @@ if(cond_res) {
case 0x6ba:
{
// LDR Rd, [Rn], Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4262,13 +5199,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x694:
@@ -4278,6 +5218,8 @@ if(cond_res) {
case 0x6bc:
{
// LDR Rd, [Rn], Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4292,13 +5234,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + offset;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x696:
@@ -4308,6 +5253,8 @@ if(cond_res) {
case 0x6be:
{
// LDR Rd, [Rn], Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4321,56 +5268,71 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address + value;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x710:
case 0x718:
{
// LDR Rd, [Rn, -Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x712:
case 0x71a:
{
// LDR Rd, [Rn, -Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x714:
case 0x71c:
{
// LDR Rd, [Rn, -Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4383,19 +5345,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x716:
case 0x71e:
{
// LDR Rd, [Rn, -Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4407,19 +5374,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x730:
case 0x738:
{
// LDR Rd, [Rn, -Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -4427,19 +5399,24 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x732:
case 0x73a:
{
// LDR Rd, [Rn, -Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4448,19 +5425,24 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x734:
case 0x73c:
{
// LDR Rd, [Rn, -Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4475,19 +5457,24 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x736:
case 0x73e:
{
// LDR Rd, [Rn, -Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4501,56 +5488,71 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x790:
case 0x798:
{
// LDR Rd, [Rn, Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x792:
case 0x79a:
{
// LDR Rd, [Rn, Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x794:
case 0x79c:
{
// LDR Rd, [Rn, Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4563,19 +5565,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x796:
case 0x79e:
{
// LDR Rd, [Rn, Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4587,19 +5594,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[dest].I = CPUReadMemory(address);
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7b0:
case 0x7b8:
{
// LDR Rd, [Rn, Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -4607,19 +5619,24 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7b2:
case 0x7ba:
{
// LDR Rd, [Rn, Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4628,19 +5645,24 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7b4:
case 0x7bc:
{
// LDR Rd, [Rn, Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4655,19 +5677,24 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7b6:
case 0x7be:
{
// LDR Rd, [Rn, Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4681,13 +5708,16 @@ if(cond_res) {
reg[dest].I = CPUReadMemory(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess32(address);
+ clockTicks = 0;
if(dest == 15) {
- clockTicks += 2;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
}
+ clockTicks += 3 + dataTicksAccess32(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x640:
@@ -4697,13 +5727,16 @@ if(cond_res) {
case 0x668:
{
// STRB Rd, [Rn], -Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x642:
@@ -4713,6 +5746,8 @@ if(cond_res) {
case 0x66a:
{
// STRB Rd, [Rn], -Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4720,7 +5755,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x644:
@@ -4730,6 +5766,8 @@ if(cond_res) {
case 0x66c:
{
// STRB Rd, [Rn], -Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4743,7 +5781,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x646:
@@ -4753,6 +5792,8 @@ if(cond_res) {
case 0x66e:
{
// STRB Rd, [Rn], -Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4765,7 +5806,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address - value;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6c0:
@@ -4775,13 +5817,16 @@ if(cond_res) {
case 0x6e8:
{
// STRB Rd, [Rn], Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6c2:
@@ -4791,6 +5836,8 @@ if(cond_res) {
case 0x6ea:
{
// STRB Rd, [Rn], Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4798,7 +5845,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6c4:
@@ -4807,7 +5855,9 @@ if(cond_res) {
case 0x6e4:
case 0x6ec:
{
- // STR Rd, [Rn], Rm, ASR #
+ // STRB Rd, [Rn], Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4821,7 +5871,8 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + offset;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6c6:
@@ -4831,6 +5882,8 @@ if(cond_res) {
case 0x6ee:
{
// STRB Rd, [Rn], Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4843,38 +5896,47 @@ if(cond_res) {
u32 address = reg[base].I;
CPUWriteByte(address, reg[dest].B.B0);
reg[base].I = address + value;
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x740:
case 0x748:
{
// STRB Rd, [Rn, -Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x742:
case 0x74a:
{
// STRB Rd, [Rn, -Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x744:
case 0x74c:
{
// STRB Rd, [Rn, -Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4887,13 +5949,16 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x746:
case 0x74e:
{
// STRB Rd, [Rn, -Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4905,26 +5970,32 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x760:
case 0x768:
{
// STRB Rd, [Rn, -Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x762:
case 0x76a:
{
// STRB Rd, [Rn, -Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -4932,13 +6003,16 @@ if(cond_res) {
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x764:
case 0x76c:
{
// STRB Rd, [Rn, -Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -4952,13 +6026,16 @@ if(cond_res) {
u32 address = reg[base].I - offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x766:
case 0x76e:
{
// STRB Rd, [Rn, -Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -4971,38 +6048,47 @@ if(cond_res) {
u32 address = reg[base].I - value;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7c0:
case 0x7c8:
{
// STRB Rd, [Rn, Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7c2:
case 0x7ca:
{
// STRB Rd, [Rn, Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7c4:
case 0x7cc:
{
// STRB Rd, [Rn, Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5015,13 +6101,16 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7c6:
case 0x7ce:
{
// STRB Rd, [Rn, Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5033,26 +6122,32 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7e0:
case 0x7e8:
{
// STRB Rd, [Rn, Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7e2:
case 0x7ea:
{
// STRB Rd, [Rn, Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -5060,13 +6155,16 @@ if(cond_res) {
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7e4:
case 0x7ec:
{
// STRB Rd, [Rn, Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5080,13 +6178,16 @@ if(cond_res) {
u32 address = reg[base].I + offset;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7e6:
case 0x7ee:
{
// STRB Rd, [Rn, Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5099,7 +6200,8 @@ if(cond_res) {
u32 address = reg[base].I + value;
reg[base].I = address;
CPUWriteByte(address, reg[dest].B.B0);
- clockTicks += 2 + CPUUpdateTicksAccess16(address);
+ clockTicks = 2 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x650:
@@ -5109,6 +6211,8 @@ if(cond_res) {
case 0x678:
{
// LDRB Rd, [Rn], -Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -5116,7 +6220,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x652:
@@ -5126,6 +6239,8 @@ if(cond_res) {
case 0x67a:
{
// LDRB Rd, [Rn], -Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -5134,7 +6249,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x654:
@@ -5144,6 +6268,8 @@ if(cond_res) {
case 0x67c:
{
// LDRB Rd, [Rn], -Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5158,7 +6284,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x656:
@@ -5168,6 +6303,8 @@ if(cond_res) {
case 0x67e:
{
// LDRB Rd, [Rn], -Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5181,7 +6318,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address - value;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6d0:
@@ -5191,6 +6337,8 @@ if(cond_res) {
case 0x6f8:
{
// LDRB Rd, [Rn], Rm, LSL #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -5198,7 +6346,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6d2:
@@ -5208,6 +6365,8 @@ if(cond_res) {
case 0x6fa:
{
// LDRB Rd, [Rn], Rm, LSR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -5216,7 +6375,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6d4:
@@ -5226,6 +6394,8 @@ if(cond_res) {
case 0x6fc:
{
// LDRB Rd, [Rn], Rm, ASR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5240,7 +6410,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + offset;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x6d6:
@@ -5250,6 +6429,8 @@ if(cond_res) {
case 0x6fe:
{
// LDRB Rd, [Rn], Rm, ROR #
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5263,38 +6444,71 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address + value;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x750:
case 0x758:
{
// LDRB Rd, [Rn, -Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x752:
case 0x75a:
{
// LDRB Rd, [Rn, -Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x754:
case 0x75c:
{
// LDRB Rd, [Rn, -Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5307,13 +6521,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x756:
case 0x75e:
{
// LDRB Rd, [Rn, -Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5325,13 +6550,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I - value;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x770:
case 0x778:
{
// LDRB Rd, [Rn, -Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -5339,13 +6575,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x772:
case 0x77a:
{
// LDRB Rd, [Rn, -Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -5354,13 +6601,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x774:
case 0x77c:
{
// LDRB Rd, [Rn, -Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5375,13 +6633,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x776:
case 0x77e:
{
// LDRB Rd, [Rn, -Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5395,38 +6664,71 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7d0:
case 0x7d8:
{
// LDRB Rd, [Rn, Rm, LSL #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7d2:
case 0x7da:
{
// LDRB Rd, [Rn, Rm, LSR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7d4:
case 0x7dc:
{
// LDRB Rd, [Rn, Rm, ASR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5439,13 +6741,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + offset;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7d6:
case 0x7de:
{
// LDRB Rd, [Rn, Rm, ROR #]
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5457,13 +6770,24 @@ if(cond_res) {
int base = (opcode >> 16) & 15;
u32 address = reg[base].I + value;
reg[dest].I = CPUReadByte(address);
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7f0:
case 0x7f8:
{
// LDRB Rd, [Rn, Rm, LSL #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = reg[opcode & 15].I << ((opcode>>7)& 31);
int dest = (opcode >> 12) & 15;
int base = (opcode >> 16) & 15;
@@ -5471,13 +6795,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7f2:
case 0x7fa:
{
// LDRB Rd, [Rn, Rm, LSR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset = shift ? reg[opcode & 15].I >> shift : 0;
int dest = (opcode >> 12) & 15;
@@ -5486,13 +6821,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7f4:
case 0x7fc:
{
// LDRB Rd, [Rn, Rm, ASR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
int offset;
if(shift)
@@ -5507,13 +6853,24 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
case 0x7f6:
case 0x7fe:
{
// LDRB Rd, [Rn, Rm, ROR #]!
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int shift = (opcode >> 7) & 31;
u32 value = reg[opcode & 15].I;
if(shift) {
@@ -5527,7 +6884,16 @@ if(cond_res) {
reg[dest].I = CPUReadByte(address);
if(dest != base)
reg[base].I = address;
- clockTicks += 3 + CPUUpdateTicksAccess16(address);
+ clockTicks = 0;
+ if(dest == 15) {
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address);
+ }
+ clockTicks += 3 + dataTicksAccess16(address) +
+ codeTicksAccess32(armNextPC);
}
break;
#define STMW_REG(val,num) \
@@ -5535,10 +6901,10 @@ if(cond_res) {
CPUWriteMemory(address, reg[(num)].I);\
if(!offset) {\
reg[base].I = temp;\
- clockTicks += 1 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccess32(address);\
offset = 1;\
} else {\
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
}\
address += 4;\
}
@@ -5546,22 +6912,23 @@ if(cond_res) {
if(opcode & (val)) {\
CPUWriteMemory(address, reg[(num)].I);\
if(!offset) {\
- clockTicks += 1 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccess32(address);\
offset = 1;\
} else {\
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
}\
address += 4;\
}
CASE_16(0x800)
- // STMDA Rn, {Rlist}
{
+ // STMDA Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
@@ -5581,20 +6948,22 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x820)
{
// STMDA Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
@@ -5615,21 +6984,23 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
reg[base].I = temp;
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x840)
{
// STMDA Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
@@ -5666,20 +7037,22 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x860)
{
// STMDA Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
@@ -5716,20 +7089,22 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
reg[base].I = temp;
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x880)
{
// STMIA Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
@@ -5749,18 +7124,20 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x8a0)
{
// STMIA Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
@@ -5783,18 +7160,20 @@ if(cond_res) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset) {
reg[base].I = temp;
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
} else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x8c0)
{
// STMIA Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
@@ -5827,18 +7206,20 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x8e0)
{
// STMIA Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
@@ -5874,21 +7255,23 @@ if(cond_res) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset) {
reg[base].I = temp;
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
} else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x900)
{
// STMDB Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
@@ -5908,20 +7291,22 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x920)
{
// STMDB Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
@@ -5942,21 +7327,23 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
reg[base].I = temp;
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x940)
{
// STMDB Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
@@ -5993,20 +7380,22 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x960)
{
// STMDB Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STMW_REG(1, 0);
@@ -6043,20 +7432,22 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
reg[base].I = temp;
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x980)
- // STMIB Rn, {Rlist}
{
+ // STMIB Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
@@ -6076,18 +7467,20 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x9a0)
{
// STMIB Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
@@ -6110,18 +7503,20 @@ if(cond_res) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset) {
reg[base].I = temp;
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
} else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x9c0)
{
// STMIB Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
STM_REG(1, 0);
STM_REG(2, 1);
@@ -6154,18 +7549,20 @@ if(cond_res) {
if(opcode & 32768) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset)
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x9e0)
{
// STMIB Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
int offset = 0;
u32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] +
cpuBitsSet[(opcode >> 8) & 255]);
@@ -6201,10 +7598,11 @@ if(cond_res) {
CPUWriteMemory(address, reg[15].I+4);
if(!offset) {
reg[base].I = temp;
- clockTicks += 1 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
} else
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
}
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
break;
@@ -6212,9 +7610,9 @@ if(cond_res) {
if(opcode & (val)) {\
reg[(num)].I = CPUReadMemory(address);\
if(offset)\
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
else {\
- clockTicks += 1 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccess32(address);\
offset = 1;\
}\
address += 4;\
@@ -6223,11 +7621,13 @@ if(cond_res) {
CASE_16(0x810)
{
// LDMDA Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6246,23 +7646,28 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x830)
{
// LDMDA Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6281,13 +7686,17 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
@@ -6295,11 +7704,13 @@ if(cond_res) {
CASE_16(0x850)
{
// LDMDA Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6319,18 +7730,16 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -6363,17 +7772,25 @@ if(cond_res) {
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x870)
{
// LDMDA Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (temp + 4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6393,10 +7810,6 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if(!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
@@ -6405,9 +7818,11 @@ if(cond_res) {
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -6443,16 +7858,24 @@ if(cond_res) {
if(!(opcode & (1 << base)))
reg[base].I = temp;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x890)
{
// LDMIA Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6471,23 +7894,29 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x8b0)
{
// LDMIA Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6506,13 +7935,17 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
@@ -6520,9 +7953,11 @@ if(cond_res) {
CASE_16(0x8d0)
{
// LDMIA Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6542,18 +7977,16 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -6586,17 +8019,25 @@ if(cond_res) {
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x8f0)
{
// LDMIA Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = reg[base].I & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6616,10 +8057,6 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if(!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
@@ -6628,9 +8065,11 @@ if(cond_res) {
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -6666,18 +8105,26 @@ if(cond_res) {
if(!(opcode & (1 << base)))
reg[base].I = temp;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x910)
{
// LDMDB Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6696,23 +8143,29 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x930)
{
// LDMDB Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6731,13 +8184,17 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
@@ -6745,11 +8202,13 @@ if(cond_res) {
CASE_16(0x950)
{
// LDMDB Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6769,18 +8228,16 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -6813,17 +8270,25 @@ if(cond_res) {
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x970)
{
// LDMDB Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I -
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = temp & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6843,10 +8308,6 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if(!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
@@ -6855,9 +8316,11 @@ if(cond_res) {
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -6893,16 +8356,24 @@ if(cond_res) {
if(!(opcode & (1 << base)))
reg[base].I = temp;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x990)
{
// LDMIB Rn, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6921,23 +8392,29 @@ if(cond_res) {
LDM_REG(16384, 14);
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x9b0)
{
// LDMIB Rn!, {Rlist}
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
LDM_REG(1, 0);
LDM_REG(2, 1);
@@ -6957,12 +8434,21 @@ if(cond_res) {
if(opcode & 32768) {
reg[15].I = CPUReadMemory(address);
if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
if(!(opcode & (1 << base)))
reg[base].I = temp;
}
@@ -6970,9 +8456,11 @@ if(cond_res) {
CASE_16(0x9d0)
{
// LDMIB Rn, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -6992,18 +8480,16 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if (!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
CPUSwitchMode(reg[17].I & 0x1f, false);
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -7036,17 +8522,25 @@ if(cond_res) {
LDM_REG(8192, 13);
LDM_REG(16384, 14);
}
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_16(0x9f0)
{
// LDMIB Rn!, {Rlist}^
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int base = (opcode & 0x000F0000) >> 16;
u32 temp = reg[base].I +
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
u32 address = (reg[base].I+4) & 0xFFFFFFFC;
- clockTicks += 2;
+ clockTicks = 0;
int offset = 0;
if(opcode & 0x8000) {
LDM_REG(1, 0);
@@ -7066,10 +8560,6 @@ if(cond_res) {
LDM_REG(16384, 14);
reg[15].I = CPUReadMemory(address);
- if(!offset)
- clockTicks += 2 + CPUUpdateTicksAccess32(address);
- else
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
if(!(opcode & (1 << base)))
reg[base].I = temp;
@@ -7078,9 +8568,11 @@ if(cond_res) {
if(armState) {
armNextPC = reg[15].I & 0xFFFFFFFC;
reg[15].I = armNextPC + 4;
+ ARM_PREFETCH;
} else {
armNextPC = reg[15].I & 0xFFFFFFFE;
reg[15].I = armNextPC + 2;
+ THUMB_PREFETCH;
}
} else {
LDM_REG(1, 0);
@@ -7116,13 +8608,18 @@ if(cond_res) {
if(!(opcode & (1 << base)))
reg[base].I = temp;
+ if (!offset)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC);
}
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
break;
CASE_256(0xa00)
{
// B
- clockTicks += 3;
int offset = opcode & 0x00FFFFFF;
if(offset & 0x00800000) {
offset |= 0xFF000000;
@@ -7131,12 +8628,16 @@ if(cond_res) {
reg[15].I += offset;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
+ clockTicks += 2 + codeTicksAccess32(armNextPC) +
+ codeTicksAccessSeq32(armNextPC);
+ busPrefetchCount=0;
}
break;
CASE_256(0xb00)
{
// BL
- clockTicks += 3;
int offset = opcode & 0x00FFFFFF;
if(offset & 0x00800000) {
offset |= 0xFF000000;
@@ -7146,12 +8647,21 @@ if(cond_res) {
reg[15].I += offset;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
+ clockTicks += 2 + codeTicksAccess32(armNextPC) +
+ codeTicksAccessSeq32(armNextPC);
+ busPrefetchCount=0;
}
break;
CASE_256(0xf00)
// SWI
- clockTicks += 3;
- CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
+ clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
+ clockTicks += 2 + codeTicksAccess32(armNextPC) +
+ codeTicksAccessSeq32(armNextPC);
+ busPrefetchCount=0;
+ CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
+
break;
#ifdef GP_SUPPORT
case 0xe11:
@@ -7186,3 +8696,6 @@ if(cond_res) {
// END
}
}
+
+if (clockTicks == 0)
+ clockTicks = codeTicksAccessSeq32(oldArmNextPC) + 1;
diff --git a/src/armdis.cpp b/src/armdis.cpp
index 5162952f..e22de54b 100644
--- a/src/armdis.cpp
+++ b/src/armdis.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -117,8 +117,8 @@ const Opcodes thumbOpcodes[] = {
{0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]"},
// Format 8
{0xfe00, 0x5200, "strh %r0, [%r3, %r6]"},
- {0xfe00, 0x5600, "ldrh %r0, [%r3, %r6]"},
- {0xfe00, 0x5a00, "ldsb %r0, [%r3, %r6]"},
+ {0xfe00, 0x5600, "ldsb %r0, [%r3, %r6]"},
+ {0xfe00, 0x5a00, "ldrh %r0, [%r3, %r6]"},
{0xfe00, 0x5e00, "ldsh %r0, [%r3, %r6]"},
// Format 9
{0xe800, 0x6000, "str%B %r0, [%r3, %p]"},
diff --git a/src/bios.cpp b/src/bios.cpp
index 7876493c..b817ec7e 100644
--- a/src/bios.cpp
+++ b/src/bios.cpp
@@ -1,1156 +1,1165 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-#include
-
-#include "GBA.h"
-#include "bios.h"
-#include "GBAinline.h"
-#include "Globals.h"
-
-s16 sineTable[256] = {
- (s16)0x0000, (s16)0x0192, (s16)0x0323, (s16)0x04B5, (s16)0x0645, (s16)0x07D5, (s16)0x0964, (s16)0x0AF1,
- (s16)0x0C7C, (s16)0x0E05, (s16)0x0F8C, (s16)0x1111, (s16)0x1294, (s16)0x1413, (s16)0x158F, (s16)0x1708,
- (s16)0x187D, (s16)0x19EF, (s16)0x1B5D, (s16)0x1CC6, (s16)0x1E2B, (s16)0x1F8B, (s16)0x20E7, (s16)0x223D,
- (s16)0x238E, (s16)0x24DA, (s16)0x261F, (s16)0x275F, (s16)0x2899, (s16)0x29CD, (s16)0x2AFA, (s16)0x2C21,
- (s16)0x2D41, (s16)0x2E5A, (s16)0x2F6B, (s16)0x3076, (s16)0x3179, (s16)0x3274, (s16)0x3367, (s16)0x3453,
- (s16)0x3536, (s16)0x3612, (s16)0x36E5, (s16)0x37AF, (s16)0x3871, (s16)0x392A, (s16)0x39DA, (s16)0x3A82,
- (s16)0x3B20, (s16)0x3BB6, (s16)0x3C42, (s16)0x3CC5, (s16)0x3D3E, (s16)0x3DAE, (s16)0x3E14, (s16)0x3E71,
- (s16)0x3EC5, (s16)0x3F0E, (s16)0x3F4E, (s16)0x3F84, (s16)0x3FB1, (s16)0x3FD3, (s16)0x3FEC, (s16)0x3FFB,
- (s16)0x4000, (s16)0x3FFB, (s16)0x3FEC, (s16)0x3FD3, (s16)0x3FB1, (s16)0x3F84, (s16)0x3F4E, (s16)0x3F0E,
- (s16)0x3EC5, (s16)0x3E71, (s16)0x3E14, (s16)0x3DAE, (s16)0x3D3E, (s16)0x3CC5, (s16)0x3C42, (s16)0x3BB6,
- (s16)0x3B20, (s16)0x3A82, (s16)0x39DA, (s16)0x392A, (s16)0x3871, (s16)0x37AF, (s16)0x36E5, (s16)0x3612,
- (s16)0x3536, (s16)0x3453, (s16)0x3367, (s16)0x3274, (s16)0x3179, (s16)0x3076, (s16)0x2F6B, (s16)0x2E5A,
- (s16)0x2D41, (s16)0x2C21, (s16)0x2AFA, (s16)0x29CD, (s16)0x2899, (s16)0x275F, (s16)0x261F, (s16)0x24DA,
- (s16)0x238E, (s16)0x223D, (s16)0x20E7, (s16)0x1F8B, (s16)0x1E2B, (s16)0x1CC6, (s16)0x1B5D, (s16)0x19EF,
- (s16)0x187D, (s16)0x1708, (s16)0x158F, (s16)0x1413, (s16)0x1294, (s16)0x1111, (s16)0x0F8C, (s16)0x0E05,
- (s16)0x0C7C, (s16)0x0AF1, (s16)0x0964, (s16)0x07D5, (s16)0x0645, (s16)0x04B5, (s16)0x0323, (s16)0x0192,
- (s16)0x0000, (s16)0xFE6E, (s16)0xFCDD, (s16)0xFB4B, (s16)0xF9BB, (s16)0xF82B, (s16)0xF69C, (s16)0xF50F,
- (s16)0xF384, (s16)0xF1FB, (s16)0xF074, (s16)0xEEEF, (s16)0xED6C, (s16)0xEBED, (s16)0xEA71, (s16)0xE8F8,
- (s16)0xE783, (s16)0xE611, (s16)0xE4A3, (s16)0xE33A, (s16)0xE1D5, (s16)0xE075, (s16)0xDF19, (s16)0xDDC3,
- (s16)0xDC72, (s16)0xDB26, (s16)0xD9E1, (s16)0xD8A1, (s16)0xD767, (s16)0xD633, (s16)0xD506, (s16)0xD3DF,
- (s16)0xD2BF, (s16)0xD1A6, (s16)0xD095, (s16)0xCF8A, (s16)0xCE87, (s16)0xCD8C, (s16)0xCC99, (s16)0xCBAD,
- (s16)0xCACA, (s16)0xC9EE, (s16)0xC91B, (s16)0xC851, (s16)0xC78F, (s16)0xC6D6, (s16)0xC626, (s16)0xC57E,
- (s16)0xC4E0, (s16)0xC44A, (s16)0xC3BE, (s16)0xC33B, (s16)0xC2C2, (s16)0xC252, (s16)0xC1EC, (s16)0xC18F,
- (s16)0xC13B, (s16)0xC0F2, (s16)0xC0B2, (s16)0xC07C, (s16)0xC04F, (s16)0xC02D, (s16)0xC014, (s16)0xC005,
- (s16)0xC000, (s16)0xC005, (s16)0xC014, (s16)0xC02D, (s16)0xC04F, (s16)0xC07C, (s16)0xC0B2, (s16)0xC0F2,
- (s16)0xC13B, (s16)0xC18F, (s16)0xC1EC, (s16)0xC252, (s16)0xC2C2, (s16)0xC33B, (s16)0xC3BE, (s16)0xC44A,
- (s16)0xC4E0, (s16)0xC57E, (s16)0xC626, (s16)0xC6D6, (s16)0xC78F, (s16)0xC851, (s16)0xC91B, (s16)0xC9EE,
- (s16)0xCACA, (s16)0xCBAD, (s16)0xCC99, (s16)0xCD8C, (s16)0xCE87, (s16)0xCF8A, (s16)0xD095, (s16)0xD1A6,
- (s16)0xD2BF, (s16)0xD3DF, (s16)0xD506, (s16)0xD633, (s16)0xD767, (s16)0xD8A1, (s16)0xD9E1, (s16)0xDB26,
- (s16)0xDC72, (s16)0xDDC3, (s16)0xDF19, (s16)0xE075, (s16)0xE1D5, (s16)0xE33A, (s16)0xE4A3, (s16)0xE611,
- (s16)0xE783, (s16)0xE8F8, (s16)0xEA71, (s16)0xEBED, (s16)0xED6C, (s16)0xEEEF, (s16)0xF074, (s16)0xF1FB,
- (s16)0xF384, (s16)0xF50F, (s16)0xF69C, (s16)0xF82B, (s16)0xF9BB, (s16)0xFB4B, (s16)0xFCDD, (s16)0xFE6E
-};
-
-void BIOS_ArcTan()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan: %08x (VCOUNT=%2d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
-
- s32 a = -(((s32)(reg[0].I*reg[0].I)) >> 14);
- s32 b = ((0xA9 * a) >> 14) + 0x390;
- b = ((b * a) >> 14) + 0x91C;
- b = ((b * a) >> 14) + 0xFB6;
- b = ((b * a) >> 14) + 0x16AA;
- b = ((b * a) >> 14) + 0x2081;
- b = ((b * a) >> 14) + 0x3651;
- b = ((b * a) >> 14) + 0xA2F9;
- a = ((s32)reg[0].I * b) >> 16;
- reg[0].I = a;
-
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan: return=%08x\n",
- reg[0].I);
- }
-#endif
-}
-
-void BIOS_ArcTan2()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan2: %08x,%08x (VCOUNT=%2d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- s16 x = reg[0].I;
- s16 y = reg[1].I;
- s16 res = 0;
- if (y == 0) {
- res = 0x8000 & x;
- } else {
- if (x == 0) {
- res = (0x8000 & y) + 0x4000;
- } else {
- if (abs(x) > abs(y)) {
- reg[1].I = x;
- reg[0].I = y << 14;
- BIOS_Div();
- BIOS_ArcTan();
- if (x < 0)
- res = 0x8000 + reg[0].I;
- else
- res = ((y & 0x8000) << 1 ) + reg[0].I;
- } else {
- reg[0].I = x << 14;
- BIOS_Div();
- BIOS_ArcTan();
- res = (0x4000 + (y & 0x8000)) - reg[0].I;
- }
- }
- }
- reg[0].I = ((u32)res) & 0xffff;
-
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan2: return=%08x\n",
- reg[0].I);
- }
-#endif
-}
-
-void BIOS_BitUnPack()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("BitUnPack: %08x,%08x,%08x (VCOUNT=%2d)\n",
- reg[0].I,
- reg[1].I,
- reg[2].I,
- VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
- u32 header = reg[2].I;
-
- int len = CPUReadHalfWord(header);
- // check address
- int bits = CPUReadByte(header+2);
- int revbits = 8 - bits;
- // u32 value = 0;
- u32 base = CPUReadMemory(header+4);
- bool addBase = (base & 0x80000000) ? true : false;
- base &= 0x7fffffff;
- int dataSize = CPUReadByte(header+3);
-
- int data = 0;
- int bitwritecount = 0;
- while(1) {
- len -= 1;
- if(len < 0)
- break;
- int mask = 0xff >> revbits;
- u8 b = CPUReadByte(source);
- source++;
- int bitcount = 0;
- while(1) {
- if(bitcount >= 8)
- break;
- u32 d = b & mask;
- u32 temp = d >> bitcount;
- if(!temp && addBase) {
- temp += base;
- }
- data |= temp << bitwritecount;
- bitwritecount += dataSize;
- if(bitwritecount >= 32) {
- CPUWriteMemory(dest, data);
- dest += 4;
- data = 0;
- bitwritecount = 0;
- }
- mask <<= bits;
- bitcount += bits;
- }
- }
-}
-
-void BIOS_BgAffineSet()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("BgAffineSet: %08x,%08x,%08x (VCOUNT=%2d)\n",
- reg[0].I,
- reg[1].I,
- reg[2].I,
- VCOUNT);
- }
-#endif
-
- u32 src = reg[0].I;
- u32 dest = reg[1].I;
- int num = reg[2].I;
-
- for(int i = 0; i < num; i++) {
- s32 cx = CPUReadMemory(src);
- src+=4;
- s32 cy = CPUReadMemory(src);
- src+=4;
- s16 dispx = CPUReadHalfWord(src);
- src+=2;
- s16 dispy = CPUReadHalfWord(src);
- src+=2;
- s16 rx = CPUReadHalfWord(src);
- src+=2;
- s16 ry = CPUReadHalfWord(src);
- src+=2;
- u16 theta = CPUReadHalfWord(src)>>8;
- src+=4; // keep structure alignment
- s32 a = sineTable[(theta+0x40)&255];
- s32 b = sineTable[theta];
-
- s16 dx = (rx * a)>>14;
- s16 dmx = (rx * b)>>14;
- s16 dy = (ry * b)>>14;
- s16 dmy = (ry * a)>>14;
-
- CPUWriteHalfWord(dest, dx);
- dest += 2;
- CPUWriteHalfWord(dest, -dmx);
- dest += 2;
- CPUWriteHalfWord(dest, dy);
- dest += 2;
- CPUWriteHalfWord(dest, dmy);
- dest += 2;
-
- s32 startx = cx - dx * dispx + dmx * dispy;
- s32 starty = cy - dy * dispx - dmy * dispy;
-
- CPUWriteMemory(dest, startx);
- dest += 4;
- CPUWriteMemory(dest, starty);
- dest += 4;
- }
-}
-
-void BIOS_CpuSet()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("CpuSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
- reg[2].I, VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
- u32 cnt = reg[2].I;
-
- if(((source & 0xe000000) == 0) ||
- ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int count = cnt & 0x1FFFFF;
-
- // 32-bit ?
- if((cnt >> 26) & 1) {
- // needed for 32-bit mode!
- source &= 0xFFFFFFFC;
- dest &= 0xFFFFFFFC;
- // fill ?
- if((cnt >> 24) & 1) {
- u32 value = CPUReadMemory(source);
- while(count) {
- CPUWriteMemory(dest, value);
- dest += 4;
- count--;
- }
- } else {
- // copy
- while(count) {
- CPUWriteMemory(dest, CPUReadMemory(source));
- source += 4;
- dest += 4;
- count--;
- }
- }
- } else {
- // 16-bit fill?
- if((cnt >> 24) & 1) {
- u16 value = CPUReadHalfWord(source);
- while(count) {
- CPUWriteHalfWord(dest, value);
- dest += 2;
- count--;
- }
- } else {
- // copy
- while(count) {
- CPUWriteHalfWord(dest, CPUReadHalfWord(source));
- source += 2;
- dest += 2;
- count--;
- }
- }
- }
-}
-
-void BIOS_CpuFastSet()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("CpuFastSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
- reg[2].I, VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
- u32 cnt = reg[2].I;
-
- if(((source & 0xe000000) == 0) ||
- ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- // needed for 32-bit mode!
- source &= 0xFFFFFFFC;
- dest &= 0xFFFFFFFC;
-
- int count = cnt & 0x1FFFFF;
-
- // fill?
- if((cnt >> 24) & 1) {
- while(count > 0) {
- // BIOS always transfers 32 bytes at a time
- u32 value = CPUReadMemory(source);
- for(int i = 0; i < 8; i++) {
- CPUWriteMemory(dest, value);
- dest += 4;
- }
- count -= 8;
- }
- } else {
- // copy
- while(count > 0) {
- // BIOS always transfers 32 bytes at a time
- for(int i = 0; i < 8; i++) {
- CPUWriteMemory(dest, CPUReadMemory(source));
- source += 4;
- dest += 4;
- }
- count -= 8;
- }
- }
-}
-
-void BIOS_Diff8bitUnFilterWram()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Diff8bitUnFilterWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
- reg[1].I, VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff) & 0xe000000) == 0))
- return;
-
- int len = header >> 8;
-
- u8 data = CPUReadByte(source++);
- CPUWriteByte(dest++, data);
- len--;
-
- while(len > 0) {
- u8 diff = CPUReadByte(source++);
- data += diff;
- CPUWriteByte(dest++, data);
- len--;
- }
-}
-
-void BIOS_Diff8bitUnFilterVram()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Diff8bitUnFilterVram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
- reg[1].I, VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- u8 data = CPUReadByte(source++);
- u16 writeData = data;
- int shift = 8;
- int bytes = 1;
-
- while(len >= 2) {
- u8 diff = CPUReadByte(source++);
- data += diff;
- writeData |= (data << shift);
- bytes++;
- shift += 8;
- if(bytes == 2) {
- CPUWriteHalfWord(dest, writeData);
- dest += 2;
- len -= 2;
- bytes = 0;
- writeData = 0;
- shift = 0;
- }
- }
-}
-
-void BIOS_Diff16bitUnFilter()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Diff16bitUnFilter: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
- reg[1].I, VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- u16 data = CPUReadHalfWord(source);
- source += 2;
- CPUWriteHalfWord(dest, data);
- dest += 2;
- len -= 2;
-
- while(len >= 2) {
- u16 diff = CPUReadHalfWord(source);
- source += 2;
- data += diff;
- CPUWriteHalfWord(dest, data);
- dest += 2;
- len -= 2;
- }
-}
-
-void BIOS_Div()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Div: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- int number = reg[0].I;
- int denom = reg[1].I;
-
- if(denom != 0) {
- reg[0].I = number / denom;
- reg[1].I = number % denom;
- s32 temp = (s32)reg[0].I;
- reg[3].I = temp < 0 ? (u32)-temp : (u32)temp;
- }
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Div: return=0x%08x,0x%08x,0x%08x\n",
- reg[0].I,
- reg[1].I,
- reg[3].I);
- }
-#endif
-}
-
-void BIOS_DivARM()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("DivARM: 0x%08x, (VCOUNT=%d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
-
- u32 temp = reg[0].I;
- reg[0].I = reg[1].I;
- reg[1].I = temp;
- BIOS_Div();
-}
-
-void BIOS_HuffUnComp()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("HuffUnComp: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- u8 treeSize = CPUReadByte(source++);
-
- u32 treeStart = source;
-
- source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte
-
- int len = header >> 8;
-
- u32 mask = 0x80000000;
- u32 data = CPUReadMemory(source);
- source += 4;
-
- int pos = 0;
- u8 rootNode = CPUReadByte(treeStart);
- u8 currentNode = rootNode;
- bool writeData = false;
- int byteShift = 0;
- int byteCount = 0;
- u32 writeValue = 0;
-
- if((header & 0x0F) == 8) {
- while(len > 0) {
- // take left
- if(pos == 0)
- pos++;
- else
- pos += (((currentNode & 0x3F)+1)<<1);
-
- if(data & mask) {
- // right
- if(currentNode & 0x40)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos+1);
- } else {
- // left
- if(currentNode & 0x80)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos);
- }
-
- if(writeData) {
- writeValue |= (currentNode << byteShift);
- byteCount++;
- byteShift += 8;
-
- pos = 0;
- currentNode = rootNode;
- writeData = false;
-
- if(byteCount == 4) {
- byteCount = 0;
- byteShift = 0;
- CPUWriteMemory(dest, writeValue);
- writeValue = 0;
- dest += 4;
- len -= 4;
- }
- }
- mask >>= 1;
- if(mask == 0) {
- mask = 0x80000000;
- data = CPUReadMemory(source);
- source += 4;
- }
- }
- } else {
- int halfLen = 0;
- int value = 0;
- while(len > 0) {
- // take left
- if(pos == 0)
- pos++;
- else
- pos += (((currentNode & 0x3F)+1)<<1);
-
- if((data & mask)) {
- // right
- if(currentNode & 0x40)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos+1);
- } else {
- // left
- if(currentNode & 0x80)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos);
- }
-
- if(writeData) {
- if(halfLen == 0)
- value |= currentNode;
- else
- value |= (currentNode<<4);
-
- halfLen += 4;
- if(halfLen == 8) {
- writeValue |= (value << byteShift);
- byteCount++;
- byteShift += 8;
-
- halfLen = 0;
- value = 0;
-
- if(byteCount == 4) {
- byteCount = 0;
- byteShift = 0;
- CPUWriteMemory(dest, writeValue);
- dest += 4;
- writeValue = 0;
- len -= 4;
- }
- }
- pos = 0;
- currentNode = rootNode;
- writeData = false;
- }
- mask >>= 1;
- if(mask == 0) {
- mask = 0x80000000;
- data = CPUReadMemory(source);
- source += 4;
- }
- }
- }
-}
-
-void BIOS_LZ77UnCompVram()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("LZ77UnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int byteCount = 0;
- int byteShift = 0;
- u32 writeValue = 0;
-
- int len = header >> 8;
-
- while(len > 0) {
- u8 d = CPUReadByte(source++);
-
- if(d) {
- for(int i = 0; i < 8; i++) {
- if(d & 0x80) {
- u16 data = CPUReadByte(source++) << 8;
- data |= CPUReadByte(source++);
- int length = (data >> 12) + 3;
- int offset = (data & 0x0FFF);
- u32 windowOffset = dest + byteCount - offset - 1;
- for(int i = 0; i < length; i++) {
- writeValue |= (CPUReadByte(windowOffset++) << byteShift);
- byteShift += 8;
- byteCount++;
-
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- } else {
- writeValue |= (CPUReadByte(source++) << byteShift);
- byteShift += 8;
- byteCount++;
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- d <<= 1;
- }
- } else {
- for(int i = 0; i < 8; i++) {
- writeValue |= (CPUReadByte(source++) << byteShift);
- byteShift += 8;
- byteCount++;
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteShift = 0;
- byteCount = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- }
- }
-}
-
-void BIOS_LZ77UnCompWram()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("LZ77UnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
- VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- while(len > 0) {
- u8 d = CPUReadByte(source++);
-
- if(d) {
- for(int i = 0; i < 8; i++) {
- if(d & 0x80) {
- u16 data = CPUReadByte(source++) << 8;
- data |= CPUReadByte(source++);
- int length = (data >> 12) + 3;
- int offset = (data & 0x0FFF);
- u32 windowOffset = dest - offset - 1;
- for(int i = 0; i < length; i++) {
- CPUWriteByte(dest++, CPUReadByte(windowOffset++));
- len--;
- if(len == 0)
- return;
- }
- } else {
- CPUWriteByte(dest++, CPUReadByte(source++));
- len--;
- if(len == 0)
- return;
- }
- d <<= 1;
- }
- } else {
- for(int i = 0; i < 8; i++) {
- CPUWriteByte(dest++, CPUReadByte(source++));
- len--;
- if(len == 0)
- return;
- }
- }
- }
-}
-
-void BIOS_ObjAffineSet()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("ObjAffineSet: 0x%08x,0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- reg[2].I,
- reg[3].I,
- VCOUNT);
- }
-#endif
-
- u32 src = reg[0].I;
- u32 dest = reg[1].I;
- int num = reg[2].I;
- int offset = reg[3].I;
-
- for(int i = 0; i < num; i++) {
- s16 rx = CPUReadHalfWord(src);
- src+=2;
- s16 ry = CPUReadHalfWord(src);
- src+=2;
- u16 theta = CPUReadHalfWord(src)>>8;
- src+=4; // keep structure alignment
-
- s32 a = (s32)sineTable[(theta+0x40)&255];
- s32 b = (s32)sineTable[theta];
-
- s16 dx = ((s32)rx * a)>>14;
- s16 dmx = ((s32)rx * b)>>14;
- s16 dy = ((s32)ry * b)>>14;
- s16 dmy = ((s32)ry * a)>>14;
-
- CPUWriteHalfWord(dest, dx);
- dest += offset;
- CPUWriteHalfWord(dest, -dmx);
- dest += offset;
- CPUWriteHalfWord(dest, dy);
- dest += offset;
- CPUWriteHalfWord(dest, dmy);
- dest += offset;
- }
-}
-
-void BIOS_RegisterRamReset(u32 flags)
-{
- // no need to trace here. this is only called directly from GBA.cpp
- // to emulate bios initialization
-
- if(flags) {
- if(flags & 0x01) {
- // clear work RAM
- memset(workRAM, 0, 0x40000);
- }
- if(flags & 0x02) {
- // clear internal RAM
- memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff
- }
- if(flags & 0x04) {
- // clear palette RAM
- memset(paletteRAM, 0, 0x400);
- }
- if(flags & 0x08) {
- // clear VRAM
- memset(vram, 0, 0x18000);
- }
- if(flags & 0x10) {
- // clean OAM
- memset(oam, 0, 0x400);
- }
-
- if(flags & 0x80) {
- int i;
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x200+i*2, 0);
-
- CPUUpdateRegister(0x202, 0xFFFF);
-
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x4+i*2, 0);
-
- for(i = 0; i < 16; i++)
- CPUUpdateRegister(0x20+i*2, 0);
-
- for(i = 0; i < 24; i++)
- CPUUpdateRegister(0xb0+i*2, 0);
-
- CPUUpdateRegister(0x130, 0);
- CPUUpdateRegister(0x20, 0x100);
- CPUUpdateRegister(0x30, 0x100);
- CPUUpdateRegister(0x26, 0x100);
- CPUUpdateRegister(0x36, 0x100);
- }
-
- if(flags & 0x20) {
- int i;
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x110+i*2, 0);
- CPUUpdateRegister(0x134, 0x8000);
- for(i = 0; i < 7; i++)
- CPUUpdateRegister(0x140+i*2, 0);
- }
-
- if(flags & 0x40) {
- int i;
- CPUWriteByte(0x4000084, 0);
- CPUWriteByte(0x4000084, 0x80);
- CPUWriteMemory(0x4000080, 0x880e0000);
- CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
- CPUWriteByte(0x4000070, 0x70);
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x90+i*2, 0);
- CPUWriteByte(0x4000070, 0);
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x90+i*2, 0);
- CPUWriteByte(0x4000084, 0);
- }
- }
-}
-
-void BIOS_RegisterRamReset()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("RegisterRamReset: 0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
-
- BIOS_RegisterRamReset(reg[0].I);
-}
-
-void BIOS_RLUnCompVram()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("RLUnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
- int byteCount = 0;
- int byteShift = 0;
- u32 writeValue = 0;
-
- while(len > 0) {
- u8 d = CPUReadByte(source++);
- int l = d & 0x7F;
- if(d & 0x80) {
- u8 data = CPUReadByte(source++);
- l += 3;
- for(int i = 0;i < l; i++) {
- writeValue |= (data << byteShift);
- byteShift += 8;
- byteCount++;
-
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- } else {
- l++;
- for(int i = 0; i < l; i++) {
- writeValue |= (CPUReadByte(source++) << byteShift);
- byteShift += 8;
- byteCount++;
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- }
- }
-}
-
-void BIOS_RLUnCompWram()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("RLUnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- u32 source = reg[0].I;
- u32 dest = reg[1].I;
-
- u32 header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- while(len > 0) {
- u8 d = CPUReadByte(source++);
- int l = d & 0x7F;
- if(d & 0x80) {
- u8 data = CPUReadByte(source++);
- l += 3;
- for(int i = 0;i < l; i++) {
- CPUWriteByte(dest++, data);
- len--;
- if(len == 0)
- return;
- }
- } else {
- l++;
- for(int i = 0; i < l; i++) {
- CPUWriteByte(dest++, CPUReadByte(source++));
- len--;
- if(len == 0)
- return;
- }
- }
- }
-}
-
-void BIOS_SoftReset()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("SoftReset: (VCOUNT=%d)\n", VCOUNT);
- }
-#endif
-
- armState = true;
- armMode = 0x1F;
- armIrqEnable = false;
- C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
- reg[13].I = 0x03007F00;
- reg[14].I = 0x00000000;
- reg[16].I = 0x00000000;
- reg[R13_IRQ].I = 0x03007FA0;
- reg[R14_IRQ].I = 0x00000000;
- reg[SPSR_IRQ].I = 0x00000000;
- reg[R13_SVC].I = 0x03007FE0;
- reg[R14_SVC].I = 0x00000000;
- reg[SPSR_SVC].I = 0x00000000;
- u8 b = internalRAM[0x7ffa];
-
- memset(&internalRAM[0x7e00], 0, 0x200);
-
- if(b) {
- armNextPC = 0x02000000;
- reg[15].I = 0x02000004;
- } else {
- armNextPC = 0x08000000;
- reg[15].I = 0x08000004;
- }
-}
-
-void BIOS_Sqrt()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Sqrt: %08x (VCOUNT=%2d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
- reg[0].I = (u32)sqrt((double)reg[0].I);
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("Sqrt: return=%08x\n",
- reg[0].I);
- }
-#endif
-}
-
-void BIOS_MidiKey2Freq()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("MidiKey2Freq: WaveData=%08x mk=%08x fp=%08x\n",
- reg[0].I,
- reg[1].I,
- reg[2].I);
- }
-#endif
- int freq = CPUReadMemory(reg[0].I+4);
- double tmp;
- tmp = ((double)(180 - reg[1].I)) - ((double)reg[2].I / 256.f);
- tmp = pow((double)2.f, tmp / 12.f);
- reg[0].I = (int)((double)freq / tmp);
-
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("MidiKey2Freq: return %08x\n",
- reg[0].I);
- }
-#endif
-}
-
-void BIOS_SndDriverJmpTableCopy()
-{
-#ifdef DEV_VERSION
- if(systemVerbose & VERBOSE_SWI) {
- log("SndDriverJmpTableCopy: dest=%08x\n",
- reg[0].I);
- }
-#endif
- for(int i = 0; i < 0x24; i++) {
- CPUWriteMemory(reg[0].I, 0x9c);
- reg[0].I += 4;
- }
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+#include
+
+#include "GBA.h"
+#include "bios.h"
+#include "GBAinline.h"
+#include "Globals.h"
+
+s16 sineTable[256] = {
+ (s16)0x0000, (s16)0x0192, (s16)0x0323, (s16)0x04B5, (s16)0x0645, (s16)0x07D5, (s16)0x0964, (s16)0x0AF1,
+ (s16)0x0C7C, (s16)0x0E05, (s16)0x0F8C, (s16)0x1111, (s16)0x1294, (s16)0x1413, (s16)0x158F, (s16)0x1708,
+ (s16)0x187D, (s16)0x19EF, (s16)0x1B5D, (s16)0x1CC6, (s16)0x1E2B, (s16)0x1F8B, (s16)0x20E7, (s16)0x223D,
+ (s16)0x238E, (s16)0x24DA, (s16)0x261F, (s16)0x275F, (s16)0x2899, (s16)0x29CD, (s16)0x2AFA, (s16)0x2C21,
+ (s16)0x2D41, (s16)0x2E5A, (s16)0x2F6B, (s16)0x3076, (s16)0x3179, (s16)0x3274, (s16)0x3367, (s16)0x3453,
+ (s16)0x3536, (s16)0x3612, (s16)0x36E5, (s16)0x37AF, (s16)0x3871, (s16)0x392A, (s16)0x39DA, (s16)0x3A82,
+ (s16)0x3B20, (s16)0x3BB6, (s16)0x3C42, (s16)0x3CC5, (s16)0x3D3E, (s16)0x3DAE, (s16)0x3E14, (s16)0x3E71,
+ (s16)0x3EC5, (s16)0x3F0E, (s16)0x3F4E, (s16)0x3F84, (s16)0x3FB1, (s16)0x3FD3, (s16)0x3FEC, (s16)0x3FFB,
+ (s16)0x4000, (s16)0x3FFB, (s16)0x3FEC, (s16)0x3FD3, (s16)0x3FB1, (s16)0x3F84, (s16)0x3F4E, (s16)0x3F0E,
+ (s16)0x3EC5, (s16)0x3E71, (s16)0x3E14, (s16)0x3DAE, (s16)0x3D3E, (s16)0x3CC5, (s16)0x3C42, (s16)0x3BB6,
+ (s16)0x3B20, (s16)0x3A82, (s16)0x39DA, (s16)0x392A, (s16)0x3871, (s16)0x37AF, (s16)0x36E5, (s16)0x3612,
+ (s16)0x3536, (s16)0x3453, (s16)0x3367, (s16)0x3274, (s16)0x3179, (s16)0x3076, (s16)0x2F6B, (s16)0x2E5A,
+ (s16)0x2D41, (s16)0x2C21, (s16)0x2AFA, (s16)0x29CD, (s16)0x2899, (s16)0x275F, (s16)0x261F, (s16)0x24DA,
+ (s16)0x238E, (s16)0x223D, (s16)0x20E7, (s16)0x1F8B, (s16)0x1E2B, (s16)0x1CC6, (s16)0x1B5D, (s16)0x19EF,
+ (s16)0x187D, (s16)0x1708, (s16)0x158F, (s16)0x1413, (s16)0x1294, (s16)0x1111, (s16)0x0F8C, (s16)0x0E05,
+ (s16)0x0C7C, (s16)0x0AF1, (s16)0x0964, (s16)0x07D5, (s16)0x0645, (s16)0x04B5, (s16)0x0323, (s16)0x0192,
+ (s16)0x0000, (s16)0xFE6E, (s16)0xFCDD, (s16)0xFB4B, (s16)0xF9BB, (s16)0xF82B, (s16)0xF69C, (s16)0xF50F,
+ (s16)0xF384, (s16)0xF1FB, (s16)0xF074, (s16)0xEEEF, (s16)0xED6C, (s16)0xEBED, (s16)0xEA71, (s16)0xE8F8,
+ (s16)0xE783, (s16)0xE611, (s16)0xE4A3, (s16)0xE33A, (s16)0xE1D5, (s16)0xE075, (s16)0xDF19, (s16)0xDDC3,
+ (s16)0xDC72, (s16)0xDB26, (s16)0xD9E1, (s16)0xD8A1, (s16)0xD767, (s16)0xD633, (s16)0xD506, (s16)0xD3DF,
+ (s16)0xD2BF, (s16)0xD1A6, (s16)0xD095, (s16)0xCF8A, (s16)0xCE87, (s16)0xCD8C, (s16)0xCC99, (s16)0xCBAD,
+ (s16)0xCACA, (s16)0xC9EE, (s16)0xC91B, (s16)0xC851, (s16)0xC78F, (s16)0xC6D6, (s16)0xC626, (s16)0xC57E,
+ (s16)0xC4E0, (s16)0xC44A, (s16)0xC3BE, (s16)0xC33B, (s16)0xC2C2, (s16)0xC252, (s16)0xC1EC, (s16)0xC18F,
+ (s16)0xC13B, (s16)0xC0F2, (s16)0xC0B2, (s16)0xC07C, (s16)0xC04F, (s16)0xC02D, (s16)0xC014, (s16)0xC005,
+ (s16)0xC000, (s16)0xC005, (s16)0xC014, (s16)0xC02D, (s16)0xC04F, (s16)0xC07C, (s16)0xC0B2, (s16)0xC0F2,
+ (s16)0xC13B, (s16)0xC18F, (s16)0xC1EC, (s16)0xC252, (s16)0xC2C2, (s16)0xC33B, (s16)0xC3BE, (s16)0xC44A,
+ (s16)0xC4E0, (s16)0xC57E, (s16)0xC626, (s16)0xC6D6, (s16)0xC78F, (s16)0xC851, (s16)0xC91B, (s16)0xC9EE,
+ (s16)0xCACA, (s16)0xCBAD, (s16)0xCC99, (s16)0xCD8C, (s16)0xCE87, (s16)0xCF8A, (s16)0xD095, (s16)0xD1A6,
+ (s16)0xD2BF, (s16)0xD3DF, (s16)0xD506, (s16)0xD633, (s16)0xD767, (s16)0xD8A1, (s16)0xD9E1, (s16)0xDB26,
+ (s16)0xDC72, (s16)0xDDC3, (s16)0xDF19, (s16)0xE075, (s16)0xE1D5, (s16)0xE33A, (s16)0xE4A3, (s16)0xE611,
+ (s16)0xE783, (s16)0xE8F8, (s16)0xEA71, (s16)0xEBED, (s16)0xED6C, (s16)0xEEEF, (s16)0xF074, (s16)0xF1FB,
+ (s16)0xF384, (s16)0xF50F, (s16)0xF69C, (s16)0xF82B, (s16)0xF9BB, (s16)0xFB4B, (s16)0xFCDD, (s16)0xFE6E
+};
+
+void BIOS_ArcTan()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("ArcTan: %08x (VCOUNT=%2d)\n",
+ reg[0].I,
+ VCOUNT);
+ }
+#endif
+
+ s32 a = -(((s32)(reg[0].I*reg[0].I)) >> 14);
+ s32 b = ((0xA9 * a) >> 14) + 0x390;
+ b = ((b * a) >> 14) + 0x91C;
+ b = ((b * a) >> 14) + 0xFB6;
+ b = ((b * a) >> 14) + 0x16AA;
+ b = ((b * a) >> 14) + 0x2081;
+ b = ((b * a) >> 14) + 0x3651;
+ b = ((b * a) >> 14) + 0xA2F9;
+ a = ((s32)reg[0].I * b) >> 16;
+ reg[0].I = a;
+
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("ArcTan: return=%08x\n",
+ reg[0].I);
+ }
+#endif
+}
+
+void BIOS_ArcTan2()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("ArcTan2: %08x,%08x (VCOUNT=%2d)\n",
+ reg[0].I,
+ reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ s32 x = reg[0].I;
+ s32 y = reg[1].I;
+ u32 res = 0;
+ if (y == 0) {
+ res = ((x>>16) & 0x8000);
+ } else {
+ if (x == 0) {
+ res = ((y>>16) & 0x8000) + 0x4000;
+ } else {
+ if ((abs(x) > abs(y)) || ((abs(x) == abs(y)) && (!((x<0) && (y<0))))) {
+ reg[1].I = x;
+ reg[0].I = y << 14;
+ BIOS_Div();
+ BIOS_ArcTan();
+ if (x < 0)
+ res = 0x8000 + reg[0].I;
+ else
+ res = (((y>>16) & 0x8000)<<1) + reg[0].I;
+ } else {
+ reg[0].I = x << 14;
+ BIOS_Div();
+ BIOS_ArcTan();
+ res = (0x4000 + ((y>>16) & 0x8000)) - reg[0].I;
+ }
+ }
+ }
+ reg[0].I = res;
+
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("ArcTan2: return=%08x\n",
+ reg[0].I);
+ }
+#endif
+}
+
+void BIOS_BitUnPack()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("BitUnPack: %08x,%08x,%08x (VCOUNT=%2d)\n",
+ reg[0].I,
+ reg[1].I,
+ reg[2].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+ u32 header = reg[2].I;
+
+ int len = CPUReadHalfWord(header);
+ // check address
+ if(((source & 0xe000000) == 0) ||
+ ((source + len) & 0xe000000) == 0)
+ return;
+
+ int bits = CPUReadByte(header+2);
+ int revbits = 8 - bits;
+ // u32 value = 0;
+ u32 base = CPUReadMemory(header+4);
+ bool addBase = (base & 0x80000000) ? true : false;
+ base &= 0x7fffffff;
+ int dataSize = CPUReadByte(header+3);
+
+ int data = 0;
+ int bitwritecount = 0;
+ while(1) {
+ len -= 1;
+ if(len < 0)
+ break;
+ int mask = 0xff >> revbits;
+ u8 b = CPUReadByte(source);
+ source++;
+ int bitcount = 0;
+ while(1) {
+ if(bitcount >= 8)
+ break;
+ u32 d = b & mask;
+ u32 temp = d >> bitcount;
+ if(d || addBase) {
+ temp += base;
+ }
+ data |= temp << bitwritecount;
+ bitwritecount += dataSize;
+ if(bitwritecount >= 32) {
+ CPUWriteMemory(dest, data);
+ dest += 4;
+ data = 0;
+ bitwritecount = 0;
+ }
+ mask <<= bits;
+ bitcount += bits;
+ }
+ }
+}
+
+void BIOS_GetBiosChecksum()
+{
+ reg[0].I=0xBAAE187F;
+}
+
+void BIOS_BgAffineSet()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("BgAffineSet: %08x,%08x,%08x (VCOUNT=%2d)\n",
+ reg[0].I,
+ reg[1].I,
+ reg[2].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 src = reg[0].I;
+ u32 dest = reg[1].I;
+ int num = reg[2].I;
+
+ for(int i = 0; i < num; i++) {
+ s32 cx = CPUReadMemory(src);
+ src+=4;
+ s32 cy = CPUReadMemory(src);
+ src+=4;
+ s16 dispx = CPUReadHalfWord(src);
+ src+=2;
+ s16 dispy = CPUReadHalfWord(src);
+ src+=2;
+ s16 rx = CPUReadHalfWord(src);
+ src+=2;
+ s16 ry = CPUReadHalfWord(src);
+ src+=2;
+ u16 theta = CPUReadHalfWord(src)>>8;
+ src+=4; // keep structure alignment
+ s32 a = sineTable[(theta+0x40)&255];
+ s32 b = sineTable[theta];
+
+ s16 dx = (rx * a)>>14;
+ s16 dmx = (rx * b)>>14;
+ s16 dy = (ry * b)>>14;
+ s16 dmy = (ry * a)>>14;
+
+ CPUWriteHalfWord(dest, dx);
+ dest += 2;
+ CPUWriteHalfWord(dest, -dmx);
+ dest += 2;
+ CPUWriteHalfWord(dest, dy);
+ dest += 2;
+ CPUWriteHalfWord(dest, dmy);
+ dest += 2;
+
+ s32 startx = cx - dx * dispx + dmx * dispy;
+ s32 starty = cy - dy * dispx - dmy * dispy;
+
+ CPUWriteMemory(dest, startx);
+ dest += 4;
+ CPUWriteMemory(dest, starty);
+ dest += 4;
+ }
+}
+
+void BIOS_CpuSet()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("CpuSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
+ reg[2].I, VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+ u32 cnt = reg[2].I;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int count = cnt & 0x1FFFFF;
+
+ // 32-bit ?
+ if((cnt >> 26) & 1) {
+ // needed for 32-bit mode!
+ source &= 0xFFFFFFFC;
+ dest &= 0xFFFFFFFC;
+ // fill ?
+ if((cnt >> 24) & 1) {
+ u32 value = (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source));
+ while(count) {
+ CPUWriteMemory(dest, value);
+ dest += 4;
+ count--;
+ }
+ } else {
+ // copy
+ while(count) {
+ CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source)));
+ source += 4;
+ dest += 4;
+ count--;
+ }
+ }
+ } else {
+ // 16-bit fill?
+ if((cnt >> 24) & 1) {
+ u16 value = (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source));
+ while(count) {
+ CPUWriteHalfWord(dest, value);
+ dest += 2;
+ count--;
+ }
+ } else {
+ // copy
+ while(count) {
+ CPUWriteHalfWord(dest, (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source)));
+ source += 2;
+ dest += 2;
+ count--;
+ }
+ }
+ }
+}
+
+void BIOS_CpuFastSet()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("CpuFastSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
+ reg[2].I, VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+ u32 cnt = reg[2].I;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ // needed for 32-bit mode!
+ source &= 0xFFFFFFFC;
+ dest &= 0xFFFFFFFC;
+
+ int count = cnt & 0x1FFFFF;
+
+ // fill?
+ if((cnt >> 24) & 1) {
+ while(count > 0) {
+ // BIOS always transfers 32 bytes at a time
+ u32 value = (source>0x0EFFFFFF ? 0xBAFFFFFB : CPUReadMemory(source));
+ for(int i = 0; i < 8; i++) {
+ CPUWriteMemory(dest, value);
+ dest += 4;
+ }
+ count -= 8;
+ }
+ } else {
+ // copy
+ while(count > 0) {
+ // BIOS always transfers 32 bytes at a time
+ for(int i = 0; i < 8; i++) {
+ CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0xBAFFFFFB :CPUReadMemory(source)));
+ source += 4;
+ dest += 4;
+ }
+ count -= 8;
+ }
+ }
+}
+
+void BIOS_Diff8bitUnFilterWram()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Diff8bitUnFilterWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
+ reg[1].I, VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff) & 0xe000000) == 0))
+ return;
+
+ int len = header >> 8;
+
+ u8 data = CPUReadByte(source++);
+ CPUWriteByte(dest++, data);
+ len--;
+
+ while(len > 0) {
+ u8 diff = CPUReadByte(source++);
+ data += diff;
+ CPUWriteByte(dest++, data);
+ len--;
+ }
+}
+
+void BIOS_Diff8bitUnFilterVram()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Diff8bitUnFilterVram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
+ reg[1].I, VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int len = header >> 8;
+
+ u8 data = CPUReadByte(source++);
+ u16 writeData = data;
+ int shift = 8;
+ int bytes = 1;
+
+ while(len >= 2) {
+ u8 diff = CPUReadByte(source++);
+ data += diff;
+ writeData |= (data << shift);
+ bytes++;
+ shift += 8;
+ if(bytes == 2) {
+ CPUWriteHalfWord(dest, writeData);
+ dest += 2;
+ len -= 2;
+ bytes = 0;
+ writeData = 0;
+ shift = 0;
+ }
+ }
+}
+
+void BIOS_Diff16bitUnFilter()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Diff16bitUnFilter: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
+ reg[1].I, VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int len = header >> 8;
+
+ u16 data = CPUReadHalfWord(source);
+ source += 2;
+ CPUWriteHalfWord(dest, data);
+ dest += 2;
+ len -= 2;
+
+ while(len >= 2) {
+ u16 diff = CPUReadHalfWord(source);
+ source += 2;
+ data += diff;
+ CPUWriteHalfWord(dest, data);
+ dest += 2;
+ len -= 2;
+ }
+}
+
+void BIOS_Div()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Div: 0x%08x,0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ int number = reg[0].I;
+ int denom = reg[1].I;
+
+ if(denom != 0) {
+ reg[0].I = number / denom;
+ reg[1].I = number % denom;
+ s32 temp = (s32)reg[0].I;
+ reg[3].I = temp < 0 ? (u32)-temp : (u32)temp;
+ }
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Div: return=0x%08x,0x%08x,0x%08x\n",
+ reg[0].I,
+ reg[1].I,
+ reg[3].I);
+ }
+#endif
+}
+
+void BIOS_DivARM()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("DivARM: 0x%08x, (VCOUNT=%d)\n",
+ reg[0].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 temp = reg[0].I;
+ reg[0].I = reg[1].I;
+ reg[1].I = temp;
+ BIOS_Div();
+}
+
+void BIOS_HuffUnComp()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("HuffUnComp: 0x%08x,0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ u8 treeSize = CPUReadByte(source++);
+
+ u32 treeStart = source;
+
+ source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte
+
+ int len = header >> 8;
+
+ u32 mask = 0x80000000;
+ u32 data = CPUReadMemory(source);
+ source += 4;
+
+ int pos = 0;
+ u8 rootNode = CPUReadByte(treeStart);
+ u8 currentNode = rootNode;
+ bool writeData = false;
+ int byteShift = 0;
+ int byteCount = 0;
+ u32 writeValue = 0;
+
+ if((header & 0x0F) == 8) {
+ while(len > 0) {
+ // take left
+ if(pos == 0)
+ pos++;
+ else
+ pos += (((currentNode & 0x3F)+1)<<1);
+
+ if(data & mask) {
+ // right
+ if(currentNode & 0x40)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart+pos+1);
+ } else {
+ // left
+ if(currentNode & 0x80)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart+pos);
+ }
+
+ if(writeData) {
+ writeValue |= (currentNode << byteShift);
+ byteCount++;
+ byteShift += 8;
+
+ pos = 0;
+ currentNode = rootNode;
+ writeData = false;
+
+ if(byteCount == 4) {
+ byteCount = 0;
+ byteShift = 0;
+ CPUWriteMemory(dest, writeValue);
+ writeValue = 0;
+ dest += 4;
+ len -= 4;
+ }
+ }
+ mask >>= 1;
+ if(mask == 0) {
+ mask = 0x80000000;
+ data = CPUReadMemory(source);
+ source += 4;
+ }
+ }
+ } else {
+ int halfLen = 0;
+ int value = 0;
+ while(len > 0) {
+ // take left
+ if(pos == 0)
+ pos++;
+ else
+ pos += (((currentNode & 0x3F)+1)<<1);
+
+ if((data & mask)) {
+ // right
+ if(currentNode & 0x40)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart+pos+1);
+ } else {
+ // left
+ if(currentNode & 0x80)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart+pos);
+ }
+
+ if(writeData) {
+ if(halfLen == 0)
+ value |= currentNode;
+ else
+ value |= (currentNode<<4);
+
+ halfLen += 4;
+ if(halfLen == 8) {
+ writeValue |= (value << byteShift);
+ byteCount++;
+ byteShift += 8;
+
+ halfLen = 0;
+ value = 0;
+
+ if(byteCount == 4) {
+ byteCount = 0;
+ byteShift = 0;
+ CPUWriteMemory(dest, writeValue);
+ dest += 4;
+ writeValue = 0;
+ len -= 4;
+ }
+ }
+ pos = 0;
+ currentNode = rootNode;
+ writeData = false;
+ }
+ mask >>= 1;
+ if(mask == 0) {
+ mask = 0x80000000;
+ data = CPUReadMemory(source);
+ source += 4;
+ }
+ }
+ }
+}
+
+void BIOS_LZ77UnCompVram()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("LZ77UnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int byteCount = 0;
+ int byteShift = 0;
+ u32 writeValue = 0;
+
+ int len = header >> 8;
+
+ while(len > 0) {
+ u8 d = CPUReadByte(source++);
+
+ if(d) {
+ for(int i = 0; i < 8; i++) {
+ if(d & 0x80) {
+ u16 data = CPUReadByte(source++) << 8;
+ data |= CPUReadByte(source++);
+ int length = (data >> 12) + 3;
+ int offset = (data & 0x0FFF);
+ u32 windowOffset = dest + byteCount - offset - 1;
+ for(int i = 0; i < length; i++) {
+ writeValue |= (CPUReadByte(windowOffset++) << byteShift);
+ byteShift += 8;
+ byteCount++;
+
+ if(byteCount == 2) {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ len--;
+ if(len == 0)
+ return;
+ }
+ } else {
+ writeValue |= (CPUReadByte(source++) << byteShift);
+ byteShift += 8;
+ byteCount++;
+ if(byteCount == 2) {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ len--;
+ if(len == 0)
+ return;
+ }
+ d <<= 1;
+ }
+ } else {
+ for(int i = 0; i < 8; i++) {
+ writeValue |= (CPUReadByte(source++) << byteShift);
+ byteShift += 8;
+ byteCount++;
+ if(byteCount == 2) {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteShift = 0;
+ byteCount = 0;
+ writeValue = 0;
+ }
+ len--;
+ if(len == 0)
+ return;
+ }
+ }
+ }
+}
+
+void BIOS_LZ77UnCompWram()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("LZ77UnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int len = header >> 8;
+
+ while(len > 0) {
+ u8 d = CPUReadByte(source++);
+
+ if(d) {
+ for(int i = 0; i < 8; i++) {
+ if(d & 0x80) {
+ u16 data = CPUReadByte(source++) << 8;
+ data |= CPUReadByte(source++);
+ int length = (data >> 12) + 3;
+ int offset = (data & 0x0FFF);
+ u32 windowOffset = dest - offset - 1;
+ for(int i = 0; i < length; i++) {
+ CPUWriteByte(dest++, CPUReadByte(windowOffset++));
+ len--;
+ if(len == 0)
+ return;
+ }
+ } else {
+ CPUWriteByte(dest++, CPUReadByte(source++));
+ len--;
+ if(len == 0)
+ return;
+ }
+ d <<= 1;
+ }
+ } else {
+ for(int i = 0; i < 8; i++) {
+ CPUWriteByte(dest++, CPUReadByte(source++));
+ len--;
+ if(len == 0)
+ return;
+ }
+ }
+ }
+}
+
+void BIOS_ObjAffineSet()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("ObjAffineSet: 0x%08x,0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ reg[1].I,
+ reg[2].I,
+ reg[3].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 src = reg[0].I;
+ u32 dest = reg[1].I;
+ int num = reg[2].I;
+ int offset = reg[3].I;
+
+ for(int i = 0; i < num; i++) {
+ s16 rx = CPUReadHalfWord(src);
+ src+=2;
+ s16 ry = CPUReadHalfWord(src);
+ src+=2;
+ u16 theta = CPUReadHalfWord(src)>>8;
+ src+=4; // keep structure alignment
+
+ s32 a = (s32)sineTable[(theta+0x40)&255];
+ s32 b = (s32)sineTable[theta];
+
+ s16 dx = ((s32)rx * a)>>14;
+ s16 dmx = ((s32)rx * b)>>14;
+ s16 dy = ((s32)ry * b)>>14;
+ s16 dmy = ((s32)ry * a)>>14;
+
+ CPUWriteHalfWord(dest, dx);
+ dest += offset;
+ CPUWriteHalfWord(dest, -dmx);
+ dest += offset;
+ CPUWriteHalfWord(dest, dy);
+ dest += offset;
+ CPUWriteHalfWord(dest, dmy);
+ dest += offset;
+ }
+}
+
+void BIOS_RegisterRamReset(u32 flags)
+{
+ // no need to trace here. this is only called directly from GBA.cpp
+ // to emulate bios initialization
+
+ CPUUpdateRegister(0x0, 0x80);
+
+ if(flags) {
+ if(flags & 0x01) {
+ // clear work RAM
+ memset(workRAM, 0, 0x40000);
+ }
+ if(flags & 0x02) {
+ // clear internal RAM
+ memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff
+ }
+ if(flags & 0x04) {
+ // clear palette RAM
+ memset(paletteRAM, 0, 0x400);
+ }
+ if(flags & 0x08) {
+ // clear VRAM
+ memset(vram, 0, 0x18000);
+ }
+ if(flags & 0x10) {
+ // clean OAM
+ memset(oam, 0, 0x400);
+ }
+
+ if(flags & 0x80) {
+ int i;
+ for(i = 0; i < 0x10; i++)
+ CPUUpdateRegister(0x200+i*2, 0);
+
+ for(i = 0; i < 0xF; i++)
+ CPUUpdateRegister(0x4+i*2, 0);
+
+ for(i = 0; i < 0x20; i++)
+ CPUUpdateRegister(0x20+i*2, 0);
+
+ for(i = 0; i < 0x18; i++)
+ CPUUpdateRegister(0xb0+i*2, 0);
+
+ CPUUpdateRegister(0x130, 0);
+ CPUUpdateRegister(0x20, 0x100);
+ CPUUpdateRegister(0x30, 0x100);
+ CPUUpdateRegister(0x26, 0x100);
+ CPUUpdateRegister(0x36, 0x100);
+ }
+
+ if(flags & 0x20) {
+ int i;
+ for(i = 0; i < 8; i++)
+ CPUUpdateRegister(0x110+i*2, 0);
+ CPUUpdateRegister(0x134, 0x8000);
+ for(i = 0; i < 7; i++)
+ CPUUpdateRegister(0x140+i*2, 0);
+ }
+
+ if(flags & 0x40) {
+ int i;
+ CPUWriteByte(0x4000084, 0);
+ CPUWriteByte(0x4000084, 0x80);
+ CPUWriteMemory(0x4000080, 0x880e0000);
+ CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
+ CPUWriteByte(0x4000070, 0x70);
+ for(i = 0; i < 8; i++)
+ CPUUpdateRegister(0x90+i*2, 0);
+ CPUWriteByte(0x4000070, 0);
+ for(i = 0; i < 8; i++)
+ CPUUpdateRegister(0x90+i*2, 0);
+ CPUWriteByte(0x4000084, 0);
+ }
+ }
+}
+
+void BIOS_RegisterRamReset()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("RegisterRamReset: 0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ VCOUNT);
+ }
+#endif
+
+ BIOS_RegisterRamReset(reg[0].I);
+}
+
+void BIOS_RLUnCompVram()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("RLUnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source & 0xFFFFFFFC);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int len = header >> 8;
+ int byteCount = 0;
+ int byteShift = 0;
+ u32 writeValue = 0;
+
+ while(len > 0) {
+ u8 d = CPUReadByte(source++);
+ int l = d & 0x7F;
+ if(d & 0x80) {
+ u8 data = CPUReadByte(source++);
+ l += 3;
+ for(int i = 0;i < l; i++) {
+ writeValue |= (data << byteShift);
+ byteShift += 8;
+ byteCount++;
+
+ if(byteCount == 2) {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ len--;
+ if(len == 0)
+ return;
+ }
+ } else {
+ l++;
+ for(int i = 0; i < l; i++) {
+ writeValue |= (CPUReadByte(source++) << byteShift);
+ byteShift += 8;
+ byteCount++;
+ if(byteCount == 2) {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ len--;
+ if(len == 0)
+ return;
+ }
+ }
+ }
+}
+
+void BIOS_RLUnCompWram()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("RLUnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n",
+ reg[0].I,
+ reg[1].I,
+ VCOUNT);
+ }
+#endif
+
+ u32 source = reg[0].I;
+ u32 dest = reg[1].I;
+
+ u32 header = CPUReadMemory(source & 0xFFFFFFFC);
+ source += 4;
+
+ if(((source & 0xe000000) == 0) ||
+ ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+ return;
+
+ int len = header >> 8;
+
+ while(len > 0) {
+ u8 d = CPUReadByte(source++);
+ int l = d & 0x7F;
+ if(d & 0x80) {
+ u8 data = CPUReadByte(source++);
+ l += 3;
+ for(int i = 0;i < l; i++) {
+ CPUWriteByte(dest++, data);
+ len--;
+ if(len == 0)
+ return;
+ }
+ } else {
+ l++;
+ for(int i = 0; i < l; i++) {
+ CPUWriteByte(dest++, CPUReadByte(source++));
+ len--;
+ if(len == 0)
+ return;
+ }
+ }
+ }
+}
+
+void BIOS_SoftReset()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("SoftReset: (VCOUNT=%d)\n", VCOUNT);
+ }
+#endif
+
+ armState = true;
+ armMode = 0x1F;
+ armIrqEnable = false;
+ C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
+ reg[13].I = 0x03007F00;
+ reg[14].I = 0x00000000;
+ reg[16].I = 0x00000000;
+ reg[R13_IRQ].I = 0x03007FA0;
+ reg[R14_IRQ].I = 0x00000000;
+ reg[SPSR_IRQ].I = 0x00000000;
+ reg[R13_SVC].I = 0x03007FE0;
+ reg[R14_SVC].I = 0x00000000;
+ reg[SPSR_SVC].I = 0x00000000;
+ u8 b = internalRAM[0x7ffa];
+
+ memset(&internalRAM[0x7e00], 0, 0x200);
+
+ if(b) {
+ armNextPC = 0x02000000;
+ reg[15].I = 0x02000004;
+ } else {
+ armNextPC = 0x08000000;
+ reg[15].I = 0x08000004;
+ }
+}
+
+void BIOS_Sqrt()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Sqrt: %08x (VCOUNT=%2d)\n",
+ reg[0].I,
+ VCOUNT);
+ }
+#endif
+ reg[0].I = (u32)sqrt((double)reg[0].I);
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("Sqrt: return=%08x\n",
+ reg[0].I);
+ }
+#endif
+}
+
+void BIOS_MidiKey2Freq()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("MidiKey2Freq: WaveData=%08x mk=%08x fp=%08x\n",
+ reg[0].I,
+ reg[1].I,
+ reg[2].I);
+ }
+#endif
+ int freq = CPUReadMemory(reg[0].I+4);
+ double tmp;
+ tmp = ((double)(180 - reg[1].I)) - ((double)reg[2].I / 256.f);
+ tmp = pow((double)2.f, tmp / 12.f);
+ reg[0].I = (int)((double)freq / tmp);
+
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("MidiKey2Freq: return %08x\n",
+ reg[0].I);
+ }
+#endif
+}
+
+void BIOS_SndDriverJmpTableCopy()
+{
+#ifdef DEV_VERSION
+ if(systemVerbose & VERBOSE_SWI) {
+ log("SndDriverJmpTableCopy: dest=%08x\n",
+ reg[0].I);
+ }
+#endif
+ for(int i = 0; i < 0x24; i++) {
+ CPUWriteMemory(reg[0].I, 0x9c);
+ reg[0].I += 4;
+ }
+}
diff --git a/src/bios.h b/src/bios.h
index 58b3417f..7e78c238 100644
--- a/src/bios.h
+++ b/src/bios.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
extern void BIOS_ArcTan();
extern void BIOS_ArcTan2();
extern void BIOS_BitUnPack();
+extern void BIOS_GetBiosChecksum();
extern void BIOS_BgAffineSet();
extern void BIOS_CpuSet();
extern void BIOS_CpuFastSet();
diff --git a/src/elf.cpp b/src/elf.cpp
index ce6c314e..af92ed97 100644
--- a/src/elf.cpp
+++ b/src/elf.cpp
@@ -1,2999 +1,2994 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-#include
-
-#include "GBA.h"
-#include "Port.h"
-#include "elf.h"
-#include "NLS.h"
-
-#define elfReadMemory(addr) \
- READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-#define DW_TAG_array_type 0x01
-#define DW_TAG_enumeration_type 0x04
-#define DW_TAG_formal_parameter 0x05
-#define DW_TAG_label 0x0a
-#define DW_TAG_lexical_block 0x0b
-#define DW_TAG_member 0x0d
-#define DW_TAG_pointer_type 0x0f
-#define DW_TAG_reference_type 0x10
-#define DW_TAG_compile_unit 0x11
-#define DW_TAG_structure_type 0x13
-#define DW_TAG_subroutine_type 0x15
-#define DW_TAG_typedef 0x16
-#define DW_TAG_union_type 0x17
-#define DW_TAG_unspecified_parameters 0x18
-#define DW_TAG_inheritance 0x1c
-#define DW_TAG_inlined_subroutine 0x1d
-#define DW_TAG_subrange_type 0x21
-#define DW_TAG_base_type 0x24
-#define DW_TAG_const_type 0x26
-#define DW_TAG_enumerator 0x28
-#define DW_TAG_subprogram 0x2e
-#define DW_TAG_variable 0x34
-#define DW_TAG_volatile_type 0x35
-
-#define DW_AT_sibling 0x01
-#define DW_AT_location 0x02
-#define DW_AT_name 0x03
-#define DW_AT_byte_size 0x0b
-#define DW_AT_bit_offset 0x0c
-#define DW_AT_bit_size 0x0d
-#define DW_AT_stmt_list 0x10
-#define DW_AT_low_pc 0x11
-#define DW_AT_high_pc 0x12
-#define DW_AT_language 0x13
-#define DW_AT_compdir 0x1b
-#define DW_AT_const_value 0x1c
-#define DW_AT_containing_type 0x1d
-#define DW_AT_inline 0x20
-#define DW_AT_producer 0x25
-#define DW_AT_prototyped 0x27
-#define DW_AT_upper_bound 0x2f
-#define DW_AT_abstract_origin 0x31
-#define DW_AT_accessibility 0x32
-#define DW_AT_artificial 0x34
-#define DW_AT_data_member_location 0x38
-#define DW_AT_decl_file 0x3a
-#define DW_AT_decl_line 0x3b
-#define DW_AT_declaration 0x3c
-#define DW_AT_encoding 0x3e
-#define DW_AT_external 0x3f
-#define DW_AT_frame_base 0x40
-#define DW_AT_macro_info 0x43
-#define DW_AT_specification 0x47
-#define DW_AT_type 0x49
-#define DW_AT_virtuality 0x4c
-#define DW_AT_vtable_elem_location 0x4d
-// DWARF 2.1/3.0 extensions
-#define DW_AT_entry_pc 0x52
-#define DW_AT_ranges 0x55
-// ARM Compiler extensions
-#define DW_AT_proc_body 0x2000
-#define DW_AT_save_offset 0x2001
-#define DW_AT_user_2002 0x2002
-// MIPS extensions
-#define DW_AT_MIPS_linkage_name 0x2007
-
-#define DW_FORM_addr 0x01
-#define DW_FORM_data2 0x05
-#define DW_FORM_data4 0x06
-#define DW_FORM_string 0x08
-#define DW_FORM_block 0x09
-#define DW_FORM_block1 0x0a
-#define DW_FORM_data1 0x0b
-#define DW_FORM_flag 0x0c
-#define DW_FORM_sdata 0x0d
-#define DW_FORM_strp 0x0e
-#define DW_FORM_udata 0x0f
-#define DW_FORM_ref_addr 0x10
-#define DW_FORM_ref4 0x13
-#define DW_FORM_ref_udata 0x15
-#define DW_FORM_indirect 0x16
-
-#define DW_OP_addr 0x03
-#define DW_OP_plus_uconst 0x23
-#define DW_OP_reg0 0x50
-#define DW_OP_reg1 0x51
-#define DW_OP_reg2 0x52
-#define DW_OP_reg3 0x53
-#define DW_OP_reg4 0x54
-#define DW_OP_reg5 0x55
-#define DW_OP_reg6 0x56
-#define DW_OP_reg7 0x57
-#define DW_OP_reg8 0x58
-#define DW_OP_reg9 0x59
-#define DW_OP_reg10 0x5a
-#define DW_OP_reg11 0x5b
-#define DW_OP_reg12 0x5c
-#define DW_OP_reg13 0x5d
-#define DW_OP_reg14 0x5e
-#define DW_OP_reg15 0x5f
-#define DW_OP_fbreg 0x91
-
-#define DW_LNS_extended_op 0x00
-#define DW_LNS_copy 0x01
-#define DW_LNS_advance_pc 0x02
-#define DW_LNS_advance_line 0x03
-#define DW_LNS_set_file 0x04
-#define DW_LNS_set_column 0x05
-#define DW_LNS_negate_stmt 0x06
-#define DW_LNS_set_basic_block 0x07
-#define DW_LNS_const_add_pc 0x08
-#define DW_LNS_fixed_advance_pc 0x09
-
-#define DW_LNE_end_sequence 0x01
-#define DW_LNE_set_address 0x02
-#define DW_LNE_define_file 0x03
-
-#define DW_CFA_advance_loc 0x01
-#define DW_CFA_offset 0x02
-#define DW_CFA_restore 0x03
-#define DW_CFA_set_loc 0x01
-#define DW_CFA_advance_loc1 0x02
-#define DW_CFA_advance_loc2 0x03
-#define DW_CFA_advance_loc4 0x04
-#define DW_CFA_offset_extended 0x05
-#define DW_CFA_restore_extended 0x06
-#define DW_CFA_undefined 0x07
-#define DW_CFA_same_value 0x08
-#define DW_CFA_register 0x09
-#define DW_CFA_remember_state 0x0a
-#define DW_CFA_restore_state 0x0b
-#define DW_CFA_def_cfa 0x0c
-#define DW_CFA_def_cfa_register 0x0d
-#define DW_CFA_def_cfa_offset 0x0e
-#define DW_CFA_nop 0x00
-
-#define CASE_TYPE_TAG \
- case DW_TAG_const_type:\
- case DW_TAG_volatile_type:\
- case DW_TAG_pointer_type:\
- case DW_TAG_base_type:\
- case DW_TAG_array_type:\
- case DW_TAG_structure_type:\
- case DW_TAG_union_type:\
- case DW_TAG_typedef:\
- case DW_TAG_subroutine_type:\
- case DW_TAG_enumeration_type:\
- case DW_TAG_enumerator:\
- case DW_TAG_reference_type
-
-struct ELFcie {
- ELFcie *next;
- u32 offset;
- u8 *augmentation;
- u32 codeAlign;
- s32 dataAlign;
- int returnAddress;
- u8 *data;
- u32 dataLen;
-};
-
-struct ELFfde {
- ELFcie *cie;
- u32 address;
- u32 end;
- u8 *data;
- u32 dataLen;
-};
-
-enum ELFRegMode {
- REG_NOT_SET,
- REG_OFFSET,
- REG_REGISTER
-};
-
-
-struct ELFFrameStateRegister {
- ELFRegMode mode;
- int reg;
- s32 offset;
-};
-
-struct ELFFrameStateRegisters {
- ELFFrameStateRegister regs[16];
- ELFFrameStateRegisters *previous;
-};
-
-enum ELFCfaMode {
- CFA_NOT_SET,
- CFA_REG_OFFSET
-};
-
-struct ELFFrameState {
- ELFFrameStateRegisters registers;
-
- ELFCfaMode cfaMode;
- int cfaRegister;
- s32 cfaOffset;
-
- u32 pc;
-
- int dataAlign;
- int codeAlign;
- int returnAddress;
-};
-
-extern bool cpuIsMultiBoot;
-
-Symbol *elfSymbols = NULL;
-char *elfSymbolsStrTab = NULL;
-int elfSymbolsCount = 0;
-
-ELFSectionHeader **elfSectionHeaders = NULL;
-char *elfSectionHeadersStringTable = NULL;
-int elfSectionHeadersCount = 0;
-u8 *elfFileData = NULL;
-
-CompileUnit *elfCompileUnits = NULL;
-DebugInfo *elfDebugInfo = NULL;
-char *elfDebugStrings = NULL;
-
-ELFcie *elfCies = NULL;
-ELFfde **elfFdes = NULL;
-int elfFdeCount = 0;
-
-CompileUnit *elfCurrentUnit = NULL;
-
-u32 elfRead4Bytes(u8 *);
-u16 elfRead2Bytes(u8 *);
-
-CompileUnit *elfGetCompileUnit(u32 addr)
-{
- if(elfCompileUnits) {
- CompileUnit *unit = elfCompileUnits;
- while(unit) {
- if(unit->lowPC) {
- if(addr >= unit->lowPC && addr < unit->highPC)
- return unit;
- } else {
- ARanges *r = unit->ranges;
- if(r) {
- int count = r->count;
- for(int j = 0; j < count; j++) {
- if(addr >= r->ranges[j].lowPC && addr < r->ranges[j].highPC)
- return unit;
- }
- }
- }
- unit = unit->next;
- }
- }
- return NULL;
-}
-
-char *elfGetAddressSymbol(u32 addr)
-{
- static char buffer[256];
-
- CompileUnit *unit = elfGetCompileUnit(addr);
- // found unit, need to find function
- if(unit) {
- Function *func = unit->functions;
- while(func) {
- if(addr >= func->lowPC && addr < func->highPC) {
- int offset = addr - func->lowPC;
- char *name = func->name;
- if(!name)
- name = "";
- if(offset)
- sprintf(buffer, "%s+%d", name, offset);
- else
- strcpy(buffer, name);
- return buffer;
- }
- func = func->next;
- }
- }
-
- if(elfSymbolsCount) {
- for(int i = 0; i < elfSymbolsCount; i++) {
- Symbol *s = &elfSymbols[i];
- if((addr >= s->value) && addr < (s->value+s->size)) {
- int offset = addr-s->value;
- char *name = s->name;
- if(name == NULL)
- name = "";
- if(offset)
- sprintf(buffer, "%s+%d", name, addr-s->value);
- else
- strcpy(buffer, name);
- return buffer;
- } else if(addr == s->value) {
- if(s->name)
- strcpy(buffer, s->name);
- else
- strcpy(buffer, "");
- return buffer;
- }
- }
- }
-
- return "";
-}
-
-bool elfFindLineInModule(u32 *addr, char *name, int line)
-{
- CompileUnit *unit = elfCompileUnits;
-
- while(unit) {
- if(unit->lineInfoTable) {
- int i;
- int count = unit->lineInfoTable->fileCount;
- char *found = NULL;
- for(i = 0; i < count; i++) {
- if(strcmp(name, unit->lineInfoTable->files[i]) == 0) {
- found = unit->lineInfoTable->files[i];
- break;
- }
- }
- // found a matching filename... try to find line now
- if(found) {
- LineInfoItem *table = unit->lineInfoTable->lines;
- count = unit->lineInfoTable->number;
- for(i = 0; i < count; i++) {
- if(table[i].file == found && table[i].line == line) {
- *addr = table[i].address;
- return true;
- }
- }
- // we can only find a single match
- return false;
- }
- }
- unit = unit->next;
- }
- return false;
-}
-
-int elfFindLine(CompileUnit *unit, Function * /* func */, u32 addr, char **f)
-{
- int currentLine = -1;
- if(unit->hasLineInfo) {
- int count = unit->lineInfoTable->number;
- LineInfoItem *table = unit->lineInfoTable->lines;
- int i;
- for(i = 0; i < count; i++) {
- if(addr <= table[i].address)
- break;
- }
- if(i == count)
- i--;
- *f = table[i].file;
- currentLine = table[i].line;
- }
- return currentLine;
-}
-
-bool elfFindLineInUnit(u32 *addr, CompileUnit *unit, int line)
-{
- if(unit->hasLineInfo) {
- int count = unit->lineInfoTable->number;
- LineInfoItem *table = unit->lineInfoTable->lines;
- int i;
- for(i = 0; i < count; i++) {
- if(line == table[i].line) {
- *addr = table[i].address;
- return true;
- }
- }
- }
- return false;
-}
-
-bool elfGetCurrentFunction(u32 addr, Function **f, CompileUnit **u)
-{
- CompileUnit *unit = elfGetCompileUnit(addr);
- // found unit, need to find function
- if(unit) {
- Function *func = unit->functions;
- while(func) {
- if(addr >= func->lowPC && addr < func->highPC) {
- *f = func;
- *u = unit;
- return true;
- }
- func = func->next;
- }
- }
- return false;
-}
-
-bool elfGetObject(char *name, Function *f, CompileUnit *u, Object **o)
-{
- if(f && u) {
- Object *v = f->variables;
-
- while(v) {
- if(strcmp(name, v->name) == 0) {
- *o = v;
- return true;
- }
- v = v->next;
- }
- v = f->parameters;
- while(v) {
- if(strcmp(name, v->name) == 0) {
- *o = v;
- return true;
- }
- v = v->next;
- }
- v = u->variables;
- while(v) {
- if(strcmp(name, v->name) == 0) {
- *o = v;
- return true;
- }
- v = v->next;
- }
- }
-
- CompileUnit *c = elfCompileUnits;
-
- while(c) {
- if(c != u) {
- Object *v = c->variables;
- while(v) {
- if(strcmp(name, v->name) == 0) {
- *o = v;
- return true;
- }
- v = v->next;
- }
- }
- c = c->next;
- }
-
- return false;
-}
-
-char *elfGetSymbol(int i, u32 *value, u32 *size, int *type)
-{
- if(i < elfSymbolsCount) {
- Symbol *s = &elfSymbols[i];
- *value = s->value;
- *size = s->size;
- *type = s->type;
- return s->name;
- }
- return NULL;
-}
-
-bool elfGetSymbolAddress(char *sym, u32 *addr, u32 *size, int *type)
-{
- if(elfSymbolsCount) {
- for(int i = 0; i < elfSymbolsCount; i++) {
- Symbol *s = &elfSymbols[i];
- if(strcmp(sym, s->name) == 0) {
- *addr = s->value;
- *size = s->size;
- *type = s->type;
- return true;
- }
- }
- }
- return false;
-}
-
-ELFfde *elfGetFde(u32 address)
-{
- if(elfFdes) {
- int i;
- for(i = 0; i < elfFdeCount; i++) {
- if(address >= elfFdes[i]->address &&
- address < elfFdes[i]->end) {
- return elfFdes[i];
- }
- }
- }
-
- return NULL;
-}
-
-void elfExecuteCFAInstructions(ELFFrameState *state, u8 *data, u32 len,
- u32 pc)
-{
- u8 *end = data + len;
- int bytes;
- int reg;
- ELFFrameStateRegisters *fs;
-
- while(data < end && state->pc < pc) {
- u8 op = *data++;
-
- switch(op >> 6) {
- case DW_CFA_advance_loc:
- state->pc += (op & 0x3f) * state->codeAlign;
- break;
- case DW_CFA_offset:
- reg = op & 0x3f;
- state->registers.regs[reg].mode = REG_OFFSET;
- state->registers.regs[reg].offset = state->dataAlign *
- (s32)elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_CFA_restore:
- // we don't care much about the other possible settings,
- // so just setting to unset is enough for now
- state->registers.regs[op & 0x3f].mode = REG_NOT_SET;
- break;
- case 0:
- switch(op & 0x3f) {
- case DW_CFA_nop:
- break;
- case DW_CFA_advance_loc1:
- state->pc += state->codeAlign * (*data++);
- break;
- case DW_CFA_advance_loc2:
- state->pc += state->codeAlign * elfRead2Bytes(data);
- data += 2;
- break;
- case DW_CFA_advance_loc4:
- state->pc += state->codeAlign * elfRead4Bytes(data);
- data += 4;
- break;
- case DW_CFA_offset_extended:
- reg = elfReadLEB128(data, &bytes);
- data += bytes;
- state->registers.regs[reg].mode = REG_OFFSET;
- state->registers.regs[reg].offset = state->dataAlign *
- (s32)elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_CFA_restore_extended:
- case DW_CFA_undefined:
- case DW_CFA_same_value:
- reg = elfReadLEB128(data, &bytes);
- data += bytes;
- state->registers.regs[reg].mode = REG_NOT_SET;
- break;
- case DW_CFA_register:
- reg = elfReadLEB128(data, &bytes);
- data += bytes;
- state->registers.regs[reg].mode = REG_REGISTER;
- state->registers.regs[reg].reg = elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_CFA_remember_state:
- fs = (ELFFrameStateRegisters *)calloc(1,
- sizeof(ELFFrameStateRegisters));
- memcpy(fs, &state->registers, sizeof(ELFFrameStateRegisters));
- state->registers.previous = fs;
- break;
- case DW_CFA_restore_state:
- if(state->registers.previous == NULL) {
- printf("Error: previous frame state is NULL.\n");
- return;
- }
- fs = state->registers.previous;
- memcpy(&state->registers, fs, sizeof(ELFFrameStateRegisters));
- free(fs);
- break;
- case DW_CFA_def_cfa:
- state->cfaRegister = elfReadLEB128(data, &bytes);
- data += bytes;
- state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
- data += bytes;
- state->cfaMode = CFA_REG_OFFSET;
- break;
- case DW_CFA_def_cfa_register:
- state->cfaRegister = elfReadLEB128(data, &bytes);
- data += bytes;
- state->cfaMode = CFA_REG_OFFSET;
- break;
- case DW_CFA_def_cfa_offset:
- state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
- data += bytes;
- state->cfaMode = CFA_REG_OFFSET;
- break;
- default:
- printf("Unknown CFA opcode %08x\n", op);
- return;
- }
- break;
- default:
- printf("Unknown CFA opcode %08x\n", op);
- return;
- }
- }
-}
-
-ELFFrameState *elfGetFrameState(ELFfde *fde, u32 address)
-{
- ELFFrameState *state = (ELFFrameState *)calloc(1, sizeof(ELFFrameState));
- state->pc = fde->address;
- state->dataAlign = fde->cie->dataAlign;
- state->codeAlign = fde->cie->codeAlign;
- state->returnAddress = fde->cie->returnAddress;
-
- elfExecuteCFAInstructions(state,
- fde->cie->data,
- fde->cie->dataLen,
- 0xffffffff);
- elfExecuteCFAInstructions(state,
- fde->data,
- fde->dataLen,
- address);
-
- return state;
-}
-
-void elfPrintCallChain(u32 address)
-{
- int count = 1;
-
- reg_pair regs[15];
- reg_pair newRegs[15];
-
- memcpy(®s[0], ®[0], sizeof(reg_pair) * 15);
-
- while(count < 20) {
- char *addr = elfGetAddressSymbol(address);
- if(*addr == 0)
- addr = "???";
-
- printf("%08x %s\n", address, addr);
-
- ELFfde *fde = elfGetFde(address);
-
- if(fde == NULL) {
- break;
- }
-
- ELFFrameState *state = elfGetFrameState(fde, address);
-
- if(!state) {
- break;
- }
-
- if(state->cfaMode == CFA_REG_OFFSET) {
- memcpy(&newRegs[0], ®s[0], sizeof(reg_pair) * 15);
- u32 addr = 0;
- for(int i = 0; i < 15; i++) {
- ELFFrameStateRegister *r = &state->registers.
- regs[i];
-
- switch(r->mode) {
- case REG_NOT_SET:
- newRegs[i].I = regs[i].I;
- break;
- case REG_OFFSET:
- newRegs[i].I = elfReadMemory(regs[state->cfaRegister].I +
- state->cfaOffset +
- r->offset);
- break;
- case REG_REGISTER:
- newRegs[i].I = regs[r->reg].I;
- break;
- default:
- printf("Unknown register mode: %d\n", r->mode);
- break;
- }
- }
- memcpy(regs, newRegs, sizeof(reg_pair)*15);
- addr = newRegs[14].I;
- addr &= 0xfffffffe;
- address = addr;
- count++;
- } else {
- printf("CFA not set\n");
- break;
- }
- if(state->registers.previous) {
- ELFFrameStateRegisters *prev = state->registers.previous;
-
- while(prev) {
- ELFFrameStateRegisters *p = prev->previous;
- free(prev);
- prev = p;
- }
- }
- free(state);
- }
-}
-
-u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type, u32 base)
-{
- u32 framebase = 0;
- if(f && f->frameBase) {
- ELFBlock *b = f->frameBase;
- switch(*b->data) {
- case DW_OP_reg0:
- case DW_OP_reg1:
- case DW_OP_reg2:
- case DW_OP_reg3:
- case DW_OP_reg4:
- case DW_OP_reg5:
- case DW_OP_reg6:
- case DW_OP_reg7:
- case DW_OP_reg8:
- case DW_OP_reg9:
- case DW_OP_reg10:
- case DW_OP_reg11:
- case DW_OP_reg12:
- case DW_OP_reg13:
- case DW_OP_reg14:
- case DW_OP_reg15:
- framebase = reg[*b->data-0x50].I;
- break;
- default:
- fprintf(stderr, "Unknown frameBase %02x\n", *b->data);
- break;
- }
- }
-
- ELFBlock *loc = o;
- u32 location = 0;
- int bytes = 0;
- if(loc) {
- switch(*loc->data) {
- case DW_OP_addr:
- location = elfRead4Bytes(loc->data+1);
- *type = LOCATION_memory;
- break;
- case DW_OP_plus_uconst:
- location = base + elfReadLEB128(loc->data+1, &bytes);
- *type = LOCATION_memory;
- break;
- case DW_OP_reg0:
- case DW_OP_reg1:
- case DW_OP_reg2:
- case DW_OP_reg3:
- case DW_OP_reg4:
- case DW_OP_reg5:
- case DW_OP_reg6:
- case DW_OP_reg7:
- case DW_OP_reg8:
- case DW_OP_reg9:
- case DW_OP_reg10:
- case DW_OP_reg11:
- case DW_OP_reg12:
- case DW_OP_reg13:
- case DW_OP_reg14:
- case DW_OP_reg15:
- location = *loc->data - 0x50;
- *type = LOCATION_register;
- break;
- case DW_OP_fbreg:
- {
- int bytes;
- s32 off = elfReadSignedLEB128(loc->data+1, &bytes);
- location = framebase + off;
- *type = LOCATION_memory;
- }
- break;
- default:
- fprintf(stderr, "Unknown location %02x\n", *loc->data);
- break;
- }
- }
- return location;
-}
-
-u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type)
-{
- return elfDecodeLocation(f, o, type, 0);
-}
-
-// reading function
-
-u32 elfRead4Bytes(u8 *data)
-{
- u32 value = *data++;
- value |= (*data++ << 8);
- value |= (*data++ << 16);
- value |= (*data << 24);
- return value;
-}
-
-u16 elfRead2Bytes(u8 *data)
-{
- u16 value = *data++;
- value |= (*data << 8);
- return value;
-}
-
-char *elfReadString(u8 *data, int *bytesRead)
-{
- if(*data == 0) {
- *bytesRead = 1;
- return NULL;
- }
- *bytesRead = strlen((char *)data) + 1;
- return (char *)data;
-}
-
-s32 elfReadSignedLEB128(u8 *data, int *bytesRead)
-{
- s32 result = 0;
- int shift = 0;
- int count = 0;
-
- u8 byte;
- do {
- byte = *data++;
- count++;
- result |= (byte & 0x7f) << shift;
- shift += 7;
- } while(byte & 0x80);
- if((shift < 32) && (byte & 0x40))
- result |= -(1 << shift);
- *bytesRead = count;
- return result;
-}
-
-u32 elfReadLEB128(u8 *data, int *bytesRead)
-{
- u32 result = 0;
- int shift = 0;
- int count = 0;
- u8 byte;
- do {
- byte = *data++;
- count++;
- result |= (byte & 0x7f) << shift;
- shift += 7;
- } while(byte & 0x80);
- *bytesRead = count;
- return result;
-}
-
-u8 *elfReadSection(u8 *data, ELFSectionHeader *sh)
-{
- return data + READ32LE(&sh->offset);
-}
-
-ELFSectionHeader *elfGetSectionByName(char *name)
-{
- for(int i = 0; i < elfSectionHeadersCount; i++) {
- if(strcmp(name,
- &elfSectionHeadersStringTable[READ32LE(&elfSectionHeaders[i]->
- name)]) == 0) {
- return elfSectionHeaders[i];
- }
- }
- return NULL;
-}
-
-ELFSectionHeader *elfGetSectionByNumber(int number)
-{
- if(number < elfSectionHeadersCount) {
- return elfSectionHeaders[number];
- }
- return NULL;
-}
-
-CompileUnit *elfGetCompileUnitForData(u8 *data)
-{
- u8 *end = elfCurrentUnit->top + 4 + elfCurrentUnit->length;
-
- if(data >= elfCurrentUnit->top && data < end)
- return elfCurrentUnit;
-
- CompileUnit *unit = elfCompileUnits;
-
- while(unit) {
- end = unit->top + 4 + unit->length;
-
- if(data >= unit->top && data < end)
- return unit;
-
- unit = unit->next;
- }
-
- printf("Error: cannot find reference to compile unit at offset %08x\n",
- (int)(data - elfDebugInfo->infodata));
- exit(-1);
-}
-
-u8 *elfReadAttribute(u8 *data, ELFAttr *attr)
-{
- int bytes;
- int form = attr->form;
- start:
- switch(form) {
- case DW_FORM_addr:
- attr->value = elfRead4Bytes(data);
- data += 4;
- break;
- case DW_FORM_data2:
- attr->value = elfRead2Bytes(data);
- data += 2;
- break;
- case DW_FORM_data4:
- attr->value = elfRead4Bytes(data);
- data += 4;
- break;
- case DW_FORM_string:
- attr->string = (char *)data;
- data += strlen(attr->string)+1;
- break;
- case DW_FORM_strp:
- attr->string = elfDebugStrings + elfRead4Bytes(data);
- data += 4;
- break;
- case DW_FORM_block:
- attr->block = (ELFBlock *)malloc(sizeof(ELFBlock));
- attr->block->length = elfReadLEB128(data, &bytes);
- data += bytes;
- attr->block->data = data;
- data += attr->block->length;
- break;
- case DW_FORM_block1:
- attr->block = (ELFBlock *)malloc(sizeof(ELFBlock));
- attr->block->length = *data++;
- attr->block->data = data;
- data += attr->block->length;
- break;
- case DW_FORM_data1:
- attr->value = *data++;
- break;
- case DW_FORM_flag:
- attr->flag = (*data++) ? true : false;
- break;
- case DW_FORM_sdata:
- attr->value = elfReadSignedLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_FORM_udata:
- attr->value = elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_FORM_ref_addr:
- attr->value = (elfDebugInfo->infodata + elfRead4Bytes(data)) -
- elfGetCompileUnitForData(data)->top;
- data += 4;
- break;
- case DW_FORM_ref4:
- attr->value = elfRead4Bytes(data);
- data += 4;
- break;
- case DW_FORM_ref_udata:
- attr->value = (elfDebugInfo->infodata +
- (elfGetCompileUnitForData(data)->top -
- elfDebugInfo->infodata) +
- elfReadLEB128(data, &bytes)) -
- elfCurrentUnit->top;
- data += bytes;
- break;
- case DW_FORM_indirect:
- form = elfReadLEB128(data, &bytes);
- data += bytes;
- goto start;
- default:
- fprintf(stderr, "Unsupported FORM %02x\n", form);
- exit(-1);
- }
- return data;
-}
-
-ELFAbbrev *elfGetAbbrev(ELFAbbrev **table, u32 number)
-{
- int hash = number % 121;
-
- ELFAbbrev *abbrev = table[hash];
-
- while(abbrev) {
- if(abbrev->number == number)
- return abbrev;
- abbrev = abbrev->next;
- }
- return NULL;
-}
-
-ELFAbbrev **elfReadAbbrevs(u8 *data, u32 offset)
-{
- data += offset;
- ELFAbbrev **abbrevs = (ELFAbbrev **)calloc(sizeof(ELFAbbrev *)*121,1);
- int bytes = 0;
- u32 number = elfReadLEB128(data, &bytes);
- data += bytes;
- while(number) {
- ELFAbbrev *abbrev = (ELFAbbrev *)calloc(sizeof(ELFAbbrev),1);
-
- // read tag information
- abbrev->number = number;
- abbrev->tag = elfReadLEB128(data, &bytes);
- data += bytes;
- abbrev->hasChildren = *data++ ? true: false;
-
- // read attributes
- int name = elfReadLEB128(data, &bytes);
- data += bytes;
- int form = elfReadLEB128(data, &bytes);
- data += bytes;
-
- while(name) {
- if((abbrev->numAttrs % 4) == 0) {
- abbrev->attrs = (ELFAttr *)realloc(abbrev->attrs,
- (abbrev->numAttrs + 4) *
- sizeof(ELFAttr));
- }
- abbrev->attrs[abbrev->numAttrs].name = name;
- abbrev->attrs[abbrev->numAttrs++].form = form;
-
- name = elfReadLEB128(data, &bytes);
- data += bytes;
- form = elfReadLEB128(data, &bytes);
- data += bytes;
- }
-
- int hash = number % 121;
- abbrev->next = abbrevs[hash];
- abbrevs[hash] = abbrev;
-
- number = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(elfGetAbbrev(abbrevs, number) != NULL)
- break;
- }
-
- return abbrevs;
-}
-
-void elfParseCFA(u8 *top)
-{
- ELFSectionHeader *h = elfGetSectionByName(".debug_frame");
-
- if(h == NULL) {
- return;
- }
-
- u8 *data = elfReadSection(top, h);
-
- u8 *topOffset = data;
-
- u8 *end = data + READ32LE(&h->size);
-
- ELFcie *cies = NULL;
-
- while(data < end) {
- u32 offset = data - topOffset;
- u32 len = elfRead4Bytes(data);
- data += 4;
-
- u8 *dataEnd = data + len;
-
- u32 id = elfRead4Bytes(data);
- data += 4;
-
- if(id == 0xffffffff) {
- // skip version
- *data++;
-
- ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
-
- cie->next = cies;
- cies = cie;
-
- cie->offset = offset;
-
- cie->augmentation = data;
- while(*data)
- data++;
- data++;
-
- if(*cie->augmentation) {
- fprintf(stderr, "Error: augmentation not supported\n");
- exit(-1);
- }
-
- int bytes;
- cie->codeAlign = elfReadLEB128(data, &bytes);
- data += bytes;
-
- cie->dataAlign = elfReadSignedLEB128(data, &bytes);
- data += bytes;
-
- cie->returnAddress = *data++;
-
- cie->data = data;
- cie->dataLen = dataEnd - data;
- } else {
- ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde));
-
- ELFcie *cie = cies;
-
- while(cie != NULL) {
- if(cie->offset == id)
- break;
- cie = cie->next;
- }
-
- if(!cie) {
- fprintf(stderr, "Cannot find CIE %08x\n", id);
- exit(-1);
- }
-
- fde->cie = cie;
-
- fde->address = elfRead4Bytes(data);
- data += 4;
-
- fde->end = fde->address + elfRead4Bytes(data);
- data += 4;
-
- fde->data = data;
- fde->dataLen = dataEnd - data;
-
- if((elfFdeCount %10) == 0) {
- elfFdes = (ELFfde **)realloc(elfFdes, (elfFdeCount+10) *
- sizeof(ELFfde *));
- }
- elfFdes[elfFdeCount++] = fde;
- }
- data = dataEnd;
- }
-
- elfCies = cies;
-}
-
-void elfAddLine(LineInfo *l, u32 a, int file, int line, int *max)
-{
- if(l->number == *max) {
- *max += 1000;
- l->lines = (LineInfoItem *)realloc(l->lines, *max*sizeof(LineInfoItem));
- }
- LineInfoItem *li = &l->lines[l->number];
- li->file = l->files[file-1];
- li->address = a;
- li->line = line;
- l->number++;
-}
-
-void elfParseLineInfo(CompileUnit *unit, u8 *top)
-{
- ELFSectionHeader *h = elfGetSectionByName(".debug_line");
- if(h == NULL) {
- fprintf(stderr, "No line information found\n");
- return;
- }
- LineInfo *l = unit->lineInfoTable = (LineInfo *)calloc(1, sizeof(LineInfo));
- l->number = 0;
- int max = 1000;
- l->lines = (LineInfoItem *)malloc(1000*sizeof(LineInfoItem));
-
- u8 *data = elfReadSection(top, h);
- data += unit->lineInfo;
- u32 totalLen = elfRead4Bytes(data);
- data += 4;
- u8 *end = data + totalLen;
- // u16 version = elfRead2Bytes(data);
- data += 2;
- // u32 offset = elfRead4Bytes(data);
- data += 4;
- int minInstrSize = *data++;
- int defaultIsStmt = *data++;
- int lineBase = (s8)*data++;
- int lineRange = *data++;
- int opcodeBase = *data++;
- u8 *stdOpLen = (u8 *)malloc(opcodeBase * sizeof(u8));
- stdOpLen[0] = 1;
- int i;
- for(i = 1; i < opcodeBase; i++)
- stdOpLen[i] = *data++;
-
- free(stdOpLen);// todo
- int bytes = 0;
-
- char *s;
- while((s = elfReadString(data, &bytes)) != NULL) {
- data += bytes;
- // fprintf(stderr, "Directory is %s\n", s);
- }
- data += bytes;
- int count = 4;
- int index = 0;
- l->files = (char **)malloc(sizeof(char *)*count);
-
- while((s = elfReadString(data, &bytes)) != NULL) {
- l->files[index++] = s;
-
- data += bytes;
- // directory
- elfReadLEB128(data, &bytes);
- data += bytes;
- // time
- elfReadLEB128(data, &bytes);
- data += bytes;
- // size
- elfReadLEB128(data, &bytes);
- data += bytes;
- // fprintf(stderr, "File is %s\n", s);
- if(index == count) {
- count += 4;
- l->files = (char **)realloc(l->files, sizeof(char *)*count);
- }
- }
- l->fileCount = index;
- data += bytes;
-
- while(data < end) {
- u32 address = 0;
- int file = 1;
- int line = 1;
- int col = 0;
- int isStmt = defaultIsStmt;
- int basicBlock = 0;
- int endSeq = 0;
-
- while(!endSeq) {
- int op = *data++;
- switch(op) {
- case DW_LNS_extended_op:
- {
- data++;
- op = *data++;
- switch(op) {
- case DW_LNE_end_sequence:
- endSeq = 1;
- break;
- case DW_LNE_set_address:
- address = elfRead4Bytes(data);
- data += 4;
- break;
- default:
- fprintf(stderr, "Unknown extended LINE opcode %02x\n", op);
- exit(-1);
- }
- }
- break;
- case DW_LNS_copy:
- // fprintf(stderr, "Address %08x line %d (%d)\n", address, line, file);
- elfAddLine(l, address, file, line, &max);
- basicBlock = 0;
- break;
- case DW_LNS_advance_pc:
- address += minInstrSize * elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_LNS_advance_line:
- line += elfReadSignedLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_LNS_set_file:
- file = elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_LNS_set_column:
- col = elfReadLEB128(data, &bytes);
- data += bytes;
- break;
- case DW_LNS_negate_stmt:
- isStmt = !isStmt;
- break;
- case DW_LNS_set_basic_block:
- basicBlock = 1;
- break;
- case DW_LNS_const_add_pc:
- address += (minInstrSize *((255 - opcodeBase)/lineRange));
- break;
- case DW_LNS_fixed_advance_pc:
- address += elfRead2Bytes(data);
- data += 2;
- break;
- default:
- op = op - opcodeBase;
- address += (op / lineRange) * minInstrSize;
- line += lineBase + (op % lineRange);
- elfAddLine(l, address, file, line, &max);
- // fprintf(stderr, "Address %08x line %d (%d)\n", address, line,file);
- basicBlock = 1;
- break;
- }
- }
- }
- l->lines = (LineInfoItem *)realloc(l->lines, l->number*sizeof(LineInfoItem));
-}
-
-u8 *elfSkipData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
-{
- int i;
- int bytes;
-
- for(i = 0; i < abbrev->numAttrs; i++) {
- data = elfReadAttribute(data, &abbrev->attrs[i]);
- if(abbrev->attrs[i].form == DW_FORM_block1)
- free(abbrev->attrs[i].block);
- }
-
- if(abbrev->hasChildren) {
- int nesting = 1;
- while(nesting) {
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- nesting--;
- continue;
- }
-
- abbrev = elfGetAbbrev(abbrevs, abbrevNum);
-
- for(i = 0; i < abbrev->numAttrs; i++) {
- data = elfReadAttribute(data, &abbrev->attrs[i]);
- if(abbrev->attrs[i].form == DW_FORM_block1)
- free(abbrev->attrs[i].block);
- }
-
- if(abbrev->hasChildren) {
- nesting++;
- }
- }
- }
- return data;
-}
-
-Type *elfParseType(CompileUnit *unit, u32);
-u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
- Object **object);
-u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
- Function **function);
-void elfCleanUp(Function *);
-
-void elfAddType(Type *type, CompileUnit *unit, u32 offset)
-{
- if(type->next == NULL) {
- if(unit->types != type && type->offset == 0) {
- type->offset = offset;
- type->next = unit->types;
- unit->types = type;
- }
- }
-}
-
-void elfParseType(u8 *data, u32 offset, ELFAbbrev *abbrev, CompileUnit *unit,
- Type **type)
-{
- switch(abbrev->tag) {
- case DW_TAG_typedef:
- {
- u32 typeref = 0;
- char *name = NULL;
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_name:
- name = attr->string;
- break;
- case DW_AT_type:
- typeref = attr->value;
- break;
- case DW_AT_decl_file:
- case DW_AT_decl_line:
- break;
- default:
- fprintf(stderr, "Unknown attribute for typedef %02x\n", attr->name);
- break;
- }
- }
- if(abbrev->hasChildren)
- fprintf(stderr, "Unexpected children for typedef\n");
- *type = elfParseType(unit, typeref);
- if(name)
- (*type)->name = name;
- return;
- }
- break;
- case DW_TAG_union_type:
- case DW_TAG_structure_type:
- {
- Type *t = (Type *)calloc(sizeof(Type), 1);
- if(abbrev->tag == DW_TAG_structure_type)
- t->type = TYPE_struct;
- else
- t->type = TYPE_union;
-
- Struct *s = (Struct *)calloc(sizeof(Struct), 1);
- t->structure = s;
- elfAddType(t, unit, offset);
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_name:
- t->name = attr->string;
- break;
- case DW_AT_byte_size:
- t->size = attr->value;
- break;
- case DW_AT_decl_file:
- case DW_AT_decl_line:
- case DW_AT_sibling:
- case DW_AT_containing_type: // todo?
- case DW_AT_declaration:
- case DW_AT_specification: // TODO:
- break;
- default:
- fprintf(stderr, "Unknown attribute for struct %02x\n", attr->name);
- break;
- }
- }
- if(abbrev->hasChildren) {
- int bytes;
- u32 num = elfReadLEB128(data, &bytes);
- data += bytes;
- int index = 0;
- while(num) {
- ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
-
- switch(abbr->tag) {
- case DW_TAG_member:
- {
- if((index % 4) == 0)
- s->members = (Member *)realloc(s->members,
- sizeof(Member)*(index+4));
- Member *m = &s->members[index];
- m->location = NULL;
- m->bitOffset = 0;
- m->bitSize = 0;
- m->byteSize = 0;
- for(int i = 0; i < abbr->numAttrs; i++) {
- ELFAttr *attr = &abbr->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_name:
- m->name = attr->string;
- break;
- case DW_AT_type:
- m->type = elfParseType(unit, attr->value);
- break;
- case DW_AT_data_member_location:
- m->location = attr->block;
- break;
- case DW_AT_byte_size:
- m->byteSize = attr->value;
- break;
- case DW_AT_bit_offset:
- m->bitOffset = attr->value;
- break;
- case DW_AT_bit_size:
- m->bitSize = attr->value;
- break;
- case DW_AT_decl_file:
- case DW_AT_decl_line:
- case DW_AT_accessibility:
- case DW_AT_artificial: // todo?
- break;
- default:
- fprintf(stderr, "Unknown member attribute %02x\n",
- attr->name);
- }
- }
- index++;
- }
- break;
- case DW_TAG_subprogram:
- {
- Function *fnc = NULL;
- data = elfParseFunction(data, abbr, unit, &fnc);
- if(fnc != NULL) {
- if(unit->lastFunction)
- unit->lastFunction->next = fnc;
- else
- unit->functions = fnc;
- unit->lastFunction = fnc;
- }
- }
- break;
- case DW_TAG_inheritance:
- // TODO: add support
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- CASE_TYPE_TAG:
- // skip types... parsed only when used
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- case DW_TAG_variable:
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- default:
- fprintf(stderr, "Unknown struct tag %02x %s\n", abbr->tag, t->name);
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- }
- num = elfReadLEB128(data, &bytes);
- data += bytes;
- }
- s->memberCount = index;
- }
- *type = t;
- return;
- }
- break;
- case DW_TAG_base_type:
- {
- Type *t = (Type *)calloc(sizeof(Type), 1);
-
- t->type = TYPE_base;
- elfAddType(t, unit, offset);
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_name:
- t->name = attr->string;
- break;
- case DW_AT_encoding:
- t->encoding = attr->value;
- break;
- case DW_AT_byte_size:
- t->size = attr->value;
- break;
- case DW_AT_bit_size:
- t->bitSize = attr->value;
- break;
- default:
- fprintf(stderr, "Unknown attribute for base type %02x\n",
- attr->name);
- break;
- }
- }
- if(abbrev->hasChildren)
- fprintf(stderr, "Unexpected children for base type\n");
- *type = t;
- return;
- }
- break;
- case DW_TAG_pointer_type:
- {
- Type *t = (Type *)calloc(sizeof(Type), 1);
-
- t->type = TYPE_pointer;
-
- elfAddType(t, unit, offset);
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data =elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_type:
- t->pointer = elfParseType(unit, attr->value);
- break;
- case DW_AT_byte_size:
- t->size = attr->value;
- break;
- default:
- fprintf(stderr, "Unknown pointer type attribute %02x\n", attr->name);
- break;
- }
- }
- if(abbrev->hasChildren)
- fprintf(stderr, "Unexpected children for pointer type\n");
- *type = t;
- return;
- }
- break;
- case DW_TAG_reference_type:
- {
- Type *t = (Type *)calloc(sizeof(Type), 1);
-
- t->type = TYPE_reference;
-
- elfAddType(t, unit, offset);
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data =elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_type:
- t->pointer = elfParseType(unit, attr->value);
- break;
- case DW_AT_byte_size:
- t->size = attr->value;
- break;
- default:
- fprintf(stderr, "Unknown ref type attribute %02x\n", attr->name);
- break;
- }
- }
- if(abbrev->hasChildren)
- fprintf(stderr, "Unexpected children for ref type\n");
- *type = t;
- return;
- }
- break;
- case DW_TAG_volatile_type:
- {
- u32 typeref = 0;
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_type:
- typeref = attr->value;
- break;
- default:
- fprintf(stderr, "Unknown volatile attribute for type %02x\n",
- attr->name);
- break;
- }
- }
- if(abbrev->hasChildren)
- fprintf(stderr, "Unexpected children for volatile type\n");
- *type = elfParseType(unit, typeref);
- return;
- }
- break;
- case DW_TAG_const_type:
- {
- u32 typeref = 0;
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_type:
- typeref = attr->value;
- break;
- default:
- fprintf(stderr, "Unknown const attribute for type %02x\n",
- attr->name);
- break;
- }
- }
- if(abbrev->hasChildren)
- fprintf(stderr, "Unexpected children for const type\n");
- *type = elfParseType(unit, typeref);
- return;
- }
- break;
- case DW_TAG_enumeration_type:
- {
- Type *t = (Type *)calloc(sizeof(Type), 1);
- t->type = TYPE_enum;
- Enum *e = (Enum *)calloc(sizeof(Enum), 1);
- t->enumeration = e;
- elfAddType(t, unit, offset);
- int count = 0;
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_name:
- t->name = attr->string;
- break;
- case DW_AT_byte_size:
- t->size = attr->value;
- break;
- case DW_AT_sibling:
- case DW_AT_decl_file:
- case DW_AT_decl_line:
- break;
- default:
- fprintf(stderr, "Unknown enum attribute %02x\n", attr->name);
- }
- }
- if(abbrev->hasChildren) {
- int bytes;
- u32 num = elfReadLEB128(data, &bytes);
- data += bytes;
- while(num) {
- ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
-
- switch(abbr->tag) {
- case DW_TAG_enumerator:
- {
- count++;
- e->members = (EnumMember *)realloc(e->members,
- count*sizeof(EnumMember));
- EnumMember *m = &e->members[count-1];
- for(int i = 0; i < abbr->numAttrs; i++) {
- ELFAttr *attr = &abbr->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_name:
- m->name = attr->string;
- break;
- case DW_AT_const_value:
- m->value = attr->value;
- break;
- default:
- fprintf(stderr, "Unknown sub param attribute %02x\n",
- attr->name);
- }
- }
- }
- break;
- default:
- fprintf(stderr, "Unknown enum tag %02x\n", abbr->tag);
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- }
- num = elfReadLEB128(data, &bytes);
- data += bytes;
- }
- }
- e->count = count;
- *type = t;
- return;
- }
- break;
- case DW_TAG_subroutine_type:
- {
- Type *t = (Type *)calloc(sizeof(Type), 1);
- t->type = TYPE_function;
- FunctionType *f = (FunctionType *)calloc(sizeof(FunctionType), 1);
- t->function = f;
- elfAddType(t, unit, offset);
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_prototyped:
- case DW_AT_sibling:
- break;
- case DW_AT_type:
- f->returnType = elfParseType(unit, attr->value);
- break;
- default:
- fprintf(stderr, "Unknown subroutine attribute %02x\n", attr->name);
- }
- }
- if(abbrev->hasChildren) {
- int bytes;
- u32 num = elfReadLEB128(data, &bytes);
- data += bytes;
- Object *lastVar = NULL;
- while(num) {
- ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
-
- switch(abbr->tag) {
- case DW_TAG_formal_parameter:
- {
- Object *o;
- data = elfParseObject(data, abbr, unit, &o);
- if(f->args)
- lastVar->next = o;
- else
- f->args = o;
- lastVar = o;
- }
- break;
- case DW_TAG_unspecified_parameters:
- // no use in the debugger yet
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- CASE_TYPE_TAG:
- // skip types... parsed only when used
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- default:
- fprintf(stderr, "Unknown subroutine tag %02x\n", abbr->tag);
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- }
- num = elfReadLEB128(data, &bytes);
- data += bytes;
- }
- }
- *type = t;
- return;
- }
- break;
- case DW_TAG_array_type:
- {
- u32 typeref = 0;
- int i;
- Array *array = (Array *)calloc(sizeof(Array), 1);
- Type *t = (Type *)calloc(sizeof(Type), 1);
- t->type = TYPE_array;
- elfAddType(t, unit, offset);
-
- for(i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_sibling:
- break;
- case DW_AT_type:
- typeref = attr->value;
- array->type = elfParseType(unit, typeref);
- break;
- default:
- fprintf(stderr, "Unknown array attribute %02x\n", attr->name);
- }
- }
- if(abbrev->hasChildren) {
- int bytes;
- u32 num = elfReadLEB128(data, &bytes);
- data += bytes;
- int index = 0;
- int maxBounds = 0;
- while(num) {
- ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
-
- switch(abbr->tag) {
- case DW_TAG_subrange_type:
- {
- if(maxBounds == index) {
- maxBounds += 4;
- array->bounds = (int *)realloc(array->bounds,
- sizeof(int)*maxBounds);
- }
- for(int i = 0; i < abbr->numAttrs; i++) {
- ELFAttr *attr = &abbr->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_upper_bound:
- array->bounds[index] = attr->value+1;
- break;
- case DW_AT_type: // ignore
- break;
- default:
- fprintf(stderr, "Unknown subrange attribute %02x\n",
- attr->name);
- }
- }
- index++;
- }
- break;
- default:
- fprintf(stderr, "Unknown array tag %02x\n", abbr->tag);
- data = elfSkipData(data, abbr, unit->abbrevs);
- break;
- }
- num = elfReadLEB128(data, &bytes);
- data += bytes;
- }
- array->maxBounds = index;
- }
- t->size = array->type->size;
- for(i = 0; i < array->maxBounds; i++)
- t->size *= array->bounds[i];
- t->array = array;
- *type = t;
- return;
- }
- break;
- default:
- fprintf(stderr, "Unknown type TAG %02x\n", abbrev->tag);
- exit(-1);
- }
-}
-
-Type *elfParseType(CompileUnit *unit, u32 offset)
-{
- Type *t = unit->types;
-
- while(t) {
- if(t->offset == offset)
- return t;
- t = t->next;
- }
- if(offset == 0) {
- Type *t = (Type *)calloc(sizeof(Type), 1);
- t->type = TYPE_void;
- t->offset = 0;
- elfAddType(t, unit, 0);
- return t;
- }
- u8 *data = unit->top + offset;
- int bytes;
- int abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
- Type *type = NULL;
-
- ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
-
- elfParseType(data, offset, abbrev, unit, &type);
- return type;
-}
-
-void elfGetObjectAttributes(CompileUnit *unit, u32 offset, Object *o)
-{
- u8 *data = unit->top + offset;
- int bytes;
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- return;
- }
-
- ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_location:
- o->location = attr->block;
- break;
- case DW_AT_name:
- if(o->name == NULL)
- o->name = attr->string;
- break;
- case DW_AT_MIPS_linkage_name:
- o->name = attr->string;
- break;
- case DW_AT_decl_file:
- o->file = attr->value;
- break;
- case DW_AT_decl_line:
- o->line = attr->value;
- break;
- case DW_AT_type:
- o->type = elfParseType(unit, attr->value);
- break;
- case DW_AT_external:
- o->external = attr->flag;
- break;
- case DW_AT_const_value:
- case DW_AT_abstract_origin:
- case DW_AT_declaration:
- case DW_AT_artificial:
- // todo
- break;
- case DW_AT_specification:
- // TODO:
- break;
- default:
- fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
- break;
- }
- }
-}
-
-u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
- Object **object)
-{
- Object *o = (Object *)calloc(sizeof(Object), 1);
-
- o->next = NULL;
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_location:
- o->location = attr->block;
- break;
- case DW_AT_name:
- if(o->name == NULL)
- o->name = attr->string;
- break;
- case DW_AT_MIPS_linkage_name:
- o->name = attr->string;
- break;
- case DW_AT_decl_file:
- o->file = attr->value;
- break;
- case DW_AT_decl_line:
- o->line = attr->value;
- break;
- case DW_AT_type:
- o->type = elfParseType(unit, attr->value);
- break;
- case DW_AT_external:
- o->external = attr->flag;
- break;
- case DW_AT_abstract_origin:
- elfGetObjectAttributes(unit, attr->value, o);
- break;
- case DW_AT_const_value:
- case DW_AT_declaration:
- case DW_AT_artificial:
- break;
- case DW_AT_specification:
- // TODO:
- break;
- default:
- fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
- break;
- }
- }
- *object = o;
- return data;
-}
-
-u8 *elfParseBlock(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
- Function *func, Object **lastVar)
-{
- int bytes;
- u32 start = func->lowPC;
- u32 end = func->highPC;
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_sibling:
- break;
- case DW_AT_low_pc:
- start = attr->value;
- break;
- case DW_AT_high_pc:
- end = attr->value;
- break;
- case DW_AT_ranges: // ignore for now
- break;
- default:
- fprintf(stderr, "Unknown block attribute %02x\n", attr->name);
- break;
- }
- }
-
- if(abbrev->hasChildren) {
- int nesting = 1;
-
- while(nesting) {
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- nesting--;
- continue;
- }
-
- abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
-
- switch(abbrev->tag) {
- CASE_TYPE_TAG: // types only parsed when used
- case DW_TAG_label: // not needed
- data = elfSkipData(data, abbrev, unit->abbrevs);
- break;
- case DW_TAG_lexical_block:
- data = elfParseBlock(data, abbrev, unit, func, lastVar);
- break;
- case DW_TAG_subprogram:
- {
- Function *f = NULL;
- data = elfParseFunction(data, abbrev, unit, &f);
- if(f != NULL) {
- if(unit->lastFunction)
- unit->lastFunction->next = f;
- else
- unit->functions = f;
- unit->lastFunction = f;
- }
- }
- break;
- case DW_TAG_variable:
- {
- Object *o;
- data = elfParseObject(data, abbrev, unit, &o);
- if(o->startScope == 0)
- o->startScope = start;
- if(o->endScope == 0)
- o->endScope = 0;
- if(func->variables)
- (*lastVar)->next = o;
- else
- func->variables = o;
- *lastVar = o;
- }
- break;
- case DW_TAG_inlined_subroutine:
- // TODO:
- data = elfSkipData(data, abbrev, unit->abbrevs);
- break;
- default:
- {
- fprintf(stderr, "Unknown block TAG %02x\n", abbrev->tag);
- data = elfSkipData(data, abbrev, unit->abbrevs);
- }
- break;
- }
- }
- }
- return data;
-}
-
-void elfGetFunctionAttributes(CompileUnit *unit, u32 offset, Function *func)
-{
- u8 *data = unit->top + offset;
- int bytes;
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- return;
- }
-
- ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
-
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
-
- switch(attr->name) {
- case DW_AT_sibling:
- break;
- case DW_AT_name:
- if(func->name == NULL)
- func->name = attr->string;
- break;
- case DW_AT_MIPS_linkage_name:
- func->name = attr->string;
- break;
- case DW_AT_low_pc:
- func->lowPC = attr->value;
- break;
- case DW_AT_high_pc:
- func->highPC = attr->value;
- break;
- case DW_AT_decl_file:
- func->file = attr->value;
- break;
- case DW_AT_decl_line:
- func->line = attr->value;
- break;
- case DW_AT_external:
- func->external = attr->flag;
- break;
- case DW_AT_frame_base:
- func->frameBase = attr->block;
- break;
- case DW_AT_type:
- func->returnType = elfParseType(unit, attr->value);
- break;
- case DW_AT_inline:
- case DW_AT_specification:
- case DW_AT_declaration:
- case DW_AT_artificial:
- case DW_AT_prototyped:
- case DW_AT_proc_body:
- case DW_AT_save_offset:
- case DW_AT_user_2002:
- case DW_AT_virtuality:
- case DW_AT_containing_type:
- case DW_AT_accessibility:
- // todo;
- break;
- case DW_AT_vtable_elem_location:
- free(attr->block);
- break;
- default:
- fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
- break;
- }
- }
-
- return;
-}
-
-u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
- Function **f)
-{
- Function *func = (Function *)calloc(sizeof(Function), 1);
- *f = func;
-
- int bytes;
- bool mangled = false;
- bool declaration = false;
- for(int i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
- switch(attr->name) {
- case DW_AT_sibling:
- break;
- case DW_AT_name:
- if(func->name == NULL)
- func->name = attr->string;
- break;
- case DW_AT_MIPS_linkage_name:
- func->name = attr->string;
- mangled = true;
- break;
- case DW_AT_low_pc:
- func->lowPC = attr->value;
- break;
- case DW_AT_high_pc:
- func->highPC = attr->value;
- break;
- case DW_AT_prototyped:
- break;
- case DW_AT_decl_file:
- func->file = attr->value;
- break;
- case DW_AT_decl_line:
- func->line = attr->value;
- break;
- case DW_AT_external:
- func->external = attr->flag;
- break;
- case DW_AT_frame_base:
- func->frameBase = attr->block;
- break;
- case DW_AT_type:
- func->returnType = elfParseType(unit, attr->value);
- break;
- case DW_AT_abstract_origin:
- elfGetFunctionAttributes(unit, attr->value, func);
- break;
- case DW_AT_declaration:
- declaration = attr->flag;
- break;
- case DW_AT_inline:
- case DW_AT_specification:
- case DW_AT_artificial:
- case DW_AT_proc_body:
- case DW_AT_save_offset:
- case DW_AT_user_2002:
- case DW_AT_virtuality:
- case DW_AT_containing_type:
- case DW_AT_accessibility:
- // todo;
- break;
- case DW_AT_vtable_elem_location:
- free(attr->block);
- break;
- default:
- fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
- break;
- }
- }
-
- if(declaration) {
- elfCleanUp(func);
- free(func);
- *f = NULL;
-
- while(1) {
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- return data;
- }
-
- abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
-
- data = elfSkipData(data, abbrev, unit->abbrevs);
- }
- }
-
- if(abbrev->hasChildren) {
- int nesting = 1;
- Object *lastParam = NULL;
- Object *lastVar = NULL;
-
- while(nesting) {
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- nesting--;
- continue;
- }
-
- abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
-
- switch(abbrev->tag) {
- CASE_TYPE_TAG: // no need to parse types. only parsed when used
- case DW_TAG_label: // not needed
- data = elfSkipData(data, abbrev, unit->abbrevs);
- break;
- case DW_TAG_subprogram:
- {
- Function *fnc=NULL;
- data = elfParseFunction(data, abbrev, unit, &fnc);
- if(fnc != NULL) {
- if(unit->lastFunction == NULL)
- unit->functions = fnc;
- else
- unit->lastFunction->next = fnc;
- unit->lastFunction = fnc;
- }
- }
- break;
- case DW_TAG_lexical_block:
- {
- data = elfParseBlock(data, abbrev, unit, func, &lastVar);
- }
- break;
- case DW_TAG_formal_parameter:
- {
- Object *o;
- data = elfParseObject(data, abbrev, unit, &o);
- if(func->parameters)
- lastParam->next = o;
- else
- func->parameters = o;
- lastParam = o;
- }
- break;
- case DW_TAG_variable:
- {
- Object *o;
- data = elfParseObject(data, abbrev, unit, &o);
- if(func->variables)
- lastVar->next = o;
- else
- func->variables = o;
- lastVar = o;
- }
- break;
- case DW_TAG_unspecified_parameters:
- case DW_TAG_inlined_subroutine:
- {
- // todo
- for(int i = 0; i < abbrev->numAttrs; i++) {
- data = elfReadAttribute(data, &abbrev->attrs[i]);
- if(abbrev->attrs[i].form == DW_FORM_block1)
- free(abbrev->attrs[i].block);
- }
-
- if(abbrev->hasChildren)
- nesting++;
- }
- break;
- default:
- {
- fprintf(stderr, "Unknown function TAG %02x\n", abbrev->tag);
- data = elfSkipData(data, abbrev, unit->abbrevs);
- }
- break;
- }
- }
- }
- return data;
-}
-
-u8 *elfParseUnknownData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
-{
- int i;
- int bytes;
- // switch(abbrev->tag) {
- // default:
- fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
-
- for(i = 0; i < abbrev->numAttrs; i++) {
- data = elfReadAttribute(data, &abbrev->attrs[i]);
- if(abbrev->attrs[i].form == DW_FORM_block1)
- free(abbrev->attrs[i].block);
- }
-
- if(abbrev->hasChildren) {
- int nesting = 1;
- while(nesting) {
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- if(!abbrevNum) {
- nesting--;
- continue;
- }
-
- abbrev = elfGetAbbrev(abbrevs, abbrevNum);
-
- fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
-
- for(i = 0; i < abbrev->numAttrs; i++) {
- data = elfReadAttribute(data, &abbrev->attrs[i]);
- if(abbrev->attrs[i].form == DW_FORM_block1)
- free(abbrev->attrs[i].block);
- }
-
- if(abbrev->hasChildren) {
- nesting++;
- }
- }
- }
- // }
- return data;
-}
-
-u8 *elfParseCompileUnitChildren(u8 *data, CompileUnit *unit)
-{
- int bytes;
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
- Object *lastObj = NULL;
- while(abbrevNum) {
- ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
- switch(abbrev->tag) {
- case DW_TAG_subprogram:
- {
- Function *func = NULL;
- data = elfParseFunction(data, abbrev, unit, &func);
- if(func != NULL) {
- if(unit->lastFunction)
- unit->lastFunction->next = func;
- else
- unit->functions = func;
- unit->lastFunction = func;
- }
- }
- break;
- CASE_TYPE_TAG:
- data = elfSkipData(data, abbrev, unit->abbrevs);
- break;
- case DW_TAG_variable:
- {
- Object *var = NULL;
- data = elfParseObject(data, abbrev, unit, &var);
- if(lastObj)
- lastObj->next = var;
- else
- unit->variables = var;
- lastObj = var;
- }
- break;
- default:
- data = elfParseUnknownData(data, abbrev, unit->abbrevs);
- break;
- }
-
- abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
- }
- return data;
-}
-
-
-CompileUnit *elfParseCompUnit(u8 *data, u8 *abbrevData)
-{
- int bytes;
- u8 *top = data;
-
- u32 length = elfRead4Bytes(data);
- data += 4;
-
- u16 version = elfRead2Bytes(data);
- data += 2;
-
- u32 offset = elfRead4Bytes(data);
- data += 4;
-
- u8 addrSize = *data++;
-
- if(version != 2) {
- fprintf(stderr, "Unsupported debugging information version %d\n", version);
- return NULL;
- }
-
- if(addrSize != 4) {
- fprintf(stderr, "Unsupported address size %d\n", addrSize);
- return NULL;
- }
-
- ELFAbbrev **abbrevs = elfReadAbbrevs(abbrevData, offset);
-
- u32 abbrevNum = elfReadLEB128(data, &bytes);
- data += bytes;
-
- ELFAbbrev *abbrev = elfGetAbbrev(abbrevs, abbrevNum);
-
- CompileUnit *unit = (CompileUnit *)calloc(sizeof(CompileUnit), 1);
- unit->top = top;
- unit->length = length;
- unit->abbrevs = abbrevs;
- unit->next = NULL;
-
- elfCurrentUnit = unit;
-
- int i;
-
- for(i = 0; i < abbrev->numAttrs; i++) {
- ELFAttr *attr = &abbrev->attrs[i];
- data = elfReadAttribute(data, attr);
-
- switch(attr->name) {
- case DW_AT_name:
- unit->name = attr->string;
- break;
- case DW_AT_stmt_list:
- unit->hasLineInfo = true;
- unit->lineInfo = attr->value;
- break;
- case DW_AT_low_pc:
- unit->lowPC = attr->value;
- break;
- case DW_AT_high_pc:
- unit->highPC = attr->value;
- break;
- case DW_AT_compdir:
- unit->compdir = attr->string;
- break;
- // ignore
- case DW_AT_language:
- case DW_AT_producer:
- case DW_AT_macro_info:
- case DW_AT_entry_pc:
- break;
- default:
- fprintf(stderr, "Unknown attribute %02x\n", attr->name);
- break;
- }
- }
-
- if(abbrev->hasChildren)
- elfParseCompileUnitChildren(data, unit);
-
- return unit;
-}
-
-void elfParseAranges(u8 *data)
-{
- ELFSectionHeader *sh = elfGetSectionByName(".debug_aranges");
- if(sh == NULL) {
- fprintf(stderr, "No aranges found\n");
- return;
- }
-
- data = elfReadSection(data, sh);
- u8 *end = data + READ32LE(&sh->size);
-
- int max = 4;
- ARanges *ranges = (ARanges *)calloc(sizeof(ARanges), 4);
-
- int index = 0;
-
- while(data < end) {
- u32 len = elfRead4Bytes(data);
- data += 4;
- // u16 version = elfRead2Bytes(data);
- data += 2;
- u32 offset = elfRead4Bytes(data);
- data += 4;
- // u8 addrSize = *data++;
- // u8 segSize = *data++;
- data += 2; // remove if uncommenting above
- data += 4;
- ranges[index].count = (len-20)/8;
- ranges[index].offset = offset;
- ranges[index].ranges = (ARange *)calloc(sizeof(ARange), (len-20)/8);
- int i = 0;
- while(true) {
- u32 addr = elfRead4Bytes(data);
- data += 4;
- u32 len = elfRead4Bytes(data);
- data += 4;
- if(addr == 0 && len == 0)
- break;
- ranges[index].ranges[i].lowPC = addr;
- ranges[index].ranges[i].highPC = addr+len;
- i++;
- }
- index++;
- if(index == max) {
- max += 4;
- ranges = (ARanges *)realloc(ranges, max*sizeof(ARanges));
- }
- }
- elfDebugInfo->numRanges = index;
- elfDebugInfo->ranges = ranges;
-}
-
-void elfReadSymtab(u8 *data)
-{
- ELFSectionHeader *sh = elfGetSectionByName(".symtab");
- int table = READ32LE(&sh->link);
-
- char *strtable = (char *)elfReadSection(data, elfGetSectionByNumber(table));
-
- ELFSymbol *symtab = (ELFSymbol *)elfReadSection(data, sh);
-
- int count = READ32LE(&sh->size) / sizeof(ELFSymbol);
- elfSymbolsCount = 0;
-
- elfSymbols = (Symbol *)malloc(sizeof(Symbol)*count);
-
- int i;
-
- for(i = 0; i < count; i++) {
- ELFSymbol *s = &symtab[i];
- int type = s->info & 15;
- int binding = s->info >> 4;
-
- if(binding) {
- Symbol *sym = &elfSymbols[elfSymbolsCount];
- sym->name = &strtable[READ32LE(&s->name)];
- sym->binding = binding;
- sym->type = type;
- sym->value = READ32LE(&s->value);
- sym->size = READ32LE(&s->size);
- elfSymbolsCount++;
- }
- }
- for(i = 0; i < count; i++) {
- ELFSymbol *s = &symtab[i];
- int bind = s->info>>4;
- int type = s->info & 15;
-
- if(!bind) {
- Symbol *sym = &elfSymbols[elfSymbolsCount];
- sym->name = &strtable[READ32LE(&s->name)];
- sym->binding = (s->info >> 4);
- sym->type = type;
- sym->value = READ32LE(&s->value);
- sym->size = READ32LE(&s->size);
- elfSymbolsCount++;
- }
- }
- elfSymbolsStrTab = strtable;
- // free(symtab);
-}
-
-bool elfReadProgram(ELFHeader *eh, u8 *data, int& size, bool parseDebug)
-{
- int count = READ16LE(&eh->e_phnum);
- int i;
-
- if(READ32LE(&eh->e_entry) == 0x2000000)
- cpuIsMultiBoot = true;
-
- // read program headers... should probably move this code down
- u8 *p = data + READ32LE(&eh->e_phoff);
- size = 0;
- for(i = 0; i < count; i++) {
- ELFProgramHeader *ph = (ELFProgramHeader *)p;
- p += sizeof(ELFProgramHeader);
- if(READ16LE(&eh->e_phentsize) != sizeof(ELFProgramHeader)) {
- p += READ16LE(&eh->e_phentsize) - sizeof(ELFProgramHeader);
- }
-
- // printf("PH %d %08x %08x %08x %08x %08x %08x %08x %08x\n",
- // i, ph->type, ph->offset, ph->vaddr, ph->paddr,
- // ph->filesz, ph->memsz, ph->flags, ph->align);
- if(cpuIsMultiBoot) {
- if(READ32LE(&ph->paddr) >= 0x2000000 &&
- READ32LE(&ph->paddr) <= 0x203ffff) {
- memcpy(&workRAM[READ32LE(&ph->paddr) & 0x3ffff],
- data + READ32LE(&ph->offset),
- READ32LE(&ph->filesz));
- size += READ32LE(&ph->filesz);
- }
- } else {
- if(READ32LE(&ph->paddr) >= 0x8000000 &&
- READ32LE(&ph->paddr) <= 0x9ffffff) {
- memcpy(&rom[READ32LE(&ph->paddr) & 0x1ffffff],
- data + READ32LE(&ph->offset),
- READ32LE(&ph->filesz));
- size += READ32LE(&ph->filesz);
- }
- }
- }
-
- char *stringTable = NULL;
-
- // read section headers
- p = data + READ32LE(&eh->e_shoff);
- count = READ16LE(&eh->e_shnum);
-
- ELFSectionHeader **sh = (ELFSectionHeader **)
- malloc(sizeof(ELFSectionHeader *) * count);
-
- for(i = 0; i < count; i++) {
- sh[i] = (ELFSectionHeader *)p;
- p += sizeof(ELFSectionHeader);
- if(READ16LE(&eh->e_shentsize) != sizeof(ELFSectionHeader))
- p += READ16LE(&eh->e_shentsize) - sizeof(ELFSectionHeader);
- }
-
- if(READ16LE(&eh->e_shstrndx) != 0) {
- stringTable = (char *)elfReadSection(data,
- sh[READ16LE(&eh->e_shstrndx)]);
- }
-
- elfSectionHeaders = sh;
- elfSectionHeadersStringTable = stringTable;
- elfSectionHeadersCount = count;
-
- for(i = 0; i < count; i++) {
- // printf("SH %d %-20s %08x %08x %08x %08x %08x %08x %08x %08x\n",
- // i, &stringTable[sh[i]->name], sh[i]->name, sh[i]->type,
- // sh[i]->flags, sh[i]->addr, sh[i]->offset, sh[i]->size,
- // sh[i]->link, sh[i]->info);
- if(READ32LE(&sh[i]->flags) & 2) { // load section
- if(cpuIsMultiBoot) {
- if(READ32LE(&sh[i]->addr) >= 0x2000000 &&
- READ32LE(&sh[i]->addr) <= 0x203ffff) {
- memcpy(&workRAM[READ32LE(&sh[i]->addr) & 0x3ffff], data +
- READ32LE(&sh[i]->offset),
- READ32LE(&sh[i]->size));
- size += READ32LE(&sh[i]->size);
- }
- } else {
- if(READ32LE(&sh[i]->addr) >= 0x8000000 &&
- READ32LE(&sh[i]->addr) <= 0x9ffffff) {
- memcpy(&rom[READ32LE(&sh[i]->addr) & 0x1ffffff],
- data + READ32LE(&sh[i]->offset),
- READ32LE(&sh[i]->size));
- size += READ32LE(&sh[i]->size);
- }
- }
- }
- }
-
- if(parseDebug) {
- fprintf(stderr, "Parsing debug info\n");
-
- ELFSectionHeader *dbgHeader = elfGetSectionByName(".debug_info");
- if(dbgHeader == NULL) {
- fprintf(stderr, "Cannot find debug information\n");
- goto end;
- }
-
- ELFSectionHeader *h = elfGetSectionByName(".debug_abbrev");
- if(h == NULL) {
- fprintf(stderr, "Cannot find abbreviation table\n");
- goto end;
- }
-
- elfDebugInfo = (DebugInfo *)calloc(sizeof(DebugInfo), 1);
- u8 *abbrevdata = elfReadSection(data, h);
-
- h = elfGetSectionByName(".debug_str");
-
- if(h == NULL)
- elfDebugStrings = NULL;
- else
- elfDebugStrings = (char *)elfReadSection(data, h);
-
- u8 *debugdata = elfReadSection(data, dbgHeader);
-
- elfDebugInfo->debugdata = data;
- elfDebugInfo->infodata = debugdata;
-
- u32 total = READ32LE(&dbgHeader->size);
- u8 *end = debugdata + total;
- u8 *ddata = debugdata;
-
- CompileUnit *last = NULL;
- CompileUnit *unit = NULL;
-
- while(ddata < end) {
- unit = elfParseCompUnit(ddata, abbrevdata);
- unit->offset = ddata-debugdata;
- elfParseLineInfo(unit, data);
- if(last == NULL)
- elfCompileUnits = unit;
- else
- last->next = unit;
- last = unit;
- ddata += 4 + unit->length;
- }
- elfParseAranges(data);
- CompileUnit *comp = elfCompileUnits;
- while(comp) {
- ARanges *r = elfDebugInfo->ranges;
- for(int i = 0; i < elfDebugInfo->numRanges; i++)
- if(r[i].offset == comp->offset) {
- comp->ranges = &r[i];
- break;
- }
- comp = comp->next;
- }
- elfParseCFA(data);
- elfReadSymtab(data);
- }
- end:
- if(sh) {
- free(sh);
- }
-
- elfSectionHeaders = NULL;
- elfSectionHeadersStringTable = NULL;
- elfSectionHeadersCount = 0;
-
- return true;
-}
-
-extern bool parseDebug;
-
-bool elfRead(const char *name, int& siz, FILE *f)
-{
- fseek(f, 0, SEEK_END);
- long size = ftell(f);
- elfFileData = (u8 *)malloc(size);
- fseek(f, 0, SEEK_SET);
- fread(elfFileData, 1, size, f);
- fclose(f);
-
- ELFHeader *header = (ELFHeader *)elfFileData;
-
- if(READ32LE(&header->magic) != 0x464C457F ||
- READ16LE(&header->e_machine) != 40 ||
- header->clazz != 1) {
- systemMessage(0, N_("Not a valid ELF file %s"), name);
- free(elfFileData);
- elfFileData = NULL;
- return false;
- }
-
- if(!elfReadProgram(header, elfFileData, siz, parseDebug)) {
- free(elfFileData);
- elfFileData = NULL;
- return false;
- }
-
- return true;
-}
-
-void elfCleanUp(Object *o)
-{
- free(o->location);
-}
-
-void elfCleanUp(Function *func)
-{
- Object *o = func->parameters;
- while(o) {
- elfCleanUp(o);
- Object *next = o->next;
- free(o);
- o = next;
- }
-
- o = func->variables;
- while(o) {
- elfCleanUp(o);
- Object *next = o->next;
- free(o);
- o = next;
- }
- free(func->frameBase);
-}
-
-void elfCleanUp(ELFAbbrev **abbrevs)
-{
- for(int i = 0; i < 121; i++) {
- ELFAbbrev *abbrev = abbrevs[i];
-
- while(abbrev) {
- free(abbrev->attrs);
- ELFAbbrev *next = abbrev->next;
- free(abbrev);
-
- abbrev = next;
- }
- }
-}
-
-void elfCleanUp(Type *t)
-{
- switch(t->type) {
- case TYPE_function:
- if(t->function) {
- Object *o = t->function->args;
- while(o) {
- elfCleanUp(o);
- Object *next = o->next;
- free(o);
- o = next;
- }
- free(t->function);
- }
- break;
- case TYPE_array:
- if(t->array) {
- free(t->array->bounds);
- free(t->array);
- }
- break;
- case TYPE_struct:
- case TYPE_union:
- if(t->structure) {
- for(int i = 0; i < t->structure->memberCount; i++) {
- free(t->structure->members[i].location);
- }
- free(t->structure->members);
- free(t->structure);
- }
- break;
- case TYPE_enum:
- if(t->enumeration) {
- free(t->enumeration->members);
- free(t->enumeration);
- }
- break;
- case TYPE_base:
- case TYPE_pointer:
- case TYPE_void:
- case TYPE_reference:
- break; // nothing to do
- }
-}
-
-void elfCleanUp(CompileUnit *comp)
-{
- elfCleanUp(comp->abbrevs);
- free(comp->abbrevs);
- Function *func = comp->functions;
- while(func) {
- elfCleanUp(func);
- Function *next = func->next;
- free(func);
- func = next;
- }
- Type *t = comp->types;
- while(t) {
- elfCleanUp(t);
- Type *next = t->next;
- free(t);
- t = next;
- }
- Object *o = comp->variables;
- while(o) {
- elfCleanUp(o);
- Object *next = o->next;
- free(o);
- o = next;
- }
- if(comp->lineInfoTable) {
- free(comp->lineInfoTable->lines);
- free(comp->lineInfoTable->files);
- free(comp->lineInfoTable);
- }
-}
-
-void elfCleanUp()
-{
- CompileUnit *comp = elfCompileUnits;
-
- while(comp) {
- elfCleanUp(comp);
- CompileUnit *next = comp->next;
- free(comp);
- comp = next;
- }
- elfCompileUnits = NULL;
- free(elfSymbols);
- elfSymbols = NULL;
- // free(elfSymbolsStrTab);
- elfSymbolsStrTab = NULL;
-
- elfDebugStrings = NULL;
- if(elfDebugInfo) {
- int num = elfDebugInfo->numRanges;
- int i;
- for(i = 0; i < num; i++) {
- free(elfDebugInfo->ranges[i].ranges);
- }
- free(elfDebugInfo->ranges);
- free(elfDebugInfo);
- elfDebugInfo = NULL;
- }
-
- if(elfFdes) {
- if(elfFdeCount) {
- for(int i = 0; i < elfFdeCount; i++)
- free(elfFdes[i]);
- }
- free(elfFdes);
-
- elfFdes = NULL;
- elfFdeCount = 0;
- }
-
- ELFcie *cie = elfCies;
- while(cie) {
- ELFcie *next = cie->next;
- free(cie);
- cie = next;
- }
- elfCies = NULL;
-
- if(elfFileData) {
- free(elfFileData);
- elfFileData = NULL;
- }
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+#include
+
+#include "GBA.h"
+#include "Port.h"
+#include "elf.h"
+#include "NLS.h"
+
+#define elfReadMemory(addr) \
+ READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
+
+#define DW_TAG_array_type 0x01
+#define DW_TAG_enumeration_type 0x04
+#define DW_TAG_formal_parameter 0x05
+#define DW_TAG_label 0x0a
+#define DW_TAG_lexical_block 0x0b
+#define DW_TAG_member 0x0d
+#define DW_TAG_pointer_type 0x0f
+#define DW_TAG_reference_type 0x10
+#define DW_TAG_compile_unit 0x11
+#define DW_TAG_structure_type 0x13
+#define DW_TAG_subroutine_type 0x15
+#define DW_TAG_typedef 0x16
+#define DW_TAG_union_type 0x17
+#define DW_TAG_unspecified_parameters 0x18
+#define DW_TAG_inheritance 0x1c
+#define DW_TAG_inlined_subroutine 0x1d
+#define DW_TAG_subrange_type 0x21
+#define DW_TAG_base_type 0x24
+#define DW_TAG_const_type 0x26
+#define DW_TAG_enumerator 0x28
+#define DW_TAG_subprogram 0x2e
+#define DW_TAG_variable 0x34
+#define DW_TAG_volatile_type 0x35
+
+#define DW_AT_sibling 0x01
+#define DW_AT_location 0x02
+#define DW_AT_name 0x03
+#define DW_AT_byte_size 0x0b
+#define DW_AT_bit_offset 0x0c
+#define DW_AT_bit_size 0x0d
+#define DW_AT_stmt_list 0x10
+#define DW_AT_low_pc 0x11
+#define DW_AT_high_pc 0x12
+#define DW_AT_language 0x13
+#define DW_AT_compdir 0x1b
+#define DW_AT_const_value 0x1c
+#define DW_AT_containing_type 0x1d
+#define DW_AT_inline 0x20
+#define DW_AT_producer 0x25
+#define DW_AT_prototyped 0x27
+#define DW_AT_upper_bound 0x2f
+#define DW_AT_abstract_origin 0x31
+#define DW_AT_accessibility 0x32
+#define DW_AT_artificial 0x34
+#define DW_AT_data_member_location 0x38
+#define DW_AT_decl_file 0x3a
+#define DW_AT_decl_line 0x3b
+#define DW_AT_declaration 0x3c
+#define DW_AT_encoding 0x3e
+#define DW_AT_external 0x3f
+#define DW_AT_frame_base 0x40
+#define DW_AT_macro_info 0x43
+#define DW_AT_specification 0x47
+#define DW_AT_type 0x49
+#define DW_AT_virtuality 0x4c
+#define DW_AT_vtable_elem_location 0x4d
+// DWARF 2.1/3.0 extensions
+#define DW_AT_entry_pc 0x52
+#define DW_AT_ranges 0x55
+// ARM Compiler extensions
+#define DW_AT_proc_body 0x2000
+#define DW_AT_save_offset 0x2001
+#define DW_AT_user_2002 0x2002
+// MIPS extensions
+#define DW_AT_MIPS_linkage_name 0x2007
+
+#define DW_FORM_addr 0x01
+#define DW_FORM_data2 0x05
+#define DW_FORM_data4 0x06
+#define DW_FORM_string 0x08
+#define DW_FORM_block 0x09
+#define DW_FORM_block1 0x0a
+#define DW_FORM_data1 0x0b
+#define DW_FORM_flag 0x0c
+#define DW_FORM_sdata 0x0d
+#define DW_FORM_strp 0x0e
+#define DW_FORM_udata 0x0f
+#define DW_FORM_ref_addr 0x10
+#define DW_FORM_ref4 0x13
+#define DW_FORM_ref_udata 0x15
+#define DW_FORM_indirect 0x16
+
+#define DW_OP_addr 0x03
+#define DW_OP_plus_uconst 0x23
+#define DW_OP_reg0 0x50
+#define DW_OP_reg1 0x51
+#define DW_OP_reg2 0x52
+#define DW_OP_reg3 0x53
+#define DW_OP_reg4 0x54
+#define DW_OP_reg5 0x55
+#define DW_OP_reg6 0x56
+#define DW_OP_reg7 0x57
+#define DW_OP_reg8 0x58
+#define DW_OP_reg9 0x59
+#define DW_OP_reg10 0x5a
+#define DW_OP_reg11 0x5b
+#define DW_OP_reg12 0x5c
+#define DW_OP_reg13 0x5d
+#define DW_OP_reg14 0x5e
+#define DW_OP_reg15 0x5f
+#define DW_OP_fbreg 0x91
+
+#define DW_LNS_extended_op 0x00
+#define DW_LNS_copy 0x01
+#define DW_LNS_advance_pc 0x02
+#define DW_LNS_advance_line 0x03
+#define DW_LNS_set_file 0x04
+#define DW_LNS_set_column 0x05
+#define DW_LNS_negate_stmt 0x06
+#define DW_LNS_set_basic_block 0x07
+#define DW_LNS_const_add_pc 0x08
+#define DW_LNS_fixed_advance_pc 0x09
+
+#define DW_LNE_end_sequence 0x01
+#define DW_LNE_set_address 0x02
+#define DW_LNE_define_file 0x03
+
+#define DW_CFA_advance_loc 0x01
+#define DW_CFA_offset 0x02
+#define DW_CFA_restore 0x03
+#define DW_CFA_set_loc 0x01
+#define DW_CFA_advance_loc1 0x02
+#define DW_CFA_advance_loc2 0x03
+#define DW_CFA_advance_loc4 0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended 0x06
+#define DW_CFA_undefined 0x07
+#define DW_CFA_same_value 0x08
+#define DW_CFA_register 0x09
+#define DW_CFA_remember_state 0x0a
+#define DW_CFA_restore_state 0x0b
+#define DW_CFA_def_cfa 0x0c
+#define DW_CFA_def_cfa_register 0x0d
+#define DW_CFA_def_cfa_offset 0x0e
+#define DW_CFA_nop 0x00
+
+#define CASE_TYPE_TAG \
+ case DW_TAG_const_type:\
+ case DW_TAG_volatile_type:\
+ case DW_TAG_pointer_type:\
+ case DW_TAG_base_type:\
+ case DW_TAG_array_type:\
+ case DW_TAG_structure_type:\
+ case DW_TAG_union_type:\
+ case DW_TAG_typedef:\
+ case DW_TAG_subroutine_type:\
+ case DW_TAG_enumeration_type:\
+ case DW_TAG_enumerator:\
+ case DW_TAG_reference_type
+
+struct ELFcie {
+ ELFcie *next;
+ u32 offset;
+ u8 *augmentation;
+ u32 codeAlign;
+ s32 dataAlign;
+ int returnAddress;
+ u8 *data;
+ u32 dataLen;
+};
+
+struct ELFfde {
+ ELFcie *cie;
+ u32 address;
+ u32 end;
+ u8 *data;
+ u32 dataLen;
+};
+
+enum ELFRegMode {
+ REG_NOT_SET,
+ REG_OFFSET,
+ REG_REGISTER
+};
+
+
+struct ELFFrameStateRegister {
+ ELFRegMode mode;
+ int reg;
+ s32 offset;
+};
+
+struct ELFFrameStateRegisters {
+ ELFFrameStateRegister regs[16];
+ ELFFrameStateRegisters *previous;
+};
+
+enum ELFCfaMode {
+ CFA_NOT_SET,
+ CFA_REG_OFFSET
+};
+
+struct ELFFrameState {
+ ELFFrameStateRegisters registers;
+
+ ELFCfaMode cfaMode;
+ int cfaRegister;
+ s32 cfaOffset;
+
+ u32 pc;
+
+ int dataAlign;
+ int codeAlign;
+ int returnAddress;
+};
+
+extern bool cpuIsMultiBoot;
+
+Symbol *elfSymbols = NULL;
+char *elfSymbolsStrTab = NULL;
+int elfSymbolsCount = 0;
+
+ELFSectionHeader **elfSectionHeaders = NULL;
+char *elfSectionHeadersStringTable = NULL;
+int elfSectionHeadersCount = 0;
+u8 *elfFileData = NULL;
+
+CompileUnit *elfCompileUnits = NULL;
+DebugInfo *elfDebugInfo = NULL;
+char *elfDebugStrings = NULL;
+
+ELFcie *elfCies = NULL;
+ELFfde **elfFdes = NULL;
+int elfFdeCount = 0;
+
+CompileUnit *elfCurrentUnit = NULL;
+
+u32 elfRead4Bytes(u8 *);
+u16 elfRead2Bytes(u8 *);
+
+CompileUnit *elfGetCompileUnit(u32 addr)
+{
+ if(elfCompileUnits) {
+ CompileUnit *unit = elfCompileUnits;
+ while(unit) {
+ if(unit->lowPC) {
+ if(addr >= unit->lowPC && addr < unit->highPC)
+ return unit;
+ } else {
+ ARanges *r = unit->ranges;
+ if(r) {
+ int count = r->count;
+ for(int j = 0; j < count; j++) {
+ if(addr >= r->ranges[j].lowPC && addr < r->ranges[j].highPC)
+ return unit;
+ }
+ }
+ }
+ unit = unit->next;
+ }
+ }
+ return NULL;
+}
+
+char *elfGetAddressSymbol(u32 addr)
+{
+ static char buffer[256];
+
+ CompileUnit *unit = elfGetCompileUnit(addr);
+ // found unit, need to find function
+ if(unit) {
+ Function *func = unit->functions;
+ while(func) {
+ if(addr >= func->lowPC && addr < func->highPC) {
+ int offset = addr - func->lowPC;
+ char *name = func->name;
+ if(!name)
+ name = "";
+ if(offset)
+ sprintf(buffer, "%s+%d", name, offset);
+ else
+ strcpy(buffer, name);
+ return buffer;
+ }
+ func = func->next;
+ }
+ }
+
+ if(elfSymbolsCount) {
+ for(int i = 0; i < elfSymbolsCount; i++) {
+ Symbol *s = &elfSymbols[i];
+ if((addr >= s->value) && addr < (s->value+s->size)) {
+ int offset = addr-s->value;
+ char *name = s->name;
+ if(name == NULL)
+ name = "";
+ if(offset)
+ sprintf(buffer, "%s+%d", name, addr-s->value);
+ else
+ strcpy(buffer, name);
+ return buffer;
+ } else if(addr == s->value) {
+ if(s->name)
+ strcpy(buffer, s->name);
+ else
+ strcpy(buffer, "");
+ return buffer;
+ }
+ }
+ }
+
+ return "";
+}
+
+bool elfFindLineInModule(u32 *addr, char *name, int line)
+{
+ CompileUnit *unit = elfCompileUnits;
+
+ while(unit) {
+ if(unit->lineInfoTable) {
+ int i;
+ int count = unit->lineInfoTable->fileCount;
+ char *found = NULL;
+ for(i = 0; i < count; i++) {
+ if(strcmp(name, unit->lineInfoTable->files[i]) == 0) {
+ found = unit->lineInfoTable->files[i];
+ break;
+ }
+ }
+ // found a matching filename... try to find line now
+ if(found) {
+ LineInfoItem *table = unit->lineInfoTable->lines;
+ count = unit->lineInfoTable->number;
+ for(i = 0; i < count; i++) {
+ if(table[i].file == found && table[i].line == line) {
+ *addr = table[i].address;
+ return true;
+ }
+ }
+ // we can only find a single match
+ return false;
+ }
+ }
+ unit = unit->next;
+ }
+ return false;
+}
+
+int elfFindLine(CompileUnit *unit, Function * /* func */, u32 addr, char **f)
+{
+ int currentLine = -1;
+ if(unit->hasLineInfo) {
+ int count = unit->lineInfoTable->number;
+ LineInfoItem *table = unit->lineInfoTable->lines;
+ int i;
+ for(i = 0; i < count; i++) {
+ if(addr <= table[i].address)
+ break;
+ }
+ if(i == count)
+ i--;
+ *f = table[i].file;
+ currentLine = table[i].line;
+ }
+ return currentLine;
+}
+
+bool elfFindLineInUnit(u32 *addr, CompileUnit *unit, int line)
+{
+ if(unit->hasLineInfo) {
+ int count = unit->lineInfoTable->number;
+ LineInfoItem *table = unit->lineInfoTable->lines;
+ int i;
+ for(i = 0; i < count; i++) {
+ if(line == table[i].line) {
+ *addr = table[i].address;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool elfGetCurrentFunction(u32 addr, Function **f, CompileUnit **u)
+{
+ CompileUnit *unit = elfGetCompileUnit(addr);
+ // found unit, need to find function
+ if(unit) {
+ Function *func = unit->functions;
+ while(func) {
+ if(addr >= func->lowPC && addr < func->highPC) {
+ *f = func;
+ *u = unit;
+ return true;
+ }
+ func = func->next;
+ }
+ }
+ return false;
+}
+
+bool elfGetObject(char *name, Function *f, CompileUnit *u, Object **o)
+{
+ if(f && u) {
+ Object *v = f->variables;
+
+ while(v) {
+ if(strcmp(name, v->name) == 0) {
+ *o = v;
+ return true;
+ }
+ v = v->next;
+ }
+ v = f->parameters;
+ while(v) {
+ if(strcmp(name, v->name) == 0) {
+ *o = v;
+ return true;
+ }
+ v = v->next;
+ }
+ v = u->variables;
+ while(v) {
+ if(strcmp(name, v->name) == 0) {
+ *o = v;
+ return true;
+ }
+ v = v->next;
+ }
+ }
+
+ CompileUnit *c = elfCompileUnits;
+
+ while(c) {
+ if(c != u) {
+ Object *v = c->variables;
+ while(v) {
+ if(strcmp(name, v->name) == 0) {
+ *o = v;
+ return true;
+ }
+ v = v->next;
+ }
+ }
+ c = c->next;
+ }
+
+ return false;
+}
+
+char *elfGetSymbol(int i, u32 *value, u32 *size, int *type)
+{
+ if(i < elfSymbolsCount) {
+ Symbol *s = &elfSymbols[i];
+ *value = s->value;
+ *size = s->size;
+ *type = s->type;
+ return s->name;
+ }
+ return NULL;
+}
+
+bool elfGetSymbolAddress(char *sym, u32 *addr, u32 *size, int *type)
+{
+ if(elfSymbolsCount) {
+ for(int i = 0; i < elfSymbolsCount; i++) {
+ Symbol *s = &elfSymbols[i];
+ if(strcmp(sym, s->name) == 0) {
+ *addr = s->value;
+ *size = s->size;
+ *type = s->type;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+ELFfde *elfGetFde(u32 address)
+{
+ if(elfFdes) {
+ int i;
+ for(i = 0; i < elfFdeCount; i++) {
+ if(address >= elfFdes[i]->address &&
+ address < elfFdes[i]->end) {
+ return elfFdes[i];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void elfExecuteCFAInstructions(ELFFrameState *state, u8 *data, u32 len,
+ u32 pc)
+{
+ u8 *end = data + len;
+ int bytes;
+ int reg;
+ ELFFrameStateRegisters *fs;
+
+ while(data < end && state->pc < pc) {
+ u8 op = *data++;
+
+ switch(op >> 6) {
+ case DW_CFA_advance_loc:
+ state->pc += (op & 0x3f) * state->codeAlign;
+ break;
+ case DW_CFA_offset:
+ reg = op & 0x3f;
+ state->registers.regs[reg].mode = REG_OFFSET;
+ state->registers.regs[reg].offset = state->dataAlign *
+ (s32)elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_CFA_restore:
+ // we don't care much about the other possible settings,
+ // so just setting to unset is enough for now
+ state->registers.regs[op & 0x3f].mode = REG_NOT_SET;
+ break;
+ case 0:
+ switch(op & 0x3f) {
+ case DW_CFA_nop:
+ break;
+ case DW_CFA_advance_loc1:
+ state->pc += state->codeAlign * (*data++);
+ break;
+ case DW_CFA_advance_loc2:
+ state->pc += state->codeAlign * elfRead2Bytes(data);
+ data += 2;
+ break;
+ case DW_CFA_advance_loc4:
+ state->pc += state->codeAlign * elfRead4Bytes(data);
+ data += 4;
+ break;
+ case DW_CFA_offset_extended:
+ reg = elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->registers.regs[reg].mode = REG_OFFSET;
+ state->registers.regs[reg].offset = state->dataAlign *
+ (s32)elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+ reg = elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->registers.regs[reg].mode = REG_NOT_SET;
+ break;
+ case DW_CFA_register:
+ reg = elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->registers.regs[reg].mode = REG_REGISTER;
+ state->registers.regs[reg].reg = elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_CFA_remember_state:
+ fs = (ELFFrameStateRegisters *)calloc(1,
+ sizeof(ELFFrameStateRegisters));
+ memcpy(fs, &state->registers, sizeof(ELFFrameStateRegisters));
+ state->registers.previous = fs;
+ break;
+ case DW_CFA_restore_state:
+ if(state->registers.previous == NULL) {
+ printf("Error: previous frame state is NULL.\n");
+ return;
+ }
+ fs = state->registers.previous;
+ memcpy(&state->registers, fs, sizeof(ELFFrameStateRegisters));
+ free(fs);
+ break;
+ case DW_CFA_def_cfa:
+ state->cfaRegister = elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->cfaMode = CFA_REG_OFFSET;
+ break;
+ case DW_CFA_def_cfa_register:
+ state->cfaRegister = elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->cfaMode = CFA_REG_OFFSET;
+ break;
+ case DW_CFA_def_cfa_offset:
+ state->cfaOffset = (s32)elfReadLEB128(data, &bytes);
+ data += bytes;
+ state->cfaMode = CFA_REG_OFFSET;
+ break;
+ default:
+ printf("Unknown CFA opcode %08x\n", op);
+ return;
+ }
+ break;
+ default:
+ printf("Unknown CFA opcode %08x\n", op);
+ return;
+ }
+ }
+}
+
+ELFFrameState *elfGetFrameState(ELFfde *fde, u32 address)
+{
+ ELFFrameState *state = (ELFFrameState *)calloc(1, sizeof(ELFFrameState));
+ state->pc = fde->address;
+ state->dataAlign = fde->cie->dataAlign;
+ state->codeAlign = fde->cie->codeAlign;
+ state->returnAddress = fde->cie->returnAddress;
+
+ elfExecuteCFAInstructions(state,
+ fde->cie->data,
+ fde->cie->dataLen,
+ 0xffffffff);
+ elfExecuteCFAInstructions(state,
+ fde->data,
+ fde->dataLen,
+ address);
+
+ return state;
+}
+
+void elfPrintCallChain(u32 address)
+{
+ int count = 1;
+
+ reg_pair regs[15];
+ reg_pair newRegs[15];
+
+ memcpy(®s[0], ®[0], sizeof(reg_pair) * 15);
+
+ while(count < 20) {
+ char *addr = elfGetAddressSymbol(address);
+ if(*addr == 0)
+ addr = "???";
+
+ printf("%08x %s\n", address, addr);
+
+ ELFfde *fde = elfGetFde(address);
+
+ if(fde == NULL) {
+ break;
+ }
+
+ ELFFrameState *state = elfGetFrameState(fde, address);
+
+ if(!state) {
+ break;
+ }
+
+ if(state->cfaMode == CFA_REG_OFFSET) {
+ memcpy(&newRegs[0], ®s[0], sizeof(reg_pair) * 15);
+ u32 addr = 0;
+ for(int i = 0; i < 15; i++) {
+ ELFFrameStateRegister *r = &state->registers.
+ regs[i];
+
+ switch(r->mode) {
+ case REG_NOT_SET:
+ newRegs[i].I = regs[i].I;
+ break;
+ case REG_OFFSET:
+ newRegs[i].I = elfReadMemory(regs[state->cfaRegister].I +
+ state->cfaOffset +
+ r->offset);
+ break;
+ case REG_REGISTER:
+ newRegs[i].I = regs[r->reg].I;
+ break;
+ default:
+ printf("Unknown register mode: %d\n", r->mode);
+ break;
+ }
+ }
+ memcpy(regs, newRegs, sizeof(reg_pair)*15);
+ addr = newRegs[14].I;
+ addr &= 0xfffffffe;
+ address = addr;
+ count++;
+ } else {
+ printf("CFA not set\n");
+ break;
+ }
+ if(state->registers.previous) {
+ ELFFrameStateRegisters *prev = state->registers.previous;
+
+ while(prev) {
+ ELFFrameStateRegisters *p = prev->previous;
+ free(prev);
+ prev = p;
+ }
+ }
+ free(state);
+ }
+}
+
+u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type, u32 base)
+{
+ u32 framebase = 0;
+ if(f && f->frameBase) {
+ ELFBlock *b = f->frameBase;
+ switch(*b->data) {
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ framebase = reg[*b->data-0x50].I;
+ break;
+ default:
+ fprintf(stderr, "Unknown frameBase %02x\n", *b->data);
+ break;
+ }
+ }
+
+ ELFBlock *loc = o;
+ u32 location = 0;
+ int bytes = 0;
+ if(loc) {
+ switch(*loc->data) {
+ case DW_OP_addr:
+ location = elfRead4Bytes(loc->data+1);
+ *type = LOCATION_memory;
+ break;
+ case DW_OP_plus_uconst:
+ location = base + elfReadLEB128(loc->data+1, &bytes);
+ *type = LOCATION_memory;
+ break;
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ location = *loc->data - 0x50;
+ *type = LOCATION_register;
+ break;
+ case DW_OP_fbreg:
+ {
+ int bytes;
+ s32 off = elfReadSignedLEB128(loc->data+1, &bytes);
+ location = framebase + off;
+ *type = LOCATION_memory;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown location %02x\n", *loc->data);
+ break;
+ }
+ }
+ return location;
+}
+
+u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type)
+{
+ return elfDecodeLocation(f, o, type, 0);
+}
+
+// reading function
+
+u32 elfRead4Bytes(u8 *data)
+{
+ u32 value = *data++;
+ value |= (*data++ << 8);
+ value |= (*data++ << 16);
+ value |= (*data << 24);
+ return value;
+}
+
+u16 elfRead2Bytes(u8 *data)
+{
+ u16 value = *data++;
+ value |= (*data << 8);
+ return value;
+}
+
+char *elfReadString(u8 *data, int *bytesRead)
+{
+ if(*data == 0) {
+ *bytesRead = 1;
+ return NULL;
+ }
+ *bytesRead = (int)strlen((char *)data) + 1;
+ return (char *)data;
+}
+
+s32 elfReadSignedLEB128(u8 *data, int *bytesRead)
+{
+ s32 result = 0;
+ int shift = 0;
+ int count = 0;
+
+ u8 byte;
+ do {
+ byte = *data++;
+ count++;
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+ } while(byte & 0x80);
+ if((shift < 32) && (byte & 0x40))
+ result |= -(1 << shift);
+ *bytesRead = count;
+ return result;
+}
+
+u32 elfReadLEB128(u8 *data, int *bytesRead)
+{
+ u32 result = 0;
+ int shift = 0;
+ int count = 0;
+ u8 byte;
+ do {
+ byte = *data++;
+ count++;
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+ } while(byte & 0x80);
+ *bytesRead = count;
+ return result;
+}
+
+u8 *elfReadSection(u8 *data, ELFSectionHeader *sh)
+{
+ return data + READ32LE(&sh->offset);
+}
+
+ELFSectionHeader *elfGetSectionByName(char *name)
+{
+ for(int i = 0; i < elfSectionHeadersCount; i++) {
+ if(strcmp(name,
+ &elfSectionHeadersStringTable[READ32LE(&elfSectionHeaders[i]->
+ name)]) == 0) {
+ return elfSectionHeaders[i];
+ }
+ }
+ return NULL;
+}
+
+ELFSectionHeader *elfGetSectionByNumber(int number)
+{
+ if(number < elfSectionHeadersCount) {
+ return elfSectionHeaders[number];
+ }
+ return NULL;
+}
+
+CompileUnit *elfGetCompileUnitForData(u8 *data)
+{
+ u8 *end = elfCurrentUnit->top + 4 + elfCurrentUnit->length;
+
+ if(data >= elfCurrentUnit->top && data < end)
+ return elfCurrentUnit;
+
+ CompileUnit *unit = elfCompileUnits;
+
+ while(unit) {
+ end = unit->top + 4 + unit->length;
+
+ if(data >= unit->top && data < end)
+ return unit;
+
+ unit = unit->next;
+ }
+
+ printf("Error: cannot find reference to compile unit at offset %08x\n",
+ (int)(data - elfDebugInfo->infodata));
+ exit(-1);
+}
+
+u8 *elfReadAttribute(u8 *data, ELFAttr *attr)
+{
+ int bytes;
+ int form = attr->form;
+ start:
+ switch(form) {
+ case DW_FORM_addr:
+ attr->value = elfRead4Bytes(data);
+ data += 4;
+ break;
+ case DW_FORM_data2:
+ attr->value = elfRead2Bytes(data);
+ data += 2;
+ break;
+ case DW_FORM_data4:
+ attr->value = elfRead4Bytes(data);
+ data += 4;
+ break;
+ case DW_FORM_string:
+ attr->string = (char *)data;
+ data += strlen(attr->string)+1;
+ break;
+ case DW_FORM_strp:
+ attr->string = elfDebugStrings + elfRead4Bytes(data);
+ data += 4;
+ break;
+ case DW_FORM_block:
+ attr->block = (ELFBlock *)malloc(sizeof(ELFBlock));
+ attr->block->length = elfReadLEB128(data, &bytes);
+ data += bytes;
+ attr->block->data = data;
+ data += attr->block->length;
+ break;
+ case DW_FORM_block1:
+ attr->block = (ELFBlock *)malloc(sizeof(ELFBlock));
+ attr->block->length = *data++;
+ attr->block->data = data;
+ data += attr->block->length;
+ break;
+ case DW_FORM_data1:
+ attr->value = *data++;
+ break;
+ case DW_FORM_flag:
+ attr->flag = (*data++) ? true : false;
+ break;
+ case DW_FORM_sdata:
+ attr->value = elfReadSignedLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_FORM_udata:
+ attr->value = elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_FORM_ref_addr:
+ attr->value = (u32)((elfDebugInfo->infodata + elfRead4Bytes(data)) - elfGetCompileUnitForData(data)->top);
+ data += 4;
+ break;
+ case DW_FORM_ref4:
+ attr->value = elfRead4Bytes(data);
+ data += 4;
+ break;
+ case DW_FORM_ref_udata:
+ attr->value = (u32)((elfDebugInfo->infodata + (elfGetCompileUnitForData(data)->top - elfDebugInfo->infodata) + elfReadLEB128(data, &bytes)) - elfCurrentUnit->top);
+ data += bytes;
+ break;
+ case DW_FORM_indirect:
+ form = elfReadLEB128(data, &bytes);
+ data += bytes;
+ goto start;
+ default:
+ fprintf(stderr, "Unsupported FORM %02x\n", form);
+ exit(-1);
+ }
+ return data;
+}
+
+ELFAbbrev *elfGetAbbrev(ELFAbbrev **table, u32 number)
+{
+ int hash = number % 121;
+
+ ELFAbbrev *abbrev = table[hash];
+
+ while(abbrev) {
+ if(abbrev->number == number)
+ return abbrev;
+ abbrev = abbrev->next;
+ }
+ return NULL;
+}
+
+ELFAbbrev **elfReadAbbrevs(u8 *data, u32 offset)
+{
+ data += offset;
+ ELFAbbrev **abbrevs = (ELFAbbrev **)calloc(sizeof(ELFAbbrev *)*121,1);
+ int bytes = 0;
+ u32 number = elfReadLEB128(data, &bytes);
+ data += bytes;
+ while(number) {
+ ELFAbbrev *abbrev = (ELFAbbrev *)calloc(sizeof(ELFAbbrev),1);
+
+ // read tag information
+ abbrev->number = number;
+ abbrev->tag = elfReadLEB128(data, &bytes);
+ data += bytes;
+ abbrev->hasChildren = *data++ ? true: false;
+
+ // read attributes
+ int name = elfReadLEB128(data, &bytes);
+ data += bytes;
+ int form = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ while(name) {
+ if((abbrev->numAttrs % 4) == 0) {
+ abbrev->attrs = (ELFAttr *)realloc(abbrev->attrs,
+ (abbrev->numAttrs + 4) *
+ sizeof(ELFAttr));
+ }
+ abbrev->attrs[abbrev->numAttrs].name = name;
+ abbrev->attrs[abbrev->numAttrs++].form = form;
+
+ name = elfReadLEB128(data, &bytes);
+ data += bytes;
+ form = elfReadLEB128(data, &bytes);
+ data += bytes;
+ }
+
+ int hash = number % 121;
+ abbrev->next = abbrevs[hash];
+ abbrevs[hash] = abbrev;
+
+ number = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(elfGetAbbrev(abbrevs, number) != NULL)
+ break;
+ }
+
+ return abbrevs;
+}
+
+void elfParseCFA(u8 *top)
+{
+ ELFSectionHeader *h = elfGetSectionByName(".debug_frame");
+
+ if(h == NULL) {
+ return;
+ }
+
+ u8 *data = elfReadSection(top, h);
+
+ u8 *topOffset = data;
+
+ u8 *end = data + READ32LE(&h->size);
+
+ ELFcie *cies = NULL;
+
+ while(data < end) {
+ u32 offset = (u32)(data - topOffset);
+ u32 len = elfRead4Bytes(data);
+ data += 4;
+
+ u8 *dataEnd = data + len;
+
+ u32 id = elfRead4Bytes(data);
+ data += 4;
+
+ if(id == 0xffffffff) {
+ // skip version
+ *data++;
+
+ ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
+
+ cie->next = cies;
+ cies = cie;
+
+ cie->offset = offset;
+
+ cie->augmentation = data;
+ while(*data)
+ data++;
+ data++;
+
+ if(*cie->augmentation) {
+ fprintf(stderr, "Error: augmentation not supported\n");
+ exit(-1);
+ }
+
+ int bytes;
+ cie->codeAlign = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ cie->dataAlign = elfReadSignedLEB128(data, &bytes);
+ data += bytes;
+
+ cie->returnAddress = *data++;
+
+ cie->data = data;
+ cie->dataLen = (u32)(dataEnd - data);
+ } else {
+ ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde));
+
+ ELFcie *cie = cies;
+
+ while(cie != NULL) {
+ if(cie->offset == id)
+ break;
+ cie = cie->next;
+ }
+
+ if(!cie) {
+ fprintf(stderr, "Cannot find CIE %08x\n", id);
+ exit(-1);
+ }
+
+ fde->cie = cie;
+
+ fde->address = elfRead4Bytes(data);
+ data += 4;
+
+ fde->end = fde->address + elfRead4Bytes(data);
+ data += 4;
+
+ fde->data = data;
+ fde->dataLen = (u32)(dataEnd - data);
+
+ if((elfFdeCount %10) == 0) {
+ elfFdes = (ELFfde **)realloc(elfFdes, (elfFdeCount+10) *
+ sizeof(ELFfde *));
+ }
+ elfFdes[elfFdeCount++] = fde;
+ }
+ data = dataEnd;
+ }
+
+ elfCies = cies;
+}
+
+void elfAddLine(LineInfo *l, u32 a, int file, int line, int *max)
+{
+ if(l->number == *max) {
+ *max += 1000;
+ l->lines = (LineInfoItem *)realloc(l->lines, *max*sizeof(LineInfoItem));
+ }
+ LineInfoItem *li = &l->lines[l->number];
+ li->file = l->files[file-1];
+ li->address = a;
+ li->line = line;
+ l->number++;
+}
+
+void elfParseLineInfo(CompileUnit *unit, u8 *top)
+{
+ ELFSectionHeader *h = elfGetSectionByName(".debug_line");
+ if(h == NULL) {
+ fprintf(stderr, "No line information found\n");
+ return;
+ }
+ LineInfo *l = unit->lineInfoTable = (LineInfo *)calloc(1, sizeof(LineInfo));
+ l->number = 0;
+ int max = 1000;
+ l->lines = (LineInfoItem *)malloc(1000*sizeof(LineInfoItem));
+
+ u8 *data = elfReadSection(top, h);
+ data += unit->lineInfo;
+ u32 totalLen = elfRead4Bytes(data);
+ data += 4;
+ u8 *end = data + totalLen;
+ // u16 version = elfRead2Bytes(data);
+ data += 2;
+ // u32 offset = elfRead4Bytes(data);
+ data += 4;
+ int minInstrSize = *data++;
+ int defaultIsStmt = *data++;
+ int lineBase = (s8)*data++;
+ int lineRange = *data++;
+ int opcodeBase = *data++;
+ u8 *stdOpLen = (u8 *)malloc(opcodeBase * sizeof(u8));
+ stdOpLen[0] = 1;
+ int i;
+ for(i = 1; i < opcodeBase; i++)
+ stdOpLen[i] = *data++;
+
+ free(stdOpLen);// todo
+ int bytes = 0;
+
+ char *s;
+ while((s = elfReadString(data, &bytes)) != NULL) {
+ data += bytes;
+ // fprintf(stderr, "Directory is %s\n", s);
+ }
+ data += bytes;
+ int count = 4;
+ int index = 0;
+ l->files = (char **)malloc(sizeof(char *)*count);
+
+ while((s = elfReadString(data, &bytes)) != NULL) {
+ l->files[index++] = s;
+
+ data += bytes;
+ // directory
+ elfReadLEB128(data, &bytes);
+ data += bytes;
+ // time
+ elfReadLEB128(data, &bytes);
+ data += bytes;
+ // size
+ elfReadLEB128(data, &bytes);
+ data += bytes;
+ // fprintf(stderr, "File is %s\n", s);
+ if(index == count) {
+ count += 4;
+ l->files = (char **)realloc(l->files, sizeof(char *)*count);
+ }
+ }
+ l->fileCount = index;
+ data += bytes;
+
+ while(data < end) {
+ u32 address = 0;
+ int file = 1;
+ int line = 1;
+ int col = 0;
+ int isStmt = defaultIsStmt;
+ int basicBlock = 0;
+ int endSeq = 0;
+
+ while(!endSeq) {
+ int op = *data++;
+ switch(op) {
+ case DW_LNS_extended_op:
+ {
+ data++;
+ op = *data++;
+ switch(op) {
+ case DW_LNE_end_sequence:
+ endSeq = 1;
+ break;
+ case DW_LNE_set_address:
+ address = elfRead4Bytes(data);
+ data += 4;
+ break;
+ default:
+ fprintf(stderr, "Unknown extended LINE opcode %02x\n", op);
+ exit(-1);
+ }
+ }
+ break;
+ case DW_LNS_copy:
+ // fprintf(stderr, "Address %08x line %d (%d)\n", address, line, file);
+ elfAddLine(l, address, file, line, &max);
+ basicBlock = 0;
+ break;
+ case DW_LNS_advance_pc:
+ address += minInstrSize * elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_LNS_advance_line:
+ line += elfReadSignedLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_LNS_set_file:
+ file = elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_LNS_set_column:
+ col = elfReadLEB128(data, &bytes);
+ data += bytes;
+ break;
+ case DW_LNS_negate_stmt:
+ isStmt = !isStmt;
+ break;
+ case DW_LNS_set_basic_block:
+ basicBlock = 1;
+ break;
+ case DW_LNS_const_add_pc:
+ address += (minInstrSize *((255 - opcodeBase)/lineRange));
+ break;
+ case DW_LNS_fixed_advance_pc:
+ address += elfRead2Bytes(data);
+ data += 2;
+ break;
+ default:
+ op = op - opcodeBase;
+ address += (op / lineRange) * minInstrSize;
+ line += lineBase + (op % lineRange);
+ elfAddLine(l, address, file, line, &max);
+ // fprintf(stderr, "Address %08x line %d (%d)\n", address, line,file);
+ basicBlock = 1;
+ break;
+ }
+ }
+ }
+ l->lines = (LineInfoItem *)realloc(l->lines, l->number*sizeof(LineInfoItem));
+}
+
+u8 *elfSkipData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
+{
+ int i;
+ int bytes;
+
+ for(i = 0; i < abbrev->numAttrs; i++) {
+ data = elfReadAttribute(data, &abbrev->attrs[i]);
+ if(abbrev->attrs[i].form == DW_FORM_block1)
+ free(abbrev->attrs[i].block);
+ }
+
+ if(abbrev->hasChildren) {
+ int nesting = 1;
+ while(nesting) {
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ nesting--;
+ continue;
+ }
+
+ abbrev = elfGetAbbrev(abbrevs, abbrevNum);
+
+ for(i = 0; i < abbrev->numAttrs; i++) {
+ data = elfReadAttribute(data, &abbrev->attrs[i]);
+ if(abbrev->attrs[i].form == DW_FORM_block1)
+ free(abbrev->attrs[i].block);
+ }
+
+ if(abbrev->hasChildren) {
+ nesting++;
+ }
+ }
+ }
+ return data;
+}
+
+Type *elfParseType(CompileUnit *unit, u32);
+u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
+ Object **object);
+u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
+ Function **function);
+void elfCleanUp(Function *);
+
+void elfAddType(Type *type, CompileUnit *unit, u32 offset)
+{
+ if(type->next == NULL) {
+ if(unit->types != type && type->offset == 0) {
+ type->offset = offset;
+ type->next = unit->types;
+ unit->types = type;
+ }
+ }
+}
+
+void elfParseType(u8 *data, u32 offset, ELFAbbrev *abbrev, CompileUnit *unit,
+ Type **type)
+{
+ switch(abbrev->tag) {
+ case DW_TAG_typedef:
+ {
+ u32 typeref = 0;
+ char *name = NULL;
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_name:
+ name = attr->string;
+ break;
+ case DW_AT_type:
+ typeref = attr->value;
+ break;
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ break;
+ default:
+ fprintf(stderr, "Unknown attribute for typedef %02x\n", attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren)
+ fprintf(stderr, "Unexpected children for typedef\n");
+ *type = elfParseType(unit, typeref);
+ if(name)
+ (*type)->name = name;
+ return;
+ }
+ break;
+ case DW_TAG_union_type:
+ case DW_TAG_structure_type:
+ {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+ if(abbrev->tag == DW_TAG_structure_type)
+ t->type = TYPE_struct;
+ else
+ t->type = TYPE_union;
+
+ Struct *s = (Struct *)calloc(sizeof(Struct), 1);
+ t->structure = s;
+ elfAddType(t, unit, offset);
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_name:
+ t->name = attr->string;
+ break;
+ case DW_AT_byte_size:
+ t->size = attr->value;
+ break;
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ case DW_AT_sibling:
+ case DW_AT_containing_type: // todo?
+ case DW_AT_declaration:
+ case DW_AT_specification: // TODO:
+ break;
+ default:
+ fprintf(stderr, "Unknown attribute for struct %02x\n", attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren) {
+ int bytes;
+ u32 num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ int index = 0;
+ while(num) {
+ ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
+
+ switch(abbr->tag) {
+ case DW_TAG_member:
+ {
+ if((index % 4) == 0)
+ s->members = (Member *)realloc(s->members,
+ sizeof(Member)*(index+4));
+ Member *m = &s->members[index];
+ m->location = NULL;
+ m->bitOffset = 0;
+ m->bitSize = 0;
+ m->byteSize = 0;
+ for(int i = 0; i < abbr->numAttrs; i++) {
+ ELFAttr *attr = &abbr->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_name:
+ m->name = attr->string;
+ break;
+ case DW_AT_type:
+ m->type = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_data_member_location:
+ m->location = attr->block;
+ break;
+ case DW_AT_byte_size:
+ m->byteSize = attr->value;
+ break;
+ case DW_AT_bit_offset:
+ m->bitOffset = attr->value;
+ break;
+ case DW_AT_bit_size:
+ m->bitSize = attr->value;
+ break;
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ case DW_AT_accessibility:
+ case DW_AT_artificial: // todo?
+ break;
+ default:
+ fprintf(stderr, "Unknown member attribute %02x\n",
+ attr->name);
+ }
+ }
+ index++;
+ }
+ break;
+ case DW_TAG_subprogram:
+ {
+ Function *fnc = NULL;
+ data = elfParseFunction(data, abbr, unit, &fnc);
+ if(fnc != NULL) {
+ if(unit->lastFunction)
+ unit->lastFunction->next = fnc;
+ else
+ unit->functions = fnc;
+ unit->lastFunction = fnc;
+ }
+ }
+ break;
+ case DW_TAG_inheritance:
+ // TODO: add support
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ CASE_TYPE_TAG:
+ // skip types... parsed only when used
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ case DW_TAG_variable:
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ default:
+ fprintf(stderr, "Unknown struct tag %02x %s\n", abbr->tag, t->name);
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ }
+ num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ }
+ s->memberCount = index;
+ }
+ *type = t;
+ return;
+ }
+ break;
+ case DW_TAG_base_type:
+ {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+
+ t->type = TYPE_base;
+ elfAddType(t, unit, offset);
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_name:
+ t->name = attr->string;
+ break;
+ case DW_AT_encoding:
+ t->encoding = attr->value;
+ break;
+ case DW_AT_byte_size:
+ t->size = attr->value;
+ break;
+ case DW_AT_bit_size:
+ t->bitSize = attr->value;
+ break;
+ default:
+ fprintf(stderr, "Unknown attribute for base type %02x\n",
+ attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren)
+ fprintf(stderr, "Unexpected children for base type\n");
+ *type = t;
+ return;
+ }
+ break;
+ case DW_TAG_pointer_type:
+ {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+
+ t->type = TYPE_pointer;
+
+ elfAddType(t, unit, offset);
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data =elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_type:
+ t->pointer = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_byte_size:
+ t->size = attr->value;
+ break;
+ default:
+ fprintf(stderr, "Unknown pointer type attribute %02x\n", attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren)
+ fprintf(stderr, "Unexpected children for pointer type\n");
+ *type = t;
+ return;
+ }
+ break;
+ case DW_TAG_reference_type:
+ {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+
+ t->type = TYPE_reference;
+
+ elfAddType(t, unit, offset);
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data =elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_type:
+ t->pointer = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_byte_size:
+ t->size = attr->value;
+ break;
+ default:
+ fprintf(stderr, "Unknown ref type attribute %02x\n", attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren)
+ fprintf(stderr, "Unexpected children for ref type\n");
+ *type = t;
+ return;
+ }
+ break;
+ case DW_TAG_volatile_type:
+ {
+ u32 typeref = 0;
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_type:
+ typeref = attr->value;
+ break;
+ default:
+ fprintf(stderr, "Unknown volatile attribute for type %02x\n",
+ attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren)
+ fprintf(stderr, "Unexpected children for volatile type\n");
+ *type = elfParseType(unit, typeref);
+ return;
+ }
+ break;
+ case DW_TAG_const_type:
+ {
+ u32 typeref = 0;
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_type:
+ typeref = attr->value;
+ break;
+ default:
+ fprintf(stderr, "Unknown const attribute for type %02x\n",
+ attr->name);
+ break;
+ }
+ }
+ if(abbrev->hasChildren)
+ fprintf(stderr, "Unexpected children for const type\n");
+ *type = elfParseType(unit, typeref);
+ return;
+ }
+ break;
+ case DW_TAG_enumeration_type:
+ {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+ t->type = TYPE_enum;
+ Enum *e = (Enum *)calloc(sizeof(Enum), 1);
+ t->enumeration = e;
+ elfAddType(t, unit, offset);
+ int count = 0;
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_name:
+ t->name = attr->string;
+ break;
+ case DW_AT_byte_size:
+ t->size = attr->value;
+ break;
+ case DW_AT_sibling:
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ break;
+ default:
+ fprintf(stderr, "Unknown enum attribute %02x\n", attr->name);
+ }
+ }
+ if(abbrev->hasChildren) {
+ int bytes;
+ u32 num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ while(num) {
+ ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
+
+ switch(abbr->tag) {
+ case DW_TAG_enumerator:
+ {
+ count++;
+ e->members = (EnumMember *)realloc(e->members,
+ count*sizeof(EnumMember));
+ EnumMember *m = &e->members[count-1];
+ for(int i = 0; i < abbr->numAttrs; i++) {
+ ELFAttr *attr = &abbr->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_name:
+ m->name = attr->string;
+ break;
+ case DW_AT_const_value:
+ m->value = attr->value;
+ break;
+ default:
+ fprintf(stderr, "Unknown sub param attribute %02x\n",
+ attr->name);
+ }
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown enum tag %02x\n", abbr->tag);
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ }
+ num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ }
+ }
+ e->count = count;
+ *type = t;
+ return;
+ }
+ break;
+ case DW_TAG_subroutine_type:
+ {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+ t->type = TYPE_function;
+ FunctionType *f = (FunctionType *)calloc(sizeof(FunctionType), 1);
+ t->function = f;
+ elfAddType(t, unit, offset);
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_prototyped:
+ case DW_AT_sibling:
+ break;
+ case DW_AT_type:
+ f->returnType = elfParseType(unit, attr->value);
+ break;
+ default:
+ fprintf(stderr, "Unknown subroutine attribute %02x\n", attr->name);
+ }
+ }
+ if(abbrev->hasChildren) {
+ int bytes;
+ u32 num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ Object *lastVar = NULL;
+ while(num) {
+ ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
+
+ switch(abbr->tag) {
+ case DW_TAG_formal_parameter:
+ {
+ Object *o;
+ data = elfParseObject(data, abbr, unit, &o);
+ if(f->args)
+ lastVar->next = o;
+ else
+ f->args = o;
+ lastVar = o;
+ }
+ break;
+ case DW_TAG_unspecified_parameters:
+ // no use in the debugger yet
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ CASE_TYPE_TAG:
+ // skip types... parsed only when used
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ default:
+ fprintf(stderr, "Unknown subroutine tag %02x\n", abbr->tag);
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ }
+ num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ }
+ }
+ *type = t;
+ return;
+ }
+ break;
+ case DW_TAG_array_type:
+ {
+ u32 typeref = 0;
+ int i;
+ Array *array = (Array *)calloc(sizeof(Array), 1);
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+ t->type = TYPE_array;
+ elfAddType(t, unit, offset);
+
+ for(i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_sibling:
+ break;
+ case DW_AT_type:
+ typeref = attr->value;
+ array->type = elfParseType(unit, typeref);
+ break;
+ default:
+ fprintf(stderr, "Unknown array attribute %02x\n", attr->name);
+ }
+ }
+ if(abbrev->hasChildren) {
+ int bytes;
+ u32 num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ int index = 0;
+ int maxBounds = 0;
+ while(num) {
+ ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num);
+
+ switch(abbr->tag) {
+ case DW_TAG_subrange_type:
+ {
+ if(maxBounds == index) {
+ maxBounds += 4;
+ array->bounds = (int *)realloc(array->bounds,
+ sizeof(int)*maxBounds);
+ }
+ for(int i = 0; i < abbr->numAttrs; i++) {
+ ELFAttr *attr = &abbr->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_upper_bound:
+ array->bounds[index] = attr->value+1;
+ break;
+ case DW_AT_type: // ignore
+ break;
+ default:
+ fprintf(stderr, "Unknown subrange attribute %02x\n",
+ attr->name);
+ }
+ }
+ index++;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown array tag %02x\n", abbr->tag);
+ data = elfSkipData(data, abbr, unit->abbrevs);
+ break;
+ }
+ num = elfReadLEB128(data, &bytes);
+ data += bytes;
+ }
+ array->maxBounds = index;
+ }
+ t->size = array->type->size;
+ for(i = 0; i < array->maxBounds; i++)
+ t->size *= array->bounds[i];
+ t->array = array;
+ *type = t;
+ return;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown type TAG %02x\n", abbrev->tag);
+ exit(-1);
+ }
+}
+
+Type *elfParseType(CompileUnit *unit, u32 offset)
+{
+ Type *t = unit->types;
+
+ while(t) {
+ if(t->offset == offset)
+ return t;
+ t = t->next;
+ }
+ if(offset == 0) {
+ Type *t = (Type *)calloc(sizeof(Type), 1);
+ t->type = TYPE_void;
+ t->offset = 0;
+ elfAddType(t, unit, 0);
+ return t;
+ }
+ u8 *data = unit->top + offset;
+ int bytes;
+ int abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+ Type *type = NULL;
+
+ ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+
+ elfParseType(data, offset, abbrev, unit, &type);
+ return type;
+}
+
+void elfGetObjectAttributes(CompileUnit *unit, u32 offset, Object *o)
+{
+ u8 *data = unit->top + offset;
+ int bytes;
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ return;
+ }
+
+ ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_location:
+ o->location = attr->block;
+ break;
+ case DW_AT_name:
+ if(o->name == NULL)
+ o->name = attr->string;
+ break;
+ case DW_AT_MIPS_linkage_name:
+ o->name = attr->string;
+ break;
+ case DW_AT_decl_file:
+ o->file = attr->value;
+ break;
+ case DW_AT_decl_line:
+ o->line = attr->value;
+ break;
+ case DW_AT_type:
+ o->type = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_external:
+ o->external = attr->flag;
+ break;
+ case DW_AT_const_value:
+ case DW_AT_abstract_origin:
+ case DW_AT_declaration:
+ case DW_AT_artificial:
+ // todo
+ break;
+ case DW_AT_specification:
+ // TODO:
+ break;
+ default:
+ fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
+ break;
+ }
+ }
+}
+
+u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
+ Object **object)
+{
+ Object *o = (Object *)calloc(sizeof(Object), 1);
+
+ o->next = NULL;
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_location:
+ o->location = attr->block;
+ break;
+ case DW_AT_name:
+ if(o->name == NULL)
+ o->name = attr->string;
+ break;
+ case DW_AT_MIPS_linkage_name:
+ o->name = attr->string;
+ break;
+ case DW_AT_decl_file:
+ o->file = attr->value;
+ break;
+ case DW_AT_decl_line:
+ o->line = attr->value;
+ break;
+ case DW_AT_type:
+ o->type = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_external:
+ o->external = attr->flag;
+ break;
+ case DW_AT_abstract_origin:
+ elfGetObjectAttributes(unit, attr->value, o);
+ break;
+ case DW_AT_const_value:
+ case DW_AT_declaration:
+ case DW_AT_artificial:
+ break;
+ case DW_AT_specification:
+ // TODO:
+ break;
+ default:
+ fprintf(stderr, "Unknown object attribute %02x\n", attr->name);
+ break;
+ }
+ }
+ *object = o;
+ return data;
+}
+
+u8 *elfParseBlock(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
+ Function *func, Object **lastVar)
+{
+ int bytes;
+ u32 start = func->lowPC;
+ u32 end = func->highPC;
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_sibling:
+ break;
+ case DW_AT_low_pc:
+ start = attr->value;
+ break;
+ case DW_AT_high_pc:
+ end = attr->value;
+ break;
+ case DW_AT_ranges: // ignore for now
+ break;
+ default:
+ fprintf(stderr, "Unknown block attribute %02x\n", attr->name);
+ break;
+ }
+ }
+
+ if(abbrev->hasChildren) {
+ int nesting = 1;
+
+ while(nesting) {
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ nesting--;
+ continue;
+ }
+
+ abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+
+ switch(abbrev->tag) {
+ CASE_TYPE_TAG: // types only parsed when used
+ case DW_TAG_label: // not needed
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ break;
+ case DW_TAG_lexical_block:
+ data = elfParseBlock(data, abbrev, unit, func, lastVar);
+ break;
+ case DW_TAG_subprogram:
+ {
+ Function *f = NULL;
+ data = elfParseFunction(data, abbrev, unit, &f);
+ if(f != NULL) {
+ if(unit->lastFunction)
+ unit->lastFunction->next = f;
+ else
+ unit->functions = f;
+ unit->lastFunction = f;
+ }
+ }
+ break;
+ case DW_TAG_variable:
+ {
+ Object *o;
+ data = elfParseObject(data, abbrev, unit, &o);
+ if(o->startScope == 0)
+ o->startScope = start;
+ if(o->endScope == 0)
+ o->endScope = 0;
+ if(func->variables)
+ (*lastVar)->next = o;
+ else
+ func->variables = o;
+ *lastVar = o;
+ }
+ break;
+ case DW_TAG_inlined_subroutine:
+ // TODO:
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ break;
+ default:
+ {
+ fprintf(stderr, "Unknown block TAG %02x\n", abbrev->tag);
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ }
+ break;
+ }
+ }
+ }
+ return data;
+}
+
+void elfGetFunctionAttributes(CompileUnit *unit, u32 offset, Function *func)
+{
+ u8 *data = unit->top + offset;
+ int bytes;
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ return;
+ }
+
+ ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+
+ switch(attr->name) {
+ case DW_AT_sibling:
+ break;
+ case DW_AT_name:
+ if(func->name == NULL)
+ func->name = attr->string;
+ break;
+ case DW_AT_MIPS_linkage_name:
+ func->name = attr->string;
+ break;
+ case DW_AT_low_pc:
+ func->lowPC = attr->value;
+ break;
+ case DW_AT_high_pc:
+ func->highPC = attr->value;
+ break;
+ case DW_AT_decl_file:
+ func->file = attr->value;
+ break;
+ case DW_AT_decl_line:
+ func->line = attr->value;
+ break;
+ case DW_AT_external:
+ func->external = attr->flag;
+ break;
+ case DW_AT_frame_base:
+ func->frameBase = attr->block;
+ break;
+ case DW_AT_type:
+ func->returnType = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_inline:
+ case DW_AT_specification:
+ case DW_AT_declaration:
+ case DW_AT_artificial:
+ case DW_AT_prototyped:
+ case DW_AT_proc_body:
+ case DW_AT_save_offset:
+ case DW_AT_user_2002:
+ case DW_AT_virtuality:
+ case DW_AT_containing_type:
+ case DW_AT_accessibility:
+ // todo;
+ break;
+ case DW_AT_vtable_elem_location:
+ free(attr->block);
+ break;
+ default:
+ fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
+ break;
+ }
+ }
+
+ return;
+}
+
+u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,
+ Function **f)
+{
+ Function *func = (Function *)calloc(sizeof(Function), 1);
+ *f = func;
+
+ int bytes;
+ bool mangled = false;
+ bool declaration = false;
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+ switch(attr->name) {
+ case DW_AT_sibling:
+ break;
+ case DW_AT_name:
+ if(func->name == NULL)
+ func->name = attr->string;
+ break;
+ case DW_AT_MIPS_linkage_name:
+ func->name = attr->string;
+ mangled = true;
+ break;
+ case DW_AT_low_pc:
+ func->lowPC = attr->value;
+ break;
+ case DW_AT_high_pc:
+ func->highPC = attr->value;
+ break;
+ case DW_AT_prototyped:
+ break;
+ case DW_AT_decl_file:
+ func->file = attr->value;
+ break;
+ case DW_AT_decl_line:
+ func->line = attr->value;
+ break;
+ case DW_AT_external:
+ func->external = attr->flag;
+ break;
+ case DW_AT_frame_base:
+ func->frameBase = attr->block;
+ break;
+ case DW_AT_type:
+ func->returnType = elfParseType(unit, attr->value);
+ break;
+ case DW_AT_abstract_origin:
+ elfGetFunctionAttributes(unit, attr->value, func);
+ break;
+ case DW_AT_declaration:
+ declaration = attr->flag;
+ break;
+ case DW_AT_inline:
+ case DW_AT_specification:
+ case DW_AT_artificial:
+ case DW_AT_proc_body:
+ case DW_AT_save_offset:
+ case DW_AT_user_2002:
+ case DW_AT_virtuality:
+ case DW_AT_containing_type:
+ case DW_AT_accessibility:
+ // todo;
+ break;
+ case DW_AT_vtable_elem_location:
+ free(attr->block);
+ break;
+ default:
+ fprintf(stderr, "Unknown function attribute %02x\n", attr->name);
+ break;
+ }
+ }
+
+ if(declaration) {
+ elfCleanUp(func);
+ free(func);
+ *f = NULL;
+
+ while(1) {
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ return data;
+ }
+
+ abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ }
+ }
+
+ if(abbrev->hasChildren) {
+ int nesting = 1;
+ Object *lastParam = NULL;
+ Object *lastVar = NULL;
+
+ while(nesting) {
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ nesting--;
+ continue;
+ }
+
+ abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+
+ switch(abbrev->tag) {
+ CASE_TYPE_TAG: // no need to parse types. only parsed when used
+ case DW_TAG_label: // not needed
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ break;
+ case DW_TAG_subprogram:
+ {
+ Function *fnc=NULL;
+ data = elfParseFunction(data, abbrev, unit, &fnc);
+ if(fnc != NULL) {
+ if(unit->lastFunction == NULL)
+ unit->functions = fnc;
+ else
+ unit->lastFunction->next = fnc;
+ unit->lastFunction = fnc;
+ }
+ }
+ break;
+ case DW_TAG_lexical_block:
+ {
+ data = elfParseBlock(data, abbrev, unit, func, &lastVar);
+ }
+ break;
+ case DW_TAG_formal_parameter:
+ {
+ Object *o;
+ data = elfParseObject(data, abbrev, unit, &o);
+ if(func->parameters)
+ lastParam->next = o;
+ else
+ func->parameters = o;
+ lastParam = o;
+ }
+ break;
+ case DW_TAG_variable:
+ {
+ Object *o;
+ data = elfParseObject(data, abbrev, unit, &o);
+ if(func->variables)
+ lastVar->next = o;
+ else
+ func->variables = o;
+ lastVar = o;
+ }
+ break;
+ case DW_TAG_unspecified_parameters:
+ case DW_TAG_inlined_subroutine:
+ {
+ // todo
+ for(int i = 0; i < abbrev->numAttrs; i++) {
+ data = elfReadAttribute(data, &abbrev->attrs[i]);
+ if(abbrev->attrs[i].form == DW_FORM_block1)
+ free(abbrev->attrs[i].block);
+ }
+
+ if(abbrev->hasChildren)
+ nesting++;
+ }
+ break;
+ default:
+ {
+ fprintf(stderr, "Unknown function TAG %02x\n", abbrev->tag);
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ }
+ break;
+ }
+ }
+ }
+ return data;
+}
+
+u8 *elfParseUnknownData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)
+{
+ int i;
+ int bytes;
+ // switch(abbrev->tag) {
+ // default:
+ fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
+
+ for(i = 0; i < abbrev->numAttrs; i++) {
+ data = elfReadAttribute(data, &abbrev->attrs[i]);
+ if(abbrev->attrs[i].form == DW_FORM_block1)
+ free(abbrev->attrs[i].block);
+ }
+
+ if(abbrev->hasChildren) {
+ int nesting = 1;
+ while(nesting) {
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ if(!abbrevNum) {
+ nesting--;
+ continue;
+ }
+
+ abbrev = elfGetAbbrev(abbrevs, abbrevNum);
+
+ fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);
+
+ for(i = 0; i < abbrev->numAttrs; i++) {
+ data = elfReadAttribute(data, &abbrev->attrs[i]);
+ if(abbrev->attrs[i].form == DW_FORM_block1)
+ free(abbrev->attrs[i].block);
+ }
+
+ if(abbrev->hasChildren) {
+ nesting++;
+ }
+ }
+ }
+ // }
+ return data;
+}
+
+u8 *elfParseCompileUnitChildren(u8 *data, CompileUnit *unit)
+{
+ int bytes;
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+ Object *lastObj = NULL;
+ while(abbrevNum) {
+ ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);
+ switch(abbrev->tag) {
+ case DW_TAG_subprogram:
+ {
+ Function *func = NULL;
+ data = elfParseFunction(data, abbrev, unit, &func);
+ if(func != NULL) {
+ if(unit->lastFunction)
+ unit->lastFunction->next = func;
+ else
+ unit->functions = func;
+ unit->lastFunction = func;
+ }
+ }
+ break;
+ CASE_TYPE_TAG:
+ data = elfSkipData(data, abbrev, unit->abbrevs);
+ break;
+ case DW_TAG_variable:
+ {
+ Object *var = NULL;
+ data = elfParseObject(data, abbrev, unit, &var);
+ if(lastObj)
+ lastObj->next = var;
+ else
+ unit->variables = var;
+ lastObj = var;
+ }
+ break;
+ default:
+ data = elfParseUnknownData(data, abbrev, unit->abbrevs);
+ break;
+ }
+
+ abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+ }
+ return data;
+}
+
+
+CompileUnit *elfParseCompUnit(u8 *data, u8 *abbrevData)
+{
+ int bytes;
+ u8 *top = data;
+
+ u32 length = elfRead4Bytes(data);
+ data += 4;
+
+ u16 version = elfRead2Bytes(data);
+ data += 2;
+
+ u32 offset = elfRead4Bytes(data);
+ data += 4;
+
+ u8 addrSize = *data++;
+
+ if(version != 2) {
+ fprintf(stderr, "Unsupported debugging information version %d\n", version);
+ return NULL;
+ }
+
+ if(addrSize != 4) {
+ fprintf(stderr, "Unsupported address size %d\n", addrSize);
+ return NULL;
+ }
+
+ ELFAbbrev **abbrevs = elfReadAbbrevs(abbrevData, offset);
+
+ u32 abbrevNum = elfReadLEB128(data, &bytes);
+ data += bytes;
+
+ ELFAbbrev *abbrev = elfGetAbbrev(abbrevs, abbrevNum);
+
+ CompileUnit *unit = (CompileUnit *)calloc(sizeof(CompileUnit), 1);
+ unit->top = top;
+ unit->length = length;
+ unit->abbrevs = abbrevs;
+ unit->next = NULL;
+
+ elfCurrentUnit = unit;
+
+ int i;
+
+ for(i = 0; i < abbrev->numAttrs; i++) {
+ ELFAttr *attr = &abbrev->attrs[i];
+ data = elfReadAttribute(data, attr);
+
+ switch(attr->name) {
+ case DW_AT_name:
+ unit->name = attr->string;
+ break;
+ case DW_AT_stmt_list:
+ unit->hasLineInfo = true;
+ unit->lineInfo = attr->value;
+ break;
+ case DW_AT_low_pc:
+ unit->lowPC = attr->value;
+ break;
+ case DW_AT_high_pc:
+ unit->highPC = attr->value;
+ break;
+ case DW_AT_compdir:
+ unit->compdir = attr->string;
+ break;
+ // ignore
+ case DW_AT_language:
+ case DW_AT_producer:
+ case DW_AT_macro_info:
+ case DW_AT_entry_pc:
+ break;
+ default:
+ fprintf(stderr, "Unknown attribute %02x\n", attr->name);
+ break;
+ }
+ }
+
+ if(abbrev->hasChildren)
+ elfParseCompileUnitChildren(data, unit);
+
+ return unit;
+}
+
+void elfParseAranges(u8 *data)
+{
+ ELFSectionHeader *sh = elfGetSectionByName(".debug_aranges");
+ if(sh == NULL) {
+ fprintf(stderr, "No aranges found\n");
+ return;
+ }
+
+ data = elfReadSection(data, sh);
+ u8 *end = data + READ32LE(&sh->size);
+
+ int max = 4;
+ ARanges *ranges = (ARanges *)calloc(sizeof(ARanges), 4);
+
+ int index = 0;
+
+ while(data < end) {
+ u32 len = elfRead4Bytes(data);
+ data += 4;
+ // u16 version = elfRead2Bytes(data);
+ data += 2;
+ u32 offset = elfRead4Bytes(data);
+ data += 4;
+ // u8 addrSize = *data++;
+ // u8 segSize = *data++;
+ data += 2; // remove if uncommenting above
+ data += 4;
+ ranges[index].count = (len-20)/8;
+ ranges[index].offset = offset;
+ ranges[index].ranges = (ARange *)calloc(sizeof(ARange), (len-20)/8);
+ int i = 0;
+ while(true) {
+ u32 addr = elfRead4Bytes(data);
+ data += 4;
+ u32 len = elfRead4Bytes(data);
+ data += 4;
+ if(addr == 0 && len == 0)
+ break;
+ ranges[index].ranges[i].lowPC = addr;
+ ranges[index].ranges[i].highPC = addr+len;
+ i++;
+ }
+ index++;
+ if(index == max) {
+ max += 4;
+ ranges = (ARanges *)realloc(ranges, max*sizeof(ARanges));
+ }
+ }
+ elfDebugInfo->numRanges = index;
+ elfDebugInfo->ranges = ranges;
+}
+
+void elfReadSymtab(u8 *data)
+{
+ ELFSectionHeader *sh = elfGetSectionByName(".symtab");
+ int table = READ32LE(&sh->link);
+
+ char *strtable = (char *)elfReadSection(data, elfGetSectionByNumber(table));
+
+ ELFSymbol *symtab = (ELFSymbol *)elfReadSection(data, sh);
+
+ int count = READ32LE(&sh->size) / sizeof(ELFSymbol);
+ elfSymbolsCount = 0;
+
+ elfSymbols = (Symbol *)malloc(sizeof(Symbol)*count);
+
+ int i;
+
+ for(i = 0; i < count; i++) {
+ ELFSymbol *s = &symtab[i];
+ int type = s->info & 15;
+ int binding = s->info >> 4;
+
+ if(binding) {
+ Symbol *sym = &elfSymbols[elfSymbolsCount];
+ sym->name = &strtable[READ32LE(&s->name)];
+ sym->binding = binding;
+ sym->type = type;
+ sym->value = READ32LE(&s->value);
+ sym->size = READ32LE(&s->size);
+ elfSymbolsCount++;
+ }
+ }
+ for(i = 0; i < count; i++) {
+ ELFSymbol *s = &symtab[i];
+ int bind = s->info>>4;
+ int type = s->info & 15;
+
+ if(!bind) {
+ Symbol *sym = &elfSymbols[elfSymbolsCount];
+ sym->name = &strtable[READ32LE(&s->name)];
+ sym->binding = (s->info >> 4);
+ sym->type = type;
+ sym->value = READ32LE(&s->value);
+ sym->size = READ32LE(&s->size);
+ elfSymbolsCount++;
+ }
+ }
+ elfSymbolsStrTab = strtable;
+ // free(symtab);
+}
+
+bool elfReadProgram(ELFHeader *eh, u8 *data, int& size, bool parseDebug)
+{
+ int count = READ16LE(&eh->e_phnum);
+ int i;
+
+ if(READ32LE(&eh->e_entry) == 0x2000000)
+ cpuIsMultiBoot = true;
+
+ // read program headers... should probably move this code down
+ u8 *p = data + READ32LE(&eh->e_phoff);
+ size = 0;
+ for(i = 0; i < count; i++) {
+ ELFProgramHeader *ph = (ELFProgramHeader *)p;
+ p += sizeof(ELFProgramHeader);
+ if(READ16LE(&eh->e_phentsize) != sizeof(ELFProgramHeader)) {
+ p += READ16LE(&eh->e_phentsize) - sizeof(ELFProgramHeader);
+ }
+
+ // printf("PH %d %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ // i, ph->type, ph->offset, ph->vaddr, ph->paddr,
+ // ph->filesz, ph->memsz, ph->flags, ph->align);
+ if(cpuIsMultiBoot) {
+ if(READ32LE(&ph->paddr) >= 0x2000000 &&
+ READ32LE(&ph->paddr) <= 0x203ffff) {
+ memcpy(&workRAM[READ32LE(&ph->paddr) & 0x3ffff],
+ data + READ32LE(&ph->offset),
+ READ32LE(&ph->filesz));
+ size += READ32LE(&ph->filesz);
+ }
+ } else {
+ if(READ32LE(&ph->paddr) >= 0x8000000 &&
+ READ32LE(&ph->paddr) <= 0x9ffffff) {
+ memcpy(&rom[READ32LE(&ph->paddr) & 0x1ffffff],
+ data + READ32LE(&ph->offset),
+ READ32LE(&ph->filesz));
+ size += READ32LE(&ph->filesz);
+ }
+ }
+ }
+
+ char *stringTable = NULL;
+
+ // read section headers
+ p = data + READ32LE(&eh->e_shoff);
+ count = READ16LE(&eh->e_shnum);
+
+ ELFSectionHeader **sh = (ELFSectionHeader **)
+ malloc(sizeof(ELFSectionHeader *) * count);
+
+ for(i = 0; i < count; i++) {
+ sh[i] = (ELFSectionHeader *)p;
+ p += sizeof(ELFSectionHeader);
+ if(READ16LE(&eh->e_shentsize) != sizeof(ELFSectionHeader))
+ p += READ16LE(&eh->e_shentsize) - sizeof(ELFSectionHeader);
+ }
+
+ if(READ16LE(&eh->e_shstrndx) != 0) {
+ stringTable = (char *)elfReadSection(data,
+ sh[READ16LE(&eh->e_shstrndx)]);
+ }
+
+ elfSectionHeaders = sh;
+ elfSectionHeadersStringTable = stringTable;
+ elfSectionHeadersCount = count;
+
+ for(i = 0; i < count; i++) {
+ // printf("SH %d %-20s %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ // i, &stringTable[sh[i]->name], sh[i]->name, sh[i]->type,
+ // sh[i]->flags, sh[i]->addr, sh[i]->offset, sh[i]->size,
+ // sh[i]->link, sh[i]->info);
+ if(READ32LE(&sh[i]->flags) & 2) { // load section
+ if(cpuIsMultiBoot) {
+ if(READ32LE(&sh[i]->addr) >= 0x2000000 &&
+ READ32LE(&sh[i]->addr) <= 0x203ffff) {
+ memcpy(&workRAM[READ32LE(&sh[i]->addr) & 0x3ffff], data +
+ READ32LE(&sh[i]->offset),
+ READ32LE(&sh[i]->size));
+ size += READ32LE(&sh[i]->size);
+ }
+ } else {
+ if(READ32LE(&sh[i]->addr) >= 0x8000000 &&
+ READ32LE(&sh[i]->addr) <= 0x9ffffff) {
+ memcpy(&rom[READ32LE(&sh[i]->addr) & 0x1ffffff],
+ data + READ32LE(&sh[i]->offset),
+ READ32LE(&sh[i]->size));
+ size += READ32LE(&sh[i]->size);
+ }
+ }
+ }
+ }
+
+ if(parseDebug) {
+ fprintf(stderr, "Parsing debug info\n");
+
+ ELFSectionHeader *dbgHeader = elfGetSectionByName(".debug_info");
+ if(dbgHeader == NULL) {
+ fprintf(stderr, "Cannot find debug information\n");
+ goto end;
+ }
+
+ ELFSectionHeader *h = elfGetSectionByName(".debug_abbrev");
+ if(h == NULL) {
+ fprintf(stderr, "Cannot find abbreviation table\n");
+ goto end;
+ }
+
+ elfDebugInfo = (DebugInfo *)calloc(sizeof(DebugInfo), 1);
+ u8 *abbrevdata = elfReadSection(data, h);
+
+ h = elfGetSectionByName(".debug_str");
+
+ if(h == NULL)
+ elfDebugStrings = NULL;
+ else
+ elfDebugStrings = (char *)elfReadSection(data, h);
+
+ u8 *debugdata = elfReadSection(data, dbgHeader);
+
+ elfDebugInfo->debugdata = data;
+ elfDebugInfo->infodata = debugdata;
+
+ u32 total = READ32LE(&dbgHeader->size);
+ u8 *end = debugdata + total;
+ u8 *ddata = debugdata;
+
+ CompileUnit *last = NULL;
+ CompileUnit *unit = NULL;
+
+ while(ddata < end) {
+ unit = elfParseCompUnit(ddata, abbrevdata);
+ unit->offset = (u32)(ddata-debugdata);
+ elfParseLineInfo(unit, data);
+ if(last == NULL)
+ elfCompileUnits = unit;
+ else
+ last->next = unit;
+ last = unit;
+ ddata += 4 + unit->length;
+ }
+ elfParseAranges(data);
+ CompileUnit *comp = elfCompileUnits;
+ while(comp) {
+ ARanges *r = elfDebugInfo->ranges;
+ for(int i = 0; i < elfDebugInfo->numRanges; i++)
+ if(r[i].offset == comp->offset) {
+ comp->ranges = &r[i];
+ break;
+ }
+ comp = comp->next;
+ }
+ elfParseCFA(data);
+ elfReadSymtab(data);
+ }
+ end:
+ if(sh) {
+ free(sh);
+ }
+
+ elfSectionHeaders = NULL;
+ elfSectionHeadersStringTable = NULL;
+ elfSectionHeadersCount = 0;
+
+ return true;
+}
+
+extern bool parseDebug;
+
+bool elfRead(const char *name, int& siz, FILE *f)
+{
+ fseek(f, 0, SEEK_END);
+ long size = ftell(f);
+ elfFileData = (u8 *)malloc(size);
+ fseek(f, 0, SEEK_SET);
+ fread(elfFileData, 1, size, f);
+ fclose(f);
+
+ ELFHeader *header = (ELFHeader *)elfFileData;
+
+ if(READ32LE(&header->magic) != 0x464C457F ||
+ READ16LE(&header->e_machine) != 40 ||
+ header->clazz != 1) {
+ systemMessage(0, N_("Not a valid ELF file %s"), name);
+ free(elfFileData);
+ elfFileData = NULL;
+ return false;
+ }
+
+ if(!elfReadProgram(header, elfFileData, siz, parseDebug)) {
+ free(elfFileData);
+ elfFileData = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+void elfCleanUp(Object *o)
+{
+ free(o->location);
+}
+
+void elfCleanUp(Function *func)
+{
+ Object *o = func->parameters;
+ while(o) {
+ elfCleanUp(o);
+ Object *next = o->next;
+ free(o);
+ o = next;
+ }
+
+ o = func->variables;
+ while(o) {
+ elfCleanUp(o);
+ Object *next = o->next;
+ free(o);
+ o = next;
+ }
+ free(func->frameBase);
+}
+
+void elfCleanUp(ELFAbbrev **abbrevs)
+{
+ for(int i = 0; i < 121; i++) {
+ ELFAbbrev *abbrev = abbrevs[i];
+
+ while(abbrev) {
+ free(abbrev->attrs);
+ ELFAbbrev *next = abbrev->next;
+ free(abbrev);
+
+ abbrev = next;
+ }
+ }
+}
+
+void elfCleanUp(Type *t)
+{
+ switch(t->type) {
+ case TYPE_function:
+ if(t->function) {
+ Object *o = t->function->args;
+ while(o) {
+ elfCleanUp(o);
+ Object *next = o->next;
+ free(o);
+ o = next;
+ }
+ free(t->function);
+ }
+ break;
+ case TYPE_array:
+ if(t->array) {
+ free(t->array->bounds);
+ free(t->array);
+ }
+ break;
+ case TYPE_struct:
+ case TYPE_union:
+ if(t->structure) {
+ for(int i = 0; i < t->structure->memberCount; i++) {
+ free(t->structure->members[i].location);
+ }
+ free(t->structure->members);
+ free(t->structure);
+ }
+ break;
+ case TYPE_enum:
+ if(t->enumeration) {
+ free(t->enumeration->members);
+ free(t->enumeration);
+ }
+ break;
+ case TYPE_base:
+ case TYPE_pointer:
+ case TYPE_void:
+ case TYPE_reference:
+ break; // nothing to do
+ }
+}
+
+void elfCleanUp(CompileUnit *comp)
+{
+ elfCleanUp(comp->abbrevs);
+ free(comp->abbrevs);
+ Function *func = comp->functions;
+ while(func) {
+ elfCleanUp(func);
+ Function *next = func->next;
+ free(func);
+ func = next;
+ }
+ Type *t = comp->types;
+ while(t) {
+ elfCleanUp(t);
+ Type *next = t->next;
+ free(t);
+ t = next;
+ }
+ Object *o = comp->variables;
+ while(o) {
+ elfCleanUp(o);
+ Object *next = o->next;
+ free(o);
+ o = next;
+ }
+ if(comp->lineInfoTable) {
+ free(comp->lineInfoTable->lines);
+ free(comp->lineInfoTable->files);
+ free(comp->lineInfoTable);
+ }
+}
+
+void elfCleanUp()
+{
+ CompileUnit *comp = elfCompileUnits;
+
+ while(comp) {
+ elfCleanUp(comp);
+ CompileUnit *next = comp->next;
+ free(comp);
+ comp = next;
+ }
+ elfCompileUnits = NULL;
+ free(elfSymbols);
+ elfSymbols = NULL;
+ // free(elfSymbolsStrTab);
+ elfSymbolsStrTab = NULL;
+
+ elfDebugStrings = NULL;
+ if(elfDebugInfo) {
+ int num = elfDebugInfo->numRanges;
+ int i;
+ for(i = 0; i < num; i++) {
+ free(elfDebugInfo->ranges[i].ranges);
+ }
+ free(elfDebugInfo->ranges);
+ free(elfDebugInfo);
+ elfDebugInfo = NULL;
+ }
+
+ if(elfFdes) {
+ if(elfFdeCount) {
+ for(int i = 0; i < elfFdeCount; i++)
+ free(elfFdes[i]);
+ }
+ free(elfFdes);
+
+ elfFdes = NULL;
+ elfFdeCount = 0;
+ }
+
+ ELFcie *cie = elfCies;
+ while(cie) {
+ ELFcie *next = cie->next;
+ free(cie);
+ cie = next;
+ }
+ elfCies = NULL;
+
+ if(elfFileData) {
+ free(elfFileData);
+ elfFileData = NULL;
+ }
+}
diff --git a/src/gb/GB.cpp b/src/gb/GB.cpp
index 55563e56..4536c2db 100644
--- a/src/gb/GB.cpp
+++ b/src/gb/GB.cpp
@@ -1,3217 +1,5442 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-#include
-#include
-
-#include "../System.h"
-#include "../NLS.h"
-#include "GB.h"
-#include "gbCheats.h"
-#include "gbGlobals.h"
-#include "gbMemory.h"
-#include "gbSGB.h"
-#include "gbSound.h"
-#include "../unzip.h"
-#include "../Util.h"
-
-#ifdef __GNUC__
-#define _stricmp strcasecmp
-#endif
-
-extern u8 *pix;
-extern bool speedup;
-
-bool gbUpdateSizes();
-
-// debugging
-bool memorydebug = false;
-char gbBuffer[2048];
-
-extern u16 gbLineMix[160];
-
-// mappers
-void (*mapper)(u16,u8) = NULL;
-void (*mapperRAM)(u16,u8) = NULL;
-u8 (*mapperReadRAM)(u16) = NULL;
-
-// registers
-gbRegister PC;
-gbRegister SP;
-gbRegister AF;
-gbRegister BC;
-gbRegister DE;
-gbRegister HL;
-u16 IFF;
-// 0xff04
-u8 register_DIV = 0;
-// 0xff05
-u8 register_TIMA = 0;
-// 0xff06
-u8 register_TMA = 0;
-// 0xff07
-u8 register_TAC = 0;
-// 0xff0f
-u8 register_IF = 0;
-// 0xff40
-u8 register_LCDC = 0;
-// 0xff41
-u8 register_STAT = 0;
-// 0xff42
-u8 register_SCY = 0;
-// 0xff43
-u8 register_SCX = 0;
-// 0xff44
-u8 register_LY = 0;
-// 0xff45
-u8 register_LYC = 0;
-// 0xff46
-u8 register_DMA = 0;
-// 0xff4a
-u8 register_WY = 0;
-// 0xff4b
-u8 register_WX = 0;
-// 0xff4f
-u8 register_VBK = 0;
-// 0xff51
-u8 register_HDMA1 = 0;
-// 0xff52
-u8 register_HDMA2 = 0;
-// 0xff53
-u8 register_HDMA3 = 0;
-// 0xff54
-u8 register_HDMA4 = 0;
-// 0xff55
-u8 register_HDMA5 = 0;
-// 0xff70
-u8 register_SVBK = 0;
-// 0xffff
-u8 register_IE = 0;
-
-// ticks definition
-int GBDIV_CLOCK_TICKS = 64;
-int GBLCD_MODE_0_CLOCK_TICKS = 51;
-int GBLCD_MODE_1_CLOCK_TICKS = 1140;
-int GBLCD_MODE_2_CLOCK_TICKS = 20;
-int GBLCD_MODE_3_CLOCK_TICKS = 43;
-int GBLY_INCREMENT_CLOCK_TICKS = 114;
-int GBTIMER_MODE_0_CLOCK_TICKS = 256;
-int GBTIMER_MODE_1_CLOCK_TICKS = 4;
-int GBTIMER_MODE_2_CLOCK_TICKS = 16;
-int GBTIMER_MODE_3_CLOCK_TICKS = 64;
-int GBSERIAL_CLOCK_TICKS = 128;
-int GBSYNCHRONIZE_CLOCK_TICKS = 52920;
-
-// state variables
-
-// interrupt
-int gbInterrupt = 0;
-int gbInterruptWait = 0;
-// serial
-int gbSerialOn = 0;
-int gbSerialTicks = 0;
-int gbSerialBits = 0;
-// timer
-int gbTimerOn = 0;
-int gbTimerTicks = 0;
-int gbTimerClockTicks = 0;
-int gbTimerMode = 0;
-// lcd
-int gbLcdMode = 2;
-int gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS;
-int gbLcdLYIncrementTicks = 0;
-// div
-int gbDivTicks = GBDIV_CLOCK_TICKS;
-// cgb
-int gbVramBank = 0;
-int gbWramBank = 1;
-int gbHdmaSource = 0x0000;
-int gbHdmaDestination = 0x8000;
-int gbHdmaBytes = 0x0000;
-int gbHdmaOn = 0;
-int gbSpeed = 0;
-// frame counting
-int gbFrameCount = 0;
-int gbFrameSkip = 0;
-int gbFrameSkipCount = 0;
-// timing
-u32 gbLastTime = 0;
-u32 gbElapsedTime = 0;
-u32 gbTimeNow = 0;
-int gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS;
-// emulator features
-int gbBattery = 0;
-int gbCaptureNumber = 0;
-bool gbCapture = false;
-bool gbCapturePrevious = false;
-int gbJoymask[4] = { 0, 0, 0, 0 };
-
-int gbRomSizes[] = { 0x00008000, // 32K
- 0x00010000, // 64K
- 0x00020000, // 128K
- 0x00040000, // 256K
- 0x00080000, // 512K
- 0x00100000, // 1024K
- 0x00200000, // 2048K
- 0x00400000, // 4096K
- 0x00800000 // 8192K
-};
-int gbRomSizesMasks[] = { 0x00007fff,
- 0x0000ffff,
- 0x0001ffff,
- 0x0003ffff,
- 0x0007ffff,
- 0x000fffff,
- 0x001fffff,
- 0x003fffff,
- 0x007fffff
-};
-
-int gbRamSizes[6] = { 0x00000000, // 0K
- 0x00000800, // 2K
- 0x00002000, // 8K
- 0x00008000, // 32K
- 0x00020000, // 128K
- 0x00010000 // 64K
-};
-
-int gbRamSizesMasks[6] = { 0x00000000,
- 0x000007ff,
- 0x00001fff,
- 0x00007fff,
- 0x0001ffff,
- 0x0000ffff
-};
-
-int gbCycles[] = {
-// 0 1 2 3 4 5 6 7 8 9 a b c d e f
- 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0
- 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1
- 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2
- 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6
- 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a
- 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b
- 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c
- 2, 3, 3, 0, 3, 4, 2, 4, 2, 4, 3, 0, 3, 0, 2, 4, // d
- 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4, // e
- 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4 // f
-};
-
-int gbCyclesCB[] = {
-// 0 1 2 3 4 5 6 7 8 9 a b c d e f
- 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0
- 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1
- 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2
- 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 8
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 9
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // a
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // b
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // c
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // d
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // e
- 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2 // f
-};
-
-u16 DAATable[] = {
- 0x0080,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,
- 0x0800,0x0900,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520,
- 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700,
- 0x1800,0x1900,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,
- 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700,
- 0x2800,0x2900,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,
- 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x3600,0x3700,
- 0x3800,0x3900,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520,
- 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,
- 0x4800,0x4900,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520,
- 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700,
- 0x5800,0x5900,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,
- 0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,
- 0x6800,0x6900,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,
- 0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x7600,0x7700,
- 0x7800,0x7900,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520,
- 0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x8600,0x8700,
- 0x8800,0x8900,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520,
- 0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x9600,0x9700,
- 0x9800,0x9900,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
- 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710,
- 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
- 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
- 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
- 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710,
- 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
- 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710,
- 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
- 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710,
- 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
- 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
- 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
- 0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,0x6610,0x6710,
- 0x6810,0x6910,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,
- 0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,0x7610,0x7710,
- 0x7810,0x7910,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530,
- 0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,0x8610,0x8710,
- 0x8810,0x8910,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530,
- 0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,0x9610,0x9710,
- 0x9810,0x9910,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530,
- 0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,0xA610,0xA710,
- 0xA810,0xA910,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530,
- 0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,0xB610,0xB710,
- 0xB810,0xB910,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530,
- 0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,0xC610,0xC710,
- 0xC810,0xC910,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530,
- 0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,0xD610,0xD710,
- 0xD810,0xD910,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530,
- 0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,0xE610,0xE710,
- 0xE810,0xE910,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530,
- 0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,0xF610,0xF710,
- 0xF810,0xF910,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
- 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710,
- 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
- 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
- 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
- 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710,
- 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
- 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710,
- 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
- 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710,
- 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
- 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
- 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
- 0x0600,0x0700,0x0800,0x0900,0x0A00,0x0B00,0x0C00,0x0D00,
- 0x0E00,0x0F00,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520,
- 0x1600,0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00,
- 0x1E00,0x1F00,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,
- 0x2600,0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2C00,0x2D00,
- 0x2E00,0x2F00,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,
- 0x3600,0x3700,0x3800,0x3900,0x3A00,0x3B00,0x3C00,0x3D00,
- 0x3E00,0x3F00,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520,
- 0x4600,0x4700,0x4800,0x4900,0x4A00,0x4B00,0x4C00,0x4D00,
- 0x4E00,0x4F00,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520,
- 0x5600,0x5700,0x5800,0x5900,0x5A00,0x5B00,0x5C00,0x5D00,
- 0x5E00,0x5F00,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,
- 0x6600,0x6700,0x6800,0x6900,0x6A00,0x6B00,0x6C00,0x6D00,
- 0x6E00,0x6F00,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,
- 0x7600,0x7700,0x7800,0x7900,0x7A00,0x7B00,0x7C00,0x7D00,
- 0x7E00,0x7F00,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520,
- 0x8600,0x8700,0x8800,0x8900,0x8A00,0x8B00,0x8C00,0x8D00,
- 0x8E00,0x8F00,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520,
- 0x9600,0x9700,0x9800,0x9900,0x9A00,0x9B00,0x9C00,0x9D00,
- 0x9E00,0x9F00,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
- 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10,
- 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
- 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10,
- 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
- 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10,
- 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
- 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10,
- 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
- 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10,
- 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
- 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10,
- 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
- 0x6610,0x6710,0x6810,0x6910,0x6A10,0x6B10,0x6C10,0x6D10,
- 0x6E10,0x6F10,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,
- 0x7610,0x7710,0x7810,0x7910,0x7A10,0x7B10,0x7C10,0x7D10,
- 0x7E10,0x7F10,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530,
- 0x8610,0x8710,0x8810,0x8910,0x8A10,0x8B10,0x8C10,0x8D10,
- 0x8E10,0x8F10,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530,
- 0x9610,0x9710,0x9810,0x9910,0x9A10,0x9B10,0x9C10,0x9D10,
- 0x9E10,0x9F10,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530,
- 0xA610,0xA710,0xA810,0xA910,0xAA10,0xAB10,0xAC10,0xAD10,
- 0xAE10,0xAF10,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530,
- 0xB610,0xB710,0xB810,0xB910,0xBA10,0xBB10,0xBC10,0xBD10,
- 0xBE10,0xBF10,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530,
- 0xC610,0xC710,0xC810,0xC910,0xCA10,0xCB10,0xCC10,0xCD10,
- 0xCE10,0xCF10,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530,
- 0xD610,0xD710,0xD810,0xD910,0xDA10,0xDB10,0xDC10,0xDD10,
- 0xDE10,0xDF10,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530,
- 0xE610,0xE710,0xE810,0xE910,0xEA10,0xEB10,0xEC10,0xED10,
- 0xEE10,0xEF10,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530,
- 0xF610,0xF710,0xF810,0xF910,0xFA10,0xFB10,0xFC10,0xFD10,
- 0xFE10,0xFF10,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
- 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10,
- 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
- 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10,
- 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
- 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10,
- 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
- 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10,
- 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
- 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10,
- 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
- 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10,
- 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
- 0x00C0,0x0140,0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,
- 0x0840,0x0940,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940,
- 0x1040,0x1140,0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,
- 0x1840,0x1940,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940,
- 0x2040,0x2140,0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,
- 0x2840,0x2940,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940,
- 0x3040,0x3140,0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,
- 0x3840,0x3940,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940,
- 0x4040,0x4140,0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,
- 0x4840,0x4940,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940,
- 0x5040,0x5140,0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,
- 0x5840,0x5940,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940,
- 0x6040,0x6140,0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,
- 0x6840,0x6940,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940,
- 0x7040,0x7140,0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,
- 0x7840,0x7940,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940,
- 0x8040,0x8140,0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,
- 0x8840,0x8940,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940,
- 0x9040,0x9140,0x9240,0x9340,0x9440,0x9540,0x9640,0x9740,
- 0x9840,0x9940,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
- 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,
- 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
- 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,
- 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
- 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,
- 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
- 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,
- 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
- 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,
- 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
- 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,
- 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
- 0xA050,0xA150,0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,
- 0xA850,0xA950,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950,
- 0xB050,0xB150,0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,
- 0xB850,0xB950,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950,
- 0xC050,0xC150,0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,
- 0xC850,0xC950,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950,
- 0xD050,0xD150,0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,
- 0xD850,0xD950,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950,
- 0xE050,0xE150,0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,
- 0xE850,0xE950,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950,
- 0xF050,0xF150,0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,
- 0xF850,0xF950,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950,
- 0x00D0,0x0150,0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,
- 0x0850,0x0950,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950,
- 0x1050,0x1150,0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,
- 0x1850,0x1950,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950,
- 0x2050,0x2150,0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,
- 0x2850,0x2950,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950,
- 0x3050,0x3150,0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,
- 0x3850,0x3950,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
- 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,
- 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
- 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,
- 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
- 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,
- 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
- 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,
- 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
- 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,
- 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
- 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,
- 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
- 0xFA60,0xFB60,0xFC60,0xFD60,0xFE60,0xFF60,0x00C0,0x0140,
- 0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940,
- 0x0A60,0x0B60,0x0C60,0x0D60,0x0E60,0x0F60,0x1040,0x1140,
- 0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940,
- 0x1A60,0x1B60,0x1C60,0x1D60,0x1E60,0x1F60,0x2040,0x2140,
- 0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940,
- 0x2A60,0x2B60,0x2C60,0x2D60,0x2E60,0x2F60,0x3040,0x3140,
- 0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940,
- 0x3A60,0x3B60,0x3C60,0x3D60,0x3E60,0x3F60,0x4040,0x4140,
- 0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940,
- 0x4A60,0x4B60,0x4C60,0x4D60,0x4E60,0x4F60,0x5040,0x5140,
- 0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940,
- 0x5A60,0x5B60,0x5C60,0x5D60,0x5E60,0x5F60,0x6040,0x6140,
- 0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940,
- 0x6A60,0x6B60,0x6C60,0x6D60,0x6E60,0x6F60,0x7040,0x7140,
- 0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940,
- 0x7A60,0x7B60,0x7C60,0x7D60,0x7E60,0x7F60,0x8040,0x8140,
- 0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940,
- 0x8A60,0x8B60,0x8C60,0x8D60,0x8E60,0x8F60,0x9040,0x9140,
- 0x9240,0x9340,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
- 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150,
- 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
- 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150,
- 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
- 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150,
- 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
- 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150,
- 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
- 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150,
- 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
- 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150,
- 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
- 0x9A70,0x9B70,0x9C70,0x9D70,0x9E70,0x9F70,0xA050,0xA150,
- 0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950,
- 0xAA70,0xAB70,0xAC70,0xAD70,0xAE70,0xAF70,0xB050,0xB150,
- 0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950,
- 0xBA70,0xBB70,0xBC70,0xBD70,0xBE70,0xBF70,0xC050,0xC150,
- 0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950,
- 0xCA70,0xCB70,0xCC70,0xCD70,0xCE70,0xCF70,0xD050,0xD150,
- 0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950,
- 0xDA70,0xDB70,0xDC70,0xDD70,0xDE70,0xDF70,0xE050,0xE150,
- 0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950,
- 0xEA70,0xEB70,0xEC70,0xED70,0xEE70,0xEF70,0xF050,0xF150,
- 0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950,
- 0xFA70,0xFB70,0xFC70,0xFD70,0xFE70,0xFF70,0x00D0,0x0150,
- 0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950,
- 0x0A70,0x0B70,0x0C70,0x0D70,0x0E70,0x0F70,0x1050,0x1150,
- 0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950,
- 0x1A70,0x1B70,0x1C70,0x1D70,0x1E70,0x1F70,0x2050,0x2150,
- 0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950,
- 0x2A70,0x2B70,0x2C70,0x2D70,0x2E70,0x2F70,0x3050,0x3150,
- 0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
- 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150,
- 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
- 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150,
- 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
- 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150,
- 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
- 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150,
- 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
- 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150,
- 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
- 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150,
- 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
-};
-
-u8 ZeroTable[] = {
- 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0
-};
-
-#define GBSAVE_GAME_VERSION_1 1
-#define GBSAVE_GAME_VERSION_2 2
-#define GBSAVE_GAME_VERSION_3 3
-#define GBSAVE_GAME_VERSION_4 4
-#define GBSAVE_GAME_VERSION_5 5
-#define GBSAVE_GAME_VERSION_6 6
-#define GBSAVE_GAME_VERSION_7 7
-#define GBSAVE_GAME_VERSION_8 8
-#define GBSAVE_GAME_VERSION_9 9
-#define GBSAVE_GAME_VERSION_10 10
-#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_10
-
-int inline gbGetValue(int min,int max,int v)
-{
- return (int)(min+(float)(max-min)*(2.0*(v/31.0)-(v/31.0)*(v/31.0)));
-}
-
-void gbGenFilter()
-{
- for (int r=0;r<32;r++) {
- for (int g=0;g<32;g++) {
- for (int b=0;b<32;b++) {
- int nr=gbGetValue(gbGetValue(4,14,g),
- gbGetValue(24,29,g),r)-4;
- int ng=gbGetValue(gbGetValue(4+gbGetValue(0,5,r),
- 14+gbGetValue(0,3,r),b),
- gbGetValue(24+gbGetValue(0,3,r),
- 29+gbGetValue(0,1,r),b),g)-4;
- int nb=gbGetValue(gbGetValue(4+gbGetValue(0,5,r),
- 14+gbGetValue(0,3,r),g),
- gbGetValue(24+gbGetValue(0,3,r),
- 29+gbGetValue(0,1,r),g),b)-4;
- gbColorFilter[(b<<10)|(g<<5)|r]=(nb<<10)|(ng<<5)|nr;
- }
- }
- }
-}
-
-bool gbIsGameboyRom(char * file)
-{
- if(strlen(file) > 4) {
- char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".gb") == 0)
- return true;
- if(_stricmp(p, ".gbc") == 0)
- return true;
- if(_stricmp(p, ".cgb") == 0)
- return true;
- if(_stricmp(p, ".sgb") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-void gbCopyMemory(u16 d, u16 s, int count)
-{
- while(count) {
- gbMemoryMap[d>>12][d & 0x0fff] = gbMemoryMap[s>>12][s & 0x0fff];
- s++;
- d++;
- count--;
- }
-}
-
-void gbDoHdma()
-{
- gbCopyMemory(gbHdmaDestination,
- gbHdmaSource,
- 0x10);
-
- gbHdmaDestination += 0x10;
- gbHdmaSource += 0x10;
-
- register_HDMA2 += 0x10;
- if(register_HDMA2 == 0x00)
- register_HDMA1++;
-
- register_HDMA4 += 0x10;
- if(register_HDMA4 == 0x00)
- register_HDMA3++;
-
- if(gbHdmaDestination == 0x96b0)
- gbHdmaBytes = gbHdmaBytes;
- gbHdmaBytes -= 0x10;
- register_HDMA5--;
- if(register_HDMA5 == 0xff)
- gbHdmaOn = 0;
-}
-
-// fix for Harley and Lego Racers
-void gbCompareLYToLYC()
-{
- if(register_LY == register_LYC) {
- // mark that we have a match
- register_STAT |= 4;
-
- // check if we need an interrupt
- if((register_STAT & 0x40) && (register_IE & 2))
- gbInterrupt |= 2;
- } else // no match
- register_STAT &= 0xfb;
-}
-
-void gbWriteMemory(register u16 address, register u8 value)
-{
- if(address < 0x8000) {
-#ifndef FINAL_VERSION
- if(memorydebug && (address>0x3fff || address < 0x2000)) {
- log("Memory register write %04x=%02x PC=%04x\n",
- address,
- value,
- PC.W);
- }
-#endif
- if(mapper)
- (*mapper)(address, value);
- return;
- }
-
- if(address < 0xa000) {
- gbMemoryMap[address>>12][address&0x0fff] = value;
- return;
- }
-
- if(address < 0xc000) {
-#ifndef FINAL_VERSION
- if(memorydebug) {
- log("Memory register write %04x=%02x PC=%04x\n",
- address,
- value,
- PC.W);
- }
-#endif
-
- if(mapper)
- (*mapperRAM)(address, value);
- return;
- }
-
- if(address < 0xfe00) {
- gbMemoryMap[address>>12][address & 0x0fff] = value;
- return;
- }
-
- if(address < 0xff00) {
- gbMemory[address] = value;
- return;
- }
-
- switch(address & 0x00ff) {
- case 0x00: {
- gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) |
- (value & 0x30));
- if(gbSgbMode) {
- gbSgbDoBitTransfer(value);
- }
-
- return;
- }
-
- case 0x01: {
- gbMemory[0xff01] = value;
- return;
- }
-
- // serial control
- case 0x02: {
- gbSerialOn = (value & 0x80);
- gbMemory[0xff02] = value;
- if(gbSerialOn) {
- gbSerialTicks = GBSERIAL_CLOCK_TICKS;
-#ifdef LINK_EMULATION
- if(linkConnected) {
- if(value & 1) {
- linkSendByte(0x100|gbMemory[0xFF01]);
- Sleep(5);
- }
- }
-#endif
- }
-
- gbSerialBits = 0;
- return;
- }
-
- // DIV register resets on any write
- case 0x04: {
- register_DIV = 0;
- return;
- }
- case 0x05:
- register_TIMA = value;
- return;
-
- case 0x06:
- register_TMA = value;
- return;
-
- // TIMER control
- case 0x07: {
- register_TAC = value;
-
- gbTimerOn = (value & 4);
- gbTimerMode = value & 3;
- // register_TIMA = register_TMA;
- switch(gbTimerMode) {
- case 0:
- gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS;
- break;
- case 1:
- gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_1_CLOCK_TICKS;
- break;
- case 2:
- gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_2_CLOCK_TICKS;
- break;
- case 3:
- gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_3_CLOCK_TICKS;
- break;
- }
- return;
- }
-
- case 0x0f: {
- register_IF = value;
- gbInterrupt = value;
- return;
- }
-
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- case 0x18:
- case 0x19:
- case 0x1a:
- case 0x1b:
- case 0x1c:
- case 0x1d:
- case 0x1e:
- case 0x1f:
- case 0x20:
- case 0x21:
- case 0x22:
- case 0x23:
- case 0x24:
- case 0x25:
- case 0x26:
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- case 0x3c:
- case 0x3d:
- case 0x3e:
- case 0x3f: {
- SOUND_EVENT(address,value);
- return;
- }
- case 0x40: {
- int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80);
-
- if(lcdChange) {
- if(value & 0x80) {
- gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS;
- gbLcdMode = 0;
- register_STAT &= 0xfc;
- register_LY = 0x00;
- } else {
- gbLcdTicks = 0;
- gbLcdMode = 0;
- register_STAT &= 0xfc;
- register_LY = 0x00;
- }
- // compareLYToLYC();
- }
- // don't draw the window if it was not enabled and not being drawn before
- if(!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 &&
- register_LY > register_WY)
- gbWindowLine = 144;
-
- register_LCDC = value;
-
- return;
- }
-
- // STAT
- case 0x41: {
- //register_STAT = (register_STAT & 0x87) |
- // (value & 0x7c);
- register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ?
- // GB bug from Devrs FAQ
- if(!gbCgbMode && (register_LCDC & 0x80) && gbLcdMode < 2)
- gbInterrupt |= 2;
- return;
- }
-
- // SCY
- case 0x42: {
- register_SCY = value;
- return;
- }
-
- // SCX
- case 0x43: {
- register_SCX = value;
- return;
- }
-
- // LY
- case 0x44: {
- // read only
- return;
- }
-
- // LYC
- case 0x45: {
- register_LYC = value;
- if((register_LCDC & 0x80)) {
- gbCompareLYToLYC();
- }
- return;
- }
-
- // DMA!
- case 0x46: {
- int source = value * 0x0100;
-
- gbCopyMemory(0xfe00,
- source,
- 0xa0);
- register_DMA = value;
- return;
- }
-
- // BGP
- case 0x47: {
- gbBgp[0] = value & 0x03;
- gbBgp[1] = (value & 0x0c)>>2;
- gbBgp[2] = (value & 0x30)>>4;
- gbBgp[3] = (value & 0xc0)>>6;
- break;
- }
-
- // OBP0
- case 0x48: {
- gbObp0[0] = value & 0x03;
- gbObp0[1] = (value & 0x0c)>>2;
- gbObp0[2] = (value & 0x30)>>4;
- gbObp0[3] = (value & 0xc0)>>6;
- break;
- }
-
- // OBP1
- case 0x49: {
- gbObp1[0] = value & 0x03;
- gbObp1[1] = (value & 0x0c)>>2;
- gbObp1[2] = (value & 0x30)>>4;
- gbObp1[3] = (value & 0xc0)>>6;
- break;
- }
-
- case 0x4a:
- register_WY = value;
- return;
-
- case 0x4b:
- register_WX = value;
- return;
-
- // KEY1
- case 0x4d: {
- if(gbCgbMode) {
- gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1);
- return;
- }
- }
- break;
-
- // VBK
- case 0x4f: {
- if(gbCgbMode) {
- value = value & 1;
- if(value == gbVramBank)
- return;
-
- int vramAddress = value * 0x2000;
- gbMemoryMap[0x08] = &gbVram[vramAddress];
- gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000];
-
- gbVramBank = value;
- register_VBK = value;
- }
- return;
- }
- break;
-
- // HDMA1
- case 0x51: {
- if(gbCgbMode) {
- if(value > 0x7f && value < 0xa0)
- value = 0;
-
- gbHdmaSource = (value << 8) | (register_HDMA2 & 0xf0);
-
- register_HDMA1 = value;
- return;
- }
- }
- break;
-
- // HDMA2
- case 0x52: {
- if(gbCgbMode) {
- value = value & 0xf0;
-
- gbHdmaSource = (register_HDMA1 << 8) | (value);
-
- register_HDMA2 = value;
- return;
- }
- }
- break;
-
- // HDMA3
- case 0x53: {
- if(gbCgbMode) {
- value = value & 0x1f;
- gbHdmaDestination = (value << 8) | (register_HDMA4 & 0xf0);
- gbHdmaDestination += 0x8000;
- register_HDMA3 = value;
- return;
- }
- }
- break;
-
- // HDMA4
- case 0x54: {
- if(gbCgbMode) {
- value = value & 0xf0;
- gbHdmaDestination = ((register_HDMA3 & 0x1f) << 8) | value;
- gbHdmaDestination += 0x8000;
- register_HDMA4 = value;
- return;
- }
- }
- break;
-
- // HDMA5
- case 0x55: {
- if(gbCgbMode) {
- gbHdmaBytes = 16 + (value & 0x7f) * 16;
- if(gbHdmaOn) {
- if(value & 0x80) {
- register_HDMA5 = (value & 0x7f);
- } else {
- register_HDMA5 = 0xff;
- gbHdmaOn = 0;
- }
- } else {
- if(value & 0x80) {
- gbHdmaOn = 1;
- register_HDMA5 = value & 0x7f;
- if(gbLcdMode == 0)
- gbDoHdma();
- } else {
- // we need to take the time it takes to complete the transfer into
- // account... according to GB DEV FAQs, the setup time is the same
- // for single and double speed, but the actual transfer takes the
- // same time
- if(gbSpeed)
- gbDmaTicks = 231 + 16 * (value & 0x7f);
- else
- gbDmaTicks = 231 + 8 * (value & 0x7f);
- gbCopyMemory(gbHdmaDestination,
- gbHdmaSource,
- gbHdmaBytes);
- gbHdmaDestination += gbHdmaBytes;
- gbHdmaSource += gbHdmaBytes;
-
- register_HDMA3 = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f;
- register_HDMA4 = gbHdmaDestination & 0xf0;
- register_HDMA1 = (gbHdmaSource >> 8) & 0xff;
- register_HDMA2 = gbHdmaSource & 0xf0;
- }
- }
- return;
- }
- }
- break;
-
- // BCPS
- case 0x68: {
- if(gbCgbMode) {
- int paletteIndex = (value & 0x3f) >> 1;
- int paletteHiLo = (value & 0x01);
-
- gbMemory[0xff68] = value;
- gbMemory[0xff69] = (paletteHiLo ?
- (gbPalette[paletteIndex] >> 8) :
- (gbPalette[paletteIndex] & 0x00ff));
- return;
- }
- }
- break;
-
- // BCPD
- case 0x69: {
- if(gbCgbMode) {
- int v = gbMemory[0xff68];
- int paletteIndex = (v & 0x3f) >> 1;
- int paletteHiLo = (v & 0x01);
- gbMemory[0xff69] = value;
- gbPalette[paletteIndex] = (paletteHiLo ?
- ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :
- ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;
-
- if(gbMemory[0xff68] & 0x80) {
- int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f;
-
- gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index;
-
- gbMemory[0xff69] = (index & 1 ?
- (gbPalette[index>>1] >> 8) :
- (gbPalette[index>>1] & 0x00ff));
-
- }
- return;
- }
- }
- break;
-
- // OCPS
- case 0x6a: {
- if(gbCgbMode) {
- int paletteIndex = (value & 0x3f) >> 1;
- int paletteHiLo = (value & 0x01);
-
- paletteIndex += 32;
-
- gbMemory[0xff6a] = value;
- gbMemory[0xff6b] = (paletteHiLo ?
- (gbPalette[paletteIndex] >> 8) :
- (gbPalette[paletteIndex] & 0x00ff));
- return;
- }
- }
- break;
-
- // OCPD
- case 0x6b: {
- if(gbCgbMode) {
- int v = gbMemory[0xff6a];
- int paletteIndex = (v & 0x3f) >> 1;
- int paletteHiLo = (v & 0x01);
-
- paletteIndex += 32;
-
- gbMemory[0xff6b] = value;
- gbPalette[paletteIndex] = (paletteHiLo ?
- ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :
- ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;
- if(gbMemory[0xff6a] & 0x80) {
- int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f;
-
- gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index;
-
- gbMemory[0xff6b] = (index & 1 ?
- (gbPalette[(index>>1) + 32] >> 8) :
- (gbPalette[(index>>1) + 32] & 0x00ff));
-
- }
- return;
- }
- }
- break;
-
- // SVBK
- case 0x70: {
- if(gbCgbMode) {
- value = value & 7;
-
- int bank = value;
- if(value == 0)
- bank = 1;
-
- if(bank == gbWramBank)
- return;
-
- int wramAddress = bank * 0x1000;
- gbMemoryMap[0x0d] = &gbWram[wramAddress];
-
- gbWramBank = bank;
- register_SVBK = value;
- return;
- }
- }
- break;
-
- case 0xff: {
- register_IE = value;
- register_IF &= value;
- return;
- }
- }
-
- gbMemory[address] = value;
-}
-
-u8 gbReadOpcode(register u16 address)
-{
- if(gbCheatMap[address])
- return gbCheatRead(address);
-
- switch(address & 0xf000) {
- case 0x0a:
- case 0x0b:
- if(mapperReadRAM)
- return mapperReadRAM(address);
- break;
- case 0x0f:
- if(address > 0xff00) {
- if (address >= 0xFF10 && address <= 0xFF3F)
- {
- return gbSoundRead(address);
- }
- switch(address & 0x00ff) {
- case 0x04:
- return register_DIV;
- case 0x05:
- return register_TIMA;
- case 0x06:
- return register_TMA;
- case 0x07:
- return (0xf8 | register_TAC);
- case 0x0f:
- return (0xe0 | register_IF);
- case 0x40:
- return register_LCDC;
- case 0x41:
- return (0x80 | register_STAT);
- case 0x42:
- return register_SCY;
- case 0x43:
- return register_SCX;
- case 0x44:
- return register_LY;
- case 0x45:
- return register_LYC;
- case 0x46:
- return register_DMA;
- case 0x4a:
- return register_WY;
- case 0x4b:
- return register_WX;
- case 0x4f:
- return (0xfe | register_VBK);
- case 0x51:
- return register_HDMA1;
- case 0x52:
- return register_HDMA2;
- case 0x53:
- return register_HDMA3;
- case 0x54:
- return register_HDMA4;
- case 0x55:
- return register_HDMA5;
- case 0x70:
- return (0xf8 | register_SVBK);
- case 0xff:
- return register_IE;
- }
- }
- break;
- }
- return gbMemoryMap[address>>12][address & 0x0fff];
-}
-
-u8 gbReadMemory(register u16 address)
-{
- if(gbCheatMap[address])
- return gbCheatRead(address);
-
- if(address < 0xa000)
- return gbMemoryMap[address>>12][address&0x0fff];
-
- if(address < 0xc000) {
-#ifndef FINAL_VERSION
- if(memorydebug) {
- log("Memory register read %04x PC=%04x\n",
- address,
- PC.W);
- }
-#endif
-
- if(mapperReadRAM)
- return mapperReadRAM(address);
- return gbMemoryMap[address>>12][address & 0x0fff];
- }
-
- if(address >= 0xff00) {
-
- if (address >= 0xFF10 && address <= 0xFF3F) {
- return gbSoundRead(address);
- }
-
- switch(address & 0x00ff) {
- case 0x00:
- {
- if(gbSgbMode) {
- gbSgbReadingController |= 4;
- gbSgbResetPacketState();
- }
-
- int b = gbMemory[0xff00];
-
- if((b & 0x30) == 0x20) {
- b &= 0xf0;
-
- int joy = 0;
- if(gbSgbMode && gbSgbMultiplayer) {
- switch(gbSgbNextController) {
- case 0x0f:
- joy = 0;
- break;
- case 0x0e:
- joy = 1;
- break;
- case 0x0d:
- joy = 2;
- break;
- case 0x0c:
- joy = 3;
- break;
- default:
- joy = 0;
- }
- }
- int joystate = gbJoymask[joy];
- if(!(joystate & 128))
- b |= 0x08;
- if(!(joystate & 64))
- b |= 0x04;
- if(!(joystate & 32))
- b |= 0x02;
- if(!(joystate & 16))
- b |= 0x01;
-
- gbMemory[0xff00] = b;
- } else if((b & 0x30) == 0x10) {
- b &= 0xf0;
-
- int joy = 0;
- if(gbSgbMode && gbSgbMultiplayer) {
- switch(gbSgbNextController) {
- case 0x0f:
- joy = 0;
- break;
- case 0x0e:
- joy = 1;
- break;
- case 0x0d:
- joy = 2;
- break;
- case 0x0c:
- joy = 3;
- break;
- default:
- joy = 0;
- }
- }
- int joystate = gbJoymask[joy];
- if(!(joystate & 8))
- b |= 0x08;
- if(!(joystate & 4))
- b |= 0x04;
- if(!(joystate & 2))
- b |= 0x02;
- if(!(joystate & 1))
- b |= 0x01;
-
- gbMemory[0xff00] = b;
- } else {
- if(gbSgbMode && gbSgbMultiplayer) {
- gbMemory[0xff00] = 0xf0 | gbSgbNextController;
- } else {
- gbMemory[0xff00] = 0xff;
- }
- }
- }
- return gbMemory[0xff00];
- break;
- case 0x01:
- return gbMemory[0xff01];
- case 0x04:
- return register_DIV;
- case 0x05:
- return register_TIMA;
- case 0x06:
- return register_TMA;
- case 0x07:
- return (0xf8 | register_TAC);
- case 0x0f:
- return (0xe0 | register_IF);
- case 0x40:
- return register_LCDC;
- case 0x41:
- return (0x80 | register_STAT);
- case 0x42:
- return register_SCY;
- case 0x43:
- return register_SCX;
- case 0x44:
- return register_LY;
- case 0x45:
- return register_LYC;
- case 0x46:
- return register_DMA;
- case 0x4a:
- return register_WY;
- case 0x4b:
- return register_WX;
- case 0x4f:
- return (0xfe | register_VBK);
- case 0x51:
- return register_HDMA1;
- case 0x52:
- return register_HDMA2;
- case 0x53:
- return register_HDMA3;
- case 0x54:
- return register_HDMA4;
- case 0x55:
- return register_HDMA5;
- case 0x70:
- return (0xf8 | register_SVBK);
- case 0xff:
- return register_IE;
- }
- }
-
- return gbMemoryMap[address>>12][address & 0x0fff];
-}
-
-void gbVblank_interrupt()
-{
- if(IFF & 0x80) {
- PC.W++;
- IFF &= 0x7f;
- }
- gbInterrupt &= 0xfe;
-
- IFF &= 0x7e;
- register_IF &= 0xfe;
-
- gbWriteMemory(--SP.W, PC.B.B1);
- gbWriteMemory(--SP.W, PC.B.B0);
- PC.W = 0x40;
-}
-
-void gbLcd_interrupt()
-{
- if(IFF & 0x80) {
- PC.W++;
- IFF &= 0x7f;
- }
- gbInterrupt &= 0xfd;
- IFF &= 0x7e;
- register_IF &= 0xfd;
-
- gbWriteMemory(--SP.W, PC.B.B1);
- gbWriteMemory(--SP.W, PC.B.B0);
-
- PC.W = 0x48;
-}
-
-void gbTimer_interrupt()
-{
- if(IFF & 0x80) {
- PC.W++;
- IFF &= 0x7f;
- }
- IFF &= 0x7e;
- gbInterrupt &= 0xfb;
- register_IF &= 0xfb;
-
- gbWriteMemory(--SP.W, PC.B.B1);
- gbWriteMemory(--SP.W, PC.B.B0);
-
- PC.W = 0x50;
-}
-
-void gbSerial_interrupt()
-{
- if(IFF & 0x80) {
- PC.W++;
- IFF &= 0x7f;
- }
- IFF &= 0x7e;
- gbInterrupt &= 0xf7;
- register_IF &= 0xf7;
-
- gbWriteMemory(--SP.W, PC.B.B1);
- gbWriteMemory(--SP.W, PC.B.B0);
-
- PC.W = 0x58;
-}
-
-void gbJoypad_interrupt()
-{
- if(IFF & 0x80) {
- PC.W++;
- IFF &= 0x7f;
- }
- IFF &= 0x7e;
- gbInterrupt &= 0xef;
- register_IF &= 0xef;
-
- gbWriteMemory(--SP.W, PC.B.B1);
- gbWriteMemory(--SP.W, PC.B.B0);
-
- PC.W = 0x60;
-}
-
-void gbSpeedSwitch()
-{
- if(gbSpeed == 0) {
- gbSpeed = 1;
- GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; //127; //51 * 2;
- GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2;
- GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; //52; //20 * 2;
- GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; //99; //43 * 2;
- GBDIV_CLOCK_TICKS = 64 * 2;
- GBLY_INCREMENT_CLOCK_TICKS = 114 * 2;
- GBTIMER_MODE_0_CLOCK_TICKS = 256; //256*2;
- GBTIMER_MODE_1_CLOCK_TICKS = 4; //4*2;
- GBTIMER_MODE_2_CLOCK_TICKS = 16; //16*2;
- GBTIMER_MODE_3_CLOCK_TICKS = 64; //64*2;
- GBSERIAL_CLOCK_TICKS = 128 * 2;
- gbDivTicks *= 2;
- gbLcdTicks *= 2;
- gbLcdLYIncrementTicks *= 2;
- // timerTicks *= 2;
- // timerClockTicks *= 2;
- gbSerialTicks *= 2;
- SOUND_CLOCK_TICKS = soundQuality * 24 * 2;
- soundTicks *= 2;
- // synchronizeTicks *= 2;
- // SYNCHRONIZE_CLOCK_TICKS *= 2;
- } else {
- gbSpeed = 0;
- GBLCD_MODE_0_CLOCK_TICKS = 51;
- GBLCD_MODE_1_CLOCK_TICKS = 1140;
- GBLCD_MODE_2_CLOCK_TICKS = 20;
- GBLCD_MODE_3_CLOCK_TICKS = 43;
- GBDIV_CLOCK_TICKS = 64;
- GBLY_INCREMENT_CLOCK_TICKS = 114;
- GBTIMER_MODE_0_CLOCK_TICKS = 256;
- GBTIMER_MODE_1_CLOCK_TICKS = 4;
- GBTIMER_MODE_2_CLOCK_TICKS = 16;
- GBTIMER_MODE_3_CLOCK_TICKS = 64;
- GBSERIAL_CLOCK_TICKS = 128;
- gbDivTicks /= 2;
- gbLcdTicks /= 2;
- gbLcdLYIncrementTicks /= 2;
- // timerTicks /= 2;
- // timerClockTicks /= 2;
- gbSerialTicks /= 2;
- SOUND_CLOCK_TICKS = soundQuality * 24;
- soundTicks /= 2;
- // synchronizeTicks /= 2;
- // SYNCHRONIZE_CLOCK_TICKS /= 2;
- }
-}
-
-void gbReset()
-{
- SP.W = 0xfffe;
- AF.W = 0x01b0;
- BC.W = 0x0013;
- DE.W = 0x00d8;
- HL.W = 0x014d;
- PC.W = 0x0100;
- IFF = 0;
- gbInterrupt = 1;
- gbInterruptWait = 0;
-
- register_DIV = 0;
- register_TIMA = 0;
- register_TMA = 0;
- register_TAC = 0;
- register_IF = 1;
- register_LCDC = 0x91;
- register_STAT = 0;
- register_SCY = 0;
- register_SCX = 0;
- register_LY = 0;
- register_LYC = 0;
- register_DMA = 0;
- register_WY = 0;
- register_WX = 0;
- register_VBK = 0;
- register_HDMA1 = 0;
- register_HDMA2 = 0;
- register_HDMA3 = 0;
- register_HDMA4 = 0;
- register_HDMA5 = 0;
- register_SVBK = 0;
- register_IE = 0;
-
- if(gbCgbMode) {
- if(gbSgbMode) {
- if(gbEmulatorType == 5)
- AF.W = 0xffb0;
- else
- AF.W = 0x01b0;
- BC.W = 0x0013;
- DE.W = 0x00d8;
- HL.W = 0x014d;
- for(int i = 0; i < 8; i++)
- gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
- } else {
- AF.W = 0x11b0;
- BC.W = 0x0000;
- DE.W = 0xff56;
- HL.W = 0x000d;
- }
- if(gbEmulatorType == 4)
- BC.B.B1 |= 0x01;
-
- register_HDMA5 = 0xff;
- gbMemory[0xff68] = 0xc0;
- gbMemory[0xff6a] = 0xc0;
- } else {
- for(int i = 0; i < 8; i++)
- gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
- }
-
- if(gbSpeed) {
- gbSpeedSwitch();
- gbMemory[0xff4d] = 0;
- }
-
- gbDivTicks = GBDIV_CLOCK_TICKS;
- gbLcdMode = 2;
- gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS;
- gbLcdLYIncrementTicks = 0;
- gbTimerTicks = 0;
- gbTimerClockTicks = 0;
- gbSerialTicks = 0;
- gbSerialBits = 0;
- gbSerialOn = 0;
- gbWindowLine = -1;
- gbTimerOn = 0;
- gbTimerMode = 0;
- // gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS;
- gbSpeed = 0;
- gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0;
-
- if(gbCgbMode) {
- gbSpeed = 0;
- gbHdmaOn = 0;
- gbHdmaSource = 0x0000;
- gbHdmaDestination = 0x8000;
- gbVramBank = 0;
- gbWramBank = 1;
- register_LY = 0x90;
- gbLcdMode = 1;
- for(int i = 0; i < 64; i++)
- gbPalette[i] = 0x7fff;
- }
-
- if(gbSgbMode) {
- gbSgbReset();
- }
-
- for(int i =0; i < 4; i++)
- gbBgp[i] = gbObp0[i] = gbObp1[i] = i;
-
- memset(&gbDataMBC1,0, sizeof(gbDataMBC1));
- gbDataMBC1.mapperROMBank = 1;
-
- gbDataMBC2.mapperRAMEnable = 0;
- gbDataMBC2.mapperROMBank = 1;
-
- memset(&gbDataMBC3,0, 6 * sizeof(int));
- gbDataMBC3.mapperROMBank = 1;
-
- memset(&gbDataMBC5, 0, sizeof(gbDataMBC5));
- gbDataMBC5.mapperROMBank = 1;
-
- memset(&gbDataHuC1, 0, sizeof(gbDataHuC1));
- gbDataHuC1.mapperROMBank = 1;
-
- memset(&gbDataHuC3, 0, sizeof(gbDataHuC3));
- gbDataHuC3.mapperROMBank = 1;
-
- gbMemoryMap[0x00] = &gbRom[0x0000];
- gbMemoryMap[0x01] = &gbRom[0x1000];
- gbMemoryMap[0x02] = &gbRom[0x2000];
- gbMemoryMap[0x03] = &gbRom[0x3000];
- gbMemoryMap[0x04] = &gbRom[0x4000];
- gbMemoryMap[0x05] = &gbRom[0x5000];
- gbMemoryMap[0x06] = &gbRom[0x6000];
- gbMemoryMap[0x07] = &gbRom[0x7000];
- if(gbCgbMode) {
- gbMemoryMap[0x08] = &gbVram[0x0000];
- gbMemoryMap[0x09] = &gbVram[0x1000];
- gbMemoryMap[0x0a] = &gbMemory[0xa000];
- gbMemoryMap[0x0b] = &gbMemory[0xb000];
- gbMemoryMap[0x0c] = &gbMemory[0xc000];
- gbMemoryMap[0x0d] = &gbWram[0x1000];
- gbMemoryMap[0x0e] = &gbMemory[0xe000];
- gbMemoryMap[0x0f] = &gbMemory[0xf000];
- } else {
- gbMemoryMap[0x08] = &gbMemory[0x8000];
- gbMemoryMap[0x09] = &gbMemory[0x9000];
- gbMemoryMap[0x0a] = &gbMemory[0xa000];
- gbMemoryMap[0x0b] = &gbMemory[0xb000];
- gbMemoryMap[0x0c] = &gbMemory[0xc000];
- gbMemoryMap[0x0d] = &gbMemory[0xd000];
- gbMemoryMap[0x0e] = &gbMemory[0xe000];
- gbMemoryMap[0x0f] = &gbMemory[0xf000];
- }
-
- if(gbRam) {
- gbMemoryMap[0x0a] = &gbRam[0x0000];
- gbMemoryMap[0x0b] = &gbRam[0x1000];
- }
-
- gbSoundReset();
-
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- gbLastTime = systemGetClock();
- gbFrameCount = 0;
-}
-
-void gbWriteSaveMBC1(const char * name)
-{
- FILE *gzFile = fopen(name,"wb");
-
- if(gzFile == NULL) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
- return;
- }
-
- fwrite(gbRam,
- 1,
- gbRamSize,
- gzFile);
-
- fclose(gzFile);
-}
-
-void gbWriteSaveMBC2(const char * name)
-{
- FILE *file = fopen(name, "wb");
-
- if(file == NULL) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
- return;
- }
-
- fwrite(&gbMemory[0xa000],
- 1,
- 256,
- file);
-
- fclose(file);
-}
-
-void gbWriteSaveMBC3(const char * name, bool extendedSave)
-{
- FILE *gzFile = fopen(name,"wb");
-
- if(gzFile == NULL) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
- return;
- }
-
- fwrite(gbRam,
- 1,
- gbRamSize,
- gzFile);
-
- if(extendedSave)
- fwrite(&gbDataMBC3.mapperSeconds,
- 1,
- 10*sizeof(int) + sizeof(time_t),
- gzFile);
-
- fclose(gzFile);
-}
-
-void gbWriteSaveMBC5(const char * name)
-{
- FILE *gzFile = fopen(name,"wb");
-
- if(gzFile == NULL) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
- return;
- }
-
- fwrite(gbRam,
- 1,
- gbRamSize,
- gzFile);
-
- fclose(gzFile);
-}
-
-void gbWriteSaveMBC7(const char * name)
-{
- FILE *file = fopen(name, "wb");
-
- if(file == NULL) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
- return;
- }
-
- fwrite(&gbMemory[0xa000],
- 1,
- 256,
- file);
-
- fclose(file);
-}
-
-bool gbReadSaveMBC1(const char * name)
-{
- gzFile gzFile = gzopen(name, "rb");
-
- if(gzFile == NULL) {
- return false;
- }
-
- int read = gzread(gzFile,
- gbRam,
- gbRamSize);
-
- if(read != gbRamSize) {
- systemMessage(MSG_FAILED_TO_READ_SGM, N_("Failed to read complete save game %s (%d)"), name, read);
- gzclose(gzFile);
- return false;
- }
-
- gzclose(gzFile);
- return true;
-}
-
-bool gbReadSaveMBC2(const char * name)
-{
- FILE *file = fopen(name, "rb");
-
- if(file == NULL) {
- return false;
- }
-
- int read = fread(&gbMemory[0xa000],
- 1,
- 256,
- file);
-
- if(read != 256) {
- systemMessage(MSG_FAILED_TO_READ_SGM,
- N_("Failed to read complete save game %s (%d)"), name, read);
- fclose(file);
- return false;
- }
-
- fclose(file);
- return true;
-}
-
-bool gbReadSaveMBC3(const char * name)
-{
- gzFile gzFile = gzopen(name, "rb");
-
- if(gzFile == NULL) {
- return false;
- }
-
- int read = gzread(gzFile,
- gbRam,
- gbRamSize);
-
- bool res = true;
-
- if(read != gbRamSize) {
- systemMessage(MSG_FAILED_TO_READ_SGM,
- N_("Failed to read complete save game %s (%d)"), name, read);
- } else {
- read = gzread(gzFile,
- &gbDataMBC3.mapperSeconds,
- sizeof(int)*10 + sizeof(time_t));
-
- if(read != (sizeof(int)*10 + sizeof(time_t)) && read != 0) {
- systemMessage(MSG_FAILED_TO_READ_RTC,
- N_("Failed to read RTC from save game %s (continuing)"),
- name);
- res = false;
- }
- }
-
- gzclose(gzFile);
- return res;
-}
-
-bool gbReadSaveMBC5(const char * name)
-{
- gzFile gzFile = gzopen(name, "rb");
-
- if(gzFile == NULL) {
- return false;
- }
-
- int read = gzread(gzFile,
- gbRam,
- gbRamSize);
-
- if(read != gbRamSize) {
- systemMessage(MSG_FAILED_TO_READ_SGM,
- N_("Failed to read complete save game %s (%d)"), name, read);
- gzclose(gzFile);
- return false;
- }
-
- gzclose(gzFile);
- return true;
-}
-
-bool gbReadSaveMBC7(const char * name)
-{
- FILE *file = fopen(name, "rb");
-
- if(file == NULL) {
- return false;
- }
-
- int read = fread(&gbMemory[0xa000],
- 1,
- 256,
- file);
-
- if(read != 256) {
- systemMessage(MSG_FAILED_TO_READ_SGM,
- N_("Failed to read complete save game %s (%d)"), name, read);
- fclose(file);
- return false;
- }
-
- fclose(file);
- return true;
-}
-
-void gbInit()
-{
- gbGenFilter();
- gbSgbInit();
-
- gbMemory = (u8 *)malloc(65536);
- memset(gbMemory,0, 65536);
-
- pix = (u8 *)calloc(1,4*257*226);
-
- gbLineBuffer = (u16 *)malloc(160 * sizeof(u16));
-}
-
-bool gbWriteBatteryFile(const char *file, bool extendedSave)
-{
- if(gbBattery) {
- int type = gbRom[0x147];
-
- switch(type) {
- case 0x03:
- gbWriteSaveMBC1(file);
- break;
- case 0x06:
- gbWriteSaveMBC2(file);
- break;
- case 0x0f:
- case 0x10:
- case 0x13:
- gbWriteSaveMBC3(file, extendedSave);
- break;
- case 0x1b:
- case 0x1e:
- gbWriteSaveMBC5(file);
- break;
- case 0x22:
- gbWriteSaveMBC7(file);
- break;
- case 0xff:
- gbWriteSaveMBC1(file);
- break;
- }
- }
- return true;
-}
-
-bool gbWriteBatteryFile(const char *file)
-{
- gbWriteBatteryFile(file, true);
- return true;
-}
-
-bool gbReadBatteryFile(const char *file)
-{
- bool res = false;
- if(gbBattery) {
- int type = gbRom[0x147];
-
- switch(type) {
- case 0x03:
- res = gbReadSaveMBC1(file);
- break;
- case 0x06:
- res = gbReadSaveMBC2(file);
- break;
- case 0x0f:
- case 0x10:
- case 0x13:
- if(!gbReadSaveMBC3(file)) {
- time(&gbDataMBC3.mapperLastTime);
- struct tm *lt;
- lt = localtime(&gbDataMBC3.mapperLastTime);
- gbDataMBC3.mapperSeconds = lt->tm_sec;
- gbDataMBC3.mapperMinutes = lt->tm_min;
- gbDataMBC3.mapperHours = lt->tm_hour;
- gbDataMBC3.mapperDays = lt->tm_yday & 255;
- gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
- (lt->tm_yday > 255 ? 1: 0);
- res = false;
- break;
- }
- res = true;
- break;
- case 0x1b:
- case 0x1e:
- res = gbReadSaveMBC5(file);
- break;
- case 0x22:
- res = gbReadSaveMBC7(file);
- case 0xff:
- res = gbReadSaveMBC1(file);
- break;
- }
- }
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
- return res;
-}
-
-bool gbReadGSASnapshot(const char *fileName)
-{
- FILE *file = fopen(fileName, "rb");
-
- if(!file) {
- systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
- return false;
- }
-
- // long size = ftell(file);
- fseek(file, 0x4, SEEK_SET);
- char buffer[16];
- char buffer2[16];
- fread(buffer, 1, 15, file);
- buffer[15] = 0;
- memcpy(buffer2, &gbRom[0x134], 15);
- buffer2[15] = 0;
- if(memcmp(buffer, buffer2, 15)) {
- systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR,
- N_("Cannot import snapshot for %s. Current game is %s"),
- buffer,
- buffer2);
- fclose(file);
- return false;
- }
- fseek(file, 0x13, SEEK_SET);
- int read = 0;
- int toRead = 0;
- switch(gbRom[0x147]) {
- case 0x03:
- case 0x0f:
- case 0x10:
- case 0x13:
- case 0x1b:
- case 0x1e:
- case 0xff:
- read = fread(gbRam, 1, gbRamSize, file);
- toRead = gbRamSize;
- break;
- case 0x06:
- case 0x22:
- read = fread(&gbMemory[0xa000],1,256,file);
- toRead = 256;
- break;
- default:
- systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE,
- N_("Unsupported snapshot file %s"),
- fileName);
- fclose(file);
- return false;
- }
- fclose(file);
- gbReset();
- return true;
-}
-
-variable_desc gbSaveGameStruct[] = {
- { &PC.W, sizeof(u16) },
- { &SP.W, sizeof(u16) },
- { &AF.W, sizeof(u16) },
- { &BC.W, sizeof(u16) },
- { &DE.W, sizeof(u16) },
- { &HL.W, sizeof(u16) },
- { &IFF, sizeof(u8) },
- { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int) },
- { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int) },
- { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int) },
- { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int) },
- { &GBDIV_CLOCK_TICKS, sizeof(int) },
- { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int) },
- { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int) },
- { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int) },
- { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int) },
- { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int) },
- { &GBSERIAL_CLOCK_TICKS, sizeof(int) },
- { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int) },
- { &gbDivTicks, sizeof(int) },
- { &gbLcdMode, sizeof(int) },
- { &gbLcdTicks, sizeof(int) },
- { &gbLcdLYIncrementTicks, sizeof(int) },
- { &gbTimerTicks, sizeof(int) },
- { &gbTimerClockTicks, sizeof(int) },
- { &gbSerialTicks, sizeof(int) },
- { &gbSerialBits, sizeof(int) },
- { &gbInterrupt, sizeof(int) },
- { &gbInterruptWait, sizeof(int) },
- { &gbSynchronizeTicks, sizeof(int) },
- { &gbTimerOn, sizeof(int) },
- { &gbTimerMode, sizeof(int) },
- { &gbSerialOn, sizeof(int) },
- { &gbWindowLine, sizeof(int) },
- { &gbCgbMode, sizeof(int) },
- { &gbVramBank, sizeof(int) },
- { &gbWramBank, sizeof(int) },
- { &gbHdmaSource, sizeof(int) },
- { &gbHdmaDestination, sizeof(int) },
- { &gbHdmaBytes, sizeof(int) },
- { &gbHdmaOn, sizeof(int) },
- { &gbSpeed, sizeof(int) },
- { &gbSgbMode, sizeof(int) },
- { ®ister_DIV, sizeof(u8) },
- { ®ister_TIMA, sizeof(u8) },
- { ®ister_TMA, sizeof(u8) },
- { ®ister_TAC, sizeof(u8) },
- { ®ister_IF, sizeof(u8) },
- { ®ister_LCDC, sizeof(u8) },
- { ®ister_STAT, sizeof(u8) },
- { ®ister_SCY, sizeof(u8) },
- { ®ister_SCX, sizeof(u8) },
- { ®ister_LY, sizeof(u8) },
- { ®ister_LYC, sizeof(u8) },
- { ®ister_DMA, sizeof(u8) },
- { ®ister_WY, sizeof(u8) },
- { ®ister_WX, sizeof(u8) },
- { ®ister_VBK, sizeof(u8) },
- { ®ister_HDMA1, sizeof(u8) },
- { ®ister_HDMA2, sizeof(u8) },
- { ®ister_HDMA3, sizeof(u8) },
- { ®ister_HDMA4, sizeof(u8) },
- { ®ister_HDMA5, sizeof(u8) },
- { ®ister_SVBK, sizeof(u8) },
- { ®ister_IE , sizeof(u8) },
- { &gbBgp[0], sizeof(u8) },
- { &gbBgp[1], sizeof(u8) },
- { &gbBgp[2], sizeof(u8) },
- { &gbBgp[3], sizeof(u8) },
- { &gbObp0[0], sizeof(u8) },
- { &gbObp0[1], sizeof(u8) },
- { &gbObp0[2], sizeof(u8) },
- { &gbObp0[3], sizeof(u8) },
- { &gbObp1[0], sizeof(u8) },
- { &gbObp1[1], sizeof(u8) },
- { &gbObp1[2], sizeof(u8) },
- { &gbObp1[3], sizeof(u8) },
- { NULL, 0 }
-};
-
-
-static bool gbWriteSaveState(gzFile gzFile)
-{
- utilWriteInt(gzFile, GBSAVE_GAME_VERSION);
-
- utilGzWrite(gzFile, &gbRom[0x134], 15);
-
- utilWriteData(gzFile, gbSaveGameStruct);
-
- utilGzWrite(gzFile, &IFF, 2);
-
- if(gbSgbMode) {
- gbSgbSaveGame(gzFile);
- }
-
- utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
- utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
- utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
- utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
- utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
- utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
-
- // not saved anymore
- // gzwrite(gzFile, pix, 256*224*sizeof(u16));
-
- utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
- // todo: remove
- utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
-
- for (int i = 0xFF10; i <= 0xFF3F; i++) gbMemory[i] = gbReadMemory(i);
-
- utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
-
- if(gbRamSize && gbRam) {
- utilGzWrite(gzFile, gbRam, gbRamSize);
- }
-
- if(gbCgbMode) {
- utilGzWrite(gzFile, gbVram, 0x4000);
- utilGzWrite(gzFile, gbWram, 0x8000);
- }
-
- gbSoundSaveGame(gzFile);
-
- gbCheatsSaveGame(gzFile);
-
- return true;
-}
-
-bool gbWriteMemSaveState(char *memory, int available)
-{
- gzFile gzFile = utilMemGzOpen(memory, available, "w");
-
- if(gzFile == NULL) {
- return false;
- }
-
- bool res = gbWriteSaveState(gzFile);
-
- long pos = utilGzMemTell(gzFile)+8;
-
- if(pos >= (available))
- res = false;
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-bool gbWriteSaveState(const char *name)
-{
- gzFile gzFile = utilGzOpen(name,"wb");
-
- if(gzFile == NULL)
- return false;
-
- bool res = gbWriteSaveState(gzFile);
-
- utilGzClose(gzFile);
- return res;
-}
-
-static bool gbReadSaveState(gzFile gzFile)
-{
- int version = utilReadInt(gzFile);
-
- if(version > GBSAVE_GAME_VERSION || version < 0) {
- systemMessage(MSG_UNSUPPORTED_VB_SGM,
- N_("Unsupported VisualBoy save game version %d"), version);
- return false;
- }
-
- u8 romname[20];
-
- utilGzRead(gzFile, romname, 15);
-
- if(memcmp(&gbRom[0x134], romname, 15) != 0) {
- systemMessage(MSG_CANNOT_LOAD_SGM_FOR,
- N_("Cannot load save game for %s. Playing %s"),
- romname, &gbRom[0x134]);
- return false;
- }
-
- utilReadData(gzFile, gbSaveGameStruct);
-
- if(version >= GBSAVE_GAME_VERSION_7) {
- utilGzRead(gzFile, &IFF, 2);
- }
-
- if(gbSgbMode) {
- gbSgbReadGame(gzFile, version);
- } else {
- gbSgbMask = 0; // loading a game at the wrong time causes no display
- }
-
- utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
- utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
- if(version < GBSAVE_GAME_VERSION_4)
- // prior to version 4, there was no adjustment for the time the game
- // was last played, so we have less to read. This needs update if the
- // structure changes again.
- utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)-sizeof(time_t));
- else
- utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
- utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
- utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
- utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
-
- if(version < GBSAVE_GAME_VERSION_5) {
- utilGzRead(gzFile, pix, 256*224*sizeof(u16));
- }
- memset(pix, 0, 257*226*sizeof(u32));
-
- if(version < GBSAVE_GAME_VERSION_6) {
- utilGzRead(gzFile, gbPalette, 64 * sizeof(u16));
- } else
- utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
-
- // todo: remove
- utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
-
- if(version < GBSAVE_GAME_VERSION_10) {
- if(!gbCgbMode && !gbSgbMode) {
- for(int i = 0; i < 8; i++)
- gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
- }
- }
-
- utilGzRead(gzFile, &gbMemory[0x8000], 0x8000);
-
- for (int i = 0xFF10; i <= 0xFF3F; i++) gbSoundEvent(i, gbMemory[i]);
-
- if(gbRamSize && gbRam) {
- utilGzRead(gzFile, gbRam, gbRamSize);
- }
-
- gbMemoryMap[0x00] = &gbRom[0x0000];
- gbMemoryMap[0x01] = &gbRom[0x1000];
- gbMemoryMap[0x02] = &gbRom[0x2000];
- gbMemoryMap[0x03] = &gbRom[0x3000];
- gbMemoryMap[0x04] = &gbRom[0x4000];
- gbMemoryMap[0x05] = &gbRom[0x5000];
- gbMemoryMap[0x06] = &gbRom[0x6000];
- gbMemoryMap[0x07] = &gbRom[0x7000];
- gbMemoryMap[0x08] = &gbMemory[0x8000];
- gbMemoryMap[0x09] = &gbMemory[0x9000];
- gbMemoryMap[0x0a] = &gbMemory[0xa000];
- gbMemoryMap[0x0b] = &gbMemory[0xb000];
- gbMemoryMap[0x0c] = &gbMemory[0xc000];
- gbMemoryMap[0x0d] = &gbMemory[0xd000];
- gbMemoryMap[0x0e] = &gbMemory[0xe000];
- gbMemoryMap[0x0f] = &gbMemory[0xf000];
-
- int type = gbRom[0x147];
-
- switch(type) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- // MBC 1
- memoryUpdateMapMBC1();
- break;
- case 0x05:
- case 0x06:
- // MBC2
- memoryUpdateMapMBC2();
- break;
- case 0x0f:
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- // MBC 3
- memoryUpdateMapMBC3();
- break;
- case 0x19:
- case 0x1a:
- case 0x1b:
- // MBC5
- memoryUpdateMapMBC5();
- break;
- case 0x1c:
- case 0x1d:
- case 0x1e:
- // MBC 5 Rumble
- memoryUpdateMapMBC5();
- break;
- case 0x22:
- // MBC 7
- memoryUpdateMapMBC7();
- break;
- case 0xfe:
- // HuC3
- memoryUpdateMapHuC3();
- break;
- case 0xff:
- // HuC1
- memoryUpdateMapHuC1();
- break;
- }
-
- if(gbCgbMode) {
- utilGzRead(gzFile, gbVram, 0x4000);
- utilGzRead(gzFile, gbWram, 0x8000);
-
- int value = register_SVBK;
- if(value == 0)
- value = 1;
-
- gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000];
- gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000];
- gbMemoryMap[0x0d] = &gbWram[value * 0x1000];
- }
-
- gbSoundReadGame(version, gzFile);
-
- if(gbBorderOn) {
- gbSgbRenderBorder();
- }
-
- systemDrawScreen();
-
- if(version > GBSAVE_GAME_VERSION_1)
- gbCheatsReadGame(gzFile, version);
-
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- return true;
-}
-
-bool gbReadMemSaveState(char *memory, int available)
-{
- gzFile gzFile = utilMemGzOpen(memory, available, "r");
-
- bool res = gbReadSaveState(gzFile);
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-bool gbReadSaveState(const char *name)
-{
- gzFile gzFile = utilGzOpen(name,"rb");
-
- if(gzFile == NULL) {
- return false;
- }
-
- bool res = gbReadSaveState(gzFile);
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-bool gbWritePNGFile(const char *fileName)
-{
- if(gbBorderOn)
- return utilWritePNGFile(fileName, 256, 224, pix);
- return utilWritePNGFile(fileName, 160, 144, pix);
-}
-
-bool gbWriteBMPFile(const char *fileName)
-{
- if(gbBorderOn)
- return utilWriteBMPFile(fileName, 256, 224, pix);
- return utilWriteBMPFile(fileName, 160, 144, pix);
-}
-
-void gbCleanUp()
-{
- if(gbRam != NULL) {
- free(gbRam);
- gbRam = NULL;
- }
-
- if(gbRom != NULL) {
- free(gbRom);
- gbRom = NULL;
- }
-
- if(gbMemory != NULL) {
- free(gbMemory);
- gbMemory = NULL;
- }
-
- if(gbLineBuffer != NULL) {
- free(gbLineBuffer);
- gbLineBuffer = NULL;
- }
-
- if(pix != NULL) {
- free(pix);
- pix = NULL;
- }
-
- gbSgbShutdown();
-
- if(gbVram != NULL) {
- free(gbVram);
- gbVram = NULL;
- }
-
- if(gbWram != NULL) {
- free(gbWram);
- gbWram = NULL;
- }
-
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-}
-
-bool gbLoadRom(const char *szFile)
-{
- int size = 0;
-
- if(gbRom != NULL) {
- gbCleanUp();
- }
-
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- gbRom = utilLoad(szFile,
- utilIsGBImage,
- NULL,
- size);
- if(!gbRom)
- return false;
-
- gbRomSize = size;
-
- return gbUpdateSizes();
-}
-
-bool gbUpdateSizes()
-{
- if(gbRom[0x148] > 8) {
- systemMessage(MSG_UNSUPPORTED_ROM_SIZE,
- N_("Unsupported rom size %02x"), gbRom[0x148]);
- return false;
- }
-
- if(gbRomSize < gbRomSizes[gbRom[0x148]]) {
- gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]);
- }
- gbRomSize = gbRomSizes[gbRom[0x148]];
- gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]];
-
- if(gbRom[0x149] > 5) {
- systemMessage(MSG_UNSUPPORTED_RAM_SIZE,
- N_("Unsupported ram size %02x"), gbRom[0x149]);
- return false;
- }
-
- gbRamSize = gbRamSizes[gbRom[0x149]];
- gbRamSizeMask = gbRamSizesMasks[gbRom[0x149]];
-
- if(gbRamSize) {
- gbRam = (u8 *)malloc(gbRamSize);
- memset(gbRam, 0xFF, gbRamSize);
- }
-
- int type = gbRom[0x147];
-
- mapperReadRAM = NULL;
-
- switch(type) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- // MBC 1
- mapper = mapperMBC1ROM;
- mapperRAM = mapperMBC1RAM;
- break;
- case 0x05:
- case 0x06:
- // MBC2
- mapper = mapperMBC2ROM;
- mapperRAM = mapperMBC2RAM;
- gbRamSize = 0x200;
- gbRamSizeMask = 0x1ff;
- break;
- case 0x0f:
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- // MBC 3
- mapper = mapperMBC3ROM;
- mapperRAM = mapperMBC3RAM;
- mapperReadRAM = mapperMBC3ReadRAM;
- break;
- case 0x19:
- case 0x1a:
- case 0x1b:
- // MBC5
- mapper = mapperMBC5ROM;
- mapperRAM = mapperMBC5RAM;
- break;
- case 0x1c:
- case 0x1d:
- case 0x1e:
- // MBC 5 Rumble
- mapper = mapperMBC5ROM;
- mapperRAM = mapperMBC5RAM;
- break;
- case 0x22:
- // MBC 7
- mapper = mapperMBC7ROM;
- mapperRAM = mapperMBC7RAM;
- mapperReadRAM = mapperMBC7ReadRAM;
- break;
- case 0xfe:
- // HuC3
- mapper = mapperHuC3ROM;
- mapperRAM = mapperHuC3RAM;
- mapperReadRAM = mapperHuC3ReadRAM;
- break;
- case 0xff:
- // HuC1
- mapper = mapperHuC1ROM;
- mapperRAM = mapperHuC1RAM;
- break;
- default:
- systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE,
- N_("Unknown cartridge type %02x"), type);
- return false;
- }
-
- switch(type) {
- case 0x03:
- case 0x06:
- case 0x0f:
- case 0x10:
- case 0x13:
- case 0x1b:
- case 0x1d:
- case 0x1e:
- case 0x22:
- case 0xff:
- gbBattery = 1;
- break;
- }
-
- if(gbRom[0x146] == 0x03) {
- if(gbEmulatorType == 0 ||
- gbEmulatorType == 2 ||
- gbEmulatorType == 5)
- gbSgbMode = 1;
- else
- gbSgbMode = 0;
- } else
- gbSgbMode = 0;
-
- if(gbRom[0x143] & 0x80) {
- if(gbEmulatorType == 0 ||
- gbEmulatorType == 1 ||
- gbEmulatorType == 4 ||
- gbEmulatorType == 5) {
- gbCgbMode = 1;
- gbVram = (u8 *)malloc(0x4000);
- gbWram = (u8 *)malloc(0x8000);
- memset(gbVram,0,0x4000);
- memset(gbWram,0,0x8000);
- memset(gbPalette,0, 2*128);
- } else {
- gbCgbMode = 0;
- }
- } else
- gbCgbMode = 0;
-
- gbInit();
- gbReset();
-
- switch(type) {
- case 0x1c:
- case 0x1d:
- case 0x1e:
- gbDataMBC5.isRumbleCartridge = 1;
- }
-
- return true;
-}
-
-void gbEmulate(int ticksToStop)
-{
- gbRegister tempRegister;
- u8 tempValue;
- s8 offset;
-
- int clockTicks = 0;
- gbDmaTicks = 0;
-
- register int opcode = 0;
-
- while(1) {
-#ifndef FINAL_VERSION
- if(systemDebug) {
- if(!(IFF & 0x80)) {
- if(systemDebug > 1) {
- sprintf(gbBuffer,"PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n",
- PC.W, AF.W, BC.W, DE.W,HL.W,SP.W,IFF);
- } else {
- sprintf(gbBuffer,"PC=%04x I=%02x\n", PC.W, IFF);
- }
- log(gbBuffer);
- }
- }
-#endif
- if(IFF & 0x80) {
- if(register_LCDC & 0x80) {
- clockTicks = gbLcdTicks;
- } else
- clockTicks = 100;
-
- if(gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks))
- clockTicks = gbLcdLYIncrementTicks;
-
- if(gbSerialOn && (gbSerialTicks < clockTicks))
- clockTicks = gbSerialTicks;
-
- if(gbTimerOn && (gbTimerTicks < clockTicks))
- clockTicks = gbTimerTicks;
-
- if(soundTicks && (soundTicks < clockTicks))
- clockTicks = soundTicks;
- } else {
- opcode = gbReadOpcode(PC.W++);
-
- if(IFF & 0x100) {
- IFF &= 0xff;
- PC.W--;
- }
-
- clockTicks = gbCycles[opcode];
-
- switch(opcode) {
- case 0xCB:
- // extended opcode
- opcode = gbReadOpcode(PC.W++);
- clockTicks = gbCyclesCB[opcode];
- switch(opcode) {
-#include "gbCodesCB.h"
- }
- break;
-#include "gbCodes.h"
- }
- }
-
- if(!emulating)
- return;
-
- if(gbDmaTicks) {
- clockTicks += gbDmaTicks;
- gbDmaTicks = 0;
- }
-
- if(gbSgbMode) {
- if(gbSgbPacketTimeout) {
- gbSgbPacketTimeout -= clockTicks;
-
- if(gbSgbPacketTimeout <= 0)
- gbSgbResetPacketState();
- }
- }
-
- ticksToStop -= clockTicks;
-
- // DIV register emulation
- gbDivTicks -= clockTicks;
- while(gbDivTicks <= 0) {
- register_DIV++;
- gbDivTicks += GBDIV_CLOCK_TICKS;
- }
-
- if(register_LCDC & 0x80) {
- // LCD stuff
- gbLcdTicks -= clockTicks;
- if(gbLcdMode == 1) {
- // during V-BLANK,we need to increment LY at the same rate!
- gbLcdLYIncrementTicks -= clockTicks;
- while(gbLcdLYIncrementTicks <= 0) {
- gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
-
- if(register_LY < 153) {
- register_LY++;
-
- gbCompareLYToLYC();
-
- if(register_LY >= 153)
- gbLcdLYIncrementTicks = 6;
- } else {
- register_LY = 0x00;
- // reset the window line
- gbWindowLine = -1;
- gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2;
- gbCompareLYToLYC();
- }
- }
- }
-
- // our counter is off, see what we need to do
- while(gbLcdTicks <= 0) {
- int framesToSkip = systemFrameSkip;
- if(speedup)
- framesToSkip = 9; // try 6 FPS during speedup
- switch(gbLcdMode) {
- case 0:
- // H-Blank
- register_LY++;
-
- gbCompareLYToLYC();
-
- // check if we reached the V-Blank period
- if(register_LY == 144) {
- // Yes, V-Blank
- // set the LY increment counter
- gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS;
- gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS;
- gbLcdMode = 1;
- if(register_LCDC & 0x80) {
- gbInterrupt |= 1; // V-Blank interrupt
- gbInterruptWait = 6;
- if(register_STAT & 0x10)
- gbInterrupt |= 2;
- }
-
- gbFrameCount++;
-
- systemFrame();
-
- if((gbFrameCount % 10) == 0)
- system10Frames(60);
-
- if(gbFrameCount >= 60) {
- u32 currentTime = systemGetClock();
- if(currentTime != gbLastTime)
- systemShowSpeed(100000/(currentTime - gbLastTime));
- else
- systemShowSpeed(0);
- gbLastTime = currentTime;
- gbFrameCount = 0;
- }
-
- if(systemReadJoypads()) {
- // read joystick
- if(gbSgbMode && gbSgbMultiplayer) {
- if(gbSgbFourPlayers) {
- gbJoymask[0] = systemReadJoypad(0);
- gbJoymask[1] = systemReadJoypad(1);
- gbJoymask[2] = systemReadJoypad(2);
- gbJoymask[3] = systemReadJoypad(3);
- } else {
- gbJoymask[0] = systemReadJoypad(0);
- gbJoymask[1] = systemReadJoypad(1);
- }
- } else {
- gbJoymask[0] = systemReadJoypad(-1);
- }
- }
- int newmask = gbJoymask[0] & 255;
-
- if(gbRom[0x147] == 0x22) {
- systemUpdateMotionSensor();
- }
-
- if(newmask) {
- gbInterrupt |= 16;
- }
-
- newmask = (gbJoymask[0] >> 10);
-
- speedup = (newmask & 1) ? true : false;
- gbCapture = (newmask & 2) ? true : false;
-
- if(gbCapture && !gbCapturePrevious) {
- gbCaptureNumber++;
- systemScreenCapture(gbCaptureNumber);
- }
- gbCapturePrevious = gbCapture;
-
- if(gbFrameSkipCount >= framesToSkip) {
- systemDrawScreen();
- gbFrameSkipCount = 0;
- } else
- gbFrameSkipCount++;
- } else {
- // go the the OAM being accessed mode
- gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
- gbLcdMode = 2;
-
- // only one LCD interrupt per line. may need to generalize...
- if(!(register_STAT & 0x40) ||
- (register_LY != register_LYC)) {
- if((register_STAT & 0x28) == 0x20)
- gbInterrupt |= 2;
- }
- }
- break;
- case 1:
- // V-Blank
- // next mode is OAM being accessed mode
- gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
- gbLcdMode = 2;
- if(!(register_STAT & 0x40) ||
- (register_LY != register_LYC)) {
- if((register_STAT & 0x28) == 0x20)
- gbInterrupt |= 2;
- }
- break;
- case 2:
- // OAM being accessed mode
-
- // next mode is OAM and VRAM in use
- gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS;
- gbLcdMode = 3;
- break;
- case 3:
- // OAM and VRAM in use
- // next mode is H-Blank
- if(register_LY < 144) {
- if(!gbSgbMask) {
- if(gbFrameSkipCount >= framesToSkip) {
- gbRenderLine();
- gbDrawSprites();
-
- switch(systemColorDepth) {
- case 16:
- {
- u16 * dest = (u16 *)pix +
- (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1)
- + gbBorderColumnSkip;
- for(int x = 0; x < 160; ) {
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
-
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
-
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
-
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- *dest++ = systemColorMap16[gbLineMix[x++]];
- }
- if(gbBorderOn)
- dest += gbBorderColumnSkip;
- *dest++ = 0; // for filters that read one pixel more
- }
- break;
- case 24:
- {
- u8 *dest = (u8 *)pix +
- 3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) +
- gbBorderColumnSkip);
- for(int x = 0; x < 160;) {
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
-
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
-
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
-
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
- dest+= 3;
- }
- }
- break;
- case 32:
- {
- u32 * dest = (u32 *)pix +
- (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1)
- + gbBorderColumnSkip;
- for(int x = 0; x < 160;) {
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
-
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
-
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
-
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- *dest++ = systemColorMap32[gbLineMix[x++]];
- }
- }
- break;
- }
- }
- }
- }
- gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS;
- gbLcdMode = 0;
- // only one LCD interrupt per line. may need to generalize...
- if(!(register_STAT & 0x40) ||
- (register_LY != register_LYC)) {
- if(register_STAT & 0x08)
- gbInterrupt |= 2;
- }
- if(gbHdmaOn) {
- gbDoHdma();
- }
- break;
- }
- // mark the correct lcd mode on STAT register
- register_STAT = (register_STAT & 0xfc) | gbLcdMode;
- }
- }
-
- // serial emulation
- if(gbSerialOn) {
-#ifdef LINK_EMULATION
- if(linkConnected) {
- gbSerialTicks -= clockTicks;
-
- while(gbSerialTicks <= 0) {
- // increment number of shifted bits
- gbSerialBits++;
- linkProc();
- if(gbSerialOn && (gbMemory[0xff02] & 1)) {
- if(gbSerialBits == 8) {
- gbSerialBits = 0;
- gbMemory[0xff01] = 0xff;
- gbMemory[0xff02] &= 0x7f;
- gbSerialOn = 0;
- gbInterrupt |= 8;
- gbSerialTicks = 0;
- }
- }
- gbSerialTicks += GBSERIAL_CLOCK_TICKS;
- }
- } else {
-#endif
- if(gbMemory[0xff02] & 1) {
- gbSerialTicks -= clockTicks;
-
- // overflow
- while(gbSerialTicks <= 0) {
- // shift serial byte to right and put a 1 bit in its place
- // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
- // increment number of shifted bits
- gbSerialBits++;
- if(gbSerialBits == 8) {
- // end of transmission
- if(gbSerialFunction) // external device
- gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);
- else
- gbMemory[0xff01] = 0xff;
- gbSerialTicks = 0;
- gbMemory[0xff02] &= 0x7f;
- gbSerialOn = 0;
- gbInterrupt |= 8;
- gbSerialBits = 0;
- } else
- gbSerialTicks += GBSERIAL_CLOCK_TICKS;
- }
- }
-#ifdef LINK_EMULATION
- }
-#endif
- }
-
- // timer emulation
- if(gbTimerOn) {
- gbTimerTicks -= clockTicks;
-
- while(gbTimerTicks <= 0) {
- register_TIMA++;
-
- if(register_TIMA == 0) {
- // timer overflow!
-
- // reload timer modulo
- register_TIMA = register_TMA;
-
- // flag interrupt
- gbInterrupt |= 4;
- }
-
- gbTimerTicks += gbTimerClockTicks;
- }
- }
-
- /*
- if(soundOffFlag) {
- if(synchronize && !speedup) {
- synchronizeTicks -= clockTicks;
-
- while(synchronizeTicks < 0) {
- synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS;
-
- DWORD now = timeGetTime();
- gbElapsedTime += (now - timeNow);
-
- if(gbElapsedTime < 50) {
- DWORD diff = 50 - gbElapsedTime;
- Sleep(diff);
- timeNow = timeGetTime();
- elapsedTime = timeNow - now - diff;
- if((int)elapsedTime < 0)
- elapsedTime = 0;
- } else {
- timeNow = timeGetTime();
- elapsedTime = 0;
- }
- }
- }
- }
- */
-
- soundTicks -= clockTicks;
-
- while(soundTicks < 0) {
- soundTicks += SOUND_CLOCK_TICKS;
-
- gbSoundTick();
- }
-
- register_IF = gbInterrupt;
-
- if(IFF & 0x20) {
- IFF &= 0xdf;
- IFF |= 0x01;
- gbInterruptWait = 0;
- } else if(gbInterrupt) {
- if(gbInterruptWait == 0) {
- // gbInterruptWait = 0;
-
- if(IFF & 0x01) {
- if((gbInterrupt & 1) && (register_IE & 1)) {
- gbVblank_interrupt();
- continue;
- }
-
- if((gbInterrupt & 2) && (register_IE & 2)) {
- gbLcd_interrupt();
- continue;
- }
-
- if((gbInterrupt & 4) && (register_IE & 4)) {
- gbTimer_interrupt();
- continue;
- }
-
- if((gbInterrupt & 8) && (register_IE & 8)) {
- gbSerial_interrupt();
- continue;
- }
-
- if((gbInterrupt & 16) && (register_IE & 16)) {
- gbJoypad_interrupt();
- continue;
- }
- }
- } else {
- gbInterruptWait -= clockTicks;
- if(gbInterruptWait < 0)
- gbInterruptWait = 0;
- }
- }
-
- if(ticksToStop <= 0) {
- if(!(register_LCDC & 0x80)) {
- if(systemReadJoypads()) {
- // read joystick
- if(gbSgbMode && gbSgbMultiplayer) {
- if(gbSgbFourPlayers) {
- gbJoymask[0] = systemReadJoypad(0);
- gbJoymask[1] = systemReadJoypad(1);
- gbJoymask[2] = systemReadJoypad(2);
- gbJoymask[3] = systemReadJoypad(3);
- } else {
- gbJoymask[0] = systemReadJoypad(0);
- gbJoymask[1] = systemReadJoypad(1);
- }
- } else {
- gbJoymask[0] = systemReadJoypad(-1);
- }
- }
- }
- return;
- }
- }
-}
-
-struct EmulatedSystem GBSystem = {
- // emuMain
- gbEmulate,
- // emuReset
- gbReset,
- // emuCleanUp
- gbCleanUp,
- // emuReadBattery
- gbReadBatteryFile,
- // emuWriteBattery
- gbWriteBatteryFile,
- // emuReadState
- gbReadSaveState,
- // emuWriteState
- gbWriteSaveState,
- // emuReadMemState
- gbReadMemSaveState,
- // emuWriteMemState
- gbWriteMemSaveState,
- // emuWritePNG
- gbWritePNGFile,
- // emuWriteBMP
- gbWriteBMPFile,
- // emuUpdateCPSR
- NULL,
- // emuHasDebugger
- false,
- // emuCount
-#ifdef FINAL_VERSION
- 70000/4,
-#else
- 1000,
-#endif
-};
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+#include
+#include
+
+#include "../System.h"
+#include "../NLS.h"
+#include "GB.h"
+#include "gbCheats.h"
+#include "gbGlobals.h"
+#include "gbMemory.h"
+#include "gbSGB.h"
+#include "gbSound.h"
+#include "../unzip.h"
+#include "../Util.h"
+
+#ifdef __GNUC__
+#define _stricmp strcasecmp
+#endif
+
+extern u8 *pix;
+extern bool speedup;
+
+bool gbUpdateSizes();
+bool inBios = false;
+
+// debugging
+bool memorydebug = false;
+char gbBuffer[2048];
+
+extern u16 gbLineMix[160];
+
+// mappers
+void (*mapper)(u16,u8) = NULL;
+void (*mapperRAM)(u16,u8) = NULL;
+u8 (*mapperReadRAM)(u16) = NULL;
+void (*mapperUpdateClock)() = NULL;
+
+// registers
+gbRegister PC;
+gbRegister SP;
+gbRegister AF;
+gbRegister BC;
+gbRegister DE;
+gbRegister HL;
+u16 IFF = 0;
+// 0xff04
+u8 register_DIV = 0;
+// 0xff05
+u8 register_TIMA = 0;
+// 0xff06
+u8 register_TMA = 0;
+// 0xff07
+u8 register_TAC = 0;
+// 0xff0f
+u8 register_IF = 0;
+// 0xff40
+u8 register_LCDC = 0;
+// 0xff41
+u8 register_STAT = 0;
+// 0xff42
+u8 register_SCY = 0;
+// 0xff43
+u8 register_SCX = 0;
+// 0xff44
+u8 register_LY = 0;
+// 0xff45
+u8 register_LYC = 0;
+// 0xff46
+u8 register_DMA = 0;
+// 0xff4a
+u8 register_WY = 0;
+// 0xff4b
+u8 register_WX = 0;
+// 0xff4f
+u8 register_VBK = 0;
+// 0xff51
+u8 register_HDMA1 = 0;
+// 0xff52
+u8 register_HDMA2 = 0;
+// 0xff53
+u8 register_HDMA3 = 0;
+// 0xff54
+u8 register_HDMA4 = 0;
+// 0xff55
+u8 register_HDMA5 = 0;
+// 0xff70
+u8 register_SVBK = 0;
+// 0xffff
+u8 register_IE = 0;
+
+// ticks definition
+int GBDIV_CLOCK_TICKS = 64;
+int GBLCD_MODE_0_CLOCK_TICKS = 51;
+int GBLCD_MODE_1_CLOCK_TICKS = 1140;
+int GBLCD_MODE_2_CLOCK_TICKS = 20;
+int GBLCD_MODE_3_CLOCK_TICKS = 43;
+int GBLY_INCREMENT_CLOCK_TICKS = 114;
+int GBTIMER_MODE_0_CLOCK_TICKS = 256;
+int GBTIMER_MODE_1_CLOCK_TICKS = 4;
+int GBTIMER_MODE_2_CLOCK_TICKS = 16;
+int GBTIMER_MODE_3_CLOCK_TICKS = 64;
+int GBSERIAL_CLOCK_TICKS = 128;
+int GBSYNCHRONIZE_CLOCK_TICKS = 52920;
+
+// state variables
+
+// general
+int clockTicks = 0;
+bool gbSystemMessage = false;
+int gbGBCColorType = 0;
+int gbHardware = 0;
+int gbRomType = 0;
+int gbRemainingClockTicks = 0;
+int gbOldClockTicks = 0;
+int gbIntBreak = 0;
+int gbInterruptLaunched = 0;
+u8 gbCheatingDevice = 0; // 1 = GS, 2 = GG
+// breakpoint
+bool breakpoint = false;
+// interrupt
+int gbInt48Signal = 0;
+int gbInterruptWait = 0;
+// serial
+int gbSerialOn = 0;
+int gbSerialTicks = 0;
+int gbSerialBits = 0;
+// timer
+bool gbTimerOn = false;
+int gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS;
+int gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS;
+int gbTimerMode = 0;
+bool gbIncreased = false;
+// The internal timer is always active, and it is
+// not reset by writing to register_TIMA/TMA, but by
+// writing to register_DIV...
+int gbInternalTimer = 0x55;
+const u8 gbTimerMask [4] = {0xff, 0x3, 0xf, 0x3f};
+const u8 gbTimerBug [8] = {0x80, 0x80, 0x02, 0x02, 0x0, 0xff, 0x0, 0xff};
+bool gbTimerModeChange = false;
+bool gbTimerOnChange = false;
+// lcd
+bool gbScreenOn = true;
+int gbLcdMode = 2;
+int gbLcdModeDelayed = 2;
+int gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS-1;
+int gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS;
+int gbLcdLYIncrementTicks = 114;
+int gbLcdLYIncrementTicksDelayed = 115;
+int gbScreenTicks = 0;
+u8 gbSCYLine[300];
+u8 gbSCXLine[300];
+u8 gbBgpLine[300];
+u8 gbObp0Line [300];
+u8 gbObp1Line [300];
+u8 gbSpritesTicks [300];
+u8 oldRegister_WY;
+bool gbLYChangeHappened = false;
+bool gbLCDChangeHappened = false;
+int gbLine99Ticks = 1;
+int gbRegisterLYLCDCOffOn = 0;
+int inUseRegister_WY = 0;
+
+// Used to keep track of the line that ellapse
+// when screen is off
+int gbWhiteScreen = 0;
+bool gbBlackScreen = false;
+int register_LCDCBusy = 0;
+
+// div
+int gbDivTicks = GBDIV_CLOCK_TICKS;
+// cgb
+int gbVramBank = 0;
+int gbWramBank = 1;
+//sgb
+bool gbSgbResetFlag = false;
+// gbHdmaDestination is 0x99d0 on startup (tested on HW)
+// but I'm not sure what gbHdmaSource is...
+int gbHdmaSource = 0x99d0;
+int gbHdmaDestination = 0x99d0;
+int gbHdmaBytes = 0x0000;
+int gbHdmaOn = 0;
+int gbSpeed = 0;
+// frame counting
+int gbFrameCount = 0;
+int gbFrameSkip = 0;
+int gbFrameSkipCount = 0;
+// timing
+u32 gbLastTime = 0;
+u32 gbElapsedTime = 0;
+u32 gbTimeNow = 0;
+int gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS;
+// emulator features
+int gbBattery = 0;
+bool gbBatteryError = false;
+int gbCaptureNumber = 0;
+bool gbCapture = false;
+bool gbCapturePrevious = false;
+int gbJoymask[4] = { 0, 0, 0, 0 };
+
+int gbRomSizes[] = { 0x00008000, // 32K
+ 0x00010000, // 64K
+ 0x00020000, // 128K
+ 0x00040000, // 256K
+ 0x00080000, // 512K
+ 0x00100000, // 1024K
+ 0x00200000, // 2048K
+ 0x00400000, // 4096K
+ 0x00800000 // 8192K
+};
+int gbRomSizesMasks[] = { 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff
+};
+
+int gbRamSizes[6] = { 0x00000000, // 0K
+ 0x00002000, // 2K // Changed to 2000 to avoid problems with gbMemoryMap...
+ 0x00002000, // 8K
+ 0x00008000, // 32K
+ 0x00020000, // 128K
+ 0x00010000 // 64K
+};
+
+int gbRamSizesMasks[6] = { 0x00000000,
+ 0x000007ff,
+ 0x00001fff,
+ 0x00007fff,
+ 0x0001ffff,
+ 0x0000ffff
+};
+
+int gbCycles[] = {
+// 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0
+ 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1
+ 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2
+ 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6
+ 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b
+ 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c
+ 2, 3, 3, 1, 3, 4, 2, 4, 2, 4, 3, 1, 3, 1, 2, 4, // d
+ 3, 3, 2, 1, 1, 4, 2, 4, 4, 1, 4, 1, 1, 1, 2, 4, // e
+ 3, 3, 2, 1, 1, 4, 2, 4, 3, 2, 4, 1, 0, 1, 2, 4 // f
+};
+
+int gbCyclesCB[] = {
+// 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 8
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 9
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // a
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // b
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // c
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // d
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // e
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2 // f
+};
+
+u16 DAATable[] = {
+ 0x0080,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,
+ 0x0800,0x0900,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520,
+ 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700,
+ 0x1800,0x1900,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,
+ 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700,
+ 0x2800,0x2900,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,
+ 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x3600,0x3700,
+ 0x3800,0x3900,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520,
+ 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,
+ 0x4800,0x4900,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520,
+ 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700,
+ 0x5800,0x5900,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,
+ 0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,
+ 0x6800,0x6900,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,
+ 0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x7600,0x7700,
+ 0x7800,0x7900,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520,
+ 0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x8600,0x8700,
+ 0x8800,0x8900,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520,
+ 0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x9600,0x9700,
+ 0x9800,0x9900,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
+ 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710,
+ 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
+ 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
+ 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
+ 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710,
+ 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
+ 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710,
+ 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
+ 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710,
+ 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
+ 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
+ 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
+ 0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,0x6610,0x6710,
+ 0x6810,0x6910,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,
+ 0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,0x7610,0x7710,
+ 0x7810,0x7910,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530,
+ 0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,0x8610,0x8710,
+ 0x8810,0x8910,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530,
+ 0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,0x9610,0x9710,
+ 0x9810,0x9910,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530,
+ 0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,0xA610,0xA710,
+ 0xA810,0xA910,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530,
+ 0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,0xB610,0xB710,
+ 0xB810,0xB910,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530,
+ 0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,0xC610,0xC710,
+ 0xC810,0xC910,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530,
+ 0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,0xD610,0xD710,
+ 0xD810,0xD910,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530,
+ 0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,0xE610,0xE710,
+ 0xE810,0xE910,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530,
+ 0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,0xF610,0xF710,
+ 0xF810,0xF910,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
+ 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710,
+ 0x0810,0x0910,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
+ 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
+ 0x1810,0x1910,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
+ 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710,
+ 0x2810,0x2910,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
+ 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710,
+ 0x3810,0x3910,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
+ 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710,
+ 0x4810,0x4910,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
+ 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
+ 0x5810,0x5910,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
+ 0x0600,0x0700,0x0800,0x0900,0x0A00,0x0B00,0x0C00,0x0D00,
+ 0x0E00,0x0F00,0x1020,0x1120,0x1220,0x1320,0x1420,0x1520,
+ 0x1600,0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00,
+ 0x1E00,0x1F00,0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,
+ 0x2600,0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2C00,0x2D00,
+ 0x2E00,0x2F00,0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,
+ 0x3600,0x3700,0x3800,0x3900,0x3A00,0x3B00,0x3C00,0x3D00,
+ 0x3E00,0x3F00,0x4020,0x4120,0x4220,0x4320,0x4420,0x4520,
+ 0x4600,0x4700,0x4800,0x4900,0x4A00,0x4B00,0x4C00,0x4D00,
+ 0x4E00,0x4F00,0x5020,0x5120,0x5220,0x5320,0x5420,0x5520,
+ 0x5600,0x5700,0x5800,0x5900,0x5A00,0x5B00,0x5C00,0x5D00,
+ 0x5E00,0x5F00,0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,
+ 0x6600,0x6700,0x6800,0x6900,0x6A00,0x6B00,0x6C00,0x6D00,
+ 0x6E00,0x6F00,0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,
+ 0x7600,0x7700,0x7800,0x7900,0x7A00,0x7B00,0x7C00,0x7D00,
+ 0x7E00,0x7F00,0x8020,0x8120,0x8220,0x8320,0x8420,0x8520,
+ 0x8600,0x8700,0x8800,0x8900,0x8A00,0x8B00,0x8C00,0x8D00,
+ 0x8E00,0x8F00,0x9020,0x9120,0x9220,0x9320,0x9420,0x9520,
+ 0x9600,0x9700,0x9800,0x9900,0x9A00,0x9B00,0x9C00,0x9D00,
+ 0x9E00,0x9F00,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
+ 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10,
+ 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
+ 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10,
+ 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
+ 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10,
+ 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
+ 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10,
+ 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
+ 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10,
+ 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
+ 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10,
+ 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
+ 0x6610,0x6710,0x6810,0x6910,0x6A10,0x6B10,0x6C10,0x6D10,
+ 0x6E10,0x6F10,0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,
+ 0x7610,0x7710,0x7810,0x7910,0x7A10,0x7B10,0x7C10,0x7D10,
+ 0x7E10,0x7F10,0x8030,0x8130,0x8230,0x8330,0x8430,0x8530,
+ 0x8610,0x8710,0x8810,0x8910,0x8A10,0x8B10,0x8C10,0x8D10,
+ 0x8E10,0x8F10,0x9030,0x9130,0x9230,0x9330,0x9430,0x9530,
+ 0x9610,0x9710,0x9810,0x9910,0x9A10,0x9B10,0x9C10,0x9D10,
+ 0x9E10,0x9F10,0xA030,0xA130,0xA230,0xA330,0xA430,0xA530,
+ 0xA610,0xA710,0xA810,0xA910,0xAA10,0xAB10,0xAC10,0xAD10,
+ 0xAE10,0xAF10,0xB030,0xB130,0xB230,0xB330,0xB430,0xB530,
+ 0xB610,0xB710,0xB810,0xB910,0xBA10,0xBB10,0xBC10,0xBD10,
+ 0xBE10,0xBF10,0xC030,0xC130,0xC230,0xC330,0xC430,0xC530,
+ 0xC610,0xC710,0xC810,0xC910,0xCA10,0xCB10,0xCC10,0xCD10,
+ 0xCE10,0xCF10,0xD030,0xD130,0xD230,0xD330,0xD430,0xD530,
+ 0xD610,0xD710,0xD810,0xD910,0xDA10,0xDB10,0xDC10,0xDD10,
+ 0xDE10,0xDF10,0xE030,0xE130,0xE230,0xE330,0xE430,0xE530,
+ 0xE610,0xE710,0xE810,0xE910,0xEA10,0xEB10,0xEC10,0xED10,
+ 0xEE10,0xEF10,0xF030,0xF130,0xF230,0xF330,0xF430,0xF530,
+ 0xF610,0xF710,0xF810,0xF910,0xFA10,0xFB10,0xFC10,0xFD10,
+ 0xFE10,0xFF10,0x00B0,0x0130,0x0230,0x0330,0x0430,0x0530,
+ 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10,
+ 0x0E10,0x0F10,0x1030,0x1130,0x1230,0x1330,0x1430,0x1530,
+ 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10,
+ 0x1E10,0x1F10,0x2030,0x2130,0x2230,0x2330,0x2430,0x2530,
+ 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10,
+ 0x2E10,0x2F10,0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,
+ 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10,
+ 0x3E10,0x3F10,0x4030,0x4130,0x4230,0x4330,0x4430,0x4530,
+ 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10,
+ 0x4E10,0x4F10,0x5030,0x5130,0x5230,0x5330,0x5430,0x5530,
+ 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10,
+ 0x5E10,0x5F10,0x6030,0x6130,0x6230,0x6330,0x6430,0x6530,
+ 0x00C0,0x0140,0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,
+ 0x0840,0x0940,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940,
+ 0x1040,0x1140,0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,
+ 0x1840,0x1940,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940,
+ 0x2040,0x2140,0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,
+ 0x2840,0x2940,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940,
+ 0x3040,0x3140,0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,
+ 0x3840,0x3940,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940,
+ 0x4040,0x4140,0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,
+ 0x4840,0x4940,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940,
+ 0x5040,0x5140,0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,
+ 0x5840,0x5940,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940,
+ 0x6040,0x6140,0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,
+ 0x6840,0x6940,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940,
+ 0x7040,0x7140,0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,
+ 0x7840,0x7940,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940,
+ 0x8040,0x8140,0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,
+ 0x8840,0x8940,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940,
+ 0x9040,0x9140,0x9240,0x9340,0x9440,0x9540,0x9640,0x9740,
+ 0x9840,0x9940,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
+ 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,
+ 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
+ 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,
+ 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
+ 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,
+ 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
+ 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,
+ 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
+ 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,
+ 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
+ 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,
+ 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
+ 0xA050,0xA150,0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,
+ 0xA850,0xA950,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950,
+ 0xB050,0xB150,0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,
+ 0xB850,0xB950,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950,
+ 0xC050,0xC150,0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,
+ 0xC850,0xC950,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950,
+ 0xD050,0xD150,0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,
+ 0xD850,0xD950,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950,
+ 0xE050,0xE150,0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,
+ 0xE850,0xE950,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950,
+ 0xF050,0xF150,0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,
+ 0xF850,0xF950,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950,
+ 0x00D0,0x0150,0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,
+ 0x0850,0x0950,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950,
+ 0x1050,0x1150,0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,
+ 0x1850,0x1950,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950,
+ 0x2050,0x2150,0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,
+ 0x2850,0x2950,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950,
+ 0x3050,0x3150,0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,
+ 0x3850,0x3950,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
+ 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,
+ 0x4850,0x4950,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
+ 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,
+ 0x5850,0x5950,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
+ 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,
+ 0x6850,0x6950,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
+ 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,
+ 0x7850,0x7950,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
+ 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,
+ 0x8850,0x8950,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
+ 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,
+ 0x9850,0x9950,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
+ 0xFA60,0xFB60,0xFC60,0xFD60,0xFE60,0xFF60,0x00C0,0x0140,
+ 0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940,
+ 0x0A60,0x0B60,0x0C60,0x0D60,0x0E60,0x0F60,0x1040,0x1140,
+ 0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940,
+ 0x1A60,0x1B60,0x1C60,0x1D60,0x1E60,0x1F60,0x2040,0x2140,
+ 0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940,
+ 0x2A60,0x2B60,0x2C60,0x2D60,0x2E60,0x2F60,0x3040,0x3140,
+ 0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940,
+ 0x3A60,0x3B60,0x3C60,0x3D60,0x3E60,0x3F60,0x4040,0x4140,
+ 0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940,
+ 0x4A60,0x4B60,0x4C60,0x4D60,0x4E60,0x4F60,0x5040,0x5140,
+ 0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940,
+ 0x5A60,0x5B60,0x5C60,0x5D60,0x5E60,0x5F60,0x6040,0x6140,
+ 0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940,
+ 0x6A60,0x6B60,0x6C60,0x6D60,0x6E60,0x6F60,0x7040,0x7140,
+ 0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940,
+ 0x7A60,0x7B60,0x7C60,0x7D60,0x7E60,0x7F60,0x8040,0x8140,
+ 0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940,
+ 0x8A60,0x8B60,0x8C60,0x8D60,0x8E60,0x8F60,0x9040,0x9140,
+ 0x9240,0x9340,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
+ 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150,
+ 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
+ 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150,
+ 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
+ 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150,
+ 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
+ 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150,
+ 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
+ 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150,
+ 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
+ 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150,
+ 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
+ 0x9A70,0x9B70,0x9C70,0x9D70,0x9E70,0x9F70,0xA050,0xA150,
+ 0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950,
+ 0xAA70,0xAB70,0xAC70,0xAD70,0xAE70,0xAF70,0xB050,0xB150,
+ 0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950,
+ 0xBA70,0xBB70,0xBC70,0xBD70,0xBE70,0xBF70,0xC050,0xC150,
+ 0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950,
+ 0xCA70,0xCB70,0xCC70,0xCD70,0xCE70,0xCF70,0xD050,0xD150,
+ 0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950,
+ 0xDA70,0xDB70,0xDC70,0xDD70,0xDE70,0xDF70,0xE050,0xE150,
+ 0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950,
+ 0xEA70,0xEB70,0xEC70,0xED70,0xEE70,0xEF70,0xF050,0xF150,
+ 0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950,
+ 0xFA70,0xFB70,0xFC70,0xFD70,0xFE70,0xFF70,0x00D0,0x0150,
+ 0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950,
+ 0x0A70,0x0B70,0x0C70,0x0D70,0x0E70,0x0F70,0x1050,0x1150,
+ 0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950,
+ 0x1A70,0x1B70,0x1C70,0x1D70,0x1E70,0x1F70,0x2050,0x2150,
+ 0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950,
+ 0x2A70,0x2B70,0x2C70,0x2D70,0x2E70,0x2F70,0x3050,0x3150,
+ 0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
+ 0x3A70,0x3B70,0x3C70,0x3D70,0x3E70,0x3F70,0x4050,0x4150,
+ 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
+ 0x4A70,0x4B70,0x4C70,0x4D70,0x4E70,0x4F70,0x5050,0x5150,
+ 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
+ 0x5A70,0x5B70,0x5C70,0x5D70,0x5E70,0x5F70,0x6050,0x6150,
+ 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
+ 0x6A70,0x6B70,0x6C70,0x6D70,0x6E70,0x6F70,0x7050,0x7150,
+ 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
+ 0x7A70,0x7B70,0x7C70,0x7D70,0x7E70,0x7F70,0x8050,0x8150,
+ 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
+ 0x8A70,0x8B70,0x8C70,0x8D70,0x8E70,0x8F70,0x9050,0x9150,
+ 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
+};
+
+u8 ZeroTable[256] = {
+ 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0
+};
+
+#define GBSAVE_GAME_VERSION_1 1
+#define GBSAVE_GAME_VERSION_2 2
+#define GBSAVE_GAME_VERSION_3 3
+#define GBSAVE_GAME_VERSION_4 4
+#define GBSAVE_GAME_VERSION_5 5
+#define GBSAVE_GAME_VERSION_6 6
+#define GBSAVE_GAME_VERSION_7 7
+#define GBSAVE_GAME_VERSION_8 8
+#define GBSAVE_GAME_VERSION_9 9
+#define GBSAVE_GAME_VERSION_10 10
+#define GBSAVE_GAME_VERSION_11 11
+#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_11
+
+int inline gbGetValue(int min,int max,int v)
+{
+ return (int)(min+(float)(max-min)*(2.0*(v/31.0)-(v/31.0)*(v/31.0)));
+}
+
+void gbGenFilter()
+{
+ for (int r=0;r<32;r++) {
+ for (int g=0;g<32;g++) {
+ for (int b=0;b<32;b++) {
+ int nr=gbGetValue(gbGetValue(4,14,g),
+ gbGetValue(24,29,g),r)-4;
+ int ng=gbGetValue(gbGetValue(4+gbGetValue(0,5,r),
+ 14+gbGetValue(0,3,r),b),
+ gbGetValue(24+gbGetValue(0,3,r),
+ 29+gbGetValue(0,1,r),b),g)-4;
+ int nb=gbGetValue(gbGetValue(4+gbGetValue(0,5,r),
+ 14+gbGetValue(0,3,r),g),
+ gbGetValue(24+gbGetValue(0,3,r),
+ 29+gbGetValue(0,1,r),g),b)-4;
+ gbColorFilter[(b<<10)|(g<<5)|r]=(nb<<10)|(ng<<5)|nr;
+ }
+ }
+ }
+}
+
+bool gbIsGameboyRom(char * file)
+{
+ if(strlen(file) > 4) {
+ char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".gb") == 0)
+ return true;
+ if(_stricmp(p, ".gbc") == 0)
+ return true;
+ if(_stricmp(p, ".cgb") == 0)
+ return true;
+ if(_stricmp(p, ".sgb") == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void gbCopyMemory(u16 d, u16 s, int count)
+{
+ while(count) {
+ gbMemoryMap[d>>12][d & 0x0fff] = gbMemoryMap[s>>12][s & 0x0fff];
+ s++;
+ d++;
+ count--;
+ }
+}
+
+void gbDoHdma()
+{
+
+ gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000,
+ gbHdmaSource & 0xfff0,
+ 0x10);
+
+ gbHdmaDestination += 0x10;
+ if (gbHdmaDestination == 0xa000)
+ gbHdmaDestination = 0x8000;
+
+ gbHdmaSource += 0x10;
+ if (gbHdmaSource == 0x8000)
+ gbHdmaSource = 0xa000;
+
+ register_HDMA2 = gbHdmaSource & 0xff;
+ register_HDMA1 = gbHdmaSource>>8;
+
+ register_HDMA4 = gbHdmaDestination & 0xff;
+ register_HDMA3 = gbHdmaDestination>>8;
+
+ gbHdmaBytes -= 0x10;
+ gbMemory[0xff55] = --register_HDMA5;
+ if(register_HDMA5 == 0xff)
+ gbHdmaOn = 0;
+
+// We need to add the dmaClockticks for HDMA !
+ if(gbSpeed)
+ gbDmaTicks = 17;
+ else
+ gbDmaTicks = 9;
+
+ if (IFF & 0x80)
+ gbDmaTicks++;
+
+}
+
+// fix for Harley and Lego Racers
+void gbCompareLYToLYC()
+{
+ if(register_LCDC & 0x80) {
+ if(register_LY == register_LYC) {
+
+ // mark that we have a match
+ register_STAT |= 4;
+
+ // check if we need an interrupt
+ if (register_STAT & 0x40)
+ {
+ // send LCD interrupt only if no interrupt 48h signal...
+ if (!gbInt48Signal)
+ {
+ register_IF |=2;
+ }
+ gbInt48Signal |= 8;
+ }
+ }
+ else // no match
+ {
+ register_STAT &= 0xfb;
+ gbInt48Signal &=~8;
+ }
+ }
+}
+
+void gbWriteMemory(register u16 address, register u8 value)
+{
+
+ if(address < 0x8000) {
+#ifndef FINAL_VERSION
+ if(memorydebug && (address>0x3fff || address < 0x2000)) {
+ log("Memory register write %04x=%02x PC=%04x\n",
+ address,
+ value,
+ PC.W);
+ }
+
+#endif
+ if(mapper)
+ (*mapper)(address, value);
+ return;
+
+ }
+
+ if(address < 0xa000) {
+ // No access to Vram during mode 3
+ // (used to emulate the gfx differences between GB & GBC-GBA/SP in Stunt Racer)
+ if ((gbLcdModeDelayed !=3) ||
+ // This part is used to emulate a small difference between hardwares
+ // (check 8-in-1's arrow on GBA/GBC to verify it)
+ ((register_LY == 0) && ((gbHardware & 0xa) && (gbScreenOn==false) &&
+ (register_LCDC & 0x80)) &&
+ (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS))))
+ gbMemoryMap[address>>12][address&0x0fff] = value;
+ return;
+ }
+
+ // Used for the mirroring of 0xC000 in 0xE000
+ if ((address >= 0xe000) && (address < 0xfe00))
+ address &= ~0x2000;
+
+ if(address < 0xc000) {
+#ifndef FINAL_VERSION
+ if(memorydebug) {
+ log("Memory register write %04x=%02x PC=%04x\n",
+ address,
+ value,
+ PC.W);
+ }
+#endif
+
+ // Is that a correct fix ??? (it used to be 'if (mapper)')...
+ if(mapperRAM)
+ (*mapperRAM)(address, value);
+ return;
+ }
+
+
+ if(address < 0xfe00) {
+ gbMemoryMap[address>>12][address & 0x0fff] = value;
+ return;
+ }
+
+ // OAM not accessible during mode 2 & 3.
+ if(address < 0xfea0)
+ {
+ if (((gbHardware & 0xa) && ((gbLcdMode | gbLcdModeDelayed) &2)) ||
+ ((gbHardware & 5) && (((gbLcdModeDelayed == 2) &&
+ (gbLcdTicksDelayed<=GBLCD_MODE_2_CLOCK_TICKS)) ||
+ (gbLcdModeDelayed == 3))))
+ return;
+ else
+ {
+ gbMemory[address] = value;
+ return;
+ }
+ }
+
+
+
+ if((address > 0xfea0) && (address < 0xff00)){ // GBC allows reading/writing to that area
+ gbMemory[address] = value;
+ return;
+ }
+
+ switch(address & 0x00ff) {
+
+ case 0x00: {
+ gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) |
+ (value & 0x30) | 0xc0);
+ if(gbSgbMode) {
+ gbSgbDoBitTransfer(value);
+ }
+ return;
+ }
+
+ case 0x01: {
+ gbMemory[0xff01] = value;
+ return;
+ }
+
+ // serial control
+ case 0x02: {
+ gbSerialOn = (value & 0x80);
+ gbMemory[0xff02] = value;
+ if(gbSerialOn) {
+ gbSerialTicks = GBSERIAL_CLOCK_TICKS;
+#ifdef LINK_EMULATION
+ if(linkConnected) {
+ if(value & 1) {
+ linkSendByte(0x100|gbMemory[0xFF01]);
+ Sleep(5);
+ }
+ }
+#endif
+ }
+
+ gbSerialBits = 0;
+ return;
+ }
+
+ case 0x04: {
+ // DIV register resets on any write
+ // (not totally perfect, but better than nothing)
+ gbMemory[0xff04] = register_DIV = 0;
+ gbDivTicks = GBDIV_CLOCK_TICKS;
+ // Another weird timer 'bug' :
+ // Writing to DIV register resets the internal timer,
+ // and can also increase TIMA/trigger an interrupt
+ // in some cases...
+ if (gbTimerOn && !(gbInternalTimer & (gbTimerClockTicks>>1)))
+ {
+ gbMemory[0xff05] = ++register_TIMA;
+ if(register_TIMA == 0) {
+ // timer overflow!
+
+ // reload timer modulo
+ gbMemory[0xff05] = register_TIMA = register_TMA;
+
+ // flag interrupt
+ gbMemory[0xff0f] = register_IF |= 4;
+ }
+ }
+ gbInternalTimer = 0xff;
+ return;
+ }
+ case 0x05:
+ gbMemory[0xff05] = register_TIMA = value;
+ return;
+
+ case 0x06:
+ gbMemory[0xff06] = register_TMA = value;
+ return;
+
+ // TIMER control
+ case 0x07: {
+
+ gbTimerModeChange = (((value & 3) != (register_TAC&3)) && (value & register_TAC & 4)) ? true : false;
+ gbTimerOnChange = (((value ^ register_TAC) & 4) == 4) ? true : false;
+
+ gbTimerOn = (value & 4) ? true : false;
+
+ if (gbTimerOnChange || gbTimerModeChange)
+ {
+ gbTimerMode = value & 3;
+
+ switch(gbTimerMode) {
+ case 0:
+ gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS;
+ break;
+ case 1:
+ gbTimerClockTicks = GBTIMER_MODE_1_CLOCK_TICKS;
+ break;
+ case 2:
+ gbTimerClockTicks = GBTIMER_MODE_2_CLOCK_TICKS;
+ break;
+ case 3:
+ gbTimerClockTicks = GBTIMER_MODE_3_CLOCK_TICKS;
+ break;
+ }
+ }
+
+
+ // This looks weird, but this emulates a bug in which register_TIMA
+ // is increased when writing to register_TAC
+ // (This fixes Korodice's long-delay between menus bug).
+
+ if (gbTimerOnChange || gbTimerModeChange)
+ {
+ bool temp = false;
+
+ if ((gbTimerOn && !gbTimerModeChange) && (gbTimerMode & 2) &&
+ !(gbInternalTimer & 0x80) && (gbInternalTimer & (gbTimerClockTicks>>1)) &&
+ !(gbInternalTimer & (gbTimerClockTicks>>5)))
+ temp = true;
+ else if ((!gbTimerOn && !gbTimerModeChange && gbTimerOnChange ) && ((gbTimerTicks-1) < (gbTimerClockTicks>>1)))
+ temp = true;
+ else if (gbTimerOn && gbTimerModeChange && !gbTimerOnChange)
+ {
+ switch(gbTimerMode & 3)
+ {
+ case 0x00:
+ temp = false;
+ break;
+ case 0x01:
+ if (((gbInternalTimer & 0x82) == 2) && (gbTimerTicks>(clockTicks+1)))
+ temp = true;
+ break;
+ case 0x02:
+ if (((gbInternalTimer & 0x88) == 0x8) && (gbTimerTicks>(clockTicks+1)))
+ temp = true;
+ break;
+ case 0x03:
+ if (((gbInternalTimer & 0xA0) == 0x20) && (gbTimerTicks>(clockTicks+1)))
+ temp = true;
+ break;
+ }
+ }
+
+ if (temp)
+ {
+ gbMemory[0xff05] = ++register_TIMA;
+ if((register_TIMA & 0xff) == 0) {
+ // timer overflow!
+
+ // reload timer modulo
+ gbMemory[0xff05] = register_TIMA = register_TMA;
+
+ // flag interrupt
+ gbMemory[0xff0f] = register_IF |= 4;
+ }
+ }
+ }
+ gbMemory[0xff07] = register_TAC = value;
+ return;
+ }
+
+ case 0x0f: {
+ gbMemory[0xff0f] = register_IF = value;
+ //gbMemory[0xff0f] = register_IE |= value;
+ return;
+ }
+
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25: {
+ if (gbMemory[NR52] & 0x80) {
+ SOUND_EVENT(address,value);
+ return;
+ }
+ }
+
+ case 0x26: {
+ SOUND_EVENT(address,value);
+ return;
+ }
+
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: {
+ gbMemory[address] = value;
+ return;
+ }
+
+ case 0x40: {
+ int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80);
+
+ // don't draw the window if it was not enabled and not being drawn before
+ if(!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 &&
+ register_LY > register_WY)
+ gbWindowLine = 146;
+ // 007 fix : don't draw the first window's 1st line if it's enable 'too late'
+ // (ie. if register_LY == register_WY when enabling it)
+ // and move it to the next line
+ else if (!(register_LCDC & 0x20) && (value & 0x20) && (register_LY == register_WY))
+ gbWindowLine = -2;
+
+
+ gbMemory[0xff40] = register_LCDC = value;
+
+
+ if(lcdChange) {
+ if((value & 0x80) && (!register_LCDCBusy)) {
+
+ // if (!gbWhiteScreen && !gbSgbMask)
+
+ // systemDrawScreen();
+
+
+
+ gbRegisterLYLCDCOffOn = (register_LY + 144) % 154;
+
+ gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 2 : 1);
+ gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 1 : 0);
+ gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 2 : 1);
+ gbLcdLYIncrementTicksDelayed = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 1 : 0);
+ gbLcdMode = 2;
+ gbLcdModeDelayed = 2;
+ gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | 2;
+ gbMemory[0xff44] = register_LY = 0x00;
+ gbInt48Signal = 0;
+ gbLYChangeHappened = false;
+ gbLCDChangeHappened = false;
+ gbWindowLine = 146;
+ oldRegister_WY = 146;
+
+ // Fix for Namco Gallery Vol.2
+ // (along with updating register_LCDC at the start of 'case 0x40') :
+ if(register_STAT & 0x20)
+ {
+ // send LCD interrupt only if no interrupt 48h signal...
+ if (!gbInt48Signal)
+ {
+ gbMemory[0xff0f] = register_IF |= 2;
+ }
+ gbInt48Signal |= 4;
+ }
+ gbCompareLYToLYC();
+
+ } else {
+
+ register_LCDCBusy = clockTicks+6;
+
+ //used to update the screen with white lines when it's off.
+ //(it looks strange, but it's pretty accurate)
+
+ gbWhiteScreen = 0;
+
+ gbScreenTicks = ((150-register_LY)*GBLY_INCREMENT_CLOCK_TICKS +
+ (49<<(gbSpeed ? 1 : 0)));
+
+ // disable the screen rendering
+ gbScreenOn = false;
+ gbLcdTicks = 0;
+ gbLcdMode = 0;
+ gbLcdModeDelayed = 0;
+ gbMemory[0xff41] = register_STAT &= 0xfc;
+ gbInt48Signal = 0;
+ }
+ }
+ return;
+ }
+
+ // STAT
+ case 0x41: {
+ //register_STAT = (register_STAT & 0x87) |
+ // (value & 0x7c);
+ gbMemory[0xff41] = register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ?
+ // GB bug from Devrs FAQ
+ // Corrected : it happens if Lcd Mode<2, but also if LY == LYC whatever
+ // Lcd Mode is, and if !gbInt48Signal in all cases. The screen being off
+ // doesn't matter (the bug will still happen).
+ // That fixes 'Satoru Nakajima - F-1 Hero' crash bug.
+
+ if((gbHardware & 5) && (((!gbInt48Signal) && (gbLcdMode<2) && (register_LCDC & 0x80)) ||
+ (register_LY == register_LYC)))
+ {
+ gbMemory[0xff0f] = register_IF |=2;
+ }
+
+ gbInt48Signal &= ((register_STAT>>3) & 0xF);
+
+ if((register_LCDC & 0x80)) {
+ if ((register_STAT & 0x08) && (gbLcdMode == 0))
+ {
+ if (!gbInt48Signal)
+ {
+ gbMemory[0xff0f] = register_IF |=2;
+ }
+ gbInt48Signal |= 1;
+ }
+ if ((register_STAT & 0x10) && (gbLcdMode == 1))
+ {
+ if (!gbInt48Signal)
+ {
+ gbMemory[0xff0f] = register_IF |=2;
+ }
+ gbInt48Signal |= 2;
+ }
+ if ((register_STAT & 0x20) && (gbLcdMode == 2))
+ {
+ if (!gbInt48Signal)
+ {
+ gbMemory[0xff0f] = register_IF |=2;
+ }
+ gbInt48Signal |= 4;
+ }
+ gbCompareLYToLYC();
+
+ gbMemory[0xff0f] = register_IF;
+ gbMemory[0xff41] = register_STAT;
+
+ }
+ return;
+ }
+
+ // SCY
+ case 0x42: {
+ int temp = -1;
+
+ if ((gbLcdMode == 3) || (gbLcdModeDelayed == 3))
+ temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
+ gbLcdLYIncrementTicks);
+
+ if (temp >=0)
+ {
+ for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
+ if (temp < 300)
+ gbSCYLine[i] = value;
+ }
+
+ else
+ memset(gbSCYLine, value, sizeof(gbSCYLine));
+
+ gbMemory[0xff42] = register_SCY = value;
+ return;
+ }
+
+ // SCX
+ case 0x43: {
+ int temp = -1;
+
+ if (gbLcdModeDelayed == 3)
+ temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
+ gbLcdLYIncrementTicksDelayed);
+
+ if (temp >=0)
+ {
+ for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
+ if (temp < 300)
+ gbSCXLine[i] = value;
+ }
+
+ else
+ memset(gbSCXLine, value, sizeof(gbSCXLine));
+
+ gbMemory[0xff43] = register_SCX = value;
+ return;
+ }
+
+ // LY
+ case 0x44: {
+ // read only
+ return;
+ }
+
+ // LYC
+ case 0x45: {
+ if (register_LYC != value)
+ {
+ gbMemory[0xff45] = register_LYC = value;
+ if(register_LCDC & 0x80) {
+ gbCompareLYToLYC();
+ }
+ }
+ return;
+ }
+
+ // DMA!
+ case 0x46: {
+ int source = value * 0x0100;
+
+ gbCopyMemory(0xfe00,
+ source,
+ 0xa0);
+ gbMemory[0xff46] = register_DMA = value;
+ return;
+ }
+
+ // BGP
+ case 0x47: {
+
+ int temp = -1;
+
+ gbMemory[0xff47] = value;
+
+ if (gbLcdModeDelayed == 3)
+ temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
+ gbLcdLYIncrementTicksDelayed);
+
+ if (temp >=0)
+ {
+ for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
+ if (temp < 300)
+ gbBgpLine[i] = value;
+ }
+ else
+ memset(gbBgpLine,value,sizeof(gbBgpLine));
+
+ gbBgp[0] = value & 0x03;
+ gbBgp[1] = (value & 0x0c)>>2;
+ gbBgp[2] = (value & 0x30)>>4;
+ gbBgp[3] = (value & 0xc0)>>6;
+ break;
+ }
+
+ // OBP0
+ case 0x48: {
+ int temp = -1;
+
+ gbMemory[0xff48] = value;
+
+ if (gbLcdModeDelayed == 3)
+ temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
+ gbLcdLYIncrementTicksDelayed);
+
+ if (temp >=0)
+ {
+ for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
+ if (temp < 300)
+ gbObp0Line[i] = value;
+ }
+ else
+ memset(gbObp0Line,value,sizeof(gbObp0Line));
+
+ gbObp0[0] = value & 0x03;
+ gbObp0[1] = (value & 0x0c)>>2;
+ gbObp0[2] = (value & 0x30)>>4;
+ gbObp0[3] = (value & 0xc0)>>6;
+ break;
+ }
+
+ // OBP1
+ case 0x49: {
+ int temp = -1;
+
+ gbMemory[0xff49] = value;
+
+ if (gbLcdModeDelayed == 3)
+ temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
+ gbLcdLYIncrementTicksDelayed);
+
+ if (temp >=0)
+ {
+ for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
+ if (temp < 300)
+ gbObp1Line[i] = value;
+ }
+ else
+ memset(gbObp1Line,value,sizeof(gbObp1Line));
+
+ gbObp1[0] = value & 0x03;
+ gbObp1[1] = (value & 0x0c)>>2;
+ gbObp1[2] = (value & 0x30)>>4;
+ gbObp1[3] = (value & 0xc0)>>6;
+ break;
+ }
+
+ // WY
+ case 0x4a:
+ gbMemory[0xff4a] = register_WY = value;
+ if ((register_LY <= register_WY) && ((gbWindowLine < 0) || (gbWindowLine>=144)))
+ {
+ gbWindowLine = -1;
+ oldRegister_WY = register_WY;
+ }
+ return;
+
+ // WX
+ case 0x4b:
+ gbMemory[0xff4b] = register_WX = value;
+ return;
+
+ // KEY1
+ case 0x4d: {
+ if(gbCgbMode) {
+ gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1) | 0x7e;
+ return;
+ }
+ }
+ break;
+
+ // VBK
+ case 0x4f: {
+ if(gbCgbMode) {
+ value = value & 1;
+ if(value == gbVramBank)
+ return;
+
+ int vramAddress = value * 0x2000;
+ gbMemoryMap[0x08] = &gbVram[vramAddress];
+ gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000];
+
+ gbVramBank = value;
+ register_VBK = value;
+ }
+ return;
+ }
+ break;
+
+ // BOOTROM disable register (also gbCgbMode enabler if value & 0x10 ?)
+ case 0x50 :
+ {
+ if (useBios && inBios && !skipBios && (value & 1))
+ {
+ gbMemoryMap[0x00] = &gbRom[0x0000];
+ memcpy ((u8 *)(gbRom+0x100), (u8 *)(gbMemory + 0x100), 0xF00);
+ inBios = false;
+ }
+ }
+
+ // HDMA1
+ case 0x51: {
+ if(gbCgbMode) {
+ if(value > 0x7f && value < 0xa0)
+ value = 0;
+
+ gbHdmaSource = (value << 8) | (gbHdmaSource & 0xf0);
+
+ register_HDMA1 = value;
+ return;
+ }
+ }
+ break;
+
+ // HDMA2
+ case 0x52: {
+ if(gbCgbMode) {
+ value = value & 0xf0;
+
+ gbHdmaSource = (gbHdmaSource & 0xff00) | (value);
+
+ register_HDMA2 = value;
+ return;
+ }
+ }
+ break;
+
+ // HDMA3
+ case 0x53: {
+ if(gbCgbMode) {
+ value = value & 0x1f;
+ gbHdmaDestination = (value << 8) | (gbHdmaDestination & 0xf0);
+ gbHdmaDestination |= 0x8000;
+ register_HDMA3 = value;
+ return;
+ }
+ }
+ break;
+
+ // HDMA4
+ case 0x54: {
+ if(gbCgbMode) {
+ value = value & 0xf0;
+ gbHdmaDestination = (gbHdmaDestination & 0x1f00) | value;
+ gbHdmaDestination |= 0x8000;
+ register_HDMA4 = value;
+ return;
+ }
+ }
+ break;
+
+ // HDMA5
+ case 0x55: {
+
+ if(gbCgbMode) {
+ gbHdmaBytes = 16 + (value & 0x7f) * 16;
+ if(gbHdmaOn) {
+ if(value & 0x80) {
+ gbMemory[0xff55] = register_HDMA5 = (value & 0x7f);
+ } else {
+ register_HDMA5 = 0xff;
+ gbHdmaOn = 0;
+ }
+ } else {
+ if(value & 0x80) {
+ gbHdmaOn = 1;
+ gbMemory[0xff55] = register_HDMA5 = value & 0x7f;
+ if(gbLcdModeDelayed == 0)
+ gbDoHdma();
+ } else {
+ // we need to take the time it takes to complete the transfer into
+ // account... according to GB DEV FAQs, the setup time is the same
+ // for single and double speed, but the actual transfer takes the
+ // same time
+ if(gbSpeed)
+ gbDmaTicks = 2+16 * ((value & 0x7f) +1);
+ else
+ gbDmaTicks = 1+8 * ((value & 0x7f)+1);
+
+ gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000,
+ gbHdmaSource & 0xfff0,
+ gbHdmaBytes);
+ gbHdmaDestination += gbHdmaBytes;
+ gbHdmaSource += gbHdmaBytes;
+
+ gbMemory[0xff51] = register_HDMA1 = 0xff;// = (gbHdmaSource >> 8) & 0xff;
+ gbMemory[0xff52] = register_HDMA2 = 0xff;// = gbHdmaSource & 0xf0;
+ gbMemory[0xff53] = register_HDMA3 = 0xff;// = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f;
+ gbMemory[0xff54] = register_HDMA4 = 0xff;// = gbHdmaDestination & 0xf0;
+ gbMemory[0xff55] = register_HDMA5 = 0xff;
+ }
+ }
+ return;
+ }
+ }
+ break;
+
+ // BCPS
+ case 0x68: {
+ if(gbCgbMode) {
+ int paletteIndex = (value & 0x3f) >> 1;
+ int paletteHiLo = (value & 0x01);
+
+ gbMemory[0xff68] = value;
+
+ gbMemory[0xff69] = (paletteHiLo ?
+ (gbPalette[paletteIndex] >> 8) :
+ (gbPalette[paletteIndex] & 0x00ff));
+ return;
+ }
+ }
+ break;
+
+ // BCPD
+ case 0x69: {
+ if(gbCgbMode) {
+ int v = gbMemory[0xff68];
+ int paletteIndex = (v & 0x3f) >> 1;
+ int paletteHiLo = (v & 0x01);
+
+ // No access to gbPalette during mode 3 (Color Panel Demo)
+ if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
+ (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
+ ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
+ ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
+ {
+ gbMemory[0xff69] = value;
+ gbPalette[paletteIndex] = (paletteHiLo ?
+ ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :
+ ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;
+ }
+
+
+ if(gbMemory[0xff68] & 0x80) {
+ int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f;
+
+ gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index;
+ gbMemory[0xff69] = (index & 1 ?
+ (gbPalette[index>>1] >> 8) :
+ (gbPalette[index>>1] & 0x00ff));
+ }
+ return;
+ }
+ }
+ break;
+
+ // OCPS
+ case 0x6a: {
+ if(gbCgbMode) {
+ int paletteIndex = (value & 0x3f) >> 1;
+ int paletteHiLo = (value & 0x01);
+
+ paletteIndex += 32;
+
+ gbMemory[0xff6a] = value;
+
+ gbMemory[0xff6b] = (paletteHiLo ?
+ (gbPalette[paletteIndex] >> 8) :
+ (gbPalette[paletteIndex] & 0x00ff));
+ return;
+ }
+ }
+ break;
+
+ // OCPD
+ case 0x6b: {
+
+ if(gbCgbMode) {
+ int v = gbMemory[0xff6a];
+ int paletteIndex = (v & 0x3f) >> 1;
+ int paletteHiLo = (v & 0x01);
+
+ paletteIndex += 32;
+
+ // No access to gbPalette during mode 3 (Color Panel Demo)
+ if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
+ (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
+ ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
+ ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
+ {
+ gbMemory[0xff6b] = value;
+ gbPalette[paletteIndex] = (paletteHiLo ?
+ ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :
+ ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;
+ }
+
+ if(gbMemory[0xff6a] & 0x80) {
+ int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f;
+
+ gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index;
+
+ gbMemory[0xff6b] = (index & 1 ?
+ (gbPalette[(index>>1) + 32] >> 8) :
+ (gbPalette[(index>>1) + 32] & 0x00ff));
+ }
+ return;
+ }
+ }
+ break;
+
+ case 0x6c: {
+ gbMemory[0xff6c] = 0xfe | value;
+ return;
+ }
+
+
+ // SVBK
+ case 0x70: {
+ if(gbCgbMode) {
+ value = value & 7;
+
+ int bank = value;
+ if(value == 0)
+ bank = 1;
+
+ if(bank == gbWramBank)
+ return;
+
+ int wramAddress = bank * 0x1000;
+ gbMemoryMap[0x0d] = &gbWram[wramAddress];
+
+ gbWramBank = bank;
+ gbMemory[0xff70] = register_SVBK = value;
+ return;
+ }
+ }
+
+ case 0x75:{
+ gbMemory[0xff75] = 0x8f | value;
+ return;
+ }
+
+ case 0xff: {
+ gbMemory[0xffff] = register_IE = value;
+ return;
+ }
+ }
+
+ if(address < 0xff80)
+ {
+ gbMemory[address] = value;
+ return;
+ }
+
+ gbMemory[address] = value;
+}
+
+u8 gbReadOpcode(register u16 address)
+{
+ if(gbCheatMap[address])
+ return gbCheatRead(address);
+
+ if(address < 0x8000)
+ return gbMemoryMap[address>>12][address&0x0fff];
+
+ if(address < 0xa000)
+ {
+ // A lot of 'ugly' checks... But only way to emulate this particular behaviour...
+ if (((gbHardware & 0xa) && ((gbLcdModeDelayed !=3) || ((register_LY == 0) &&
+ (gbScreenOn==false) && (register_LCDC & 0x80)) &&
+ (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) ||
+ ((gbHardware & 0x5) && (gbLcdModeDelayed !=3) &&
+ ((gbLcdMode !=3) || ((register_LY == 0) && ((gbScreenOn==false) &&
+ (register_LCDC & 0x80)) &&
+ (gbLcdLYIncrementTicks ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS))))))
+ return gbMemoryMap[address>>12][address&0x0fff];
+ return 0xff;
+ }
+
+ // Used for the mirroring of 0xC000 in 0xE000
+ if ((address >= 0xe000) && (address < 0xfe00))
+ address &= ~0x2000;
+
+ switch(address & 0xf000) {
+ case 0x0a:
+ case 0x0b:
+ if(mapperReadRAM)
+ return mapperReadRAM(address);
+ break;
+ case 0x0f:
+ if(address > 0xff00) {
+ switch(address & 0x00ff) {
+ case 0x02:
+ return (gbMemory[0xff02]);
+ case 0x03:
+ return (0xff);
+ case 0x04:
+ return register_DIV;
+ case 0x05:
+ return register_TIMA;
+ case 0x06:
+ return register_TMA;
+ case 0x07:
+ return (0xf8 | register_TAC);
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ return (0xff);
+ case 0x0f:
+ return (0xe0 | gbMemory[0xff0f]);
+ case 0x40:
+ return register_LCDC;
+ case 0x41:
+ // This is a GB/C only bug (ie. not GBA/SP).
+ if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed))
+ return (0x80 | gbMemory[0xff41] & 0xFC);
+ else
+ return (0x80 | gbMemory[0xff41]);
+ case 0x42:
+ return register_SCY;
+ case 0x43:
+ return register_SCX;
+ case 0x44:
+ if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) ||
+ (!(register_LCDC && 0x80)))
+ return 0;
+ else
+ return register_LY;
+ case 0x45:
+ return register_LYC;
+ case 0x46:
+ return register_DMA;
+ case 0x4a:
+ return register_WY;
+ case 0x4b:
+ return register_WX;
+ case 0x4c:
+ return 0xff;
+ case 0x4f:
+ return (0xfe | register_VBK);
+ case 0x51:
+ return register_HDMA1;
+ case 0x52:
+ return register_HDMA2;
+ case 0x53:
+ return register_HDMA3;
+ case 0x54:
+ return register_HDMA4;
+ case 0x55:
+ return register_HDMA5;
+ case 0x68:
+ case 0x6a:
+ if (gbCgbMode)
+ return (0x40 | gbMemory[address]);
+ else
+ return 0xc0;
+ case 0x69:
+ case 0x6b:
+ if (gbCgbMode)
+ {
+ // No access to gbPalette during mode 3 (Color Panel Demo)
+ if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
+ (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
+ ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
+ ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
+ return (gbMemory[address]);
+ else
+ return 0xff;
+ }
+ else
+ return 0xff;
+ case 0x70:
+ if (gbCgbMode)
+ return (0xf8 | register_SVBK);
+ else
+ return 0xff;
+ case 0xff:
+ return register_IE;
+ }
+ }
+ // OAM not accessible during mode 2 & 3.
+ if(((address >= 0xfe00) && (address<0xfea0)) &&
+ ((gbLcdMode | gbLcdModeDelayed) &2))
+ return 0xff;
+ break;
+ }
+
+ if ((address >= 0xfea0) && (address < 0xff00))
+ {
+ if (gbHardware & 1)
+ return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff );
+ else if (gbHardware & 2)
+ return gbMemoryMap[address>>12][address & 0x0fff];
+ else if (gbHardware & 4)
+ return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 );
+ else if (gbHardware & 8)
+ return ((address & 0xf0) |((address & 0xf0)>>4));
+ }
+
+ return gbMemoryMap[address>>12][address & 0x0fff];
+}
+
+u8 gbReadMemory(register u16 address)
+{
+ if(gbCheatMap[address])
+ return gbCheatRead(address);
+
+
+ if(address < 0x8000)
+ return gbMemoryMap[address>>12][address&0x0fff];
+
+ if(address < 0xa000)
+ {
+ // A lot of 'ugly' checks... But only way to emulate this particular behaviour...
+ if (((gbHardware & 0xa) && ((gbLcdModeDelayed !=3) || ((register_LY == 0) &&
+ (gbScreenOn==false) && (register_LCDC & 0x80)) &&
+ (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS)))) ||
+ ((gbHardware & 0x5) && (gbLcdModeDelayed !=3) &&
+ ((gbLcdMode !=3) || ((register_LY == 0) && ((gbScreenOn==false) &&
+ (register_LCDC & 0x80)) &&
+ (gbLcdLYIncrementTicks ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS))))))
+ return gbMemoryMap[address>>12][address&0x0fff];
+ return 0xff;
+ }
+
+ if ((address >= 0xe000) && (address < 0xfe00))
+ address &= ~0x2000;
+
+ if(address < 0xc000) {
+#ifndef FINAL_VERSION
+ if(memorydebug) {
+ log("Memory register read %04x PC=%04x\n",
+ address,
+ PC.W);
+ }
+#endif
+
+ // for the 2kb ram limit (fixes crash in shawu's story
+ // but now its sram test fails, as the it expects 8kb and not 2kb...
+ // So use the 'genericflashcard' option to fix it).
+ if (address<=(0xa000+gbRamSizeMask))
+ {
+ if(mapperReadRAM)
+ return mapperReadRAM(address);
+ return gbMemoryMap[address>>12][address & 0x0fff];
+ }
+ return 0xff;
+ }
+
+ if(address >= 0xff00) {
+ switch(address & 0x00ff) {
+ case 0x00:
+ {
+ if(gbSgbMode) {
+ gbSgbReadingController |= 4;
+ gbSgbResetPacketState();
+ }
+
+ int b = gbMemory[0xff00];
+
+ if((b & 0x30) == 0x20) {
+ b &= 0xf0;
+
+ int joy = 0;
+ if(gbSgbMode && gbSgbMultiplayer) {
+ switch(gbSgbNextController) {
+ case 0x0f:
+ joy = 0;
+ break;
+ case 0x0e:
+ joy = 1;
+ break;
+ case 0x0d:
+ joy = 2;
+ break;
+ case 0x0c:
+ joy = 3;
+ break;
+ default:
+ joy = 0;
+ }
+ }
+ int joystate = gbJoymask[joy];
+ if(!(joystate & 128))
+ b |= 0x08;
+ if(!(joystate & 64))
+ b |= 0x04;
+ if(!(joystate & 32))
+ b |= 0x02;
+ if(!(joystate & 16))
+ b |= 0x01;
+
+ gbMemory[0xff00] = b;
+ } else if((b & 0x30) == 0x10) {
+ b &= 0xf0;
+
+ int joy = 0;
+ if(gbSgbMode && gbSgbMultiplayer) {
+ switch(gbSgbNextController) {
+ case 0x0f:
+ joy = 0;
+ break;
+ case 0x0e:
+ joy = 1;
+ break;
+ case 0x0d:
+ joy = 2;
+ break;
+ case 0x0c:
+ joy = 3;
+ break;
+ default:
+ joy = 0;
+ }
+ }
+ int joystate = gbJoymask[joy];
+ if(!(joystate & 8))
+ b |= 0x08;
+ if(!(joystate & 4))
+ b |= 0x04;
+ if(!(joystate & 2))
+ b |= 0x02;
+ if(!(joystate & 1))
+ b |= 0x01;
+
+ gbMemory[0xff00] = b;
+ } else {
+ if(gbSgbMode && gbSgbMultiplayer) {
+ gbMemory[0xff00] = 0xf0 | gbSgbNextController;
+ } else {
+ gbMemory[0xff00] = 0xff;
+ }
+ }
+ }
+ return gbMemory[0xff00];
+ break;
+ case 0x01:
+ return gbMemory[0xff01];
+ case 0x02:
+ return (gbMemory[0xff02]);
+ case 0x04:
+ return register_DIV;
+ case 0x05:
+ return register_TIMA;
+ case 0x06:
+ return register_TMA;
+ case 0x07:
+ return (0xf8 | register_TAC);
+ case 0x0f:
+ return (0xe0 | gbMemory[0xff0f]);
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0x3B:
+ case 0x3C:
+ case 0x3D:
+ case 0x3E:
+ case 0x3F:
+ if ((gbMemory[NR30] & 0x80) && (gbMemory[NR34] & 0x80))
+ return 0xFF;
+ else
+ return gbMemoryMap[address>>12][address & 0x0fff];
+ case 0x40:
+ return register_LCDC;
+ case 0x41:
+ // This is a GB/C only bug (ie. not GBA/SP).
+ if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed))
+ return (0x80 | gbMemory[0xff41] & 0xFC);
+ else
+ return (0x80 | gbMemory[0xff41]);
+ case 0x42:
+ return register_SCY;
+ case 0x43:
+ return register_SCX;
+ case 0x44:
+ if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) ||
+ (!(register_LCDC && 0x80)))
+ return (0);
+ else
+ return register_LY;
+ case 0x45:
+ return register_LYC;
+ case 0x46:
+ return register_DMA;
+ case 0x4a:
+ return register_WY;
+ case 0x4b:
+ return register_WX;
+ case 0x4f:
+ return (0xfe | register_VBK);
+ case 0x51:
+ return register_HDMA1;
+ case 0x52:
+ return register_HDMA2;
+ case 0x53:
+ return register_HDMA3;
+ case 0x54:
+ return register_HDMA4;
+ case 0x55:
+ return register_HDMA5;
+ case 0x68:
+ case 0x6a:
+ if (gbCgbMode)
+ return (0x40 | gbMemory[address]);
+ else
+ return 0xc0;
+ case 0x69:
+ case 0x6b:
+ if (gbCgbMode)
+ {
+ // No access to gbPalette during mode 3 (Color Panel Demo)
+ if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
+ (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
+ ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
+ ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
+ return (gbMemory[address]);
+ else
+ return 0xff;
+ }
+ else
+ return 0xff;
+ case 0x70:
+ if (gbCgbMode)
+ return (0xf8 | register_SVBK);
+ else
+ return 0xff;
+ case 0xff:
+ return register_IE;
+ }
+ }
+ // OAM not accessible during mode 2 & 3.
+ if(((address >= 0xfe00) && (address<0xfea0)) &&
+ (((gbLcdMode | gbLcdModeDelayed) &2) &&
+ (!(gbSpeed && (gbHardware & 0x2) && !(gbLcdModeDelayed & 2) && (gbLcdMode == 2))) ||
+ (gbSpeed && (gbHardware & 0x2) && (gbLcdModeDelayed == 0) && (gbLcdTicksDelayed == (GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299])))))
+ return 0xff;
+
+ if ((address >= 0xfea0) && (address < 0xff00))
+ {
+ if (gbHardware & 1)
+ return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff );
+ else if (gbHardware & 2)
+ return gbMemoryMap[address>>12][address & 0x0fff];
+ else if (gbHardware & 4)
+ return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 );
+ else if (gbHardware & 8)
+ return ((address & 0xf0) |((address & 0xf0)>>4));
+ }
+
+ return gbMemoryMap[address>>12][address & 0x0fff];
+}
+
+void gbVblank_interrupt()
+{
+ gbCheatWrite(false); // Emulates GS codes.
+ gbMemory[0xff0f] = register_IF &= 0xfe;
+ gbWriteMemory(--SP.W, PC.B.B1);
+ gbWriteMemory(--SP.W, PC.B.B0);
+ PC.W = 0x40;
+}
+
+void gbLcd_interrupt()
+{
+ gbMemory[0xff0f] = register_IF &= 0xfd;
+ gbWriteMemory(--SP.W, PC.B.B1);
+ gbWriteMemory(--SP.W, PC.B.B0);
+ PC.W = 0x48;
+}
+
+void gbTimer_interrupt()
+{
+ gbMemory[0xff0f] = register_IF &= 0xfb;
+ gbWriteMemory(--SP.W, PC.B.B1);
+ gbWriteMemory(--SP.W, PC.B.B0);
+ PC.W = 0x50;
+}
+
+void gbSerial_interrupt()
+{
+ gbMemory[0xff0f] = register_IF &= 0xf7;
+ gbWriteMemory(--SP.W, PC.B.B1);
+ gbWriteMemory(--SP.W, PC.B.B0);
+ PC.W = 0x58;
+}
+
+void gbJoypad_interrupt()
+{
+ gbMemory[0xff0f] = register_IF &= 0xef;
+ gbWriteMemory(--SP.W, PC.B.B1);
+ gbWriteMemory(--SP.W, PC.B.B0);
+ PC.W = 0x60;
+}
+
+void gbSpeedSwitch()
+{
+ gbBlackScreen = true;
+ if(gbSpeed == 0) {
+ gbSpeed = 1;
+ GBLCD_MODE_0_CLOCK_TICKS = 51 * 2;
+ GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2;
+ GBLCD_MODE_2_CLOCK_TICKS = 20 * 2;
+ GBLCD_MODE_3_CLOCK_TICKS = 43 * 2;
+ GBLY_INCREMENT_CLOCK_TICKS = 114 * 2;
+ GBDIV_CLOCK_TICKS = 64;
+ GBTIMER_MODE_0_CLOCK_TICKS = 256;
+ GBTIMER_MODE_1_CLOCK_TICKS = 4;
+ GBTIMER_MODE_2_CLOCK_TICKS = 16;
+ GBTIMER_MODE_3_CLOCK_TICKS = 64;
+ GBSERIAL_CLOCK_TICKS = 128 * 2;
+ gbLcdTicks *= 2;
+ gbLcdTicksDelayed *=2;
+ gbLcdTicksDelayed--;
+ gbLcdLYIncrementTicks *= 2;
+ gbLcdLYIncrementTicksDelayed *= 2;
+ gbLcdLYIncrementTicksDelayed--;
+ gbSerialTicks *= 2;
+ SOUND_CLOCK_TICKS = soundQuality * 24 * 2;
+ soundTicks *= 2;
+ gbLine99Ticks = 3;
+ } else {
+ gbSpeed = 0;
+ GBLCD_MODE_0_CLOCK_TICKS = 51;
+ GBLCD_MODE_1_CLOCK_TICKS = 1140;
+ GBLCD_MODE_2_CLOCK_TICKS = 20;
+ GBLCD_MODE_3_CLOCK_TICKS = 43;
+ GBLY_INCREMENT_CLOCK_TICKS = 114;
+ GBDIV_CLOCK_TICKS = 64;
+ GBTIMER_MODE_0_CLOCK_TICKS = 256;
+ GBTIMER_MODE_1_CLOCK_TICKS = 4;
+ GBTIMER_MODE_2_CLOCK_TICKS = 16;
+ GBTIMER_MODE_3_CLOCK_TICKS = 64;
+ GBSERIAL_CLOCK_TICKS = 128;
+ gbLcdTicks >>= 1;
+ gbLcdTicksDelayed++;
+ gbLcdTicksDelayed >>=1;
+ gbLcdLYIncrementTicks >>= 1;
+ gbLcdLYIncrementTicksDelayed++;
+ gbLcdLYIncrementTicksDelayed >>= 1;
+ gbSerialTicks /= 2;
+ SOUND_CLOCK_TICKS = soundQuality * 24;
+ soundTicks /= 2;
+ gbLine99Ticks = 1;
+ if (gbHardware & 8)
+ gbLine99Ticks++;
+ }
+ gbDmaTicks += (134)*GBLY_INCREMENT_CLOCK_TICKS + (37<<(gbSpeed ? 1 : 0));
+}
+
+bool CPUIsGBBios(const char * file)
+{
+ if(strlen(file) > 4) {
+ const char * p = strrchr(file,'.');
+
+ if(p != NULL) {
+ if(_stricmp(p, ".gb") == 0)
+ return true;
+ if(_stricmp(p, ".bin") == 0)
+ return true;
+ if(_stricmp(p, ".bios") == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void gbCPUInit(const char *biosFileName, bool useBiosFile)
+{
+ useBios = false;
+ if (useBiosFile)
+ {
+ int size = 0x100;
+ if(utilLoad(biosFileName,
+ CPUIsGBBios,
+ bios,
+ size)) {
+ if(size == 0x100)
+ useBios = true;
+ else
+ systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file size"));
+ }
+ }
+}
+
+void gbGetHardwareType()
+{
+ gbCgbMode = 0;
+ gbSgbMode = 0;
+ if(gbRom[0x143] & 0x80) {
+ if((gbEmulatorType == 0) ||
+ gbEmulatorType == 1 ||
+ gbEmulatorType == 4) {
+ gbCgbMode = 1;
+ }
+ }
+
+ if((gbCgbMode == 0 ) && (gbRom[0x146] == 0x03)) {
+ if(gbEmulatorType == 0 ||
+ gbEmulatorType == 2 ||
+ gbEmulatorType == 5)
+ gbSgbMode = 1;
+ }
+
+ gbHardware = 1; // GB
+ if (((gbCgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 1))
+ gbHardware = 2; // GBC
+ else if (((gbSgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 2) || (gbEmulatorType == 5))
+ gbHardware = 4; // SGB(2)
+ else if (gbEmulatorType == 4)
+ gbHardware = 8; // GBA
+
+ gbGBCColorType = 0;
+ if (gbHardware & 8) // If GBA is selected, choose the GBA default settings.
+ gbGBCColorType = 2; // (0 = GBC, 1 = GBA, 2 = GBASP)
+}
+
+void gbReset()
+{
+ gbGetHardwareType();
+
+ oldRegister_WY = 146;
+ gbInterruptLaunched = 0;
+
+ if(gbCgbMode == 1) {
+ if (gbVram == NULL)
+ gbVram = (u8 *)malloc(0x4000);
+ if (gbWram == NULL)
+ gbWram = (u8 *)malloc(0x8000);
+ memset(gbVram,0,0x4000);
+ memset(gbPalette,0, 2*128);
+ }
+ else
+ {
+ if(gbVram != NULL) {
+ free(gbVram);
+ gbVram = NULL;
+ }
+ if(gbWram != NULL) {
+ free(gbWram);
+ gbWram = NULL;
+ }
+ }
+
+ gbLYChangeHappened = false;
+ gbLCDChangeHappened = false;
+ gbBlackScreen = false;
+ gbInterruptWait = 0;
+ gbDmaTicks = 0;
+ clockTicks = 0;
+
+ if(gbSpeed) {
+ gbSpeedSwitch();
+ gbMemory[0xff4d] = 0;
+ }
+
+ // clean Wram
+ // This kinda emulates the startup state of Wram on GB/C (not very accurate,
+ // but way closer to the reality than filling it with 00es or FFes).
+ // On GBA/GBASP, it's kinda filled with random data.
+ // In all cases, most of the 2nd bank is filled with 00s.
+ // The starting data are important for some 'buggy' games, like Buster Brothers or
+ // Karamuchou ha Oosawagi!.
+ if (gbMemory != NULL)
+ {
+ memset(gbMemory,0xff, 65536);
+ for (int temp = 0xC000; temp < 0xE000; temp++)
+ if ((temp & 0x8) ^((temp & 0x800)>>8))
+ {
+ if ((gbHardware & 0x02) && (gbGBCColorType == 0))
+ gbMemory[temp] = 0x0;
+ else
+ gbMemory[temp] = 0x0f;
+ }
+
+ else
+ gbMemory[temp] = 0xff;
+ }
+
+
+
+ // clean LineBuffer
+ if (gbLineBuffer != NULL)
+ memset(gbLineBuffer, 0, sizeof(gbLineBuffer));
+ // clean Pix
+ if (pix != NULL)
+ memset(pix, 0, sizeof(pix));
+ // clean Vram
+ if (gbVram != NULL)
+ memset(gbVram, 0, 0x4000);
+ // clean Wram 2
+ // This kinda emulates the startup state of Wram on GBC (not very accurate,
+ // but way closer to the reality than filling it with 00es or FFes).
+ // On GBA/GBASP, it's kinda filled with random data.
+ // In all cases, most of the 2nd bank is filled with 00s.
+ // The starting data are important for some 'buggy' games, like Buster Brothers or
+ // Karamuchou ha Oosawagi!
+ if (gbWram != NULL)
+ {
+ for (int i = 0; i<8; i++)
+ if (i != 2)
+ memcpy ((u16 *)(gbWram+i*0x1000), (u16 *)(gbMemory+0xC000), 0x1000);
+ }
+
+ memset(gbSCYLine,0,sizeof(gbSCYLine));
+ memset(gbSCXLine,0,sizeof(gbSCXLine));
+ memset(gbBgpLine,0xfc,sizeof(gbBgpLine));
+ if (gbHardware & 5)
+ {
+ memset(gbObp0Line,0xff,sizeof(gbObp0Line));
+ memset(gbObp1Line,0xff,sizeof(gbObp1Line));
+ }
+ else
+ {
+ memset(gbObp0Line,0x0,sizeof(gbObp0Line));
+ memset(gbObp1Line,0x0,sizeof(gbObp1Line));
+ }
+ memset(gbSpritesTicks,0x0,sizeof(gbSpritesTicks));
+
+ SP.W = 0xfffe;
+ AF.W = 0x01b0;
+ BC.W = 0x0013;
+ DE.W = 0x00d8;
+ HL.W = 0x014d;
+ PC.W = 0x0100;
+ IFF = 0;
+ gbInt48Signal = 0;
+
+ register_TIMA = 0;
+ register_TMA = 0;
+ register_TAC = 0;
+ gbMemory[0xff0f] = register_IF = 1;
+ gbMemory[0xff40] = register_LCDC = 0x91;
+ gbMemory[0xff47] = 0xfc;
+
+ if (gbCgbMode)
+ gbMemory[0xff4d] = 0x7e;
+ else
+ gbMemory[0xff4d] = 0xff;
+
+ if (!gbCgbMode)
+ gbMemory[0xff70] = gbMemory[0xff74] = 0xff;
+
+ if (gbCgbMode)
+ gbMemory[0xff56] = 0x3e;
+ else
+ gbMemory[0xff56] = 0xff;
+
+ register_SCY = 0;
+ register_SCX = 0;
+ register_LYC = 0;
+ register_DMA = 0xff;
+ register_WY = 0;
+ register_WX = 0;
+ register_VBK = 0;
+ register_HDMA1 = 0xff;
+ register_HDMA2 = 0xff;
+ register_HDMA3 = 0xff;
+ register_HDMA4 = 0xff;
+ register_HDMA5 = 0xff;
+ register_SVBK = 0;
+ register_IE = 0;
+
+ if (gbCgbMode)
+ gbMemory[0xff02] = 0x7c;
+ else
+ gbMemory[0xff02] = 0x7e;
+
+ gbMemory[0xff03] = 0xff;
+ int i;
+ for (i = 0x8; i<0xf; i++)
+ gbMemory[0xff00+i] = 0xff;
+
+ gbMemory[0xff13] = 0xff;
+ gbMemory[0xff15] = 0xff;
+ gbMemory[0xff18] = 0xff;
+ gbMemory[0xff1d] = 0xff;
+ gbMemory[0xff1f] = 0xff;
+
+ for (i = 0x27; i<0x30; i++)
+ gbMemory[0xff00+i] = 0xff;
+
+ gbMemory[0xff4c] = 0xff;
+ gbMemory[0xff4e] = 0xff;
+ gbMemory[0xff50] = 0xff;
+
+ for (i = 0x57; i<0x68; i++)
+ gbMemory[0xff00+i] = 0xff;
+
+ for (i = 0x5d; i<0x70; i++)
+ gbMemory[0xff00+i] = 0xff;
+
+ gbMemory[0xff71] = 0xff;
+
+ for (i = 0x78; i<0x80; i++)
+ gbMemory[0xff00+i] = 0xff;
+
+ if (gbHardware & 0xa)
+ {
+
+ if (gbHardware & 2)
+ {
+ AF.W = 0x1180;
+ BC.W = 0x0000;
+ }
+ else
+ {
+ AF.W = 0x1100;
+ BC.W = 0x0100; // GBA/SP have B = 0x01 (which means GBC & GBA/SP bootrom are different !)
+ }
+
+ gbMemory[0xff26] = 0xf1;
+ if (gbCgbMode)
+ {
+
+ gbMemory[0xff31] = 0xff;
+ gbMemory[0xff33] = 0xff;
+ gbMemory[0xff35] = 0xff;
+ gbMemory[0xff37] = 0xff;
+ gbMemory[0xff39] = 0xff;
+ gbMemory[0xff3b] = 0xff;
+ gbMemory[0xff3d] = 0xff;
+
+ gbMemory[0xff44] = register_LY = 0x90;
+ gbDivTicks = 0x19 + ((gbHardware & 2) >> 1);
+ gbInternalTimer = 0x58 + ((gbHardware & 2) >> 1);
+ gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS -
+ (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 72 + ((gbHardware & 2) >> 1);
+ gbLcdLYIncrementTicks = 72 + ((gbHardware & 2) >> 1);
+ gbMemory[0xff04] = register_DIV = 0x1E;
+ }
+ else
+ {
+ gbMemory[0xff44] = register_LY = 0x94;
+ gbDivTicks = 0x22 + ((gbHardware & 2) >> 1);
+ gbInternalTimer = 0x61 + ((gbHardware & 2) >> 1);
+ gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS -
+ (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 25 + ((gbHardware & 2) >> 1);
+ gbLcdLYIncrementTicks = 25 + ((gbHardware & 2) >> 1);
+ gbMemory[0xff04] = register_DIV = 0x26;
+ }
+
+
+ DE.W = 0xff56;
+ HL.W = 0x000d;
+
+ register_HDMA5 = 0xff;
+ gbMemory[0xff68] = 0xc0;
+ gbMemory[0xff6a] = 0xc0;
+
+
+ gbMemory[0xff41] = register_STAT = 0x81;
+ gbLcdMode = 1;
+ }
+ else
+ {
+ if (gbHardware & 4)
+ {
+ if(gbEmulatorType == 5)
+ AF.W = 0xffb0;
+ else
+ AF.W = 0x01b0;
+ BC.W = 0x0013;
+ DE.W = 0x00d8;
+ HL.W = 0x014d;
+ }
+ gbDivTicks = 14;
+ gbInternalTimer = gbDivTicks--;
+ gbMemory[0xff04] = register_DIV = 0xAB;
+ gbMemory[0xff41] = register_STAT = 0x85;
+ gbMemory[0xff44] = register_LY = 0x00;
+ gbLcdTicks = 15;
+ gbLcdLYIncrementTicks = 114+gbLcdTicks;
+ gbLcdMode = 1;
+
+ // used for the handling of the gb Boot Rom
+ if ((gbHardware & 5) && (bios != NULL) && useBios && !skipBios)
+ {
+ memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000);
+ memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100);
+ gbWhiteScreen = 0;
+
+ gbInternalTimer = 0x3e;
+ gbDivTicks = 0x3f;
+ gbMemory[0xff04] = register_DIV = 0x00;
+ PC.W = 0x0000;
+ register_LCDC = 0x11;
+ gbScreenOn = false;
+ gbLcdTicks = 0;
+ gbLcdMode = 0;
+ gbLcdModeDelayed = 0;
+ gbMemory[0xff41] = register_STAT &= 0xfc;
+ gbInt48Signal = 0;
+ gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS;
+ }
+ }
+
+ gbLine99Ticks = 1;
+ if (gbHardware & 8)
+ gbLine99Ticks++;
+
+ gbLcdModeDelayed = gbLcdMode;
+ gbLcdTicksDelayed = gbLcdTicks+1;
+ gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks+1;
+
+
+ gbTimerModeChange = false;
+ gbTimerOnChange = false;
+ gbTimerOn = false;
+
+ if(gbCgbMode) {
+ for (int i = 0; i<0x20; i++)
+ gbPalette[i] = 0x7fff;
+
+ // This is just to show that the starting values of the OBJ palettes are different
+ // between the 3 consoles, and that they 'kinda' stay the same at each reset
+ // (they can slightly change, somehow (randomly?)).
+ // You can check the effects of gbGBCColorType on the "Vila Caldan Color" gbc demo.
+ // Note that you could also check the Div register to check on which system the game
+ // is running (GB,GBC and GBA(SP) have different startup values).
+ // Unfortunatly, I don't have any SGB system, so I can't get their starting values.
+
+ if (gbGBCColorType == 0) // GBC Hardware
+ {
+ gbPalette[0x20] = 0x0600;
+ gbPalette[0x21] = 0xfdf3;
+ gbPalette[0x22] = 0x041c;
+ gbPalette[0x23] = 0xf5db;
+ gbPalette[0x24] = 0x4419;
+ gbPalette[0x25] = 0x57ea;
+ gbPalette[0x26] = 0x2808;
+ gbPalette[0x27] = 0x9b75;
+ gbPalette[0x28] = 0x129b;
+ gbPalette[0x29] = 0xfce0;
+ gbPalette[0x2a] = 0x22da;
+ gbPalette[0x2b] = 0x4ac5;
+ gbPalette[0x2c] = 0x2d71;
+ gbPalette[0x2d] = 0xf0c2;
+ gbPalette[0x2e] = 0x5137;
+ gbPalette[0x2f] = 0x2d41;
+ gbPalette[0x30] = 0x6b2d;
+ gbPalette[0x31] = 0x2215;
+ gbPalette[0x32] = 0xbe0a;
+ gbPalette[0x33] = 0xc053;
+ gbPalette[0x34] = 0xfe5f;
+ gbPalette[0x35] = 0xe000;
+ gbPalette[0x36] = 0xbe10;
+ gbPalette[0x37] = 0x914d;
+ gbPalette[0x38] = 0x7f91;
+ gbPalette[0x39] = 0x02b5;
+ gbPalette[0x3a] = 0x77ac;
+ gbPalette[0x3b] = 0x14e5;
+ gbPalette[0x3c] = 0xcf89;
+ gbPalette[0x3d] = 0xa03d;
+ gbPalette[0x3e] = 0xfd50;
+ gbPalette[0x3f] = 0x91ff;
+ }
+ else if (gbGBCColorType == 1) // GBA Hardware
+ {
+ gbPalette[0x20] = 0xbe00;
+ gbPalette[0x21] = 0xfdfd;
+ gbPalette[0x22] = 0xbd69;
+ gbPalette[0x23] = 0x7baf;
+ gbPalette[0x24] = 0xf5ff;
+ gbPalette[0x25] = 0x3f8f;
+ gbPalette[0x26] = 0xcee5;
+ gbPalette[0x27] = 0x5bf7;
+ gbPalette[0x28] = 0xb35b;
+ gbPalette[0x29] = 0xef97;
+ gbPalette[0x2a] = 0xef9f;
+ gbPalette[0x2b] = 0x97f7;
+ gbPalette[0x2c] = 0x82bf;
+ gbPalette[0x2d] = 0x9f3d;
+ gbPalette[0x2e] = 0xddde;
+ gbPalette[0x2f] = 0xbad5;
+ gbPalette[0x30] = 0x3cba;
+ gbPalette[0x31] = 0xdfd7;
+ gbPalette[0x32] = 0xedea;
+ gbPalette[0x33] = 0xfeda;
+ gbPalette[0x34] = 0xf7f9;
+ gbPalette[0x35] = 0xfdee;
+ gbPalette[0x36] = 0x6d2f;
+ gbPalette[0x37] = 0xf0e6;
+ gbPalette[0x38] = 0xf7f0;
+ gbPalette[0x39] = 0xf296;
+ gbPalette[0x3a] = 0x3bf1;
+ gbPalette[0x3b] = 0xe211;
+ gbPalette[0x3c] = 0x69ba;
+ gbPalette[0x3d] = 0x3d0d;
+ gbPalette[0x3e] = 0xdfd3;
+ gbPalette[0x3f] = 0xa6ba;
+ }
+ else if (gbGBCColorType == 2) // GBASP Hardware
+ {
+ gbPalette[0x20] = 0x9c00;
+ gbPalette[0x21] = 0x6340;
+ gbPalette[0x22] = 0x10c6;
+ gbPalette[0x23] = 0xdb97;
+ gbPalette[0x24] = 0x7622;
+ gbPalette[0x25] = 0x3e57;
+ gbPalette[0x26] = 0x2e12;
+ gbPalette[0x27] = 0x95c3;
+ gbPalette[0x28] = 0x1095;
+ gbPalette[0x29] = 0x488c;
+ gbPalette[0x2a] = 0x8241;
+ gbPalette[0x2b] = 0xde8c;
+ gbPalette[0x2c] = 0xfabc;
+ gbPalette[0x2d] = 0x0e81;
+ gbPalette[0x2e] = 0x7675;
+ gbPalette[0x2f] = 0xfdec;
+ gbPalette[0x30] = 0xddfd;
+ gbPalette[0x31] = 0x5995;
+ gbPalette[0x32] = 0x066a;
+ gbPalette[0x33] = 0xed1e;
+ gbPalette[0x34] = 0x1e84;
+ gbPalette[0x35] = 0x1d14;
+ gbPalette[0x36] = 0x11c3;
+ gbPalette[0x37] = 0x2749;
+ gbPalette[0x38] = 0xa727;
+ gbPalette[0x39] = 0x6266;
+ gbPalette[0x3a] = 0xe27b;
+ gbPalette[0x3b] = 0xe3fc;
+ gbPalette[0x3c] = 0x1f76;
+ gbPalette[0x3d] = 0xf158;
+ gbPalette[0x3e] = 0x468e;
+ gbPalette[0x3f] = 0xa540;
+ }
+ } else {
+ if(gbSgbMode) {
+ for(int i = 0; i < 8; i++)
+ gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
+
+ }
+ for(int i = 0; i < 8; i++)
+ gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
+ }
+
+ GBTIMER_MODE_0_CLOCK_TICKS = 256;
+ GBTIMER_MODE_1_CLOCK_TICKS = 4;
+ GBTIMER_MODE_2_CLOCK_TICKS = 16;
+ GBTIMER_MODE_3_CLOCK_TICKS = 64;
+
+ GBLY_INCREMENT_CLOCK_TICKS = 114;
+ gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS;
+ gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS;
+ gbSerialTicks = 0;
+ gbSerialBits = 0;
+ gbSerialOn = 0;
+ gbWindowLine = -1;
+ gbTimerOn = false;
+ gbTimerMode = 0;
+ gbSpeed = 0;
+ gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0;
+
+ if(gbCgbMode) {
+ gbSpeed = 0;
+ gbHdmaOn = 0;
+ gbHdmaSource = 0x99d0;
+ gbHdmaDestination = 0x99d0;
+ gbVramBank = 0;
+ gbWramBank = 1;
+
+ }
+
+ // used to clean the borders
+ if (gbSgbMode)
+ {
+ gbSgbResetFlag = true;
+ gbSgbReset();
+ if (gbBorderOn)
+ gbSgbRenderBorder();
+ gbSgbResetFlag = false;
+ }
+
+ for(i = 0; i < 4; i++)
+ gbBgp[i] = gbObp0[i] = gbObp1[i] = i;
+
+ memset(&gbDataMBC1,0, sizeof(gbDataMBC1));
+ gbDataMBC1.mapperROMBank = 1;
+
+ gbDataMBC2.mapperRAMEnable = 0;
+ gbDataMBC2.mapperROMBank = 1;
+
+ memset(&gbDataMBC3,0, 6 * sizeof(int));
+ gbDataMBC3.mapperROMBank = 1;
+
+ memset(&gbDataMBC5, 0, sizeof(gbDataMBC5));
+ gbDataMBC5.mapperROMBank = 1;
+
+ memset(&gbDataHuC1, 0, sizeof(gbDataHuC1));
+ gbDataHuC1.mapperROMBank = 1;
+
+ memset(&gbDataHuC3, 0, sizeof(gbDataHuC3));
+ gbDataHuC3.mapperROMBank = 1;
+
+ memset(&gbDataTAMA5,0, 26*sizeof(int));
+ gbDataTAMA5.mapperROMBank = 1;
+
+ memset(&gbDataMMM01,0, sizeof(gbDataMMM01));
+ gbDataMMM01.mapperROMBank = 1;
+
+ if (useBios && !skipBios && (gbHardware & 5))
+ {
+ gbMemoryMap[0x00] = &gbMemory[0x0000];
+ inBios = true;
+ }
+ else
+ {
+ gbMemoryMap[0x00] = &gbRom[0x0000];
+ inBios = false;
+ }
+
+ gbMemoryMap[0x01] = &gbRom[0x1000];
+ gbMemoryMap[0x02] = &gbRom[0x2000];
+ gbMemoryMap[0x03] = &gbRom[0x3000];
+ gbMemoryMap[0x04] = &gbRom[0x4000];
+ gbMemoryMap[0x05] = &gbRom[0x5000];
+ gbMemoryMap[0x06] = &gbRom[0x6000];
+ gbMemoryMap[0x07] = &gbRom[0x7000];
+ if(gbCgbMode) {
+ gbMemoryMap[0x08] = &gbVram[0x0000];
+ gbMemoryMap[0x09] = &gbVram[0x1000];
+ gbMemoryMap[0x0a] = &gbMemory[0xa000];
+ gbMemoryMap[0x0b] = &gbMemory[0xb000];
+ gbMemoryMap[0x0c] = &gbMemory[0xc000];
+ gbMemoryMap[0x0d] = &gbWram[0x1000];
+ gbMemoryMap[0x0e] = &gbMemory[0xe000];
+ gbMemoryMap[0x0f] = &gbMemory[0xf000];
+ } else {
+ gbMemoryMap[0x08] = &gbMemory[0x8000];
+ gbMemoryMap[0x09] = &gbMemory[0x9000];
+ gbMemoryMap[0x0a] = &gbMemory[0xa000];
+ gbMemoryMap[0x0b] = &gbMemory[0xb000];
+ gbMemoryMap[0x0c] = &gbMemory[0xc000];
+ gbMemoryMap[0x0d] = &gbMemory[0xd000];
+ gbMemoryMap[0x0e] = &gbMemory[0xe000];
+ gbMemoryMap[0x0f] = &gbMemory[0xf000];
+ }
+
+ if(gbRam) {
+ gbMemoryMap[0x0a] = &gbRam[0x0000];
+ gbMemoryMap[0x0b] = &gbRam[0x1000];
+ }
+
+ gbSoundReset();
+
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+
+ gbLastTime = systemGetClock();
+ gbFrameCount = 0;
+
+ gbScreenOn = true;
+ gbSystemMessage = false;
+
+ gbCheatWrite(true); // Emulates GS codes.
+
+}
+
+void gbWriteSaveMBC1(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *gzFile = fopen(name,"wb");
+
+ if(gzFile == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+
+ fwrite(gbRam,
+ 1,
+ (gbRamSizeMask+1),
+ gzFile);
+
+ fclose(gzFile);
+ }
+}
+
+void gbWriteSaveMBC2(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *file = fopen(name, "wb");
+
+ if(file == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+
+ fwrite(&gbMemory[0xa000],
+ 1,
+ 256,
+ file);
+
+ fclose(file);
+ }
+}
+
+void gbWriteSaveMBC3(const char * name, bool extendedSave)
+{
+ if (gbRam || extendedSave)
+ {
+ FILE *gzFile = fopen(name,"wb");
+ if (gbRam)
+ {
+
+ if(gzFile == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+
+ fwrite(gbRam,
+ 1,
+ (gbRamSizeMask+1),
+ gzFile);
+ }
+
+ if(extendedSave)
+ fwrite(&gbDataMBC3.mapperSeconds,
+ 1,
+ 10*sizeof(int) + sizeof(time_t),
+ gzFile);
+
+ fclose(gzFile);
+ }
+}
+
+void gbWriteSaveMBC5(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *gzFile = fopen(name,"wb");
+
+ if(gzFile == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+
+ fwrite(gbRam,
+ 1,
+ (gbRamSizeMask+1),
+ gzFile);
+
+ fclose(gzFile);
+ }
+}
+
+void gbWriteSaveMBC7(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *file = fopen(name, "wb");
+
+ if(file == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+
+ fwrite(&gbMemory[0xa000],
+ 1,
+ 256,
+ file);
+
+ fclose(file);
+ }
+}
+
+void gbWriteSaveTAMA5(const char * name, bool extendedSave)
+{
+ FILE *gzFile = fopen(name,"wb");
+
+ if(gzFile == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+ if (gbRam)
+ fwrite(gbRam,
+ 1,
+ (gbRamSizeMask+1),
+ gzFile);
+
+ fwrite(gbTAMA5ram,
+ 1,
+ (gbTAMA5ramSize),
+ gzFile);
+
+ if(extendedSave)
+ fwrite(&gbDataTAMA5.mapperSeconds,
+ 1,
+ 14*sizeof(int) + sizeof(time_t),
+ gzFile);
+
+ fclose(gzFile);
+}
+
+void gbWriteSaveMMM01(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *gzFile = fopen(name,"wb");
+
+ if(gzFile == NULL) {
+ systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
+ return;
+ }
+
+ fwrite(gbRam,
+ 1,
+ (gbRamSizeMask+1),
+ gzFile);
+
+ fclose(gzFile);
+ }
+}
+
+
+bool gbReadSaveMBC1(const char * name)
+{
+ if (gbRam)
+ {
+ gzFile gzFile = gzopen(name, "rb");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ int read = gzread(gzFile,
+ gbRam,
+ (gbRamSizeMask+1));
+
+ if(read != (gbRamSizeMask+1)) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gzclose(gzFile);
+ gbBatteryError = true;
+ return false;
+ }
+
+ // Also checks if the battery file it bigger than gbRamSizeMask+1 !
+ u8 data[1];
+ data[0] = 0;
+
+ read = gzread(gzFile,
+ data,
+ 1);
+ if(read >0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gzclose(gzFile);
+ gbBatteryError = true;
+ return false;
+ }
+
+ gzclose(gzFile);
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool gbReadSaveMBC2(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *file = fopen(name, "rb");
+
+ if(file == NULL) {
+ return false;
+ }
+
+ size_t read = fread(&gbMemory[0xa000],
+ 1,
+ 256,
+ file);
+
+ if(read != 256) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ fclose(file);
+ gbBatteryError = true;
+ return false;
+ }
+
+ // Also checks if the battery file it bigger than gbRamSizeMask+1 !
+ u8 data[1];
+ data[0] = 0;
+
+ read = fread(&data[0],
+ 1,
+ 1,
+ file);
+ if(read > 0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ fclose(file);
+ gbBatteryError = true;
+ return false;
+ }
+
+ fclose(file);
+ return true;
+ }
+ else
+ return false;
+}
+
+bool gbReadSaveMBC3(const char * name)
+{
+ gzFile gzFile = gzopen(name, "rb");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ int read = 0;
+
+ if (gbRam)
+ read = gzread(gzFile,
+ gbRam,
+ (gbRamSizeMask+1));
+ else
+ read = (gbRamSizeMask+1);
+
+
+ bool res = true;
+
+ if(read != (gbRamSizeMask+1)) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gbBatteryError = true;
+ res = false;
+ } else if ((gbRomType == 0xf) || (gbRomType == 0x10)){
+ read = gzread(gzFile,
+ &gbDataMBC3.mapperSeconds,
+ sizeof(int)*10 + sizeof(time_t));
+
+ if(read != (sizeof(int)*10 + sizeof(time_t)) && read != 0) {
+ systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
+ name);
+ res = false;
+ }
+ else if (read == 0)
+ {
+ systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
+ name);
+ res = false;
+ }
+ else
+ {
+ // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
+ u8 data[1];
+ data[0] = 0;
+
+ read = gzread(gzFile,
+ data,
+ 1);
+ if(read >0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gbBatteryError = true;
+ res = false;
+ }
+ }
+ }
+
+ gzclose(gzFile);
+ return res;
+}
+
+bool gbReadSaveMBC5(const char * name)
+{
+ if (gbRam)
+ {
+ gzFile gzFile = gzopen(name, "rb");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ int read = gzread(gzFile,
+ gbRam,
+ (gbRamSizeMask+1));
+
+ if(read != (gbRamSizeMask+1)) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gzclose(gzFile);
+ gbBatteryError = true;
+ return false;
+ }
+
+
+ // Also checks if the battery file it bigger than gbRamSizeMask+1 !
+ u8 data[1];
+ data[0] = 0;
+
+ read = gzread(gzFile,
+ data,
+ 1);
+ if(read >0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gzclose(gzFile);
+ gbBatteryError = true;
+ return false;
+ }
+
+ gzclose(gzFile);
+ return true;
+ }
+ else
+ return false;
+}
+
+bool gbReadSaveMBC7(const char * name)
+{
+ if (gbRam)
+ {
+ FILE *file = fopen(name, "rb");
+
+ if(file == NULL) {
+ return false;
+ }
+
+ size_t read = fread(&gbMemory[0xa000],
+ 1,
+ 256,
+ file);
+
+ if(read != 256) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ fclose(file);
+ gbBatteryError = true;
+ return false;
+ }
+
+ // Also checks if the battery file it bigger than gbRamSizeMask+1 !
+ u8 data[1];
+ data[0] = 0;
+
+ read = fread(&data[0],
+ 1,
+ 1,
+ file);
+ if(read > 0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ fclose(file);
+ gbBatteryError = true;
+ return false;
+ }
+
+ fclose(file);
+ return true;
+ }
+ else
+ return false;
+}
+
+bool gbReadSaveTAMA5(const char * name)
+{
+ gzFile gzFile = gzopen(name, "rb");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ int read = 0;
+
+ if (gbRam)
+ read = gzread(gzFile,
+ gbRam,
+ (gbRamSizeMask+1));
+ else
+ read = gbRamSizeMask;
+
+ read += gzread(gzFile,
+ gbTAMA5ram,
+ gbTAMA5ramSize);
+
+ bool res = true;
+
+ if(read != (gbRamSizeMask+gbTAMA5ramSize+1)) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gbBatteryError = true;
+ res = false;
+ } else {
+ read = gzread(gzFile,
+ &gbDataTAMA5.mapperSeconds,
+ sizeof(int)*14 + sizeof(time_t));
+
+ if(read != (sizeof(int)*14 + sizeof(time_t)) && read != 0) {
+ systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
+ name);
+ res = false;
+ }
+ else if (read == 0)
+ {
+ systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
+ name);
+ res = false;
+ }
+ else
+ {
+ // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
+ u8 data[1];
+ data[0] = 0;
+
+ read = gzread(gzFile,
+ data,
+ 1);
+ if(read >0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gbBatteryError = true;
+ res = false;
+ }
+ }
+ }
+
+ gzclose(gzFile);
+ return res;
+}
+
+
+bool gbReadSaveMMM01(const char * name)
+{
+ if (gbRam)
+ {
+ gzFile gzFile = gzopen(name, "rb");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ int read = gzread(gzFile,
+ gbRam,
+ (gbRamSizeMask+1));
+
+ if(read != (gbRamSizeMask+1)) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gzclose(gzFile);
+ gbBatteryError = true;
+ return false;
+ }
+
+ // Also checks if the battery file it bigger than gbRamSizeMask+1 !
+ u8 data[1];
+ data[0] = 0;
+
+ read = gzread(gzFile,
+ data,
+ 1);
+ if(read >0) {
+ systemMessage(MSG_FAILED_TO_READ_SGM,
+ N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
+ gzclose(gzFile);
+ gbBatteryError = true;
+ return false;
+ }
+
+ gzclose(gzFile);
+ return true;
+ }
+ else
+ return false;
+}
+
+void gbInit()
+{
+ gbGenFilter();
+ gbSgbInit();
+
+ gbMemory = (u8 *)malloc(65536);
+
+ pix = (u8 *)calloc(1,4*257*226);
+
+ gbLineBuffer = (u16 *)malloc(160 * sizeof(u16));
+}
+
+bool gbWriteBatteryFile(const char *file, bool extendedSave)
+{
+ if(gbBattery) {
+ switch(gbRomType) {
+ case 0x03:
+ gbWriteSaveMBC1(file);
+ break;
+ case 0x06:
+ gbWriteSaveMBC2(file);
+ break;
+ case 0x0d:
+ gbWriteSaveMMM01(file);
+ break;
+ case 0x0f:
+ case 0x10:
+ gbWriteSaveMBC3(file, extendedSave);
+ break;
+ case 0x13:
+ case 0xfc:
+ gbWriteSaveMBC3(file, false);
+ case 0x1b:
+ case 0x1e:
+ gbWriteSaveMBC5(file);
+ break;
+ case 0x22:
+ gbWriteSaveMBC7(file);
+ break;
+ case 0xfd:
+ gbWriteSaveTAMA5(file, extendedSave);
+ break;
+ case 0xff:
+ gbWriteSaveMBC1(file);
+ break;
+ }
+ }
+ return true;
+}
+
+bool gbWriteBatteryFile(const char *file)
+{
+ if (!gbBatteryError)
+ {
+ gbWriteBatteryFile(file, true);
+ return true;
+ }
+ else return false;
+}
+
+bool gbReadBatteryFile(const char *file)
+{
+ bool res = false;
+ if(gbBattery) {
+ switch(gbRomType) {
+ case 0x03:
+ res = gbReadSaveMBC1(file);
+ break;
+ case 0x06:
+ res = gbReadSaveMBC2(file);
+ break;
+ case 0x0d:
+ res = gbReadSaveMMM01(file);
+ break;
+ case 0x0f:
+ case 0x10:
+ if(!gbReadSaveMBC3(file)) {
+ time(&gbDataMBC3.mapperLastTime);
+ struct tm *lt;
+ lt = localtime(&gbDataMBC3.mapperLastTime);
+ gbDataMBC3.mapperSeconds = lt->tm_sec;
+ gbDataMBC3.mapperMinutes = lt->tm_min;
+ gbDataMBC3.mapperHours = lt->tm_hour;
+ gbDataMBC3.mapperDays = lt->tm_yday & 255;
+ gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
+ (lt->tm_yday > 255 ? 1: 0);
+ res = false;
+ break;
+ }
+ res = true;
+ break;
+ case 0x13:
+ case 0xfc:
+ res = gbReadSaveMBC3(file);
+ case 0x1b:
+ case 0x1e:
+ res = gbReadSaveMBC5(file);
+ break;
+ case 0x22:
+ res = gbReadSaveMBC7(file);
+ case 0xfd:
+ if(!gbReadSaveTAMA5(file)) {
+ u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ time(&gbDataTAMA5.mapperLastTime);
+ struct tm *lt;
+ lt = localtime(&gbDataTAMA5.mapperLastTime);
+ gbDataTAMA5.mapperSeconds = lt->tm_sec;
+ gbDataTAMA5.mapperMinutes = lt->tm_min;
+ gbDataTAMA5.mapperHours = lt->tm_hour;
+ gbDataTAMA5.mapperDays = 1;
+ gbDataTAMA5.mapperMonths = 1;
+ gbDataTAMA5.mapperYears = 1970;
+ int days = lt->tm_yday+365*3;
+ while (days)
+ {
+ gbDataTAMA5.mapperDays++;
+ days--;
+ if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1])
+ {
+ gbDataTAMA5.mapperDays = 1;
+ gbDataTAMA5.mapperMonths++;
+ if (gbDataTAMA5.mapperMonths>12)
+ {
+ gbDataTAMA5.mapperMonths = 1;
+ gbDataTAMA5.mapperYears++;
+ if ((gbDataTAMA5.mapperYears & 3) == 0)
+ gbDaysinMonth[1] = 29;
+ else
+ gbDaysinMonth[1] = 28;
+ }
+ }
+ }
+ gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) |
+ (lt->tm_yday > 255 ? 1: 0);
+ res = false;
+ break;
+ }
+ res = true;
+ break;
+ case 0xff:
+ res = gbReadSaveMBC1(file);
+ break;
+ }
+ }
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+ return res;
+}
+
+bool gbReadGSASnapshot(const char *fileName)
+{
+ FILE *file = fopen(fileName, "rb");
+
+ if(!file) {
+ systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
+ return false;
+ }
+
+ fseek(file, 0x4, SEEK_SET);
+ char buffer[16];
+ char buffer2[16];
+ fread(buffer, 1, 15, file);
+ buffer[15] = 0;
+ memcpy(buffer2, &gbRom[0x134], 15);
+ buffer2[15] = 0;
+ if(memcmp(buffer, buffer2, 15)) {
+ systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR,
+ N_("Cannot import snapshot for %s. Current game is %s"),
+ buffer,
+ buffer2);
+ fclose(file);
+ return false;
+ }
+ fseek(file, 0x13, SEEK_SET);
+ size_t read = 0;
+ int toRead = 0;
+ switch(gbRomType) {
+ case 0x03:
+ case 0x0f:
+ case 0x10:
+ case 0x13:
+ case 0x1b:
+ case 0x1e:
+ case 0xff:
+ read = fread(gbRam, 1, (gbRamSizeMask+1), file);
+ toRead = (gbRamSizeMask+1);
+ break;
+ case 0x06:
+ case 0x22:
+ read = fread(&gbMemory[0xa000],1,256,file);
+ toRead = 256;
+ break;
+ default:
+ systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE,
+ N_("Unsupported snapshot file %s"),
+ fileName);
+ fclose(file);
+ return false;
+ }
+ fclose(file);
+ gbReset();
+ return true;
+}
+
+variable_desc gbSaveGameStruct[] = {
+ { &PC.W, sizeof(u16) },
+ { &SP.W, sizeof(u16) },
+ { &AF.W, sizeof(u16) },
+ { &BC.W, sizeof(u16) },
+ { &DE.W, sizeof(u16) },
+ { &HL.W, sizeof(u16) },
+ { &IFF, sizeof(u8) },
+ { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int) },
+ { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int) },
+ { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int) },
+ { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int) },
+ { &GBDIV_CLOCK_TICKS, sizeof(int) },
+ { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int) },
+ { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int) },
+ { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int) },
+ { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int) },
+ { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int) },
+ { &GBSERIAL_CLOCK_TICKS, sizeof(int) },
+ { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int) },
+ { &gbDivTicks, sizeof(int) },
+ { &gbLcdMode, sizeof(int) },
+ { &gbLcdTicks, sizeof(int) },
+ { &gbLcdLYIncrementTicks, sizeof(int) },
+ { &gbTimerTicks, sizeof(int) },
+ { &gbTimerClockTicks, sizeof(int) },
+ { &gbSerialTicks, sizeof(int) },
+ { &gbSerialBits, sizeof(int) },
+ { &gbInt48Signal, sizeof(int) },
+ { &gbInterruptWait, sizeof(int) },
+ { &gbSynchronizeTicks, sizeof(int) },
+ { &gbTimerOn, sizeof(int) },
+ { &gbTimerMode, sizeof(int) },
+ { &gbSerialOn, sizeof(int) },
+ { &gbWindowLine, sizeof(int) },
+ { &gbCgbMode, sizeof(int) },
+ { &gbVramBank, sizeof(int) },
+ { &gbWramBank, sizeof(int) },
+ { &gbHdmaSource, sizeof(int) },
+ { &gbHdmaDestination, sizeof(int) },
+ { &gbHdmaBytes, sizeof(int) },
+ { &gbHdmaOn, sizeof(int) },
+ { &gbSpeed, sizeof(int) },
+ { &gbSgbMode, sizeof(int) },
+ { ®ister_DIV, sizeof(u8) },
+ { ®ister_TIMA, sizeof(u8) },
+ { ®ister_TMA, sizeof(u8) },
+ { ®ister_TAC, sizeof(u8) },
+ { ®ister_IF, sizeof(u8) },
+ { ®ister_LCDC, sizeof(u8) },
+ { ®ister_STAT, sizeof(u8) },
+ { ®ister_SCY, sizeof(u8) },
+ { ®ister_SCX, sizeof(u8) },
+ { ®ister_LY, sizeof(u8) },
+ { ®ister_LYC, sizeof(u8) },
+ { ®ister_DMA, sizeof(u8) },
+ { ®ister_WY, sizeof(u8) },
+ { ®ister_WX, sizeof(u8) },
+ { ®ister_VBK, sizeof(u8) },
+ { ®ister_HDMA1, sizeof(u8) },
+ { ®ister_HDMA2, sizeof(u8) },
+ { ®ister_HDMA3, sizeof(u8) },
+ { ®ister_HDMA4, sizeof(u8) },
+ { ®ister_HDMA5, sizeof(u8) },
+ { ®ister_SVBK, sizeof(u8) },
+ { ®ister_IE , sizeof(u8) },
+ { &gbBgp[0], sizeof(u8) },
+ { &gbBgp[1], sizeof(u8) },
+ { &gbBgp[2], sizeof(u8) },
+ { &gbBgp[3], sizeof(u8) },
+ { &gbObp0[0], sizeof(u8) },
+ { &gbObp0[1], sizeof(u8) },
+ { &gbObp0[2], sizeof(u8) },
+ { &gbObp0[3], sizeof(u8) },
+ { &gbObp1[0], sizeof(u8) },
+ { &gbObp1[1], sizeof(u8) },
+ { &gbObp1[2], sizeof(u8) },
+ { &gbObp1[3], sizeof(u8) },
+ { NULL, 0 }
+};
+
+
+static bool gbWriteSaveState(gzFile gzFile)
+{
+
+ utilWriteInt(gzFile, GBSAVE_GAME_VERSION);
+
+ utilGzWrite(gzFile, &gbRom[0x134], 15);
+
+ utilWriteInt(gzFile, useBios);
+ utilWriteInt(gzFile, inBios);
+
+ utilWriteData(gzFile, gbSaveGameStruct);
+
+ utilGzWrite(gzFile, &IFF, 2);
+
+ if(gbSgbMode) {
+ gbSgbSaveGame(gzFile);
+ }
+
+ utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
+ utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
+ utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
+ utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
+ utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
+ utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
+ utilGzWrite(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5));
+ if (gbTAMA5ram != NULL)
+ utilGzWrite(gzFile, gbTAMA5ram, gbTAMA5ramSize);
+ utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
+
+ utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
+
+ utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
+
+ if(gbRamSize && gbRam) {
+ utilWriteInt(gzFile, gbRamSize);
+ utilGzWrite(gzFile, gbRam, gbRamSize);
+ }
+
+ if(gbCgbMode) {
+ utilGzWrite(gzFile, gbVram, 0x4000);
+ utilGzWrite(gzFile, gbWram, 0x8000);
+ }
+
+ gbSoundSaveGame(gzFile);
+
+ gbCheatsSaveGame(gzFile);
+
+ utilWriteInt(gzFile, gbLcdModeDelayed);
+ utilWriteInt(gzFile, gbLcdTicksDelayed);
+ utilWriteInt(gzFile, gbLcdLYIncrementTicksDelayed);
+ utilWriteInt(gzFile, gbSpritesTicks[299]);
+ utilWriteInt(gzFile, gbTimerModeChange);
+ utilWriteInt(gzFile, gbTimerOnChange);
+ utilWriteInt(gzFile, gbHardware);
+ utilWriteInt(gzFile, gbBlackScreen);
+ utilWriteInt(gzFile, oldRegister_WY);
+ utilWriteInt(gzFile, gbWindowLine);
+ utilWriteInt(gzFile, inUseRegister_WY);
+ utilWriteInt(gzFile, gbScreenOn);
+ return true;
+}
+
+bool gbWriteMemSaveState(char *memory, int available)
+{
+ gzFile gzFile = utilMemGzOpen(memory, available, "w");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ bool res = gbWriteSaveState(gzFile);
+
+ long pos = utilGzMemTell(gzFile)+8;
+
+ if(pos >= (available))
+ res = false;
+
+ utilGzClose(gzFile);
+
+ return res;
+}
+
+bool gbWriteSaveState(const char *name)
+{
+ gzFile gzFile = utilGzOpen(name,"wb");
+
+ if(gzFile == NULL)
+ return false;
+
+ bool res = gbWriteSaveState(gzFile);
+
+ utilGzClose(gzFile);
+ return res;
+}
+
+static bool gbReadSaveState(gzFile gzFile)
+{
+ int version = utilReadInt(gzFile);
+
+ if(version > GBSAVE_GAME_VERSION || version < 0) {
+ systemMessage(MSG_UNSUPPORTED_VB_SGM,
+ N_("Unsupported VisualBoy save game version %d"), version);
+ return false;
+ }
+
+ u8 romname[20];
+
+ utilGzRead(gzFile, romname, 15);
+
+ if(memcmp(&gbRom[0x134], romname, 15) != 0) {
+ systemMessage(MSG_CANNOT_LOAD_SGM_FOR,
+ N_("Cannot load save game for %s. Playing %s"),
+ romname, &gbRom[0x134]);
+ return false;
+ }
+
+
+ bool ub = false;
+ bool ib = false;
+
+ if (version >= 11)
+ {
+ ub = utilReadInt(gzFile) ? true : false;
+ ib = utilReadInt(gzFile) ? true : false;
+
+ if((ub != useBios) && (ib)) {
+ if(useBios)
+ systemMessage(MSG_SAVE_GAME_NOT_USING_BIOS,
+ N_("Save game is not using the BIOS files"));
+ else
+ systemMessage(MSG_SAVE_GAME_USING_BIOS,
+ N_("Save game is using the BIOS file"));
+ return false;
+ }
+ }
+
+ gbReset();
+
+ inBios = ib;
+
+ utilReadData(gzFile, gbSaveGameStruct);
+
+
+ // Correct crash when loading color gameboy save in regular gameboy type.
+ if (!gbCgbMode)
+ {
+ if(gbVram != NULL) {
+ free(gbVram);
+ gbVram = NULL;
+ }
+ if(gbWram != NULL) {
+ free(gbWram);
+ gbWram = NULL;
+ }
+ }
+ else
+ {
+ if(gbVram == NULL)
+ gbVram = (u8 *)malloc(0x4000);
+ if(gbWram == NULL)
+ gbWram = (u8 *)malloc(0x8000);
+ memset(gbVram,0,0x4000);
+ memset(gbPalette,0, 2*128);
+ }
+
+
+
+ if(version >= GBSAVE_GAME_VERSION_7) {
+ utilGzRead(gzFile, &IFF, 2);
+ }
+
+ if(gbSgbMode) {
+ gbSgbReadGame(gzFile, version);
+ } else {
+ gbSgbMask = 0; // loading a game at the wrong time causes no display
+ }
+ if (version<11)
+ utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1) - sizeof(int));
+ else
+ utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
+ utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
+ if(version < GBSAVE_GAME_VERSION_4)
+ // prior to version 4, there was no adjustment for the time the game
+ // was last played, so we have less to read. This needs update if the
+ // structure changes again.
+ utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)-sizeof(time_t));
+ else
+ utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
+ utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
+ utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
+ utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
+ if (version>=11)
+ {
+ utilGzRead(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5));
+ if (gbTAMA5ram != NULL)
+ utilGzRead(gzFile, gbTAMA5ram, gbTAMA5ramSize);
+ utilGzRead(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
+ }
+
+ if(version < GBSAVE_GAME_VERSION_5) {
+ utilGzRead(gzFile, pix, 256*224*sizeof(u16));
+ }
+ memset(pix, 0, 257*226*sizeof(u32));
+
+ if(version < GBSAVE_GAME_VERSION_6) {
+ utilGzRead(gzFile, gbPalette, 64 * sizeof(u16));
+ } else
+ utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
+
+ if (version < 11)
+ utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
+
+ if(version < GBSAVE_GAME_VERSION_10) {
+ if(!gbCgbMode && !gbSgbMode) {
+ for(int i = 0; i < 8; i++)
+ gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
+ }
+ }
+
+ utilGzRead(gzFile, &gbMemory[0x8000], 0x8000);
+
+ if(gbRamSize && gbRam) {
+ if (version < 11)
+ utilGzRead(gzFile, gbRam, gbRamSize);
+ else
+ {
+ int ramSize = utilReadInt(gzFile);
+ utilGzRead(gzFile, gbRam, (gbRamSize>ramSize) ? ramSize : gbRamSize);
+ if (ramSize>gbRamSize)
+ gzseek(gzFile,ramSize-gbRamSize,SEEK_CUR);
+ }
+ }
+
+ memset(gbSCYLine, register_SCY, sizeof(gbSCYLine));
+ memset(gbSCXLine, register_SCX, sizeof(gbSCXLine));
+ memset(gbBgpLine, (gbBgp[0] | (gbBgp[1]<<2) | (gbBgp[2]<<4) |
+ (gbBgp[3]<<6)), sizeof(gbBgpLine));
+ memset(gbObp0Line, (gbObp0[0] | (gbObp0[1]<<2) | (gbObp0[2]<<4) |
+ (gbObp0[3]<<6)), sizeof(gbObp0Line));
+ memset(gbObp1Line, (gbObp1[0] | (gbObp1[1]<<2) | (gbObp1[2]<<4) |
+ (gbObp1[3]<<6)), sizeof(gbObp1Line));
+ memset(gbSpritesTicks, 0x0, sizeof(gbSpritesTicks));
+
+ if (inBios)
+ {
+ gbMemoryMap[0x00] = &gbMemory[0x0000];
+ memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000);
+ memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100);
+ }
+ else
+ gbMemoryMap[0x00] = &gbRom[0x0000];
+ gbMemoryMap[0x01] = &gbRom[0x1000];
+ gbMemoryMap[0x02] = &gbRom[0x2000];
+ gbMemoryMap[0x03] = &gbRom[0x3000];
+ gbMemoryMap[0x04] = &gbRom[0x4000];
+ gbMemoryMap[0x05] = &gbRom[0x5000];
+ gbMemoryMap[0x06] = &gbRom[0x6000];
+ gbMemoryMap[0x07] = &gbRom[0x7000];
+ gbMemoryMap[0x08] = &gbMemory[0x8000];
+ gbMemoryMap[0x09] = &gbMemory[0x9000];
+ gbMemoryMap[0x0a] = &gbMemory[0xa000];
+ gbMemoryMap[0x0b] = &gbMemory[0xb000];
+ gbMemoryMap[0x0c] = &gbMemory[0xc000];
+ gbMemoryMap[0x0d] = &gbMemory[0xd000];
+ gbMemoryMap[0x0e] = &gbMemory[0xe000];
+ gbMemoryMap[0x0f] = &gbMemory[0xf000];
+
+ switch(gbRomType) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ // MBC 1
+ memoryUpdateMapMBC1();
+ break;
+ case 0x05:
+ case 0x06:
+ // MBC2
+ memoryUpdateMapMBC2();
+ break;
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ // MMM01
+ memoryUpdateMapMMM01();
+ break;
+ case 0x0f:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ // MBC 3
+ memoryUpdateMapMBC3();
+ break;
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ // MBC5
+ memoryUpdateMapMBC5();
+ break;
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ // MBC 5 Rumble
+ memoryUpdateMapMBC5();
+ break;
+ case 0x22:
+ // MBC 7
+ memoryUpdateMapMBC7();
+ break;
+ case 0x56:
+ // GS3
+ memoryUpdateMapGS3();
+ break;
+ case 0xfd:
+ // TAMA5
+ memoryUpdateMapTAMA5();
+ break;
+ case 0xfe:
+ // HuC3
+ memoryUpdateMapHuC3();
+ break;
+ case 0xff:
+ // HuC1
+ memoryUpdateMapHuC1();
+ break;
+ }
+
+ if(gbCgbMode) {
+ utilGzRead(gzFile, gbVram, 0x4000);
+ utilGzRead(gzFile, gbWram, 0x8000);
+
+ int value = register_SVBK;
+ if(value == 0)
+ value = 1;
+
+ gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000];
+ gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000];
+ gbMemoryMap[0x0d] = &gbWram[value * 0x1000];
+ }
+
+ gbSoundReadGame(version, gzFile);
+
+ if (gbCgbMode && gbSgbMode) {
+ gbSgbMode = 0;
+ }
+
+ if(gbBorderOn && !gbSgbMask) {
+ gbSgbRenderBorder();
+ }
+
+ systemDrawScreen();
+
+ if(version > GBSAVE_GAME_VERSION_1)
+ gbCheatsReadGame(gzFile, version);
+
+ if (version<11)
+ {
+ gbWriteMemory(0xff00, 0);
+ gbMemory[0xff04] = register_DIV;
+ gbMemory[0xff05] = register_TIMA;
+ gbMemory[0xff06] = register_TMA;
+ gbMemory[0xff07] = register_TAC;
+ gbMemory[0xff40] = register_LCDC;
+ gbMemory[0xff42] = register_SCY;
+ gbMemory[0xff43] = register_SCX;
+ gbMemory[0xff44] = register_LY;
+ gbMemory[0xff45] = register_LYC;
+ gbMemory[0xff46] = register_DMA;
+ gbMemory[0xff4a] = register_WY;
+ gbMemory[0xff4b] = register_WX;
+ gbMemory[0xff4f] = register_VBK;
+ gbMemory[0xff51] = register_HDMA1;
+ gbMemory[0xff52] = register_HDMA2;
+ gbMemory[0xff53] = register_HDMA3;
+ gbMemory[0xff54] = register_HDMA4;
+ gbMemory[0xff55] = register_HDMA5;
+ gbMemory[0xff70] = register_SVBK;
+ gbMemory[0xffff] = register_IE;
+ GBDIV_CLOCK_TICKS = 64;
+
+ if (gbSpeed)
+ gbDivTicks /=2;
+
+ if ((gbLcdMode == 0) && (register_STAT & 8))
+ gbInt48Signal |= 1;
+ if ((gbLcdMode == 1) && (register_STAT & 0x10))
+ gbInt48Signal |= 2;
+ if ((gbLcdMode == 2) && (register_STAT & 0x20))
+ gbInt48Signal |= 4;
+ if ((register_LY==register_LYC) && (register_STAT & 0x40))
+ gbInt48Signal |= 8;
+
+ gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS;
+
+ if (gbLcdMode == 2)
+ gbLcdLYIncrementTicks-=GBLCD_MODE_2_CLOCK_TICKS-gbLcdTicks;
+ else if (gbLcdMode == 3)
+ gbLcdLYIncrementTicks -=GBLCD_MODE_2_CLOCK_TICKS+GBLCD_MODE_3_CLOCK_TICKS-gbLcdTicks;
+ else if (gbLcdMode == 0)
+ gbLcdLYIncrementTicks =gbLcdTicks;
+ else if (gbLcdMode == 1)
+ {
+ gbLcdLYIncrementTicks = gbLcdTicks % GBLY_INCREMENT_CLOCK_TICKS;
+ if (register_LY == 0x99)
+ gbLcdLYIncrementTicks =gbLine99Ticks;
+ else if (register_LY == 0)
+ gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
+ }
+
+ gbLcdModeDelayed = gbLcdMode;
+ gbLcdTicksDelayed = gbLcdTicks--;
+ gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks--;
+ gbInterruptWait = 0;
+ memset(gbSpritesTicks,0,sizeof(gbSpritesTicks));
+ }
+ else
+ {
+ gbLcdModeDelayed = utilReadInt(gzFile);
+ gbLcdTicksDelayed = utilReadInt(gzFile);
+ gbLcdLYIncrementTicksDelayed = utilReadInt(gzFile);
+ gbSpritesTicks[299] = utilReadInt(gzFile) & 0xff;
+ gbTimerModeChange = (utilReadInt(gzFile) ? true : false);
+ gbTimerOnChange = (utilReadInt(gzFile) ? true : false);
+ gbHardware = utilReadInt(gzFile);
+ gbBlackScreen = (utilReadInt(gzFile) ? true : false);
+ oldRegister_WY = utilReadInt(gzFile);
+ gbWindowLine = utilReadInt(gzFile);
+ inUseRegister_WY = utilReadInt(gzFile);
+ gbScreenOn = (utilReadInt(gzFile) ? true : false);
+ }
+
+ if (gbSpeed)
+ gbLine99Ticks *= 2;
+
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+
+ return true;
+}
+
+bool gbReadMemSaveState(char *memory, int available)
+{
+ gzFile gzFile = utilMemGzOpen(memory, available, "r");
+
+ bool res = gbReadSaveState(gzFile);
+
+ utilGzClose(gzFile);
+
+ return res;
+}
+
+bool gbReadSaveState(const char *name)
+{
+ gzFile gzFile = utilGzOpen(name,"rb");
+
+ if(gzFile == NULL) {
+ return false;
+ }
+
+ bool res = gbReadSaveState(gzFile);
+
+ utilGzClose(gzFile);
+
+ return res;
+}
+
+bool gbWritePNGFile(const char *fileName)
+{
+ if(gbBorderOn)
+ return utilWritePNGFile(fileName, 256, 224, pix);
+ return utilWritePNGFile(fileName, 160, 144, pix);
+}
+
+bool gbWriteBMPFile(const char *fileName)
+{
+ if(gbBorderOn)
+ return utilWriteBMPFile(fileName, 256, 224, pix);
+ return utilWriteBMPFile(fileName, 160, 144, pix);
+}
+
+void gbCleanUp()
+{
+ if(gbRam != NULL) {
+ free(gbRam);
+ gbRam = NULL;
+ }
+
+ if(gbRom != NULL) {
+ free(gbRom);
+ gbRom = NULL;
+ }
+
+ if(gbMemory != NULL) {
+ free(gbMemory);
+ gbMemory = NULL;
+ }
+
+ if(gbLineBuffer != NULL) {
+ free(gbLineBuffer);
+ gbLineBuffer = NULL;
+ }
+
+ if(pix != NULL) {
+ free(pix);
+ pix = NULL;
+ }
+
+ gbSgbShutdown();
+
+ if(gbVram != NULL) {
+ free(gbVram);
+ gbVram = NULL;
+ }
+
+ if(gbWram != NULL) {
+ free(gbWram);
+ gbWram = NULL;
+ }
+
+ if(gbTAMA5ram != NULL) {
+ free(gbTAMA5ram);
+ gbTAMA5ram = NULL;
+ }
+
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+}
+
+bool gbLoadRom(const char *szFile)
+{
+ int size = 0;
+
+ if(gbRom != NULL) {
+ gbCleanUp();
+ }
+
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+
+ gbRom = utilLoad(szFile,
+ utilIsGBImage,
+ NULL,
+ size);
+ if(!gbRom)
+ return false;
+
+ gbRomSize = size;
+
+ gbBatteryError = false;
+
+ if(bios != NULL) {
+ free(bios);
+ bios = NULL;
+ }
+ bios = (u8 *)calloc(1,0x100);
+
+ return gbUpdateSizes();
+}
+
+bool gbUpdateSizes()
+{
+ if(gbRom[0x148] > 8) {
+ systemMessage(MSG_UNSUPPORTED_ROM_SIZE,
+ N_("Unsupported rom size %02x"), gbRom[0x148]);
+ return false;
+ }
+
+ if(gbRomSize < gbRomSizes[gbRom[0x148]]) {
+ gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]);
+ for (int i = gbRomSize; igbRomSizes[gbRom[0x148]]) && (genericflashcardEnable))
+ {
+ gbRomSize = gbRomSize>>16;
+ gbRom[0x148] = 0;
+ if (gbRomSize)
+ {
+ while (!((gbRomSize & 1) || (gbRom[0x148] == 7)))
+ {
+ gbRom[0x148]++;
+ gbRomSize>>=1;
+ }
+ gbRom[0x148]++;
+ }
+ gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]);
+ }
+ gbRomSize = gbRomSizes[gbRom[0x148]];
+ gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]];
+
+
+ // The 'genericflashcard' option allows some PD to work.
+ // However, the setting is dangerous (if you let in enabled
+ // and play a normal game, it might just break everything).
+ // That's why it is not saved in the emulator options.
+ // Also I added some checks in VBA to make sure your saves will not be
+ // overwritten if you wrongly enable this option for a game
+ // you already played (and vice-versa, ie. if you forgot to
+ // enable the option for a game you played with it enabled, like Shawu Story).
+ u8 ramsize = genericflashcardEnable ? 5 : gbRom[0x149];
+ gbRom[0x149] = ramsize;
+
+ if ((gbRom[2] == 0x6D) && (gbRom[5] == 0x47) && (gbRom[6] == 0x65) && (gbRom[7] == 0x6E) &&
+ (gbRom[8] == 0x69) && (gbRom[9] == 0x65) && (gbRom[0xA] == 0x28) && (gbRom[0xB] == 0x54))
+ {
+ gbCheatingDevice = 1; // GameGenie
+ for (int i = 0; i < 0x20; i++) // Cleans GG hardware registers
+ gbRom[0x4000+i] = 0;
+ }
+ else if (((gbRom[0x104] == 0x44) && (gbRom[0x156] == 0xEA) && (gbRom[0x158] == 0x7F) &&
+ (gbRom[0x159] == 0xEA) && (gbRom[0x15B] == 0x7F)) || ((gbRom[0x165] == 0x3E) &&
+ (gbRom[0x166] == 0xD9) && (gbRom[0x16D] == 0xE1) && (gbRom[0x16E] == 0x7F)))
+ gbCheatingDevice = 2; // GameShark
+ else gbCheatingDevice = 0;
+
+ if(ramsize > 5) {
+ systemMessage(MSG_UNSUPPORTED_RAM_SIZE,
+ N_("Unsupported ram size %02x"), gbRom[0x149]);
+ return false;
+ }
+
+ gbRamSize = gbRamSizes[ramsize];
+ gbRamSizeMask = gbRamSizesMasks[ramsize];
+
+ if(gbRamSize) {
+ gbRam = (u8 *)malloc(gbRamSize);
+ memset(gbRam, 0xff, gbRamSize);
+ }
+
+
+ gbRomType = gbRom[0x147];
+ if (genericflashcardEnable)
+ {
+ /*if (gbRomType<2)
+ gbRomType =3;
+ else if ((gbRomType == 0xc) || (gbRomType == 0xf) || (gbRomType == 0x12) ||
+ (gbRomType == 0x16) || (gbRomType == 0x1a) || (gbRomType == 0x1d))
+ gbRomType++;
+ else if ((gbRomType == 0xb) || (gbRomType == 0x11) || (gbRomType == 0x15) ||
+ (gbRomType == 0x19) || (gbRomType == 0x1c))
+ gbRomType+=2;
+ else if ((gbRomType == 0x5) || (gbRomType == 0x6))
+ gbRomType = 0x1a;*/
+ gbRomType = 0x1b;
+ }
+ else if (gbCheatingDevice == 1)
+ gbRomType = 0x55;
+ else if (gbCheatingDevice == 2)
+ gbRomType = 0x56;
+
+ gbRom[0x147] = gbRomType;
+
+ mapperReadRAM = NULL;
+
+ switch(gbRomType) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x08:
+ case 0x09:
+ // MBC 1
+ mapper = mapperMBC1ROM;
+ mapperRAM = mapperMBC1RAM;
+ mapperReadRAM = mapperMBC1ReadRAM;
+ break;
+ case 0x05:
+ case 0x06:
+ // MBC2
+ mapper = mapperMBC2ROM;
+ mapperRAM = mapperMBC2RAM;
+ gbRamSize = 0x200;
+ gbRamSizeMask = 0x1ff;
+ break;
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ // MMM01
+ mapper = mapperMMM01ROM;
+ mapperRAM = mapperMMM01RAM;
+ break;
+ case 0x0f:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0xfc:
+ // MBC 3
+ mapper = mapperMBC3ROM;
+ mapperRAM = mapperMBC3RAM;
+ mapperReadRAM = mapperMBC3ReadRAM;
+ break;
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ // MBC5
+ mapper = mapperMBC5ROM;
+ mapperRAM = mapperMBC5RAM;
+ mapperReadRAM = mapperMBC5ReadRAM;
+ break;
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ // MBC 5 Rumble
+ mapper = mapperMBC5ROM;
+ mapperRAM = mapperMBC5RAM;
+ mapperReadRAM = mapperMBC5ReadRAM;
+ break;
+ case 0x22:
+ // MBC 7
+ mapper = mapperMBC7ROM;
+ mapperRAM = mapperMBC7RAM;
+ mapperReadRAM = mapperMBC7ReadRAM;
+ break;
+ // GG (GameGenie)
+ case 0x55:
+ mapper = mapperGGROM;
+ break;
+ case 0x56:
+ // GS (GameShark)
+ mapper = mapperGS3ROM;
+ break;
+ case 0xfd:
+ // TAMA5
+ if (gbRam!= NULL)
+ {
+ free(gbRam);
+ gbRam = NULL;
+ }
+
+ ramsize = 3;
+ gbRamSize = gbRamSizes[3];
+ gbRamSizeMask = gbRamSizesMasks[3];
+ gbRam = (u8 *)malloc(gbRamSize);
+ memset(gbRam, 0x0, gbRamSize);
+
+ gbTAMA5ramSize = 0x100;
+
+ if (gbTAMA5ram == NULL)
+ gbTAMA5ram = (u8 *)malloc(gbTAMA5ramSize);
+ memset(gbTAMA5ram, 0x0, gbTAMA5ramSize);
+
+ mapperRAM = mapperTAMA5RAM;
+ mapperReadRAM = mapperTAMA5ReadRAM;
+ mapperUpdateClock = memoryUpdateTAMA5Clock;
+ break;
+ case 0xfe:
+ // HuC3
+ mapper = mapperHuC3ROM;
+ mapperRAM = mapperHuC3RAM;
+ mapperReadRAM = mapperHuC3ReadRAM;
+ break;
+ case 0xff:
+ // HuC1
+ mapper = mapperHuC1ROM;
+ mapperRAM = mapperHuC1RAM;
+ break;
+ default:
+ systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE,
+ N_("Unknown cartridge type %02x"), gbRomType);
+ return false;
+ }
+
+ switch(gbRomType) {
+ case 0x03:
+ case 0x06:
+ case 0x0f:
+ case 0x10:
+ case 0x13:
+ case 0x1b:
+ case 0x1d:
+ case 0x1e:
+ case 0x22:
+ case 0xfd:
+ case 0xff:
+ gbBattery = 1;
+ break;
+ }
+
+ gbInit();
+
+ //gbReset();
+
+ switch(gbRomType) {
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ gbDataMBC5.isRumbleCartridge = 1;
+ }
+
+ return true;
+}
+
+int gbGetNextEvent (int clockTicks)
+{
+ if (register_LCDC & 0x80)
+ {
+ if(gbLcdTicks < clockTicks)
+ clockTicks = gbLcdTicks;
+
+ if(gbLcdTicksDelayed < clockTicks)
+ clockTicks = gbLcdTicksDelayed;
+
+ if(gbLcdLYIncrementTicksDelayed < clockTicks)
+ clockTicks = gbLcdLYIncrementTicksDelayed;
+ }
+
+ if(gbLcdLYIncrementTicks < clockTicks)
+ clockTicks = gbLcdLYIncrementTicks;
+
+ if(gbSerialOn && (gbSerialTicks < clockTicks))
+ clockTicks = gbSerialTicks;
+
+ if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks))
+ clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1;
+
+ if(soundTicks && (soundTicks < clockTicks))
+ clockTicks = soundTicks;
+
+ if ((clockTicks<=0) || (gbInterruptWait))
+ clockTicks = 1;
+
+ return clockTicks;
+}
+
+void gbDrawLine()
+{
+ switch(systemColorDepth) {
+ case 16:
+ {
+ u16 * dest = (u16 *)pix +
+ (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1)
+ + gbBorderColumnSkip;
+ for(int x = 0; x < 160; ) {
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ *dest++ = systemColorMap16[gbLineMix[x++]];
+ }
+ if(gbBorderOn)
+ dest += gbBorderColumnSkip;
+ *dest++ = 0; // for filters that read one pixel more
+ }
+ break;
+
+ case 24:
+ {
+ u8 *dest = (u8 *)pix +
+ 3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) +
+ gbBorderColumnSkip);
+ for(int x = 0; x < 160;) {
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
+ dest+= 3;
+ }
+ }
+ break;
+
+ case 32:
+ {
+ u32 * dest = (u32 *)pix +
+ (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1)
+ + gbBorderColumnSkip;
+ for(int x = 0; x < 160;) {
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ *dest++ = systemColorMap32[gbLineMix[x++]];
+ }
+ }
+ break;
+ }
+}
+
+void gbEmulate(int ticksToStop)
+{
+ gbRegister tempRegister;
+ u8 tempValue;
+ s8 offset;
+
+ clockTicks = 0;
+ gbDmaTicks = 0;
+
+ register int opcode = 0;
+
+ int opcode1 = 0;
+ int opcode2 = 0;
+ bool execute = false;
+
+ while(1) {
+#ifndef FINAL_VERSION
+ if(systemDebug) {
+ if(!(IFF & 0x80)) {
+ if(systemDebug > 1) {
+ sprintf(gbBuffer,"PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n",
+ PC.W, AF.W, BC.W, DE.W,HL.W,SP.W,IFF);
+ } else {
+ sprintf(gbBuffer,"PC=%04x I=%02x\n", PC.W, IFF);
+ }
+ log(gbBuffer);
+ }
+ }
+#endif
+
+ u16 oldPCW = PC.W;
+
+ if(IFF & 0x80) {
+ if(register_LCDC & 0x80) {
+ clockTicks = gbLcdTicks;
+ } else
+ clockTicks = 1000;
+
+ clockTicks = gbGetNextEvent(clockTicks);
+
+ /*if(gbLcdTicksDelayed < clockTicks)
+ clockTicks = gbLcdTicksDelayed;
+
+ if(gbLcdLYIncrementTicksDelayed < clockTicks)
+ clockTicks = gbLcdLYIncrementTicksDelayed;
+
+ if(gbLcdLYIncrementTicks < clockTicks)
+ clockTicks = gbLcdLYIncrementTicks;
+
+ if(gbSerialOn && (gbSerialTicks < clockTicks))
+ clockTicks = gbSerialTicks;
+
+ if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks))
+ clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1;
+
+ if(soundTicks && (soundTicks < clockTicks))
+ clockTicks = soundTicks;
+
+ if ((clockTicks<=0) || (gbInterruptWait))
+ clockTicks = 1;*/
+
+ } else {
+
+ // First we apply the clockTicks, then we execute the opcodes.
+ opcode1 = 0;
+ opcode2 = 0;
+ execute = true;
+
+ opcode2 = opcode1 = opcode = gbReadOpcode(PC.W++);
+
+ // If HALT state was launched while IME = 0 and (register_IF & register_IE & 0x1F),
+ // PC.W is not incremented for the first byte of the next instruction.
+ if (IFF & 2)
+ {
+ PC.W--;
+ IFF &= ~2;
+ }
+
+ clockTicks = gbCycles[opcode];
+
+ switch(opcode) {
+ case 0xCB:
+ // extended opcode
+ opcode2 = opcode = gbReadOpcode(PC.W++);
+ clockTicks = gbCyclesCB[opcode];
+ break;
+ }
+ gbOldClockTicks = clockTicks-1;
+ gbIntBreak = 1;
+ }
+
+
+ if(!emulating)
+ return;
+
+ // For 'breakpoint' support (opcode 0xFC is considered as a breakpoint)
+ if ((clockTicks==0) && execute)
+ {
+ PC.W = oldPCW;
+ return;
+ }
+
+
+ if (!(IFF & 0x80))
+ clockTicks = 1;
+
+ gbRedoLoop:
+
+
+
+ if (gbInterruptWait)
+ gbInterruptWait = 0;
+ else
+ gbInterruptLaunched = 0;
+
+
+ // Used for the EI/DI instruction's delay.
+ if (IFF & 0x38)
+ {
+ int tempIFF = (IFF >> 4) & 3;
+
+ if (tempIFF <=clockTicks)
+ {
+ tempIFF = 0;
+ IFF |=1;
+ }
+ else
+ tempIFF -= clockTicks;
+ IFF = (IFF & 0xCF) | (tempIFF <<4);
+
+ if (IFF & 0x08)
+ IFF &= 0x82;
+ }
+
+
+ if (register_LCDCBusy)
+ {
+ register_LCDCBusy-=clockTicks;
+ if (register_LCDCBusy<0)
+ register_LCDCBusy = 0;
+ }
+
+
+ if(gbSgbMode) {
+ if(gbSgbPacketTimeout) {
+ gbSgbPacketTimeout -= clockTicks;
+
+ if(gbSgbPacketTimeout <= 0)
+ gbSgbResetPacketState();
+ }
+ }
+
+ ticksToStop -= clockTicks;
+
+ // DIV register emulation
+ gbDivTicks -= clockTicks;
+ while(gbDivTicks <= 0) {
+ gbMemory[0xff04] = ++register_DIV;
+ gbDivTicks += GBDIV_CLOCK_TICKS;
+ }
+
+ if(register_LCDC & 0x80) {
+ // LCD stuff
+
+ gbLcdTicks -= clockTicks;
+ gbLcdTicksDelayed -= clockTicks;
+ gbLcdLYIncrementTicks -= clockTicks;
+ gbLcdLYIncrementTicksDelayed -= clockTicks;
+
+
+ // our counters are off, see what we need to do
+
+ // This looks (and kinda is) complicated, however this
+ // is the only way I found to emulate properly the way
+ // the real hardware operates...
+ while(((gbLcdTicks <= 0) && (gbLCDChangeHappened == false)) ||
+ ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened == true)) ||
+ ((gbLcdLYIncrementTicks <= 0) && (gbLYChangeHappened == false)) ||
+ ((gbLcdLYIncrementTicksDelayed<=0) && (gbLYChangeHappened == true)))
+ {
+
+ if ((gbLcdLYIncrementTicks <= 0) && (!gbLYChangeHappened))
+ {
+ gbLYChangeHappened = true;
+ gbMemory[0xff44] = register_LY = (register_LY + 1) % 154;
+
+ if (register_LY == 0x91)
+ {
+ /* if (IFF & 0x80)
+ gbScreenOn = !gbScreenOn;
+ else*/ if (register_LCDC & 0x80)
+ gbScreenOn = true;
+ }
+
+ gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
+
+ if (gbLcdMode == 1)
+ {
+
+ if(register_LY == 153)
+ gbLcdLYIncrementTicks -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
+ else if(register_LY == 0)
+ gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
+ }
+
+ // GB only 'bug' : Halt state is broken one tick before LY==LYC interrupt
+ // is reflected in the registers.
+ if ((gbHardware & 5) && (IFF & 0x80) && (register_LY == register_LYC)
+ && (register_STAT & 0x40) && (register_LY != 0))
+ {
+ if (!((gbLcdModeDelayed != 1) && (register_LY==0)))
+ {
+ gbInt48Signal &= ~9;
+ gbCompareLYToLYC();
+ gbLYChangeHappened = false;
+ gbMemory[0xff41] = register_STAT;
+ gbMemory[0xff0f] = register_IF;
+ }
+
+ gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks+1;
+ }
+ }
+
+
+ if ((gbLcdTicks <= 0) && (!gbLCDChangeHappened))
+ {
+ gbLCDChangeHappened = true;
+
+ switch(gbLcdMode)
+ {
+ case 0:
+ {
+ // H-Blank
+ // check if we reached the V-Blank period
+ if(register_LY == 144) {
+ // Yes, V-Blank
+ // set the LY increment counter
+ if (gbHardware & 0x5)
+ {
+ register_IF |= 1; // V-Blank interrupt
+ }
+
+ gbInt48Signal &= ~6;
+ if(register_STAT & 0x10)
+ {
+ // send LCD interrupt only if no interrupt 48h signal...
+ if ((!(gbInt48Signal & 1)) && ((!(gbInt48Signal & 8)) || (gbHardware & 0x0a)))
+ {
+ register_IF |=2;
+ gbInterruptLaunched |= 2;
+ if (gbHardware & 0xa)
+ gbInterruptWait = 1;
+ }
+ gbInt48Signal |= 2;
+ }
+ gbInt48Signal &= ~1;
+
+ gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS;
+ gbLcdMode = 1;
+
+ } else {
+ // go the the OAM being accessed mode
+ gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
+ gbLcdMode = 2;
+
+ gbInt48Signal &= ~6;
+ if(register_STAT & 0x20)
+ {
+ // send LCD interrupt only if no interrupt 48h signal...
+ if (!gbInt48Signal)
+ {
+ register_IF |= 2;
+ gbInterruptLaunched |= 2;
+ }
+ gbInt48Signal |= 4;
+ }
+ gbInt48Signal &= ~1;
+ }
+ }
+ break;
+ case 1:
+ {
+ // V-Blank
+ // next mode is OAM being accessed mode
+ gbInt48Signal &= ~5;
+ if(register_STAT & 0x20)
+ {
+ // send LCD interrupt only if no interrupt 48h signal...
+ if (!gbInt48Signal)
+ {
+ register_IF |= 2;
+ gbInterruptLaunched |= 2;
+ if ((gbHardware & 0xa) && (IFF & 0x80))
+ gbInterruptWait = 1;
+ }
+ gbInt48Signal |= 4;
+ }
+ gbInt48Signal &= ~2;
+
+ gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
+
+ gbLcdMode = 2;
+ register_LY = 0x00;
+
+ }
+ break;
+ case 2:
+ {
+
+ // OAM being accessed mode
+ // next mode is OAM and VRAM in use
+ if ((gbScreenOn) && (register_LCDC & 0x80))
+ {
+ gbDrawSprites(false);
+ // Used to add a one tick delay when a window line is drawn.
+ //(fixes a part of Carmaggedon problem)
+ if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) &&
+ (gbWindowLine != -2)) {
+
+ int inUseRegister_WY = 0;
+ int tempgbWindowLine = gbWindowLine;
+
+ if ((tempgbWindowLine == -1) || (tempgbWindowLine>144))
+ {
+ inUseRegister_WY = oldRegister_WY;
+ if (register_LY>oldRegister_WY)
+ tempgbWindowLine = 146;
+ }
+
+ int wy = inUseRegister_WY;
+
+ if(register_LY >= inUseRegister_WY) {
+
+ if (tempgbWindowLine == -1)
+ tempgbWindowLine = 0;
+
+ int wx = register_WX;
+ wx -= 7;
+ if (wx<0)
+ wx = 0;
+
+ if((wx <= 159) && (tempgbWindowLine <= 143))
+ for (int i = wx; i<300; i++)
+ if (gbSpeed)
+ gbSpritesTicks[i]+=3;
+ else
+ gbSpritesTicks[i]+=1;
+ }
+ }
+ }
+
+ gbInt48Signal &= ~7;
+
+ gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299];
+ gbLcdMode = 3;
+ }
+ break;
+ case 3:
+ {
+ // OAM and VRAM in use
+ // next mode is H-Blank
+
+
+ gbInt48Signal &= ~7;
+ if(register_STAT & 0x08)
+ {
+ // send LCD interrupt only if no interrupt 48h signal...
+ if (!(gbInt48Signal & 8))
+ {
+ register_IF |= 2;
+ if ((gbHardware & 0xa) && (IFF & 0x80))
+ gbInterruptWait = 1;
+ }
+ gbInt48Signal |= 1;
+ }
+
+ gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299];
+
+ gbLcdMode = 0;
+
+ // No HDMA during HALT !
+ if(gbHdmaOn && (!(IFF & 0x80) || (register_IE & register_IF & 0x1f))) {
+ gbDoHdma();
+ }
+
+ }
+ break;
+ }
+ }
+
+
+ if ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened)) {
+ int framesToSkip = systemFrameSkip;
+ if(speedup)
+ framesToSkip = 9; // try 6 FPS during speedup
+ //gbLcdTicksDelayed = gbLcdTicks+1;
+ gbLCDChangeHappened = false;
+ switch(gbLcdModeDelayed) {
+ case 0:
+ {
+ // H-Blank
+
+ memset(gbSCYLine,gbSCYLine[299],sizeof(gbSCYLine));
+ memset(gbSCXLine,gbSCXLine[299],sizeof(gbSCXLine));
+ memset(gbBgpLine,gbBgpLine[299],sizeof(gbBgpLine));
+ memset(gbObp0Line,gbObp0Line[299],sizeof(gbObp0Line));
+ memset(gbObp1Line,gbObp1Line[299],sizeof(gbObp1Line));
+ memset(gbSpritesTicks,gbSpritesTicks[299],sizeof(gbSpritesTicks));
+
+ if (gbWindowLine <0)
+ oldRegister_WY = register_WY;
+ // check if we reached the V-Blank period
+ if(register_LY == 144) {
+ // Yes, V-Blank
+ // set the LY increment counter
+
+ if(register_LCDC & 0x80) {
+ if (gbHardware & 0xa)
+ {
+
+ register_IF |= 1; // V-Blank interrupt
+ gbInterruptLaunched |=1;
+ }
+
+
+ }
+
+ gbLcdTicksDelayed += GBLCD_MODE_1_CLOCK_TICKS;
+ gbLcdModeDelayed = 1;
+
+ gbFrameCount++;
+ systemFrame();
+
+ if((gbFrameCount % 10) == 0)
+ system10Frames(60);
+
+ if(gbFrameCount >= 60) {
+ u32 currentTime = systemGetClock();
+ if(currentTime != gbLastTime)
+ systemShowSpeed(100000/(currentTime - gbLastTime));
+ else
+ systemShowSpeed(0);
+ gbLastTime = currentTime;
+ gbFrameCount = 0;
+ }
+
+ if(systemReadJoypads()) {
+ // read joystick
+ if(gbSgbMode && gbSgbMultiplayer) {
+ if(gbSgbFourPlayers) {
+ gbJoymask[0] = systemReadJoypad(0);
+ gbJoymask[1] = systemReadJoypad(1);
+ gbJoymask[2] = systemReadJoypad(2);
+ gbJoymask[3] = systemReadJoypad(3);
+ } else {
+ gbJoymask[0] = systemReadJoypad(0);
+ gbJoymask[1] = systemReadJoypad(1);
+ }
+ } else {
+ gbJoymask[0] = systemReadJoypad(-1);
+ }
+ }
+ int newmask = gbJoymask[0] & 255;
+
+ if(gbRomType == 0x22) {
+ systemUpdateMotionSensor();
+ }
+
+ if(newmask)
+ {
+ gbMemory[0xff0f] |= 16;
+ }
+
+
+ newmask = (gbJoymask[0] >> 10);
+
+ speedup = (newmask & 1) ? true : false;
+ gbCapture = (newmask & 2) ? true : false;
+
+ if(gbCapture && !gbCapturePrevious) {
+ gbCaptureNumber++;
+ systemScreenCapture(gbCaptureNumber);
+ }
+ gbCapturePrevious = gbCapture;
+
+ if(gbFrameSkipCount >= framesToSkip) {
+
+ if(!gbSgbMask)
+ {
+ if (gbBorderOn)
+ gbSgbRenderBorder();
+ //if (gbScreenOn)
+ systemDrawScreen();
+ }
+ gbFrameSkipCount = 0;
+ } else
+ gbFrameSkipCount++;
+
+ } else {
+ // go the the OAM being accessed mode
+ gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS;
+ gbLcdModeDelayed = 2;
+ gbInt48Signal &= ~3;
+ }
+ }
+ break;
+ case 1:
+ {
+ // V-Blank
+ // next mode is OAM being accessed mode
+
+ // gbScreenOn = true;
+
+ oldRegister_WY = register_WY;
+
+ gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS;
+ gbLcdModeDelayed = 2;
+
+ // reset the window line
+ gbWindowLine = -1;
+ }
+ break;
+ case 2:
+ {
+ // OAM being accessed mode
+ // next mode is OAM and VRAM in use
+ gbLcdTicksDelayed += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299];
+ gbLcdModeDelayed = 3;
+ }
+ break;
+ case 3:
+ {
+
+ // OAM and VRAM in use
+ // next mode is H-Blank
+ if((register_LY < 144) && (register_LCDC & 0x80) && gbScreenOn) {
+ if(!gbSgbMask) {
+ if(gbFrameSkipCount >= framesToSkip) {
+ if (!gbBlackScreen)
+ {
+ gbRenderLine();
+ gbDrawSprites(true);
+ }
+ else if (gbBlackScreen)
+ {
+ u16 color = gbColorOption ? gbColorFilter[0] : 0;
+ if (!gbCgbMode)
+ color = gbColorOption ? gbColorFilter[gbPalette[3] & 0x7FFF] :
+ gbPalette[3] & 0x7FFF;
+ for(int i = 0; i < 160; i++)
+ {
+ gbLineMix[i] = color;
+ gbLineBuffer[i] = 0;
+ }
+ }
+ gbDrawLine();
+ }
+ }
+ }
+ gbLcdTicksDelayed += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299];
+ gbLcdModeDelayed = 0;
+ }
+ break;
+ }
+ }
+
+ if ((gbLcdLYIncrementTicksDelayed <= 0) && (gbLYChangeHappened == true))
+ {
+
+ gbLYChangeHappened = false;
+
+ if (!((gbLcdMode != 1) && (register_LY==0)))
+ {
+ {
+ gbInt48Signal &= ~8;
+ gbCompareLYToLYC();
+ if ((gbInt48Signal == 8) && (!((register_LY == 0) && (gbHardware & 1))))
+ gbInterruptLaunched |= 2;
+ if ((gbHardware & (gbSpeed ? 8 : 2)) && (register_LY==0) && ((register_STAT & 0x44) == 0x44) && (gbLcdLYIncrementTicksDelayed==0))
+ {
+ gbInterruptWait = 1;
+
+ }
+ }
+ }
+ gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS;
+
+ if (gbLcdModeDelayed == 1)
+ {
+
+ if(register_LY == 153)
+ gbLcdLYIncrementTicksDelayed -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
+ else if(register_LY == 0)
+ gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
+ }
+ gbMemory[0xff0f] = register_IF;
+ gbMemory[0xff41] = register_STAT;
+ }
+ }
+ gbMemory[0xff0f] = register_IF;
+ gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | gbLcdModeDelayed;
+ }
+ else
+ {
+
+ // Used to update the screen with white lines when it's off.
+ // (it looks strange, but it's kinda accurate :p)
+ // You can try the Mario Demo Vx.x for exemple
+ // (check the bottom 2 lines while moving)
+ if (!gbWhiteScreen)
+ {
+ gbScreenTicks -= clockTicks;
+ gbLcdLYIncrementTicks -= clockTicks;
+ while (gbLcdLYIncrementTicks <=0)
+ {
+ register_LY = ((register_LY+1)%154);
+ gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS;
+ }
+ if (gbScreenTicks <= 0)
+ {
+ gbWhiteScreen = 1;
+ u8 register_LYLcdOff = ((register_LY+154)%154);
+ for (register_LY=0;register_LY <= 0x90;register_LY++)
+ {
+ u16 color = gbColorOption ? gbColorFilter[0x7FFF] :
+ 0x7FFF;
+ if (!gbCgbMode)
+ color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] :
+ gbPalette[0] & 0x7FFF;
+ for(int i = 0; i < 160; i++)
+ {
+ gbLineMix[i] = color;
+ gbLineBuffer[i] = 0;
+ }
+ gbDrawLine();
+ }
+ register_LY = register_LYLcdOff;
+ }
+ }
+
+ if (gbWhiteScreen)
+ {
+ gbLcdLYIncrementTicks -= clockTicks;
+
+ while (gbLcdLYIncrementTicks <=0)
+ {
+ register_LY = ((register_LY+1)%154);
+ gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS;
+ if (register_LY<144)
+ {
+
+ u16 color = gbColorOption ? gbColorFilter[0x7FFF] :
+ 0x7FFF;
+ if (!gbCgbMode)
+ color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] :
+ gbPalette[0] & 0x7FFF;
+ for(int i = 0; i < 160; i++)
+ {
+ gbLineMix[i] = color;
+ gbLineBuffer[i] = 0;
+ }
+ gbDrawLine();
+ }
+ else if ((register_LY==144) && (!systemFrameSkip))
+ {
+ int framesToSkip = systemFrameSkip;
+ if(speedup)
+ framesToSkip = 9; // try 6 FPS during speedup
+ if((gbFrameSkipCount >= framesToSkip) || (gbWhiteScreen == 1)) {
+ gbWhiteScreen = 2;
+
+ if(!gbSgbMask)
+ {
+ if (gbBorderOn)
+ gbSgbRenderBorder();
+ //if (gbScreenOn)
+ systemDrawScreen();
+ }
+ }
+ if(systemReadJoypads()) {
+ // read joystick
+ if(gbSgbMode && gbSgbMultiplayer) {
+ if(gbSgbFourPlayers) {
+ gbJoymask[0] = systemReadJoypad(0);
+ gbJoymask[1] = systemReadJoypad(1);
+ gbJoymask[2] = systemReadJoypad(2);
+ gbJoymask[3] = systemReadJoypad(3);
+ } else {
+ gbJoymask[0] = systemReadJoypad(0);
+ gbJoymask[1] = systemReadJoypad(1);
+ }
+ } else {
+ gbJoymask[0] = systemReadJoypad(-1);
+ }
+ }
+ gbFrameCount++;
+
+ systemFrame();
+
+ if((gbFrameCount % 10) == 0)
+ system10Frames(60);
+
+ if(gbFrameCount >= 60) {
+ u32 currentTime = systemGetClock();
+ if(currentTime != gbLastTime)
+ systemShowSpeed(100000/(currentTime - gbLastTime));
+ else
+ systemShowSpeed(0);
+ gbLastTime = currentTime;
+ gbFrameCount = 0;
+ }
+ }
+ }
+ }
+ }
+
+ gbMemory[0xff41] = register_STAT;
+
+ // serial emulation
+ if(gbSerialOn) {
+#ifdef LINK_EMULATION
+ if(linkConnected) {
+ gbSerialTicks -= clockTicks;
+
+ while(gbSerialTicks <= 0) {
+ // increment number of shifted bits
+ gbSerialBits++;
+ linkProc();
+ if(gbSerialOn && (gbMemory[0xff02] & 1)) {
+ if(gbSerialBits == 8) {
+ gbSerialBits = 0;
+ gbMemory[0xff01] = 0xff;
+ gbMemory[0xff02] &= 0x7f;
+ gbSerialOn = 0;
+ gbMemory[0xff0f] = register_IF |= 8;
+ gbSerialTicks = 0;
+ }
+ }
+ gbSerialTicks += GBSERIAL_CLOCK_TICKS;
+ }
+ } else {
+#endif
+ if(gbMemory[0xff02] & 1) {
+ gbSerialTicks -= clockTicks;
+
+ // overflow
+ while(gbSerialTicks <= 0) {
+ // shift serial byte to right and put a 1 bit in its place
+ // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
+ // increment number of shifted bits
+ gbSerialBits++;
+ if(gbSerialBits == 8) {
+ // end of transmission
+ if(gbSerialFunction) // external device
+ gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);
+ else
+ gbMemory[0xff01] = 0xff;
+ gbSerialTicks = 0;
+ gbMemory[0xff02] &= 0x7f;
+ gbSerialOn = 0;
+ gbMemory[0xff0f] = register_IF |= 8;
+ gbSerialBits = 0;
+ } else
+ gbSerialTicks += GBSERIAL_CLOCK_TICKS;
+ }
+ }
+#ifdef LINK_EMULATION
+ }
+#endif
+ }
+
+
+ soundTicks -= clockTicks;
+
+ while(soundTicks < 0) {
+ soundTicks += SOUND_CLOCK_TICKS;
+
+ gbSoundTick();
+ }
+
+
+ // timer emulation
+
+ if(gbTimerOn) {
+ gbTimerTicks= ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1-clockTicks;
+
+ while(gbTimerTicks <= 0) {
+ register_TIMA++;
+ // timer overflow!
+ if((register_TIMA & 0xff) == 0) {
+ // reload timer modulo
+ register_TIMA = register_TMA;
+ // flag interrupt
+ gbMemory[0xff0f] = register_IF |= 4;
+ }
+ gbTimerTicks += gbTimerClockTicks;
+ }
+ gbTimerOnChange = false;
+ gbTimerModeChange = false;
+
+ gbMemory[0xff05] = register_TIMA;
+
+ }
+
+ gbInternalTimer -= clockTicks;
+ while (gbInternalTimer<0)
+ gbInternalTimer+=0x100;
+
+ /*
+ if(soundOffFlag) {
+ if(synchronize && !speedup) {
+ synchronizeTicks -= clockTicks;
+
+ while(synchronizeTicks < 0) {
+ synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS;
+
+ DWORD now = timeGetTime();
+ gbElapsedTime += (now - timeNow);
+
+ if(gbElapsedTime < 50) {
+ DWORD diff = 50 - gbElapsedTime;
+ Sleep(diff);
+ timeNow = timeGetTime();
+ elapsedTime = timeNow - now - diff;
+ if((int)elapsedTime < 0)
+ elapsedTime = 0;
+ } else {
+ timeNow = timeGetTime();
+ elapsedTime = 0;
+ }
+ }
+ }
+ }
+ */
+
+ clockTicks = 0;
+
+ if (gbIntBreak == 1)
+ {
+ gbIntBreak = 0;
+ if ((register_IE & register_IF & gbInterruptLaunched & 0x3) &&
+ ((IFF & 0x81) == 1) && (!gbInterruptWait) && (execute))
+ {
+ gbIntBreak = 2;
+ PC.W = oldPCW;
+ execute = false;
+ gbOldClockTicks = 0;
+ }
+ if (gbOldClockTicks)
+ {
+ clockTicks = gbOldClockTicks;
+ gbOldClockTicks = 0;
+ goto gbRedoLoop;
+ }
+ }
+
+ // Executes the opcode(s), and apply the instruction's remaining clockTicks (if any).
+ if (execute)
+ {
+ switch(opcode1) {
+ case 0xCB:
+ // extended opcode
+ switch(opcode2) {
+#include "gbCodesCB.h"
+ }
+ break;
+#include "gbCodes.h"
+ }
+ execute = false;
+
+ if (clockTicks)
+ {
+ gbDmaTicks += clockTicks;
+ clockTicks = 0;
+ }
+ }
+
+ if (gbDmaTicks)
+ {
+ clockTicks = gbGetNextEvent(gbDmaTicks);
+
+ if (clockTicks<=gbDmaTicks)
+ gbDmaTicks -= clockTicks;
+ else
+ {
+ clockTicks = gbDmaTicks;
+ gbDmaTicks = 0;
+ }
+
+ goto gbRedoLoop;
+ }
+
+
+ // Remove the 'if an IE is pending' flag if IE has finished being executed.
+ if ((IFF & 0x40) && !(IFF & 0x30))
+ IFF &= 0x81;
+
+
+
+ if ((register_IE & register_IF & 0x1f) && (IFF & 0x81) && (!gbInterruptWait))
+ {
+
+ if (IFF & 1)
+ {
+ // Add 5 ticks for the interrupt execution time
+ gbDmaTicks += 5;
+
+ if (gbIntBreak == 2)
+ {
+ gbDmaTicks--;
+ gbIntBreak = 0;
+ }
+
+
+ if(register_IF & register_IE & 1)
+ gbVblank_interrupt();
+ else if(register_IF & register_IE & 2)
+ gbLcd_interrupt();
+ else if(register_IF & register_IE & 4)
+ gbTimer_interrupt();
+ else if(register_IF & register_IE & 8)
+ gbSerial_interrupt();
+ else if(register_IF & register_IE & 16)
+ gbJoypad_interrupt();
+ }
+
+ IFF &= ~0x81;
+ }
+
+ if (IFF & 0x08)
+ IFF &=~0x79;
+
+ // Used to apply the interrupt's execution time.
+ if (gbDmaTicks)
+ {
+ clockTicks = gbGetNextEvent(gbDmaTicks);
+
+ if (clockTicks<=gbDmaTicks)
+ gbDmaTicks -= clockTicks;
+ else
+ {
+ clockTicks = gbDmaTicks;
+ gbDmaTicks = 0;
+ }
+ goto gbRedoLoop;
+ }
+
+
+ gbBlackScreen = false;
+
+ if((ticksToStop <= 0)) {
+ if(!(register_LCDC & 0x80)) {
+ if(systemReadJoypads()) {
+ // read joystick
+ if(gbSgbMode && gbSgbMultiplayer) {
+ if(gbSgbFourPlayers) {
+ gbJoymask[0] = systemReadJoypad(0);
+ gbJoymask[1] = systemReadJoypad(1);
+ gbJoymask[2] = systemReadJoypad(2);
+ gbJoymask[3] = systemReadJoypad(3);
+ } else {
+ gbJoymask[0] = systemReadJoypad(0);
+ gbJoymask[1] = systemReadJoypad(1);
+ }
+ } else {
+ gbJoymask[0] = systemReadJoypad(-1);
+ }
+ }
+ }
+ return;
+ }
+ }
+}
+
+struct EmulatedSystem GBSystem = {
+ // emuMain
+ gbEmulate,
+ // emuReset
+ gbReset,
+ // emuCleanUp
+ gbCleanUp,
+ // emuReadBattery
+ gbReadBatteryFile,
+ // emuWriteBattery
+ gbWriteBatteryFile,
+ // emuReadState
+ gbReadSaveState,
+ // emuWriteState
+ gbWriteSaveState,
+ // emuReadMemState
+ gbReadMemSaveState,
+ // emuWriteMemState
+ gbWriteMemSaveState,
+ // emuWritePNG
+ gbWritePNGFile,
+ // emuWriteBMP
+ gbWriteBMPFile,
+ // emuUpdateCPSR
+ NULL,
+ // emuHasDebugger
+ false,
+ // emuCount
+#ifdef FINAL_VERSION
+ 70000/4,
+#else
+ 1000,
+#endif
+};
diff --git a/src/gb/gb.h b/src/gb/gb.h
index 1527c77a..26099f14 100644
--- a/src/gb/gb.h
+++ b/src/gb/gb.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -38,11 +38,15 @@ typedef union {
extern bool gbLoadRom(const char *);
extern void gbEmulate(int);
+extern void gbWriteMemory(register u16, register u8);
+extern void gbDrawLine();
extern bool gbIsGameboyRom(const char *);
extern void gbSoundReset();
extern void gbSoundSetQuality(int);
+extern void gbGetHardwareType();
extern void gbReset();
extern void gbCleanUp();
+extern void gbCPUInit(const char *,bool);
extern bool gbWriteBatteryFile(const char *);
extern bool gbWriteBatteryFile(const char *, bool);
extern bool gbReadBatteryFile(const char *);
diff --git a/src/gb/gbCheats.cpp b/src/gb/gbCheats.cpp
index 941bb166..62a7ccb3 100644
--- a/src/gb/gbCheats.cpp
+++ b/src/gb/gbCheats.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -27,9 +27,11 @@
#include "gbCheats.h"
#include "gbGlobals.h"
+#include "GB.h"
gbCheat gbCheatList[100];
int gbCheatNumber = 0;
+int gbNextCheat = 0;
bool gbCheatMap[0x10000];
extern bool cheatsEnabled;
@@ -50,7 +52,7 @@ void gbCheatUpdateMap()
void gbCheatsSaveGame(gzFile gzFile)
{
utilWriteInt(gzFile, gbCheatNumber);
- if(gbCheatNumber)
+ if(gbCheatNumber>0)
utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber);
}
@@ -81,7 +83,7 @@ void gbCheatsReadGame(gzFile gzFile, int version)
} else {
gbCheatNumber = utilReadInt(gzFile);
- if(gbCheatNumber) {
+ if(gbCheatNumber>0) {
utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber);
}
}
@@ -163,7 +165,7 @@ bool gbCheatsLoadCheatList(const char *file)
bool gbVerifyGsCode(const char *code)
{
- int len = strlen(code);
+ size_t len = strlen(code);
if(len == 0)
return true;
@@ -180,10 +182,6 @@ bool gbVerifyGsCode(const char *code)
GBCHEAT_HEX_VALUE(code[4]) << 4 |
GBCHEAT_HEX_VALUE(code[5]);
- if(address < 0xa000 ||
- address > 0xdfff)
- return false;
-
return true;
}
@@ -220,15 +218,23 @@ void gbAddGsCheat(const char *code, const char *desc)
gbCheatList[i].compare = 0;
gbCheatList[i].enabled = true;
-
- gbCheatMap[gbCheatList[i].address] = true;
-
+
+ int gsCode = gbCheatList[i].code;
+
+ if ((gsCode !=1) && ((gsCode & 0xF0) !=0x80) && ((gsCode & 0xF0) !=0x90) &&
+ ((gsCode & 0xF0) !=0xA0) && ((gsCode) !=0xF0) && ((gsCode) !=0xF1))
+ systemMessage(MSG_WRONG_GAMESHARK_CODE,
+ N_("Wrong GameShark code type : %s"), code);
+ else if (((gsCode & 0xF0) ==0xA0) || ((gsCode) ==0xF0) || ((gsCode) ==0xF1))
+ systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE,
+ N_("Unsupported GameShark code type : %s"), code);
+
gbCheatNumber++;
}
bool gbVerifyGgCode(const char *code)
{
- int len = strlen(code);
+ size_t len = strlen(code);
if(len != 11 &&
len != 7 &&
@@ -313,12 +319,12 @@ void gbAddGgCheat(const char *code, const char *desc)
int i = gbCheatNumber;
- int len = strlen(code);
+ size_t len = strlen(code);
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
- gbCheatList[i].code = 1;
+ gbCheatList[i].code = 0x101;
gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
GBCHEAT_HEX_VALUE(code[1]);
@@ -338,9 +344,12 @@ void gbAddGgCheat(const char *code, const char *desc)
compare ^= 0x45;
gbCheatList[i].compare = compare;
- gbCheatList[i].code = 0;
+ //gbCheatList[i].code = 0;
+ gbCheatList[i].code = 0x100; // fix for compare value
+
}
+
gbCheatList[i].enabled = true;
gbCheatMap[gbCheatList[i].address] = true;
@@ -425,6 +434,7 @@ bool gbCheatReadGSCodeFile(const char *fileName)
return true;
}
+// Used to emulated GG codes
u8 gbCheatRead(u16 address)
{
if(!cheatsEnabled)
@@ -437,26 +447,72 @@ u8 gbCheatRead(u16 address)
if(gbMemoryMap[address>>12][address&0xFFF] == gbCheatList[i].compare)
return gbCheatList[i].value;
break;
- case 0x00:
- case 0x01:
- case 0x80:
- return gbCheatList[i].value;
- case 0x90:
- case 0x91:
- case 0x92:
- case 0x93:
- case 0x94:
- case 0x95:
- case 0x96:
- case 0x97:
- if(address >= 0xd000 && address < 0xe000) {
- if(((gbMemoryMap[0x0d] - gbWram)/0x1000) ==
- (gbCheatList[i].code - 0x90))
- return gbCheatList[i].value;
- } else
+ case 0x101: // GameGenie 6 digits code support
return gbCheatList[i].value;
+ break;
}
}
}
return gbMemoryMap[address>>12][address&0xFFF];
}
+
+
+// Used to emulate GS codes.
+void gbCheatWrite(bool reboot)
+{
+ if(cheatsEnabled)
+ {
+ u16 address = 0;
+
+ if (gbNextCheat >= gbCheatNumber)
+ gbNextCheat = 0;
+
+ for(int i = gbNextCheat; i < gbCheatNumber; i++) {
+ if(gbCheatList[i].enabled) {
+ address = gbCheatList[i].address;
+ if ((!reboot) && (address >= 0x8000) && !((address>=0xA000) && (address<0xC000)))
+ { // These codes are executed one per one, at each Vblank
+ switch(gbCheatList[i].code) {
+ case 0x01:
+ gbWriteMemory(address, gbCheatList[i].value);
+ gbNextCheat = i+1;
+ return;
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ case 0x98:
+ case 0x99:
+ case 0x9A:
+ case 0x9B:
+ case 0x9C:
+ case 0x9D:
+ case 0x9E:
+ case 0x9F:
+ int oldbank = gbMemory[0xff70];
+ gbWriteMemory(0xff70, gbCheatList[i].code & 0xf);
+ gbWriteMemory(address, gbCheatList[i].value);
+ gbWriteMemory(0xff70, oldbank);
+ gbNextCheat = i+1;
+ return;
+ }
+ }
+ else // These codes are only executed when the game is booted
+ {
+ switch(gbCheatList[i].code & 0xF0) {
+ case 0x80:
+ gbWriteMemory(0x0000, 0x0A);
+ gbWriteMemory(0x4000, gbCheatList[i].value & 0xF);
+ gbWriteMemory(address, gbCheatList[i].value);
+ gbNextCheat = i+1;
+ return;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/gb/gbCheats.h b/src/gb/gbCheats.h
index 3845a53c..418b2862 100644
--- a/src/gb/gbCheats.h
+++ b/src/gb/gbCheats.h
@@ -50,6 +50,7 @@ extern void gbCheatRemoveAll();
extern void gbCheatEnable(int);
extern void gbCheatDisable(int);
extern u8 gbCheatRead(u16);
+extern void gbCheatWrite(bool);
extern int gbCheatNumber;
extern gbCheat gbCheatList[100];
diff --git a/src/gb/gbCodes.h b/src/gb/gbCodes.h
index 43c45199..73dd088b 100644
--- a/src/gb/gbCodes.h
+++ b/src/gb/gbCodes.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -22,8 +22,8 @@
break;
case 0x01:
// LD BC, NNNN
- BC.B.B0=gbReadMemory(PC.W++);
- BC.B.B1=gbReadMemory(PC.W++);
+ BC.B.B0=gbReadOpcode(PC.W++);
+ BC.B.B1=gbReadOpcode(PC.W++);
break;
case 0x02:
// LD (BC),A
@@ -102,7 +102,9 @@
opcode = gbReadOpcode(PC.W++);
if(gbCgbMode) {
if(gbMemory[0xff4d] & 1) {
+
gbSpeedSwitch();
+ //clockTicks += 228*144-(gbSpeed ? 62 : 63);
if(gbSpeed == 0)
gbMemory[0xff4d] = 0x00;
@@ -113,8 +115,8 @@
break;
case 0x11:
// LD DE, NNNN
- DE.B.B0=gbReadMemory(PC.W++);
- DE.B.B1=gbReadMemory(PC.W++);
+ DE.B.B0=gbReadOpcode(PC.W++);
+ DE.B.B1=gbReadOpcode(PC.W++);
break;
case 0x12:
// LD (DE),A
@@ -147,7 +149,7 @@
break;
case 0x18:
// JR NN
- PC.W+=(s8)gbReadMemory(PC.W)+1;
+ PC.W+=(s8)gbReadOpcode(PC.W)+1;
break;
case 0x19:
// ADD HL,DE
@@ -190,14 +192,14 @@
if(AF.B.B0&Z_FLAG)
PC.W++;
else {
- PC.W+=(s8)gbReadMemory(PC.W)+1;
+ PC.W+=(s8)gbReadOpcode(PC.W)+1;
clockTicks++;
}
break;
case 0x21:
// LD HL,NNNN
- HL.B.B0=gbReadMemory(PC.W++);
- HL.B.B1=gbReadMemory(PC.W++);
+ HL.B.B0=gbReadOpcode(PC.W++);
+ HL.B.B1=gbReadOpcode(PC.W++);
break;
case 0x22:
// LDI (HL),A
@@ -233,7 +235,7 @@
case 0x28:
// JR Z,NN
if(AF.B.B0&Z_FLAG) {
- PC.W+=(s8)gbReadMemory(PC.W)+1;
+ PC.W+=(s8)gbReadOpcode(PC.W)+1;
clockTicks++;
} else
PC.W++;
@@ -278,14 +280,14 @@
if(AF.B.B0&C_FLAG)
PC.W++;
else {
- PC.W+=(s8)gbReadMemory(PC.W)+1;
+ PC.W+=(s8)gbReadOpcode(PC.W)+1;
clockTicks++;
}
break;
case 0x31:
// LD SP,NNNN
- SP.B.B0=gbReadMemory(PC.W++);
- SP.B.B1=gbReadMemory(PC.W++);
+ SP.B.B0=gbReadOpcode(PC.W++);
+ SP.B.B1=gbReadOpcode(PC.W++);
break;
case 0x32:
// LDD (HL),A
@@ -318,7 +320,7 @@
case 0x38:
// JR C,NN
if(AF.B.B0&C_FLAG) {
- PC.W+=(s8)gbReadMemory(PC.W)+1;
+ PC.W+=(s8)gbReadOpcode(PC.W)+1;
clockTicks ++;
} else
PC.W++;
@@ -575,16 +577,24 @@ case 0x38:
break;
case 0x76:
// HALT
- if(IFF & 1) {
+ // If an EI is pending, the interrupts are triggered before Halt state !!
+ // Fix Torpedo Range's intro.
+ if (IFF & 0x40)
+ {
+ IFF &= ~0x70;
+ IFF |=1;
PC.W--;
- IFF |= 0x80;
- } else {
- if((register_IE & register_IF) > 0)
- IFF |= 0x100;
- else {
- PC.W--;
- IFF |= 0x81;
+ }
+ else
+ {
+ // if (IE & IF) and interrupts are disabeld,
+ // Halt is cancelled.
+ if ((register_IE & register_IF & 0x1f) && !(IFF & 1))
+ {
+ IFF|=2;
}
+ else
+ IFF |= 0x80;
}
break;
case 0x77:
@@ -1036,16 +1046,16 @@ case 0x38:
if(AF.B.B0&Z_FLAG)
PC.W+=2;
else {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W);
PC.W=tempRegister.W;
clockTicks++;
}
break;
case 0xc3:
// JP NNNN
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W);
PC.W=tempRegister.W;
break;
case 0xc4:
@@ -1053,8 +1063,8 @@ case 0x38:
if(AF.B.B0&Z_FLAG)
PC.W+=2;
else {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W++);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W,PC.B.B1);
gbWriteMemory(--SP.W,PC.B.B0);
PC.W=tempRegister.W;
@@ -1096,8 +1106,8 @@ case 0x38:
case 0xca:
// JP Z,NNNN
if(AF.B.B0&Z_FLAG) {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W);
PC.W=tempRegister.W;
clockTicks++;
} else
@@ -1107,8 +1117,8 @@ case 0x38:
case 0xcc:
// CALL Z,NNNN
if(AF.B.B0&Z_FLAG) {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W++);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W,PC.B.B1);
gbWriteMemory(--SP.W,PC.B.B0);
PC.W=tempRegister.W;
@@ -1118,8 +1128,8 @@ case 0x38:
break;
case 0xcd:
// CALL NNNN
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W++);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W,PC.B.B1);
gbWriteMemory(--SP.W,PC.B.B0);
PC.W=tempRegister.W;
@@ -1156,20 +1166,24 @@ case 0x38:
if(AF.B.B0&C_FLAG)
PC.W+=2;
else {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W);
PC.W=tempRegister.W;
clockTicks++;
}
break;
// D3 illegal
+ case 0xd3:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xd4:
// CALL NC,NNNN
if(AF.B.B0&C_FLAG)
PC.W+=2;
else {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W++);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W,PC.B.B1);
gbWriteMemory(--SP.W,PC.B.B0);
PC.W=tempRegister.W;
@@ -1200,7 +1214,7 @@ case 0x38:
if(AF.B.B0&C_FLAG) {
PC.B.B0=gbReadMemory(SP.W++);
PC.B.B1=gbReadMemory(SP.W++);
- clockTicks += 4;
+ clockTicks += 3;
}
break;
case 0xd9:
@@ -1212,19 +1226,23 @@ case 0x38:
case 0xda:
// JP C,NNNN
if(AF.B.B0&C_FLAG) {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W);
PC.W=tempRegister.W;
clockTicks++;
} else
PC.W+=2;
break;
// DB illegal
+ case 0xdb:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xdc:
// CALL C,NNNN
if(AF.B.B0&C_FLAG) {
- tempRegister.B.B0=gbReadMemory(PC.W++);
- tempRegister.B.B1=gbReadMemory(PC.W++);
+ tempRegister.B.B0=gbReadOpcode(PC.W++);
+ tempRegister.B.B1=gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W,PC.B.B1);
gbWriteMemory(--SP.W,PC.B.B0);
PC.W=tempRegister.W;
@@ -1233,6 +1251,10 @@ case 0x38:
PC.W+=2;
break;
// DD illegal
+ case 0xdd:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xde:
// SBC NN
tempValue=gbReadOpcode(PC.W++);
@@ -1262,6 +1284,11 @@ case 0x38:
break;
// E3 illegal
// E4 illegal
+ case 0xe3:
+ case 0xe4:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xe5:
// PUSH HL
gbWriteMemory(--SP.W,HL.B.B1);
@@ -1308,6 +1335,12 @@ case 0x38:
// EB illegal
// EC illegal
// ED illegal
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xee:
// XOR NN
tempValue=gbReadOpcode(PC.W++);
@@ -1336,9 +1369,13 @@ case 0x38:
case 0xf3:
// DI
// IFF&=0xFE;
- IFF&=(~0x21);
+ IFF|=0x08;
break;
// F4 illegal
+ case 0xf4:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xf5:
// PUSH AF
gbWriteMemory(--SP.W,AF.B.B1);
@@ -1383,10 +1420,23 @@ case 0x38:
break;
case 0xfb:
// EI
- IFF|=0x20;
+ if (!(IFF & 0x30))
+ // If an EI is executed right before HALT,
+ // the interrupts are triggered before the Halt state !!
+ // Fix Torpedo Range Intro.
+ // IFF |= 0x10 : 1 ticks before the EI enables the interrupts
+ // IFF |= 0x40 : marks that an EI is being executed.
+ IFF|=0x50;
break;
- // FC illegal
+ // FC illegal (FC = breakpoint)
+ case 0xfc:
+ breakpoint = true;
+ break;
// FD illegal
+ case 0xfd:
+ PC.W--;
+ IFF = 0;
+ break;
case 0xfe:
// CP NN
tempValue=gbReadOpcode(PC.W++);
@@ -1401,7 +1451,10 @@ case 0x38:
PC.W=0x0038;
break;
default:
- systemMessage(0, N_("Unknown opcode %02x at %04x"),
- gbReadOpcode(PC.W-1),PC.W-1);
- emulating = false;
+ if (gbSystemMessage == false)
+ {
+ systemMessage(0, N_("Unknown opcode %02x at %04x"),
+ gbReadOpcode(PC.W-1),PC.W-1);
+ gbSystemMessage =true;
+ }
return;
diff --git a/src/gb/gbCodesCB.h b/src/gb/gbCodesCB.h
index 05dce6e6..5a09d8d5 100644
--- a/src/gb/gbCodesCB.h
+++ b/src/gb/gbCodesCB.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -1282,7 +1282,10 @@
AF.B.B1|=1<<7;
break;
default:
- systemMessage(0, N_("Unknown opcode %02x at %04x"),
- gbReadOpcode(PC.W-1),PC.W-1);
- emulating = false;
+ if (gbSystemMessage == false)
+ {
+ systemMessage(0, N_("Unknown opcode %02x at %04x"),
+ gbReadOpcode(PC.W-1),PC.W-1);
+ gbSystemMessage =true;
+ }
return;
diff --git a/src/gb/gbGfx.cpp b/src/gb/gbGfx.cpp
index aa639664..6558b4eb 100644
--- a/src/gb/gbGfx.cpp
+++ b/src/gb/gbGfx.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -58,9 +58,12 @@ u8 gbInvertTab[256] = {
};
u16 gbLineMix[160];
+u16 gbWindowColor[160];
+extern int inUseRegister_WY;
void gbRenderLine()
{
+ memset(gbLineMix, 0, sizeof(gbLineMix));
u8 * bank0;
u8 * bank1;
if(gbCgbMode) {
@@ -86,10 +89,9 @@ void gbRenderLine()
if(y >= 144)
return;
- // int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip;
-
- int sx = register_SCX;
- int sy = register_SCY;
+ int SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4);
+ int sx = gbSCXLine[(gbSpeed ? 0 : 4)+SpritesTicks];
+ int sy = gbSCYLine[(gbSpeed ? 11 : 5)+SpritesTicks];
sy+=y;
@@ -113,16 +115,17 @@ void gbRenderLine()
tile_map_address++;
- if((register_LCDC & 16) == 0) {
- if(tile < 128) tile += 128;
- else tile -= 128;
- }
+ if(!(register_LCDC & 0x10))
+ tile ^= 0x80;
int tile_pattern_address = tile_pattern + tile * 16 + by*2;
if(register_LCDC & 0x80) {
if((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) {
while(x < 160) {
+
+
+
u8 tile_a = 0;
u8 tile_b = 0;
@@ -155,7 +158,7 @@ void gbRenderLine()
if(gbCgbMode) {
c = c + (attrs & 7)*4;
} else {
- c = gbBgp[c];
+ c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+SpritesTicks]>>(c<<1)) &3;
if(gbSgbMode && !gbCgbMode) {
int dx = x >> 3;
int dy = y >> 3;
@@ -168,42 +171,92 @@ void gbRenderLine()
c = c + 4*palette;
}
}
- gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :
- gbPalette[c];
+ gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] :
+ gbPalette[c] & 0x7FFF;
x++;
if(x >= 160)
break;
bx >>= 1;
}
- tx++;
- if(tx == 32)
- tx = 0;
+
bx = 128;
-
+
+ SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4);
+
+ sx = gbSCXLine[x+(gbSpeed ? 0 : 4)+SpritesTicks];
+
+ sy = gbSCYLine[x+(gbSpeed ? 11 : 5)+SpritesTicks];
+
+
+ tx = ((sx+x)>>3) & 0x1f;
+
+ sy+=y;
+
+ sy &= 255;
+
+ ty = sy >> 3;
+
+ by = sy & 7;
+
+ tile_pattern_address = tile_pattern + tile * 16 + by * 2;
+
+ tile_map_line_y = tile_map + ty * 32;
+
+ tile_map_address = tile_map_line_y + tx;
+
if(bank1)
attrs = bank1[tile_map_line_y + tx];
tile = bank0[tile_map_line_y + tx];
-
- if((register_LCDC & 16) == 0) {
- if(tile < 128) tile += 128;
- else tile -= 128;
- }
+
+ if(!(register_LCDC & 0x10))
+ tile ^= 0x80;
+
tile_pattern_address = tile_pattern + tile * 16 + by * 2;
}
} else {
- for(int i = 0; i < 160; i++) {
- gbLineMix[i] = gbPalette[0];
+ // Use gbBgp[0] instead of 0 (?)
+ // (this fixes white flashes on Last Bible II)
+ // Also added the gbColorOption (fixes Dracula Densetsu II color problems)
+ for(int i = 0; i < 160; i++)
+ {
+ u16 color = gbColorOption ? gbColorFilter[0x7FFF] :
+ 0x7FFF;
+ if (!gbCgbMode)
+ color = gbColorOption ? gbColorFilter[gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF] :
+ gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF;
+ gbLineMix[i] = color;
gbLineBuffer[i] = 0;
}
}
// do the window display
- if((register_LCDC & 0x20) && (layerSettings & 0x2000)) {
- int wy = register_WY;
+ // LCDC.0 also enables/disables the window in !gbCgbMode ?!?!
+ // (tested on real hardware)
+ // This fixes Last Bible II & Zankurou Musouken
+ if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) &&
+ (layerSettings & 0x2000) && (gbWindowLine != -2)) {
+ int i = 0;
+ // Fix (accurate emulation) for most of the window display problems
+ // (ie. Zen - Intergalactic Ninja, Urusei Yatsura...).
+ if ((gbWindowLine == -1) || (gbWindowLine>144))
+ {
+ inUseRegister_WY = oldRegister_WY;
+ if (register_LY>oldRegister_WY)
+ gbWindowLine = 146;
+ // for (i = 0; i<160; i++)
+ // gbWindowColor[i] = gbLineMix[i];
+ }
+
+ int wy = inUseRegister_WY;
- if(y >= wy) {
+ if(y >= inUseRegister_WY) {
+
+ if (gbWindowLine == -1)
+ gbWindowLine = 0;
+
int wx = register_WX;
+ int swx = 0;
wx -= 7;
if( wx <= 159 && gbWindowLine <= 143) {
@@ -212,10 +265,7 @@ void gbRenderLine()
if((register_LCDC & 0x40) != 0)
tile_map = 0x1c00;
-
- if(gbWindowLine == -1) {
- gbWindowLine = 0;
- }
+
tx = 0;
ty = gbWindowLine >> 3;
@@ -223,6 +273,25 @@ void gbRenderLine()
bx = 128;
by = gbWindowLine & 7;
+ // Tries to emulate the 'window scrolling bug' when wx == 0 (ie. wx-7 == -7).
+ // Nothing close to perfect, but good enought for now...
+ if (wx == -7)
+ {
+ swx = 7-((gbSCXLine[0]-1) & 7);
+ bx >>= ((gbSCXLine[0]+((swx != 1) ? 1 : 0)) & 7);
+ if (swx == 1)
+ swx = 2;
+
+ //bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7);
+
+ if ((swx == 7))
+ {
+ //wx = 0;
+ if ((gbWindowLine>0) || (wy == 0))
+ swx = 0;
+ }
+ }
+ else
if(wx < 0) {
bx >>= (-wx);
wx = 0;
@@ -247,6 +316,10 @@ void gbRenderLine()
tile_pattern_address = tile_pattern + tile * 16 + by*2;
+ if (wx)
+ for (i = 0; i=0)
+ {
if(attrs & 0x80)
gbLineBuffer[x] = 0x300 + c;
else
@@ -280,8 +355,8 @@ void gbRenderLine()
if(gbCgbMode) {
c = c + (attrs & 7) * 4;
} else {
- c = gbBgp[c];
- if(gbSgbMode && ! gbCgbMode) {
+ c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(c<<1)) &3;
+ if(gbSgbMode && !gbCgbMode) {
int dx = x >> 3;
int dy = y >> 3;
@@ -293,8 +368,9 @@ void gbRenderLine()
c = c + 4*palette;
}
}
- gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :
- gbPalette[c];
+ gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] :
+ gbPalette[c] & 0x7FFF;
+ }
x++;
if(x >= 160)
break;
@@ -314,13 +390,30 @@ void gbRenderLine()
}
tile_pattern_address = tile_pattern + tile * 16 + by * 2;
}
+
+ //for (i = swx; i<160; i++)
+ // gbLineMix[i] = gbWindowColor[i];
gbWindowLine++;
}
}
}
+ else if (gbWindowLine == -2)
+ {
+ inUseRegister_WY = oldRegister_WY;
+ if (register_LY>oldRegister_WY)
+ gbWindowLine = 146;
+ else
+ gbWindowLine = 0;
+ }
} else {
- for(int i = 0; i < 160; i++) {
- gbLineMix[i] = gbPalette[0];
+ u16 color = gbColorOption ? gbColorFilter[0x7FFF] :
+ 0x7FFF;
+ if (!gbCgbMode)
+ color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] :
+ gbPalette[0] & 0x7FFF;
+ for(int i = 0; i < 160; i++)
+ {
+ gbLineMix[i] = color;
gbLineBuffer[i] = 0;
}
}
@@ -346,8 +439,11 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
int init = 0x0000;
- // int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip;
-
+ for (int i = 0; i<4; i++)
+ {
+ gbObp0[i] = (gbObp0Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3;
+ gbObp1[i] = (gbObp1Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3;
+ }
u8 *pal = gbObp0;
int flipx = (flags & 0x20);
@@ -366,7 +462,7 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
int a = 0;
int b = 0;
- if(gbCgbMode && flags & 0x08) {
+ if(gbCgbMode && (flags & 0x08)) {
a = bank1[address++];
b = bank1[address++];
} else {
@@ -392,12 +488,14 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
continue;
u16 color = gbLineBuffer[xxx];
-
- if(prio) {
+
+ // Fixes OAM-BG priority
+ if(prio && (register_LCDC & 1)) {
if(color < 0x200 && ((color & 0xFF) != 0))
continue;
}
- if(color >= 0x300 && color != 0x300)
+ // Fixes OAM-BG priority for Moorhuhn 2
+ if(color >= 0x300 && color != 0x300 && (register_LCDC & 1))
continue;
else if(color >= 0x200 && color < 0x300) {
int sprite = color & 0xff;
@@ -412,7 +510,9 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
if(sprite < spriteNumber)
continue;
} else {
- if(spriteX < x+8)
+ // Fixes GB sprites priorities (was '< x + 8' before)
+ // ('A boy and his blob...' sprites' emulation is now correct)
+ if(spriteX < x)
continue;
}
}
@@ -442,12 +542,12 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
}
}
- gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] :
- gbPalette[c];
+ gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] :
+ gbPalette[c] & 0x7FFF;
}
}
-void gbDrawSprites()
+void gbDrawSprites(bool draw)
{
int x = 0;
int y = 0;
@@ -455,6 +555,9 @@ void gbDrawSprites()
int size = (register_LCDC & 4);
+ if (!draw)
+ memset (gbSpritesTicks, 0, sizeof(gbSpritesTicks));
+
if(!(register_LCDC & 0x80))
return;
@@ -473,11 +576,19 @@ void gbDrawSprites()
if(x > 0 && y > 0 && x < 168 && y < 160) {
// check if sprite intersects current line
int t = yc -y + 16;
- if(size && t >=0 && t < 16) {
- gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i);
- count++;
- } else if(!size && t >= 0 && t < 8) {
- gbDrawSpriteTile(tile, x-8, yc, t, flags,size,i);
+ if((size && t >=0 && t < 16) || (!size && t >= 0 && t < 8)) {
+ if (draw)
+ gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i);
+ else
+ {
+ for (int j = x-8; j<300; j++)
+ if (j>=0)
+ if (gbSpeed)
+ gbSpritesTicks[j] += 5;
+ else
+ gbSpritesTicks[j] += 2+(count&1);
+
+ }
count++;
}
}
@@ -486,5 +597,5 @@ void gbDrawSprites()
break;
}
}
-}
-
+ return;
+}
\ No newline at end of file
diff --git a/src/gb/gbGlobals.cpp b/src/gb/gbGlobals.cpp
index 90b1af15..877d28f4 100644
--- a/src/gb/gbGlobals.cpp
+++ b/src/gb/gbGlobals.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ int gbRomSizeMask = 0;
int gbRomSize = 0;
int gbRamSizeMask = 0;
int gbRamSize = 0;
+int gbTAMA5ramSize = 0;
u8 *gbMemory = NULL;
u8 *gbVram = NULL;
@@ -31,6 +32,7 @@ u8 *gbRom = NULL;
u8 *gbRam = NULL;
u8 *gbWram = NULL;
u16 *gbLineBuffer = NULL;
+u8 *gbTAMA5ram = NULL;
u16 gbPalette[128];
u8 gbBgp[4] = { 0, 1, 2, 3};
@@ -38,6 +40,7 @@ u8 gbObp0[4] = { 0, 1, 2, 3};
u8 gbObp1[4] = { 0, 1, 2, 3};
int gbWindowLine = -1;
+bool genericflashcardEnable = false;
int gbCgbMode = 0;
u16 gbColorFilter[32768];
diff --git a/src/gb/gbGlobals.h b/src/gb/gbGlobals.h
index 380f9331..d214d0d3 100644
--- a/src/gb/gbGlobals.h
+++ b/src/gb/gbGlobals.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -21,6 +21,11 @@ extern int gbRomSizeMask;
extern int gbRomSize;
extern int gbRamSize;
extern int gbRamSizeMask;
+extern int gbTAMA5ramSize;
+
+extern bool useBios;
+extern bool skipBios;
+extern u8 *bios;
extern u8 *gbRom;
extern u8 *gbRam;
@@ -28,6 +33,7 @@ extern u8 *gbVram;
extern u8 *gbWram;
extern u8 *gbMemory;
extern u16 *gbLineBuffer;
+extern u8 *gbTAMA5ram;
extern u8 *gbMemoryMap[16];
@@ -46,6 +52,19 @@ extern u8 gbBgp[4];
extern u8 gbObp0[4];
extern u8 gbObp1[4];
extern u16 gbPalette[128];
+extern bool gbScreenOn;
+extern bool gbDrawWindow;
+extern u8 gbSCYLine[300];
+// gbSCXLine is used for the emulation (bug) of the SX change
+// found in the Artic Zone game.
+extern u8 gbSCXLine[300];
+// gbBgpLine is used for the emulation of the
+// Prehistorik Man's title screen scroller.
+extern u8 gbBgpLine[300];
+extern u8 gbObp0Line [300];
+extern u8 gbObp1Line [300];
+// gbSpritesTicks is used for the emulation of Parodius' Laser Beam.
+extern u8 gbSpritesTicks[300];
extern u8 register_LCDC;
extern u8 register_LY;
@@ -54,8 +73,10 @@ extern u8 register_SCX;
extern u8 register_WY;
extern u8 register_WX;
extern u8 register_VBK;
+extern u8 oldRegister_WY;
extern int emulating;
+extern bool genericflashcardEnable;
extern int gbBorderLineSkip;
extern int gbBorderRowSkip;
@@ -63,6 +84,6 @@ extern int gbBorderColumnSkip;
extern int gbDmaTicks;
extern void gbRenderLine();
-extern void gbDrawSprites();
+extern void gbDrawSprites(bool);
extern u8 (*gbSerialFunction)(u8);
diff --git a/src/gb/gbMemory.cpp b/src/gb/gbMemory.cpp
index be379d3e..fd57aee1 100644
--- a/src/gb/gbMemory.cpp
+++ b/src/gb/gbMemory.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -20,6 +20,12 @@
#include "../Port.h"
#include "gbGlobals.h"
#include "gbMemory.h"
+#include "GB.h"
+u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+const u8 gbDisabledRam [8] = {0x80, 0xff, 0xf0, 0x00, 0x30, 0xbf, 0xbf, 0xbf};
+extern int gbHardware;
+extern int gbGBCColorType;
+extern gbRegister PC;
mapperMBC1 gbDataMBC1 = {
0, // RAM enable
@@ -27,7 +33,8 @@ mapperMBC1 gbDataMBC1 = {
0, // RAM bank
0, // memory model
0, // ROM high address
- 0 // RAM address
+ 0, // RAM address
+ 0 // Rom Bank 0 remapping
};
// MBC1 ROM write registers
@@ -41,17 +48,25 @@ void mapperMBC1ROM(u16 address, u8 value)
break;
case 0x2000: // ROM bank select
// value = value & 0x1f;
- if(value == 0)
- value = 1;
+ if ((value == 1) && (address == 0x2100))
+ gbDataMBC1.mapperRomBank0Remapping = 1;
+
+ if((value & 0x1f) == 0)
+ value += 1;
if(value == gbDataMBC1.mapperROMBank)
break;
tmpAddress = value << 14;
// check current model
+ if (gbDataMBC1.mapperRomBank0Remapping == 3) {
+ tmpAddress = (value & 0xf) << 14;
+ tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 18;
+ }
+ else
if(gbDataMBC1.mapperMemoryModel == 0) {
// model is 16/8, so we have a high address in use
- tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
+ tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 19;
}
tmpAddress &= gbRomSizeMask;
@@ -63,16 +78,39 @@ void mapperMBC1ROM(u16 address, u8 value)
break;
case 0x4000: // RAM bank select
if(gbDataMBC1.mapperMemoryModel == 1) {
+ if (!gbRamSize)
+ {
+ if (gbDataMBC1.mapperRomBank0Remapping == 3)
+ {
+ gbDataMBC1.mapperROMHighAddress = value & 0x03;
+ tmpAddress = (gbDataMBC1.mapperROMHighAddress) << 18;
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x00] = &gbRom[tmpAddress];
+ gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000];
+ gbMemoryMap[0x04] = &gbRom[tmpAddress + 0x4000];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x5000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x6000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x7000];
+ }
+ else gbDataMBC1.mapperRomBank0Remapping = 0;
+ }
// 4/32 model, RAM bank switching provided
value = value & 0x03;
if(value == gbDataMBC1.mapperRAMBank)
break;
tmpAddress = value << 13;
tmpAddress &= gbRamSizeMask;
- gbMemoryMap[0x0a] = &gbRam[tmpAddress];
- gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
+ if(gbRamSize) {
+ gbMemoryMap[0x0a] = &gbRam[tmpAddress];
+ gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
+ }
gbDataMBC1.mapperRAMBank = value;
gbDataMBC1.mapperRAMAddress = tmpAddress;
+
+ if (gbDataMBC1.mapperRomBank0Remapping != 3)
+ gbDataMBC1.mapperROMHighAddress = 0;
} else {
// 16/8, set the high address
gbDataMBC1.mapperROMHighAddress = value & 0x03;
@@ -83,10 +121,57 @@ void mapperMBC1ROM(u16 address, u8 value)
gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+ if(gbRamSize) {
+ gbMemoryMap[0x0a] = &gbRam[0];
+ gbMemoryMap[0x0b] = &gbRam[0x1000];
+ }
+
+ gbDataMBC1.mapperRAMBank = 0;
}
break;
case 0x6000: // memory model select
gbDataMBC1.mapperMemoryModel = value & 1;
+
+ if(gbDataMBC1.mapperMemoryModel == 1) {
+ // 4/32 model, RAM bank switching provided
+
+ value = gbDataMBC1.mapperRAMBank & 0x03;
+ tmpAddress = value << 13;
+ tmpAddress &= gbRamSizeMask;
+ if(gbRamSize) {
+ gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress];
+ gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000];
+ gbDataMBC1.mapperRomBank0Remapping = 0;
+ }
+ else gbDataMBC1.mapperRomBank0Remapping |=2;
+
+ gbDataMBC1.mapperRAMBank = value;
+ gbDataMBC1.mapperRAMAddress = tmpAddress;
+
+ tmpAddress = gbDataMBC1.mapperROMBank << 14;
+
+
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+
+ } else {
+ // 16/8, set the high address
+
+ tmpAddress = gbDataMBC1.mapperROMBank << 14;
+ tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+ if(gbRamSize) {
+ gbMemoryMap[0x0a] = &gbRam[0];
+ gbMemoryMap[0x0b] = &gbRam[0x1000];
+ }
+ }
break;
}
}
@@ -102,23 +187,72 @@ void mapperMBC1RAM(u16 address, u8 value)
}
}
+// MBC1 read RAM
+u8 mapperMBC1ReadRAM(u16 address)
+{
+
+ if(gbDataMBC1.mapperRAMEnable)
+ return gbMemoryMap[address>>12][address & 0x0fff];
+
+ if (!genericflashcardEnable)
+ return 0xff;
+ else
+ if ((address & 0x1000) >= 0x1000)
+ {
+ // The value returned when reading RAM while it's disabled
+ // is constant, exept for the GBASP hardware.
+ // (actually, is the address that read is out of the ROM, the returned value if 0xff...)
+ if (PC.W>=0xff80)
+ return 0xff;
+ else
+ if ((gbHardware & 0x08) && (gbGBCColorType == 2))
+ {
+ if (address & 1)
+ return 0xfb;
+ else
+ return 0x7a;
+ }
+ else
+ return 0x0a;
+ }
+ else
+ return gbDisabledRam[address & 7];
+}
+
void memoryUpdateMapMBC1()
{
int tmpAddress = gbDataMBC1.mapperROMBank << 14;
// check current model
- if(gbDataMBC1.mapperMemoryModel == 1) {
- // model is 16/8, so we have a high address in use
- tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
+ if (gbDataMBC1.mapperRomBank0Remapping == 3) {
+ tmpAddress = (gbDataMBC1.mapperROMHighAddress & 3) << 18;
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x00] = &gbRom[tmpAddress];
+ gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000];
+
+ tmpAddress |= (gbDataMBC1.mapperROMBank & 0xf) << 14;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+ }
+ else
+ {
+ if(gbDataMBC1.mapperMemoryModel == 0) {
+ // model is 16/8, so we have a high address in use
+ tmpAddress |= (gbDataMBC1.mapperROMHighAddress & 3) << 19;
+ }
+
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
}
- tmpAddress &= gbRomSizeMask;
- gbMemoryMap[0x04] = &gbRom[tmpAddress];
- gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
- gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
- gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
-
- if(gbRamSize) {
+ if((gbRamSize) && (gbDataMBC1.mapperMemoryModel == 1)){
gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress];
gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000];
}
@@ -210,7 +344,7 @@ void memoryUpdateMBC3Clock()
time_t diff = now - gbDataMBC3.mapperLastTime;
if(diff > 0) {
// update the clock according to the last update time
- gbDataMBC3.mapperSeconds += diff % 60;
+ gbDataMBC3.mapperSeconds += (int)(diff % 60);
if(gbDataMBC3.mapperSeconds > 59) {
gbDataMBC3.mapperSeconds -= 60;
gbDataMBC3.mapperMinutes++;
@@ -218,22 +352,22 @@ void memoryUpdateMBC3Clock()
diff /= 60;
- gbDataMBC3.mapperMinutes += diff % 60;
- if(gbDataMBC3.mapperMinutes > 60) {
+ gbDataMBC3.mapperMinutes += (int)(diff % 60);
+ if(gbDataMBC3.mapperMinutes > 59) {
gbDataMBC3.mapperMinutes -= 60;
gbDataMBC3.mapperHours++;
}
diff /= 60;
- gbDataMBC3.mapperHours += diff % 24;
- if(gbDataMBC3.mapperHours > 24) {
+ gbDataMBC3.mapperHours += (int)(diff % 24);
+ if(gbDataMBC3.mapperHours > 23) {
gbDataMBC3.mapperHours -= 24;
gbDataMBC3.mapperDays++;
}
diff /= 24;
- gbDataMBC3.mapperDays += diff;
+ gbDataMBC3.mapperDays += (int)(diff & 0xffffffff);
if(gbDataMBC3.mapperDays > 255) {
if(gbDataMBC3.mapperDays > 511) {
gbDataMBC3.mapperDays %= 512;
@@ -365,7 +499,30 @@ u8 mapperMBC3ReadRAM(u16 address)
return gbDataMBC3.mapperLControl;
}
}
- return 0;
+
+ if (!genericflashcardEnable)
+ return 0xff;
+ else
+ if ((address & 0x1000) >= 0x1000)
+ {
+ // The value returned when reading RAM while it's disabled
+ // is constant, exept for the GBASP hardware.
+ // (actually, is the address that read is out of the ROM, the returned value if 0xff...)
+ if (PC.W>=0xff80)
+ return 0xff;
+ else
+ if ((gbHardware & 0x08) && (gbGBCColorType == 2))
+ {
+ if (address & 1)
+ return 0xfb;
+ else
+ return 0x7a;
+ }
+ else
+ return 0x0a;
+ }
+ else
+ return gbDisabledRam[address & 7];
}
void memoryUpdateMapMBC3()
@@ -406,6 +563,7 @@ void mapperMBC5ROM(u16 address, u8 value)
gbDataMBC5.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0);
break;
case 0x2000: // ROM bank select
+
if(address < 0x3000) {
value = value & 0xff;
if(value == gbDataMBC5.mapperROMBank)
@@ -466,6 +624,38 @@ void mapperMBC5RAM(u16 address, u8 value)
}
}
+// MBC5 read RAM
+u8 mapperMBC5ReadRAM(u16 address)
+{
+
+ if(gbDataMBC5.mapperRAMEnable)
+ return gbMemoryMap[address>>12][address & 0x0fff];
+
+ if (!genericflashcardEnable)
+ return 0xff;
+ else
+ if ((address & 0x1000) >= 0x1000)
+ {
+ // The value returned when reading RAM while it's disabled
+ // is constant, exept for the GBASP hardware.
+ // (actually, is the address that read is out of the ROM, the returned value if 0xff...)
+ if (PC.W>=0xff80)
+ return 0xff;
+ else
+ if ((gbHardware & 0x08) && (gbGBCColorType == 2))
+ {
+ if (address & 1)
+ return 0xfb;
+ else
+ return 0x7a;
+ }
+ else
+ return 0x0a;
+ }
+ else
+ return gbDisabledRam[address & 7];
+}
+
void memoryUpdateMapMBC5()
{
int tmpAddress = (gbDataMBC5.mapperROMBank << 14) |
@@ -568,7 +758,30 @@ u8 mapperMBC7ReadRAM(u16 address)
case 0xa080:
return gbDataMBC7.value;
}
- return 0xff;
+
+ if (!genericflashcardEnable)
+ return 0xff;
+ else
+ if ((address & 0x1000) >= 0x1000)
+ {
+ // The value returned when reading RAM while it's disabled
+ // is constant, exept for the GBASP hardware.
+ // (actually, is the address that read is out of the ROM, the returned value if 0xff...)
+ if (PC.W>=0xff80)
+ return 0xff;
+ else
+ if ((gbHardware & 0x08) && (gbGBCColorType == 2))
+ {
+ if (address & 1)
+ return 0xfb;
+ else
+ return 0x7a;
+ }
+ else
+ return 0x0a;
+ }
+ else
+ return gbDisabledRam[address & 7];
}
// MBC7 RAM write
@@ -717,7 +930,7 @@ void mapperMBC7RAM(u16 address, u8 value)
void memoryUpdateMapMBC7()
{
- int tmpAddress = (gbDataMBC5.mapperROMBank << 14);
+ int tmpAddress = (gbDataMBC7.mapperROMBank << 14);
tmpAddress &= gbRomSizeMask;
gbMemoryMap[0x04] = &gbRom[tmpAddress];
@@ -965,3 +1178,540 @@ void memoryUpdateMapHuC3()
gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
}
}
+
+// TAMA5 (for Tamagotchi 3 (gb)).
+// Very basic (and ugly :p) support, only rom bank switching is actually working...
+mapperTAMA5 gbDataTAMA5 = {
+ 1, // RAM enable
+ 1, // ROM bank
+ 0, // RAM bank
+ 0, // RAM address
+ 0, // RAM Byte select
+ 0, // mapper command number
+ 0, // mapper last command;
+ 0, // commands 0x0
+ 0, // commands 0x1
+ 0, // commands 0x2
+ 0, // commands 0x3
+ 0, // commands 0x4
+ 0, // commands 0x5
+ 0, // commands 0x6
+ 0, // commands 0x7
+ 0, // commands 0x8
+ 0, // commands 0x9
+ 0, // commands 0xa
+ 0, // commands 0xb
+ 0, // commands 0xc
+ 0, // commands 0xd
+ 0, // commands 0xe
+ 0, // commands 0xf
+ 0, // register
+ 0, // timer clock latch
+ 0, // timer clock register
+ 0, // timer seconds
+ 0, // timer minutes
+ 0, // timer hours
+ 0, // timer days
+ 0, // timer months
+ 0, // timer years
+ 0, // timer control
+ 0, // timer latched seconds
+ 0, // timer latched minutes
+ 0, // timer latched hours
+ 0, // timer latched days
+ 0, // timer latched months
+ 0, // timer latched years
+ 0, // timer latched control
+ (time_t)-1 // last time
+};
+
+
+void memoryUpdateTAMA5Clock()
+{
+ if ((gbDataTAMA5.mapperYears & 3) == 0)
+ gbDaysinMonth[1] = 29;
+ else
+ gbDaysinMonth[1] = 28;
+
+ time_t now = time(NULL);
+ time_t diff = now - gbDataTAMA5.mapperLastTime;
+ if(diff > 0) {
+ // update the clock according to the last update time
+ gbDataTAMA5.mapperSeconds += (int)(diff % 60);
+ if(gbDataTAMA5.mapperSeconds > 59) {
+ gbDataTAMA5.mapperSeconds -= 60;
+ gbDataTAMA5.mapperMinutes++;
+ }
+
+ diff /= 60;
+
+ gbDataTAMA5.mapperMinutes += (int)(diff % 60);
+ if(gbDataTAMA5.mapperMinutes > 59) {
+ gbDataTAMA5.mapperMinutes -= 60;
+ gbDataTAMA5.mapperHours++;
+ }
+
+ diff /= 60;
+
+ gbDataTAMA5.mapperHours += (int)(diff % 24);
+ diff /= 24;
+ if(gbDataTAMA5.mapperHours > 23) {
+ gbDataTAMA5.mapperHours -= 24;
+ diff++;
+
+ }
+
+ time_t days = diff;
+ while (days)
+ {
+ gbDataTAMA5.mapperDays++;
+ days--;
+ if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1])
+ {
+ gbDataTAMA5.mapperDays = 1;
+ gbDataTAMA5.mapperMonths++;
+ if (gbDataTAMA5.mapperMonths>12)
+ {
+ gbDataTAMA5.mapperMonths = 1;
+ gbDataTAMA5.mapperYears++;
+ if ((gbDataTAMA5.mapperYears & 3) == 0)
+ gbDaysinMonth[1] = 29;
+ else
+ gbDaysinMonth[1] = 28;
+ }
+ }
+ }
+ }
+ gbDataTAMA5.mapperLastTime = now;
+
+}
+
+
+
+// TAMA5 RAM write
+void mapperTAMA5RAM(u16 address, u8 value)
+{
+ if ((address & 0xffff) <= 0xa001)
+ {
+ switch (address & 1)
+ {
+ case 0: // 'Values' Register
+ {
+ value &= 0xf;
+ gbDataTAMA5.mapperCommands[gbDataTAMA5.mapperCommandNumber] = value;
+ gbMemoryMap[0xa][0] = value;
+
+ int test = gbDataTAMA5.mapperCommands[gbDataTAMA5.mapperCommandNumber & 0x0e] |
+ (gbDataTAMA5.mapperCommands[(gbDataTAMA5.mapperCommandNumber & 0x0e) +1]<<4);
+
+ if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 0) // Read Command !!!
+ {
+ gbDataTAMA5.mapperROMBank = gbDataTAMA5.mapperCommands[0] |
+ (gbDataTAMA5.mapperCommands[1]<<4);
+
+ int tmpAddress = (gbDataTAMA5.mapperROMBank << 14);
+
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+
+ gbDataTAMA5.mapperCommands[0x0f] = 0;
+ }
+ else if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 4)
+ {
+ gbDataTAMA5.mapperCommands[0x0f] = 1;
+ if (gbDataTAMA5.mapperCommandNumber == 4)
+ gbDataTAMA5.mapperCommands[5] =0; // correct ?
+ }
+ else if ((gbDataTAMA5.mapperCommandNumber & 0xe) == 6)
+ {
+ gbDataTAMA5.mapperRamByteSelect = (gbDataTAMA5.mapperCommands[7]<<4) |
+ (gbDataTAMA5.mapperCommands[6]&0x0f);
+
+ // Write Commands !!!
+ if (gbDataTAMA5.mapperCommands[0x0f] && (gbDataTAMA5.mapperCommandNumber == 7))
+ {
+ int data = gbDataTAMA5.mapperCommands[0x04] & 0x0f |
+ (gbDataTAMA5.mapperCommands[0x05] <<4);
+
+ // Not sure when the write command should reset...
+ // but it doesn't seem to matter.
+ // gbDataTAMA5.mapperCommands[0x0f] = 0;
+
+ if (gbDataTAMA5.mapperRamByteSelect == 0x8) // Timer stuff
+ {
+ switch (data & 0xf)
+ {
+ case 0x7:
+ gbDataTAMA5.mapperDays = ((gbDataTAMA5.mapperDays)/10)*10 + (data >> 4);
+ break;
+ case 0x8:
+ gbDataTAMA5.mapperDays = (gbDataTAMA5.mapperDays%10) + (data >>4)*10;
+ break;
+ case 0x9:
+ gbDataTAMA5.mapperMonths = ((gbDataTAMA5.mapperMonths)/10)*10 + (data >> 4);
+ break;
+ case 0xa:
+ gbDataTAMA5.mapperMonths = (gbDataTAMA5.mapperMonths%10) + (data >>4)*10;
+ break;
+ case 0xb:
+ gbDataTAMA5.mapperYears = ((gbDataTAMA5.mapperYears)%1000) + (data >> 4)*1000;
+ break;
+ case 0xc:
+ gbDataTAMA5.mapperYears = (gbDataTAMA5.mapperYears%100) + (gbDataTAMA5.mapperYears/1000)*1000 +
+ (data >>4)*100;
+ break;
+ default :
+ break;
+ }
+ }
+ else if (gbDataTAMA5.mapperRamByteSelect == 0x18) // Timer stuff again
+ {
+ memoryUpdateTAMA5Clock();
+ gbDataTAMA5.mapperLSeconds = gbDataTAMA5.mapperSeconds;
+ gbDataTAMA5.mapperLMinutes = gbDataTAMA5.mapperMinutes;
+ gbDataTAMA5.mapperLHours = gbDataTAMA5.mapperHours;
+ gbDataTAMA5.mapperLDays = gbDataTAMA5.mapperDays;
+ gbDataTAMA5.mapperLMonths = gbDataTAMA5.mapperMonths;
+ gbDataTAMA5.mapperLYears = gbDataTAMA5.mapperYears;
+ gbDataTAMA5.mapperLControl = gbDataTAMA5.mapperControl;
+
+ int seconds = (gbDataTAMA5.mapperLSeconds / 10)*16 + gbDataTAMA5.mapperLSeconds %10;
+ int secondsL = (gbDataTAMA5.mapperLSeconds % 10);
+ int secondsH = (gbDataTAMA5.mapperLSeconds / 10);
+ int minutes = (gbDataTAMA5.mapperLMinutes / 10)*16 + gbDataTAMA5.mapperLMinutes %10;
+ int hours = (gbDataTAMA5.mapperLHours / 10)*16 + gbDataTAMA5.mapperLHours %10;
+ int DaysL = gbDataTAMA5.mapperLDays % 10;
+ int DaysH = gbDataTAMA5.mapperLDays /10;
+ int MonthsL = gbDataTAMA5.mapperLMonths % 10;
+ int MonthsH = gbDataTAMA5.mapperLMonths / 10;
+ int Years3 = (gbDataTAMA5.mapperLYears / 100) % 10;
+ int Years4 = (gbDataTAMA5.mapperLYears / 1000);
+
+ switch (data & 0x0f)
+ {
+ // I guess cases 0 and 1 are used for secondsL and secondsH
+ // so the game would update the timer values on screen when
+ // the seconds reset to 0... ?
+ case 0x0:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = secondsL;
+ break;
+ case 0x1:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = secondsH;
+ break;
+ case 0x7:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = DaysL; // days low
+ break;
+ case 0x8:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = DaysH; // days high
+ break;
+ case 0x9:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = MonthsL; // month low
+ break;
+ case 0xa:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = MonthsH; // month high
+ break;
+ case 0xb:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = Years4; // years 4th digit
+ break;
+ case 0xc:
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = Years3; // years 3rd digit
+ break;
+ default :
+ break;
+ }
+
+ gbTAMA5ram[0x54] = seconds; // incorrect ? (not used by the game) ?
+ gbTAMA5ram[0x64] = minutes;
+ gbTAMA5ram[0x74] = hours;
+ gbTAMA5ram[0x84] = DaysH*16+DaysL; // incorrect ? (not used by the game) ?
+ gbTAMA5ram[0x94] = MonthsH*16+MonthsL; // incorrect ? (not used by the game) ?
+
+ time(&gbDataTAMA5.mapperLastTime);
+
+ gbMemoryMap[0xa][0] = 1;
+ }
+ else if (gbDataTAMA5.mapperRamByteSelect == 0x28) // Timer stuff again
+ {
+ if ((data & 0xf) == 0xb)
+ gbDataTAMA5.mapperYears = ((gbDataTAMA5.mapperYears>>2)<<2) + (data & 3);
+ }
+ else if (gbDataTAMA5.mapperRamByteSelect == 0x44)
+ {
+ gbDataTAMA5.mapperMinutes = (data/16)*10 + data%16;
+ }
+ else if (gbDataTAMA5.mapperRamByteSelect == 0x54)
+ {
+ gbDataTAMA5.mapperHours = (data/16)*10 + data%16;
+ }
+ else
+ {
+ gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect] = data;
+ }
+ }
+ }
+ }
+ break;
+ case 1: // 'Commands' Register
+ {
+ gbMemoryMap[0xa][1] = gbDataTAMA5.mapperCommandNumber = value;
+
+ // This should be only a 'is the flashrom ready ?' command.
+ // However as I couldn't find any 'copy' command
+ // (that seems to be needed for the saving system to work)
+ // I put it there...
+ if (value == 0x0a)
+ {
+ for (int i = 0; i<0x10; i++)
+ for (int j = 0; j<0x10; j++)
+ if (!(j&2))
+ gbTAMA5ram[(i*0x10)+j | 2] = gbTAMA5ram[(i*0x10)+j];
+ // Enable this to see the content of the flashrom in 0xe000
+ /*for (int k = 0; k<0x100; k++)
+ gbMemoryMap[0xe][k] = gbTAMA5ram[k];*/
+
+ gbMemoryMap[0xa][0] = gbDataTAMA5.mapperRAMEnable = 1;
+ }
+ else
+ {
+ if ((value & 0x0e) == 0x0c)
+ {
+ gbDataTAMA5.mapperRamByteSelect = gbDataTAMA5.mapperCommands[6] |
+ (gbDataTAMA5.mapperCommands[7]<<4);
+
+ u8 byte = gbTAMA5ram[gbDataTAMA5.mapperRamByteSelect];
+
+ gbMemoryMap[0xa][0] = (value & 1) ? byte >> 4 : byte & 0x0f;
+
+ gbDataTAMA5.mapperCommands[0x0f] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ if(gbDataTAMA5.mapperRAMEnable) {
+ if(gbDataTAMA5.mapperRAMBank != -1) {
+ if(gbRamSize) {
+ gbMemoryMap[address>>12][address & 0x0fff] = value;
+ systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
+ }
+ }
+ }
+ }
+}
+
+
+// TAMA5 read RAM
+u8 mapperTAMA5ReadRAM(u16 address)
+{
+ return gbMemoryMap[address>>12][address & 0xfff];
+}
+
+
+void memoryUpdateMapTAMA5()
+{
+ int tmpAddress = (gbDataTAMA5.mapperROMBank << 14);
+
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+
+ if(gbRamSize) {
+ tmpAddress = 0 << 13;
+ tmpAddress &= gbRamSizeMask;
+ gbMemoryMap[0x0a] = &gbRam[tmpAddress];
+ gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
+ }
+}
+
+// MMM01 Used in Momotarou collection (however the rom is corrupted)
+mapperMMM01 gbDataMMM01 ={
+ 0, // RAM enable
+ 1, // ROM bank
+ 0, // RAM bank
+ 0, // memory model
+ 0, // ROM high address
+ 0, // RAM address
+ 0 // Rom Bank 0 remapping
+};
+
+// MMM01 ROM write registers
+void mapperMMM01ROM(u16 address, u8 value)
+{
+ int tmpAddress = 0;
+
+ switch(address & 0x6000) {
+ case 0x0000: // RAM enable register
+ gbDataMMM01.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0);
+ break;
+ case 0x2000: // ROM bank select
+ // value = value & 0x1f;
+ if(value == 0)
+ value = 1;
+ if(value == gbDataMMM01.mapperROMBank)
+ break;
+
+ tmpAddress = value << 14;
+
+ // check current model
+ if(gbDataMMM01.mapperMemoryModel == 0) {
+ // model is 16/8, so we have a high address in use
+ tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19;
+ }
+ else
+ tmpAddress |= gbDataMMM01.mapperRomBank0Remapping << 18;
+
+ tmpAddress &= gbRomSizeMask;
+ gbDataMMM01.mapperROMBank = value;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+ break;
+ case 0x4000: // RAM bank select
+ if(gbDataMMM01.mapperMemoryModel == 1) {
+ // 4/32 model, RAM bank switching provided
+ value = value & 0x03;
+ if(value == gbDataMBC1.mapperRAMBank)
+ break;
+ tmpAddress = value << 13;
+ tmpAddress &= gbRamSizeMask;
+ gbMemoryMap[0x0a] = &gbRam[tmpAddress];
+ gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
+ gbDataMMM01.mapperRAMBank = value;
+ gbDataMMM01.mapperRAMAddress = tmpAddress;
+ } else {
+ // 16/8, set the high address
+ gbDataMMM01.mapperROMHighAddress = value & 0x03;
+ tmpAddress = gbDataMMM01.mapperROMBank << 14;
+ tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19;
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+
+ gbDataMMM01.mapperRomBank0Remapping = ((value<<1) | (value & 0x40 ? 1 : 0)) & 0xff;
+ tmpAddress = gbDataMMM01.mapperRomBank0Remapping << 18;
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x00] = &gbRom[tmpAddress];
+ gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000];
+ }
+ break;
+ case 0x6000: // memory model select
+ gbDataMMM01.mapperMemoryModel = value & 1;
+ break;
+ }
+}
+
+// MMM01 RAM write
+void mapperMMM01RAM(u16 address, u8 value)
+{
+ if(gbDataMMM01.mapperRAMEnable) {
+ if(gbRamSize) {
+ gbMemoryMap[address >> 12][address & 0x0fff] = value;
+ systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
+ }
+ }
+}
+
+void memoryUpdateMapMMM01()
+{
+ int tmpAddress = gbDataMMM01.mapperROMBank << 14;
+
+ // check current model
+ if(gbDataMMM01.mapperMemoryModel == 1) {
+ // model is 16/8, so we have a high address in use
+ tmpAddress |= (gbDataMMM01.mapperROMHighAddress) << 19;
+ }
+
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
+
+ tmpAddress = gbDataMMM01.mapperRomBank0Remapping << 18;
+ tmpAddress &= gbRomSizeMask;
+ gbMemoryMap[0x00] = &gbRom[tmpAddress];
+ gbMemoryMap[0x01] = &gbRom[tmpAddress + 0x1000];
+ gbMemoryMap[0x02] = &gbRom[tmpAddress + 0x2000];
+ gbMemoryMap[0x03] = &gbRom[tmpAddress + 0x3000];
+
+ if(gbRamSize) {
+ gbMemoryMap[0x0a] = &gbRam[gbDataMMM01.mapperRAMAddress];
+ gbMemoryMap[0x0b] = &gbRam[gbDataMMM01.mapperRAMAddress + 0x1000];
+ }
+}
+
+// GameGenie ROM write registers
+void mapperGGROM(u16 address, u8 value)
+{
+ int tmpAddress = 0;
+
+ switch(address & 0x6000) {
+ case 0x0000: // RAM enable register
+ break;
+ case 0x2000: // GameGenie has only a half bank
+ break;
+ case 0x4000: // GameGenie has no RAM
+ if ((address >=0x4001) && (address <= 0x4020)) // GG Hardware Registers
+ gbMemoryMap[address >> 12][address & 0x0fff] = value;
+ break;
+ case 0x6000: // GameGenie has only a half bank
+ break;
+ }
+}
+
+
+// GS3 Used to emulate the GS V3.0 rom bank switching
+mapperGS3 gbDataGS3 = { 1 }; // ROM bank
+
+void mapperGS3ROM(u16 address, u8 value)
+{
+ int tmpAddress = 0;
+
+ switch(address & 0x6000) {
+ case 0x0000: // GS has no ram
+ break;
+ case 0x2000: // GS has no 'classic' ROM bank select
+ break;
+ case 0x4000: // GS has no ram
+ break;
+ case 0x6000: // 0x6000 area is RW, and used for GS hardware registers
+
+ if (address == 0x7FE1) // This is the (half) ROM bank select register
+ {
+ if(value == gbDataGS3.mapperROMBank)
+ break;
+ tmpAddress = value << 13;
+
+ tmpAddress &= gbRomSizeMask;
+ gbDataGS3.mapperROMBank = value;
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+ }
+ else
+ gbMemoryMap[address>>12][address & 0x0fff] = value;
+ break;
+ }
+}
+
+void memoryUpdateMapGS3()
+{
+ int tmpAddress = gbDataGS3.mapperROMBank << 13;
+
+ tmpAddress &= gbRomSizeMask;
+ // GS can only change a half ROM bank
+ gbMemoryMap[0x04] = &gbRom[tmpAddress];
+ gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
+}
\ No newline at end of file
diff --git a/src/gb/gbMemory.h b/src/gb/gbMemory.h
index 9ce19edd..ef714d19 100644
--- a/src/gb/gbMemory.h
+++ b/src/gb/gbMemory.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@ struct mapperMBC1 {
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
+ int mapperRomBank0Remapping;
};
struct mapperMBC2 {
@@ -106,15 +107,62 @@ struct mapperHuC3 {
int mapperRegister8;
};
+struct mapperTAMA5 {
+ int mapperRAMEnable;
+ int mapperROMBank;
+ int mapperRAMBank;
+ int mapperRAMAddress;
+ int mapperRamByteSelect;
+ int mapperCommandNumber;
+ int mapperLastCommandNumber;
+ int mapperCommands[0x10];
+ int mapperRegister;
+ int mapperClockLatch;
+ int mapperClockRegister;
+ int mapperSeconds;
+ int mapperMinutes;
+ int mapperHours;
+ int mapperDays;
+ int mapperMonths;
+ int mapperYears;
+ int mapperControl;
+ int mapperLSeconds;
+ int mapperLMinutes;
+ int mapperLHours;
+ int mapperLDays;
+ int mapperLMonths;
+ int mapperLYears;
+ int mapperLControl;
+ time_t mapperLastTime;
+};
+
+struct mapperMMM01 {
+ int mapperRAMEnable;
+ int mapperROMBank;
+ int mapperRAMBank;
+ int mapperMemoryModel;
+ int mapperROMHighAddress;
+ int mapperRAMAddress;
+ int mapperRomBank0Remapping;
+};
+
+struct mapperGS3 {
+ int mapperROMBank;
+};
+
extern mapperMBC1 gbDataMBC1;
extern mapperMBC2 gbDataMBC2;
extern mapperMBC3 gbDataMBC3;
extern mapperMBC5 gbDataMBC5;
extern mapperHuC1 gbDataHuC1;
extern mapperHuC3 gbDataHuC3;
+extern mapperTAMA5 gbDataTAMA5;
+extern mapperMMM01 gbDataMMM01;
+extern mapperGS3 gbDataGS3;
void mapperMBC1ROM(u16,u8);
void mapperMBC1RAM(u16,u8);
+u8 mapperMBC1ReadRAM(u16);
void mapperMBC2ROM(u16,u8);
void mapperMBC2RAM(u16,u8);
void mapperMBC3ROM(u16,u8);
@@ -122,6 +170,7 @@ void mapperMBC3RAM(u16,u8);
u8 mapperMBC3ReadRAM(u16);
void mapperMBC5ROM(u16,u8);
void mapperMBC5RAM(u16,u8);
+u8 mapperMBC5ReadRAM(u16);
void mapperMBC7ROM(u16,u8);
void mapperMBC7RAM(u16,u8);
u8 mapperMBC7ReadRAM(u16);
@@ -130,7 +179,13 @@ void mapperHuC1RAM(u16,u8);
void mapperHuC3ROM(u16,u8);
void mapperHuC3RAM(u16,u8);
u8 mapperHuC3ReadRAM(u16);
-
+void mapperTAMA5RAM(u16,u8);
+u8 mapperTAMA5ReadRAM(u16);
+void memoryUpdateTAMA5Clock();
+void mapperMMM01ROM(u16,u8);
+void mapperMMM01RAM(u16,u8);
+void mapperGGROM(u16,u8);
+void mapperGS3ROM(u16,u8);
//extern void (*mapper)(u16,u8);
//extern void (*mapperRAM)(u16,u8);
//extern u8 (*mapperReadRAM)(u16);
@@ -142,7 +197,9 @@ extern void memoryUpdateMapMBC5();
extern void memoryUpdateMapMBC7();
extern void memoryUpdateMapHuC1();
extern void memoryUpdateMapHuC3();
-
+extern void memoryUpdateMapTAMA5();
+extern void memoryUpdateMapMMM01();
+extern void memoryUpdateMapGS3();
diff --git a/src/gb/gbSGB.cpp b/src/gb/gbSGB.cpp
index dc7a1d80..9c8469fc 100644
--- a/src/gb/gbSGB.cpp
+++ b/src/gb/gbSGB.cpp
@@ -1,917 +1,917 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-#include
-
-#include "../win32/stdafx.h"
-#include "../win32/VBA.h"
-#include "../System.h"
-#include "../Port.h"
-#include "../Util.h"
-#include "GB.h"
-#include "gbGlobals.h"
-
-extern u8 *pix;
-extern bool speedup;
-
-#define GBSGB_NONE 0
-#define GBSGB_RESET 1
-#define GBSGB_PACKET_TRANSMIT 2
-
-u8 *gbSgbBorderChar = NULL;
-u8 *gbSgbBorder = NULL;
-
-int gbSgbCGBSupport = 0;
-int gbSgbMask = 0;
-int gbSgbMode = 0;
-int gbSgbPacketState = GBSGB_NONE;
-int gbSgbBit = 0;
-int gbSgbPacketTimeout = 0;
-int GBSGB_PACKET_TIMEOUT = 66666;
-u8 gbSgbPacket[16*7];
-int gbSgbPacketNBits = 0;
-int gbSgbPacketByte = 0;
-int gbSgbPacketNumber = 0;
-int gbSgbMultiplayer = 0;
-int gbSgbFourPlayers = 0;
-u8 gbSgbNextController = 0x0f;
-u8 gbSgbReadingController = 0;
-u16 gbSgbSCPPalette[4*512];
-u8 gbSgbATF[20 * 18];
-u8 gbSgbATFList[45 * 20 * 18];
-u8 gbSgbScreenBuffer[4160];
-
-inline void gbSgbDraw24Bit(u8 *p, u16 v)
-{
- *((u32*) p) = systemColorMap32[v];
-}
-
-inline void gbSgbDraw32Bit(u32 *p, u16 v)
-{
- *p = systemColorMap32[v];
-}
-
-inline void gbSgbDraw16Bit(u16 *p, u16 v)
-{
- *p = systemColorMap16[v];
-}
-
-void gbSgbReset()
-{
- gbSgbPacketTimeout = 0;
- gbSgbCGBSupport = 0;
- gbSgbMask = 0;
- gbSgbPacketState = GBSGB_NONE;
- gbSgbBit = 0;
- gbSgbPacketNBits = 0;
- gbSgbPacketNumber = 0;
- gbSgbMultiplayer = 0;
- gbSgbFourPlayers = 0;
- gbSgbNextController = 0x0f;
- gbSgbReadingController = 0;
-
- memset(gbSgbSCPPalette, 0, 512*4);
- memset(gbSgbATF, 0, 20*18);
- memset(gbSgbATFList, 0, 45 * 20 * 18);
- memset(gbSgbPacket, 0, 16 * 7);
- memset(gbSgbBorderChar, 0, 32*256);
- memset(gbSgbBorder, 0, 2048);
-
- int i;
- for(i = 1; i < 2048; i+=2) {
- gbSgbBorder[i] = 1 << 2;
- }
-
- for(i = 0; i < 4; i++) {
- gbPalette[i*4] = (0x1f) | (0x1f << 5) | (0x1f << 10);
- gbPalette[i*4+1] = (0x15) | (0x15 << 5) | (0x15 << 10);
- gbPalette[i*4+2] = (0x0c) | (0x0c << 5) | (0x0c << 10);
- gbPalette[i*4+3] = 0;
- }
-}
-
-void gbSgbInit()
-{
- gbSgbBorderChar = (u8 *)malloc(32 * 256);
- gbSgbBorder = (u8 *)malloc(2048);
-
- gbSgbReset();
-}
-
-void gbSgbShutdown()
-{
- if(gbSgbBorderChar != NULL) {
- free(gbSgbBorderChar);
- gbSgbBorderChar = NULL;
- }
-
- if(gbSgbBorder != NULL) {
- free(gbSgbBorder);
- gbSgbBorder = NULL;
- }
-}
-
-void gbSgbFillScreen(u16 color)
-{
- switch(systemColorDepth) {
- case 16:
- {
- for(int y = 0; y < 144; y++) {
- int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+2) +
- gbBorderColumnSkip;
- u16 *dest = (u16*)pix + yLine;
- for(register int x = 0; x < 160; x++)
- gbSgbDraw16Bit(dest++, color);
- }
- }
- break;
- case 24:
- {
- for(int y = 0; y < 144; y++) {
- int yLine = (y+gbBorderRowSkip)*gbBorderLineSkip + gbBorderColumnSkip;
- u8 *dest = (u8 *)pix + yLine*3;
- for(register int x = 0; x < 160; x++) {
- gbSgbDraw24Bit(dest, color);
- dest += 3;
- }
- }
- }
- break;
- case 32:
- {
- for(int y = 0; y < 144; y++) {
- int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+1) + gbBorderColumnSkip;
- u32 *dest = (u32 *)pix + yLine;
- for(register int x = 0; x < 160; x++) {
- gbSgbDraw32Bit(dest++, color);
- }
- }
- }
- break;
- }
-}
-
-#define getmem(x) gbMemoryMap[(x) >> 12][(x) & 0xfff]
-
-void gbSgbRenderScreenToBuffer()
-{
- u16 mapAddress = 0x9800;
-
- if(register_LCDC & 0x08)
- mapAddress = 0x9c00;
-
- u16 patternAddress = 0x8800;
-
- int flag = 1;
-
- if(register_LCDC & 0x10) {
- patternAddress = 0x8000;
- flag = 0;
- }
-
- u8 *toAddress = gbSgbScreenBuffer;
-
- for(int i = 0; i < 13; i++) {
- for(int j = 0; j < 20; j++) {
- int tile = getmem(mapAddress);
- mapAddress++;
-
- if(flag) {
- if(tile > 127)
- tile -= 128;
- else
- tile += 128;
- }
- for(int k = 0; k < 16; k++)
- *toAddress++ = getmem(patternAddress + tile*16 + k);
- }
- mapAddress += 12;
- }
-}
-
-void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
-{
- u16 *dest = (u16*)pix + ((y+1) * (256+2)) + x;
- u8 *dest8 = (u8*)pix + ((y*256)+x)*3;
- u32 *dest32 = (u32*)pix + ((y+1)*257) + x;
-
- u8 *tileAddress = &gbSgbBorderChar[tile * 32];
- u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
-
- u8 l = 8;
-
- u8 palette = ((attr >> 2 ) & 7);
-
- if(palette < 4)
- palette += 4;
-
- palette *= 16;
-
- u8 xx = 0;
- u8 yy = 0;
-
- int flipX = attr & 0x40;
- int flipY = attr & 0x80;
-
- while(l > 0) {
- u8 mask = 0x80;
- u8 a = *tileAddress++;
- u8 b = *tileAddress++;
- u8 c = *tileAddress2++;
- u8 d = *tileAddress2++;
-
- while(mask > 0) {
-
- u8 color = 0;
- if(a & mask)
- color++;
- if(b & mask)
- color+=2;
- if(c & mask)
- color+=4;
- if(d & mask)
- color+=8;
-
- u8 xxx = xx;
- u8 yyy = yy;
-
- if(flipX)
- xxx = 7 - xx;
- if(flipY)
- yyy = 7 - yy;
-
- u16 c = gbPalette[palette + color];
- if(!color)
- c = gbPalette[0];
- if((yy < 40 || yy >= 184) || (xx < 48 || xx >= 208)) {
- switch(systemColorDepth) {
- case 16:
- gbSgbDraw16Bit(dest + yyy*(256+2) + xxx, c);
- break;
- case 24:
- gbSgbDraw24Bit(dest8 + (yyy*256+xxx)*3, c);
- break;
- case 32:
- gbSgbDraw32Bit(dest32 + yyy*(256+1)+xxx, c);
- break;
- }
- }
-
- mask >>= 1;
-
- xx++;
- }
- yy++;
- xx = 0;
- l--;
- mask = 0x80;
- }
-}
-
-void gbSgbRenderBorder()
-{
- if(gbBorderOn) {
- if (theApp.filterLCD) utilUpdateSystemColorMaps(0);
- u8 *fromAddress = gbSgbBorder;
-
- for(u8 y = 0; y < 28; y++) {
- for(u8 x = 0; x< 32; x++) {
- u8 tile = *fromAddress++;
- u8 attr = *fromAddress++;
-
- gbSgbDrawBorderTile(x*8,y*8,tile,attr);
- }
- }
- if (theApp.filterLCD) utilUpdateSystemColorMaps(1);
- }
-}
-
-void gbSgbPicture()
-{
- gbSgbRenderScreenToBuffer();
-
- memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048);
-
- u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048];
-
- for(int i = 64; i < 128; i++) {
- gbPalette[i] = READ16LE(paletteAddr++);
- }
-
- gbSgbCGBSupport |= 4;
-
- if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) {
- gbBorderOn = 1;
- systemGbBorderOn();
- }
-
- if(gbBorderOn && !gbSgbMask)
- gbSgbRenderBorder();
-
- if(gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) {
- gbSgbCGBSupport = 0;
- gbSgbMode = 0;
- gbSgbMask = 0;
- gbSgbRenderBorder();
- gbReset();
- }
-
- if(gbSgbCGBSupport > 4)
- gbSgbCGBSupport = 0;
-}
-
-void gbSgbSetPalette(int a,int b,u16 *p)
-{
- u16 bit00 = READ16LE(p++);
- int i;
-
- for(i = 1; i < 4; i++) {
- gbPalette[a*4+i] = READ16LE(p++);
- }
-
- for(i = 1; i < 4; i++) {
- gbPalette[b*4+i] = READ16LE(p++);
- }
-
- gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00;
- if(gbBorderOn && !gbSgbMask)
- gbSgbRenderBorder();
-}
-
-void gbSgbScpPalette()
-{
- gbSgbRenderScreenToBuffer();
-
- u16 *fromAddress = (u16 *)gbSgbScreenBuffer;
-
- for(int i = 0; i < 512*4; i++) {
- gbSgbSCPPalette[i] = READ16LE(fromAddress++);
- }
-}
-
-void gbSgbSetATF(int n)
-{
- if(n < 0)
- n = 0;
- if(n > 44)
- n = 44;
- memcpy(gbSgbATF,&gbSgbATFList[n * 20 * 18], 20 * 18);
-
- if(gbSgbPacket[1] & 0x40) {
- gbSgbMask = 0;
- if(gbBorderOn)
- gbSgbRenderBorder();
- }
-}
-
-void gbSgbSetPalette()
-{
- u16 pal = READ16LE((((u16 *)&gbSgbPacket[1])))&511;
- memcpy(&gbPalette[0], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
-
- pal = READ16LE((((u16 *)&gbSgbPacket[3])))&511;
- memcpy(&gbPalette[4], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
-
- pal = READ16LE((((u16 *)&gbSgbPacket[5])))&511;
- memcpy(&gbPalette[8], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
-
- pal = READ16LE((((u16 *)&gbSgbPacket[7])))&511;
- memcpy(&gbPalette[12], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
-
- u8 atf = gbSgbPacket[9];
-
- if(atf & 0x80) {
- gbSgbSetATF(atf & 0x3f);
- }
-
- if(atf & 0x40) {
- gbSgbMask = 0;
- if(gbBorderOn)
- gbSgbRenderBorder();
- }
-}
-
-void gbSgbAttributeBlock()
-{
- u8 *fromAddress = &gbSgbPacket[1];
-
- u8 nDataSet = *fromAddress++;
- if(nDataSet > 12)
- nDataSet = 12;
- if(nDataSet == 0)
- nDataSet = 1;
-
- while(nDataSet) {
- u8 controlCode = (*fromAddress++) & 7;
- u8 paletteDesignation = (*fromAddress++) & 0x3f;
- u8 startH = (*fromAddress++) & 0x1f;
- u8 startV = (*fromAddress++) & 0x1f;
- u8 endH = (*fromAddress++) & 0x1f;
- u8 endV = (*fromAddress++) & 0x1f;
-
- u8 * toAddress = gbSgbATF;
-
- for(u8 y = 0; y < 18; y++) {
- for(u8 x = 0; x < 20; x++) {
- if(x < startH || y < startV ||
- x > endH || y > endV) {
- // outside
- if(controlCode & 0x04)
- *toAddress = (paletteDesignation >> 4) & 0x03;
- } else if(x > startH && x < endH &&
- y > startV && y < endV) {
- // inside
- if(controlCode & 0x01)
- *toAddress = paletteDesignation & 0x03;
- } else {
- // surrounding line
- if(controlCode & 0x02)
- *toAddress = (paletteDesignation>>2) & 0x03;
- else if(controlCode == 0x01)
- *toAddress = paletteDesignation & 0x03;
- }
- toAddress++;
- }
- }
- nDataSet--;
- }
-}
-
-void gbSgbSetColumnPalette(u8 col, u8 p)
-{
- // if(col < 0)
- // col = 0;
- if(col > 19)
- col = 19;
-
- p &= 3;
-
- u8 *toAddress = &gbSgbATF[col];
-
- for(u8 y = 0; y < 18; y++) {
- *toAddress = p;
- toAddress += 20;
- }
-}
-
-void gbSgbSetRowPalette(u8 row, u8 p)
-{
- // if(row < 0)
- // row = 0;
- if(row > 17)
- row = 17;
-
- p &= 3;
-
- u8 *toAddress = &gbSgbATF[row*20];
-
- for(u8 x = 0; x < 20; x++) {
- *toAddress++ = p;
- }
-}
-
-void gbSgbAttributeDivide()
-{
- u8 control = gbSgbPacket[1];
- u8 coord = gbSgbPacket[2];
- u8 colorBR = control & 3;
- u8 colorAL = (control >> 2) & 3;
- u8 colorOL = (control >> 4) & 3;
-
- if(control & 0x40) {
- if(coord > 17)
- coord = 17;
-
- for(u8 i = 0; i < 18; i++) {
- if(i < coord)
- gbSgbSetRowPalette(i, colorAL);
- else if ( i > coord)
- gbSgbSetRowPalette(i, colorBR);
- else
- gbSgbSetRowPalette(i, colorOL);
- }
- } else {
- if(coord > 19)
- coord = 19;
-
- for(u8 i = 0; i < 20; i++) {
- if(i < coord)
- gbSgbSetColumnPalette(i, colorAL);
- else if ( i > coord)
- gbSgbSetColumnPalette(i, colorBR);
- else
- gbSgbSetColumnPalette(i, colorOL);
- }
- }
-}
-
-void gbSgbAttributeLine()
-{
- u8 *fromAddress = &gbSgbPacket[1];
-
- u8 nDataSet = *fromAddress++;
-
- if(nDataSet > 0x6e)
- nDataSet = 0x6e;
-
- while(nDataSet) {
- u8 line = *fromAddress++;
- u8 num = line & 0x1f;
- u8 pal = (line >> 5) & 0x03;
- if(line & 0x80) {
- if(num > 17)
- num = 17;
- gbSgbSetRowPalette(num,pal);
- } else {
- if(num > 19)
- num = 19;
- gbSgbSetColumnPalette(num,pal);
- }
- nDataSet--;
- }
-}
-
-void gbSgbAttributeCharacter()
-{
- u8 startH = gbSgbPacket[1] & 0x1f;
- u8 startV = gbSgbPacket[2] & 0x1f;
- int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3]));
- int style = gbSgbPacket[5] & 1;
- if(startH > 19)
- startH = 19;
- if(startV > 17)
- startV = 17;
-
- u8 s = 6;
- u8 *fromAddress = &gbSgbPacket[6];
- u8 v = *fromAddress++;
-
- if(style) {
- while(nDataSet) {
- u8 p = (v >> s) & 3;
- gbSgbATF[startV * 20 + startH] = p;
- startV++;
- if(startV == 18) {
- startV = 0;
- startH++;
- if(startH == 20)
- break;
- }
-
- if(s)
- s -= 2;
- else {
- s = 6;
- v = *fromAddress++;
- nDataSet--;
- }
- }
- } else {
- while(nDataSet) {
- u8 p = (v >> s) & 3;
- gbSgbATF[startV * 20 + startH] = p;
- startH++;
- if(startH == 20) {
- startH = 0;
- startV++;
- if(startV == 18)
- break;
- }
-
- if(s)
- s -= 2;
- else {
- s = 6;
- v = *fromAddress++;
- nDataSet--;
- }
- }
- }
-}
-
-void gbSgbSetATFList()
-{
- gbSgbRenderScreenToBuffer();
-
- u8 *fromAddress = gbSgbScreenBuffer;
- u8 *toAddress = gbSgbATFList;
-
- for(int i = 0; i < 45; i++) {
- for(int j = 0; j < 90; j++) {
- u8 v = *fromAddress++;
- u8 s = 6;
- if(i == 2)
- s = 6;
- for(int k = 0; k < 4; k++) {
- *toAddress++ = (v >> s) & 0x03;
- s -= 2;
- }
- }
- }
-}
-
-void gbSgbMaskEnable()
-{
- int gbSgbMaskFlag = gbSgbPacket[1] & 3;
-
- gbSgbMask = gbSgbMaskFlag;
-
- switch(gbSgbMaskFlag) {
- case 1:
- break;
- case 2:
- gbSgbFillScreen(0x0000);
- // memset(&gbPalette[0], 0, 128*sizeof(u16));
- break;
- case 3:
- gbSgbFillScreen(gbPalette[0]);
- break;
- }
- if(!gbSgbMask) {
- if(gbBorderOn)
- gbSgbRenderBorder();
- }
-}
-
-void gbSgbChrTransfer()
-{
- gbSgbRenderScreenToBuffer();
-
- int address = (gbSgbPacket[1] & 1) * (128*32);
-
- if(gbSgbPacket[1] & 1)
- gbSgbCGBSupport |= 2;
- else
- gbSgbCGBSupport |= 1;
-
- memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32);
-
- if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) {
- gbBorderOn = 1;
- systemGbBorderOn();
- }
-
- if(gbBorderOn && !gbSgbMask)
- gbSgbRenderBorder();
-
- if(gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) {
- gbSgbCGBSupport = 0;
- gbSgbMode = 0;
- gbSgbMask = 0;
- gbSgbRenderBorder();
- gbReset();
- }
-
- if(gbSgbCGBSupport > 4)
- gbSgbCGBSupport = 0;
-}
-
-void gbSgbMultiRequest()
-{
- if(gbSgbPacket[1] & 1) {
- gbSgbMultiplayer = 1;
- if(gbSgbPacket[1] & 2)
- gbSgbFourPlayers = 1;
- else
- gbSgbFourPlayers = 0;
- gbSgbNextController = 0x0e;
- } else {
- gbSgbFourPlayers = 0;
- gbSgbMultiplayer = 0;
- gbSgbNextController = 0x0f;
- }
-}
-
-void gbSgbCommand()
-{
- int command = gbSgbPacket[0] >> 3;
- // int nPacket = gbSgbPacket[0] & 7;
-
- switch(command) {
- case 0x00:
- gbSgbSetPalette(0,1,(u16 *)&gbSgbPacket[1]);
- break;
- case 0x01:
- gbSgbSetPalette(2,3,(u16 *)&gbSgbPacket[1]);
- break;
- case 0x02:
- gbSgbSetPalette(0,3,(u16 *)&gbSgbPacket[1]);
- break;
- case 0x03:
- gbSgbSetPalette(1,2,(u16 *)&gbSgbPacket[1]);
- break;
- case 0x04:
- gbSgbAttributeBlock();
- break;
- case 0x05:
- gbSgbAttributeLine();
- break;
- case 0x06:
- gbSgbAttributeDivide();
- break;
- case 0x07:
- gbSgbAttributeCharacter();
- break;
- case 0x0a:
- gbSgbSetPalette();
- break;
- case 0x0b:
- gbSgbScpPalette();
- break;
- case 0x11:
- gbSgbMultiRequest();
- break;
- case 0x13:
- gbSgbChrTransfer();
- break;
- case 0x14:
- gbSgbPicture();
- break;
- case 0x15:
- gbSgbSetATFList();
- break;
- case 0x16:
- gbSgbSetATF(gbSgbPacket[1] & 0x3f);
- break;
- case 0x17:
- gbSgbMaskEnable();
- break;
- }
-}
-
-void gbSgbResetPacketState()
-{
- gbSgbPacketState = GBSGB_NONE;
- gbSgbPacketTimeout = 0;
-}
-
-void gbSgbDoBitTransfer(u8 value)
-{
- value = value & 0x30;
- switch(gbSgbPacketState) {
- case GBSGB_NONE:
- if(value == 0) {
- gbSgbPacketState = GBSGB_RESET;
- gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
- } else if (value == 0x30) {
- if(gbSgbMultiplayer) {
- if((gbSgbReadingController & 7) == 7) {
- gbSgbReadingController = 0;
- if(gbSgbMultiplayer) {
- gbSgbNextController--;
- if(gbSgbFourPlayers) {
- if(gbSgbNextController == 0x0b)
- gbSgbNextController = 0x0f;
- } else {
- if(gbSgbNextController == 0x0d)
- gbSgbNextController = 0x0f;
- }
- }
- } else {
- gbSgbReadingController &= 3;
- }
- }
- gbSgbPacketTimeout = 0;
- } else {
- if(value == 0x10)
- gbSgbReadingController |= 0x2;
- else if(value == 0x20)
- gbSgbReadingController |= 0x01;
- gbSgbPacketTimeout = 0;
- }
- gbSgbPacketTimeout = 0;
- break;
- case GBSGB_RESET:
- if(value == 0x30) {
- gbSgbPacketState = GBSGB_PACKET_TRANSMIT;
- gbSgbPacketByte = 0;
- gbSgbPacketNBits = 0;
- gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
- } else if(value == 0x00) {
- gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
- gbSgbPacketState = GBSGB_RESET;
- } else {
- gbSgbPacketState = GBSGB_NONE;
- gbSgbPacketTimeout = 0;
- }
- break;
- case GBSGB_PACKET_TRANSMIT:
- if(value == 0) {
- gbSgbPacketState = GBSGB_RESET;
- gbSgbPacketTimeout = 0;
- } else if (value == 0x30){
- if(gbSgbPacketNBits == 128) {
- gbSgbPacketNBits = 0;
- gbSgbPacketByte = 0;
- gbSgbPacketNumber++;
- gbSgbPacketTimeout = 0;
- if(gbSgbPacketNumber == (gbSgbPacket[0] & 7)) {
- gbSgbCommand();
- gbSgbPacketNumber = 0;
- gbSgbPacketState = GBSGB_NONE;
- gbSgbPacketTimeout = 0;
- }
- } else {
- if(gbSgbPacketNBits < 128) {
- gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1;
- gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit;
- gbSgbPacketNBits++;
- if(!(gbSgbPacketNBits & 7)) {
- gbSgbPacketByte++;
- }
- gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
- }
- }
- } else {
- if(value == 0x20)
- gbSgbBit = 0x00;
- else
- gbSgbBit = 0x80;
- gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
- }
- gbSgbReadingController = 0;
- break;
- default:
- gbSgbPacketState = GBSGB_NONE;
- gbSgbPacketTimeout = 0;
- break;
- }
-}
-
-variable_desc gbSgbSaveStruct[] = {
- { &gbSgbMask, sizeof(int) },
- { &gbSgbPacketState, sizeof(int) },
- { &gbSgbBit, sizeof(int) },
- { &gbSgbPacketNBits, sizeof(int) },
- { &gbSgbPacketByte, sizeof(int) },
- { &gbSgbPacketNumber, sizeof(int) },
- { &gbSgbMultiplayer, sizeof(int) },
- { &gbSgbNextController, sizeof(u8) },
- { &gbSgbReadingController, sizeof(u8) },
- { NULL, 0 }
-};
-
-variable_desc gbSgbSaveStructV3[] = {
- { &gbSgbMask, sizeof(int) },
- { &gbSgbPacketState, sizeof(int) },
- { &gbSgbBit, sizeof(int) },
- { &gbSgbPacketNBits, sizeof(int) },
- { &gbSgbPacketByte, sizeof(int) },
- { &gbSgbPacketNumber, sizeof(int) },
- { &gbSgbMultiplayer, sizeof(int) },
- { &gbSgbNextController, sizeof(u8) },
- { &gbSgbReadingController, sizeof(u8) },
- { &gbSgbFourPlayers, sizeof(int) },
- { NULL, 0 }
-};
-
-void gbSgbSaveGame(gzFile gzFile)
-{
- utilWriteData(gzFile, gbSgbSaveStructV3);
-
- utilGzWrite(gzFile, gbSgbBorder, 2048);
- utilGzWrite(gzFile, gbSgbBorderChar, 32*256);
-
- utilGzWrite(gzFile, gbSgbPacket, 16*7);
-
- utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
- utilGzWrite(gzFile, gbSgbATF, 20 * 18);
- utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18);
-}
-
-void gbSgbReadGame(gzFile gzFile, int version)
-{
- if(version >= 3)
- utilReadData(gzFile, gbSgbSaveStructV3);
- else {
- utilReadData(gzFile, gbSgbSaveStruct);
- gbSgbFourPlayers = 0;
- }
-
- if(version >= 8) {
- utilGzRead(gzFile, gbSgbBorder, 2048);
- utilGzRead(gzFile, gbSgbBorderChar, 32*256);
- }
-
- utilGzRead(gzFile, gbSgbPacket, 16*7);
-
- utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
- utilGzRead(gzFile, gbSgbATF, 20 * 18);
- utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18);
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+#include
+
+#include "../System.h"
+#include "../Port.h"
+#include "../Util.h"
+#include "GB.h"
+#include "gbGlobals.h"
+
+extern u8 *pix;
+extern bool speedup;
+extern bool gbSgbResetFlag;
+
+#define GBSGB_NONE 0
+#define GBSGB_RESET 1
+#define GBSGB_PACKET_TRANSMIT 2
+
+u8 *gbSgbBorderChar = NULL;
+u8 *gbSgbBorder = NULL;
+
+int gbSgbCGBSupport = 0;
+int gbSgbMask = 0;
+int gbSgbMode = 0;
+int gbSgbPacketState = GBSGB_NONE;
+int gbSgbBit = 0;
+int gbSgbPacketTimeout = 0;
+int GBSGB_PACKET_TIMEOUT = 66666;
+u8 gbSgbPacket[16*7];
+int gbSgbPacketNBits = 0;
+int gbSgbPacketByte = 0;
+int gbSgbPacketNumber = 0;
+int gbSgbMultiplayer = 0;
+int gbSgbFourPlayers = 0;
+u8 gbSgbNextController = 0x0f;
+u8 gbSgbReadingController = 0;
+u16 gbSgbSCPPalette[4*512];
+u8 gbSgbATF[20 * 18];
+u8 gbSgbATFList[45 * 20 * 18];
+u8 gbSgbScreenBuffer[4160];
+
+inline void gbSgbDraw24Bit(u8 *p, u16 v)
+{
+ *((u32*) p) = systemColorMap32[v];
+}
+
+inline void gbSgbDraw32Bit(u32 *p, u16 v)
+{
+ *p = systemColorMap32[v];
+}
+
+inline void gbSgbDraw16Bit(u16 *p, u16 v)
+{
+ *p = systemColorMap16[v];
+}
+
+void gbSgbReset()
+{
+ gbSgbPacketTimeout = 0;
+ gbSgbCGBSupport = 0;
+ gbSgbMask = 0;
+ gbSgbPacketState = GBSGB_NONE;
+ gbSgbBit = 0;
+ gbSgbPacketNBits = 0;
+ gbSgbPacketNumber = 0;
+ gbSgbMultiplayer = 0;
+ gbSgbFourPlayers = 0;
+ gbSgbNextController = 0x0f;
+ gbSgbReadingController = 0;
+
+ memset(gbSgbSCPPalette, 0, 512*4);
+ memset(gbSgbATF, 0, 20*18);
+ memset(gbSgbATFList, 0, 45 * 20 * 18);
+ memset(gbSgbPacket, 0, 16 * 7);
+ memset(gbSgbBorderChar, 0, 32*256);
+ memset(gbSgbBorder, 0, 2048);
+
+ int i;
+ for(i = 1; i < 2048; i+=2) {
+ gbSgbBorder[i] = 1 << 2;
+ }
+
+ for(i = 0; i < 32; i++) {
+ gbPalette[i*4] = (0x1f) | (0x1f << 5) | (0x1f << 10);
+ gbPalette[i*4+1] = (0x15) | (0x15 << 5) | (0x15 << 10);
+ gbPalette[i*4+2] = (0x0c) | (0x0c << 5) | (0x0c << 10);
+ gbPalette[i*4+3] = 0;
+ }
+}
+
+void gbSgbInit()
+{
+ gbSgbBorderChar = (u8 *)malloc(32 * 256);
+ gbSgbBorder = (u8 *)malloc(2048);
+
+ gbSgbReset();
+}
+
+void gbSgbShutdown()
+{
+ if(gbSgbBorderChar != NULL) {
+ free(gbSgbBorderChar);
+ gbSgbBorderChar = NULL;
+ }
+
+ if(gbSgbBorder != NULL) {
+ free(gbSgbBorder);
+ gbSgbBorder = NULL;
+ }
+}
+
+void gbSgbFillScreen(u16 color)
+{
+ switch(systemColorDepth) {
+ case 16:
+ {
+ for(int y = 0; y < 144; y++) {
+ int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+2) +
+ gbBorderColumnSkip;
+ u16 *dest = (u16*)pix + yLine;
+ for(register int x = 0; x < 160; x++)
+ gbSgbDraw16Bit(dest++, color);
+ }
+ }
+ break;
+ case 24:
+ {
+ for(int y = 0; y < 144; y++) {
+ int yLine = (y+gbBorderRowSkip)*gbBorderLineSkip + gbBorderColumnSkip;
+ u8 *dest = (u8 *)pix + yLine*3;
+ for(register int x = 0; x < 160; x++) {
+ gbSgbDraw24Bit(dest, color);
+ dest += 3;
+ }
+ }
+ }
+ break;
+ case 32:
+ {
+ for(int y = 0; y < 144; y++) {
+ int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+1) + gbBorderColumnSkip;
+ u32 *dest = (u32 *)pix + yLine;
+ for(register int x = 0; x < 160; x++) {
+ gbSgbDraw32Bit(dest++, color);
+ }
+ }
+ }
+ break;
+ }
+}
+
+#define getmem(x) gbMemoryMap[(x) >> 12][(x) & 0xfff]
+
+void gbSgbRenderScreenToBuffer()
+{
+ u16 mapAddress = 0x9800;
+
+ if(register_LCDC & 0x08)
+ mapAddress = 0x9c00;
+
+ u16 patternAddress = 0x8800;
+
+ int flag = 1;
+
+ if(register_LCDC & 0x10) {
+ patternAddress = 0x8000;
+ flag = 0;
+ }
+
+ u8 *toAddress = gbSgbScreenBuffer;
+
+ for(int i = 0; i < 13; i++) {
+ for(int j = 0; j < 20; j++) {
+ int tile = getmem(mapAddress);
+ mapAddress++;
+
+ if(flag) {
+ if(tile > 127)
+ tile -= 128;
+ else
+ tile += 128;
+ }
+ for(int k = 0; k < 16; k++)
+ *toAddress++ = getmem(patternAddress + tile*16 + k);
+ }
+ mapAddress += 12;
+ }
+}
+
+void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
+{
+ u16 *dest = (u16*)pix + ((y+1) * (256+2)) + x;
+ u8 *dest8 = (u8*)pix + ((y*256)+x)*3;
+ u32 *dest32 = (u32*)pix + ((y+1)*257) + x;
+
+ u8 *tileAddress = &gbSgbBorderChar[tile * 32];
+ u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
+
+ u8 l = 8;
+
+ u8 palette = ((attr >> 2 ) & 7);
+
+ if(palette < 4)
+ palette += 4;
+
+ palette *= 16;
+
+ u8 xx = 0;
+ u8 yy = 0;
+
+ int flipX = attr & 0x40;
+ int flipY = attr & 0x80;
+
+ while(l > 0) {
+ u8 mask = 0x80;
+ u8 a = *tileAddress++;
+ u8 b = *tileAddress++;
+ u8 c = *tileAddress2++;
+ u8 d = *tileAddress2++;
+
+ while(mask > 0) {
+
+ u8 color = 0;
+ if(a & mask)
+ color++;
+ if(b & mask)
+ color+=2;
+ if(c & mask)
+ color+=4;
+ if(d & mask)
+ color+=8;
+
+ u8 xxx = xx;
+ u8 yyy = yy;
+
+ if(flipX)
+ xxx = 7 - xx;
+ if(flipY)
+ yyy = 7 - yy;
+
+ u16 c = gbPalette[palette + color];
+
+ // Fix for Super Snaky ???
+ // (it allows SGB borders to not redraw on the GB screen)
+ //if(!color)
+ // c = gbPalette[0];
+ if(((yy < 40 || yy >= 184) || (xx < 48 || xx >= 208)) && (color || (gbSgbResetFlag == true))) {
+ switch(systemColorDepth) {
+ case 16:
+ gbSgbDraw16Bit(dest + yyy*(256+2) + xxx, c);
+ break;
+ case 24:
+ gbSgbDraw24Bit(dest8 + (yyy*256+xxx)*3, c);
+ break;
+ case 32:
+ gbSgbDraw32Bit(dest32 + yyy*(256+1)+xxx, c);
+ break;
+ }
+ }
+
+ mask >>= 1;
+
+ xx++;
+ }
+ yy++;
+ xx = 0;
+ l--;
+ mask = 0x80;
+ }
+}
+
+void gbSgbRenderBorder()
+{
+ if(gbBorderOn) {
+ u8 *fromAddress = gbSgbBorder;
+
+ for(u8 y = 0; y < 28; y++) {
+ for(u8 x = 0; x< 32; x++) {
+ u8 tile = *fromAddress++;
+ u8 attr = *fromAddress++;
+
+ gbSgbDrawBorderTile(x*8,y*8,tile,attr);
+ }
+ }
+ }
+}
+
+void gbSgbPicture()
+{
+ gbSgbRenderScreenToBuffer();
+
+ memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048);
+
+ u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048];
+
+ for(int i = 64; i < 128; i++) {
+ gbPalette[i] = READ16LE(paletteAddr++);
+ }
+
+ gbSgbCGBSupport |= 4;
+
+ if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) {
+ gbBorderOn = 1;
+ systemGbBorderOn();
+ }
+
+ if(gbBorderOn && !gbSgbMask)
+ gbSgbRenderBorder();
+
+ if(gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) {
+ gbSgbCGBSupport = 0;
+ gbSgbMode = 0;
+ gbSgbMask = 0;
+ gbSgbRenderBorder();
+ gbReset();
+ }
+
+ if(gbSgbCGBSupport > 4)
+ gbSgbCGBSupport = 0;
+}
+
+void gbSgbSetPalette(int a,int b,u16 *p)
+{
+ u16 bit00 = READ16LE(p++);
+ int i;
+
+ for(i = 1; i < 4; i++) {
+ gbPalette[a*4+i] = READ16LE(p++);
+ }
+
+ for(i = 1; i < 4; i++) {
+ gbPalette[b*4+i] = READ16LE(p++);
+ }
+
+ gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00;
+ if(gbBorderOn && !gbSgbMask)
+ gbSgbRenderBorder();
+}
+
+void gbSgbScpPalette()
+{
+ gbSgbRenderScreenToBuffer();
+
+ u16 *fromAddress = (u16 *)gbSgbScreenBuffer;
+
+ for(int i = 0; i < 512*4; i++) {
+ gbSgbSCPPalette[i] = READ16LE(fromAddress++);
+ }
+}
+
+void gbSgbSetATF(int n)
+{
+ if(n < 0)
+ n = 0;
+ if(n > 44)
+ n = 44;
+ memcpy(gbSgbATF,&gbSgbATFList[n * 20 * 18], 20 * 18);
+
+ if(gbSgbPacket[1] & 0x40) {
+ gbSgbMask = 0;
+ if(gbBorderOn)
+ gbSgbRenderBorder();
+ }
+}
+
+void gbSgbSetPalette()
+{
+ u16 pal = READ16LE((((u16 *)&gbSgbPacket[1])))&511;
+ memcpy(&gbPalette[0], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
+
+ pal = READ16LE((((u16 *)&gbSgbPacket[3])))&511;
+ memcpy(&gbPalette[4], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
+
+ pal = READ16LE((((u16 *)&gbSgbPacket[5])))&511;
+ memcpy(&gbPalette[8], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
+
+ pal = READ16LE((((u16 *)&gbSgbPacket[7])))&511;
+ memcpy(&gbPalette[12], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16));
+
+ u8 atf = gbSgbPacket[9];
+
+ if(atf & 0x80) {
+ gbSgbSetATF(atf & 0x3f);
+ }
+
+ if(atf & 0x40) {
+ gbSgbMask = 0;
+ if(gbBorderOn)
+ gbSgbRenderBorder();
+ }
+}
+
+void gbSgbAttributeBlock()
+{
+ u8 *fromAddress = &gbSgbPacket[1];
+
+ u8 nDataSet = *fromAddress++;
+ if(nDataSet > 12)
+ nDataSet = 12;
+ if(nDataSet == 0)
+ nDataSet = 1;
+
+ while(nDataSet) {
+ u8 controlCode = (*fromAddress++) & 7;
+ u8 paletteDesignation = (*fromAddress++) & 0x3f;
+ u8 startH = (*fromAddress++) & 0x1f;
+ u8 startV = (*fromAddress++) & 0x1f;
+ u8 endH = (*fromAddress++) & 0x1f;
+ u8 endV = (*fromAddress++) & 0x1f;
+
+ u8 * toAddress = gbSgbATF;
+
+ for(u8 y = 0; y < 18; y++) {
+ for(u8 x = 0; x < 20; x++) {
+ if(x < startH || y < startV ||
+ x > endH || y > endV) {
+ // outside
+ if(controlCode & 0x04)
+ *toAddress = (paletteDesignation >> 4) & 0x03;
+ } else if(x > startH && x < endH &&
+ y > startV && y < endV) {
+ // inside
+ if(controlCode & 0x01)
+ *toAddress = paletteDesignation & 0x03;
+ } else {
+ // surrounding line
+ if(controlCode & 0x02)
+ *toAddress = (paletteDesignation>>2) & 0x03;
+ else if(controlCode == 0x01)
+ *toAddress = paletteDesignation & 0x03;
+ }
+ toAddress++;
+ }
+ }
+ nDataSet--;
+ }
+}
+
+void gbSgbSetColumnPalette(u8 col, u8 p)
+{
+ // if(col < 0)
+ // col = 0;
+ if(col > 19)
+ col = 19;
+
+ p &= 3;
+
+ u8 *toAddress = &gbSgbATF[col];
+
+ for(u8 y = 0; y < 18; y++) {
+ *toAddress = p;
+ toAddress += 20;
+ }
+}
+
+void gbSgbSetRowPalette(u8 row, u8 p)
+{
+ // if(row < 0)
+ // row = 0;
+ if(row > 17)
+ row = 17;
+
+ p &= 3;
+
+ u8 *toAddress = &gbSgbATF[row*20];
+
+ for(u8 x = 0; x < 20; x++) {
+ *toAddress++ = p;
+ }
+}
+
+void gbSgbAttributeDivide()
+{
+ u8 control = gbSgbPacket[1];
+ u8 coord = gbSgbPacket[2];
+ u8 colorBR = control & 3;
+ u8 colorAL = (control >> 2) & 3;
+ u8 colorOL = (control >> 4) & 3;
+
+ if(control & 0x40) {
+ if(coord > 17)
+ coord = 17;
+
+ for(u8 i = 0; i < 18; i++) {
+ if(i < coord)
+ gbSgbSetRowPalette(i, colorAL);
+ else if ( i > coord)
+ gbSgbSetRowPalette(i, colorBR);
+ else
+ gbSgbSetRowPalette(i, colorOL);
+ }
+ } else {
+ if(coord > 19)
+ coord = 19;
+
+ for(u8 i = 0; i < 20; i++) {
+ if(i < coord)
+ gbSgbSetColumnPalette(i, colorAL);
+ else if ( i > coord)
+ gbSgbSetColumnPalette(i, colorBR);
+ else
+ gbSgbSetColumnPalette(i, colorOL);
+ }
+ }
+}
+
+void gbSgbAttributeLine()
+{
+ u8 *fromAddress = &gbSgbPacket[1];
+
+ u8 nDataSet = *fromAddress++;
+
+ if(nDataSet > 0x6e)
+ nDataSet = 0x6e;
+
+ while(nDataSet) {
+ u8 line = *fromAddress++;
+ u8 num = line & 0x1f;
+ u8 pal = (line >> 5) & 0x03;
+ if(line & 0x80) {
+ if(num > 17)
+ num = 17;
+ gbSgbSetRowPalette(num,pal);
+ } else {
+ if(num > 19)
+ num = 19;
+ gbSgbSetColumnPalette(num,pal);
+ }
+ nDataSet--;
+ }
+}
+
+void gbSgbAttributeCharacter()
+{
+ u8 startH = gbSgbPacket[1] & 0x1f;
+ u8 startV = gbSgbPacket[2] & 0x1f;
+ int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3]));
+ int style = gbSgbPacket[5] & 1;
+ if(startH > 19)
+ startH = 19;
+ if(startV > 17)
+ startV = 17;
+
+ u8 s = 6;
+ u8 *fromAddress = &gbSgbPacket[6];
+ u8 v = *fromAddress++;
+
+ if(style) {
+ while(nDataSet) {
+ u8 p = (v >> s) & 3;
+ gbSgbATF[startV * 20 + startH] = p;
+ startV++;
+ if(startV == 18) {
+ startV = 0;
+ startH++;
+ if(startH == 20)
+ break;
+ }
+
+ if(s)
+ s -= 2;
+ else {
+ s = 6;
+ v = *fromAddress++;
+ nDataSet--;
+ }
+ }
+ } else {
+ while(nDataSet) {
+ u8 p = (v >> s) & 3;
+ gbSgbATF[startV * 20 + startH] = p;
+ startH++;
+ if(startH == 20) {
+ startH = 0;
+ startV++;
+ if(startV == 18)
+ break;
+ }
+
+ if(s)
+ s -= 2;
+ else {
+ s = 6;
+ v = *fromAddress++;
+ nDataSet--;
+ }
+ }
+ }
+}
+
+void gbSgbSetATFList()
+{
+ gbSgbRenderScreenToBuffer();
+
+ u8 *fromAddress = gbSgbScreenBuffer;
+ u8 *toAddress = gbSgbATFList;
+
+ for(int i = 0; i < 45; i++) {
+ for(int j = 0; j < 90; j++) {
+ u8 v = *fromAddress++;
+ u8 s = 6;
+ if(i == 2)
+ s = 6;
+ for(int k = 0; k < 4; k++) {
+ *toAddress++ = (v >> s) & 0x03;
+ s -= 2;
+ }
+ }
+ }
+}
+
+void gbSgbMaskEnable()
+{
+ int gbSgbMaskFlag = gbSgbPacket[1] & 3;
+
+ gbSgbMask = gbSgbMaskFlag;
+
+ switch(gbSgbMaskFlag) {
+ case 1:
+ break;
+ case 2:
+ gbSgbFillScreen(0x0000);
+ // memset(&gbPalette[0], 0, 128*sizeof(u16));
+ break;
+ case 3:
+ gbSgbFillScreen(gbPalette[0]);
+ break;
+ }
+ if(!gbSgbMask) {
+ if(gbBorderOn)
+ gbSgbRenderBorder();
+ }
+}
+
+void gbSgbChrTransfer()
+{
+ gbSgbRenderScreenToBuffer();
+
+ int address = (gbSgbPacket[1] & 1) * (128*32);
+
+ if(gbSgbPacket[1] & 1)
+ gbSgbCGBSupport |= 2;
+ else
+ gbSgbCGBSupport |= 1;
+
+ memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32);
+
+ if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) {
+ gbBorderOn = 1;
+ systemGbBorderOn();
+ }
+
+ if(gbBorderOn && !gbSgbMask)
+ gbSgbRenderBorder();
+
+ if(gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) {
+ gbSgbCGBSupport = 0;
+ gbSgbMode = 0;
+ gbSgbMask = 0;
+ gbSgbRenderBorder();
+ gbReset();
+ }
+
+ if(gbSgbCGBSupport > 4)
+ gbSgbCGBSupport = 0;
+}
+
+void gbSgbMultiRequest()
+{
+ if(gbSgbPacket[1] & 1) {
+ gbSgbMultiplayer = 1;
+ if(gbSgbPacket[1] & 2)
+ gbSgbFourPlayers = 1;
+ else
+ gbSgbFourPlayers = 0;
+ gbSgbNextController = 0x0e;
+ } else {
+ gbSgbFourPlayers = 0;
+ gbSgbMultiplayer = 0;
+ gbSgbNextController = 0x0f;
+ }
+}
+
+void gbSgbCommand()
+{
+ int command = gbSgbPacket[0] >> 3;
+ // int nPacket = gbSgbPacket[0] & 7;
+
+ switch(command) {
+ case 0x00:
+ gbSgbSetPalette(0,1,(u16 *)&gbSgbPacket[1]);
+ break;
+ case 0x01:
+ gbSgbSetPalette(2,3,(u16 *)&gbSgbPacket[1]);
+ break;
+ case 0x02:
+ gbSgbSetPalette(0,3,(u16 *)&gbSgbPacket[1]);
+ break;
+ case 0x03:
+ gbSgbSetPalette(1,2,(u16 *)&gbSgbPacket[1]);
+ break;
+ case 0x04:
+ gbSgbAttributeBlock();
+ break;
+ case 0x05:
+ gbSgbAttributeLine();
+ break;
+ case 0x06:
+ gbSgbAttributeDivide();
+ break;
+ case 0x07:
+ gbSgbAttributeCharacter();
+ break;
+ case 0x0a:
+ gbSgbSetPalette();
+ break;
+ case 0x0b:
+ gbSgbScpPalette();
+ break;
+ case 0x11:
+ gbSgbMultiRequest();
+ break;
+ case 0x13:
+ gbSgbChrTransfer();
+ break;
+ case 0x14:
+ gbSgbPicture();
+ break;
+ case 0x15:
+ gbSgbSetATFList();
+ break;
+ case 0x16:
+ gbSgbSetATF(gbSgbPacket[1] & 0x3f);
+ break;
+ case 0x17:
+ gbSgbMaskEnable();
+ break;
+ }
+}
+
+void gbSgbResetPacketState()
+{
+ gbSgbPacketState = GBSGB_NONE;
+ gbSgbPacketTimeout = 0;
+}
+
+void gbSgbDoBitTransfer(u8 value)
+{
+ value = value & 0x30;
+ switch(gbSgbPacketState) {
+ case GBSGB_NONE:
+ if(value == 0) {
+ gbSgbPacketState = GBSGB_RESET;
+ gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
+ } else if (value == 0x30) {
+ if(gbSgbMultiplayer) {
+ if((gbSgbReadingController & 7) == 7) {
+ gbSgbReadingController = 0;
+ if(gbSgbMultiplayer) {
+ gbSgbNextController--;
+ if(gbSgbFourPlayers) {
+ if(gbSgbNextController == 0x0b)
+ gbSgbNextController = 0x0f;
+ } else {
+ if(gbSgbNextController == 0x0d)
+ gbSgbNextController = 0x0f;
+ }
+ }
+ } else {
+ gbSgbReadingController &= 3;
+ }
+ }
+ gbSgbPacketTimeout = 0;
+ } else {
+ if(value == 0x10)
+ gbSgbReadingController |= 0x2;
+ else if(value == 0x20)
+ gbSgbReadingController |= 0x01;
+ gbSgbPacketTimeout = 0;
+ }
+ gbSgbPacketTimeout = 0;
+ break;
+ case GBSGB_RESET:
+ if(value == 0x30) {
+ gbSgbPacketState = GBSGB_PACKET_TRANSMIT;
+ gbSgbPacketByte = 0;
+ gbSgbPacketNBits = 0;
+ gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
+ } else if(value == 0x00) {
+ gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
+ gbSgbPacketState = GBSGB_RESET;
+ } else {
+ gbSgbPacketState = GBSGB_NONE;
+ gbSgbPacketTimeout = 0;
+ }
+ break;
+ case GBSGB_PACKET_TRANSMIT:
+ if(value == 0) {
+ gbSgbPacketState = GBSGB_RESET;
+ gbSgbPacketTimeout = 0;
+ } else if (value == 0x30){
+ if(gbSgbPacketNBits == 128) {
+ gbSgbPacketNBits = 0;
+ gbSgbPacketByte = 0;
+ gbSgbPacketNumber++;
+ gbSgbPacketTimeout = 0;
+ if(gbSgbPacketNumber == (gbSgbPacket[0] & 7)) {
+ gbSgbCommand();
+ gbSgbPacketNumber = 0;
+ gbSgbPacketState = GBSGB_NONE;
+ gbSgbPacketTimeout = 0;
+ }
+ } else {
+ if(gbSgbPacketNBits < 128) {
+ gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1;
+ gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit;
+ gbSgbPacketNBits++;
+ if(!(gbSgbPacketNBits & 7)) {
+ gbSgbPacketByte++;
+ }
+ gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
+ }
+ }
+ } else {
+ if(value == 0x20)
+ gbSgbBit = 0x00;
+ else
+ gbSgbBit = 0x80;
+ gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
+ }
+ gbSgbReadingController = 0;
+ break;
+ default:
+ gbSgbPacketState = GBSGB_NONE;
+ gbSgbPacketTimeout = 0;
+ break;
+ }
+}
+
+variable_desc gbSgbSaveStruct[] = {
+ { &gbSgbMask, sizeof(int) },
+ { &gbSgbPacketState, sizeof(int) },
+ { &gbSgbBit, sizeof(int) },
+ { &gbSgbPacketNBits, sizeof(int) },
+ { &gbSgbPacketByte, sizeof(int) },
+ { &gbSgbPacketNumber, sizeof(int) },
+ { &gbSgbMultiplayer, sizeof(int) },
+ { &gbSgbNextController, sizeof(u8) },
+ { &gbSgbReadingController, sizeof(u8) },
+ { NULL, 0 }
+};
+
+variable_desc gbSgbSaveStructV3[] = {
+ { &gbSgbMask, sizeof(int) },
+ { &gbSgbPacketState, sizeof(int) },
+ { &gbSgbBit, sizeof(int) },
+ { &gbSgbPacketNBits, sizeof(int) },
+ { &gbSgbPacketByte, sizeof(int) },
+ { &gbSgbPacketNumber, sizeof(int) },
+ { &gbSgbMultiplayer, sizeof(int) },
+ { &gbSgbNextController, sizeof(u8) },
+ { &gbSgbReadingController, sizeof(u8) },
+ { &gbSgbFourPlayers, sizeof(int) },
+ { NULL, 0 }
+};
+
+void gbSgbSaveGame(gzFile gzFile)
+{
+ utilWriteData(gzFile, gbSgbSaveStructV3);
+
+ utilGzWrite(gzFile, gbSgbBorder, 2048);
+ utilGzWrite(gzFile, gbSgbBorderChar, 32*256);
+
+ utilGzWrite(gzFile, gbSgbPacket, 16*7);
+
+ utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
+ utilGzWrite(gzFile, gbSgbATF, 20 * 18);
+ utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18);
+}
+
+void gbSgbReadGame(gzFile gzFile, int version)
+{
+ if(version >= 3)
+ utilReadData(gzFile, gbSgbSaveStructV3);
+ else {
+ utilReadData(gzFile, gbSgbSaveStruct);
+ gbSgbFourPlayers = 0;
+ }
+
+ if(version >= 8) {
+ utilGzRead(gzFile, gbSgbBorder, 2048);
+ utilGzRead(gzFile, gbSgbBorderChar, 32*256);
+ }
+
+ utilGzRead(gzFile, gbSgbPacket, 16*7);
+
+ utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
+ utilGzRead(gzFile, gbSgbATF, 20 * 18);
+ utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18);
+}
diff --git a/src/gb/gbSound.cpp b/src/gb/gbSound.cpp
index 4d018e44..0a0685b4 100644
--- a/src/gb/gbSound.cpp
+++ b/src/gb/gbSound.cpp
@@ -1,525 +1,1032 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include
-
-#include "../System.h"
-#include "../Util.h"
-#include "gbGlobals.h"
-#include "gbSound.h"
-
-#include "../Gb_Apu/Multi_Buffer.h"
-#include "../Gb_Apu/Gb_Apu.h"
-
-extern u8 soundBuffer[6][735];
-extern u16 soundFinalWave[1470];
-extern int soundVolume;
-
-#define SOUND_MAGIC 0x60000000
-#define SOUND_MAGIC_2 0x30000000
-#define NOISE_MAGIC 5
-
-extern int speed;
-
-extern void soundResume();
-
-extern u8 soundWavePattern[4][32];
-
-extern int soundBufferLen;
-extern int soundBufferTotalLen;
-extern int soundQuality;
-extern bool soundPaused;
-extern int soundPlay;
-extern int soundTicks;
-extern int SOUND_CLOCK_TICKS;
-extern u32 soundNextPosition;
-
-extern int soundLevel1;
-extern int soundLevel2;
-extern int soundBalance;
-extern int soundMasterOn;
-extern int soundIndex;
-extern int soundBufferIndex;
-int soundVIN = 0;
-extern int soundDebug;
-
-extern Multi_Buffer * apu_out;
-extern Gb_Apu * apu;
-
-extern int sound1On;
-extern int sound1ATL;
-extern int sound1Skip;
-extern int sound1Index;
-extern int sound1Continue;
-extern int sound1EnvelopeVolume;
-extern int sound1EnvelopeATL;
-extern int sound1EnvelopeUpDown;
-extern int sound1EnvelopeATLReload;
-extern int sound1SweepATL;
-extern int sound1SweepATLReload;
-extern int sound1SweepSteps;
-extern int sound1SweepUpDown;
-extern int sound1SweepStep;
-extern u8 *sound1Wave;
-
-extern int sound2On;
-extern int sound2ATL;
-extern int sound2Skip;
-extern int sound2Index;
-extern int sound2Continue;
-extern int sound2EnvelopeVolume;
-extern int sound2EnvelopeATL;
-extern int sound2EnvelopeUpDown;
-extern int sound2EnvelopeATLReload;
-extern u8 *sound2Wave;
-
-extern int sound3On;
-extern int sound3ATL;
-extern int sound3Skip;
-extern int sound3Index;
-extern int sound3Continue;
-extern int sound3OutputLevel;
-extern int sound3Last;
-
-extern int sound4On;
-extern int sound4Clock;
-extern int sound4ATL;
-extern int sound4Skip;
-extern int sound4Index;
-extern int sound4ShiftRight;
-extern int sound4ShiftSkip;
-extern int sound4ShiftIndex;
-extern int sound4NSteps;
-extern int sound4CountDown;
-extern int sound4Continue;
-extern int sound4EnvelopeVolume;
-extern int sound4EnvelopeATL;
-extern int sound4EnvelopeUpDown;
-extern int sound4EnvelopeATLReload;
-
-extern int soundEnableFlag;
-
-extern int soundFreqRatio[8];
-extern int soundShiftClock[16];
-
-extern s16 soundFilter[4000];
-extern s16 soundLeft[5];
-extern s16 soundRight[5];
-extern int soundEchoIndex;
-extern bool soundEcho;
-extern bool soundLowPass;
-extern bool soundReverse;
-extern bool soundOffFlag;
-
-u8 gbSoundRead(u16 address)
-{
- if (address < NR10 || address > 0xFF3F || !apu) return gbMemory[address];
- if (address == NR51) return soundBalance;
-
- int clock = (SOUND_CLOCK_TICKS - soundTicks) * 95 / (24 * (gbSpeed ? 2 : 1));
-
- int ret = apu->read_register(clock, address);
-
- switch ( address )
- {
- case NR10:
- ret |= 0x80; break;
-
- case NR11:
- case NR21:
- ret |= 0x3F; break;
-
- case NR13:
- case NR23:
- case NR31:
- case NR33:
- ret = 0xFF; break;
-
- case NR14:
- case NR24:
- case NR34:
- case NR44:
- ret |= 0xBF; break;
-
- case NR30:
- ret |= 0x7F; break;
-
- case NR32:
- ret |= 0x9F; break;
- }
-
- return ret;
-}
-
-void gbSoundEvent(register u16 address, register int data)
-{
- int freq = 0;
-
- gbMemory[address] = data;
-
-#ifndef FINAL_VERSION
- if(soundDebug) {
- // don't translate. debug only
- log("Sound event: %08lx %02x\n", address, data);
- }
-#endif
- if (apu && address >= NR10 && address <= 0xFF3F)
- {
- int clock = (SOUND_CLOCK_TICKS - soundTicks) * 95 / (24 * (gbSpeed ? 2 : 1));
- if (address == NR50)
- {
- apu->write_register(clock, address, data);
- }
- else if (address == NR51)
- {
- soundBalance = data;
- apu->write_register(clock, address, data & soundEnableFlag);
- }
- else
- apu->write_register(clock, address, data);
- }
-}
-
- void gbSoundChannel1()
-{
-}
-
-void gbSoundChannel2()
-{
-}
-
-void gbSoundChannel3()
-{
-}
-
-void gbSoundChannel4()
-{
-}
-
-void gbSoundMix()
-{
- int res = 0;
-
- blip_sample_t out[2] = {0, 0};
-
- if ( ! apu_out ) return;
-
- while (!apu_out->read_samples(&out[0], 2))
- {
- int ticks = SOUND_CLOCK_TICKS * 95 / (24 * (gbSpeed ? 2 : 1));
- bool was_stereo = apu->end_frame( ticks );
- apu_out->end_frame( ticks, was_stereo );
- }
-
- res = out[0];
-
- //res = (res * 7 * 60) >> 8;
-
-
- if(soundEcho) {
- res *= 2;
- res += soundFilter[soundEchoIndex];
- res /= 2;
- soundFilter[soundEchoIndex++] = res;
- }
-
- if(soundLowPass) {
- soundLeft[4] = soundLeft[3];
- soundLeft[3] = soundLeft[2];
- soundLeft[2] = soundLeft[1];
- soundLeft[1] = soundLeft[0];
- soundLeft[0] = res;
- res = (soundLeft[4] + 2*soundLeft[3] + 8*soundLeft[2] + 2*soundLeft[1] +
- soundLeft[0])/14;
- }
-
- switch(soundVolume) {
- case 0:
- case 1:
- case 2:
- case 3:
- res *= (soundVolume+1);
- break;
- case 4:
- res >>= 2;
- break;
- case 5:
- res >>= 1;
- break;
- }
-
- if(res > 32767)
- res = 32767;
- if(res < -32768)
- res = -32768;
-
- if(soundReverse)
- soundFinalWave[++soundBufferIndex] = res;
- else
- soundFinalWave[soundBufferIndex++] = res;
-
- res = out[1];
-
- if(soundEcho) {
- res *= 2;
- res += soundFilter[soundEchoIndex];
- res /= 2;
- soundFilter[soundEchoIndex++] = res;
-
- if(soundEchoIndex >= 4000)
- soundEchoIndex = 0;
- }
-
- if(soundLowPass) {
- soundRight[4] = soundRight[3];
- soundRight[3] = soundRight[2];
- soundRight[2] = soundRight[1];
- soundRight[1] = soundRight[0];
- soundRight[0] = res;
- res = (soundRight[4] + 2*soundRight[3] + 8*soundRight[2] + 2*soundRight[1] +
- soundRight[0])/14;
- }
-
- switch(soundVolume) {
- case 0:
- case 1:
- case 2:
- case 3:
- res *= (soundVolume+1);
- break;
- case 4:
- res >>= 2;
- break;
- case 5:
- res >>= 1;
- break;
- }
-
- if(res > 32767)
- res = 32767;
- if(res < -32768)
- res = -32768;
-
- if(soundReverse)
- soundFinalWave[-1+soundBufferIndex++] = res;
- else
- soundFinalWave[soundBufferIndex++] = res;
-}
-
-void gbSoundTick()
-{
- if(systemSoundOn) {
- if(soundMasterOn) {
- /*gbSoundChannel1();
- gbSoundChannel2();
- gbSoundChannel3();
- gbSoundChannel4();*/
-
- gbSoundMix();
- } else {
- soundFinalWave[soundBufferIndex++] = 0;
- soundFinalWave[soundBufferIndex++] = 0;
- }
-
- soundIndex++;
-
- if(2*soundBufferIndex >= soundBufferLen) {
- if(systemSoundOn) {
- if(soundPaused) {
- soundResume();
- }
-
- systemWriteDataToSoundBuffer();
- }
- soundIndex = 0;
- soundBufferIndex = 0;
- }
- }
-}
-
-void gbSoundReset()
-{
- soundPaused = 1;
- soundPlay = 0;
- SOUND_CLOCK_TICKS = soundQuality * 24;
- soundTicks = SOUND_CLOCK_TICKS;
- soundNextPosition = 0;
- soundMasterOn = 1;
- soundIndex = 0;
- soundBufferIndex = 0;
- soundLevel1 = 7;
- soundLevel2 = 7;
- soundVIN = 0;
-
-
- // don't translate
- if(soundDebug) {
- log("*** Sound Init ***\n");
- }
-
-
- if (apu_out)
- {
- apu_out->clear();
- apu->reset(false);
-
- extern const BOOST::uint8_t sound_data[Gb_Apu::end_addr - Gb_Apu::start_addr + 1];
-
- int addr = 0;
-
- while (addr < 0x30) {
- apu->write_register( 0, 0xFF10 + addr, sound_data [ addr ] );
- addr++;
- }
- }
- // don't translate
- if(soundDebug) {
- log("*** Sound Init Complete ***\n");
- }
-
- if (apu)
- {
- int addr = 0xff30;
-
- while(addr < 0xff40) {
- /*gbMemory[addr++] = 0x00;
- gbMemory[addr++] = 0xff;*/
- gbSoundEvent(addr++, 0x00);
- gbSoundEvent(addr++, 0xFF);
- }
- }
-
- memset(soundFinalWave, 0x00, soundBufferLen);
-
-
- memset(soundFilter, 0, sizeof(soundFilter));
- soundEchoIndex = 0;
-}
-
-extern bool soundInit(bool gba = true);
-extern void soundShutdown();
-
-void gbSoundSetQuality(int quality)
-{
- if(soundQuality != quality && systemCanChangeSoundQuality()) {
- if(!soundOffFlag)
- soundShutdown();
- soundQuality = quality;
- soundNextPosition = 0;
- if(!soundOffFlag)
- soundInit(false);
- SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
- soundIndex = 0;
- soundBufferIndex = 0;
- } else {
- soundNextPosition = 0;
- SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
- soundIndex = 0;
- soundBufferIndex = 0;
- }
-}
-
-variable_desc gbSoundSaveStruct[] = {
- { &soundPaused, sizeof(int) },
- { &soundPlay, sizeof(int) },
- { &soundTicks, sizeof(int) },
- { &SOUND_CLOCK_TICKS, sizeof(int) },
- { &soundLevel1, sizeof(int) },
- { &soundLevel2, sizeof(int) },
- { &soundBalance, sizeof(int) },
- { &soundMasterOn, sizeof(int) },
- { &soundIndex, sizeof(int) },
- { &soundVIN, sizeof(int) },
- { &sound1On, sizeof(int) },
- { &sound1ATL, sizeof(int) },
- { &sound1Skip, sizeof(int) },
- { &sound1Index, sizeof(int) },
- { &sound1Continue, sizeof(int) },
- { &sound1EnvelopeVolume, sizeof(int) },
- { &sound1EnvelopeATL, sizeof(int) },
- { &sound1EnvelopeATLReload, sizeof(int) },
- { &sound1EnvelopeUpDown, sizeof(int) },
- { &sound1SweepATL, sizeof(int) },
- { &sound1SweepATLReload, sizeof(int) },
- { &sound1SweepSteps, sizeof(int) },
- { &sound1SweepUpDown, sizeof(int) },
- { &sound1SweepStep, sizeof(int) },
- { &sound2On, sizeof(int) },
- { &sound2ATL, sizeof(int) },
- { &sound2Skip, sizeof(int) },
- { &sound2Index, sizeof(int) },
- { &sound2Continue, sizeof(int) },
- { &sound2EnvelopeVolume, sizeof(int) },
- { &sound2EnvelopeATL, sizeof(int) },
- { &sound2EnvelopeATLReload, sizeof(int) },
- { &sound2EnvelopeUpDown, sizeof(int) },
- { &sound3On, sizeof(int) },
- { &sound3ATL, sizeof(int) },
- { &sound3Skip, sizeof(int) },
- { &sound3Index, sizeof(int) },
- { &sound3Continue, sizeof(int) },
- { &sound3OutputLevel, sizeof(int) },
- { &sound4On, sizeof(int) },
- { &sound4ATL, sizeof(int) },
- { &sound4Skip, sizeof(int) },
- { &sound4Index, sizeof(int) },
- { &sound4Clock, sizeof(int) },
- { &sound4ShiftRight, sizeof(int) },
- { &sound4ShiftSkip, sizeof(int) },
- { &sound4ShiftIndex, sizeof(int) },
- { &sound4NSteps, sizeof(int) },
- { &sound4CountDown, sizeof(int) },
- { &sound4Continue, sizeof(int) },
- { &sound4EnvelopeVolume, sizeof(int) },
- { &sound4EnvelopeATL, sizeof(int) },
- { &sound4EnvelopeATLReload, sizeof(int) },
- { &sound4EnvelopeUpDown, sizeof(int) },
- { &soundEnableFlag, sizeof(int) },
- { NULL, 0 }
-};
-
-void gbSoundSaveGame(gzFile gzFile)
-{
- utilWriteData(gzFile, gbSoundSaveStruct);
-
- utilGzWrite(gzFile, soundBuffer, 4*735);
- utilGzWrite(gzFile, soundFinalWave, 2*735);
- utilGzWrite(gzFile, &soundQuality, sizeof(int));
-}
-
-void gbSoundReadGame(int version,gzFile gzFile)
-{
- utilReadData(gzFile, gbSoundSaveStruct);
-
- soundBufferIndex = soundIndex * 2;
-
- utilGzRead(gzFile, soundBuffer, 4*735);
- utilGzRead(gzFile, soundFinalWave, 2*735);
-
- if(version >=7) {
- int quality = 1;
- utilGzRead(gzFile, &quality, sizeof(int));
- gbSoundSetQuality(quality);
- } else {
- soundQuality = -1;
- gbSoundSetQuality(1);
- }
-
- sound1Wave = soundWavePattern[gbMemory[NR11] >> 6];
- sound2Wave = soundWavePattern[gbMemory[NR21] >> 6];
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include
+
+#include "../System.h"
+#include "../Util.h"
+#include "gbGlobals.h"
+#include "gbSound.h"
+
+extern u8 soundBuffer[6][735];
+extern u16 soundFinalWave[1470];
+extern int soundVolume;
+
+#define SOUND_MAGIC 0x60000000
+#define SOUND_MAGIC_2 0x30000000
+#define NOISE_MAGIC 5
+
+extern int speed;
+extern int gbHardware;
+
+extern void soundResume();
+
+extern u8 soundWavePattern[4][32];
+
+extern int soundBufferLen;
+extern int soundBufferTotalLen;
+extern int soundQuality;
+extern bool soundPaused;
+extern int soundPlay;
+extern int soundTicks;
+extern int SOUND_CLOCK_TICKS;
+extern u32 soundNextPosition;
+
+extern int soundLevel1;
+extern int soundLevel2;
+extern int soundBalance;
+extern int soundMasterOn;
+extern int soundIndex;
+extern int soundBufferIndex;
+int soundVIN = 0;
+extern int soundDebug;
+
+extern int sound1On;
+extern int sound1ATL;
+int sound1ATLreload;
+int freq1low;
+int freq1high;
+extern int sound1Skip;
+extern int sound1Index;
+extern int sound1Continue;
+extern int sound1EnvelopeVolume;
+extern int sound1EnvelopeATL;
+extern int sound1EnvelopeUpDown;
+extern int sound1EnvelopeATLReload;
+extern int sound1SweepATL;
+extern int sound1SweepATLReload;
+extern int sound1SweepSteps;
+extern int sound1SweepUpDown;
+extern int sound1SweepStep;
+extern u8 *sound1Wave;
+
+extern int sound2On;
+extern int sound2ATL;
+int sound2ATLreload;
+int freq2low;
+int freq2high;
+extern int sound2Skip;
+extern int sound2Index;
+extern int sound2Continue;
+extern int sound2EnvelopeVolume;
+extern int sound2EnvelopeATL;
+extern int sound2EnvelopeUpDown;
+extern int sound2EnvelopeATLReload;
+extern u8 *sound2Wave;
+
+extern int sound3On;
+extern int sound3ATL;
+int sound3ATLreload;
+int freq3low;
+int freq3high;
+extern int sound3Skip;
+extern int sound3Index;
+extern int sound3Continue;
+extern int sound3OutputLevel;
+extern int sound3Last;
+
+extern int sound4On;
+extern int sound4Clock;
+extern int sound4ATL;
+int sound4ATLreload;
+int freq4;
+extern int sound4Skip;
+extern int sound4Index;
+extern int sound4ShiftRight;
+extern int sound4ShiftSkip;
+extern int sound4ShiftIndex;
+extern int sound4NSteps;
+extern int sound4CountDown;
+extern int sound4Continue;
+extern int sound4EnvelopeVolume;
+extern int sound4EnvelopeATL;
+extern int sound4EnvelopeUpDown;
+extern int sound4EnvelopeATLReload;
+
+extern int soundEnableFlag;
+
+extern int soundFreqRatio[8];
+extern int soundShiftClock[16];
+
+extern s16 soundFilter[4000];
+extern s16 soundLeft[5];
+extern s16 soundRight[5];
+extern int soundEchoIndex;
+extern bool soundEcho;
+extern bool soundLowPass;
+extern bool soundReverse;
+extern bool soundOffFlag;
+
+bool gbDigitalSound = false;
+
+void gbSoundEvent(register u16 address, register int data)
+{
+ int freq = 0;
+
+ gbMemory[address] = data;
+
+#ifndef FINAL_VERSION
+ if(soundDebug) {
+ // don't translate. debug only
+ log("Sound event: %08lx %02x\n", address, data);
+ }
+#endif
+ switch(address) {
+ case NR10:
+ gbMemory[address] = data | 0x80;
+ sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7);
+ sound1SweepSteps = data & 7;
+ sound1SweepUpDown = data & 0x08;
+ sound1SweepStep = 0;
+ break;
+ case NR11:
+ gbMemory[address] = data | 0x3f;
+ sound1Wave = soundWavePattern[data >> 6];
+ sound1ATL = sound1ATLreload = 172 * (64 - (data & 0x3f));
+ break;
+ case NR12:
+ sound1EnvelopeVolume = data >> 4;
+ sound1EnvelopeUpDown = data & 0x08;
+ sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7);
+ break;
+ case NR13:
+ gbMemory[address] = 0xff;
+ freq1low = data;
+ freq = ((((int)(freq1high & 7)) << 8) | freq1low);
+ sound1ATL = sound1ATLreload;
+ freq = 2048 - freq;
+ if(freq) {
+ sound1Skip = SOUND_MAGIC / freq;
+ } else
+ sound1Skip = 0;
+ break;
+ case NR14:
+ gbMemory[address] = data | 0xbf;
+ freq1high = data;
+ freq = ((((int)(freq1high & 7)) << 8) | freq1low);
+ freq = 2048 - freq;
+ sound1ATL = sound1ATLreload;
+ sound1Continue = data & 0x40;
+ if(freq) {
+ sound1Skip = SOUND_MAGIC / freq;
+ } else
+ sound1Skip = 0;
+ if(data & 0x80) {
+ gbMemory[NR52] |= 1;
+ sound1EnvelopeVolume = gbMemory[NR12] >> 4;
+ sound1EnvelopeUpDown = gbMemory[NR12] & 0x08;
+ sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7);
+ sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7);
+ sound1SweepSteps = gbMemory[NR10] & 7;
+ sound1SweepUpDown = gbMemory[NR10] & 0x08;
+ sound1SweepStep = 0;
+
+ sound1Index = 0;
+ sound1On = 1;
+ }
+ break;
+ case NR21:
+ gbMemory[address] = data | 0x3f;
+ sound2Wave = soundWavePattern[data >> 6];
+ sound2ATL = sound2ATLreload = 172 * (64 - (data & 0x3f));
+ break;
+ case NR22:
+ sound2EnvelopeVolume = data >> 4;
+ sound2EnvelopeUpDown = data & 0x08;
+ sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7);
+ break;
+ case NR23:
+ gbMemory[address] = 0xff;
+ freq2low = data;
+ freq = (((int)(freq2high & 7)) << 8) | freq2low;
+ sound2ATL = sound2ATLreload;
+ freq = 2048 - freq;
+ if(freq) {
+ sound2Skip = SOUND_MAGIC / freq;
+ } else
+ sound2Skip = 0;
+ break;
+ case NR24:
+ gbMemory[address] = data | 0xbf;
+ freq2high = data;
+ freq = (((int)(freq2high & 7)) << 8) | freq2low;
+ freq = 2048 - freq;
+ sound2ATL = sound2ATLreload;
+ sound2Continue = data & 0x40;
+ if(freq) {
+ sound2Skip = SOUND_MAGIC / freq;
+ } else
+ sound2Skip = 0;
+ if(data & 0x80) {
+ gbMemory[NR52] |= 2;
+ sound2EnvelopeVolume = gbMemory[NR22] >> 4;
+ sound2EnvelopeUpDown = gbMemory[NR22] & 0x08;
+ sound2ATL = sound2ATLreload;
+ sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7);
+
+ sound2Index = 0;
+ sound2On = 1;
+ }
+ break;
+ case NR30:
+ gbMemory[address] = data | 0x7f;
+ if(!(data & 0x80)) {
+ gbMemory[NR52] &= 0xfb;
+ sound3On = 0;
+ }
+ break;
+ case NR31:
+ gbMemory[address] = 0xff;
+ sound3ATL = sound3ATLreload = 172 * (256-data);
+ break;
+ case NR32:
+ gbMemory[address] = data | 0x9f;
+ sound3OutputLevel = (data >> 5) & 3;
+ break;
+ case NR33:
+ gbMemory[address] = 0xff;
+ freq3low = data;
+ freq = 2048 - (((int)(freq3high&7) << 8) | freq3low);
+ if(freq) {
+ sound3Skip = SOUND_MAGIC_2 / freq;
+ } else
+ sound3Skip = 0;
+ break;
+ case NR34:
+ gbMemory[address] = data | 0xbf;
+ freq3high = data;
+ freq = 2048 - (((int)(freq3high&7) << 8) | freq3low);
+ if(freq) {
+ sound3Skip = SOUND_MAGIC_2 / freq;
+ } else {
+ sound3Skip = 0;
+ }
+ sound3Continue = data & 0x40;
+ if((data & 0x80) && (gbMemory[NR30] & 0x80)) {
+ gbMemory[NR52] |= 4;
+ sound3ATL = sound3ATLreload;
+ sound3Index = 0;
+ sound3On = 1;
+ }
+ break;
+ case NR41:
+ sound4ATL = sound4ATLreload = 172 * (64 - (data & 0x3f));
+ break;
+ case NR42:
+ sound4EnvelopeVolume = data >> 4;
+ sound4EnvelopeUpDown = data & 0x08;
+ sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7);
+ break;
+ case NR43:
+ freq = freq4 = soundFreqRatio[data & 7];
+ sound4NSteps = data & 0x08;
+
+ sound4Skip = (freq << 8) / NOISE_MAGIC;
+
+ sound4Clock = data >> 4;
+
+ freq = freq / soundShiftClock[sound4Clock];
+
+ sound4ShiftSkip = (freq << 8) / NOISE_MAGIC;
+
+ break;
+ case NR44:
+ gbMemory[address] = data | 0xbf;
+ sound4Continue = data & 0x40;
+ if(data & 0x80) {
+ gbMemory[NR52] |= 8;
+ sound4EnvelopeVolume = gbMemory[NR42] >> 4;
+ sound4EnvelopeUpDown = gbMemory[NR42] & 0x08;
+ sound4ATL = sound4ATLreload;
+ sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7);
+
+ sound4On = 1;
+
+ sound4Index = 0;
+ sound4ShiftIndex = 0;
+
+ if(sound4NSteps)
+ sound4ShiftRight = 0x7fff;
+ else
+ sound4ShiftRight = 0x7f;
+ }
+ break;
+ case NR50:
+ soundVIN = data & 0x88;
+ soundLevel1 = data & 7;
+ soundLevel2 = (data >> 4) & 7;
+ break;
+ case NR51:
+ soundBalance = (data & soundEnableFlag);
+ break;
+ case NR52:
+ soundMasterOn = data & 0x80;
+ if(!(data & 0x80)) {
+ sound1On = 0;
+ sound2On = 0;
+ sound3On = 0;
+ sound4On = 0;
+ gbMemory[address] &= 0xf0;
+ }
+ gbMemory[address] = data & 0x80 | 0x70 | (gbMemory[address] & 0xf);
+ break;
+ }
+
+ gbDigitalSound = true;
+
+ if(sound1On && sound1EnvelopeVolume != 0)
+ gbDigitalSound = false;
+ if(sound2On && sound2EnvelopeVolume != 0)
+ gbDigitalSound = false;
+ if(sound3On && sound3OutputLevel != 0)
+ gbDigitalSound = false;
+ if(sound4On && sound4EnvelopeVolume != 0)
+ gbDigitalSound = false;
+}
+
+ void gbSoundChannel1()
+{
+ int vol = sound1EnvelopeVolume;
+
+ int freq = 0;
+
+ int value = 0;
+
+ if(sound1On && (sound1ATL || !sound1Continue)) {
+ sound1Index += soundQuality*sound1Skip;
+ sound1Index &= 0x1fffffff;
+
+ value = ((s8)sound1Wave[sound1Index>>24]) * vol;
+ }
+
+ soundBuffer[0][soundIndex] = value;
+
+
+ if(sound1On) {
+ if(sound1ATL) {
+ sound1ATL-=soundQuality;
+
+ if(sound1ATL <=0 && sound1Continue) {
+ gbMemory[NR52] &= 0xfe;
+ sound1On = 0;
+ }
+ }
+
+ if(sound1EnvelopeATL) {
+ sound1EnvelopeATL-=soundQuality;
+
+ if(sound1EnvelopeATL<=0) {
+ if(sound1EnvelopeUpDown) {
+ if(sound1EnvelopeVolume < 15)
+ sound1EnvelopeVolume++;
+ } else {
+ if(sound1EnvelopeVolume)
+ sound1EnvelopeVolume--;
+ }
+
+ sound1EnvelopeATL += sound1EnvelopeATLReload;
+ }
+ }
+
+ if(sound1SweepATL) {
+ sound1SweepATL-=soundQuality;
+
+ if(sound1SweepATL<=0) {
+ freq = (((int)(freq1high & 7)) << 8) | freq1low;
+
+ int updown = 1;
+
+ if(sound1SweepUpDown)
+ updown = -1;
+
+ int newfreq = 0;
+ if(sound1SweepSteps) {
+ newfreq = freq + updown * freq / (1 << sound1SweepSteps);
+ if(newfreq == freq)
+ newfreq = 0;
+ } else
+ newfreq = freq;
+
+ if(newfreq < 0) {
+ sound1SweepATL += sound1SweepATLReload;
+ } else if(newfreq > 2047) {
+ sound1SweepATL = 0;
+ sound1On = 0;
+ gbMemory[NR52] &= 0xfe;
+ } else {
+ sound1SweepATL += sound1SweepATLReload;
+ sound1Skip = SOUND_MAGIC/(2048 - newfreq);
+
+ freq1low = newfreq & 0xff;
+ freq1high = (freq1high & 0xf8) |((newfreq >> 8) & 7);
+ }
+ }
+ }
+ }
+}
+
+void gbSoundChannel2()
+{
+ // int freq = 0;
+ int vol = sound2EnvelopeVolume;
+
+ int value = 0;
+
+ if(sound2On && (sound2ATL || !sound2Continue)) {
+ sound2Index += soundQuality*sound2Skip;
+ sound2Index &= 0x1fffffff;
+
+ value = ((s8)sound2Wave[sound2Index>>24]) * vol;
+ }
+
+ soundBuffer[1][soundIndex] = value;
+
+ if(sound2On) {
+ if(sound2ATL) {
+ sound2ATL-=soundQuality;
+
+ if(sound2ATL <= 0 && sound2Continue) {
+ gbMemory[NR52] &= 0xfd;
+ sound2On = 0;
+ }
+ }
+
+ if(sound2EnvelopeATL) {
+ sound2EnvelopeATL-=soundQuality;
+
+ if(sound2EnvelopeATL <= 0) {
+ if(sound2EnvelopeUpDown) {
+ if(sound2EnvelopeVolume < 15)
+ sound2EnvelopeVolume++;
+ } else {
+ if(sound2EnvelopeVolume)
+ sound2EnvelopeVolume--;
+ }
+ sound2EnvelopeATL += sound2EnvelopeATLReload;
+ }
+ }
+ }
+}
+
+void gbSoundChannel3()
+{
+ int value = 0;
+
+ if(sound3On && (sound3ATL || !sound3Continue)) {
+
+ value = sound3Last;
+
+ sound3Index += soundQuality*sound3Skip;
+ sound3Index &= 0x1fffffff;
+
+ value = gbMemory[0xff30 + (sound3Index>>25)];
+
+ if( (sound3Index & 0x01000000)) {
+ value &= 0x0f;
+ } else {
+ value >>= 4;
+ }
+
+ value -= 8;
+
+ switch(sound3OutputLevel) {
+ case 0:
+ value = 0;
+ break;
+ case 1:
+ break;
+ case 2:
+ value = (value >> 1);
+ break;
+ case 3:
+ value = (value >> 2);
+ break;
+ }
+ sound3Last = value;
+ }
+
+ soundBuffer[2][soundIndex] = value;
+
+ if(sound3On) {
+ if(sound3ATL) {
+ sound3ATL-=soundQuality;
+
+ if(sound3ATL <= 0 && sound3Continue) {
+ gbMemory[NR52] &= 0xfb;
+ sound3On = 0;
+ }
+ }
+ }
+}
+
+void gbSoundChannel4()
+{
+ int vol = sound4EnvelopeVolume;
+
+ int value = 0;
+
+ if(sound4Clock <= 0x0c) {
+ if(sound4On && (sound4ATL || !sound4Continue)) {
+ sound4Index += soundQuality*sound4Skip;
+ sound4ShiftIndex += soundQuality*sound4ShiftSkip;
+
+ if(sound4NSteps) {
+ while(sound4ShiftIndex > 0x1fffff) {
+ sound4ShiftRight = (((sound4ShiftRight << 6) ^
+ (sound4ShiftRight << 5)) & 0x40) |
+ (sound4ShiftRight >> 1);
+ sound4ShiftIndex -= 0x200000;
+ }
+ } else {
+ while(sound4ShiftIndex > 0x1fffff) {
+ sound4ShiftRight = (((sound4ShiftRight << 14) ^
+ (sound4ShiftRight << 13)) & 0x4000) |
+ (sound4ShiftRight >> 1);
+
+ sound4ShiftIndex -= 0x200000;
+ }
+ }
+
+ sound4Index &= 0x1fffff;
+ sound4ShiftIndex &= 0x1fffff;
+
+ value = ((sound4ShiftRight & 1)*2-1) * vol;
+ } else {
+ value = 0;
+ }
+ }
+
+ soundBuffer[3][soundIndex] = value;
+
+ if(sound4On) {
+ if(sound4ATL) {
+ sound4ATL-=soundQuality;
+
+ if(sound4ATL <= 0 && sound4Continue) {
+ gbMemory[NR52] &= 0xf7;
+ sound4On = 0;
+ }
+ }
+
+ if(sound4EnvelopeATL) {
+ sound4EnvelopeATL-=soundQuality;
+
+ if(sound4EnvelopeATL <= 0) {
+ if(sound4EnvelopeUpDown) {
+ if(sound4EnvelopeVolume < 15)
+ sound4EnvelopeVolume++;
+ } else {
+ if(sound4EnvelopeVolume)
+ sound4EnvelopeVolume--;
+ }
+ sound4EnvelopeATL += sound4EnvelopeATLReload;
+ }
+ }
+ }
+}
+
+void gbSoundMix()
+{
+ int res = 0;
+
+ if(soundBalance & 16) {
+ res += ((s8)soundBuffer[0][soundIndex]);
+ }
+ if(soundBalance & 32) {
+ res += ((s8)soundBuffer[1][soundIndex]);
+ }
+ if(soundBalance & 64) {
+ res += ((s8)soundBuffer[2][soundIndex]);
+ }
+ if(soundBalance & 128) {
+ res += ((s8)soundBuffer[3][soundIndex]);
+ }
+
+ if(gbDigitalSound)
+ res *= soundLevel1*256;
+ else
+ res *= soundLevel1*60;
+
+ if(soundEcho) {
+ res *= 2;
+ res += soundFilter[soundEchoIndex];
+ res /= 2;
+ soundFilter[soundEchoIndex++] = res;
+ }
+
+ if(soundLowPass) {
+ soundLeft[4] = soundLeft[3];
+ soundLeft[3] = soundLeft[2];
+ soundLeft[2] = soundLeft[1];
+ soundLeft[1] = soundLeft[0];
+ soundLeft[0] = res;
+ res = (soundLeft[4] + 2*soundLeft[3] + 8*soundLeft[2] + 2*soundLeft[1] +
+ soundLeft[0])/14;
+ }
+
+ switch(soundVolume) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ res *= (soundVolume+1);
+ break;
+ case 4:
+ res >>= 2;
+ break;
+ case 5:
+ res >>= 1;
+ break;
+ }
+
+ if(res > 32767)
+ res = 32767;
+ if(res < -32768)
+ res = -32768;
+
+ if(soundReverse)
+ soundFinalWave[++soundBufferIndex] = res;
+ else
+ soundFinalWave[soundBufferIndex++] = res;
+
+ res = 0;
+
+ if(soundBalance & 1) {
+ res += ((s8)soundBuffer[0][soundIndex]);
+ }
+ if(soundBalance & 2) {
+ res += ((s8)soundBuffer[1][soundIndex]);
+ }
+ if(soundBalance & 4) {
+ res += ((s8)soundBuffer[2][soundIndex]);
+ }
+ if(soundBalance & 8) {
+ res += ((s8)soundBuffer[3][soundIndex]);
+ }
+
+ if(gbDigitalSound)
+ res *= soundLevel2*256;
+ else
+ res *= soundLevel2*60;
+
+ if(soundEcho) {
+ res *= 2;
+ res += soundFilter[soundEchoIndex];
+ res /= 2;
+ soundFilter[soundEchoIndex++] = res;
+
+ if(soundEchoIndex >= 4000)
+ soundEchoIndex = 0;
+ }
+
+ if(soundLowPass) {
+ soundRight[4] = soundRight[3];
+ soundRight[3] = soundRight[2];
+ soundRight[2] = soundRight[1];
+ soundRight[1] = soundRight[0];
+ soundRight[0] = res;
+ res = (soundRight[4] + 2*soundRight[3] + 8*soundRight[2] + 2*soundRight[1] +
+ soundRight[0])/14;
+ }
+
+ switch(soundVolume) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ res *= (soundVolume+1);
+ break;
+ case 4:
+ res >>= 2;
+ break;
+ case 5:
+ res >>= 1;
+ break;
+ }
+
+ if(res > 32767)
+ res = 32767;
+ if(res < -32768)
+ res = -32768;
+
+ if(soundReverse)
+ soundFinalWave[-1+soundBufferIndex++] = res;
+ else
+ soundFinalWave[soundBufferIndex++] = res;
+}
+
+void gbSoundTick()
+{
+ if(systemSoundOn) {
+ if(soundMasterOn) {
+ gbSoundChannel1();
+ gbSoundChannel2();
+ gbSoundChannel3();
+ gbSoundChannel4();
+
+ gbSoundMix();
+ } else {
+ soundFinalWave[soundBufferIndex++] = 0;
+ soundFinalWave[soundBufferIndex++] = 0;
+ }
+
+ soundIndex++;
+
+ if(2*soundBufferIndex >= soundBufferLen) {
+ if(systemSoundOn) {
+ if(soundPaused) {
+ soundResume();
+ }
+
+ systemWriteDataToSoundBuffer();
+ }
+ soundIndex = 0;
+ soundBufferIndex = 0;
+ }
+ }
+}
+
+void gbSoundReset()
+{
+ soundPaused = true;
+ soundPlay = 0;
+ SOUND_CLOCK_TICKS = soundQuality * 24;
+ soundTicks = SOUND_CLOCK_TICKS;
+ soundNextPosition = 0;
+ soundMasterOn = 1;
+ soundIndex = 0;
+ soundBufferIndex = 0;
+ soundLevel1 = 7;
+ soundLevel2 = 7;
+ soundVIN = 0;
+
+ sound1On = 0;
+ sound1ATL = 0;
+ sound1Skip = 0;
+ sound1Index = 0;
+ sound1Continue = 0;
+ sound1EnvelopeVolume = 0;
+ sound1EnvelopeATL = 0;
+ sound1EnvelopeUpDown = 0;
+ sound1EnvelopeATLReload = 0;
+ sound1SweepATL = 0;
+ sound1SweepATLReload = 0;
+ sound1SweepSteps = 0;
+ sound1SweepUpDown = 0;
+ sound1SweepStep = 0;
+ sound1Wave = soundWavePattern[2];
+
+ sound2On = 0;
+ sound2ATL = 0;
+ sound2Skip = 0;
+ sound2Index = 0;
+ sound2Continue = 0;
+ sound2EnvelopeVolume = 0;
+ sound2EnvelopeATL = 0;
+ sound2EnvelopeUpDown = 0;
+ sound2EnvelopeATLReload = 0;
+ sound2Wave = soundWavePattern[2];
+
+ sound3On = 0;
+ sound3ATL = 0;
+ sound3Skip = 0;
+ sound3Index = 0;
+ sound3Continue = 0;
+ sound3OutputLevel = 0;
+
+ sound4On = 0;
+ sound4Clock = 0;
+ sound4ATL = 0;
+ sound4Skip = 0;
+ sound4Index = 0;
+ sound4ShiftRight = 0x7f;
+ sound4NSteps = 0;
+ sound4CountDown = 0;
+ sound4Continue = 0;
+ sound4EnvelopeVolume = 0;
+ sound4EnvelopeATL = 0;
+ sound4EnvelopeUpDown = 0;
+ sound4EnvelopeATLReload = 0;
+
+ // don't translate
+ if(soundDebug) {
+ log("*** Sound Init ***\n");
+ }
+
+ gbSoundEvent(0xff10, 0x80);
+ gbSoundEvent(0xff11, 0xbf);
+ gbSoundEvent(0xff12, 0xf3);
+ gbSoundEvent(0xff14, 0xbf);
+ gbSoundEvent(0xff16, 0x3f);
+ gbSoundEvent(0xff17, 0x00);
+ gbSoundEvent(0xff19, 0xbf);
+
+ gbSoundEvent(0xff1a, 0x7f);
+ gbSoundEvent(0xff1b, 0xff);
+ gbSoundEvent(0xff1c, 0xbf);
+ gbSoundEvent(0xff1e, 0xbf);
+
+ gbSoundEvent(0xff20, 0xff);
+ gbSoundEvent(0xff21, 0x00);
+ gbSoundEvent(0xff22, 0x00);
+ gbSoundEvent(0xff23, 0xbf);
+ gbSoundEvent(0xff24, 0x77);
+ gbSoundEvent(0xff25, 0xf3);
+
+ if (gbHardware & 0x4)
+ gbSoundEvent(0xff26, 0xf0);
+ else
+ gbSoundEvent(0xff26, 0xf1);
+
+ // don't translate
+ if(soundDebug) {
+ log("*** Sound Init Complete ***\n");
+ }
+
+ sound1On = 0;
+ sound2On = 0;
+ sound3On = 0;
+ sound4On = 0;
+
+ int addr = 0xff30;
+
+ while(addr < 0xff40) {
+ gbMemory[addr++] = 0x00;
+ gbMemory[addr++] = 0xff;
+ }
+
+ memset(soundFinalWave, 0x00, soundBufferLen);
+
+
+ memset(soundFilter, 0, sizeof(soundFilter));
+ soundEchoIndex = 0;
+}
+
+extern bool soundInit(bool gb);
+extern void soundShutdown();
+
+void gbSoundSetQuality(int quality)
+{
+ if(soundQuality != quality && systemCanChangeSoundQuality()) {
+ if(!soundOffFlag)
+ soundShutdown();
+ soundQuality = quality;
+ soundNextPosition = 0;
+ if(!soundOffFlag)
+ soundInit(false);
+ SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
+ soundIndex = 0;
+ soundBufferIndex = 0;
+ } else {
+ soundNextPosition = 0;
+ SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
+ soundIndex = 0;
+ soundBufferIndex = 0;
+ }
+}
+
+variable_desc gbSoundSaveStruct[] = {
+ { &soundPaused, sizeof(int) },
+ { &soundPlay, sizeof(int) },
+ { &soundTicks, sizeof(int) },
+ { &SOUND_CLOCK_TICKS, sizeof(int) },
+ { &soundLevel1, sizeof(int) },
+ { &soundLevel2, sizeof(int) },
+ { &soundBalance, sizeof(int) },
+ { &soundMasterOn, sizeof(int) },
+ { &soundIndex, sizeof(int) },
+ { &soundVIN, sizeof(int) },
+ { &sound1On, sizeof(int) },
+ { &sound1ATL, sizeof(int) },
+ { &sound1Skip, sizeof(int) },
+ { &sound1Index, sizeof(int) },
+ { &sound1Continue, sizeof(int) },
+ { &sound1EnvelopeVolume, sizeof(int) },
+ { &sound1EnvelopeATL, sizeof(int) },
+ { &sound1EnvelopeATLReload, sizeof(int) },
+ { &sound1EnvelopeUpDown, sizeof(int) },
+ { &sound1SweepATL, sizeof(int) },
+ { &sound1SweepATLReload, sizeof(int) },
+ { &sound1SweepSteps, sizeof(int) },
+ { &sound1SweepUpDown, sizeof(int) },
+ { &sound1SweepStep, sizeof(int) },
+ { &sound2On, sizeof(int) },
+ { &sound2ATL, sizeof(int) },
+ { &sound2Skip, sizeof(int) },
+ { &sound2Index, sizeof(int) },
+ { &sound2Continue, sizeof(int) },
+ { &sound2EnvelopeVolume, sizeof(int) },
+ { &sound2EnvelopeATL, sizeof(int) },
+ { &sound2EnvelopeATLReload, sizeof(int) },
+ { &sound2EnvelopeUpDown, sizeof(int) },
+ { &sound3On, sizeof(int) },
+ { &sound3ATL, sizeof(int) },
+ { &sound3Skip, sizeof(int) },
+ { &sound3Index, sizeof(int) },
+ { &sound3Continue, sizeof(int) },
+ { &sound3OutputLevel, sizeof(int) },
+ { &sound4On, sizeof(int) },
+ { &sound4ATL, sizeof(int) },
+ { &sound4Skip, sizeof(int) },
+ { &sound4Index, sizeof(int) },
+ { &sound4Clock, sizeof(int) },
+ { &sound4ShiftRight, sizeof(int) },
+ { &sound4ShiftSkip, sizeof(int) },
+ { &sound4ShiftIndex, sizeof(int) },
+ { &sound4NSteps, sizeof(int) },
+ { &sound4CountDown, sizeof(int) },
+ { &sound4Continue, sizeof(int) },
+ { &sound4EnvelopeVolume, sizeof(int) },
+ { &sound4EnvelopeATL, sizeof(int) },
+ { &sound4EnvelopeATLReload, sizeof(int) },
+ { &sound4EnvelopeUpDown, sizeof(int) },
+ { &soundEnableFlag, sizeof(int) },
+ { NULL, 0 }
+};
+
+void gbSoundSaveGame(gzFile gzFile)
+{
+ utilWriteData(gzFile, gbSoundSaveStruct);
+
+ utilWriteInt(gzFile, sound1ATLreload);
+ utilWriteInt(gzFile, freq1low);
+ utilWriteInt(gzFile, freq1high);
+ utilWriteInt(gzFile, sound2ATLreload);
+ utilWriteInt(gzFile, freq2low);
+ utilWriteInt(gzFile, freq2high);
+ utilWriteInt(gzFile, sound3ATLreload);
+ utilWriteInt(gzFile, freq3low);
+ utilWriteInt(gzFile, freq3high);
+ utilWriteInt(gzFile, sound4ATLreload);
+ utilWriteInt(gzFile, freq4);
+
+ utilGzWrite(gzFile, soundBuffer, 4*735);
+ utilGzWrite(gzFile, soundFinalWave, 2*735);
+ utilGzWrite(gzFile, &soundQuality, sizeof(int));
+}
+
+void gbSoundReadGame(int version,gzFile gzFile)
+{
+ utilReadData(gzFile, gbSoundSaveStruct);
+
+ if (version<11)
+ {
+ sound1ATLreload = 172 * (64 - (gbMemory[NR11] & 0x3f));
+ freq1low = gbMemory[NR13];
+ freq1high = gbMemory[NR14] & 7;
+ sound2ATLreload = 172 * (64 - (gbMemory[NR21] & 0x3f));
+ freq2low = gbMemory[NR23];
+ freq2high = gbMemory[NR24] & 7;
+ sound3ATLreload = 172 * (256 - gbMemory[NR31]);
+ freq3low = gbMemory[NR33];
+ freq3high = gbMemory[NR34] & 7;
+ sound4ATLreload = 172 * (64 - (gbMemory[NR41] & 0x3f));
+ freq4 = soundFreqRatio[gbMemory[NR43] & 7];
+ }
+ else
+ {
+ sound1ATLreload = utilReadInt(gzFile);
+ freq1low = utilReadInt(gzFile);
+ freq1high = utilReadInt(gzFile);
+ sound2ATLreload = utilReadInt(gzFile);
+ freq2low = utilReadInt(gzFile);
+ freq2high = utilReadInt(gzFile);
+ sound3ATLreload = utilReadInt(gzFile);
+ freq3low = utilReadInt(gzFile);
+ freq3high = utilReadInt(gzFile);
+ sound4ATLreload = utilReadInt(gzFile);
+ freq4 = utilReadInt(gzFile);
+ }
+
+ soundBufferIndex = soundIndex * 2;
+
+ utilGzRead(gzFile, soundBuffer, 4*735);
+ utilGzRead(gzFile, soundFinalWave, 2*735);
+
+ if(version >=7) {
+ int quality = 1;
+ utilGzRead(gzFile, &quality, sizeof(int));
+ gbSoundSetQuality(quality);
+ } else {
+ soundQuality = -1;
+ gbSoundSetQuality(1);
+ }
+
+ sound1Wave = soundWavePattern[gbMemory[NR11] >> 6];
+ sound2Wave = soundWavePattern[gbMemory[NR21] >> 6];
+}
diff --git a/src/gb/gbSound.h b/src/gb/gbSound.h
index 8509a107..50658b24 100644
--- a/src/gb/gbSound.h
+++ b/src/gb/gbSound.h
@@ -1,61 +1,59 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#define NR10 0xff10
-#define NR11 0xff11
-#define NR12 0xff12
-#define NR13 0xff13
-#define NR14 0xff14
-#define NR21 0xff16
-#define NR22 0xff17
-#define NR23 0xff18
-#define NR24 0xff19
-#define NR30 0xff1a
-#define NR31 0xff1b
-#define NR32 0xff1c
-#define NR33 0xff1d
-#define NR34 0xff1e
-#define NR41 0xff20
-#define NR42 0xff21
-#define NR43 0xff22
-#define NR44 0xff23
-#define NR50 0xff24
-#define NR51 0xff25
-#define NR52 0xff26
-
-#define SOUND_EVENT(address,value) \
- gbSoundEvent(address,value)
-
-extern void gbSoundTick();
-extern void gbSoundPause();
-extern void gbSoundResume();
-extern void gbSoundEnable(int);
-extern void gbSoundDisable(int);
-extern int gbSoundGetEnable();
-extern void gbSoundReset();
-extern void gbSoundSaveGame(gzFile);
-extern void gbSoundReadGame(int,gzFile);
-extern void gbSoundEvent(register u16, register int);
-extern void gbSoundSetQuality(int);
-
-extern u8 gbSoundRead(u16 address);
-
-extern int soundTicks;
-extern int soundQuality;
-extern int SOUND_CLOCK_TICKS;
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#define NR10 0xff10
+#define NR11 0xff11
+#define NR12 0xff12
+#define NR13 0xff13
+#define NR14 0xff14
+#define NR21 0xff16
+#define NR22 0xff17
+#define NR23 0xff18
+#define NR24 0xff19
+#define NR30 0xff1a
+#define NR31 0xff1b
+#define NR32 0xff1c
+#define NR33 0xff1d
+#define NR34 0xff1e
+#define NR41 0xff20
+#define NR42 0xff21
+#define NR43 0xff22
+#define NR44 0xff23
+#define NR50 0xff24
+#define NR51 0xff25
+#define NR52 0xff26
+
+#define SOUND_EVENT(address,value) \
+ gbSoundEvent(address,value)
+
+extern void gbSoundTick();
+extern void gbSoundPause();
+extern void gbSoundResume();
+extern void gbSoundEnable(int);
+extern void gbSoundDisable(int);
+extern int gbSoundGetEnable();
+extern void gbSoundReset();
+extern void gbSoundSaveGame(gzFile);
+extern void gbSoundReadGame(int,gzFile);
+extern void gbSoundEvent(register u16, register int);
+extern void gbSoundSetQuality(int);
+
+extern int soundTicks;
+extern int soundQuality;
+extern int SOUND_CLOCK_TICKS;
diff --git a/src/getopt.cpp b/src/getopt.cpp
deleted file mode 100644
index 9a127443..00000000
--- a/src/getopt.cpp
+++ /dev/null
@@ -1,1048 +0,0 @@
-#include
-
-/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to drepper@gnu.org
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98
- Free Software Foundation, Inc.
-
- NOTE: This source is derived from an old version taken from the GNU C
- Library (glibc).
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in .
- Ditto for AIX 3.2 and . */
-#ifndef _NO_PROTO
-# define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include
-#endif
-
-#if !defined __STDC__ || !__STDC__
-/* This is a separate conditional since some stdc systems
- reject `defined (const)'. */
-# ifndef const
-# define const
-# endif
-#endif
-
-#include
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-# include
-# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-# define ELIDE_CODE
-# endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
-# include
-# include
-#endif /* GNU C library. */
-
-#ifdef VMS
-# include
-# if HAVE_STRING_H - 0
-# include
-# endif
-#endif
-
-#ifndef _
-/* This is for other GNU distributions with internationalized messages.
- When compiling libc, the _ macro is predefined. */
-# ifdef HAVE_LIBINTL_H
-# include
-# define _(msgid) gettext (msgid)
-# else
-# define _(msgid) (msgid)
-# endif
-#endif
-
-#ifdef _MSC_VER
-#include
-#include
-#endif
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-char *optarg = NULL;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-/* 1003.2 says this must be 1 before any call. */
-int optind = 1;
-
-/* Formerly, initialization of getopt depended on optind==0, which
- causes problems with re-calling getopt as programs generally don't
- know that. */
-
-int __getopt_initialized = 0;
-
-/* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
- for unrecognized options. */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
- This must be initialized on some systems to avoid linking in the
- system's own getopt implementation. */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return -1 with `optind' != ARGC. */
-
-static enum
-{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-/* Value of POSIXLY_CORRECT environment variable. */
-static char *posixly_correct;
-
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
- because there are many ways it can cause trouble.
- On some systems, it contains special magic macros that don't work
- in GCC. */
-# include
-# define my_index strchr
-#else
-
-# if HAVE_STRING_H
-# include
-# else
-# if HAVE_STRINGS_H
-# include
-# endif
-# endif
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-#ifndef getenv
-extern char *getenv ();
-#endif
-
-static char *
-my_index (const char *str, int chr)
-{
- while (*str)
- {
- if (*str == chr)
- return (char *) str;
- str++;
- }
- return 0;
-}
-
-/* If using GCC, we can safely declare strlen this way.
- If not using GCC, it is ok not to declare it. */
-#ifdef __GNUC__
-/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
- That was relevant to code that was here before. */
-# if (!defined __STDC__ || !__STDC__) && !defined strlen
-/* gcc with -traditional declares the built-in strlen to return int,
- and has done so at least since version 2.4.5. -- rms. */
-extern int strlen (const char *);
-# endif /* not __STDC__ */
-#endif /* __GNUC__ */
-
-#endif /* not __GNU_LIBRARY__ */
-
-/* Handle permutation of arguments. */
-
-/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
-static int first_nonopt;
-static int last_nonopt;
-
-#ifdef _LIBC
-/* Bash 2.0 gives us an environment variable containing flags
- indicating ARGV elements that should not be considered arguments. */
-
-/* Defined in getopt_init.c */
-extern char *__getopt_nonoption_flags;
-
-static int nonoption_flags_max_len;
-static int nonoption_flags_len;
-
-static int original_argc;
-static char *const *original_argv;
-
-/* Make sure the environment variable bash 2.0 puts in the environment
- is valid for the getopt call we must make sure that the ARGV passed
- to getopt is that one passed to the process. */
-static void
-__attribute__ ((unused))
-store_args_and_env (int argc, char *const *argv)
-{
- /* XXX This is no good solution. We should rather copy the args so
- that we can compare them later. But we must not use malloc(3). */
- original_argc = argc;
- original_argv = argv;
-}
-# ifdef text_set_element
-text_set_element (__libc_subinit, store_args_and_env);
-# endif /* text_set_element */
-
-# define SWAP_FLAGS(ch1, ch2) \
- if (nonoption_flags_len > 0) \
- { \
- char __tmp = __getopt_nonoption_flags[ch1]; \
- __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
- __getopt_nonoption_flags[ch2] = __tmp; \
- }
-#else /* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif /* _LIBC */
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,optind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved. */
-
-#if defined __STDC__ && __STDC__
-static void exchange (char **);
-#endif
-
-static void
-exchange (char **argv)
-{
- int bottom = first_nonopt;
- int middle = last_nonopt;
- int top = optind;
- char *tem;
-
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place.
- It leaves the longer segment in the right place overall,
- but it consists of two parts that need to be swapped next. */
-
-#ifdef _LIBC
- /* First make sure the handling of the `__getopt_nonoption_flags'
- string can work normally. Our top argument must be in the range
- of the string. */
- if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
- {
- /* We must extend the array. The user plays games with us and
- presents new arguments. */
- char *new_str = malloc (top + 1);
- if (new_str == NULL)
- nonoption_flags_len = nonoption_flags_max_len = 0;
- else
- {
- memset (__mempcpy (new_str, __getopt_nonoption_flags,
- nonoption_flags_max_len),
- '\0', top + 1 - nonoption_flags_max_len);
- nonoption_flags_max_len = top + 1;
- __getopt_nonoption_flags = new_str;
- }
- }
-#endif
-
- while (top > middle && middle > bottom)
- {
- if (top - middle > middle - bottom)
- {
- /* Bottom segment is the short one. */
- int len = middle - bottom;
- register int i;
-
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[top - (middle - bottom) + i];
- argv[top - (middle - bottom) + i] = tem;
- SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
- }
- /* Exclude the moved bottom segment from further swapping. */
- top -= len;
- }
- else
- {
- /* Top segment is the short one. */
- int len = top - middle;
- register int i;
-
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[middle + i];
- argv[middle + i] = tem;
- SWAP_FLAGS (bottom + i, middle + i);
- }
- /* Exclude the moved top segment from further swapping. */
- bottom += len;
- }
- }
-
- /* Update records for the slots the non-options now occupy. */
-
- first_nonopt += (optind - last_nonopt);
- last_nonopt = optind;
-}
-
-/* Initialize the internal data when the first call is made. */
-
-#if defined __STDC__ && __STDC__
-static const char *_getopt_initialize (int, char *const *, const char *);
-#endif
-static const char *
-_getopt_initialize (int argc, char *const *argv, const char *optstring)
-{
- /* Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
-
- first_nonopt = last_nonopt = optind;
-
- nextchar = NULL;
-
- posixly_correct = getenv ("POSIXLY_CORRECT");
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (posixly_correct != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
-
-#ifdef _LIBC
- if (posixly_correct == NULL
- && argc == original_argc && argv == original_argv)
- {
- if (nonoption_flags_max_len == 0)
- {
- if (__getopt_nonoption_flags == NULL
- || __getopt_nonoption_flags[0] == '\0')
- nonoption_flags_max_len = -1;
- else
- {
- const char *orig_str = __getopt_nonoption_flags;
- int len = nonoption_flags_max_len = strlen (orig_str);
- if (nonoption_flags_max_len < argc)
- nonoption_flags_max_len = argc;
- __getopt_nonoption_flags =
- (char *) malloc (nonoption_flags_max_len);
- if (__getopt_nonoption_flags == NULL)
- nonoption_flags_max_len = -1;
- else
- memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
- '\0', nonoption_flags_max_len - len);
- }
- }
- nonoption_flags_len = nonoption_flags_max_len;
- }
- else
- nonoption_flags_len = 0;
-#endif
-
- return optstring;
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns -1.
- Then `optind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `opterr' to
- zero, the error message is suppressed but we still return '?'.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- The elements of ARGV aren't really const, because we permute them.
- But we pretend they're const in the prototype to be compatible
- with other systems.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-int
-_getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only)
-{
- optarg = NULL;
-
- if (optind == 0 || !__getopt_initialized)
- {
- if (optind == 0)
- optind = 1; /* Don't scan ARGV[0], the program name. */
- optstring = _getopt_initialize (argc, argv, optstring);
- __getopt_initialized = 1;
- }
-
- /* Test whether ARGV[optind] points to a non-option argument.
- Either it does not have option syntax, or there is an environment flag
- from the shell indicating it is not an option. The later information
- is only used when the used in the GNU libc. */
-#ifdef _LIBC
-# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
- || (optind < nonoption_flags_len \
- && __getopt_nonoption_flags[optind] == '1'))
-#else
-# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#endif
-
- if (nextchar == NULL || *nextchar == '\0')
- {
- /* Advance to the next ARGV-element. */
-
- /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
- moved back by the user (who may also have changed the arguments). */
- if (last_nonopt > optind)
- last_nonopt = optind;
- if (first_nonopt > optind)
- first_nonopt = optind;
-
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
-
- /* Skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (optind < argc && NONOPTION_P)
- optind++;
- last_nonopt = optind;
- }
-
- /* The special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (optind != argc && !strcmp (argv[optind], "--"))
- {
- optind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
-
- optind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
-
- if (optind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return -1;
- }
-
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if (NONOPTION_P)
- {
- if (ordering == REQUIRE_ORDER)
- return -1;
- optarg = argv[optind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element.
- Skip the initial punctuation. */
-
- nextchar = (argv[optind] + 1
- + (longopts != NULL && argv[optind][1] == '-'));
- }
-
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
-
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL
- && (argv[optind][1] == '-'
- || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = -1;
- int option_index;
-
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar)
- == (unsigned int) strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- if (opterr)
- fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- optopt = 0;
- return '?';
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- optind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- if (opterr)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- _("%s: option `--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- _("%s: option `%c%s' doesn't allow an argument\n"),
- argv[0], argv[optind - 1][0], pfound->name);
-
- nextchar += strlen (nextchar);
-
- optopt = pfound->val;
- return '?';
- }
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (opterr)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- optopt = pfound->val;
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
-
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-'
- || my_index (optstring, *nextchar) == NULL)
- {
- if (opterr)
- {
- if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
- argv[0], nextchar);
- else
- /* +option or -option */
- fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
- argv[0], argv[optind][0], nextchar);
- }
- nextchar = (char *) "";
- optind++;
- optopt = 0;
- return '?';
- }
- }
-
- /* Look at and handle the next short option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index (optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':')
- {
- if (opterr)
- {
- if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, _("%s: illegal option -- %c\n"),
- argv[0], c);
- else
- fprintf (stderr, _("%s: invalid option -- %c\n"),
- argv[0], c);
- }
- optopt = c;
- return '?';
- }
- /* Convenience. Treat POSIX -W foo same as long option --foo */
- if (temp[0] == 'W' && temp[1] == ';')
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0;
- int option_index;
-
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (opterr)
- {
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, _("%s: option requires an argument -- %c\n"),
- argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- return c;
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
-
- /* optarg is now the argument, see if it's in the
- table of longopts. */
-
- for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar) == strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
- if (ambig && !exact)
- {
- if (opterr)
- fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- return '?';
- }
- if (pfound != NULL)
- {
- option_index = indfound;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- if (opterr)
- fprintf (stderr, _("\
-%s: option `-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name);
-
- nextchar += strlen (nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (opterr)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- nextchar = NULL;
- return 'W'; /* Let the application handle it. */
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- optind++;
- }
- else
- optarg = NULL;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (opterr)
- {
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr,
- _("%s: option requires an argument -- %c\n"),
- argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
-}
-
-int
-getopt (int argc, char *const *argv, const char *optstring)
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0);
-}
-
-#endif /* Not ELIDE_CODE. */
-
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
- the above definition of `getopt'. */
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
-
- c = getopt (argc, argv, "abc:d:0123456789");
- if (c == -1)
- break;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
diff --git a/src/getopt.h b/src/getopt.h
index 9268121e..cb5feba1 100644
--- a/src/getopt.h
+++ b/src/getopt.h
@@ -131,10 +131,7 @@ extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
-extern int _getopt_internal (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind,
- int long_only);
+extern int _getopt_internal ();
#endif /* __STDC__ */
#ifdef __cplusplus
diff --git a/src/getopt1.cpp b/src/getopt1.cpp
deleted file mode 100644
index b32d85bc..00000000
--- a/src/getopt1.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
- Free Software Foundation, Inc.
-
- NOTE: This source is derived from an old version taken from the GNU C
- Library (glibc).
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "getopt.h"
-
-#if !defined __STDC__ || !__STDC__
-/* This is a separate conditional since some stdc systems
- reject `defined (const)'. */
-#ifndef const
-#define const
-#endif
-#endif
-
-#include
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-#include
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-#include
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-int
-getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index)
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
- If an option that starts with '-' (not '--') doesn't match a long option,
- but does match a short option, it is parsed as a short option
- instead. */
-
-int
-getopt_long_only (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index)
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
-}
-
-
-#endif /* Not ELIDE_CODE. */
-
-#ifdef TEST
-
-#include
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
- int option_index = 0;
- static struct option long_options[] =
- {
- {"add", 1, 0, 0},
- {"append", 0, 0, 0},
- {"delete", 1, 0, 0},
- {"verbose", 0, 0, 0},
- {"create", 0, 0, 0},
- {"file", 1, 0, 0},
- {0, 0, 0, 0}
- };
-
- c = getopt_long (argc, argv, "abc:d:0123456789",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0:
- printf ("option %s", long_options[option_index].name);
- if (optarg)
- printf (" with arg %s", optarg);
- printf ("\n");
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case 'd':
- printf ("option d with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
diff --git a/src/interframe.cpp b/src/interframe.cpp
index 78ea76fd..e4a17227 100644
--- a/src/interframe.cpp
+++ b/src/interframe.cpp
@@ -1,648 +1,581 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "System.h"
-#include
-#include
-
-#ifdef MMX
-extern "C" bool cpu_mmx;
-#endif
-
-/*
- * Thanks to Kawaks' Mr. K for the code
-
- Incorporated into vba by Anthony Di Franco
-*/
-
-static u8 *frm1 = NULL;
-static u8 *frm2 = NULL;
-static u8 *frm3 = NULL;
-
-extern int RGB_LOW_BITS_MASK;
-extern u32 qRGB_COLOR_MASK[2];
-
-static void Init()
-{
- frm1 = (u8 *)calloc(322*242,4);
- // 1 frame ago
- frm2 = (u8 *)calloc(322*242,4);
- // 2 frames ago
- frm3 = (u8 *)calloc(322*242,4);
- // 3 frames ago
-}
-
-void InterframeCleanup()
-{
- if(frm1)
- free(frm1);
- if(frm2)
- free(frm2);
- if(frm3)
- free(frm3);
- frm1 = frm2 = frm3 = NULL;
-}
-
-#ifdef MMX
-static void SmartIB_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- u16 *src0 = (u16 *)srcPtr;
- u16 *src1 = (u16 *)frm1;
- u16 *src2 = (u16 *)frm2;
- u16 *src3 = (u16 *)frm3;
-
- int sPitch = srcPitch >> 1;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
- int count = width >> 2;
-
- for(int i = 0; i < height; i++) {
-#ifdef __GNUC__
- asm volatile (
- "push %4\n"
- "movq 0(%5), %%mm7\n" // colorMask
- "0:\n"
- "movq 0(%0), %%mm0\n" // src0
- "movq 0(%1), %%mm1\n" // src1
- "movq 0(%2), %%mm2\n" // src2
- "movq 0(%3), %%mm3\n" // src3
- "movq %%mm0, 0(%3)\n" // src3 = src0
- "movq %%mm0, %%mm4\n"
- "movq %%mm1, %%mm5\n"
- "pcmpeqw %%mm2, %%mm5\n" // src1 == src2 (A)
- "pcmpeqw %%mm3, %%mm4\n" // src3 == src0 (B)
- "por %%mm5, %%mm4\n" // A | B
- "movq %%mm2, %%mm5\n"
- "pcmpeqw %%mm0, %%mm5\n" // src0 == src2 (C)
- "pcmpeqw %%mm1, %%mm3\n" // src1 == src3 (D)
- "por %%mm3, %%mm5\n" // C|D
- "pandn %%mm5, %%mm4\n" // (!(A|B))&(C|D)
- "movq %%mm0, %%mm2\n"
- "pand %%mm7, %%mm2\n" // color & colorMask
- "pand %%mm7, %%mm1\n" // src1 & colorMask
- "psrlw $1, %%mm2\n" // (color & colorMask) >> 1 (E)
- "psrlw $1, %%mm1\n" // (src & colorMask) >> 1 (F)
- "paddw %%mm2, %%mm1\n" // E+F
- "pand %%mm4, %%mm1\n" // (E+F) & res
- "pandn %%mm0, %%mm4\n" // color& !res
-
- "por %%mm1, %%mm4\n"
- "movq %%mm4, 0(%0)\n" // src0 = res
-
- "addl $8, %0\n"
- "addl $8, %1\n"
- "addl $8, %2\n"
- "addl $8, %3\n"
-
- "decl %4\n"
- "jnz 0b\n"
- "pop %4\n"
- "emms\n"
- : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (src3)
- : "r" (count), "r" (qRGB_COLOR_MASK)
- );
-#else
- __asm {
- movq mm7, qword ptr [qRGB_COLOR_MASK];
- mov eax, src0;
- mov ebx, src1;
- mov ecx, src2;
- mov edx, src3;
- mov edi, count;
- label0:
- movq mm0, qword ptr [eax]; // src0
- movq mm1, qword ptr [ebx]; // src1
- movq mm2, qword ptr [ecx]; // src2
- movq mm3, qword ptr [edx]; // src3
- movq qword ptr [edx], mm0; // src3 = src0
- movq mm4, mm0;
- movq mm5, mm1;
- pcmpeqw mm5, mm2; // src1 == src2 (A)
- pcmpeqw mm4, mm3; // src3 == src0 (B)
- por mm4, mm5; // A | B
- movq mm5, mm2;
- pcmpeqw mm5, mm0; // src0 == src2 (C)
- pcmpeqw mm3, mm1; // src1 == src3 (D)
- por mm5, mm3; // C|D
- pandn mm4, mm5; // (!(A|B))&(C|D)
- movq mm2, mm0;
- pand mm2, mm7; // color & colorMask
- pand mm1, mm7; // src1 & colorMask
- psrlw mm2, 1; // (color & colorMask) >> 1 (E)
- psrlw mm1, 1; // (src & colorMask) >> 1 (F)
- paddw mm1, mm2; // E+F
- pand mm1, mm4; // (E+F) & res
- pandn mm4, mm0; // color & !res
-
- por mm4, mm1;
- movq qword ptr [eax], mm4; // src0 = res
-
- add eax, 8;
- add ebx, 8;
- add ecx, 8;
- add edx, 8;
-
- dec edi;
- jnz label0;
- mov src0, eax;
- mov src1, ebx;
- mov src2, ecx;
- mov src3, edx;
- emms;
- }
-#endif
- src0+= sPitch;
- src1+= sPitch;
- src2+= sPitch;
- src3+= sPitch;
- }
-
- /* Swap buffers around */
- u8 *temp = frm1;
- frm1 = frm3;
- frm3 = frm2;
- frm2 = temp;
-}
-#endif
-
-void SmartIB(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- if(frm1 == NULL) {
- Init();
- }
-#ifdef MMX
- if(cpu_mmx) {
- SmartIB_MMX(srcPtr, srcPitch, width, height);
- return;
- }
-#endif
-
- u16 colorMask = ~RGB_LOW_BITS_MASK;
-
- u16 *src0 = (u16 *)srcPtr;
- u16 *src1 = (u16 *)frm1;
- u16 *src2 = (u16 *)frm2;
- u16 *src3 = (u16 *)frm3;
-
- int sPitch = srcPitch >> 1;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
-
- int pos = 0;
- for (int j = 0; j < height; j++) {
- for (int i = 0; i < width; i++) {
- u16 color = src0[pos];
- src0[pos] =
- (src1[pos] != src2[pos]) &&
- (src3[pos] != color) &&
- ((color == src2[pos]) || (src1[pos] == src3[pos]))
- ? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
- color;
- src3[pos] = color; /* oldest buffer now holds newest frame */
- pos++;
- }
- pos += sPitch;
- }
-
- /* Swap buffers around */
- u8 *temp = frm1;
- frm1 = frm3;
- frm3 = frm2;
- frm2 = temp;
-}
-
-#ifdef MMX
-static void SmartIB32_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- u32 *src0 = (u32 *)srcPtr;
- u32 *src1 = (u32 *)frm1;
- u32 *src2 = (u32 *)frm2;
- u32 *src3 = (u32 *)frm3;
-
- int sPitch = srcPitch >> 2;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
- int count = width >> 1;
-
- for(int i = 0; i < height; i++) {
-#ifdef __GNUC__
- asm volatile (
- "push %4\n"
- "movq 0(%5), %%mm7\n" // colorMask
- "0:\n"
- "movq 0(%0), %%mm0\n" // src0
- "movq 0(%1), %%mm1\n" // src1
- "movq 0(%2), %%mm2\n" // src2
- "movq 0(%3), %%mm3\n" // src3
- "movq %%mm0, 0(%3)\n" // src3 = src0
- "movq %%mm0, %%mm4\n"
- "movq %%mm1, %%mm5\n"
- "pcmpeqd %%mm2, %%mm5\n" // src1 == src2 (A)
- "pcmpeqd %%mm3, %%mm4\n" // src3 == src0 (B)
- "por %%mm5, %%mm4\n" // A | B
- "movq %%mm2, %%mm5\n"
- "pcmpeqd %%mm0, %%mm5\n" // src0 == src2 (C)
- "pcmpeqd %%mm1, %%mm3\n" // src1 == src3 (D)
- "por %%mm3, %%mm5\n" // C|D
- "pandn %%mm5, %%mm4\n" // (!(A|B))&(C|D)
- "movq %%mm0, %%mm2\n"
- "pand %%mm7, %%mm2\n" // color & colorMask
- "pand %%mm7, %%mm1\n" // src1 & colorMask
- "psrld $1, %%mm2\n" // (color & colorMask) >> 1 (E)
- "psrld $1, %%mm1\n" // (src & colorMask) >> 1 (F)
- "paddd %%mm2, %%mm1\n" // E+F
- "pand %%mm4, %%mm1\n" // (E+F) & res
- "pandn %%mm0, %%mm4\n" // color& !res
-
- "por %%mm1, %%mm4\n"
- "movq %%mm4, 0(%0)\n" // src0 = res
-
- "addl $8, %0\n"
- "addl $8, %1\n"
- "addl $8, %2\n"
- "addl $8, %3\n"
-
- "decl %4\n"
- "jnz 0b\n"
- "pop %4\n"
- "emms\n"
- : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (src3)
- : "r" (count), "r" (qRGB_COLOR_MASK)
- );
-#else
- __asm {
- movq mm7, qword ptr [qRGB_COLOR_MASK];
- mov eax, src0;
- mov ebx, src1;
- mov ecx, src2;
- mov edx, src3;
- mov edi, count;
- label0:
- movq mm0, qword ptr [eax]; // src0
- movq mm1, qword ptr [ebx]; // src1
- movq mm2, qword ptr [ecx]; // src2
- movq mm3, qword ptr [edx]; // src3
- movq qword ptr [edx], mm0; // src3 = src0
- movq mm4, mm0;
- movq mm5, mm1;
- pcmpeqd mm5, mm2; // src1 == src2 (A)
- pcmpeqd mm4, mm3; // src3 == src0 (B)
- por mm4, mm5; // A | B
- movq mm5, mm2;
- pcmpeqd mm5, mm0; // src0 == src2 (C)
- pcmpeqd mm3, mm1; // src1 == src3 (D)
- por mm5, mm3; // C|D
- pandn mm4, mm5; // (!(A|B))&(C|D)
- movq mm2, mm0;
- pand mm2, mm7; // color & colorMask
- pand mm1, mm7; // src1 & colorMask
- psrld mm2, 1; // (color & colorMask) >> 1 (E)
- psrld mm1, 1; // (src & colorMask) >> 1 (F)
- paddd mm1, mm2; // E+F
- pand mm1, mm4; // (E+F) & res
- pandn mm4, mm0; // color & !res
-
- por mm4, mm1;
- movq qword ptr [eax], mm4; // src0 = res
-
- add eax, 8;
- add ebx, 8;
- add ecx, 8;
- add edx, 8;
-
- dec edi;
- jnz label0;
- mov src0, eax;
- mov src1, ebx;
- mov src2, ecx;
- mov src3, edx;
- emms;
- }
-#endif
-
- src0 += sPitch;
- src1 += sPitch;
- src2 += sPitch;
- src3 += sPitch;
- }
- /* Swap buffers around */
- u8 *temp = frm1;
- frm1 = frm3;
- frm3 = frm2;
- frm2 = temp;
-}
-#endif
-
-void SmartIB32(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- if(frm1 == NULL) {
- Init();
- }
-#ifdef MMX
- if(cpu_mmx) {
- SmartIB32_MMX(srcPtr, srcPitch, width, height);
- return;
- }
-#endif
-
- u32 *src0 = (u32 *)srcPtr;
- u32 *src1 = (u32 *)frm1;
- u32 *src2 = (u32 *)frm2;
- u32 *src3 = (u32 *)frm3;
-
- u32 colorMask = 0xfefefe;
-
- int sPitch = srcPitch >> 2;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
- int pos = 0;
-
- for (int j = 0; j < height; j++) {
- for (int i = 0; i < width; i++) {
- u32 color = src0[pos];
- src0[pos] =
- (src1[pos] != src2[pos]) &&
- (src3[pos] != color) &&
- ((color == src2[pos]) || (src1[pos] == src3[pos]))
- ? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
- color;
- src3[pos] = color; /* oldest buffer now holds newest frame */
- pos++;
- }
- pos += sPitch;
- }
-
- /* Swap buffers around */
- u8 *temp = frm1;
- frm1 = frm3;
- frm3 = frm2;
- frm2 = temp;
-}
-
-#ifdef MMX
-static void MotionBlurIB_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- u16 *src0 = (u16 *)srcPtr;
- u16 *src1 = (u16 *)frm1;
-
- int sPitch = srcPitch >> 1;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
- int count = width >> 2;
-
- for(int i = 0; i < height; i++) {
-#ifdef __GNUC__
- asm volatile (
- "push %2\n"
- "movq 0(%3), %%mm7\n" // colorMask
- "0:\n"
- "movq 0(%0), %%mm0\n" // src0
- "movq 0(%1), %%mm1\n" // src1
- "movq %%mm0, 0(%1)\n" // src1 = src0
- "pand %%mm7, %%mm0\n" // color & colorMask
- "pand %%mm7, %%mm1\n" // src1 & colorMask
- "psrlw $1, %%mm0\n" // (color & colorMask) >> 1 (E)
- "psrlw $1, %%mm1\n" // (src & colorMask) >> 1 (F)
- "paddw %%mm1, %%mm0\n" // E+F
-
- "movq %%mm0, 0(%0)\n" // src0 = res
-
- "addl $8, %0\n"
- "addl $8, %1\n"
-
- "decl %2\n"
- "jnz 0b\n"
- "pop %2\n"
- "emms\n"
- : "+r" (src0), "+r" (src1)
- : "r" (count), "r" (qRGB_COLOR_MASK)
- );
-#else
- __asm {
- movq mm7, qword ptr [qRGB_COLOR_MASK];
- mov eax, src0;
- mov ebx, src1;
- mov edi, count;
- label0:
- movq mm0, qword ptr [eax]; // src0
- movq mm1, qword ptr [ebx]; // src1
- movq qword ptr [ebx], mm0; // src1 = src0
- pand mm0, mm7; // color & colorMask
- pand mm1, mm7; // src1 & colorMask
- psrlw mm0, 1; // (color & colorMask) >> 1 (E)
- psrlw mm1, 1; // (src & colorMask) >> 1 (F)
- paddw mm0, mm1; // E+F
-
- movq qword ptr [eax], mm0; // src0 = res
-
- add eax, 8;
- add ebx, 8;
-
- dec edi;
- jnz label0;
- mov src0, eax;
- mov src1, ebx;
- emms;
- }
-#endif
- src0 += sPitch;
- src1 += sPitch;
- }
-}
-#endif
-
-void MotionBlurIB(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- if(frm1 == NULL) {
- Init();
- }
-
-#ifdef MMX
- if(cpu_mmx) {
- MotionBlurIB_MMX(srcPtr, srcPitch, width, height);
- return;
- }
-#endif
-
- u16 colorMask = ~RGB_LOW_BITS_MASK;
-
- u16 *src0 = (u16 *)srcPtr;
- u16 *src1 = (u16 *)frm1;
-
- int sPitch = srcPitch >> 1;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
-
- int pos = 0;
- for (int j = 0; j < height; j++) {
- for (int i = 0; i < width; i++) {
- u16 color = src0[pos];
- src0[pos] =
- (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1));
- src1[pos] = color;
- pos++;
- }
- pos += sPitch;
- }
-}
-
-#ifdef MMX
-static void MotionBlurIB32_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- u32 *src0 = (u32 *)srcPtr;
- u32 *src1 = (u32 *)frm1;
-
- int sPitch = srcPitch >> 2;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
- int count = width >> 1;
-
- for(int i = 0; i < height; i++) {
-#ifdef __GNUC__
- asm volatile (
- "push %2\n"
- "movq 0(%3), %%mm7\n" // colorMask
- "0:\n"
- "movq 0(%0), %%mm0\n" // src0
- "movq 0(%1), %%mm1\n" // src1
- "movq %%mm0, 0(%1)\n" // src1 = src0
- "pand %%mm7, %%mm0\n" // color & colorMask
- "pand %%mm7, %%mm1\n" // src1 & colorMask
- "psrld $1, %%mm0\n" // (color & colorMask) >> 1 (E)
- "psrld $1, %%mm1\n" // (src & colorMask) >> 1 (F)
- "paddd %%mm1, %%mm0\n" // E+F
-
- "movq %%mm0, 0(%0)\n" // src0 = res
-
- "addl $8, %0\n"
- "addl $8, %1\n"
-
- "decl %2\n"
- "jnz 0b\n"
- "pop %2\n"
- "emms\n"
- : "+r" (src0), "+r" (src1)
- : "r" (count), "r" (qRGB_COLOR_MASK)
- );
-#else
- __asm {
- movq mm7, qword ptr [qRGB_COLOR_MASK];
- mov eax, src0;
- mov ebx, src1;
- mov edi, count;
- label0:
- movq mm0, qword ptr [eax]; // src0
- movq mm1, qword ptr [ebx]; // src1
- movq qword ptr [ebx], mm0; // src1 = src0
- pand mm0, mm7; // color & colorMask
- pand mm1, mm7; // src1 & colorMask
- psrld mm0, 1; // (color & colorMask) >> 1 (E)
- psrld mm1, 1; // (src & colorMask) >> 1 (F)
- paddd mm0, mm1; // E+F
-
- movq qword ptr [eax], mm0; // src0 = res
-
- add eax, 8;
- add ebx, 8;
-
- dec edi;
- jnz label0;
- mov src0, eax;
- mov src1, ebx;
- emms;
- }
-#endif
- src0 += sPitch;
- src1 += sPitch;
- }
-}
-#endif
-
-void MotionBlurIB32(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- if(frm1 == NULL) {
- Init();
- }
-
-#ifdef MMX
- if(cpu_mmx) {
- MotionBlurIB32_MMX(srcPtr, srcPitch, width, height);
- return;
- }
-#endif
-
- u32 *src0 = (u32 *)srcPtr;
- u32 *src1 = (u32 *)frm1;
-
- u32 colorMask = 0xfefefe;
-
- int sPitch = srcPitch >> 2;
- if (width > sPitch) width = sPitch;
- sPitch -= width;
- int pos = 0;
-
- for (int j = 0; j < height; j++) {
- for (int i = 0; i < width; i++) {
- u32 color = src0[pos];
- src0[pos] = (((color & colorMask) >> 1) +
- ((src1[pos] & colorMask) >> 1));
- src1[pos] = color;
- pos++;
- }
- pos += sPitch;
- }
-}
-
-static int count = 0;
-
-void InterlaceIB(u8 *srcPtr, u32 srcPitch, int width, int height)
-{
- if(frm1 == NULL) {
- Init();
- }
-
- u16 colorMask = ~RGB_LOW_BITS_MASK;
-
- u16 *src0 = (u16 *)srcPtr;
- u16 *src1 = (u16 *)frm1;
-
- int sPitch = srcPitch >> 1;
-
- int pos = 0;
- for (int j = 0; j < height; j++) {
- bool render = count ? (j & 1) != 0 : (j & 1) == 0;
- if(render) {
- for (int i = 0; i < sPitch; i++) {
- u16 color = src0[pos];
- src0[pos] =
- (((color & colorMask) >> 1) + ((((src1[pos] & colorMask) >> 1) & colorMask) >> 1));
- src1[pos] = color;
- pos++;
- }
- } else {
- for (int i = 0; i < sPitch; i++) {
- u16 color = src0[pos];
- src0[pos] =
- (((((color & colorMask) >> 1) & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1));
- src1[pos] = color;
- pos++;
- }
- }
- }
- count = count ^ 1;
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "System.h"
+#include
+#include
+
+#ifdef MMX
+extern "C" bool cpu_mmx;
+#endif
+
+/*
+ * Thanks to Kawaks' Mr. K for the code
+
+ Incorporated into vba by Anthony Di Franco
+*/
+
+static u8 *frm1 = NULL;
+static u8 *frm2 = NULL;
+static u8 *frm3 = NULL;
+
+extern int RGB_LOW_BITS_MASK;
+extern u32 qRGB_COLOR_MASK[2];
+
+static void Init()
+{
+ frm1 = (u8 *)calloc(322*242,4);
+ // 1 frame ago
+ frm2 = (u8 *)calloc(322*242,4);
+ // 2 frames ago
+ frm3 = (u8 *)calloc(322*242,4);
+ // 3 frames ago
+}
+
+void InterframeCleanup()
+{
+ if(frm1)
+ free(frm1);
+ if(frm2)
+ free(frm2);
+ if(frm3)
+ free(frm3);
+ frm1 = frm2 = frm3 = NULL;
+}
+
+#ifdef MMX
+static void SmartIB_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ u16 *src0 = (u16 *)srcPtr;
+ u16 *src1 = (u16 *)frm1;
+ u16 *src2 = (u16 *)frm2;
+ u16 *src3 = (u16 *)frm3;
+
+ int count = width >> 2;
+
+ for(int i = 0; i < height; i++) {
+#ifdef __GNUC__
+ asm volatile (
+ "push %4\n"
+ "movq 0(%5), %%mm7\n" // colorMask
+ "0:\n"
+ "movq 0(%0), %%mm0\n" // src0
+ "movq 0(%1), %%mm1\n" // src1
+ "movq 0(%2), %%mm2\n" // src2
+ "movq 0(%3), %%mm3\n" // src3
+ "movq %%mm0, 0(%3)\n" // src3 = src0
+ "movq %%mm0, %%mm4\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqw %%mm2, %%mm5\n" // src1 == src2 (A)
+ "pcmpeqw %%mm3, %%mm4\n" // src3 == src0 (B)
+ "por %%mm5, %%mm4\n" // A | B
+ "movq %%mm2, %%mm5\n"
+ "pcmpeqw %%mm0, %%mm5\n" // src0 == src2 (C)
+ "pcmpeqw %%mm1, %%mm3\n" // src1 == src3 (D)
+ "por %%mm3, %%mm5\n" // C|D
+ "pandn %%mm5, %%mm4\n" // (!(A|B))&(C|D)
+ "movq %%mm0, %%mm2\n"
+ "pand %%mm7, %%mm2\n" // color & colorMask
+ "pand %%mm7, %%mm1\n" // src1 & colorMask
+ "psrlw $1, %%mm2\n" // (color & colorMask) >> 1 (E)
+ "psrlw $1, %%mm1\n" // (src & colorMask) >> 1 (F)
+ "paddw %%mm2, %%mm1\n" // E+F
+ "pand %%mm4, %%mm1\n" // (E+F) & res
+ "pandn %%mm0, %%mm4\n" // color& !res
+
+ "por %%mm1, %%mm4\n"
+ "movq %%mm4, 0(%0)\n" // src0 = res
+
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $8, %3\n"
+
+ "decl %4\n"
+ "jnz 0b\n"
+ "pop %4\n"
+ "emms\n"
+ : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (src3)
+ : "r" (count), "r" (qRGB_COLOR_MASK)
+ );
+#else
+ __asm {
+ movq mm7, qword ptr [qRGB_COLOR_MASK];
+ mov eax, src0;
+ mov ebx, src1;
+ mov ecx, src2;
+ mov edx, src3;
+ mov edi, count;
+ label0:
+ movq mm0, qword ptr [eax]; // src0
+ movq mm1, qword ptr [ebx]; // src1
+ movq mm2, qword ptr [ecx]; // src2
+ movq mm3, qword ptr [edx]; // src3
+ movq qword ptr [edx], mm0; // src3 = src0
+ movq mm4, mm0;
+ movq mm5, mm1;
+ pcmpeqw mm5, mm2; // src1 == src2 (A)
+ pcmpeqw mm4, mm3; // src3 == src0 (B)
+ por mm4, mm5; // A | B
+ movq mm5, mm2;
+ pcmpeqw mm5, mm0; // src0 == src2 (C)
+ pcmpeqw mm3, mm1; // src1 == src3 (D)
+ por mm5, mm3; // C|D
+ pandn mm4, mm5; // (!(A|B))&(C|D)
+ movq mm2, mm0;
+ pand mm2, mm7; // color & colorMask
+ pand mm1, mm7; // src1 & colorMask
+ psrlw mm2, 1; // (color & colorMask) >> 1 (E)
+ psrlw mm1, 1; // (src & colorMask) >> 1 (F)
+ paddw mm1, mm2; // E+F
+ pand mm1, mm4; // (E+F) & res
+ pandn mm4, mm0; // color & !res
+
+ por mm4, mm1;
+ movq qword ptr [eax], mm4; // src0 = res
+
+ add eax, 8;
+ add ebx, 8;
+ add ecx, 8;
+ add edx, 8;
+
+ dec edi;
+ jnz label0;
+ mov src0, eax;
+ mov src1, ebx;
+ mov src2, ecx;
+ mov src3, edx;
+ emms;
+ }
+#endif
+ src0+=2;
+ src1+=2;
+ src2+=2;
+ src3+=2;
+ }
+
+ /* Swap buffers around */
+ u8 *temp = frm1;
+ frm1 = frm3;
+ frm3 = frm2;
+ frm2 = temp;
+}
+#endif
+
+void SmartIB(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ if(frm1 == NULL) {
+ Init();
+ }
+#ifdef MMX
+ if(cpu_mmx) {
+ SmartIB_MMX(srcPtr, srcPitch, width, height);
+ return;
+ }
+#endif
+
+ u16 colorMask = ~RGB_LOW_BITS_MASK;
+
+ u16 *src0 = (u16 *)srcPtr;
+ u16 *src1 = (u16 *)frm1;
+ u16 *src2 = (u16 *)frm2;
+ u16 *src3 = (u16 *)frm3;
+
+ int sPitch = srcPitch >> 1;
+
+ int pos = 0;
+ for (int j = 0; j < height; j++)
+ for (int i = 0; i < sPitch; i++) {
+ u16 color = src0[pos];
+ src0[pos] =
+ (src1[pos] != src2[pos]) &&
+ (src3[pos] != color) &&
+ ((color == src2[pos]) || (src1[pos] == src3[pos]))
+ ? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
+ color;
+ src3[pos] = color; /* oldest buffer now holds newest frame */
+ pos++;
+ }
+
+ /* Swap buffers around */
+ u8 *temp = frm1;
+ frm1 = frm3;
+ frm3 = frm2;
+ frm2 = temp;
+}
+
+#ifdef MMX
+static void SmartIB32_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ u32 *src0 = (u32 *)srcPtr;
+ u32 *src1 = (u32 *)frm1;
+ u32 *src2 = (u32 *)frm2;
+ u32 *src3 = (u32 *)frm3;
+
+ int count = width >> 1;
+
+ for(int i = 0; i < height; i++) {
+#ifdef __GNUC__
+ asm volatile (
+ "push %4\n"
+ "movq 0(%5), %%mm7\n" // colorMask
+ "0:\n"
+ "movq 0(%0), %%mm0\n" // src0
+ "movq 0(%1), %%mm1\n" // src1
+ "movq 0(%2), %%mm2\n" // src2
+ "movq 0(%3), %%mm3\n" // src3
+ "movq %%mm0, 0(%3)\n" // src3 = src0
+ "movq %%mm0, %%mm4\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqd %%mm2, %%mm5\n" // src1 == src2 (A)
+ "pcmpeqd %%mm3, %%mm4\n" // src3 == src0 (B)
+ "por %%mm5, %%mm4\n" // A | B
+ "movq %%mm2, %%mm5\n"
+ "pcmpeqd %%mm0, %%mm5\n" // src0 == src2 (C)
+ "pcmpeqd %%mm1, %%mm3\n" // src1 == src3 (D)
+ "por %%mm3, %%mm5\n" // C|D
+ "pandn %%mm5, %%mm4\n" // (!(A|B))&(C|D)
+ "movq %%mm0, %%mm2\n"
+ "pand %%mm7, %%mm2\n" // color & colorMask
+ "pand %%mm7, %%mm1\n" // src1 & colorMask
+ "psrld $1, %%mm2\n" // (color & colorMask) >> 1 (E)
+ "psrld $1, %%mm1\n" // (src & colorMask) >> 1 (F)
+ "paddd %%mm2, %%mm1\n" // E+F
+ "pand %%mm4, %%mm1\n" // (E+F) & res
+ "pandn %%mm0, %%mm4\n" // color& !res
+
+ "por %%mm1, %%mm4\n"
+ "movq %%mm4, 0(%0)\n" // src0 = res
+
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $8, %3\n"
+
+ "decl %4\n"
+ "jnz 0b\n"
+ "pop %4\n"
+ "emms\n"
+ : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (src3)
+ : "r" (count), "r" (qRGB_COLOR_MASK)
+ );
+#else
+ __asm {
+ movq mm7, qword ptr [qRGB_COLOR_MASK];
+ mov eax, src0;
+ mov ebx, src1;
+ mov ecx, src2;
+ mov edx, src3;
+ mov edi, count;
+ label0:
+ movq mm0, qword ptr [eax]; // src0
+ movq mm1, qword ptr [ebx]; // src1
+ movq mm2, qword ptr [ecx]; // src2
+ movq mm3, qword ptr [edx]; // src3
+ movq qword ptr [edx], mm0; // src3 = src0
+ movq mm4, mm0;
+ movq mm5, mm1;
+ pcmpeqd mm5, mm2; // src1 == src2 (A)
+ pcmpeqd mm4, mm3; // src3 == src0 (B)
+ por mm4, mm5; // A | B
+ movq mm5, mm2;
+ pcmpeqd mm5, mm0; // src0 == src2 (C)
+ pcmpeqd mm3, mm1; // src1 == src3 (D)
+ por mm5, mm3; // C|D
+ pandn mm4, mm5; // (!(A|B))&(C|D)
+ movq mm2, mm0;
+ pand mm2, mm7; // color & colorMask
+ pand mm1, mm7; // src1 & colorMask
+ psrld mm2, 1; // (color & colorMask) >> 1 (E)
+ psrld mm1, 1; // (src & colorMask) >> 1 (F)
+ paddd mm1, mm2; // E+F
+ pand mm1, mm4; // (E+F) & res
+ pandn mm4, mm0; // color & !res
+
+ por mm4, mm1;
+ movq qword ptr [eax], mm4; // src0 = res
+
+ add eax, 8;
+ add ebx, 8;
+ add ecx, 8;
+ add edx, 8;
+
+ dec edi;
+ jnz label0;
+ mov src0, eax;
+ mov src1, ebx;
+ mov src2, ecx;
+ mov src3, edx;
+ emms;
+ }
+#endif
+
+ src0++;
+ src1++;
+ src2++;
+ src3++;
+ }
+ /* Swap buffers around */
+ u8 *temp = frm1;
+ frm1 = frm3;
+ frm3 = frm2;
+ frm2 = temp;
+}
+#endif
+
+void SmartIB32(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ if(frm1 == NULL) {
+ Init();
+ }
+#ifdef MMX
+ if(cpu_mmx) {
+ SmartIB32_MMX(srcPtr, srcPitch, width, height);
+ return;
+ }
+#endif
+
+ u32 *src0 = (u32 *)srcPtr;
+ u32 *src1 = (u32 *)frm1;
+ u32 *src2 = (u32 *)frm2;
+ u32 *src3 = (u32 *)frm3;
+
+ u32 colorMask = 0xfefefe;
+
+ int sPitch = srcPitch >> 2;
+ int pos = 0;
+
+ for (int j = 0; j < height; j++)
+ for (int i = 0; i < sPitch; i++) {
+ u32 color = src0[pos];
+ src0[pos] =
+ (src1[pos] != src2[pos]) &&
+ (src3[pos] != color) &&
+ ((color == src2[pos]) || (src1[pos] == src3[pos]))
+ ? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
+ color;
+ src3[pos] = color; /* oldest buffer now holds newest frame */
+ pos++;
+ }
+
+ /* Swap buffers around */
+ u8 *temp = frm1;
+ frm1 = frm3;
+ frm3 = frm2;
+ frm2 = temp;
+}
+
+#ifdef MMX
+static void MotionBlurIB_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ u16 *src0 = (u16 *)srcPtr;
+ u16 *src1 = (u16 *)frm1;
+
+ int count = width >> 2;
+
+ for(int i = 0; i < height; i++) {
+#ifdef __GNUC__
+ asm volatile (
+ "push %2\n"
+ "movq 0(%3), %%mm7\n" // colorMask
+ "0:\n"
+ "movq 0(%0), %%mm0\n" // src0
+ "movq 0(%1), %%mm1\n" // src1
+ "movq %%mm0, 0(%1)\n" // src1 = src0
+ "pand %%mm7, %%mm0\n" // color & colorMask
+ "pand %%mm7, %%mm1\n" // src1 & colorMask
+ "psrlw $1, %%mm0\n" // (color & colorMask) >> 1 (E)
+ "psrlw $1, %%mm1\n" // (src & colorMask) >> 1 (F)
+ "paddw %%mm1, %%mm0\n" // E+F
+
+ "movq %%mm0, 0(%0)\n" // src0 = res
+
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+
+ "decl %2\n"
+ "jnz 0b\n"
+ "pop %2\n"
+ "emms\n"
+ : "+r" (src0), "+r" (src1)
+ : "r" (count), "r" (qRGB_COLOR_MASK)
+ );
+#else
+ __asm {
+ movq mm7, qword ptr [qRGB_COLOR_MASK];
+ mov eax, src0;
+ mov ebx, src1;
+ mov edi, count;
+ label0:
+ movq mm0, qword ptr [eax]; // src0
+ movq mm1, qword ptr [ebx]; // src1
+ movq qword ptr [ebx], mm0; // src1 = src0
+ pand mm0, mm7; // color & colorMask
+ pand mm1, mm7; // src1 & colorMask
+ psrlw mm0, 1; // (color & colorMask) >> 1 (E)
+ psrlw mm1, 1; // (src & colorMask) >> 1 (F)
+ paddw mm0, mm1; // E+F
+
+ movq qword ptr [eax], mm0; // src0 = res
+
+ add eax, 8;
+ add ebx, 8;
+
+ dec edi;
+ jnz label0;
+ mov src0, eax;
+ mov src1, ebx;
+ emms;
+ }
+#endif
+ src0+=2;
+ src1+=2;
+ }
+}
+#endif
+
+void MotionBlurIB(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ if(frm1 == NULL) {
+ Init();
+ }
+
+#ifdef MMX
+ if(cpu_mmx) {
+ MotionBlurIB_MMX(srcPtr, srcPitch, width, height);
+ return;
+ }
+#endif
+
+ u16 colorMask = ~RGB_LOW_BITS_MASK;
+
+ u16 *src0 = (u16 *)srcPtr;
+ u16 *src1 = (u16 *)frm1;
+
+ int sPitch = srcPitch >> 1;
+
+ int pos = 0;
+ for (int j = 0; j < height; j++)
+ for (int i = 0; i < sPitch; i++) {
+ u16 color = src0[pos];
+ src0[pos] =
+ (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1));
+ src1[pos] = color;
+ pos++;
+ }
+}
+
+#ifdef MMX
+static void MotionBlurIB32_MMX(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ u32 *src0 = (u32 *)srcPtr;
+ u32 *src1 = (u32 *)frm1;
+
+ int count = width >> 1;
+
+ for(int i = 0; i < height; i++) {
+#ifdef __GNUC__
+ asm volatile (
+ "push %2\n"
+ "movq 0(%3), %%mm7\n" // colorMask
+ "0:\n"
+ "movq 0(%0), %%mm0\n" // src0
+ "movq 0(%1), %%mm1\n" // src1
+ "movq %%mm0, 0(%1)\n" // src1 = src0
+ "pand %%mm7, %%mm0\n" // color & colorMask
+ "pand %%mm7, %%mm1\n" // src1 & colorMask
+ "psrld $1, %%mm0\n" // (color & colorMask) >> 1 (E)
+ "psrld $1, %%mm1\n" // (src & colorMask) >> 1 (F)
+ "paddd %%mm1, %%mm0\n" // E+F
+
+ "movq %%mm0, 0(%0)\n" // src0 = res
+
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+
+ "decl %2\n"
+ "jnz 0b\n"
+ "pop %2\n"
+ "emms\n"
+ : "+r" (src0), "+r" (src1)
+ : "r" (count), "r" (qRGB_COLOR_MASK)
+ );
+#else
+ __asm {
+ movq mm7, qword ptr [qRGB_COLOR_MASK];
+ mov eax, src0;
+ mov ebx, src1;
+ mov edi, count;
+ label0:
+ movq mm0, qword ptr [eax]; // src0
+ movq mm1, qword ptr [ebx]; // src1
+ movq qword ptr [ebx], mm0; // src1 = src0
+ pand mm0, mm7; // color & colorMask
+ pand mm1, mm7; // src1 & colorMask
+ psrld mm0, 1; // (color & colorMask) >> 1 (E)
+ psrld mm1, 1; // (src & colorMask) >> 1 (F)
+ paddd mm0, mm1; // E+F
+
+ movq qword ptr [eax], mm0; // src0 = res
+
+ add eax, 8;
+ add ebx, 8;
+
+ dec edi;
+ jnz label0;
+ mov src0, eax;
+ mov src1, ebx;
+ emms;
+ }
+#endif
+ src0++;
+ src1++;
+ }
+}
+#endif
+
+void MotionBlurIB32(u8 *srcPtr, u32 srcPitch, int width, int height)
+{
+ if(frm1 == NULL) {
+ Init();
+ }
+
+#ifdef MMX
+ if(cpu_mmx) {
+ MotionBlurIB32_MMX(srcPtr, srcPitch, width, height);
+ return;
+ }
+#endif
+
+ u32 *src0 = (u32 *)srcPtr;
+ u32 *src1 = (u32 *)frm1;
+
+ u32 colorMask = 0xfefefe;
+
+ int sPitch = srcPitch >> 2;
+ int pos = 0;
+
+ for (int j = 0; j < height; j++)
+ for (int i = 0; i < sPitch; i++) {
+ u32 color = src0[pos];
+ src0[pos] = (((color & colorMask) >> 1) +
+ ((src1[pos] & colorMask) >> 1));
+ src1[pos] = color;
+ pos++;
+ }
+}
diff --git a/src/interp.h b/src/interp.h
index b899ea73..9df8856a 100644
--- a/src/interp.h
+++ b/src/interp.h
@@ -40,11 +40,6 @@
static unsigned interp_mask[2];
static unsigned interp_bits_per_pixel;
-typedef unsigned short interp_uint16;
-typedef unsigned int interp_uint32;
-
-#define restrict
-
#define INTERP_16_MASK_1(v) (v & interp_mask[0])
#define INTERP_16_MASK_2(v) (v & interp_mask[1])
diff --git a/src/memgzio.cpp b/src/memgzio.c
similarity index 93%
rename from src/memgzio.cpp
rename to src/memgzio.c
index 2d1d2040..528539c3 100644
--- a/src/memgzio.cpp
+++ b/src/memgzio.c
@@ -9,7 +9,7 @@
* Adapted from original gzio.c from zlib library by Forgotten
*/
-/* @(#) $Id: memgzio.c,v 1.3 2004/01/17 23:07:32 kxu Exp $ */
+/* @(#) $Id: memgzio.c,v 1.5 2006/06/06 21:04:20 spacy51 Exp $ */
#include
#include
@@ -125,7 +125,7 @@ local size_t memWrite(const void *buffer, size_t size, size_t count,
total = file->available;
}
memcpy(file->next, buffer, total);
- file->available -= total;
+ file->available -= (int)total;
file->next += total;
return total;
}
@@ -147,7 +147,7 @@ local size_t memRead(void *buffer, size_t size, size_t count,
total = file->available;
}
memcpy(buffer, file->next, total);
- file->available -= total;
+ file->available -= (int)total;
file->next += total;
return total;
}
@@ -170,7 +170,7 @@ local int memPutc(int c, MEMFILE *file)
local long memTell(MEMFILE *f)
{
- return (f->next - f->memory) - 8;
+ return (long)(f->next - f->memory) - 8;
}
local int memError(MEMFILE *f)
@@ -197,7 +197,7 @@ local int memPrintf(MEMFILE *f, const char *format, ...)
len = vsprintf(buffer, format, list);
va_end(list);
- return memWrite(buffer, 1, len, f);
+ return (int)memWrite(buffer, 1, len, f);
}
/* ===========================================================================
@@ -209,7 +209,10 @@ local int memPrintf(MEMFILE *f, const char *format, ...)
can be checked to distinguish the two cases (if errno is zero, the
zlib error is Z_MEM_ERROR).
*/
-local gzFile gz_open (char *memory, const int available, const char *mode)
+local gzFile gz_open (memory, available, mode)
+ char *memory;
+ const int available;
+ const char *mode;
{
int err;
int level = Z_DEFAULT_COMPRESSION; /* compression level */
@@ -309,7 +312,10 @@ local gzFile gz_open (char *memory, const int available, const char *mode)
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing.
*/
-gzFile ZEXPORT memgzopen (char *memory, int available, const char *mode)
+gzFile ZEXPORT memgzopen (memory, available, mode)
+ char *memory;
+ int available;
+ const char *mode;
{
return gz_open (memory, available, mode);
}
@@ -319,12 +325,13 @@ gzFile ZEXPORT memgzopen (char *memory, int available, const char *mode)
for end of file.
IN assertion: the stream s has been sucessfully opened for reading.
*/
-local int get_byte(mem_stream *s)
+local int get_byte(s)
+ mem_stream *s;
{
if (s->z_eof) return EOF;
if (s->stream.avail_in == 0) {
errno = 0;
- s->stream.avail_in = memRead(s->inbuf, 1, Z_BUFSIZE, s->file);
+ s->stream.avail_in = (uInt)memRead(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) {
s->z_eof = 1;
if (memError(s->file)) s->z_err = Z_ERRNO;
@@ -345,7 +352,8 @@ local int get_byte(mem_stream *s)
s->stream.avail_in is zero for the first time, but may be non-zero
for concatenated .gz files.
*/
-local void check_header(mem_stream *s)
+local void check_header(s)
+ mem_stream *s;
{
int method; /* method byte */
int flags; /* flags byte */
@@ -397,7 +405,8 @@ local void check_header(mem_stream *s)
* Cleanup then free the given mem_stream. Return a zlib error code.
Try freeing in the reverse order of allocations.
*/
-local int destroy (mem_stream *s)
+local int destroy (s)
+ mem_stream *s;
{
int err = Z_OK;
@@ -434,7 +443,10 @@ local int destroy (mem_stream *s)
Reads the given number of uncompressed bytes from the compressed file.
gzread returns the number of bytes actually read (0 for end of file).
*/
-int ZEXPORT memgzread (gzFile file, voidp buf, unsigned len)
+int ZEXPORT memgzread (file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
{
mem_stream *s = (mem_stream*)file;
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
@@ -464,8 +476,7 @@ int ZEXPORT memgzread (gzFile file, voidp buf, unsigned len)
s->stream.avail_in -= n;
}
if (s->stream.avail_out > 0) {
- s->stream.avail_out -= memRead(next_out, 1, s->stream.avail_out,
- s->file);
+ s->stream.avail_out -= (uInt)memRead(next_out, 1, s->stream.avail_out, s->file);
}
len -= s->stream.avail_out;
s->stream.total_in += (uLong)len;
@@ -476,7 +487,7 @@ int ZEXPORT memgzread (gzFile file, voidp buf, unsigned len)
if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0;
- s->stream.avail_in = memRead(s->inbuf, 1, Z_BUFSIZE, s->file);
+ s->stream.avail_in = (uInt)memRead(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) {
s->z_eof = 1;
if (memError(s->file)) {
@@ -526,7 +537,10 @@ int ZEXPORT memgzread (gzFile file, voidp buf, unsigned len)
Writes the given number of uncompressed bytes into the compressed file.
gzwrite returns the number of bytes actually written (0 in case of error).
*/
-int ZEXPORT memgzwrite (gzFile file, const voidp buf, unsigned len)
+int ZEXPORT memgzwrite (file, buf, len)
+ gzFile file;
+ const voidp buf;
+ unsigned len;
{
mem_stream *s = (mem_stream*)file;
@@ -558,7 +572,9 @@ int ZEXPORT memgzwrite (gzFile file, const voidp buf, unsigned len)
Flushes all pending output into the compressed file. The parameter
flush is as in the deflate() function.
*/
-local int do_flush (gzFile file, int flush)
+local int do_flush (file, flush)
+ gzFile file;
+ int flush;
{
uInt len;
int done = 0;
@@ -598,7 +614,9 @@ local int do_flush (gzFile file, int flush)
/* ===========================================================================
Outputs a long in LSB order to the given file
*/
-local void putLong (MEMFILE *file, uLong x)
+local void putLong (file, x)
+ MEMFILE *file;
+ uLong x;
{
int n;
for (n = 0; n < 4; n++) {
@@ -611,7 +629,8 @@ local void putLong (MEMFILE *file, uLong x)
Reads a long in LSB order from the given mem_stream. Sets z_err in case
of error.
*/
-local uLong getLong (mem_stream *s)
+local uLong getLong (s)
+ mem_stream *s;
{
uLong x = (uLong)get_byte(s);
int c;
@@ -628,7 +647,8 @@ local uLong getLong (mem_stream *s)
Flushes all pending output if necessary, closes the compressed file
and deallocates all the (de)compression state.
*/
-int ZEXPORT memgzclose (gzFile file)
+int ZEXPORT memgzclose (file)
+ gzFile file;
{
int err;
mem_stream *s = (mem_stream*)file;
@@ -649,7 +669,8 @@ int ZEXPORT memgzclose (gzFile file)
return destroy((mem_stream*)file);
}
-long ZEXPORT memtell(gzFile file)
+long ZEXPORT memtell(file)
+ gzFile file;
{
mem_stream *s = (mem_stream*)file;
diff --git a/src/memgzio.h b/src/memgzio.h
index 3f761411..d4b4ad77 100644
--- a/src/memgzio.h
+++ b/src/memgzio.h
@@ -8,7 +8,12 @@
/* memgzio.c - IO on .gz files in memory
* Adapted from original gzio.c from zlib library by Forgotten
*/
-#include
+
+#if defined(HAVE_ZUTIL_H) || defined(_WIN32)
+# include
+#else
+# include "../win32/dependencies/zlib/zutil.h"
+#endif
gzFile ZEXPORT memgzopen(char *memory, int, const char *);
int ZEXPORT memgzread(gzFile, voidp, unsigned);
diff --git a/src/remote.cpp b/src/remote.cpp
index 40fdb3df..d673a553 100644
--- a/src/remote.cpp
+++ b/src/remote.cpp
@@ -20,7 +20,7 @@
#include
#include
-#ifndef WIN32
+#ifndef _WIN32
# include
# include
# include
@@ -32,14 +32,15 @@
# else // ! HAVE_ARPA_INET_H
# define socklen_t int
# endif // ! HAVE_ARPA_INET_H
-#else // WIN32
+# define SOCKET int
+#else // _WIN32
# include
# include
# define socklen_t int
# define close closesocket
# define read _read
# define write _write
-#endif // WIN32
+#endif // _WIN32
#include "GBA.h"
@@ -54,8 +55,8 @@ extern void debuggerSignal(int,int);
int remotePort = 55555;
int remoteSignal = 5;
-int remoteSocket = -1;
-int remoteListenSocket = -1;
+SOCKET remoteSocket = -1;
+SOCKET remoteListenSocket = -1;
bool remoteConnected = false;
bool remoteResumed = false;
@@ -85,11 +86,11 @@ int remoteTcpRecv(char *data, int len)
bool remoteTcpInit()
{
if(remoteSocket == -1) {
-#ifdef WIN32
+#ifdef _WIN32
WSADATA wsaData;
int error = WSAStartup(MAKEWORD(1,1),&wsaData);
-#endif // WIN32
- int s = socket(PF_INET, SOCK_STREAM, 0);
+#endif // _WIN32
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
remoteListenSocket = s;
@@ -131,19 +132,19 @@ bool remoteTcpInit()
}
socklen_t len = sizeof(addr);
-#ifdef WIN32
+#ifdef _WIN32
int flag = 0;
ioctlsocket(s, FIONBIO, (unsigned long *)&flag);
-#endif // WIN32
- int s2 = accept(s, (sockaddr *)&addr, &len);
+#endif // _WIN32
+ SOCKET s2 = accept(s, (sockaddr *)&addr, &len);
if(s2 > 0) {
fprintf(stderr, "Got a connection from %s %d\n",
inet_ntoa((in_addr)addr.sin_addr),
ntohs(addr.sin_port));
} else {
-#ifdef WIN32
+#ifdef _WIN32
int error = WSAGetLastError();
-#endif // WIN32
+#endif // _WIN32
}
char dummy;
recv(s2, &dummy, 1, 0);
@@ -230,14 +231,14 @@ void remotePutPacket(char *packet)
char *hex = "0123456789abcdef";
char buffer[1024];
- int count = strlen(packet);
+ size_t count = strlen(packet);
unsigned char csum = 0;
char *p = buffer;
*p++ = '$';
- for(int i = 0 ;i < count; i++) {
+ for(size_t i = 0 ;i < count; i++) {
csum += packet[i];
*p++ = packet[i];
}
@@ -246,7 +247,7 @@ void remotePutPacket(char *packet)
*p++ = hex[csum & 15];
*p++ = 0;
// printf("Sending %s\n", buffer);
- remoteSendFnc(buffer, count + 4);
+ remoteSendFnc(buffer, (int)count + 4);
char c = 0;
remoteRecvFnc(&c, 1);
diff --git a/src/thumb.h b/src/thumb.h
index 51502583..ebf036a6 100644
--- a/src/thumb.h
+++ b/src/thumb.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -17,6 +17,17 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+// The following define updates oldreg when debugger_last is activated
+
+#define UPDATE_OLD_REG \
+ if (debugger_last) { \
+ sprintf(oldbuffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 4); \
+ for (xxx=0; xxx<18; xxx++){ \
+ oldreg[xxx]=reg[xxx].I; \
+ } \
+ }
+
+
#ifdef C_CORE
#define NEG(i) ((i) >> 31)
#define POS(i) ((~(i)) >> 31)
@@ -763,16 +774,29 @@
#endif
#endif
-u32 opcode = CPUReadHalfWordQuick(armNextPC);
-clockTicks = thumbCycles[opcode >> 8] + memoryWaitFetch[(armNextPC >> 24) & 15];
+
+#ifdef BKPT_SUPPORT
+u8 xxx;
+#endif
+
+u32 opcode = cpuPrefetch[0];
+cpuPrefetch[0] = cpuPrefetch[1];
+
+busPrefetch = false;
+ if (busPrefetchCount & 0xFFFFFF00)
+ busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF);
+
+clockTicks = 0;
+u32 oldArmNextPC = armNextPC;
#ifndef FINAL_VERSION
if(armNextPC == stop) {
- armNextPC = armNextPC++;
+ armNextPC++;
}
#endif
armNextPC = reg[15].I;
reg[15].I += 2;
+THUMB_PREFETCH_NEXT;
switch(opcode >> 8) {
case 0x00:
@@ -901,54 +925,22 @@ switch(opcode >> 8) {
}
break;
case 0x20:
- // MOV R0, #Offset8
- reg[0].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[0].I ? false : true);
- break;
case 0x21:
- // MOV R1, #Offset8
- reg[1].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[1].I ? false : true);
- break;
case 0x22:
- // MOV R2, #Offset8
- reg[2].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[2].I ? false : true);
- break;
case 0x23:
- // MOV R3, #Offset8
- reg[3].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[3].I ? false : true);
- break;
case 0x24:
- // MOV R4, #Offset8
- reg[4].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[4].I ? false : true);
- break;
case 0x25:
- // MOV R5, #Offset8
- reg[5].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[5].I ? false : true);
- break;
case 0x26:
- // MOV R6, #Offset8
- reg[6].I = opcode & 255;
- N_FLAG = false;
- Z_FLAG = (reg[6].I ? false : true);
- break;
case 0x27:
- // MOV R7, #Offset8
- reg[7].I = opcode & 255;
+ {
+ u8 regist = (opcode >> 8) & 7;
+ // MOV R0~R7, #Offset8
+ reg[regist].I = opcode & 255;
N_FLAG = false;
- Z_FLAG = (reg[7].I ? false : true);
+ Z_FLAG = (reg[regist].I ? false : true);
+ }
break;
- case 0x28:
+case 0x28:
// CMP R0, #Offset8
CMP_RN_O8(0);
break;
@@ -1044,6 +1036,7 @@ switch(opcode >> 8) {
// SUB R7,#Offset8
SUB_RN_O8(7);
break;
+
case 0x40:
switch((opcode >> 6) & 3) {
case 0x00:
@@ -1093,7 +1086,7 @@ switch(opcode >> 8) {
}
N_FLAG = reg[dest].I & 0x80000000 ? true : false;
Z_FLAG = reg[dest].I ? false : true;
- clockTicks++;
+ clockTicks = codeTicksAccess16(armNextPC)+2;
}
break;
case 0x03:
@@ -1115,7 +1108,7 @@ switch(opcode >> 8) {
}
N_FLAG = reg[dest].I & 0x80000000 ? true : false;
Z_FLAG = reg[dest].I ? false : true;
- clockTicks++;
+ clockTicks = codeTicksAccess16(armNextPC)+2;
}
break;
}
@@ -1144,7 +1137,7 @@ switch(opcode >> 8) {
}
N_FLAG = reg[dest].I & 0x80000000 ? true : false;
Z_FLAG = reg[dest].I ? false : true;
- clockTicks++;
+ clockTicks = codeTicksAccess16(armNextPC)+2;
}
break;
case 0x01:
@@ -1181,7 +1174,7 @@ switch(opcode >> 8) {
reg[dest].I = value;
}
}
- clockTicks++;
+ clockTicks = codeTicksAccess16(armNextPC)+2;
N_FLAG = reg[dest].I & 0x80000000 ? true : false;
Z_FLAG = reg[dest].I ? false : true;
}
@@ -1239,19 +1232,22 @@ switch(opcode >> 8) {
case 0x01:
{
// MUL Rd, Rs
+ clockTicks = 1;
int dest = opcode & 7;
- u32 rm = reg[(opcode >> 3) & 7].I;
- reg[dest].I = reg[dest].I * rm;
+ u32 rm = reg[dest].I;
+ reg[dest].I = reg[(opcode >> 3) & 7].I * rm;
if (((s32)rm) < 0)
rm = ~rm;
if ((rm & 0xFFFFFF00) == 0)
- clockTicks += 1;
+ clockTicks += 0;
else if ((rm & 0xFFFF0000) == 0)
- clockTicks += 2;
+ clockTicks += 1;
else if ((rm & 0xFF000000) == 0)
- clockTicks += 3;
+ clockTicks += 2;
else
- clockTicks += 4;
+ clockTicks += 3;
+ busPrefetchCount = (busPrefetchCount<>(8-clockTicks));
+ clockTicks += codeTicksAccess16(armNextPC) + 1;
Z_FLAG = reg[dest].I ? false : true;
N_FLAG = reg[dest].I & 0x80000000 ? true : false;
}
@@ -1294,7 +1290,9 @@ switch(opcode >> 8) {
reg[15].I &= 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
- clockTicks++;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC)+1;
+ clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1;
}
break;
case 3:
@@ -1304,7 +1302,9 @@ switch(opcode >> 8) {
reg[15].I &= 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
- clockTicks++;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC)+1;
+ clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1;
}
break;
}
@@ -1359,20 +1359,33 @@ switch(opcode >> 8) {
// MOV Hd, Rs
reg[dest+8].I = reg[base].I;
if(dest == 7) {
+#ifdef BKPT_SUPPORT
+ UPDATE_OLD_REG
+#endif
+
reg[15].I &= 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
- clockTicks++;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC)+1;
+ clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1;
}
break;
case 3:
// MOV Hd, Hs
reg[dest+8].I = reg[base+8].I;
if(dest == 7) {
+
+#ifdef BKPT_SUPPORT
+ UPDATE_OLD_REG
+#endif
+
reg[15].I &= 0xFFFFFFFE;
armNextPC = reg[15].I;
reg[15].I += 2;
- clockTicks++;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC)+1;
+ clockTicks += clockTicks+codeTicksAccess16(armNextPC)+1;
}
break;
}
@@ -1381,33 +1394,54 @@ switch(opcode >> 8) {
case 0x47:
{
int base = (opcode >> 3) & 7;
+ busPrefetchCount=0;
switch((opcode >>6) & 3) {
case 0:
// BX Rs
+#ifdef BKPT_SUPPORT
+ UPDATE_OLD_REG
+#endif
reg[15].I = (reg[base].I) & 0xFFFFFFFE;
if(reg[base].I & 1) {
armState = false;
armNextPC = reg[15].I;
reg[15].I += 2;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC) +
+ codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
} else {
armState = true;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks = codeTicksAccessSeq32(armNextPC) +
+ codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
}
break;
case 1:
// BX Hs
+
+#ifdef BKPT_SUPPORT
+ UPDATE_OLD_REG
+#endif
+
reg[15].I = (reg[8+base].I) & 0xFFFFFFFE;
if(reg[8+base].I & 1) {
armState = false;
armNextPC = reg[15].I;
reg[15].I += 2;
+ THUMB_PREFETCH;
+ clockTicks = dataTicksAccess16(armNextPC) + dataTicksAccess16(armNextPC) +
+ codeTicksAccess16(armNextPC) + 3;
} else {
armState = true;
reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I;
reg[15].I += 4;
+ ARM_PREFETCH;
+ clockTicks = dataTicksAccess32(armNextPC) + dataTicksAccess32(armNextPC) +
+ codeTicksAccess32(armNextPC) + 3;
}
break;
default:
@@ -1416,143 +1450,119 @@ switch(opcode >> 8) {
}
break;
case 0x48:
- // LDR R0,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[0].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x49:
- // LDR R1,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[1].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x4a:
- // LDR R2,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[2].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x4b:
- // LDR R3,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[3].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x4c:
- // LDR R4,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[4].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x4d:
- // LDR R5,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[5].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x4e:
- // LDR R6,[PC, #Imm]
- {
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[6].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x4f:
- // LDR R7,[PC, #Imm]
+ // LDR R0~R7,[PC, #Imm]
{
- u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[7].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
+ u8 regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
+ reg[regist].I = CPUReadMemoryQuick(address);
+ busPrefetchCount=0;
+ clockTicks = 3 + dataTicksAccess32(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x50:
case 0x51:
// STR Rd, [Rs, Rn]
{
- u32
- address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
CPUWriteMemory(address,
reg[opcode & 7].I);
- clockTicks += CPUUpdateTicksAccess32(address);
+ clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
case 0x52:
case 0x53:
// STRH Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
CPUWriteHalfWord(address,
reg[opcode&7].W.W0);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
case 0x54:
case 0x55:
// STRB Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I;
CPUWriteByte(address,
reg[opcode & 7].B.B0);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
case 0x56:
case 0x57:
// LDSB Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
reg[opcode&7].I = (s8)CPUReadByte(address);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = 3 + dataTicksAccess16(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x58:
case 0x59:
// LDR Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
reg[opcode&7].I = CPUReadMemory(address);
- clockTicks += CPUUpdateTicksAccess32(address);
+ clockTicks = 3 + dataTicksAccess32(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x5a:
case 0x5b:
// LDRH Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
reg[opcode&7].I = CPUReadHalfWord(address);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = 3 + dataTicksAccess32(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x5c:
case 0x5d:
// LDRB Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
reg[opcode&7].I = CPUReadByte(address);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = 3 + dataTicksAccess16(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x5e:
case 0x5f:
// LDSH Rd, [Rs, Rn]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = 3 + dataTicksAccess16(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x60:
@@ -1565,10 +1575,12 @@ switch(opcode >> 8) {
case 0x67:
// STR Rd, [Rs, #Imm]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
CPUWriteMemory(address,
reg[opcode&7].I);
- clockTicks += CPUUpdateTicksAccess32(address);
+ clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
case 0x68:
@@ -1581,9 +1593,12 @@ switch(opcode >> 8) {
case 0x6f:
// LDR Rd, [Rs, #Imm]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
reg[opcode&7].I = CPUReadMemory(address);
- clockTicks += CPUUpdateTicksAccess32(address);
+ clockTicks = 3 + dataTicksAccess32(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x70:
@@ -1596,10 +1611,12 @@ switch(opcode >> 8) {
case 0x77:
// STRB Rd, [Rs, #Imm]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
CPUWriteByte(address,
reg[opcode&7].B.B0);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
case 0x78:
@@ -1612,9 +1629,12 @@ switch(opcode >> 8) {
case 0x7f:
// LDRB Rd, [Rs, #Imm]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
reg[opcode&7].I = CPUReadByte(address);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = 3 + dataTicksAccess16(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x80:
@@ -1627,10 +1647,12 @@ switch(opcode >> 8) {
case 0x87:
// STRH Rd, [Rs, #Imm]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
CPUWriteHalfWord(address,
reg[opcode&7].W.W0);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
case 0x88:
@@ -1643,203 +1665,79 @@ switch(opcode >> 8) {
case 0x8f:
// LDRH Rd, [Rs, #Imm]
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
reg[opcode&7].I = CPUReadHalfWord(address);
- clockTicks += CPUUpdateTicksAccess16(address);
+ clockTicks = 3 + dataTicksAccess16(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0x90:
- // STR R0, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[0].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x91:
- // STR R1, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[1].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x92:
- // STR R2, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[2].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x93:
- // STR R3, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[3].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x94:
- // STR R4, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[4].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x95:
- // STR R5, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[5].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x96:
- // STR R6, [SP, #Imm]
+ case 0x97:
+ // STR R0~R7, [SP, #Imm]
{
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[6].I);
- clockTicks += CPUUpdateTicksAccess32(address);
+ u8 regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ u32 address = reg[13].I + ((opcode&255)<<2);
+ CPUWriteMemory(address, reg[regist].I);
+ clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
}
break;
- case 0x97:
- // STR R7, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[7].I);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x98:
- // LDR R0, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[0].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x99:
- // LDR R1, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[1].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x9a:
- // LDR R2, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[2].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x9b:
- // LDR R3, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[3].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x9c:
- // LDR R4, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[4].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x9d:
- // LDR R5, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[5].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x9e:
- // LDR R6, [SP, #Imm]
- {
- u32 address = reg[13].I + ((opcode&255)<<2);
- reg[6].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
- }
- break;
case 0x9f:
- // LDR R7, [SP, #Imm]
+ // LDR R0~R7, [SP, #Imm]
{
+ u8 regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
u32 address = reg[13].I + ((opcode&255)<<2);
- reg[7].I = CPUReadMemoryQuick(address);
- clockTicks += CPUUpdateTicksAccess32(address);
+ reg[regist].I = CPUReadMemoryQuick(address);
+ clockTicks = 3 + dataTicksAccess32(address) +
+ codeTicksAccess16(armNextPC);
}
break;
case 0xa0:
- // ADD R0, PC, Imm
- reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa1:
- // ADD R1, PC, Imm
- reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa2:
- // ADD R2, PC, Imm
- reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa3:
- // ADD R3, PC, Imm
- reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa4:
- // ADD R4, PC, Imm
- reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa5:
- // ADD R5, PC, Imm
- reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa6:
- // ADD R6, PC, Imm
- reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- break;
case 0xa7:
- // ADD R7, PC, Imm
- reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
+ {
+ // ADD R0~R7, PC, Imm
+ u8 regist = (opcode >> 8) & 7;
+ reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
+ }
break;
case 0xa8:
- // ADD R0, SP, Imm
- reg[0].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xa9:
- // ADD R1, SP, Imm
- reg[1].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xaa:
- // ADD R2, SP, Imm
- reg[2].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xab:
- // ADD R3, SP, Imm
- reg[3].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xac:
- // ADD R4, SP, Imm
- reg[4].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xad:
- // ADD R5, SP, Imm
- reg[5].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xae:
- // ADD R6, SP, Imm
- reg[6].I = reg[13].I + ((opcode&255)<<2);
- break;
case 0xaf:
- // ADD R7, SP, Imm
- reg[7].I = reg[13].I + ((opcode&255)<<2);
- break;
+ {
+ // ADD R0~R7, SP, Imm
+ u8 regist = (opcode >> 8) & 7;
+ reg[regist].I = reg[13].I + ((opcode&255)<<2);
+ }
+ break;
case 0xb0:
{
// ADD SP, Imm
@@ -1853,15 +1751,17 @@ switch(opcode >> 8) {
if(opcode & (val)) {\
CPUWriteMemory(address, reg[(r)].I);\
if(offset)\
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
else\
- clockTicks += 1 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccess32(address);\
offset = 1;\
address += 4;\
}
case 0xb4:
// PUSH {Rlist}
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = 0;
u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
u32 address = temp & 0xFFFFFFFC;
@@ -1873,12 +1773,15 @@ switch(opcode >> 8) {
PUSH_REG(32, 5);
PUSH_REG(64, 6);
PUSH_REG(128, 7);
+ clockTicks += codeTicksAccess16(armNextPC)+1;
reg[13].I = temp;
}
break;
case 0xb5:
// PUSH {Rlist, LR}
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = 0;
u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
u32 address = temp & 0xFFFFFFFC;
@@ -1891,6 +1794,7 @@ switch(opcode >> 8) {
PUSH_REG(64, 6);
PUSH_REG(128, 7);
PUSH_REG(256, 14);
+ clockTicks += codeTicksAccess16(armNextPC)+1;
reg[13].I = temp;
}
break;
@@ -1898,18 +1802,21 @@ switch(opcode >> 8) {
if(opcode & (val)) {\
reg[(r)].I = CPUReadMemory(address);\
if(offset)\
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
else\
- clockTicks += 2 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccess32(address);\
offset = 1;\
address += 4;\
}
case 0xbc:
// POP {Rlist}
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = 0;
u32 address = reg[13].I & 0xFFFFFFFC;
u32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
+ clockTicks = 0;
POP_REG(1, 0);
POP_REG(2, 1);
POP_REG(4, 2);
@@ -1919,14 +1826,18 @@ switch(opcode >> 8) {
POP_REG(64, 6);
POP_REG(128, 7);
reg[13].I = temp;
+ clockTicks += codeTicksAccess16(armNextPC)+2;
}
break;
case 0xbd:
// POP {Rlist, PC}
{
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
int offset = 0;
u32 address = reg[13].I & 0xFFFFFFFC;
u32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
+ clockTicks = 0;
POP_REG(1, 0);
POP_REG(2, 1);
POP_REG(4, 2);
@@ -1937,12 +1848,15 @@ switch(opcode >> 8) {
POP_REG(128, 7);
reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
if(offset)
- clockTicks += CPUUpdateTicksAccessSeq32(address);
+ clockTicks += 1 + dataTicksAccessSeq32(address);
else
- clockTicks += CPUUpdateTicksAccess32(address);
+ clockTicks += 1 + dataTicksAccess32(address);
armNextPC = reg[15].I;
reg[15].I += 2;
reg[13].I = temp;
+ THUMB_PREFETCH;
+ busPrefetchCount=0;
+ clockTicks += codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
}
break;
#define THUMB_STM_REG(val,r,b) \
@@ -1950,297 +1864,67 @@ switch(opcode >> 8) {
CPUWriteMemory(address, reg[(r)].I);\
if(!offset) {\
reg[(b)].I = temp;\
- clockTicks += 1 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccess32(address);\
} else \
- clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
offset = 1;\
address += 4;\
}
case 0xc0:
- {
- // STM R0!, {Rlist}
- u32 address = reg[0].I & 0xFFFFFFFC;
- u32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 0);
- THUMB_STM_REG(2, 1, 0);
- THUMB_STM_REG(4, 2, 0);
- THUMB_STM_REG(8, 3, 0);
- THUMB_STM_REG(16, 4, 0);
- THUMB_STM_REG(32, 5, 0);
- THUMB_STM_REG(64, 6, 0);
- THUMB_STM_REG(128, 7, 0);
- }
- break;
case 0xc1:
- {
- // STM R1!, {Rlist}
- u32 address = reg[1].I & 0xFFFFFFFC;
- u32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 1);
- THUMB_STM_REG(2, 1, 1);
- THUMB_STM_REG(4, 2, 1);
- THUMB_STM_REG(8, 3, 1);
- THUMB_STM_REG(16, 4, 1);
- THUMB_STM_REG(32, 5, 1);
- THUMB_STM_REG(64, 6, 1);
- THUMB_STM_REG(128, 7, 1);
- }
- break;
case 0xc2:
- {
- // STM R2!, {Rlist}
- u32 address = reg[2].I & 0xFFFFFFFC;
- u32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 2);
- THUMB_STM_REG(2, 1, 2);
- THUMB_STM_REG(4, 2, 2);
- THUMB_STM_REG(8, 3, 2);
- THUMB_STM_REG(16, 4, 2);
- THUMB_STM_REG(32, 5, 2);
- THUMB_STM_REG(64, 6, 2);
- THUMB_STM_REG(128, 7, 2);
- }
- break;
case 0xc3:
- {
- // STM R3!, {Rlist}
- u32 address = reg[3].I & 0xFFFFFFFC;
- u32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 3);
- THUMB_STM_REG(2, 1, 3);
- THUMB_STM_REG(4, 2, 3);
- THUMB_STM_REG(8, 3, 3);
- THUMB_STM_REG(16, 4, 3);
- THUMB_STM_REG(32, 5, 3);
- THUMB_STM_REG(64, 6, 3);
- THUMB_STM_REG(128, 7, 3);
- }
- break;
case 0xc4:
- {
- // STM R4!, {Rlist}
- u32 address = reg[4].I & 0xFFFFFFFC;
- u32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 4);
- THUMB_STM_REG(2, 1, 4);
- THUMB_STM_REG(4, 2, 4);
- THUMB_STM_REG(8, 3, 4);
- THUMB_STM_REG(16, 4, 4);
- THUMB_STM_REG(32, 5, 4);
- THUMB_STM_REG(64, 6, 4);
- THUMB_STM_REG(128, 7, 4);
- }
- break;
case 0xc5:
- {
- // STM R5!, {Rlist}
- u32 address = reg[5].I & 0xFFFFFFFC;
- u32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 5);
- THUMB_STM_REG(2, 1, 5);
- THUMB_STM_REG(4, 2, 5);
- THUMB_STM_REG(8, 3, 5);
- THUMB_STM_REG(16, 4, 5);
- THUMB_STM_REG(32, 5, 5);
- THUMB_STM_REG(64, 6, 5);
- THUMB_STM_REG(128, 7, 5);
- }
- break;
case 0xc6:
- {
- // STM R6!, {Rlist}
- u32 address = reg[6].I & 0xFFFFFFFC;
- u32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xff];
- int offset = 0;
- // store
- THUMB_STM_REG(1, 0, 6);
- THUMB_STM_REG(2, 1, 6);
- THUMB_STM_REG(4, 2, 6);
- THUMB_STM_REG(8, 3, 6);
- THUMB_STM_REG(16, 4, 6);
- THUMB_STM_REG(32, 5, 6);
- THUMB_STM_REG(64, 6, 6);
- THUMB_STM_REG(128, 7, 6);
- }
- break;
case 0xc7:
{
- // STM R7!, {Rlist}
- u32 address = reg[7].I & 0xFFFFFFFC;
- u32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xff];
+ // STM R0~7!, {Rlist}
+ u8 regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ u32 address = reg[regist].I & 0xFFFFFFFC;
+ u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
int offset = 0;
// store
- THUMB_STM_REG(1, 0, 7);
- THUMB_STM_REG(2, 1, 7);
- THUMB_STM_REG(4, 2, 7);
- THUMB_STM_REG(8, 3, 7);
- THUMB_STM_REG(16, 4, 7);
- THUMB_STM_REG(32, 5, 7);
- THUMB_STM_REG(64, 6, 7);
- THUMB_STM_REG(128, 7, 7);
+ THUMB_STM_REG(1, 0, regist);
+ THUMB_STM_REG(2, 1, regist);
+ THUMB_STM_REG(4, 2, regist);
+ THUMB_STM_REG(8, 3, regist);
+ THUMB_STM_REG(16, 4, regist);
+ THUMB_STM_REG(32, 5, regist);
+ THUMB_STM_REG(64, 6, regist);
+ THUMB_STM_REG(128, 7, regist);
+ clockTicks = codeTicksAccess16(armNextPC)+1;
}
- break;
+ break;
#define THUMB_LDM_REG(val,r) \
if(opcode & (val)) {\
reg[(r)].I = CPUReadMemory(address);\
if(offset)\
- clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);\
- else\
- clockTicks += 2 + CPUUpdateTicksAccess32(address);\
+ clockTicks += 1 + dataTicksAccessSeq32(address);\
+ else \
+ clockTicks += 1 + dataTicksAccess32(address);\
offset = 1;\
address += 4;\
}
case 0xc8:
- {
- // LDM R0!, {Rlist}
- u32 address = reg[0].I & 0xFFFFFFFC;
- u32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 1))
- reg[0].I = temp;
- }
- break;
case 0xc9:
- {
- // LDM R1!, {Rlist}
- u32 address = reg[1].I & 0xFFFFFFFC;
- u32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 2))
- reg[1].I = temp;
- }
- break;
case 0xca:
- {
- // LDM R2!, {Rlist}
- u32 address = reg[2].I & 0xFFFFFFFC;
- u32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 4))
- reg[2].I = temp;
- }
- break;
case 0xcb:
- {
- // LDM R3!, {Rlist}
- u32 address = reg[3].I & 0xFFFFFFFC;
- u32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 8))
- reg[3].I = temp;
- }
- break;
case 0xcc:
- {
- // LDM R4!, {Rlist}
- u32 address = reg[4].I & 0xFFFFFFFC;
- u32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 16))
- reg[4].I = temp;
- }
- break;
case 0xcd:
- {
- // LDM R5!, {Rlist}
- u32 address = reg[5].I & 0xFFFFFFFC;
- u32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 32))
- reg[5].I = temp;
- }
- break;
case 0xce:
- {
- // LDM R6!, {Rlist}
- u32 address = reg[6].I & 0xFFFFFFFC;
- u32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xFF];
- int offset = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 64))
- reg[6].I = temp;
- }
- break;
case 0xcf:
{
- // LDM R7!, {Rlist}
- u32 address = reg[7].I & 0xFFFFFFFC;
- u32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xFF];
+ // LDM R0~R7!, {Rlist}
+ u8 regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ u32 address = reg[regist].I & 0xFFFFFFFC;
+ u32 temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
int offset = 0;
+ clockTicks = 0;
// load
THUMB_LDM_REG(1, 0);
THUMB_LDM_REG(2, 1);
@@ -2249,141 +1933,232 @@ switch(opcode >> 8) {
THUMB_LDM_REG(16, 4);
THUMB_LDM_REG(32, 5);
THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- if(!(opcode & 128))
- reg[7].I = temp;
+ THUMB_LDM_REG(128, 7);
+ clockTicks += codeTicksAccess16(armNextPC)+2;
+ if(!(opcode & (1<> 8) {
reg[15].I += offset;
armNextPC = reg[15].I;
reg[15].I += 2;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
+ codeTicksAccess16(armNextPC) + 3;
+ busPrefetchCount=0;
}
break;
case 0xf0:
@@ -2410,6 +2189,7 @@ switch(opcode >> 8) {
// BLL #offset
int offset = (opcode & 0x7FF);
reg[14].I = reg[15].I + (offset << 12);
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
}
break;
case 0xf4:
@@ -2420,6 +2200,7 @@ switch(opcode >> 8) {
// BLL #offset
int offset = (opcode & 0x7FF);
reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000);
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
}
break;
case 0xf8:
@@ -2438,6 +2219,10 @@ switch(opcode >> 8) {
armNextPC = reg[15].I;
reg[15].I += 2;
reg[14].I = temp|1;
+ THUMB_PREFETCH;
+ clockTicks = codeTicksAccessSeq16(armNextPC) +
+ codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3;
+ busPrefetchCount = 0;
}
break;
#ifdef BKPT_SUPPORT
@@ -2472,3 +2257,6 @@ switch(opcode >> 8) {
CPUUndefinedException();
break;
}
+
+if (clockTicks==0)
+clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1;
diff --git a/src/unzip.cpp b/src/unzip.cpp
index 98c50e94..876691a5 100644
--- a/src/unzip.cpp
+++ b/src/unzip.cpp
@@ -154,7 +154,7 @@ typedef struct
local int unzlocal_getByte(FILE *fin,int *pi)
{
unsigned char c;
- int err = fread(&c, 1, 1, fin);
+ size_t err = fread(&c, 1, 1, fin);
if (err==1)
{
*pi = (int)c;
diff --git a/src/win32/AboutDialog.cpp b/src/win32/AboutDialog.cpp
index 0d634e2b..f558fd14 100644
--- a/src/win32/AboutDialog.cpp
+++ b/src/win32/AboutDialog.cpp
@@ -19,8 +19,9 @@
// AboutDialog.cpp : implementation file
//
+#include "stdafx.h"
#include "AboutDialog.h"
-#include "..\..\res\resource.h"
+#include "../AutoBuild.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -63,15 +64,13 @@ BOOL AboutDialog::OnInitDialog()
{
CDialog::OnInitDialog();
+ CWnd *p = GetDlgItem(IDC_TRANSLATOR_URL);
+ if(p) {
+ m_translator.SubclassDlgItem(IDC_TRANSLATOR_URL, this);
+ }
+
m_link.SetWindowText("http://vba.ngemu.com");
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
-
-void AboutDialog::OnOK()
-{
- // TODO: Add extra validation here
-
- CDialog::OnOK();
-}
diff --git a/src/win32/AboutDialog.h b/src/win32/AboutDialog.h
index fdb48d3d..aacc74d8 100644
--- a/src/win32/AboutDialog.h
+++ b/src/win32/AboutDialog.h
@@ -27,7 +27,7 @@
//
#include "stdafx.h"
#include "Hyperlink.h"
-#include "..\..\res\resource.h"
+#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
// AboutDialog dialog
@@ -60,7 +60,6 @@ class AboutDialog : public CDialog
// Generated message map functions
//{{AFX_MSG(AboutDialog)
virtual BOOL OnInitDialog();
- virtual void OnOK();
//}}AFX_MSG
diff --git a/src/win32/AccelEditor.cpp b/src/win32/AccelEditor.cpp
index 0747e26e..b632914d 100644
--- a/src/win32/AccelEditor.cpp
+++ b/src/win32/AccelEditor.cpp
@@ -156,7 +156,7 @@ void AccelEditor::OnSelchangeCommands()
pAccel->GetString(szBuffer);
index = m_currents.AddString(szBuffer);
// and a pointer to the accel object.
- m_currents.SetItemData(index, (DWORD)pAccel);
+ m_currents.SetItemData(index, (DWORD_PTR)pAccel);
}
}
// Init the key editor
@@ -180,12 +180,12 @@ void AccelEditor::OnAssign()
WORD wKey;
bool bCtrl, bAlt, bShift;
- int index;
-
+
if (!m_key.GetAccelKey(wKey, bCtrl, bAlt, bShift))
return; // no valid key, abort
int count = m_commands.GetCount();
+ int index;
for (index = 0; index < count; index++) {
wIDCommand = LOWORD(m_commands.GetItemData(index));
@@ -235,7 +235,7 @@ void AccelEditor::OnAssign()
pAccel->GetString(szBuffer);
index = m_currents.AddString(szBuffer);
- m_currents.SetItemData(index, (DWORD)pAccel);
+ m_currents.SetItemData(index, (DWORD_PTR)pAccel);
// Reset the key editor.
m_key.ResetKey();
diff --git a/src/win32/AcceleratorManager.cpp b/src/win32/AcceleratorManager.cpp
index ad4d4cfb..ca3f8fc6 100644
--- a/src/win32/AcceleratorManager.cpp
+++ b/src/win32/AcceleratorManager.cpp
@@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
-//#include "..\..\res\resource.h"
+//#include "resource.h"
#include "../System.h"
#include "AcceleratorManager.h"
@@ -247,7 +247,7 @@ bool CAcceleratorManager::UpdateWndTable()
}
}
- int nAccel = arrayACCEL.GetSize();
+ INT_PTR nAccel = arrayACCEL.GetSize();
LPACCEL lpAccel = (LPACCEL)LocalAlloc(LPTR, nAccel * sizeof(ACCEL));
if (!lpAccel) {
for (iLoop = 0; iLoop < nAccel; iLoop++)
@@ -268,7 +268,7 @@ bool CAcceleratorManager::UpdateWndTable()
}
arrayACCEL.RemoveAll();
- HACCEL hNewTable = CreateAcceleratorTable(lpAccel, nAccel);
+ HACCEL hNewTable = CreateAcceleratorTable(lpAccel, (int)nAccel);
if (!hNewTable) {
::LocalFree(lpAccel);
return false;
@@ -709,14 +709,14 @@ bool CAcceleratorManager::Write()
}
// AccelsDatasArray.InsertAt(0, MAKELONG(65535, iCount));
- int count = AccelsDatasArray.GetSize();
+ INT_PTR count = AccelsDatasArray.GetSize();
DWORD *data = (DWORD *)malloc(count * sizeof(DWORD));
ASSERT(data != NULL);
for(int index = 0; index < count; index++)
data[index] = AccelsDatasArray[index];
- regSetBinaryValue("keyboard", (char *)data, count*sizeof(DWORD));
+ regSetBinaryValue("keyboard", (char *)data, (int)(count*sizeof(DWORD)));
AccelsDatasArray.RemoveAll();
CmdDatasArray.RemoveAll();
diff --git a/src/win32/AcceleratorManager.h b/src/win32/AcceleratorManager.h
index c0b12885..1999c57c 100644
--- a/src/win32/AcceleratorManager.h
+++ b/src/win32/AcceleratorManager.h
@@ -33,6 +33,7 @@
#endif // _MSC_VER >= 1000
+
#include "CmdAccelOb.h"
diff --git a/src/win32/BitmapControl.h b/src/win32/BitmapControl.h
index f2f0c4d8..8a847553 100644
--- a/src/win32/BitmapControl.h
+++ b/src/win32/BitmapControl.h
@@ -20,7 +20,7 @@
#if !defined(AFX_BITMAPCONTROL_H__2434AADB_B6A5_4E43_AA16_7B65B6F7FA26__INCLUDED_)
#define AFX_BITMAPCONTROL_H__2434AADB_B6A5_4E43_AA16_7B65B6F7FA26__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/BugReport.cpp b/src/win32/BugReport.cpp
index ad7c31f9..ce4dcd4d 100644
--- a/src/win32/BugReport.cpp
+++ b/src/win32/BugReport.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
#include "BugReport.h"
#include "../agbprint.h"
+#include "../AutoBuild.h"
#include "../GBA.h"
#include "../Globals.h"
#include "../Port.h"
@@ -215,7 +216,6 @@ CString BugReport::createReport()
AppendFormat(report, "Using BIOS : %d\r\n", theApp.useBiosFile);
AppendFormat(report, "Skip BIOS : %d\r\n", theApp.skipBiosFile);
AppendFormat(report, "Disable SFX : %d\r\n", cpuDisableSfx);
- AppendFormat(report, "Skip intro : %d\r\n", theApp.removeIntros);
AppendFormat(report, "Throttle : %d\r\n", theApp.throttle);
AppendFormat(report, "Rewind : %d\r\n", theApp.rewindTimer);
AppendFormat(report, "Auto frame : %d\r\n", theApp.autoFrameSkip);
@@ -226,6 +226,7 @@ CString BugReport::createReport()
AppendFormat(report, "Green shift : %08x\r\n", systemGreenShift);
AppendFormat(report, "Blue shift : %08x\r\n", systemBlueShift);
AppendFormat(report, "Layer setting: %04X\r\n", layerSettings);
+ AppendFormat(report, "Mirroring : %d\r\n", mirroringEnable);
AppendFormat(report, "Save type : %d (%d)\r\n",
theApp.winSaveType, cpuSaveType);
AppendFormat(report, "Flash size : %08X (%08x)\r\n",
diff --git a/src/win32/CmdAccelOb.cpp b/src/win32/CmdAccelOb.cpp
index 4172b726..a911b9b3 100644
--- a/src/win32/CmdAccelOb.cpp
+++ b/src/win32/CmdAccelOb.cpp
@@ -1,526 +1,527 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 1998 by Thierry Maurel
-// All rights reserved
-//
-// Distribute freely, except: don't remove my name from the source or
-// documentation (don't take credit for my work), mark your changes (don't
-// get me blamed for your possible bugs), don't alter or remove this
-// notice.
-// No warrantee of any kind, express or implied, is included with this
-// software; use at your own risk, responsibility for damages (if any) to
-// anyone resulting from the use of this software rests entirely with the
-// user.
-//
-// Send bug reports, bug fixes, enhancements, requests, flames, etc., and
-// I'll try to keep a version up to date. I can be reached as follows:
-// tmaurel@caramail.com (or tmaurel@hol.fr)
-//
-////////////////////////////////////////////////////////////////////////////////
-// File : CmdAccelOb.cpp
-// Project : AccelsEditor
-////////////////////////////////////////////////////////////////////////////////
-// Version : 1.0 * Author : T.Maurel
-// Date : 17.08.98
-//
-// Remarks :
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include "stdafx.h"
-#include "CmdAccelOb.h"
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-MAPVIRTKEYS mapVirtKeys[] = {
- {VK_LBUTTON, "VK_LBUTTON"},
- {VK_RBUTTON, "VK_RBUTTON"},
- {VK_CANCEL, "VK_CANCEL"},
- {VK_MBUTTON, "VK_MBUTTON"},
- {VK_BACK, "BACK"},
- {VK_TAB, "TAB"},
- {VK_CLEAR, "VK_CLEAR"},
- {VK_RETURN, "RETURN"},
- {VK_SHIFT, "SHIFT"},
- {VK_CONTROL, "CONTROL"},
- {VK_MENU, "MENU"},
- {VK_PAUSE, "PAUSE"},
- {VK_CAPITAL, "CAPITAL"},
- {VK_ESCAPE, "ESCAPE"},
- {VK_SPACE, "SPACE"},
- {VK_PRIOR, "PRIOR"},
- {VK_NEXT, "NEXT"},
- {VK_END, "END"},
- {VK_HOME, "HOME"},
- {VK_LEFT, "LEFT"},
- {VK_UP, "UP"},
- {VK_RIGHT, "RIGHT"},
- {VK_DOWN, "DOWN"},
- {VK_SELECT, "VK_SELECT"},
- {VK_PRINT, "PRINT"},
- {VK_EXECUTE, "EXECUTE"},
- {VK_SNAPSHOT, "SNAPSHOT"},
- {VK_INSERT, "INSERT"},
- {VK_DELETE, "DELETE"},
- {VK_HELP, "VK_HELP"},
- {WORD('0'), "0"},
- {WORD('1'), "1"},
- {WORD('2'), "2"},
- {WORD('3'), "3"},
- {WORD('4'), "4"},
- {WORD('5'), "5"},
- {WORD('6'), "6"},
- {WORD('7'), "7"},
- {WORD('8'), "8"},
- {WORD('9'), "9"},
- {WORD('A'), "A"},
- {WORD('B'), "B"},
- {WORD('C'), "C"},
- {WORD('D'), "D"},
- {WORD('E'), "E"},
- {WORD('F'), "F"},
- {WORD('G'), "G"},
- {WORD('H'), "H"},
- {WORD('I'), "I"},
- {WORD('J'), "J"},
- {WORD('K'), "K"},
- {WORD('L'), "L"},
- {WORD('M'), "M"},
- {WORD('N'), "N"},
- {WORD('O'), "O"},
- {WORD('P'), "P"},
- {WORD('Q'), "Q"},
- {WORD('R'), "R"},
- {WORD('S'), "S"},
- {WORD('T'), "T"},
- {WORD('U'), "U"},
- {WORD('V'), "V"},
- {WORD('W'), "W"},
- {WORD('X'), "X"},
- {WORD('Y'), "Y"},
- {WORD('Z'), "Z"},
- {VK_LWIN, "VK_LWIN"},
- {VK_RWIN, "VK_RWIN"},
- {VK_APPS, "VK_APPS"},
- {VK_NUMPAD0, "NUMPAD0"},
- {VK_NUMPAD1, "NUMPAD1"},
- {VK_NUMPAD2, "NUMPAD2"},
- {VK_NUMPAD3, "NUMPAD3"},
- {VK_NUMPAD4, "NUMPAD4"},
- {VK_NUMPAD5, "NUMPAD5"},
- {VK_NUMPAD6, "NUMPAD6"},
- {VK_NUMPAD7, "NUMPAD7"},
- {VK_NUMPAD8, "NUMPAD8"},
- {VK_NUMPAD9, "NUMPAD9"},
- {VK_MULTIPLY, "MULTIPLY"},
- {VK_ADD, "ADD"},
- {VK_SEPARATOR, "SEPARATOR"},
- {VK_SUBTRACT, "SUBTRACT"},
- {VK_DECIMAL, "DECIMAL"},
- {VK_DIVIDE, "DIVIDE"},
- {VK_F1, "F1"},
- {VK_F2, "F2"},
- {VK_F3, "F3"},
- {VK_F4, "F4"},
- {VK_F5, "F5"},
- {VK_F6, "F6"},
- {VK_F7, "F7"},
- {VK_F8, "F8"},
- {VK_F9, "F9"},
- {VK_F10, "F10"},
- {VK_F11, "F11"},
- {VK_F12, "F12"},
- {VK_F13, "F13"},
- {VK_F14, "F14"},
- {VK_F15, "F15"},
- {VK_F16, "F16"},
- {VK_F17, "F17"},
- {VK_F18, "F18"},
- {VK_F19, "F19"},
- {VK_F20, "F20"},
- {VK_F21, "F21"},
- {VK_F22, "F22"},
- {VK_F23, "F23"},
- {VK_F24, "F24"},
- {VK_NUMLOCK, "NUMLOCK"},
- {VK_SCROLL, "VK_SCROLL"},
- {VK_ATTN, "VK_ATTN"},
- {VK_CRSEL, "VK_CRSEL"},
- {VK_EXSEL, "VK_EXSEL"},
- {VK_EREOF, "VK_EREOF"},
- {VK_PLAY, "VK_PLAY"},
- {VK_ZOOM, "VK_ZOOM"},
- {VK_NONAME, "VK_NONAME"},
- {VK_PA1, "VK_PA1"},
- {VK_OEM_CLEAR, "VK_OEM_CLEAR"},
-};
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-MAPVIRTKEYS mapVirtSysKeys[] = {
- {FCONTROL, "Ctrl"},
- {FALT, "Alt"},
- {FSHIFT, "Shift"},
-};
-
-
-////////////////////////////////////////////////////////////////////////
-// helper fct for external access
-////////////////////////////////////////////////////////////////////////
-//
-//
-TCHAR* mapVirtKeysStringFromWORD(WORD wKey)
-{
- for (int index = 0; index < sizeof(mapVirtKeys)/sizeof(mapVirtKeys[0]); index++) {
- if (mapVirtKeys[index].wKey == wKey)
- return mapVirtKeys[index].szKey;
- }
- return NULL;
-}
-
-
-
-////////////////////////////////////////////////////////////////////////
-//
-#define DEFAULT_ACCEL 0x01
-#define USER_ACCEL 0x02
-
-
-////////////////////////////////////////////////////////////////////////
-//
-////////////////////////////////////////////////////////////////////////
-//
-//
-CAccelsOb::CAccelsOb()
-{
- m_cVirt = 0;
- m_wKey = 0;
- m_bLocked = false;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CAccelsOb::CAccelsOb(CAccelsOb* pFrom)
-{
- ASSERT(pFrom != NULL);
-
- m_cVirt = pFrom->m_cVirt;
- m_wKey = pFrom->m_wKey;
- m_bLocked = pFrom->m_bLocked;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CAccelsOb::CAccelsOb(BYTE cVirt, WORD wKey, bool bLocked)
-{
- m_cVirt = cVirt;
- m_wKey = wKey;
- m_bLocked = bLocked;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CAccelsOb::CAccelsOb(LPACCEL pACCEL)
-{
- ASSERT(pACCEL != NULL);
-
- m_cVirt = pACCEL->fVirt;
- m_wKey = pACCEL->key;
- m_bLocked = false;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CAccelsOb& CAccelsOb::operator=(const CAccelsOb& from)
-{
- m_cVirt = from.m_cVirt;
- m_wKey = from.m_wKey;
- m_bLocked = from.m_bLocked;
-
- return *this;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CAccelsOb::GetString(CString& szBuffer)
-{
- szBuffer = "";
- // in case of the object is not assigned, we avoid error messages
- if (m_wKey == 0)
- return;
-
- // modifiers part
- for (int i = 0; i < sizetable(mapVirtSysKeys); i++) {
- if (m_cVirt & mapVirtSysKeys[i].wKey) {
- szBuffer += mapVirtSysKeys[i].szKey;
- szBuffer += "+";
- }
- }
- // and virtual key part
- if (1) for (int i = 0; i < sizetable(mapVirtKeys); i++) {
- if (m_wKey == mapVirtKeys[i].wKey) {
- szBuffer += mapVirtKeys[i].szKey;
- return;
- }
- }
- AfxMessageBox("Internal error : (CAccelsOb::GetString) m_wKey invalid");
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-bool CAccelsOb::IsEqual(WORD wKey, bool bCtrl, bool bAlt, bool bShift)
-{
- // CString szTemp;
- // GetString(szTemp);
-
-
- bool m_bCtrl = (m_cVirt & FCONTROL) ? true : false;
- bool bRet = (bCtrl == m_bCtrl);
-
- bool m_bAlt = (m_cVirt & FALT) ? true : false;
- bRet &= (bAlt == m_bAlt);
-
- bool m_bShift = (m_cVirt & FSHIFT) ? true : false;
- bRet &= (bShift == m_bShift);
-
- bRet &= static_cast(m_wKey == wKey);
-
- return bRet;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-DWORD CAccelsOb::GetData()
-{
- BYTE cLocalCodes = 0;
- if (m_bLocked)
- cLocalCodes = DEFAULT_ACCEL;
- else
- cLocalCodes = USER_ACCEL;
-
- WORD bCodes = MAKEWORD(m_cVirt, cLocalCodes);
- return MAKELONG(m_wKey, bCodes);
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-bool CAccelsOb::SetData(DWORD dwDatas)
-{
- m_wKey = LOWORD(dwDatas);
-
- WORD bCodes = HIWORD(dwDatas);
- m_cVirt = LOBYTE(bCodes);
-
- BYTE cLocalCodes = HIBYTE(bCodes);
- m_bLocked = static_cast(cLocalCodes == DEFAULT_ACCEL);
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-#ifdef _DEBUG
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CAccelsOb::AssertValid() const
-{
- CObject::AssertValid();
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CAccelsOb::Dump(CDumpContext& dc) const
-{
- dc << "\t\t";
- CObject::Dump(dc);
- dc << "\t\tlocked=" << m_bLocked << ", cVirt=" << m_cVirt << ", wKey=" << m_wKey << "\n\n";
-
-}
-#endif
-
-////////////////////////////////////////////////////////////////////////
-//
-////////////////////////////////////////////////////////////////////////
-//
-//
-CCmdAccelOb::CCmdAccelOb()
-{
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CCmdAccelOb::CCmdAccelOb(WORD wIDCommand, LPCTSTR szCommand)
-{
- ASSERT(szCommand != NULL);
-
- m_wIDCommand = wIDCommand;
- m_szCommand = szCommand;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CCmdAccelOb::CCmdAccelOb(BYTE cVirt, WORD wIDCommand, WORD wKey, LPCTSTR szCommand, bool bLocked)
-{
- ASSERT(szCommand != NULL);
-
- m_wIDCommand = wIDCommand;
- m_szCommand = szCommand;
-
- CAccelsOb* pAccel = DEBUG_NEW CAccelsOb(cVirt, wKey, bLocked);
- ASSERT(pAccel != NULL);
- m_Accels.AddTail(pAccel);
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CCmdAccelOb::~CCmdAccelOb()
-{
- POSITION pos = m_Accels.GetHeadPosition();
- while (pos != NULL)
- delete m_Accels.GetNext(pos);
- m_Accels.RemoveAll();
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CCmdAccelOb::Add(BYTE cVirt, WORD wKey, bool bLocked)
-{
- CAccelsOb* pAccel = DEBUG_NEW CAccelsOb(cVirt, wKey, bLocked);
- ASSERT(pAccel != NULL);
- m_Accels.AddTail(pAccel);
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CCmdAccelOb::Add(CAccelsOb* pAccel)
-{
- ASSERT(pAccel != NULL);
- m_Accels.AddTail(pAccel);
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-CCmdAccelOb& CCmdAccelOb::operator=(const CCmdAccelOb& from)
-{
- Reset();
-
- m_wIDCommand = from.m_wIDCommand;
- m_szCommand = from.m_szCommand;
-
- CAccelsOb* pAccel;
- POSITION pos = from.m_Accels.GetHeadPosition();
- while (pos != NULL) {
- pAccel = DEBUG_NEW CAccelsOb(from.m_Accels.GetNext(pos));
- ASSERT(pAccel != NULL);
- m_Accels.AddTail(pAccel);
- }
- return *this;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CCmdAccelOb::DeleteUserAccels()
-{
- CAccelsOb* pAccel;
- POSITION prevPos;
- POSITION pos = m_Accels.GetHeadPosition();
- while (pos != NULL) {
- prevPos = pos;
- pAccel = m_Accels.GetNext(pos);
- if (!pAccel->m_bLocked) {
- delete pAccel;
- m_Accels.RemoveAt(prevPos);
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CCmdAccelOb::Reset()
-{
- m_wIDCommand = 0;
- m_szCommand = "Empty command";
-
- CAccelsOb* pAccel;
- POSITION pos = m_Accels.GetHeadPosition();
- while (pos != NULL) {
- pAccel = m_Accels.GetNext(pos);
- delete pAccel;
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-#ifdef _DEBUG
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CCmdAccelOb::AssertValid() const
-{
- // call base class function first
- CObject::AssertValid();
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-void CCmdAccelOb::Dump( CDumpContext& dc ) const
-{
- // call base class function first
- dc << "\t";
- CObject::Dump( dc );
-
- // now do the stuff for our specific class
- dc << "\tIDCommand = " << m_wIDCommand;
- dc << "\n\tszCommand = " << m_szCommand;
- dc << "\n\tAccelerators = {\n";
-
- CAccelsOb* pAccel;
- POSITION pos = m_Accels.GetHeadPosition();
- while (pos != NULL) {
- pAccel = m_Accels.GetNext(pos);
- dc << pAccel;
- }
- dc << "\t}\n";
-}
-#endif
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1998 by Thierry Maurel
+// All rights reserved
+//
+// Distribute freely, except: don't remove my name from the source or
+// documentation (don't take credit for my work), mark your changes (don't
+// get me blamed for your possible bugs), don't alter or remove this
+// notice.
+// No warrantee of any kind, express or implied, is included with this
+// software; use at your own risk, responsibility for damages (if any) to
+// anyone resulting from the use of this software rests entirely with the
+// user.
+//
+// Send bug reports, bug fixes, enhancements, requests, flames, etc., and
+// I'll try to keep a version up to date. I can be reached as follows:
+// tmaurel@caramail.com (or tmaurel@hol.fr)
+//
+////////////////////////////////////////////////////////////////////////////////
+// File : CmdAccelOb.cpp
+// Project : AccelsEditor
+////////////////////////////////////////////////////////////////////////////////
+// Version : 1.0 * Author : T.Maurel
+// Date : 17.08.98
+//
+// Remarks :
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CmdAccelOb.h"
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+MAPVIRTKEYS mapVirtKeys[] = {
+ {VK_LBUTTON, "VK_LBUTTON"},
+ {VK_RBUTTON, "VK_RBUTTON"},
+ {VK_CANCEL, "VK_CANCEL"},
+ {VK_MBUTTON, "VK_MBUTTON"},
+ {VK_BACK, "BACK"},
+ {VK_TAB, "TAB"},
+ {VK_CLEAR, "VK_CLEAR"},
+ {VK_RETURN, "RETURN"},
+ {VK_SHIFT, "SHIFT"},
+ {VK_CONTROL, "CONTROL"},
+ {VK_MENU, "MENU"},
+ {VK_PAUSE, "PAUSE"},
+ {VK_CAPITAL, "CAPITAL"},
+ {VK_ESCAPE, "ESCAPE"},
+ {VK_SPACE, "SPACE"},
+ {VK_PRIOR, "PRIOR"},
+ {VK_NEXT, "NEXT"},
+ {VK_END, "END"},
+ {VK_HOME, "HOME"},
+ {VK_LEFT, "LEFT"},
+ {VK_UP, "UP"},
+ {VK_RIGHT, "RIGHT"},
+ {VK_DOWN, "DOWN"},
+ {VK_SELECT, "VK_SELECT"},
+ {VK_PRINT, "PRINT"},
+ {VK_EXECUTE, "EXECUTE"},
+ {VK_SNAPSHOT, "SNAPSHOT"},
+ {VK_INSERT, "INSERT"},
+ {VK_DELETE, "DELETE"},
+ {VK_HELP, "VK_HELP"},
+ {WORD('0'), "0"},
+ {WORD('1'), "1"},
+ {WORD('2'), "2"},
+ {WORD('3'), "3"},
+ {WORD('4'), "4"},
+ {WORD('5'), "5"},
+ {WORD('6'), "6"},
+ {WORD('7'), "7"},
+ {WORD('8'), "8"},
+ {WORD('9'), "9"},
+ {WORD('A'), "A"},
+ {WORD('B'), "B"},
+ {WORD('C'), "C"},
+ {WORD('D'), "D"},
+ {WORD('E'), "E"},
+ {WORD('F'), "F"},
+ {WORD('G'), "G"},
+ {WORD('H'), "H"},
+ {WORD('I'), "I"},
+ {WORD('J'), "J"},
+ {WORD('K'), "K"},
+ {WORD('L'), "L"},
+ {WORD('M'), "M"},
+ {WORD('N'), "N"},
+ {WORD('O'), "O"},
+ {WORD('P'), "P"},
+ {WORD('Q'), "Q"},
+ {WORD('R'), "R"},
+ {WORD('S'), "S"},
+ {WORD('T'), "T"},
+ {WORD('U'), "U"},
+ {WORD('V'), "V"},
+ {WORD('W'), "W"},
+ {WORD('X'), "X"},
+ {WORD('Y'), "Y"},
+ {WORD('Z'), "Z"},
+ {VK_LWIN, "VK_LWIN"},
+ {VK_RWIN, "VK_RWIN"},
+ {VK_APPS, "VK_APPS"},
+ {VK_NUMPAD0, "NUMPAD0"},
+ {VK_NUMPAD1, "NUMPAD1"},
+ {VK_NUMPAD2, "NUMPAD2"},
+ {VK_NUMPAD3, "NUMPAD3"},
+ {VK_NUMPAD4, "NUMPAD4"},
+ {VK_NUMPAD5, "NUMPAD5"},
+ {VK_NUMPAD6, "NUMPAD6"},
+ {VK_NUMPAD7, "NUMPAD7"},
+ {VK_NUMPAD8, "NUMPAD8"},
+ {VK_NUMPAD9, "NUMPAD9"},
+ {VK_MULTIPLY, "MULTIPLY"},
+ {VK_ADD, "ADD"},
+ {VK_SEPARATOR, "SEPARATOR"},
+ {VK_SUBTRACT, "SUBTRACT"},
+ {VK_DECIMAL, "DECIMAL"},
+ {VK_DIVIDE, "DIVIDE"},
+ {VK_F1, "F1"},
+ {VK_F2, "F2"},
+ {VK_F3, "F3"},
+ {VK_F4, "F4"},
+ {VK_F5, "F5"},
+ {VK_F6, "F6"},
+ {VK_F7, "F7"},
+ {VK_F8, "F8"},
+ {VK_F9, "F9"},
+ {VK_F10, "F10"},
+ {VK_F11, "F11"},
+ {VK_F12, "F12"},
+ {VK_F13, "F13"},
+ {VK_F14, "F14"},
+ {VK_F15, "F15"},
+ {VK_F16, "F16"},
+ {VK_F17, "F17"},
+ {VK_F18, "F18"},
+ {VK_F19, "F19"},
+ {VK_F20, "F20"},
+ {VK_F21, "F21"},
+ {VK_F22, "F22"},
+ {VK_F23, "F23"},
+ {VK_F24, "F24"},
+ {VK_NUMLOCK, "NUMLOCK"},
+ {VK_SCROLL, "VK_SCROLL"},
+ {VK_ATTN, "VK_ATTN"},
+ {VK_CRSEL, "VK_CRSEL"},
+ {VK_EXSEL, "VK_EXSEL"},
+ {VK_EREOF, "VK_EREOF"},
+ {VK_PLAY, "VK_PLAY"},
+ {VK_ZOOM, "VK_ZOOM"},
+ {VK_NONAME, "VK_NONAME"},
+ {VK_PA1, "VK_PA1"},
+ {VK_OEM_CLEAR, "VK_OEM_CLEAR"},
+};
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+MAPVIRTKEYS mapVirtSysKeys[] = {
+ {FCONTROL, "Ctrl"},
+ {FALT, "Alt"},
+ {FSHIFT, "Shift"},
+};
+
+
+////////////////////////////////////////////////////////////////////////
+// helper fct for external access
+////////////////////////////////////////////////////////////////////////
+//
+//
+TCHAR* mapVirtKeysStringFromWORD(WORD wKey)
+{
+ for (int index = 0; index < sizeof(mapVirtKeys)/sizeof(mapVirtKeys[0]); index++) {
+ if (mapVirtKeys[index].wKey == wKey)
+ return mapVirtKeys[index].szKey;
+ }
+ return NULL;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+//
+#define DEFAULT_ACCEL 0x01
+#define USER_ACCEL 0x02
+
+
+////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////
+//
+//
+CAccelsOb::CAccelsOb()
+{
+ m_cVirt = 0;
+ m_wKey = 0;
+ m_bLocked = false;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CAccelsOb::CAccelsOb(CAccelsOb* pFrom)
+{
+ ASSERT(pFrom != NULL);
+
+ m_cVirt = pFrom->m_cVirt;
+ m_wKey = pFrom->m_wKey;
+ m_bLocked = pFrom->m_bLocked;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CAccelsOb::CAccelsOb(BYTE cVirt, WORD wKey, bool bLocked)
+{
+ m_cVirt = cVirt;
+ m_wKey = wKey;
+ m_bLocked = bLocked;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CAccelsOb::CAccelsOb(LPACCEL pACCEL)
+{
+ ASSERT(pACCEL != NULL);
+
+ m_cVirt = pACCEL->fVirt;
+ m_wKey = pACCEL->key;
+ m_bLocked = false;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CAccelsOb& CAccelsOb::operator=(const CAccelsOb& from)
+{
+ m_cVirt = from.m_cVirt;
+ m_wKey = from.m_wKey;
+ m_bLocked = from.m_bLocked;
+
+ return *this;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CAccelsOb::GetString(CString& szBuffer)
+{
+ szBuffer = "";
+ // in case of the object is not assigned, we avoid error messages
+ if (m_wKey == 0)
+ return;
+
+ // modifiers part
+ int i;
+ for (i = 0; i < sizetable(mapVirtSysKeys); i++) {
+ if (m_cVirt & mapVirtSysKeys[i].wKey) {
+ szBuffer += mapVirtSysKeys[i].szKey;
+ szBuffer += "+";
+ }
+ }
+ // and virtual key part
+ for (i = 0; i < sizetable(mapVirtKeys); i++) {
+ if (m_wKey == mapVirtKeys[i].wKey) {
+ szBuffer += mapVirtKeys[i].szKey;
+ return;
+ }
+ }
+ AfxMessageBox("Internal error : (CAccelsOb::GetString) m_wKey invalid");
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+bool CAccelsOb::IsEqual(WORD wKey, bool bCtrl, bool bAlt, bool bShift)
+{
+ // CString szTemp;
+ // GetString(szTemp);
+
+
+ bool m_bCtrl = (m_cVirt & FCONTROL) ? true : false;
+ bool bRet = (bCtrl == m_bCtrl);
+
+ bool m_bAlt = (m_cVirt & FALT) ? true : false;
+ bRet &= (bAlt == m_bAlt);
+
+ bool m_bShift = (m_cVirt & FSHIFT) ? true : false;
+ bRet &= (bShift == m_bShift);
+
+ bRet &= static_cast(m_wKey == wKey);
+
+ return bRet;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+DWORD CAccelsOb::GetData()
+{
+ BYTE cLocalCodes = 0;
+ if (m_bLocked)
+ cLocalCodes = DEFAULT_ACCEL;
+ else
+ cLocalCodes = USER_ACCEL;
+
+ WORD bCodes = MAKEWORD(m_cVirt, cLocalCodes);
+ return MAKELONG(m_wKey, bCodes);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+bool CAccelsOb::SetData(DWORD dwDatas)
+{
+ m_wKey = LOWORD(dwDatas);
+
+ WORD bCodes = HIWORD(dwDatas);
+ m_cVirt = LOBYTE(bCodes);
+
+ BYTE cLocalCodes = HIBYTE(bCodes);
+ m_bLocked = static_cast(cLocalCodes == DEFAULT_ACCEL);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+#ifdef _DEBUG
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CAccelsOb::AssertValid() const
+{
+ CObject::AssertValid();
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CAccelsOb::Dump(CDumpContext& dc) const
+{
+ dc << "\t\t";
+ CObject::Dump(dc);
+ dc << "\t\tlocked=" << m_bLocked << ", cVirt=" << m_cVirt << ", wKey=" << m_wKey << "\n\n";
+
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////
+//
+//
+CCmdAccelOb::CCmdAccelOb()
+{
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CCmdAccelOb::CCmdAccelOb(WORD wIDCommand, LPCTSTR szCommand)
+{
+ ASSERT(szCommand != NULL);
+
+ m_wIDCommand = wIDCommand;
+ m_szCommand = szCommand;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CCmdAccelOb::CCmdAccelOb(BYTE cVirt, WORD wIDCommand, WORD wKey, LPCTSTR szCommand, bool bLocked)
+{
+ ASSERT(szCommand != NULL);
+
+ m_wIDCommand = wIDCommand;
+ m_szCommand = szCommand;
+
+ CAccelsOb* pAccel = DEBUG_NEW CAccelsOb(cVirt, wKey, bLocked);
+ ASSERT(pAccel != NULL);
+ m_Accels.AddTail(pAccel);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CCmdAccelOb::~CCmdAccelOb()
+{
+ POSITION pos = m_Accels.GetHeadPosition();
+ while (pos != NULL)
+ delete m_Accels.GetNext(pos);
+ m_Accels.RemoveAll();
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CCmdAccelOb::Add(BYTE cVirt, WORD wKey, bool bLocked)
+{
+ CAccelsOb* pAccel = DEBUG_NEW CAccelsOb(cVirt, wKey, bLocked);
+ ASSERT(pAccel != NULL);
+ m_Accels.AddTail(pAccel);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CCmdAccelOb::Add(CAccelsOb* pAccel)
+{
+ ASSERT(pAccel != NULL);
+ m_Accels.AddTail(pAccel);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+CCmdAccelOb& CCmdAccelOb::operator=(const CCmdAccelOb& from)
+{
+ Reset();
+
+ m_wIDCommand = from.m_wIDCommand;
+ m_szCommand = from.m_szCommand;
+
+ CAccelsOb* pAccel;
+ POSITION pos = from.m_Accels.GetHeadPosition();
+ while (pos != NULL) {
+ pAccel = DEBUG_NEW CAccelsOb(from.m_Accels.GetNext(pos));
+ ASSERT(pAccel != NULL);
+ m_Accels.AddTail(pAccel);
+ }
+ return *this;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CCmdAccelOb::DeleteUserAccels()
+{
+ CAccelsOb* pAccel;
+ POSITION prevPos;
+ POSITION pos = m_Accels.GetHeadPosition();
+ while (pos != NULL) {
+ prevPos = pos;
+ pAccel = m_Accels.GetNext(pos);
+ if (!pAccel->m_bLocked) {
+ delete pAccel;
+ m_Accels.RemoveAt(prevPos);
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CCmdAccelOb::Reset()
+{
+ m_wIDCommand = 0;
+ m_szCommand = "Empty command";
+
+ CAccelsOb* pAccel;
+ POSITION pos = m_Accels.GetHeadPosition();
+ while (pos != NULL) {
+ pAccel = m_Accels.GetNext(pos);
+ delete pAccel;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+#ifdef _DEBUG
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CCmdAccelOb::AssertValid() const
+{
+ // call base class function first
+ CObject::AssertValid();
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+void CCmdAccelOb::Dump( CDumpContext& dc ) const
+{
+ // call base class function first
+ dc << "\t";
+ CObject::Dump( dc );
+
+ // now do the stuff for our specific class
+ dc << "\tIDCommand = " << m_wIDCommand;
+ dc << "\n\tszCommand = " << m_szCommand;
+ dc << "\n\tAccelerators = {\n";
+
+ CAccelsOb* pAccel;
+ POSITION pos = m_Accels.GetHeadPosition();
+ while (pos != NULL) {
+ pAccel = m_Accels.GetNext(pos);
+ dc << pAccel;
+ }
+ dc << "\t}\n";
+}
+#endif
diff --git a/src/win32/ColorButton.h b/src/win32/ColorButton.h
index 3d12f74b..340db218 100644
--- a/src/win32/ColorButton.h
+++ b/src/win32/ColorButton.h
@@ -20,7 +20,7 @@
#if !defined(AFX_COLORBUTTON_H__DF02109B_B91C_49FD_954F_74A48B83C314__INCLUDED_)
#define AFX_COLORBUTTON_H__DF02109B_B91C_49FD_954F_74A48B83C314__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/ColorControl.h b/src/win32/ColorControl.h
index e66832c6..9ebaf03d 100644
--- a/src/win32/ColorControl.h
+++ b/src/win32/ColorControl.h
@@ -20,7 +20,7 @@
#if !defined(AFX_COLORCONTROL_H__747E1E47_DDFA_4D67_B337_A473F2BACB86__INCLUDED_)
#define AFX_COLORCONTROL_H__747E1E47_DDFA_4D67_B337_A473F2BACB86__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/Commands.cpp b/src/win32/Commands.cpp
index 3e9ae39d..163b1acc 100644
--- a/src/win32/Commands.cpp
+++ b/src/win32/Commands.cpp
@@ -1,253 +1,258 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include "AcceleratorManager.h"
-#include "..\..\res\resource.h"
-#include
-
-#include // MFC Templates extension
-#ifndef CMapStringToWord
-typedef CMap< CString, LPCSTR, WORD, WORD& > CMapStringToWord;
-#endif
-
-static CMapStringToWord winAccelStrings;
-static bool initialized = false;
-
-struct {
- const char *command;
- WORD id;
-} winAccelCommands[] = {
- { "FileOpen", ID_FILE_OPEN },
- { "FileOpenGameboy", ID_FILE_OPENGAMEBOY },
- { "FileLoad", ID_FILE_LOAD },
- { "FileSave", ID_FILE_SAVE },
- { "FileLoadGame01", ID_FILE_LOADGAME_SLOT1 },
- { "FileLoadGame02", ID_FILE_LOADGAME_SLOT2 },
- { "FileLoadGame03", ID_FILE_LOADGAME_SLOT3 },
- { "FileLoadGame04", ID_FILE_LOADGAME_SLOT4 },
- { "FileLoadGame05", ID_FILE_LOADGAME_SLOT5 },
- { "FileLoadGame06", ID_FILE_LOADGAME_SLOT6 },
- { "FileLoadGame07", ID_FILE_LOADGAME_SLOT7 },
- { "FileLoadGame08", ID_FILE_LOADGAME_SLOT8 },
- { "FileLoadGame09", ID_FILE_LOADGAME_SLOT9 },
- { "FileLoadGame10", ID_FILE_LOADGAME_SLOT10 },
- { "FileLoadGameAutoLoad", ID_FILE_LOADGAME_AUTOLOADMOSTRECENT },
- { "FileLoadGameRecent", ID_FILE_LOADGAME_MOSTRECENT },
- { "FileSaveGame01", ID_FILE_SAVEGAME_SLOT1 },
- { "FileSaveGame02", ID_FILE_SAVEGAME_SLOT2 },
- { "FileSaveGame03", ID_FILE_SAVEGAME_SLOT3 },
- { "FileSaveGame04", ID_FILE_SAVEGAME_SLOT4 },
- { "FileSaveGame05", ID_FILE_SAVEGAME_SLOT5 },
- { "FileSaveGame06", ID_FILE_SAVEGAME_SLOT6 },
- { "FileSaveGame07", ID_FILE_SAVEGAME_SLOT7 },
- { "FileSaveGame08", ID_FILE_SAVEGAME_SLOT8 },
- { "FileSaveGame09", ID_FILE_SAVEGAME_SLOT9 },
- { "FileSaveGame10", ID_FILE_SAVEGAME_SLOT10 },
- { "FileSaveGameOldest", ID_FILE_SAVEGAME_OLDESTSLOT },
- { "FileRecentReset", ID_FILE_RECENT_RESET },
- { "FileRecentFreeze", ID_FILE_RECENT_FREEZE },
- { "FileRecent01", ID_FILE_MRU_FILE1 },
- { "FileRecent02", ID_FILE_MRU_FILE2 },
- { "FileRecent03", ID_FILE_MRU_FILE3 },
- { "FileRecent04", ID_FILE_MRU_FILE4 },
- { "FileRecent05", ID_FILE_MRU_FILE5 },
- { "FileRecent06", ID_FILE_MRU_FILE6 },
- { "FileRecent07", ID_FILE_MRU_FILE7 },
- { "FileRecent08", ID_FILE_MRU_FILE8 },
- { "FileRecent09", ID_FILE_MRU_FILE9 },
- { "FileRecent10", ID_FILE_MRU_FILE10 },
- { "FilePause", ID_FILE_PAUSE },
- { "FileReset", ID_FILE_RESET },
- { "FileImportBatteryFile", ID_FILE_IMPORT_BATTERYFILE },
- { "FileImportGamesharkCodeFile", ID_FILE_IMPORT_GAMESHARKCODEFILE },
- { "FileImportGamesharkSnapshot", ID_FILE_IMPORT_GAMESHARKSNAPSHOT },
- { "FileExportBatteryFile", ID_FILE_EXPORT_BATTERYFILE },
- { "FileExportGamesharkSnapshot", ID_FILE_EXPORT_GAMESHARKSNAPSHOT },
- { "FileScreenCapture", ID_FILE_SCREENCAPTURE },
- { "FileRomInformation", ID_FILE_ROMINFORMATION },
- { "FileToggleMenu", ID_FILE_TOGGLEMENU },
- { "FileClose", ID_FILE_CLOSE },
- { "FileExit", ID_FILE_EXIT },
- { "OptionsFrameSkip0", ID_OPTIONS_VIDEO_FRAMESKIP_0 },
- { "OptionsFrameSkip1", ID_OPTIONS_VIDEO_FRAMESKIP_1 },
- { "OptionsFrameSkip2", ID_OPTIONS_VIDEO_FRAMESKIP_2 },
- { "OptionsFrameSkip3", ID_OPTIONS_VIDEO_FRAMESKIP_3 },
- { "OptionsFrameSkip4", ID_OPTIONS_VIDEO_FRAMESKIP_4 },
- { "OptionsFrameSkip5", ID_OPTIONS_VIDEO_FRAMESKIP_5 },
- { "OptionsFrameSkip6", ID_OPTIONS_VIDEO_FRAMESKIP_6 },
- { "OptionsFrameSkip7", ID_OPTIONS_VIDEO_FRAMESKIP_7 },
- { "OptionsFrameSkip8", ID_OPTIONS_VIDEO_FRAMESKIP_8 },
- { "OptionsFrameSkip9", ID_OPTIONS_VIDEO_FRAMESKIP_9 },
- { "OptionsThrottleNone", ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE },
- { "OptionsThrottle025%", ID_OPTIONS_FRAMESKIP_THROTTLE_25 },
- { "OptionsThrottle050%", ID_OPTIONS_FRAMESKIP_THROTTLE_50 },
- { "OptionsThrottle100%", ID_OPTIONS_FRAMESKIP_THROTTLE_100 },
- { "OptionsThrottle150%", ID_OPTIONS_FRAMESKIP_THROTTLE_150 },
- { "OptionsThrottle200%", ID_OPTIONS_FRAMESKIP_THROTTLE_200 },
- { "OptionsThrottleOther", ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER },
- { "OptionsVideoRenderGDI", ID_OPTIONS_VIDEO_RENDERMETHOD_GDI },
- { "OptionsVideoRenderDDRAW", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW },
- { "OptionsVideoRenderD3D", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D },
- { "OptionsVideoRenderOGL", ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL },
- { "OptionsVideoVsync", ID_OPTIONS_VIDEO_VSYNC },
- { "OptionsVideoX1", ID_OPTIONS_VIDEO_X1 },
- { "OptionsVideoX2", ID_OPTIONS_VIDEO_X2 },
- { "OptionsVideoX3", ID_OPTIONS_VIDEO_X3 },
- { "OptionsVideoX4", ID_OPTIONS_VIDEO_X4 },
- { "OptionsVideo320x240", ID_OPTIONS_VIDEO_FULLSCREEN320X240 },
- { "OptionsVideo640x480", ID_OPTIONS_VIDEO_FULLSCREEN640X480 },
- { "OptionsVideo800x600", ID_OPTIONS_VIDEO_FULLSCREEN800X600 },
- { "OptionsVideoFullscreen", ID_OPTIONS_VIDEO_FULLSCREEN },
- { "OptionsVideoFullscreenMaxScale", ID_OPTIONS_VIDEO_FULLSCREENMAXSCALE },
- { "OptionsVideoLayersBg0", ID_OPTIONS_VIDEO_LAYERS_BG0 },
- { "OptionsVideoLayersBg1", ID_OPTIONS_VIDEO_LAYERS_BG1 },
- { "OptionsVideoLayersBg2", ID_OPTIONS_VIDEO_LAYERS_BG2 },
- { "OptionsVideoLayersBg3", ID_OPTIONS_VIDEO_LAYERS_BG3 },
- { "OptionsVideoLayersOBJ", ID_OPTIONS_VIDEO_LAYERS_OBJ },
- { "OptionsVideoLayersWIN0", ID_OPTIONS_VIDEO_LAYERS_WIN0 },
- { "OptionsVideoLayersWIN1", ID_OPTIONS_VIDEO_LAYERS_WIN1 },
- { "OptionsVideoLayersOBJWIN", ID_OPTIONS_VIDEO_LAYERS_OBJWIN },
- { "OptionsEmulatorAssociate", ID_OPTIONS_EMULATOR_ASSOCIATE },
- { "OptionsEmulatorDirectories", ID_OPTIONS_EMULATOR_DIRECTORIES },
- { "OptionsEmulatorSelectBIOS", ID_OPTIONS_EMULATOR_SELECTBIOSFILE },
- { "OptionsEmulatorUseBIOS", ID_OPTIONS_EMULATOR_USEBIOSFILE },
- { "OptionsEmulatorSkipBIOS", ID_OPTIONS_EMULATOR_SKIPBIOS },
- { "OptionsEmulatorShowSpeedNone", ID_OPTIONS_EMULATOR_SHOWSPEED_NONE },
- { "OptionsEmulatorShowSpeedPercentage", ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE },
- { "OptionsEmulatorShowSpeedDetailed", ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED },
- { "OptionsEmulatorShowSpeedTransparent", ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT },
- { "OptionsEmulatorSpeedupToggle", ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE },
- { "OptionsEmulatorRemoveIntros", ID_OPTIONS_EMULATOR_REMOVEINTROSGBA },
- { "OptionsEmulatorAutoHideMenu", ID_OPTIONS_EMULATOR_AUTOHIDEMENU },
- { "OptionsEmulatorSaveAuto", ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC },
- { "OptionsEmulatorSaveEEPROM", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM },
- { "OptionsEmulatorSaveSRAM", ID_OPTIONS_EMULATOR_SAVETYPE_SRAM },
- { "OptionsEmulatorSaveFLASH", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH },
- { "OptionsEmulatorSaveEEPROMSensor", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR },
- { "OptionsEmulatorSaveFlash64K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K },
- { "OptionsEmulatorSaveFlash128K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M },
- { "OptionsEmulatorAutoIPSPatch", ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH },
- { "OptionsEmulatorAGBPrint", ID_OPTIONS_EMULATOR_AGBPRINT },
- { "OptionsEmulatorRTC", ID_OPTIONS_EMULATOR_REALTIMECLOCK },
- { "OptionsEmulatorRewindInterval", ID_OPTIONS_EMULATOR_REWINDINTERVAL },
- { "OptionsSoundOff", ID_OPTIONS_SOUND_OFF },
- { "OptionsSoundMute", ID_OPTIONS_SOUND_OFF }, /* mute hax */
- { "OptionsSoundOn", ID_OPTIONS_SOUND_ON },
- { "OptionsSoundChannel1", ID_OPTIONS_SOUND_CHANNEL1 },
- { "OptionsSoundChannel2", ID_OPTIONS_SOUND_CHANNEL2 },
- { "OptionsSoundChannel3", ID_OPTIONS_SOUND_CHANNEL3 },
- { "OptionsSoundChannel4", ID_OPTIONS_SOUND_CHANNEL4 },
- { "OptionsSoundDirectSoundA", ID_OPTIONS_SOUND_DIRECTSOUNDA },
- { "OptionsSoundDirectSoundB", ID_OPTIONS_SOUND_DIRECTSOUNDB },
- { "OptionsSound11Khz", ID_OPTIONS_SOUND_11KHZ },
- { "OptionsSound22Khz", ID_OPTIONS_SOUND_22KHZ },
- { "OptionsSound44Khz", ID_OPTIONS_SOUND_44KHZ },
- { "OptionsSoundEcho", ID_OPTIONS_SOUND_ECHO },
- { "OptionsSoundLowPassFilter", ID_OPTIONS_SOUND_LOWPASSFILTER },
- { "OptionsSoundReverseStereo", ID_OPTIONS_SOUND_REVERSESTEREO },
- { "OptionsSoundVolume1x", ID_OPTIONS_SOUND_VOLUME_1X },
- { "OptionsSoundVolume2x", ID_OPTIONS_SOUND_VOLUME_2X },
- { "OptionsSoundVolume3x", ID_OPTIONS_SOUND_VOLUME_3X },
- { "OptionsSoundVolume4x", ID_OPTIONS_SOUND_VOLUME_4X },
- { "OptionsGameboyBorder", ID_OPTIONS_GAMEBOY_BORDER },
- { "OptionsGameboyBorderAutomatic", ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC },
- { "OptionsGameboyColors", ID_OPTIONS_GAMEBOY_COLORS },
- { "OptionsFilterNormal", ID_OPTIONS_FILTER_NORMAL },
- { "OptionsFilterTVMode", ID_OPTIONS_FILTER_TVMODE },
- { "OptionsFilter2xSaI", ID_OPTIONS_FILTER_2XSAI },
- { "OptionsFilterSuper2xSaI", ID_OPTIONS_FILTER_SUPER2XSAI },
- { "OptionsFilterSuperEagle", ID_OPTIONS_FILTER_SUPEREAGLE },
- { "OptionsFilterPixelate", ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL },
- { "OptionsFilterAdMameScale2x", ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X },
- { "OptionsFilterSimple2x", ID_OPTIONS_FILTER16BIT_SIMPLE2X },
- { "OptionsFilterBilinear", ID_OPTIONS_FILTER_BILINEAR },
- { "OptionsFilterBilinearPlus", ID_OPTIONS_FILTER_BILINEARPLUS },
- { "OptionsFilterScanlines", ID_OPTIONS_FILTER_SCANLINES },
- { "OptionsFilterHq2x", ID_OPTIONS_FILTER_HQ2X },
- { "OptionsFilterLq2x", ID_OPTIONS_FILTER_LQ2X },
- { "OptionsFilterIFBNone", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE },
- { "OptionsFilterIFBMotionBlur", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR },
- { "OptionsFilterIFBSmart", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART },
- { "OptionsFilterDisableMMX", ID_OPTIONS_FILTER_DISABLEMMX },
- { "OptionsJoypadConfigure1", ID_OPTIONS_JOYPAD_CONFIGURE_1 },
- { "OptionsJoypadConfigure2", ID_OPTIONS_JOYPAD_CONFIGURE_2 },
- { "OptionsJoypadConfigure3", ID_OPTIONS_JOYPAD_CONFIGURE_3 },
- { "OptionsJoypadConfigure4", ID_OPTIONS_JOYPAD_CONFIGURE_4 },
- { "OptionsJoypadMotionConfigure", ID_OPTIONS_JOYPAD_MOTIONCONFIGURE },
- { "OptionsJoypadAutofireA", ID_OPTIONS_JOYPAD_AUTOFIRE_A },
- { "OptionsJoypadAutofireB", ID_OPTIONS_JOYPAD_AUTOFIRE_B },
- { "OptionsJoypadAutofireL", ID_OPTIONS_JOYPAD_AUTOFIRE_L },
- { "OptionsJoypadAutofireR", ID_OPTIONS_JOYPAD_AUTOFIRE_R },
- { "CheatsSearch", ID_CHEATS_SEARCHFORCHEATS },
- { "CheatsList", ID_CHEATS_CHEATLIST },
- { "CheatsLoad", ID_CHEATS_LOADCHEATLIST },
- { "CheatsSave", ID_CHEATS_SAVECHEATLIST },
- { "CheatsDisable", ID_CHEATS_DISABLECHEATS },
- { "ToolsDebugGDB", ID_TOOLS_DEBUG_GDB },
- { "ToolsDebugGDBLoad", ID_TOOLS_DEBUG_LOADANDWAIT },
- { "ToolsDebugGDBBreak", ID_TOOLS_DEBUG_BREAK },
- { "ToolsDebugGDBDisconnect", ID_TOOLS_DEBUG_DISCONNECT },
- { "ToolsDisassemble", ID_TOOLS_DISASSEMBLE },
- { "ToolsIOViewer", ID_TOOLS_IOVIEWER },
- { "ToolsLogging", ID_TOOLS_LOGGING },
- { "ToolsMapViewer", ID_TOOLS_MAPVIEW },
- { "ToolsMemoryViewer", ID_TOOLS_MEMORYVIEWER },
- { "ToolsOAMViewer", ID_TOOLS_OAMVIEWER },
- { "ToolsPaletteViewer", ID_TOOLS_PALETTEVIEW },
- { "ToolsTileViewer", ID_TOOLS_TILEVIEWER },
- { "ToolsNextFrame", ID_DEBUG_NEXTFRAME },
- { "ToolsRecordSoundStartRecording", ID_OPTIONS_SOUND_STARTRECORDING },
- { "ToolsRecordSoundStopRecording", ID_OPTIONS_SOUND_STOPRECORDING },
- { "ToolsRecordAVIStartRecording", ID_TOOLS_RECORD_STARTAVIRECORDING },
- { "ToolsRecordAVIStopRecording", ID_TOOLS_RECORD_STOPAVIRECORDING },
- { "ToolsRecordMovieStartRecording", ID_TOOLS_RECORD_STARTMOVIERECORDING },
- { "ToolsRecordMovieStopRecording", ID_TOOLS_RECORD_STOPMOVIERECORDING },
- { "ToolsPlayMovieStartPlaying", ID_TOOLS_PLAY_STARTMOVIEPLAYING },
- { "ToolsPlayMovieStopPlaying", ID_TOOLS_PLAY_STOPMOVIEPLAYING },
- { "ToolsRewind", ID_TOOLS_REWIND },
- { "ToolsCustomize", ID_TOOLS_CUSTOMIZE },
- { "HelpBugReport", ID_HELP_BUGREPORT },
- { "HelpFAQ", ID_HELP_FAQ },
- { "HelpAbout", ID_HELP_ABOUT }
-};
-
-bool winAccelGetID(const char *command, WORD& id)
-{
- if(!initialized) {
- int count = sizeof(winAccelCommands)/sizeof(winAccelCommands[0]);
-
- for(int i = 0; i < count; i++) {
- winAccelStrings.SetAt(winAccelCommands[i].command, winAccelCommands[i].id);
- }
- initialized = true;
- }
-
- return winAccelStrings.Lookup(command, id) ? true : false;
-}
-
-void winAccelAddCommands(CAcceleratorManager& mgr)
-{
- int count = sizeof(winAccelCommands)/sizeof(winAccelCommands[0]);
-
- for(int i = 0; i < count; i++) {
- if(!mgr.AddCommandAccel(winAccelCommands[i].id, winAccelCommands[i].command, false))
- mgr.CreateEntry(winAccelCommands[i].id, winAccelCommands[i].command);
- }
-
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+#include "AcceleratorManager.h"
+#include "resource.h"
+#include
+
+#include // MFC Templates extension
+#ifndef CMapStringToWord
+typedef CMap< CString, LPCSTR, WORD, WORD& > CMapStringToWord;
+#endif
+
+static CMapStringToWord winAccelStrings;
+static bool initialized = false;
+
+struct {
+ const char *command;
+ WORD id;
+} winAccelCommands[] = {
+ { "FileOpen", ID_FILE_OPEN },
+ { "FileOpenGameboy", ID_FILE_OPENGAMEBOY },
+ { "FileLoad", ID_FILE_LOAD },
+ { "FileSave", ID_FILE_SAVE },
+ { "FileLoadGame01", ID_FILE_LOADGAME_SLOT1 },
+ { "FileLoadGame02", ID_FILE_LOADGAME_SLOT2 },
+ { "FileLoadGame03", ID_FILE_LOADGAME_SLOT3 },
+ { "FileLoadGame04", ID_FILE_LOADGAME_SLOT4 },
+ { "FileLoadGame05", ID_FILE_LOADGAME_SLOT5 },
+ { "FileLoadGame06", ID_FILE_LOADGAME_SLOT6 },
+ { "FileLoadGame07", ID_FILE_LOADGAME_SLOT7 },
+ { "FileLoadGame08", ID_FILE_LOADGAME_SLOT8 },
+ { "FileLoadGame09", ID_FILE_LOADGAME_SLOT9 },
+ { "FileLoadGame10", ID_FILE_LOADGAME_SLOT10 },
+ { "FileLoadGameAutoLoad", ID_FILE_LOADGAME_AUTOLOADMOSTRECENT },
+ { "FileLoadGameRecent", ID_FILE_LOADGAME_MOSTRECENT },
+ { "FileSaveGame01", ID_FILE_SAVEGAME_SLOT1 },
+ { "FileSaveGame02", ID_FILE_SAVEGAME_SLOT2 },
+ { "FileSaveGame03", ID_FILE_SAVEGAME_SLOT3 },
+ { "FileSaveGame04", ID_FILE_SAVEGAME_SLOT4 },
+ { "FileSaveGame05", ID_FILE_SAVEGAME_SLOT5 },
+ { "FileSaveGame06", ID_FILE_SAVEGAME_SLOT6 },
+ { "FileSaveGame07", ID_FILE_SAVEGAME_SLOT7 },
+ { "FileSaveGame08", ID_FILE_SAVEGAME_SLOT8 },
+ { "FileSaveGame09", ID_FILE_SAVEGAME_SLOT9 },
+ { "FileSaveGame10", ID_FILE_SAVEGAME_SLOT10 },
+ { "FileSaveGameOldest", ID_FILE_SAVEGAME_OLDESTSLOT },
+ { "FileRecentReset", ID_FILE_RECENT_RESET },
+ { "FileRecentFreeze", ID_FILE_RECENT_FREEZE },
+ { "FileRecent01", ID_FILE_MRU_FILE1 },
+ { "FileRecent02", ID_FILE_MRU_FILE2 },
+ { "FileRecent03", ID_FILE_MRU_FILE3 },
+ { "FileRecent04", ID_FILE_MRU_FILE4 },
+ { "FileRecent05", ID_FILE_MRU_FILE5 },
+ { "FileRecent06", ID_FILE_MRU_FILE6 },
+ { "FileRecent07", ID_FILE_MRU_FILE7 },
+ { "FileRecent08", ID_FILE_MRU_FILE8 },
+ { "FileRecent09", ID_FILE_MRU_FILE9 },
+ { "FileRecent10", ID_FILE_MRU_FILE10 },
+ { "FilePause", ID_FILE_PAUSE },
+ { "FileReset", ID_FILE_RESET },
+ { "FileImportBatteryFile", ID_FILE_IMPORT_BATTERYFILE },
+ { "FileImportGamesharkCodeFile", ID_FILE_IMPORT_GAMESHARKCODEFILE },
+ { "FileImportGamesharkSnapshot", ID_FILE_IMPORT_GAMESHARKSNAPSHOT },
+ { "FileExportBatteryFile", ID_FILE_EXPORT_BATTERYFILE },
+ { "FileExportGamesharkSnapshot", ID_FILE_EXPORT_GAMESHARKSNAPSHOT },
+ { "FileScreenCapture", ID_FILE_SCREENCAPTURE },
+ { "FileRomInformation", ID_FILE_ROMINFORMATION },
+ { "FileToggleMenu", ID_FILE_TOGGLEMENU },
+ { "FileClose", ID_FILE_CLOSE },
+ { "FileExit", ID_FILE_EXIT },
+ { "OptionsFrameSkip0", ID_OPTIONS_VIDEO_FRAMESKIP_0 },
+ { "OptionsFrameSkip1", ID_OPTIONS_VIDEO_FRAMESKIP_1 },
+ { "OptionsFrameSkip2", ID_OPTIONS_VIDEO_FRAMESKIP_2 },
+ { "OptionsFrameSkip3", ID_OPTIONS_VIDEO_FRAMESKIP_3 },
+ { "OptionsFrameSkip4", ID_OPTIONS_VIDEO_FRAMESKIP_4 },
+ { "OptionsFrameSkip5", ID_OPTIONS_VIDEO_FRAMESKIP_5 },
+ { "OptionsFrameSkip6", ID_OPTIONS_VIDEO_FRAMESKIP_6 },
+ { "OptionsFrameSkip7", ID_OPTIONS_VIDEO_FRAMESKIP_7 },
+ { "OptionsFrameSkip8", ID_OPTIONS_VIDEO_FRAMESKIP_8 },
+ { "OptionsFrameSkip9", ID_OPTIONS_VIDEO_FRAMESKIP_9 },
+ { "OptionsThrottleNone", ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE },
+ { "OptionsThrottle025%", ID_OPTIONS_FRAMESKIP_THROTTLE_25 },
+ { "OptionsThrottle050%", ID_OPTIONS_FRAMESKIP_THROTTLE_50 },
+ { "OptionsThrottle100%", ID_OPTIONS_FRAMESKIP_THROTTLE_100 },
+ { "OptionsThrottle150%", ID_OPTIONS_FRAMESKIP_THROTTLE_150 },
+ { "OptionsThrottle200%", ID_OPTIONS_FRAMESKIP_THROTTLE_200 },
+ { "OptionsThrottleOther", ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER },
+ { "OptionsVideoRenderGDI", ID_OPTIONS_VIDEO_RENDERMETHOD_GDI },
+ { "OptionsVideoRenderDDRAW", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW },
+ { "OptionsVideoRenderD3D", ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D },
+ { "OptionsVideoRenderOGL", ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL },
+ { "OptionsVideoRenderSelectSkin", ID_OPTIONS_VIDEO_RENDEROPTIONS_SELECTSKIN },
+ { "OptionsVideoRenderSkin", ID_OPTIONS_VIDEO_RENDEROPTIONS_SKIN },
+ { "OptionsVideoVsync", ID_OPTIONS_VIDEO_VSYNC },
+ { "OptionsVideoX1", ID_OPTIONS_VIDEO_X1 },
+ { "OptionsVideoX2", ID_OPTIONS_VIDEO_X2 },
+ { "OptionsVideoX3", ID_OPTIONS_VIDEO_X3 },
+ { "OptionsVideoX4", ID_OPTIONS_VIDEO_X4 },
+ { "OptionsVideo320x240", ID_OPTIONS_VIDEO_FULLSCREEN320X240 },
+ { "OptionsVideo640x480", ID_OPTIONS_VIDEO_FULLSCREEN640X480 },
+ { "OptionsVideo800x600", ID_OPTIONS_VIDEO_FULLSCREEN800X600 },
+ { "OptionsVideoFullscreen", ID_OPTIONS_VIDEO_FULLSCREEN },
+ { "OptionsVideoFullscreenMaxScale", ID_OPTIONS_VIDEO_FULLSCREENMAXSCALE },
+ { "OptionsVideoLayersBg0", ID_OPTIONS_VIDEO_LAYERS_BG0 },
+ { "OptionsVideoLayersBg1", ID_OPTIONS_VIDEO_LAYERS_BG1 },
+ { "OptionsVideoLayersBg2", ID_OPTIONS_VIDEO_LAYERS_BG2 },
+ { "OptionsVideoLayersBg3", ID_OPTIONS_VIDEO_LAYERS_BG3 },
+ { "OptionsVideoLayersOBJ", ID_OPTIONS_VIDEO_LAYERS_OBJ },
+ { "OptionsVideoLayersWIN0", ID_OPTIONS_VIDEO_LAYERS_WIN0 },
+ { "OptionsVideoLayersWIN1", ID_OPTIONS_VIDEO_LAYERS_WIN1 },
+ { "OptionsVideoLayersOBJWIN", ID_OPTIONS_VIDEO_LAYERS_OBJWIN },
+ { "OptionsEmulatorAssociate", ID_OPTIONS_EMULATOR_ASSOCIATE },
+ { "OptionsEmulatorDirectories", ID_OPTIONS_EMULATOR_DIRECTORIES },
+ { "OptionsEmulatorSelectBIOS", ID_OPTIONS_EMULATOR_SELECTBIOSFILE },
+ { "OptionsEmulatorUseBIOS", ID_OPTIONS_EMULATOR_USEBIOSFILE },
+ { "OptionsEmulatorGameOverrides", ID_OPTIONS_EMULATOR_GAMEOVERRIDES },
+ { "OptionsEmulatorSkipBIOS", ID_OPTIONS_EMULATOR_SKIPBIOS },
+ { "OptionsEmulatorShowSpeedNone", ID_OPTIONS_EMULATOR_SHOWSPEED_NONE },
+ { "OptionsEmulatorShowSpeedPercentage", ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE },
+ { "OptionsEmulatorShowSpeedDetailed", ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED },
+ { "OptionsEmulatorShowSpeedTransparent", ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT },
+ { "OptionsEmulatorSpeedupToggle", ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE },
+ { "OptionsEmulatorAutoHideMenu", ID_OPTIONS_EMULATOR_AUTOHIDEMENU },
+ { "OptionsEmulatorSaveAuto", ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC },
+ { "OptionsEmulatorSaveEEPROM", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM },
+ { "OptionsEmulatorSaveSRAM", ID_OPTIONS_EMULATOR_SAVETYPE_SRAM },
+ { "OptionsEmulatorSaveFLASH", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH },
+ { "OptionsEmulatorSaveEEPROMSensor", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR },
+ { "OptionsEmulatorSaveFlash64K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K },
+ { "OptionsEmulatorSaveFlash128K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M },
+ { "OptionsEmulatorAutoIPSPatch", ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH },
+ { "OptionsEmulatorAGBPrint", ID_OPTIONS_EMULATOR_AGBPRINT },
+ { "OptionsEmulatorRTC", ID_OPTIONS_EMULATOR_REALTIMECLOCK },
+ { "OptionsEmulatorGenericflashcard", ID_OPTIONS_EMULATOR_GENERICFLASHCARD },
+ { "OptionsEmulatorRewindInterval", ID_OPTIONS_EMULATOR_REWINDINTERVAL },
+ { "OptionsSoundOff", ID_OPTIONS_SOUND_OFF },
+ { "OptionsSoundMute", ID_OPTIONS_SOUND_MUTE },
+ { "OptionsSoundOn", ID_OPTIONS_SOUND_ON },
+ { "OptionsSoundChannel1", ID_OPTIONS_SOUND_CHANNEL1 },
+ { "OptionsSoundChannel2", ID_OPTIONS_SOUND_CHANNEL2 },
+ { "OptionsSoundChannel3", ID_OPTIONS_SOUND_CHANNEL3 },
+ { "OptionsSoundChannel4", ID_OPTIONS_SOUND_CHANNEL4 },
+ { "OptionsSoundDirectSoundA", ID_OPTIONS_SOUND_DIRECTSOUNDA },
+ { "OptionsSoundDirectSoundB", ID_OPTIONS_SOUND_DIRECTSOUNDB },
+ { "OptionsSound11Khz", ID_OPTIONS_SOUND_11KHZ },
+ { "OptionsSound22Khz", ID_OPTIONS_SOUND_22KHZ },
+ { "OptionsSound44Khz", ID_OPTIONS_SOUND_44KHZ },
+ { "OptionsSoundEcho", ID_OPTIONS_SOUND_ECHO },
+ { "OptionsSoundLowPassFilter", ID_OPTIONS_SOUND_LOWPASSFILTER },
+ { "OptionsSoundReverseStereo", ID_OPTIONS_SOUND_REVERSESTEREO },
+ { "OptionsSoundVolume1x", ID_OPTIONS_SOUND_VOLUME_1X },
+ { "OptionsSoundVolume2x", ID_OPTIONS_SOUND_VOLUME_2X },
+ { "OptionsSoundVolume3x", ID_OPTIONS_SOUND_VOLUME_3X },
+ { "OptionsSoundVolume4x", ID_OPTIONS_SOUND_VOLUME_4X },
+ { "OptionsGameboyBorder", ID_OPTIONS_GAMEBOY_BORDER },
+ { "OptionsGameboyBorderAutomatic", ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC },
+ { "OptionsGameboyColors", ID_OPTIONS_GAMEBOY_COLORS },
+ { "OptionsFilterNormal", ID_OPTIONS_FILTER_NORMAL },
+ { "OptionsFilterTVMode", ID_OPTIONS_FILTER_TVMODE },
+ { "OptionsFilter2xSaI", ID_OPTIONS_FILTER_2XSAI },
+ { "OptionsFilterSuper2xSaI", ID_OPTIONS_FILTER_SUPER2XSAI },
+ { "OptionsFilterSuperEagle", ID_OPTIONS_FILTER_SUPEREAGLE },
+ { "OptionsFilterPixelate", ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL },
+ { "OptionsFilterMotionBlur", ID_OPTIONS_FILTER16BIT_MOTIONBLUREXPERIMENTAL },
+ { "OptionsFilterAdMameScale2x", ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X },
+ { "OptionsFilterSimple2x", ID_OPTIONS_FILTER16BIT_SIMPLE2X },
+ { "OptionsFilterBilinear", ID_OPTIONS_FILTER_BILINEAR },
+ { "OptionsFilterBilinearPlus", ID_OPTIONS_FILTER_BILINEARPLUS },
+ { "OptionsFilterScanlines", ID_OPTIONS_FILTER_SCANLINES },
+ { "OptionsFilterHq2x", ID_OPTIONS_FILTER_HQ2X },
+ { "OptionsFilterLq2x", ID_OPTIONS_FILTER_LQ2X },
+ { "OptionsFilterIFBNone", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE },
+ { "OptionsFilterIFBMotionBlur", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR },
+ { "OptionsFilterIFBSmart", ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART },
+ { "OptionsFilterDisableMMX", ID_OPTIONS_FILTER_DISABLEMMX },
+ { "OptionsJoypadConfigure1", ID_OPTIONS_JOYPAD_CONFIGURE_1 },
+ { "OptionsJoypadConfigure2", ID_OPTIONS_JOYPAD_CONFIGURE_2 },
+ { "OptionsJoypadConfigure3", ID_OPTIONS_JOYPAD_CONFIGURE_3 },
+ { "OptionsJoypadConfigure4", ID_OPTIONS_JOYPAD_CONFIGURE_4 },
+ { "OptionsJoypadMotionConfigure", ID_OPTIONS_JOYPAD_MOTIONCONFIGURE },
+ { "OptionsJoypadAutofireA", ID_OPTIONS_JOYPAD_AUTOFIRE_A },
+ { "OptionsJoypadAutofireB", ID_OPTIONS_JOYPAD_AUTOFIRE_B },
+ { "OptionsJoypadAutofireL", ID_OPTIONS_JOYPAD_AUTOFIRE_L },
+ { "OptionsJoypadAutofireR", ID_OPTIONS_JOYPAD_AUTOFIRE_R },
+ { "CheatsSearch", ID_CHEATS_SEARCHFORCHEATS },
+ { "CheatsList", ID_CHEATS_CHEATLIST },
+ { "CheatsLoad", ID_CHEATS_LOADCHEATLIST },
+ { "CheatsSave", ID_CHEATS_SAVECHEATLIST },
+ { "CheatsDisable", ID_CHEATS_DISABLECHEATS },
+ { "ToolsDebugGDB", ID_TOOLS_DEBUG_GDB },
+ { "ToolsDebugGDBLoad", ID_TOOLS_DEBUG_LOADANDWAIT },
+ { "ToolsDebugGDBBreak", ID_TOOLS_DEBUG_BREAK },
+ { "ToolsDebugGDBDisconnect", ID_TOOLS_DEBUG_DISCONNECT },
+ { "ToolsDisassemble", ID_TOOLS_DISASSEMBLE },
+ { "ToolsIOViewer", ID_TOOLS_IOVIEWER },
+ { "ToolsLogging", ID_TOOLS_LOGGING },
+ { "ToolsMapViewer", ID_TOOLS_MAPVIEW },
+ { "ToolsMemoryViewer", ID_TOOLS_MEMORYVIEWER },
+ { "ToolsOAMViewer", ID_TOOLS_OAMVIEWER },
+ { "ToolsPaletteViewer", ID_TOOLS_PALETTEVIEW },
+ { "ToolsTileViewer", ID_TOOLS_TILEVIEWER },
+ { "ToolsNextFrame", ID_DEBUG_NEXTFRAME },
+ { "ToolsRecordSoundStartRecording", ID_OPTIONS_SOUND_STARTRECORDING },
+ { "ToolsRecordSoundStopRecording", ID_OPTIONS_SOUND_STOPRECORDING },
+ { "ToolsRecordAVIStartRecording", ID_TOOLS_RECORD_STARTAVIRECORDING },
+ { "ToolsRecordAVIStopRecording", ID_TOOLS_RECORD_STOPAVIRECORDING },
+ { "ToolsRecordMovieStartRecording", ID_TOOLS_RECORD_STARTMOVIERECORDING },
+ { "ToolsRecordMovieStopRecording", ID_TOOLS_RECORD_STOPMOVIERECORDING },
+ { "ToolsPlayMovieStartPlaying", ID_TOOLS_PLAY_STARTMOVIEPLAYING },
+ { "ToolsPlayMovieStopPlaying", ID_TOOLS_PLAY_STOPMOVIEPLAYING },
+ { "ToolsRewind", ID_TOOLS_REWIND },
+ { "ToolsCustomize", ID_TOOLS_CUSTOMIZE },
+ { "HelpBugReport", ID_HELP_BUGREPORT },
+ { "HelpFAQ", ID_HELP_FAQ },
+ { "HelpAbout", ID_HELP_ABOUT },
+ { "SystemMinimize", ID_SYSTEM_MINIMIZE }
+};
+
+bool winAccelGetID(const char *command, WORD& id)
+{
+ if(!initialized) {
+ int count = sizeof(winAccelCommands)/sizeof(winAccelCommands[0]);
+
+ for(int i = 0; i < count; i++) {
+ winAccelStrings.SetAt(winAccelCommands[i].command, winAccelCommands[i].id);
+ }
+ initialized = true;
+ }
+
+ return winAccelStrings.Lookup(command, id) ? true : false;
+}
+
+void winAccelAddCommands(CAcceleratorManager& mgr)
+{
+ int count = sizeof(winAccelCommands)/sizeof(winAccelCommands[0]);
+
+ for(int i = 0; i < count; i++) {
+ if(!mgr.AddCommandAccel(winAccelCommands[i].id, winAccelCommands[i].command, false))
+ mgr.CreateEntry(winAccelCommands[i].id, winAccelCommands[i].command);
+ }
+
+}
diff --git a/src/win32/Direct3D.cpp b/src/win32/Direct3D.cpp
index 6b22ce38..82de2d17 100644
--- a/src/win32/Direct3D.cpp
+++ b/src/win32/Direct3D.cpp
@@ -1,1060 +1,636 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2005 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include
-#include "VBA.H"
-#include "MainWnd.h"
-#include "UniVideoModeDlg.h"
-#include "../Util.h"
-#include "../Globals.h"
-#include "../Util.h"
-#include "../gb/gbGlobals.h"
-// Link with Direct3D9
-#pragma comment(lib, "D3d9.lib")
-#pragma comment(lib, "D3dx9.lib")
-#define DIRECT3D_VERSION 0x0900
-#include
-#include
-
-#include "../gbafilter.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#ifdef MMX
-extern "C" bool cpu_mmx;
-extern bool detectMMX();
-#endif
-
-extern int Init_2xSaI(u32);
-extern void winlog(const char *,...);
-extern int systemSpeed;
-
-
-// Vertex format declarations
-const DWORD D3DFVF_TEXTBOXVERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
-struct TEXTBOXVERTEX {
- FLOAT x, y, z, rhw;
- D3DCOLOR color;
-};
-const DWORD D3DFVF_IMAGEVERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
-struct IMAGEVERTEX {
- FLOAT x, y, z;
- D3DCOLOR color;
- FLOAT u, v;
-};
-
-
-
-class Direct3DDisplay : public IDisplay
-{
-public: // Class
- Direct3DDisplay();
- virtual ~Direct3DDisplay();
-
-
-public: // Interface
- virtual bool initialize();
- virtual void cleanup();
- virtual void render();
- virtual void renderMenu();
- virtual void clear();
- virtual bool changeRenderSize(int w, int h);
- virtual void resize(int w, int h);
- virtual DISPLAY_TYPE getType() { return DIRECT_3D; };
- virtual void setOption(const char *, int);
- virtual int selectFullScreenMode(GUID **);
- virtual int selectFullScreenMode2();
-
-
-private: // Functions
- void restoreDeviceObjects(void);
- void invalidateDeviceObjects();
- void setPresentationType();
- bool initializeOffscreen(unsigned int w, unsigned int h);
- void updateFiltering(int);
- bool resetDevice();
- void initializeMatrices();
-
-
-private: // Variables
- int SelectedFreq, SelectedAdapter;
- bool initSucessful;
- bool doNotRender;
- bool filterDisabled;
- bool lockableBuffer;
- LPDIRECT3D9 pD3D;
- LPDIRECT3DDEVICE9 pDevice;
- LPDIRECT3DTEXTURE9 pTexture;
- LPD3DXFONT pFont;
- D3DPRESENT_PARAMETERS dpp;
- D3DFORMAT screenFormat;
- D3DDISPLAYMODE mode;
-
- bool fullscreen;
- int width, height; // Size of the source image to display
- IMAGEVERTEX verts[4]; // The coordinates for our image texture
- TEXTBOXVERTEX msgBox[4];
- int textureWidth; // Size of the texture,
- int textureHeight; // where the source image is copied to
- bool keepAspectRatio;
-};
-
-Direct3DDisplay::Direct3DDisplay()
-{
- initSucessful = false;
- doNotRender = true;
- pD3D = NULL;
- pDevice = NULL;
- pTexture = NULL;
- pFont = NULL;
- screenFormat = D3DFMT_UNKNOWN;
- width = 0;
- height = 0;
- filterDisabled = false;
- keepAspectRatio = false; // theApp.d3dKeepAspectRatio;
- lockableBuffer = false;
-}
-
-Direct3DDisplay::~Direct3DDisplay()
-{
- cleanup();
-}
-
-void Direct3DDisplay::setPresentationType()
-{
- // Change display mode
- memset(&dpp, 0, sizeof(dpp));
- dpp.Windowed = !fullscreen;
- if (fullscreen)
- dpp.BackBufferFormat =
- (theApp.fsColorDepth == 32) ? D3DFMT_X8R8G8B8 : D3DFMT_R5G6B5;
- else
- dpp.BackBufferFormat = mode.Format;
- dpp.BackBufferCount = 3;
- dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
- dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- dpp.BackBufferWidth = fullscreen ? theApp.fsWidth : theApp.surfaceSizeX;
- dpp.BackBufferHeight = fullscreen ? theApp.fsHeight : theApp.surfaceSizeY;
- dpp.hDeviceWindow = theApp.m_pMainWnd->GetSafeHwnd();
- dpp.FullScreen_RefreshRateInHz = fullscreen ? theApp.fsFrequency : 0;
-// dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
- dpp.Flags = theApp.menuToggle ? D3DPRESENTFLAG_LOCKABLE_BACKBUFFER : 0;
- if (theApp.vsync)
- dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync
- else
- dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync
-}
-
-void Direct3DDisplay::cleanup()
-{ // interface funtion
- if(pD3D != NULL) {
- if(pFont) {
- pFont->Release();
- pFont = NULL;
- }
-
- if(pTexture)
- {
- pTexture->Release();
- pTexture = NULL;
- }
-
- if(pDevice) {
- pDevice->Release();
- pDevice = NULL;
- }
-
- pD3D->Release();
- pD3D = NULL;
- }
-
- initSucessful = false;
- doNotRender = true;
-}
-
-bool Direct3DDisplay::initialize()
-{ // interface function
- initSucessful = false;
- doNotRender = true;
-
- // Get emulated image's dimensions
- switch(theApp.cartridgeType)
- {
- case IMAGE_GBA:
- theApp.sizeX = 240;
- theApp.sizeY = 160;
- break;
- case IMAGE_GB:
- if (gbBorderOn)
- {
- theApp.sizeX = 256;
- theApp.sizeY = 224;
- }
- else
- {
- theApp.sizeX = 160;
- theApp.sizeY = 144;
- }
- break;
- }
-
- theApp.rect.left = 0;
- theApp.rect.top = 0;
- theApp.rect.right = theApp.sizeX;
- theApp.rect.bottom = theApp.sizeY;
-
-
- switch(theApp.videoOption)
- {
- case VIDEO_1X:
- theApp.surfaceSizeX = theApp.sizeX;
- theApp.surfaceSizeY = theApp.sizeY;
- fullscreen = false;
- break;
- case VIDEO_2X:
- theApp.surfaceSizeX = theApp.sizeX * 2;
- theApp.surfaceSizeY = theApp.sizeY * 2;
- fullscreen = false;
- break;
- case VIDEO_3X:
- theApp.surfaceSizeX = theApp.sizeX * 3;
- theApp.surfaceSizeY = theApp.sizeY * 3;
- fullscreen = false;
- break;
- case VIDEO_4X:
- theApp.surfaceSizeX = theApp.sizeX * 4;
- theApp.surfaceSizeY = theApp.sizeY * 4;
- fullscreen = false;
- break;
- case VIDEO_320x240:
- case VIDEO_640x480:
- case VIDEO_800x600:
- case VIDEO_1024x768:
- case VIDEO_1280x1024:
- case VIDEO_OTHER:
- float scaleX = ((float)theApp.fsWidth / theApp.sizeX);
- float scaleY = ((float)theApp.fsHeight / theApp.sizeY);
- float min = scaleX < scaleY ? scaleX : scaleY;
- if(theApp.fsMaxScale)
- min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
- if(theApp.fullScreenStretch)
- {
- theApp.surfaceSizeX = theApp.fsWidth;
- theApp.surfaceSizeY = theApp.fsHeight;
- }
- else
- {
- theApp.surfaceSizeX = (int)(theApp.sizeX * min);
- theApp.surfaceSizeY = (int)(theApp.sizeY * min);
- }
- fullscreen = true;
- break;
- }
-
-
- theApp.dest.left = 0;
- theApp.dest.top = 0;
- theApp.dest.right = theApp.surfaceSizeX;
- theApp.dest.bottom = theApp.surfaceSizeY;
-
- DWORD style = WS_POPUP | WS_VISIBLE;
- DWORD styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- style |= WS_OVERLAPPEDWINDOW;
- else
- styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
- else
- AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
-
- int winSizeX = theApp.dest.right-theApp.dest.left;
- int winSizeY = theApp.dest.bottom-theApp.dest.top;
-
- if(theApp.videoOption > VIDEO_4X) {
- winSizeX = theApp.fsWidth;
- winSizeY = theApp.fsHeight;
- }
- int x = 0;
- int y = 0;
-
- if(theApp.videoOption <= VIDEO_4X) {
- x = theApp.windowPositionX;
- y = theApp.windowPositionY;
- }
-
- // Create a window
- MainWnd *pWnd = new MainWnd;
- theApp.m_pMainWnd = pWnd;
-
- pWnd->CreateEx(
- styleEx,
- theApp.wndClass,
- "VisualBoyAdvance",
- style,
- x, y,
- winSizeX, winSizeY,
- NULL,
- 0);
-
- if (!(HWND)*pWnd)
- {
- winlog("Error creating Window %08x\n", GetLastError());
- return FALSE;
- }
-
- theApp.updateMenuBar();
-
- theApp.adjustDestRect();
-
-
- // Create an IDirect3D9 object
- pD3D = Direct3DCreate9(D3D_SDK_VERSION);
- if(pD3D == NULL)
- {
- winlog("Error creating Direct3D object\n");
- return FALSE;
- }
-
-
-
-
- // Display resolution
- pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
-
- switch(mode.Format) {
- case D3DFMT_R8G8B8:
- systemColorDepth = 24;
- systemRedShift = 19;
- systemGreenShift = 11;
- systemBlueShift = 3;
- Init_2xSaI(32);
- break;
- case D3DFMT_X8R8G8B8:
- systemColorDepth = 32;
- systemRedShift = 19;
- systemGreenShift = 11;
- systemBlueShift = 3;
- Init_2xSaI(32);
- break;
- case D3DFMT_R5G6B5:
- systemColorDepth = 16;
- systemRedShift = 11;
- systemGreenShift = 6;
- systemBlueShift = 0;
- Init_2xSaI(565);
- break;
- case D3DFMT_X1R5G5B5:
- systemColorDepth = 16;
- systemRedShift = 10;
- systemGreenShift = 5;
- systemBlueShift = 0;
- Init_2xSaI(555);
- break;
- default:
- systemMessage(0,"Unsupported D3D format %d", mode.Format);
- return false;
- }
- theApp.fsColorDepth = systemColorDepth;
-
- // Check the available pre-defined fullscreen modes and enable menu items
- unsigned int nModes, i;
- D3DDISPLAYMODE dm;
-
- theApp.mode320Available = false;
- theApp.mode640Available = false;
- theApp.mode800Available = false;
- theApp.mode1024Available = false;
- theApp.mode1280Available = false;
-
- nModes = pD3D->GetAdapterModeCount(theApp.fsAdapter, mode.Format);
- for (i = 0; iEnumAdapterModes(theApp.fsAdapter, mode.Format, i, &dm) )
- {
- if ( (dm.Width == 320) && (dm.Height == 240) )
- theApp.mode320Available = true;
- if ( (dm.Width == 640) && (dm.Height == 480) )
- theApp.mode640Available = true;
- if ( (dm.Width == 800) && (dm.Height == 600) )
- theApp.mode800Available = true;
- if ( (dm.Width == 1024) && (dm.Height == 768) )
- theApp.mode1024Available = true;
- if ( (dm.Width == 1280) && (dm.Height == 1024) )
- theApp.mode1280Available = true;
- }
- }
-
-
-#ifdef MMX
- if (!theApp.disableMMX)
- cpu_mmx = theApp.detectMMX();
- else
- cpu_mmx = 0;
-#endif
-
- screenFormat = mode.Format;
-
- setPresentationType();
-
-
- DWORD BehaviorFlags;
- D3DCAPS9 caps;
- if (D3D_OK == pD3D->GetDeviceCaps(theApp.fsAdapter, D3DDEVTYPE_HAL, &caps)) {
- if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
- BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
- } else {
- BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
- }
- if (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) {
- BehaviorFlags |= D3DCREATE_PUREDEVICE;
- }
- } else {
- winlog("Error retrieving device's D3D capabilities\n");
- return false;
- }
-
-
- HRESULT hret = pD3D->CreateDevice(theApp.fsAdapter,
- caps.DeviceType,
- pWnd->GetSafeHwnd(),
- BehaviorFlags,
- &dpp,
- &pDevice);
-#ifdef _DEBUG
- switch(hret)
- {
- case D3DERR_DEVICELOST:
- winlog("Error creating Direct3DDevice (D3DERR_DEVICELOST)\n");
- return false;
- break;
- case D3DERR_INVALIDCALL:
- winlog("Error creating Direct3DDevice (D3DERR_INVALIDCALL)\n");
- return false;
- break;
- case D3DERR_NOTAVAILABLE:
- winlog("Error creating Direct3DDevice (D3DERR_NOTAVAILABLE)\n");
- return false;
- break;
- case D3DERR_OUTOFVIDEOMEMORY:
- winlog("Error creating Direct3DDevice (D3DERR_OUTOFVIDEOMEMORY)\n");
- return false;
- break;
- }
-#endif
-
- restoreDeviceObjects();
-
- // Set the status message's background vertex information, that does not need to be changed in realtime
- msgBox[0].z = 0.5f;
- msgBox[0].rhw = 1.0f;
- msgBox[0].color = 0x7fffffff;
- msgBox[1].z = 0.5f;
- msgBox[1].rhw = 1.0f;
- msgBox[1].color = 0x7f7f7f7f;
- msgBox[2].z = 0.5f;
- msgBox[2].rhw = 1.0f;
- msgBox[2].color = 0x7f7f7fff;
- msgBox[3].z = 0.5f;
- msgBox[3].rhw = 1.0f;
- msgBox[3].color = 0x7f7f7f7f;
-
- // Set up the vertices of the texture
- verts[0].z = verts[1].z = verts[2].z = verts[3].z = 1.0f;
- verts[0].color = verts[1].color = verts[2].color = verts[3].color = D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff);
- verts[1].u = verts[2].u = 1.0f;
- verts[0].u = verts[3].u = 0.0f;
- verts[0].v = verts[1].v = 0.0f;
- verts[2].v = verts[3].v = 1.0f;
- verts[0].x = verts[3].x = 0.0f;
- verts[1].x = verts[2].x = 1.0f;
- verts[0].y = verts[1].y = 0.0f;
- verts[2].y = verts[3].y = 1.0f;
-
-
-
- utilUpdateSystemColorMaps(theApp.filterLCD );
- theApp.updateFilter();
- theApp.updateIFB();
-
- pWnd->DragAcceptFiles(TRUE);
-
- initSucessful = true;
- doNotRender = false;
- return TRUE;
-}
-
-bool Direct3DDisplay::initializeOffscreen(unsigned int w, unsigned int h)
-{
- D3DFORMAT format = screenFormat;
-
- unsigned int correctedWidth=w, correctedHeight=h;
-
- // This function corrects the texture size automaticly
- if(D3D_OK == D3DXCheckTextureRequirements(
- pDevice,
- &correctedWidth,
- &correctedHeight,
- NULL,
- 0,
- &format,
- D3DPOOL_MANAGED))
- {
- if( (correctedWidth < w) || (correctedHeight < h) )
- {
- if(theApp.filterFunction)
- {
- filterDisabled = true;
- theApp.filterFunction = NULL;
- systemMessage(0, "3D card cannot support needed texture size for filter function. Disabling it");
- }
- else
- systemMessage(0, "Graphics card doesn't support needed texture size for emulation.");
- }
- else filterDisabled = false;
-
- if(D3D_OK == D3DXCreateTexture(
- pDevice,
- correctedWidth,
- correctedHeight,
- 1,
- D3DUSAGE_DYNAMIC,
- format,
- D3DPOOL_DEFAULT,
- &pTexture) )
- {
- width = w;
- height = h;
- textureWidth = correctedWidth;
- textureHeight = correctedHeight;
- return true;
- }
- else systemMessage(0, "Texture creation failed");
- }
- return false;
-}
-
-
-void Direct3DDisplay::updateFiltering(int filter)
-{ //TODO: use GetSampletState before changing
- if(!pDevice) {
- return;
- }
-
- HRESULT res;
-
- switch(filter)
- {
- default:
- case 0:
- // point filtering
- res = pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
- if (res != D3D_OK) {
- systemMessage(0, "Could not set point filtering mode: %d", res);
- return;
- }
- res = pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
- if (res != D3D_OK) {
- systemMessage(0, "Could not set point filtering mode: %d", res);
- return;
- }
- break;
- case 1:
- // bilinear
- res = pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
- if (res != D3D_OK) {
- systemMessage(0, "Could not set bilinear filtering mode: %d", res);
- return;
- }
- res = pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
- if (res != D3D_OK) {
- systemMessage(0, "Could not set bilinear filtering mode: %d", res);
- return;
- }
- // Don't wrap textures .. otherwise bottom blurs top to bottom
- pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
- pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
- break;
- }
- return;
-}
-
-void Direct3DDisplay::clear()
-{ // interface function
- if(!initSucessful) return;
-
- if (pDevice)
- pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,
-#ifdef _DEBUG
- 0xffff00ff //pink
-#else
- 0xff000000 //black
-#endif
- , 1.0f, 0L );
-}
-
-void Direct3DDisplay::renderMenu()
-{ // interface function
- if(!initSucessful) return;
-
- if(theApp.m_pMainWnd)
- theApp.m_pMainWnd->DrawMenuBar();
-}
-
-void Direct3DDisplay::render()
-{ // interface function
- if(!pDevice) return;
- if(!initSucessful) return;
- if(doNotRender) return;
-
- unsigned int nBytesPerPixel = systemColorDepth >> 3; // This is the byte count of a Pixel
- unsigned int pitch = (theApp.filterWidth * nBytesPerPixel) + 4; // The size of a scanline in bytes
-
- // Test the cooperative level to see if it's okay to render
- HRESULT hr;
- hr = pDevice->TestCooperativeLevel();
- switch(hr)
- {
- case D3DERR_DEVICENOTRESET:
- resetDevice();
- break;
- case D3DERR_DEVICELOST:
- winlog("Render: D3DERR_DEVICELOST\n");
- return;
- break;
- case D3DERR_DRIVERINTERNALERROR:
- winlog("Render: D3DERR_DRIVERINTERNALERROR\n");
- cleanup();
- if(initialize()) {
- return;
- } else { // reinitialize device failed
- AfxPostQuitMessage(D3DERR_DRIVERINTERNALERROR);
- }
- break;
- }
-
- // Clear the screen
- if (pDevice)
- pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,
-#ifdef _DEBUG
- 0xffff00ff //pink
-#else
- 0xff000000 //black
-#endif
- , 1.0f, 0L );
-
-
- if(SUCCEEDED(pDevice->BeginScene()))
- {
- D3DLOCKED_RECT locked;
-
- if( D3D_OK == pTexture->LockRect(0, &locked, NULL, D3DLOCK_DISCARD) )
- {
- if(theApp.filterFunction)
- {
- theApp.filterFunction(
- pix + pitch,
- pitch,
- (u8*)theApp.delta,
- (u8*)locked.pBits,
- locked.Pitch,
- theApp.filterWidth,
- theApp.filterHeight);
- }
- else
- {
- // Copy the image at [pix] to the locked Direct3D texture
- __asm
- {
- mov eax, theApp.sizeX ; Initialize
- mov ebx, theApp.sizeY ;
- mov edi, locked.pBits ;
- mov edx, locked.Pitch ;
-
- cmp systemColorDepth, 16 ; Check systemColorDepth==16bit
- jnz gbaOtherColor ;
- sub edx, eax ;
- sub edx, eax ;
- mov esi, pix ;
- lea esi,[esi+2*eax+4] ;
- shr eax, 1 ;
-gbaLoop16bit:
- mov ecx, eax ;
- rep movsd ;
- add esi, 4 ;
- add edi, edx ;
- dec ebx ;
- jnz gbaLoop16bit ;
- jmp gbaLoopEnd ;
-gbaOtherColor:
- cmp systemColorDepth, 32 ; Check systemColorDepth==32bit
- jnz gbaOtherColor2 ;
-
- lea esi, [eax*4] ;
- sub edx, esi ;
- mov esi, pix ;
- lea esi, [esi+4*eax+4] ;
-gbaLoop32bit:
- mov ecx, eax ;
- rep movsd ; ECX times: Move DWORD at [ESI] to [EDI] | ESI++ EDI++
- add esi, 4 ;
- add edi, edx ;
- dec ebx ;
- jnz gbaLoop32bit ;
- jmp gbaLoopEnd ;
-gbaOtherColor2:
- lea eax, [eax+2*eax] ; Work like systemColorDepth==24bit
- sub edx, eax ;
-gbaLoop24bit:
- mov ecx, eax ;
- shr ecx, 2 ;
- rep movsd ;
- add edi, edx ;
- dec ebx ;
- jnz gbaLoop24bit ;
-gbaLoopEnd:
- }
-
- //C Version of the code above
- //unsigned int i;
- //int x, y, srcPitch = (theApp.sizeX+1) * nBytesPerPixel;
- //unsigned char * src = ((unsigned char*)pix)+srcPitch;
- //unsigned char * dst = (unsigned char*)locked.pBits;
- //for (y=0;yUnlockRect(0);
-
- pDevice->SetFVF( D3DFVF_IMAGEVERTEX );
- pDevice->SetTexture( 0, pTexture );
- pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, verts, sizeof( IMAGEVERTEX ) );
-
- } // SUCCEEDED(pTexture->LockRect...
- else
- {
- systemMessage(0,"Rendering error");
- }
-
-
- // Draw the screen message
- if(theApp.screenMessage)
- {
- if( ((GetTickCount() - theApp.screenMessageTime) < 3000) &&
- !theApp.disableStatusMessage && pFont )
- {
- CRect msgRect(
- 64,
- dpp.BackBufferHeight - 32,
- dpp.BackBufferWidth - 64,
- dpp.BackBufferHeight);
-
- msgBox[0].x = (FLOAT)msgRect.left;
- msgBox[0].y = (FLOAT)msgRect.top;
- msgBox[1].x = (FLOAT)msgRect.right;
- msgBox[1].y = (FLOAT)msgRect.top;
- msgBox[2].x = (FLOAT)msgRect.right;
- msgBox[2].y = (FLOAT)msgRect.bottom;
- msgBox[3].x = (FLOAT)msgRect.left;
- msgBox[3].y = (FLOAT)msgRect.bottom;
-
- pDevice->SetFVF( D3DFVF_TEXTBOXVERTEX );
- pDevice->SetTexture( 0, NULL );
- pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, msgBox, sizeof(TEXTBOXVERTEX));
-
- pFont->DrawText(NULL, theApp.screenMessageBuffer, -1, msgRect, DT_CENTER | DT_VCENTER, 0x7fff0000);
- }
- else theApp.screenMessage = false;
- }
-
-
- // Draw the speed
- if( (theApp.videoOption > VIDEO_4X) && theApp.showSpeed )
- {
- // Create the string text
- char buffer[30];
- if(theApp.showSpeed == TRUE)
- sprintf(buffer, "%3d%%", systemSpeed);
- else
- sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
- systemFrameSkip,
- theApp.showRenderedFrames);
-
- //Draw the string
- D3DCOLOR speedColor;
- theApp.showSpeedTransparent==TRUE ? speedColor = 0x7fffffff : speedColor = 0xffffffff;
-
- CRect speedRect(
- 64,
- 0,
- dpp.BackBufferWidth - 64,
- 32);
-
- pFont->DrawText(NULL, buffer, -1, speedRect, DT_CENTER | DT_VCENTER, speedColor);
- }
-
- pDevice->EndScene();
-
- pDevice->Present( NULL, NULL, NULL, NULL ); //Draw everything to the screen
- }
-}
-
-
-void Direct3DDisplay::invalidateDeviceObjects()
-{
-
- if(pFont) {
- pFont->Release();
- pFont = NULL;
- }
-}
-
-void Direct3DDisplay::restoreDeviceObjects()
-{
- // Create the font
- D3DXCreateFont( pDevice, 24, 0, FW_BOLD, 1, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, "Arial", &pFont );
-
- // Set texture filter
- updateFiltering(theApp.d3dFilter);
-
- // Set device settings
- pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
- pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
- pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
- pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
- if (theApp.menuToggle)
- pDevice->SetDialogBoxMode( TRUE );
- pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
-
- // Set matrices
- initializeMatrices();
-}
-
-
-void Direct3DDisplay::resize(int w, int h)
-{ // interface function
- if(!initSucessful) return;
-
- if ( (w>0) && (h>0) ) {
- if(pDevice)
- {
- dpp.BackBufferWidth = w;
- dpp.BackBufferHeight = h;
- setPresentationType();
- if (resetDevice()) {
- doNotRender = false;
- }
- }
- } else {
- doNotRender = true;
- }
-
-}
-
-
-bool Direct3DDisplay::changeRenderSize(int w, int h)
-{ // interface function
- if(!initSucessful) return false;
-
- // w and h is the size of the filtered image (So this could be 3xGBASize)
- if(w != width || h != height)
- {
- if(pTexture) {
- pTexture->Release();
- pTexture = NULL;
- }
-
- if(!initializeOffscreen(w, h)) {
- return false;
- }
- }
-
- if(filterDisabled && theApp.filterFunction)
- theApp.filterFunction = NULL;
-
- // Set up 2D matrices
- initializeMatrices();
-
- return true;
-}
-
-void Direct3DDisplay::setOption(const char *option, int value)
-{ // interface function
- if(!initSucessful) return;
-
- if(!strcmp(option, "d3dFilter"))
- updateFiltering(theApp.d3dFilter);
-
- if(!strcmp(option, "vsync"))
- {
- if (pDevice)
- {
- if (theApp.vsync)
- dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync
- else
- dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync
- resetDevice();
- }
- }
-
- if(!strcmp(option, "triplebuffering"))
- {
- if (theApp.tripleBuffering)
- dpp.BackBufferCount = 3;
- else
- dpp.BackBufferCount = 2;
- resetDevice();
- }
-
- if(!strcmp(option, "d3dKeepAspectRatio"))
- keepAspectRatio = true; //theApp.d3dKeepAspectRatio;
-}
-
-int Direct3DDisplay::selectFullScreenMode(GUID **)
-{ // interface function
- int w, h, b;
- UniVideoModeDlg dlg(0, &w, &h, &b, &SelectedFreq, &SelectedAdapter);
-
- if (0 == dlg.DoModal())
- {
- return (b<<24) + (w<<12) + h;
- // Bits<<24 | Width<<12 | Height
- }
- else
- {
- return -1;
- }
-}
-
-int Direct3DDisplay::selectFullScreenMode2()
-{
- return (SelectedAdapter<<16) + SelectedFreq;
-}
-
-// Reset Device and Resources
-bool Direct3DDisplay::resetDevice()
-{
- invalidateDeviceObjects();
- if(pTexture) {
- pDevice->SetTexture( 0, NULL);
- pTexture->Release();
- pTexture = NULL;
- }
- if (!theApp.menuToggle)
- pDevice->SetDialogBoxMode( FALSE );
-
- HRESULT hr = pDevice->Reset(&dpp);
- if (hr == D3D_OK)
- {
- restoreDeviceObjects();
- if(!initializeOffscreen(width, height))
- return false;
-
- return true;
- }
- else
- {
- switch(hr)
- {
- case D3DERR_DEVICELOST:
- winlog("Render_DeviceLost: D3DERR_DEVICELOST\n");
- break;
- case D3DERR_DRIVERINTERNALERROR:
- winlog("Render_DeviceLost: D3DERR_DRIVERINTERNALERROR\n");
- break;
- case D3DERR_INVALIDCALL:
- winlog("Render_DeviceLost: D3DERR_INVALIDCALL\n");
- break;
- case D3DERR_OUTOFVIDEOMEMORY:
- winlog("Render_DeviceLost: D3DERR_OUTOFVIDEOMEMORY\n");
- break;
- case E_OUTOFMEMORY:
- winlog("Render_DeviceLost: E_OUTOFMEMORY\n");
- break;
- }
- winlog("Failed to reset device: %08x\n", hr);
- return false;
- }
-}
-
-void Direct3DDisplay::initializeMatrices()
-{ // Configure matrices to use standard orthogonal projection (2D)
- D3DXMATRIX Ortho2D;
- D3DXMATRIX Identity;
- D3DXMATRIX temp1, temp2;
-
- // Initialize an orthographic matrix which automaticly compensates the difference between image size and texture size
- if (!keepAspectRatio) {
- D3DXMatrixOrthoOffCenterLH(
- &Ortho2D,
- 0.0f, // left
- 1.0f * (FLOAT)width / (FLOAT)textureWidth, // right
- 1.0f * (FLOAT)height / (FLOAT)textureHeight, // bottom
- 0.0f, // top
- 0.0f, 1.0f); // z
- } else {
- FLOAT l=0.0f, r=0.0f, b=0.0f, t=0.0f;
- FLOAT srcAspectRatio = (FLOAT)theApp.sizeX / (FLOAT)theApp.sizeY;
- FLOAT aspectRatio = (FLOAT)dpp.BackBufferWidth / (FLOAT)dpp.BackBufferHeight;
- FLOAT textureImageDiffX = (FLOAT)width / (FLOAT)textureWidth;
- FLOAT textureImageDiffY = (FLOAT)height / (FLOAT)textureHeight;
- aspectRatio /= srcAspectRatio;
-
- if(aspectRatio > 1.0f) {
- r = 1.0f * textureImageDiffX * aspectRatio;
- b = 1.0f * textureImageDiffY;
- } else {
- r = 1.0f * textureImageDiffX;
- b = 1.0f * textureImageDiffY * (1.0f / aspectRatio);
- }
-
- D3DXMatrixOrthoOffCenterLH(
- &temp1,
- l,
- r,
- b,
- t,
- 0.0f, 1.0f); // z
- D3DXMatrixTranslation( // translate matrix > move image
- &temp2,
- (aspectRatio>1.0)?( (aspectRatio - 1.0f) * 0.5f * textureImageDiffX ):0.0f,
- (aspectRatio<1.0)?( ((1.0f/aspectRatio) - 1.0f) * 0.5f * textureImageDiffY ):0.0f,
- 0.0f);
- D3DXMatrixMultiply(&Ortho2D, &temp2, &temp1);
- }
-
- D3DXMatrixIdentity(&Identity); // Identity = Do not change anything
-
- pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D);
- pDevice->SetTransform(D3DTS_WORLD, &Identity);
- pDevice->SetTransform(D3DTS_VIEW, &Identity);
-}
-
-IDisplay *newDirect3DDisplay()
-{
- return new Direct3DDisplay();
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+
+#include "Display.h"
+
+#include "MainWnd.h"
+
+#include "../System.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../Text.h"
+#include "../Util.h"
+#include "../gb/gbGlobals.h"
+
+// Direct3D
+#define DIRECT3D_VERSION 0x0900
+#include // main include file
+#include // required for font rednering
+#include // contains debug functions
+
+extern int Init_2xSaI(u32); // initializes all pixel filters
+extern int systemSpeed;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#ifdef MMX
+extern "C" bool cpu_mmx;
+extern bool detectMMX();
+#endif
+
+
+class Direct3DDisplay : public IDisplay {
+private:
+ LPDIRECT3D9 pD3D;
+ LPDIRECT3DDEVICE9 pDevice;
+ D3DPRESENT_PARAMETERS dpp;
+ D3DFORMAT screenFormat;
+ LPDIRECT3DSURFACE9 emulatedImage;
+ D3DTEXTUREFILTERTYPE filter;
+ int width;
+ int height;
+ RECT destRect;
+ bool failed;
+ ID3DXFont *pFont;
+
+ void createFont();
+ void destroyFont();
+ void createSurface();
+ void destroySurface();
+ void calculateDestRect();
+ bool resetDevice();
+
+public:
+ Direct3DDisplay();
+ virtual ~Direct3DDisplay();
+ virtual DISPLAY_TYPE getType() { return DIRECT_3D; };
+
+ virtual bool initialize();
+ virtual void cleanup();
+ virtual void clear();
+ virtual void render();
+
+ virtual void renderMenu();
+ virtual bool changeRenderSize( int w, int h );
+ virtual void resize( int w, int h );
+ virtual void setOption( const char *option, int value );
+ virtual int selectFullScreenMode( GUID ** );
+};
+
+
+Direct3DDisplay::Direct3DDisplay()
+{
+ pD3D = NULL;
+ pDevice = NULL;
+ screenFormat = D3DFMT_X8R8G8B8;
+ width = 0;
+ height = 0;
+ failed = false;
+ pFont = NULL;
+ emulatedImage = NULL;
+ filter = D3DTEXF_POINT;
+}
+
+
+Direct3DDisplay::~Direct3DDisplay()
+{
+ cleanup();
+}
+
+
+void Direct3DDisplay::cleanup()
+{
+ destroyFont();
+ destroySurface();
+
+ if( pDevice ) {
+ pDevice->Release();
+ pDevice = NULL;
+ }
+
+ if( pD3D ) {
+ pD3D->Release();
+ pD3D = NULL;
+ }
+}
+
+
+bool Direct3DDisplay::initialize()
+{
+ switch(theApp.cartridgeType)
+ {
+ case IMAGE_GBA:
+ theApp.sizeX = 240;
+ theApp.sizeY = 160;
+ break;
+ case IMAGE_GB:
+ if (gbBorderOn)
+ {
+ theApp.sizeX = 256;
+ theApp.sizeY = 224;
+ }
+ else
+ {
+ theApp.sizeX = 160;
+ theApp.sizeY = 144;
+ }
+ break;
+ }
+
+
+ switch(theApp.videoOption)
+ {
+ case VIDEO_1X:
+ theApp.surfaceSizeX = theApp.sizeX;
+ theApp.surfaceSizeY = theApp.sizeY;
+ break;
+ case VIDEO_2X:
+ theApp.surfaceSizeX = theApp.sizeX * 2;
+ theApp.surfaceSizeY = theApp.sizeY * 2;
+ break;
+ case VIDEO_3X:
+ theApp.surfaceSizeX = theApp.sizeX * 3;
+ theApp.surfaceSizeY = theApp.sizeY * 3;
+ break;
+ case VIDEO_4X:
+ theApp.surfaceSizeX = theApp.sizeX * 4;
+ theApp.surfaceSizeY = theApp.sizeY * 4;
+ break;
+ case VIDEO_320x240:
+ case VIDEO_640x480:
+ case VIDEO_800x600:
+ case VIDEO_1024x768:
+ case VIDEO_1280x1024:
+ case VIDEO_OTHER:
+ float scaleX = ((float)theApp.fsWidth / theApp.sizeX);
+ float scaleY = ((float)theApp.fsHeight / theApp.sizeY);
+ float min = (scaleX < scaleY) ? scaleX : scaleY;
+ if(theApp.fullScreenStretch) {
+ theApp.surfaceSizeX = theApp.fsWidth;
+ theApp.surfaceSizeY = theApp.fsHeight;
+ } else {
+ theApp.surfaceSizeX = (int)(theApp.sizeX * min);
+ theApp.surfaceSizeY = (int)(theApp.sizeY * min);
+ }
+ break;
+ }
+
+ theApp.rect.left = 0;
+ theApp.rect.top = 0;
+ theApp.rect.right = theApp.sizeX;
+ theApp.rect.bottom = theApp.sizeY;
+
+ theApp.dest.left = 0;
+ theApp.dest.top = 0;
+ theApp.dest.right = theApp.surfaceSizeX;
+ theApp.dest.bottom = theApp.surfaceSizeY;
+
+
+ DWORD style = WS_POPUP | WS_VISIBLE;
+ DWORD styleEx = 0;
+
+ if(theApp.videoOption <= VIDEO_4X) {
+ style |= WS_OVERLAPPEDWINDOW;
+ } else {
+ styleEx = 0;
+ }
+
+ if(theApp.videoOption <= VIDEO_4X) {
+ AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
+ } else {
+ AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
+ }
+
+ int winSizeX = theApp.dest.right-theApp.dest.left;
+ int winSizeY = theApp.dest.bottom-theApp.dest.top;
+
+ if(theApp.videoOption > VIDEO_4X) {
+ winSizeX = theApp.fsWidth;
+ winSizeY = theApp.fsHeight;
+ }
+
+ int x = 0, y = 0;
+
+ if(theApp.videoOption <= VIDEO_4X) {
+ x = theApp.windowPositionX;
+ y = theApp.windowPositionY;
+ }
+
+
+ // Create a window
+ MainWnd *pWnd = new MainWnd;
+ theApp.m_pMainWnd = pWnd;
+
+ pWnd->CreateEx(styleEx,
+ theApp.wndClass,
+ _T("VisualBoyAdvance"),
+ style,
+ x,y,winSizeX,winSizeY,
+ NULL,
+ 0);
+
+ if (!(HWND)*pWnd) {
+ DXTRACE_ERR_MSGBOX( _T("Error creating window"), 0 );
+ return FALSE;
+ }
+ pWnd->DragAcceptFiles(TRUE);
+ theApp.updateMenuBar();
+ theApp.adjustDestRect();
+
+
+ // load Direct3D v9
+ pD3D = Direct3DCreate9( D3D_SDK_VERSION );
+
+ if(pD3D == NULL) {
+ DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D object"), 0 );
+ return FALSE;
+ }
+
+ theApp.mode320Available = FALSE;
+ theApp.mode640Available = FALSE;
+ theApp.mode800Available = FALSE;
+
+ D3DDISPLAYMODE mode;
+ pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
+ screenFormat = mode.Format;
+
+ switch(mode.Format) {
+ case D3DFMT_R8G8B8:
+ systemColorDepth = 24;
+ systemRedShift = 19;
+ systemGreenShift = 11;
+ systemBlueShift = 3;
+ break;
+ case D3DFMT_X8R8G8B8:
+ systemColorDepth = 32;
+ systemRedShift = 19;
+ systemGreenShift = 11;
+ systemBlueShift = 3;
+ Init_2xSaI(32);
+ break;
+ case D3DFMT_R5G6B5:
+ systemColorDepth = 16;
+ systemRedShift = 11;
+ systemGreenShift = 6;
+ systemBlueShift = 0;
+ Init_2xSaI(565);
+ break;
+ case D3DFMT_X1R5G5B5:
+ systemColorDepth = 16;
+ systemRedShift = 10;
+ systemGreenShift = 5;
+ systemBlueShift = 0;
+ Init_2xSaI(555);
+ break;
+ default:
+ DXTRACE_ERR_MSGBOX( _T("Unsupport D3D format"), 0 );
+ return false;
+ }
+ theApp.fsColorDepth = systemColorDepth;
+ utilUpdateSystemColorMaps();
+
+
+#ifdef MMX
+ if(!theApp.disableMMX) {
+ cpu_mmx = theApp.detectMMX();
+ } else {
+ cpu_mmx = 0;
+ }
+#endif
+
+
+ theApp.updateFilter();
+ theApp.updateIFB();
+
+
+ // create device
+ ZeroMemory(&dpp, sizeof(dpp));
+ dpp.Windowed = TRUE;
+ dpp.BackBufferFormat = mode.Format;
+ dpp.BackBufferCount = theApp.tripleBuffering ? 2 : 1;
+ dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ dpp.BackBufferWidth = 0; // use width of hDeviceWindow
+ dpp.BackBufferHeight = 0; // use height of hDeviceWindow
+ dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
+ dpp.PresentationInterval = theApp.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
+
+ HRESULT hret = pD3D->CreateDevice(
+ D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ pWnd->GetSafeHwnd(),
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+ &dpp,
+ &pDevice);
+ if( FAILED( hret ) ) {
+ DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D device"), hret );
+ return false;
+ }
+
+ createFont();
+ createSurface();
+ calculateDestRect();
+
+ setOption( _T("d3dFilter"), theApp.d3dFilter );
+
+ if(failed) return false;
+
+ return TRUE;
+}
+
+
+void Direct3DDisplay::renderMenu()
+{
+ checkFullScreen();
+ if(theApp.m_pMainWnd) {
+ theApp.m_pMainWnd->DrawMenuBar();
+ }
+}
+
+
+void Direct3DDisplay::clear()
+{
+ if( pDevice ) {
+ pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00,0x00,0x00), 0.0f, 0 );
+ }
+}
+
+
+void Direct3DDisplay::render()
+{
+ if( failed ) return;
+ if(!pDevice) return;
+ if( FAILED( pDevice->TestCooperativeLevel() ) ) return;
+
+ clear();
+
+ pDevice->BeginScene();
+
+ // copy pix to emulatedImage and apply pixel filter if selected
+ HRESULT hr;
+ D3DLOCKED_RECT lr;
+ if( FAILED( hr = emulatedImage->LockRect( &lr, NULL, D3DLOCK_DISCARD ) ) ) {
+ DXTRACE_ERR_MSGBOX( _T("Can not lock back buffer"), hr );
+ return;
+ } else {
+ if( !theApp.filterFunction ) {
+ copyImage( pix, lr.pBits, theApp.sizeX, theApp.sizeY, lr.Pitch, systemColorDepth );
+ } else {
+ u32 pitch = theApp.filterWidth * (systemColorDepth>>3) + 4;
+ theApp.filterFunction( pix + pitch,
+ pitch,
+ (u8*)theApp.delta,
+ (u8*)lr.pBits,
+ lr.Pitch,
+ theApp.filterWidth,
+ theApp.filterHeight);
+ }
+ emulatedImage->UnlockRect();
+ }
+
+ // copy emulatedImage to pBackBuffer and scale with or without aspect ratio
+ LPDIRECT3DSURFACE9 pBackBuffer;
+ pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
+ if( theApp.fullScreenStretch ) {
+ pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, NULL, filter );
+ } else {
+ pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, &destRect, filter );
+ }
+ pBackBuffer->Release();
+ pBackBuffer = NULL;
+
+ D3DCOLOR color;
+ RECT r;
+ r.left = 4;
+ r.right = dpp.BackBufferWidth - 4;
+
+ if( theApp.screenMessage ) {
+ color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0xFF, 0x00, 0x00) : D3DCOLOR_ARGB(0xFF, 0xFF, 0x00, 0x00);
+ if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage && pFont ) {
+ r.top = dpp.BackBufferHeight - 20;
+ r.bottom = dpp.BackBufferHeight - 4;
+ pFont->DrawText( NULL, theApp.screenMessageBuffer, -1, &r, 0, color );
+ } else {
+ theApp.screenMessage = false;
+ }
+ }
+
+ if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) {
+ color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0x00, 0x00, 0xFF) : D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0xFF);
+ char buffer[30];
+ if( theApp.showSpeed == 1 ) {
+ sprintf( buffer, "%3d%%", systemSpeed );
+ } else {
+ sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames );
+ }
+
+ r.top = 4;
+ r.bottom = 20;
+ pFont->DrawText( NULL, buffer, -1, &r, 0, color );
+ }
+
+ pDevice->EndScene();
+
+ pDevice->Present( NULL, NULL, NULL, NULL );
+
+ return;
+}
+
+
+bool Direct3DDisplay::changeRenderSize( int w, int h )
+{
+ if( (w != width) || (h != height) ) {
+ width = w; height = h;
+ if( pDevice ) {
+ destroySurface();
+ createSurface();
+ calculateDestRect();
+ }
+ }
+ return true;
+}
+
+
+void Direct3DDisplay::resize( int w, int h )
+{
+ if( (w != dpp.BackBufferWidth) || (h != dpp.BackBufferHeight) ) {
+ dpp.BackBufferWidth = (UINT)w;
+ dpp.BackBufferHeight = (UINT)h;
+ resetDevice();
+ calculateDestRect();
+ }
+}
+
+
+int Direct3DDisplay::selectFullScreenMode( GUID ** )
+{
+ HRESULT hr;
+ D3DDISPLAYMODE dm;
+ if( FAILED( hr = pDevice->GetDisplayMode( 0, &dm ) ) ) {
+ DXTRACE_ERR_MSGBOX( _T("pDevice->GetDisplayMode failed"), hr );
+ return false;
+ }
+
+ UINT bitsPerPixel;
+ switch( dm.Format )
+ {
+ case D3DFMT_A2R10G10B10:
+ case D3DFMT_X8R8G8B8:
+ bitsPerPixel = 32;
+ break;
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R5G6B5:
+ bitsPerPixel = 16;
+ break;
+ }
+
+ return (bitsPerPixel << 24) | (dm.Width << 12) | dm.Height;
+}
+
+
+void Direct3DDisplay::createFont()
+{
+ if( !pFont ) {
+ HRESULT hr = D3DXCreateFont(
+ pDevice,
+ 14,
+ 0,
+ FW_BOLD,
+ 1,
+ FALSE,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ DEFAULT_PITCH || FF_DONTCARE,
+ _T("Arial"),
+ &pFont );
+ if( FAILED( hr ) ) {
+ DXTRACE_ERR_MSGBOX( _T("createFont failed"), hr );
+ }
+ }
+}
+
+
+void Direct3DDisplay::destroyFont()
+{
+ if( pFont ) {
+ pFont->Release();
+ pFont = NULL;
+ }
+}
+
+
+void Direct3DDisplay::createSurface()
+{
+ if( !emulatedImage ) {
+ HRESULT hr = pDevice->CreateOffscreenPlainSurface(
+ width, height,
+ dpp.BackBufferFormat,
+ D3DPOOL_DEFAULT,
+ &emulatedImage,
+ NULL );
+ if( FAILED( hr ) ) {
+ DXTRACE_ERR_MSGBOX( _T("createSurface failed"), hr );
+ }
+ }
+}
+
+
+void Direct3DDisplay::destroySurface()
+{
+ if( emulatedImage ) {
+ emulatedImage->Release();
+ emulatedImage = NULL;
+ }
+}
+
+
+void Direct3DDisplay::calculateDestRect()
+{
+ float scaleX = (float)dpp.BackBufferWidth / (float)width;
+ float scaleY = (float)dpp.BackBufferHeight / (float)height;
+ float min = (scaleX < scaleY) ? scaleX : scaleY;
+ if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) {
+ min = (float)theApp.fsMaxScale;
+ }
+ destRect.left = 0;
+ destRect.top = 0;
+ destRect.right = (LONG)(width * min);
+ destRect.bottom = (LONG)(height * min);
+ if( destRect.right != dpp.BackBufferWidth ) {
+ LONG diff = (dpp.BackBufferWidth - destRect.right) / 2;
+ destRect.left += diff;
+ destRect.right += diff;
+ }
+ if( destRect.bottom != dpp.BackBufferHeight ) {
+ LONG diff = (dpp.BackBufferHeight - destRect.bottom) / 2;
+ destRect.top += diff;
+ destRect.bottom += diff;
+ }
+}
+
+
+void Direct3DDisplay::setOption( const char *option, int value )
+{
+ if( !_tcscmp( option, _T("vsync") ) ) {
+ dpp.PresentationInterval = value ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
+ resetDevice();
+ }
+
+ if( !_tcscmp( option, _T("tripleBuffering") ) ) {
+ dpp.BackBufferCount = value ? 2 : 1;
+ resetDevice();
+ }
+
+ if( !_tcscmp( option, _T("d3dFilter") ) ) {
+ switch( value )
+ {
+ case 0: //point
+ filter = D3DTEXF_POINT;
+ break;
+ case 1: //linear
+ filter = D3DTEXF_LINEAR;
+ break;
+ }
+ }
+
+ if( !_tcscmp( option, _T("maxScale") ) ) {
+ calculateDestRect();
+ }
+}
+
+
+bool Direct3DDisplay::resetDevice()
+{
+ if( !pDevice ) return false;
+
+ HRESULT hr;
+ destroyFont();
+ destroySurface();
+ if( FAILED( hr = pDevice->Reset( &dpp ) ) ) {
+ //DXTRACE_ERR_MSGBOX( _T("pDevice->Reset failed"), hr );
+ failed = true;
+ return false;
+ }
+ createFont();
+ createSurface();
+ failed = false;
+ return true;
+}
+
+
+IDisplay *newDirect3DDisplay()
+{
+ return new Direct3DDisplay();
+}
diff --git a/src/win32/DirectDraw.cpp b/src/win32/DirectDraw.cpp
index 67d4f48e..0a4797e5 100644
--- a/src/win32/DirectDraw.cpp
+++ b/src/win32/DirectDraw.cpp
@@ -21,8 +21,6 @@
#define DIRECTDRAW_VERSION 0x0700
#include
-#include
-
#include "../System.h"
#include "../gb/gbGlobals.h"
#include "../GBA.h"
@@ -33,7 +31,9 @@
#include "VBA.h"
#include "MainWnd.h"
#include "Reg.h"
-#include "..\..\res\resource.h"
+#include "resource.h"
+
+#include "Display.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -58,18 +58,7 @@ private:
int height;
bool failed;
- volatile unsigned wait_lastscanline;
- volatile unsigned wait_screenheight;
- volatile unsigned wait_maxheight;
- volatile unsigned wait_firstline;
- HANDLE wait_event;
- UINT wait_timerres;
- UINT wait_timerid;
-
bool initializeOffscreen(int w, int h);
- bool StartTimer();
- void StopTimer();
- static void CALLBACK g_timer_proc( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2 );
public:
DirectDrawDisplay();
virtual ~DirectDrawDisplay();
@@ -83,9 +72,8 @@ public:
virtual bool changeRenderSize(int w, int h);
virtual DISPLAY_TYPE getType() { return DIRECT_DRAW; };
virtual void setOption(const char *, int) {}
+ virtual bool isSkinSupported() { return true; }
virtual int selectFullScreenMode(GUID **);
-
- void timer_proc( UINT id, UINT msg, DWORD_PTR dw1, DWORD_PTR dw2 );
};
static HRESULT WINAPI checkModesAvailable(LPDDSURFACEDESC2 surf, LPVOID lpContext)
@@ -144,10 +132,6 @@ DirectDrawDisplay::DirectDrawDisplay()
width = 0;
height = 0;
failed = false;
- wait_screenheight = 0;
- wait_event = 0;
- wait_timerres = 0;
- wait_timerid = 0;
}
DirectDrawDisplay::~DirectDrawDisplay()
@@ -158,15 +142,6 @@ DirectDrawDisplay::~DirectDrawDisplay()
void DirectDrawDisplay::cleanup()
{
if(pDirectDraw != NULL) {
- if ( wait_timerid ) {
- StopTimer();
- }
-
- if ( wait_event ) {
- CloseHandle( wait_event );
- wait_event = 0;
- }
-
if(ddsClipper != NULL) {
ddsClipper->Release();
ddsClipper = NULL;
@@ -192,7 +167,11 @@ void DirectDrawDisplay::cleanup()
}
if(ddrawDLL != NULL) {
- FreeLibrary(ddrawDLL);
+#ifdef _AFXDLL
+ AfxFreeLibrary( ddrawDLL );
+#else
+ FreeLibrary( ddrawDLL );
+#endif
ddrawDLL = NULL;
}
width = 0;
@@ -228,13 +207,13 @@ bool DirectDrawDisplay::initialize()
case VIDEO_1280x1024:
case VIDEO_OTHER:
{
- float scaleX = ((float)theApp.fsWidth / (float)theApp.sizeX);
- float scaleY = ((float)theApp.fsHeight / (float)theApp.sizeY);
- float min = scaleX < scaleY ? scaleX : scaleY;
+ int scaleX = (theApp.fsWidth / theApp.sizeX);
+ int scaleY = (theApp.fsHeight / theApp.sizeY);
+ int min = scaleX < scaleY ? scaleX : scaleY;
if(theApp.fsMaxScale)
min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
- theApp.surfaceSizeX = (int)(theApp.sizeX * min);
- theApp.surfaceSizeY = (int)(theApp.sizeY * min);
+ theApp.surfaceSizeX = theApp.sizeX * min;
+ theApp.surfaceSizeY = theApp.sizeY * min;
if(theApp.fullScreenStretch) {
theApp.surfaceSizeX = theApp.fsWidth;
theApp.surfaceSizeY = theApp.fsHeight;
@@ -242,7 +221,7 @@ bool DirectDrawDisplay::initialize()
}
break;
}
-
+
theApp.rect.left = 0;
theApp.rect.top = 0;
theApp.rect.right = theApp.sizeX;
@@ -306,7 +285,12 @@ bool DirectDrawDisplay::initialize()
if(theApp.pVideoDriverGUID)
guid = theApp.pVideoDriverGUID;
- ddrawDLL = LoadLibrary("DDRAW.DLL");
+#ifdef _AFXDLL
+ ddrawDLL = AfxLoadLibrary("ddraw.dll");
+#else
+ ddrawDLL = LoadLibrary( _T("ddraw.dll") );
+#endif
+
HRESULT (WINAPI *DDrawCreateEx)(GUID *,LPVOID *,REFIID,IUnknown *);
if(ddrawDLL != NULL) {
DDrawCreateEx = (HRESULT (WINAPI *)(GUID *,LPVOID *,REFIID,IUnknown *))
@@ -459,12 +443,6 @@ bool DirectDrawDisplay::initialize()
}
// }
- wait_event = CreateEvent( NULL, FALSE, FALSE, NULL );
-
- if ( ! StartTimer() ) {
- return FALSE;
- }
-
DDPIXELFORMAT px;
px.dwSize = sizeof(px);
@@ -633,7 +611,7 @@ bool DirectDrawDisplay::initializeOffscreen(int w, int h)
winlog("B shift: %d\n", systemBlueShift);
}
- utilUpdateSystemColorMaps(theApp.filterLCD);
+ utilUpdateSystemColorMaps();
width = w;
height = h;
return true;
@@ -671,6 +649,7 @@ void DirectDrawDisplay::checkFullScreen()
void DirectDrawDisplay::render()
{
HRESULT hret;
+ unsigned int nBytesPerPixel = systemColorDepth>>3;
if(pDirectDraw == NULL ||
ddsOffscreen == NULL ||
@@ -743,62 +722,9 @@ void DirectDrawDisplay::render()
copyY = 144;
}
}
- // MMX doesn't seem to be faster to copy the data
- __asm {
- mov eax, copyX;
- mov ebx, copyY;
-
- mov esi, pix;
- mov edi, ddsDesc.lpSurface;
- mov edx, ddsDesc.lPitch;
- cmp systemColorDepth, 16;
- jnz gbaOtherColor;
- sub edx, eax;
- sub edx, eax;
- lea esi,[esi+2*eax+4];
- shr eax, 1;
- gbaLoop16bit:
- mov ecx, eax;
- repz movsd;
- inc esi;
- inc esi;
- inc esi;
- inc esi;
- add edi, edx;
- dec ebx;
- jnz gbaLoop16bit;
- jmp gbaLoopEnd;
- gbaOtherColor:
- cmp systemColorDepth, 32;
- jnz gbaOtherColor2;
-
- sub edx, eax;
- sub edx, eax;
- sub edx, eax;
- sub edx, eax;
- lea esi, [esi+4*eax+4];
- gbaLoop32bit:
- mov ecx, eax;
- repz movsd;
- add esi, 4;
- add edi, edx;
- dec ebx;
- jnz gbaLoop32bit;
- jmp gbaLoopEnd;
- gbaOtherColor2:
- lea eax, [eax+2*eax];
- sub edx, eax;
- gbaLoop24bit:
- mov ecx, eax;
- shr ecx, 2;
- repz movsd;
- add edi, edx;
- dec ebx;
- jnz gbaLoop24bit;
- gbaLoopEnd:
- }
+ copyImage( pix, ddsDesc.lpSurface, copyX, copyY, ddsDesc.lPitch, systemColorDepth );
}
- if(theApp.showSpeed && theApp.videoOption > VIDEO_4X) {
+ if(theApp.showSpeed && (theApp.videoOption > VIDEO_4X || theApp.skin != NULL)) {
char buffer[30];
if(theApp.showSpeed == 1)
sprintf(buffer, "%3d%%", systemSpeed);
@@ -826,8 +752,7 @@ void DirectDrawDisplay::render()
if(hret == DD_OK) {
if(theApp.vsync && !(theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) && !speedup) { // isn't the Flip() call synced unless a certain flag is passed to it?
- //hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
- WaitForSingleObject( wait_event, 100 );
+ hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
}
ddsOffscreen->PageLock(0);
if(theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) {
@@ -865,7 +790,7 @@ void DirectDrawDisplay::render()
SetTextColor(hdc, RGB(255,0,0));
SetBkMode(hdc,TRANSPARENT);
TextOut(hdc, theApp.dest.left+10, theApp.dest.bottom - 20, theApp.screenMessageBuffer,
- strlen(theApp.screenMessageBuffer));
+ (int)_tcslen(theApp.screenMessageBuffer));
ddsPrimary->ReleaseDC(hdc);
} else {
theApp.screenMessage = false;
@@ -883,74 +808,8 @@ int DirectDrawDisplay::selectFullScreenMode(GUID **pGUID)
return winVideoModeSelect(theApp.m_pMainWnd, pGUID);
}
-bool DirectDrawDisplay::StartTimer()
-{
- MMRESULT result;
-
- TIMECAPS tc;
-
- if ( TIMERR_NOERROR == timeGetDevCaps( & tc, sizeof( TIMECAPS ) ) ) {
- wait_timerres = min( max( tc.wPeriodMin, 1 ), tc.wPeriodMax );
- timeBeginPeriod( wait_timerres );
- } else {
- return false;
- }
-
- result = timeSetEvent( wait_timerres, wait_timerres, & DirectDrawDisplay::g_timer_proc, ( DWORD_PTR ) this, TIME_PERIODIC );
-
- if (NULL != result) {
- wait_timerid = (UINT)result;
- return true;
- }
-
- return false;
-}
-
-void DirectDrawDisplay::StopTimer()
-{
- MMRESULT result;
-
- result = timeKillEvent( wait_timerid );
- if ( TIMERR_NOERROR == result ) {
- wait_timerid = 0;
- }
-
- if ( 0 != wait_timerres ) {
- timeEndPeriod( wait_timerres );
- wait_timerres = 0;
- }
-}
-
-void CALLBACK DirectDrawDisplay::g_timer_proc( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2 )
-{
- DirectDrawDisplay * p_this = reinterpret_cast< DirectDrawDisplay * >( dwUser );
- if ( p_this ) {
- p_this->timer_proc( id, msg, dw1, dw2 );
- }
-}
-
-void DirectDrawDisplay::timer_proc( UINT id, UINT msg, DWORD_PTR dw1, DWORD_PTR dw2 )
-{
- DWORD scanline;
- if ( pDirectDraw->GetScanLine( & scanline ) == DD_OK ) {
- unsigned height = GetSystemMetrics( SM_CYSCREEN );
- if ( wait_screenheight != height ) {
- wait_screenheight = height;
- wait_maxheight = height;
- }
- if ( scanline >= wait_maxheight ) wait_maxheight = scanline + 1;
-
- scanline = ( scanline + wait_maxheight - min( theApp.dest.bottom, wait_screenheight ) ) % wait_maxheight;
-
- if ( scanline < wait_lastscanline ) {
- PulseEvent( wait_event );
- }
-
- wait_lastscanline = scanline;
- }
-}
-
IDisplay *newDirectDrawDisplay()
{
return new DirectDrawDisplay();
}
+
diff --git a/src/win32/DirectInput.cpp b/src/win32/DirectInput.cpp
index c280ced5..074559c2 100644
--- a/src/win32/DirectInput.cpp
+++ b/src/win32/DirectInput.cpp
@@ -1,594 +1,598 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include "Reg.h"
-#include "WinResUtil.h"
-#include "Input.h"
-
-#define DIRECTINPUT_VERSION 0x0500
-#include
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-extern void directXMessage(const char *);
-extern void winlog(const char *msg,...);
-
-#define POV_UP 1
-#define POV_DOWN 2
-#define POV_RIGHT 4
-#define POV_LEFT 8
-
-class DirectInput : public Input {
-private:
- HINSTANCE dinputDLL;
-
-public:
- virtual void checkDevices();
- DirectInput();
- virtual ~DirectInput();
-
- virtual bool initialize();
- virtual bool readDevices();
- virtual u32 readDevice(int which);
- virtual CString getKeyName(int key);
- virtual void checkKeys();
- virtual void checkMotionKeys();
- virtual void activate();
- virtual void loadSettings();
- virtual void saveSettings();
-};
-
-struct deviceInfo {
- LPDIRECTINPUTDEVICE device;
- BOOL isPolled;
- int nButtons;
- int nAxes;
- int nPovs;
- BOOL first;
- struct {
- DWORD offset;
- LONG center;
- LONG negative;
- LONG positive;
- } axis[8];
- int needed;
- union {
- UCHAR data[256];
- DIJOYSTATE state;
- };
-};
-
-static deviceInfo *currentDevice = NULL;
-static int numDevices = 1;
-static deviceInfo *pDevices = NULL;
-static LPDIRECTINPUT pDirectInput = NULL;
-static int joyDebug = 0;
-static int axisNumber = 0;
-
-
-//KeyList joypad[JOYPADS * KEYS_PER_PAD + MOTION_KEYS];
-
-
-USHORT defvalues[JOYPADS * KEYS_PER_PAD + MOTION_KEYS] =
- {
- DIK_LEFT, DIK_RIGHT,
- DIK_UP, DIK_DOWN,
- DIK_Z, DIK_X,
- DIK_RETURN,DIK_BACK,
- DIK_A, DIK_S,
- DIK_SPACE, DIK_F12,
- DIK_C,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,
- DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2
-};
-
-
-void winReadKey(const char *name, KeyList& Keys)
-{
- CString TxtKeyList = regQueryStringValue(name, "");
- int curPos= 0;
-
- CString resToken=TxtKeyList.Tokenize(",",curPos);
- while (resToken != "")
- {
- Keys.AddTail(atoi(resToken));
- resToken= TxtKeyList.Tokenize(",",curPos);
- };
-}
-
-void winReadKey(const char *name, int num, KeyList& Keys)
-{
- char buffer[80];
-
- sprintf(buffer, "Joy%d_%s", num, name);
- winReadKey(buffer, Keys);
-}
-
-
-void winReadKeys()
-{
-
- for(int i = 0; i < JOYPADS; i++) {
- winReadKey("Left", i, joypad[JOYPAD(i,KEY_LEFT)]);
- winReadKey("Right", i, joypad[JOYPAD(i, KEY_RIGHT)]);
- winReadKey("Up", i, joypad[JOYPAD(i,KEY_UP)]);
- winReadKey("Down", i, joypad[JOYPAD(i,KEY_DOWN)]);
- winReadKey("A", i, joypad[JOYPAD(i,KEY_BUTTON_A)]);
- winReadKey("B", i, joypad[JOYPAD(i,KEY_BUTTON_B)]);
- winReadKey("L", i, joypad[JOYPAD(i,KEY_BUTTON_L)]);
- winReadKey("R", i, joypad[JOYPAD(i,KEY_BUTTON_R)]);
- winReadKey("Start", i, joypad[JOYPAD(i,KEY_BUTTON_START)]);
- winReadKey("Select", i, joypad[JOYPAD(i,KEY_BUTTON_SELECT)]);
- winReadKey("Speed", i, joypad[JOYPAD(i,KEY_BUTTON_SPEED)]);
- winReadKey("Capture", i, joypad[JOYPAD(i,KEY_BUTTON_CAPTURE)]);
- winReadKey("GS", i, joypad[JOYPAD(i,KEY_BUTTON_GS)]);
- }
- winReadKey("Motion_Left", joypad[MOTION(KEY_LEFT)]);
- winReadKey("Motion_Right", joypad[MOTION(KEY_RIGHT)]);
- winReadKey("Motion_Up", joypad[MOTION(KEY_UP)]);
- winReadKey("Motion_Down", joypad[MOTION(KEY_DOWN)]);
-}
-
-void winSaveKey(char *name, KeyList& value)
-{
- CString txtKeys;
-
- POSITION p = value.GetHeadPosition();
- while(p!=NULL)
- {
- CString tmp;
- tmp.Format("%d", value.GetNext(p));
- txtKeys+=tmp;
- if (p!=NULL)
- txtKeys+=",";
- }
- regSetStringValue(name, txtKeys);
-}
-
-static void winSaveKey(char *name, int num, KeyList& value)
-{
- char buffer[80];
-
- sprintf(buffer, "Joy%d_%s", num, name);
- winSaveKey(buffer, value);
-}
-
-void winSaveKeys()
-{
- for(int i = 0; i < JOYPADS; i++) {
- winSaveKey("Left", i, joypad[JOYPAD(i,KEY_LEFT)]);
- winSaveKey("Right", i, joypad[JOYPAD(i,KEY_RIGHT)]);
- winSaveKey("Up", i, joypad[JOYPAD(i,KEY_UP)]);
- winSaveKey("Speed", i, joypad[JOYPAD(i,KEY_BUTTON_SPEED)]);
- winSaveKey("Capture", i, joypad[JOYPAD(i,KEY_BUTTON_CAPTURE)]);
- winSaveKey("GS", i, joypad[JOYPAD(i,KEY_BUTTON_GS)]);
- winSaveKey("Down", i, joypad[JOYPAD(i,KEY_DOWN)]);
- winSaveKey("A", i, joypad[JOYPAD(i,KEY_BUTTON_A)]);
- winSaveKey("B", i, joypad[JOYPAD(i,KEY_BUTTON_B)]);
- winSaveKey("L", i, joypad[JOYPAD(i,KEY_BUTTON_L)]);
- winSaveKey("R", i, joypad[JOYPAD(i,KEY_BUTTON_R)]);
- winSaveKey("Start", i, joypad[JOYPAD(i,KEY_BUTTON_START)]);
- winSaveKey("Select", i, joypad[JOYPAD(i,KEY_BUTTON_SELECT)]);
- }
- regSetDwordValue("joyVersion", 1);
-
- winSaveKey("Motion_Left",
- joypad[MOTION(KEY_LEFT)]);
- winSaveKey("Motion_Right",
- joypad[MOTION(KEY_RIGHT)]);
- winSaveKey("Motion_Up",
- joypad[MOTION(KEY_UP)]);
- winSaveKey("Motion_Down",
- joypad[MOTION(KEY_DOWN)]);
-}
-
-static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
- VOID* pContext )
-{
- DIPROPRANGE diprg;
- diprg.diph.dwSize = sizeof(DIPROPRANGE);
- diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- diprg.diph.dwHow = DIPH_BYOFFSET;
- diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
-
- diprg.lMin = -32768;
- diprg.lMax = 32767;
- // try to set the range
- if(FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) {
- // Get the range for the axis
- if( FAILED(currentDevice->device->
- GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) {
- return DIENUM_STOP;
- }
- }
-
- DIPROPDWORD didz;
-
- didz.diph.dwSize = sizeof(didz);
- didz.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- didz.diph.dwHow = DIPH_BYOFFSET;
- didz.diph.dwObj = pdidoi->dwOfs;
-
- didz.dwData = 5000;
-
- currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph);
-
- LONG center = (diprg.lMin + diprg.lMax)/2;
- LONG threshold = (diprg.lMax - center)/2;
-
- // only 8 axis supported
- if(axisNumber < 8) {
- currentDevice->axis[axisNumber].center = center;
- currentDevice->axis[axisNumber].negative = center - threshold;
- currentDevice->axis[axisNumber].positive = center + threshold;
- currentDevice->axis[axisNumber].offset = pdidoi->dwOfs;
- }
- axisNumber++;
- return DIENUM_CONTINUE;
-}
-
-static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
- VOID* pContext )
-{
- return DIENUM_CONTINUE;
-}
-
-static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst,
- LPVOID lpvContext)
-{
- ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo));
-
- HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance,
- &pDevices[numDevices].device,
- NULL);
-
- if(hRet != DI_OK)
- return DIENUM_STOP;
-
- DIDEVCAPS caps;
- caps.dwSize=sizeof(DIDEVCAPS);
-
- hRet = pDevices[numDevices].device->GetCapabilities(&caps);
-
- if(hRet == DI_OK) {
- if(caps.dwFlags & DIDC_POLLEDDATAFORMAT ||
- caps.dwFlags & DIDC_POLLEDDEVICE)
- pDevices[numDevices].isPolled = TRUE;
-
- pDevices[numDevices].nButtons = caps.dwButtons;
- pDevices[numDevices].nAxes = caps.dwAxes;
- pDevices[numDevices].nPovs = caps.dwPOVs;
-
- for(int i = 0; i < 6; i++) {
- pDevices[numDevices].axis[i].center = 0x8000;
- pDevices[numDevices].axis[i].negative = 0x4000;
- pDevices[numDevices].axis[i].positive = 0xc000;
- }
- } else if(joyDebug)
- winlog("Failed to get device capabilities %08x\n", hRet);
-
- if(joyDebug) {
- // don't translate. debug only
- winlog("******************************\n");
- winlog("Joystick %2d name : %s\n", numDevices, pInst->tszProductName);
- }
-
- numDevices++;
-
-
- return DIENUM_CONTINUE;
-}
-
-BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst,
- LPVOID lpvContext)
-{
- numDevices++;
-
- return DIENUM_CONTINUE;
-}
-
-static int getPovState(DWORD value)
-{
- int state = 0;
- if(LOWORD(value) != 0xFFFF) {
- if(value < 9000 || value > 27000)
- state |= POV_UP;
- if(value > 0 && value < 18000)
- state |= POV_RIGHT;
- if(value > 9000 && value < 27000)
- state |= POV_DOWN;
- if(value > 18000)
- state |= POV_LEFT;
- }
- return state;
-}
-
-static void checkKeys()
-{
- int dev = 0;
- int i;
-
- for(i = 0; i < (sizeof(joypad) / sizeof(joypad[0])); i++)
- {
- if (joypad[i].IsEmpty() && defvalues[i])
- joypad[i].AddTail(defvalues[i]);
- POSITION p = joypad[i].GetHeadPosition();
- while(p!=NULL)
- {
- USHORT k = joypad[i].GetNext(p);
- if (k > 0 && DEVICEOF(k) < numDevices)
- pDevices[DEVICEOF(k)].needed = true;
- }
- }
-}
-
-#define KEYDOWN(buffer,key) (buffer[key] & 0x80)
-
-static bool readKeyboard()
-{
- if(pDevices[0].needed) {
- if (!theApp.dinputKeyFocus) {
- memset(pDevices[0].data, 0, 256);
- return true;
- }
- HRESULT hret = pDevices[0].device->
- GetDeviceState(256,
- (LPVOID)pDevices[0].data);
-
- if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
- hret = pDevices[0].device->Acquire();
- if(hret != DI_OK)
- return false;
- hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data);
- }
-
- return hret == DI_OK;
- }
- return true;
-}
-
-static bool readJoystick(int joy)
-{
- if(pDevices[joy].needed) {
- if(pDevices[joy].isPolled)
- ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
-
- HRESULT hret = pDevices[joy].device->
- GetDeviceState(sizeof(DIJOYSTATE),
- (LPVOID)&pDevices[joy].state);
-
- if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
- hret = pDevices[joy].device->Acquire();
-
- if(hret == DI_OK) {
-
- if(pDevices[joy].isPolled)
- ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
-
- hret = pDevices[joy].device->
- GetDeviceState(sizeof(DIJOYSTATE),
- (LPVOID)&pDevices[joy].state);
- }
- }
-
- return hret == DI_OK;
- }
-
- return true;
-}
-
-static void checkKeyboard()
-{
- HRESULT hret = pDevices[0].device->Acquire();
- hret = pDevices[0].device->
- GetDeviceState(256,
- (LPVOID)pDevices[0].data);
-
- if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
- return;
- }
-
- if(hret == DI_OK) {
- for(int i = 0; i < 256; i++) {
- if(KEYDOWN(pDevices[0].data, i)) {
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i);
- break;
- }
- }
- }
-}
-
-static void checkJoypads()
-{
- DIDEVICEOBJECTINSTANCE di;
-
- ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
-
- di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
-
- int i =0;
-
- DIJOYSTATE joystick;
-
- for(i = 1; i < numDevices; i++) {
- HRESULT hret = pDevices[i].device->Acquire();
-
-
- if(pDevices[i].isPolled)
- ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll();
-
- hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick);
-
- int j;
-
- if(pDevices[i].first) {
- memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
- pDevices[i].first = FALSE;
- continue;
- }
-
- for(j = 0; j < pDevices[i].nButtons; j++) {
- if(((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j])
- & joystick.rgbButtons[j]) & 0x80) {
- HWND focus = GetFocus();
-
- SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128);
- }
- }
-
- for(j = 0; j < pDevices[i].nAxes && j < 8; j++) {
- LONG value = pDevices[i].axis[j].center;
- LONG old = 0;
- switch(pDevices[i].axis[j].offset) {
- case DIJOFS_X:
- value = joystick.lX;
- old = pDevices[i].state.lX;
- break;
- case DIJOFS_Y:
- value = joystick.lY;
- old = pDevices[i].state.lY;
- break;
- case DIJOFS_Z:
- value = joystick.lZ;
- old = pDevices[i].state.lZ;
- break;
- case DIJOFS_RX:
- value = joystick.lRx;
- old = pDevices[i].state.lRx;
- break;
- case DIJOFS_RY:
- value = joystick.lRy;
- old = pDevices[i].state.lRy;
- break;
- case DIJOFS_RZ:
- value = joystick.lRz;
- old = pDevices[i].state.lRz;
- break;
- case DIJOFS_SLIDER(0):
- value = joystick.rglSlider[0];
- old = pDevices[i].state.rglSlider[0];
- break;
- case DIJOFS_SLIDER(1):
- value = joystick.rglSlider[1];
- old = pDevices[i].state.rglSlider[1];
- break;
- }
- if(value != old) {
- if(value < pDevices[i].axis[j].negative)
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1));
- else if (value > pDevices[i].axis[j].positive)
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1);
- }
- }
-
- for(j = 0;j < 4 && j < pDevices[i].nPovs; j++) {
- if(LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) {
- int state = getPovState(joystick.rgdwPOV[j]);
-
- if(state & POV_UP)
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20);
- else if(state & POV_DOWN)
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21);
- else if(state & POV_RIGHT)
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22);
- else if(state & POV_LEFT)
- SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23);
- }
- }
-
- memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
- }
-}
-
-BOOL checkKey(int key)
-{
- int dev = DEVICEOF(key);
- int k = KEYOF(key);
-
- if(dev == 0) {
- return KEYDOWN(pDevices[0].data,k);
- } else {
- if(k < 16) {
- int axis = k >> 1;
- LONG value = pDevices[dev].axis[axis].center;
- switch(pDevices[dev].axis[axis].offset) {
- case DIJOFS_X:
- value = pDevices[dev].state.lX;
- break;
- case DIJOFS_Y:
- value = pDevices[dev].state.lY;
- break;
- case DIJOFS_Z:
- value = pDevices[dev].state.lZ;
- break;
- case DIJOFS_RX:
- value = pDevices[dev].state.lRx;
- break;
- case DIJOFS_RY:
- value = pDevices[dev].state.lRy;
- break;
- case DIJOFS_RZ:
- value = pDevices[dev].state.lRz;
- break;
- case DIJOFS_SLIDER(0):
- value = pDevices[dev].state.rglSlider[0];
- break;
- case DIJOFS_SLIDER(1):
- value = pDevices[dev].state.rglSlider[1];
- break;
- }
-
- if(k & 1)
- return value > pDevices[dev].axis[axis].positive;
- return value < pDevices[dev].axis[axis].negative;
- } else if(k < 48) {
- int hat = (k >> 2) & 3;
- int state = getPovState(pDevices[dev].state.rgdwPOV[hat]);
- BOOL res = FALSE;
- switch(k & 3) {
- case 0:
- res = state & POV_UP;
- break;
- case 1:
- res = state & POV_DOWN;
- break;
- case 2:
- res = state & POV_RIGHT;
- break;
- case 3:
- res = state & POV_LEFT;
- break;
- }
- return res;
- } else if(k >= 128) {
- return pDevices[dev].state.rgbButtons[k-128] & 0x80;
- }
- }
-
- return FALSE;
-}
+
+/* VisualBoyAdvance S - GB & GBA emulator
+ Copyright (C) 2006 Spacy
+
+ Original VBA Credits:
+ Copyright (C) 1999-2003 Forgotten
+ Copyright (C) 2004-2006 VBA development team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "stdafx.h"
+#include "VBA.h"
+#include "Input.h"
+#include "Reg.h"
+#include "WinResUtil.h"
+
+#define DIRECTINPUT_VERSION 0x0800
+#include
+#pragma comment(lib, "Dinput8")
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+extern void directXMessage(const char *);
+extern void winlog(const char *msg,...);
+
+#define POV_UP 1
+#define POV_DOWN 2
+#define POV_RIGHT 4
+#define POV_LEFT 8
+
+class DirectInput : public Input {
+public:
+ virtual void checkDevices();
+ DirectInput();
+ virtual ~DirectInput();
+
+ virtual bool initialize();
+ virtual bool readDevices();
+ virtual u32 readDevice(int which);
+ virtual CString getKeyName(LONG_PTR key);
+ virtual void checkKeys();
+ virtual void checkMotionKeys();
+ virtual void activate();
+ virtual void loadSettings();
+ virtual void saveSettings();
+};
+
+struct deviceInfo {
+ LPDIRECTINPUTDEVICE8 device;
+ BOOL isPolled;
+ int nButtons;
+ int nAxes;
+ int nPovs;
+ BOOL first;
+ struct {
+ DWORD offset;
+ LONG center;
+ LONG negative;
+ LONG positive;
+ } axis[8];
+ int needed;
+ union {
+ UCHAR data[256];
+ DIJOYSTATE state;
+ };
+};
+
+static deviceInfo *currentDevice = NULL;
+static int numDevices = 1;
+static deviceInfo *pDevices = NULL;
+static LPDIRECTINPUT8 pDirectInput = NULL;
+static int axisNumber = 0;
+
+
+
+
+LONG_PTR defvalues[JOYPADS * KEYS_PER_PAD + MOTION_KEYS] =
+ {
+ DIK_LEFT, DIK_RIGHT,
+ DIK_UP, DIK_DOWN,
+ DIK_Z, DIK_X,
+ DIK_RETURN,DIK_BACK,
+ DIK_A, DIK_S,
+ DIK_SPACE, DIK_F12,
+ DIK_C,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,
+ DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2
+};
+
+
+void winReadKey(const char *name, KeyList& Keys)
+{
+ CString TxtKeyList = regQueryStringValue(name, "");
+ int curPos= 0;
+
+ CString resToken=TxtKeyList.Tokenize(",",curPos);
+ while (resToken != "")
+ {
+ Keys.AddTail(atoi(resToken));
+ resToken= TxtKeyList.Tokenize(",",curPos);
+ };
+}
+
+void winReadKey(const char *name, int num, KeyList& Keys)
+{
+ char buffer[80];
+
+ sprintf(buffer, "Joy%d_%s", num, name);
+ winReadKey(buffer, Keys);
+}
+
+
+void winReadKeys()
+{
+
+ for(int i = 0; i < JOYPADS; i++) {
+ winReadKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]);
+ winReadKey("Right", i, theApp.input->joypaddata[JOYPAD(i, KEY_RIGHT)]);
+ winReadKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]);
+ winReadKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]);
+ winReadKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]);
+ winReadKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]);
+ winReadKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]);
+ winReadKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]);
+ winReadKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]);
+ winReadKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]);
+ winReadKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]);
+ winReadKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]);
+ winReadKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]);
+ }
+ winReadKey("Motion_Left", theApp.input->joypaddata[MOTION(KEY_LEFT)]);
+ winReadKey("Motion_Right", theApp.input->joypaddata[MOTION(KEY_RIGHT)]);
+ winReadKey("Motion_Up", theApp.input->joypaddata[MOTION(KEY_UP)]);
+ winReadKey("Motion_Down", theApp.input->joypaddata[MOTION(KEY_DOWN)]);
+}
+
+void winSaveKey(char *name, KeyList& value)
+{
+ CString txtKeys;
+
+ POSITION p = value.GetHeadPosition();
+ while(p!=NULL)
+ {
+ CString tmp;
+ tmp.Format("%d", value.GetNext(p));
+ txtKeys+=tmp;
+ if (p!=NULL)
+ txtKeys+=",";
+ }
+ regSetStringValue(name, txtKeys);
+}
+
+static void winSaveKey(char *name, int num, KeyList& value)
+{
+ char buffer[80];
+
+ sprintf(buffer, "Joy%d_%s", num, name);
+ winSaveKey(buffer, value);
+}
+
+void winSaveKeys()
+{
+ for(int i = 0; i < JOYPADS; i++) {
+ winSaveKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]);
+ winSaveKey("Right", i, theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)]);
+ winSaveKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]);
+ winSaveKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]);
+ winSaveKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]);
+ winSaveKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]);
+ winSaveKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]);
+ winSaveKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]);
+ winSaveKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]);
+ winSaveKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]);
+ winSaveKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]);
+ winSaveKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]);
+ winSaveKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]);
+ }
+ regSetDwordValue("joyVersion", 1);
+
+ winSaveKey("Motion_Left",
+ theApp.input->joypaddata[MOTION(KEY_LEFT)]);
+ winSaveKey("Motion_Right",
+ theApp.input->joypaddata[MOTION(KEY_RIGHT)]);
+ winSaveKey("Motion_Up",
+ theApp.input->joypaddata[MOTION(KEY_UP)]);
+ winSaveKey("Motion_Down",
+ theApp.input->joypaddata[MOTION(KEY_DOWN)]);
+}
+
+static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
+ VOID* pContext )
+{
+ DIPROPRANGE diprg;
+ diprg.diph.dwSize = sizeof(DIPROPRANGE);
+ diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ diprg.diph.dwHow = DIPH_BYOFFSET;
+ diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
+
+ diprg.lMin = -32768;
+ diprg.lMax = 32767;
+ // try to set the range
+ if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) {
+ // Get the range for the axis
+ if ( FAILED(currentDevice->device->
+ GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) {
+ return DIENUM_STOP;
+ }
+ }
+
+ DIPROPDWORD didz;
+
+ didz.diph.dwSize = sizeof(didz);
+ didz.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ didz.diph.dwHow = DIPH_BYOFFSET;
+ didz.diph.dwObj = pdidoi->dwOfs;
+
+ didz.dwData = 5000;
+
+ currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph);
+
+ LONG center = (diprg.lMin + diprg.lMax)/2;
+ LONG threshold = (diprg.lMax - center)/2;
+
+ // only 8 axis supported
+ if (axisNumber < 8) {
+ currentDevice->axis[axisNumber].center = center;
+ currentDevice->axis[axisNumber].negative = center - threshold;
+ currentDevice->axis[axisNumber].positive = center + threshold;
+ currentDevice->axis[axisNumber].offset = pdidoi->dwOfs;
+ }
+ axisNumber++;
+ return DIENUM_CONTINUE;
+}
+
+static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
+ VOID* pContext )
+{
+ return DIENUM_CONTINUE;
+}
+
+static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst,
+ LPVOID lpvContext)
+{
+ ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo));
+
+ HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance,
+ &pDevices[numDevices].device,
+ NULL);
+
+ if (hRet != DI_OK)
+ return DIENUM_STOP;
+
+ DIDEVCAPS caps;
+ caps.dwSize=sizeof(DIDEVCAPS);
+
+ hRet = pDevices[numDevices].device->GetCapabilities(&caps);
+
+ if (hRet == DI_OK) {
+ if (caps.dwFlags & DIDC_POLLEDDATAFORMAT ||
+ caps.dwFlags & DIDC_POLLEDDEVICE)
+ pDevices[numDevices].isPolled = TRUE;
+
+ pDevices[numDevices].nButtons = caps.dwButtons;
+ pDevices[numDevices].nAxes = caps.dwAxes;
+ pDevices[numDevices].nPovs = caps.dwPOVs;
+
+ for (int i = 0; i < 6; i++) {
+ pDevices[numDevices].axis[i].center = 0x8000;
+ pDevices[numDevices].axis[i].negative = 0x4000;
+ pDevices[numDevices].axis[i].positive = 0xc000;
+ }
+ }
+
+
+ numDevices++;
+
+
+ return DIENUM_CONTINUE;
+}
+
+BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst,
+ LPVOID lpvContext)
+{
+ numDevices++;
+
+ return DIENUM_CONTINUE;
+}
+
+static int getPovState(DWORD value)
+{
+ int state = 0;
+ if (LOWORD(value) != 0xFFFF) {
+ if (value < 9000 || value > 27000)
+ state |= POV_UP;
+ if (value > 0 && value < 18000)
+ state |= POV_RIGHT;
+ if (value > 9000 && value < 27000)
+ state |= POV_DOWN;
+ if (value > 18000)
+ state |= POV_LEFT;
+ }
+ return state;
+}
+
+static void checkKeys()
+{
+ LONG_PTR dev = 0;
+ int i;
+
+ for(i = 0; i < (sizeof(theApp.input->joypaddata) / sizeof(theApp.input->joypaddata[0])); i++)
+ {
+ if (theApp.input->joypaddata[i].IsEmpty() && defvalues[i])
+ theApp.input->joypaddata[i].AddTail(defvalues[i]);
+ POSITION p = theApp.input->joypaddata[i].GetHeadPosition();
+ while(p!=NULL)
+ {
+ LONG_PTR k = theApp.input->joypaddata[i].GetNext(p);
+ if (k > 0 && DEVICEOF(k) < numDevices)
+ pDevices[DEVICEOF(k)].needed = true;
+ }
+ }
+}
+
+#define KEYDOWN(buffer,key) (buffer[key] & 0x80)
+
+static bool readKeyboard()
+{
+ if (pDevices[0].needed) {
+ HRESULT hret = pDevices[0].device->
+ GetDeviceState(256,
+ (LPVOID)pDevices[0].data);
+
+ if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
+ hret = pDevices[0].device->Acquire();
+ if (hret != DI_OK)
+ return false;
+ hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data);
+ }
+
+ return hret == DI_OK;
+ }
+ return true;
+}
+
+static bool readJoystick(int joy)
+{
+ if (pDevices[joy].needed) {
+ if (pDevices[joy].isPolled)
+ ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
+
+ HRESULT hret = pDevices[joy].device->
+ GetDeviceState(sizeof(DIJOYSTATE),
+ (LPVOID)&pDevices[joy].state);
+
+ if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
+ hret = pDevices[joy].device->Acquire();
+
+ if (hret == DI_OK) {
+
+ if (pDevices[joy].isPolled)
+ ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
+
+ hret = pDevices[joy].device->
+ GetDeviceState(sizeof(DIJOYSTATE),
+ (LPVOID)&pDevices[joy].state);
+ }
+ }
+
+ return hret == DI_OK;
+ }
+
+ return true;
+}
+
+static void checkKeyboard()
+{
+ // mham fix. Patch #1378104
+ UCHAR keystate[256];
+ HRESULT hret = pDevices[0].device->Acquire();
+
+ if (pDevices[0].first) {
+ pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data);
+ pDevices[0].first = FALSE;
+ return;
+ }
+
+ hret = pDevices[0].device->
+ GetDeviceState(256, (LPVOID)keystate);
+
+ if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
+ return;
+ }
+
+ if (hret == DI_OK) {
+ for (int i = 0; i < 256; i++) {
+ if (keystate[i] == pDevices[0].data[i]) continue;
+ if (KEYDOWN(keystate, i)) {
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i);
+ break;
+ }
+ }
+ }
+ memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256);
+}
+
+static void checkJoypads()
+{
+ DIDEVICEOBJECTINSTANCE di;
+
+ ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
+
+ di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
+
+ int i =0;
+
+ DIJOYSTATE joystick;
+
+ for (i = 1; i < numDevices; i++) {
+ HRESULT hret = pDevices[i].device->Acquire();
+
+
+ if (pDevices[i].isPolled)
+ ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll();
+
+ hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick);
+
+ int j;
+
+ if (pDevices[i].first) {
+ memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
+ pDevices[i].first = FALSE;
+ continue;
+ }
+
+ for (j = 0; j < pDevices[i].nButtons; j++) {
+ if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j])
+ & joystick.rgbButtons[j]) & 0x80) {
+ HWND focus = GetFocus();
+
+ SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128);
+ }
+ }
+
+ for (j = 0; j < pDevices[i].nAxes && j < 8; j++) {
+ LONG value = pDevices[i].axis[j].center;
+ LONG old = 0;
+ switch (pDevices[i].axis[j].offset) {
+ case DIJOFS_X:
+ value = joystick.lX;
+ old = pDevices[i].state.lX;
+ break;
+ case DIJOFS_Y:
+ value = joystick.lY;
+ old = pDevices[i].state.lY;
+ break;
+ case DIJOFS_Z:
+ value = joystick.lZ;
+ old = pDevices[i].state.lZ;
+ break;
+ case DIJOFS_RX:
+ value = joystick.lRx;
+ old = pDevices[i].state.lRx;
+ break;
+ case DIJOFS_RY:
+ value = joystick.lRy;
+ old = pDevices[i].state.lRy;
+ break;
+ case DIJOFS_RZ:
+ value = joystick.lRz;
+ old = pDevices[i].state.lRz;
+ break;
+ case DIJOFS_SLIDER(0):
+ value = joystick.rglSlider[0];
+ old = pDevices[i].state.rglSlider[0];
+ break;
+ case DIJOFS_SLIDER(1):
+ value = joystick.rglSlider[1];
+ old = pDevices[i].state.rglSlider[1];
+ break;
+ }
+ if (value != old) {
+ if (value < pDevices[i].axis[j].negative)
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1));
+ else if (value > pDevices[i].axis[j].positive)
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1);
+ }
+ }
+
+ for (j = 0;j < 4 && j < pDevices[i].nPovs; j++) {
+ if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) {
+ int state = getPovState(joystick.rgdwPOV[j]);
+
+ if (state & POV_UP)
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20);
+ else if (state & POV_DOWN)
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21);
+ else if (state & POV_RIGHT)
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22);
+ else if (state & POV_LEFT)
+ SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23);
+ }
+ }
+
+ memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
+ }
+}
+
+BOOL checkKey(LONG_PTR key)
+{
+ LONG_PTR dev = (key >> 8);
+
+ LONG_PTR k = (key & 255);
+
+ if (dev == 0) {
+ return KEYDOWN(pDevices[0].data,k);
+ } else {
+ if (k < 16) {
+ LONG_PTR axis = k >> 1;
+ LONG value = pDevices[dev].axis[axis].center;
+ switch (pDevices[dev].axis[axis].offset) {
+ case DIJOFS_X:
+ value = pDevices[dev].state.lX;
+ break;
+ case DIJOFS_Y:
+ value = pDevices[dev].state.lY;
+ break;
+ case DIJOFS_Z:
+ value = pDevices[dev].state.lZ;
+ break;
+ case DIJOFS_RX:
+ value = pDevices[dev].state.lRx;
+ break;
+ case DIJOFS_RY:
+ value = pDevices[dev].state.lRy;
+ break;
+ case DIJOFS_RZ:
+ value = pDevices[dev].state.lRz;
+ break;
+ case DIJOFS_SLIDER(0):
+ value = pDevices[dev].state.rglSlider[0];
+ break;
+ case DIJOFS_SLIDER(1):
+ value = pDevices[dev].state.rglSlider[1];
+ break;
+ }
+
+ if (k & 1)
+ return value > pDevices[dev].axis[axis].positive;
+ return value < pDevices[dev].axis[axis].negative;
+ } else if (k < 48) {
+ LONG_PTR hat = (k >> 2) & 3;
+ int state = getPovState(pDevices[dev].state.rgdwPOV[hat]);
+ BOOL res = FALSE;
+ switch (k & 3) {
+ case 0:
+ res = state & POV_UP;
+ break;
+ case 1:
+ res = state & POV_DOWN;
+ break;
+ case 2:
+ res = state & POV_RIGHT;
+ break;
+ case 3:
+ res = state & POV_LEFT;
+ break;
+ }
+ return res;
+ } else if (k >= 128) {
+ return pDevices[dev].state.rgbButtons[k-128] & 0x80;
+ }
+ }
+
+ return FALSE;
+}
BOOL checkKey(KeyList &k)
{
@@ -599,373 +603,337 @@ BOOL checkKey(KeyList &k)
return TRUE;
}
return FALSE;
-}
-
-DirectInput::DirectInput()
-{
- dinputDLL = NULL;
-}
-
-DirectInput::~DirectInput()
-{
- saveSettings();
- if(pDirectInput != NULL) {
- if(pDevices) {
- for(int i = 0; i < numDevices ; i++) {
- if(pDevices[i].device) {
- pDevices[i].device->Unacquire();
- pDevices[i].device->Release();
- pDevices[i].device = NULL;
- }
- }
- free(pDevices);
- pDevices = NULL;
- }
-
- pDirectInput->Release();
- pDirectInput = NULL;
- }
-
- if(dinputDLL) {
- FreeLibrary(dinputDLL);
- dinputDLL = NULL;
- }
-}
-
-bool DirectInput::initialize()
-{
- joyDebug = GetPrivateProfileInt("config",
- "joyDebug",
- 0,
- "VBA.ini");
- dinputDLL = LoadLibrary("DINPUT.DLL");
- HRESULT (WINAPI *DInputCreate)(HINSTANCE,DWORD,LPDIRECTINPUT *,IUnknown *);
- if(dinputDLL != NULL) {
- DInputCreate = (HRESULT (WINAPI *)(HINSTANCE,DWORD,LPDIRECTINPUT *,IUnknown *))
- GetProcAddress(dinputDLL, "DirectInputCreateA");
-
- if(DInputCreate == NULL) {
- directXMessage("DirectInputCreateA");
- return false;
- }
- } else {
- directXMessage("DINPUT.DLL");
- return false;
- }
-
- HRESULT hret = DInputCreate(AfxGetInstanceHandle(),
- DIRECTINPUT_VERSION,
- &pDirectInput,
- NULL);
- if(hret != DI_OK) {
- // errorMessage(myLoadString(IDS_ERROR_DISP_CREATE), hret);
- return false;
- }
-
- hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK,
- DIEnumDevicesCallback2,
- NULL,
- DIEDFL_ATTACHEDONLY);
-
-
-
- pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo));
-
- hret = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL);
- pDevices[0].isPolled = false;
- pDevices[0].needed = true;
-
- if(hret != DI_OK) {
- // errorMessage(myLoadString(IDS_ERROR_DISP_CREATEDEVICE), hret);
- return false;
- }
-
-
- numDevices = 1;
-
- hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK,
- DIEnumDevicesCallback,
- NULL,
- DIEDFL_ATTACHEDONLY);
-
- // hret = pDevices[0].device->SetCooperativeLevel(hWindow,
- // DISCL_FOREGROUND|
- // DISCL_NONEXCLUSIVE);
-
- if(hret != DI_OK) {
- // errorMessage(myLoadString(IDS_ERROR_DISP_LEVEL), hret);
- return false;
- }
-
- hret = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard);
-
- if(hret != DI_OK) {
- // errorMessage(myLoadString(IDS_ERROR_DISP_DATAFORMAT), hret);
- return false;
- }
-
- for(int i = 1; i < numDevices; i++) {
- pDevices[i].device->SetDataFormat(&c_dfDIJoystick);
- pDevices[i].needed = false;
- currentDevice = &pDevices[i];
- axisNumber = 0;
- currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS);
- currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV);
- if(joyDebug) {
- // don't translate. debug only
- winlog("Joystick %2d polled : %d\n", i, currentDevice->isPolled);
- winlog("Joystick %2d buttons : %d\n", i, currentDevice->nButtons);
- winlog("Joystick %2d povs : %d\n", i, currentDevice->nPovs);
- winlog("Joystick %2d axes : %d\n", i, currentDevice->nAxes);
- for(int j = 0; j < currentDevice->nAxes; j++) {
- winlog("Axis %2d offset : %08lx\n", j, currentDevice->axis[j].
- offset);
- winlog("Axis %2d center : %08lx\n", j, currentDevice->axis[j].
- center);
- winlog("Axis %2d negative : %08lx\n", j, currentDevice->axis[j].
- negative);
- winlog("Axis %2d positive : %08lx\n", j, currentDevice->axis[j].
- positive);
- }
- }
-
- currentDevice = NULL;
- }
-
- if (1) for(int i = 0; i < numDevices; i++)
- pDevices[i].device->Acquire();
-
- return true;
-}
-
-bool DirectInput::readDevices()
-{
- bool ok = true;
- for(int i = 0; i < numDevices; i++) {
- if(pDevices[i].needed) {
- if(i) {
- ok = readJoystick(i);
- } else
- ok = readKeyboard();
- }
- }
- return ok;
-}
-
-u32 DirectInput::readDevice(int which)
-{
- u32 res = 0;
- int i = theApp.joypadDefault;
- if(which >= 0 && which <= 3)
- i = which;
-
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_A)]))
- res |= 1;
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_B)]))
- res |= 2;
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_SELECT)]))
- res |= 4;
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_START)]))
- res |= 8;
- if(checkKey(joypad[JOYPAD(i,KEY_RIGHT)]))
- res |= 16;
- if(checkKey(joypad[JOYPAD(i,KEY_LEFT)]))
- res |= 32;
- if(checkKey(joypad[JOYPAD(i,KEY_UP)]))
- res |= 64;
- if(checkKey(joypad[JOYPAD(i,KEY_DOWN)]))
- res |= 128;
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_R)]))
- res |= 256;
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_L)]))
- res |= 512;
-
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_GS)]))
- res |= 4096;
-
- if(theApp.autoFire) {
- res &= (~theApp.autoFire);
- if(theApp.autoFireToggle)
- res |= theApp.autoFire;
- theApp.autoFireToggle = !theApp.autoFireToggle;
- }
-
- // disallow L+R or U+D of being pressed at the same time
- if((res & 48) == 48)
- res &= ~16;
- if((res & 192) == 192)
- res &= ~128;
-
- if(theApp.movieRecording) {
- if(i == theApp.joypadDefault) {
- if(res != theApp.movieLastJoypad) {
- fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile);
- fwrite(&res, 1, sizeof(res), theApp.movieFile);
- theApp.movieLastJoypad = res;
- }
- }
- }
- if(theApp.moviePlaying) {
- if(theApp.movieFrame == theApp.moviePlayFrame) {
- theApp.movieLastJoypad = theApp.movieNextJoypad;
- theApp.movieReadNext();
- }
- res = theApp.movieLastJoypad;
- }
- // we don't record speed up or screen capture buttons
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_SPEED)]) || theApp.speedupToggle)
- res |= 1024;
- if(checkKey(joypad[JOYPAD(i,KEY_BUTTON_CAPTURE)]))
- res |= 2048;
-
- return res;
-}
-
-CString DirectInput::getKeyName(int key)
-{
- int d = (key >> 8);
- int k = key & 255;
-
- DIDEVICEOBJECTINSTANCE di;
-
- ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
-
- di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
-
- CString winBuffer = winResLoadString(IDS_ERROR);
-
- if(d == 0) {
- pDevices[0].device->GetObjectInfo(&di,key,DIPH_BYOFFSET);
- winBuffer = di.tszName;
- } else {
- if(k < 16) {
- if(k < 4) {
- switch(k) {
- case 0:
- winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d);
- break;
- case 1:
- winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d);
- break;
- case 2:
- winBuffer.Format(winResLoadString(IDS_JOY_UP), d);
- break;
- case 3:
- winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d);
- break;
- }
- } else {
- pDevices[d].device->GetObjectInfo(&di,
- pDevices[d].axis[k>>1].offset,
- DIPH_BYOFFSET);
- if(k & 1)
- winBuffer.Format("Joy %d %s +", d, di.tszName);
- else
- winBuffer.Format("Joy %d %s -", d, di.tszName);
- }
- } else if(k < 48) {
- int hat = (k >> 2) & 3;
- pDevices[d].device->GetObjectInfo(&di,
- DIJOFS_POV(hat),
- DIPH_BYOFFSET);
- char *dir = "up";
- int dd = k & 3;
- if(dd == 1)
- dir = "down";
- else if(dd == 2)
- dir = "right";
- else if(dd == 3)
- dir = "left";
- winBuffer.Format("Joy %d %s %s", d, di.tszName, dir);
- } else {
- pDevices[d].device->GetObjectInfo(&di,
- DIJOFS_BUTTON(k-128),
- DIPH_BYOFFSET);
- winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName);
- }
- }
-
- return winBuffer;
-}
-
-void DirectInput::checkKeys()
-{
- ::checkKeys();
-}
-
-void DirectInput::checkMotionKeys()
-{
- if(checkKey(joypad[MOTION(KEY_LEFT)])) {
- theApp.sensorX += 3;
- if(theApp.sensorX > 2197)
- theApp.sensorX = 2197;
- if(theApp.sensorX < 2047)
- theApp.sensorX = 2057;
- } else if(checkKey(joypad[MOTION(KEY_RIGHT)])) {
- theApp.sensorX -= 3;
- if(theApp.sensorX < 1897)
- theApp.sensorX = 1897;
- if(theApp.sensorX > 2047)
- theApp.sensorX = 2037;
- } else if(theApp.sensorX > 2047) {
- theApp.sensorX -= 2;
- if(theApp.sensorX < 2047)
- theApp.sensorX = 2047;
- } else {
- theApp.sensorX += 2;
- if(theApp.sensorX > 2047)
- theApp.sensorX = 2047;
- }
-
- if(checkKey(joypad[MOTION(KEY_UP)])) {
- theApp.sensorY += 3;
- if(theApp.sensorY > 2197)
- theApp.sensorY = 2197;
- if(theApp.sensorY < 2047)
- theApp.sensorY = 2057;
- } else if(checkKey(joypad[MOTION(KEY_DOWN)])) {
- theApp.sensorY -= 3;
- if(theApp.sensorY < 1897)
- theApp.sensorY = 1897;
- if(theApp.sensorY > 2047)
- theApp.sensorY = 2037;
- } else if(theApp.sensorY > 2047) {
- theApp.sensorY -= 2;
- if(theApp.sensorY < 2047)
- theApp.sensorY = 2047;
- } else {
- theApp.sensorY += 2;
- if(theApp.sensorY > 2047)
- theApp.sensorY = 2047;
- }
-}
-
-Input *newDirectInput()
-{
- return new DirectInput;
-}
-
-
-void DirectInput::checkDevices()
-{
- checkJoypads();
- checkKeyboard();
-}
-
-void DirectInput::activate()
-{
- for(int i = 0; i < numDevices; i++) {
- if(pDevices != NULL && pDevices[i].device != NULL)
- pDevices[i].device->Acquire();
- }
-}
-
-void DirectInput::loadSettings()
-{
- winReadKeys();
-}
-
-void DirectInput::saveSettings()
-{
- winSaveKeys();
-}
+}
+
+DirectInput::DirectInput()
+{}
+
+DirectInput::~DirectInput()
+{
+ saveSettings();
+ if (pDirectInput != NULL) {
+ if (pDevices) {
+ for (int i = 0; i < numDevices ; i++) {
+ if (pDevices[i].device) {
+ pDevices[i].device->Unacquire();
+ pDevices[i].device->Release();
+ pDevices[i].device = NULL;
+ }
+ }
+ free(pDevices);
+ pDevices = NULL;
+ }
+
+ pDirectInput->Release();
+ pDirectInput = NULL;
+ }
+}
+
+
+bool DirectInput::initialize()
+{
+
+ HRESULT hr;
+
+ hr = DirectInput8Create(
+ AfxGetInstanceHandle(),
+ DIRECTINPUT_VERSION,
+ IID_IDirectInput8,
+ (LPVOID*)&pDirectInput,
+ NULL );
+
+ if ( hr != DI_OK ) {
+ return false;
+ }
+
+
+
+
+ hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL,
+ DIEnumDevicesCallback2,
+ NULL,
+ DIEDFL_ATTACHEDONLY);
+
+
+
+ pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo));
+
+ hr = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL);
+ pDevices[0].isPolled = false;
+ pDevices[0].needed = true;
+ pDevices[0].first = true;
+
+ if (hr != DI_OK) {
+ return false;
+ }
+
+
+ numDevices = 1;
+
+ hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL,
+ DIEnumDevicesCallback,
+ NULL,
+ DIEDFL_ATTACHEDONLY);
+
+
+ if (hr != DI_OK) {
+ return false;
+ }
+
+ hr = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard);
+
+ if (hr != DI_OK) {
+ return false;
+ }
+
+ int i;
+ for (i = 1; i < numDevices; i++) {
+ pDevices[i].device->SetDataFormat(&c_dfDIJoystick);
+ pDevices[i].needed = false;
+ pDevices[i].first = true;
+ currentDevice = &pDevices[i];
+ axisNumber = 0;
+ currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS);
+ currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV);
+
+
+ currentDevice = NULL;
+ }
+
+ for (i = 0; i < numDevices; i++)
+ pDevices[i].device->Acquire();
+
+ return true;
+}
+
+bool DirectInput::readDevices()
+{
+ bool ok = true;
+ for (int i = 0; i < numDevices; i++) {
+ if (pDevices[i].needed) {
+ if (i) {
+ ok = readJoystick(i);
+ } else
+ ok = readKeyboard();
+ }
+ }
+ return ok;
+}
+
+u32 DirectInput::readDevice(int which)
+{
+ u32 res = 0;
+ int i = theApp.joypadDefault;
+ if(which >= 0 && which <= 3)
+ i = which;
+
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]))
+ res |= 1;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]))
+ res |= 2;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]))
+ res |= 4;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]))
+ res |= 8;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)]))
+ res |= 16;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]))
+ res |= 32;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_UP)]))
+ res |= 64;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]))
+ res |= 128;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]))
+ res |= 256;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]))
+ res |= 512;
+
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]))
+ res |= 4096;
+
+ if(theApp.autoFire) {
+ res &= (~theApp.autoFire);
+ if(theApp.autoFireToggle)
+ res |= theApp.autoFire;
+ theApp.autoFireToggle = !theApp.autoFireToggle;
+ }
+
+ // disallow L+R or U+D of being pressed at the same time
+ if((res & 48) == 48)
+ res &= ~16;
+ if((res & 192) == 192)
+ res &= ~128;
+
+ if(theApp.movieRecording) {
+ if(i == theApp.joypadDefault) {
+ if(res != theApp.movieLastJoypad) {
+ fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile);
+ fwrite(&res, 1, sizeof(res), theApp.movieFile);
+ theApp.movieLastJoypad = res;
+ }
+ }
+ }
+ if(theApp.moviePlaying) {
+ if(theApp.movieFrame == theApp.moviePlayFrame) {
+ theApp.movieLastJoypad = theApp.movieNextJoypad;
+ theApp.movieReadNext();
+ }
+ res = theApp.movieLastJoypad;
+ }
+ // we don't record speed up or screen capture buttons
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]) || theApp.speedupToggle)
+ res |= 1024;
+ if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]))
+ res |= 2048;
+
+ return res;
+}
+
+CString DirectInput::getKeyName(LONG_PTR key)
+{
+ LONG_PTR d = (key >> 8);
+ LONG_PTR k = key & 255;
+
+ DIDEVICEOBJECTINSTANCE di;
+
+ ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
+
+ di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
+
+ CString winBuffer = winResLoadString(IDS_ERROR);
+
+ if (d == 0) {
+ pDevices[0].device->GetObjectInfo( &di, (DWORD)key, DIPH_BYOFFSET );
+ winBuffer = di.tszName;
+ } else {
+ if (k < 16) {
+ if (k < 4) {
+ switch (k) {
+ case 0:
+ winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d);
+ break;
+ case 1:
+ winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d);
+ break;
+ case 2:
+ winBuffer.Format(winResLoadString(IDS_JOY_UP), d);
+ break;
+ case 3:
+ winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d);
+ break;
+ }
+ } else {
+ pDevices[d].device->GetObjectInfo(&di,
+ pDevices[d].axis[k>>1].offset,
+ DIPH_BYOFFSET);
+ if (k & 1)
+ winBuffer.Format("Joy %d %s +", d, di.tszName);
+ else
+ winBuffer.Format("Joy %d %s -", d, di.tszName);
+ }
+ } else if (k < 48) {
+ LONG_PTR hat = (k >> 2) & 3;
+ pDevices[d].device->GetObjectInfo(&di,
+ (DWORD)DIJOFS_POV(hat),
+ DIPH_BYOFFSET);
+ char *dir = "up";
+ LONG_PTR dd = k & 3;
+ if (dd == 1)
+ dir = "down";
+ else if (dd == 2)
+ dir = "right";
+ else if (dd == 3)
+ dir = "left";
+ winBuffer.Format("Joy %d %s %s", d, di.tszName, dir);
+ } else {
+ pDevices[d].device->GetObjectInfo(&di,
+ (DWORD)DIJOFS_BUTTON(k-128),
+ DIPH_BYOFFSET);
+ winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName);
+ }
+ }
+
+ return winBuffer;
+}
+
+void DirectInput::checkKeys()
+{
+ ::checkKeys();
+}
+
+void DirectInput::checkMotionKeys()
+{
+ if(checkKey(theApp.input->joypaddata[MOTION(KEY_LEFT)])) {
+ theApp.sensorX += 3;
+ if(theApp.sensorX > 2197)
+ theApp.sensorX = 2197;
+ if(theApp.sensorX < 2047)
+ theApp.sensorX = 2057;
+ } else if(checkKey(theApp.input->joypaddata[MOTION(KEY_RIGHT)])) {
+ theApp.sensorX -= 3;
+ if(theApp.sensorX < 1897)
+ theApp.sensorX = 1897;
+ if(theApp.sensorX > 2047)
+ theApp.sensorX = 2037;
+ } else if(theApp.sensorX > 2047) {
+ theApp.sensorX -= 2;
+ if(theApp.sensorX < 2047)
+ theApp.sensorX = 2047;
+ } else {
+ theApp.sensorX += 2;
+ if(theApp.sensorX > 2047)
+ theApp.sensorX = 2047;
+ }
+
+ if(checkKey(theApp.input->joypaddata[MOTION(KEY_UP)])) {
+ theApp.sensorY += 3;
+ if(theApp.sensorY > 2197)
+ theApp.sensorY = 2197;
+ if(theApp.sensorY < 2047)
+ theApp.sensorY = 2057;
+ } else if(checkKey(theApp.input->joypaddata[MOTION(KEY_DOWN)])) {
+ theApp.sensorY -= 3;
+ if(theApp.sensorY < 1897)
+ theApp.sensorY = 1897;
+ if(theApp.sensorY > 2047)
+ theApp.sensorY = 2037;
+ } else if(theApp.sensorY > 2047) {
+ theApp.sensorY -= 2;
+ if(theApp.sensorY < 2047)
+ theApp.sensorY = 2047;
+ } else {
+ theApp.sensorY += 2;
+ if(theApp.sensorY > 2047)
+ theApp.sensorY = 2047;
+ }
+}
+
+Input *newDirectInput()
+{
+ return new DirectInput;
+}
+
+
+void DirectInput::checkDevices()
+{
+ checkJoypads();
+ checkKeyboard();
+}
+
+void DirectInput::activate()
+{
+ for (int i = 0; i < numDevices; i++) {
+ if (pDevices != NULL && pDevices[i].device != NULL)
+ pDevices[i].device->Acquire();
+ }
+}
+
+void DirectInput::loadSettings()
+{
+ winReadKeys();
+}
+
+void DirectInput::saveSettings()
+{
+ winSaveKeys();
+}
diff --git a/src/win32/DirectSound.cpp b/src/win32/DirectSound.cpp
index 24f0fb15..4c897be1 100644
--- a/src/win32/DirectSound.cpp
+++ b/src/win32/DirectSound.cpp
@@ -1,380 +1,383 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004-2005 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include "VBA.h"
-#include "AVIWrite.h"
-#include "Sound.h"
-#include "WavWriter.h"
-
-#include "../System.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../Sound.h"
-
-#include
-#include //DirectSound
-
-extern bool soundBufferLow;
-
-class DirectSound : public ISound
-{
-private:
- HINSTANCE dsoundDLL;
- LPDIRECTSOUND pDirectSound;
- LPDIRECTSOUNDBUFFER dsbPrimary;
- LPDIRECTSOUNDBUFFER dsbSecondary;
- LPDIRECTSOUNDNOTIFY dsbNotify;
- HANDLE dsbEvent;
- WAVEFORMATEX wfx;
-
-public:
- DirectSound();
- virtual ~DirectSound();
-
- bool init();
- void pause();
- void reset();
- void resume();
- void write();
-};
-
-DirectSound::DirectSound()
-{
- dsoundDLL = NULL;
- pDirectSound = NULL;
- dsbPrimary = NULL;
- dsbSecondary = NULL;
- dsbNotify = NULL;
- dsbEvent = NULL;
-}
-
-DirectSound::~DirectSound()
-{
- if(theApp.aviRecorder != NULL) {
- delete theApp.aviRecorder;
- theApp.aviRecorder = NULL;
- theApp.aviFrameNumber = 0;
- }
-
- if(theApp.soundRecording) {
- if(theApp.soundRecorder != NULL) {
- delete theApp.soundRecorder;
- theApp.soundRecorder = NULL;
- }
- theApp.soundRecording = false;
- }
-
- if(dsbNotify != NULL) {
- dsbNotify->Release();
- dsbNotify = NULL;
- }
-
- if(dsbEvent != NULL) {
- CloseHandle(dsbEvent);
- dsbEvent = NULL;
- }
-
- if(pDirectSound != NULL) {
- if(dsbPrimary != NULL) {
- dsbPrimary->Release();
- dsbPrimary = NULL;
- }
-
- if(dsbSecondary != NULL) {
- dsbSecondary->Release();
- dsbSecondary = NULL;
- }
-
- pDirectSound->Release();
- pDirectSound = NULL;
- }
-
- if(dsoundDLL != NULL) {
- FreeLibrary(dsoundDLL);
- dsoundDLL = NULL;
- }
-}
-
-bool DirectSound::init()
-{
- HRESULT hr;
-
- dsoundDLL = LoadLibrary("dsound.dll");
- HRESULT (WINAPI *DSoundCreate)(LPCGUID,LPDIRECTSOUND *,IUnknown *);
- if(dsoundDLL != NULL) {
- DSoundCreate = (HRESULT (WINAPI *)(LPCGUID,LPDIRECTSOUND *,IUnknown *))
- GetProcAddress(dsoundDLL, "DirectSoundCreate8");
-
- if(DSoundCreate == NULL) {
- theApp.directXMessage("DirectSoundCreate8");
- return false;
- }
- } else {
- theApp.directXMessage("dsound.dll");
- return false;
- }
-
- if((hr = DSoundCreate(NULL,&pDirectSound,NULL) != DS_OK)) {
- // errorMessage(myLoadString(IDS_ERROR_SOUND_CREATE), hr);
- systemMessage(IDS_CANNOT_CREATE_DIRECTSOUND,
- "Cannot create DirectSound %08x", hr);
- pDirectSound = NULL;
- dsbSecondary = NULL;
- return false;
- }
-
- if((hr=pDirectSound->SetCooperativeLevel((HWND)*theApp.m_pMainWnd,
- DSSCL_EXCLUSIVE)) != DS_OK) {
- // errorMessage(myLoadString(IDS_ERROR_SOUND_LEVEL), hr);
- systemMessage(IDS_CANNOT_SETCOOPERATIVELEVEL,
- "Cannot SetCooperativeLevel %08x", hr);
- return false;
- }
-
- DSBUFFERDESC dsbdesc;
- ZeroMemory(&dsbdesc,sizeof(DSBUFFERDESC));
- dsbdesc.dwSize=sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
-
- if((hr=pDirectSound->CreateSoundBuffer(&dsbdesc,
- &dsbPrimary,
- NULL) != DS_OK)) {
- // errorMessage(myLoadString(IDS_ERROR_SOUND_BUFFER),hr);
- systemMessage(IDS_CANNOT_CREATESOUNDBUFFER,
- "Cannot CreateSoundBuffer %08x", hr);
- return false;
- }
-
- // Set primary buffer format
-
- memset(&wfx, 0, sizeof(WAVEFORMATEX));
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = 2;
- switch(soundQuality) {
- case 2:
- wfx.nSamplesPerSec = 22050;
- soundBufferLen = 736*2;
- soundBufferTotalLen = 7360*2;
- break;
- case 4:
- wfx.nSamplesPerSec = 11025;
- soundBufferLen = 368*2;
- soundBufferTotalLen = 3680*2;
- break;
- default:
- soundQuality = 1;
- wfx.nSamplesPerSec = 44100;
- soundBufferLen = 1470*2;
- soundBufferTotalLen = 14700*2;
- }
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = (wfx.wBitsPerSample / 8) * wfx.nChannels;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
-
- if((hr = dsbPrimary->SetFormat(&wfx)) != DS_OK) {
- // errorMessage(myLoadString(IDS_ERROR_SOUND_PRIMARY),hr);
- systemMessage(IDS_CANNOT_SETFORMAT_PRIMARY,
- "Cannot SetFormat for primary %08x", hr);
- return false;
- }
-
- ZeroMemory(&dsbdesc,sizeof(DSBUFFERDESC));
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLPOSITIONNOTIFY;
- dsbdesc.dwBufferBytes = soundBufferTotalLen;
- dsbdesc.lpwfxFormat = &wfx;
-
- if((hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL))
- != DS_OK) {
- dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
- if((hr = pDirectSound->CreateSoundBuffer(&dsbdesc, &dsbSecondary, NULL))
- != DS_OK) {
- systemMessage(IDS_CANNOT_CREATESOUNDBUFFER_SEC,
- "Cannot CreateSoundBuffer secondary %08x", hr);
- return false;
- }
- }
-
- dsbSecondary->SetCurrentPosition(0);
-
- if(!theApp.useOldSync) {
- hr = dsbSecondary->QueryInterface(IID_IDirectSoundNotify,
- (void **)&dsbNotify);
- if(!FAILED(hr)) {
- dsbEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-
- DSBPOSITIONNOTIFY notify[10];
-
- for(int i = 0; i < 10; i++) {
- notify[i].dwOffset = i*soundBufferLen;
- notify[i].hEventNotify = dsbEvent;
- }
- if(FAILED(dsbNotify->SetNotificationPositions(10, notify))) {
- dsbNotify->Release();
- dsbNotify = NULL;
- CloseHandle(dsbEvent);
- dsbEvent = NULL;
- }
- }
- }
-
- hr = dsbPrimary->Play(0,0,DSBPLAY_LOOPING);
-
- if(hr != DS_OK) {
- // errorMessage(myLoadString(IDS_ERROR_SOUND_PLAYPRIM), hr);
- systemMessage(IDS_CANNOT_PLAY_PRIMARY, "Cannot Play primary %08x", hr);
- return false;
- }
-
- setsystemSoundOn(true);
- return true;
-}
-
-void DirectSound::pause()
-{
- if(dsbSecondary != NULL) {
- DWORD status = 0;
- dsbSecondary->GetStatus(&status);
-
- if(status & DSBSTATUS_PLAYING) {
- dsbSecondary->Stop();
- }
- }
-}
-
-void DirectSound::reset()
-{
- if(dsbSecondary) {
- dsbSecondary->Stop();
- dsbSecondary->SetCurrentPosition(0);
- }
-}
-
-void DirectSound::resume()
-{
- if(dsbSecondary != NULL) {
- dsbSecondary->Play(0,0,DSBPLAY_LOOPING);
- }
-}
-
-void DirectSound::write()
-{
- int len = soundBufferLen;
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
-
- if(!pDirectSound)
- return;
-
- if(theApp.soundRecording) {
- if(dsbSecondary) {
- if(theApp.soundRecorder == NULL) {
- theApp.soundRecorder = new WavWriter;
- WAVEFORMATEX format;
- dsbSecondary->GetFormat(&format, sizeof(format), NULL);
- if(theApp.soundRecorder->Open(theApp.soundRecordName))
- theApp.soundRecorder->SetFormat(&format);
- }
- }
-
- if(theApp.soundRecorder) {
- theApp.soundRecorder->AddSound((u8 *)soundFinalWave, len);
- }
- }
-
- if(theApp.aviRecording) {
- if(theApp.aviRecorder) {
- if(dsbSecondary) {
- if(!theApp.aviRecorder->IsSoundAdded()) {
- WAVEFORMATEX format;
- dsbSecondary->GetFormat(&format, sizeof(format), NULL);
- theApp.aviRecorder->SetSoundFormat(&format);
- }
- }
-
- theApp.aviRecorder->AddSound((const char *)soundFinalWave, len);
- }
- }
-
- HRESULT hr;
-
- if(!speedup && synchronize && !theApp.throttle) {
- DWORD status=0;
- hr = dsbSecondary->GetStatus(&status);
- if(status && DSBSTATUS_PLAYING) {
- if(!soundPaused) {
- DWORD play;
- while(true) {
- dsbSecondary->GetCurrentPosition(&play, NULL);
- int BufferLeft = ((soundNextPosition <= play) ?
- play - soundNextPosition :
- soundBufferTotalLen - soundNextPosition + play);
-
- if(BufferLeft > soundBufferLen)
- {
- if (BufferLeft > soundBufferTotalLen - (soundBufferLen * 3))
- soundBufferLow = true;
- break;
- }
- soundBufferLow = false;
-
- if(dsbEvent) {
- WaitForSingleObject(dsbEvent, 50);
- }
- }
- }
- } else {
- setsoundPaused(true);
- }
- }
- // Obtain memory address of write block. This will be in two parts
- // if the block wraps around.
- hr = dsbSecondary->Lock(soundNextPosition, soundBufferLen, &lpvPtr1,
- &dwBytes1, &lpvPtr2, &dwBytes2,
- 0);
-
- // If DSERR_BUFFERLOST is returned, restore and retry lock.
- if (DSERR_BUFFERLOST == hr) {
- dsbSecondary->Restore();
- hr = dsbSecondary->Lock(soundNextPosition, soundBufferLen,&lpvPtr1,
- &dwBytes1, &lpvPtr2, &dwBytes2,
- 0);
- }
-
- soundNextPosition += soundBufferLen;
- soundNextPosition = soundNextPosition % soundBufferTotalLen;
-
- if SUCCEEDED(hr) {
- // Write to pointers.
- CopyMemory(lpvPtr1, soundFinalWave, dwBytes1);
- if (NULL != lpvPtr2) {
- CopyMemory(lpvPtr2, soundFinalWave+dwBytes1, dwBytes2);
- }
- // Release the data back to DirectSound.
- hr = dsbSecondary->Unlock(lpvPtr1, dwBytes1, lpvPtr2,
- dwBytes2);
- }
-}
-
-ISound *newDirectSound()
-{
- return new DirectSound();
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2004-2006 VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// MFC
+#include "stdafx.h"
+
+// Tools
+#include "AVIWrite.h"
+#include "WavWriter.h"
+
+// Internals
+#include "../System.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../Sound.h"
+
+// DirectSound8
+#include
+#pragma comment( lib, "Dsound" )
+#pragma comment( lib, "Dxguid" )
+
+extern bool soundBufferLow;
+
+class DirectSound : public ISound
+{
+private:
+ LPDIRECTSOUND8 pDirectSound; // DirectSound interface
+ LPDIRECTSOUNDBUFFER dsbPrimary; // Primary DirectSound buffer
+ LPDIRECTSOUNDBUFFER dsbSecondary; // Secondary DirectSound buffer
+ LPDIRECTSOUNDNOTIFY8 dsbNotify;
+ HANDLE dsbEvent;
+ WAVEFORMATEX wfx; // Primary buffer wave format
+
+public:
+ DirectSound();
+ virtual ~DirectSound();
+
+ bool init(); // initialize the primary and secondary sound buffer
+ void pause(); // pause the secondary sound buffer
+ void reset(); // stop and reset the secondary sound buffer
+ void resume(); // resume the secondary sound buffer
+ void write(); // write the emulated sound to the secondary sound buffer
+};
+
+
+DirectSound::DirectSound()
+{
+ CoInitialize( NULL );
+
+ pDirectSound = NULL;
+ dsbPrimary = NULL;
+ dsbSecondary = NULL;
+ dsbNotify = NULL;
+ dsbEvent = NULL;
+}
+
+
+DirectSound::~DirectSound()
+{
+ if(theApp.aviRecorder) {
+ delete theApp.aviRecorder;
+ theApp.aviRecorder = NULL;
+ theApp.aviFrameNumber = 0;
+ }
+
+ if(theApp.soundRecording) {
+ if(theApp.soundRecorder) {
+ delete theApp.soundRecorder;
+ theApp.soundRecorder = NULL;
+ }
+ theApp.soundRecording = false;
+ }
+
+ if(dsbNotify) {
+ dsbNotify->Release();
+ dsbNotify = NULL;
+ }
+
+ if(dsbEvent) {
+ CloseHandle(dsbEvent);
+ dsbEvent = NULL;
+ }
+
+ if(pDirectSound) {
+ if(dsbPrimary) {
+ dsbPrimary->Release();
+ dsbPrimary = NULL;
+ }
+
+ if(dsbSecondary) {
+ dsbSecondary->Release();
+ dsbSecondary = NULL;
+ }
+
+ pDirectSound->Release();
+ pDirectSound = NULL;
+ }
+
+ CoUninitialize();
+}
+
+
+bool DirectSound::init()
+{
+ HRESULT hr;
+ DWORD freq;
+ DSBUFFERDESC dsbdesc;
+ int i;
+
+
+ // Initialize DirectSound
+ if( FAILED( hr = DirectSoundCreate8( &DSDEVID_DefaultPlayback, &pDirectSound, NULL ) ) ) {
+ systemMessage( IDS_CANNOT_CREATE_DIRECTSOUND, _T("Cannot create DirectSound %08x"), hr );
+ pDirectSound = NULL;
+ return false;
+ }
+
+
+ if( FAILED( hr = pDirectSound->SetCooperativeLevel( theApp.m_pMainWnd->GetSafeHwnd(), DSSCL_EXCLUSIVE ) ) ) {
+ systemMessage( IDS_CANNOT_SETCOOPERATIVELEVEL, _T("Cannot SetCooperativeLevel %08x"), hr );
+ return false;
+ }
+
+
+ // Create primary sound buffer
+ ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ if( theApp.dsoundDisableHardwareAcceleration ) {
+ dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
+ }
+
+ if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbPrimary, NULL ) ) ) {
+ systemMessage(IDS_CANNOT_CREATESOUNDBUFFER, _T("Cannot CreateSoundBuffer %08x"), hr);
+ return false;
+ }
+
+ switch(soundQuality)
+ {
+ case 4:
+ freq = 11025;
+ break;
+ case 2:
+ freq = 22050;
+ break;
+ default:
+ soundQuality = 1;
+ case 1:
+ freq = 44100;
+ break;
+ }
+ soundBufferLen = freq*2/30;
+ soundBufferTotalLen = soundBufferLen * 10;
+
+ ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = 2;
+ wfx.nSamplesPerSec = freq;
+ wfx.wBitsPerSample = 16;
+ wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+
+ if( FAILED( hr = dsbPrimary->SetFormat( &wfx ) ) ) {
+ systemMessage( IDS_CANNOT_SETFORMAT_PRIMARY, _T("CreateSoundBuffer(primary) failed %08x"), hr );
+ return false;
+ }
+
+
+ // Create secondary sound buffer
+ ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS;
+ if( theApp.dsoundDisableHardwareAcceleration ) {
+ dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
+ }
+ dsbdesc.dwBufferBytes = soundBufferTotalLen;
+ dsbdesc.lpwfxFormat = &wfx;
+
+ if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbSecondary, NULL ) ) ) {
+ systemMessage( IDS_CANNOT_CREATESOUNDBUFFER, _T("CreateSoundBuffer(secondary) failed %08x"), hr );
+ return false;
+ }
+
+ if( FAILED( hr = dsbSecondary->SetCurrentPosition( 0 ) ) ) {
+ systemMessage( 0, _T("dsbSecondary->SetCurrentPosition failed %08x"), hr );
+ return false;
+ }
+
+
+ if( !theApp.useOldSync ) {
+ if( FAILED( hr = dsbSecondary->QueryInterface( IID_IDirectSoundNotify8, (LPVOID*)&dsbNotify ) ) ) {
+ dsbEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ DSBPOSITIONNOTIFY notify[10];
+ for( i = 0; i < 10; i++ ) {
+ notify[i].dwOffset = i * soundBufferLen;
+ notify[i].hEventNotify = dsbEvent;
+ }
+
+ if( FAILED( dsbNotify->SetNotificationPositions( 10, notify ) ) ) {
+ dsbNotify->Release();
+ dsbNotify = NULL;
+ CloseHandle(dsbEvent);
+ dsbEvent = NULL;
+ }
+ }
+ }
+
+
+ // Play primary buffer
+ if( FAILED( hr = dsbPrimary->Play( 0, 0, DSBPLAY_LOOPING ) ) ) {
+ systemMessage( IDS_CANNOT_PLAY_PRIMARY, _T("Cannot Play primary %08x"), hr );
+ return false;
+ }
+
+ systemSoundOn = true;
+
+ return true;
+}
+
+
+void DirectSound::pause()
+{
+ if( dsbSecondary == NULL ) return;
+
+ DWORD status;
+
+ dsbSecondary->GetStatus( &status );
+
+ if( status & DSBSTATUS_PLAYING ) dsbSecondary->Stop();
+}
+
+
+void DirectSound::reset()
+{
+ if( dsbSecondary == NULL ) return;
+
+ dsbSecondary->Stop();
+
+ dsbSecondary->SetCurrentPosition( 0 );
+}
+
+
+void DirectSound::resume()
+{
+ if( dsbSecondary == NULL ) return;
+
+ dsbSecondary->Play( 0, 0, DSBPLAY_LOOPING );
+}
+
+
+void DirectSound::write()
+{
+ if(!pDirectSound) return;
+
+
+ HRESULT hr;
+ DWORD status = 0;
+ DWORD play = 0;
+ WAVEFORMATEX format;
+ LPVOID lpvPtr1;
+ DWORD dwBytes1 = 0;
+ LPVOID lpvPtr2;
+ DWORD dwBytes2 = 0;
+
+
+ if( theApp.soundRecording ) {
+ if( dsbSecondary ) {
+ if( theApp.soundRecorder ) {
+ theApp.soundRecorder->AddSound( (u8 *)soundFinalWave, soundBufferLen );
+ } else {
+ theApp.soundRecorder = new WavWriter;
+ dsbSecondary->GetFormat( &format, sizeof(format), NULL );
+ if( theApp.soundRecorder->Open( theApp.soundRecordName ) ) {
+ theApp.soundRecorder->SetFormat( &format );
+ }
+ }
+ }
+ }
+
+
+ if( theApp.aviRecording ) {
+ if( theApp.aviRecorder ) {
+ if( dsbSecondary ) {
+ if( !theApp.aviRecorder->IsSoundAdded() ) {
+ dsbSecondary->GetFormat( &format, sizeof(format), NULL );
+ theApp.aviRecorder->SetSoundFormat( &format );
+ }
+ }
+ theApp.aviRecorder->AddSound( (const char *)soundFinalWave, soundBufferLen );
+ }
+ }
+
+
+ if( !speedup && synchronize && !theApp.throttle ) {
+ hr = dsbSecondary->GetStatus(&status);
+ if( status & DSBSTATUS_PLAYING ) {
+ if( !soundPaused ) {
+ while( true ) {
+ dsbSecondary->GetCurrentPosition(&play, NULL);
+ int BufferLeft = ((soundNextPosition <= play) ?
+ play - soundNextPosition :
+ soundBufferTotalLen - soundNextPosition + play);
+
+ if(BufferLeft > soundBufferLen)
+ {
+ if (BufferLeft > soundBufferTotalLen - (soundBufferLen * 3))
+ soundBufferLow = true;
+ break;
+ }
+ soundBufferLow = false;
+
+ if(dsbEvent) {
+ WaitForSingleObject(dsbEvent, 50);
+ }
+ }
+ }
+ } else {
+ setsoundPaused(true);
+ }
+ }
+
+
+ // Obtain memory address of write block.
+ // This will be in two parts if the block wraps around.
+ if( DSERR_BUFFERLOST == ( hr = dsbSecondary->Lock(
+ soundNextPosition,
+ soundBufferLen,
+ &lpvPtr1,
+ &dwBytes1,
+ &lpvPtr2,
+ &dwBytes2,
+ 0 ) ) ) {
+ // If DSERR_BUFFERLOST is returned, restore and retry lock.
+ dsbSecondary->Restore();
+ hr = dsbSecondary->Lock(
+ soundNextPosition,
+ soundBufferLen,
+ &lpvPtr1,
+ &dwBytes1,
+ &lpvPtr2,
+ &dwBytes2,
+ 0 );
+ }
+
+ soundNextPosition += soundBufferLen;
+ soundNextPosition = soundNextPosition % soundBufferTotalLen;
+
+ if( SUCCEEDED( hr ) ) {
+ // Write to pointers.
+ CopyMemory( lpvPtr1, soundFinalWave, dwBytes1 );
+ if ( lpvPtr2 ) {
+ CopyMemory( lpvPtr2, soundFinalWave + dwBytes1, dwBytes2 );
+ }
+
+ // Release the data back to DirectSound.
+ hr = dsbSecondary->Unlock( lpvPtr1, dwBytes1, lpvPtr2, dwBytes2 );
+ } else {
+ systemMessage( 0, _T("dsbSecondary->Lock() failed: %08x"), hr );
+ return;
+ }
+}
+
+
+ISound *newDirectSound()
+{
+ return new DirectSound();
+}
diff --git a/src/win32/Directories.cpp b/src/win32/Directories.cpp
index 4a1bec69..d4585228 100644
--- a/src/win32/Directories.cpp
+++ b/src/win32/Directories.cpp
@@ -26,6 +26,7 @@
#include "WinResUtil.h"
#include
+#include
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -54,27 +55,21 @@ static int CALLBACK browseCallbackProc(HWND hWnd, UINT msg,
Directories::Directories(CWnd* pParent /*=NULL*/)
: CDialog(Directories::IDD, pParent)
{
- //{{AFX_DATA_INIT(Directories)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
}
void Directories::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(Directories)
DDX_Control(pDX, IDC_SAVE_PATH, m_savePath);
DDX_Control(pDX, IDC_ROM_PATH, m_romPath);
DDX_Control(pDX, IDC_GBROM_PATH, m_gbromPath);
DDX_Control(pDX, IDC_CAPTURE_PATH, m_capturePath);
DDX_Control(pDX, IDC_BATTERY_PATH, m_batteryPath);
- //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(Directories, CDialog)
- //{{AFX_MSG_MAP(Directories)
ON_BN_CLICKED(IDC_BATTERY_DIR, OnBatteryDir)
ON_BN_CLICKED(IDC_BATTERY_DIR_RESET, OnBatteryDirReset)
ON_BN_CLICKED(IDC_CAPTURE_DIR, OnCaptureDir)
@@ -85,8 +80,7 @@ BEGIN_MESSAGE_MAP(Directories, CDialog)
ON_BN_CLICKED(IDC_ROM_DIR_RESET, OnRomDirReset)
ON_BN_CLICKED(IDC_SAVE_DIR, OnSaveDir)
ON_BN_CLICKED(IDC_SAVE_DIR_RESET, OnSaveDirReset)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
+END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Directories message handlers
@@ -206,23 +200,76 @@ void Directories::OnCancel()
void Directories::OnOK()
{
- CString buffer;
- m_romPath.GetWindowText(buffer);
- if(!buffer.IsEmpty())
- regSetStringValue("romdir", buffer);
- m_gbromPath.GetWindowText(buffer);
- if(!buffer.IsEmpty())
- regSetStringValue("gbromdir", buffer);
- m_batteryPath.GetWindowText(buffer);
- if(!buffer.IsEmpty())
- regSetStringValue("batteryDir", buffer);
- m_savePath.GetWindowText(buffer);
- if(!buffer.IsEmpty())
- regSetStringValue("saveDir", buffer);
- m_capturePath.GetWindowText(buffer);
- if(!buffer.IsEmpty())
- regSetStringValue("captureDir", buffer);
- EndDialog(TRUE);
+ char baseDir[MAX_PATH+1];
+ char temp[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+
+
+ CString buffer;
+
+ m_romPath.GetWindowText(buffer);
+ if( !buffer.IsEmpty() )
+ regSetStringValue( "romdir", buffer );
+ if( buffer[0] == '.' ) {
+ strcpy( temp, baseDir );
+ strcat( temp, "\\" );
+ strcat( temp, buffer );
+ buffer = temp;
+ }
+ if( !directoryDoesExist( buffer ) )
+ SHCreateDirectoryEx( NULL, buffer, NULL );
+
+ m_gbromPath.GetWindowText(buffer);
+ if( !buffer.IsEmpty() )
+ regSetStringValue( "gbromdir", buffer );
+ if( buffer[0] == '.' ) {
+ strcpy( temp, baseDir );
+ strcat( temp, "\\" );
+ strcat( temp, buffer );
+ buffer = temp;
+ }
+ if( !directoryDoesExist( buffer ) )
+ SHCreateDirectoryEx( NULL, buffer, NULL );
+
+ m_batteryPath.GetWindowText(buffer);
+ if( !buffer.IsEmpty() )
+ regSetStringValue( "batteryDir", buffer );
+ if( buffer[0] == '.' ) {
+ strcpy( temp, baseDir );
+ strcat( temp, "\\" );
+ strcat( temp, buffer );
+ buffer = temp;
+ }
+ if( !directoryDoesExist( buffer ) )
+ SHCreateDirectoryEx( NULL, buffer, NULL );
+
+ m_savePath.GetWindowText(buffer);
+ if( !buffer.IsEmpty() )
+ regSetStringValue( "saveDir", buffer );
+ if( buffer[0] == '.' ) {
+ strcpy( temp, baseDir );
+ strcat( temp, "\\" );
+ strcat( temp, buffer );
+ buffer = temp;
+ }
+ if( !directoryDoesExist( buffer ) )
+ SHCreateDirectoryEx( NULL, buffer, NULL );
+
+ m_capturePath.GetWindowText(buffer);
+ if( !buffer.IsEmpty() )
+ regSetStringValue( "captureDir", buffer );
+ if( buffer[0] == '.' ) {
+ strcpy( temp, baseDir );
+ strcat( temp, "\\" );
+ strcat( temp, buffer );
+ buffer = temp;
+ }
+ if( !directoryDoesExist( buffer ) )
+ SHCreateDirectoryEx( NULL, buffer, NULL );
+
+ EndDialog(TRUE);
}
CString Directories::browseForDir(CString title)
diff --git a/src/win32/Directories.h b/src/win32/Directories.h
index 50087355..8479694e 100644
--- a/src/win32/Directories.h
+++ b/src/win32/Directories.h
@@ -75,7 +75,24 @@ class Directories : public CDialog
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
- };
+private:
+
+ bool directoryDoesExist(const char *directory)
+ { // returns true if the directory does exist
+ HANDLE hDir;
+ hDir = CreateFile(
+ directory,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL );
+ bool retval = (hDir == INVALID_HANDLE_VALUE) ? false : true;
+ CloseHandle( hDir );
+ return retval;
+ }
+};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
diff --git a/src/win32/Disassemble.cpp b/src/win32/Disassemble.cpp
index fab2d533..3c4eaaa0 100644
--- a/src/win32/Disassemble.cpp
+++ b/src/win32/Disassemble.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -118,6 +118,7 @@ void Disassemble::OnAutomatic()
void Disassemble::OnArm()
{
mode = 1;
+ address&=0xfffffffC;
refresh();
}
@@ -133,21 +134,30 @@ void Disassemble::OnGo()
CString buffer;
m_address.GetWindowText(buffer);
sscanf(buffer, "%x", &address);
+ if (mode==1)
+ address&=0xfffffffc;
+ else if (mode==2)
+ address&=0xfffffffe;
refresh();
}
void Disassemble::OnGopc()
{
+ if(rom != NULL)
+ {
if(armState)
address = armNextPC - 16;
else
address = armNextPC - 8;
refresh();
+ }
}
void Disassemble::OnNext()
{
+ if(rom != NULL)
+ {
CPULoop(1);
if(armState) {
u32 total = address+count*4;
@@ -163,6 +173,7 @@ void Disassemble::OnNext()
}
}
refresh();
+ }
}
void Disassemble::OnRefresh()
@@ -173,6 +184,7 @@ void Disassemble::OnRefresh()
void Disassemble::OnThumb()
{
mode = 2;
+ address&=0xfffffffe;
refresh();
}
diff --git a/src/win32/Display.h b/src/win32/Display.h
index b63005e9..a44885ab 100644
--- a/src/win32/Display.h
+++ b/src/win32/Display.h
@@ -17,6 +17,8 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#pragma once
+
enum DISPLAY_TYPE {
GDI = 0,
DIRECT_DRAW = 1,
@@ -32,13 +34,15 @@ class IDisplay {
virtual bool initialize() = 0;
virtual void cleanup() = 0;
virtual void render() = 0;
- virtual void checkFullScreen() { };
- virtual void renderMenu() { };
+ virtual void checkFullScreen() {};
+ virtual void renderMenu() {};
virtual void clear() = 0;
virtual bool changeRenderSize(int w, int h) { return true; };
virtual void resize(int w, int h) {};
- virtual void setOption(const char *option, int value) = 0;
+ virtual void setOption(const char *option, int value) {};
virtual DISPLAY_TYPE getType() = 0;
+ virtual bool isSkinSupported() { return false; }
virtual int selectFullScreenMode(GUID **) = 0;
- virtual int selectFullScreenMode2() { return 0; };
};
+
+void copyImage( void *source, void *destination, unsigned int width, unsigned int height, unsigned int destinationPitch, unsigned int colorDepth );
diff --git a/src/win32/FileDlg.cpp b/src/win32/FileDlg.cpp
index 9cee23e1..14e30c9a 100644
--- a/src/win32/FileDlg.cpp
+++ b/src/win32/FileDlg.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
// FileDlg.cpp: implementation of the FileDlg class.
//
-//////////////////////////////////////////////////////////////////////
+
#include "stdafx.h"
#include
#include
@@ -26,7 +26,7 @@
#include "VBA.h"
#include "FileDlg.h"
#include "../System.h"
-#include "..\..\res\resource.h"
+#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -159,20 +159,23 @@ void FileDlg::OnTypeChange(HWND hwnd)
ASSERT(typeControl != NULL);
- int sel = ::SendMessage(typeControl, CB_GETCURSEL, 0, 0);
+ LRESULT sel = ::SendMessage(typeControl, CB_GETCURSEL, 0, 0);
ASSERT(sel != -1);
LPCTSTR typeName = extensions[sel];
if(filename.GetLength() == 0) {
- filename.Format("*%s", typeName);
+ if(strlen(typeName) != 0)
+ filename.Format("*%s", typeName);
} else {
- int index = filename.Find('.');
- if (index == -1) {
- filename = filename + typeName;
- } else {
- filename = filename.Left(index) + typeName;
+ if(strlen(typeName) != 0) {
+ int index = filename.Find('.');
+ if (index == -1) {
+ filename = filename + typeName;
+ } else {
+ filename = filename.Left(index) + typeName;
+ }
}
}
SetWindowText(fileNameControl, filename);
diff --git a/src/win32/GBACheats.cpp b/src/win32/GBACheats.cpp
index f36b3101..d7ee5866 100644
--- a/src/win32/GBACheats.cpp
+++ b/src/win32/GBACheats.cpp
@@ -683,7 +683,7 @@ bool AddCheat::addCheat()
code.Format("%08x:%08x", address, value);
break;
}
-
+
cheatsAdd(code, buffer, address ,address, value,-1, sizeType);
return true;
}
@@ -765,16 +765,16 @@ void GBACheatList::OnEnable()
if(mark != -1) {
LVITEM item;
for(int i = 0; i < count; i++) {
- memset(&item,0, sizeof(item));
+ memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM|LVIF_STATE;
item.stateMask = LVIS_SELECTED;
item.iItem = i;
if(m_list.GetItem(&item)) {
if(item.state & LVIS_SELECTED) {
if(cheatsList[item.lParam].enabled)
- cheatsDisable(item.lParam);
+ cheatsDisable((int)(item.lParam & 0xFFFFFFFF));
else
- cheatsEnable(item.lParam);
+ cheatsEnable((int)(item.lParam & 0xFFFFFFFF));
}
}
}
@@ -796,7 +796,7 @@ void GBACheatList::OnRemove()
item.stateMask = LVIS_SELECTED;
if(m_list.GetItem(&item)) {
if(item.state & LVIS_SELECTED) {
- cheatsDelete(item.lParam, restoreValues);
+ cheatsDelete((int)(item.lParam & 0xFFFFFFFF), restoreValues);
}
}
}
@@ -838,9 +838,9 @@ void GBACheatList::OnItemchangedCheatList(NMHDR* pNMHDR, LRESULT* pResult)
if(((l->uOldState & LVIS_STATEIMAGEMASK)>>12) !=
(((l->uNewState & LVIS_STATEIMAGEMASK)>>12))) {
if(m_list.GetCheck(l->iItem))
- cheatsEnable(l->lParam);
+ cheatsEnable((int)(l->lParam & 0xFFFFFFFF));
else
- cheatsDisable(l->lParam);
+ cheatsDisable((int)(l->lParam & 0xFFFFFFFF));
refresh();
}
}
diff --git a/src/win32/GBACheats.h b/src/win32/GBACheats.h
index 79a6f9ae..3066d871 100644
--- a/src/win32/GBACheats.h
+++ b/src/win32/GBACheats.h
@@ -20,7 +20,7 @@
#if !defined(AFX_GBACHEATS_H__FC31D47D_52C8_42B2_95C7_7C3FD09316A4__INCLUDED_)
#define AFX_GBACHEATS_H__FC31D47D_52C8_42B2_95C7_7C3FD09316A4__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/GBCheatsDlg.cpp b/src/win32/GBCheatsDlg.cpp
index dc8c164f..6362eeaa 100644
--- a/src/win32/GBCheatsDlg.cpp
+++ b/src/win32/GBCheatsDlg.cpp
@@ -637,7 +637,7 @@ bool AddGBCheat::addCheat()
m_desc.GetWindowText(buffer);
- int bank = (address >> 16);
+ LONG_PTR bank = (address >> 16);
address &= 0xFFFF;
if(address >= 0xd000)
@@ -689,9 +689,7 @@ BOOL AddGBCheat::OnInitDialog()
buffer.Format("%02x:%08x", (address>>16), address&0xFFFF);
m_address.SetWindowText(buffer);
m_address.EnableWindow(FALSE);
- ::SetWindowLong(m_address,
- GWL_USERDATA,
- address);
+ ::SetWindowLongPtr( m_address.GetSafeHwnd(), GWLP_USERDATA, address);
numberType = regQueryDwordValue("gbCheatsNumberType", 2);
if(numberType < 0 || numberType > 2)
@@ -826,9 +824,9 @@ void GBCheatList::OnEnable()
item.iItem = mark;
if(m_list.GetItem(&item)) {
if(gbCheatList[item.lParam].enabled)
- gbCheatDisable(item.lParam);
+ gbCheatDisable((int)item.lParam);
else
- gbCheatEnable(item.lParam);
+ gbCheatEnable((int)item.lParam);
refresh();
}
}
@@ -844,7 +842,7 @@ void GBCheatList::OnRemove()
item.mask = LVIF_PARAM;
item.iItem = mark;
if(m_list.GetItem(&item)) {
- gbCheatRemove(item.lParam);
+ gbCheatRemove((int)item.lParam);
refresh();
}
}
@@ -872,9 +870,9 @@ void GBCheatList::OnItemchangedCheatList(NMHDR* pNMHDR, LRESULT* pResult)
if(((l->uOldState & LVIS_STATEIMAGEMASK)>>12) !=
(((l->uNewState & LVIS_STATEIMAGEMASK)>>12))) {
if(m_list.GetCheck(l->iItem))
- gbCheatEnable(l->lParam);
+ gbCheatEnable((int)l->lParam);
else
- gbCheatDisable(l->lParam);
+ gbCheatDisable((int)l->lParam);
refresh();
}
}
diff --git a/src/win32/GBCheatsDlg.h b/src/win32/GBCheatsDlg.h
index 0f3f1d43..68b9f71e 100644
--- a/src/win32/GBCheatsDlg.h
+++ b/src/win32/GBCheatsDlg.h
@@ -121,7 +121,7 @@ class AddGBCheat : public CDialog
// Implementation
protected:
- u32 address;
+ LONG_PTR address;
// Generated message map functions
//{{AFX_MSG(AddGBCheat)
diff --git a/src/win32/GBColorDlg.cpp b/src/win32/GBColorDlg.cpp
index a2527aa6..6096e9d8 100644
--- a/src/win32/GBColorDlg.cpp
+++ b/src/win32/GBColorDlg.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -32,28 +32,31 @@ extern u16 gbPalette[128];
static u16 defaultPalettes[][24] = {
{
- 0x7FFF, 0x56B5, 0x318C, 0x0000, 0x7FFF, 0x56B5, 0x318C, 0x0000,
+ 0x7FFF, 0x56B5, 0x318C, 0x0000, 0x7FFF, 0x56B5, 0x318C, 0x0000,
},
{
- 0x6200, 0x7E10, 0x7C10, 0x5000, 0x6200, 0x7E10, 0x7C10, 0x5000,
+ 0x6200, 0x7E10, 0x7C10, 0x5000, 0x6200, 0x7E10, 0x7C10, 0x5000,
},
{
- 0x4008, 0x4000, 0x2000, 0x2008, 0x4008, 0x4000, 0x2000, 0x2008,
+ 0x4008, 0x4000, 0x2000, 0x2008, 0x4008, 0x4000, 0x2000, 0x2008,
},
{
- 0x43F0, 0x03E0, 0x4200, 0x2200, 0x43F0, 0x03E0, 0x4200, 0x2200,
+ 0x43F0, 0x03E0, 0x4200, 0x2200, 0x43F0, 0x03E0, 0x4200, 0x2200,
},
{
- 0x43FF, 0x03FF, 0x221F, 0x021F, 0x43FF, 0x03FF, 0x221F, 0x021F,
+ 0x43FF, 0x03FF, 0x221F, 0x021F, 0x43FF, 0x03FF, 0x221F, 0x021F,
},
{
- 0x621F, 0x7E1F, 0x7C1F, 0x2010, 0x621F, 0x7E1F, 0x7C1F, 0x2010,
+ 0x621F, 0x7E1F, 0x7C1F, 0x2010, 0x621F, 0x7E1F, 0x7C1F, 0x2010,
},
{
- 0x621F, 0x401F, 0x001F, 0x2010, 0x621F, 0x401F, 0x001F, 0x2010,
+ 0x621F, 0x401F, 0x001F, 0x2010, 0x621F, 0x401F, 0x001F, 0x2010,
},
{
- 0x421F, 0x03E0, 0x7C00, 0x401F, 0x021F, 0x2200, 0x4008, 0x2010,
+ 0x1B8E, 0x02C0, 0x0DA0, 0x1140, 0x1B8E, 0x02C0, 0x0DA0, 0x1140,
+ },
+ {
+ 0x7BDE, /*0x23F0*/ 0x5778, /*0x5DC0*/ 0x5640, 0x0000, 0x7BDE, /*0x3678*/ 0x529C, /*0x0980*/ 0x2990, 0x0000,
}
};
@@ -70,20 +73,15 @@ static char THIS_FILE[] = __FILE__;
GBColorDlg::GBColorDlg(CWnd* pParent /*=NULL*/)
: CDialog(GBColorDlg::IDD, pParent)
{
- //{{AFX_DATA_INIT(GBColorDlg)
- which = -1;
- //}}AFX_DATA_INIT
which = gbPaletteOption;
}
void GBColorDlg::DoDataExchange(CDataExchange* pDX)
{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(GBColorDlg)
+ CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PREDEFINED, m_predefined);
- DDX_Radio(pDX, IDC_DEFAULT, which);
- //}}AFX_DATA_MAP
+ DDX_Radio(pDX, IDC_DEFAULT, which);
}
@@ -95,8 +93,8 @@ BEGIN_MESSAGE_MAP(GBColorDlg, CDialog)
ON_BN_CLICKED(IDC_USER2, OnUser2)
ON_BN_CLICKED(ID_OK, OnOk)
ON_BN_CLICKED(ID_CANCEL, OnCancel)
- ON_CBN_SELCHANGE(IDC_PREDEFINED, OnSelchangePredefined)
- //}}AFX_MSG_MAP
+ ON_CBN_SELCHANGE(IDC_PREDEFINED, OnSelchangePredefined)
+ //}}AFX_MSG_MAP
ON_CONTROL_RANGE(BN_CLICKED, IDC_COLOR_BG0, IDC_COLOR_OB3, OnColorClicked)
END_MESSAGE_MAP()
@@ -167,10 +165,12 @@ BOOL GBColorDlg::OnInitDialog()
"Green Forest",
"Hot Desert",
"Pink Dreams",
- "Weird Colors"
+ "Weird Colors",
+ "Real GB Colors",
+ "Real 'GB on GBASP' Colors"
};
- for(int j = 0; j < 7; j++) {
+ for(int j = 0; j < 9; j++) {
int index = m_predefined.AddString(names[j]);
m_predefined.SetItemData(index, j);
}
@@ -222,15 +222,20 @@ void GBColorDlg::OnColorClicked(UINT id)
{
id -= IDC_COLOR_BG0;
- u16 color = colors[id];
+ u16 color = colors[which*8+id];
- CColorDialog dlg(RGB(color & 0x1f, (color >> 5) & 0x1f, (color >> 10) & 0x1f),
+ COLORREF colorInit =
+ RGB((color & 0x1f) << 3, ((color >> 5) & 0x1f) << 3, ((color >> 10) & 0x1f) << 3);
+
+ CColorDialog dlg(colorInit,
CC_FULLOPEN | CC_ANYCOLOR, this);
- if(dlg.DoModal()) {
+
+ if(IDOK == dlg.DoModal())
+ {
COLORREF c = dlg.GetColor();
- colors[which*8+id] = (u16)((c >> 3) & 0x1f | ((c >> 11) & 0x1f) << 5 |
- ((c >> 19) & 0x1f) << 10);
+ colors[which*8+id] = (u16)((c >> 3) & 0x1f | ((c >> 11) & 0x1f) << 5 | ((c >> 19) & 0x1f) << 10);
+
colorControls[id].setColor(colors[which*8+id]);
}
}
@@ -246,7 +251,7 @@ void GBColorDlg::OnSelchangePredefined()
int sel = m_predefined.GetCurSel();
if(sel != -1) {
- int data = m_predefined.GetItemData(sel);
+ DWORD_PTR data = m_predefined.GetItemData(sel);
for(int i = 0; i < 8; i++) {
colorControls[i].setColor(defaultPalettes[data][i]);
colors[which*8+i] = defaultPalettes[data][i];
diff --git a/src/win32/GBColorDlg.h b/src/win32/GBColorDlg.h
index d19c3082..f94576a2 100644
--- a/src/win32/GBColorDlg.h
+++ b/src/win32/GBColorDlg.h
@@ -21,7 +21,7 @@
#define AFX_GBCOLORDLG_H__8D6126EF_06BB_48CF_ABB3_2CC4B1B60358__INCLUDED_
#include "ColorButton.h" // Added by ClassView
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/GBDisassemble.cpp b/src/win32/GBDisassemble.cpp
index 6eee4ec7..4a00d827 100644
--- a/src/win32/GBDisassemble.cpp
+++ b/src/win32/GBDisassemble.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -39,6 +39,7 @@ extern gbRegister DE;
extern gbRegister HL;
extern gbRegister SP;
extern gbRegister PC;
+extern u8 register_LY;
extern u16 IFF;
extern int gbDis(char *, u16);
@@ -114,8 +115,9 @@ void GBDisassemble::OnNext()
void GBDisassemble::OnGo()
{
CString buffer;
+
m_address.GetWindowText(buffer);
- sscanf(buffer, "%x", &address);
+ sscanf(buffer, "%hx", &address);
refresh();
}
@@ -242,6 +244,8 @@ void GBDisassemble::refresh()
GetDlgItem(IDC_R5)->SetWindowText(buffer);
sprintf(buffer, "%04x", IFF);
GetDlgItem(IDC_R6)->SetWindowText(buffer);
+ sprintf(buffer, "%04x", register_LY);
+ GetDlgItem(IDC_LY)->SetWindowText(buffer);
m_z = (AF.B.B0 & 0x80) != 0;
m_n = (AF.B.B0 & 0x40) != 0;
diff --git a/src/win32/GBDisassemble.h b/src/win32/GBDisassemble.h
index 0a37a6b0..31fb6963 100644
--- a/src/win32/GBDisassemble.h
+++ b/src/win32/GBDisassemble.h
@@ -20,7 +20,7 @@
#if !defined(AFX_GBDISASSEMBLE_H__3EFD5B47_6DBF_4F63_8F91_A9511EC590EB__INCLUDED_)
#define AFX_GBDISASSEMBLE_H__3EFD5B47_6DBF_4F63_8F91_A9511EC590EB__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/GBMapView.cpp b/src/win32/GBMapView.cpp
index c3cd7149..47ee202e 100644
--- a/src/win32/GBMapView.cpp
+++ b/src/win32/GBMapView.cpp
@@ -499,8 +499,8 @@ LRESULT GBMapView::OnMapInfo(WPARAM wParam, LPARAM lParam)
u8 *colors = (u8 *)lParam;
mapViewZoom.setColors(colors);
- int x = wParam & 0xffff;
- int y = (wParam >> 16);
+ int x = (int)(wParam & 0xffff);
+ int y = (int)(wParam >> 16);
CString buffer;
buffer.Format("(%d,%d)", x, y);
diff --git a/src/win32/GBMapView.h b/src/win32/GBMapView.h
index 2b2b006a..c429a4dc 100644
--- a/src/win32/GBMapView.h
+++ b/src/win32/GBMapView.h
@@ -31,7 +31,7 @@
#include "ZoomControl.h"
#include "ResizeDlg.h"
#include "IUpdate.h"
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
/////////////////////////////////////////////////////////////////////////////
// GBMapView dialog
diff --git a/src/win32/GBPaletteView.cpp b/src/win32/GBPaletteView.cpp
index fa9e57f2..1c6a4719 100644
--- a/src/win32/GBPaletteView.cpp
+++ b/src/win32/GBPaletteView.cpp
@@ -135,8 +135,8 @@ void GBPaletteView::save(int which)
if(dlg.DoModal() == IDCANCEL) {
return;
}
-
- captureBuffer = dlg.GetPathName();
+
+ captureBuffer = dlg.GetPathName();
PaletteViewControl *p = NULL;
diff --git a/src/win32/GBTileView.cpp b/src/win32/GBTileView.cpp
index 69bbe326..23c44800 100644
--- a/src/win32/GBTileView.cpp
+++ b/src/win32/GBTileView.cpp
@@ -460,8 +460,8 @@ LRESULT GBTileView::OnMapInfo(WPARAM wParam, LPARAM lParam)
u8 *colors = (u8 *)lParam;
zoom.setColors(colors);
- int x = (wParam & 0xFFFF)/8;
- int y = ((wParam >> 16) & 0xFFFF)/8;
+ int x = (int)((wParam & 0xffff)/8);
+ int y = (int)(((wParam >> 16) & 0xFFFF)/8);
int tiles = 0x0000;
if(charBase)
diff --git a/src/win32/GDIDisplay.cpp b/src/win32/GDIDisplay.cpp
index dc179804..22431c33 100644
--- a/src/win32/GDIDisplay.cpp
+++ b/src/win32/GDIDisplay.cpp
@@ -1,479 +1,402 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2005 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include
-
-#include "../System.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "..\gb\gbGlobals.h"
-#include "../Text.h"
-#include "../Util.h"
-#include "UniVideoModeDlg.h"
-
-#include "VBA.h"
-#include "MainWnd.h"
-#include "Reg.h"
-#include "..\..\res\resource.h"
-
-#include "../gbafilter.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-extern void winlog(const char *,...);
-extern int Init_2xSaI(u32);
-extern int systemSpeed;
-extern int winVideoModeSelect(CWnd *, GUID **);
-
-
-class GDIDisplay : public IDisplay
-{
-private:
- u8 *filterData;
- u8 info[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
- int SelectedFreq, SelectedAdapter;
-public:
- GDIDisplay();
- virtual ~GDIDisplay();
-
- virtual bool changeRenderSize(int w, int h);
- virtual bool initialize();
- virtual void cleanup();
- virtual void render();
- virtual void checkFullScreen();
- virtual void renderMenu();
- virtual void clear();
- virtual DISPLAY_TYPE getType() { return GDI; };
- virtual void setOption(const char *, int) {}
- virtual int selectFullScreenMode(GUID **);
- virtual int selectFullScreenMode2();
-};
-
-
-static int calculateShift(u32 mask)
-{
- int m = 0;
-
- while(mask) {
- m++;
- mask >>= 1;
- }
-
- return m-5;
-}
-
-GDIDisplay::GDIDisplay()
-{
- filterData = NULL;
-}
-
-GDIDisplay::~GDIDisplay()
-{
- cleanup();
-}
-
-void GDIDisplay::cleanup()
-{
- if(filterData)
- {
- delete [] filterData;
- filterData = NULL;
- }
-}
-
-bool GDIDisplay::initialize()
-{
- switch(theApp.cartridgeType)
- {
- case 0:
- theApp.sizeX = 240;
- theApp.sizeY = 160;
- break;
- case 1:
- if(gbBorderOn)
- {
- theApp.sizeX = 256;
- theApp.sizeY = 224;
- }
- else
- {
- theApp.sizeX = 160;
- theApp.sizeY = 144;
- }
- break;
- }
-
- switch(theApp.videoOption)
- {
- case VIDEO_1X:
- theApp.surfaceSizeX = theApp.sizeX;
- theApp.surfaceSizeY = theApp.sizeY;
- break;
- case VIDEO_2X:
- theApp.surfaceSizeX = theApp.sizeX * 2;
- theApp.surfaceSizeY = theApp.sizeY * 2;
- break;
- case VIDEO_3X:
- theApp.surfaceSizeX = theApp.sizeX * 3;
- theApp.surfaceSizeY = theApp.sizeY * 3;
- break;
- case VIDEO_4X:
- theApp.surfaceSizeX = theApp.sizeX * 4;
- theApp.surfaceSizeY = theApp.sizeY * 4;
- break;
- case VIDEO_320x240:
- case VIDEO_640x480:
- case VIDEO_800x600:
- case VIDEO_1024x768:
- case VIDEO_1280x1024:
- case VIDEO_OTHER:
- float scaleX = ((float)theApp.fsWidth / theApp.sizeX);
- float scaleY = ((float)theApp.fsHeight / theApp.sizeY);
- float min = scaleX < scaleY ? scaleX : scaleY;
- if(theApp.fsMaxScale)
- min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
- if(theApp.fullScreenStretch)
- {
- theApp.surfaceSizeX = theApp.fsWidth;
- theApp.surfaceSizeY = theApp.fsHeight;
- }
- else
- {
- theApp.surfaceSizeX = (int)(theApp.sizeX * min);
- theApp.surfaceSizeY = (int)(theApp.sizeY * min);
- }
- break;
- }
-
- theApp.rect.left = 0;
- theApp.rect.top = 0;
- theApp.rect.right = theApp.sizeX;
- theApp.rect.bottom = theApp.sizeY;
-
- theApp.dest.left = 0;
- theApp.dest.top = 0;
- theApp.dest.right = theApp.surfaceSizeX;
- theApp.dest.bottom = theApp.surfaceSizeY;
-
- DWORD style = WS_POPUP | WS_VISIBLE;
- DWORD styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- style |= WS_OVERLAPPEDWINDOW;
- else
- styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
- else
- AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
-
- int winSizeX = theApp.dest.right-theApp.dest.left;
- int winSizeY = theApp.dest.bottom-theApp.dest.top;
-
- if(theApp.videoOption > VIDEO_4X) {
- winSizeX = theApp.fsWidth;
- winSizeY = theApp.fsHeight;
- }
-
- int x = 0;
- int y = 0;
-
- if(theApp.videoOption <= VIDEO_4X) {
- x = theApp.windowPositionX;
- y = theApp.windowPositionY;
- }
-
- // Create a window
- MainWnd *pWnd = new MainWnd;
- theApp.m_pMainWnd = pWnd;
-
- pWnd->CreateEx(styleEx,
- theApp.wndClass,
- "VisualBoyAdvance",
- style,
- x,y,winSizeX,winSizeY,
- NULL,
- 0);
-
- if (!(HWND)*pWnd) {
- winlog("Error creating Window %08x\n", GetLastError());
- return FALSE;
- }
-
- theApp.updateMenuBar();
-
- theApp.adjustDestRect();
-
- // Enumerate available display modes
- theApp.mode320Available = false;
- theApp.mode640Available = false;
- theApp.mode800Available = false;
- theApp.mode1024Available = false;
- theApp.mode1280Available = false;
- DISPLAY_DEVICE dev;
- dev.cb = sizeof(DISPLAY_DEVICE);
- EnumDisplayDevices(NULL, 0, &dev, 0);
- DEVMODE mode;
- for (DWORD iMode = 0;
- TRUE == EnumDisplaySettings(dev.DeviceName, iMode, &mode);
- iMode++)
- {
- if ( (mode.dmBitsPerPel == 16) &&
- (mode.dmPelsWidth==320) && (mode.dmPelsHeight==240))
- theApp.mode320Available = true;
-
- if ( (mode.dmBitsPerPel == 16) &&
- (mode.dmPelsWidth==640) && (mode.dmPelsHeight==480))
- theApp.mode640Available = true;
-
- if ( (mode.dmBitsPerPel == 16) &&
- (mode.dmPelsWidth==800) && (mode.dmPelsHeight==600))
- theApp.mode800Available = true;
-
- if ( (mode.dmBitsPerPel == 32) &&
- (mode.dmPelsWidth==1024) && (mode.dmPelsHeight==768))
- theApp.mode1024Available = true;
-
- if ( (mode.dmBitsPerPel == 32) &&
- (mode.dmPelsWidth==1280) && (mode.dmPelsHeight==1024))
- theApp.mode1280Available = true;
- }
-
- // Go into fullscreen
- if(theApp.videoOption >= VIDEO_320x240)
- {
- mode.dmBitsPerPel = theApp.fsColorDepth;
- mode.dmPelsWidth = theApp.fsWidth;
- mode.dmPelsHeight = theApp.fsHeight;
- mode.dmDisplayFrequency = theApp.fsFrequency;
- mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
- DISPLAY_DEVICE dd;
- dd.cb = sizeof(DISPLAY_DEVICE);
- EnumDisplayDevices(NULL, theApp.fsAdapter, &dd, 0);
- ChangeDisplaySettingsEx(dd.DeviceName, &mode, NULL, CDS_FULLSCREEN, NULL);
- }
- else // Reset from fullscreen
- {
- ChangeDisplaySettings(NULL, 0);
- }
-
-
- // Initialize 2xSaI
- HDC dc = GetDC(NULL);
- HBITMAP hbm = CreateCompatibleBitmap(dc, 1, 1);
- BITMAPINFO *bi = (BITMAPINFO *)info;
- ZeroMemory(bi, sizeof(info));
- bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
- GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
- DeleteObject(hbm);
- ReleaseDC(NULL, dc);
-
- if(bi->bmiHeader.biCompression == BI_BITFIELDS) {
- systemColorDepth = bi->bmiHeader.biBitCount;
- if(systemColorDepth == 15)
- systemColorDepth = 16;
- systemRedShift = calculateShift(*((DWORD *)&bi->bmiColors[0]));
- systemGreenShift = calculateShift(*((DWORD *)&bi->bmiColors[1]));
- systemBlueShift = calculateShift(*((DWORD *)&bi->bmiColors[2]));
- if(systemColorDepth == 16) {
- if(systemGreenShift == 6) {
- Init_2xSaI(565);
- } else {
- Init_2xSaI(555);
- }
- } else if(systemColorDepth == 32)
- Init_2xSaI(32);
- } else {
- systemColorDepth = 32;
- systemRedShift = 19;
- systemGreenShift = 11;
- systemBlueShift = 3;
-
- Init_2xSaI(32);
- }
-
-
- // Setup system color depth
- theApp.fsColorDepth = systemColorDepth;
- if(systemColorDepth == 24)
- theApp.filterFunction = NULL;
-#ifdef MMX
- if(!theApp.disableMMX)
- cpu_mmx = theApp.detectMMX();
- else
- cpu_mmx = 0;
-#endif
-
- utilUpdateSystemColorMaps(theApp.filterLCD );
- theApp.updateFilter();
- theApp.updateIFB();
-
- pWnd->DragAcceptFiles(TRUE);
-
- return TRUE;
-}
-
-
-void GDIDisplay::clear()
-{
- CDC *dc = theApp.m_pMainWnd->GetDC();
- CBrush brush(RGB(0x00, 0x00, 0x00));
- dc->FillRect(CRect(0, 0, theApp.fsWidth, theApp.fsHeight), &brush);
- theApp.m_pMainWnd->ReleaseDC(dc);
-}
-
-void GDIDisplay::renderMenu()
-{
- checkFullScreen();
- theApp.m_pMainWnd->DrawMenuBar();
-}
-
-void GDIDisplay::checkFullScreen()
-{
-}
-
-void GDIDisplay::render()
-{
- unsigned int pitch = theApp.filterWidth * (systemColorDepth / 8) + 4;
-
- BITMAPINFO *bi = (BITMAPINFO *)info;
- bi->bmiHeader.biWidth = theApp.filterWidth + 1;
- bi->bmiHeader.biHeight = -theApp.filterHeight;
-
- if(theApp.filterFunction)
- {
- bi->bmiHeader.biWidth = theApp.rect.right;
- bi->bmiHeader.biHeight = -(int)theApp.rect.bottom;
-
- (*theApp.filterFunction)(
- pix + pitch,
- pitch,
- (u8*)theApp.delta,
- (u8*)filterData,
- theApp.rect.right * (systemColorDepth / 8),
- theApp.filterWidth,
- theApp.filterHeight);
- }
-
- POINT p1, p2;
- p1.x = theApp.dest.left;
- p1.y = theApp.dest.top;
- p2.x = theApp.dest.right;
- p2.y = theApp.dest.bottom;
- theApp.m_pMainWnd->ScreenToClient(&p1);
- theApp.m_pMainWnd->ScreenToClient(&p2);
-
- CDC *dc = theApp.m_pMainWnd->GetDC();
-
- // Draw bitmap to device
- StretchDIBits(
- dc->GetSafeHdc(),
- p1.x, p1.y,
- p2.x - p1.x,
- p2.y - p1.y,
- theApp.rect.left, theApp.rect.top,
- theApp.rect.right - theApp.rect.left,
- theApp.rect.bottom - theApp.rect.top,
- theApp.filterFunction ? filterData : pix + pitch,
- bi,
- DIB_RGB_COLORS,
- SRCCOPY);
-
- // Draw frame counter
- if (theApp.showSpeed && (theApp.videoOption >= VIDEO_320x240))
- {
- CString speedText;
- if (theApp.showSpeed == 1)
- speedText.AppendFormat("%3d%%", systemSpeed);
- else
- speedText.AppendFormat("%3d%%(%d, %d fps)",
- systemSpeed, systemFrameSkip, theApp.showRenderedFrames);
-
- dc->SetTextColor(RGB(0xFF, 0x3F, 0x3F));
- if (theApp.showSpeedTransparent)
- dc->SetBkMode(TRANSPARENT);
- else
- dc->SetBkMode(OPAQUE);
- dc->SetBkColor(RGB(0xFF, 0xFF, 0xFF));
- dc->TextOut(p1.x + 16, p1.y + 16, speedText);
- }
-
- // Draw screen message
- if (theApp.screenMessage)
- {
- if ( ((GetTickCount() - theApp.screenMessageTime) < 3000) && !theApp.disableStatusMessage )
- {
- dc->SetTextColor(RGB(0x3F, 0x3F, 0xFF));
- if (theApp.showSpeedTransparent)
- dc->SetBkMode(TRANSPARENT);
- else
- dc->SetBkMode(OPAQUE);
- dc->SetBkColor(RGB(0xFF, 0xFF, 0xFF));
- dc->TextOut(p1.x + 16, p2.y - 16, theApp.screenMessageBuffer);
- }
- else
- theApp.screenMessage = false;
- }
-
- theApp.m_pMainWnd->ReleaseDC(dc);
-}
-
-int GDIDisplay::selectFullScreenMode(GUID **pGUID)
-{
- int w, h, b;
- UniVideoModeDlg dlg(0, &w, &h, &b, &SelectedFreq, &SelectedAdapter);
-
- if (0 == dlg.DoModal())
- {
- return (b<<24) + (w<<12) + h;
- // Bits<<24 | Width<<12 | Height
- }
- else
- {
- return -1;
- }
-}
-
-int GDIDisplay::selectFullScreenMode2()
-{
- return (SelectedAdapter<<16) + SelectedFreq;
-}
-
-bool GDIDisplay::changeRenderSize(int w, int h)
-{
- if (filterData)
- {
- delete [] filterData;
- filterData = NULL;
- }
- filterData = new u8[w*h*(systemColorDepth>>3)];
- return true;
-}
-
-
-IDisplay *newGDIDisplay()
-{
- return new GDIDisplay();
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+
+#include "Display.h"
+
+#include "../System.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../Text.h"
+#include "../Util.h"
+
+#include "VBA.h"
+#include "MainWnd.h"
+#include "Reg.h"
+#include "resource.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+extern void winlog(const char *,...);
+extern int Init_2xSaI(u32);
+extern int systemSpeed;
+
+class GDIDisplay : public IDisplay {
+private:
+ u8 *filterData;
+ u8 info[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
+
+public:
+ GDIDisplay();
+ virtual ~GDIDisplay();
+
+ virtual bool initialize();
+ virtual void cleanup();
+ virtual void render();
+ virtual void checkFullScreen();
+ virtual void renderMenu();
+ virtual void clear();
+ virtual DISPLAY_TYPE getType() { return GDI; };
+ virtual void setOption(const char *, int) {}
+ virtual bool isSkinSupported() { return true; }
+ virtual int selectFullScreenMode(GUID **);
+};
+
+static int calculateShift(u32 mask)
+{
+ int m = 0;
+
+ while(mask) {
+ m++;
+ mask >>= 1;
+ }
+
+ return m-5;
+}
+
+GDIDisplay::GDIDisplay()
+{
+ filterData = (u8 *)malloc(4*4*256*240);
+}
+
+GDIDisplay::~GDIDisplay()
+{
+ cleanup();
+}
+
+void GDIDisplay::cleanup()
+{
+ if(filterData) {
+ free(filterData);
+ filterData = NULL;
+ }
+}
+
+bool GDIDisplay::initialize()
+{
+ theApp.sizeX = 240;
+ theApp.sizeY = 160;
+ switch(theApp.videoOption) {
+ case VIDEO_1X:
+ theApp.surfaceSizeX = theApp.sizeX;
+ theApp.surfaceSizeY = theApp.sizeY;
+ break;
+ case VIDEO_2X:
+ theApp.surfaceSizeX = theApp.sizeX * 2;
+ theApp.surfaceSizeY = theApp.sizeY * 2;
+ break;
+ case VIDEO_3X:
+ theApp.surfaceSizeX = theApp.sizeX * 3;
+ theApp.surfaceSizeY = theApp.sizeY * 3;
+ break;
+ case VIDEO_4X:
+ theApp.surfaceSizeX = theApp.sizeX * 4;
+ theApp.surfaceSizeY = theApp.sizeY * 4;
+ break;
+ case VIDEO_320x240:
+ case VIDEO_640x480:
+ case VIDEO_800x600:
+ case VIDEO_OTHER:
+ {
+ int scaleX = (theApp.fsWidth / theApp.sizeX);
+ int scaleY = (theApp.fsHeight / theApp.sizeY);
+ int min = scaleX < scaleY ? scaleX : scaleY;
+ if(theApp.fsMaxScale)
+ min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
+ theApp.surfaceSizeX = theApp.sizeX * min;
+ theApp.surfaceSizeY = theApp.sizeY * min;
+ if(theApp.fullScreenStretch) {
+ theApp.surfaceSizeX = theApp.fsWidth;
+ theApp.surfaceSizeY = theApp.fsHeight;
+ }
+ }
+ break;
+ }
+
+ theApp.rect.left = 0;
+ theApp.rect.top = 0;
+ theApp.rect.right = theApp.sizeX;
+ theApp.rect.bottom = theApp.sizeY;
+
+ theApp.dest.left = 0;
+ theApp.dest.top = 0;
+ theApp.dest.right = theApp.surfaceSizeX;
+ theApp.dest.bottom = theApp.surfaceSizeY;
+
+ DWORD style = WS_POPUP | WS_VISIBLE;
+ DWORD styleEx = 0;
+
+ if(theApp.videoOption <= VIDEO_4X)
+ style |= WS_OVERLAPPEDWINDOW;
+ else
+ styleEx = 0;
+
+ if(theApp.videoOption <= VIDEO_4X)
+ AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
+ else
+ AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
+
+ int winSizeX = theApp.dest.right-theApp.dest.left;
+ int winSizeY = theApp.dest.bottom-theApp.dest.top;
+
+ if(theApp.videoOption > VIDEO_4X) {
+ winSizeX = theApp.fsWidth;
+ winSizeY = theApp.fsHeight;
+ }
+
+ int x = 0;
+ int y = 0;
+
+ if(theApp.videoOption <= VIDEO_4X) {
+ x = theApp.windowPositionX;
+ y = theApp.windowPositionY;
+ }
+
+ // Create a window
+ MainWnd *pWnd = new MainWnd;
+ theApp.m_pMainWnd = pWnd;
+
+ pWnd->CreateEx(styleEx,
+ theApp.wndClass,
+ "VisualBoyAdvance",
+ style,
+ x,y,winSizeX,winSizeY,
+ NULL,
+ 0);
+
+ if (!(HWND)*pWnd) {
+ winlog("Error creating Window %08x\n", GetLastError());
+ return FALSE;
+ }
+
+ theApp.updateMenuBar();
+
+ theApp.adjustDestRect();
+
+ theApp.mode320Available = false;
+ theApp.mode640Available = false;
+ theApp.mode800Available = false;
+
+ HDC dc = GetDC(NULL);
+ HBITMAP hbm = CreateCompatibleBitmap(dc, 1, 1);
+ BITMAPINFO *bi = (BITMAPINFO *)info;
+ ZeroMemory(bi, sizeof(info));
+ bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
+ GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
+ DeleteObject(hbm);
+ ReleaseDC(NULL, dc);
+
+ if(bi->bmiHeader.biCompression == BI_BITFIELDS) {
+ systemColorDepth = bi->bmiHeader.biBitCount;
+ if(systemColorDepth == 15)
+ systemColorDepth = 16;
+ systemRedShift = calculateShift(*((DWORD *)&bi->bmiColors[0]));
+ systemGreenShift = calculateShift(*((DWORD *)&bi->bmiColors[1]));
+ systemBlueShift = calculateShift(*((DWORD *)&bi->bmiColors[2]));
+ if(systemColorDepth == 16) {
+ if(systemGreenShift == 6) {
+ Init_2xSaI(565);
+ } else {
+ Init_2xSaI(555);
+ }
+ } else if(systemColorDepth == 32)
+ Init_2xSaI(32);
+ } else {
+ systemColorDepth = 32;
+ systemRedShift = 19;
+ systemGreenShift = 11;
+ systemBlueShift = 3;
+
+ Init_2xSaI(32);
+ }
+ theApp.fsColorDepth = systemColorDepth;
+ if(systemColorDepth == 24)
+ theApp.filterFunction = NULL;
+#ifdef MMX
+ if(!theApp.disableMMX)
+ cpu_mmx = theApp.detectMMX();
+ else
+ cpu_mmx = 0;
+#endif
+
+ utilUpdateSystemColorMaps();
+ theApp.updateFilter();
+ theApp.updateIFB();
+
+ pWnd->DragAcceptFiles(TRUE);
+
+ return TRUE;
+}
+
+void GDIDisplay::clear()
+{
+}
+
+void GDIDisplay::renderMenu()
+{
+ checkFullScreen();
+ theApp.m_pMainWnd->DrawMenuBar();
+}
+
+void GDIDisplay::checkFullScreen()
+{
+}
+
+void GDIDisplay::render()
+{
+ BITMAPINFO *bi = (BITMAPINFO *)info;
+ bi->bmiHeader.biWidth = theApp.filterWidth+1;
+ bi->bmiHeader.biHeight = -theApp.filterHeight;
+
+ int pitch = theApp.filterWidth * 2 + 4;
+ if(systemColorDepth == 24)
+ pitch = theApp.filterWidth * 3;
+ else if(systemColorDepth == 32)
+ pitch = theApp.filterWidth * 4 + 4;
+
+ if(theApp.filterFunction) {
+ bi->bmiHeader.biWidth = theApp.filterWidth * 2;
+ bi->bmiHeader.biHeight = -theApp.filterHeight * 2;
+
+ if(systemColorDepth == 16)
+ (*theApp.filterFunction)(pix+pitch,
+ pitch,
+ (u8*)theApp.delta,
+ (u8*)filterData,
+ theApp.filterWidth*2*2,
+ theApp.filterWidth,
+ theApp.filterHeight);
+ else
+ (*theApp.filterFunction)(pix+pitch,
+ pitch,
+ (u8*)theApp.delta,
+ (u8*)filterData,
+ theApp.filterWidth*4*2,
+ theApp.filterWidth,
+ theApp.filterHeight);
+ }
+
+ if(theApp.showSpeed && (theApp.videoOption > VIDEO_4X || theApp.skin != NULL)) {
+ char buffer[30];
+ if(theApp.showSpeed == 1)
+ sprintf(buffer, "%3d%%", systemSpeed);
+ else
+ sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
+ systemFrameSkip,
+ theApp.showRenderedFrames);
+
+ if(theApp.filterFunction) {
+ int p = theApp.filterWidth * 4;
+ if(systemColorDepth == 24)
+ p = theApp.filterWidth * 6;
+ else if(systemColorDepth == 32)
+ p = theApp.filterWidth * 8;
+ if(theApp.showSpeedTransparent)
+ drawTextTransp((u8*)filterData,
+ p,
+ 10,
+ theApp.filterHeight*2-10,
+ buffer);
+ else
+ drawText((u8*)filterData,
+ p,
+ 10,
+ theApp.filterHeight*2-10,
+ buffer);
+ } else {
+ if(theApp.showSpeedTransparent)
+ drawTextTransp((u8*)pix,
+ pitch,
+ 10,
+ theApp.filterHeight-10,
+ buffer);
+ else
+ drawText((u8*)pix,
+ pitch,
+ 10,
+ theApp.filterHeight-10,
+ buffer);
+ }
+ }
+
+ POINT p;
+ p.x = theApp.dest.left;
+ p.y = theApp.dest.top;
+ CWnd *pWnd = theApp.m_pMainWnd;
+ pWnd->ScreenToClient(&p);
+ POINT p2;
+ p2.x = theApp.dest.right;
+ p2.y = theApp.dest.bottom;
+ pWnd->ScreenToClient(&p2);
+
+ CDC *dc = pWnd->GetDC();
+
+ StretchDIBits((HDC)*dc,
+ p.x,
+ p.y,
+ p2.x - p.x,
+ p2.y - p.y,
+ 0,
+ 0,
+ theApp.rect.right,
+ theApp.rect.bottom,
+ theApp.filterFunction ? filterData : pix+pitch,
+ bi,
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ if(theApp.screenMessage) {
+ if(((GetTickCount() - theApp.screenMessageTime) < 3000) &&
+ !theApp.disableStatusMessage) {
+ dc->SetTextColor(RGB(255,0,0));
+ dc->SetBkMode(TRANSPARENT);
+ dc->TextOut(p.x+10, p2.y - 20, theApp.screenMessageBuffer);
+ } else {
+ theApp.screenMessage = false;
+ }
+ }
+
+ pWnd->ReleaseDC(dc);
+}
+
+int GDIDisplay::selectFullScreenMode(GUID **)
+{
+ HWND wnd = GetDesktopWindow();
+ RECT r;
+ GetWindowRect(wnd, &r);
+ int w = (r.right - r.left) & 4095;
+ int h = (r.bottom - r.top) & 4095;
+ HDC dc = GetDC(wnd);
+ int c = GetDeviceCaps(dc, BITSPIXEL);
+ ReleaseDC(wnd, dc);
+
+ return (c << 24) | (w << 12) | h;
+}
+
+IDisplay *newGDIDisplay()
+{
+ return new GDIDisplay();
+}
+
diff --git a/src/win32/IOViewer.cpp b/src/win32/IOViewer.cpp
index 491000e9..bcc5afb5 100644
--- a/src/win32/IOViewer.cpp
+++ b/src/win32/IOViewer.cpp
@@ -1,202 +1,239 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-// IOViewer.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "vba.h"
-#include "IOViewer.h"
-
-#include "../System.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../Sound.h"
-
-#include "IOViewerRegs.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// IOViewer dialog
-
-
-IOViewer::IOViewer(CWnd* pParent /*=NULL*/)
- : ResizeDlg(IOViewer::IDD, pParent)
-{
- //{{AFX_DATA_INIT(IOViewer)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- selected = 0;
- autoUpdate = false;
-}
-
-
-void IOViewer::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(IOViewer)
- DDX_Control(pDX, IDC_VALUE, m_value);
- DDX_Control(pDX, IDC_ADDRESSES, m_address);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(IOViewer, CDialog)
- //{{AFX_MSG_MAP(IOViewer)
- ON_BN_CLICKED(IDC_CLOSE, OnClose)
- ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
- ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
- ON_CBN_SELCHANGE(IDC_ADDRESSES, OnSelchangeAddresses)
- ON_BN_CLICKED(IDC_APPLY, OnApply)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
-// IOViewer message handlers
-
-void IOViewer::OnClose()
-{
- theApp.winRemoveUpdateListener(this);
-
- DestroyWindow();
-}
-
-void IOViewer::OnRefresh()
-{
- // TODO: Add your control notification handler code here
-
-}
-
-void IOViewer::OnAutoUpdate()
-{
- autoUpdate = !autoUpdate;
- if(autoUpdate) {
- theApp.winAddUpdateListener(this);
- } else {
- theApp.winRemoveUpdateListener(this);
- }
-}
-
-void IOViewer::OnSelchangeAddresses()
-{
- selected = m_address.GetCurSel();
-
- update();
-}
-
-void IOViewer::PostNcDestroy()
-{
- delete this;
-}
-
-BOOL IOViewer::OnInitDialog()
-{
- CDialog::OnInitDialog();
-
- // winCenterWindow(getHandle());
- DIALOG_SIZER_START( sz )
- DIALOG_SIZER_END()
- SetData(sz,
- TRUE,
- HKEY_CURRENT_USER,
- "Software\\Emulators\\VisualBoyAdvance\\Viewer\\IOView",
- NULL);
-
- CFont *font = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT));
- int i;
- for(i = 0; i < sizeof(ioViewRegisters)/sizeof(IOData); i++) {
- m_address.AddString(ioViewRegisters[i].name);
- }
- m_address.SetFont(font);
- for(i = 0; i < 16; i++) {
- GetDlgItem(IDC_BIT_0+i)->SetFont(font);
- }
-
- RECT cbSize;
- int Height;
-
- m_address.GetClientRect(&cbSize);
- Height = m_address.GetItemHeight(0);
- Height += m_address.GetItemHeight(0) * (10);
-
- // Note: The use of SM_CYEDGE assumes that we're using Windows '95
- // Now add on the height of the border of the edit box
- Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges
-
- // The height of the border of the drop-down box
- Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges
-
- // now set the size of the window
- m_address.SetWindowPos(NULL,
- 0, 0,
- cbSize.right, Height,
- SWP_NOMOVE | SWP_NOZORDER);
-
- m_address.SetCurSel(0);
- update();
-
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
-
-void IOViewer::update()
-{
- CString buffer;
-
- const IOData *sel = &ioViewRegisters[selected];
- u16 data = sel->address ? *sel->address :
- (ioMem ? soundRead16(sel->offset) : 0);
-
- for(int i = 0; i < 16; i++) {
- CButton *pWnd = (CButton *)GetDlgItem(IDC_BIT_0 + i);
-
- if(pWnd) {
- if(!(sel->write & (1 << i)))
- pWnd->EnableWindow(FALSE);
- else
- pWnd->EnableWindow(TRUE);
- pWnd->SetCheck(((data & (1 << i)) >> i));
- buffer.Format("%2d %s", i, sel->bits[i]);
- pWnd->SetWindowText(buffer);
- }
- }
-
- buffer.Format("%04X", data);
- m_value.SetWindowText(buffer);
-}
-
-void IOViewer::OnApply()
-{
- const IOData *sel = &ioViewRegisters[selected];
- u16 res = 0;
- for(int i = 0; i < 16; i++) {
- CButton *pWnd = (CButton *)GetDlgItem(IDC_BIT_0 + i);
-
- if(pWnd) {
- if(pWnd->GetCheck())
- res |= (1 << i);
- }
- }
- CPUWriteHalfWord(0x4000000+sel->offset, res);
- update();
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// IOViewer.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "vba.h"
+#include "IOViewer.h"
+
+#include "../System.h"
+#include "../GBA.h"
+#include "../Globals.h"
+
+#include "IOViewerRegs.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// IOViewer dialog
+
+
+IOViewer::IOViewer(CWnd* pParent /*=NULL*/)
+ : ResizeDlg(IOViewer::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(IOViewer)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ selected = 0;
+ autoUpdate = false;
+}
+
+
+void IOViewer::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(IOViewer)
+ DDX_Control(pDX, IDC_VALUE, m_value);
+ DDX_Control(pDX, IDC_ADDRESSES, m_address);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(IOViewer, CDialog)
+ //{{AFX_MSG_MAP(IOViewer)
+ ON_BN_CLICKED(IDC_CLOSE, OnClose)
+ ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
+ ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate)
+ ON_CBN_SELCHANGE(IDC_ADDRESSES, OnSelchangeAddresses)
+ ON_BN_CLICKED(IDC_APPLY, OnApply)
+ ON_BN_CLICKED(IDC_BIT_0, bitChange)
+ ON_BN_CLICKED(IDC_BIT_1, bitChange)
+ ON_BN_CLICKED(IDC_BIT_2, bitChange)
+ ON_BN_CLICKED(IDC_BIT_3, bitChange)
+ ON_BN_CLICKED(IDC_BIT_4, bitChange)
+ ON_BN_CLICKED(IDC_BIT_5, bitChange)
+ ON_BN_CLICKED(IDC_BIT_6, bitChange)
+ ON_BN_CLICKED(IDC_BIT_7, bitChange)
+ ON_BN_CLICKED(IDC_BIT_8, bitChange)
+ ON_BN_CLICKED(IDC_BIT_9, bitChange)
+ ON_BN_CLICKED(IDC_BIT_10, bitChange)
+ ON_BN_CLICKED(IDC_BIT_11, bitChange)
+ ON_BN_CLICKED(IDC_BIT_12, bitChange)
+ ON_BN_CLICKED(IDC_BIT_13, bitChange)
+ ON_BN_CLICKED(IDC_BIT_14, bitChange)
+ ON_BN_CLICKED(IDC_BIT_15, bitChange)
+ //}}AFX_MSG_MAP
+ END_MESSAGE_MAP()
+
+ /////////////////////////////////////////////////////////////////////////////
+// IOViewer message handlers
+
+void IOViewer::OnClose()
+{
+ theApp.winRemoveUpdateListener(this);
+
+ DestroyWindow();
+}
+
+void IOViewer::bitChange()
+{
+ CString buffer;
+ u16 data = 0;
+
+ for(int i = 0; i < 16; i++) {
+ CButton *pWnd = (CButton *)GetDlgItem(IDC_BIT_0 + i);
+
+ if(pWnd) {
+ if(pWnd->GetCheck())
+ data |= (1 << i);
+ }
+ }
+
+ buffer.Format("%04X", data);
+ m_value.SetWindowText(buffer);
+}
+
+void IOViewer::OnRefresh()
+{
+ // TODO: Add your control notification handler code here
+
+ update();
+}
+
+void IOViewer::OnAutoUpdate()
+{
+ autoUpdate = !autoUpdate;
+ if(autoUpdate) {
+ theApp.winAddUpdateListener(this);
+ } else {
+ theApp.winRemoveUpdateListener(this);
+ }
+}
+
+void IOViewer::OnSelchangeAddresses()
+{
+ selected = m_address.GetCurSel();
+
+ update();
+}
+
+void IOViewer::PostNcDestroy()
+{
+ delete this;
+}
+
+BOOL IOViewer::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // winCenterWindow(getHandle());
+ DIALOG_SIZER_START( sz )
+ DIALOG_SIZER_END()
+ SetData(sz,
+ TRUE,
+ HKEY_CURRENT_USER,
+ "Software\\Emulators\\VisualBoyAdvance\\Viewer\\IOView",
+ NULL);
+
+ CFont *font = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT));
+ int i;
+ for(i = 0; i < sizeof(ioViewRegisters)/sizeof(IOData); i++) {
+ m_address.AddString(ioViewRegisters[i].name);
+ }
+ m_address.SetFont(font);
+ for(i = 0; i < 16; i++) {
+ GetDlgItem(IDC_BIT_0+i)->SetFont(font);
+ }
+
+ RECT cbSize;
+ int Height;
+
+ m_address.GetClientRect(&cbSize);
+ Height = m_address.GetItemHeight(0);
+ Height += m_address.GetItemHeight(0) * (10);
+
+ // Note: The use of SM_CYEDGE assumes that we're using Windows '95
+ // Now add on the height of the border of the edit box
+ Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges
+
+ // The height of the border of the drop-down box
+ Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges
+
+ // now set the size of the window
+ m_address.SetWindowPos(NULL,
+ 0, 0,
+ cbSize.right, Height,
+ SWP_NOMOVE | SWP_NOZORDER);
+
+ m_address.SetCurSel(0);
+ update();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void IOViewer::update()
+{
+ CString buffer;
+
+ const IOData *sel = &ioViewRegisters[selected];
+ u16 data = sel->address ? *sel->address :
+ (ioMem ? *((u16 *)&ioMem[sel->offset]) : 0);
+
+ for(int i = 0; i < 16; i++) {
+ CButton *pWnd = (CButton *)GetDlgItem(IDC_BIT_0 + i);
+
+ if(pWnd) {
+ if(!(sel->write & (1 << i)))
+ pWnd->EnableWindow(FALSE);
+ else
+ pWnd->EnableWindow(TRUE);
+ pWnd->SetCheck(((data & (1 << i)) >> i));
+ buffer.Format("%2d %s", i, sel->bits[i]);
+ pWnd->SetWindowText(buffer);
+ }
+ }
+
+ buffer.Format("%04X", data);
+ m_value.SetWindowText(buffer);
+}
+
+void IOViewer::OnApply()
+{
+ if(rom != NULL)
+ {
+ const IOData *sel = &ioViewRegisters[selected];
+ u16 res = 0;
+ for(int i = 0; i < 16; i++) {
+ CButton *pWnd = (CButton *)GetDlgItem(IDC_BIT_0 + i);
+
+ if(pWnd) {
+ if(pWnd->GetCheck())
+ res |= (1 << i);
+ }
+ }
+ CPUWriteHalfWord(0x4000000+sel->offset, res);
+ update();
+ }
+}
diff --git a/src/win32/IOViewer.h b/src/win32/IOViewer.h
index d768b018..e262f9ec 100644
--- a/src/win32/IOViewer.h
+++ b/src/win32/IOViewer.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@ class IOViewer : public ResizeDlg, IUpdateListener
// Construction
public:
void update();
+ void bitChange();
bool autoUpdate;
int selected;
IOViewer(CWnd* pParent = NULL); // standard constructor
diff --git a/src/win32/IOViewerRegs.h b/src/win32/IOViewerRegs.h
index 9d28a6e2..4491308e 100644
--- a/src/win32/IOViewerRegs.h
+++ b/src/win32/IOViewerRegs.h
@@ -1,7 +1,7 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -258,7 +258,7 @@ const IOData ioViewRegisters[] = {
}
},
{
- &BG2HOFS, 0x18, "0x4000018-BG8HOFS", 0x01FF,
+ &BG2HOFS, 0x18, "0x4000018-BG2HOFS", 0x01FF,
{
"",
"",
@@ -1119,7 +1119,7 @@ const IOData ioViewRegisters[] = {
}
},
{
- NULL, 0x82, "0x4000082-SGCNT0_H", 0xFF1F,
+ NULL, 0x82, "0x4000082-SGCNT0_H", 0xFF0F,
{
"",
"Sound 1-4 Volume (2 bits)",
diff --git a/src/win32/Input.h b/src/win32/Input.h
index 345e2a61..93813252 100644
--- a/src/win32/Input.h
+++ b/src/win32/Input.h
@@ -22,10 +22,6 @@
#include "../System.h"
#define JOYCONFIG_MESSAGE (WM_USER + 1000)
-
-typedef CList KeyList;
-//typedef CList KeyList;
-
#define JOYPADS 4
#define MOTION_KEYS 4
#define KEYS_PER_PAD 13
@@ -35,6 +31,8 @@ typedef CList KeyList;
#define DEVICEOF(key) (key >> 8)
#define KEYOF(key) (key & 255)
+typedef CList KeyList;
+
enum {
KEY_LEFT, KEY_RIGHT,
KEY_UP, KEY_DOWN,
@@ -46,6 +44,7 @@ enum {
};
class Input {
+
public:
KeyList joypaddata[JOYPADS * KEYS_PER_PAD + MOTION_KEYS];
@@ -56,7 +55,7 @@ class Input {
virtual bool readDevices() = 0;
virtual u32 readDevice(int which) = 0;
- virtual CString getKeyName(int key) = 0;
+ virtual CString getKeyName(LONG_PTR key) = 0;
virtual void checkKeys() = 0;
virtual void checkMotionKeys() = 0;
virtual void checkDevices() = 0;
@@ -65,6 +64,4 @@ class Input {
virtual void saveSettings() = 0;
};
-#define joypad theApp.input->joypaddata
-
#endif
diff --git a/src/win32/Joypad.cpp b/src/win32/Joypad.cpp
index 9b88fd7d..bd8594da 100644
--- a/src/win32/Joypad.cpp
+++ b/src/win32/Joypad.cpp
@@ -43,25 +43,25 @@ void AssignKey(KeyList &Key, int Out)
CString GetKeyListName(KeyList& Keys)
{
- CString txtKeys;
-
- POSITION p = Keys.GetHeadPosition();
- while(p!=NULL)
- {
- txtKeys+=theApp.input->getKeyName(Keys.GetNext(p));
- if (p!=NULL)
- txtKeys+=", ";
- }
+ CString txtKeys;
+
+ POSITION p = Keys.GetHeadPosition();
+ while(p!=NULL)
+ {
+ txtKeys+=theApp.input->getKeyName(Keys.GetNext(p));
+ if (p!=NULL)
+ txtKeys+=", ";
+ }
return txtKeys;
}
void CopyKeys(KeyList &Out, KeyList &In)
{
Out.RemoveAll();
- POSITION p = In.GetHeadPosition();
- while(p!=NULL)
- Out.AddTail(In.GetNext(p));
-}
+ POSITION p = In.GetHeadPosition();
+ while(p!=NULL)
+ Out.AddTail(In.GetNext(p));
+}
#define AssignKeys(in, out) CopyKeys(out, in);
@@ -100,6 +100,7 @@ LRESULT JoypadEditControl::OnJoyConfig(WPARAM wParam, LPARAM lParam)
return TRUE;
}
+
BOOL JoypadEditControl::PreTranslateMessage(MSG *pMsg)
{
if(pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN))
@@ -125,35 +126,33 @@ JoypadConfig::JoypadConfig(int w, CWnd* pParent /*=NULL*/)
void JoypadConfig::DoDataExchange(CDataExchange* pDX)
{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(JoypadConfig)
- DDX_Control(pDX, IDC_EDIT_UP, up);
- DDX_Control(pDX, IDC_EDIT_SPEED, speed);
- DDX_Control(pDX, IDC_EDIT_RIGHT, right);
- DDX_Control(pDX, IDC_EDIT_LEFT, left);
- DDX_Control(pDX, IDC_EDIT_DOWN, down);
- DDX_Control(pDX, IDC_EDIT_CAPTURE, capture);
- DDX_Control(pDX, IDC_EDIT_BUTTON_START, buttonStart);
- DDX_Control(pDX, IDC_EDIT_BUTTON_SELECT, buttonSelect);
- DDX_Control(pDX, IDC_EDIT_BUTTON_R, buttonR);
- DDX_Control(pDX, IDC_EDIT_BUTTON_L, buttonL);
- DDX_Control(pDX, IDC_EDIT_BUTTON_GS, buttonGS);
- DDX_Control(pDX, IDC_EDIT_BUTTON_B, buttonB);
- DDX_Control(pDX, IDC_EDIT_BUTTON_A, buttonA);
- //}}AFX_DATA_MAP
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(JoypadConfig)
+ DDX_Control(pDX, IDC_EDIT_UP, up);
+ DDX_Control(pDX, IDC_EDIT_SPEED, speed);
+ DDX_Control(pDX, IDC_EDIT_RIGHT, right);
+ DDX_Control(pDX, IDC_EDIT_LEFT, left);
+ DDX_Control(pDX, IDC_EDIT_DOWN, down);
+ DDX_Control(pDX, IDC_EDIT_CAPTURE, capture);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_START, buttonStart);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_SELECT, buttonSelect);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_R, buttonR);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_L, buttonL);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_GS, buttonGS);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_B, buttonB);
+ DDX_Control(pDX, IDC_EDIT_BUTTON_A, buttonA);
+ //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(JoypadConfig, CDialog)
- //{{AFX_MSG_MAP(JoypadConfig)
ON_BN_CLICKED(ID_CANCEL, OnCancel)
ON_BN_CLICKED(ID_OK, OnOk)
ON_WM_CHAR()
ON_WM_DESTROY()
ON_WM_TIMER()
ON_WM_KEYDOWN()
- //}}AFX_MSG_MAP
- ON_BN_CLICKED(IDC_APPENDMODE, &JoypadConfig::OnBnClickedAppendmode)
+ ON_BN_CLICKED(IDC_APPENDMODE, &JoypadConfig::OnBnClickedAppendmode)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
@@ -166,19 +165,19 @@ void JoypadConfig::OnCancel()
void JoypadConfig::OnOk()
{
- AssignKeys(up.m_Keys,joypad[JOYPAD(which,KEY_UP)]);
- AssignKeys(speed.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_SPEED)]);
- AssignKeys(right.m_Keys,joypad[JOYPAD(which,KEY_RIGHT)]);
- AssignKeys(left.m_Keys,joypad[JOYPAD(which,KEY_LEFT)]);
- AssignKeys(down.m_Keys,joypad[JOYPAD(which,KEY_DOWN)]);
- AssignKeys(capture.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_CAPTURE)]);
- AssignKeys(buttonStart.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_START)]);
- AssignKeys(buttonSelect.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_SELECT)]);
- AssignKeys(buttonR.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_R)]);
- AssignKeys(buttonL.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_L)]);
- AssignKeys(buttonGS.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_GS)]);
- AssignKeys(buttonB.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_B)]);
- AssignKeys(buttonA.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_A)]);
+ AssignKeys(up.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_UP)]);
+ AssignKeys(speed.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SPEED)]);
+ AssignKeys(right.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_RIGHT)]);
+ AssignKeys(left.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_LEFT)]);
+ AssignKeys(down.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_DOWN)]);
+ AssignKeys(capture.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_CAPTURE)]);
+ AssignKeys(buttonStart.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_START)]);
+ AssignKeys(buttonSelect.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SELECT)]);
+ AssignKeys(buttonR.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_R)]);
+ AssignKeys(buttonL.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_L)]);
+ AssignKeys(buttonGS.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_GS)]);
+ AssignKeys(buttonB.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_B)]);
+ AssignKeys(buttonA.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_A)]);
theApp.input->checkKeys();
EndDialog(TRUE);
@@ -195,7 +194,7 @@ void JoypadConfig::OnDestroy()
KillTimer(timerId);
}
-void JoypadConfig::OnTimer(UINT nIDEvent)
+void JoypadConfig::OnTimer(UINT_PTR nIDEvent)
{
theApp.input->checkDevices();
@@ -212,35 +211,35 @@ BOOL JoypadConfig::OnInitDialog()
bAppendMode = FALSE;
- timerId = SetTimer(0,200,NULL);
+ timerId = SetTimer(0,50,NULL);
- CopyKeys(up.m_Keys,joypad[JOYPAD(which,KEY_UP)]);
- CopyKeys(speed.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_SPEED)]);
- CopyKeys(right.m_Keys,joypad[JOYPAD(which,KEY_RIGHT)]);
- CopyKeys(left.m_Keys,joypad[JOYPAD(which,KEY_LEFT)]);
- CopyKeys(down.m_Keys,joypad[JOYPAD(which,KEY_DOWN)]);
- CopyKeys(capture.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_CAPTURE)]);
- CopyKeys(buttonStart.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_START)]);
- CopyKeys(buttonSelect.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_SELECT)]);
- CopyKeys(buttonR.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_R)]);
- CopyKeys(buttonL.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_L)]);
- CopyKeys(buttonGS.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_GS)]);
- CopyKeys(buttonB.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_B)]);
- CopyKeys(buttonA.m_Keys,joypad[JOYPAD(which,KEY_BUTTON_A)]);
+ CopyKeys(up.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_UP)]);
+ CopyKeys(speed.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SPEED)]);
+ CopyKeys(right.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_RIGHT)]);
+ CopyKeys(left.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_LEFT)]);
+ CopyKeys(down.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_DOWN)]);
+ CopyKeys(capture.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_CAPTURE)]);
+ CopyKeys(buttonStart.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_START)]);
+ CopyKeys(buttonSelect.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SELECT)]);
+ CopyKeys(buttonR.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_R)]);
+ CopyKeys(buttonL.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_L)]);
+ CopyKeys(buttonGS.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_GS)]);
+ CopyKeys(buttonB.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_B)]);
+ CopyKeys(buttonA.m_Keys,theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_A)]);
- up.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_UP)]));
- down.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_DOWN)]));
- left.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_LEFT)]));
- right.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_RIGHT)]));
- buttonA.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_A)]));
- buttonB.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_B)]));
- buttonL.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_L)]));
- buttonR.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_R)]));
- buttonSelect.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_SELECT)]));
- buttonStart.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_START)]));
- speed.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_SPEED)]));
- capture.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_CAPTURE)]));
- buttonGS.SetWindowText(GetKeyListName(joypad[JOYPAD(which,KEY_BUTTON_GS)]));
+ up.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_UP)]));
+ down.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_DOWN)]));
+ left.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_LEFT)]));
+ right.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_RIGHT)]));
+ buttonA.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_A)]));
+ buttonB.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_B)]));
+ buttonL.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_L)]));
+ buttonR.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_R)]));
+ buttonSelect.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SELECT)]));
+ buttonStart.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_START)]));
+ speed.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SPEED)]));
+ capture.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_CAPTURE)]));
+ buttonGS.SetWindowText(GetKeyListName(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_GS)]));
CenterWindow();
@@ -248,47 +247,47 @@ BOOL JoypadConfig::OnInitDialog()
// EXCEPTION: OCX Property Pages should return FALSE
}
-void JoypadConfig::assignKey(int id, int key)
+void JoypadConfig::assignKey(int id, LONG_PTR key)
{
switch(id) {
case IDC_EDIT_LEFT:
- AssignKey(joypad[JOYPAD(which,KEY_LEFT)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_LEFT)],key);
break;
case IDC_EDIT_RIGHT:
- AssignKey(joypad[JOYPAD(which,KEY_RIGHT)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_RIGHT)],key);
break;
case IDC_EDIT_UP:
- AssignKey(joypad[JOYPAD(which,KEY_UP)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_UP)],key);
break;
case IDC_EDIT_SPEED:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_SPEED)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SPEED)],key);
break;
case IDC_EDIT_CAPTURE:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_CAPTURE)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_CAPTURE)],key);
break;
case IDC_EDIT_DOWN:
- AssignKey(joypad[JOYPAD(which,KEY_DOWN)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_DOWN)],key);
break;
case IDC_EDIT_BUTTON_A:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_A)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_A)],key);
break;
case IDC_EDIT_BUTTON_B:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_B)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_B)],key);
break;
case IDC_EDIT_BUTTON_L:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_L)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_L)],key);
break;
case IDC_EDIT_BUTTON_R:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_R)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_R)],key);
break;
case IDC_EDIT_BUTTON_START:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_START)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_START)],key);
break;
case IDC_EDIT_BUTTON_SELECT:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_SELECT)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_SELECT)],key);
break;
case IDC_EDIT_BUTTON_GS:
- AssignKey(joypad[JOYPAD(which,KEY_BUTTON_GS)],key);
+ AssignKey(theApp.input->joypaddata[JOYPAD(which,KEY_BUTTON_GS)],key);
break;
}
}
@@ -322,15 +321,12 @@ void MotionConfig::DoDataExchange(CDataExchange* pDX)
BEGIN_MESSAGE_MAP(MotionConfig, CDialog)
- //{{AFX_MSG_MAP(MotionConfig)
ON_BN_CLICKED(ID_CANCEL, OnCancel)
ON_BN_CLICKED(ID_OK, OnOk)
- ON_WM_CHAR()
ON_WM_DESTROY()
ON_WM_KEYDOWN()
ON_WM_TIMER()
- //}}AFX_MSG_MAP
- ON_BN_CLICKED(IDC_APPENDMODE, &MotionConfig::OnBnClickedAppendmode)
+ ON_BN_CLICKED(IDC_APPENDMODE, &MotionConfig::OnBnClickedAppendmode)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
@@ -343,16 +339,11 @@ void MotionConfig::OnCancel()
void MotionConfig::OnOk()
{
+ assignKeys();
theApp.input->checkKeys();
EndDialog( TRUE);
}
-void MotionConfig::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
-{
-}
-
-
-
void MotionConfig::OnDestroy()
{
CDialog::OnDestroy();
@@ -360,24 +351,23 @@ void MotionConfig::OnDestroy()
KillTimer(timerId);
}
-
BOOL MotionConfig::OnInitDialog()
{
CDialog::OnInitDialog();
- timerId = SetTimer(0,200,NULL);
+ timerId = SetTimer(0,50,NULL);
- CopyKeys(up.m_Keys, joypad[MOTION(KEY_UP)]);
- up.SetWindowText(GetKeyListName(joypad[MOTION(KEY_UP)]));
+ CopyKeys(up.m_Keys, theApp.input->joypaddata[MOTION(KEY_UP)]);
+ up.SetWindowText(GetKeyListName(theApp.input->joypaddata[MOTION(KEY_UP)]));
- CopyKeys(down.m_Keys, joypad[MOTION(KEY_DOWN)]);
- down.SetWindowText(GetKeyListName(joypad[MOTION(KEY_DOWN)]));
+ CopyKeys(down.m_Keys, theApp.input->joypaddata[MOTION(KEY_DOWN)]);
+ down.SetWindowText(GetKeyListName(theApp.input->joypaddata[MOTION(KEY_DOWN)]));
- CopyKeys(left.m_Keys, joypad[MOTION(KEY_LEFT)]);
- left.SetWindowText(GetKeyListName(joypad[MOTION(KEY_LEFT)]));
+ CopyKeys(left.m_Keys, theApp.input->joypaddata[MOTION(KEY_LEFT)]);
+ left.SetWindowText(GetKeyListName(theApp.input->joypaddata[MOTION(KEY_LEFT)]));
- CopyKeys(right.m_Keys, joypad[MOTION(KEY_RIGHT)]);
- right.SetWindowText(GetKeyListName(joypad[MOTION(KEY_RIGHT)]));
+ CopyKeys(right.m_Keys, theApp.input->joypaddata[MOTION(KEY_RIGHT)]);
+ right.SetWindowText(GetKeyListName(theApp.input->joypaddata[MOTION(KEY_RIGHT)]));
CenterWindow();
@@ -400,16 +390,16 @@ void MotionConfig::assignKey(int id, int key)
{
switch(id) {
case IDC_EDIT_LEFT:
- AssignKey(joypad[MOTION(KEY_LEFT)],key);
+ AssignKey(theApp.input->joypaddata[MOTION(KEY_LEFT)],key);
break;
case IDC_EDIT_RIGHT:
- AssignKey(joypad[MOTION(KEY_RIGHT)],key);
+ AssignKey(theApp.input->joypaddata[MOTION(KEY_RIGHT)],key);
break;
case IDC_EDIT_UP:
- AssignKey(joypad[MOTION(KEY_UP)],key);
+ AssignKey(theApp.input->joypaddata[MOTION(KEY_UP)],key);
break;
case IDC_EDIT_DOWN:
- AssignKey(joypad[MOTION(KEY_DOWN)],key);
+ AssignKey(theApp.input->joypaddata[MOTION(KEY_DOWN)],key);
break;
}
}
@@ -430,13 +420,13 @@ void MotionConfig::assignKeys()
id = IDC_EDIT_RIGHT;
assignKey(id, GetWindowLong(right, GWL_USERDATA));
}
-
-void JoypadConfig::OnBnClickedAppendmode()
-{
- bAppendMode = (::SendMessage(GetDlgItem(IDC_APPENDMODE)->GetSafeHwnd(), BM_GETCHECK, 0, 0L) != 0);
-}
-
-void MotionConfig::OnBnClickedAppendmode()
-{
- bAppendMode = (::SendMessage(GetDlgItem(IDC_APPENDMODE)->GetSafeHwnd(), BM_GETCHECK, 0, 0L) != 0);
-}
+
+void JoypadConfig::OnBnClickedAppendmode()
+{
+ bAppendMode = (::SendMessage(GetDlgItem(IDC_APPENDMODE)->GetSafeHwnd(), BM_GETCHECK, 0, 0L) != 0);
+}
+
+void MotionConfig::OnBnClickedAppendmode()
+{
+ bAppendMode = (::SendMessage(GetDlgItem(IDC_APPENDMODE)->GetSafeHwnd(), BM_GETCHECK, 0, 0L) != 0);
+}
diff --git a/src/win32/Joypad.h b/src/win32/Joypad.h
index 8bff067d..30400956 100644
--- a/src/win32/Joypad.h
+++ b/src/win32/Joypad.h
@@ -1,176 +1,176 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
#include "afxwin.h"
-#if !defined(AFX_JOYPAD_H__FFFB2470_9EEC_4D2D_A5F0_3BF31579999A__INCLUDED_)
-#define AFX_JOYPAD_H__FFFB2470_9EEC_4D2D_A5F0_3BF31579999A__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// Joypad.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// JoypadEditControl window
-
-class JoypadEditControl : public CEdit
-{
- // Construction
-public:
-
- JoypadEditControl();
-
- KeyList m_Keys;
-
- // Attributes
- public:
-
- // Operations
- public:
-
- // Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(JoypadEditControl)
- //}}AFX_VIRTUAL
-
- // Implementation
- public:
- virtual BOOL PreTranslateMessage(MSG *pMsg);
- afx_msg LRESULT OnJoyConfig(WPARAM wParam, LPARAM lParam);
- virtual ~JoypadEditControl();
-
- // Generated message map functions
- protected:
- //{{AFX_MSG(JoypadEditControl)
- afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
- //}}AFX_MSG
-
- DECLARE_MESSAGE_MAP()
- };
-
- /////////////////////////////////////////////////////////////////////////////
-
-/////////////////////////////////////////////////////////////////////////////
-// JoypadConfig dialog
-
-class JoypadConfig : public CDialog
-{
- // Construction
- public:
- void assignKey(int id, int key);
- JoypadConfig(int w, CWnd* pParent = NULL); // standard constructor
-
- // Dialog Data
- //{{AFX_DATA(JoypadConfig)
- enum { IDD = IDD_CONFIG };
- JoypadEditControl up;
- JoypadEditControl speed;
- JoypadEditControl right;
- JoypadEditControl left;
- JoypadEditControl down;
- JoypadEditControl capture;
- JoypadEditControl buttonStart;
- JoypadEditControl buttonSelect;
- JoypadEditControl buttonR;
- JoypadEditControl buttonL;
- JoypadEditControl buttonGS;
- JoypadEditControl buttonB;
- JoypadEditControl buttonA;
-
- //}}AFX_DATA
-
-
- // Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(JoypadConfig)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
- // Implementation
- protected:
- UINT timerId;
- int which;
-
- // Generated message map functions
- //{{AFX_MSG(JoypadConfig)
- afx_msg void OnCancel();
- afx_msg void OnOk();
- afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
- afx_msg void OnDestroy();
- afx_msg void OnTimer(UINT nIDEvent);
- afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
- virtual BOOL OnInitDialog();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
+#if !defined(AFX_JOYPAD_H__FFFB2470_9EEC_4D2D_A5F0_3BF31579999A__INCLUDED_)
+#define AFX_JOYPAD_H__FFFB2470_9EEC_4D2D_A5F0_3BF31579999A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// Joypad.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// JoypadEditControl window
+
+class JoypadEditControl : public CEdit
+{
+ // Construction
+public:
+
+ JoypadEditControl();
+
+ KeyList m_Keys;
+
+ // Attributes
+ public:
+
+ // Operations
+ public:
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(JoypadEditControl)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+ public:
+ virtual BOOL PreTranslateMessage(MSG *pMsg);
+ afx_msg LRESULT OnJoyConfig(WPARAM wParam, LPARAM lParam);
+ virtual ~JoypadEditControl();
+
+ // Generated message map functions
+ protected:
+ //{{AFX_MSG(JoypadEditControl)
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// JoypadConfig dialog
+
+class JoypadConfig : public CDialog
+{
+ // Construction
+ public:
+ void assignKey(int id, LONG_PTR key);
+ JoypadConfig(int w, CWnd* pParent = NULL); // standard constructor
+
+ // Dialog Data
+ //{{AFX_DATA(JoypadConfig)
+ enum { IDD = IDD_CONFIG };
+ JoypadEditControl up;
+ JoypadEditControl speed;
+ JoypadEditControl right;
+ JoypadEditControl left;
+ JoypadEditControl down;
+ JoypadEditControl capture;
+ JoypadEditControl buttonStart;
+ JoypadEditControl buttonSelect;
+ JoypadEditControl buttonR;
+ JoypadEditControl buttonL;
+ JoypadEditControl buttonGS;
+ JoypadEditControl buttonB;
+ JoypadEditControl buttonA;
+
+ //}}AFX_DATA
+
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(JoypadConfig)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ // Implementation
+ protected:
+ UINT timerId;
+ int which;
+
+ // Generated message map functions
+ //{{AFX_MSG(JoypadConfig)
+ afx_msg void OnCancel();
+ afx_msg void OnOk();
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnDestroy();
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedAppendmode();
-};
- /////////////////////////////////////////////////////////////////////////////
-// MotionConfig dialog
-
-class MotionConfig : public CDialog
-{
- // Construction
- public:
- void assignKeys();
- void assignKey(int id, int key);
- MotionConfig(CWnd* pParent = NULL); // standard constructor
-
- // Dialog Data
- //{{AFX_DATA(MotionConfig)
- enum { IDD = IDD_MOTION_CONFIG };
- JoypadEditControl up;
- JoypadEditControl right;
- JoypadEditControl left;
- JoypadEditControl down;
- //}}AFX_DATA
-
-
- // Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(MotionConfig)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
- // Implementation
- protected:
-
- // Generated message map functions
- //{{AFX_MSG(MotionConfig)
- afx_msg void OnCancel();
- afx_msg void OnOk();
- afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
- afx_msg void OnDestroy();
- virtual BOOL OnInitDialog();
- afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
- afx_msg void OnTimer(UINT nIDEvent);
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
- private:
- UINT timerId;
+};
+ /////////////////////////////////////////////////////////////////////////////
+// MotionConfig dialog
+
+class MotionConfig : public CDialog
+{
+ // Construction
+ public:
+ void assignKeys();
+ void assignKey(int id, int key);
+ MotionConfig(CWnd* pParent = NULL); // standard constructor
+
+ // Dialog Data
+ //{{AFX_DATA(MotionConfig)
+ enum { IDD = IDD_MOTION_CONFIG };
+ JoypadEditControl up;
+ JoypadEditControl right;
+ JoypadEditControl left;
+ JoypadEditControl down;
+ //}}AFX_DATA
+
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(MotionConfig)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ // Implementation
+ protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(MotionConfig)
+ afx_msg void OnCancel();
+ afx_msg void OnOk();
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnDestroy();
+ virtual BOOL OnInitDialog();
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnTimer(UINT nIDEvent);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+ private:
+ UINT timerId;
public:
afx_msg void OnBnClickedAppendmode();
-};
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_JOYPAD_H__FFFB2470_9EEC_4D2D_A5F0_3BF31579999A__INCLUDED_)
+};
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_JOYPAD_H__FFFB2470_9EEC_4D2D_A5F0_3BF31579999A__INCLUDED_)
diff --git a/src/win32/Logging.cpp b/src/win32/Logging.cpp
index 697b6d42..2739d573 100644
--- a/src/win32/Logging.cpp
+++ b/src/win32/Logging.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -225,7 +225,7 @@ BOOL Logging::OnInitDialog()
m_dma2 = (systemVerbose & 64) != 0;
m_dma3 = (systemVerbose & 128) != 0;
m_undefined = (systemVerbose & 256) != 0;
- m_agbprint = (systemVerbose & 256) != 0;
+ m_agbprint = (systemVerbose & 512) != 0;
UpdateData(FALSE);
m_log.LimitText(-1);
@@ -237,7 +237,7 @@ BOOL Logging::OnInitDialog()
void Logging::log(const char *s)
{
- int size = ::SendMessage(m_log, WM_GETTEXTLENGTH, 0, 0);
+ DWORD size = (DWORD)::SendMessage(m_log, WM_GETTEXTLENGTH, 0, 0);
m_log.SetSel(size, size);
m_log.ReplaceSel(s);
}
diff --git a/src/win32/MainWnd.cpp b/src/win32/MainWnd.cpp
index 227576f9..195c2622 100644
--- a/src/win32/MainWnd.cpp
+++ b/src/win32/MainWnd.cpp
@@ -1,1137 +1,1314 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-// MainWnd.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "VBA.h"
-#include "MainWnd.h"
-
-#include
-
-#include "FileDlg.h"
-#include "Reg.h"
-#include "WinResUtil.h"
-
-#include "../System.h"
-#include "../cheatSearch.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../Flash.h"
-#include "../Globals.h"
-#include "../gb/GB.h"
-#include "../gb/gbCheats.h"
-#include "../gb/gbGlobals.h"
-#include "../RTC.h"
-#include "../Sound.h"
-#include "../Util.h"
-#include ".\mainwnd.h"
-
-#include "../Link.h" // Link
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#define VBA_CONFIRM_MODE WM_APP + 100
-
-extern void remoteCleanUp();
-
-/////////////////////////////////////////////////////////////////////////////
-// MainWnd
-
-MainWnd::MainWnd()
-{
- m_hAccelTable = NULL;
- arrow = LoadCursor(NULL, IDC_ARROW);
-}
-
-MainWnd::~MainWnd()
-{
-}
-
-
-BEGIN_MESSAGE_MAP(MainWnd, CWnd)
- //{{AFX_MSG_MAP(MainWnd)
- ON_WM_CLOSE()
- ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
- ON_COMMAND(ID_HELP_FAQ, OnHelpFaq)
- ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
- ON_WM_INITMENUPOPUP()
- ON_COMMAND(ID_FILE_PAUSE, OnFilePause)
- ON_UPDATE_COMMAND_UI(ID_FILE_PAUSE, OnUpdateFilePause)
- ON_COMMAND(ID_FILE_RESET, OnFileReset)
- ON_UPDATE_COMMAND_UI(ID_FILE_RESET, OnUpdateFileReset)
- ON_UPDATE_COMMAND_UI(ID_FILE_RECENT_FREEZE, OnUpdateFileRecentFreeze)
- ON_COMMAND(ID_FILE_RECENT_RESET, OnFileRecentReset)
- ON_COMMAND(ID_FILE_RECENT_FREEZE, OnFileRecentFreeze)
- ON_COMMAND(ID_FILE_EXIT, OnFileExit)
- ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
- ON_UPDATE_COMMAND_UI(ID_FILE_CLOSE, OnUpdateFileClose)
- ON_COMMAND(ID_FILE_OPENGAMEBOY, OnFileOpengameboy)
- ON_COMMAND(ID_FILE_LOAD, OnFileLoad)
- ON_UPDATE_COMMAND_UI(ID_FILE_LOAD, OnUpdateFileLoad)
- ON_COMMAND(ID_FILE_SAVE, OnFileSave)
- ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
- ON_COMMAND(ID_FILE_IMPORT_BATTERYFILE, OnFileImportBatteryfile)
- ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT_BATTERYFILE, OnUpdateFileImportBatteryfile)
- ON_COMMAND(ID_FILE_IMPORT_GAMESHARKCODEFILE, OnFileImportGamesharkcodefile)
- ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT_GAMESHARKCODEFILE, OnUpdateFileImportGamesharkcodefile)
- ON_COMMAND(ID_FILE_IMPORT_GAMESHARKSNAPSHOT, OnFileImportGamesharksnapshot)
- ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT_GAMESHARKSNAPSHOT, OnUpdateFileImportGamesharksnapshot)
- ON_COMMAND(ID_FILE_EXPORT_BATTERYFILE, OnFileExportBatteryfile)
- ON_UPDATE_COMMAND_UI(ID_FILE_EXPORT_BATTERYFILE, OnUpdateFileExportBatteryfile)
- ON_COMMAND(ID_FILE_EXPORT_GAMESHARKSNAPSHOT, OnFileExportGamesharksnapshot)
- ON_UPDATE_COMMAND_UI(ID_FILE_EXPORT_GAMESHARKSNAPSHOT, OnUpdateFileExportGamesharksnapshot)
- ON_COMMAND(ID_FILE_SCREENCAPTURE, OnFileScreencapture)
- ON_UPDATE_COMMAND_UI(ID_FILE_SCREENCAPTURE, OnUpdateFileScreencapture)
- ON_COMMAND(ID_FILE_ROMINFORMATION, OnFileRominformation)
- ON_UPDATE_COMMAND_UI(ID_FILE_ROMINFORMATION, OnUpdateFileRominformation)
- ON_COMMAND(ID_FILE_TOGGLEMENU, OnFileTogglemenu)
- ON_UPDATE_COMMAND_UI(ID_FILE_TOGGLEMENU, OnUpdateFileTogglemenu)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE, OnUpdateOptionsFrameskipThrottleNothrottle)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_25, OnUpdateOptionsFrameskipThrottle25)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_50, OnUpdateOptionsFrameskipThrottle50)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_100, OnUpdateOptionsFrameskipThrottle100)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_150, OnUpdateOptionsFrameskipThrottle150)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_200, OnUpdateOptionsFrameskipThrottle200)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER, OnUpdateOptionsFrameskipThrottleOther)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE, OnOptionsFrameskipThrottleNothrottle)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_25, OnOptionsFrameskipThrottle25)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_50, OnOptionsFrameskipThrottle50)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_100, OnOptionsFrameskipThrottle100)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_150, OnOptionsFrameskipThrottle150)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_200, OnOptionsFrameskipThrottle200)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER, OnOptionsFrameskipThrottleOther)
- ON_COMMAND(ID_OPTIONS_FRAMESKIP_AUTOMATIC, OnOptionsFrameskipAutomatic)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_AUTOMATIC, OnUpdateOptionsFrameskipAutomatic)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_0, OnUpdateOptionsVideoFrameskip0)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_1, OnUpdateOptionsVideoFrameskip1)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_2, OnUpdateOptionsVideoFrameskip2)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_3, OnUpdateOptionsVideoFrameskip3)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_4, OnUpdateOptionsVideoFrameskip4)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_5, OnUpdateOptionsVideoFrameskip5)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_6, OnUpdateOptionsVideoFrameskip6)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_7, OnUpdateOptionsVideoFrameskip7)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_8, OnUpdateOptionsVideoFrameskip8)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_9, OnUpdateOptionsVideoFrameskip9)
- ON_COMMAND(ID_OPTIONS_VIDEO_VSYNC, OnOptionsVideoVsync)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_VSYNC, OnUpdateOptionsVideoVsync)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X1, OnUpdateOptionsVideoX1)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X2, OnUpdateOptionsVideoX2)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X3, OnUpdateOptionsVideoX3)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X4, OnUpdateOptionsVideoX4)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN320X240, OnUpdateOptionsVideoFullscreen320x240)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN640X480, OnUpdateOptionsVideoFullscreen640x480)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN800X600, OnUpdateOptionsVideoFullscreen800x600)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN320X240, OnOptionsVideoFullscreen320x240)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN640X480, OnOptionsVideoFullscreen640x480)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN800X600, OnOptionsVideoFullscreen800x600)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN, OnOptionsVideoFullscreen)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN, OnUpdateOptionsVideoFullscreen)
- ON_WM_MOVE()
- ON_WM_SIZE()
- ON_COMMAND(ID_OPTIONS_VIDEO_DISABLESFX, OnOptionsVideoDisablesfx)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_DISABLESFX, OnUpdateOptionsVideoDisablesfx)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREENSTRETCHTOFIT, OnOptionsVideoFullscreenstretchtofit)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREENSTRETCHTOFIT, OnUpdateOptionsVideoFullscreenstretchtofit)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_GDI, OnOptionsVideoRendermethodGdi)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_GDI, OnUpdateOptionsVideoRendermethodGdi)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW, OnOptionsVideoRendermethodDirectdraw)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW, OnUpdateOptionsVideoRendermethodDirectdraw)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D, OnOptionsVideoRendermethodDirect3d)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D, OnUpdateOptionsVideoRendermethodDirect3d)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL, OnOptionsVideoRendermethodOpengl)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL, OnUpdateOptionsVideoRendermethodOpengl)
- ON_COMMAND(ID_OPTIONS_VIDEO_TRIPLEBUFFERING, OnOptionsVideoTriplebuffering)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_TRIPLEBUFFERING, OnUpdateOptionsVideoTriplebuffering)
- ON_COMMAND(ID_OPTIONS_VIDEO_DDRAWEMULATIONONLY, OnOptionsVideoDdrawemulationonly)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_DDRAWEMULATIONONLY, OnUpdateOptionsVideoDdrawemulationonly)
- ON_COMMAND(ID_OPTIONS_VIDEO_DDRAWUSEVIDEOMEMORY, OnOptionsVideoDdrawusevideomemory)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_DDRAWUSEVIDEOMEMORY, OnUpdateOptionsVideoDdrawusevideomemory)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DNOFILTER, OnOptionsVideoRenderoptionsD3dnofilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DNOFILTER, OnUpdateOptionsVideoRenderoptionsD3dnofilter)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DBILINEAR, OnOptionsVideoRenderoptionsD3dbilinear)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DBILINEAR, OnUpdateOptionsVideoRenderoptionsD3dbilinear)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLNEAREST, OnOptionsVideoRenderoptionsGlnearest)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLNEAREST, OnUpdateOptionsVideoRenderoptionsGlnearest)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLBILINEAR, OnOptionsVideoRenderoptionsGlbilinear)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLBILINEAR, OnUpdateOptionsVideoRenderoptionsGlbilinear)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE, OnOptionsVideoRenderoptionsGltriangle)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE, OnUpdateOptionsVideoRenderoptionsGltriangle)
- ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS, OnOptionsVideoRenderoptionsGlquads)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS, OnUpdateOptionsVideoRenderoptionsGlquads)
- ON_WM_CONTEXTMENU()
- ON_COMMAND(ID_OPTIONS_EMULATOR_ASSOCIATE, OnOptionsEmulatorAssociate)
- ON_COMMAND(ID_OPTIONS_EMULATOR_DIRECTORIES, OnOptionsEmulatorDirectories)
- ON_COMMAND(ID_OPTIONS_EMULATOR_DISABLESTATUSMESSAGES, OnOptionsEmulatorDisablestatusmessages)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_DISABLESTATUSMESSAGES, OnUpdateOptionsEmulatorDisablestatusmessages)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SYNCHRONIZE, OnOptionsEmulatorSynchronize)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SYNCHRONIZE, OnUpdateOptionsEmulatorSynchronize)
- ON_COMMAND(ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE, OnOptionsEmulatorPausewheninactive)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE, OnUpdateOptionsEmulatorPausewheninactive)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE, OnOptionsEmulatorSpeeduptoggle)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE, OnUpdateOptionsEmulatorSpeeduptoggle)
- ON_COMMAND(ID_OPTIONS_EMULATOR_REMOVEINTROSGBA, OnOptionsEmulatorRemoveintrosgba)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_REMOVEINTROSGBA, OnUpdateOptionsEmulatorRemoveintrosgba)
- ON_COMMAND(ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH, OnOptionsEmulatorAutomaticallyipspatch)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH, OnUpdateOptionsEmulatorAutomaticallyipspatch)
- ON_COMMAND(ID_OPTIONS_EMULATOR_AGBPRINT, OnOptionsEmulatorAgbprint)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AGBPRINT, OnUpdateOptionsEmulatorAgbprint)
- ON_COMMAND(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnOptionsEmulatorRealtimeclock)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnUpdateOptionsEmulatorRealtimeclock)
- ON_COMMAND(ID_OPTIONS_EMULATOR_AUTOHIDEMENU, OnOptionsEmulatorAutohidemenu)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOHIDEMENU, OnUpdateOptionsEmulatorAutohidemenu)
- ON_COMMAND(ID_OPTIONS_EMULATOR_REWINDINTERVAL, OnOptionsEmulatorRewindinterval)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC, OnOptionsEmulatorSavetypeAutomatic)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC, OnUpdateOptionsEmulatorSavetypeAutomatic)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM, OnOptionsEmulatorSavetypeEeprom)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM, OnUpdateOptionsEmulatorSavetypeEeprom)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_SRAM, OnOptionsEmulatorSavetypeSram)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_SRAM, OnUpdateOptionsEmulatorSavetypeSram)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH, OnOptionsEmulatorSavetypeFlash)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH, OnUpdateOptionsEmulatorSavetypeFlash)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR, OnOptionsEmulatorSavetypeEepromsensor)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR, OnUpdateOptionsEmulatorSavetypeEepromsensor)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_NONE, OnOptionsEmulatorSavetypeNone)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_NONE, OnUpdateOptionsEmulatorSavetypeNone)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K, OnOptionsEmulatorSavetypeFlash512k)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K, OnUpdateOptionsEmulatorSavetypeFlash512k)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M, OnOptionsEmulatorSavetypeFlash1m)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M, OnUpdateOptionsEmulatorSavetypeFlash1m)
- ON_COMMAND(ID_OPTIONS_EMULATOR_USEBIOSFILE, OnOptionsEmulatorUsebiosfile)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_USEBIOSFILE, OnUpdateOptionsEmulatorUsebiosfile)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SKIPBIOS, OnOptionsEmulatorSkipbios)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SKIPBIOS, OnUpdateOptionsEmulatorSkipbios)
- ON_COMMAND(ID_OPTIONS_EMULATOR_SELECTBIOSFILE, OnOptionsEmulatorSelectbiosfile)
- ON_COMMAND(ID_OPTIONS_EMULATOR_PNGFORMAT, OnOptionsEmulatorPngformat)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_PNGFORMAT, OnUpdateOptionsEmulatorPngformat)
- ON_COMMAND(ID_OPTIONS_EMULATOR_BMPFORMAT, OnOptionsEmulatorBmpformat)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_BMPFORMAT, OnUpdateOptionsEmulatorBmpformat)
-// ON_COMMAND(ID_OPTIONS_SOUND_OFF, OnOptionsSoundOff) /* mute hax */
-// ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_OFF, OnUpdateOptionsSoundOff) /* mute hax */
- ON_COMMAND(ID_OPTIONS_SOUND_OFF, OnOptionsSoundMute) /* mute hax */
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_OFF, OnUpdateOptionsSoundMute) /* mute hax */
- ON_COMMAND(ID_OPTIONS_SOUND_ON, OnOptionsSoundOn)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_ON, OnUpdateOptionsSoundOn)
- ON_COMMAND(ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION, OnOptionsSoundUseoldsynchronization)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION, OnUpdateOptionsSoundUseoldsynchronization)
- ON_COMMAND(ID_OPTIONS_SOUND_ECHO, OnOptionsSoundEcho)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_ECHO, OnUpdateOptionsSoundEcho)
- ON_COMMAND(ID_OPTIONS_SOUND_LOWPASSFILTER, OnOptionsSoundLowpassfilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_LOWPASSFILTER, OnUpdateOptionsSoundLowpassfilter)
- ON_COMMAND(ID_OPTIONS_SOUND_REVERSESTEREO, OnOptionsSoundReversestereo)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_REVERSESTEREO, OnUpdateOptionsSoundReversestereo)
- ON_COMMAND(ID_OPTIONS_SOUND_11KHZ, OnOptionsSound11khz)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_11KHZ, OnUpdateOptionsSound11khz)
- ON_COMMAND(ID_OPTIONS_SOUND_22KHZ, OnOptionsSound22khz)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_22KHZ, OnUpdateOptionsSound22khz)
- ON_COMMAND(ID_OPTIONS_SOUND_44KHZ, OnOptionsSound44khz)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_44KHZ, OnUpdateOptionsSound44khz)
- ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL1, OnOptionsSoundChannel1)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL1, OnUpdateOptionsSoundChannel1)
- ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL2, OnOptionsSoundChannel2)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL2, OnUpdateOptionsSoundChannel2)
- ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL3, OnOptionsSoundChannel3)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL3, OnUpdateOptionsSoundChannel3)
- ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL4, OnOptionsSoundChannel4)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL4, OnUpdateOptionsSoundChannel4)
- ON_COMMAND(ID_OPTIONS_SOUND_DIRECTSOUNDA, OnOptionsSoundDirectsounda)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_DIRECTSOUNDA, OnUpdateOptionsSoundDirectsounda)
- ON_COMMAND(ID_OPTIONS_SOUND_DIRECTSOUNDB, OnOptionsSoundDirectsoundb)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_DIRECTSOUNDB, OnUpdateOptionsSoundDirectsoundb)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_BORDER, OnOptionsGameboyBorder)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_BORDER, OnUpdateOptionsGameboyBorder)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_PRINTER, OnOptionsGameboyPrinter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_PRINTER, OnUpdateOptionsGameboyPrinter)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC, OnOptionsGameboyBorderAutomatic)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC, OnUpdateOptionsGameboyBorderAutomatic)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_AUTOMATIC, OnOptionsGameboyAutomatic)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_AUTOMATIC, OnUpdateOptionsGameboyAutomatic)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_GBA, OnOptionsGameboyGba)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_GBA, OnUpdateOptionsGameboyGba)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_CGB, OnOptionsGameboyCgb)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_CGB, OnUpdateOptionsGameboyCgb)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_SGB, OnOptionsGameboySgb)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_SGB, OnUpdateOptionsGameboySgb)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_SGB2, OnOptionsGameboySgb2)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_SGB2, OnUpdateOptionsGameboySgb2)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_GB, OnOptionsGameboyGb)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_GB, OnUpdateOptionsGameboyGb)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_REALCOLORS, OnOptionsGameboyRealcolors)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_REALCOLORS, OnUpdateOptionsGameboyRealcolors)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS, OnOptionsGameboyGameboycolors)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS, OnUpdateOptionsGameboyGameboycolors)
- ON_COMMAND(ID_OPTIONS_GAMEBOY_COLORS, OnOptionsGameboyColors)
- ON_COMMAND(ID_OPTIONS_FILTER_DISABLEMMX, OnOptionsFilterDisablemmx)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_DISABLEMMX, OnUpdateOptionsFilterDisablemmx)
- ON_COMMAND(ID_OPTIONS_LANGUAGE_SYSTEM, OnOptionsLanguageSystem)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_LANGUAGE_SYSTEM, OnUpdateOptionsLanguageSystem)
- ON_COMMAND(ID_OPTIONS_LANGUAGE_ENGLISH, OnOptionsLanguageEnglish)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_LANGUAGE_ENGLISH, OnUpdateOptionsLanguageEnglish)
- ON_COMMAND(ID_OPTIONS_LANGUAGE_OTHER, OnOptionsLanguageOther)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_LANGUAGE_OTHER, OnUpdateOptionsLanguageOther)
- ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_1, OnOptionsJoypadConfigure1)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_1, OnUpdateOptionsJoypadConfigure1)
- ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_2, OnOptionsJoypadConfigure2)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_2, OnUpdateOptionsJoypadConfigure2)
- ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_3, OnOptionsJoypadConfigure3)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_3, OnUpdateOptionsJoypadConfigure3)
- ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_4, OnOptionsJoypadConfigure4)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_4, OnUpdateOptionsJoypadConfigure4)
- ON_COMMAND(ID_OPTIONS_JOYPAD_MOTIONCONFIGURE, OnOptionsJoypadMotionconfigure)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_MOTIONCONFIGURE, OnUpdateOptionsJoypadMotionconfigure)
- ON_COMMAND(ID_CHEATS_SEARCHFORCHEATS, OnCheatsSearchforcheats)
- ON_UPDATE_COMMAND_UI(ID_CHEATS_SEARCHFORCHEATS, OnUpdateCheatsSearchforcheats)
- ON_COMMAND(ID_CHEATS_CHEATLIST, OnCheatsCheatlist)
- ON_UPDATE_COMMAND_UI(ID_CHEATS_CHEATLIST, OnUpdateCheatsCheatlist)
- ON_COMMAND(ID_CHEATS_AUTOMATICSAVELOADCHEATS, OnCheatsAutomaticsaveloadcheats)
- ON_COMMAND(ID_CHEATS_LOADCHEATLIST, OnCheatsLoadcheatlist)
- ON_UPDATE_COMMAND_UI(ID_CHEATS_LOADCHEATLIST, OnUpdateCheatsLoadcheatlist)
- ON_COMMAND(ID_CHEATS_SAVECHEATLIST, OnCheatsSavecheatlist)
- ON_UPDATE_COMMAND_UI(ID_CHEATS_SAVECHEATLIST, OnUpdateCheatsSavecheatlist)
- ON_COMMAND(ID_TOOLS_DISASSEMBLE, OnToolsDisassemble)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_DISASSEMBLE, OnUpdateToolsDisassemble)
- ON_COMMAND(ID_TOOLS_LOGGING, OnToolsLogging)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_LOGGING, OnUpdateToolsLogging)
- ON_COMMAND(ID_TOOLS_IOVIEWER, OnToolsIoviewer)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_IOVIEWER, OnUpdateToolsIoviewer)
- ON_COMMAND(ID_TOOLS_MAPVIEW, OnToolsMapview)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_MAPVIEW, OnUpdateToolsMapview)
- ON_COMMAND(ID_TOOLS_MEMORYVIEWER, OnToolsMemoryviewer)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_MEMORYVIEWER, OnUpdateToolsMemoryviewer)
- ON_COMMAND(ID_TOOLS_OAMVIEWER, OnToolsOamviewer)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_OAMVIEWER, OnUpdateToolsOamviewer)
- ON_COMMAND(ID_TOOLS_PALETTEVIEW, OnToolsPaletteview)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_PALETTEVIEW, OnUpdateToolsPaletteview)
- ON_COMMAND(ID_TOOLS_TILEVIEWER, OnToolsTileviewer)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_TILEVIEWER, OnUpdateToolsTileviewer)
- ON_COMMAND(ID_DEBUG_NEXTFRAME, OnDebugNextframe)
- ON_UPDATE_COMMAND_UI(ID_CHEATS_AUTOMATICSAVELOADCHEATS, OnUpdateCheatsAutomaticsaveloadcheats)
- ON_COMMAND(ID_TOOLS_DEBUG_GDB, OnToolsDebugGdb)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_GDB, OnUpdateToolsDebugGdb)
- ON_COMMAND(ID_TOOLS_DEBUG_LOADANDWAIT, OnToolsDebugLoadandwait)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_LOADANDWAIT, OnUpdateToolsDebugLoadandwait)
- ON_COMMAND(ID_TOOLS_DEBUG_BREAK, OnToolsDebugBreak)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_BREAK, OnUpdateToolsDebugBreak)
- ON_COMMAND(ID_TOOLS_DEBUG_DISCONNECT, OnToolsDebugDisconnect)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_DISCONNECT, OnUpdateToolsDebugDisconnect)
- ON_COMMAND(ID_OPTIONS_SOUND_STARTRECORDING, OnOptionsSoundStartrecording)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_STARTRECORDING, OnUpdateOptionsSoundStartrecording)
- ON_COMMAND(ID_OPTIONS_SOUND_STOPRECORDING, OnOptionsSoundStoprecording)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_STOPRECORDING, OnUpdateOptionsSoundStoprecording)
- ON_COMMAND(ID_TOOLS_RECORD_STARTAVIRECORDING, OnToolsRecordStartavirecording)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STARTAVIRECORDING, OnUpdateToolsRecordStartavirecording)
- ON_COMMAND(ID_TOOLS_RECORD_STOPAVIRECORDING, OnToolsRecordStopavirecording)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STOPAVIRECORDING, OnUpdateToolsRecordStopavirecording)
- ON_WM_PAINT()
- ON_COMMAND(ID_TOOLS_RECORD_STARTMOVIERECORDING, OnToolsRecordStartmovierecording)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STARTMOVIERECORDING, OnUpdateToolsRecordStartmovierecording)
- ON_COMMAND(ID_TOOLS_RECORD_STOPMOVIERECORDING, OnToolsRecordStopmovierecording)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STOPMOVIERECORDING, OnUpdateToolsRecordStopmovierecording)
- ON_COMMAND(ID_TOOLS_PLAY_STARTMOVIEPLAYING, OnToolsPlayStartmovieplaying)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_PLAY_STARTMOVIEPLAYING, OnUpdateToolsPlayStartmovieplaying)
- ON_COMMAND(ID_TOOLS_PLAY_STOPMOVIEPLAYING, OnToolsPlayStopmovieplaying)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_PLAY_STOPMOVIEPLAYING, OnUpdateToolsPlayStopmovieplaying)
- ON_COMMAND(ID_TOOLS_REWIND, OnToolsRewind)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_REWIND, OnUpdateToolsRewind)
- ON_COMMAND(ID_TOOLS_CUSTOMIZE, OnToolsCustomize)
- ON_UPDATE_COMMAND_UI(ID_TOOLS_CUSTOMIZE, OnUpdateToolsCustomize)
- ON_COMMAND(ID_HELP_BUGREPORT, OnHelpBugreport)
- ON_WM_MOUSEMOVE()
- ON_WM_INITMENU()
- ON_WM_ACTIVATE()
- ON_WM_ACTIVATEAPP()
- ON_WM_DROPFILES()
- ON_COMMAND(ID_FILE_SAVEGAME_OLDESTSLOT, OnFileSavegameOldestslot)
- ON_UPDATE_COMMAND_UI(ID_FILE_SAVEGAME_OLDESTSLOT, OnUpdateFileSavegameOldestslot)
- ON_COMMAND(ID_FILE_LOADGAME_MOSTRECENT, OnFileLoadgameMostrecent)
- ON_UPDATE_COMMAND_UI(ID_FILE_LOADGAME_MOSTRECENT, OnUpdateFileLoadgameMostrecent)
- ON_COMMAND(ID_FILE_LOADGAME_AUTOLOADMOSTRECENT, OnFileLoadgameAutoloadmostrecent)
- ON_UPDATE_COMMAND_UI(ID_FILE_LOADGAME_AUTOLOADMOSTRECENT, OnUpdateFileLoadgameAutoloadmostrecent)
- ON_COMMAND(ID_OPTIONS_SOUND_VOLUME_25X, OnOptionsSoundVolume25x)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_VOLUME_25X, OnUpdateOptionsSoundVolume25x)
- ON_COMMAND(ID_OPTIONS_SOUND_VOLUME_5X, OnOptionsSoundVolume5x)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_VOLUME_5X, OnUpdateOptionsSoundVolume5x)
- ON_COMMAND(ID_CHEATS_DISABLECHEATS, OnCheatsDisablecheats)
- ON_UPDATE_COMMAND_UI(ID_CHEATS_DISABLECHEATS, OnUpdateCheatsDisablecheats)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREENMAXSCALE, OnOptionsVideoFullscreenmaxscale)
-
- ON_COMMAND(ID_OPTIONS_LINK_OPTIONS, OnLinkOptions)
- ON_COMMAND(ID_OPTIONS_LINK_LOG, OnOptionsLinkLog)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_LINK_LOG, OnUpdateOptionsLinkLog)
- ON_COMMAND(ID_OPTIONS_LINK_WIRELESSADAPTER, OnOptionsLinkRFU)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_LINK_WIRELESSADAPTER, OnUpdateOptionsLinkRFU)
- //}}AFX_MSG_MAP
- ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE10, OnFileRecentFile)
- ON_COMMAND_EX_RANGE(ID_FILE_LOADGAME_SLOT1, ID_FILE_LOADGAME_SLOT10, OnFileLoadSlot)
- ON_COMMAND_EX_RANGE(ID_FILE_SAVEGAME_SLOT1, ID_FILE_SAVEGAME_SLOT10, OnFileSaveSlot)
- ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_LOADGAME_SLOT1, ID_FILE_LOADGAME_SLOT10, OnUpdateFileLoadGameSlot)
- ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_SAVEGAME_SLOT1, ID_FILE_SAVEGAME_SLOT10, OnUpdateFileSaveGameSlot)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_FRAMESKIP_0, ID_OPTIONS_VIDEO_FRAMESKIP_5, OnOptionsFrameskip)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_FRAMESKIP_6, ID_OPTIONS_VIDEO_FRAMESKIP_9, OnOptionsFrameskip)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_X1, ID_OPTIONS_VIDEO_X4, OnOptionVideoSize)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_LAYERS_BG0, ID_OPTIONS_VIDEO_LAYERS_OBJWIN, OnVideoLayer)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_VIDEO_LAYERS_BG0, ID_OPTIONS_VIDEO_LAYERS_OBJWIN, OnUpdateVideoLayer)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_EMULATOR_SHOWSPEED_NONE, ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT, OnOptionsEmulatorShowSpeed)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_EMULATOR_SHOWSPEED_NONE, ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT, OnUpdateOptionsEmulatorShowSpeed)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_SOUND_VOLUME_1X, ID_OPTIONS_SOUND_VOLUME_4X, OnOptionsSoundVolume)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_SOUND_VOLUME_1X, ID_OPTIONS_SOUND_VOLUME_4X, OnUpdateOptionsSoundVolume)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_PRIORITY_HIGHEST, ID_OPTIONS_PRIORITY_BELOWNORMAL, OnOptionsPriority)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_PRIORITY_HIGHEST, ID_OPTIONS_PRIORITY_BELOWNORMAL, OnUpdateOptionsPriority)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_NORMAL, ID_OPTIONS_FILTER_TVMODE, OnOptionsFilter)
- ON_COMMAND_EX(ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL, OnOptionsFilter)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X, ID_OPTIONS_FILTER16BIT_SIMPLE2X, OnOptionsFilter)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_BILINEAR, ID_OPTIONS_FILTER_BILINEARPLUS, OnOptionsFilter)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_SCANLINES, ID_OPTIONS_FILTER_SCANLINES, OnOptionsFilter)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_HQ2X, ID_OPTIONS_FILTER_LQ2X, OnOptionsFilter)
- ON_COMMAND_EX(ID_OPTIONS_FILTER_HQ3X, OnOptionsFilter)
- ON_COMMAND_EX(ID_OPTIONS_FILTER_HQ4X, OnOptionsFilter)
- ON_COMMAND_EX(ID_OPTIONS_FILTER_SIMPLE3X, OnOptionsFilter)
- ON_COMMAND_EX(ID_OPTIONS_FILTER_SIMPLE4X, OnOptionsFilter)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_NORMAL, ID_OPTIONS_FILTER_TVMODE, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X, ID_OPTIONS_FILTER16BIT_SIMPLE2X, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_BILINEAR, ID_OPTIONS_FILTER_BILINEARPLUS, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_SCANLINES, ID_OPTIONS_FILTER_SCANLINES, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_HQ2X, ID_OPTIONS_FILTER_LQ2X, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_SIMPLE3X, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_SIMPLE4X, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_HQ3X, OnUpdateOptionsFilter)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_HQ4X, OnUpdateOptionsFilter)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE, ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART, OnOptionsFilterIFB)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE, ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART, OnUpdateOptionsFilterIFB)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1, ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4, OnOptionsJoypadDefault)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1, ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4, OnUpdateOptionsJoypadDefault)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_JOYPAD_AUTOFIRE_A, ID_OPTIONS_JOYPAD_AUTOFIRE_R, OnOptionsJoypadAutofire)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_JOYPAD_AUTOFIRE_A, ID_OPTIONS_JOYPAD_AUTOFIRE_R, OnUpdateOptionsJoypadAutofire)
- ON_MESSAGE(VBA_CONFIRM_MODE, OnConfirmMode)
- ON_MESSAGE(WM_SYSCOMMAND, OnMySysCommand)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN1280X1024, OnOptionsVideoFullscreen1280x1024)
- ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN1024X768, OnOptionsVideoFullscreen1024x768)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN1024X768, OnUpdateOptionsVideoFullscreen1024x768)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN1280X1024, OnUpdateOptionsVideoFullscreen1280x1024)
- ON_COMMAND(ID_OPTIONS_FILTER_LCDCOLORS, OnOptionsFilterLcdcolors)
- ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_LCDCOLORS, OnUpdateOptionsFilterLcdcolors)
- ON_COMMAND_EX_RANGE(ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE, ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE, OnOptionsSoundPcminterpolation)
- ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE, ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE, OnUpdateOptionsSoundPcminterpolation)
- ON_WM_SETFOCUS()
- ON_WM_KILLFOCUS()
- END_MESSAGE_MAP()
-
-
- /////////////////////////////////////////////////////////////////////////////
-// MainWnd message handlers
-
-void MainWnd::OnClose()
-{
- CWnd::OnClose();
-
- delete this;
-}
-
-bool MainWnd::FileRun()
-{
- // save battery file before we change the filename...
- if(rom != NULL || gbRom != NULL) {
- if(theApp.autoSaveLoadCheatList)
- winSaveCheatListDefault();
- writeBatteryFile();
- cheatSearchCleanup(&cheatSearchData);
- theApp.emulator.emuCleanUp();
- remoteCleanUp();
- emulating = false;
-#ifdef APU_LOGGER_H
- end_apu_log();
-#endif
- }
- char tempName[2048];
- char file[2048];
-
- utilGetBaseName(theApp.szFile, tempName);
-
- _fullpath(file, tempName, 1024);
- theApp.filename = file;
-
- int index = theApp.filename.ReverseFind('.');
- if(index != -1)
- theApp.filename = theApp.filename.Left(index);
-
- CString ipsname;
- ipsname.Format("%s.ips", theApp.filename);
-
- if(!theApp.dir.GetLength()) {
- int index = theApp.filename.ReverseFind('\\');
- if(index != -1) {
- theApp.dir = theApp.filename.Left(index-1);
- }
- }
-
- IMAGE_TYPE type = utilFindType(theApp.szFile);
-
- if(type == IMAGE_UNKNOWN) {
- systemMessage(IDS_UNSUPPORTED_FILE_TYPE,
- "Unsupported file type: %s", theApp.szFile);
- return false;
- }
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
- theApp.cartridgeType = (int)type;
- if(type == IMAGE_GB) {
- if(!gbLoadRom(theApp.szFile))
- return false;
- theApp.emulator = GBSystem;
- gbBorderOn = theApp.winGbBorderOn;
- theApp.romSize = gbRomSize;
- if(theApp.autoIPS) {
- int size = gbRomSize;
- utilApplyIPS(ipsname, &gbRom, &size);
- if(size != gbRomSize) {
- extern bool gbUpdateSizes();
- gbUpdateSizes();
- gbReset();
- theApp.romSize = size;
- }
- }
- } else {
- int size = CPULoadRom(theApp.szFile);
- if(!size)
- return false;
-
- theApp.romSize = size;
-
- flashSetSize(theApp.winFlashSize);
- rtcEnable(theApp.winRtcEnable);
- cpuSaveType = theApp.winSaveType;
-
- // if(cpuEnhancedDetection && winSaveType == 0) {
- // utilGBAFindSave(rom, size);
- // }
- GetModuleFileName(NULL, tempName, 2048);
-
- char *p = strrchr(tempName, '\\');
- if(p)
- *p = 0;
-
- char buffer[5];
- strncpy(buffer, (const char *)&rom[0xac], 4);
- buffer[4] = 0;
-
- strcat(tempName, "\\vba-over.ini");
-
- UINT i = GetPrivateProfileInt(buffer,
- "rtcEnabled",
- -1,
- tempName);
- if(i != (UINT)-1)
- rtcEnable(i == 0 ? false : true);
-
- i = GetPrivateProfileInt(buffer,
- "flashSize",
- -1,
- tempName);
- if(i != (UINT)-1 && (i == 0x10000 || i == 0x20000))
- flashSetSize((int)i);
-
- i = GetPrivateProfileInt(buffer,
- "saveType",
- -1,
- tempName);
- if(i != (UINT)-1 && (i <= 5))
- cpuSaveType = (int)i;
-
- theApp.emulator = GBASystem;
- /* disabled due to problems
- if(theApp.removeIntros && rom != NULL) {
- *((u32 *)rom)= 0xea00002e;
- }
- */
-
- if(theApp.autoIPS) {
- int size = 0x2000000;
- utilApplyIPS(ipsname, &rom, &size);
- if(size != 0x2000000) {
- CPUReset();
- }
- }
- }
-
- if(theApp.soundInitialized) {
- if(theApp.cartridgeType == 1)
- gbSoundReset();
- else
- soundReset();
- } else {
- //if(!soundOffFlag) /* mute hax */
- soundInit(!theApp.cartridgeType);
- if ( soundOffFlag )
- soundDisable(0x30f);
- theApp.soundInitialized = true;
- }
-
-#ifdef APU_LOGGER_H
- begin_apu_log("apu_log.txt");
-#endif
-
- if(type == IMAGE_GBA) {
- skipBios = theApp.skipBiosFile ? true : false;
- CPUInit((char *)(LPCTSTR)theApp.biosFileName, theApp.useBiosFile ? true : false);
- CPUReset();
- }
-
- readBatteryFile();
-
- if(theApp.autoSaveLoadCheatList)
- winLoadCheatListDefault();
-
- theApp.addRecentFile(theApp.szFile);
-
- theApp.updateWindowSize(theApp.videoOption);
-
- theApp.updateFrameSkip();
-
- if(theApp.autoHideMenu && theApp.videoOption > VIDEO_4X && theApp.menuToggle)
- OnFileTogglemenu();
-
- emulating = true;
-
- if(theApp.autoLoadMostRecent)
- OnFileLoadgameMostrecent();
-
- theApp.frameskipadjust = 0;
- theApp.renderedFrames = 0;
- theApp.autoFrameSkipLastTime = theApp.throttleLastTime = systemGetClock();
-
- theApp.rewindCount = 0;
- theApp.rewindCounter = 0;
- theApp.rewindSaveNeeded = false;
-
- return true;
-}
-
-void MainWnd::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
-{
- ASSERT(pMenu != NULL);
-
- CCmdUI state;
- state.m_pMenu = pMenu;
- ASSERT(state.m_pOther == NULL);
- ASSERT(state.m_pParentMenu == NULL);
-
- // determine if menu is popup in top-level menu and set m_pOther to
- // it if so (m_pParentMenu == NULL indicates that it is secondary popup)
- HMENU hParentMenu;
- if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
- state.m_pParentMenu = pMenu; // parent == child for tracking popup
- else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL) {
- CWnd* pParent = GetTopLevelParent();
- // child windows don't have menus -- need to go to the top!
- if (pParent != NULL &&
- (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL) {
- int nIndexMax = ::GetMenuItemCount(hParentMenu);
- for (int nIndex = 0; nIndex < nIndexMax; nIndex++) {
- if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu) {
- // when popup is found, m_pParentMenu is containing menu
- state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
- break;
- }
- }
- }
- }
-
- state.m_nIndexMax = pMenu->GetMenuItemCount();
- for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
- state.m_nIndex++) {
- state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
- if (state.m_nID == 0)
- continue; // menu separator or invalid cmd - ignore it
-
- ASSERT(state.m_pOther == NULL);
- ASSERT(state.m_pMenu != NULL);
- if (state.m_nID == (UINT)-1) {
- // possibly a popup menu, route to first item of that popup
- state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
- if (state.m_pSubMenu == NULL ||
- (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
- state.m_nID == (UINT)-1) {
- continue; // first item of popup can't be routed to
- }
- state.DoUpdate(this, FALSE); // popups are never auto disabled
- } else {
- // normal menu item
- // Auto enable/disable if frame window has 'm_bAutoMenuEnable'
- // set and command is _not_ a system command.
- state.m_pSubMenu = NULL;
- state.DoUpdate(this, state.m_nID < 0xF000);
- }
-
- // adjust for menu deletions and additions
- UINT nCount = pMenu->GetMenuItemCount();
- if (nCount < state.m_nIndexMax) {
- state.m_nIndex -= (state.m_nIndexMax - nCount);
- while (state.m_nIndex < nCount &&
- pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID) {
- state.m_nIndex++;
- }
- }
- state.m_nIndexMax = nCount;
- }
-}
-
-void MainWnd::OnMove(int x, int y)
-{
- CWnd::OnMove(x, y);
-
- if(!theApp.changingVideoSize) {
- if(this) {
- if(!IsIconic()) {
- RECT r;
-
- GetWindowRect(&r);
- theApp.windowPositionX = r.left;
- theApp.windowPositionY = r.top;
- theApp.adjustDestRect();
- regSetDwordValue("windowX", theApp.windowPositionX);
- regSetDwordValue("windowY", theApp.windowPositionY);
- }
- }
- }
-}
-
-void MainWnd::OnSize(UINT nType, int cx, int cy)
-{
- CWnd::OnSize(nType, cx, cy);
-
- if(!theApp.changingVideoSize) {
- if(this) {
- if(!IsIconic()) {
- if(theApp.iconic) {
- if(emulating) {
- soundResume();
- theApp.paused = false;
- }
- }
- if(theApp.videoOption <= VIDEO_4X) {
- theApp.surfaceSizeX = cx;
- theApp.surfaceSizeY = cy;
- theApp.adjustDestRect();
- if(theApp.display)
- theApp.display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top);
- }
- } else {
- if(emulating) {
- if(!theApp.paused) {
- theApp.paused = true;
- soundPause();
- }
- }
- theApp.iconic = true;
- }
- }
- }
-}
-
-void MainWnd::winSaveCheatListDefault()
-{
- CString name;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- name = theApp.filename;
- CString dir = regQueryStringValue("saveDir", NULL);
-
- if(!dir.GetLength())
- dir = getDirFromFile(filename);
-
- if(isDriveRoot(dir))
- filename.Format("%s%s.clt", dir, name);
- else
- filename.Format("%s\\%s.clt", dir, name);
-
- winSaveCheatList(filename);
-}
-
-void MainWnd::winSaveCheatList(const char *name)
-{
- if(theApp.cartridgeType == 0)
- cheatsSaveCheatList(name);
- else
- gbCheatsSaveCheatList(name);
-}
-
-void MainWnd::winLoadCheatListDefault()
-{
- CString name;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- name = theApp.filename;
- CString dir = regQueryStringValue("saveDir", NULL);
-
- if(!dir.GetLength())
- dir = getDirFromFile(filename);
-
- if(isDriveRoot(dir))
- filename.Format("%s%s.clt", dir, name);
- else
- filename.Format("%s\\%s.clt", dir, name);
-
- winLoadCheatList(filename);
-}
-
-void MainWnd::winLoadCheatList(const char *name)
-{
- bool res = false;
-
- if(theApp.cartridgeType == 0)
- res = cheatsLoadCheatList(name);
- else
- res = gbCheatsLoadCheatList(name);
-
- if(res)
- systemScreenMessage(winResLoadString(IDS_LOADED_CHEATS));
-}
-
-CString MainWnd::getDirFromFile(CString& file)
-{
- CString temp = file;
- int index = temp.ReverseFind('\\');
-
- if(index != -1) {
- temp = temp.Left(index);
- if(temp.GetLength() == 2 && temp[1] == ':')
- temp += "\\";
- } else {
- temp = "";
- }
- return temp;
-}
-
-bool MainWnd::isDriveRoot(CString& file)
-{
- if(file.GetLength() == 3) {
- if(file[1] == ':' && file[2] == '\\')
- return true;
- }
- return false;
-}
-
-void MainWnd::writeBatteryFile()
-{
- CString buffer;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- buffer = theApp.filename;
-
- CString saveDir = regQueryStringValue("batteryDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(isDriveRoot(saveDir))
- filename.Format("%s%s.sav", saveDir, buffer);
- else
- filename.Format("%s\\%s.sav", saveDir, buffer);
-
- if(theApp.emulator.emuWriteBattery)
- theApp.emulator.emuWriteBattery(filename);
-}
-
-
-void MainWnd::readBatteryFile()
-{
- CString buffer;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- buffer = theApp.filename;
-
- CString saveDir = regQueryStringValue("batteryDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(isDriveRoot(saveDir))
- filename.Format("%s%s.sav", saveDir, buffer);
- else
- filename.Format("%s\\%s.sav", saveDir, buffer);
-
- bool res = false;
-
- if(theApp.emulator.emuReadBattery)
- res = theApp.emulator.emuReadBattery(filename);
-
- if(res)
- systemScreenMessage(winResLoadString(IDS_LOADED_BATTERY));
-}
-
-CString MainWnd::winLoadFilter(UINT id)
-{
- CString res = winResLoadString(id);
- res.Replace('_','|');
-
- return res;
-}
-
-bool MainWnd::loadSaveGame(const char *name)
-{
- if(theApp.emulator.emuReadState)
- return theApp.emulator.emuReadState(name);
- return false;
-}
-
-bool MainWnd::writeSaveGame(const char *name)
-{
- if(theApp.emulator.emuWriteState)
- return theApp.emulator.emuWriteState(name);
- return false;
-}
-
-void MainWnd::OnContextMenu(CWnd* pWnd, CPoint point)
-{
- winMouseOn();
-}
-
-bool MainWnd::fileOpenSelect()
-{
- theApp.dir = "";
- CString initialDir = regQueryStringValue("romdir",".");
- if(!initialDir.IsEmpty())
- theApp.dir = initialDir;
-
- int selectedFilter = regQueryDwordValue("selectedFilter", 0);
- if(selectedFilter < 0 || selectedFilter > 2)
- selectedFilter = 0;
-
- theApp.szFile = "";
-
- LPCTSTR exts[] = { "" };
- CString filter = winLoadFilter(IDS_FILTER_ROM);
- CString title = winResLoadString(IDS_SELECT_ROM);
-
- FileDlg dlg(this, "", filter, selectedFilter, "", exts, theApp.dir, title, false);
-
- if(dlg.DoModal() == IDOK) {
- regSetDwordValue("selectedFilter", dlg.m_ofn.nFilterIndex);
- theApp.szFile = dlg.GetPathName();
- theApp.dir = theApp.szFile.Left(dlg.m_ofn.nFileOffset);
- if(theApp.dir.GetLength() > 3 && theApp.dir[theApp.dir.GetLength()-1] == '\\')
- theApp.dir = theApp.dir.Left(theApp.dir.GetLength()-1);
- regSetStringValue("romdir", theApp.dir);
- return true;
- }
- return false;
-}
-
-void MainWnd::OnPaint()
-{
- CPaintDC dc(this); // device context for painting
-
- if(emulating) {
- theApp.painting = true;
- systemDrawScreen();
- theApp.painting = false;
- theApp.renderedFrames--;
- }
-}
-
-BOOL MainWnd::PreTranslateMessage(MSG* pMsg)
-{
- if (CWnd::PreTranslateMessage(pMsg))
- return TRUE;
-
- if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) {
- return theApp.hAccel != NULL && ::TranslateAccelerator(m_hWnd, theApp.hAccel, pMsg);
- }
-
- return FALSE;
-}
-
-void MainWnd::screenCapture(int captureNumber)
-{
- CString buffer;
-
- CString captureDir = regQueryStringValue("captureDir", "");
- int index = theApp.filename.ReverseFind('\\');
-
- CString name;
- if(index != -1)
- name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- name = theApp.filename;
-
- if(captureDir.IsEmpty())
- captureDir = getDirFromFile(theApp.filename);
-
- LPCTSTR ext = "png";
- if(theApp.captureFormat != 0)
- ext = "bmp";
-
- if(isDriveRoot(captureDir))
- buffer.Format("%s%s_%02d.%s",
- captureDir,
- name,
- captureNumber,
- ext);
- else
- buffer.Format("%s\\%s_%02d.%s",
- captureDir,
- name,
- captureNumber,
- ext);
-
- if(theApp.captureFormat == 0)
- theApp.emulator.emuWritePNG(buffer);
- else
- theApp.emulator.emuWriteBMP(buffer);
-
- CString msg = winResLoadString(IDS_SCREEN_CAPTURE);
- systemScreenMessage(msg);
-}
-
-void MainWnd::winMouseOn()
-{
- SetCursor(arrow);
- if(theApp.videoOption > VIDEO_4X) {
- theApp.mouseCounter = 10;
- } else
- theApp.mouseCounter = 0;
-}
-
-void MainWnd::OnMouseMove(UINT nFlags, CPoint point)
-{
- winMouseOn();
-
- CWnd::OnMouseMove(nFlags, point);
-}
-
-void MainWnd::OnInitMenu(CMenu* pMenu)
-{
- CWnd::OnInitMenu(pMenu);
-
- soundPause();
-}
-
-void MainWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
-{
- CWnd::OnActivate(nState, pWndOther, bMinimized);
-
- bool a = (nState == WA_ACTIVE) || (nState == WA_CLICKACTIVE);
-
- if(a && theApp.input) {
- theApp.active = a;
- theApp.input->activate();
- if(!theApp.paused) {
- if(emulating) {
- soundResume();
- }
- }
- } else {
- theApp.wasPaused = true;
- if(theApp.pauseWhenInactive) {
- if(emulating) {
- soundPause();
- }
- theApp.active = a;
- }
-
- memset(theApp.delta,255,sizeof(theApp.delta));
- }
-
- if(theApp.paused && emulating)
- {
- theApp.painting = true;
- systemDrawScreen();
- theApp.painting = false;
- theApp.renderedFrames--;
- }
-}
-
-#if _MSC_VER <= 1200
-void MainWnd::OnActivateApp(BOOL bActive, HTASK hTask)
-#else
-void MainWnd::OnActivateApp(BOOL bActive, DWORD hTask)
-#endif
-{
- CWnd::OnActivateApp(bActive, hTask);
-
- if(theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) {
- if(bActive) {
- if(theApp.display)
- theApp.display->clear();
- }
- }
-}
-
-void MainWnd::OnDropFiles(HDROP hDropInfo)
-{
- char szFile[1024];
-
- if(DragQueryFile(hDropInfo,
- 0,
- szFile,
- 1024)) {
- theApp.szFile = szFile;
- if(FileRun()) {
- SetForegroundWindow();
- emulating = TRUE;
- } else {
- emulating = FALSE;
- soundPause();
- }
- }
- DragFinish(hDropInfo);
-}
-
-LRESULT MainWnd::OnMySysCommand(WPARAM wParam, LPARAM lParam)
-{
- if(emulating && !theApp.paused) {
- if((wParam&0xFFF0) == SC_SCREENSAVE || (wParam&0xFFF0) == SC_MONITORPOWER)
- return 0;
- }
- return Default();
-}
-
-void MainWnd::OnSetFocus(CWnd * pOldWnd)
-{
- theApp.dinputKeyFocus = true;
-}
-
-void MainWnd::OnKillFocus(CWnd * pNewWnd)
-{
- theApp.dinputKeyFocus = false;
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// MainWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "VBA.h"
+#include "MainWnd.h"
+
+#include
+#include
+
+#include "FileDlg.h"
+#include "Reg.h"
+#include "WinResUtil.h"
+
+#include "../System.h"
+#include "../AutoBuild.h"
+#include "../cheatSearch.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../Flash.h"
+#include "../Globals.h"
+#include "../gb/GB.h"
+#include "../gb/gbCheats.h"
+#include "../gb/gbGlobals.h"
+#include "../RTC.h"
+#include "../Sound.h"
+#include "../Util.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define VBA_CONFIRM_MODE WM_APP + 100
+
+extern void remoteCleanUp();
+extern int gbHardware;
+
+/////////////////////////////////////////////////////////////////////////////
+// MainWnd
+
+MainWnd::MainWnd()
+{
+ m_hAccelTable = NULL;
+ arrow = LoadCursor(NULL, IDC_ARROW);
+}
+
+MainWnd::~MainWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(MainWnd, CWnd)
+ //{{AFX_MSG_MAP(MainWnd)
+ ON_WM_CLOSE()
+ ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
+ ON_COMMAND(ID_HELP_FAQ, OnHelpFaq)
+ ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
+ ON_WM_INITMENUPOPUP()
+ ON_COMMAND(ID_FILE_PAUSE, OnFilePause)
+ ON_UPDATE_COMMAND_UI(ID_FILE_PAUSE, OnUpdateFilePause)
+ ON_COMMAND(ID_FILE_RESET, OnFileReset)
+ ON_UPDATE_COMMAND_UI(ID_FILE_RESET, OnUpdateFileReset)
+ ON_UPDATE_COMMAND_UI(ID_FILE_RECENT_FREEZE, OnUpdateFileRecentFreeze)
+ ON_COMMAND(ID_FILE_RECENT_RESET, OnFileRecentReset)
+ ON_COMMAND(ID_FILE_RECENT_FREEZE, OnFileRecentFreeze)
+ ON_COMMAND(ID_FILE_EXIT, OnFileExit)
+ ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
+ ON_UPDATE_COMMAND_UI(ID_FILE_CLOSE, OnUpdateFileClose)
+ ON_COMMAND(ID_FILE_OPENGAMEBOY, OnFileOpengameboy)
+ ON_COMMAND(ID_FILE_LOAD, OnFileLoad)
+ ON_UPDATE_COMMAND_UI(ID_FILE_LOAD, OnUpdateFileLoad)
+ ON_COMMAND(ID_FILE_SAVE, OnFileSave)
+ ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
+ ON_COMMAND(ID_FILE_IMPORT_BATTERYFILE, OnFileImportBatteryfile)
+ ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT_BATTERYFILE, OnUpdateFileImportBatteryfile)
+ ON_COMMAND(ID_FILE_IMPORT_GAMESHARKCODEFILE, OnFileImportGamesharkcodefile)
+ ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT_GAMESHARKCODEFILE, OnUpdateFileImportGamesharkcodefile)
+ ON_COMMAND(ID_FILE_IMPORT_GAMESHARKSNAPSHOT, OnFileImportGamesharksnapshot)
+ ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT_GAMESHARKSNAPSHOT, OnUpdateFileImportGamesharksnapshot)
+ ON_COMMAND(ID_FILE_EXPORT_BATTERYFILE, OnFileExportBatteryfile)
+ ON_UPDATE_COMMAND_UI(ID_FILE_EXPORT_BATTERYFILE, OnUpdateFileExportBatteryfile)
+ ON_COMMAND(ID_FILE_EXPORT_GAMESHARKSNAPSHOT, OnFileExportGamesharksnapshot)
+ ON_UPDATE_COMMAND_UI(ID_FILE_EXPORT_GAMESHARKSNAPSHOT, OnUpdateFileExportGamesharksnapshot)
+ ON_COMMAND(ID_FILE_SCREENCAPTURE, OnFileScreencapture)
+ ON_UPDATE_COMMAND_UI(ID_FILE_SCREENCAPTURE, OnUpdateFileScreencapture)
+ ON_COMMAND(ID_FILE_ROMINFORMATION, OnFileRominformation)
+ ON_UPDATE_COMMAND_UI(ID_FILE_ROMINFORMATION, OnUpdateFileRominformation)
+ ON_COMMAND(ID_FILE_TOGGLEMENU, OnFileTogglemenu)
+ ON_UPDATE_COMMAND_UI(ID_FILE_TOGGLEMENU, OnUpdateFileTogglemenu)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE, OnUpdateOptionsFrameskipThrottleNothrottle)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_25, OnUpdateOptionsFrameskipThrottle25)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_50, OnUpdateOptionsFrameskipThrottle50)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_100, OnUpdateOptionsFrameskipThrottle100)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_150, OnUpdateOptionsFrameskipThrottle150)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_200, OnUpdateOptionsFrameskipThrottle200)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER, OnUpdateOptionsFrameskipThrottleOther)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_NOTHROTTLE, OnOptionsFrameskipThrottleNothrottle)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_25, OnOptionsFrameskipThrottle25)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_50, OnOptionsFrameskipThrottle50)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_100, OnOptionsFrameskipThrottle100)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_150, OnOptionsFrameskipThrottle150)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_200, OnOptionsFrameskipThrottle200)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_THROTTLE_OTHER, OnOptionsFrameskipThrottleOther)
+ ON_COMMAND(ID_OPTIONS_FRAMESKIP_AUTOMATIC, OnOptionsFrameskipAutomatic)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FRAMESKIP_AUTOMATIC, OnUpdateOptionsFrameskipAutomatic)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_0, OnUpdateOptionsVideoFrameskip0)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_1, OnUpdateOptionsVideoFrameskip1)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_2, OnUpdateOptionsVideoFrameskip2)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_3, OnUpdateOptionsVideoFrameskip3)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_4, OnUpdateOptionsVideoFrameskip4)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_5, OnUpdateOptionsVideoFrameskip5)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_6, OnUpdateOptionsVideoFrameskip6)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_7, OnUpdateOptionsVideoFrameskip7)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_8, OnUpdateOptionsVideoFrameskip8)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FRAMESKIP_9, OnUpdateOptionsVideoFrameskip9)
+ ON_COMMAND(ID_OPTIONS_VIDEO_VSYNC, OnOptionsVideoVsync)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_VSYNC, OnUpdateOptionsVideoVsync)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X1, OnUpdateOptionsVideoX1)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X2, OnUpdateOptionsVideoX2)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X3, OnUpdateOptionsVideoX3)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_X4, OnUpdateOptionsVideoX4)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN320X240, OnUpdateOptionsVideoFullscreen320x240)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN640X480, OnUpdateOptionsVideoFullscreen640x480)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN800X600, OnUpdateOptionsVideoFullscreen800x600)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN320X240, OnOptionsVideoFullscreen320x240)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN640X480, OnOptionsVideoFullscreen640x480)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN800X600, OnOptionsVideoFullscreen800x600)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN, OnOptionsVideoFullscreen)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN, OnUpdateOptionsVideoFullscreen)
+ ON_WM_MOVE()
+ ON_WM_SIZE()
+ ON_COMMAND(ID_OPTIONS_VIDEO_DISABLESFX, OnOptionsVideoDisablesfx)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_DISABLESFX, OnUpdateOptionsVideoDisablesfx)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREENSTRETCHTOFIT, OnOptionsVideoFullscreenstretchtofit)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREENSTRETCHTOFIT, OnUpdateOptionsVideoFullscreenstretchtofit)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_GDI, OnOptionsVideoRendermethodGdi)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_GDI, OnUpdateOptionsVideoRendermethodGdi)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW, OnOptionsVideoRendermethodDirectdraw)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECTDRAW, OnUpdateOptionsVideoRendermethodDirectdraw)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D, OnOptionsVideoRendermethodDirect3d)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_DIRECT3D, OnUpdateOptionsVideoRendermethodDirect3d)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL, OnOptionsVideoRendermethodOpengl)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDERMETHOD_OPENGL, OnUpdateOptionsVideoRendermethodOpengl)
+ ON_COMMAND(ID_OPTIONS_VIDEO_TRIPLEBUFFERING, OnOptionsVideoTriplebuffering)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_TRIPLEBUFFERING, OnUpdateOptionsVideoTriplebuffering)
+ ON_COMMAND(ID_OPTIONS_VIDEO_DDRAWEMULATIONONLY, OnOptionsVideoDdrawemulationonly)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_DDRAWEMULATIONONLY, OnUpdateOptionsVideoDdrawemulationonly)
+ ON_COMMAND(ID_OPTIONS_VIDEO_DDRAWUSEVIDEOMEMORY, OnOptionsVideoDdrawusevideomemory)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_DDRAWUSEVIDEOMEMORY, OnUpdateOptionsVideoDdrawusevideomemory)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DNOFILTER, OnOptionsVideoRenderoptionsD3dnofilter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DNOFILTER, OnUpdateOptionsVideoRenderoptionsD3dnofilter)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DBILINEAR, OnOptionsVideoRenderoptionsD3dbilinear)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_D3DBILINEAR, OnUpdateOptionsVideoRenderoptionsD3dbilinear)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLNEAREST, OnOptionsVideoRenderoptionsGlnearest)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLNEAREST, OnUpdateOptionsVideoRenderoptionsGlnearest)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLBILINEAR, OnOptionsVideoRenderoptionsGlbilinear)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLBILINEAR, OnUpdateOptionsVideoRenderoptionsGlbilinear)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE, OnOptionsVideoRenderoptionsGltriangle)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLTRIANGLE, OnUpdateOptionsVideoRenderoptionsGltriangle)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS, OnOptionsVideoRenderoptionsGlquads)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_GLQUADS, OnUpdateOptionsVideoRenderoptionsGlquads)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_SELECTSKIN, OnOptionsVideoRenderoptionsSelectskin)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_SELECTSKIN, OnUpdateOptionsVideoRenderoptionsSelectskin)
+ ON_COMMAND(ID_OPTIONS_VIDEO_RENDEROPTIONS_SKIN, OnOptionsVideoRenderoptionsSkin)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_RENDEROPTIONS_SKIN, OnUpdateOptionsVideoRenderoptionsSkin)
+ ON_WM_CONTEXTMENU()
+ ON_COMMAND(ID_OPTIONS_EMULATOR_ASSOCIATE, OnOptionsEmulatorAssociate)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_DIRECTORIES, OnOptionsEmulatorDirectories)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_DISABLESTATUSMESSAGES, OnOptionsEmulatorDisablestatusmessages)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_DISABLESTATUSMESSAGES, OnUpdateOptionsEmulatorDisablestatusmessages)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SYNCHRONIZE, OnOptionsEmulatorSynchronize)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SYNCHRONIZE, OnUpdateOptionsEmulatorSynchronize)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE, OnOptionsEmulatorPausewheninactive)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_PAUSEWHENINACTIVE, OnUpdateOptionsEmulatorPausewheninactive)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE, OnOptionsEmulatorSpeeduptoggle)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SPEEDUPTOGGLE, OnUpdateOptionsEmulatorSpeeduptoggle)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH, OnOptionsEmulatorAutomaticallyipspatch)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOMATICALLYIPSPATCH, OnUpdateOptionsEmulatorAutomaticallyipspatch)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_AGBPRINT, OnOptionsEmulatorAgbprint)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AGBPRINT, OnUpdateOptionsEmulatorAgbprint)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnOptionsEmulatorRealtimeclock)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_REALTIMECLOCK, OnUpdateOptionsEmulatorRealtimeclock)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_GENERICFLASHCARD, OnOptionsEmulatorGenericflashcard)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_GENERICFLASHCARD, OnUpdateOptionsEmulatorGenericflashcard)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_AUTOHIDEMENU, OnOptionsEmulatorAutohidemenu)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_AUTOHIDEMENU, OnUpdateOptionsEmulatorAutohidemenu)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_REWINDINTERVAL, OnOptionsEmulatorRewindinterval)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC, OnOptionsEmulatorSavetypeAutomatic)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_AUTOMATIC, OnUpdateOptionsEmulatorSavetypeAutomatic)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM, OnOptionsEmulatorSavetypeEeprom)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROM, OnUpdateOptionsEmulatorSavetypeEeprom)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_SRAM, OnOptionsEmulatorSavetypeSram)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_SRAM, OnUpdateOptionsEmulatorSavetypeSram)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH, OnOptionsEmulatorSavetypeFlash)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH, OnUpdateOptionsEmulatorSavetypeFlash)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR, OnOptionsEmulatorSavetypeEepromsensor)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR, OnUpdateOptionsEmulatorSavetypeEepromsensor)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_NONE, OnOptionsEmulatorSavetypeNone)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_NONE, OnUpdateOptionsEmulatorSavetypeNone)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K, OnOptionsEmulatorSavetypeFlash512k)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K, OnUpdateOptionsEmulatorSavetypeFlash512k)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M, OnOptionsEmulatorSavetypeFlash1m)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M, OnUpdateOptionsEmulatorSavetypeFlash1m)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_USEBIOSFILE, OnOptionsEmulatorUsebiosfile)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_USEBIOSFILE, OnUpdateOptionsEmulatorUsebiosfile)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SKIPBIOS, OnOptionsEmulatorSkipbios)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_SKIPBIOS, OnUpdateOptionsEmulatorSkipbios)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_SELECTBIOSFILE, OnOptionsEmulatorSelectbiosfile)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_PNGFORMAT, OnOptionsEmulatorPngformat)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_PNGFORMAT, OnUpdateOptionsEmulatorPngformat)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_BMPFORMAT, OnOptionsEmulatorBmpformat)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_BMPFORMAT, OnUpdateOptionsEmulatorBmpformat)
+ ON_COMMAND(ID_OPTIONS_SOUND_OFF, OnOptionsSoundOff)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_OFF, OnUpdateOptionsSoundOff)
+ ON_COMMAND(ID_OPTIONS_SOUND_MUTE, OnOptionsSoundMute)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_MUTE, OnUpdateOptionsSoundMute)
+ ON_COMMAND(ID_OPTIONS_SOUND_ON, OnOptionsSoundOn)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_ON, OnUpdateOptionsSoundOn)
+ ON_COMMAND(ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION, OnOptionsSoundUseoldsynchronization)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_USEOLDSYNCHRONIZATION, OnUpdateOptionsSoundUseoldsynchronization)
+ ON_COMMAND(ID_OPTIONS_SOUND_ECHO, OnOptionsSoundEcho)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_ECHO, OnUpdateOptionsSoundEcho)
+ ON_COMMAND(ID_OPTIONS_SOUND_LOWPASSFILTER, OnOptionsSoundLowpassfilter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_LOWPASSFILTER, OnUpdateOptionsSoundLowpassfilter)
+ ON_COMMAND(ID_OPTIONS_SOUND_REVERSESTEREO, OnOptionsSoundReversestereo)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_REVERSESTEREO, OnUpdateOptionsSoundReversestereo)
+ ON_COMMAND(ID_OPTIONS_SOUND_11KHZ, OnOptionsSound11khz)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_11KHZ, OnUpdateOptionsSound11khz)
+ ON_COMMAND(ID_OPTIONS_SOUND_22KHZ, OnOptionsSound22khz)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_22KHZ, OnUpdateOptionsSound22khz)
+ ON_COMMAND(ID_OPTIONS_SOUND_44KHZ, OnOptionsSound44khz)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_44KHZ, OnUpdateOptionsSound44khz)
+ ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL1, OnOptionsSoundChannel1)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL1, OnUpdateOptionsSoundChannel1)
+ ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL2, OnOptionsSoundChannel2)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL2, OnUpdateOptionsSoundChannel2)
+ ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL3, OnOptionsSoundChannel3)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL3, OnUpdateOptionsSoundChannel3)
+ ON_COMMAND(ID_OPTIONS_SOUND_CHANNEL4, OnOptionsSoundChannel4)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_CHANNEL4, OnUpdateOptionsSoundChannel4)
+ ON_COMMAND(ID_OPTIONS_SOUND_DIRECTSOUNDA, OnOptionsSoundDirectsounda)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_DIRECTSOUNDA, OnUpdateOptionsSoundDirectsounda)
+ ON_COMMAND(ID_OPTIONS_SOUND_DIRECTSOUNDB, OnOptionsSoundDirectsoundb)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_DIRECTSOUNDB, OnUpdateOptionsSoundDirectsoundb)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_BORDER, OnOptionsGameboyBorder)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_BORDER, OnUpdateOptionsGameboyBorder)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_PRINTER, OnOptionsGameboyPrinter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_PRINTER, OnUpdateOptionsGameboyPrinter)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC, OnOptionsGameboyBorderAutomatic)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC, OnUpdateOptionsGameboyBorderAutomatic)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_AUTOMATIC, OnOptionsGameboyAutomatic)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_AUTOMATIC, OnUpdateOptionsGameboyAutomatic)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_GBA, OnOptionsGameboyGba)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_GBA, OnUpdateOptionsGameboyGba)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_CGB, OnOptionsGameboyCgb)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_CGB, OnUpdateOptionsGameboyCgb)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_SGB, OnOptionsGameboySgb)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_SGB, OnUpdateOptionsGameboySgb)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_SGB2, OnOptionsGameboySgb2)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_SGB2, OnUpdateOptionsGameboySgb2)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_GB, OnOptionsGameboyGb)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_GB, OnUpdateOptionsGameboyGb)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_REALCOLORS, OnOptionsGameboyRealcolors)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_REALCOLORS, OnUpdateOptionsGameboyRealcolors)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS, OnOptionsGameboyGameboycolors)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_GAMEBOY_GAMEBOYCOLORS, OnUpdateOptionsGameboyGameboycolors)
+ ON_COMMAND(ID_OPTIONS_GAMEBOY_COLORS, OnOptionsGameboyColors)
+ ON_COMMAND(ID_OPTIONS_FILTER_DISABLEMMX, OnOptionsFilterDisablemmx)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_DISABLEMMX, OnUpdateOptionsFilterDisablemmx)
+ ON_COMMAND(ID_OPTIONS_LANGUAGE_SYSTEM, OnOptionsLanguageSystem)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_LANGUAGE_SYSTEM, OnUpdateOptionsLanguageSystem)
+ ON_COMMAND(ID_OPTIONS_LANGUAGE_ENGLISH, OnOptionsLanguageEnglish)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_LANGUAGE_ENGLISH, OnUpdateOptionsLanguageEnglish)
+ ON_COMMAND(ID_OPTIONS_LANGUAGE_OTHER, OnOptionsLanguageOther)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_LANGUAGE_OTHER, OnUpdateOptionsLanguageOther)
+ ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_1, OnOptionsJoypadConfigure1)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_1, OnUpdateOptionsJoypadConfigure1)
+ ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_2, OnOptionsJoypadConfigure2)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_2, OnUpdateOptionsJoypadConfigure2)
+ ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_3, OnOptionsJoypadConfigure3)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_3, OnUpdateOptionsJoypadConfigure3)
+ ON_COMMAND(ID_OPTIONS_JOYPAD_CONFIGURE_4, OnOptionsJoypadConfigure4)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_CONFIGURE_4, OnUpdateOptionsJoypadConfigure4)
+ ON_COMMAND(ID_OPTIONS_JOYPAD_MOTIONCONFIGURE, OnOptionsJoypadMotionconfigure)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_JOYPAD_MOTIONCONFIGURE, OnUpdateOptionsJoypadMotionconfigure)
+ ON_COMMAND(ID_CHEATS_SEARCHFORCHEATS, OnCheatsSearchforcheats)
+ ON_UPDATE_COMMAND_UI(ID_CHEATS_SEARCHFORCHEATS, OnUpdateCheatsSearchforcheats)
+ ON_COMMAND(ID_CHEATS_CHEATLIST, OnCheatsCheatlist)
+ ON_UPDATE_COMMAND_UI(ID_CHEATS_CHEATLIST, OnUpdateCheatsCheatlist)
+ ON_COMMAND(ID_CHEATS_AUTOMATICSAVELOADCHEATS, OnCheatsAutomaticsaveloadcheats)
+ ON_COMMAND(ID_CHEATS_LOADCHEATLIST, OnCheatsLoadcheatlist)
+ ON_UPDATE_COMMAND_UI(ID_CHEATS_LOADCHEATLIST, OnUpdateCheatsLoadcheatlist)
+ ON_COMMAND(ID_CHEATS_SAVECHEATLIST, OnCheatsSavecheatlist)
+ ON_UPDATE_COMMAND_UI(ID_CHEATS_SAVECHEATLIST, OnUpdateCheatsSavecheatlist)
+ ON_COMMAND(ID_TOOLS_DISASSEMBLE, OnToolsDisassemble)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_DISASSEMBLE, OnUpdateToolsDisassemble)
+ ON_COMMAND(ID_TOOLS_LOGGING, OnToolsLogging)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_LOGGING, OnUpdateToolsLogging)
+ ON_COMMAND(ID_TOOLS_IOVIEWER, OnToolsIoviewer)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_IOVIEWER, OnUpdateToolsIoviewer)
+ ON_COMMAND(ID_TOOLS_MAPVIEW, OnToolsMapview)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_MAPVIEW, OnUpdateToolsMapview)
+ ON_COMMAND(ID_TOOLS_MEMORYVIEWER, OnToolsMemoryviewer)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_MEMORYVIEWER, OnUpdateToolsMemoryviewer)
+ ON_COMMAND(ID_TOOLS_OAMVIEWER, OnToolsOamviewer)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_OAMVIEWER, OnUpdateToolsOamviewer)
+ ON_COMMAND(ID_TOOLS_PALETTEVIEW, OnToolsPaletteview)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_PALETTEVIEW, OnUpdateToolsPaletteview)
+ ON_COMMAND(ID_TOOLS_TILEVIEWER, OnToolsTileviewer)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_TILEVIEWER, OnUpdateToolsTileviewer)
+ ON_COMMAND(ID_DEBUG_NEXTFRAME, OnDebugNextframe)
+ ON_UPDATE_COMMAND_UI(ID_CHEATS_AUTOMATICSAVELOADCHEATS, OnUpdateCheatsAutomaticsaveloadcheats)
+ ON_COMMAND(ID_TOOLS_DEBUG_GDB, OnToolsDebugGdb)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_GDB, OnUpdateToolsDebugGdb)
+ ON_COMMAND(ID_TOOLS_DEBUG_LOADANDWAIT, OnToolsDebugLoadandwait)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_LOADANDWAIT, OnUpdateToolsDebugLoadandwait)
+ ON_COMMAND(ID_TOOLS_DEBUG_BREAK, OnToolsDebugBreak)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_BREAK, OnUpdateToolsDebugBreak)
+ ON_COMMAND(ID_TOOLS_DEBUG_DISCONNECT, OnToolsDebugDisconnect)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_DISCONNECT, OnUpdateToolsDebugDisconnect)
+ ON_COMMAND(ID_OPTIONS_SOUND_STARTRECORDING, OnOptionsSoundStartrecording)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_STARTRECORDING, OnUpdateOptionsSoundStartrecording)
+ ON_COMMAND(ID_OPTIONS_SOUND_STOPRECORDING, OnOptionsSoundStoprecording)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_STOPRECORDING, OnUpdateOptionsSoundStoprecording)
+ ON_COMMAND(ID_TOOLS_RECORD_STARTAVIRECORDING, OnToolsRecordStartavirecording)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STARTAVIRECORDING, OnUpdateToolsRecordStartavirecording)
+ ON_COMMAND(ID_TOOLS_RECORD_STOPAVIRECORDING, OnToolsRecordStopavirecording)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STOPAVIRECORDING, OnUpdateToolsRecordStopavirecording)
+ ON_WM_PAINT()
+ ON_COMMAND(ID_TOOLS_RECORD_STARTMOVIERECORDING, OnToolsRecordStartmovierecording)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STARTMOVIERECORDING, OnUpdateToolsRecordStartmovierecording)
+ ON_COMMAND(ID_TOOLS_RECORD_STOPMOVIERECORDING, OnToolsRecordStopmovierecording)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_RECORD_STOPMOVIERECORDING, OnUpdateToolsRecordStopmovierecording)
+ ON_COMMAND(ID_TOOLS_PLAY_STARTMOVIEPLAYING, OnToolsPlayStartmovieplaying)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_PLAY_STARTMOVIEPLAYING, OnUpdateToolsPlayStartmovieplaying)
+ ON_COMMAND(ID_TOOLS_PLAY_STOPMOVIEPLAYING, OnToolsPlayStopmovieplaying)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_PLAY_STOPMOVIEPLAYING, OnUpdateToolsPlayStopmovieplaying)
+ ON_COMMAND(ID_TOOLS_REWIND, OnToolsRewind)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_REWIND, OnUpdateToolsRewind)
+ ON_COMMAND(ID_TOOLS_CUSTOMIZE, OnToolsCustomize)
+ ON_UPDATE_COMMAND_UI(ID_TOOLS_CUSTOMIZE, OnUpdateToolsCustomize)
+ ON_COMMAND(ID_HELP_BUGREPORT, OnHelpBugreport)
+ ON_WM_MOUSEMOVE()
+ ON_WM_INITMENU()
+ ON_WM_ACTIVATE()
+ ON_WM_ACTIVATEAPP()
+ ON_WM_DROPFILES()
+ ON_COMMAND(ID_FILE_SAVEGAME_OLDESTSLOT, OnFileSavegameOldestslot)
+ ON_UPDATE_COMMAND_UI(ID_FILE_SAVEGAME_OLDESTSLOT, OnUpdateFileSavegameOldestslot)
+ ON_COMMAND(ID_FILE_LOADGAME_MOSTRECENT, OnFileLoadgameMostrecent)
+ ON_UPDATE_COMMAND_UI(ID_FILE_LOADGAME_MOSTRECENT, OnUpdateFileLoadgameMostrecent)
+ ON_COMMAND(ID_FILE_LOADGAME_AUTOLOADMOSTRECENT, OnFileLoadgameAutoloadmostrecent)
+ ON_UPDATE_COMMAND_UI(ID_FILE_LOADGAME_AUTOLOADMOSTRECENT, OnUpdateFileLoadgameAutoloadmostrecent)
+ ON_COMMAND(ID_OPTIONS_SOUND_VOLUME_25X, OnOptionsSoundVolume25x)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_VOLUME_25X, OnUpdateOptionsSoundVolume25x)
+ ON_COMMAND(ID_OPTIONS_SOUND_VOLUME_5X, OnOptionsSoundVolume5x)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_VOLUME_5X, OnUpdateOptionsSoundVolume5x)
+ ON_COMMAND(ID_CHEATS_DISABLECHEATS, OnCheatsDisablecheats)
+ ON_UPDATE_COMMAND_UI(ID_CHEATS_DISABLECHEATS, OnUpdateCheatsDisablecheats)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREENMAXSCALE, OnOptionsVideoFullscreenmaxscale)
+ ON_COMMAND(ID_OPTIONS_EMULATOR_GAMEOVERRIDES, OnOptionsEmulatorGameoverrides)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_EMULATOR_GAMEOVERRIDES, OnUpdateOptionsEmulatorGameoverrides)
+ ON_COMMAND(ID_HELP_GNUPUBLICLICENSE, OnHelpGnupubliclicense)
+ ON_COMMAND(ID_OPTIONS_LINK_OPTIONS, OnLinkOptions)
+ ON_COMMAND(ID_OPTIONS_LINK_LOG, OnOptionsLinkLog)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_LINK_LOG, OnUpdateOptionsLinkLog)
+ ON_COMMAND(ID_OPTIONS_LINK_WIRELESSADAPTER, OnOptionsLinkRFU)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_LINK_WIRELESSADAPTER, OnUpdateOptionsLinkRFU)
+ //}}AFX_MSG_MAP
+ ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE10, OnFileRecentFile)
+ ON_COMMAND_EX_RANGE(ID_FILE_LOADGAME_SLOT1, ID_FILE_LOADGAME_SLOT10, OnFileLoadSlot)
+ ON_COMMAND_EX_RANGE(ID_FILE_SAVEGAME_SLOT1, ID_FILE_SAVEGAME_SLOT10, OnFileSaveSlot)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_LOADGAME_SLOT1, ID_FILE_LOADGAME_SLOT10, OnUpdateFileLoadGameSlot)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_SAVEGAME_SLOT1, ID_FILE_SAVEGAME_SLOT10, OnUpdateFileSaveGameSlot)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_FRAMESKIP_0, ID_OPTIONS_VIDEO_FRAMESKIP_5, OnOptionsFrameskip)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_FRAMESKIP_6, ID_OPTIONS_VIDEO_FRAMESKIP_9, OnOptionsFrameskip)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_X1, ID_OPTIONS_VIDEO_X4, OnOptionVideoSize)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_VIDEO_LAYERS_BG0, ID_OPTIONS_VIDEO_LAYERS_OBJWIN, OnVideoLayer)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_VIDEO_LAYERS_BG0, ID_OPTIONS_VIDEO_LAYERS_OBJWIN, OnUpdateVideoLayer)
+ ON_COMMAND(ID_SYSTEM_MINIMIZE, OnSystemMinimize)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_EMULATOR_SHOWSPEED_NONE, ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT, OnOptionsEmulatorShowSpeed)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_EMULATOR_SHOWSPEED_NONE, ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT, OnUpdateOptionsEmulatorShowSpeed)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_SOUND_VOLUME_1X, ID_OPTIONS_SOUND_VOLUME_4X, OnOptionsSoundVolume)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_SOUND_VOLUME_1X, ID_OPTIONS_SOUND_VOLUME_4X, OnUpdateOptionsSoundVolume)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_PRIORITY_HIGHEST, ID_OPTIONS_PRIORITY_BELOWNORMAL, OnOptionsPriority)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_PRIORITY_HIGHEST, ID_OPTIONS_PRIORITY_BELOWNORMAL, OnUpdateOptionsPriority)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_NORMAL, ID_OPTIONS_FILTER_TVMODE, OnOptionsFilter)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL, ID_OPTIONS_FILTER16BIT_MOTIONBLUREXPERIMENTAL, OnOptionsFilter)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X, ID_OPTIONS_FILTER16BIT_SIMPLE2X, OnOptionsFilter)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_BILINEAR, ID_OPTIONS_FILTER_BILINEARPLUS, OnOptionsFilter)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_SCANLINES, ID_OPTIONS_FILTER_SCANLINES, OnOptionsFilter)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_HQ2X, ID_OPTIONS_FILTER_LQ2X, OnOptionsFilter)
+ ON_COMMAND_EX(ID_OPTIONS_FILTER_HQ3X, OnOptionsFilter)
+ ON_COMMAND_EX(ID_OPTIONS_FILTER_HQ4X, OnOptionsFilter)
+ ON_COMMAND_EX(ID_OPTIONS_FILTER_SIMPLE3X, OnOptionsFilter)
+ ON_COMMAND_EX(ID_OPTIONS_FILTER_SIMPLE4X, OnOptionsFilter)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_NORMAL, ID_OPTIONS_FILTER_TVMODE, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL, ID_OPTIONS_FILTER16BIT_MOTIONBLUREXPERIMENTAL, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X, ID_OPTIONS_FILTER16BIT_SIMPLE2X, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_BILINEAR, ID_OPTIONS_FILTER_BILINEARPLUS, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_SCANLINES, ID_OPTIONS_FILTER_SCANLINES, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_HQ2X, ID_OPTIONS_FILTER_LQ2X, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_SIMPLE3X, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_SIMPLE4X, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_HQ3X, OnUpdateOptionsFilter)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_HQ4X, OnUpdateOptionsFilter)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE, ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART, OnOptionsFilterIFB)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE, ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART, OnUpdateOptionsFilterIFB)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1, ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4, OnOptionsJoypadDefault)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1, ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_4, OnUpdateOptionsJoypadDefault)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_JOYPAD_AUTOFIRE_A, ID_OPTIONS_JOYPAD_AUTOFIRE_R, OnOptionsJoypadAutofire)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_JOYPAD_AUTOFIRE_A, ID_OPTIONS_JOYPAD_AUTOFIRE_R, OnUpdateOptionsJoypadAutofire)
+ ON_MESSAGE(VBA_CONFIRM_MODE, OnConfirmMode)
+ ON_MESSAGE(WM_SYSCOMMAND, OnMySysCommand)
+ ON_COMMAND(ID_OPTIONS_SOUND_HARDWAREACCELERATION, &MainWnd::OnOptionsSoundHardwareacceleration)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUND_HARDWAREACCELERATION, &MainWnd::OnUpdateOptionsSoundHardwareacceleration)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN1280X1024, OnOptionsVideoFullscreen1280x1024)
+ ON_COMMAND(ID_OPTIONS_VIDEO_FULLSCREEN1024X768, OnOptionsVideoFullscreen1024x768)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN1024X768, OnUpdateOptionsVideoFullscreen1024x768)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_VIDEO_FULLSCREEN1280X1024, OnUpdateOptionsVideoFullscreen1280x1024)
+ ON_COMMAND(ID_OPTIONS_FILTER_LCDCOLORS, OnOptionsFilterLcdcolors)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_FILTER_LCDCOLORS, OnUpdateOptionsFilterLcdcolors)
+ ON_COMMAND_EX_RANGE(ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE, ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE, OnOptionsSoundPcminterpolation)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE, ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE, OnUpdateOptionsSoundPcminterpolation)
+ ON_WM_SETFOCUS()
+ ON_WM_KILLFOCUS()
+ END_MESSAGE_MAP()
+
+
+ /////////////////////////////////////////////////////////////////////////////
+// MainWnd message handlers
+
+void MainWnd::OnClose()
+{
+ emulating = false;
+ CWnd::OnClose();
+
+ delete this;
+}
+
+bool MainWnd::FileRun()
+{
+ // save battery file before we change the filename...
+ if(rom != NULL || gbRom != NULL) {
+ if(theApp.autoSaveLoadCheatList)
+ winSaveCheatListDefault();
+ writeBatteryFile();
+ cheatSearchCleanup(&cheatSearchData);
+ theApp.emulator.emuCleanUp();
+ remoteCleanUp();
+ emulating = false;
+#ifdef APU_LOGGER_H
+ end_apu_log();
+#endif
+ }
+ char tempName[2048];
+ char file[2048];
+
+ utilGetBaseName(theApp.szFile, tempName);
+
+ _fullpath(file, tempName, 1024);
+ theApp.filename = file;
+
+ int index = theApp.filename.ReverseFind('.');
+ if(index != -1)
+ theApp.filename = theApp.filename.Left(index);
+
+ CString ipsname;
+ ipsname.Format("%s.ips", theApp.filename);
+
+ if(!theApp.dir.GetLength()) {
+ int index = theApp.filename.ReverseFind('\\');
+ if(index != -1) {
+ theApp.dir = theApp.filename.Left(index-1);
+ }
+ }
+
+ IMAGE_TYPE type = utilFindType(theApp.szFile);
+
+ if(type == IMAGE_UNKNOWN) {
+ systemMessage(IDS_UNSUPPORTED_FILE_TYPE,
+ "Unsupported file type: %s", theApp.szFile);
+ return false;
+ }
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+ theApp.cartridgeType = type;
+ if(type == IMAGE_GB) {
+ genericflashcardEnable = theApp.winGenericflashcardEnable;
+
+
+ if(!gbLoadRom(theApp.szFile))
+ return false;
+
+ gbGetHardwareType();
+
+ // used for the handling of the gb Boot Rom
+ if (gbHardware & 5)
+ {
+ char tempName[2048];
+ GetModuleFileName(NULL, tempName, 2048);
+
+ char *p = strrchr(tempName, '\\');
+ if(p)
+ *p = 0;
+
+ strcat(tempName, "\\DMG_ROM.bin");
+
+ skipBios = theApp.skipBiosFile ? true : false;
+ gbCPUInit(tempName, theApp.useBiosFile ? true : false);
+ }
+
+
+
+ gbReset();
+ theApp.emulator = GBSystem;
+ gbBorderOn = theApp.winGbBorderOn;
+ theApp.romSize = gbRomSize;
+
+
+ if(theApp.autoIPS) {
+ int size = gbRomSize;
+ utilApplyIPS(ipsname, &gbRom, &size);
+ if(size != gbRomSize) {
+ extern bool gbUpdateSizes();
+ gbUpdateSizes();
+ gbReset();
+ theApp.romSize = size;
+ }
+ }
+ } else {
+ int size = CPULoadRom(theApp.szFile);
+ if(!size)
+ return false;
+
+ theApp.romSize = size;
+
+ flashSetSize(theApp.winFlashSize);
+ rtcEnable(theApp.winRtcEnable);
+ cpuSaveType = theApp.winSaveType;
+
+ GetModuleFileName(NULL, tempName, 2048);
+
+ char *p = strrchr(tempName, '\\');
+ if(p)
+ *p = 0;
+
+ char buffer[5];
+ strncpy(buffer, (const char *)&rom[0xac], 4);
+ buffer[4] = 0;
+
+ strcat(tempName, "\\vba-over.ini");
+
+ UINT i = GetPrivateProfileInt(buffer,
+ "rtcEnabled",
+ -1,
+ tempName);
+ if(i != (UINT)-1)
+ rtcEnable(i == 0 ? false : true);
+
+ i = GetPrivateProfileInt(buffer,
+ "flashSize",
+ -1,
+ tempName);
+ if(i != (UINT)-1 && (i == 0x10000 || i == 0x20000))
+ flashSetSize((int)i);
+
+ i = GetPrivateProfileInt(buffer,
+ "saveType",
+ -1,
+ tempName);
+ if(i != (UINT)-1 && (i <= 5))
+ cpuSaveType = (int)i;
+ i = GetPrivateProfileInt(buffer,
+ "mirroringEnabled",
+ -1,
+ tempName);
+ if(i != (UINT)-1)
+ doMirroring (i == 0 ? false : true);
+
+ theApp.emulator = GBASystem;
+ /* disabled due to problems
+ if(theApp.removeIntros && rom != NULL) {
+ *((u32 *)rom)= 0xea00002e;
+ }
+ */
+
+ if(theApp.autoIPS) {
+ int size = 0x2000000;
+ utilApplyIPS(ipsname, &rom, &size);
+ if(size != 0x2000000) {
+ CPUReset();
+ }
+ }
+ }
+
+ if(theApp.soundInitialized) {
+ if(theApp.cartridgeType == 1)
+ gbSoundReset();
+ else
+ soundReset();
+ } else {
+ if(!soundOffFlag)
+ soundInit(!(theApp.cartridgeType==1));
+ theApp.soundInitialized = true;
+ }
+
+#ifdef APU_LOGGER_H
+ begin_apu_log("apu_log.txt");
+#endif
+
+ if(type == IMAGE_GBA) {
+ skipBios = theApp.skipBiosFile ? true : false;
+ CPUInit((char *)(LPCTSTR)theApp.biosFileName, theApp.useBiosFile ? true : false);
+ CPUReset();
+ }
+
+ readBatteryFile();
+
+ if(theApp.autoSaveLoadCheatList)
+ winLoadCheatListDefault();
+
+ theApp.addRecentFile(theApp.szFile);
+
+ theApp.updateWindowSize(theApp.videoOption);
+
+ theApp.updateFrameSkip();
+
+ if(theApp.autoHideMenu && theApp.videoOption > VIDEO_4X && theApp.menuToggle)
+ OnFileTogglemenu();
+
+ emulating = true;
+
+ if(theApp.autoLoadMostRecent)
+ OnFileLoadgameMostrecent();
+
+ theApp.frameskipadjust = 0;
+ theApp.renderedFrames = 0;
+ theApp.autoFrameSkipLastTime = theApp.throttleLastTime = systemGetClock();
+
+ theApp.rewindCount = 0;
+ theApp.rewindCounter = 0;
+ theApp.rewindSaveNeeded = false;
+
+ return true;
+}
+
+void MainWnd::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
+{
+ ASSERT(pMenu != NULL);
+
+ CCmdUI state;
+ state.m_pMenu = pMenu;
+ ASSERT(state.m_pOther == NULL);
+ ASSERT(state.m_pParentMenu == NULL);
+
+ // determine if menu is popup in top-level menu and set m_pOther to
+ // it if so (m_pParentMenu == NULL indicates that it is secondary popup)
+ HMENU hParentMenu;
+ if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
+ state.m_pParentMenu = pMenu; // parent == child for tracking popup
+ else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL) {
+ CWnd* pParent = GetTopLevelParent();
+ // child windows don't have menus -- need to go to the top!
+ if (pParent != NULL &&
+ (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL) {
+ int nIndexMax = ::GetMenuItemCount(hParentMenu);
+ for (int nIndex = 0; nIndex < nIndexMax; nIndex++) {
+ if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu) {
+ // when popup is found, m_pParentMenu is containing menu
+ state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
+ break;
+ }
+ }
+ }
+ }
+
+ state.m_nIndexMax = pMenu->GetMenuItemCount();
+ for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
+ state.m_nIndex++) {
+ state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
+ if (state.m_nID == 0)
+ continue; // menu separator or invalid cmd - ignore it
+
+ ASSERT(state.m_pOther == NULL);
+ ASSERT(state.m_pMenu != NULL);
+ if (state.m_nID == (UINT)-1) {
+ // possibly a popup menu, route to first item of that popup
+ state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
+ if (state.m_pSubMenu == NULL ||
+ (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
+ state.m_nID == (UINT)-1) {
+ continue; // first item of popup can't be routed to
+ }
+ state.DoUpdate(this, FALSE); // popups are never auto disabled
+ } else {
+ // normal menu item
+ // Auto enable/disable if frame window has 'm_bAutoMenuEnable'
+ // set and command is _not_ a system command.
+ state.m_pSubMenu = NULL;
+ state.DoUpdate(this, state.m_nID < 0xF000);
+ }
+
+ // adjust for menu deletions and additions
+ UINT nCount = pMenu->GetMenuItemCount();
+ if (nCount < state.m_nIndexMax) {
+ state.m_nIndex -= (state.m_nIndexMax - nCount);
+ while (state.m_nIndex < nCount &&
+ pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID) {
+ state.m_nIndex++;
+ }
+ }
+ state.m_nIndexMax = nCount;
+ }
+}
+
+void MainWnd::OnMove(int x, int y)
+{
+ CWnd::OnMove(x, y);
+
+ if(!theApp.changingVideoSize) {
+ if(this) {
+ if(!IsIconic()) {
+ RECT r;
+
+ GetWindowRect(&r);
+ theApp.windowPositionX = r.left;
+ theApp.windowPositionY = r.top;
+ theApp.adjustDestRect();
+ regSetDwordValue("windowX", theApp.windowPositionX);
+ regSetDwordValue("windowY", theApp.windowPositionY);
+ }
+ }
+ }
+}
+
+void MainWnd::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+
+ if(!theApp.changingVideoSize) {
+ if(this) {
+ if(!IsIconic()) {
+ if(theApp.iconic) {
+ if(emulating) {
+ soundResume();
+ theApp.paused = false;
+ }
+ }
+ if(theApp.videoOption <= VIDEO_4X) {
+ theApp.surfaceSizeX = cx;
+ theApp.surfaceSizeY = cy;
+ theApp.adjustDestRect();
+ if(theApp.display)
+ theApp.display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top);
+ }
+ } else {
+ if(emulating) {
+ if(!theApp.paused) {
+ theApp.paused = true;
+ soundPause();
+ }
+ }
+ theApp.iconic = true;
+ }
+ }
+ }
+}
+
+void MainWnd::winSaveCheatListDefault()
+{
+ CString name;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ name = theApp.filename;
+ CString dir = regQueryStringValue("saveDir", NULL);
+ if( dir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, dir );
+ dir = baseDir;
+ }
+
+ if(!dir.GetLength())
+ dir = getDirFromFile(filename);
+
+ if(isDriveRoot(dir))
+ filename.Format("%s%s.clt", dir, name);
+ else
+ filename.Format("%s\\%s.clt", dir, name);
+
+ winSaveCheatList(filename);
+}
+
+void MainWnd::winSaveCheatList(const char *name)
+{
+ if(theApp.cartridgeType == 0)
+ cheatsSaveCheatList(name);
+ else
+ gbCheatsSaveCheatList(name);
+}
+
+void MainWnd::winLoadCheatListDefault()
+{
+ CString name;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ name = theApp.filename;
+ CString dir = regQueryStringValue("saveDir", NULL);
+ if( dir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, dir );
+ dir = baseDir;
+ }
+
+ if(!dir.GetLength())
+ dir = getDirFromFile(filename);
+
+ if(isDriveRoot(dir))
+ filename.Format("%s%s.clt", dir, name);
+ else
+ filename.Format("%s\\%s.clt", dir, name);
+
+ winLoadCheatList(filename);
+}
+
+void MainWnd::winLoadCheatList(const char *name)
+{
+ bool res = false;
+
+ if(theApp.cartridgeType == 0)
+ res = cheatsLoadCheatList(name);
+ else
+ res = gbCheatsLoadCheatList(name);
+
+ if(res)
+ systemScreenMessage(winResLoadString(IDS_LOADED_CHEATS));
+}
+
+CString MainWnd::getDirFromFile(CString& file)
+{
+ CString temp = file;
+ int index = temp.ReverseFind('\\');
+
+ if(index != -1) {
+ temp = temp.Left(index);
+ if(temp.GetLength() == 2 && temp[1] == ':')
+ temp += "\\";
+ } else {
+ temp = "";
+ }
+ return temp;
+}
+
+bool MainWnd::isDriveRoot(CString& file)
+{
+ if(file.GetLength() == 3) {
+ if(file[1] == ':' && file[2] == '\\')
+ return true;
+ }
+ return false;
+}
+
+void MainWnd::writeBatteryFile()
+{
+ CString buffer;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ buffer = theApp.filename;
+
+ CString saveDir = regQueryStringValue("batteryDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(isDriveRoot(saveDir))
+ filename.Format("%s%s.sav", saveDir, buffer);
+ else
+ filename.Format("%s\\%s.sav", saveDir, buffer);
+
+ if(theApp.emulator.emuWriteBattery)
+ theApp.emulator.emuWriteBattery(filename);
+}
+
+
+void MainWnd::readBatteryFile()
+{
+ CString buffer;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ buffer = theApp.filename;
+
+ CString saveDir = regQueryStringValue("batteryDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(isDriveRoot(saveDir))
+ filename.Format("%s%s.sav", saveDir, buffer);
+ else
+ filename.Format("%s\\%s.sav", saveDir, buffer);
+
+ bool res = false;
+
+ if(theApp.emulator.emuReadBattery)
+ res = theApp.emulator.emuReadBattery(filename);
+
+ if(res)
+ systemScreenMessage(winResLoadString(IDS_LOADED_BATTERY));
+}
+
+CString MainWnd::winLoadFilter(UINT id)
+{
+ CString res = winResLoadString(id);
+ res.Replace('_','|');
+
+ return res;
+}
+
+bool MainWnd::loadSaveGame(const char *name)
+{
+ if(theApp.emulator.emuReadState)
+ return theApp.emulator.emuReadState(name);
+ return false;
+}
+
+bool MainWnd::writeSaveGame(const char *name)
+{
+ if(theApp.emulator.emuWriteState)
+ return theApp.emulator.emuWriteState(name);
+ return false;
+}
+
+void MainWnd::OnContextMenu(CWnd* pWnd, CPoint point)
+{
+ winMouseOn();
+ if(theApp.skin) {
+ if(theApp.popup == NULL) {
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+ theApp.popup = CreatePopupMenu();
+ if(theApp.menu != NULL) {
+ int count = GetMenuItemCount(theApp.menu);
+ OSVERSIONINFO info;
+ info.dwOSVersionInfoSize = sizeof(info);
+ GetVersionEx(&info);
+
+ if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+ for(int i = 0; i < count; i++) {
+ char buffer[256];
+ MENUITEMINFO info;
+ ZeroMemory(&info, sizeof(info));
+ info.cbSize = sizeof(info) - sizeof(HBITMAP);
+ info.fMask = MIIM_STRING | MIIM_SUBMENU;
+ info.dwTypeData = buffer;
+ info.cch = 256;
+ if(!GetMenuItemInfo(theApp.menu, i, MF_BYPOSITION, &info)) {
+ }
+ if(!AppendMenu(theApp.popup, MF_POPUP|MF_STRING, (UINT_PTR)info.hSubMenu, buffer)) {
+ }
+ }
+ } else {
+ for(int i = 0; i < count; i++) {
+ wchar_t buffer[256];
+ MENUITEMINFOW info;
+ ZeroMemory(&info, sizeof(info));
+ info.cbSize = sizeof(info) - sizeof(HBITMAP);
+ info.fMask = MIIM_STRING | MIIM_SUBMENU;
+ info.dwTypeData = buffer;
+ info.cch = 256;
+ if(!GetMenuItemInfoW(theApp.menu, i, MF_BYPOSITION, &info)) {
+ }
+ if(!AppendMenuW(theApp.popup, MF_POPUP|MF_STRING, (UINT_PTR)info.hSubMenu, buffer)) {
+ }
+ }
+ }
+ }
+ }
+ int x = point.x;
+ int y = point.y;
+ if(x == -1 && y == -1) {
+ x = (theApp.dest.left + theApp.dest.right) / 2;
+ y = (theApp.dest.top + theApp.dest.bottom) / 2;
+ }
+ if(!TrackPopupMenu(theApp.popup, 0, x, y, 0, m_hWnd, NULL)) {
+ }
+ }
+}
+
+void MainWnd::OnSystemMinimize()
+{
+ ShowWindow(SW_SHOWMINIMIZED);
+}
+
+
+bool MainWnd::fileOpenSelect( bool gb )
+{
+ theApp.dir = _T("");
+ CString initialDir;
+ if( gb ) {
+ initialDir = regQueryStringValue( _T("gbromdir"), _T(".") );
+ } else {
+ initialDir = regQueryStringValue( _T("romdir"), _T(".") );
+ }
+
+ if( initialDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, initialDir );
+ initialDir = baseDir;
+ }
+
+ if( !initialDir.IsEmpty() ) {
+ theApp.dir = initialDir;
+ }
+
+ int selectedFilter = 0;
+ if( !gb ) {
+ selectedFilter = regQueryDwordValue( _T("selectedFilter"), 0);
+ if( (selectedFilter < 0) || (selectedFilter > 2) ) {
+ selectedFilter = 0;
+ }
+ }
+
+ theApp.szFile = _T("");
+
+ LPCTSTR exts[] = { _T(""), _T(""), _T(""), _T("") };
+ CString filter;
+ CString title;
+ if( gb ) {
+ filter = winLoadFilter( IDS_FILTER_GBROM );
+ title = winResLoadString( IDS_SELECT_ROM );
+ } else {
+ filter = winLoadFilter( IDS_FILTER_ROM );
+ title = winResLoadString( IDS_SELECT_ROM );
+ }
+
+ FileDlg dlg( this, _T(""), filter, selectedFilter, _T(""), exts, theApp.dir, title, false);
+
+ if( dlg.DoModal() == IDOK ) {
+ if( !gb ) {
+ regSetDwordValue( _T("selectedFilter"), dlg.m_ofn.nFilterIndex );
+ }
+ theApp.szFile = dlg.GetPathName();
+ theApp.dir = theApp.szFile.Left( dlg.m_ofn.nFileOffset );
+ if( (theApp.dir.GetLength() > 3) && (theApp.dir[theApp.dir.GetLength()-1] == _T('\\')) ) {
+ theApp.dir = theApp.dir.Left( theApp.dir.GetLength() - 1 );
+ }
+ SetCurrentDirectory( theApp.dir );
+ return true;
+ }
+ return false;
+}
+
+
+void MainWnd::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+
+ if(emulating) {
+ theApp.painting = true;
+ systemDrawScreen();
+ theApp.painting = false;
+ theApp.renderedFrames--;
+ }
+}
+
+BOOL MainWnd::PreTranslateMessage(MSG* pMsg)
+{
+ if (CWnd::PreTranslateMessage(pMsg))
+ return TRUE;
+
+ if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) {
+ return theApp.hAccel != NULL && ::TranslateAccelerator(m_hWnd, theApp.hAccel, pMsg);
+ }
+
+ return FALSE;
+}
+
+void MainWnd::screenCapture(int captureNumber)
+{
+ CString buffer;
+
+ CString captureDir = regQueryStringValue("captureDir", "");
+ if( captureDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, captureDir );
+ captureDir = baseDir;
+ }
+ int index = theApp.filename.ReverseFind('\\');
+
+ CString name;
+ if(index != -1)
+ name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ name = theApp.filename;
+
+ if(captureDir.IsEmpty())
+ captureDir = getDirFromFile(theApp.filename);
+
+ LPCTSTR ext = "png";
+ if(theApp.captureFormat != 0)
+ ext = "bmp";
+
+ if(isDriveRoot(captureDir))
+ buffer.Format("%s%s_%02d.%s",
+ captureDir,
+ name,
+ captureNumber,
+ ext);
+ else
+ buffer.Format("%s\\%s_%02d.%s",
+ captureDir,
+ name,
+ captureNumber,
+ ext);
+
+ // check if file exists
+ DWORD dwAttr = GetFileAttributes( buffer );
+ if( dwAttr != INVALID_FILE_ATTRIBUTES ) {
+ // screenshot file already exists
+ screenCapture(++captureNumber);
+ // this will recursively use the first non-existent screenshot number
+ return;
+ }
+
+ if(theApp.captureFormat == 0)
+ theApp.emulator.emuWritePNG(buffer);
+ else
+ theApp.emulator.emuWriteBMP(buffer);
+
+ CString msg = winResLoadString(IDS_SCREEN_CAPTURE);
+ systemScreenMessage(msg);
+}
+
+void MainWnd::winMouseOn()
+{
+ SetCursor(arrow);
+ if(theApp.videoOption > VIDEO_4X) {
+ theApp.mouseCounter = 10;
+ } else
+ theApp.mouseCounter = 0;
+}
+
+void MainWnd::OnMouseMove(UINT nFlags, CPoint point)
+{
+ winMouseOn();
+
+ CWnd::OnMouseMove(nFlags, point);
+}
+
+void MainWnd::OnInitMenu(CMenu* pMenu)
+{
+ CWnd::OnInitMenu(pMenu);
+
+ soundPause();
+}
+
+void MainWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
+{
+ CWnd::OnActivate(nState, pWndOther, bMinimized);
+
+ bool a = (nState == WA_ACTIVE) || (nState == WA_CLICKACTIVE);
+
+ if(a && theApp.input) {
+ theApp.active = a;
+ theApp.input->activate();
+ if(!theApp.paused) {
+ if(emulating) {
+ soundResume();
+ }
+ }
+ } else {
+ theApp.wasPaused = true;
+ if(theApp.pauseWhenInactive) {
+ if(emulating) {
+ soundPause();
+ }
+ theApp.active = a;
+ }
+
+ memset(theApp.delta,255,sizeof(theApp.delta));
+ }
+
+ if(theApp.paused && emulating)
+ {
+ theApp.painting = true;
+ systemDrawScreen();
+ theApp.painting = false;
+ theApp.renderedFrames--;
+ }
+}
+
+#if _MSC_VER <= 1200
+void MainWnd::OnActivateApp(BOOL bActive, HTASK hTask)
+#else
+void MainWnd::OnActivateApp(BOOL bActive, DWORD hTask)
+#endif
+{
+ CWnd::OnActivateApp(bActive, hTask);
+
+ if(theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) {
+ if(bActive) {
+ if(theApp.display)
+ theApp.display->clear();
+ }
+ }
+}
+
+void MainWnd::OnDropFiles(HDROP hDropInfo)
+{
+ char szFile[1024];
+
+ if(DragQueryFile(hDropInfo,
+ 0,
+ szFile,
+ 1024)) {
+ theApp.szFile = szFile;
+ if(FileRun()) {
+ SetForegroundWindow();
+ emulating = TRUE;
+ } else {
+ emulating = FALSE;
+ soundPause();
+ }
+ }
+ DragFinish(hDropInfo);
+}
+
+LRESULT MainWnd::OnMySysCommand(WPARAM wParam, LPARAM lParam)
+{
+ if(emulating && !theApp.paused) {
+ if((wParam&0xFFF0) == SC_SCREENSAVE || (wParam&0xFFF0) == SC_MONITORPOWER)
+ return 0;
+ }
+ return Default();
+}
+
diff --git a/src/win32/MainWnd.h b/src/win32/MainWnd.h
index 6407b415..14c3404f 100644
--- a/src/win32/MainWnd.h
+++ b/src/win32/MainWnd.h
@@ -1,442 +1,446 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#if !defined(AFX_MAINWND_H__E8AD28B9_C9FB_4EC2_A2DC_DD1BBA55A275__INCLUDED_)
-#define AFX_MAINWND_H__E8AD28B9_C9FB_4EC2_A2DC_DD1BBA55A275__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// MainWnd.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// MainWnd window
-
-class MainWnd : public CWnd
-{
- // Construction
- public:
- MainWnd();
-
- // Attributes
- public:
-
- // Operations
- public:
- bool FileRun();
-
- // Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(MainWnd)
- public:
- virtual BOOL PreTranslateMessage(MSG* pMsg);
- //}}AFX_VIRTUAL
-
- // Implementation
- public:
- HCURSOR arrow;
- void winMouseOn();
- void screenCapture(int captureNumber);
- HACCEL m_hAccelTable;
- bool fileOpenSelect();
- afx_msg LRESULT OnConfirmMode(WPARAM, LPARAM);
- afx_msg LRESULT OnMySysCommand(WPARAM, LPARAM);
- afx_msg void OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI);
- afx_msg void OnUpdateFileSaveGameSlot(CCmdUI *pCmdUI);
- afx_msg void OnUpdateOptionsJoypadAutofire(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsJoypadAutofire(UINT nID);
- afx_msg void OnUpdateOptionsJoypadDefault(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsJoypadDefault(UINT nID);
- afx_msg void OnUpdateOptionsFilterIFB(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsFilterIFB(UINT nID);
- afx_msg void OnUpdateOptionsFilter(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsFilter(UINT nID);
- afx_msg void OnUpdateOptionsPriority(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsPriority(UINT nID);
- afx_msg void OnSetFocus(CWnd * pOldWnd);
- afx_msg void OnKillFocus(CWnd * pNewWnd);
-
- void updateSoundChannels(UINT nID);
- afx_msg void OnUpdateOptionsSoundVolume(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsSoundVolume(UINT nID);
- afx_msg void OnUpdateOptionsEmulatorShowSpeed(CCmdUI *pCmdUI);
- afx_msg BOOL OnOptionsEmulatorShowSpeed(UINT nID);
- afx_msg void OnSystemMinimize();
- afx_msg void OnUpdateVideoLayer(CCmdUI* pCmdUI);
- afx_msg BOOL OnVideoLayer(UINT nID);
- void winConfirmMode();
- afx_msg BOOL OnOptionVideoSize(UINT nID);
- afx_msg BOOL OnOptionsFrameskip(UINT nID);
- bool fileImportGSACodeFile(CString& fileName);
- bool writeSaveGame(const char *name);
- bool loadSaveGame(const char *name);
- CString winLoadFilter(UINT id);
- void winLoadCheatList(const char *name);
- void winLoadCheatListDefault();
- void readBatteryFile();
- void writeBatteryFile();
- bool isDriveRoot(CString& file);
- CString getDirFromFile(CString& file);
- void winSaveCheatList(const char *name);
- void winSaveCheatListDefault();
- virtual ~MainWnd();
-
- // Generated message map functions
- protected:
- //{{AFX_MSG(MainWnd)
- afx_msg void OnClose();
- afx_msg void OnHelpAbout();
- afx_msg void OnHelpFaq();
- afx_msg void OnFileOpen();
- afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
- afx_msg void OnFilePause();
- afx_msg void OnUpdateFilePause(CCmdUI* pCmdUI);
- afx_msg void OnFileReset();
- afx_msg void OnUpdateFileReset(CCmdUI* pCmdUI);
- afx_msg void OnUpdateFileRecentFreeze(CCmdUI* pCmdUI);
- afx_msg void OnFileRecentReset();
- afx_msg void OnFileRecentFreeze();
- afx_msg void OnFileExit();
- afx_msg void OnFileClose();
- afx_msg void OnUpdateFileClose(CCmdUI* pCmdUI);
- afx_msg void OnFileOpengameboy();
- afx_msg void OnFileLoad();
- afx_msg void OnUpdateFileLoad(CCmdUI* pCmdUI);
- afx_msg void OnFileSave();
- afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI);
- afx_msg void OnFileImportBatteryfile();
- afx_msg void OnUpdateFileImportBatteryfile(CCmdUI* pCmdUI);
- afx_msg void OnFileImportGamesharkcodefile();
- afx_msg void OnUpdateFileImportGamesharkcodefile(CCmdUI* pCmdUI);
- afx_msg void OnFileImportGamesharksnapshot();
- afx_msg void OnUpdateFileImportGamesharksnapshot(CCmdUI* pCmdUI);
- afx_msg void OnFileExportBatteryfile();
- afx_msg void OnUpdateFileExportBatteryfile(CCmdUI* pCmdUI);
- afx_msg void OnFileExportGamesharksnapshot();
- afx_msg void OnUpdateFileExportGamesharksnapshot(CCmdUI* pCmdUI);
- afx_msg void OnFileScreencapture();
- afx_msg void OnUpdateFileScreencapture(CCmdUI* pCmdUI);
- afx_msg void OnFileRominformation();
- afx_msg void OnUpdateFileRominformation(CCmdUI* pCmdUI);
- afx_msg void OnFileTogglemenu();
- afx_msg void OnUpdateFileTogglemenu(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsFrameskipThrottleOther(CCmdUI* pCmdUI);
- afx_msg void OnOptionsFrameskipThrottleNothrottle();
- afx_msg void OnOptionsFrameskipThrottle25();
- afx_msg void OnOptionsFrameskipThrottle50();
- afx_msg void OnOptionsFrameskipThrottle100();
- afx_msg void OnOptionsFrameskipThrottle150();
- afx_msg void OnOptionsFrameskipThrottle200();
- afx_msg void OnOptionsFrameskipThrottleOther();
- afx_msg void OnOptionsFrameskipAutomatic();
- afx_msg void OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip0(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip1(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip2(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip3(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip4(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip5(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip6(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip7(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip8(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFrameskip9(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoVsync();
- afx_msg void OnUpdateOptionsVideoVsync(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoX1(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoX2(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoX3(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoX4(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFullscreen320x240(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFullscreen640x480(CCmdUI* pCmdUI);
- afx_msg void OnUpdateOptionsVideoFullscreen800x600(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoFullscreen320x240();
- afx_msg void OnOptionsVideoFullscreen640x480();
- afx_msg void OnOptionsVideoFullscreen800x600();
- afx_msg void OnOptionsVideoFullscreen();
- afx_msg void OnUpdateOptionsVideoFullscreen(CCmdUI* pCmdUI);
- afx_msg void OnMove(int x, int y);
- afx_msg void OnSize(UINT nType, int cx, int cy);
- afx_msg void OnOptionsVideoDisablesfx();
- afx_msg void OnUpdateOptionsVideoDisablesfx(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoFullscreenstretchtofit();
- afx_msg void OnUpdateOptionsVideoFullscreenstretchtofit(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRendermethodGdi();
- afx_msg void OnUpdateOptionsVideoRendermethodGdi(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRendermethodDirectdraw();
- afx_msg void OnUpdateOptionsVideoRendermethodDirectdraw(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRendermethodDirect3d();
- afx_msg void OnUpdateOptionsVideoRendermethodDirect3d(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRendermethodOpengl();
- afx_msg void OnUpdateOptionsVideoRendermethodOpengl(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoTriplebuffering();
- afx_msg void OnUpdateOptionsVideoTriplebuffering(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoDdrawemulationonly();
- afx_msg void OnUpdateOptionsVideoDdrawemulationonly(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoDdrawusevideomemory();
- afx_msg void OnUpdateOptionsVideoDdrawusevideomemory(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRenderoptionsD3dnofilter();
- afx_msg void OnUpdateOptionsVideoRenderoptionsD3dnofilter(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRenderoptionsD3dbilinear();
- afx_msg void OnUpdateOptionsVideoRenderoptionsD3dbilinear(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRenderoptionsGlnearest();
- afx_msg void OnUpdateOptionsVideoRenderoptionsGlnearest(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRenderoptionsGlbilinear();
- afx_msg void OnUpdateOptionsVideoRenderoptionsGlbilinear(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRenderoptionsGltriangle();
- afx_msg void OnUpdateOptionsVideoRenderoptionsGltriangle(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoRenderoptionsGlquads();
- afx_msg void OnUpdateOptionsVideoRenderoptionsGlquads(CCmdUI* pCmdUI);
- afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
- afx_msg void OnOptionsEmulatorAssociate();
- afx_msg void OnOptionsEmulatorDirectories();
- afx_msg void OnOptionsEmulatorDisablestatusmessages();
- afx_msg void OnUpdateOptionsEmulatorDisablestatusmessages(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSynchronize();
- afx_msg void OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorPausewheninactive();
- afx_msg void OnUpdateOptionsEmulatorPausewheninactive(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSpeeduptoggle();
- afx_msg void OnUpdateOptionsEmulatorSpeeduptoggle(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorRemoveintrosgba();
- afx_msg void OnUpdateOptionsEmulatorRemoveintrosgba(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorAutomaticallyipspatch();
- afx_msg void OnUpdateOptionsEmulatorAutomaticallyipspatch(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorAgbprint();
- afx_msg void OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorRealtimeclock();
- afx_msg void OnUpdateOptionsEmulatorRealtimeclock(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorAutohidemenu();
- afx_msg void OnUpdateOptionsEmulatorAutohidemenu(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorRewindinterval();
- afx_msg void OnOptionsEmulatorSavetypeAutomatic();
- afx_msg void OnUpdateOptionsEmulatorSavetypeAutomatic(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeEeprom();
- afx_msg void OnUpdateOptionsEmulatorSavetypeEeprom(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeSram();
- afx_msg void OnUpdateOptionsEmulatorSavetypeSram(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeFlash();
- afx_msg void OnUpdateOptionsEmulatorSavetypeFlash(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeEepromsensor();
- afx_msg void OnUpdateOptionsEmulatorSavetypeEepromsensor(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeNone();
- afx_msg void OnUpdateOptionsEmulatorSavetypeNone(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeFlash512k();
- afx_msg void OnUpdateOptionsEmulatorSavetypeFlash512k(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSavetypeFlash1m();
- afx_msg void OnUpdateOptionsEmulatorSavetypeFlash1m(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorUsebiosfile();
- afx_msg void OnUpdateOptionsEmulatorUsebiosfile(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSkipbios();
- afx_msg void OnUpdateOptionsEmulatorSkipbios(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorSelectbiosfile();
- afx_msg void OnOptionsEmulatorPngformat();
- afx_msg void OnUpdateOptionsEmulatorPngformat(CCmdUI* pCmdUI);
- afx_msg void OnOptionsEmulatorBmpformat();
- afx_msg void OnUpdateOptionsEmulatorBmpformat(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundOff(); /* mute hax */
- afx_msg void OnUpdateOptionsSoundOff(CCmdUI* pCmdUI); /* mute hax */
- afx_msg void OnOptionsSoundMute();
- afx_msg void OnUpdateOptionsSoundMute(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundOn();
- afx_msg void OnUpdateOptionsSoundOn(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundUseoldsynchronization();
- afx_msg void OnUpdateOptionsSoundUseoldsynchronization(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundEcho();
- afx_msg void OnUpdateOptionsSoundEcho(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundLowpassfilter();
- afx_msg void OnUpdateOptionsSoundLowpassfilter(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundReversestereo();
- afx_msg void OnUpdateOptionsSoundReversestereo(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSound11khz();
- afx_msg void OnUpdateOptionsSound11khz(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSound22khz();
- afx_msg void OnUpdateOptionsSound22khz(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSound44khz();
- afx_msg void OnUpdateOptionsSound44khz(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundChannel1();
- afx_msg void OnUpdateOptionsSoundChannel1(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundChannel2();
- afx_msg void OnUpdateOptionsSoundChannel2(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundChannel3();
- afx_msg void OnUpdateOptionsSoundChannel3(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundChannel4();
- afx_msg void OnUpdateOptionsSoundChannel4(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundDirectsounda();
- afx_msg void OnUpdateOptionsSoundDirectsounda(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundDirectsoundb();
- afx_msg void OnUpdateOptionsSoundDirectsoundb(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyBorder();
- afx_msg void OnUpdateOptionsGameboyBorder(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyPrinter();
- afx_msg void OnUpdateOptionsGameboyPrinter(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyBorderAutomatic();
- afx_msg void OnUpdateOptionsGameboyBorderAutomatic(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyAutomatic();
- afx_msg void OnUpdateOptionsGameboyAutomatic(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyGba();
- afx_msg void OnUpdateOptionsGameboyGba(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyCgb();
- afx_msg void OnUpdateOptionsGameboyCgb(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboySgb();
- afx_msg void OnUpdateOptionsGameboySgb(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboySgb2();
- afx_msg void OnUpdateOptionsGameboySgb2(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyGb();
- afx_msg void OnUpdateOptionsGameboyGb(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyRealcolors();
- afx_msg void OnUpdateOptionsGameboyRealcolors(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyGameboycolors();
- afx_msg void OnUpdateOptionsGameboyGameboycolors(CCmdUI* pCmdUI);
- afx_msg void OnOptionsGameboyColors();
- afx_msg void OnOptionsFilterDisablemmx();
- afx_msg void OnUpdateOptionsFilterDisablemmx(CCmdUI* pCmdUI);
- afx_msg void OnOptionsLanguageSystem();
- afx_msg void OnUpdateOptionsLanguageSystem(CCmdUI* pCmdUI);
- afx_msg void OnOptionsLanguageEnglish();
- afx_msg void OnUpdateOptionsLanguageEnglish(CCmdUI* pCmdUI);
- afx_msg void OnOptionsLanguageOther();
- afx_msg void OnUpdateOptionsLanguageOther(CCmdUI* pCmdUI);
- afx_msg void OnOptionsJoypadConfigure1();
- afx_msg void OnUpdateOptionsJoypadConfigure1(CCmdUI* pCmdUI);
- afx_msg void OnOptionsJoypadConfigure2();
- afx_msg void OnUpdateOptionsJoypadConfigure2(CCmdUI* pCmdUI);
- afx_msg void OnOptionsJoypadConfigure3();
- afx_msg void OnUpdateOptionsJoypadConfigure3(CCmdUI* pCmdUI);
- afx_msg void OnOptionsJoypadConfigure4();
- afx_msg void OnUpdateOptionsJoypadConfigure4(CCmdUI* pCmdUI);
- afx_msg void OnOptionsJoypadMotionconfigure();
- afx_msg void OnUpdateOptionsJoypadMotionconfigure(CCmdUI* pCmdUI);
- afx_msg void OnCheatsSearchforcheats();
- afx_msg void OnUpdateCheatsSearchforcheats(CCmdUI* pCmdUI);
- afx_msg void OnCheatsCheatlist();
- afx_msg void OnUpdateCheatsCheatlist(CCmdUI* pCmdUI);
- afx_msg void OnCheatsAutomaticsaveloadcheats();
- afx_msg void OnCheatsLoadcheatlist();
- afx_msg void OnUpdateCheatsLoadcheatlist(CCmdUI* pCmdUI);
- afx_msg void OnCheatsSavecheatlist();
- afx_msg void OnUpdateCheatsSavecheatlist(CCmdUI* pCmdUI);
- afx_msg void OnToolsDisassemble();
- afx_msg void OnUpdateToolsDisassemble(CCmdUI* pCmdUI);
- afx_msg void OnToolsLogging();
- afx_msg void OnUpdateToolsLogging(CCmdUI* pCmdUI);
- afx_msg void OnToolsIoviewer();
- afx_msg void OnUpdateToolsIoviewer(CCmdUI* pCmdUI);
- afx_msg void OnToolsMapview();
- afx_msg void OnUpdateToolsMapview(CCmdUI* pCmdUI);
- afx_msg void OnToolsMemoryviewer();
- afx_msg void OnUpdateToolsMemoryviewer(CCmdUI* pCmdUI);
- afx_msg void OnToolsOamviewer();
- afx_msg void OnUpdateToolsOamviewer(CCmdUI* pCmdUI);
- afx_msg void OnToolsPaletteview();
- afx_msg void OnUpdateToolsPaletteview(CCmdUI* pCmdUI);
- afx_msg void OnToolsTileviewer();
- afx_msg void OnUpdateToolsTileviewer(CCmdUI* pCmdUI);
- afx_msg void OnDebugNextframe();
- afx_msg void OnUpdateCheatsAutomaticsaveloadcheats(CCmdUI* pCmdUI);
- afx_msg void OnToolsDebugGdb();
- afx_msg void OnUpdateToolsDebugGdb(CCmdUI* pCmdUI);
- afx_msg void OnToolsDebugLoadandwait();
- afx_msg void OnUpdateToolsDebugLoadandwait(CCmdUI* pCmdUI);
- afx_msg void OnToolsDebugBreak();
- afx_msg void OnUpdateToolsDebugBreak(CCmdUI* pCmdUI);
- afx_msg void OnToolsDebugDisconnect();
- afx_msg void OnUpdateToolsDebugDisconnect(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundStartrecording();
- afx_msg void OnUpdateOptionsSoundStartrecording(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundStoprecording();
- afx_msg void OnUpdateOptionsSoundStoprecording(CCmdUI* pCmdUI);
- afx_msg void OnToolsRecordStartavirecording();
- afx_msg void OnUpdateToolsRecordStartavirecording(CCmdUI* pCmdUI);
- afx_msg void OnToolsRecordStopavirecording();
- afx_msg void OnUpdateToolsRecordStopavirecording(CCmdUI* pCmdUI);
- afx_msg void OnPaint();
- afx_msg void OnToolsRecordStartmovierecording();
- afx_msg void OnUpdateToolsRecordStartmovierecording(CCmdUI* pCmdUI);
- afx_msg void OnToolsRecordStopmovierecording();
- afx_msg void OnUpdateToolsRecordStopmovierecording(CCmdUI* pCmdUI);
- afx_msg void OnToolsPlayStartmovieplaying();
- afx_msg void OnUpdateToolsPlayStartmovieplaying(CCmdUI* pCmdUI);
- afx_msg void OnToolsPlayStopmovieplaying();
- afx_msg void OnUpdateToolsPlayStopmovieplaying(CCmdUI* pCmdUI);
- afx_msg void OnToolsRewind();
- afx_msg void OnUpdateToolsRewind(CCmdUI* pCmdUI);
- afx_msg void OnToolsCustomize();
- afx_msg void OnUpdateToolsCustomize(CCmdUI* pCmdUI);
- afx_msg void OnHelpBugreport();
- afx_msg void OnMouseMove(UINT nFlags, CPoint point);
- afx_msg void OnInitMenu(CMenu* pMenu);
- afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
-#if _MSC_VER <= 1200
- afx_msg void OnActivateApp(BOOL bActive, HTASK hTask);
-#else
- afx_msg void OnActivateApp(BOOL bActive, DWORD hTask);
-#endif
- afx_msg void OnDropFiles(HDROP hDropInfo);
- afx_msg void OnFileSavegameOldestslot();
- afx_msg void OnUpdateFileSavegameOldestslot(CCmdUI* pCmdUI);
- afx_msg void OnFileLoadgameMostrecent();
- afx_msg void OnUpdateFileLoadgameMostrecent(CCmdUI* pCmdUI);
- afx_msg void OnFileLoadgameAutoloadmostrecent();
- afx_msg void OnUpdateFileLoadgameAutoloadmostrecent(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundVolume25x();
- afx_msg void OnUpdateOptionsSoundVolume25x(CCmdUI* pCmdUI);
- afx_msg void OnOptionsSoundVolume5x();
- afx_msg void OnUpdateOptionsSoundVolume5x(CCmdUI* pCmdUI);
- afx_msg void OnCheatsDisablecheats();
- afx_msg void OnUpdateCheatsDisablecheats(CCmdUI* pCmdUI);
- afx_msg void OnOptionsVideoFullscreenmaxscale();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-
- afx_msg BOOL OnFileRecentFile(UINT nID);
- afx_msg BOOL OnFileLoadSlot(UINT nID);
- afx_msg BOOL OnFileSaveSlot(UINT nID);
- afx_msg void OnOptionsFilterLcdcolors();
- afx_msg void OnUpdateOptionsFilterLcdcolors(CCmdUI *pCmdUI);
-
- afx_msg BOOL OnOptionsSoundPcminterpolation(UINT nID);
- afx_msg void OnUpdateOptionsSoundPcminterpolation(CCmdUI *pCmdUI);
-public:
- afx_msg void OnOptionsVideoFullscreen1280x1024();
- afx_msg void OnOptionsVideoFullscreen1024x768();
- afx_msg void OnUpdateOptionsVideoFullscreen1024x768(CCmdUI *pCmdUI);
- afx_msg void OnUpdateOptionsVideoFullscreen1280x1024(CCmdUI *pCmdUI);
- void OnLinkOptions();
- void OnOptionsLinkLog() ;
- void OnUpdateOptionsLinkLog(CCmdUI* pCmdUI) ;
- void OnOptionsLinkRFU() ;
- void OnUpdateOptionsLinkRFU(CCmdUI* pCmdUI) ;
-
-
-
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_MAINWND_H__E8AD28B9_C9FB_4EC2_A2DC_DD1BBA55A275__INCLUDED_)
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#if !defined(AFX_MAINWND_H__E8AD28B9_C9FB_4EC2_A2DC_DD1BBA55A275__INCLUDED_)
+#define AFX_MAINWND_H__E8AD28B9_C9FB_4EC2_A2DC_DD1BBA55A275__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// MainWnd.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// MainWnd window
+
+class MainWnd : public CWnd
+{
+ // Construction
+ public:
+ MainWnd();
+
+ // Attributes
+ public:
+
+ // Operations
+ public:
+ bool FileRun();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(MainWnd)
+ public:
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ //}}AFX_VIRTUAL
+
+ // Implementation
+ public:
+ HCURSOR arrow;
+ void winMouseOn();
+ void screenCapture(int captureNumber);
+ HACCEL m_hAccelTable;
+ bool fileOpenSelect( bool gb = false );
+ afx_msg LRESULT OnConfirmMode(WPARAM, LPARAM);
+ afx_msg LRESULT OnMySysCommand(WPARAM, LPARAM);
+ afx_msg void OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI);
+ afx_msg void OnUpdateFileSaveGameSlot(CCmdUI *pCmdUI);
+ afx_msg void OnUpdateOptionsJoypadAutofire(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsJoypadAutofire(UINT nID);
+ afx_msg void OnUpdateOptionsJoypadDefault(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsJoypadDefault(UINT nID);
+ afx_msg void OnUpdateOptionsFilterIFB(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsFilterIFB(UINT nID);
+ afx_msg void OnUpdateOptionsFilter(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsFilter(UINT nID);
+ afx_msg void OnUpdateOptionsPriority(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsPriority(UINT nID);
+ void updateSoundChannels(UINT nID);
+ afx_msg void OnUpdateOptionsSoundVolume(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsSoundVolume(UINT nID);
+ afx_msg void OnUpdateOptionsEmulatorShowSpeed(CCmdUI *pCmdUI);
+ afx_msg BOOL OnOptionsEmulatorShowSpeed(UINT nID);
+ afx_msg void OnSystemMinimize();
+ afx_msg void OnUpdateVideoLayer(CCmdUI* pCmdUI);
+ afx_msg BOOL OnVideoLayer(UINT nID);
+ void winConfirmMode();
+ afx_msg BOOL OnOptionVideoSize(UINT nID);
+ afx_msg BOOL OnOptionsFrameskip(UINT nID);
+ bool fileImportGSACodeFile(CString& fileName);
+ bool writeSaveGame(const char *name);
+ bool loadSaveGame(const char *name);
+ CString winLoadFilter(UINT id);
+ void winLoadCheatList(const char *name);
+ void winLoadCheatListDefault();
+ void readBatteryFile();
+ void writeBatteryFile();
+ bool isDriveRoot(CString& file);
+ CString getDirFromFile(CString& file);
+ void winSaveCheatList(const char *name);
+ void winSaveCheatListDefault();
+ virtual ~MainWnd();
+
+ // Generated message map functions
+ protected:
+ //{{AFX_MSG(MainWnd)
+ afx_msg void OnClose();
+ afx_msg void OnHelpAbout();
+ afx_msg void OnHelpFaq();
+ afx_msg void OnFileOpen();
+ afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
+ afx_msg void OnFilePause();
+ afx_msg void OnUpdateFilePause(CCmdUI* pCmdUI);
+ afx_msg void OnFileReset();
+ afx_msg void OnUpdateFileReset(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateFileRecentFreeze(CCmdUI* pCmdUI);
+ afx_msg void OnFileRecentReset();
+ afx_msg void OnFileRecentFreeze();
+ afx_msg void OnFileExit();
+ afx_msg void OnFileClose();
+ afx_msg void OnUpdateFileClose(CCmdUI* pCmdUI);
+ afx_msg void OnFileOpengameboy();
+ afx_msg void OnFileLoad();
+ afx_msg void OnUpdateFileLoad(CCmdUI* pCmdUI);
+ afx_msg void OnFileSave();
+ afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI);
+ afx_msg void OnFileImportBatteryfile();
+ afx_msg void OnUpdateFileImportBatteryfile(CCmdUI* pCmdUI);
+ afx_msg void OnFileImportGamesharkcodefile();
+ afx_msg void OnUpdateFileImportGamesharkcodefile(CCmdUI* pCmdUI);
+ afx_msg void OnFileImportGamesharksnapshot();
+ afx_msg void OnUpdateFileImportGamesharksnapshot(CCmdUI* pCmdUI);
+ afx_msg void OnFileExportBatteryfile();
+ afx_msg void OnUpdateFileExportBatteryfile(CCmdUI* pCmdUI);
+ afx_msg void OnFileExportGamesharksnapshot();
+ afx_msg void OnUpdateFileExportGamesharksnapshot(CCmdUI* pCmdUI);
+ afx_msg void OnFileScreencapture();
+ afx_msg void OnUpdateFileScreencapture(CCmdUI* pCmdUI);
+ afx_msg void OnFileRominformation();
+ afx_msg void OnUpdateFileRominformation(CCmdUI* pCmdUI);
+ afx_msg void OnFileTogglemenu();
+ afx_msg void OnUpdateFileTogglemenu(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsFrameskipThrottleOther(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsFrameskipThrottleNothrottle();
+ afx_msg void OnOptionsFrameskipThrottle25();
+ afx_msg void OnOptionsFrameskipThrottle50();
+ afx_msg void OnOptionsFrameskipThrottle100();
+ afx_msg void OnOptionsFrameskipThrottle150();
+ afx_msg void OnOptionsFrameskipThrottle200();
+ afx_msg void OnOptionsFrameskipThrottleOther();
+ afx_msg void OnOptionsFrameskipAutomatic();
+ afx_msg void OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip0(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip1(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip2(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip3(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip4(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip5(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip6(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip7(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip8(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFrameskip9(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoVsync();
+ afx_msg void OnUpdateOptionsVideoVsync(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoX1(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoX2(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoX3(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoX4(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFullscreen320x240(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFullscreen640x480(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFullscreen800x600(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoFullscreen320x240();
+ afx_msg void OnOptionsVideoFullscreen640x480();
+ afx_msg void OnOptionsVideoFullscreen800x600();
+ afx_msg void OnOptionsVideoFullscreen();
+ afx_msg void OnUpdateOptionsVideoFullscreen(CCmdUI* pCmdUI);
+ afx_msg void OnMove(int x, int y);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnOptionsVideoDisablesfx();
+ afx_msg void OnUpdateOptionsVideoDisablesfx(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoFullscreenstretchtofit();
+ afx_msg void OnUpdateOptionsVideoFullscreenstretchtofit(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRendermethodGdi();
+ afx_msg void OnUpdateOptionsVideoRendermethodGdi(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRendermethodDirectdraw();
+ afx_msg void OnUpdateOptionsVideoRendermethodDirectdraw(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRendermethodDirect3d();
+ afx_msg void OnUpdateOptionsVideoRendermethodDirect3d(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRendermethodOpengl();
+ afx_msg void OnUpdateOptionsVideoRendermethodOpengl(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoTriplebuffering();
+ afx_msg void OnUpdateOptionsVideoTriplebuffering(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoDdrawemulationonly();
+ afx_msg void OnUpdateOptionsVideoDdrawemulationonly(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoDdrawusevideomemory();
+ afx_msg void OnUpdateOptionsVideoDdrawusevideomemory(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsD3dnofilter();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsD3dnofilter(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsD3dbilinear();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsD3dbilinear(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsGlnearest();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsGlnearest(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsGlbilinear();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsGlbilinear(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsGltriangle();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsGltriangle(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsGlquads();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsGlquads(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsSelectskin();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsSelectskin(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoRenderoptionsSkin();
+ afx_msg void OnUpdateOptionsVideoRenderoptionsSkin(CCmdUI* pCmdUI);
+ afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+ afx_msg void OnOptionsEmulatorAssociate();
+ afx_msg void OnOptionsEmulatorDirectories();
+ afx_msg void OnOptionsEmulatorDisablestatusmessages();
+ afx_msg void OnUpdateOptionsEmulatorDisablestatusmessages(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSynchronize();
+ afx_msg void OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorPausewheninactive();
+ afx_msg void OnUpdateOptionsEmulatorPausewheninactive(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSpeeduptoggle();
+ afx_msg void OnUpdateOptionsEmulatorSpeeduptoggle(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorAutomaticallyipspatch();
+ afx_msg void OnUpdateOptionsEmulatorAutomaticallyipspatch(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorAgbprint();
+ afx_msg void OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorRealtimeclock();
+ afx_msg void OnUpdateOptionsEmulatorRealtimeclock(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorGenericflashcard();
+ afx_msg void OnUpdateOptionsEmulatorGenericflashcard(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorAutohidemenu();
+ afx_msg void OnUpdateOptionsEmulatorAutohidemenu(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorRewindinterval();
+ afx_msg void OnOptionsEmulatorSavetypeAutomatic();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeAutomatic(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeEeprom();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeEeprom(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeSram();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeSram(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeFlash();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeFlash(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeEepromsensor();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeEepromsensor(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeNone();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeNone(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeFlash512k();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeFlash512k(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSavetypeFlash1m();
+ afx_msg void OnUpdateOptionsEmulatorSavetypeFlash1m(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorUsebiosfile();
+ afx_msg void OnUpdateOptionsEmulatorUsebiosfile(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSkipbios();
+ afx_msg void OnUpdateOptionsEmulatorSkipbios(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorSelectbiosfile();
+ afx_msg void OnOptionsEmulatorPngformat();
+ afx_msg void OnUpdateOptionsEmulatorPngformat(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsEmulatorBmpformat();
+ afx_msg void OnUpdateOptionsEmulatorBmpformat(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundOff();
+ afx_msg void OnUpdateOptionsSoundOff(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundMute();
+ afx_msg void OnUpdateOptionsSoundMute(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundOn();
+ afx_msg void OnUpdateOptionsSoundOn(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundUseoldsynchronization();
+ afx_msg void OnUpdateOptionsSoundUseoldsynchronization(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundEcho();
+ afx_msg void OnUpdateOptionsSoundEcho(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundLowpassfilter();
+ afx_msg void OnUpdateOptionsSoundLowpassfilter(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundReversestereo();
+ afx_msg void OnUpdateOptionsSoundReversestereo(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSound11khz();
+ afx_msg void OnUpdateOptionsSound11khz(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSound22khz();
+ afx_msg void OnUpdateOptionsSound22khz(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSound44khz();
+ afx_msg void OnUpdateOptionsSound44khz(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundChannel1();
+ afx_msg void OnUpdateOptionsSoundChannel1(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundChannel2();
+ afx_msg void OnUpdateOptionsSoundChannel2(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundChannel3();
+ afx_msg void OnUpdateOptionsSoundChannel3(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundChannel4();
+ afx_msg void OnUpdateOptionsSoundChannel4(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundDirectsounda();
+ afx_msg void OnUpdateOptionsSoundDirectsounda(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundDirectsoundb();
+ afx_msg void OnUpdateOptionsSoundDirectsoundb(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyBorder();
+ afx_msg void OnUpdateOptionsGameboyBorder(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyPrinter();
+ afx_msg void OnUpdateOptionsGameboyPrinter(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyBorderAutomatic();
+ afx_msg void OnUpdateOptionsGameboyBorderAutomatic(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyAutomatic();
+ afx_msg void OnUpdateOptionsGameboyAutomatic(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyGba();
+ afx_msg void OnUpdateOptionsGameboyGba(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyCgb();
+ afx_msg void OnUpdateOptionsGameboyCgb(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboySgb();
+ afx_msg void OnUpdateOptionsGameboySgb(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboySgb2();
+ afx_msg void OnUpdateOptionsGameboySgb2(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyGb();
+ afx_msg void OnUpdateOptionsGameboyGb(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyRealcolors();
+ afx_msg void OnUpdateOptionsGameboyRealcolors(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyGameboycolors();
+ afx_msg void OnUpdateOptionsGameboyGameboycolors(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsGameboyColors();
+ afx_msg void OnOptionsFilterDisablemmx();
+ afx_msg void OnUpdateOptionsFilterDisablemmx(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsLanguageSystem();
+ afx_msg void OnUpdateOptionsLanguageSystem(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsLanguageEnglish();
+ afx_msg void OnUpdateOptionsLanguageEnglish(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsLanguageOther();
+ afx_msg void OnUpdateOptionsLanguageOther(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsJoypadConfigure1();
+ afx_msg void OnUpdateOptionsJoypadConfigure1(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsJoypadConfigure2();
+ afx_msg void OnUpdateOptionsJoypadConfigure2(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsJoypadConfigure3();
+ afx_msg void OnUpdateOptionsJoypadConfigure3(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsJoypadConfigure4();
+ afx_msg void OnUpdateOptionsJoypadConfigure4(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsJoypadMotionconfigure();
+ afx_msg void OnUpdateOptionsJoypadMotionconfigure(CCmdUI* pCmdUI);
+ afx_msg void OnCheatsSearchforcheats();
+ afx_msg void OnUpdateCheatsSearchforcheats(CCmdUI* pCmdUI);
+ afx_msg void OnCheatsCheatlist();
+ afx_msg void OnUpdateCheatsCheatlist(CCmdUI* pCmdUI);
+ afx_msg void OnCheatsAutomaticsaveloadcheats();
+ afx_msg void OnCheatsLoadcheatlist();
+ afx_msg void OnUpdateCheatsLoadcheatlist(CCmdUI* pCmdUI);
+ afx_msg void OnCheatsSavecheatlist();
+ afx_msg void OnUpdateCheatsSavecheatlist(CCmdUI* pCmdUI);
+ afx_msg void OnToolsDisassemble();
+ afx_msg void OnUpdateToolsDisassemble(CCmdUI* pCmdUI);
+ afx_msg void OnToolsLogging();
+ afx_msg void OnUpdateToolsLogging(CCmdUI* pCmdUI);
+ afx_msg void OnToolsIoviewer();
+ afx_msg void OnUpdateToolsIoviewer(CCmdUI* pCmdUI);
+ afx_msg void OnToolsMapview();
+ afx_msg void OnUpdateToolsMapview(CCmdUI* pCmdUI);
+ afx_msg void OnToolsMemoryviewer();
+ afx_msg void OnUpdateToolsMemoryviewer(CCmdUI* pCmdUI);
+ afx_msg void OnToolsOamviewer();
+ afx_msg void OnUpdateToolsOamviewer(CCmdUI* pCmdUI);
+ afx_msg void OnToolsPaletteview();
+ afx_msg void OnUpdateToolsPaletteview(CCmdUI* pCmdUI);
+ afx_msg void OnToolsTileviewer();
+ afx_msg void OnUpdateToolsTileviewer(CCmdUI* pCmdUI);
+ afx_msg void OnDebugNextframe();
+ afx_msg void OnUpdateCheatsAutomaticsaveloadcheats(CCmdUI* pCmdUI);
+ afx_msg void OnToolsDebugGdb();
+ afx_msg void OnUpdateToolsDebugGdb(CCmdUI* pCmdUI);
+ afx_msg void OnToolsDebugLoadandwait();
+ afx_msg void OnUpdateToolsDebugLoadandwait(CCmdUI* pCmdUI);
+ afx_msg void OnToolsDebugBreak();
+ afx_msg void OnUpdateToolsDebugBreak(CCmdUI* pCmdUI);
+ afx_msg void OnToolsDebugDisconnect();
+ afx_msg void OnUpdateToolsDebugDisconnect(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundStartrecording();
+ afx_msg void OnUpdateOptionsSoundStartrecording(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundStoprecording();
+ afx_msg void OnUpdateOptionsSoundStoprecording(CCmdUI* pCmdUI);
+ afx_msg void OnToolsRecordStartavirecording();
+ afx_msg void OnUpdateToolsRecordStartavirecording(CCmdUI* pCmdUI);
+ afx_msg void OnToolsRecordStopavirecording();
+ afx_msg void OnUpdateToolsRecordStopavirecording(CCmdUI* pCmdUI);
+ afx_msg void OnPaint();
+ afx_msg void OnToolsRecordStartmovierecording();
+ afx_msg void OnUpdateToolsRecordStartmovierecording(CCmdUI* pCmdUI);
+ afx_msg void OnToolsRecordStopmovierecording();
+ afx_msg void OnUpdateToolsRecordStopmovierecording(CCmdUI* pCmdUI);
+ afx_msg void OnToolsPlayStartmovieplaying();
+ afx_msg void OnUpdateToolsPlayStartmovieplaying(CCmdUI* pCmdUI);
+ afx_msg void OnToolsPlayStopmovieplaying();
+ afx_msg void OnUpdateToolsPlayStopmovieplaying(CCmdUI* pCmdUI);
+ afx_msg void OnToolsRewind();
+ afx_msg void OnUpdateToolsRewind(CCmdUI* pCmdUI);
+ afx_msg void OnToolsCustomize();
+ afx_msg void OnUpdateToolsCustomize(CCmdUI* pCmdUI);
+ afx_msg void OnHelpBugreport();
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg void OnInitMenu(CMenu* pMenu);
+ afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
+#if _MSC_VER <= 1200
+ afx_msg void OnActivateApp(BOOL bActive, HTASK hTask);
+#else
+ afx_msg void OnActivateApp(BOOL bActive, DWORD hTask);
+#endif
+ afx_msg void OnDropFiles(HDROP hDropInfo);
+ afx_msg void OnFileSavegameOldestslot();
+ afx_msg void OnUpdateFileSavegameOldestslot(CCmdUI* pCmdUI);
+ afx_msg void OnFileLoadgameMostrecent();
+ afx_msg void OnUpdateFileLoadgameMostrecent(CCmdUI* pCmdUI);
+ afx_msg void OnFileLoadgameAutoloadmostrecent();
+ afx_msg void OnUpdateFileLoadgameAutoloadmostrecent(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundVolume25x();
+ afx_msg void OnUpdateOptionsSoundVolume25x(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsSoundVolume5x();
+ afx_msg void OnUpdateOptionsSoundVolume5x(CCmdUI* pCmdUI);
+ afx_msg void OnCheatsDisablecheats();
+ afx_msg void OnUpdateCheatsDisablecheats(CCmdUI* pCmdUI);
+ afx_msg void OnOptionsVideoFullscreenmaxscale();
+ afx_msg void OnOptionsEmulatorGameoverrides();
+ afx_msg void OnUpdateOptionsEmulatorGameoverrides(CCmdUI* pCmdUI);
+ afx_msg void OnHelpGnupubliclicense();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ afx_msg BOOL OnFileRecentFile(UINT nID);
+ afx_msg BOOL OnFileLoadSlot(UINT nID);
+ afx_msg BOOL OnFileSaveSlot(UINT nID);
+ afx_msg void OnOptionsFilterLcdcolors();
+ afx_msg void OnUpdateOptionsFilterLcdcolors(CCmdUI *pCmdUI);
+
+ afx_msg BOOL OnOptionsSoundPcminterpolation(UINT nID);
+ afx_msg void OnUpdateOptionsSoundPcminterpolation(CCmdUI *pCmdUI);
+public:
+ afx_msg void OnOptionsSoundHardwareacceleration();
+ afx_msg void OnUpdateOptionsSoundHardwareacceleration(CCmdUI *pCmdUI);
+ afx_msg void OnOptionsVideoFullscreen1280x1024();
+ afx_msg void OnOptionsVideoFullscreen1024x768();
+ afx_msg void OnUpdateOptionsVideoFullscreen1024x768(CCmdUI *pCmdUI);
+ afx_msg void OnUpdateOptionsVideoFullscreen1280x1024(CCmdUI *pCmdUI);
+ void OnLinkOptions();
+ void OnOptionsLinkLog() ;
+ void OnUpdateOptionsLinkLog(CCmdUI* pCmdUI) ;
+ void OnOptionsLinkRFU() ;
+ void OnUpdateOptionsLinkRFU(CCmdUI* pCmdUI) ;
+
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINWND_H__E8AD28B9_C9FB_4EC2_A2DC_DD1BBA55A275__INCLUDED_)
diff --git a/src/win32/MainWndFile.cpp b/src/win32/MainWndFile.cpp
index 1322ee5b..a5c0e6e4 100644
--- a/src/win32/MainWndFile.cpp
+++ b/src/win32/MainWndFile.cpp
@@ -1,900 +1,1005 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include "MainWnd.h"
-
-#include "ExportGSASnapshot.h"
-#include "FileDlg.h"
-#include "GSACodeSelect.h"
-#include "RomInfo.h"
-#include "Reg.h"
-#include "WinResUtil.h"
-
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../NLS.h"
-#include "../Sound.h"
-#include "../gb/GB.h"
-#include "../gb/gbCheats.h"
-#include "../gb/gbGlobals.h"
-#include "../Link.h"
-
-extern int emulating;
-
-extern void remoteCleanUp();
-
-void MainWnd::OnFileOpen()
-{
- theApp.winCheckFullscreen();
- if(fileOpenSelect()) {
- FileRun();
- }
-}
-
-void MainWnd::OnFilePause()
-{
- theApp.paused = !theApp.paused;
- if(emulating) {
- if(theApp.paused) {
- theApp.wasPaused = true;
- soundPause();
- } else {
- soundResume();
- }
- }
-}
-
-void MainWnd::OnUpdateFilePause(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.paused);
-}
-
-void MainWnd::OnFileReset()
-{
- if(emulating) {
- theApp.emulator.emuReset();
- systemScreenMessage(winResLoadString(IDS_RESET));
- }
-}
-
-void MainWnd::OnUpdateFileReset(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnUpdateFileRecentFreeze(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.recentFreeze);
-
- if(pCmdUI->m_pMenu == NULL)
- return;
-
- CMenu *pMenu = pCmdUI->m_pMenu;
-
- int i;
- for(i = 0; i < 10; i++) {
- if(!pMenu->RemoveMenu(ID_FILE_MRU_FILE1+i, MF_BYCOMMAND))
- break;
- }
-
- for(i = 0; i < 10; i++) {
- CString p = theApp.recentFiles[i];
- if(p.GetLength() == 0)
- break;
- int index = p.ReverseFind('\\');
-
- if(index != -1)
- p = p.Right(p.GetLength()-index-1);
-
- pMenu->AppendMenu(MF_STRING, ID_FILE_MRU_FILE1+i, p);
- }
- theApp.winAccelMgr.UpdateMenu((HMENU)*pMenu);
-}
-
-BOOL MainWnd::OnFileRecentFile(UINT nID)
-{
- if(theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1].GetLength()) {
- theApp.szFile = theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1];
- if(FileRun())
- emulating = true;
- else {
- emulating = false;
- soundPause();
- }
- }
- return TRUE;
-}
-
-void MainWnd::OnFileRecentReset()
-{
- int i = 0;
- for(i = 0; i < 10; i++)
- theApp.recentFiles[i] = "";
-}
-
-void MainWnd::OnFileRecentFreeze()
-{
- theApp.recentFreeze = !theApp.recentFreeze;
-}
-
-void MainWnd::OnFileExit()
-{
- SendMessage(WM_CLOSE);
-}
-
-void MainWnd::OnFileClose()
-{
- // save battery file before we change the filename...
- if(rom != NULL || gbRom != NULL) {
- if(theApp.autoSaveLoadCheatList)
- winSaveCheatListDefault();
- writeBatteryFile();
- soundPause();
- theApp.emulator.emuCleanUp();
- remoteCleanUp();
- }
- emulating = 0;
- RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
- systemSetTitle("VisualBoyAdvance");
-}
-
-void MainWnd::OnUpdateFileClose(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileOpengameboy()
-{
- theApp.winCheckFullscreen();
- theApp.dir = "";
- CString initialDir = regQueryStringValue("gbromdir",".");
- if(!initialDir.IsEmpty())
- theApp.dir = initialDir;
-
- theApp.szFile = "";
-
- LPCTSTR exts[] = { "" };
- CString filter = winLoadFilter(IDS_FILTER_GBROM);
- CString title = winResLoadString(IDS_SELECT_ROM);
-
- FileDlg dlg(this, "", filter, 0, "", exts, initialDir, title, false);
-
- if(dlg.DoModal() == IDOK) {
- theApp.szFile = dlg.GetPathName();
- theApp.dir = theApp.szFile.Left(dlg.m_ofn.nFileOffset);
- if(theApp.dir.GetLength() > 3 && theApp.dir[theApp.dir.GetLength()-1] == '\\')
- theApp.dir = theApp.dir.Left(theApp.dir.GetLength()-1);
- regSetStringValue("gbromdir", theApp.dir);
- FileRun();
- }
-}
-
-void MainWnd::OnFileLoad()
-{
- theApp.winCheckFullscreen();
- CString buffer;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- buffer = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(isDriveRoot(saveDir))
- filename.Format("%s%s.sgm", saveDir, buffer);
- else
- filename.Format("%s\\%s.sgm", saveDir, buffer);
-
- LPCTSTR exts[] = { ".sgm" };
- CString filter = winLoadFilter(IDS_FILTER_SGM);
- CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME);
-
- FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, false);
-
- if(dlg.DoModal() == IDOK) {
- bool res = loadSaveGame(dlg.GetPathName());
-
- theApp.rewindCount = 0;
- theApp.rewindCounter = 0;
- theApp.rewindSaveNeeded = false;
-
- if(res)
- systemScreenMessage(winResLoadString(IDS_LOADED_STATE));
- }
-}
-
-void MainWnd::OnUpdateFileLoad(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-BOOL MainWnd::OnFileLoadSlot(UINT nID)
-{
- nID = nID + 1 - ID_FILE_LOADGAME_SLOT1;
-
- CString buffer;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- buffer = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(isDriveRoot(saveDir))
- filename.Format("%s%s%d.sgm", saveDir, buffer, nID);
- else
- filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID);
-
- bool res = loadSaveGame(filename);
-
- theApp.rewindCount = 0;
- theApp.rewindCounter = 0;
- theApp.rewindSaveNeeded = false;
-
- CString format = winResLoadString(IDS_LOADED_STATE_N);
- buffer.Format(format, nID);
-
- systemScreenMessage(buffer);
-
- return res;
-}
-
-void MainWnd::OnFileSave()
-{
- theApp.winCheckFullscreen();
- CString buffer;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- buffer = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(isDriveRoot(saveDir))
- filename.Format("%s%s.sgm", saveDir, buffer);
- else
- filename.Format("%s\\%s.sgm", saveDir, buffer);
-
- LPCTSTR exts[] = { ".sgm" };
- CString filter = winLoadFilter(IDS_FILTER_SGM);
- CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME);
-
- FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, true);
-
- if(dlg.DoModal() == IDOK) {
- bool res = writeSaveGame(dlg.GetPathName());
- if(res)
- systemScreenMessage(winResLoadString(IDS_WROTE_STATE));
- }
-}
-
-void MainWnd::OnUpdateFileSave(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-BOOL MainWnd::OnFileSaveSlot(UINT nID)
-{
- nID = nID + 1 - ID_FILE_SAVEGAME_SLOT1;
-
- CString buffer;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- buffer = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(isDriveRoot(saveDir))
- filename.Format("%s%s%d.sgm", saveDir, buffer, nID);
- else
- filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID);
-
- bool res = writeSaveGame(filename);
-
- CString format = winResLoadString(IDS_WROTE_STATE_N);
- buffer.Format(format, nID);
-
- systemScreenMessage(buffer);
-
- return res;
-}
-
-void MainWnd::OnFileImportBatteryfile()
-{
- theApp.winCheckFullscreen();
- LPCTSTR exts[] = { ".sav" };
- CString filter = winLoadFilter(IDS_FILTER_SAV);
- CString title = winResLoadString(IDS_SELECT_BATTERY_FILE);
-
- CString saveDir = regQueryStringValue("batteryDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- FileDlg dlg(this, "", filter, 0, "", exts, saveDir, title, false);
-
- if(dlg.DoModal() == IDCANCEL)
- return;
-
- CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST);
- CString str2 = winResLoadString(IDS_CONFIRM_ACTION);
-
- if(MessageBox(str1,
- str2,
- MB_OKCANCEL) == IDCANCEL)
- return;
-
- bool res = false;
-
- res = theApp.emulator.emuReadBattery(dlg.GetPathName());
-
- if(!res)
- systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", dlg.GetPathName());
- else {
- theApp.emulator.emuReset();
- }
-}
-
-void MainWnd::OnUpdateFileImportBatteryfile(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileImportGamesharkcodefile()
-{
- theApp.winCheckFullscreen();
- LPCTSTR exts[] = { "" };
- CString filter = theApp.cartridgeType == 0 ? winLoadFilter(IDS_FILTER_SPC) : winLoadFilter(IDS_FILTER_GCF);
- CString title = winResLoadString(IDS_SELECT_CODE_FILE);
-
- FileDlg dlg(this, "", filter, 0, "", exts, "", title, false);
-
- if(dlg.DoModal() == IDCANCEL)
- return;
-
- CString str1 = winResLoadString(IDS_CODES_WILL_BE_LOST);
- CString str2 = winResLoadString(IDS_CONFIRM_ACTION);
-
- if(MessageBox(str1,
- str2,
- MB_OKCANCEL) == IDCANCEL)
- return;
-
- bool res = false;
- CString file = dlg.GetPathName();
- if(theApp.cartridgeType == 1)
- res = gbCheatReadGSCodeFile(file);
- else {
- res = fileImportGSACodeFile(file);
- }
-}
-
-void MainWnd::OnUpdateFileImportGamesharkcodefile(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileImportGamesharksnapshot()
-{
- theApp.winCheckFullscreen();
- LPCTSTR exts[] = { "" };
- CString filter = theApp.cartridgeType == 1 ? winLoadFilter(IDS_FILTER_GBS) : winLoadFilter(IDS_FILTER_SPS);
- CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE);
-
- FileDlg dlg(this, "", filter, 0, "", exts, "", title, false);
-
- if(dlg.DoModal() == IDCANCEL)
- return;
-
- CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST);
- CString str2 = winResLoadString(IDS_CONFIRM_ACTION);
-
- if(MessageBox(str1,
- str2,
- MB_OKCANCEL) == IDCANCEL)
- return;
-
- if(theApp.cartridgeType == 1)
- gbReadGSASnapshot(dlg.GetPathName());
- else
- CPUReadGSASnapshot(dlg.GetPathName());
-}
-
-void MainWnd::OnUpdateFileImportGamesharksnapshot(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileExportBatteryfile()
-{
- theApp.winCheckFullscreen();
- CString name;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- name = theApp.filename;
-
- LPCTSTR exts[] = {".sav", ".dat" };
-
- CString filter = winLoadFilter(IDS_FILTER_SAV);
- CString title = winResLoadString(IDS_SELECT_BATTERY_FILE);
-
- CString saveDir = regQueryStringValue("batteryDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- FileDlg dlg(this,
- name,
- filter,
- 1,
- "SAV",
- exts,
- saveDir,
- title,
- true);
-
- if(dlg.DoModal() == IDCANCEL) {
- return;
- }
-
- bool result = false;
-
- if(theApp.cartridgeType == 1) {
- result = gbWriteBatteryFile(dlg.GetPathName(), false);
- } else
- result = theApp.emulator.emuWriteBattery(dlg.GetPathName());
-
- if(!result)
- systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s",
- dlg.GetPathName());
-}
-
-void MainWnd::OnUpdateFileExportBatteryfile(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileExportGamesharksnapshot()
-{
- theApp.winCheckFullscreen();
- if(eepromInUse) {
- systemMessage(IDS_EEPROM_NOT_SUPPORTED, "EEPROM saves cannot be exported");
- return;
- }
-
- CString name;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- name = theApp.filename;
-
- LPCTSTR exts[] = {".sps" };
-
- CString filter = winLoadFilter(IDS_FILTER_SPS);
- CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE);
-
- FileDlg dlg(this,
- name,
- filter,
- 1,
- "SPS",
- exts,
- "",
- title,
- true);
-
- if(dlg.DoModal() == IDCANCEL)
- return;
-
- char buffer[16];
- strncpy(buffer, (const char *)&rom[0xa0], 12);
- buffer[12] = 0;
-
- ExportGSASnapshot dlg2(dlg.GetPathName(), buffer, this);
- dlg2.DoModal();
-}
-
-void MainWnd::OnUpdateFileExportGamesharksnapshot(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating && theApp.cartridgeType == 0);
-}
-
-void MainWnd::OnFileScreencapture()
-{
- theApp.winCheckFullscreen();
- CString name;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- name = theApp.filename;
-
- CString capdir = regQueryStringValue("captureDir", "");
- if(capdir.IsEmpty())
- capdir = getDirFromFile(name);
-
- CString ext = "png";
-
- if(theApp.captureFormat != 0)
- ext = "bmp";
-
- if(isDriveRoot(capdir))
- filename.Format("%s%s.%s", capdir, name, ext);
- else
- filename.Format("%s\\%s.%s", capdir, name, ext);
-
- LPCTSTR exts[] = {".png", ".bmp" };
-
- CString filter = winLoadFilter(IDS_FILTER_PNG);
- CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
-
- FileDlg dlg(this,
- filename,
- filter,
- theApp.captureFormat ? 2 : 1,
- theApp.captureFormat ? "BMP" : "PNG",
- exts,
- capdir,
- title,
- true);
-
- if(dlg.DoModal() == IDCANCEL)
- return;
-
- if(dlg.getFilterIndex() == 2)
- theApp.emulator.emuWriteBMP(dlg.GetPathName());
- else
- theApp.emulator.emuWritePNG(dlg.GetPathName());
-
- systemScreenMessage(winResLoadString(IDS_SCREEN_CAPTURE));
-}
-
-void MainWnd::OnUpdateFileScreencapture(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileRominformation()
-{
- theApp.winCheckFullscreen();
- if(theApp.cartridgeType == 0) {
- RomInfoGBA dlg(rom);
- dlg.DoModal();
- } else {
- RomInfoGB dlg(gbRom);
- dlg.DoModal();
- }
-}
-
-void MainWnd::OnUpdateFileRominformation(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileTogglemenu()
-{
- if(theApp.videoOption <= VIDEO_4X)
- return;
-
- theApp.menuToggle = !theApp.menuToggle;
-
- if(theApp.menuToggle) {
- theApp.updateMenuBar();
- if(theApp.tripleBuffering) {
- if(theApp.display)
- theApp.display->checkFullScreen();
- DrawMenuBar();
- }
- } else {
- SetMenu(NULL);
- DestroyMenu(theApp.menu);
- }
-
- theApp.adjustDestRect();
- if(theApp.display)
- theApp.display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top);
-
-}
-
-void MainWnd::OnUpdateFileTogglemenu(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.videoOption > VIDEO_4X);
-}
-
-bool MainWnd::fileImportGSACodeFile(CString& fileName)
-{
- FILE *f = fopen(fileName, "rb");
-
- if(f == NULL) {
- systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", fileName);
- return false;
- }
-
- u32 len;
- fread(&len, 1, 4, f);
- if(len != 14) {
- fclose(f);
- systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s",
- fileName);
- return false;
- }
- char buffer[16];
- fread(buffer, 1, 14, f);
- buffer[14] = 0;
- if(memcmp(buffer, "SharkPortCODES", 14)) {
- fclose(f);
- systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s",
- fileName);
- return false;
- }
- fseek(f, 0x1e, SEEK_SET);
- fread(&len, 1, 4, f);
- int game = 0;
- if(len > 1) {
- GSACodeSelect dlg(f);
- game = dlg.DoModal();
- }
- fclose(f);
-
- bool v3 = false;
-
- int index = fileName.ReverseFind('.');
-
- if(index != -1) {
- if(fileName.Right(3).CompareNoCase("XPC") == 0)
- v3 = true;
- }
-
- if(game != -1) {
- return cheatsImportGSACodeFile(fileName, game, v3);
- }
-
- return true;
-}
-
-void MainWnd::OnFileSavegameOldestslot()
-{
- if(!emulating)
- return;
-
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- filename = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(!isDriveRoot(saveDir))
- saveDir += "\\";
-
- CString name;
- CFileStatus status;
- CString str;
- unsigned long time = (unsigned long)-1;
- int found = 0;
-
- for(int i = 0; i < 10; i++) {
- name.Format("%s%s%d.sgm", saveDir, filename, i+1);
-
- if(emulating && CFile::GetStatus(name, status)) {
- if((unsigned long)status.m_mtime.GetTime() < time) {
- time = (time_t)status.m_mtime.GetTime();
- found = i;
- }
- } else {
- found = i;
- break;
- }
- }
- OnFileSaveSlot(ID_FILE_SAVEGAME_SLOT1+found);
-}
-
-void MainWnd::OnUpdateFileSavegameOldestslot(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
- if(pCmdUI->m_pSubMenu != NULL) {
- CMenu *pMenu = pCmdUI->m_pSubMenu;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- filename = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(!isDriveRoot(saveDir))
- saveDir += "\\";
-
- CString name;
- CFileStatus status;
- CString str;
-
- for(int i = 0; i < 10; i++) {
- name.Format("%s%s%d.sgm", saveDir, filename, i+1);
-
- if(emulating && CFile::GetStatus(name, status)) {
- CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S");
- str.Format("%d %s", i+1, timestamp);
- } else {
- str.Format("%d ----/--/-- --:--:--", i+1);
- }
- pMenu->ModifyMenu(ID_FILE_SAVEGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_SAVEGAME_SLOT1+i, str);
- }
-
- theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu());
- }
-}
-
-void MainWnd::OnFileLoadgameMostrecent()
-{
- if(!emulating)
- return;
-
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- filename = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(!isDriveRoot(saveDir))
- saveDir += "\\";
-
- CString name;
- CFileStatus status;
- CString str;
- unsigned long time = 0;
- int found = -1;
-
- for(int i = 0; i < 10; i++) {
- name.Format("%s%s%d.sgm", saveDir, filename, i+1);
-
- if(emulating && CFile::GetStatus(name, status)) {
- if((unsigned long)status.m_mtime.GetTime() > time) {
- time = (time_t)status.m_mtime.GetTime();
- found = i;
- }
- }
- }
- if(found != -1) {
- OnFileLoadSlot(ID_FILE_LOADGAME_SLOT1+found);
- }
-}
-
-void MainWnd::OnUpdateFileLoadgameMostrecent(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(emulating);
-
- if(pCmdUI->m_pSubMenu != NULL) {
- CMenu *pMenu = pCmdUI->m_pSubMenu;
- CString filename;
-
- int index = theApp.filename.ReverseFind('\\');
-
- if(index != -1)
- filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
- else
- filename = theApp.filename;
-
- CString saveDir = regQueryStringValue("saveDir", NULL);
-
- if(saveDir.IsEmpty())
- saveDir = getDirFromFile(theApp.filename);
-
- if(!isDriveRoot(saveDir))
- saveDir += "\\";
-
- CString name;
- CFileStatus status;
- CString str;
-
- for(int i = 0; i < 10; i++) {
- name.Format("%s%s%d.sgm", saveDir, filename, i+1);
-
- if(emulating && CFile::GetStatus(name, status)) {
- CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S");
- str.Format("%d %s", i+1, timestamp);
- } else {
- str.Format("%d ----/--/-- --:--:--", i+1);
- }
- pMenu->ModifyMenu(ID_FILE_LOADGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_LOADGAME_SLOT1+i, str);
- }
-
- theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu());
- }
-}
-
-void MainWnd::OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnUpdateFileSaveGameSlot(CCmdUI *pCmdUI)
-{
- pCmdUI->Enable(emulating);
-}
-
-void MainWnd::OnFileLoadgameAutoloadmostrecent()
-{
- theApp.autoLoadMostRecent = !theApp.autoLoadMostRecent;
-}
-
-void MainWnd::OnUpdateFileLoadgameAutoloadmostrecent(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.autoLoadMostRecent);
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005-2006 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+#include "MainWnd.h"
+
+#include
+
+#include "ExportGSASnapshot.h"
+#include "FileDlg.h"
+#include "GSACodeSelect.h"
+#include "RomInfo.h"
+#include "Reg.h"
+#include "WinResUtil.h"
+
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../NLS.h"
+#include "../Sound.h"
+#include "../gb/GB.h"
+#include "../gb/gbCheats.h"
+#include "../gb/gbGlobals.h"
+
+extern int emulating;
+
+extern void remoteCleanUp();
+extern void InterframeCleanup();
+
+
+void MainWnd::OnFileOpen()
+{
+ theApp.winCheckFullscreen();
+ if( fileOpenSelect( false ) ) {
+ FileRun();
+ }
+}
+
+
+void MainWnd::OnFilePause()
+{
+ theApp.paused = !theApp.paused;
+ if(emulating) {
+ if(theApp.paused) {
+ theApp.wasPaused = true;
+ soundPause();
+ } else {
+ soundResume();
+ }
+ }
+}
+
+void MainWnd::OnUpdateFilePause(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.paused);
+}
+
+void MainWnd::OnFileReset()
+{
+ if(emulating) {
+ theApp.emulator.emuReset();
+ systemScreenMessage(winResLoadString(IDS_RESET));
+ }
+}
+
+void MainWnd::OnUpdateFileReset(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnUpdateFileRecentFreeze(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.recentFreeze);
+
+ if(pCmdUI->m_pMenu == NULL)
+ return;
+
+ CMenu *pMenu = pCmdUI->m_pMenu;
+
+ int i;
+ for(i = 0; i < 10; i++) {
+ if(!pMenu->RemoveMenu(ID_FILE_MRU_FILE1+i, MF_BYCOMMAND))
+ break;
+ }
+
+ for(i = 0; i < 10; i++) {
+ CString p = theApp.recentFiles[i];
+ if(p.GetLength() == 0)
+ break;
+ int index = p.ReverseFind('\\');
+
+ if(index != -1)
+ p = p.Right(p.GetLength()-index-1);
+
+ pMenu->AppendMenu(MF_STRING, ID_FILE_MRU_FILE1+i, p);
+ }
+ theApp.winAccelMgr.UpdateMenu((HMENU)*pMenu);
+}
+
+BOOL MainWnd::OnFileRecentFile(UINT nID)
+{
+ if(theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1].GetLength()) {
+ theApp.szFile = theApp.recentFiles[(nID&0xFFFF)-ID_FILE_MRU_FILE1];
+ if(FileRun())
+ emulating = true;
+ else {
+ emulating = false;
+ soundPause();
+ }
+ }
+ return TRUE;
+}
+
+void MainWnd::OnFileRecentReset()
+{
+ int i = 0;
+ for(i = 0; i < 10; i++)
+ theApp.recentFiles[i] = "";
+}
+
+void MainWnd::OnFileRecentFreeze()
+{
+ theApp.recentFreeze = !theApp.recentFreeze;
+}
+
+void MainWnd::OnFileExit()
+{
+ SendMessage(WM_CLOSE);
+}
+
+void MainWnd::OnFileClose()
+{
+ // save battery file before we change the filename...
+ if(rom != NULL || gbRom != NULL) {
+ if(theApp.autoSaveLoadCheatList)
+ winSaveCheatListDefault();
+ writeBatteryFile();
+ soundPause();
+ theApp.emulator.emuCleanUp();
+ remoteCleanUp();
+ }
+ emulating = 0;
+ RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
+ systemSetTitle("VisualBoyAdvance");
+}
+
+void MainWnd::OnUpdateFileClose(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+
+void MainWnd::OnFileOpengameboy()
+{
+ theApp.winCheckFullscreen();
+ if( fileOpenSelect( true ) ) {
+ FileRun();
+ }
+}
+
+
+void MainWnd::OnFileLoad()
+{
+ theApp.winCheckFullscreen();
+ CString buffer;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ buffer = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(isDriveRoot(saveDir))
+ filename.Format("%s%s.sgm", saveDir, buffer);
+ else
+ filename.Format("%s\\%s.sgm", saveDir, buffer);
+
+ LPCTSTR exts[] = { ".sgm" };
+ CString filter = winLoadFilter(IDS_FILTER_SGM);
+ CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME);
+
+ FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, false);
+
+ if(dlg.DoModal() == IDOK) {
+ bool res = loadSaveGame(dlg.GetPathName());
+
+ theApp.rewindCount = 0;
+ theApp.rewindCounter = 0;
+ theApp.rewindSaveNeeded = false;
+
+ if(res)
+ systemScreenMessage(winResLoadString(IDS_LOADED_STATE));
+ }
+}
+
+void MainWnd::OnUpdateFileLoad(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+BOOL MainWnd::OnFileLoadSlot(UINT nID)
+{
+ nID = nID + 1 - ID_FILE_LOADGAME_SLOT1;
+
+ CString buffer;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ buffer = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(isDriveRoot(saveDir))
+ filename.Format("%s%s%d.sgm", saveDir, buffer, nID);
+ else
+ filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID);
+
+ CString format = winResLoadString(IDS_LOADED_STATE_N);
+ buffer.Format(format, nID);
+
+ bool res = loadSaveGame(filename);
+
+ if (theApp.paused)
+ InterframeCleanup();
+
+ systemScreenMessage(buffer);
+
+ systemDrawScreen();
+
+ //theApp.rewindCount = 0;
+ //theApp.rewindCounter = 0;
+ //theApp.rewindSaveNeeded = false;
+
+ return res;
+}
+
+void MainWnd::OnFileSave()
+{
+ theApp.winCheckFullscreen();
+ CString buffer;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ buffer = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(isDriveRoot(saveDir))
+ filename.Format("%s%s.sgm", saveDir, buffer);
+ else
+ filename.Format("%s\\%s.sgm", saveDir, buffer);
+
+ LPCTSTR exts[] = { ".sgm" };
+ CString filter = winLoadFilter(IDS_FILTER_SGM);
+ CString title = winResLoadString(IDS_SELECT_SAVE_GAME_NAME);
+
+ FileDlg dlg(this, filename, filter, 0, "", exts, saveDir, title, true);
+
+ if(dlg.DoModal() == IDOK) {
+ bool res = writeSaveGame(dlg.GetPathName());
+ if(res)
+ systemScreenMessage(winResLoadString(IDS_WROTE_STATE));
+ }
+}
+
+void MainWnd::OnUpdateFileSave(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+BOOL MainWnd::OnFileSaveSlot(UINT nID)
+{
+ nID = nID + 1 - ID_FILE_SAVEGAME_SLOT1;
+
+ CString buffer;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ buffer = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ buffer = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(isDriveRoot(saveDir))
+ filename.Format("%s%s%d.sgm", saveDir, buffer, nID);
+ else
+ filename.Format("%s\\%s%d.sgm", saveDir, buffer, nID);
+
+ bool res = writeSaveGame(filename);
+
+ CString format = winResLoadString(IDS_WROTE_STATE_N);
+ buffer.Format(format, nID);
+
+ systemScreenMessage(buffer);
+
+ systemDrawScreen();
+
+ return res;
+}
+
+void MainWnd::OnFileImportBatteryfile()
+{
+ theApp.winCheckFullscreen();
+ LPCTSTR exts[] = { ".sav" };
+ CString filter = winLoadFilter(IDS_FILTER_SAV);
+ CString title = winResLoadString(IDS_SELECT_BATTERY_FILE);
+
+ CString saveDir = regQueryStringValue("batteryDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ FileDlg dlg(this, "", filter, 0, "", exts, saveDir, title, false);
+
+ if(dlg.DoModal() == IDCANCEL)
+ return;
+
+ CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST);
+ CString str2 = winResLoadString(IDS_CONFIRM_ACTION);
+
+ if(MessageBox(str1,
+ str2,
+ MB_OKCANCEL) == IDCANCEL)
+ return;
+
+ bool res = false;
+
+ res = theApp.emulator.emuReadBattery(dlg.GetPathName());
+
+ if(!res)
+ systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", dlg.GetPathName());
+ else {
+ //Removed the reset to allow loading a battery file 'within' a save state.
+ //theApp.emulator.emuReset();
+ }
+}
+
+void MainWnd::OnUpdateFileImportBatteryfile(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileImportGamesharkcodefile()
+{
+ theApp.winCheckFullscreen();
+ LPCTSTR exts[] = { "" };
+ CString filter = theApp.cartridgeType == 0 ? winLoadFilter(IDS_FILTER_SPC) : winLoadFilter(IDS_FILTER_GCF);
+ CString title = winResLoadString(IDS_SELECT_CODE_FILE);
+
+ FileDlg dlg(this, "", filter, 0, "", exts, "", title, false);
+
+ if(dlg.DoModal() == IDCANCEL)
+ return;
+
+ CString str1 = winResLoadString(IDS_CODES_WILL_BE_LOST);
+ CString str2 = winResLoadString(IDS_CONFIRM_ACTION);
+
+ if(MessageBox(str1,
+ str2,
+ MB_OKCANCEL) == IDCANCEL)
+ return;
+
+ bool res = false;
+ CString file = dlg.GetPathName();
+ if(theApp.cartridgeType == 1)
+ res = gbCheatReadGSCodeFile(file);
+ else {
+ res = fileImportGSACodeFile(file);
+ }
+}
+
+void MainWnd::OnUpdateFileImportGamesharkcodefile(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileImportGamesharksnapshot()
+{
+ theApp.winCheckFullscreen();
+ LPCTSTR exts[] = { ".gbs" };
+ CString filter = theApp.cartridgeType == 1 ? winLoadFilter(IDS_FILTER_GBS) : winLoadFilter(IDS_FILTER_SPS);
+ CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE);
+
+ FileDlg dlg(this, "", filter, 0, "", exts, "", title, false);
+
+ if(dlg.DoModal() == IDCANCEL)
+ return;
+
+ CString str1 = winResLoadString(IDS_SAVE_WILL_BE_LOST);
+ CString str2 = winResLoadString(IDS_CONFIRM_ACTION);
+
+ if(MessageBox(str1,
+ str2,
+ MB_OKCANCEL) == IDCANCEL)
+ return;
+
+ if(theApp.cartridgeType == 1)
+ gbReadGSASnapshot(dlg.GetPathName());
+ else
+ CPUReadGSASnapshot(dlg.GetPathName());
+}
+
+void MainWnd::OnUpdateFileImportGamesharksnapshot(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileExportBatteryfile()
+{
+ theApp.winCheckFullscreen();
+ CString name;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ name = theApp.filename;
+
+ LPCTSTR exts[] = {".sav", ".dat" };
+
+ CString filter = winLoadFilter(IDS_FILTER_SAV);
+ CString title = winResLoadString(IDS_SELECT_BATTERY_FILE);
+
+ CString saveDir = regQueryStringValue("batteryDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ FileDlg dlg(this,
+ name,
+ filter,
+ 1,
+ "SAV",
+ exts,
+ saveDir,
+ title,
+ true);
+
+ if(dlg.DoModal() == IDCANCEL) {
+ return;
+ }
+
+ bool result = false;
+
+ if(theApp.cartridgeType == 1) {
+ result = gbWriteBatteryFile(dlg.GetPathName(), false);
+ } else
+ result = theApp.emulator.emuWriteBattery(dlg.GetPathName());
+
+ if(!result)
+ systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s",
+ dlg.GetPathName());
+}
+
+void MainWnd::OnUpdateFileExportBatteryfile(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileExportGamesharksnapshot()
+{
+ theApp.winCheckFullscreen();
+ if(eepromInUse) {
+ systemMessage(IDS_EEPROM_NOT_SUPPORTED, "EEPROM saves cannot be exported");
+ return;
+ }
+
+ CString name;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ name = theApp.filename;
+
+ LPCTSTR exts[] = {".sps" };
+
+ CString filter = winLoadFilter(IDS_FILTER_SPS);
+ CString title = winResLoadString(IDS_SELECT_SNAPSHOT_FILE);
+
+ FileDlg dlg(this,
+ name,
+ filter,
+ 1,
+ "SPS",
+ exts,
+ "",
+ title,
+ true);
+
+ if(dlg.DoModal() == IDCANCEL)
+ return;
+
+ char buffer[16];
+ strncpy(buffer, (const char *)&rom[0xa0], 12);
+ buffer[12] = 0;
+
+ ExportGSASnapshot dlg2(dlg.GetPathName(), buffer, this);
+ dlg2.DoModal();
+}
+
+void MainWnd::OnUpdateFileExportGamesharksnapshot(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating && theApp.cartridgeType == 0);
+}
+
+void MainWnd::OnFileScreencapture()
+{
+ theApp.winCheckFullscreen();
+ CString name;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ name = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ name = theApp.filename;
+
+ CString capdir = regQueryStringValue("captureDir", "");
+ if( capdir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, capdir );
+ capdir = baseDir;
+ }
+ if(capdir.IsEmpty())
+ capdir = getDirFromFile(theApp.filename);
+
+ CString ext = "png";
+
+ if(theApp.captureFormat != 0)
+ ext = "bmp";
+
+ if(isDriveRoot(capdir))
+ filename.Format("%s%s.%s", capdir, name, ext);
+ else
+ filename.Format("%s\\%s.%s", capdir, name, ext);
+
+ LPCTSTR exts[] = {".png", ".bmp" };
+
+ CString filter = winLoadFilter(IDS_FILTER_PNG);
+ CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
+
+ FileDlg dlg(this,
+ filename,
+ filter,
+ theApp.captureFormat ? 2 : 1,
+ theApp.captureFormat ? "BMP" : "PNG",
+ exts,
+ capdir,
+ title,
+ true);
+
+ if(dlg.DoModal() == IDCANCEL)
+ return;
+
+ if(dlg.getFilterIndex() == 2)
+ theApp.emulator.emuWriteBMP(dlg.GetPathName());
+ else
+ theApp.emulator.emuWritePNG(dlg.GetPathName());
+
+ systemScreenMessage(winResLoadString(IDS_SCREEN_CAPTURE));
+}
+
+void MainWnd::OnUpdateFileScreencapture(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileRominformation()
+{
+ theApp.winCheckFullscreen();
+ if(theApp.cartridgeType == 0) {
+ RomInfoGBA dlg(rom);
+ dlg.DoModal();
+ } else {
+ RomInfoGB dlg(gbRom);
+ dlg.DoModal();
+ }
+}
+
+void MainWnd::OnUpdateFileRominformation(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileTogglemenu()
+{
+ if(theApp.videoOption <= VIDEO_4X)
+ return;
+
+ theApp.menuToggle = !theApp.menuToggle;
+
+ if(theApp.menuToggle) {
+ theApp.updateMenuBar();
+ if(theApp.tripleBuffering) {
+ if(theApp.display)
+ theApp.display->checkFullScreen();
+ DrawMenuBar();
+ }
+ } else {
+ SetMenu(NULL);
+ DestroyMenu(theApp.menu);
+ }
+
+ theApp.adjustDestRect();
+ if(theApp.display)
+ theApp.display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top);
+}
+
+void MainWnd::OnUpdateFileTogglemenu(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.videoOption > VIDEO_4X);
+}
+
+bool MainWnd::fileImportGSACodeFile(CString& fileName)
+{
+ FILE *f = fopen(fileName, "rb");
+
+ if(f == NULL) {
+ systemMessage(MSG_CANNOT_OPEN_FILE, "Cannot open file %s", fileName);
+ return false;
+ }
+
+ u32 len;
+ fread(&len, 1, 4, f);
+ if(len != 14) {
+ fclose(f);
+ systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s",
+ fileName);
+ return false;
+ }
+ char buffer[16];
+ fread(buffer, 1, 14, f);
+ buffer[14] = 0;
+ if(memcmp(buffer, "SharkPortCODES", 14)) {
+ fclose(f);
+ systemMessage(MSG_UNSUPPORTED_CODE_FILE, "Unsupported code file %s",
+ fileName);
+ return false;
+ }
+ fseek(f, 0x1e, SEEK_SET);
+ fread(&len, 1, 4, f);
+ INT_PTR game = 0;
+ if(len > 1) {
+ GSACodeSelect dlg(f);
+ game = dlg.DoModal();
+ }
+ fclose(f);
+
+ bool v3 = false;
+
+ int index = fileName.ReverseFind('.');
+
+ if(index != -1) {
+ if(fileName.Right(3).CompareNoCase("XPC") == 0)
+ v3 = true;
+ }
+
+ if(game != -1) {
+ return cheatsImportGSACodeFile(fileName, (int)game, v3);
+ }
+
+ return true;
+}
+
+void MainWnd::OnFileSavegameOldestslot()
+{
+ if(!emulating)
+ return;
+
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ filename = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(!isDriveRoot(saveDir))
+ saveDir += "\\";
+
+ CString name;
+ CFileStatus status;
+ CString str;
+ time_t time = (time_t)-1;
+ int found = 0;
+
+ for(int i = 0; i < 10; i++) {
+ name.Format("%s%s%d.sgm", saveDir, filename, i+1);
+
+ if(emulating && CFile::GetStatus(name, status)) {
+ if(status.m_mtime.GetTime() < time) {
+ time = status.m_mtime.GetTime();
+ found = i;
+ }
+ } else {
+ found = i;
+ break;
+ }
+ }
+ OnFileSaveSlot(ID_FILE_SAVEGAME_SLOT1+found);
+}
+
+void MainWnd::OnUpdateFileSavegameOldestslot(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+ if(pCmdUI->m_pSubMenu != NULL) {
+ CMenu *pMenu = pCmdUI->m_pSubMenu;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ filename = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(!isDriveRoot(saveDir))
+ saveDir += "\\";
+
+ CString name;
+ CFileStatus status;
+ CString str;
+
+ for(int i = 0; i < 10; i++) {
+ name.Format("%s%s%d.sgm", saveDir, filename, i+1);
+
+ if(emulating && CFile::GetStatus(name, status)) {
+ CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S");
+ str.Format("%d %s", i+1, timestamp);
+ } else {
+ str.Format("%d ----/--/-- --:--:--", i+1);
+ }
+ pMenu->ModifyMenu(ID_FILE_SAVEGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_SAVEGAME_SLOT1+i, str);
+ }
+
+ theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu());
+ }
+}
+
+void MainWnd::OnFileLoadgameMostrecent()
+{
+ if(!emulating)
+ return;
+
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ filename = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(!isDriveRoot(saveDir))
+ saveDir += "\\";
+
+ CString name;
+ CFileStatus status;
+ CString str;
+ time_t time = 0;
+ int found = -1;
+
+ for(int i = 0; i < 10; i++) {
+ name.Format("%s%s%d.sgm", saveDir, filename, i+1);
+
+ if(emulating && CFile::GetStatus(name, status)) {
+if(status.m_mtime.GetTime() < time) {
+ time = status.m_mtime.GetTime();
+ found = i;
+ }
+ }
+ }
+ if(found != -1) {
+ OnFileLoadSlot(ID_FILE_LOADGAME_SLOT1+found);
+ }
+}
+
+void MainWnd::OnUpdateFileLoadgameMostrecent(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+
+ if(pCmdUI->m_pSubMenu != NULL) {
+ CMenu *pMenu = pCmdUI->m_pSubMenu;
+ CString filename;
+
+ int index = theApp.filename.ReverseFind('\\');
+
+ if(index != -1)
+ filename = theApp.filename.Right(theApp.filename.GetLength()-index-1);
+ else
+ filename = theApp.filename;
+
+ CString saveDir = regQueryStringValue("saveDir", NULL);
+ if( saveDir[0] == '.' ) {
+ // handle as relative path
+ char baseDir[MAX_PATH+1];
+ GetModuleFileName( NULL, baseDir, MAX_PATH );
+ baseDir[MAX_PATH] = '\0'; // for security reasons
+ PathRemoveFileSpec( baseDir ); // removes the trailing file name and backslash
+ strcat( baseDir, "\\" );
+ strcat( baseDir, saveDir );
+ saveDir = baseDir;
+ }
+
+ if(saveDir.IsEmpty())
+ saveDir = getDirFromFile(theApp.filename);
+
+ if(!isDriveRoot(saveDir))
+ saveDir += "\\";
+
+ CString name;
+ CFileStatus status;
+ CString str;
+
+ for(int i = 0; i < 10; i++) {
+ name.Format("%s%s%d.sgm", saveDir, filename, i+1);
+
+ if(emulating && CFile::GetStatus(name, status)) {
+ CString timestamp = status.m_mtime.Format("%Y/%m/%d %H:%M:%S");
+ str.Format("%d %s", i+1, timestamp);
+ } else {
+ str.Format("%d ----/--/-- --:--:--", i+1);
+ }
+ pMenu->ModifyMenu(ID_FILE_LOADGAME_SLOT1+i, MF_STRING|MF_BYCOMMAND, ID_FILE_LOADGAME_SLOT1+i, str);
+ }
+
+ theApp.winAccelMgr.UpdateMenu(pMenu->GetSafeHmenu());
+ }
+}
+
+void MainWnd::OnUpdateFileLoadGameSlot(CCmdUI *pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnUpdateFileSaveGameSlot(CCmdUI *pCmdUI)
+{
+ pCmdUI->Enable(emulating);
+}
+
+void MainWnd::OnFileLoadgameAutoloadmostrecent()
+{
+ theApp.autoLoadMostRecent = !theApp.autoLoadMostRecent;
+}
+
+void MainWnd::OnUpdateFileLoadgameAutoloadmostrecent(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.autoLoadMostRecent);
+}
diff --git a/src/win32/MainWndHelp.cpp b/src/win32/MainWndHelp.cpp
index bbecc0ba..5d04917a 100644
--- a/src/win32/MainWndHelp.cpp
+++ b/src/win32/MainWndHelp.cpp
@@ -44,3 +44,9 @@ void MainWnd::OnHelpBugreport()
dlg.DoModal();
}
+
+void MainWnd::OnHelpGnupubliclicense()
+{
+ ::ShellExecute(0, _T("open"), "http://www.gnu.org/licenses/gpl.html",
+ 0, 0, SW_SHOWNORMAL);
+}
diff --git a/src/win32/MainWndOptions.cpp b/src/win32/MainWndOptions.cpp
index 541190c2..413bc984 100644
--- a/src/win32/MainWndOptions.cpp
+++ b/src/win32/MainWndOptions.cpp
@@ -1,1770 +1,1938 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include "MainWnd.h"
-
-#include "Associate.h"
-#include "Directories.h"
-#include "FileDlg.h"
-#include "GBColorDlg.h"
-#include "Joypad.h"
-#include "MaxScale.h"
-#include "ModeConfirm.h"
-#include "Reg.h"
-#include "RewindInterval.h"
-#include "Throttle.h"
-#include "WinResUtil.h"
-#include "LinkOptions.h"
-
-#include "../System.h"
-#include "../agbprint.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../Sound.h"
-#include "../Util.h"
-#include "../gb/GB.h"
-#include "../gb/gbGlobals.h"
-#include "../gb/gbPrinter.h"
-#include "../Link.h"
-
-extern int emulating;
-
-#define VBA_CONFIRM_MODE WM_APP + 100
-
-extern void CPUUpdateRenderBuffers(bool force);
-
-void MainWnd::OnOptionsFrameskipThrottleNothrottle()
-{
- theApp.throttle = 0;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.throttle == 0);
-}
-
-void MainWnd::OnOptionsFrameskipThrottle25()
-{
- theApp.throttle = 25;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.throttle == 25);
-}
-
-void MainWnd::OnOptionsFrameskipThrottle50()
-{
- theApp.throttle = 50;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.throttle == 50);
-}
-
-void MainWnd::OnOptionsFrameskipThrottle100()
-{
- theApp.throttle = 100;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.throttle == 100);
-}
-
-void MainWnd::OnOptionsFrameskipThrottle150()
-{
- theApp.throttle = 150;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.throttle == 150);
-}
-
-void MainWnd::OnOptionsFrameskipThrottle200()
-{
- theApp.throttle = 200;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.throttle == 200);
-}
-
-void MainWnd::OnOptionsFrameskipThrottleOther()
-{
- Throttle dlg;
- int v = dlg.DoModal();
- if(v)
- theApp.throttle = v;
-}
-
-void MainWnd::OnUpdateOptionsFrameskipThrottleOther(CCmdUI* pCmdUI)
-{
- int throttle = theApp.throttle;
- pCmdUI->SetCheck(throttle != 0 && throttle != 25 &&
- throttle != 50 && throttle != 100 &&
- throttle != 150 && throttle != 200);
-}
-
-void MainWnd::OnOptionsFrameskipAutomatic()
-{
- theApp.autoFrameSkip = !theApp.autoFrameSkip;
- if(!theApp.autoFrameSkip && emulating)
- theApp.updateFrameSkip();
-}
-
-void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.autoFrameSkip);
-}
-
-BOOL MainWnd::OnOptionsFrameskip(UINT nID)
-{
- switch(nID) {
- case ID_OPTIONS_VIDEO_FRAMESKIP_0:
- case ID_OPTIONS_VIDEO_FRAMESKIP_1:
- case ID_OPTIONS_VIDEO_FRAMESKIP_2:
- case ID_OPTIONS_VIDEO_FRAMESKIP_3:
- case ID_OPTIONS_VIDEO_FRAMESKIP_4:
- case ID_OPTIONS_VIDEO_FRAMESKIP_5:
- if(theApp.cartridgeType == 0) {
- frameSkip = nID - ID_OPTIONS_VIDEO_FRAMESKIP_0;
- } else {
- gbFrameSkip = nID - ID_OPTIONS_VIDEO_FRAMESKIP_0;
- }
- if(emulating)
- theApp.updateFrameSkip();
- return TRUE;
- break;
- case ID_OPTIONS_VIDEO_FRAMESKIP_6:
- case ID_OPTIONS_VIDEO_FRAMESKIP_7:
- case ID_OPTIONS_VIDEO_FRAMESKIP_8:
- case ID_OPTIONS_VIDEO_FRAMESKIP_9:
- if(theApp.cartridgeType == 0) {
- frameSkip = 6 + nID - ID_OPTIONS_VIDEO_FRAMESKIP_6;
- } else {
- gbFrameSkip = 6 + nID - ID_OPTIONS_VIDEO_FRAMESKIP_6;
- }
- if(emulating)
- theApp.updateFrameSkip();
- return TRUE;
- break;
- }
- return FALSE;
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip0(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 0 : gbFrameSkip == 0);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip1(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 1 : gbFrameSkip == 1);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip2(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 2 : gbFrameSkip == 2);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip3(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 3 : gbFrameSkip == 3);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip4(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 4 : gbFrameSkip == 4);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip5(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 5 : gbFrameSkip == 5);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip6(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 6 : gbFrameSkip == 6);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip7(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 7 : gbFrameSkip == 7);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip8(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 8 : gbFrameSkip == 8);
-}
-
-void MainWnd::OnUpdateOptionsVideoFrameskip9(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.cartridgeType == 0 ? frameSkip == 9 : gbFrameSkip == 9);
-}
-
-void MainWnd::OnOptionsVideoVsync()
-{
- theApp.vsync = !theApp.vsync;
- theApp.updateRenderMethod(true);
-}
-
-void MainWnd::OnUpdateOptionsVideoVsync(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.vsync);
-}
-
-void MainWnd::OnUpdateOptionsVideoX1(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_1X);
-}
-
-void MainWnd::OnUpdateOptionsVideoX2(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_2X);
-}
-
-void MainWnd::OnUpdateOptionsVideoX3(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_3X);
-}
-
-void MainWnd::OnUpdateOptionsVideoX4(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_4X);
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreen320x240(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.mode320Available);
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_320x240);
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreen640x480(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.mode640Available);
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_640x480);
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreen800x600(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.mode800Available);
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_800x600);
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreen1024x768(CCmdUI *pCmdUI)
-{
- pCmdUI->Enable(theApp.mode1024Available);
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_1024x768);
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreen1280x1024(CCmdUI *pCmdUI)
-{
- pCmdUI->Enable(theApp.mode1280Available);
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_1280x1024);
-}
-
-BOOL MainWnd::OnOptionVideoSize(UINT nID)
-{
- theApp.updateVideoSize(nID);
- theApp.m_pMainWnd->PostMessage(VBA_CONFIRM_MODE);
- return TRUE;
-}
-
-void MainWnd::OnOptionsVideoFullscreen320x240()
-{
- OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN320X240);
-}
-
-void MainWnd::OnOptionsVideoFullscreen640x480()
-{
- OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN640X480);
-}
-
-void MainWnd::OnOptionsVideoFullscreen800x600()
-{
- OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN800X600);
-}
-
-void MainWnd::OnOptionsVideoFullscreen1024x768()
-{
- OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN1024X768);
-}
-
-void MainWnd::OnOptionsVideoFullscreen1280x1024()
-{
- OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN1280X1024);
-}
-
-void MainWnd::OnOptionsVideoFullscreen()
-{
- theApp.winCheckFullscreen();
- GUID *pGUID = NULL;
- int size = theApp.display->selectFullScreenMode(&pGUID);
- if(size != -1) {
- int width = (size >> 12) & 4095;
- int height = (size & 4095);
- int colorDepth = (size >> 24);
- if(width != theApp.fsWidth ||
- height != theApp.fsHeight ||
- colorDepth != theApp.fsColorDepth ||
- pGUID != theApp.pVideoDriverGUID ||
- theApp.videoOption != VIDEO_OTHER) {
- theApp.fsForceChange = true;
- theApp.fsWidth = width;
- theApp.fsHeight = height;
- theApp.fsFrequency = (theApp.display->selectFullScreenMode2() & 0xFFFF);
- theApp.fsAdapter = theApp.display->selectFullScreenMode2();
- theApp.fsAdapter = (theApp.fsAdapter & 0xFFFF0000) >> 16;
- theApp.fsColorDepth = colorDepth;
- theApp.pVideoDriverGUID = pGUID;
- if(pGUID) {
- theApp.videoDriverGUID = *pGUID;
- regSetDwordValue("defaultVideoDriver", FALSE);
- regSetBinaryValue("videoDriverGUID",
- (char *)pGUID, sizeof(GUID));
- } else {
- regSetDwordValue("defaultVideoDriver", TRUE);
- }
- theApp.updateVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN);
- theApp.m_pMainWnd->PostMessage(VBA_CONFIRM_MODE);
- }
- }
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreen(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.videoOption == VIDEO_OTHER);
-}
-
-void MainWnd::OnOptionsVideoDisablesfx()
-{
- cpuDisableSfx = !cpuDisableSfx;
- if(emulating && theApp.cartridgeType == 0)
- CPUUpdateRender();
-}
-
-void MainWnd::OnUpdateOptionsVideoDisablesfx(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(!cpuDisableSfx);
-}
-
-void MainWnd::OnOptionsVideoFullscreenstretchtofit()
-{
- theApp.fullScreenStretch = !theApp.fullScreenStretch;
- theApp.updateWindowSize(theApp.videoOption);
- if(theApp.display)
- theApp.display->clear();
-}
-
-void MainWnd::OnUpdateOptionsVideoFullscreenstretchtofit(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.fullScreenStretch);
-}
-
-BOOL MainWnd::OnVideoLayer(UINT nID)
-{
- layerSettings ^= 0x0100 <<
- ((nID & 0xFFFF) - ID_OPTIONS_VIDEO_LAYERS_BG0);
- layerEnable = DISPCNT & layerSettings;
- CPUUpdateRenderBuffers(false);
- return TRUE;
-}
-
-void MainWnd::OnUpdateVideoLayer(CCmdUI *pCmdUI)
-{
- pCmdUI->SetCheck((layerSettings >> (8 + pCmdUI->m_nID - ID_OPTIONS_VIDEO_LAYERS_BG0)) & 1);
- switch(pCmdUI->m_nID) {
- case ID_OPTIONS_VIDEO_LAYERS_BG1:
- case ID_OPTIONS_VIDEO_LAYERS_BG2:
- case ID_OPTIONS_VIDEO_LAYERS_BG3:
- case ID_OPTIONS_VIDEO_LAYERS_WIN1:
- case ID_OPTIONS_VIDEO_LAYERS_OBJWIN:
- pCmdUI->Enable(theApp.cartridgeType == 0);
- break;
- }
-}
-
-void MainWnd::OnOptionsVideoRendermethodGdi()
-{
- theApp.renderMethod = GDI;
- theApp.updateRenderMethod(false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsVideoRendermethodGdi(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.renderMethod == GDI);
-}
-
-void MainWnd::OnOptionsVideoRendermethodDirectdraw()
-{
- theApp.renderMethod = DIRECT_DRAW;
- theApp.updateRenderMethod(false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsVideoRendermethodDirectdraw(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.renderMethod == DIRECT_DRAW);
-}
-
-void MainWnd::OnOptionsVideoRendermethodDirect3d()
-{
- theApp.renderMethod = DIRECT_3D;
- theApp.updateRenderMethod(false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsVideoRendermethodDirect3d(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.renderMethod == DIRECT_3D);
-}
-
-void MainWnd::OnOptionsVideoRendermethodOpengl()
-{
- theApp.renderMethod = OPENGL;
- theApp.updateRenderMethod(false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsVideoRendermethodOpengl(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.renderMethod == OPENGL);
-}
-
-void MainWnd::OnOptionsVideoTriplebuffering()
-{
- theApp.tripleBuffering = !theApp.tripleBuffering;
- theApp.updateRenderMethod(true);
-}
-
-void MainWnd::OnUpdateOptionsVideoTriplebuffering(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.tripleBuffering);
-}
-
-void MainWnd::OnOptionsVideoDdrawemulationonly()
-{
- theApp.ddrawEmulationOnly = !theApp.ddrawEmulationOnly;
-}
-
-void MainWnd::OnUpdateOptionsVideoDdrawemulationonly(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.ddrawEmulationOnly);
-}
-
-void MainWnd::OnOptionsVideoDdrawusevideomemory()
-{
- theApp.ddrawUseVideoMemory = !theApp.ddrawUseVideoMemory;
-}
-
-void MainWnd::OnUpdateOptionsVideoDdrawusevideomemory(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.ddrawUseVideoMemory);
-}
-
-void MainWnd::OnOptionsVideoRenderoptionsD3dnofilter()
-{
- theApp.d3dFilter = 0;
- if(theApp.display)
- theApp.display->setOption("d3dFilter", 0);
-}
-
-void MainWnd::OnUpdateOptionsVideoRenderoptionsD3dnofilter(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.d3dFilter == 0);
-}
-
-void MainWnd::OnOptionsVideoRenderoptionsD3dbilinear()
-{
- theApp.d3dFilter = 1;
- if(theApp.display)
- theApp.display->setOption("d3dFilter", 1);
-}
-
-void MainWnd::OnUpdateOptionsVideoRenderoptionsD3dbilinear(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.d3dFilter == 1);
-}
-
-void MainWnd::OnOptionsVideoRenderoptionsGlnearest()
-{
- theApp.glFilter = 0;
- if(theApp.display)
- theApp.display->setOption("glFilter", 0);
-}
-
-void MainWnd::OnUpdateOptionsVideoRenderoptionsGlnearest(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.glFilter == 0);
-}
-
-void MainWnd::OnOptionsVideoRenderoptionsGlbilinear()
-{
- theApp.glFilter = 1;
- if(theApp.display)
- theApp.display->setOption("glFilter", 1);
-}
-
-void MainWnd::OnUpdateOptionsVideoRenderoptionsGlbilinear(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.glFilter == 1);
-}
-
-void MainWnd::OnOptionsVideoRenderoptionsGltriangle()
-{
- theApp.glType = 0;
- if(theApp.display)
- theApp.display->setOption("glType", 0);
-}
-
-void MainWnd::OnUpdateOptionsVideoRenderoptionsGltriangle(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.glType == 0);
-}
-
-void MainWnd::OnOptionsVideoRenderoptionsGlquads()
-{
- theApp.glType = 1;
- if(theApp.display)
- theApp.display->setOption("glType", 1);
-}
-
-void MainWnd::OnUpdateOptionsVideoRenderoptionsGlquads(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.glType == 1);
-}
-
-void MainWnd::OnOptionsEmulatorAssociate()
-{
- theApp.winCheckFullscreen();
- Associate dlg;
- dlg.DoModal();
-}
-
-void MainWnd::OnOptionsEmulatorDirectories()
-{
- theApp.winCheckFullscreen();
- Directories dlg;
- dlg.DoModal();
-}
-
-void MainWnd::OnOptionsEmulatorDisablestatusmessages()
-{
- theApp.disableStatusMessage = !theApp.disableStatusMessage;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorDisablestatusmessages(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.disableStatusMessage);
-}
-
-void MainWnd::OnOptionsEmulatorSynchronize()
-{
- synchronize = !synchronize;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(synchronize);
-}
-
-void MainWnd::OnOptionsEmulatorPausewheninactive()
-{
- theApp.pauseWhenInactive = !theApp.pauseWhenInactive;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorPausewheninactive(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.pauseWhenInactive);
-}
-
-void MainWnd::OnOptionsEmulatorSpeeduptoggle()
-{
- theApp.speedupToggle = !theApp.speedupToggle;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSpeeduptoggle(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.speedupToggle);
-}
-
-void MainWnd::OnOptionsEmulatorRemoveintrosgba()
-{
- // theApp.removeIntros = !theApp.removeIntros;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorRemoveintrosgba(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(false);
- // pCmdUI->SetCheck(theApp.removeIntros);
-}
-
-void MainWnd::OnOptionsEmulatorAutomaticallyipspatch()
-{
- theApp.autoIPS = !theApp.autoIPS;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorAutomaticallyipspatch(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.autoIPS);
-}
-
-void MainWnd::OnOptionsEmulatorAgbprint()
-{
- agbPrintEnable(!agbPrintIsEnabled());
-}
-
-void MainWnd::OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(agbPrintIsEnabled());
-}
-
-void MainWnd::OnOptionsEmulatorRealtimeclock()
-{
- theApp.winRtcEnable = !theApp.winRtcEnable;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorRealtimeclock(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winRtcEnable);
-}
-
-void MainWnd::OnOptionsEmulatorAutohidemenu()
-{
- theApp.autoHideMenu = !theApp.autoHideMenu;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorAutohidemenu(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.autoHideMenu);
-}
-
-void MainWnd::OnOptionsEmulatorRewindinterval()
-{
- RewindInterval dlg(theApp.rewindTimer/6);
- int v = dlg.DoModal();
-
- if(v >= 0) {
- theApp.rewindTimer = v*6; // convert to a multiple of 10 frames
- regSetDwordValue("rewindTimer", v);
- if(v == 0) {
- if(theApp.rewindMemory)
- free(theApp.rewindMemory);
- theApp.rewindMemory = NULL;
- theApp.rewindCount = 0;
- theApp.rewindCounter = 0;
- theApp.rewindSaveNeeded = false;
- } else {
- if(theApp.rewindMemory == NULL)
- theApp.rewindMemory = (char *)malloc(8*REWIND_SIZE);
- }
- }
-}
-
-BOOL MainWnd::OnOptionsEmulatorShowSpeed(UINT nID)
-{
- switch(nID) {
- case ID_OPTIONS_EMULATOR_SHOWSPEED_NONE:
- theApp.showSpeed = 0;
- systemSetTitle("VisualBoyAdvance");
- break;
- case ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE:
- theApp.showSpeed = 1;
- break;
- case ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED:
- theApp.showSpeed = 2;
- break;
- case ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT:
- theApp.showSpeedTransparent = !theApp.showSpeedTransparent;
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorShowSpeed(CCmdUI *pCmdUI)
-{
- switch(pCmdUI->m_nID) {
- case ID_OPTIONS_EMULATOR_SHOWSPEED_NONE:
- pCmdUI->SetCheck(theApp.showSpeed == 0);
- break;
- case ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE:
- pCmdUI->SetCheck(theApp.showSpeed == 1);
- break;
- case ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED:
- pCmdUI->SetCheck(theApp.showSpeed == 2);
- break;
- case ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT:
- pCmdUI->SetCheck(theApp.showSpeedTransparent);
- break;
- }
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeAutomatic()
-{
- theApp.winSaveType = 0;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeAutomatic(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winSaveType == 0);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeEeprom()
-{
- theApp.winSaveType = 1;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeEeprom(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winSaveType == 1);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeSram()
-{
- theApp.winSaveType = 2;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeSram(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winSaveType == 2);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeFlash()
-{
- theApp.winSaveType = 3;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winSaveType == 3);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeEepromsensor()
-{
- theApp.winSaveType = 4;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeEepromsensor(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winSaveType == 4);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeNone()
-{
- theApp.winSaveType = 5;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeNone(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winSaveType == 5);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeFlash512k()
-{
- flashSetSize(0x10000);
- theApp.winFlashSize = 0x10000;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash512k(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winFlashSize == 0x10000);
-}
-
-void MainWnd::OnOptionsEmulatorSavetypeFlash1m()
-{
- flashSetSize(0x20000);
- theApp.winFlashSize = 0x20000;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash1m(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winFlashSize == 0x20000);
-}
-
-void MainWnd::OnOptionsEmulatorUsebiosfile()
-{
- if(!theApp.biosFileName.IsEmpty())
- theApp.useBiosFile = !theApp.useBiosFile;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorUsebiosfile(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.useBiosFile);
- pCmdUI->Enable(!theApp.biosFileName.IsEmpty());
-}
-
-void MainWnd::OnOptionsEmulatorSkipbios()
-{
- theApp.skipBiosFile = !theApp.skipBiosFile;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorSkipbios(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.skipBiosFile);
-}
-
-void MainWnd::OnOptionsEmulatorSelectbiosfile()
-{
- theApp.winCheckFullscreen();
- LPCTSTR exts[] = { "" };
- CString filter = winLoadFilter(IDS_FILTER_BIOS);
- CString title = winResLoadString(IDS_SELECT_BIOS_FILE);
-
- FileDlg dlg(this,
- theApp.biosFileName,
- filter,
- 0,
- "BIOS",
- exts,
- "",
- title,
- false);
-
- if(dlg.DoModal() == IDOK) {
- theApp.biosFileName = dlg.GetPathName();
- }
-}
-
-void MainWnd::OnOptionsEmulatorPngformat()
-{
- theApp.captureFormat = 0;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorPngformat(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.captureFormat == 0);
-}
-
-void MainWnd::OnOptionsEmulatorBmpformat()
-{
- theApp.captureFormat = 1;
-}
-
-void MainWnd::OnUpdateOptionsEmulatorBmpformat(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.captureFormat == 1);
-}
-
-void MainWnd::OnOptionsSoundOff()
-{
- soundOffFlag = true;
- soundShutdown();
-}
-
-void MainWnd::OnUpdateOptionsSoundOff(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundOffFlag);
-}
-
-void MainWnd::OnOptionsSoundMute()
-{
- soundDisable(0x30f);
-}
-
-void MainWnd::OnUpdateOptionsSoundMute(CCmdUI* pCmdUI)
-{
- int active = soundGetEnable() & 0x30f;
- pCmdUI->SetCheck(active == 0);
-}
-
-void MainWnd::OnOptionsSoundOn()
-{
- //if(soundOffFlag) {
- soundOffFlag = false;
- //soundInit(!theApp.cartridgeType);
- //}
- soundEnable(0x30f);
-}
-
-void MainWnd::OnUpdateOptionsSoundOn(CCmdUI* pCmdUI)
-{
- //int active = soundGetEnable() & 0x30f;
- pCmdUI->SetCheck(/*active != 0 &&*/ !soundOffFlag);
-}
-
-void MainWnd::OnOptionsSoundUseoldsynchronization()
-{
- theApp.useOldSync = !theApp.useOldSync;
- systemMessage(IDS_SETTING_WILL_BE_EFFECTIVE,
- "Setting will be effective the next time you start the emulator");
-}
-
-void MainWnd::OnUpdateOptionsSoundUseoldsynchronization(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.useOldSync);
-}
-
-void MainWnd::OnOptionsSoundEcho()
-{
- soundEcho = !soundEcho;
-}
-
-void MainWnd::OnUpdateOptionsSoundEcho(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundEcho);
-}
-
-void MainWnd::OnOptionsSoundLowpassfilter()
-{
- soundLowPass = !soundLowPass;
-}
-
-void MainWnd::OnUpdateOptionsSoundLowpassfilter(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundLowPass);
-}
-
-void MainWnd::OnOptionsSoundReversestereo()
-{
- soundReverse = !soundReverse;
-}
-
-void MainWnd::OnUpdateOptionsSoundReversestereo(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundReverse);
-}
-
-void MainWnd::OnOptionsSound11khz()
-{
- if(theApp.cartridgeType == 0)
- soundSetQuality(4);
- else
- gbSoundSetQuality(4);
-}
-
-void MainWnd::OnUpdateOptionsSound11khz(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundQuality == 4);
-}
-
-void MainWnd::OnOptionsSound22khz()
-{
- if(theApp.cartridgeType == 0)
- soundSetQuality(2);
- else
- gbSoundSetQuality(2);
-}
-
-void MainWnd::OnUpdateOptionsSound22khz(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundQuality == 2);
-}
-
-void MainWnd::OnOptionsSound44khz()
-{
- if(theApp.cartridgeType == 0)
- soundSetQuality(1);
- else
- gbSoundSetQuality(1);
-}
-
-void MainWnd::OnUpdateOptionsSound44khz(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundQuality == 1);
-}
-
-BOOL MainWnd::OnOptionsSoundVolume(UINT nID)
-{
- soundVolume = nID - ID_OPTIONS_SOUND_VOLUME_1X;
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsSoundVolume(CCmdUI *pCmdUI)
-{
- pCmdUI->SetCheck(soundVolume == (int)(pCmdUI->m_nID - ID_OPTIONS_SOUND_VOLUME_1X));
-}
-
-
-void MainWnd::OnOptionsSoundVolume25x()
-{
- soundVolume = 4;
-}
-
-void MainWnd::OnUpdateOptionsSoundVolume25x(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundVolume == 4);
-}
-
-void MainWnd::OnOptionsSoundVolume5x()
-{
- soundVolume = 5;
-}
-
-void MainWnd::OnUpdateOptionsSoundVolume5x(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundVolume == 5);
-}
-
-void MainWnd::updateSoundChannels(UINT id)
-{
- int flag = 0;
-
- if ( soundOffFlag ) return; // mute hax
-
- if(id == ID_OPTIONS_SOUND_CHANNEL1)
- flag = 1;
-
- if(id == ID_OPTIONS_SOUND_CHANNEL2)
- flag = 2;
-
- if(id == ID_OPTIONS_SOUND_CHANNEL3)
- flag = 4;
-
- if(id == ID_OPTIONS_SOUND_CHANNEL4)
- flag = 8;
-
- if(id == ID_OPTIONS_SOUND_DIRECTSOUNDA)
- flag = 256;
-
- if(id == ID_OPTIONS_SOUND_DIRECTSOUNDB)
- flag = 512;
-
- int active = soundGetEnable() & 0x30f;
-
- if(active & flag)
- active &= (~flag);
- else
- active |= flag;
-
- soundEnable(active);
- soundDisable((~active)&0x30f);
-}
-
-void MainWnd::OnOptionsSoundChannel1()
-{
- updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL1);
-}
-
-void MainWnd::OnUpdateOptionsSoundChannel1(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundGetEnable() & 1);
-}
-
-void MainWnd::OnOptionsSoundChannel2()
-{
- updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL2);
-}
-
-void MainWnd::OnUpdateOptionsSoundChannel2(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundGetEnable() & 2);
-}
-
-void MainWnd::OnOptionsSoundChannel3()
-{
- updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL3);
-}
-
-void MainWnd::OnUpdateOptionsSoundChannel3(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundGetEnable() & 4);
-}
-
-void MainWnd::OnOptionsSoundChannel4()
-{
- updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL4);
-}
-
-void MainWnd::OnUpdateOptionsSoundChannel4(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundGetEnable() & 8);
-}
-
-void MainWnd::OnOptionsSoundDirectsounda()
-{
- updateSoundChannels(ID_OPTIONS_SOUND_DIRECTSOUNDA);
-}
-
-void MainWnd::OnUpdateOptionsSoundDirectsounda(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundGetEnable() & 256);
- pCmdUI->Enable(theApp.cartridgeType == 0);
-}
-
-void MainWnd::OnOptionsSoundDirectsoundb()
-{
- updateSoundChannels(ID_OPTIONS_SOUND_DIRECTSOUNDB);
-}
-
-void MainWnd::OnUpdateOptionsSoundDirectsoundb(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(soundGetEnable() & 512);
- pCmdUI->Enable(theApp.cartridgeType == 0);
-}
-
-BOOL MainWnd::OnOptionsSoundPcminterpolation(UINT nID)
-{
- switch (nID)
- {
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE:
- soundInterpolation = 0;
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_LINEAR:
- soundInterpolation = 1;
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_CUBIC:
- soundInterpolation = 2;
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_FIR:
- soundInterpolation = 3;
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE:
- soundInterpolation = 4;
- break;
-
- default:
- return FALSE;
- }
-
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsSoundPcminterpolation(CCmdUI *pCmdUI)
-{
- switch (pCmdUI->m_nID)
- {
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE:
- pCmdUI->SetCheck(soundInterpolation == 0);
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_LINEAR:
- pCmdUI->SetCheck(soundInterpolation == 1);
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_CUBIC:
- pCmdUI->SetCheck(soundInterpolation == 2);
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_FIR:
- pCmdUI->SetCheck(soundInterpolation == 3);
- break;
- case ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE:
- pCmdUI->SetCheck(soundInterpolation == 4);
- break;
-
- default:
- return;
- }
- pCmdUI->Enable(theApp.cartridgeType == 0);
-}
-
-void MainWnd::OnOptionsGameboyBorder()
-{
- theApp.winGbBorderOn = !theApp.winGbBorderOn;
- gbBorderOn = theApp.winGbBorderOn;
- if(emulating && theApp.cartridgeType == 1 && gbBorderOn) {
- gbSgbRenderBorder();
- }
- theApp.updateWindowSize(theApp.videoOption);
-}
-
-void MainWnd::OnUpdateOptionsGameboyBorder(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.winGbBorderOn);
-}
-
-void MainWnd::OnOptionsGameboyPrinter()
-{
- theApp.winGbPrinterEnabled = !theApp.winGbPrinterEnabled;
- if(theApp.winGbPrinterEnabled)
- gbSerialFunction = gbPrinterSend;
- else
- gbSerialFunction = NULL;
-}
-
-void MainWnd::OnUpdateOptionsGameboyPrinter(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbSerialFunction == gbPrinterSend);
-}
-
-void MainWnd::OnOptionsGameboyBorderAutomatic()
-{
- gbBorderAutomatic = !gbBorderAutomatic;
- if(emulating && theApp.cartridgeType == 1 && gbBorderOn) {
- gbSgbRenderBorder();
- theApp.updateWindowSize(theApp.videoOption);
- }
-}
-
-void MainWnd::OnUpdateOptionsGameboyBorderAutomatic(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbBorderAutomatic);
-}
-
-void MainWnd::OnOptionsGameboyAutomatic()
-{
- gbEmulatorType = 0;
-}
-
-void MainWnd::OnUpdateOptionsGameboyAutomatic(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbEmulatorType == 0);
-}
-
-void MainWnd::OnOptionsGameboyGba()
-{
- gbEmulatorType = 4;
-}
-
-void MainWnd::OnUpdateOptionsGameboyGba(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbEmulatorType == 4);
-}
-
-void MainWnd::OnOptionsGameboyCgb()
-{
- gbEmulatorType = 1;
-}
-
-void MainWnd::OnUpdateOptionsGameboyCgb(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbEmulatorType == 1);
-}
-
-void MainWnd::OnOptionsGameboySgb()
-{
- gbEmulatorType = 2;
-}
-
-void MainWnd::OnUpdateOptionsGameboySgb(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbEmulatorType == 2);
-}
-
-void MainWnd::OnOptionsGameboySgb2()
-{
- gbEmulatorType = 5;
-}
-
-void MainWnd::OnUpdateOptionsGameboySgb2(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbEmulatorType == 5);
-}
-
-void MainWnd::OnOptionsGameboyGb()
-{
- gbEmulatorType = 3;
-}
-
-void MainWnd::OnUpdateOptionsGameboyGb(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbEmulatorType == 3);
-}
-
-void MainWnd::OnOptionsGameboyRealcolors()
-{
- gbColorOption = 0;
-}
-
-void MainWnd::OnUpdateOptionsGameboyRealcolors(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbColorOption == 0);
-}
-
-void MainWnd::OnOptionsGameboyGameboycolors()
-{
- gbColorOption = 1;
-}
-
-void MainWnd::OnUpdateOptionsGameboyGameboycolors(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(gbColorOption == 1);
-}
-
-
-void MainWnd::OnOptionsGameboyColors()
-{
- theApp.winCheckFullscreen();
- GBColorDlg dlg;
- if(dlg.DoModal()) {
- gbPaletteOption = dlg.getWhich();
- memcpy(systemGbPalette, dlg.getColors(), 24*sizeof(u16));
- if(emulating && theApp.cartridgeType == 1) {
- memcpy(gbPalette, &systemGbPalette[dlg.getWhich()*8], 8*sizeof(u16));
- }
- }
-}
-
-BOOL MainWnd::OnOptionsPriority(UINT nID)
-{
- switch(nID) {
- case ID_OPTIONS_PRIORITY_HIGHEST:
- theApp.threadPriority = 0;
- break;
- case ID_OPTIONS_PRIORITY_ABOVENORMAL:
- theApp.threadPriority = 1;
- break;
- case ID_OPTIONS_PRIORITY_NORMAL:
- theApp.threadPriority = 2;
- break;
- case ID_OPTIONS_PRIORITY_BELOWNORMAL:
- theApp.threadPriority = 3;
- break;
- default:
- return FALSE;
- }
- theApp.updatePriority();
-
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsPriority(CCmdUI *pCmdUI)
-{
- switch(pCmdUI->m_nID) {
- case ID_OPTIONS_PRIORITY_HIGHEST:
- pCmdUI->SetCheck(theApp.threadPriority == 0);
- break;
- case ID_OPTIONS_PRIORITY_ABOVENORMAL:
- pCmdUI->SetCheck(theApp.threadPriority == 1);
- break;
- case ID_OPTIONS_PRIORITY_NORMAL:
- pCmdUI->SetCheck(theApp.threadPriority == 2);
- break;
- case ID_OPTIONS_PRIORITY_BELOWNORMAL:
- pCmdUI->SetCheck(theApp.threadPriority == 3);
- break;
- }
-}
-
-BOOL MainWnd::OnOptionsFilter(UINT nID)
-{
- switch(nID)
- {
- case ID_OPTIONS_FILTER_NORMAL:
- theApp.filterType = FILTER_NONE;
- break;
- case ID_OPTIONS_FILTER_TVMODE:
- theApp.filterType = FILTER_TVMODE;
- break;
- case ID_OPTIONS_FILTER_2XSAI:
- theApp.filterType = FILTER_2XSAI;
- break;
- case ID_OPTIONS_FILTER_SUPER2XSAI:
- theApp.filterType = FILTER_SUPER2XSAI;
- break;
- case ID_OPTIONS_FILTER_SUPEREAGLE:
- theApp.filterType = FILTER_SUPEREAGLE;
- break;
- case ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL:
- theApp.filterType = FILTER_PIXELATE;
- break;
- case ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X:
- theApp.filterType = FILTER_MAMESCALE2X;
- break;
- case ID_OPTIONS_FILTER16BIT_SIMPLE2X:
- theApp.filterType = FILTER_SIMPLE2X;
- break;
- case ID_OPTIONS_FILTER_BILINEAR:
- theApp.filterType = FILTER_BILINEAR;
- break;
- case ID_OPTIONS_FILTER_BILINEARPLUS:
- theApp.filterType = FILTER_BILINEARPLUS;
- break;
- case ID_OPTIONS_FILTER_SCANLINES:
- theApp.filterType = FILTER_SCANLINES;
- break;
- case ID_OPTIONS_FILTER_HQ2X:
- theApp.filterType = FILTER_HQ2X;
- break;
- case ID_OPTIONS_FILTER_LQ2X:
- theApp.filterType = FILTER_LQ2X;
- break;
- case ID_OPTIONS_FILTER_SIMPLE3X:
- theApp.filterType = FILTER_SIMPLE3X;
- break;
- case ID_OPTIONS_FILTER_SIMPLE4X:
- theApp.filterType = FILTER_SIMPLE4X;
- break;
- case ID_OPTIONS_FILTER_HQ3X:
- theApp.filterType = FILTER_HQ3X;
- break;
- case ID_OPTIONS_FILTER_HQ4X:
- theApp.filterType = FILTER_HQ4X;
- break;
- default:
- return FALSE;
- }
- theApp.updateFilter();
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsFilter(CCmdUI *pCmdUI)
-{
- pCmdUI->Enable( systemColorDepth == 16 || systemColorDepth == 32 );
-
- switch(pCmdUI->m_nID) {
- case ID_OPTIONS_FILTER_NORMAL:
- pCmdUI->SetCheck(theApp.filterType == FILTER_NONE);
- break;
- case ID_OPTIONS_FILTER_TVMODE:
- pCmdUI->SetCheck(theApp.filterType == FILTER_TVMODE);
- break;
- case ID_OPTIONS_FILTER_2XSAI:
- pCmdUI->SetCheck(theApp.filterType == FILTER_2XSAI);
- break;
- case ID_OPTIONS_FILTER_SUPER2XSAI:
- pCmdUI->SetCheck(theApp.filterType == FILTER_SUPER2XSAI);
- break;
- case ID_OPTIONS_FILTER_SUPEREAGLE:
- pCmdUI->SetCheck(theApp.filterType == FILTER_SUPEREAGLE);
- break;
- case ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL:
- pCmdUI->SetCheck(theApp.filterType == FILTER_PIXELATE);
- break;
- case ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_MAMESCALE2X);
- break;
- case ID_OPTIONS_FILTER16BIT_SIMPLE2X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_SIMPLE2X);
- break;
- case ID_OPTIONS_FILTER_BILINEAR:
- pCmdUI->SetCheck(theApp.filterType == FILTER_BILINEAR);
- break;
- case ID_OPTIONS_FILTER_BILINEARPLUS:
- pCmdUI->SetCheck(theApp.filterType == FILTER_BILINEARPLUS);
- break;
- case ID_OPTIONS_FILTER_SCANLINES:
- pCmdUI->SetCheck(theApp.filterType == FILTER_SCANLINES);
- break;
- case ID_OPTIONS_FILTER_HQ2X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_HQ2X);
- break;
- case ID_OPTIONS_FILTER_LQ2X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_LQ2X);
- break;
- case ID_OPTIONS_FILTER_SIMPLE3X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_SIMPLE3X);
- break;
- case ID_OPTIONS_FILTER_SIMPLE4X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_SIMPLE4X);
- break;
- case ID_OPTIONS_FILTER_HQ3X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_HQ3X);
- break;
- case ID_OPTIONS_FILTER_HQ4X:
- pCmdUI->SetCheck(theApp.filterType == FILTER_HQ4X);
- break;
- }
-}
-
-BOOL MainWnd::OnOptionsFilterIFB(UINT nID)
-{
- switch(nID) {
- case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE:
- theApp.ifbType = 0;
- break;
- case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR:
- theApp.ifbType = 1;
- break;
- case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART:
- theApp.ifbType = 2;
- break;
- default:
- return FALSE;
- }
- theApp.updateIFB();
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsFilterIFB(CCmdUI *pCmdUI)
-{
- switch(pCmdUI->m_nID) {
- case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE:
- pCmdUI->SetCheck(theApp.ifbType == 0);
- break;
- case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR:
- pCmdUI->SetCheck(theApp.ifbType == 1);
- break;
- case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART:
- pCmdUI->SetCheck(theApp.ifbType == 2);
- break;
- }
-}
-
-void MainWnd::OnOptionsFilterDisablemmx()
-{
-#ifdef MMX
- theApp.disableMMX = !theApp.disableMMX;
- if(!theApp.disableMMX)
- cpu_mmx = theApp.detectMMX();
- else
- cpu_mmx = 0;
-#endif
-}
-
-void MainWnd::OnUpdateOptionsFilterDisablemmx(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.disableMMX);
-}
-
-void MainWnd::OnOptionsFilterLcdcolors()
-{
- theApp.filterLCD = !theApp.filterLCD;
- utilUpdateSystemColorMaps(theApp.filterLCD);
-}
-
-void MainWnd::OnUpdateOptionsFilterLcdcolors(CCmdUI *pCmdUI)
-{
- pCmdUI->SetCheck(theApp.filterLCD);
-}
-
-void MainWnd::OnOptionsLanguageSystem()
-{
- theApp.winSetLanguageOption(0, false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsLanguageSystem(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.languageOption == 0);
-}
-
-void MainWnd::OnOptionsLanguageEnglish()
-{
- theApp.winSetLanguageOption(1, false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsLanguageEnglish(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.languageOption == 1);
-}
-
-void MainWnd::OnOptionsLanguageOther()
-{
- theApp.winCheckFullscreen();
- theApp.winSetLanguageOption(2, false);
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnUpdateOptionsLanguageOther(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(theApp.languageOption == 2);
-}
-
-
-void MainWnd::OnOptionsJoypadConfigure1()
-{
- theApp.winCheckFullscreen();
- JoypadConfig dlg(0);
- dlg.DoModal();
-}
-
-void MainWnd::OnUpdateOptionsJoypadConfigure1(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
-}
-
-void MainWnd::OnOptionsJoypadConfigure2()
-{
- theApp.winCheckFullscreen();
- JoypadConfig dlg(1);
- dlg.DoModal();
-}
-
-void MainWnd::OnUpdateOptionsJoypadConfigure2(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
-}
-
-void MainWnd::OnOptionsJoypadConfigure3()
-{
- theApp.winCheckFullscreen();
- JoypadConfig dlg(2);
- dlg.DoModal();
-}
-
-void MainWnd::OnUpdateOptionsJoypadConfigure3(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
-}
-
-void MainWnd::OnOptionsJoypadConfigure4()
-{
- theApp.winCheckFullscreen();
- JoypadConfig dlg(3);
- dlg.DoModal();
-}
-
-void MainWnd::OnUpdateOptionsJoypadConfigure4(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
-}
-
-BOOL MainWnd::OnOptionsJoypadDefault(UINT nID)
-{
- theApp.joypadDefault = nID - ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1;
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsJoypadDefault(CCmdUI *pCmdUI)
-{
- pCmdUI->SetCheck(theApp.joypadDefault == (int)(pCmdUI->m_nID - ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1));
-}
-
-void MainWnd::OnOptionsJoypadMotionconfigure()
-{
- theApp.winCheckFullscreen();
- MotionConfig dlg;
- dlg.DoModal();
-}
-
-void MainWnd::OnUpdateOptionsJoypadMotionconfigure(CCmdUI* pCmdUI)
-{
- pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
-}
-
-BOOL MainWnd::OnOptionsJoypadAutofire(UINT nID)
-{
- switch(nID) {
- case ID_OPTIONS_JOYPAD_AUTOFIRE_A:
- if(theApp.autoFire & 1) {
- theApp.autoFire &= ~1;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_A_DISABLED));
- } else {
- theApp.autoFire |= 1;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_A));
- }
- break;
- case ID_OPTIONS_JOYPAD_AUTOFIRE_B:
- if(theApp.autoFire & 2) {
- theApp.autoFire &= ~2;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_B_DISABLED));
- } else {
- theApp.autoFire |= 2;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_B));
- }
- break;
- case ID_OPTIONS_JOYPAD_AUTOFIRE_L:
- if(theApp.autoFire & 512) {
- theApp.autoFire &= ~512;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_L_DISABLED));
- } else {
- theApp.autoFire |= 512;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_L));
- }
- break;
- case ID_OPTIONS_JOYPAD_AUTOFIRE_R:
- if(theApp.autoFire & 256) {
- theApp.autoFire &= ~256;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_R_DISABLED));
- } else {
- theApp.autoFire |= 256;
- systemScreenMessage(winResLoadString(IDS_AUTOFIRE_R));
- }
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-void MainWnd::OnUpdateOptionsJoypadAutofire(CCmdUI *pCmdUI)
-{
- bool check = true;
- switch(pCmdUI->m_nID) {
- case ID_OPTIONS_JOYPAD_AUTOFIRE_A:
- check = (theApp.autoFire & 1) != 0;
- break;
- case ID_OPTIONS_JOYPAD_AUTOFIRE_B:
- check = (theApp.autoFire & 2) != 0;
- break;
- case ID_OPTIONS_JOYPAD_AUTOFIRE_L:
- check = (theApp.autoFire & 512) != 0;
- break;
- case ID_OPTIONS_JOYPAD_AUTOFIRE_R:
- check = (theApp.autoFire & 256) != 0;
- break;
- }
- pCmdUI->SetCheck(check);
-}
-
-LRESULT MainWnd::OnConfirmMode(WPARAM, LPARAM)
-{
- // we need to do this separately or the window will not have the right
- // parent. must be related to the way MFC does modal dialogs
- winConfirmMode();
- return 0;
-}
-
-void MainWnd::winConfirmMode()
-{
- if(theApp.renderMethod == DIRECT_DRAW && theApp.videoOption > VIDEO_4X) {
- theApp.winCheckFullscreen();
- ModeConfirm dlg(theApp.m_pMainWnd);
-
- if(!dlg.DoModal()) {
- theApp.updateVideoSize(ID_OPTIONS_VIDEO_X2);
- }
- }
- theApp.winAccelMgr.UpdateMenu(theApp.menu);
-}
-
-void MainWnd::OnOptionsVideoFullscreenmaxscale()
-{
- MaxScale dlg;
-
- theApp.winCheckFullscreen();
-
- dlg.DoModal();
-}
-
-
-void MainWnd::OnLinkOptions()
-{
- LinkOptions dlg;
-
- dlg.DoModal();
-}
-
-void MainWnd::OnOptionsLinkLog()
-{
- if(linklog){
- if(linklogfile!=NULL) fclose(linklogfile);
- linklog = 0;
- linklogfile = NULL;
- } else {
- linklog=1;
- openLinkLog();
- }
-}
-
-void MainWnd::OnUpdateOptionsLinkLog(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(linklog);
-}
-
-void MainWnd::OnOptionsLinkRFU()
-{
- if(adapter) adapter = false;
- else {
- adapter = true;
- MessageBox("Please note this is the first version\nof RFU emulation code and it's not 100% bug free.\nAlso only 2 players single computer are supported at this time.", "Warning", MB_OK);
- }
-}
-
-void MainWnd::OnUpdateOptionsLinkRFU(CCmdUI* pCmdUI)
-{
- pCmdUI->SetCheck(adapter);
-}
\ No newline at end of file
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+#include "MainWnd.h"
+
+#include "Associate.h"
+#include "Directories.h"
+#include "FileDlg.h"
+#include "GameOverrides.h"
+#include "LinkOptions.h"
+#include "GBColorDlg.h"
+#include "Joypad.h"
+#include "MaxScale.h"
+#include "ModeConfirm.h"
+#include "Reg.h"
+#include "RewindInterval.h"
+#include "skin.h"
+#include "Throttle.h"
+#include "WinResUtil.h"
+
+#include "../System.h"
+#include "../agbprint.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../Sound.h"
+#include "../gb/GB.h"
+#include "../gb/gbGlobals.h"
+#include "../gb/gbPrinter.h"
+#include "../Link.h"
+#include
+
+extern int emulating;
+
+#define VBA_CONFIRM_MODE WM_APP + 100
+
+extern void CPUUpdateRenderBuffers(bool force);
+
+void MainWnd::OnOptionsFrameskipThrottleNothrottle()
+{
+ theApp.throttle = 0;
+ theApp.autoFrameSkip = false;
+}
+
+void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.throttle == 0);
+}
+
+void MainWnd::OnOptionsFrameskipThrottle25()
+{
+ theApp.throttle = 25;
+ theApp.autoFrameSkip = false;
+}
+
+void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.throttle == 25);
+}
+
+void MainWnd::OnOptionsFrameskipThrottle50()
+{
+ theApp.throttle = 50;
+ theApp.autoFrameSkip = false;
+}
+
+void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.throttle == 50);
+}
+
+void MainWnd::OnOptionsFrameskipThrottle100()
+{
+ theApp.throttle = 100;
+ theApp.autoFrameSkip = false;
+}
+
+void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.throttle == 100);
+}
+
+void MainWnd::OnOptionsFrameskipThrottle150()
+{
+ theApp.throttle = 150;
+ theApp.autoFrameSkip = false;
+}
+
+void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.throttle == 150);
+}
+
+void MainWnd::OnOptionsFrameskipThrottle200()
+{
+ theApp.throttle = 200;
+ theApp.autoFrameSkip = false;
+}
+
+void MainWnd::OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.throttle == 200);
+}
+
+
+void MainWnd::OnOptionsFrameskipThrottleOther()
+{
+ Throttle dlg;
+ int v = (int)dlg.DoModal();
+
+ if( v ) {
+ theApp.throttle = v;
+ theApp.autoFrameSkip = false;
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsFrameskipThrottleOther(CCmdUI* pCmdUI)
+{
+ int throttle = theApp.throttle;
+ pCmdUI->SetCheck(throttle != 0 && throttle != 25 &&
+ throttle != 50 && throttle != 100 &&
+ throttle != 150 && throttle != 200);
+}
+
+void MainWnd::OnOptionsFrameskipAutomatic()
+{
+ theApp.autoFrameSkip = !theApp.autoFrameSkip;
+ if(!theApp.autoFrameSkip && emulating)
+ theApp.updateFrameSkip();
+ else
+ {
+ theApp.throttle = false;
+ frameSkip = 0;
+ systemFrameSkip = 0;
+ }
+}
+
+void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.autoFrameSkip);
+}
+
+BOOL MainWnd::OnOptionsFrameskip(UINT nID)
+{
+ switch(nID) {
+ case ID_OPTIONS_VIDEO_FRAMESKIP_0:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_1:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_2:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_3:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_4:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_5:
+ if(theApp.cartridgeType == IMAGE_GBA) {
+ frameSkip = nID - ID_OPTIONS_VIDEO_FRAMESKIP_0;
+ } else {
+ gbFrameSkip = nID - ID_OPTIONS_VIDEO_FRAMESKIP_0;
+ }
+ if(emulating)
+ theApp.updateFrameSkip();
+ theApp.autoFrameSkip = false;
+ return TRUE;
+ break;
+ case ID_OPTIONS_VIDEO_FRAMESKIP_6:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_7:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_8:
+ case ID_OPTIONS_VIDEO_FRAMESKIP_9:
+ if(theApp.cartridgeType == IMAGE_GBA) {
+ frameSkip = 6 + nID - ID_OPTIONS_VIDEO_FRAMESKIP_6;
+ } else {
+ gbFrameSkip = 6 + nID - ID_OPTIONS_VIDEO_FRAMESKIP_6;
+ }
+ if(emulating)
+ theApp.updateFrameSkip();
+ theApp.autoFrameSkip = false;
+ return TRUE;
+ break;
+ }
+ return FALSE;
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip0(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 0 : gbFrameSkip == 0);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip1(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 1 : gbFrameSkip == 1);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip2(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 2 : gbFrameSkip == 2);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip3(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 3 : gbFrameSkip == 3);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip4(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 4 : gbFrameSkip == 4);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip5(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 5 : gbFrameSkip == 5);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip6(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 6 : gbFrameSkip == 6);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip7(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 7 : gbFrameSkip == 7);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip8(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 8 : gbFrameSkip == 8);
+}
+
+void MainWnd::OnUpdateOptionsVideoFrameskip9(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.cartridgeType == IMAGE_GBA ? frameSkip == 9 : gbFrameSkip == 9);
+}
+
+
+void MainWnd::OnOptionsVideoVsync()
+{
+ theApp.vsync = !theApp.vsync;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("vsync"), theApp.vsync );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoVsync(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.vsync);
+}
+
+void MainWnd::OnUpdateOptionsVideoX1(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_1X);
+}
+
+void MainWnd::OnUpdateOptionsVideoX2(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_2X);
+}
+
+void MainWnd::OnUpdateOptionsVideoX3(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_3X);
+}
+
+void MainWnd::OnUpdateOptionsVideoX4(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_4X);
+}
+
+void MainWnd::OnUpdateOptionsVideoFullscreen320x240(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.mode320Available);
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_320x240);
+}
+
+void MainWnd::OnUpdateOptionsVideoFullscreen640x480(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.mode640Available);
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_640x480);
+}
+
+void MainWnd::OnUpdateOptionsVideoFullscreen800x600(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.mode800Available);
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_800x600);
+}
+
+void MainWnd::OnUpdateOptionsVideoFullscreen1024x768(CCmdUI *pCmdUI)
+{
+ pCmdUI->Enable(theApp.mode1024Available);
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_1024x768);
+}
+
+void MainWnd::OnUpdateOptionsVideoFullscreen1280x1024(CCmdUI *pCmdUI)
+{
+ pCmdUI->Enable(theApp.mode1280Available);
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_1280x1024);
+}
+
+BOOL MainWnd::OnOptionVideoSize(UINT nID)
+{
+ theApp.updateVideoSize(nID);
+ theApp.m_pMainWnd->PostMessage(VBA_CONFIRM_MODE);
+ return TRUE;
+}
+
+
+void MainWnd::OnOptionsVideoFullscreen320x240()
+{
+ OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN320X240);
+}
+
+void MainWnd::OnOptionsVideoFullscreen640x480()
+{
+ OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN640X480);
+}
+
+void MainWnd::OnOptionsVideoFullscreen800x600()
+{
+ OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN800X600);
+}
+
+void MainWnd::OnOptionsVideoFullscreen1024x768()
+{
+ OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN1024X768);
+}
+
+void MainWnd::OnOptionsVideoFullscreen1280x1024()
+{
+ OnOptionVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN1280X1024);
+}
+
+void MainWnd::OnOptionsVideoFullscreen()
+{
+ theApp.winCheckFullscreen();
+ GUID *pGUID = NULL;
+ int size = theApp.display->selectFullScreenMode(&pGUID);
+ if(size != -1) {
+ int width = (size >> 12) & 4095;
+ int height = (size & 4095);
+ int colorDepth = (size >> 24);
+ if(width != theApp.fsWidth ||
+ height != theApp.fsHeight ||
+ colorDepth != theApp.fsColorDepth ||
+ pGUID != theApp.pVideoDriverGUID ||
+ theApp.videoOption != VIDEO_OTHER) {
+ theApp.fsForceChange = true;
+ theApp.fsWidth = width;
+ theApp.fsHeight = height;
+ theApp.fsFrequency = 60;
+ theApp.fsColorDepth = colorDepth;
+ theApp.pVideoDriverGUID = pGUID;
+ if(pGUID) {
+ theApp.videoDriverGUID = *pGUID;
+ regSetDwordValue("defaultVideoDriver", FALSE);
+ regSetBinaryValue("videoDriverGUID",
+ (char *)pGUID, sizeof(GUID));
+ } else {
+ regSetDwordValue("defaultVideoDriver", TRUE);
+ }
+ theApp.updateVideoSize(ID_OPTIONS_VIDEO_FULLSCREEN);
+ theApp.m_pMainWnd->PostMessage(VBA_CONFIRM_MODE);
+ }
+ }
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsVideoFullscreen(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.videoOption == VIDEO_OTHER);
+}
+
+void MainWnd::OnOptionsVideoDisablesfx()
+{
+ cpuDisableSfx = !cpuDisableSfx;
+ if(emulating && theApp.cartridgeType == IMAGE_GBA)
+ CPUUpdateRender();
+}
+
+void MainWnd::OnUpdateOptionsVideoDisablesfx(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(cpuDisableSfx);
+}
+
+
+void MainWnd::OnOptionsVideoFullscreenstretchtofit()
+{
+ theApp.fullScreenStretch = !theApp.fullScreenStretch;
+ theApp.updateWindowSize( theApp.videoOption );
+ if( theApp.display ) {
+ if( emulating ) {
+ theApp.display->clear( );
+ }
+ theApp.display->setOption( _T("fullScreenStretch"), theApp.fullScreenStretch );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoFullscreenstretchtofit(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.fullScreenStretch);
+}
+
+BOOL MainWnd::OnVideoLayer(UINT nID)
+{
+ layerSettings ^= 0x0100 <<
+ ((nID & 0xFFFF) - ID_OPTIONS_VIDEO_LAYERS_BG0);
+ layerEnable = DISPCNT & layerSettings;
+ CPUUpdateRenderBuffers(false);
+ return TRUE;
+}
+
+void MainWnd::OnUpdateVideoLayer(CCmdUI *pCmdUI)
+{
+ pCmdUI->SetCheck((layerSettings >> (8 + pCmdUI->m_nID - ID_OPTIONS_VIDEO_LAYERS_BG0)) & 1);
+ switch(pCmdUI->m_nID) {
+ case ID_OPTIONS_VIDEO_LAYERS_BG1:
+ case ID_OPTIONS_VIDEO_LAYERS_BG2:
+ case ID_OPTIONS_VIDEO_LAYERS_BG3:
+ case ID_OPTIONS_VIDEO_LAYERS_WIN1:
+ case ID_OPTIONS_VIDEO_LAYERS_OBJWIN:
+ pCmdUI->Enable(theApp.cartridgeType == 0);
+ break;
+ }
+}
+
+void MainWnd::OnOptionsVideoRendermethodGdi()
+{
+ theApp.renderMethod = GDI;
+ theApp.updateRenderMethod(false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsVideoRendermethodGdi(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.renderMethod == GDI);
+}
+
+void MainWnd::OnOptionsVideoRendermethodDirectdraw()
+{
+ theApp.renderMethod = DIRECT_DRAW;
+ theApp.updateRenderMethod(false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsVideoRendermethodDirectdraw(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.renderMethod == DIRECT_DRAW);
+}
+
+void MainWnd::OnOptionsVideoRendermethodDirect3d()
+{
+ theApp.renderMethod = DIRECT_3D;
+ theApp.updateRenderMethod(false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsVideoRendermethodDirect3d(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.renderMethod == DIRECT_3D);
+}
+
+void MainWnd::OnOptionsVideoRendermethodOpengl()
+{
+ theApp.renderMethod = OPENGL;
+ theApp.updateRenderMethod(false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsVideoRendermethodOpengl(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.renderMethod == OPENGL);
+}
+
+
+void MainWnd::OnOptionsVideoTriplebuffering()
+{
+ theApp.tripleBuffering = !theApp.tripleBuffering;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("tripleBuffering"), theApp.tripleBuffering );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoTriplebuffering(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.tripleBuffering);
+}
+
+void MainWnd::OnOptionsVideoDdrawemulationonly()
+{
+ theApp.ddrawEmulationOnly = !theApp.ddrawEmulationOnly;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("ddrawEmulationOnly"), theApp.ddrawEmulationOnly );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoDdrawemulationonly(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.ddrawEmulationOnly);
+}
+
+
+void MainWnd::OnOptionsVideoDdrawusevideomemory()
+{
+ theApp.ddrawUseVideoMemory = !theApp.ddrawUseVideoMemory;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("ddrawUseVideoMemory"), theApp.ddrawUseVideoMemory );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoDdrawusevideomemory(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.ddrawUseVideoMemory);
+}
+
+void MainWnd::OnOptionsVideoRenderoptionsD3dnofilter()
+{
+ theApp.d3dFilter = 0;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("d3dFilter"), theApp.d3dFilter );
+ }
+}
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsD3dnofilter(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.d3dFilter == 0);
+}
+
+
+void MainWnd::OnOptionsVideoRenderoptionsD3dbilinear()
+{
+ theApp.d3dFilter = 1;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("d3dFilter"), theApp.d3dFilter );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsD3dbilinear(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.d3dFilter == 1);
+}
+
+
+void MainWnd::OnOptionsVideoRenderoptionsGlnearest()
+{
+ theApp.glFilter = 0;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("glFilter"), theApp.glFilter );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsGlnearest(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.glFilter == 0);
+}
+
+
+void MainWnd::OnOptionsVideoRenderoptionsGlbilinear()
+{
+ theApp.glFilter = 1;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("glFilter"), theApp.glFilter );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsGlbilinear(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.glFilter == 1);
+}
+
+
+void MainWnd::OnOptionsVideoRenderoptionsGltriangle()
+{
+ theApp.glType = 0;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("glType"), theApp.glType );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsGltriangle(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.glType == 0);
+}
+
+
+void MainWnd::OnOptionsVideoRenderoptionsGlquads()
+{
+ theApp.glType = 1;
+ if( theApp.display ) {
+ theApp.display->setOption( _T("glType"), theApp.glType );
+ }
+}
+
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsGlquads(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.glType == 1);
+}
+
+void MainWnd::OnOptionsVideoRenderoptionsSelectskin()
+{
+#ifndef NOSKINS
+ LPCTSTR exts[] = {".ini" };
+ CString filter = winLoadFilter(IDS_FILTER_INI);
+ CString title = winResLoadString(IDS_SELECT_SKIN_FILE);
+
+ FileDlg dlg(this,
+ theApp.skinName,
+ filter,
+ 0,
+ "INI",
+ exts,
+ "",
+ title,
+ false);
+
+ if(dlg.DoModal() == IDCANCEL) {
+ return;
+ }
+
+ bool result = false;
+ if(!theApp.skinEnabled) {
+ theApp.skinEnabled = !theApp.skinEnabled;
+ regSetDwordValue("skinEnabled", theApp.skinEnabled);
+ }
+
+ if(theApp.skin && theApp.skinEnabled) {
+ delete theApp.skin;
+ theApp.skin = NULL;
+ }
+
+ theApp.skinName = dlg.GetPathName();
+
+ theApp.winUpdateSkin();
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+#else
+ systemMessage( 0, _T("This build of VBA does not support skins!") );
+#endif
+}
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsSelectskin(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.display && theApp.display->isSkinSupported() &&
+ theApp.videoOption <= VIDEO_4X);
+}
+
+void MainWnd::OnOptionsVideoRenderoptionsSkin()
+{
+#ifndef NOSKINS
+ theApp.skinEnabled = !theApp.skinEnabled;
+ theApp.updateRenderMethod(true);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+#else
+ systemMessage( 0, _T("This build of VBA does not support skins!") );
+#endif
+}
+
+void MainWnd::OnUpdateOptionsVideoRenderoptionsSkin(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.skinEnabled);
+ pCmdUI->Enable(theApp.display && theApp.display->isSkinSupported() && theApp.videoOption <= VIDEO_4X);
+}
+
+void MainWnd::OnOptionsEmulatorAssociate()
+{
+ theApp.winCheckFullscreen();
+ Associate dlg;
+ dlg.DoModal();
+}
+
+void MainWnd::OnOptionsEmulatorDirectories()
+{
+ theApp.winCheckFullscreen();
+ Directories dlg;
+ dlg.DoModal();
+}
+
+void MainWnd::OnOptionsEmulatorDisablestatusmessages()
+{
+ theApp.disableStatusMessage = !theApp.disableStatusMessage;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorDisablestatusmessages(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.disableStatusMessage);
+}
+
+void MainWnd::OnOptionsEmulatorSynchronize()
+{
+ synchronize = !synchronize;
+ if (synchronize)
+ theApp.throttle = false;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(synchronize);
+}
+
+void MainWnd::OnOptionsEmulatorPausewheninactive()
+{
+ theApp.pauseWhenInactive = !theApp.pauseWhenInactive;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorPausewheninactive(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.pauseWhenInactive);
+}
+
+void MainWnd::OnOptionsEmulatorSpeeduptoggle()
+{
+ theApp.speedupToggle = !theApp.speedupToggle;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSpeeduptoggle(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.speedupToggle);
+}
+
+void MainWnd::OnOptionsEmulatorAutomaticallyipspatch()
+{
+ theApp.autoIPS = !theApp.autoIPS;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorAutomaticallyipspatch(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.autoIPS);
+}
+
+void MainWnd::OnOptionsEmulatorAgbprint()
+{
+ agbPrintEnable(!agbPrintIsEnabled());
+}
+
+void MainWnd::OnUpdateOptionsEmulatorAgbprint(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(agbPrintIsEnabled());
+}
+
+void MainWnd::OnOptionsEmulatorRealtimeclock()
+{
+ theApp.winRtcEnable = !theApp.winRtcEnable;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorRealtimeclock(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winRtcEnable);
+}
+
+void MainWnd::OnOptionsEmulatorAutohidemenu()
+{
+ theApp.autoHideMenu = !theApp.autoHideMenu;
+}
+
+void MainWnd::OnOptionsEmulatorGenericflashcard()
+{
+ if(emulating && theApp.cartridgeType == IMAGE_GB)
+ theApp.winGenericflashcardEnable = !theApp.winGenericflashcardEnable;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorGenericflashcard(CCmdUI* pCmdUI)
+{
+ if(emulating && theApp.cartridgeType == IMAGE_GB)
+ pCmdUI->SetCheck(theApp.winGenericflashcardEnable);
+ else
+ pCmdUI->SetCheck(false);
+
+ pCmdUI->Enable(emulating && theApp.cartridgeType == IMAGE_GB);
+}
+
+void MainWnd::OnUpdateOptionsEmulatorAutohidemenu(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.autoHideMenu);
+}
+
+
+void MainWnd::OnOptionsEmulatorRewindinterval()
+{
+ RewindInterval dlg(theApp.rewindTimer/6);
+ int v = (int)dlg.DoModal();
+
+ if( v >= 0 ) {
+ theApp.rewindTimer = v*6; // convert to a multiple of 10 frames
+ regSetDwordValue("rewindTimer", v);
+ if(v == 0) {
+ if(theApp.rewindMemory) {
+ free(theApp.rewindMemory);
+ theApp.rewindMemory = NULL;
+ }
+ theApp.rewindCount = 0;
+ theApp.rewindCounter = 0;
+ theApp.rewindSaveNeeded = false;
+ } else {
+ if(theApp.rewindMemory == NULL) {
+ theApp.rewindMemory = (char *)malloc(8*REWIND_SIZE);
+ }
+ }
+ }
+}
+
+
+BOOL MainWnd::OnOptionsEmulatorShowSpeed(UINT nID)
+{
+ switch(nID) {
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_NONE:
+ theApp.showSpeed = 0;
+ systemSetTitle("VisualBoyAdvance");
+ break;
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE:
+ theApp.showSpeed = 1;
+ break;
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED:
+ theApp.showSpeed = 2;
+ break;
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT:
+ theApp.showSpeedTransparent = !theApp.showSpeedTransparent;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorShowSpeed(CCmdUI *pCmdUI)
+{
+ switch(pCmdUI->m_nID) {
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_NONE:
+ pCmdUI->SetCheck(theApp.showSpeed == 0);
+ break;
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_PERCENTAGE:
+ pCmdUI->SetCheck(theApp.showSpeed == 1);
+ break;
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_DETAILED:
+ pCmdUI->SetCheck(theApp.showSpeed == 2);
+ break;
+ case ID_OPTIONS_EMULATOR_SHOWSPEED_TRANSPARENT:
+ pCmdUI->SetCheck(theApp.showSpeedTransparent);
+ break;
+ }
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeAutomatic()
+{
+ theApp.winSaveType = 0;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeAutomatic(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winSaveType == 0);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeEeprom()
+{
+ theApp.winSaveType = 1;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeEeprom(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winSaveType == 1);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeSram()
+{
+ theApp.winSaveType = 2;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeSram(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winSaveType == 2);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeFlash()
+{
+ theApp.winSaveType = 3;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winSaveType == 3);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeEepromsensor()
+{
+ theApp.winSaveType = 4;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeEepromsensor(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winSaveType == 4);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeNone()
+{
+ theApp.winSaveType = 5;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeNone(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winSaveType == 5);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeFlash512k()
+{
+ flashSetSize(0x10000);
+ theApp.winFlashSize = 0x10000;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash512k(CCmdUI* pCmdUI)
+{
+ // changed theApp.winFlashSize to flashSize to reflect the actual
+ // flashsize value used by the emu (it can change upon battery loading)
+ pCmdUI->SetCheck(flashSize == 0x10000);
+}
+
+void MainWnd::OnOptionsEmulatorSavetypeFlash1m()
+{
+ flashSetSize(0x20000);
+ theApp.winFlashSize = 0x20000;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSavetypeFlash1m(CCmdUI* pCmdUI)
+{
+ // changed theApp.winFlashSize to flashSize to reflect the actual
+ // flashsize value used by the emu (it can change upon battery loading)
+ pCmdUI->SetCheck(flashSize == 0x20000);
+}
+
+void MainWnd::OnOptionsEmulatorUsebiosfile()
+{
+ if(!theApp.biosFileName.IsEmpty())
+ theApp.useBiosFile = !theApp.useBiosFile;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorUsebiosfile(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.useBiosFile);
+ pCmdUI->Enable(!theApp.biosFileName.IsEmpty());
+}
+
+void MainWnd::OnOptionsEmulatorSkipbios()
+{
+ theApp.skipBiosFile = !theApp.skipBiosFile;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorSkipbios(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.skipBiosFile);
+}
+
+void MainWnd::OnOptionsEmulatorSelectbiosfile()
+{
+ theApp.winCheckFullscreen();
+ LPCTSTR exts[] = { "" };
+ CString filter = winLoadFilter(IDS_FILTER_BIOS);
+ CString title = winResLoadString(IDS_SELECT_BIOS_FILE);
+
+ FileDlg dlg(this,
+ theApp.biosFileName,
+ filter,
+ 0,
+ "BIOS",
+ exts,
+ "",
+ title,
+ false);
+
+ if(dlg.DoModal() == IDOK) {
+ theApp.biosFileName = dlg.GetPathName();
+ }
+}
+
+void MainWnd::OnOptionsEmulatorPngformat()
+{
+ theApp.captureFormat = 0;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorPngformat(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.captureFormat == 0);
+}
+
+void MainWnd::OnOptionsEmulatorBmpformat()
+{
+ theApp.captureFormat = 1;
+}
+
+void MainWnd::OnUpdateOptionsEmulatorBmpformat(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.captureFormat == 1);
+}
+
+void MainWnd::OnOptionsSoundOff()
+{
+ soundOffFlag = true;
+ soundShutdown();
+ theApp.soundInitialized = false;
+}
+
+void MainWnd::OnUpdateOptionsSoundOff(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundOffFlag);
+}
+
+void MainWnd::OnOptionsSoundMute()
+{
+ soundDisable(0x30f);
+}
+
+void MainWnd::OnUpdateOptionsSoundMute(CCmdUI* pCmdUI)
+{
+ int active = soundGetEnable() & 0x30f;
+ pCmdUI->SetCheck(active == 0);
+}
+
+void MainWnd::OnOptionsSoundOn()
+{
+ if(soundOffFlag) {
+ soundOffFlag = false;
+ // soundInit();
+ }
+ soundEnable(0x30f);
+}
+
+void MainWnd::OnUpdateOptionsSoundOn(CCmdUI* pCmdUI)
+{
+ int active = soundGetEnable() & 0x30f;
+ pCmdUI->SetCheck(active != 0 && !soundOffFlag);
+}
+
+void MainWnd::OnOptionsSoundUseoldsynchronization()
+{
+ theApp.useOldSync = !theApp.useOldSync;
+ systemMessage(IDS_SETTING_WILL_BE_EFFECTIVE,
+ "Setting will be effective the next time you start the emulator");
+}
+
+void MainWnd::OnUpdateOptionsSoundUseoldsynchronization(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.useOldSync);
+}
+
+void MainWnd::OnOptionsSoundEcho()
+{
+ soundEcho = !soundEcho;
+}
+
+void MainWnd::OnUpdateOptionsSoundEcho(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundEcho);
+}
+
+void MainWnd::OnOptionsSoundLowpassfilter()
+{
+ soundLowPass = !soundLowPass;
+}
+
+void MainWnd::OnUpdateOptionsSoundLowpassfilter(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundLowPass);
+}
+
+void MainWnd::OnOptionsSoundReversestereo()
+{
+ soundReverse = !soundReverse;
+}
+
+void MainWnd::OnUpdateOptionsSoundReversestereo(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundReverse);
+}
+
+void MainWnd::OnOptionsSound11khz()
+{
+ if(theApp.cartridgeType == 0)
+ soundSetQuality(4);
+ else
+ gbSoundSetQuality(4);
+}
+
+void MainWnd::OnUpdateOptionsSound11khz(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundQuality == 4);
+}
+
+void MainWnd::OnOptionsSound22khz()
+{
+ if(theApp.cartridgeType == 0)
+ soundSetQuality(2);
+ else
+ gbSoundSetQuality(2);
+}
+
+void MainWnd::OnUpdateOptionsSound22khz(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundQuality == 2);
+}
+
+void MainWnd::OnOptionsSound44khz()
+{
+ if(theApp.cartridgeType == 0)
+ soundSetQuality(1);
+ else
+ gbSoundSetQuality(1);
+}
+
+void MainWnd::OnUpdateOptionsSound44khz(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundQuality == 1);
+}
+
+BOOL MainWnd::OnOptionsSoundVolume(UINT nID)
+{
+ soundVolume = nID - ID_OPTIONS_SOUND_VOLUME_1X;
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsSoundVolume(CCmdUI *pCmdUI)
+{
+ pCmdUI->SetCheck(soundVolume == (int)(pCmdUI->m_nID - ID_OPTIONS_SOUND_VOLUME_1X));
+}
+
+
+void MainWnd::OnOptionsSoundVolume25x()
+{
+ soundVolume = 4;
+}
+
+void MainWnd::OnUpdateOptionsSoundVolume25x(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundVolume == 4);
+}
+
+void MainWnd::OnOptionsSoundVolume5x()
+{
+ soundVolume = 5;
+}
+
+void MainWnd::OnUpdateOptionsSoundVolume5x(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundVolume == 5);
+}
+
+void MainWnd::updateSoundChannels(UINT id)
+{
+ int flag = 0;
+
+ if(id == ID_OPTIONS_SOUND_CHANNEL1)
+ flag = 1;
+
+ if(id == ID_OPTIONS_SOUND_CHANNEL2)
+ flag = 2;
+
+ if(id == ID_OPTIONS_SOUND_CHANNEL3)
+ flag = 4;
+
+ if(id == ID_OPTIONS_SOUND_CHANNEL4)
+ flag = 8;
+
+ if(id == ID_OPTIONS_SOUND_DIRECTSOUNDA)
+ flag = 256;
+
+ if(id == ID_OPTIONS_SOUND_DIRECTSOUNDB)
+ flag = 512;
+
+ int active = soundGetEnable() & 0x30f;
+
+ if(active & flag)
+ active &= (~flag);
+ else
+ active |= flag;
+
+ soundEnable(active);
+ soundDisable((~active)&0x30f);
+}
+
+void MainWnd::OnOptionsSoundChannel1()
+{
+ updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL1);
+}
+
+void MainWnd::OnUpdateOptionsSoundChannel1(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundGetEnable() & 1);
+}
+
+void MainWnd::OnOptionsSoundChannel2()
+{
+ updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL2);
+}
+
+void MainWnd::OnUpdateOptionsSoundChannel2(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundGetEnable() & 2);
+}
+
+void MainWnd::OnOptionsSoundChannel3()
+{
+ updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL3);
+}
+
+void MainWnd::OnUpdateOptionsSoundChannel3(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundGetEnable() & 4);
+}
+
+void MainWnd::OnOptionsSoundChannel4()
+{
+ updateSoundChannels(ID_OPTIONS_SOUND_CHANNEL4);
+}
+
+void MainWnd::OnUpdateOptionsSoundChannel4(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundGetEnable() & 8);
+}
+
+void MainWnd::OnOptionsSoundDirectsounda()
+{
+ updateSoundChannels(ID_OPTIONS_SOUND_DIRECTSOUNDA);
+}
+
+void MainWnd::OnUpdateOptionsSoundDirectsounda(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundGetEnable() & 256);
+ pCmdUI->Enable(theApp.cartridgeType == 0);
+}
+
+void MainWnd::OnOptionsSoundDirectsoundb()
+{
+ updateSoundChannels(ID_OPTIONS_SOUND_DIRECTSOUNDB);
+}
+
+void MainWnd::OnUpdateOptionsSoundDirectsoundb(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(soundGetEnable() & 512);
+ pCmdUI->Enable(theApp.cartridgeType == 0);
+}
+
+BOOL MainWnd::OnOptionsSoundPcminterpolation(UINT nID)
+{
+ switch (nID)
+ {
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE:
+ soundInterpolation = 0;
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_LINEAR:
+ soundInterpolation = 1;
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_CUBIC:
+ soundInterpolation = 2;
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_FIR:
+ soundInterpolation = 3;
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE:
+ soundInterpolation = 4;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsSoundPcminterpolation(CCmdUI *pCmdUI)
+{
+ switch (pCmdUI->m_nID)
+ {
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_NONE:
+ pCmdUI->SetCheck(soundInterpolation == 0);
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_LINEAR:
+ pCmdUI->SetCheck(soundInterpolation == 1);
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_CUBIC:
+ pCmdUI->SetCheck(soundInterpolation == 2);
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_FIR:
+ pCmdUI->SetCheck(soundInterpolation == 3);
+ break;
+ case ID_OPTIONS_SOUND_PCMINTERPOLATION_LIBRESAMPLE:
+ pCmdUI->SetCheck(soundInterpolation == 4);
+ break;
+
+ default:
+ return;
+ }
+ pCmdUI->Enable(theApp.cartridgeType == 0);
+}
+
+void MainWnd::OnOptionsGameboyBorder()
+{
+ theApp.winGbBorderOn = !theApp.winGbBorderOn;
+ gbBorderOn = theApp.winGbBorderOn;
+ if(emulating && theApp.cartridgeType == 1 && gbBorderOn) {
+ gbSgbRenderBorder();
+ }
+ theApp.updateWindowSize(theApp.videoOption);
+}
+
+void MainWnd::OnUpdateOptionsGameboyBorder(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.winGbBorderOn);
+}
+
+void MainWnd::OnOptionsGameboyPrinter()
+{
+ theApp.winGbPrinterEnabled = !theApp.winGbPrinterEnabled;
+ if(theApp.winGbPrinterEnabled)
+ gbSerialFunction = gbPrinterSend;
+ else
+ gbSerialFunction = NULL;
+}
+
+void MainWnd::OnUpdateOptionsGameboyPrinter(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbSerialFunction == gbPrinterSend);
+}
+
+void MainWnd::OnOptionsGameboyBorderAutomatic()
+{
+ gbBorderAutomatic = !gbBorderAutomatic;
+ if(emulating && theApp.cartridgeType == 1 && gbBorderOn) {
+ gbSgbRenderBorder();
+ theApp.updateWindowSize(theApp.videoOption);
+ }
+}
+
+void MainWnd::OnUpdateOptionsGameboyBorderAutomatic(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbBorderAutomatic);
+}
+
+void MainWnd::OnOptionsGameboyAutomatic()
+{
+ gbEmulatorType = 0;
+}
+
+void MainWnd::OnUpdateOptionsGameboyAutomatic(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbEmulatorType == 0);
+}
+
+void MainWnd::OnOptionsGameboyGba()
+{
+ gbEmulatorType = 4;
+}
+
+void MainWnd::OnUpdateOptionsGameboyGba(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbEmulatorType == 4);
+}
+
+void MainWnd::OnOptionsGameboyCgb()
+{
+ gbEmulatorType = 1;
+}
+
+void MainWnd::OnUpdateOptionsGameboyCgb(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbEmulatorType == 1);
+}
+
+void MainWnd::OnOptionsGameboySgb()
+{
+ gbEmulatorType = 2;
+}
+
+void MainWnd::OnUpdateOptionsGameboySgb(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbEmulatorType == 2);
+}
+
+void MainWnd::OnOptionsGameboySgb2()
+{
+ gbEmulatorType = 5;
+}
+
+void MainWnd::OnUpdateOptionsGameboySgb2(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbEmulatorType == 5);
+}
+
+void MainWnd::OnOptionsGameboyGb()
+{
+ gbEmulatorType = 3;
+}
+
+void MainWnd::OnUpdateOptionsGameboyGb(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbEmulatorType == 3);
+}
+
+void MainWnd::OnOptionsGameboyRealcolors()
+{
+ gbColorOption = 0;
+}
+
+void MainWnd::OnUpdateOptionsGameboyRealcolors(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbColorOption == 0);
+}
+
+void MainWnd::OnOptionsGameboyGameboycolors()
+{
+ gbColorOption = 1;
+}
+
+void MainWnd::OnUpdateOptionsGameboyGameboycolors(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(gbColorOption == 1);
+}
+
+
+void MainWnd::OnOptionsGameboyColors()
+{
+ theApp.winCheckFullscreen();
+ GBColorDlg dlg;
+ if(dlg.DoModal()) {
+ gbPaletteOption = dlg.getWhich();
+ memcpy(systemGbPalette, dlg.getColors(), 24*sizeof(u16));
+ if(emulating && theApp.cartridgeType == 1) {
+ memcpy(gbPalette, &systemGbPalette[dlg.getWhich()*8], 8*sizeof(u16));
+ }
+ }
+}
+
+BOOL MainWnd::OnOptionsPriority(UINT nID)
+{
+ switch(nID) {
+ case ID_OPTIONS_PRIORITY_HIGHEST:
+ theApp.threadPriority = 0;
+ break;
+ case ID_OPTIONS_PRIORITY_ABOVENORMAL:
+ theApp.threadPriority = 1;
+ break;
+ case ID_OPTIONS_PRIORITY_NORMAL:
+ theApp.threadPriority = 2;
+ break;
+ case ID_OPTIONS_PRIORITY_BELOWNORMAL:
+ theApp.threadPriority = 3;
+ break;
+ default:
+ return FALSE;
+ }
+ theApp.updatePriority();
+
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsPriority(CCmdUI *pCmdUI)
+{
+ switch(pCmdUI->m_nID) {
+ case ID_OPTIONS_PRIORITY_HIGHEST:
+ pCmdUI->SetCheck(theApp.threadPriority == 0);
+ break;
+ case ID_OPTIONS_PRIORITY_ABOVENORMAL:
+ pCmdUI->SetCheck(theApp.threadPriority == 1);
+ break;
+ case ID_OPTIONS_PRIORITY_NORMAL:
+ pCmdUI->SetCheck(theApp.threadPriority == 2);
+ break;
+ case ID_OPTIONS_PRIORITY_BELOWNORMAL:
+ pCmdUI->SetCheck(theApp.threadPriority == 3);
+ break;
+ }
+}
+
+BOOL MainWnd::OnOptionsFilter(UINT nID)
+{
+ switch(nID)
+ {
+ case ID_OPTIONS_FILTER_NORMAL:
+ theApp.filterType = FILTER_NONE;
+ break;
+ case ID_OPTIONS_FILTER_TVMODE:
+ theApp.filterType = FILTER_TVMODE;
+ break;
+ case ID_OPTIONS_FILTER_2XSAI:
+ theApp.filterType = FILTER_2XSAI;
+ break;
+ case ID_OPTIONS_FILTER_SUPER2XSAI:
+ theApp.filterType = FILTER_SUPER2XSAI;
+ break;
+ case ID_OPTIONS_FILTER_SUPEREAGLE:
+ theApp.filterType = FILTER_SUPEREAGLE;
+ break;
+ case ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL:
+ theApp.filterType = FILTER_PIXELATE;
+ break;
+ case ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X:
+ theApp.filterType = FILTER_MAMESCALE2X;
+ break;
+ case ID_OPTIONS_FILTER16BIT_SIMPLE2X:
+ theApp.filterType = FILTER_SIMPLE2X;
+ break;
+ case ID_OPTIONS_FILTER_BILINEAR:
+ theApp.filterType = FILTER_BILINEAR;
+ break;
+ case ID_OPTIONS_FILTER_BILINEARPLUS:
+ theApp.filterType = FILTER_BILINEARPLUS;
+ break;
+ case ID_OPTIONS_FILTER_SCANLINES:
+ theApp.filterType = FILTER_SCANLINES;
+ break;
+ case ID_OPTIONS_FILTER_HQ2X:
+ theApp.filterType = FILTER_HQ2X;
+ break;
+ case ID_OPTIONS_FILTER_LQ2X:
+ theApp.filterType = FILTER_LQ2X;
+ break;
+ case ID_OPTIONS_FILTER_SIMPLE3X:
+ theApp.filterType = FILTER_SIMPLE3X;
+ break;
+ case ID_OPTIONS_FILTER_SIMPLE4X:
+ theApp.filterType = FILTER_SIMPLE4X;
+ break;
+ case ID_OPTIONS_FILTER_HQ3X:
+ theApp.filterType = FILTER_HQ3X;
+ break;
+ case ID_OPTIONS_FILTER_HQ4X:
+ theApp.filterType = FILTER_HQ4X;
+ break;
+ default:
+ return FALSE;
+ }
+ theApp.updateFilter();
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsFilter(CCmdUI *pCmdUI)
+{
+ pCmdUI->Enable( systemColorDepth == 16 || systemColorDepth == 32 );
+
+ switch(pCmdUI->m_nID) {
+ case ID_OPTIONS_FILTER_NORMAL:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_NONE);
+ break;
+ case ID_OPTIONS_FILTER_TVMODE:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_TVMODE);
+ break;
+ case ID_OPTIONS_FILTER_2XSAI:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_2XSAI);
+ break;
+ case ID_OPTIONS_FILTER_SUPER2XSAI:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_SUPER2XSAI);
+ break;
+ case ID_OPTIONS_FILTER_SUPEREAGLE:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_SUPEREAGLE);
+ break;
+ case ID_OPTIONS_FILTER16BIT_PIXELATEEXPERIMENTAL:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_PIXELATE);
+ break;
+ case ID_OPTIONS_FILTER16BIT_ADVANCEMAMESCALE2X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_MAMESCALE2X);
+ break;
+ case ID_OPTIONS_FILTER16BIT_SIMPLE2X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_SIMPLE2X);
+ break;
+ case ID_OPTIONS_FILTER_BILINEAR:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_BILINEAR);
+ break;
+ case ID_OPTIONS_FILTER_BILINEARPLUS:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_BILINEARPLUS);
+ break;
+ case ID_OPTIONS_FILTER_SCANLINES:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_SCANLINES);
+ break;
+ case ID_OPTIONS_FILTER_HQ2X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_HQ2X);
+ break;
+ case ID_OPTIONS_FILTER_LQ2X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_LQ2X);
+ break;
+ case ID_OPTIONS_FILTER_SIMPLE3X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_SIMPLE3X);
+ break;
+ case ID_OPTIONS_FILTER_SIMPLE4X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_SIMPLE4X);
+ break;
+ case ID_OPTIONS_FILTER_HQ3X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_HQ3X);
+ break;
+ case ID_OPTIONS_FILTER_HQ4X:
+ pCmdUI->SetCheck(theApp.filterType == FILTER_HQ4X);
+ break;
+ }
+}
+
+BOOL MainWnd::OnOptionsFilterIFB(UINT nID)
+{
+ switch(nID) {
+ case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE:
+ theApp.ifbType = 0;
+ break;
+ case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR:
+ theApp.ifbType = 1;
+ break;
+ case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART:
+ theApp.ifbType = 2;
+ break;
+ default:
+ return FALSE;
+ }
+ theApp.updateIFB();
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsFilterIFB(CCmdUI *pCmdUI)
+{
+ switch(pCmdUI->m_nID) {
+ case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_NONE:
+ pCmdUI->SetCheck(theApp.ifbType == 0);
+ break;
+ case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_MOTIONBLUR:
+ pCmdUI->SetCheck(theApp.ifbType == 1);
+ break;
+ case ID_OPTIONS_FILTER_INTERFRAMEBLENDING_SMART:
+ pCmdUI->SetCheck(theApp.ifbType == 2);
+ break;
+ }
+}
+
+void MainWnd::OnOptionsFilterDisablemmx()
+{
+#ifdef MMX
+ theApp.disableMMX = !theApp.disableMMX;
+ if(!theApp.disableMMX)
+ cpu_mmx = theApp.detectMMX();
+ else
+ cpu_mmx = 0;
+#endif
+}
+
+void MainWnd::OnUpdateOptionsFilterDisablemmx(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.disableMMX);
+}
+
+void MainWnd::OnOptionsFilterLcdcolors()
+{
+// todo: depreciated
+ theApp.filterLCD = !theApp.filterLCD;
+ utilUpdateSystemColorMaps();
+}
+
+void MainWnd::OnUpdateOptionsFilterLcdcolors(CCmdUI *pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.filterLCD);
+}
+
+void MainWnd::OnOptionsLanguageSystem()
+{
+ theApp.winSetLanguageOption(0, false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsLanguageSystem(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.languageOption == 0);
+}
+
+void MainWnd::OnOptionsLanguageEnglish()
+{
+ theApp.winSetLanguageOption(1, false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsLanguageEnglish(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.languageOption == 1);
+}
+
+void MainWnd::OnOptionsLanguageOther()
+{
+ theApp.winCheckFullscreen();
+ theApp.winSetLanguageOption(2, false);
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnUpdateOptionsLanguageOther(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.languageOption == 2);
+}
+
+
+void MainWnd::OnOptionsJoypadConfigure1()
+{
+ theApp.winCheckFullscreen();
+ JoypadConfig dlg(0);
+ dlg.DoModal();
+}
+
+void MainWnd::OnUpdateOptionsJoypadConfigure1(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
+}
+
+void MainWnd::OnOptionsJoypadConfigure2()
+{
+ theApp.winCheckFullscreen();
+ JoypadConfig dlg(1);
+ dlg.DoModal();
+}
+
+void MainWnd::OnUpdateOptionsJoypadConfigure2(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
+}
+
+void MainWnd::OnOptionsJoypadConfigure3()
+{
+ theApp.winCheckFullscreen();
+ JoypadConfig dlg(2);
+ dlg.DoModal();
+}
+
+void MainWnd::OnUpdateOptionsJoypadConfigure3(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
+}
+
+void MainWnd::OnOptionsJoypadConfigure4()
+{
+ theApp.winCheckFullscreen();
+ JoypadConfig dlg(3);
+ dlg.DoModal();
+}
+
+void MainWnd::OnUpdateOptionsJoypadConfigure4(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
+}
+
+BOOL MainWnd::OnOptionsJoypadDefault(UINT nID)
+{
+ theApp.joypadDefault = nID - ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1;
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsJoypadDefault(CCmdUI *pCmdUI)
+{
+ pCmdUI->SetCheck(theApp.joypadDefault == (int)(pCmdUI->m_nID - ID_OPTIONS_JOYPAD_DEFAULTJOYPAD_1));
+}
+
+void MainWnd::OnOptionsJoypadMotionconfigure()
+{
+ theApp.winCheckFullscreen();
+ MotionConfig dlg;
+ dlg.DoModal();
+}
+
+void MainWnd::OnUpdateOptionsJoypadMotionconfigure(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(theApp.videoOption != VIDEO_320x240);
+}
+
+BOOL MainWnd::OnOptionsJoypadAutofire(UINT nID)
+{
+ switch(nID) {
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_A:
+ if(theApp.autoFire & 1) {
+ theApp.autoFire &= ~1;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_A_DISABLED));
+ } else {
+ theApp.autoFire |= 1;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_A));
+ }
+ break;
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_B:
+ if(theApp.autoFire & 2) {
+ theApp.autoFire &= ~2;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_B_DISABLED));
+ } else {
+ theApp.autoFire |= 2;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_B));
+ }
+ break;
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_L:
+ if(theApp.autoFire & 512) {
+ theApp.autoFire &= ~512;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_L_DISABLED));
+ } else {
+ theApp.autoFire |= 512;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_L));
+ }
+ break;
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_R:
+ if(theApp.autoFire & 256) {
+ theApp.autoFire &= ~256;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_R_DISABLED));
+ } else {
+ theApp.autoFire |= 256;
+ systemScreenMessage(winResLoadString(IDS_AUTOFIRE_R));
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void MainWnd::OnUpdateOptionsJoypadAutofire(CCmdUI *pCmdUI)
+{
+ bool check = true;
+ switch(pCmdUI->m_nID) {
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_A:
+ check = (theApp.autoFire & 1) != 0;
+ break;
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_B:
+ check = (theApp.autoFire & 2) != 0;
+ break;
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_L:
+ check = (theApp.autoFire & 512) != 0;
+ break;
+ case ID_OPTIONS_JOYPAD_AUTOFIRE_R:
+ check = (theApp.autoFire & 256) != 0;
+ break;
+ }
+ pCmdUI->SetCheck(check);
+}
+
+LRESULT MainWnd::OnConfirmMode(WPARAM, LPARAM)
+{
+ // we need to do this separately or the window will not have the right
+ // parent. must be related to the way MFC does modal dialogs
+ winConfirmMode();
+ return 0;
+}
+
+void MainWnd::winConfirmMode()
+{
+ if( theApp.videoOption > VIDEO_4X ) {
+ theApp.winCheckFullscreen();
+ ModeConfirm dlg(theApp.m_pMainWnd);
+
+ if(!dlg.DoModal()) {
+ theApp.updateVideoSize(ID_OPTIONS_VIDEO_X2);
+ }
+ }
+ theApp.winAccelMgr.UpdateMenu(theApp.menu);
+}
+
+void MainWnd::OnOptionsVideoFullscreenmaxscale()
+{
+ MaxScale dlg;
+
+ theApp.winCheckFullscreen();
+
+ dlg.DoModal();
+
+ if( theApp.display ) {
+ theApp.display->setOption( _T("maxScale"), theApp.fsMaxScale );
+ }
+}
+
+
+void MainWnd::OnLinkOptions()
+{
+ LinkOptions dlg;
+
+ dlg.DoModal();
+}
+
+void MainWnd::OnOptionsLinkLog()
+{
+ if(linklog){
+ if(linklogfile!=NULL) fclose(linklogfile);
+ linklog = 0;
+ linklogfile = NULL;
+ } else {
+ linklog=1;
+ openLinkLog();
+ }
+}
+
+void MainWnd::OnUpdateOptionsLinkLog(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(linklog);
+}
+
+void MainWnd::OnOptionsLinkRFU()
+{
+ if(adapter) adapter = false;
+ else {
+ adapter = true;
+ MessageBox("Please note this is the first version\nof RFU emulation code and it's not 100% bug free.\nAlso only 2 players single computer are supported at this time.", "Warning", MB_OK);
+ }
+}
+
+void MainWnd::OnUpdateOptionsLinkRFU(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(adapter);
+}
+
+
+void MainWnd::OnOptionsEmulatorGameoverrides()
+{
+ if(emulating && theApp.cartridgeType == 0) {
+ GameOverrides dlg(this);
+ dlg.DoModal();
+ }
+}
+
+void MainWnd::OnUpdateOptionsEmulatorGameoverrides(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(emulating && (theApp.cartridgeType == 0));
+}
+
+void MainWnd::OnOptionsSoundHardwareacceleration()
+{
+ theApp.dsoundDisableHardwareAcceleration = !theApp.dsoundDisableHardwareAcceleration;
+ systemSoundShutdown();
+ systemSoundInit();
+}
+
+void MainWnd::OnUpdateOptionsSoundHardwareacceleration(CCmdUI *pCmdUI)
+{
+ pCmdUI->SetCheck(!theApp.dsoundDisableHardwareAcceleration);
+}
diff --git a/src/win32/MainWndTools.cpp b/src/win32/MainWndTools.cpp
index 1441a148..b75e0792 100644
--- a/src/win32/MainWndTools.cpp
+++ b/src/win32/MainWndTools.cpp
@@ -51,7 +51,7 @@ static char THIS_FILE[] = __FILE__;
extern bool debugger;
extern int emulating;
-extern int remoteSocket;
+extern SOCKET remoteSocket;
extern void remoteCleanUp();
extern void remoteSetSockets(SOCKET, SOCKET);
@@ -205,7 +205,7 @@ void MainWnd::OnToolsDebugGdb()
remoteSetSockets(wait.getListenSocket(), wait.getSocket());
debugger = true;
emulating = 1;
- theApp.cartridgeType = 0;
+ theApp.cartridgeType = IMAGE_GBA;
theApp.filename = "\\gnu_stub";
rom = (u8 *)malloc(0x2000000);
workRAM = (u8 *)calloc(1, 0x40000);
@@ -214,7 +214,7 @@ void MainWnd::OnToolsDebugGdb()
paletteRAM = (u8 *)calloc(1,0x400);
vram = (u8 *)calloc(1, 0x20000);
oam = (u8 *)calloc(1, 0x400);
- pix = (u8 *)calloc(1, 4 * 240 * 160);
+ pix = (u8 *)calloc(1, 4 * 241 * 162);
ioMem = (u8 *)calloc(1, 0x400);
theApp.emulator = GBASystem;
diff --git a/src/win32/MapView.cpp b/src/win32/MapView.cpp
index 92e7c725..a93bcfda 100644
--- a/src/win32/MapView.cpp
+++ b/src/win32/MapView.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -465,6 +465,7 @@ void MapView::renderMode5()
bg = 2;
}
+
void MapView::OnRefresh()
{
paint();
@@ -511,6 +512,12 @@ void MapView::paint()
case 5:
renderMode5();
break;
+ case 6:
+ renderMode5();
+ break;
+ case 7:
+ renderMode5();
+ break;
}
enableButtons(mode);
SIZE s;
@@ -759,7 +766,7 @@ u32 MapView::GetClickAddress(int x, int y)
u32 base = ((control >> 8) & 0x1f) * 0x800 + 0x6000000;
// all text bgs (16 bits)
- if(mode == 0 ||(mode < 3 && bg < 2)) {
+ if(mode == 0 ||(mode < 3 && bg < 2) || mode == 6 || mode == 7) {
return GetTextClickAddress(base, x, y);
}
// rot bgs (8 bits)
@@ -779,8 +786,8 @@ LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam)
u8 *colors = (u8 *)lParam;
mapViewZoom.setColors(colors);
- int x = wParam & 0xffff;
- int y = (wParam >> 16);
+ int x = (int)(wParam & 0xffff);
+ int y = (int)(wParam >> 16);
CString buffer;
buffer.Format("(%d,%d)", x, y);
@@ -791,7 +798,7 @@ LRESULT MapView::OnMapInfo(WPARAM wParam, LPARAM lParam)
GetDlgItem(IDC_ADDRESS)->SetWindowText(buffer);
int mode = DISPCNT & 7;
- if(mode >= 3) {
+ if(mode >= 3 && mode <=5) {
// bitmap modes
GetDlgItem(IDC_TILE_NUM)->SetWindowText("---");
GetDlgItem(IDC_FLIP)->SetWindowText("--");
@@ -991,36 +998,39 @@ void MapView::savePNG(const char *name)
fclose(fp);
}
-void MapView::OnSave()
+void MapView::OnSave()
{
- CString filename;
+ if(rom != NULL)
+ {
+ CString filename;
- if(theApp.captureFormat == 0)
- filename = "map.png";
- else
- filename = "map.bmp";
+ if(theApp.captureFormat == 0)
+ filename = "map.png";
+ else
+ filename = "map.bmp";
- LPCTSTR exts[] = {".png", ".bmp" };
+ LPCTSTR exts[] = {".png", ".bmp" };
- CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
- CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
+ CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
+ CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
- FileDlg dlg(this,
- filename,
- filter,
- theApp.captureFormat ? 2 : 1,
- theApp.captureFormat ? "BMP" : "PNG",
- exts,
- "",
- title,
- true);
+ FileDlg dlg(this,
+ filename,
+ filter,
+ theApp.captureFormat ? 2 : 1,
+ theApp.captureFormat ? "BMP" : "PNG",
+ exts,
+ "",
+ title,
+ true);
- if(dlg.DoModal() == IDCANCEL) {
- return;
+ if(dlg.DoModal() == IDCANCEL) {
+ return;
+ }
+
+ if(dlg.getFilterIndex() == 2)
+ saveBMP(dlg.GetPathName());
+ else
+ savePNG(dlg.GetPathName());
}
-
- if(dlg.getFilterIndex() == 2)
- saveBMP(dlg.GetPathName());
- else
- savePNG(dlg.GetPathName());
}
diff --git a/src/win32/MapView.h b/src/win32/MapView.h
index db0a575d..48d068f7 100644
--- a/src/win32/MapView.h
+++ b/src/win32/MapView.h
@@ -31,7 +31,7 @@
#include "ZoomControl.h"
#include "ResizeDlg.h"
#include "IUpdate.h"
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
/////////////////////////////////////////////////////////////////////////////
// MapView dialog
diff --git a/src/win32/MaxScale.cpp b/src/win32/MaxScale.cpp
index 1972f887..2daf5d7f 100644
--- a/src/win32/MaxScale.cpp
+++ b/src/win32/MaxScale.cpp
@@ -71,10 +71,6 @@ void MaxScale::OnOk()
CString tmp;
m_value.GetWindowText(tmp);
theApp.fsMaxScale = atoi(tmp);
- theApp.updateWindowSize(theApp.videoOption);
- if(theApp.display)
- theApp.display->clear();
- this->SetFocus();
EndDialog(TRUE);
}
diff --git a/src/win32/MemoryViewer.cpp b/src/win32/MemoryViewer.cpp
index ff9c8796..27443ae2 100644
--- a/src/win32/MemoryViewer.cpp
+++ b/src/win32/MemoryViewer.cpp
@@ -535,8 +535,8 @@ void MemoryViewer::moveAddress(s32 offset, int nibbleOff)
}
LRESULT MemoryViewer::OnWMChar(WPARAM wParam, LPARAM LPARAM)
-{
- if(OnEditInput(wParam))
+{ // The WM_CHAR message uses Unicode Transformation Format (UTF)-16.
+ if(OnEditInput((UINT)(wParam & 0xFFFF)))
return 0;
return 1;
}
diff --git a/src/win32/MemoryViewer.h b/src/win32/MemoryViewer.h
index 2db7189e..e1a82e39 100644
--- a/src/win32/MemoryViewer.h
+++ b/src/win32/MemoryViewer.h
@@ -20,7 +20,7 @@
#if !defined(AFX_MEMORYVIEWER_H__52C50474_5399_4D0B_A3E4_4C52C4E0EAA0__INCLUDED_)
#define AFX_MEMORYVIEWER_H__52C50474_5399_4D0B_A3E4_4C52C4E0EAA0__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/MemoryViewerAddressSize.h b/src/win32/MemoryViewerAddressSize.h
index 71d3b5ee..248c9420 100644
--- a/src/win32/MemoryViewerAddressSize.h
+++ b/src/win32/MemoryViewerAddressSize.h
@@ -20,7 +20,7 @@
#if !defined(AFX_MEMORYVIEWERADDRESSSIZE_H__04605262_2B1D_4EED_A467_B6C56AC2CACD__INCLUDED_)
#define AFX_MEMORYVIEWERADDRESSSIZE_H__04605262_2B1D_4EED_A467_B6C56AC2CACD__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/MemoryViewerDlg.cpp b/src/win32/MemoryViewerDlg.cpp
index 09449de4..3078102f 100644
--- a/src/win32/MemoryViewerDlg.cpp
+++ b/src/win32/MemoryViewerDlg.cpp
@@ -320,14 +320,59 @@ void MemoryViewerDlg::setCurrentAddress(u32 address)
void MemoryViewerDlg::OnSave()
{
- MemoryViewerAddressSize dlg;
- CString buffer;
+ if(rom != NULL)
+ {
+ MemoryViewerAddressSize dlg;
+ CString buffer;
- dlg.setAddress(m_viewer.getCurrentAddress());
+ dlg.setAddress(m_viewer.getCurrentAddress());
- LPCTSTR exts[] = { ".dmp" };
+ LPCTSTR exts[] = { ".dmp" };
- if(dlg.DoModal() == IDOK) {
+ if(dlg.DoModal() == IDOK) {
+ CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP);
+ CString title = winResLoadString(IDS_SELECT_DUMP_FILE);
+
+ FileDlg file(this,
+ buffer,
+ filter,
+ 0,
+ "DMP",
+ exts,
+ "",
+ title,
+ true);
+ if(file.DoModal() == IDOK) {
+ buffer = file.GetPathName();
+
+ FILE *f = fopen(buffer, "wb");
+
+ if(f == NULL) {
+ systemMessage(IDS_ERROR_CREATING_FILE, buffer);
+ return;
+ }
+
+ int size = dlg.getSize();
+ u32 addr = dlg.getAddress();
+
+ for(int i = 0; i < size; i++) {
+ fputc(CPUReadByteQuick(addr), f);
+ addr++;
+ }
+
+ fclose(f);
+ }
+ }
+ }
+}
+
+void MemoryViewerDlg::OnLoad()
+{
+ if(rom != NULL)
+ {
+ CString buffer;
+ LPCTSTR exts[] = { ".dmp" };
+
CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP);
CString title = winResLoadString(IDS_SELECT_DUMP_FILE);
@@ -338,86 +383,47 @@ void MemoryViewerDlg::OnSave()
"DMP",
exts,
"",
- title,
- true);
+ title,
+ false);
+
if(file.DoModal() == IDOK) {
buffer = file.GetPathName();
-
- FILE *f = fopen(buffer, "wb");
-
+ FILE *f = fopen(buffer, "rb");
if(f == NULL) {
- systemMessage(IDS_ERROR_CREATING_FILE, buffer);
+ systemMessage(IDS_CANNOT_OPEN_FILE,
+ "Cannot open file %s",
+ buffer);
return;
}
+
+ MemoryViewerAddressSize dlg;
- int size = dlg.getSize();
- u32 addr = dlg.getAddress();
+ fseek(f, 0, SEEK_END);
+ int size = ftell(f);
- for(int i = 0; i < size; i++) {
- fputc(CPUReadByteQuick(addr), f);
- addr++;
+ fseek(f, 0, SEEK_SET);
+
+ dlg.setAddress(m_viewer.getCurrentAddress());
+ dlg.setSize(size);
+
+ if(dlg.DoModal() == IDOK) {
+ int size = dlg.getSize();
+ u32 addr = dlg.getAddress();
+
+ for(int i = 0; i < size; i++) {
+ int c = fgetc(f);
+ if(c == -1)
+ break;
+ CPUWriteByteQuick(addr, c);
+ addr++;
+ }
+ OnRefresh();
}
-
- fclose(f);
+ fclose(f);
}
}
}
-void MemoryViewerDlg::OnLoad()
-{
- CString buffer;
- LPCTSTR exts[] = { ".dmp" };
-
- CString filter = theApp.winLoadFilter(IDS_FILTER_DUMP);
- CString title = winResLoadString(IDS_SELECT_DUMP_FILE);
-
- FileDlg file(this,
- buffer,
- filter,
- 0,
- "DMP",
- exts,
- "",
- title,
- false);
-
- if(file.DoModal() == IDOK) {
- buffer = file.GetPathName();
- FILE *f = fopen(buffer, "rb");
- if(f == NULL) {
- systemMessage(IDS_CANNOT_OPEN_FILE,
- "Cannot open file %s",
- buffer);
- return;
- }
-
- MemoryViewerAddressSize dlg;
-
- fseek(f, 0, SEEK_END);
- int size = ftell(f);
-
- fseek(f, 0, SEEK_SET);
-
- dlg.setAddress(m_viewer.getCurrentAddress());
- dlg.setSize(size);
-
- if(dlg.DoModal() == IDOK) {
- int size = dlg.getSize();
- u32 addr = dlg.getAddress();
-
- for(int i = 0; i < size; i++) {
- int c = fgetc(f);
- if(c == -1)
- break;
- CPUWriteByteQuick(addr, c);
- addr++;
- }
- OnRefresh();
- }
- fclose(f);
- }
-}
-
void MemoryViewerDlg::PostNcDestroy()
{
delete this;
diff --git a/src/win32/ModeConfirm.cpp b/src/win32/ModeConfirm.cpp
index 6ac88032..6ac68bf9 100644
--- a/src/win32/ModeConfirm.cpp
+++ b/src/win32/ModeConfirm.cpp
@@ -100,7 +100,7 @@ BOOL ModeConfirm::OnInitDialog()
// EXCEPTION: OCX Property Pages should return FALSE
}
-void ModeConfirm::OnTimer(UINT nIDEvent)
+void ModeConfirm::OnTimer(UINT_PTR nIDEvent)
{
CString buffer;
count--;
diff --git a/src/win32/ModeConfirm.h b/src/win32/ModeConfirm.h
index 0e5a1838..4f8787ec 100644
--- a/src/win32/ModeConfirm.h
+++ b/src/win32/ModeConfirm.h
@@ -34,7 +34,7 @@ class ModeConfirm : public CDialog
// Construction
public:
int count;
- UINT timer;
+ UINT_PTR timer;
ModeConfirm(CWnd* pParent); // standard constructor
// Dialog Data
@@ -60,7 +60,7 @@ class ModeConfirm : public CDialog
afx_msg void OnOk();
afx_msg void OnDestroy();
virtual BOOL OnInitDialog();
- afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnTimer(UINT_PTR nIDEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
diff --git a/src/win32/OamView.cpp b/src/win32/OamView.cpp
index 13c233ac..c389c4d4 100644
--- a/src/win32/OamView.cpp
+++ b/src/win32/OamView.cpp
@@ -463,37 +463,40 @@ void OamView::savePNG(const char *name)
void OamView::OnSave()
{
- CString captureBuffer;
+ if(rom != NULL)
+ {
+ CString captureBuffer;
- if(theApp.captureFormat == 0)
- captureBuffer = "oam.png";
- else
- captureBuffer = "oam.bmp";
+ if(theApp.captureFormat == 0)
+ captureBuffer = "oam.png";
+ else
+ captureBuffer = "oam.bmp";
- LPCTSTR exts[] = {".png", ".bmp" };
+ LPCTSTR exts[] = {".png", ".bmp" };
- CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
- CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
+ CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
+ CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
- FileDlg dlg(this,
- captureBuffer,
- filter,
- theApp.captureFormat ? 2 : 1,
- theApp.captureFormat ? "BMP" : "PNG",
- exts,
- "",
- title,
- true);
+ FileDlg dlg(this,
+ captureBuffer,
+ filter,
+ theApp.captureFormat ? 2 : 1,
+ theApp.captureFormat ? "BMP" : "PNG",
+ exts,
+ "",
+ title,
+ true);
- if(dlg.DoModal() == IDCANCEL) {
- return;
+ if(dlg.DoModal() == IDCANCEL) {
+ return;
+ }
+ captureBuffer = dlg.GetPathName();
+
+ if(dlg.getFilterIndex() == 2)
+ saveBMP(captureBuffer);
+ else
+ savePNG(captureBuffer);
}
- captureBuffer = dlg.GetPathName();
-
- if(dlg.getFilterIndex() == 2)
- saveBMP(captureBuffer);
- else
- savePNG(captureBuffer);
}
BOOL OamView::OnInitDialog()
diff --git a/src/win32/OpenGL.cpp b/src/win32/OpenGL.cpp
index e64b302d..2cf71e84 100644
--- a/src/win32/OpenGL.cpp
+++ b/src/win32/OpenGL.cpp
@@ -1,552 +1,669 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-#include "MainWnd.h"
-#include
-
-#include "../System.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../Text.h"
-#include "../Util.h"
-
-#include "Reg.h"
-#include "..\..\res\resource.h"
-
-#include "../gbafilter.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#ifdef MMX
-extern "C" bool cpu_mmx;
-
-extern bool detectMMX();
-#endif
-
-extern int Init_2xSaI(u32);
-extern void winlog(const char *,...);
-extern int systemSpeed;
-
-class OpenGLDisplay : public IDisplay {
-private:
- HDC hDC;
- HGLRC hglrc;
- GLuint texture;
- int width;
- int height;
- float size;
- u8 *filterData;
- bool failed;
-
- bool initializeTexture(int w, int h);
- void updateFiltering(int);
-public:
- OpenGLDisplay();
- virtual ~OpenGLDisplay();
-
- virtual bool initialize();
- virtual void cleanup();
- virtual void render();
- virtual void checkFullScreen();
- virtual void renderMenu();
- virtual void clear();
- virtual bool changeRenderSize(int w, int h);
- virtual void resize(int w, int h);
- virtual DISPLAY_TYPE getType() { return OPENGL; };
- virtual void setOption(const char *, int);
- virtual int selectFullScreenMode(GUID **);
-};
-
-OpenGLDisplay::OpenGLDisplay()
-{
- hDC = NULL;
- hglrc = NULL;
- texture = 0;
- width = 0;
- height = 0;
- size = 0.0f;
- filterData = (u8 *)malloc(4*4*4*256*240);
- failed = false;
-}
-
-OpenGLDisplay::~OpenGLDisplay()
-{
- cleanup();
-}
-
-void OpenGLDisplay::cleanup()
-{
- if(texture != 0) {
- glDeleteTextures(1, &texture);
- texture = 0;
- }
- if(hglrc != NULL) {
- wglDeleteContext(hglrc);
- wglMakeCurrent(NULL, NULL);
- hglrc = NULL;
- }
- if(hDC != NULL) {
- ReleaseDC(*theApp.m_pMainWnd, hDC);
- hDC = NULL;
- }
- if(filterData) {
- free(filterData);
- filterData = NULL;
- }
- width = 0;
- height = 0;
- size = 0.0f;
-}
-
-bool OpenGLDisplay::initialize()
-{
- theApp.sizeX = 240;
- theApp.sizeY = 160;
-
- switch(theApp.videoOption) {
- case VIDEO_1X:
- theApp.surfaceSizeX = theApp.sizeX;
- theApp.surfaceSizeY = theApp.sizeY;
- break;
- case VIDEO_2X:
- theApp.surfaceSizeX = theApp.sizeX * 2;
- theApp.surfaceSizeY = theApp.sizeY * 2;
- break;
- case VIDEO_3X:
- theApp.surfaceSizeX = theApp.sizeX * 3;
- theApp.surfaceSizeY = theApp.sizeY * 3;
- break;
- case VIDEO_4X:
- theApp.surfaceSizeX = theApp.sizeX * 4;
- theApp.surfaceSizeY = theApp.sizeY * 4;
- break;
- case VIDEO_320x240:
- case VIDEO_640x480:
- case VIDEO_800x600:
- case VIDEO_1024x768:
- case VIDEO_1280x1024:
- case VIDEO_OTHER:
- {
- RECT r;
- ::GetWindowRect(GetDesktopWindow(), &r);
- theApp.fsWidth = r.right - r.left;
- theApp.fsHeight = r.bottom - r.top;
-
- /* Need to fix this code later. For now, Fullscreen takes the whole
- screen.
- int scaleX = (fsWidth / sizeX);
- int scaleY = (fsHeight / sizeY);
- int min = scaleX < scaleY ? scaleX : scaleY;
- surfaceSizeX = sizeX * min;
- surfaceSizeY = sizeY * min;
- if(fullScreenStretch) {
- */
- theApp.surfaceSizeX = theApp.fsWidth;
- theApp.surfaceSizeY = theApp.fsHeight;
- // }
- }
- break;
- }
-
- theApp.rect.left = 0;
- theApp.rect.top = 0;
- theApp.rect.right = theApp.sizeX;
- theApp.rect.bottom = theApp.sizeY;
-
- theApp.dest.left = 0;
- theApp.dest.top = 0;
- theApp.dest.right = theApp.surfaceSizeX;
- theApp.dest.bottom = theApp.surfaceSizeY;
-
- DWORD style = WS_POPUP | WS_VISIBLE;
- DWORD styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- style |= WS_OVERLAPPEDWINDOW;
- else
- styleEx = 0;
-
- if(theApp.videoOption <= VIDEO_4X)
- AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
- else
- AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
-
- int winSizeX = theApp.dest.right-theApp.dest.left;
- int winSizeY = theApp.dest.bottom-theApp.dest.top;
-
- if(theApp.videoOption > VIDEO_4X) {
- winSizeX = theApp.fsWidth;
- winSizeY = theApp.fsHeight;
- }
-
- int x = 0;
- int y = 0;
-
- if(theApp.videoOption <= VIDEO_4X) {
- x = theApp.windowPositionX;
- y = theApp.windowPositionY;
- }
-
- // Create a window
- MainWnd *pWnd = new MainWnd;
- theApp.m_pMainWnd = pWnd;
-
- pWnd->CreateEx(styleEx,
- theApp.wndClass,
- "VisualBoyAdvance",
- style,
- x,y,winSizeX,winSizeY,
- NULL,
- 0);
-
- if (!(HWND)*pWnd) {
- winlog("Error creating Window %08x\n", GetLastError());
- return FALSE;
- }
-
- theApp.updateMenuBar();
-
- theApp.adjustDestRect();
-
- theApp.mode320Available = FALSE;
- theApp.mode640Available = FALSE;
- theApp.mode800Available = FALSE;
-
- CDC *dc = pWnd->GetDC();
- HDC hDC = dc->GetSafeHdc();
-
- PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
- 1, // version number
- PFD_DRAW_TO_WINDOW | // support window
- PFD_SUPPORT_OPENGL | // support OpenGL
- PFD_DOUBLEBUFFER, // double buffered
- PFD_TYPE_RGBA, // RGBA type
- 16, // 16-bit color depth
- 0, 0, 0, 0, 0, 0, // color bits ignored
- 0, // no alpha buffer
- 0, // shift bit ignored
- 0, // no accumulation buffer
- 0, 0, 0, 0, // accum bits ignored
- 32, // 32-bit z-buffer
- 0, // no stencil buffer
- 0, // no auxiliary buffer
- PFD_MAIN_PLANE, // main layer
- 0, // reserved
- 0, 0, 0 // layer masks ignored
- };
- int iPixelFormat;
-
- if(!(iPixelFormat = ChoosePixelFormat(hDC, &pfd))) {
- winlog("Failed ChoosePixelFormat\n");
- return false;
- }
-
- // obtain detailed information about
- // the device context's first pixel format
- if(!(DescribePixelFormat(hDC, iPixelFormat,
- sizeof(PIXELFORMATDESCRIPTOR), &pfd))) {
- winlog("Failed DescribePixelFormat\n");
- return false;
- }
-
- if(!SetPixelFormat(hDC, iPixelFormat, &pfd)) {
- winlog("Failed SetPixelFormat\n");
- return false;
- }
-
- if(!(hglrc = wglCreateContext(hDC))) {
- winlog("Failed wglCreateContext\n");
- return false;
- }
-
- if(!wglMakeCurrent(hDC, hglrc)) {
- winlog("Failed wglMakeCurrent\n");
- return false;
- }
- pWnd->ReleaseDC(dc);
-
- // setup 2D gl environment
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glEnable(GL_TEXTURE_2D);
-
- glViewport(0, 0, theApp.surfaceSizeX, theApp.surfaceSizeY);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(0.0, (GLdouble)(theApp.surfaceSizeX), (GLdouble)(theApp.surfaceSizeY),
- 0.0, 0.0,1.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- systemRedShift = 3;
- systemGreenShift = 11;
- systemBlueShift = 19;
- systemColorDepth = 32;
- theApp.fsColorDepth = 32;
-
- Init_2xSaI(32);
-#ifdef MMX
- if(!theApp.disableMMX)
- cpu_mmx = theApp.detectMMX();
- else
- cpu_mmx = 0;
-#endif
-
- if(theApp.ddrawDebug) {
- winlog("R shift: %d\n", systemRedShift);
- winlog("G shift: %d\n", systemGreenShift);
- winlog("B shift: %d\n", systemBlueShift);
- }
-
- utilUpdateSystemColorMaps(theApp.filterLCD);
- theApp.updateFilter();
- theApp.updateIFB();
-
- if(failed)
- return false;
-
- pWnd->DragAcceptFiles(TRUE);
-
- return TRUE;
-}
-
-void OpenGLDisplay::clear()
-{
-}
-
-void OpenGLDisplay::renderMenu()
-{
- checkFullScreen();
- if(theApp.m_pMainWnd)
- theApp.m_pMainWnd->DrawMenuBar();
-}
-
-void OpenGLDisplay::checkFullScreen()
-{
- // if(tripleBuffering)
- // pOpenGL->FlipToGDISurface();
-}
-
-void OpenGLDisplay::render()
-{
- int pitch = theApp.filterWidth * 4 + 4;
- u8 *data = pix + (theApp.sizeX+1)*4;
-
- if(theApp.filterFunction) {
- data = filterData;
- theApp.filterFunction(pix+pitch,
- pitch,
- (u8*)theApp.delta,
- (u8*)filterData,
- theApp.rect.right * (systemColorDepth / 8),
- theApp.filterWidth,
- theApp.filterHeight);
- }
-
- if(theApp.videoOption > VIDEO_4X && theApp.showSpeed) {
- char buffer[30];
- if(theApp.showSpeed == 1)
- sprintf(buffer, "%3d%%", systemSpeed);
- else
- sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
- systemFrameSkip,
- theApp.showRenderedFrames);
-
- if(theApp.filterFunction) {
- int p = theApp.rect.right * 2;
- if(systemColorDepth == 24)
- p = theApp.rect.right * 3;
- else if(systemColorDepth == 32)
- p = theApp.rect.right * 4;
- if(theApp.showSpeedTransparent)
- drawTextTransp((u8*)filterData,
- p,
- 10,
- theApp.rect.bottom-10,
- buffer);
- else
- drawText((u8*)filterData,
- p,
- 10,
- theApp.rect.bottom-10,
- buffer);
- } else {
- if(theApp.showSpeedTransparent)
- drawTextTransp((u8*)pix,
- pitch,
- 10,
- theApp.filterHeight-10,
- buffer);
- else
- drawText((u8*)pix,
- pitch,
- 10,
- theApp.filterHeight-10,
- buffer);
- }
- }
-
- // Texturemap complete texture to surface so we have free scaling
- // and antialiasing
- if(theApp.filterFunction) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, theApp.rect.right);
- } else {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, theApp.sizeX+1);
- }
-
- glTexSubImage2D( GL_TEXTURE_2D,0,
- 0,0, theApp.rect.right,theApp.rect.bottom,
- GL_RGBA,GL_UNSIGNED_BYTE,data);
-
- if(theApp.glType == 0) {
- glBegin(GL_TRIANGLE_STRIP);
- glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
- glTexCoord2f(theApp.rect.right/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0);
- glTexCoord2f(0.0, theApp.rect.bottom/size); glVertex3i(0, theApp.surfaceSizeY, 0);
- glTexCoord2f(theApp.rect.right/size, theApp.rect.bottom/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0);
- glEnd();
- } else {
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
- glTexCoord2f(theApp.rect.right/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0);
- glTexCoord2f(theApp.rect.right/size, theApp.rect.bottom/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0);
- glTexCoord2f(0.0, theApp.rect.bottom/size); glVertex3i(0, theApp.surfaceSizeY, 0);
- glEnd();
- }
-
- CDC *dc = theApp.m_pMainWnd->GetDC();
-
- if(theApp.screenMessage) {
- if(((GetTickCount() - theApp.screenMessageTime) < 3000) &&
- !theApp.disableStatusMessage) {
- dc->SetTextColor(RGB(255,0,0));
- dc->SetBkMode(TRANSPARENT);
- dc->TextOut(10, theApp.surfaceSizeY - 20, theApp.screenMessageBuffer);
- } else {
- theApp.screenMessage = false;
- }
- }
-
- SwapBuffers(dc->GetSafeHdc());
-
- theApp.m_pMainWnd->ReleaseDC(dc);
-}
-
-void OpenGLDisplay::resize(int w, int h)
-{
- glViewport(0, 0, w, h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(0.0, (GLdouble)(w), (GLdouble)(h),
- 0.0, 0.0,1.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-}
-
-void OpenGLDisplay::updateFiltering(int value)
-{
- switch(value) {
- case 0:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- break;
- case 1:
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- break;
- }
-}
-
-bool OpenGLDisplay::initializeTexture(int w, int h)
-{
- int mySize = 256;
- size = 256.0f;
- if(w > 255 || h > 255) {
- size = 512.0f;
- mySize = 512;
- }
- if(w > 512 || h > 512) {
- size = 1024.0f;
- mySize = 1024;
- }
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
-
- int filter = regQueryDwordValue("glFilter", 0);
- if(filter < 0 || filter > 1)
- filter = 0;
- updateFiltering(filter);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mySize, mySize, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, NULL );
- width = w;
- height = h;
-
- return true;
-}
-
-bool OpenGLDisplay::changeRenderSize(int w, int h)
-{
- if(width != w || height != h) {
- if(texture != 0) {
- glDeleteTextures(1, &texture);
- texture = 0;
- }
- if(!initializeTexture(w, h)) {
- failed = true;
- return false;
- }
- }
- return true;
-}
-
-void OpenGLDisplay::setOption(const char *option, int value)
-{
- if(!strcmp(option, "glFilter"))
- updateFiltering(value);
-}
-
-int OpenGLDisplay::selectFullScreenMode(GUID **)
-{
- HWND wnd = GetDesktopWindow();
- RECT r;
- GetWindowRect(wnd, &r);
- int w = (r.right - r.left) & 4095;
- int h = (r.bottom - r.top) & 4095;
- HDC dc = GetDC(wnd);
- int c = GetDeviceCaps(dc, BITSPIXEL);
- ReleaseDC(wnd, dc);
-
- return (c << 24) | (w << 12) | h;
-}
-
-IDisplay *newOpenGLDisplay()
-{
- return new OpenGLDisplay();
-}
-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+// Copyright (C) 2005-2006 VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+
+#include "MainWnd.h"
+
+#include "../System.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../Text.h"
+#include "../Util.h"
+#include "../gb/gbGlobals.h"
+
+#include
+
+// OpenGL
+#include // main include file
+typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
+
+extern int Init_2xSaI(u32);
+extern void winlog(const char *,...);
+extern int systemSpeed;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#ifdef MMX
+extern "C" bool cpu_mmx;
+extern bool detectMMX();
+#endif
+
+
+class OpenGLDisplay : public IDisplay {
+private:
+ HDC hDC;
+ HGLRC hglrc;
+ GLuint texture;
+ int width;
+ int height;
+ float size;
+ u8 *filterData;
+ RECT destRect;
+ bool failed;
+
+ void initializeMatrices( int w, int h );
+ bool initializeTexture( int w, int h );
+ void updateFiltering( int value );
+ void setVSync( int interval = 1 );
+ void calculateDestRect( int w, int h );
+
+public:
+ OpenGLDisplay();
+ virtual ~OpenGLDisplay();
+ virtual DISPLAY_TYPE getType() { return OPENGL; };
+
+ virtual bool initialize();
+ virtual void cleanup();
+ virtual void render();
+ virtual void renderMenu();
+ virtual void clear();
+ virtual bool changeRenderSize( int w, int h );
+ virtual void resize( int w, int h );
+ virtual void setOption( const char *, int );
+ virtual int selectFullScreenMode( GUID ** );
+};
+
+
+OpenGLDisplay::OpenGLDisplay()
+{
+ hDC = NULL;
+ hglrc = NULL;
+ texture = 0;
+ width = 0;
+ height = 0;
+ size = 0.0f;
+ filterData = (u8 *)malloc(4*4*256*240);
+ failed = false;
+}
+
+
+OpenGLDisplay::~OpenGLDisplay()
+{
+ cleanup();
+}
+
+
+void OpenGLDisplay::cleanup()
+{
+ if(texture != 0) {
+ glDeleteTextures(1, &texture);
+ texture = 0;
+ }
+
+ if(hglrc != NULL) {
+ wglDeleteContext(hglrc);
+ wglMakeCurrent(NULL, NULL);
+ hglrc = NULL;
+ }
+
+ if(hDC != NULL) {
+ ReleaseDC(*theApp.m_pMainWnd, hDC);
+ hDC = NULL;
+ }
+
+ if(filterData) {
+ free(filterData);
+ filterData = NULL;
+ }
+
+ width = 0;
+ height = 0;
+ size = 0.0f;
+}
+
+
+bool OpenGLDisplay::initialize()
+{
+ switch( theApp.cartridgeType )
+ {
+ case IMAGE_GBA:
+ theApp.sizeX = 240;
+ theApp.sizeY = 160;
+ break;
+ case IMAGE_GB:
+ if ( gbBorderOn )
+ {
+ theApp.sizeX = 256;
+ theApp.sizeY = 224;
+ }
+ else
+ {
+ theApp.sizeX = 160;
+ theApp.sizeY = 144;
+ }
+ break;
+ }
+
+
+ switch(theApp.videoOption)
+ {
+ case VIDEO_1X:
+ theApp.surfaceSizeX = theApp.sizeX;
+ theApp.surfaceSizeY = theApp.sizeY;
+ break;
+ case VIDEO_2X:
+ theApp.surfaceSizeX = theApp.sizeX * 2;
+ theApp.surfaceSizeY = theApp.sizeY * 2;
+ break;
+ case VIDEO_3X:
+ theApp.surfaceSizeX = theApp.sizeX * 3;
+ theApp.surfaceSizeY = theApp.sizeY * 3;
+ break;
+ case VIDEO_4X:
+ theApp.surfaceSizeX = theApp.sizeX * 4;
+ theApp.surfaceSizeY = theApp.sizeY * 4;
+ break;
+ case VIDEO_320x240:
+ case VIDEO_640x480:
+ case VIDEO_800x600:
+ case VIDEO_OTHER:
+ {
+ if( theApp.fullScreenStretch ) {
+ theApp.surfaceSizeX = theApp.fsWidth;
+ theApp.surfaceSizeY = theApp.fsHeight;
+ } else {
+ float scaleX = (float)theApp.fsWidth / (float)theApp.sizeX;
+ float scaleY = (float)theApp.fsHeight / (float)theApp.sizeY;
+ float min = ( scaleX < scaleY ) ? scaleX : scaleY;
+ if( theApp.fsMaxScale )
+ min = ( min > (float)theApp.fsMaxScale ) ? (float)theApp.fsMaxScale : min;
+ theApp.surfaceSizeX = (int)((float)theApp.sizeX * min);
+ theApp.surfaceSizeY = (int)((float)theApp.sizeY * min);
+ }
+ }
+ break;
+ }
+
+ theApp.rect.left = 0;
+ theApp.rect.top = 0;
+ theApp.rect.right = theApp.sizeX;
+ theApp.rect.bottom = theApp.sizeY;
+
+ theApp.dest.left = 0;
+ theApp.dest.top = 0;
+ theApp.dest.right = theApp.surfaceSizeX;
+ theApp.dest.bottom = theApp.surfaceSizeY;
+
+ DWORD style = WS_POPUP | WS_VISIBLE;
+ DWORD styleEx = 0;
+
+ if( theApp.videoOption <= VIDEO_4X )
+ style |= WS_OVERLAPPEDWINDOW;
+ else
+ styleEx = 0;
+
+ if( theApp.videoOption <= VIDEO_4X )
+ AdjustWindowRectEx( &theApp.dest, style, TRUE, styleEx );
+ else
+ AdjustWindowRectEx( &theApp.dest, style, FALSE, styleEx );
+
+ int winSizeX = theApp.dest.right - theApp.dest.left;
+ int winSizeY = theApp.dest.bottom - theApp.dest.top;
+ int x = 0, y = 0;
+
+ if( theApp.videoOption <= VIDEO_4X ) {
+ x = theApp.windowPositionX;
+ y = theApp.windowPositionY;
+ } else {
+ winSizeX = theApp.fsWidth;
+ winSizeY = theApp.fsHeight;
+ }
+
+ // Create a window
+ MainWnd *pWnd = new MainWnd;
+ theApp.m_pMainWnd = pWnd;
+
+ pWnd->CreateEx(
+ styleEx,
+ theApp.wndClass,
+ "VisualBoyAdvance",
+ style,
+ x,y,winSizeX,winSizeY,
+ NULL,
+ 0 );
+
+ if (!(HWND)*pWnd) {
+ winlog("Error creating Window %08x\n", GetLastError());
+ return FALSE;
+ }
+
+ theApp.updateMenuBar();
+
+ theApp.adjustDestRect();
+
+ theApp.mode320Available = FALSE;
+ theApp.mode640Available = FALSE;
+ theApp.mode800Available = FALSE;
+
+ CDC *dc = pWnd->GetDC();
+ HDC hDC = dc->GetSafeHdc();
+
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1, // version number
+ PFD_DRAW_TO_WINDOW | // support window
+ PFD_SUPPORT_OPENGL | // support OpenGL
+ PFD_DOUBLEBUFFER, // double buffered
+ PFD_TYPE_RGBA, // RGBA type
+ 24, // 24-bit color depth
+ 0, 0, 0, 0, 0, 0, // color bits ignored
+ 0, // no alpha buffer
+ 0, // shift bit ignored
+ 0, // no accumulation buffer
+ 0, 0, 0, 0, // accum bits ignored
+ 32, // 32-bit z-buffer
+ 0, // no stencil buffer
+ 0, // no auxiliary buffer
+ PFD_MAIN_PLANE, // main layer
+ 0, // reserved
+ 0, 0, 0 // layer masks ignored
+ };
+
+ int iPixelFormat;
+ if( !(iPixelFormat = ChoosePixelFormat( hDC, &pfd )) ) {
+ winlog( "Failed ChoosePixelFormat\n" );
+ return false;
+ }
+
+ // obtain detailed information about
+ // the device context's first pixel format
+ if( !( DescribePixelFormat(
+ hDC,
+ iPixelFormat,
+ sizeof(PIXELFORMATDESCRIPTOR),
+ &pfd ) ) )
+ {
+ winlog( "Failed DescribePixelFormat\n" );
+ return false;
+ }
+
+ if( !SetPixelFormat( hDC, iPixelFormat, &pfd ) ) {
+ winlog( "Failed SetPixelFormat\n" );
+ return false;
+ }
+
+ if( !( hglrc = wglCreateContext( hDC ) ) ) {
+ winlog( "Failed wglCreateContext\n" );
+ return false;
+ }
+
+ if( !wglMakeCurrent(hDC, hglrc) ) {
+ winlog( "Failed wglMakeCurrent\n" );
+ return false;
+ }
+
+ pWnd->ReleaseDC( dc );
+
+ // setup 2D gl environment
+ glPushAttrib( GL_ENABLE_BIT );
+ glDisable( GL_DEPTH_TEST );
+ glDisable( GL_CULL_FACE );
+ glEnable( GL_TEXTURE_2D );
+
+ initializeMatrices( theApp.surfaceSizeX, theApp.surfaceSizeY );
+
+ setVSync( theApp.vsync );
+
+#ifdef MMX
+ if(!theApp.disableMMX)
+ cpu_mmx = theApp.detectMMX();
+ else
+ cpu_mmx = 0;
+#endif
+
+ systemRedShift = 3;
+ systemGreenShift = 11;
+ systemBlueShift = 19;
+ systemColorDepth = 32;
+ theApp.fsColorDepth = 32;
+
+ Init_2xSaI(32);
+
+ utilUpdateSystemColorMaps();
+ theApp.updateFilter();
+ theApp.updateIFB();
+
+ if(failed)
+ return false;
+
+ pWnd->DragAcceptFiles(TRUE);
+
+ return TRUE;
+}
+
+
+void OpenGLDisplay::clear()
+{
+ glClear( GL_COLOR_BUFFER_BIT );
+}
+
+
+void OpenGLDisplay::renderMenu()
+{
+ checkFullScreen();
+ if( theApp.m_pMainWnd )
+ theApp.m_pMainWnd->DrawMenuBar();
+}
+
+
+void OpenGLDisplay::render()
+{
+ clear();
+
+ int pitch = theApp.filterWidth * 4 + 4;
+ u8 *data = pix + ( theApp.sizeX + 1 ) * 4;
+
+ // apply pixel filter
+ if(theApp.filterFunction) {
+ data = filterData;
+ theApp.filterFunction(
+ pix + pitch,
+ pitch,
+ (u8*)theApp.delta,
+ (u8*)filterData,
+ theApp.filterWidth * 4 * 2,
+ theApp.filterWidth,
+ theApp.filterHeight);
+ }
+
+ // Texturemap complete texture to surface
+ // so we have free scaling and antialiasing
+ int mult;
+ if( theApp.filterFunction ) {
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX << 1 );
+ mult = 2;
+ } else {
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 );
+ mult = 1;
+ }
+
+ glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ 0,
+ 0,
+ mult * theApp.sizeX,
+ mult * theApp.sizeY,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ data );
+
+ if( theApp.glType == 0 ) {
+ glBegin( GL_TRIANGLE_STRIP );
+
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3i( 0, 0, 0 );
+
+ glTexCoord2f( (float)(mult * theApp.sizeX) / size, 0.0f );
+ glVertex3i( theApp.surfaceSizeX, 0, 0 );
+
+ glTexCoord2f( 0.0f, (float)(mult * theApp.sizeY) / size );
+ glVertex3i( 0, theApp.surfaceSizeY, 0 );
+
+ glTexCoord2f( (float)(mult * theApp.sizeX) / size, (float)(mult * theApp.sizeY) / size );
+ glVertex3i( theApp.surfaceSizeX, theApp.surfaceSizeY, 0 );
+
+ glEnd();
+ } else {
+ glBegin( GL_QUADS );
+
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3i( 0, 0, 0 );
+
+ glTexCoord2f( (float)(mult * theApp.sizeX) / size, 0.0f );
+ glVertex3i( theApp.surfaceSizeX, 0, 0 );
+
+ glTexCoord2f( (float)(mult * theApp.sizeX) / size, (float)(mult * theApp.sizeY) / size );
+ glVertex3i( theApp.surfaceSizeX, theApp.surfaceSizeY, 0 );
+
+ glTexCoord2f( 0.0f, (float)(mult * theApp.sizeY) / size );
+ glVertex3i( 0, theApp.surfaceSizeY, 0 );
+
+ glEnd();
+ }
+
+ CDC *dc = theApp.m_pMainWnd->GetDC();
+
+ SwapBuffers( dc->GetSafeHdc() );
+ // since OpenGL draws on the back buffer,
+ // we have to swap it to the front buffer to see it
+
+ // draw informations with GDI on the front buffer
+ dc->SetBkMode( theApp.showSpeedTransparent ? TRANSPARENT : OPAQUE );
+ if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) {
+ char buffer[30];
+ if( theApp.showSpeed == 1 ) {
+ sprintf( buffer, "%3d%%", systemSpeed );
+ } else {
+ sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames );
+ }
+ dc->SetTextColor( RGB(0x00, 0x00, 0xFF) );
+ dc->TextOut( 10, 20, buffer );
+ }
+ if( theApp.screenMessage ) {
+ if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage ) {
+ dc->SetTextColor( RGB(0xFF, 0x00, 0x00) );
+ dc->TextOut( 10, theApp.surfaceSizeY - 20, theApp.screenMessageBuffer );
+ } else {
+ theApp.screenMessage = false;
+ }
+ }
+
+ theApp.m_pMainWnd->ReleaseDC( dc );
+}
+
+
+void OpenGLDisplay::resize( int w, int h )
+{
+ initializeMatrices( w, h );
+}
+
+
+void OpenGLDisplay::updateFiltering( int value )
+{
+ switch( value )
+ {
+ case 0:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ break;
+ case 1:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ break;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+}
+
+
+void OpenGLDisplay::initializeMatrices( int w, int h )
+{
+ if( theApp.fullScreenStretch ) {
+ glViewport( 0, 0, w, h );
+ } else {
+ calculateDestRect( w, h );
+ glViewport(
+ destRect.left,
+ destRect.top,
+ destRect.right - destRect.left,
+ destRect.bottom - destRect.top );
+ }
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho(
+ /* left */ 1.0f,
+ /* right */ (GLdouble)(w - 1),
+ /* bottom */ (GLdouble)(h - 1),
+ /* top */ 1.0f,
+ 0.0f,
+ 1.0f );
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+
+bool OpenGLDisplay::initializeTexture( int w, int h )
+{
+ // size = 2^n
+ // w = 24 > size = 256 = 2^8
+ // w = 255 > size = 256 = 2^8
+ // w = 256 > size = 512 = 2^9
+ // w = 300 > size = 512 = 2^9
+ // OpenGL textures have to be square and a power of 2
+
+ float n1 = log10( (float)w ) / log10( 2.0f );
+ float n2 = log10( (float)h ) / log10( 2.0f );
+ float n = ( n1 > n2 ) ? n1 : n2;
+
+ if( ((float)((int)n)) != n ) {
+ // round up
+ n = ((float)((int)n)) + 1.0f;
+ }
+
+ size = pow( 2.0f, n );
+
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ updateFiltering( theApp.glFilter );
+
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ (GLsizei)size,
+ (GLsizei)size,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL );
+
+ width = w;
+ height = h;
+
+ return ( glGetError() == GL_NO_ERROR) ? true : false;
+}
+
+
+void OpenGLDisplay::setVSync( int interval )
+{
+ const char *extensions = (const char *)glGetString( GL_EXTENSIONS );
+
+ if( strstr( extensions, "WGL_EXT_swap_control" ) == 0 ) {
+ winlog( "Error: WGL_EXT_swap_control extension not supported on your computer.\n" );
+ return;
+ } else {
+ PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = NULL;
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" );
+ if( wglSwapIntervalEXT ) {
+ wglSwapIntervalEXT( interval );
+ }
+ }
+}
+
+
+bool OpenGLDisplay::changeRenderSize( int w, int h )
+{
+ if( (width != w) || (height != h) ) {
+ if( texture != 0 ) {
+ glDeleteTextures( 1, &texture );
+ texture = 0;
+ }
+
+ if( !initializeTexture( w, h ) ) {
+ failed = true;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void OpenGLDisplay::calculateDestRect( int w, int h )
+{
+ float scaleX = (float)w / (float)width;
+ float scaleY = (float)h / (float)height;
+ float min = (scaleX < scaleY) ? scaleX : scaleY;
+ if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) {
+ min = (float)theApp.fsMaxScale;
+ }
+ destRect.left = 0;
+ destRect.top = 0;
+ destRect.right = (LONG)(width * min);
+ destRect.bottom = (LONG)(height * min);
+ if( destRect.right != w ) {
+ LONG diff = (w - destRect.right) / 2;
+ destRect.left += diff;
+ destRect.right += diff;
+ }
+ if( destRect.bottom != h ) {
+ LONG diff = (h - destRect.bottom) / 2;
+ destRect.top += diff;
+ destRect.bottom += diff;
+ }
+}
+
+
+void OpenGLDisplay::setOption( const char *option, int value )
+{
+ if( !_tcscmp( option, _T("vsync") ) ) {
+ setVSync( value );
+ }
+
+ if( !_tcscmp( option, _T("glFilter") ) ) {
+ updateFiltering( value );
+ }
+
+ if( !_tcscmp( option, _T("maxScale") ) ) {
+ initializeMatrices( theApp.dest.right, theApp.dest.bottom );
+ }
+
+ if( !_tcscmp( option, _T("fullScreenStretch") ) ) {
+ initializeMatrices( theApp.dest.right, theApp.dest.bottom );
+ }
+}
+
+
+int OpenGLDisplay::selectFullScreenMode( GUID ** )
+{
+ HWND wnd = GetDesktopWindow();
+ RECT r;
+ GetWindowRect( wnd, &r );
+ int w = ( r.right - r.left ) & 0xFFF;
+ int h = ( r.bottom - r.top ) & 0xFFF;
+ HDC dc = GetDC( wnd );
+ int c = GetDeviceCaps( dc, BITSPIXEL );
+ ReleaseDC( wnd, dc );
+ return (c << 24) | (w << 12) | h;
+}
+
+
+IDisplay *newOpenGLDisplay()
+{
+ return new OpenGLDisplay();
+}
diff --git a/src/win32/PaletteView.cpp b/src/win32/PaletteView.cpp
index bd4e72f0..5f164fe8 100644
--- a/src/win32/PaletteView.cpp
+++ b/src/win32/PaletteView.cpp
@@ -109,51 +109,54 @@ BOOL PaletteView::OnInitDialog()
void PaletteView::save(int which)
{
- CString captureBuffer;
+ if(rom != NULL)
+ {
+ CString captureBuffer;
- if(which == 0)
- captureBuffer = "bg.pal";
- else
- captureBuffer = "obj.pal";
+ if(which == 0)
+ captureBuffer = "bg.pal";
+ else
+ captureBuffer = "obj.pal";
- LPCTSTR exts[] = {".pal", ".pal", ".act" };
+ LPCTSTR exts[] = {".pal", ".pal", ".act" };
- CString filter = theApp.winLoadFilter(IDS_FILTER_PAL);
- CString title = winResLoadString(IDS_SELECT_PALETTE_NAME);
- FileDlg dlg(this,
- captureBuffer,
- filter,
- 1,
- "PAL",
- exts,
- "",
- title,
- true);
+ CString filter = theApp.winLoadFilter(IDS_FILTER_PAL);
+ CString title = winResLoadString(IDS_SELECT_PALETTE_NAME);
+ FileDlg dlg(this,
+ captureBuffer,
+ filter,
+ 1,
+ "PAL",
+ exts,
+ "",
+ title,
+ true);
- if(dlg.DoModal() == IDCANCEL) {
- return;
- }
-
- captureBuffer = dlg.GetPathName();
+ if(dlg.DoModal() == IDCANCEL) {
+ return;
+ }
- PaletteViewControl *p = NULL;
+ captureBuffer = dlg.GetPathName();
- if(which == 0)
- p = &paletteView;
- else
- p = &paletteViewOBJ;
+ PaletteViewControl *p = NULL;
+
+ if(which == 0)
+ p = &paletteView;
+ else
+ p = &paletteViewOBJ;
- switch(dlg.getFilterIndex()) {
- case 0:
- case 1:
- p->saveMSPAL(captureBuffer);
- break;
- case 2:
- p->saveJASCPAL(captureBuffer);
- break;
- case 3:
- p->saveAdobe(captureBuffer);
- break;
+ switch(dlg.getFilterIndex()) {
+ case 0:
+ case 1:
+ p->saveMSPAL(captureBuffer);
+ break;
+ case 2:
+ p->saveJASCPAL(captureBuffer);
+ break;
+ case 3:
+ p->saveAdobe(captureBuffer);
+ break;
+ }
}
}
diff --git a/src/win32/Reg.cpp b/src/win32/Reg.cpp
index ac931c0a..90730671 100644
--- a/src/win32/Reg.cpp
+++ b/src/win32/Reg.cpp
@@ -1,369 +1,374 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#include "stdafx.h"
-
-static char buffer[2048];
-static HKEY vbKey = NULL;
-static CString regVbaPath;
-
-#define VBA_PREF "preferences"
-
-bool regEnabled = true;
-
-void regInit(const char *path)
-{
- DWORD disp = 0;
- LONG res = RegCreateKeyEx(HKEY_CURRENT_USER,
- "Software\\Emulators\\VisualBoyAdvance",
- 0,
- "",
- REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
- NULL,
- &vbKey,
- &disp);
- regVbaPath.Format("%s\\vba.ini", path);
-}
-
-void regShutdown()
-{
- LONG res = RegCloseKey(vbKey);
-}
-
-const char *regGetINIPath()
-{
- return regVbaPath;
-}
-
-char *regQueryStringValue(const char * key, char *def)
-{
- if(regEnabled) {
- DWORD type = 0;
- DWORD size = 2048;
-
- LONG res = RegQueryValueEx(vbKey,
- key,
- NULL,
- &type,
- (UCHAR *)buffer,
- &size);
-
- if(res == ERROR_SUCCESS && type == REG_SZ)
- return buffer;
-
- return def;
- }
-
- DWORD res = GetPrivateProfileString(VBA_PREF,
- key,
- def,
- (LPTSTR)buffer,
- 2048,
- regVbaPath);
-
- if(res)
- return buffer;
-
- return def;
-}
-
-DWORD regQueryDwordValue(const char * key, DWORD def, bool force)
-{
- if(regEnabled || force) {
- DWORD type = 0;
- DWORD size = sizeof(DWORD);
- DWORD result = 0;
-
- LONG res = RegQueryValueEx(vbKey,
- key,
- NULL,
- &type,
- (UCHAR *)&result,
- &size);
-
- if(res == ERROR_SUCCESS && type == REG_DWORD)
- return result;
-
- return def;
- }
-
- return GetPrivateProfileInt(VBA_PREF,
- key,
- def,
- regVbaPath);
-}
-
-BOOL regQueryBinaryValue(const char * key, char *value, int count)
-{
- if(regEnabled) {
- DWORD type = 0;
- DWORD size = count;
- DWORD result = 0;
-
-
- LONG res = RegQueryValueEx(vbKey,
- key,
- NULL,
- &type,
- (UCHAR *)value,
- &size);
-
- if(res == ERROR_SUCCESS && type == REG_BINARY)
- return TRUE;
-
- return FALSE;
- }
- CString k = key;
- k += "Count";
- int size = GetPrivateProfileInt(VBA_PREF,
- k,
- -1,
- regVbaPath);
- if(size >= 0 && size < count)
- count = size;
- return GetPrivateProfileStruct(VBA_PREF,
- key,
- value,
- count,
- regVbaPath);
-}
-
-void regSetStringValue(const char * key, const char * value)
-{
- if(regEnabled) {
- LONG res = RegSetValueEx(vbKey,
- key,
- NULL,
- REG_SZ,
- (const UCHAR *)value,
- strlen(value)+1);
- } else {
- WritePrivateProfileString(VBA_PREF,
- key,
- value,
- regVbaPath);
- }
-}
-
-void regSetDwordValue(const char * key, DWORD value, bool force)
-{
- if(regEnabled || force) {
- LONG res = RegSetValueEx(vbKey,
- key,
- NULL,
- REG_DWORD,
- (const UCHAR *)&value,
- sizeof(DWORD));
- } else {
- wsprintf(buffer, "%u", value);
- WritePrivateProfileString(VBA_PREF,
- key,
- buffer,
- regVbaPath);
- }
-}
-
-void regSetBinaryValue(const char *key, char *value, int count)
-{
- if(regEnabled) {
- LONG res = RegSetValueEx(vbKey,
- key,
- NULL,
- REG_BINARY,
- (const UCHAR *)value,
- count);
- } else {
- CString k = key;
- k += "Count";
- wsprintf(buffer, "%u", count);
-
- WritePrivateProfileString(VBA_PREF,
- k,
- buffer,
- regVbaPath);
-
- WritePrivateProfileStruct(VBA_PREF,
- key,
- value,
- count,
- regVbaPath);
- }
-}
-
-void regDeleteValue(char *key)
-{
- if(regEnabled) {
- LONG res = RegDeleteValue(vbKey,
- key);
- } else {
- WritePrivateProfileString(VBA_PREF,
- key,
- NULL,
- regVbaPath);
- }
-}
-
-bool regCreateFileType(const char *ext, const char *type)
-{
- DWORD disp = 0;
- HKEY key;
- LONG res = RegCreateKeyEx(HKEY_CLASSES_ROOT,
- ext,
- 0,
- "",
- REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
- NULL,
- &key,
- &disp);
- if(res == ERROR_SUCCESS) {
- res = RegSetValueEx(key,
- "",
- 0,
- REG_SZ,
- (const UCHAR *)type,
- strlen(type)+1);
- RegCloseKey(key);
- return true;
- }
- return false;
-}
-
-bool regAssociateType(const char *type, const char *desc, const char *application)
-{
- DWORD disp = 0;
- HKEY key;
- LONG res = RegCreateKeyEx(HKEY_CLASSES_ROOT,
- type,
- 0,
- "",
- REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
- NULL,
- &key,
- &disp);
- if(res == ERROR_SUCCESS) {
- res = RegSetValueEx(key,
- "",
- 0,
- REG_SZ,
- (const UCHAR *)desc,
- strlen(desc)+1);
- HKEY key2;
- res = RegCreateKeyEx(key,
- "Shell\\Open\\Command",
- 0,
- "",
- REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
- NULL,
- &key2,
- &disp);
- if(res == ERROR_SUCCESS) {
- res = RegSetValueEx(key2,
- "",
- 0,
- REG_SZ,
- (const UCHAR *)application,
- strlen(application)+1);
- RegCloseKey(key2);
- RegCloseKey(key);
- return true;
- }
-
- RegCloseKey(key);
- }
- return false;
-}
-
-static void regExportSettingsToINI(HKEY key, const char *section)
-{
- char valueName[256];
- int index = 0;
- while(1) {
- DWORD nameSize = 256;
- DWORD size = 2048;
- DWORD type;
- LONG res = RegEnumValue(key,
- index,
- valueName,
- &nameSize,
- NULL,
- &type,
- (LPBYTE)buffer,
- &size);
-
- if(res == ERROR_SUCCESS) {
- switch(type) {
- case REG_DWORD:
- {
- char temp[256];
- wsprintf(temp, "%u", *((DWORD *)buffer));
- WritePrivateProfileString(section,
- valueName,
- temp,
- regVbaPath);
- }
- break;
- case REG_SZ:
- WritePrivateProfileString(section,
- valueName,
- buffer,
- regVbaPath);
- break;
- case REG_BINARY:
- {
- char temp[256];
-
- wsprintf(temp, "%u", size);
- CString k = valueName;
- k += "Count";
- WritePrivateProfileString(section,
- k,
- temp,
- regVbaPath);
- WritePrivateProfileStruct(section,
- valueName,
- buffer,
- size,
- regVbaPath);
- }
- break;
- }
- index++;
- } else
- break;
- }
-}
-
-void regExportSettingsToINI()
-{
- if(vbKey != NULL) {
- regExportSettingsToINI(vbKey, VBA_PREF);
- }
-
- HKEY key;
-
- if(RegOpenKey(HKEY_CURRENT_USER,
- "Software\\Emulators\\VisualBoyAdvance\\Viewer", &key) ==
- ERROR_SUCCESS) {
- regExportSettingsToINI(key, "Viewer");
- RegCloseKey(key);
- }
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "stdafx.h"
+
+static char buffer[2048];
+static HKEY vbKey = NULL;
+static CString *regVbaPath = NULL;
+
+#define VBA_PREF "preferences"
+
+bool regEnabled = true;
+
+void regInit(const char *path)
+{
+ DWORD disp = 0;
+ LONG res = RegCreateKeyEx(HKEY_CURRENT_USER,
+ "Software\\Emulators\\VisualBoyAdvance",
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &vbKey,
+ &disp);
+ if( regVbaPath != NULL ) {
+ delete regVbaPath;
+ regVbaPath = NULL;
+ }
+ regVbaPath = new CString();
+ regVbaPath->Format("%s\\vba.ini", path);
+}
+
+void regShutdown()
+{
+ LONG res = RegCloseKey(vbKey);
+}
+
+const char *regGetINIPath()
+{
+ return *regVbaPath;
+}
+
+char *regQueryStringValue(const char * key, char *def)
+{
+ if(regEnabled) {
+ DWORD type = 0;
+ DWORD size = 2048;
+
+ LONG res = RegQueryValueEx(vbKey,
+ key,
+ NULL,
+ &type,
+ (UCHAR *)buffer,
+ &size);
+
+ if(res == ERROR_SUCCESS && type == REG_SZ)
+ return buffer;
+
+ return def;
+ }
+
+ DWORD res = GetPrivateProfileString(VBA_PREF,
+ key,
+ def,
+ (LPTSTR)buffer,
+ 2048,
+ *regVbaPath);
+
+ if(res)
+ return buffer;
+
+ return def;
+}
+
+DWORD regQueryDwordValue(const char * key, DWORD def, bool force)
+{
+ if(regEnabled || force) {
+ DWORD type = 0;
+ DWORD size = sizeof(DWORD);
+ DWORD result = 0;
+
+ LONG res = RegQueryValueEx(vbKey,
+ key,
+ NULL,
+ &type,
+ (UCHAR *)&result,
+ &size);
+
+ if(res == ERROR_SUCCESS && type == REG_DWORD)
+ return result;
+
+ return def;
+ }
+
+ return GetPrivateProfileInt(VBA_PREF,
+ key,
+ def,
+ *regVbaPath);
+}
+
+BOOL regQueryBinaryValue(const char * key, char *value, int count)
+{
+ if(regEnabled) {
+ DWORD type = 0;
+ DWORD size = count;
+ DWORD result = 0;
+
+
+ LONG res = RegQueryValueEx(vbKey,
+ key,
+ NULL,
+ &type,
+ (UCHAR *)value,
+ &size);
+
+ if(res == ERROR_SUCCESS && type == REG_BINARY)
+ return TRUE;
+
+ return FALSE;
+ }
+ CString k = key;
+ k += "Count";
+ int size = GetPrivateProfileInt(VBA_PREF,
+ k,
+ -1,
+ *regVbaPath);
+ if(size >= 0 && size < count)
+ count = size;
+ return GetPrivateProfileStruct(VBA_PREF,
+ key,
+ value,
+ count,
+ *regVbaPath);
+}
+
+void regSetStringValue(const char * key, const char * value)
+{
+ if(regEnabled) {
+ LONG res = RegSetValueEx(vbKey,
+ key,
+ NULL,
+ REG_SZ,
+ (const UCHAR *)value,
+ lstrlen(value)+1);
+ } else {
+ WritePrivateProfileString(VBA_PREF,
+ key,
+ value,
+ *regVbaPath);
+ }
+}
+
+void regSetDwordValue(const char * key, DWORD value, bool force)
+{
+ if(regEnabled || force) {
+ LONG res = RegSetValueEx(vbKey,
+ key,
+ NULL,
+ REG_DWORD,
+ (const UCHAR *)&value,
+ sizeof(DWORD));
+ } else {
+ wsprintf(buffer, "%u", value);
+ WritePrivateProfileString(VBA_PREF,
+ key,
+ buffer,
+ *regVbaPath);
+ }
+}
+
+void regSetBinaryValue(const char *key, char *value, int count)
+{
+ if(regEnabled) {
+ LONG res = RegSetValueEx(vbKey,
+ key,
+ NULL,
+ REG_BINARY,
+ (const UCHAR *)value,
+ count);
+ } else {
+ CString k = key;
+ k += "Count";
+ wsprintf(buffer, "%u", count);
+
+ WritePrivateProfileString(VBA_PREF,
+ k,
+ buffer,
+ *regVbaPath);
+
+ WritePrivateProfileStruct(VBA_PREF,
+ key,
+ value,
+ count,
+ *regVbaPath);
+ }
+}
+
+void regDeleteValue(char *key)
+{
+ if(regEnabled) {
+ LONG res = RegDeleteValue(vbKey,
+ key);
+ } else {
+ WritePrivateProfileString(VBA_PREF,
+ key,
+ NULL,
+ *regVbaPath);
+ }
+}
+
+bool regCreateFileType(const char *ext, const char *type)
+{
+ DWORD disp = 0;
+ HKEY key;
+ LONG res = RegCreateKeyEx(HKEY_CLASSES_ROOT,
+ ext,
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &key,
+ &disp);
+ if(res == ERROR_SUCCESS) {
+ res = RegSetValueEx(key,
+ "",
+ 0,
+ REG_SZ,
+ (const UCHAR *)type,
+ lstrlen(type)+1);
+ RegCloseKey(key);
+ return true;
+ }
+ return false;
+}
+
+bool regAssociateType(const char *type, const char *desc, const char *application)
+{
+ DWORD disp = 0;
+ HKEY key;
+ LONG res = RegCreateKeyEx(HKEY_CLASSES_ROOT,
+ type,
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &key,
+ &disp);
+ if(res == ERROR_SUCCESS) {
+ res = RegSetValueEx(key,
+ "",
+ 0,
+ REG_SZ,
+ (const UCHAR *)desc,
+ lstrlen(desc)+1);
+ HKEY key2;
+ res = RegCreateKeyEx(key,
+ "Shell\\Open\\Command",
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &key2,
+ &disp);
+ if(res == ERROR_SUCCESS) {
+ res = RegSetValueEx(key2,
+ "",
+ 0,
+ REG_SZ,
+ (const UCHAR *)application,
+ lstrlen(application)+1);
+ RegCloseKey(key2);
+ RegCloseKey(key);
+ return true;
+ }
+
+ RegCloseKey(key);
+ }
+ return false;
+}
+
+static void regExportSettingsToINI(HKEY key, const char *section)
+{
+ char valueName[256];
+ int index = 0;
+ while(1) {
+ DWORD nameSize = 256;
+ DWORD size = 2048;
+ DWORD type;
+ LONG res = RegEnumValue(key,
+ index,
+ valueName,
+ &nameSize,
+ NULL,
+ &type,
+ (LPBYTE)buffer,
+ &size);
+
+ if(res == ERROR_SUCCESS) {
+ switch(type) {
+ case REG_DWORD:
+ {
+ char temp[256];
+ wsprintf(temp, "%u", *((DWORD *)buffer));
+ WritePrivateProfileString(section,
+ valueName,
+ temp,
+ *regVbaPath);
+ }
+ break;
+ case REG_SZ:
+ WritePrivateProfileString(section,
+ valueName,
+ buffer,
+ *regVbaPath);
+ break;
+ case REG_BINARY:
+ {
+ char temp[256];
+
+ wsprintf(temp, "%u", size);
+ CString k = valueName;
+ k += "Count";
+ WritePrivateProfileString(section,
+ k,
+ temp,
+ *regVbaPath);
+ WritePrivateProfileStruct(section,
+ valueName,
+ buffer,
+ size,
+ *regVbaPath);
+ }
+ break;
+ }
+ index++;
+ } else
+ break;
+ }
+}
+
+void regExportSettingsToINI()
+{
+ if(vbKey != NULL) {
+ regExportSettingsToINI(vbKey, VBA_PREF);
+ }
+
+ HKEY key;
+
+ if(RegOpenKey(HKEY_CURRENT_USER,
+ "Software\\Emulators\\VisualBoyAdvance\\Viewer", &key) ==
+ ERROR_SUCCESS) {
+ regExportSettingsToINI(key, "Viewer");
+ RegCloseKey(key);
+ }
+}
diff --git a/src/win32/Reg.h b/src/win32/Reg.h
index 1e658711..7d3350e9 100644
--- a/src/win32/Reg.h
+++ b/src/win32/Reg.h
@@ -1,37 +1,37 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifndef VBA_REG_H
-#define VBA_REG_H
-
-extern bool regEnabled;
-
-char *regQueryStringValue(const char *key, char *def);
-DWORD regQueryDwordValue(const char *key, DWORD def, bool force=false);
-BOOL regQueryBinaryValue(const char *key, char *value, int count);
-void regSetStringValue(const char *key,const char *value);
-void regSetDwordValue(const char *key,DWORD value,bool force=false);
-void regSetBinaryValue(const char *key, char *value, int count);
-void regDeleteValue(char *key);
-void regInit(const char *);
-void regShutdown();
-bool regCreateFileType(const char *ext, const char *type);
-bool regAssociateType(const char *type, const char *desc, const char *application);
-void regExportSettingsToINI();
-#endif // VBA_REG_H
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef VBA_REG_H
+#define VBA_REG_H
+
+extern bool regEnabled;
+
+char *regQueryStringValue(const char *key, char *def);
+DWORD regQueryDwordValue(const char *key, DWORD def, bool force=false);
+BOOL regQueryBinaryValue(const char *key, char *value, int count);
+void regSetStringValue(const char *key,const char *value);
+void regSetDwordValue(const char *key,DWORD value,bool force=false);
+void regSetBinaryValue(const char *key, char *value, int count);
+void regDeleteValue(char *key);
+void regInit(const char *);
+void regShutdown();
+bool regCreateFileType(const char *ext, const char *type);
+bool regAssociateType(const char *type, const char *desc, const char *application);
+void regExportSettingsToINI();
+#endif // VBA_REG_H
diff --git a/src/win32/ResizeDlg.cpp b/src/win32/ResizeDlg.cpp
index af843dbe..93fb4735 100644
--- a/src/win32/ResizeDlg.cpp
+++ b/src/win32/ResizeDlg.cpp
@@ -1,561 +1,561 @@
-/*----------------------------------------------------------------------
- Copyright (c) Gipsysoft. All Rights Reserved.
- File: DialogSizer_Set.cpp
- Web site: http://gipsysoft.com
-
- This software is provided 'as-is', without any express or implied warranty.
-
- In no event will the author be held liable for any damages arising from the
- use of this software.
-
- Permission is granted to anyone to use this software for any purpose, including
- commercial applications, and to alter it and redistribute it freely, subject
- to the following restrictions:
-
- 1) The origin of this software must not be misrepresented; you must not claim
- that you wrote the original software. If you use this software in a product,
- an acknowledgment in the product documentation is requested but not required.
- 2) Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software. Altered source is encouraged
- to be submitted back to the original author so it can be shared with the
- community. Please share your changes.
- 3) This notice may not be removed or altered from any source distribution.
-
- Owner: russf@gipsysoft.com
- Purpose: Main functionality for sizeable dialogs
-
- Store a local copy of the user settings
- Subclass the window
- Respond to various messages withinn the subclassed window.
-
- ----------------------------------------------------------------------*/
-#include "stdafx.h"
-#include "VBA.h"
-#include "ResizeDlg.h"
-#undef ASSERT
-#include "WinHelper.h"
-
-// moved functions to this file to reduce number of files
-
-struct RegistryData
-{
- WINDOWPLACEMENT m_wpl;
-};
-
-
-struct DialogData // dd
-{
- HKEY hkRootSave;
- LPCTSTR pcszName;
-
- //
- // The number of items contained in the psd member.
- // Used in the DeferWindowPos structure and in allocating memory
- int nItemCount;
- DialogSizerSizingItem *psd;
-
- //
- // We need the smallest to respond to the WM_GETMINMAXINFO message
- POINT m_ptSmallest;
-
- //
- // We don't strictly speaking need to say how big the biggest can be but
- POINT m_ptLargest;
- bool m_bLargestSet;
-
- //
- // we need this to decide how much the window has changed size when we get a WM_SIZE message
- SIZE m_sizeClient;
-
- //
- // Draw the sizing grip...or not
- bool m_bMaximised;
- BOOL m_bShowSizingGrip;
-
- WinHelper::CRect m_rcGrip;
-};
-
-//extern bool regEnabled;
-extern const char *regGetINIPath();
-
-void AssertFailed(char *file, int line, char *exp)
-{
- char buffer[1024];
-
- sprintf(buffer, "File %s\nLine %d\nExpression %s\nPress Retry to debug",
- file, line, exp);
- int res = MessageBox(*theApp.m_pMainWnd, buffer, "Assertion failed!",
- MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL |
- MB_ABORTRETRYIGNORE);
-
- if(res == IDRETRY) {
- __asm int 3;
- } else if(res == IDABORT)
- SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0);
-}
-
-void ApiFailure(char *pcszFilename, int nLine, char *pcszExpression )
-{
- const DWORD dwLastError = ::GetLastError();
- LPCTSTR lpMsgBuf;
- (void)::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dwLastError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL );
-
- char szExeName[ MAX_PATH ];
-
- if( !GetModuleFileName( NULL, szExeName, countof( szExeName ) ) )
- strcpy( szExeName, "" );
-
-
- char szMessage[ 1024 ];
- _snprintf( szMessage, countof( szMessage )
- , "API VERIFY Failure!"
- "\nProgram: %s"
- "\n"
- "\nFile %s"
- "\nLine %d"
- "\n"
- "\nExpression %s"
- "\n"
- "\nLast Error %d"
- "\n %s"
- "\n\nPress Retry to debug the application"
- , szExeName
- , pcszFilename
- , nLine
- , pcszExpression
- , dwLastError
- , lpMsgBuf
- );
-
- (void)LocalFree( (LPVOID)lpMsgBuf );
- HWND hwndParent = ::GetActiveWindow();
- hwndParent = ::GetLastActivePopup( hwndParent );
- int nCode = ::MessageBoxA( hwndParent,
- szMessage,
- "Debug Helper",
- MB_TASKMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE |
- MB_SETFOREGROUND );
- if(nCode == IDABORT) {
- ::SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0);
- } else if(nCode == IDRETRY)
- __asm int 3;
-}
-
-long FASTCALL RegQueryValueExRecursive( HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData )
-{
- TCHAR szBuffer[ 256 ];
- R_ASSERT( lstrlen( lpValueName ) < countof( szBuffer ) );
- (void)lstrcpy( szBuffer, lpValueName );
-
- LPTSTR pszBuffer = szBuffer;
- LPTSTR pszLast = szBuffer;
- while( *pszBuffer )
- {
- if( *pszBuffer == _T('\\') || *pszBuffer == _T('/') )
- {
- pszLast = pszBuffer;
- lpValueName = pszLast + 1;
- }
- pszBuffer++;
- }
-
- /*if(!regEnabled) {*/
- if(GetPrivateProfileStruct("Viewer",
- lpValueName,
- lpData,
- *lpcbData,
- regGetINIPath())) {
- *lpType = REG_BINARY;
- return ERROR_SUCCESS;
- }
- return -1;
- /*}
-
- bool m_bNeedToCloseKey = false;
- if( pszLast != szBuffer )
- {
- *pszLast = _T('\000');
- HKEY hkeyTemp;
- long lRet = RegOpenKey( hKey, szBuffer, &hkeyTemp );
- if( lRet != ERROR_SUCCESS )
- {
- return lRet;
- }
- hKey = hkeyTemp;
- m_bNeedToCloseKey = true;
- }
-
- long lRet = RegQueryValueEx( hKey, lpValueName, lpReserved, lpType, lpData, lpcbData );
- if( m_bNeedToCloseKey )
- {
- R_VERIFY( RegCloseKey( hKey ) == ERROR_SUCCESS );
- }
- return lRet;*/
-}
-
-long FASTCALL RegSetValueExRecursive( HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData )
-{
- TCHAR szBuffer[ 256 ];
- R_ASSERT( lstrlen( lpValueName ) < countof( szBuffer ) );
- (void)lstrcpy( szBuffer, lpValueName );
-
- LPTSTR pszBuffer = szBuffer;
- LPTSTR pszLast = szBuffer;
- while( *pszBuffer )
- {
- if( *pszBuffer == _T('\\') || *pszBuffer == _T('/') )
- {
- pszLast = pszBuffer;
- lpValueName = pszLast + 1;
- }
- pszBuffer++;
- }
-
- /*if(!regEnabled) {*/
- if(WritePrivateProfileStruct("Viewer",
- lpValueName,
- (LPVOID)lpData,
- cbData,
- regGetINIPath())) {
- return ERROR_SUCCESS;
- }
- return -1;
- /*}
-
- bool m_bNeedToCloseKey = false;
- if( pszLast != szBuffer )
- {
- *pszLast = _T('\000');
- HKEY hkeyTemp;
- long lRet = RegOpenKey( hKey, szBuffer, &hkeyTemp );
- if( lRet != ERROR_SUCCESS )
- {
- lRet = RegCreateKey( hKey, szBuffer, &hkeyTemp );
- if( lRet != ERROR_SUCCESS )
- return lRet;
- }
- hKey = hkeyTemp;
- m_bNeedToCloseKey = true;
- }
-
- long lRet = RegSetValueEx( hKey, lpValueName, Reserved, dwType, lpData, cbData );
- if( m_bNeedToCloseKey )
- {
- R_VERIFY( RegCloseKey( hKey ) == ERROR_SUCCESS );
- }
- return lRet;*/
-}
-
-
-int ResizeDlgGetItemCount(const DialogSizerSizingItem *psd)
-{
- R_ASSERT( psd );
- int nCount = 0;
- while( psd->uSizeInfo != 0xFFFFFFFF )
- {
- nCount++;
- psd++;
- }
- return nCount;
-}
-
-void ResizeDlgUpdateGripperRect( const int cx, const int cy, WinHelper::CRect &rcGrip )
-{
- const int nGripWidth = GetSystemMetrics( SM_CYVSCROLL );
- const int nGripHeight = GetSystemMetrics( SM_CXVSCROLL );
- rcGrip.left = cx - nGripWidth;
- rcGrip.top = cy - nGripHeight;
- rcGrip.right = cx;
- rcGrip.bottom = cy;
-}
-
-void ResizeDlgUpdateGripper( HWND hwnd, DialogData *pdd )
-{
- if( pdd->m_bShowSizingGrip )
- {
- WinHelper::CRect rcOld( pdd->m_rcGrip );
-
- ResizeDlgUpdateGripperRect( pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip );
-
- //
- // We also need to invalidate the combined area of the old and new rectangles
- // otherwise we would have trail of grippers when we sized the dialog larger
- // in any axis
- (void)UnionRect( &rcOld, &rcOld, &pdd->m_rcGrip );
- (void)InvalidateRect( hwnd, &rcOld, TRUE );
- }
-}
-
-void ResizeDlgCopyItems( DialogSizerSizingItem *psdDest, const DialogSizerSizingItem *psdSource )
- //
- // Will copy all of the items in psdSource into psdDest.
-{
- //
- // Loop til we reach the end
- while( psdSource->uSizeInfo != 0xFFFFFFFF )
- {
- *psdDest = *psdSource;
- psdDest++;
- psdSource++;
- }
- // And when we do copy the last item
- *psdDest = *psdSource;
-}
-
-
-ResizeDlg::ResizeDlg(UINT id, CWnd *parent)
- : CDialog(id, parent)
-{
- dd = NULL;
-}
-
-void *ResizeDlg::AddDialogData()
- //
- // Firstly determine if the data already exists, if it does then return that, if not then we will
- // create and initialise a brand new structure.
-{
- DialogData *pdd = (DialogData*)dd;
- if( !pdd ) {
- pdd = (DialogData *)calloc(1, sizeof(DialogData));
- }
-
- if( pdd ) {
- //
- // Store some sizes etc. for later.
- CRect rc;
- GetWindowRect( rc );
- pdd->m_ptSmallest.x = rc.Width();
- pdd->m_ptSmallest.y = rc.Height();
-
-
- GetClientRect( rc );
- pdd->m_sizeClient = rc.Size();
- dd = pdd;
- ResizeDlgUpdateGripperRect( pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip );
- }
- return pdd;
-}
-
-BOOL ResizeDlg::SetData(const DialogSizerSizingItem *psd,
- BOOL bShowSizingGrip,
- HKEY hkRootSave,
- LPCTSTR pcszName,
- SIZE *psizeMax)
- //
- // Setting a dialog sizeable involves subclassing the window and handling it's
- // WM_SIZE messages, if we have a hkRootSave and pcszName then we will also be loading/saving
- // the size and position of the window from the registry. We load from the registry when we
- // subclass the window and we save to the registry when we get a WM_DESTROY.
- //
- // It will return non-zero for success and zero if it fails
-{
- R_ASSERT( psd );
- R_ASSERT( ( hkRootSave != NULL && pcszName != NULL )
- || ( hkRootSave == NULL && pcszName == NULL ) );
- //
- // Make sure all of the parameters are valid.
- if( ::IsWindow( *this )
- && psd
- && ( ( hkRootSave != NULL && pcszName != NULL &&
- !IsBadStringPtr( pcszName, 0xFFFF ) ) ||
- ( hkRootSave == NULL && pcszName == NULL ) )
- && ( psizeMax == NULL || !IsBadReadPtr( psizeMax, sizeof( SIZE ) ) )
- ) {
- DialogData *pdd = (DialogData *)AddDialogData();
- if( pdd ) {
- pdd->hkRootSave = hkRootSave;
- pdd->pcszName = pcszName;
- pdd->m_bShowSizingGrip = bShowSizingGrip;
- pdd->nItemCount = ResizeDlgGetItemCount( psd ) + 1;
- pdd->psd = (DialogSizerSizingItem *)
- calloc(pdd->nItemCount,
- sizeof(DialogSizerSizingItem ));
- if( pdd->psd ) {
- //
- // Copy all of the user controls etc. for later, this way the user can quite happily
- // let the structure go out of scope.
- ResizeDlgCopyItems( pdd->psd, psd );
- if( psizeMax ) {
- pdd->m_ptLargest.x = psizeMax->cx;
- pdd->m_ptLargest.y = psizeMax->cy;
- pdd->m_bLargestSet = true;
- }
-
- //
- // If the there was save info passed in then we need to make damn good use of it
- // by attempting to load the RegistryData structure
- if( hkRootSave && pcszName ) {
- RegistryData rd;
- DWORD dwSize = sizeof( RegistryData );
- DWORD dwType = REG_BINARY;
- if( RegQueryValueExRecursive( hkRootSave, pcszName, NULL, &dwType, reinterpret_cast( &rd ), &dwSize ) == ERROR_SUCCESS && dwSize == sizeof( rd ) ) {
- if( !(GetWindowLong( *this, GWL_STYLE ) & WS_VISIBLE) )
- rd.m_wpl.showCmd = SW_HIDE;
-
- VAPI( SetWindowPlacement( &rd.m_wpl ) );
- }
- }
- return TRUE;
- } else {
- free(pdd);
- }
- }
- }
- return FALSE;
-}
-
-void ResizeDlg::UpdateWindowSize(const int cx, const int cy, HWND hwnd)
-{
- DialogData *pdd = (DialogData*)dd;
- if( pdd ) {
- const int nDeltaX = cx - pdd->m_sizeClient.cx;
- const int nDeltaY = cy - pdd->m_sizeClient.cy;
- WinHelper::CDeferWindowPos def( pdd->nItemCount );
- WinHelper::CRect rc;
- const DialogSizerSizingItem *psd = pdd->psd;
- while( psd->uSizeInfo != 0xFFFFFFFF ) {
- HWND hwndChild = ::GetDlgItem( *this, psd->uControlID );
- if( ::IsWindow( hwndChild ) ) {
- VAPI( ::GetWindowRect( hwndChild, rc ) );
- (void)::MapWindowPoints( ::GetDesktopWindow(), hwnd,
- (LPPOINT)&rc, 2 );
-
- //
- // Adjust the window horizontally
- if( psd->uSizeInfo & DS_MoveX ) {
- rc.left += nDeltaX;
- rc.right += nDeltaX;
- }
-
- //
- // Adjust the window vertically
- if( psd->uSizeInfo & DS_MoveY ) {
- rc.top += nDeltaY;
- rc.bottom += nDeltaY;
- }
-
- //
- // Size the window horizontally
- if( psd->uSizeInfo & DS_SizeX ) {
- rc.right += nDeltaX;
- }
-
- //
- // Size the window vertically
- if( psd->uSizeInfo & DS_SizeY ) {
- rc.bottom += nDeltaY;
- }
-
- (void)def.DeferWindowPos( hwndChild, NULL, rc,
- SWP_NOACTIVATE | SWP_NOZORDER );
- }
- psd++;
- }
-
- pdd->m_sizeClient.cx = cx;
- pdd->m_sizeClient.cy = cy;
-
- //
- // If we have a sizing grip enabled then adjust it's position
- ResizeDlgUpdateGripper( hwnd, pdd );
- }
-}
-
-BOOL ResizeDlg::OnWndMsg(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *res )
- // Actual window procedure that will handle saving window size/position and moving
- // the controls whilst the window sizes.
-{
- if(dd == NULL) {
- return CDialog::OnWndMsg(msg, wParam, lParam, res);
- }
- switch( msg ) {
- case WM_ERASEBKGND:
- {
- BOOL r = CDialog::OnWndMsg(msg, wParam, lParam, res);
- DialogData *pdd = (DialogData*)dd;
- if( pdd && pdd->m_bShowSizingGrip && !pdd->m_bMaximised ) {
- VAPI( ::DrawFrameControl( reinterpret_cast( wParam ),
- pdd->m_rcGrip,
- DFC_SCROLL, DFCS_SCROLLSIZEGRIP ) );
- }
- return r;
- }
- case WM_SIZE:
- {
- DialogData *pdd = (DialogData*)dd;
- if( pdd && wParam != SIZE_MINIMIZED ) {
- pdd->m_bMaximised = ( wParam == SIZE_MAXIMIZED ? true : false );
- UpdateWindowSize( LOWORD( lParam ), HIWORD( lParam ), *this);
- }
- }
- break;
- case WM_NCHITTEST:
- {
- //
- // If the gripper is enabled then perform a simple hit test on our gripper area.
- DialogData *pdd = (DialogData*)dd;
- if( pdd && pdd->m_bShowSizingGrip ) {
- POINT pt = { LOWORD(lParam), HIWORD(lParam) };
- (void)ScreenToClient( &pt );
- if( PtInRect( pdd->m_rcGrip, pt ) )
- return (BOOL)HTBOTTOMRIGHT;
- }
- }
- break;
- case WM_GETMINMAXINFO:
- {
- //
- // Our opportunity to say that we do not want the dialog to grow or shrink any more.
- DialogData *pdd = (DialogData*)dd;
- LPMINMAXINFO lpmmi = reinterpret_cast( lParam );
- lpmmi->ptMinTrackSize = pdd->m_ptSmallest;
- if( pdd->m_bLargestSet ) {
- lpmmi->ptMaxTrackSize = pdd->m_ptLargest;
- }
- }
- return (BOOL)0;
- case WM_NOTIFY:
- {
- if( reinterpret_cast(lParam)->code == PSN_SETACTIVE ) {
- CRect rc;
- VAPI( ::GetClientRect( *GetParent( ), &rc ) );
- UpdateWindowSize( rc.Width(), rc.Height(), *GetParent( ) );
- }
- }
- break;
- case WM_DESTROY:
- {
- //
- // Our opportunty for cleanup.
- // Simply acquire all of our objects, free the appropriate memory and remove the
- // properties from the window. If we do not remove the properties then they will constitute
- // a resource leak.
- DialogData *pdd = (DialogData*)dd;
- if( pdd ) {
- RegistryData rd;
- rd.m_wpl.length = sizeof( rd.m_wpl );
- VAPI( GetWindowPlacement( &rd.m_wpl ) );
-
- if( pdd->hkRootSave && pdd->pcszName ) {
- (void)RegSetValueExRecursive( pdd->hkRootSave, pdd->pcszName,
- NULL, REG_BINARY,
- reinterpret_cast( &rd ),
- sizeof( rd ) );
- }
-
- if( pdd->psd ) {
- free(pdd->psd);
- }
- free(pdd);
- }
-
- }
- break;
- }
- return CDialog::OnWndMsg(msg, wParam, lParam, res);
-}
+/*----------------------------------------------------------------------
+ Copyright (c) Gipsysoft. All Rights Reserved.
+ File: DialogSizer_Set.cpp
+ Web site: http://gipsysoft.com
+
+ This software is provided 'as-is', without any express or implied warranty.
+
+ In no event will the author be held liable for any damages arising from the
+ use of this software.
+
+ Permission is granted to anyone to use this software for any purpose, including
+ commercial applications, and to alter it and redistribute it freely, subject
+ to the following restrictions:
+
+ 1) The origin of this software must not be misrepresented; you must not claim
+ that you wrote the original software. If you use this software in a product,
+ an acknowledgment in the product documentation is requested but not required.
+ 2) Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software. Altered source is encouraged
+ to be submitted back to the original author so it can be shared with the
+ community. Please share your changes.
+ 3) This notice may not be removed or altered from any source distribution.
+
+ Owner: russf@gipsysoft.com
+ Purpose: Main functionality for sizeable dialogs
+
+ Store a local copy of the user settings
+ Subclass the window
+ Respond to various messages withinn the subclassed window.
+
+ ----------------------------------------------------------------------*/
+#include "stdafx.h"
+#include "VBA.h"
+#include "ResizeDlg.h"
+#undef ASSERT
+#include "WinHelper.h"
+
+// moved functions to this file to reduce number of files
+
+struct RegistryData
+{
+ WINDOWPLACEMENT m_wpl;
+};
+
+
+struct DialogData // dd
+{
+ HKEY hkRootSave;
+ LPCTSTR pcszName;
+
+ //
+ // The number of items contained in the psd member.
+ // Used in the DeferWindowPos structure and in allocating memory
+ int nItemCount;
+ DialogSizerSizingItem *psd;
+
+ //
+ // We need the smallest to respond to the WM_GETMINMAXINFO message
+ POINT m_ptSmallest;
+
+ //
+ // We don't strictly speaking need to say how big the biggest can be but
+ POINT m_ptLargest;
+ bool m_bLargestSet;
+
+ //
+ // we need this to decide how much the window has changed size when we get a WM_SIZE message
+ SIZE m_sizeClient;
+
+ //
+ // Draw the sizing grip...or not
+ bool m_bMaximised;
+ BOOL m_bShowSizingGrip;
+
+ WinHelper::CRect m_rcGrip;
+};
+
+extern bool regEnabled;
+extern const char *regGetINIPath();
+
+void AssertFailed(char *file, int line, char *exp)
+{
+ char buffer[1024];
+
+ sprintf(buffer, "File %s\nLine %d\nExpression %s\nPress Retry to debug",
+ file, line, exp);
+ int res = MessageBox(*theApp.m_pMainWnd, buffer, "Assertion failed!",
+ MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL |
+ MB_ABORTRETRYIGNORE);
+
+ if(res == IDRETRY) {
+ DebugBreak();
+ } else if(res == IDABORT)
+ SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0);
+}
+
+void ApiFailure(char *pcszFilename, int nLine, char *pcszExpression )
+{
+ const DWORD dwLastError = ::GetLastError();
+ LPCTSTR lpMsgBuf;
+ (void)::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, dwLastError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf, 0, NULL );
+
+ char szExeName[ MAX_PATH ];
+
+ if( !GetModuleFileName( NULL, szExeName, countof( szExeName ) ) )
+ strcpy( szExeName, "" );
+
+
+ char szMessage[ 1024 ];
+ _snprintf( szMessage, countof( szMessage )
+ , "API VERIFY Failure!"
+ "\nProgram: %s"
+ "\n"
+ "\nFile %s"
+ "\nLine %d"
+ "\n"
+ "\nExpression %s"
+ "\n"
+ "\nLast Error %d"
+ "\n %s"
+ "\n\nPress Retry to debug the application"
+ , szExeName
+ , pcszFilename
+ , nLine
+ , pcszExpression
+ , dwLastError
+ , lpMsgBuf
+ );
+
+ (void)LocalFree( (LPVOID)lpMsgBuf );
+ HWND hwndParent = ::GetActiveWindow();
+ hwndParent = ::GetLastActivePopup( hwndParent );
+ int nCode = ::MessageBoxA( hwndParent,
+ szMessage,
+ "Debug Helper",
+ MB_TASKMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE |
+ MB_SETFOREGROUND );
+ if(nCode == IDABORT) {
+ ::SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0);
+ } else if(nCode == IDRETRY)
+ DebugBreak();
+}
+
+long FASTCALL RegQueryValueExRecursive( HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData )
+{
+ TCHAR szBuffer[ 256 ];
+ R_ASSERT( lstrlen( lpValueName ) < countof( szBuffer ) );
+ (void)lstrcpy( szBuffer, lpValueName );
+
+ LPTSTR pszBuffer = szBuffer;
+ LPTSTR pszLast = szBuffer;
+ while( *pszBuffer )
+ {
+ if( *pszBuffer == _T('\\') || *pszBuffer == _T('/') )
+ {
+ pszLast = pszBuffer;
+ lpValueName = pszLast + 1;
+ }
+ pszBuffer++;
+ }
+
+ if(!regEnabled) {
+ if(GetPrivateProfileStruct("Viewer",
+ lpValueName,
+ lpData,
+ *lpcbData,
+ regGetINIPath())) {
+ *lpType = REG_BINARY;
+ return ERROR_SUCCESS;
+ }
+ return -1;
+ }
+
+ bool m_bNeedToCloseKey = false;
+ if( pszLast != szBuffer )
+ {
+ *pszLast = _T('\000');
+ HKEY hkeyTemp;
+ long lRet = RegOpenKey( hKey, szBuffer, &hkeyTemp );
+ if( lRet != ERROR_SUCCESS )
+ {
+ return lRet;
+ }
+ hKey = hkeyTemp;
+ m_bNeedToCloseKey = true;
+ }
+
+ long lRet = RegQueryValueEx( hKey, lpValueName, lpReserved, lpType, lpData, lpcbData );
+ if( m_bNeedToCloseKey )
+ {
+ R_VERIFY( RegCloseKey( hKey ) == ERROR_SUCCESS );
+ }
+ return lRet;
+}
+
+long FASTCALL RegSetValueExRecursive( HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData )
+{
+ TCHAR szBuffer[ 256 ];
+ R_ASSERT( lstrlen( lpValueName ) < countof( szBuffer ) );
+ (void)lstrcpy( szBuffer, lpValueName );
+
+ LPTSTR pszBuffer = szBuffer;
+ LPTSTR pszLast = szBuffer;
+ while( *pszBuffer )
+ {
+ if( *pszBuffer == _T('\\') || *pszBuffer == _T('/') )
+ {
+ pszLast = pszBuffer;
+ lpValueName = pszLast + 1;
+ }
+ pszBuffer++;
+ }
+
+ if(!regEnabled) {
+ if(WritePrivateProfileStruct("Viewer",
+ lpValueName,
+ (LPVOID)lpData,
+ cbData,
+ regGetINIPath())) {
+ return ERROR_SUCCESS;
+ }
+ return -1;
+ }
+
+ bool m_bNeedToCloseKey = false;
+ if( pszLast != szBuffer )
+ {
+ *pszLast = _T('\000');
+ HKEY hkeyTemp;
+ long lRet = RegOpenKey( hKey, szBuffer, &hkeyTemp );
+ if( lRet != ERROR_SUCCESS )
+ {
+ lRet = RegCreateKey( hKey, szBuffer, &hkeyTemp );
+ if( lRet != ERROR_SUCCESS )
+ return lRet;
+ }
+ hKey = hkeyTemp;
+ m_bNeedToCloseKey = true;
+ }
+
+ long lRet = RegSetValueEx( hKey, lpValueName, Reserved, dwType, lpData, cbData );
+ if( m_bNeedToCloseKey )
+ {
+ R_VERIFY( RegCloseKey( hKey ) == ERROR_SUCCESS );
+ }
+ return lRet;
+}
+
+
+int ResizeDlgGetItemCount(const DialogSizerSizingItem *psd)
+{
+ R_ASSERT( psd );
+ int nCount = 0;
+ while( psd->uSizeInfo != 0xFFFFFFFF )
+ {
+ nCount++;
+ psd++;
+ }
+ return nCount;
+}
+
+void ResizeDlgUpdateGripperRect( const int cx, const int cy, WinHelper::CRect &rcGrip )
+{
+ const int nGripWidth = GetSystemMetrics( SM_CYVSCROLL );
+ const int nGripHeight = GetSystemMetrics( SM_CXVSCROLL );
+ rcGrip.left = cx - nGripWidth;
+ rcGrip.top = cy - nGripHeight;
+ rcGrip.right = cx;
+ rcGrip.bottom = cy;
+}
+
+void ResizeDlgUpdateGripper( HWND hwnd, DialogData *pdd )
+{
+ if( pdd->m_bShowSizingGrip )
+ {
+ WinHelper::CRect rcOld( pdd->m_rcGrip );
+
+ ResizeDlgUpdateGripperRect( pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip );
+
+ //
+ // We also need to invalidate the combined area of the old and new rectangles
+ // otherwise we would have trail of grippers when we sized the dialog larger
+ // in any axis
+ (void)UnionRect( &rcOld, &rcOld, &pdd->m_rcGrip );
+ (void)InvalidateRect( hwnd, &rcOld, TRUE );
+ }
+}
+
+void ResizeDlgCopyItems( DialogSizerSizingItem *psdDest, const DialogSizerSizingItem *psdSource )
+ //
+ // Will copy all of the items in psdSource into psdDest.
+{
+ //
+ // Loop til we reach the end
+ while( psdSource->uSizeInfo != 0xFFFFFFFF )
+ {
+ *psdDest = *psdSource;
+ psdDest++;
+ psdSource++;
+ }
+ // And when we do copy the last item
+ *psdDest = *psdSource;
+}
+
+
+ResizeDlg::ResizeDlg(UINT id, CWnd *parent)
+ : CDialog(id, parent)
+{
+ dd = NULL;
+}
+
+void *ResizeDlg::AddDialogData()
+ //
+ // Firstly determine if the data already exists, if it does then return that, if not then we will
+ // create and initialise a brand new structure.
+{
+ DialogData *pdd = (DialogData*)dd;
+ if( !pdd ) {
+ pdd = (DialogData *)calloc(1, sizeof(DialogData));
+ }
+
+ if( pdd ) {
+ //
+ // Store some sizes etc. for later.
+ CRect rc;
+ GetWindowRect( rc );
+ pdd->m_ptSmallest.x = rc.Width();
+ pdd->m_ptSmallest.y = rc.Height();
+
+
+ GetClientRect( rc );
+ pdd->m_sizeClient = rc.Size();
+ dd = pdd;
+ ResizeDlgUpdateGripperRect( pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip );
+ }
+ return pdd;
+}
+
+BOOL ResizeDlg::SetData(const DialogSizerSizingItem *psd,
+ BOOL bShowSizingGrip,
+ HKEY hkRootSave,
+ LPCTSTR pcszName,
+ SIZE *psizeMax)
+ //
+ // Setting a dialog sizeable involves subclassing the window and handling it's
+ // WM_SIZE messages, if we have a hkRootSave and pcszName then we will also be loading/saving
+ // the size and position of the window from the registry. We load from the registry when we
+ // subclass the window and we save to the registry when we get a WM_DESTROY.
+ //
+ // It will return non-zero for success and zero if it fails
+{
+ R_ASSERT( psd );
+ R_ASSERT( ( hkRootSave != NULL && pcszName != NULL )
+ || ( hkRootSave == NULL && pcszName == NULL ) );
+ //
+ // Make sure all of the parameters are valid.
+ if( ::IsWindow( *this )
+ && psd
+ && ( ( hkRootSave != NULL && pcszName != NULL &&
+ !IsBadStringPtr( pcszName, 0xFFFF ) ) ||
+ ( hkRootSave == NULL && pcszName == NULL ) )
+ && ( psizeMax == NULL || !IsBadReadPtr( psizeMax, sizeof( SIZE ) ) )
+ ) {
+ DialogData *pdd = (DialogData *)AddDialogData();
+ if( pdd ) {
+ pdd->hkRootSave = hkRootSave;
+ pdd->pcszName = pcszName;
+ pdd->m_bShowSizingGrip = bShowSizingGrip;
+ pdd->nItemCount = ResizeDlgGetItemCount( psd ) + 1;
+ pdd->psd = (DialogSizerSizingItem *)
+ calloc(pdd->nItemCount,
+ sizeof(DialogSizerSizingItem ));
+ if( pdd->psd ) {
+ //
+ // Copy all of the user controls etc. for later, this way the user can quite happily
+ // let the structure go out of scope.
+ ResizeDlgCopyItems( pdd->psd, psd );
+ if( psizeMax ) {
+ pdd->m_ptLargest.x = psizeMax->cx;
+ pdd->m_ptLargest.y = psizeMax->cy;
+ pdd->m_bLargestSet = true;
+ }
+
+ //
+ // If the there was save info passed in then we need to make damn good use of it
+ // by attempting to load the RegistryData structure
+ if( hkRootSave && pcszName ) {
+ RegistryData rd;
+ DWORD dwSize = sizeof( RegistryData );
+ DWORD dwType = REG_BINARY;
+ if( RegQueryValueExRecursive( hkRootSave, pcszName, NULL, &dwType, reinterpret_cast( &rd ), &dwSize ) == ERROR_SUCCESS && dwSize == sizeof( rd ) ) {
+ if( !(GetWindowLong( *this, GWL_STYLE ) & WS_VISIBLE) )
+ rd.m_wpl.showCmd = SW_HIDE;
+
+ VAPI( SetWindowPlacement( &rd.m_wpl ) );
+ }
+ }
+ return TRUE;
+ } else {
+ free(pdd);
+ }
+ }
+ }
+ return FALSE;
+}
+
+void ResizeDlg::UpdateWindowSize(const int cx, const int cy, HWND hwnd)
+{
+ DialogData *pdd = (DialogData*)dd;
+ if( pdd ) {
+ const int nDeltaX = cx - pdd->m_sizeClient.cx;
+ const int nDeltaY = cy - pdd->m_sizeClient.cy;
+ WinHelper::CDeferWindowPos def( pdd->nItemCount );
+ WinHelper::CRect rc;
+ const DialogSizerSizingItem *psd = pdd->psd;
+ while( psd->uSizeInfo != 0xFFFFFFFF ) {
+ HWND hwndChild = ::GetDlgItem( *this, psd->uControlID );
+ if( ::IsWindow( hwndChild ) ) {
+ VAPI( ::GetWindowRect( hwndChild, rc ) );
+ (void)::MapWindowPoints( ::GetDesktopWindow(), hwnd,
+ (LPPOINT)&rc, 2 );
+
+ //
+ // Adjust the window horizontally
+ if( psd->uSizeInfo & DS_MoveX ) {
+ rc.left += nDeltaX;
+ rc.right += nDeltaX;
+ }
+
+ //
+ // Adjust the window vertically
+ if( psd->uSizeInfo & DS_MoveY ) {
+ rc.top += nDeltaY;
+ rc.bottom += nDeltaY;
+ }
+
+ //
+ // Size the window horizontally
+ if( psd->uSizeInfo & DS_SizeX ) {
+ rc.right += nDeltaX;
+ }
+
+ //
+ // Size the window vertically
+ if( psd->uSizeInfo & DS_SizeY ) {
+ rc.bottom += nDeltaY;
+ }
+
+ (void)def.DeferWindowPos( hwndChild, NULL, rc,
+ SWP_NOACTIVATE | SWP_NOZORDER );
+ }
+ psd++;
+ }
+
+ pdd->m_sizeClient.cx = cx;
+ pdd->m_sizeClient.cy = cy;
+
+ //
+ // If we have a sizing grip enabled then adjust it's position
+ ResizeDlgUpdateGripper( hwnd, pdd );
+ }
+}
+
+BOOL ResizeDlg::OnWndMsg(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *res )
+ // Actual window procedure that will handle saving window size/position and moving
+ // the controls whilst the window sizes.
+{
+ if(dd == NULL) {
+ return CDialog::OnWndMsg(msg, wParam, lParam, res);
+ }
+ switch( msg ) {
+ case WM_ERASEBKGND:
+ {
+ BOOL r = CDialog::OnWndMsg(msg, wParam, lParam, res);
+ DialogData *pdd = (DialogData*)dd;
+ if( pdd && pdd->m_bShowSizingGrip && !pdd->m_bMaximised ) {
+ VAPI( ::DrawFrameControl( reinterpret_cast( wParam ),
+ pdd->m_rcGrip,
+ DFC_SCROLL, DFCS_SCROLLSIZEGRIP ) );
+ }
+ return r;
+ }
+ case WM_SIZE:
+ {
+ DialogData *pdd = (DialogData*)dd;
+ if( pdd && wParam != SIZE_MINIMIZED ) {
+ pdd->m_bMaximised = ( wParam == SIZE_MAXIMIZED ? true : false );
+ UpdateWindowSize( LOWORD( lParam ), HIWORD( lParam ), *this);
+ }
+ }
+ break;
+ case WM_NCHITTEST:
+ {
+ //
+ // If the gripper is enabled then perform a simple hit test on our gripper area.
+ DialogData *pdd = (DialogData*)dd;
+ if( pdd && pdd->m_bShowSizingGrip ) {
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ (void)ScreenToClient( &pt );
+ if( PtInRect( pdd->m_rcGrip, pt ) )
+ return (BOOL)HTBOTTOMRIGHT;
+ }
+ }
+ break;
+ case WM_GETMINMAXINFO:
+ {
+ //
+ // Our opportunity to say that we do not want the dialog to grow or shrink any more.
+ DialogData *pdd = (DialogData*)dd;
+ LPMINMAXINFO lpmmi = reinterpret_cast( lParam );
+ lpmmi->ptMinTrackSize = pdd->m_ptSmallest;
+ if( pdd->m_bLargestSet ) {
+ lpmmi->ptMaxTrackSize = pdd->m_ptLargest;
+ }
+ }
+ return (BOOL)0;
+ case WM_NOTIFY:
+ {
+ if( reinterpret_cast(lParam)->code == PSN_SETACTIVE ) {
+ CRect rc;
+ VAPI( ::GetClientRect( *GetParent( ), &rc ) );
+ UpdateWindowSize( rc.Width(), rc.Height(), *GetParent( ) );
+ }
+ }
+ break;
+ case WM_DESTROY:
+ {
+ //
+ // Our opportunty for cleanup.
+ // Simply acquire all of our objects, free the appropriate memory and remove the
+ // properties from the window. If we do not remove the properties then they will constitute
+ // a resource leak.
+ DialogData *pdd = (DialogData*)dd;
+ if( pdd ) {
+ RegistryData rd;
+ rd.m_wpl.length = sizeof( rd.m_wpl );
+ VAPI( GetWindowPlacement( &rd.m_wpl ) );
+
+ if( pdd->hkRootSave && pdd->pcszName ) {
+ (void)RegSetValueExRecursive( pdd->hkRootSave, pdd->pcszName,
+ NULL, REG_BINARY,
+ reinterpret_cast( &rd ),
+ sizeof( rd ) );
+ }
+
+ if( pdd->psd ) {
+ free(pdd->psd);
+ }
+ free(pdd);
+ }
+
+ }
+ break;
+ }
+ return CDialog::OnWndMsg(msg, wParam, lParam, res);
+}
diff --git a/src/win32/RomInfo.cpp b/src/win32/RomInfo.cpp
index 9892038d..1569d72f 100644
--- a/src/win32/RomInfo.cpp
+++ b/src/win32/RomInfo.cpp
@@ -1,6 +1,6 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004-2005 Forgotten and the VBA development team
+// Copyright (C) 2004-2006 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -356,6 +356,15 @@ BOOL RomInfoGB::OnInitDialog()
case 0x06:
type = "ROM+MBC2+BATT";
break;
+ case 0x0b:
+ type = "ROM+MMM01";
+ break;
+ case 0x0c:
+ type = "ROM+MMM01+RAM";
+ break;
+ case 0x0d:
+ type = "ROM+MMM01+RAM+BATT";
+ break;
case 0x0f:
type = "ROM+MBC3+TIMER+BATT";
break;
@@ -392,6 +401,18 @@ BOOL RomInfoGB::OnInitDialog()
case 0x22:
type = "ROM+MBC7+BATT";
break;
+ case 0x55:
+ type = "GameGenie";
+ break;
+ case 0x56:
+ type = "GameShark V3.0";
+ break;
+ case 0xfc:
+ type = "ROM+POCKET CAMERA";
+ break;
+ case 0xfd:
+ type = "ROM+BANDAI TAMA5";
+ break;
case 0xfe:
type = "ROM+HuC-3";
break;
@@ -533,51 +554,44 @@ void RomInfoGBA::OnOk()
BOOL RomInfoGBA::OnInitDialog()
{
CDialog::OnInitDialog();
-
- char buffer[32];
- // Game Title
+ char buffer[13];
+
strncpy(buffer, (const char *)&rom[0xa0], 12);
buffer[12] = 0;
GetDlgItem(IDC_ROM_TITLE)->SetWindowText(buffer);
- // Game Code
strncpy(buffer, (const char *)&rom[0xac], 4);
buffer[4] = 0;
GetDlgItem(IDC_ROM_GAME_CODE)->SetWindowText(buffer);
- // Maker Code
strncpy(buffer, (const char *)&rom[0xb0],2);
buffer[2] = 0;
GetDlgItem(IDC_ROM_MAKER_CODE)->SetWindowText(buffer);
- // Maker Code -> Maker Name
GetDlgItem(IDC_ROM_MAKER_NAME)->SetWindowText(winGBARomInfoFindMakerCode(buffer));
- // Main Unit Code
sprintf(buffer, "%02x", rom[0xb3]);
GetDlgItem(IDC_ROM_UNIT_CODE)->SetWindowText(buffer);
- // Device Type
sprintf(buffer, "%02x", rom[0xb4]);
+ if( rom[0xb4] & 0x80 ) {
+ strcat(buffer, " (DACS)");
+ }
GetDlgItem(IDC_ROM_DEVICE_TYPE)->SetWindowText(buffer);
- // ROM Version Number
sprintf(buffer, "%02x", rom[0xbc]);
GetDlgItem(IDC_ROM_VERSION)->SetWindowText(buffer);
- // Complement Check
- int x, crc = 0x19;
- for(int i = 0xa0; i < 0xbd; i++)
- {
- x = rom[i];
- crc += x;
+ u8 crc = 0x19;
+ for(int i = 0xa0; i < 0xbd; i++) {
+ crc += rom[i];
}
- crc = (-crc) & 0xFF;
- char same = (rom[0xbd] == crc) ? '=' : '/'; // Compare
- sprintf(buffer, "ROM: %02X %c EMU: %02X", rom[0xbd], same, crc);
- GetDlgItem(IDC_ROM_CRC)->SetWindowText(buffer);
+ crc = (-crc) & 255;
+
+ sprintf(buffer, "%02x (%02x)", crc, rom[0xbd]);
+ GetDlgItem(IDC_ROM_CRC)->SetWindowText(buffer);
CenterWindow();
return TRUE; // return TRUE unless you set the focus to a control
diff --git a/src/win32/TileView.cpp b/src/win32/TileView.cpp
index 24b3a4c7..40cd0f64 100644
--- a/src/win32/TileView.cpp
+++ b/src/win32/TileView.cpp
@@ -265,38 +265,41 @@ void TileView::savePNG(const char *name)
void TileView::OnSave()
{
- CString captureBuffer;
+ if(rom != NULL)
+ {
+ CString captureBuffer;
- if(theApp.captureFormat == 0)
- captureBuffer = "tiles.png";
- else
- captureBuffer = "tiles.bmp";
+ if(theApp.captureFormat == 0)
+ captureBuffer = "tiles.png";
+ else
+ captureBuffer = "tiles.bmp";
- LPCTSTR exts[] = {".png", ".bmp" };
+ LPCTSTR exts[] = {".png", ".bmp" };
- CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
- CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
+ CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
+ CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
- FileDlg dlg(this,
- captureBuffer,
- filter,
- theApp.captureFormat ? 2 : 1,
- theApp.captureFormat ? "BMP" : "PNG",
- exts,
- "",
- title,
- true);
+ FileDlg dlg(this,
+ captureBuffer,
+ filter,
+ theApp.captureFormat ? 2 : 1,
+ theApp.captureFormat ? "BMP" : "PNG",
+ exts,
+ "",
+ title,
+ true);
- if(dlg.DoModal() == IDCANCEL) {
- return;
+ if(dlg.DoModal() == IDCANCEL) {
+ return;
+ }
+
+ captureBuffer = dlg.GetPathName();
+
+ if(dlg.getFilterIndex() == 2)
+ saveBMP(captureBuffer);
+ else
+ savePNG(captureBuffer);
}
-
- captureBuffer = dlg.GetPathName();
-
- if(dlg.getFilterIndex() == 2)
- saveBMP(captureBuffer);
- else
- savePNG(captureBuffer);
}
void TileView::renderTile256(int tile, int x, int y, u8 *charBase, u16 *palette)
@@ -526,8 +529,8 @@ LRESULT TileView::OnMapInfo(WPARAM wParam, LPARAM lParam)
u8 *colors = (u8 *)lParam;
zoom.setColors(colors);
- int x = (wParam & 0xFFFF)/8;
- int y = ((wParam >> 16) & 0xFFFF)/8;
+ int x = (int)((wParam & 0xFFFF) / 8);
+ int y = (int)(((wParam >> 16) & 0xFFFF) / 8);
u32 address = 0x6000000 + 0x4000 * charBase;
int tile = 32 * y + x;
diff --git a/src/win32/VBA.cpp b/src/win32/VBA.cpp
index 682d3f96..3dcf1381 100644
--- a/src/win32/VBA.cpp
+++ b/src/win32/VBA.cpp
@@ -1,2313 +1,2518 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-// VBA.cpp : Defines the class behaviors for the application.
-//
-#include "stdafx.h"
-#include
-
-#include "AVIWrite.h"
-#include "LangSelect.h"
-#include "MainWnd.h"
-#include "Reg.h"
-#include "..\..\res\resource.h"
-#include "WavWriter.h"
-#include "WinResUtil.h"
-
-#include "../System.h"
-#include "../agbprint.h"
-#include "../cheatSearch.h"
-#include "../GBA.h"
-#include "../Globals.h"
-#include "../RTC.h"
-#include "../Sound.h"
-#include "../Util.h"
-#include "../gb/gbGlobals.h"
-#include "../gb/gbPrinter.h"
-
-/* Link
----------------------*/
-#include "../Link.h"
-/* ---------------- */
-
-#include "../gbafilter.h"
-
-#ifdef SDL
-#pragma comment( lib, "SDL" )
-#pragma comment( lib, "SDLmain" )
-#endif
-
-extern void Pixelate(u8*,u32,u8*,u8*,u32,int,int);
-extern void Pixelate32(u8*,u32,u8*,u8*,u32,int,int);
-extern void MotionBlur(u8*,u32,u8*,u8*,u32,int,int);
-extern void MotionBlur32(u8*,u32,u8*,u8*,u32,int,int);
-extern void _2xSaI(u8*,u32,u8*,u8*,u32,int,int);
-extern void _2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
-extern void Super2xSaI(u8*,u32,u8*,u8*,u32,int,int);
-extern void Super2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
-extern void SuperEagle(u8*,u32,u8*,u8*,u32,int,int);
-extern void SuperEagle32(u8*,u32,u8*,u8*,u32,int,int);
-extern void AdMame2x(u8*,u32,u8*,u8*,u32,int,int);
-extern void AdMame2x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void Bilinear(u8*,u32,u8*,u8*,u32,int,int);
-extern void Bilinear32(u8*,u32,u8*,u8*,u32,int,int);
-extern void BilinearPlus(u8*,u32,u8*,u8*,u32,int,int);
-extern void BilinearPlus32(u8*,u32,u8*,u8*,u32,int,int);
-extern void Scanlines(u8*,u32,u8*,u8*,u32,int,int);
-extern void Scanlines32(u8*,u32,u8*,u8*,u32,int,int);
-extern void ScanlinesTV(u8*,u32,u8*,u8*,u32,int,int);
-extern void ScanlinesTV32(u8*,u32,u8*,u8*,u32,int,int);
-extern void hq2x(u8*,u32,u8*,u8*,u32,int,int);
-extern void hq2x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void lq2x(u8*,u32,u8*,u8*,u32,int,int);
-extern void lq2x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void Simple2x16(u8*,u32,u8*,u8*,u32,int,int);
-extern void Simple2x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void Simple3x16(u8*,u32,u8*,u8*,u32,int,int);
-extern void Simple3x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void Simple4x16(u8*,u32,u8*,u8*,u32,int,int);
-extern void Simple4x32(u8*,u32,u8*,u8*,u32,int,int);
-
-extern void hq3x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void hq3x16(u8*,u32,u8*,u8*,u32,int,int);
-extern void hq4x32(u8*,u32,u8*,u8*,u32,int,int);
-extern void hq4x16(u8*,u32,u8*,u8*,u32,int,int);
-
-extern void SmartIB(u8*,u32,int,int);
-extern void SmartIB32(u8*,u32,int,int);
-extern void MotionBlurIB(u8*,u32,int,int);
-extern void InterlaceIB(u8*,u32,int,int);
-extern void MotionBlurIB32(u8*,u32,int,int);
-
-extern void toolsLog(const char *);
-
-extern IDisplay *newGDIDisplay();
-extern IDisplay *newDirectDrawDisplay();
-extern IDisplay *newDirect3DDisplay();
-extern IDisplay *newOpenGLDisplay();
-
-extern Input *newDirectInput();
-
-extern ISound *newDirectSound();
-
-extern void remoteStubSignal(int, int);
-extern void remoteOutput(char *, u32);
-extern void remoteStubMain();
-extern void remoteSetProtocol(int);
-extern void remoteCleanUp();
-extern int remoteSocket;
-
-extern void InterframeCleanup();
-
-void winlog(const char *msg, ...);
-
-/* Link
----------------------*/
-extern int InitLink(void);
-extern void CloseLink(void);
-//extern int linkid;
-extern char inifile[];
-extern FILE *linklogfile;
-/* ------------------- */
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-int emulating = 0;
-bool debugger = false;
-int RGB_LOW_BITS_MASK = 0;
-bool b16to32Video = false;
-int systemFrameSkip = 0;
-int systemSpeed = 0;
-bool systemSoundOn = false;
-u32 systemColorMap32[0x10000];
-u16 systemColorMap16[0x10000];
-u16 systemGbPalette[24];
-int systemRedShift = 0;
-int systemBlueShift = 0;
-int systemGreenShift = 0;
-int systemColorDepth = 16;
-int systemVerbose = 0;
-int systemDebug = 0;
-int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-bool soundBufferLow = 0;
-void winSignal(int,int);
-void winOutput(char *, u32);
-
-void (*dbgSignal)(int,int) = winSignal;
-void (*dbgOutput)(char *, u32) = winOutput;
-
-#ifdef MMX
-extern "C" bool cpu_mmx;
-#endif
-
-void directXMessage(const char *msg)
-{
- systemMessage(IDS_DIRECTX_7_REQUIRED,
- "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s",
- msg);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// VBA
-
-BEGIN_MESSAGE_MAP(VBA, CWinApp)
- //{{AFX_MSG_MAP(VBA)
- // NOTE - the ClassWizard will add and remove mapping macros here.
- // DO NOT EDIT what you see in these blocks of generated code!
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
-// VBA construction
-
-VBA::VBA()
-{
- mode320Available = false;
- mode640Available = false;
- mode800Available = false;
- mode1024Available = false;
- mode1280Available = false;
- windowPositionX = 0;
- windowPositionY = 0;
- filterFunction = NULL;
- ifbFunction = NULL;
- ifbType = 0;
- filterType = FILTER_NONE;
- filterWidth = 0;
- filterHeight = 0;
- fsWidth = 0;
- fsHeight = 0;
- fsColorDepth = 0;
- fsForceChange = false;
- surfaceSizeX = 0;
- surfaceSizeY = 0;
- sizeX = 0;
- sizeY = 0;
- videoOption = VIDEO_3X;
- fullScreenStretch = false;
- disableStatusMessage = false;
- showSpeed = 0;
- showSpeedTransparent = true;
- showRenderedFrames = 0;
- screenMessage = false;
- screenMessageTime = 0;
- menuToggle = true;
- display = NULL;
- menu = NULL;
- popup = NULL;
- cartridgeType = 0;
- soundInitialized = false;
- useBiosFile = false;
- skipBiosFile = false;
- active = true;
- paused = false;
- recentFreeze = false;
- autoSaveLoadCheatList = false;
- winout = NULL;
- removeIntros = false;
- autoIPS = false;
- winGbBorderOn = 0;
- winFlashSize = 0x20000;
- winRtcEnable = false;
- winSaveType = 0;
- rewindMemory = NULL;
- rewindPos = 0;
- rewindTopPos = 0;
- rewindCounter = 0;
- rewindCount = 0;
- rewindSaveNeeded = false;
- rewindTimer = 0;
- captureFormat = 0;
- tripleBuffering = true;
- autoHideMenu = false;
- throttle = 0;
- throttleLastTime = 0;
- autoFrameSkipLastTime = 0;
- autoFrameSkip = false;
- vsync = false;
- changingVideoSize = false;
- pVideoDriverGUID = NULL;
- renderMethod = DIRECT_DRAW;
- iconic = false;
- ddrawEmulationOnly = false;
- ddrawUsingEmulationOnly = false;
- ddrawDebug = false;
- ddrawUseVideoMemory = false;
- d3dFilter = 0;
- glFilter = 0;
- glType = 0;
- regEnabled = false;
- pauseWhenInactive = true;
- speedupToggle = false;
- useOldSync = false;
- winGbPrinterEnabled = false;
- threadPriority = 2;
- disableMMX = false;
- languageOption = 0;
- languageModule = NULL;
- languageName = "";
- renderedFrames = 0;
- input = NULL;
- joypadDefault = 0;
- autoFire = 0;
- autoFireToggle = false;
- winPauseNextFrame = false;
- soundRecording = false;
- soundRecorder = NULL;
- sound = NULL;
- aviRecording = false;
- aviRecorder = NULL;
- aviFrameNumber = 0;
- painting = false;
- movieRecording = false;
- moviePlaying = false;
- movieFrame = 0;
- moviePlayFrame = 0;
- movieFile = NULL;
- movieLastJoypad = 0;
- movieNextJoypad = 0;
- sensorX = 2047;
- sensorY = 2047;
- mouseCounter = 0;
- wasPaused = false;
- frameskipadjust = 0;
- autoLoadMostRecent = false;
- fsMaxScale = 0;
- romSize = 0;
-
- updateCount = 0;
-
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- ZeroMemory(&emulator, sizeof(emulator));
-
- hAccel = NULL;
-
- for(int i = 0; i < 24;) {
- systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
- systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
- systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
- systemGbPalette[i++] = 0;
- }
-}
-
-VBA::~VBA()
-{
- InterframeCleanup();
-
- saveSettings();
-
- if(moviePlaying) {
- if(movieFile != NULL) {
- fclose(movieFile);
- movieFile = NULL;
- }
- moviePlaying = false;
- movieLastJoypad = 0;
- }
-
- if(movieRecording) {
- if(movieFile != NULL) {
- // record the last joypad change so that the correct time can be
- // recorded
- fwrite(&movieFrame, 1, sizeof(int), movieFile);
- fwrite(&movieLastJoypad, 1, sizeof(u32), movieFile);
- fclose(movieFile);
- movieFile = NULL;
- }
- movieRecording = false;
- moviePlaying = false;
- movieLastJoypad = 0;
- }
-
- if(aviRecorder) {
- delete aviRecorder;
- aviRecording = false;
- }
-
- if(soundRecorder) {
- delete soundRecorder;
- soundRecorder = NULL;
- }
- soundRecording = false;
- soundPause();
- soundShutdown();
-
- if(gbRom != NULL || rom != NULL) {
- if(autoSaveLoadCheatList)
- ((MainWnd *)m_pMainWnd)->winSaveCheatListDefault();
- ((MainWnd *)m_pMainWnd)->writeBatteryFile();
- cheatSearchCleanup(&cheatSearchData);
- emulator.emuCleanUp();
- }
-
- if(input)
- delete input;
-
- shutdownDisplay();
-
- if(rewindMemory)
- free(rewindMemory);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// The one and only VBA object
-
-VBA theApp;
-//#include
-/////////////////////////////////////////////////////////////////////////////
-// VBA initialization
-
-// code from SDL_main.c for Windows
-/* Parse a command line buffer into arguments */
-static int parseCommandLine(char *cmdline, char **argv)
-{
- char *bufp;
- int argc;
-
- argc = 0;
- for ( bufp = cmdline; *bufp; ) {
- /* Skip leading whitespace */
- while ( isspace(*bufp) ) {
- ++bufp;
- }
- /* Skip over argument */
- if ( *bufp == '"' ) {
- ++bufp;
- if ( *bufp ) {
- if ( argv ) {
- argv[argc] = bufp;
- }
- ++argc;
- }
- /* Skip over word */
- while ( *bufp && (*bufp != '"') ) {
- ++bufp;
- }
- } else {
- if ( *bufp ) {
- if ( argv ) {
- argv[argc] = bufp;
- }
- ++argc;
- }
- /* Skip over word */
- while ( *bufp && ! isspace(*bufp) ) {
- ++bufp;
- }
- }
- if ( *bufp ) {
- if ( argv ) {
- *bufp = '\0';
- }
- ++bufp;
- }
- }
- if ( argv ) {
- argv[argc] = NULL;
- }
- return(argc);
-}
-
-BOOL VBA::InitInstance()
-{
- AfxEnableControlContainer();
- // Standard initialization
- // If you are not using these features and wish to reduce the size
- // of your final executable, you should remove from the following
- // the specific initialization routines you do not need.
-
- SetRegistryKey(_T("VBA"));
-
- remoteSetProtocol(0);
-
- systemVerbose = GetPrivateProfileInt("config",
- "verbose",
- 0,
- "VBA.ini");
-
- systemDebug = GetPrivateProfileInt("config",
- "debug",
- 0,
- "VBA.ini");
- ddrawDebug = GetPrivateProfileInt("config",
- "ddrawDebug",
- 0,
- "VBA.ini") ? true : false;
-
- wndClass = AfxRegisterWndClass(0, LoadCursor(IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(IDI_ICON));
-
- char winBuffer[2048];
-
- GetModuleFileName(NULL, winBuffer, 2048);
- char *p = strrchr(winBuffer, '\\');
- if(p)
- *p = 0;
-
- if(!InitLink())
- return FALSE;;
-
- regInit(winBuffer);
-
- loadSettings();
-
- if(!openLinkLog())
- return FALSE;
-
- if(!initInput())
- return FALSE;
-
- if(!initDisplay()) {
- if(videoOption >= VIDEO_320x240) {
- regSetDwordValue("video", VIDEO_1X);
- if(pVideoDriverGUID)
- regSetDwordValue("defaultVideoDriver", TRUE);
- }
- return FALSE;
- }
-
- hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));
-
- winAccelMgr.Connect((MainWnd *)m_pMainWnd);
-
- winAccelMgr.SetRegKey(HKEY_CURRENT_USER, "Software\\Emulators\\VisualBoyAdvance");
-
- extern void winAccelAddCommands(CAcceleratorManager&);
-
- winAccelAddCommands(winAccelMgr);
-
- winAccelMgr.CreateDefaultTable();
-
- winAccelMgr.Load();
-
- winAccelMgr.UpdateWndTable();
-
- winAccelMgr.UpdateMenu(menu);
-
- if (m_lpCmdLine[0])
- {
- int argc = parseCommandLine(m_lpCmdLine, NULL);
- char **argv = (char **)malloc((argc+1)*sizeof(char *));
- parseCommandLine(m_lpCmdLine, argv);
- if(argc > 0) {
- szFile = argv[0];
- filename = szFile;
- }
- int index = filename.ReverseFind('.');
-
- if(index != -1)
- filename = filename.Left(index);
-
- if(((MainWnd*)m_pMainWnd)->FileRun())
- emulating = true;
- else
- emulating = false;
- free(argv);
- }
-
- return TRUE;
-}
-
-void VBA::adjustDestRect()
-{
- POINT point;
- point.x = 0;
- point.y = 0;
-
- m_pMainWnd->ClientToScreen(&point);
- dest.top = point.y;
- dest.left = point.x;
-
- point.x = surfaceSizeX;
- point.y = surfaceSizeY;
-
- m_pMainWnd->ClientToScreen(&point);
- dest.bottom = point.y;
- dest.right = point.x;
-
- // make sure that dest rect lies in the monitor
- if(videoOption >= VIDEO_320x240) {
- dest.top -= windowPositionY;
- dest.left -= windowPositionX;
- dest.bottom-= windowPositionY;
- dest.right -= windowPositionX;
- }
-
- int menuSkip = 0;
-
- if(videoOption >= VIDEO_320x240 && menuToggle) {
- int m = GetSystemMetrics(SM_CYMENU);
- menuSkip = m;
- dest.bottom -=m;
- }
-
- if(videoOption > VIDEO_4X) {
- int top = (fsHeight - surfaceSizeY) / 2;
- int left = (fsWidth - surfaceSizeX) / 2;
- dest.top += top;
- dest.bottom += top;
- dest.left += left;
- dest.right += left;
- if(fullScreenStretch) {
- dest.top = 0+menuSkip;
- dest.left = 0;
- dest.right = fsWidth;
- dest.bottom = fsHeight;
- }
- }
-}
-
-void VBA::updateIFB()
-{
- if(systemColorDepth == 16) {
- switch(ifbType) {
- case 0:
- default:
- ifbFunction = NULL;
- break;
- case 1:
- ifbFunction = MotionBlurIB;
- break;
- case 2:
- ifbFunction = SmartIB;
- break;
- }
- } else if(systemColorDepth == 32) {
- switch(ifbType) {
- case 0:
- default:
- ifbFunction = NULL;
- break;
- case 1:
- ifbFunction = MotionBlurIB32;
- break;
- case 2:
- ifbFunction = SmartIB32;
- break;
- }
- } else
- ifbFunction = NULL;
-}
-
-void VBA::updateFilter()
-{
- // BEGIN hacky ugly code
-
- // HQ3X asm wants 16 bit input. When we switch
- // away from 16 bits we need to restore the driver values
-
- if ( b16to32Video )
- {
- b16to32Video = false;
- systemColorDepth = 32;
- systemRedShift = 19;
- systemGreenShift = 11;
- systemBlueShift = 3;
- utilUpdateSystemColorMaps(theApp.filterLCD);
- }
- // END hacky ugly code
-
- filterWidth = sizeX;
- filterHeight = sizeY;
- filterMagnification = 1;
-
-
- if ( videoOption == VIDEO_1X || videoOption == VIDEO_320x240 )
- {
- filterFunction = NULL;
- filterMagnification = 1;
- }
- else
- {
- if ( systemColorDepth == 16 )
- {
- switch(filterType)
- {
- default:
- case FILTER_NONE:
- filterFunction = NULL;
- filterMagnification = 1;
- break;
- case FILTER_TVMODE:
- filterFunction = ScanlinesTV;
- filterMagnification = 2;
- break;
- case FILTER_2XSAI:
- filterFunction = _2xSaI;
- filterMagnification = 2;
- break;
- case FILTER_SUPER2XSAI:
- filterFunction = Super2xSaI;
- filterMagnification = 2;
- break;
- case FILTER_SUPEREAGLE:
- filterFunction = SuperEagle;
- filterMagnification = 2;
- break;
- case FILTER_PIXELATE:
- filterFunction = Pixelate;
- filterMagnification = 2;
- break;
- case FILTER_MAMESCALE2X:
- filterFunction = AdMame2x;
- filterMagnification = 2;
- break;
- case FILTER_SIMPLE2X:
- filterFunction = Simple2x16;
- filterMagnification = 2;
- break;
- case FILTER_BILINEAR:
- filterFunction = Bilinear;
- filterMagnification = 2;
- break;
- case FILTER_BILINEARPLUS:
- filterFunction = BilinearPlus;
- filterMagnification = 2;
- break;
- case FILTER_SCANLINES:
- filterFunction = Scanlines;
- filterMagnification = 2;
- break;
- case FILTER_HQ2X:
- filterFunction = hq2x;
- filterMagnification = 2;
- break;
- case FILTER_LQ2X:
- filterFunction = lq2x;
- filterMagnification = 2;
- break;
- case FILTER_SIMPLE3X:
- filterFunction = Simple3x16;
- filterMagnification = 3;
- break;
- case FILTER_SIMPLE4X:
- filterFunction = Simple4x16;
- filterMagnification = 4;
- break;
- case FILTER_HQ3X:
- filterFunction = hq3x16;
- filterMagnification = 3;
- break;
- case FILTER_HQ4X:
- filterFunction = hq4x16;
- filterMagnification = 4;
- break;
- }
- }
-
- if ( systemColorDepth == 32 )
- {
- switch(filterType)
- {
- default:
- case FILTER_NONE:
- filterFunction = NULL;
- filterMagnification = 1;
- break;
- case FILTER_TVMODE:
- filterFunction = ScanlinesTV32;
- filterMagnification = 2;
- break;
- case FILTER_2XSAI:
- filterFunction = _2xSaI32;
- filterMagnification = 2;
- break;
- case FILTER_SUPER2XSAI:
- filterFunction = Super2xSaI32;
- filterMagnification = 2;
- break;
- case FILTER_SUPEREAGLE:
- filterFunction = SuperEagle32;
- filterMagnification = 2;
- break;
- case FILTER_PIXELATE:
- filterFunction = Pixelate32;
- filterMagnification = 2;
- break;
- case FILTER_MAMESCALE2X:
- filterFunction = AdMame2x32;
- filterMagnification = 2;
- break;
- case FILTER_SIMPLE2X:
- filterFunction = Simple2x32;
- filterMagnification = 2;
- break;
- case FILTER_BILINEAR:
- filterFunction = Bilinear32;
- filterMagnification = 2;
- break;
- case FILTER_BILINEARPLUS:
- filterFunction = BilinearPlus32;
- filterMagnification = 2;
- break;
- case FILTER_SCANLINES:
- filterFunction = Scanlines32;
- filterMagnification = 2;
- break;
- case FILTER_HQ2X:
- filterFunction = hq2x32;
- filterMagnification = 2;
- break;
- case FILTER_LQ2X:
- filterFunction = lq2x32;
- filterMagnification = 2;
- break;
- case FILTER_SIMPLE3X:
- filterFunction = Simple3x32;
- filterMagnification = 3;
- break;
- case FILTER_SIMPLE4X:
- filterFunction = Simple4x32;
- filterMagnification = 4;
- break;
- case FILTER_HQ3X:
- filterFunction = hq3x32;
- filterMagnification = 3;
- b16to32Video=true;
- break;
- case FILTER_HQ4X:
- filterFunction = hq4x32;
- filterMagnification = 4;
- b16to32Video=true;
- break;
- }
- }
- }
-
- rect.right = sizeX * filterMagnification;
- rect.bottom = sizeY * filterMagnification;
-
- if( filterType != FILTER_NONE )
- memset(delta, 0xFF, sizeof(delta));
-
- if( display )
- display->changeRenderSize(rect.right, rect.bottom);
-
- if (b16to32Video)
- {
- systemColorDepth = 16;
- systemRedShift = 11;
- systemGreenShift = 6;
- systemBlueShift = 0;
- utilUpdateSystemColorMaps(theApp.filterLCD);
- }
-}
-
-
-void VBA::updateMenuBar()
-{
- if(menu != NULL) {
- if(m_pMainWnd)
- m_pMainWnd->SetMenu(NULL);
- m_menu.Detach();
- DestroyMenu(menu);
- }
-
- if(popup != NULL) {
- // force popup recreation if language changed
- DestroyMenu(popup);
- popup = NULL;
- }
-
- m_menu.Attach(winResLoadMenu(MAKEINTRESOURCE(IDR_MENU)));
- menu = (HMENU)m_menu;
-
- if(m_pMainWnd)
- m_pMainWnd->SetMenu(&m_menu);
-
- if (display)
- display->clear();
-}
-
-void winlog(const char *msg, ...)
-{
- CString buffer;
- va_list valist;
-
- va_start(valist, msg);
- buffer.FormatV(msg, valist);
-
- if(theApp.winout == NULL) {
- theApp.winout = fopen("vba-trace.log","w");
- }
-
- fputs(buffer, theApp.winout);
-
- va_end(valist);
-}
-
-void log(const char *msg, ...)
-{
- CString buffer;
- va_list valist;
-
- va_start(valist, msg);
- buffer.FormatV(msg, valist);
-
- toolsLog(buffer);
-
- va_end(valist);
-}
-
-bool systemReadJoypads()
-{
- if(theApp.input)
- return theApp.input->readDevices();
- return false;
-}
-
-u32 systemReadJoypad(int which)
-{
- if(theApp.input)
- return theApp.input->readDevice(which);
- return 0;
-}
-
-void systemDrawScreen()
-{
- if(theApp.display == NULL)
- return;
-
- theApp.renderedFrames++;
-
- if(theApp.updateCount) {
- POSITION pos = theApp.updateList.GetHeadPosition();
- while(pos) {
- IUpdateListener *up = theApp.updateList.GetNext(pos);
- up->update();
- }
- }
-
- if(theApp.aviRecording && !theApp.painting) {
- int width = 240;
- int height = 160;
- switch(theApp.cartridgeType) {
- case 0:
- width = 240;
- height = 160;
- break;
- case 1:
- if(gbBorderOn) {
- width = 256;
- height = 224;
- } else {
- width = 160;
- height = 144;
- }
- break;
- }
-
- if(theApp.aviRecorder == NULL) {
- theApp.aviRecorder = new AVIWrite();
- theApp.aviFrameNumber = 0;
-
- theApp.aviRecorder->SetFPS(60);
-
- BITMAPINFOHEADER bi;
- memset(&bi, 0, sizeof(bi));
- bi.biSize = 0x28;
- bi.biPlanes = 1;
- bi.biBitCount = 24;
- bi.biWidth = width;
- bi.biHeight = height;
- bi.biSizeImage = 3*width*height;
- theApp.aviRecorder->SetVideoFormat(&bi);
- theApp.aviRecorder->Open(theApp.aviRecordName);
- }
-
- char *bmp = new char[width*height*3];
-
- utilWriteBMP(bmp, width, height, pix);
- theApp.aviRecorder->AddFrame(theApp.aviFrameNumber, bmp);
-
- delete bmp;
- }
-
- if(theApp.ifbFunction) {
- if(systemColorDepth == 16)
- theApp.ifbFunction(pix+theApp.filterWidth*2+4, theApp.filterWidth*2+4,
- theApp.filterWidth, theApp.filterHeight);
- else
- theApp.ifbFunction(pix+theApp.filterWidth*4+4, theApp.filterWidth*4+4,
- theApp.filterWidth, theApp.filterHeight);
- }
-
- if(!soundBufferLow)
- theApp.display->render();
- else
- soundBufferLow = false;
-}
-
-void systemScreenCapture(int captureNumber)
-{
- if(theApp.m_pMainWnd)
- ((MainWnd *)theApp.m_pMainWnd)->screenCapture(captureNumber);
-}
-
-u32 systemGetClock()
-{
- return GetTickCount();
-}
-
-void systemMessage(int number, const char *defaultMsg, ...)
-{
- CString buffer;
- va_list valist;
- CString msg = defaultMsg;
- if(number)
- msg = winResLoadString(number);
-
- va_start(valist, defaultMsg);
- buffer.FormatV(msg, valist);
-
- theApp.winCheckFullscreen();
-
- AfxGetApp()->m_pMainWnd->MessageBox(buffer, winResLoadString(IDS_ERROR), MB_OK|MB_ICONERROR);
-
- va_end(valist);
-}
-
-void systemSetTitle(const char *title)
-{
- if(theApp.m_pMainWnd != NULL) {
- AfxGetApp()->m_pMainWnd->SetWindowText(title);
- }
-}
-
-void systemShowSpeed(int speed)
-{
- systemSpeed = speed;
- theApp.showRenderedFrames = theApp.renderedFrames;
- theApp.renderedFrames = 0;
- if(theApp.videoOption <= VIDEO_4X && theApp.showSpeed) {
- CString buffer;
- if(theApp.showSpeed == 1)
- buffer.Format("VisualBoyAdvance-%3d%%", systemSpeed);
- else
- buffer.Format("VisualBoyAdvance-%3d%%(%d, %d fps)", systemSpeed,
- systemFrameSkip,
- theApp.showRenderedFrames);
-
- systemSetTitle(buffer);
- }
-}
-
-void systemFrame()
-{
- if(theApp.aviRecording)
- theApp.aviFrameNumber++;
- if(theApp.movieRecording || theApp.moviePlaying)
- theApp.movieFrame++;
-}
-
-void system10Frames(int rate)
-{
- u32 time = systemGetClock();
- if(!theApp.wasPaused && theApp.autoFrameSkip && !theApp.throttle) {
- u32 diff = time - theApp.autoFrameSkipLastTime;
- int speed = 100;
-
- if(diff)
- speed = (1000000/rate)/diff;
-
- if(speed >= 98) {
- theApp.frameskipadjust++;
-
- if(theApp.frameskipadjust >= 3) {
- theApp.frameskipadjust=0;
- if(systemFrameSkip > 0)
- systemFrameSkip--;
- }
- } else {
- if(speed < 80)
- theApp.frameskipadjust -= (90 - speed)/5;
- else if(systemFrameSkip < 9)
- theApp.frameskipadjust--;
-
- if(theApp.frameskipadjust <= -2) {
- theApp.frameskipadjust += 2;
- if(systemFrameSkip < 9)
- systemFrameSkip++;
- }
- }
- }
- if(!theApp.wasPaused && theApp.throttle) {
- if(!speedup) {
- u32 diff = time - theApp.throttleLastTime;
-
- int target = (1000000/(rate*theApp.throttle));
- int d = (target - diff);
-
- if(d > 0) {
- Sleep(d);
- }
- }
- theApp.throttleLastTime = systemGetClock();
- }
- if(theApp.rewindMemory) {
- if(++theApp.rewindCounter >= (theApp.rewindTimer)) {
- theApp.rewindSaveNeeded = true;
- theApp.rewindCounter = 0;
- }
- }
- if(systemSaveUpdateCounter) {
- if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
- ((MainWnd *)theApp.m_pMainWnd)->writeBatteryFile();
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
- }
- }
-
- theApp.wasPaused = false;
- theApp.autoFrameSkipLastTime = time;
-}
-
-void systemScreenMessage(const char *msg)
-{
- theApp.screenMessage = true;
- theApp.screenMessageTime = GetTickCount();
- theApp.screenMessageBuffer = msg;
-
- if(theApp.screenMessageBuffer.GetLength() > 40)
- theApp.screenMessageBuffer = theApp.screenMessageBuffer.Left(40);
-}
-
-void systemUpdateMotionSensor()
-{
- if(theApp.input)
- theApp.input->checkMotionKeys();
-}
-
-int systemGetSensorX()
-{
- return theApp.sensorX;
-}
-
-int systemGetSensorY()
-{
- return theApp.sensorY;
-}
-
-bool systemSoundInit()
-{
- if(theApp.sound)
- delete theApp.sound;
-
- theApp.sound = newDirectSound();
- return theApp.sound->init();
-}
-
-
-void systemSoundShutdown()
-{
- if(theApp.sound)
- delete theApp.sound;
- theApp.sound = NULL;
-}
-
-void systemSoundPause()
-{
- if(theApp.sound)
- theApp.sound->pause();
-}
-
-void systemSoundReset()
-{
- if(theApp.sound)
- theApp.sound->reset();
-}
-
-void systemSoundResume()
-{
- if(theApp.sound)
- theApp.sound->resume();
-}
-
-void systemWriteDataToSoundBuffer()
-{
- if(theApp.sound)
- theApp.sound->write();
-}
-
-bool systemCanChangeSoundQuality()
-{
- return true;
-}
-
-bool systemPauseOnFrame()
-{
- if(theApp.winPauseNextFrame) {
- theApp.paused = true;
- theApp.winPauseNextFrame = false;
- return true;
- }
- return false;
-}
-
-void systemGbBorderOn()
-{
- if(emulating && theApp.cartridgeType == 1 && gbBorderOn) {
- theApp.updateWindowSize(theApp.videoOption);
- }
-}
-
-BOOL VBA::OnIdle(LONG lCount)
-{
- if(emulating && debugger) {
- MSG msg;
- remoteStubMain();
- if(debugger)
- return TRUE; // continue loop
- return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
- } else if(emulating && active && !paused) {
- for(int i = 0; i < 2; i++) {
- emulator.emuMain(emulator.emuCount);
- if(lanlink.connected&&linkid&&lc.numtransfers==0) lc.CheckConn();
-
- if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) {
- rewindCount++;
- if(rewindCount > 8)
- rewindCount = 8;
- if(emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE],
- REWIND_SIZE)) {
- rewindPos = ++rewindPos & 7;
- if(rewindCount == 8)
- rewindTopPos = ++rewindTopPos & 7;
- }
- }
-
- rewindSaveNeeded = false;
- }
-
- if(mouseCounter) {
- if(--mouseCounter == 0) {
- SetCursor(NULL);
- }
- }
- return TRUE;
- }
- return FALSE;
-
- // return CWinApp::OnIdle(lCount);
-}
-
-void VBA::addRecentFile(CString file)
-{
- // Do not change recent list if frozen
- if(recentFreeze)
- return;
- int i = 0;
- for(i = 0; i < 10; i++) {
- if(recentFiles[i].GetLength() == 0)
- break;
-
- if(recentFiles[i].Compare(file) == 0) {
- if(i == 0)
- return;
- CString p = recentFiles[i];
- for(int j = i; j > 0; j--) {
- recentFiles[j] = recentFiles[j-1];
- }
- recentFiles[0] = p;
- return;
- }
- }
- int num = 0;
- for(i = 0; i < 10; i++) {
- if(recentFiles[i].GetLength() != 0)
- num++;
- }
- if(num == 10) {
- num--;
- }
-
- for(i = num; i >= 1; i--) {
- recentFiles[i] = recentFiles[i-1];
- }
- recentFiles[0] = file;
-}
-
-void VBA::loadSettings()
-{
- CString buffer;
-
- languageOption = regQueryDwordValue("language", 1);
- if(languageOption < 0 || languageOption > 2)
- languageOption = 1;
-
- buffer = regQueryStringValue("languageName", "");
- if(!buffer.IsEmpty()) {
- languageName = buffer.Left(3);
- } else
- languageName = "";
-
- winSetLanguageOption(languageOption, true);
-
- frameSkip = regQueryDwordValue("frameSkip", 0);
- if(frameSkip < 0 || frameSkip > 9)
- frameSkip = 0;
-
- gbFrameSkip = regQueryDwordValue("gbFrameSkip", 0);
- if(gbFrameSkip < 0 || gbFrameSkip > 9)
- gbFrameSkip = 0;
-
- autoFrameSkip = regQueryDwordValue("autoFrameSkip", FALSE) ? TRUE : FALSE;
-
- vsync = regQueryDwordValue("vsync", false) ? true : false ;
- synchronize = regQueryDwordValue("synchronize", TRUE) ? true : false;
- fullScreenStretch = regQueryDwordValue("stretch", FALSE) ? true : false;
-
- videoOption = regQueryDwordValue("video", VIDEO_3X);
-
- if(videoOption < VIDEO_1X || videoOption > VIDEO_OTHER)
- videoOption = VIDEO_3X;
-
- bool defaultVideoDriver = regQueryDwordValue("defaultVideoDriver", true) ?
- true : false;
-
- if(!regQueryBinaryValue("videoDriverGUID", (char *)&videoDriverGUID,
- sizeof(GUID))) {
- defaultVideoDriver = TRUE;
- }
-
- if(defaultVideoDriver)
- pVideoDriverGUID = NULL;
- else
- pVideoDriverGUID = &videoDriverGUID;
-
- fsWidth = regQueryDwordValue("fsWidth", 0);
- fsHeight = regQueryDwordValue("fsHeight", 0);
- fsColorDepth = regQueryDwordValue("fsColorDepth", 0);
- fsFrequency = regQueryDwordValue("fsFrequency", 60);
- fsAdapter = regQueryDwordValue("fsAdapter", 0);
-
- if(videoOption == VIDEO_OTHER)
- {
- if(fsWidth < 0 || fsWidth > 4095 || fsHeight < 0 || fsHeight > 4095)
- videoOption = 0;
- if(fsColorDepth != 16 && fsColorDepth != 24 && fsColorDepth != 32)
- videoOption = 0;
- }
-
- renderMethod = (DISPLAY_TYPE)regQueryDwordValue("renderMethod", DIRECT_3D);
-
- if(renderMethod < GDI || renderMethod > OPENGL)
- renderMethod = DIRECT_3D;
-
- windowPositionX = regQueryDwordValue("windowX", 0);
- if(windowPositionX < 0)
- windowPositionX = 0;
- windowPositionY = regQueryDwordValue("windowY", 0);
- if(windowPositionY < 0)
- windowPositionY = 0;
-
- useBiosFile = regQueryDwordValue("useBios", 0) ? true: false;
-
- skipBiosFile = regQueryDwordValue("skipBios", 0) ? true : false;
-
- buffer = regQueryStringValue("biosFile", "");
-
- if(!buffer.IsEmpty()) {
- biosFileName = buffer;
- }
-
- int res = regQueryDwordValue("soundEnable", 0x30f);
-
- soundEnable(res);
- soundDisable(~res);
-
- soundOffFlag = (regQueryDwordValue("soundOff", 0)) ? true : false;
-
- soundQuality = regQueryDwordValue("soundQuality", 1);
-
- soundEcho = regQueryDwordValue("soundEcho", 0) ? true : false;
-
- soundLowPass = regQueryDwordValue("soundLowPass", 0) ? true : false;
-
- soundReverse = regQueryDwordValue("soundReverse", 0) ? true : false;
-
- soundVolume = regQueryDwordValue("soundVolume", 0);
- if(soundVolume < 0 || soundVolume > 5)
- soundVolume = 0;
-
- soundInterpolation = regQueryDwordValue("soundInterpolation", 0);
- if(soundInterpolation < 0 || soundInterpolation > 4)
- soundInterpolation = 0;
-
- ddrawEmulationOnly = regQueryDwordValue("ddrawEmulationOnly", false) ? true : false;
- ddrawUseVideoMemory = regQueryDwordValue("ddrawUseVideoMemory", false) ? true : false;
- tripleBuffering = regQueryDwordValue("tripleBuffering", true) ? true : false;
-
- d3dFilter = regQueryDwordValue("d3dFilter", 0);
- if(d3dFilter < 0 || d3dFilter > 1)
- d3dFilter = 0;
- glFilter = regQueryDwordValue("glFilter", 0);
- if(glFilter < 0 || glFilter > 1)
- glFilter = 0;
- glType = regQueryDwordValue("glType", 0);
- if(glType < 0 || glType > 1)
- glType = 0;
-
- filterType = regQueryDwordValue("filter", 0);
- if(filterType < 0 || filterType > 16)
- filterType = 0;
-
- disableMMX = regQueryDwordValue("disableMMX", 0) ? true: false;
-
- disableStatusMessage = regQueryDwordValue("disableStatus", 0) ? true : false;
-
- showSpeed = regQueryDwordValue("showSpeed", 0);
- if(showSpeed < 0 || showSpeed > 2)
- showSpeed = 0;
-
- showSpeedTransparent = regQueryDwordValue("showSpeedTransparent", TRUE) ?
- TRUE : FALSE;
-
- winGbPrinterEnabled = regQueryDwordValue("gbPrinter", false) ? true : false;
-
- if(winGbPrinterEnabled)
- gbSerialFunction = gbPrinterSend;
- else
- gbSerialFunction = NULL;
-
- pauseWhenInactive = regQueryDwordValue("pauseWhenInactive", 1) ?
- true : false;
-
- useOldSync = regQueryDwordValue("useOldSync", 0) ?
- TRUE : FALSE;
-
- captureFormat = regQueryDwordValue("captureFormat", 0);
-
- removeIntros = regQueryDwordValue("removeIntros", false) ? true : false;
-
- recentFreeze = regQueryDwordValue("recentFreeze", false) ? true : false;
-
- autoIPS = regQueryDwordValue("autoIPS", false) ? true : false;
-
- cpuDisableSfx = regQueryDwordValue("disableSfx", 0) ? true : false;
-
- winSaveType = regQueryDwordValue("saveType", 0);
- if(winSaveType < 0 || winSaveType > 5)
- winSaveType = 0;
-
- cpuEnhancedDetection = regQueryDwordValue("enhancedDetection", 1) ? true :
- false;
-
- ifbType = regQueryDwordValue("ifbType", 0);
- if(ifbType < 0 || ifbType > 2)
- ifbType = 0;
-
- winFlashSize = regQueryDwordValue("flashSize", 0x20000);
- if(winFlashSize != 0x10000 && winFlashSize != 0x20000)
- winFlashSize = 0x20000;
-
- agbPrintEnable(regQueryDwordValue("agbPrint", 0) ? true : false);
-
- winRtcEnable = regQueryDwordValue("rtcEnabled", 1) ? true : false;
- rtcEnable(winRtcEnable);
-
- autoHideMenu = regQueryDwordValue("autoHideMenu", 0) ? true : false;
-
- switch(videoOption) {
- case VIDEO_320x240:
- fsWidth = 320;
- fsHeight = 240;
- fsColorDepth = 16;
- fsFrequency = 60;
- break;
- case VIDEO_640x480:
- fsWidth = 640;
- fsHeight = 480;
- fsColorDepth = 16;
- fsFrequency = 60;
- break;
- case VIDEO_800x600:
- fsWidth = 800;
- fsHeight = 600;
- fsColorDepth = 16;
- fsFrequency = 60;
- break;
- case VIDEO_1024x768:
- fsWidth = 1024;
- fsHeight = 768;
- fsColorDepth = 16;
- fsFrequency = 60;
- break;
- case VIDEO_1280x1024:
- fsWidth = 1280;
- fsHeight = 1024;
- fsColorDepth = 16;
- fsFrequency = 60;
- break;
- }
-
- winGbBorderOn = regQueryDwordValue("borderOn", 0);
- gbBorderAutomatic = regQueryDwordValue("borderAutomatic", 0);
- gbEmulatorType = regQueryDwordValue("emulatorType", 4);
- if(gbEmulatorType < 0 || gbEmulatorType > 5)
- gbEmulatorType = 4;
- gbColorOption = regQueryDwordValue("colorOption", 0);
-
- threadPriority = regQueryDwordValue("priority", 2);
-
- if(threadPriority < 0 || threadPriority >3)
- threadPriority = 2;
- updatePriority();
-
- autoSaveLoadCheatList = regQueryDwordValue("autoSaveCheatList", 0) ?
- true : false;
-
- gbPaletteOption = regQueryDwordValue("gbPaletteOption", 0);
- if(gbPaletteOption < 0)
- gbPaletteOption = 0;
- if(gbPaletteOption > 2)
- gbPaletteOption = 2;
-
- regQueryBinaryValue("gbPalette", (char *)systemGbPalette,
- 24*sizeof(u16));
-
- rewindTimer = regQueryDwordValue("rewindTimer", 0);
-
- if(rewindTimer < 0 || rewindTimer > 600)
- rewindTimer = 0;
-
- rewindTimer *= 6; // convert to 10 frames multiple
-
- if(rewindTimer != 0)
- rewindMemory = (char *)malloc(8*REWIND_SIZE);
-
- for(int i = 0; i < 10; i++) {
- buffer.Format("recent%d", i);
- char *s = regQueryStringValue(buffer, NULL);
- if(s == NULL)
- break;
- recentFiles[i] = s;
- }
-
- joypadDefault = regQueryDwordValue("joypadDefault", 0);
- if(joypadDefault < 0 || joypadDefault > 3)
- joypadDefault = 0;
-
- autoLoadMostRecent = regQueryDwordValue("autoLoadMostRecent", false) ? true :
- false;
-
- cheatsEnabled = regQueryDwordValue("cheatsEnabled", true) ? true : false;
-
- fsMaxScale = regQueryDwordValue("fsMaxScale", 0);
-
- throttle = regQueryDwordValue("throttle", 0);
- if(throttle < 5 || throttle > 1000)
- throttle = 0;
-
- linktimeout = regQueryDwordValue("LinkTimeout", 1000);
-
- linklog = regQueryDwordValue("Linklog", false) ? true : false;
- if(linklog)
- openLinkLog();
-
- adapter = regQueryDwordValue("RFU", false) ? true : false;
-
- lanlink.active = regQueryDwordValue("LAN", 0) ? true : false;
-}
-
-void VBA::updateFrameSkip()
-{
- switch(cartridgeType) {
- case 0:
- systemFrameSkip = frameSkip;
- break;
- case 1:
- systemFrameSkip = gbFrameSkip;
- break;
- }
-}
-
-void VBA::updateVideoSize(UINT id)
-{
- int value = 0;
-
- switch(id) {
- case ID_OPTIONS_VIDEO_X1:
- value = VIDEO_1X;
- break;
- case ID_OPTIONS_VIDEO_X2:
- value = VIDEO_2X;
- break;
- case ID_OPTIONS_VIDEO_X3:
- value = VIDEO_3X;
- break;
- case ID_OPTIONS_VIDEO_X4:
- value = VIDEO_4X;
- break;
- case ID_OPTIONS_VIDEO_FULLSCREEN320X240:
- value = VIDEO_320x240;
- fsWidth = 320;
- fsHeight = 240;
- fsColorDepth = 16;
- break;
- case ID_OPTIONS_VIDEO_FULLSCREEN640X480:
- value = VIDEO_640x480;
- fsWidth = 640;
- fsHeight = 480;
- fsColorDepth = 16;
- break;
- case ID_OPTIONS_VIDEO_FULLSCREEN800X600:
- value = VIDEO_800x600;
- fsWidth = 800;
- fsHeight = 600;
- fsColorDepth = 16;
- break;
- case ID_OPTIONS_VIDEO_FULLSCREEN1024X768:
- value = VIDEO_1024x768;
- fsWidth = 1024;
- fsHeight = 768;
- fsColorDepth = 32;
- break;
- case ID_OPTIONS_VIDEO_FULLSCREEN1280X1024:
- value = VIDEO_1280x1024;
- fsWidth = 1280;
- fsHeight = 1024;
- fsColorDepth = 32;
- break;
- case ID_OPTIONS_VIDEO_FULLSCREEN:
- value = VIDEO_OTHER;
- break;
- }
-
- if(videoOption == value && value != VIDEO_OTHER)
- return;
-
- updateWindowSize(value);
-}
-
-typedef BOOL (WINAPI *GETMENUBARINFO)(HWND, LONG, LONG, PMENUBARINFO);
-
-static void winCheckMenuBarInfo(int& winSizeX, int& winSizeY)
-{
- HINSTANCE hinstDll;
- DWORD dwVersion = 0;
-
- hinstDll = LoadLibrary("USER32.DLL");
-
- if(hinstDll) {
- GETMENUBARINFO func = (GETMENUBARINFO)GetProcAddress(hinstDll,
- "GetMenuBarInfo");
-
- if(func) {
- MENUBARINFO info;
- info.cbSize = sizeof(info);
-
- func(AfxGetMainWnd()->GetSafeHwnd(), OBJID_MENU, 0, &info);
-
- int menuHeight = GetSystemMetrics(SM_CYMENU);
-
- if((info.rcBar.bottom - info.rcBar.top) > menuHeight) {
- winSizeY += (info.rcBar.bottom - info.rcBar.top) - menuHeight + 1;
- theApp.m_pMainWnd->SetWindowPos(
- 0, //HWND_TOPMOST,
- theApp.windowPositionX,
- theApp.windowPositionY,
- winSizeX,
- winSizeY,
- SWP_NOMOVE | SWP_SHOWWINDOW);
- }
- }
- FreeLibrary(hinstDll);
- }
-}
-
-void VBA::updateWindowSize(int value)
-{
- regSetDwordValue("video", value);
-
- if(value == VIDEO_OTHER) {
- regSetDwordValue("fsWidth", fsWidth);
- regSetDwordValue("fsHeight", fsHeight);
- regSetDwordValue("fsColorDepth", fsColorDepth);
- }
-
- if(((value >= VIDEO_320x240) &&
- (videoOption != value)) ||
- (videoOption >= VIDEO_320x240 &&
- value <= VIDEO_4X) ||
- fsForceChange) {
- fsForceChange = false;
- changingVideoSize = true;
- shutdownDisplay();
- if(input) {
- delete input;
- input = NULL;
- }
- m_pMainWnd->DragAcceptFiles(FALSE);
- CWnd *pWnd = m_pMainWnd;
- m_pMainWnd = NULL;
- pWnd->DestroyWindow();
- delete pWnd;
- videoOption = value;
- if(!initDisplay()) {
- if(videoOption == VIDEO_320x240 ||
- videoOption == VIDEO_640x480 ||
- videoOption == VIDEO_800x600 ||
- videoOption == VIDEO_1024x768 ||
- videoOption == VIDEO_1280x1024 ||
- videoOption == VIDEO_OTHER) {
- regSetDwordValue("video", VIDEO_1X);
- if(pVideoDriverGUID)
- regSetDwordValue("defaultVideoDriver", TRUE);
- }
- changingVideoSize = false;
- AfxPostQuitMessage(0);
- return;
- }
- if(!initInput()) {
- changingVideoSize = false;
- AfxPostQuitMessage(0);
- return;
- }
- input->checkKeys();
- updateMenuBar();
- changingVideoSize = FALSE;
- updateWindowSize(videoOption);
- return;
- }
-
- sizeX = 240;
- sizeY = 160;
-
- videoOption = value;
-
- if(cartridgeType == 1) {
- if(gbBorderOn) {
- sizeX = 256;
- sizeY = 224;
- gbBorderLineSkip = 256;
- gbBorderColumnSkip = 48;
- gbBorderRowSkip = 40;
- } else {
- sizeX = 160;
- sizeY = 144;
- gbBorderLineSkip = 160;
- gbBorderColumnSkip = 0;
- gbBorderRowSkip = 0;
- }
- }
-
- surfaceSizeX = sizeX;
- surfaceSizeY = sizeY;
-
- switch(videoOption) {
- case VIDEO_1X:
- surfaceSizeX = sizeX;
- surfaceSizeY = sizeY;
- break;
- case VIDEO_2X:
- surfaceSizeX = sizeX * 2;
- surfaceSizeY = sizeY * 2;
- break;
- case VIDEO_3X:
- surfaceSizeX = sizeX * 3;
- surfaceSizeY = sizeY * 3;
- break;
- case VIDEO_4X:
- surfaceSizeX = sizeX * 4;
- surfaceSizeY = sizeY * 4;
- break;
- case VIDEO_320x240:
- case VIDEO_640x480:
- case VIDEO_800x600:
- case VIDEO_1024x768:
- case VIDEO_1280x1024:
- case VIDEO_OTHER:
- {
- float scaleX = 1;
- float scaleY = 1;
- scaleX = ((float)fsWidth / sizeX);
- scaleY = ((float)fsHeight / sizeY);
- float min = scaleX < scaleY ? scaleX : scaleY;
- if(fsMaxScale)
- min = min > fsMaxScale ? fsMaxScale : min;
- surfaceSizeX = (int)(min * sizeX);
- surfaceSizeY = (int)(min * sizeY);
-
- if(fullScreenStretch)
- {
- surfaceSizeX = fsWidth;
- surfaceSizeY = fsHeight;
- }
- }
- break;
- }
-
- rect.right = sizeX;
- rect.bottom = sizeY;
-
- int winSizeX = sizeX;
- int winSizeY = sizeY;
-
- if(videoOption <= VIDEO_4X) {
- dest.left = 0;
- dest.top = 0;
- dest.right = surfaceSizeX;
- dest.bottom = surfaceSizeY;
-
- DWORD style = WS_POPUP | WS_VISIBLE;
-
- style |= WS_OVERLAPPEDWINDOW;
-
- menuToggle = TRUE;
- AdjustWindowRectEx(&dest, style, TRUE, 0); //WS_EX_TOPMOST);
-
- winSizeX = dest.right-dest.left;
- winSizeY = dest.bottom-dest.top;
-
- m_pMainWnd->SetWindowPos(0, //HWND_TOPMOST,
- windowPositionX,
- windowPositionY,
- winSizeX,
- winSizeY,
- SWP_NOMOVE | SWP_SHOWWINDOW);
-
- winCheckMenuBarInfo(winSizeX, winSizeY);
- }
-
- adjustDestRect();
-
- updateIFB();
- updateFilter();
-
- m_pMainWnd->RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
-}
-
-bool VBA::initDisplay()
-{
- return updateRenderMethod(false);
-}
-
-bool VBA::updateRenderMethod(bool force)
-{
- bool res = updateRenderMethod0(force);
-
- while(!res && renderMethod > 0) {
- if(renderMethod == OPENGL)
- renderMethod = DIRECT_3D;
- else if(renderMethod == DIRECT_3D)
- renderMethod = DIRECT_DRAW;
- else if(renderMethod == DIRECT_DRAW) {
- if(videoOption > VIDEO_4X) {
- videoOption = VIDEO_2X;
- force = true;
- } else
- renderMethod = GDI;
- }
-
- res = updateRenderMethod(force);
- }
- return res;
-}
-
-bool VBA::updateRenderMethod0(bool force)
-{
- bool initInput = false;
- b16to32Video = false;
-
- if(display) {
- if(display->getType() != renderMethod || force) {
- initInput = true;
- changingVideoSize = true;
- shutdownDisplay();
- if(input) {
- delete input;
- input = NULL;
- }
- CWnd *pWnd = m_pMainWnd;
-
- m_pMainWnd = NULL;
- pWnd->DragAcceptFiles(FALSE);
- pWnd->DestroyWindow();
- delete pWnd;
-
- display = NULL;
- regSetDwordValue("renderMethod", renderMethod);
- }
- }
- if(display == NULL) {
- switch(renderMethod) {
- case GDI:
- display = newGDIDisplay();
- break;
- case DIRECT_DRAW:
- display = newDirectDrawDisplay();
- break;
- case DIRECT_3D:
- display = newDirect3DDisplay();
- break;
- case OPENGL:
- display = newOpenGLDisplay();
- break;
- }
-
- if(display->initialize()) {
- if(initInput) {
- if(!this->initInput()) {
- changingVideoSize = false;
- AfxPostQuitMessage(0);
- return false;
- }
- input->checkKeys();
- updateMenuBar();
- changingVideoSize = false;
- updateWindowSize(videoOption);
-
- m_pMainWnd->ShowWindow(SW_SHOW);
- m_pMainWnd->UpdateWindow();
- m_pMainWnd->SetFocus();
-
- return true;
- } else {
- changingVideoSize = false;
- return true;
- }
- }
- changingVideoSize = false;
- }
- return true;
-}
-
-void VBA::winCheckFullscreen()
-{
- if(videoOption > VIDEO_4X && tripleBuffering) {
- if(display)
- display->checkFullScreen();
- }
-}
-
-void VBA::shutdownDisplay()
-{
- if(display != NULL) {
- display->cleanup();
- delete display;
- display = NULL;
- }
-}
-
-void VBA::directXMessage(const char *msg)
-{
- systemMessage(IDS_DIRECTX_7_REQUIRED,
- "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s",
- msg);
-}
-
-void VBA::updatePriority()
-{
- switch(threadPriority) {
- case 0:
- SetThreadPriority(THREAD_PRIORITY_HIGHEST);
- break;
- case 1:
- SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
- break;
- case 3:
- SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
- break;
- default:
- SetThreadPriority(THREAD_PRIORITY_NORMAL);
- }
-}
-
-#ifdef MMX
-bool VBA::detectMMX()
-{
- bool support = false;
- char brand[13];
-
- // check for Intel chip
- __try {
- __asm {
- mov eax, 0;
- cpuid;
- mov [dword ptr brand+0], ebx;
- mov [dword ptr brand+4], edx;
- mov [dword ptr brand+8], ecx;
- }
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- if(_exception_code() == STATUS_ILLEGAL_INSTRUCTION) {
- return false;
- }
- return false;
- }
- // Check for Intel or AMD CPUs
- if(strncmp(brand, "GenuineIntel", 12)) {
- if(strncmp(brand, "AuthenticAMD", 12)) {
- return false;
- }
- }
-
- __asm {
- mov eax, 1;
- cpuid;
- test edx, 00800000h;
- jz NotFound;
- mov [support], 1;
- NotFound:
- }
- return support;
-}
-#endif
-
-void VBA::winSetLanguageOption(int option, bool force)
-{
- if(((option == languageOption) && option != 2) && !force)
- return;
- switch(option) {
- case 0:
- {
- char lbuffer[10];
-
- if(GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SABBREVLANGNAME,
- lbuffer, 10)) {
- HINSTANCE l = winLoadLanguage(lbuffer);
- if(l == NULL) {
- LCID locIdBase = MAKELCID( MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANG_NEUTRAL ), SORT_DEFAULT );
- if(GetLocaleInfo(locIdBase, LOCALE_SABBREVLANGNAME,
- lbuffer, 10)) {
- l = winLoadLanguage(lbuffer);
- if(l == NULL) {
- systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
- "Failed to load library %s",
- lbuffer);
- return;
- }
- }
- }
- AfxSetResourceHandle(l);
- if(languageModule != NULL)
- FreeLibrary(languageModule);
- languageModule = l;
- } else {
- systemMessage(IDS_FAILED_TO_GET_LOCINFO,
- "Failed to get locale information");
- return;
- }
- }
- break;
- case 1:
- if(languageModule != NULL)
- FreeLibrary(languageModule);
- languageModule = NULL;
- AfxSetResourceHandle(AfxGetInstanceHandle());
- break;
- case 2:
- {
- if(!force) {
- LangSelect dlg;
- if(dlg.DoModal()) {
- HINSTANCE l = winLoadLanguage(languageName);
- if(l == NULL) {
- systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
- "Failed to load library %s",
- languageName);
- return;
- }
- AfxSetResourceHandle(l);
- if(languageModule != NULL)
- FreeLibrary(languageModule);
- languageModule = l;
- }
- } else {
- if(languageName.IsEmpty())
- return;
- HINSTANCE l = winLoadLanguage(languageName);
- if(l == NULL) {
- systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
- "Failed to load library %s",
- languageName);
- return;
- }
- AfxSetResourceHandle(l);
- if(languageModule != NULL)
- FreeLibrary(languageModule);
- languageModule = l;
- }
- }
- break;
- }
- languageOption = option;
- updateMenuBar();
-}
-
-HINSTANCE VBA::winLoadLanguage(const char *name)
-{
- CString buffer;
-
- buffer.Format("vba_%s.dll", name);
-
- HINSTANCE l = LoadLibrary(buffer);
-
- if(l == NULL) {
- if(strlen(name) == 3) {
- char buffer2[3];
- buffer2[0] = name[0];
- buffer2[1] = name[1];
- buffer2[2] = 0;
- buffer.Format("vba_%s.dll", buffer2);
-
- return LoadLibrary(buffer);
- }
- }
- return l;
-}
-
-
-bool VBA::initInput()
-{
- if(input)
- delete input;
- input = newDirectInput();
- if(input->initialize()) {
- input->loadSettings();
- input->checkKeys();
- return true;
- }
- delete input;
- return false;
-}
-
-void VBA::winAddUpdateListener(IUpdateListener *l)
-{
- updateList.AddTail(l);
- updateCount++;
-}
-
-void VBA::winRemoveUpdateListener(IUpdateListener *l)
-{
- POSITION pos = updateList.Find(l);
- if(pos) {
- updateList.RemoveAt(pos);
- updateCount--;
- if(updateCount < 0)
- updateCount = 0;
- }
-}
-
-CString VBA::winLoadFilter(UINT id)
-{
- CString res = winResLoadString(id);
- res.Replace('_','|');
-
- return res;
-}
-
-void VBA::movieReadNext()
-{
- if(movieFile) {
- bool movieEnd = false;
-
- if(fread(&moviePlayFrame, 1, sizeof(int), movieFile) == sizeof(int)) {
- if(fread(&movieNextJoypad, 1, sizeof(u32), movieFile) == sizeof(int)) {
- // make sure we don't have spurious entries on the movie that can
- // cause us to play it forever
- if(moviePlayFrame <= movieFrame)
- movieEnd = true;
- } else
- movieEnd = true;
- } else
- movieEnd = true;
- if(movieEnd) {
- CString string = winResLoadString(IDS_END_OF_MOVIE);
- systemScreenMessage(string);
- moviePlaying = false;
- fclose(movieFile);
- movieFile = NULL;
- return;
- }
- } else
- moviePlaying = false;
-}
-
-void VBA::saveSettings()
-{
- regSetDwordValue("language", languageOption);
-
- regSetStringValue("languageName", languageName);
-
- regSetDwordValue("frameSkip", frameSkip);
-
- regSetDwordValue("gbFrameSkip", gbFrameSkip);
-
- regSetDwordValue("autoFrameSkip", autoFrameSkip);
-
- regSetDwordValue("vsync", vsync);
- regSetDwordValue("synchronize", synchronize);
- regSetDwordValue("stretch", fullScreenStretch);
-
- regSetDwordValue("video", videoOption);
-
- regSetDwordValue("defaultVideoDriver", pVideoDriverGUID == NULL);
-
- if(pVideoDriverGUID) {
- regSetBinaryValue("videoDriverGUID", (char *)&videoDriverGUID,
- sizeof(GUID));
- }
-
-
- regSetDwordValue("fsWidth", fsWidth);
- regSetDwordValue("fsHeight", fsHeight);
- regSetDwordValue("fsColorDepth", fsColorDepth);
- regSetDwordValue("fsFrequency", fsFrequency);
- regSetDwordValue("fsAdapter", fsAdapter);
-
- regSetDwordValue("renderMethod", renderMethod);
-
- regSetDwordValue("windowX", windowPositionX);
- regSetDwordValue("windowY", windowPositionY);
-
- regSetDwordValue("useBios", useBiosFile);
-
- regSetDwordValue("skipBios", skipBiosFile);
-
- if(!biosFileName.IsEmpty())
- regSetStringValue("biosFile", biosFileName);
-
- regSetDwordValue("soundEnable", soundGetEnable() & 0x30f);
-
- regSetDwordValue("soundOff", soundOffFlag);
-
- regSetDwordValue("soundQuality", soundQuality);
-
- regSetDwordValue("soundEcho", soundEcho);
-
- regSetDwordValue("soundLowPass", soundLowPass);
-
- regSetDwordValue("soundReverse", soundReverse);
-
- regSetDwordValue("soundVolume", soundVolume);
-
- regSetDwordValue("soundInterpolation", soundInterpolation);
-
- regSetDwordValue("ddrawEmulationOnly", ddrawEmulationOnly);
- regSetDwordValue("ddrawUseVideoMemory", ddrawUseVideoMemory);
- regSetDwordValue("tripleBuffering", tripleBuffering);
-
- regSetDwordValue("d3dFilter", d3dFilter);
- regSetDwordValue("glFilter", glFilter);
- regSetDwordValue("glType", glType);
-
- regSetDwordValue("filter", filterType);
-
- regSetDwordValue("LCDFilter", filterLCD);
-
- regSetDwordValue("disableMMX", disableMMX);
-
- regSetDwordValue("disableStatus", disableStatusMessage);
-
- regSetDwordValue("showSpeed", showSpeed);
-
- regSetDwordValue("showSpeedTransparent", showSpeedTransparent);
-
- regSetDwordValue("gbPrinter", winGbPrinterEnabled);
-
- regSetDwordValue("pauseWhenInactive", pauseWhenInactive);
-
- regSetDwordValue("useOldSync", useOldSync);
-
- regSetDwordValue("captureFormat", captureFormat);
-
- regSetDwordValue("removeIntros", removeIntros);
-
- regSetDwordValue("recentFreeze", recentFreeze);
-
- regSetDwordValue("autoIPS", autoIPS);
-
- regSetDwordValue("disableSfx", cpuDisableSfx);
-
- regSetDwordValue("saveType", winSaveType);
-
- regSetDwordValue("enhancedDetection", cpuEnhancedDetection);
-
- regSetDwordValue("ifbType", ifbType);
-
- regSetDwordValue("flashSize", winFlashSize);
-
- regSetDwordValue("agbPrint", agbPrintIsEnabled());
-
- regSetDwordValue("rtcEnabled", winRtcEnable);
-
- regSetDwordValue("autoHideMenu", autoHideMenu);
-
- regSetDwordValue("borderOn", winGbBorderOn);
- regSetDwordValue("borderAutomatic", gbBorderAutomatic);
- regSetDwordValue("emulatorType", gbEmulatorType);
- regSetDwordValue("colorOption", gbColorOption);
-
- regSetDwordValue("priority", threadPriority);
-
- regSetDwordValue("autoSaveCheatList", autoSaveLoadCheatList);
-
- regSetDwordValue("gbPaletteOption", gbPaletteOption);
-
- regSetBinaryValue("gbPalette", (char *)systemGbPalette,
- 24*sizeof(u16));
-
- regSetDwordValue("rewindTimer", rewindTimer/6);
-
- CString buffer;
- for(int i = 0; i < 10; i++) {
- buffer.Format("recent%d", i);
- regSetStringValue(buffer, recentFiles[i]);
- }
-
- regSetDwordValue("joypadDefault", joypadDefault);
- regSetDwordValue("autoLoadMostRecent", autoLoadMostRecent);
- regSetDwordValue("cheatsEnabled", cheatsEnabled);
- regSetDwordValue("fsMaxScale", fsMaxScale);
- regSetDwordValue("throttle", throttle);
-
-
- regSetDwordValue("LinkTimeout", linktimeout);
- regSetDwordValue("Linklog", linklog);
- regSetDwordValue("RFU", adapter);
-}
-
-void winSignal(int, int)
-{
-}
-
-#define CPUReadByteQuick(addr) \
- map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
-
-void winOutput(char *s, u32 addr)
-{
- if(s) {
- toolsLog(s);
- } else {
- CString str;
- char c;
-
- c = CPUReadByteQuick(addr);
- addr++;
- while(c) {
- str += c;
- c = CPUReadByteQuick(addr);
- addr++;
- }
- toolsLog(str);
- }
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// VBA.cpp : Defines the class behaviors for the application.
+//
+#include "stdafx.h"
+
+#include "AVIWrite.h"
+#include "LangSelect.h"
+#include "MainWnd.h"
+#include "Reg.h"
+#include "resource.h"
+#include "resource2.h"
+#include "skin.h"
+#include "WavWriter.h"
+#include "WinResUtil.h"
+
+#include "../System.h"
+#include "../agbprint.h"
+#include "../cheatSearch.h"
+#include "../GBA.h"
+#include "../Globals.h"
+#include "../RTC.h"
+#include "../Sound.h"
+#include "../Util.h"
+#include "../gb/gbGlobals.h"
+#include "../gb/gbPrinter.h"
+
+/* Link
+---------------------*/
+#include "../Link.h"
+/* ---------------- */
+
+#include "../gbafilter.h"
+
+#ifdef SDL
+#pragma comment( lib, "SDL" )
+#pragma comment( lib, "SDLmain" )
+#endif
+
+extern void Pixelate(u8*,u32,u8*,u8*,u32,int,int);
+extern void Pixelate32(u8*,u32,u8*,u8*,u32,int,int);
+extern void MotionBlur(u8*,u32,u8*,u8*,u32,int,int);
+extern void MotionBlur32(u8*,u32,u8*,u8*,u32,int,int);
+extern void _2xSaI(u8*,u32,u8*,u8*,u32,int,int);
+extern void _2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
+extern void Super2xSaI(u8*,u32,u8*,u8*,u32,int,int);
+extern void Super2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
+extern void SuperEagle(u8*,u32,u8*,u8*,u32,int,int);
+extern void SuperEagle32(u8*,u32,u8*,u8*,u32,int,int);
+extern void AdMame2x(u8*,u32,u8*,u8*,u32,int,int);
+extern void AdMame2x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void Bilinear(u8*,u32,u8*,u8*,u32,int,int);
+extern void Bilinear32(u8*,u32,u8*,u8*,u32,int,int);
+extern void BilinearPlus(u8*,u32,u8*,u8*,u32,int,int);
+extern void BilinearPlus32(u8*,u32,u8*,u8*,u32,int,int);
+extern void Scanlines(u8*,u32,u8*,u8*,u32,int,int);
+extern void Scanlines32(u8*,u32,u8*,u8*,u32,int,int);
+extern void ScanlinesTV(u8*,u32,u8*,u8*,u32,int,int);
+extern void ScanlinesTV32(u8*,u32,u8*,u8*,u32,int,int);
+extern void hq2x(u8*,u32,u8*,u8*,u32,int,int);
+extern void hq2x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void lq2x(u8*,u32,u8*,u8*,u32,int,int);
+extern void lq2x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void Simple2x16(u8*,u32,u8*,u8*,u32,int,int);
+extern void Simple2x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void Simple3x16(u8*,u32,u8*,u8*,u32,int,int);
+extern void Simple3x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void Simple4x16(u8*,u32,u8*,u8*,u32,int,int);
+extern void Simple4x32(u8*,u32,u8*,u8*,u32,int,int);
+
+extern void hq3x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void hq3x16(u8*,u32,u8*,u8*,u32,int,int);
+extern void hq4x32(u8*,u32,u8*,u8*,u32,int,int);
+extern void hq4x16(u8*,u32,u8*,u8*,u32,int,int);
+
+extern void SmartIB(u8*,u32,int,int);
+extern void SmartIB32(u8*,u32,int,int);
+extern void MotionBlurIB(u8*,u32,int,int);
+extern void InterlaceIB(u8*,u32,int,int);
+extern void MotionBlurIB32(u8*,u32,int,int);
+
+extern void toolsLog(const char *);
+
+extern IDisplay *newGDIDisplay();
+extern IDisplay *newDirectDrawDisplay();
+extern IDisplay *newDirect3DDisplay();
+extern IDisplay *newOpenGLDisplay();
+
+extern Input *newDirectInput();
+
+extern ISound *newDirectSound();
+
+extern void remoteStubSignal(int, int);
+extern void remoteOutput(char *, u32);
+extern void remoteStubMain();
+extern void remoteSetProtocol(int);
+extern void remoteCleanUp();
+extern int remoteSocket;
+
+extern void InterframeCleanup();
+
+void winlog(const char *msg, ...);
+
+/* Link
+---------------------*/
+extern int InitLink(void);
+extern void CloseLink(void);
+//extern int linkid;
+extern char inifile[];
+extern FILE *linklogfile;
+/* ------------------- */
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+int emulating = 0;
+bool debugger = false;
+int RGB_LOW_BITS_MASK = 0;
+bool b16to32Video = false;
+int systemFrameSkip = 0;
+int systemSpeed = 0;
+bool systemSoundOn = false;
+u32 systemColorMap32[0x10000];
+u16 systemColorMap16[0x10000];
+u16 systemGbPalette[24];
+int systemRedShift = 0;
+int systemBlueShift = 0;
+int systemGreenShift = 0;
+int systemColorDepth = 16;
+int systemVerbose = 0;
+int systemDebug = 0;
+int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+bool soundBufferLow = 0;
+void winSignal(int,int);
+void winOutput(char *, u32);
+
+void (*dbgSignal)(int,int) = winSignal;
+void (*dbgOutput)(char *, u32) = winOutput;
+
+#ifdef MMX
+extern "C" bool cpu_mmx;
+#endif
+
+namespace Sm60FPS
+{
+ float K_fCpuSpeed = 98.0f;
+ float K_fTargetFps = 60.0f * K_fCpuSpeed / 100;
+ float K_fDT = 1000.0f / K_fTargetFps;
+
+ u32 dwTimeElapse;
+ u32 dwTime0;
+ u32 dwTime1;
+ u32 nFrameCnt;
+ float fWantFPS;
+ float fCurFPS;
+ bool bLastSkip;
+ int nCurSpeed;
+ int bSaveMoreCPU;
+};
+
+void directXMessage(const char *msg)
+{
+ systemMessage(IDS_DIRECTX_7_REQUIRED,
+ "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s",
+ msg);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// VBA
+
+BEGIN_MESSAGE_MAP(VBA, CWinApp)
+ //{{AFX_MSG_MAP(VBA)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG_MAP
+ END_MESSAGE_MAP()
+
+ /////////////////////////////////////////////////////////////////////////////
+// VBA construction
+
+VBA::VBA()
+{
+ mode320Available = false;
+ mode640Available = false;
+ mode800Available = false;
+ mode1024Available = false;
+ mode1280Available = false;
+ windowPositionX = 0;
+ windowPositionY = 0;
+ filterFunction = NULL;
+ ifbFunction = NULL;
+ ifbType = 0;
+ filterType = FILTER_NONE;
+ filterWidth = 0;
+ filterHeight = 0;
+ fsAdapter = 0;
+ fsWidth = 0;
+ fsHeight = 0;
+ fsColorDepth = 0;
+ fsFrequency = 0;
+ fsForceChange = false;
+ surfaceSizeX = 0;
+ surfaceSizeY = 0;
+ sizeX = 0;
+ sizeY = 0;
+ videoOption = 0;
+ fullScreenStretch = false;
+ disableStatusMessage = false;
+ showSpeed = 0;
+ showSpeedTransparent = true;
+ showRenderedFrames = 0;
+ screenMessage = false;
+ screenMessageTime = 0;
+ menuToggle = true;
+ display = NULL;
+ menu = NULL;
+ popup = NULL;
+ cartridgeType = IMAGE_GBA;
+ soundInitialized = false;
+ useBiosFile = false;
+ skipBiosFile = false;
+ active = true;
+ paused = false;
+ recentFreeze = false;
+ autoSaveLoadCheatList = false;
+ winout = NULL;
+ removeIntros = false;
+ autoIPS = true;
+ winGbBorderOn = 0;
+ winFlashSize = 0x20000;
+ winRtcEnable = false;
+ winGenericflashcardEnable = false;
+ winSaveType = 0;
+ rewindMemory = NULL;
+ rewindPos = 0;
+ rewindTopPos = 0;
+ rewindCounter = 0;
+ rewindCount = 0;
+ rewindSaveNeeded = false;
+ rewindTimer = 0;
+ captureFormat = 0;
+ tripleBuffering = true;
+ autoHideMenu = false;
+ throttle = 0;
+ throttleLastTime = 0;
+ autoFrameSkipLastTime = 0;
+ autoFrameSkip = false;
+ vsync = false;
+ changingVideoSize = false;
+ pVideoDriverGUID = NULL;
+ renderMethod = DIRECT_DRAW;
+ iconic = false;
+ ddrawEmulationOnly = false;
+ ddrawUsingEmulationOnly = false;
+ ddrawDebug = false;
+ ddrawUseVideoMemory = false;
+ d3dFilter = 0;
+ glFilter = 0;
+ glType = 0;
+ skin = NULL;
+ skinName = "";
+ skinEnabled = false;
+ skinButtons = 0;
+ regEnabled = false;
+ pauseWhenInactive = true;
+ speedupToggle = false;
+ useOldSync = false;
+ winGbPrinterEnabled = false;
+ threadPriority = 2;
+ disableMMX = false;
+ languageOption = 0;
+ languageModule = NULL;
+ languageName = "";
+ renderedFrames = 0;
+ input = NULL;
+ joypadDefault = 0;
+ autoFire = 0;
+ autoFireToggle = false;
+ winPauseNextFrame = false;
+ soundRecording = false;
+ soundRecorder = NULL;
+ dsoundDisableHardwareAcceleration = true;
+ sound = NULL;
+ aviRecording = false;
+ aviRecorder = NULL;
+ aviFrameNumber = 0;
+ painting = false;
+ movieRecording = false;
+ moviePlaying = false;
+ movieFrame = 0;
+ moviePlayFrame = 0;
+ movieFile = NULL;
+ movieLastJoypad = 0;
+ movieNextJoypad = 0;
+ sensorX = 2047;
+ sensorY = 2047;
+ mouseCounter = 0;
+ wasPaused = false;
+ frameskipadjust = 0;
+ autoLoadMostRecent = false;
+ fsMaxScale = 0;
+ romSize = 0;
+
+ updateCount = 0;
+
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+
+ ZeroMemory(&emulator, sizeof(emulator));
+
+ hAccel = NULL;
+
+ for(int i = 0; i < 24;) {
+ systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
+ systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
+ systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
+ systemGbPalette[i++] = 0;
+ }
+}
+
+VBA::~VBA()
+{
+ InterframeCleanup();
+
+ char winBuffer[2048];
+
+ GetModuleFileName(NULL, winBuffer, 2048);
+ char *p = strrchr(winBuffer, '\\');
+ if(p)
+ *p = 0;
+
+ regInit(winBuffer);
+
+ saveSettings();
+
+ if(moviePlaying) {
+ if(movieFile != NULL) {
+ fclose(movieFile);
+ movieFile = NULL;
+ }
+ moviePlaying = false;
+ movieLastJoypad = 0;
+ }
+
+ if(movieRecording) {
+ if(movieFile != NULL) {
+ // record the last joypad change so that the correct time can be
+ // recorded
+ fwrite(&movieFrame, 1, sizeof(int), movieFile);
+ fwrite(&movieLastJoypad, 1, sizeof(u32), movieFile);
+ fclose(movieFile);
+ movieFile = NULL;
+ }
+ movieRecording = false;
+ moviePlaying = false;
+ movieLastJoypad = 0;
+ }
+
+ if(aviRecorder) {
+ delete aviRecorder;
+ aviRecording = false;
+ }
+
+ if(soundRecorder) {
+ delete soundRecorder;
+ soundRecorder = NULL;
+ }
+ soundRecording = false;
+ soundPause();
+ soundShutdown();
+
+ if(gbRom != NULL || rom != NULL) {
+ if(autoSaveLoadCheatList)
+ ((MainWnd *)m_pMainWnd)->winSaveCheatListDefault();
+ ((MainWnd *)m_pMainWnd)->writeBatteryFile();
+ cheatSearchCleanup(&cheatSearchData);
+ emulator.emuCleanUp();
+ }
+
+ if(input)
+ delete input;
+
+ shutdownDisplay();
+
+ if(skin) {
+ delete skin;
+ }
+
+ if(rewindMemory)
+ free(rewindMemory);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only VBA object
+
+VBA theApp;
+/////////////////////////////////////////////////////////////////////////////
+// VBA initialization
+
+// code from SDL_main.c for Windows
+/* Parse a command line buffer into arguments */
+static int parseCommandLine(char *cmdline, char **argv)
+{
+ char *bufp;
+ int argc;
+
+ argc = 0;
+ for ( bufp = cmdline; *bufp; ) {
+ /* Skip leading whitespace */
+ while ( isspace(*bufp) ) {
+ ++bufp;
+ }
+ /* Skip over argument */
+ if ( *bufp == '"' ) {
+ ++bufp;
+ if ( *bufp ) {
+ if ( argv ) {
+ argv[argc] = bufp;
+ }
+ ++argc;
+ }
+ /* Skip over word */
+ while ( *bufp && (*bufp != '"') ) {
+ ++bufp;
+ }
+ } else {
+ if ( *bufp ) {
+ if ( argv ) {
+ argv[argc] = bufp;
+ }
+ ++argc;
+ }
+ /* Skip over word */
+ while ( *bufp && ! isspace(*bufp) ) {
+ ++bufp;
+ }
+ }
+ if ( *bufp ) {
+ if ( argv ) {
+ *bufp = '\0';
+ }
+ ++bufp;
+ }
+ }
+ if ( argv ) {
+ argv[argc] = NULL;
+ }
+ return(argc);
+}
+
+BOOL VBA::InitInstance()
+{
+#if _MSC_VER < 1400
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+#endif
+
+ SetRegistryKey(_T("VBA"));
+
+ remoteSetProtocol(0);
+
+ systemVerbose = GetPrivateProfileInt("config",
+ "verbose",
+ 0,
+ "VBA.ini");
+
+ systemDebug = GetPrivateProfileInt("config",
+ "debug",
+ 0,
+ "VBA.ini");
+ ddrawDebug = GetPrivateProfileInt("config",
+ "ddrawDebug",
+ 0,
+ "VBA.ini") ? true : false;
+
+ wndClass = AfxRegisterWndClass(0, LoadCursor(IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(IDI_ICON));
+
+ char winBuffer[2048];
+
+ GetModuleFileName(NULL, winBuffer, 2048);
+ char *p = strrchr(winBuffer, '\\');
+ if(p)
+ *p = 0;
+
+ if(!InitLink())
+ return FALSE;;
+
+ regInit(winBuffer);
+
+ loadSettings();
+
+ if(!openLinkLog())
+ return FALSE;
+
+ if(!initInput())
+ return FALSE;
+
+ if(!initDisplay()) {
+ if(videoOption >= VIDEO_320x240) {
+ regSetDwordValue("video", VIDEO_1X);
+ if(pVideoDriverGUID)
+ regSetDwordValue("defaultVideoDriver", TRUE);
+ }
+ return FALSE;
+ }
+
+ hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));
+
+ winAccelMgr.Connect((MainWnd *)m_pMainWnd);
+
+ winAccelMgr.SetRegKey(HKEY_CURRENT_USER, "Software\\Emulators\\VisualBoyAdvance");
+
+ extern void winAccelAddCommands(CAcceleratorManager&);
+
+ winAccelAddCommands(winAccelMgr);
+
+ winAccelMgr.CreateDefaultTable();
+
+ winAccelMgr.Load();
+
+ winAccelMgr.UpdateWndTable();
+
+ winAccelMgr.UpdateMenu(menu);
+
+ if (m_lpCmdLine[0])
+ {
+ int argc = parseCommandLine(m_lpCmdLine, NULL);
+ char **argv = (char **)malloc((argc+1)*sizeof(char *));
+ parseCommandLine(m_lpCmdLine, argv);
+ if(argc > 0) {
+ szFile = argv[0];
+ filename = szFile;
+ }
+ int index = filename.ReverseFind('.');
+
+ if(index != -1)
+ filename = filename.Left(index);
+
+ if(((MainWnd*)m_pMainWnd)->FileRun())
+ emulating = true;
+ else
+ emulating = false;
+ free(argv);
+ }
+
+ return TRUE;
+}
+
+void VBA::adjustDestRect()
+{
+ POINT point;
+ RECT skinRect;
+ if(skin)
+ skinRect = skin->GetBlitRect();
+
+ point.x = 0;
+ point.y = 0;
+
+ if(skin) {
+ point.x = skinRect.left;
+ point.y = skinRect.top;
+ }
+
+ m_pMainWnd->ClientToScreen(&point);
+ dest.top = point.y;
+ dest.left = point.x;
+
+ point.x = surfaceSizeX;
+ point.y = surfaceSizeY;
+
+ if(skin) {
+ point.x = skinRect.right;
+ point.y = skinRect.bottom;
+ }
+
+ m_pMainWnd->ClientToScreen(&point);
+ dest.bottom = point.y;
+ dest.right = point.x;
+
+ // make sure that dest rect lies in the monitor
+ if(videoOption >= VIDEO_320x240) {
+ dest.top -= windowPositionY;
+ dest.left -= windowPositionX;
+ dest.bottom-= windowPositionY;
+ dest.right -= windowPositionX;
+ }
+
+ if(skin)
+ return;
+
+ int menuSkip = 0;
+
+ if(videoOption >= VIDEO_320x240 && menuToggle) {
+ int m = GetSystemMetrics(SM_CYMENU);
+ menuSkip = m;
+ dest.bottom -=m;
+ }
+
+ if(videoOption > VIDEO_4X) {
+ int top = (fsHeight - surfaceSizeY) / 2;
+ int left = (fsWidth - surfaceSizeX) / 2;
+ dest.top += top;
+ dest.bottom += top;
+ dest.left += left;
+ dest.right += left;
+ if(fullScreenStretch) {
+ dest.top = 0+menuSkip;
+ dest.left = 0;
+ dest.right = fsWidth;
+ dest.bottom = fsHeight;
+ }
+ }
+}
+
+
+void VBA::updateIFB()
+{
+ if(systemColorDepth == 16) {
+ switch(ifbType) {
+ case 0:
+ default:
+ ifbFunction = NULL;
+ break;
+ case 1:
+ ifbFunction = MotionBlurIB;
+ break;
+ case 2:
+ ifbFunction = SmartIB;
+ break;
+ }
+ } else if(systemColorDepth == 32) {
+ switch(ifbType) {
+ case 0:
+ default:
+ ifbFunction = NULL;
+ break;
+ case 1:
+ ifbFunction = MotionBlurIB32;
+ break;
+ case 2:
+ ifbFunction = SmartIB32;
+ break;
+ }
+ } else
+ ifbFunction = NULL;
+}
+
+void VBA::updateFilter()
+{
+ // BEGIN hacky ugly code
+
+ // HQ3X asm wants 16 bit input. When we switch
+ // away from 16 bits we need to restore the driver values
+
+ if ( b16to32Video )
+ {
+ b16to32Video = false;
+ systemColorDepth = 32;
+ systemRedShift = 19;
+ systemGreenShift = 11;
+ systemBlueShift = 3;
+ utilUpdateSystemColorMaps();
+ }
+ // END hacky ugly code
+
+ filterWidth = sizeX;
+ filterHeight = sizeY;
+ filterMagnification = 1;
+
+
+ if ( videoOption == VIDEO_1X || videoOption == VIDEO_320x240 )
+ {
+ filterFunction = NULL;
+ filterMagnification = 1;
+ }
+ else
+ {
+ if ( systemColorDepth == 16 )
+ {
+ switch(filterType)
+ {
+ default:
+ case FILTER_NONE:
+ filterFunction = NULL;
+ filterMagnification = 1;
+ break;
+ case FILTER_TVMODE:
+ filterFunction = ScanlinesTV;
+ filterMagnification = 2;
+ break;
+ case FILTER_2XSAI:
+ filterFunction = _2xSaI;
+ filterMagnification = 2;
+ break;
+ case FILTER_SUPER2XSAI:
+ filterFunction = Super2xSaI;
+ filterMagnification = 2;
+ break;
+ case FILTER_SUPEREAGLE:
+ filterFunction = SuperEagle;
+ filterMagnification = 2;
+ break;
+ case FILTER_PIXELATE:
+ filterFunction = Pixelate;
+ filterMagnification = 2;
+ break;
+ case FILTER_MAMESCALE2X:
+ filterFunction = AdMame2x;
+ filterMagnification = 2;
+ break;
+ case FILTER_SIMPLE2X:
+ filterFunction = Simple2x16;
+ filterMagnification = 2;
+ break;
+ case FILTER_BILINEAR:
+ filterFunction = Bilinear;
+ filterMagnification = 2;
+ break;
+ case FILTER_BILINEARPLUS:
+ filterFunction = BilinearPlus;
+ filterMagnification = 2;
+ break;
+ case FILTER_SCANLINES:
+ filterFunction = Scanlines;
+ filterMagnification = 2;
+ break;
+ case FILTER_HQ2X:
+ filterFunction = hq2x;
+ filterMagnification = 2;
+ break;
+ case FILTER_LQ2X:
+ filterFunction = lq2x;
+ filterMagnification = 2;
+ break;
+ case FILTER_SIMPLE3X:
+ filterFunction = Simple3x16;
+ filterMagnification = 3;
+ break;
+ case FILTER_SIMPLE4X:
+ filterFunction = Simple4x16;
+ filterMagnification = 4;
+ break;
+ case FILTER_HQ3X:
+ filterFunction = hq3x16;
+ filterMagnification = 3;
+ break;
+ case FILTER_HQ4X:
+ filterFunction = hq4x16;
+ filterMagnification = 4;
+ break;
+ }
+ }
+
+ if ( systemColorDepth == 32 )
+ {
+ switch(filterType)
+ {
+ default:
+ case FILTER_NONE:
+ filterFunction = NULL;
+ filterMagnification = 1;
+ break;
+ case FILTER_TVMODE:
+ filterFunction = ScanlinesTV32;
+ filterMagnification = 2;
+ break;
+ case FILTER_2XSAI:
+ filterFunction = _2xSaI32;
+ filterMagnification = 2;
+ break;
+ case FILTER_SUPER2XSAI:
+ filterFunction = Super2xSaI32;
+ filterMagnification = 2;
+ break;
+ case FILTER_SUPEREAGLE:
+ filterFunction = SuperEagle32;
+ filterMagnification = 2;
+ break;
+ case FILTER_PIXELATE:
+ filterFunction = Pixelate32;
+ filterMagnification = 2;
+ break;
+ case FILTER_MAMESCALE2X:
+ filterFunction = AdMame2x32;
+ filterMagnification = 2;
+ break;
+ case FILTER_SIMPLE2X:
+ filterFunction = Simple2x32;
+ filterMagnification = 2;
+ break;
+ case FILTER_BILINEAR:
+ filterFunction = Bilinear32;
+ filterMagnification = 2;
+ break;
+ case FILTER_BILINEARPLUS:
+ filterFunction = BilinearPlus32;
+ filterMagnification = 2;
+ break;
+ case FILTER_SCANLINES:
+ filterFunction = Scanlines32;
+ filterMagnification = 2;
+ break;
+ case FILTER_HQ2X:
+ filterFunction = hq2x32;
+ filterMagnification = 2;
+ break;
+ case FILTER_LQ2X:
+ filterFunction = lq2x32;
+ filterMagnification = 2;
+ break;
+ case FILTER_SIMPLE3X:
+ filterFunction = Simple3x32;
+ filterMagnification = 3;
+ break;
+ case FILTER_SIMPLE4X:
+ filterFunction = Simple4x32;
+ filterMagnification = 4;
+ break;
+ case FILTER_HQ3X:
+ filterFunction = hq3x32;
+ filterMagnification = 3;
+ b16to32Video=true;
+ break;
+ case FILTER_HQ4X:
+ filterFunction = hq4x32;
+ filterMagnification = 4;
+ b16to32Video=true;
+ break;
+ }
+ }
+ }
+
+ rect.right = sizeX * filterMagnification;
+ rect.bottom = sizeY * filterMagnification;
+
+ if( filterType != FILTER_NONE )
+ memset(delta, 0xFF, sizeof(delta));
+
+ if( display )
+ display->changeRenderSize(rect.right, rect.bottom);
+
+ if (b16to32Video)
+ {
+ systemColorDepth = 16;
+ systemRedShift = 11;
+ systemGreenShift = 6;
+ systemBlueShift = 0;
+ utilUpdateSystemColorMaps();
+ }
+}
+
+
+void VBA::updateMenuBar()
+{
+ if(menu != NULL) {
+ if(m_pMainWnd)
+ m_pMainWnd->SetMenu(NULL);
+ m_menu.Detach();
+ DestroyMenu(menu);
+ }
+
+ if(popup != NULL) {
+ // force popup recreation if language changed
+ DestroyMenu(popup);
+ popup = NULL;
+ }
+
+ m_menu.Attach(winResLoadMenu(MAKEINTRESOURCE(IDR_MENU)));
+ menu = (HMENU)m_menu;
+
+ // don't set a menu if skin is active
+ if(skin == NULL)
+ if(m_pMainWnd)
+ m_pMainWnd->SetMenu(&m_menu);
+}
+
+void winlog(const char *msg, ...)
+{
+ CString buffer;
+ va_list valist;
+
+ va_start(valist, msg);
+ buffer.FormatV(msg, valist);
+
+ if(theApp.winout == NULL) {
+ theApp.winout = fopen("vba-trace.log","w");
+ }
+
+ fputs(buffer, theApp.winout);
+
+ va_end(valist);
+}
+
+void log(const char *msg, ...)
+{
+ CString buffer;
+ va_list valist;
+
+ va_start(valist, msg);
+ buffer.FormatV(msg, valist);
+
+ toolsLog(buffer);
+
+ va_end(valist);
+}
+
+bool systemReadJoypads()
+{
+ if(theApp.input)
+ return theApp.input->readDevices();
+ return false;
+}
+
+u32 systemReadJoypad(int which)
+{
+ if(theApp.input)
+ return theApp.input->readDevice(which);
+ return 0;
+}
+
+void systemDrawScreen()
+{
+ if(theApp.display == NULL)
+ return;
+
+ theApp.renderedFrames++;
+
+ if(theApp.updateCount) {
+ POSITION pos = theApp.updateList.GetHeadPosition();
+ while(pos) {
+ IUpdateListener *up = theApp.updateList.GetNext(pos);
+ up->update();
+ }
+ }
+
+ if (Sm60FPS_CanSkipFrame())
+ return;
+
+ if(theApp.aviRecording && !theApp.painting) {
+ int width = 240;
+ int height = 160;
+ switch(theApp.cartridgeType) {
+ case 0:
+ width = 240;
+ height = 160;
+ break;
+ case 1:
+ if(gbBorderOn) {
+ width = 256;
+ height = 224;
+ } else {
+ width = 160;
+ height = 144;
+ }
+ break;
+ }
+
+ if(theApp.aviRecorder == NULL) {
+ theApp.aviRecorder = new AVIWrite();
+ theApp.aviFrameNumber = 0;
+
+ theApp.aviRecorder->SetFPS(60);
+
+ BITMAPINFOHEADER bi;
+ memset(&bi, 0, sizeof(bi));
+ bi.biSize = 0x28;
+ bi.biPlanes = 1;
+ bi.biBitCount = 24;
+ bi.biWidth = width;
+ bi.biHeight = height;
+ bi.biSizeImage = 3*width*height;
+ theApp.aviRecorder->SetVideoFormat(&bi);
+ theApp.aviRecorder->Open(theApp.aviRecordName);
+ }
+
+ char *bmp = new char[width*height*3];
+
+ utilWriteBMP(bmp, width, height, pix);
+ theApp.aviRecorder->AddFrame(theApp.aviFrameNumber, bmp);
+
+ delete bmp;
+ }
+
+ if( theApp.ifbFunction ) {
+ theApp.ifbFunction( pix + (theApp.filterWidth * (systemColorDepth>>3)) + 4,
+ (theApp.filterWidth * (systemColorDepth>>3)) + 4,
+ theApp.filterWidth, theApp.filterHeight );
+ }
+
+ if(!soundBufferLow)
+ theApp.display->render();
+ else
+ soundBufferLow = false;
+
+ Sm60FPS_Sleep();
+}
+
+void systemScreenCapture(int captureNumber)
+{
+ if(theApp.m_pMainWnd)
+ ((MainWnd *)theApp.m_pMainWnd)->screenCapture(captureNumber);
+}
+
+u32 systemGetClock()
+{
+ return GetTickCount();
+}
+
+void systemMessage(int number, const char *defaultMsg, ...)
+{
+ CString buffer;
+ va_list valist;
+ CString msg = defaultMsg;
+ if(number)
+ msg = winResLoadString(number);
+
+ va_start(valist, defaultMsg);
+ buffer.FormatV(msg, valist);
+
+ theApp.winCheckFullscreen();
+
+ AfxGetApp()->m_pMainWnd->MessageBox(buffer, winResLoadString(IDS_ERROR), MB_OK|MB_ICONERROR);
+
+ va_end(valist);
+}
+
+void systemSetTitle(const char *title)
+{
+ if(theApp.m_pMainWnd != NULL) {
+ AfxGetApp()->m_pMainWnd->SetWindowText(title);
+ }
+}
+
+void systemShowSpeed(int speed)
+{
+ systemSpeed = speed;
+ theApp.showRenderedFrames = theApp.renderedFrames;
+ theApp.renderedFrames = 0;
+ if(theApp.videoOption <= VIDEO_4X && theApp.showSpeed) {
+ CString buffer;
+ if(theApp.showSpeed == 1)
+ buffer.Format("VisualBoyAdvance-%3d%%", systemSpeed);
+ else
+ buffer.Format("VisualBoyAdvance-%3d%%(%d, %d fps)", systemSpeed,
+ systemFrameSkip,
+ theApp.showRenderedFrames);
+
+ systemSetTitle(buffer);
+ }
+}
+
+void systemFrame()
+{
+ if(theApp.aviRecording)
+ theApp.aviFrameNumber++;
+ if(theApp.movieRecording || theApp.moviePlaying)
+ theApp.movieFrame++;
+}
+
+void system10Frames(int rate)
+{
+ u32 time = systemGetClock();
+
+ if (theApp.autoFrameSkip)
+ {
+ u32 diff = time - theApp.autoFrameSkipLastTime;
+ Sm60FPS::nCurSpeed = 100;
+
+ if (diff)
+ Sm60FPS::nCurSpeed = (1000000/rate)/diff;
+ }
+
+
+
+ if(!theApp.wasPaused && theApp.throttle) {
+ if(!speedup) {
+ u32 diff = time - theApp.throttleLastTime;
+
+ int target = (1000000/(rate*theApp.throttle));
+ int d = (target - diff);
+
+ if(d > 0) {
+ Sleep(d);
+ }
+ }
+ theApp.throttleLastTime = systemGetClock();
+ }
+ if(theApp.rewindMemory) {
+ if(++theApp.rewindCounter >= (theApp.rewindTimer)) {
+ theApp.rewindSaveNeeded = true;
+ theApp.rewindCounter = 0;
+ }
+ }
+ if(systemSaveUpdateCounter) {
+ if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
+ ((MainWnd *)theApp.m_pMainWnd)->writeBatteryFile();
+ systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
+ }
+ }
+
+ theApp.wasPaused = false;
+ theApp.autoFrameSkipLastTime = time;
+}
+
+void systemScreenMessage(const char *msg)
+{
+ theApp.screenMessage = true;
+ theApp.screenMessageTime = GetTickCount();
+ theApp.screenMessageBuffer = msg;
+
+ if(theApp.screenMessageBuffer.GetLength() > 40)
+ theApp.screenMessageBuffer = theApp.screenMessageBuffer.Left(40);
+}
+
+void systemUpdateMotionSensor()
+{
+ if(theApp.input)
+ theApp.input->checkMotionKeys();
+}
+
+int systemGetSensorX()
+{
+ return theApp.sensorX;
+}
+
+int systemGetSensorY()
+{
+ return theApp.sensorY;
+}
+
+bool systemSoundInit()
+{
+ if(theApp.sound)
+ delete theApp.sound;
+
+ theApp.sound = newDirectSound();
+ return theApp.sound->init();
+}
+
+
+void systemSoundShutdown()
+{
+ if(theApp.sound)
+ delete theApp.sound;
+ theApp.sound = NULL;
+}
+
+void systemSoundPause()
+{
+ if(theApp.sound)
+ theApp.sound->pause();
+}
+
+void systemSoundReset()
+{
+ if(theApp.sound)
+ theApp.sound->reset();
+}
+
+void systemSoundResume()
+{
+ if(theApp.sound)
+ theApp.sound->resume();
+}
+
+void systemWriteDataToSoundBuffer()
+{
+ if(theApp.sound)
+ theApp.sound->write();
+}
+
+bool systemCanChangeSoundQuality()
+{
+ return true;
+}
+
+bool systemPauseOnFrame()
+{
+ if(theApp.winPauseNextFrame) {
+ theApp.paused = true;
+ theApp.winPauseNextFrame = false;
+ return true;
+ }
+ return false;
+}
+
+void systemGbBorderOn()
+{
+ if(emulating && theApp.cartridgeType == IMAGE_GB && gbBorderOn) {
+ theApp.updateWindowSize(theApp.videoOption);
+ }
+}
+
+BOOL VBA::OnIdle(LONG lCount)
+{
+ if(emulating && debugger) {
+ MSG msg;
+ remoteStubMain();
+ if(debugger)
+ return TRUE; // continue loop
+ return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
+ } else if(emulating && active && !paused) {
+ for(int i = 0; i < 2; i++) {
+ emulator.emuMain(emulator.emuCount);
+ if(lanlink.connected&&linkid&&lc.numtransfers==0) lc.CheckConn();
+
+ if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) {
+ rewindCount++;
+ if(rewindCount > 8)
+ rewindCount = 8;
+ if(emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE],
+ REWIND_SIZE)) {
+ rewindPos = ++rewindPos & 7;
+ if(rewindCount == 8)
+ rewindTopPos = ++rewindTopPos & 7;
+ }
+ }
+
+ rewindSaveNeeded = false;
+ }
+
+ if(mouseCounter) {
+ if(--mouseCounter == 0) {
+ SetCursor(NULL);
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+
+ // return CWinApp::OnIdle(lCount);
+}
+
+void VBA::addRecentFile(CString file)
+{
+ // Do not change recent list if frozen
+ if(recentFreeze)
+ return;
+ int i = 0;
+ for(i = 0; i < 10; i++) {
+ if(recentFiles[i].GetLength() == 0)
+ break;
+
+ if(recentFiles[i].Compare(file) == 0) {
+ if(i == 0)
+ return;
+ CString p = recentFiles[i];
+ for(int j = i; j > 0; j--) {
+ recentFiles[j] = recentFiles[j-1];
+ }
+ recentFiles[0] = p;
+ return;
+ }
+ }
+ int num = 0;
+ for(i = 0; i < 10; i++) {
+ if(recentFiles[i].GetLength() != 0)
+ num++;
+ }
+ if(num == 10) {
+ num--;
+ }
+
+ for(i = num; i >= 1; i--) {
+ recentFiles[i] = recentFiles[i-1];
+ }
+ recentFiles[0] = file;
+}
+
+void VBA::loadSettings()
+{
+ CString buffer;
+
+ languageOption = regQueryDwordValue("language", 1);
+ if(languageOption < 0 || languageOption > 2)
+ languageOption = 1;
+
+ buffer = regQueryStringValue("languageName", "");
+ if(!buffer.IsEmpty()) {
+ languageName = buffer.Left(3);
+ } else
+ languageName = "";
+
+ winSetLanguageOption(languageOption, true);
+
+ frameSkip = regQueryDwordValue("frameSkip", 0);
+ if(frameSkip < 0 || frameSkip > 9)
+ frameSkip = 0;
+
+ gbFrameSkip = regQueryDwordValue("gbFrameSkip", 0);
+ if(gbFrameSkip < 0 || gbFrameSkip > 9)
+ gbFrameSkip = 0;
+
+ autoFrameSkip = regQueryDwordValue("autoFrameSkip", FALSE) ? TRUE : FALSE;
+
+ vsync = regQueryDwordValue("vsync", false) ? true : false ;
+ synchronize = regQueryDwordValue("synchronize", 1) ? true : false;
+ fullScreenStretch = regQueryDwordValue("stretch", 0) ? true : false;
+
+ videoOption = regQueryDwordValue("video", VIDEO_3X);
+
+ if(videoOption < VIDEO_1X || videoOption > VIDEO_OTHER)
+ videoOption = VIDEO_3X;
+
+ bool defaultVideoDriver = regQueryDwordValue("defaultVideoDriver", true) ?
+ true : false;
+
+ if(!regQueryBinaryValue("videoDriverGUID", (char *)&videoDriverGUID,
+ sizeof(GUID))) {
+ defaultVideoDriver = TRUE;
+ }
+
+ if(defaultVideoDriver)
+ pVideoDriverGUID = NULL;
+ else
+ pVideoDriverGUID = &videoDriverGUID;
+
+ fsAdapter = regQueryDwordValue("fsAdapter", 0);
+ fsWidth = regQueryDwordValue("fsWidth", 0);
+ fsHeight = regQueryDwordValue("fsHeight", 0);
+ fsColorDepth = regQueryDwordValue("fsColorDepth", 0);
+ fsFrequency = regQueryDwordValue("fsFrequency", 60);
+ fsAdapter = regQueryDwordValue("fsAdapter", 0);
+
+ if(videoOption == VIDEO_OTHER) {
+ if(fsWidth < 0 || fsWidth > 4095 || fsHeight < 0 || fsHeight > 4095)
+ videoOption = 0;
+ if(fsColorDepth != 16 && fsColorDepth != 24 && fsColorDepth != 32)
+ videoOption = 0;
+ }
+
+ renderMethod = (DISPLAY_TYPE)regQueryDwordValue("renderMethod", DIRECT_DRAW);
+ if(renderMethod < GDI || renderMethod > OPENGL)
+ renderMethod = DIRECT_DRAW;
+
+ windowPositionX = regQueryDwordValue("windowX", 0);
+ if(windowPositionX < 0)
+ windowPositionX = 0;
+ windowPositionY = regQueryDwordValue("windowY", 0);
+ if(windowPositionY < 0)
+ windowPositionY = 0;
+
+ useBiosFile = regQueryDwordValue("useBios", 0) ? true: false;
+
+ skipBiosFile = regQueryDwordValue("skipBios", 0) ? true : false;
+
+ buffer = regQueryStringValue("biosFile", "");
+
+ if(!buffer.IsEmpty()) {
+ biosFileName = buffer;
+ }
+
+ int res = regQueryDwordValue("soundEnable", 0x30f);
+
+ soundEnable(res);
+ soundDisable(~res);
+
+ soundOffFlag = (regQueryDwordValue("soundOff", 0)) ? true : false;
+
+ soundQuality = regQueryDwordValue("soundQuality", 1);
+
+ soundEcho = regQueryDwordValue("soundEcho", 0) ? true : false;
+
+ soundLowPass = regQueryDwordValue("soundLowPass", 0) ? true : false;
+
+ soundReverse = regQueryDwordValue("soundReverse", 0) ? true : false;
+
+ soundVolume = regQueryDwordValue("soundVolume", 0);
+ if(soundVolume < 0 || soundVolume > 5)
+ soundVolume = 0;
+
+ soundInterpolation = regQueryDwordValue("soundInterpolation", 0);
+ if(soundInterpolation < 0 || soundInterpolation > 4)
+ soundInterpolation = 0;
+
+ ddrawEmulationOnly = regQueryDwordValue("ddrawEmulationOnly", false) ? true : false;
+ ddrawUseVideoMemory = regQueryDwordValue("ddrawUseVideoMemory", true) ? true : false;
+ tripleBuffering = regQueryDwordValue("tripleBuffering", false) ? true : false;
+
+ d3dFilter = regQueryDwordValue("d3dFilter", 1);
+ if(d3dFilter < 0 || d3dFilter > 1)
+ d3dFilter = 1;
+
+ glFilter = regQueryDwordValue("glFilter", 1);
+ if(glFilter < 0 || glFilter > 1)
+ glFilter = 1;
+
+ glType = regQueryDwordValue("glType", 0);
+ if(glType < 0 || glType > 1)
+ glType = 0;
+
+ filterType = regQueryDwordValue("filter", 0);
+ if(filterType < 0 || filterType > 16)
+ filterType = 0;
+
+ disableMMX = regQueryDwordValue("disableMMX", false) ? true: false;
+
+ disableStatusMessage = regQueryDwordValue("disableStatus", 0) ? true : false;
+
+ showSpeed = regQueryDwordValue("showSpeed", 0);
+ if(showSpeed < 0 || showSpeed > 2)
+ showSpeed = 0;
+
+ showSpeedTransparent = regQueryDwordValue("showSpeedTransparent", TRUE) ?
+ TRUE : FALSE;
+
+ winGbPrinterEnabled = regQueryDwordValue("gbPrinter", false) ? true : false;
+
+ if(winGbPrinterEnabled)
+ gbSerialFunction = gbPrinterSend;
+ else
+ gbSerialFunction = NULL;
+
+ pauseWhenInactive = regQueryDwordValue("pauseWhenInactive", 1) ?
+ true : false;
+
+ useOldSync = regQueryDwordValue("useOldSync", 0) ?
+ TRUE : FALSE;
+
+ captureFormat = regQueryDwordValue("captureFormat", 0);
+
+ removeIntros = regQueryDwordValue("removeIntros", false) ? true : false;
+
+ recentFreeze = regQueryDwordValue("recentFreeze", false) ? true : false;
+
+ autoIPS = regQueryDwordValue("autoIPS", true) ? true : false;
+
+ cpuDisableSfx = regQueryDwordValue("disableSfx", 0) ? true : false;
+
+ winSaveType = regQueryDwordValue("saveType", 0);
+ if(winSaveType < 0 || winSaveType > 5)
+ winSaveType = 0;
+
+ ifbType = regQueryDwordValue("ifbType", 0);
+ if(ifbType < 0 || ifbType > 2)
+ ifbType = 0;
+
+ winFlashSize = regQueryDwordValue("flashSize", 0x10000);
+ if(winFlashSize != 0x10000 && winFlashSize != 0x20000)
+ winFlashSize = 0x10000;
+ flashSize = winFlashSize;
+
+ agbPrintEnable(regQueryDwordValue("agbPrint", 0) ? true : false);
+
+ winRtcEnable = regQueryDwordValue("rtcEnabled", 0) ? true : false;
+ rtcEnable(winRtcEnable);
+
+ autoHideMenu = regQueryDwordValue("autoHideMenu", 0) ? true : false;
+
+ skinEnabled = regQueryDwordValue("skinEnabled", 0) ? true : false;
+
+ skinName = regQueryStringValue("skinName", "");
+
+ switch(videoOption) {
+ case VIDEO_320x240:
+ fsWidth = 320;
+ fsHeight = 240;
+ fsColorDepth = 16;
+ fsFrequency = 60;
+ break;
+ case VIDEO_640x480:
+ fsWidth = 640;
+ fsHeight = 480;
+ fsColorDepth = 16;
+ fsFrequency = 60;
+ break;
+ case VIDEO_800x600:
+ fsWidth = 800;
+ fsHeight = 600;
+ fsColorDepth = 16;
+ fsFrequency = 60;
+ break;
+ case VIDEO_1024x768:
+ fsWidth = 1024;
+ fsHeight = 768;
+ fsColorDepth = 16;
+ fsFrequency = 60;
+ break;
+ case VIDEO_1280x1024:
+ fsWidth = 1280;
+ fsHeight = 1024;
+ fsColorDepth = 16;
+ fsFrequency = 60;
+ break;
+ }
+
+ winGbBorderOn = regQueryDwordValue("borderOn", 0);
+ gbBorderAutomatic = regQueryDwordValue("borderAutomatic", 0);
+ gbEmulatorType = regQueryDwordValue("emulatorType", 1);
+ if(gbEmulatorType < 0 || gbEmulatorType > 5)
+ gbEmulatorType = 1;
+ gbColorOption = regQueryDwordValue("colorOption", 0);
+
+ threadPriority = regQueryDwordValue("priority", 2);
+
+ if(threadPriority < 0 || threadPriority >3)
+ threadPriority = 2;
+ updatePriority();
+
+ autoSaveLoadCheatList = regQueryDwordValue("autoSaveCheatList", 0) ?
+ true : false;
+
+ gbPaletteOption = regQueryDwordValue("gbPaletteOption", 0);
+ if(gbPaletteOption < 0)
+ gbPaletteOption = 0;
+ if(gbPaletteOption > 2)
+ gbPaletteOption = 2;
+
+ regQueryBinaryValue("gbPalette", (char *)systemGbPalette,
+ 24*sizeof(u16));
+
+ rewindTimer = regQueryDwordValue("rewindTimer", 0);
+
+ if(rewindTimer < 0 || rewindTimer > 600)
+ rewindTimer = 0;
+
+ rewindTimer *= 6; // convert to 10 frames multiple
+
+ if(rewindTimer != 0)
+ rewindMemory = (char *)malloc(8*REWIND_SIZE);
+
+ for(int i = 0; i < 10; i++) {
+ buffer.Format("recent%d", i);
+ char *s = regQueryStringValue(buffer, NULL);
+ if(s == NULL)
+ break;
+ recentFiles[i] = s;
+ }
+
+ joypadDefault = regQueryDwordValue("joypadDefault", 0);
+ if(joypadDefault < 0 || joypadDefault > 3)
+ joypadDefault = 0;
+
+ autoLoadMostRecent = regQueryDwordValue("autoLoadMostRecent", false) ? true :
+ false;
+
+ cheatsEnabled = regQueryDwordValue("cheatsEnabled", true) ? true : false;
+
+ fsMaxScale = regQueryDwordValue("fsMaxScale", 0);
+
+ throttle = regQueryDwordValue("throttle", 0);
+ if(throttle < 5 || throttle > 1000)
+ throttle = 0;
+
+ linktimeout = regQueryDwordValue("LinkTimeout", 1000);
+
+ linklog = regQueryDwordValue("Linklog", false) ? true : false;
+ if(linklog)
+ openLinkLog();
+
+ adapter = regQueryDwordValue("RFU", false) ? true : false;
+
+ lanlink.active = regQueryDwordValue("LAN", 0) ? true : false;
+ if (autoFrameSkip)
+ {
+ throttle = 0;
+ frameSkip = 0;
+ systemFrameSkip = 0;
+ }
+
+ Sm60FPS::bSaveMoreCPU = regQueryDwordValue("saveMoreCPU", 0);
+}
+
+void VBA::updateFrameSkip()
+{
+ switch(cartridgeType) {
+ case 0:
+ systemFrameSkip = frameSkip;
+ break;
+ case 1:
+ systemFrameSkip = gbFrameSkip;
+ break;
+ }
+}
+
+void VBA::updateVideoSize(UINT id)
+{
+ int value = 0;
+
+ switch(id) {
+ case ID_OPTIONS_VIDEO_X1:
+ value = VIDEO_1X;
+ break;
+ case ID_OPTIONS_VIDEO_X2:
+ value = VIDEO_2X;
+ break;
+ case ID_OPTIONS_VIDEO_X3:
+ value = VIDEO_3X;
+ break;
+ case ID_OPTIONS_VIDEO_X4:
+ value = VIDEO_4X;
+ break;
+ case ID_OPTIONS_VIDEO_FULLSCREEN320X240:
+ value = VIDEO_320x240;
+ fsWidth = 320;
+ fsHeight = 240;
+ fsColorDepth = 16;
+ break;
+ case ID_OPTIONS_VIDEO_FULLSCREEN640X480:
+ value = VIDEO_640x480;
+ fsWidth = 640;
+ fsHeight = 480;
+ fsColorDepth = 16;
+ break;
+ case ID_OPTIONS_VIDEO_FULLSCREEN800X600:
+ value = VIDEO_800x600;
+ fsWidth = 800;
+ fsHeight = 600;
+ fsColorDepth = 16;
+ break;
+ case ID_OPTIONS_VIDEO_FULLSCREEN1024X768:
+ value = VIDEO_1024x768;
+ fsWidth = 1024;
+ fsHeight = 768;
+ fsColorDepth = 32;
+ break;
+ case ID_OPTIONS_VIDEO_FULLSCREEN1280X1024:
+ value = VIDEO_1280x1024;
+ fsWidth = 1280;
+ fsHeight = 1024;
+ fsColorDepth = 32;
+ break;
+ case ID_OPTIONS_VIDEO_FULLSCREEN:
+ value = VIDEO_OTHER;
+ break;
+ }
+
+ updateWindowSize(value);
+}
+
+typedef BOOL (WINAPI *GETMENUBARINFO)(HWND, LONG, LONG, PMENUBARINFO);
+
+static void winCheckMenuBarInfo(int& winSizeX, int& winSizeY)
+{
+ HINSTANCE hinstDll;
+ DWORD dwVersion = 0;
+
+#ifdef _AFXDLL
+ hinstDll = AfxLoadLibrary("user32.dll");
+#else
+ hinstDll = LoadLibrary( _T("user32.dll") );
+#endif
+
+ if(hinstDll) {
+ GETMENUBARINFO func = (GETMENUBARINFO)GetProcAddress(hinstDll, "GetMenuBarInfo");
+
+ if(func) {
+ MENUBARINFO info;
+ info.cbSize = sizeof(MENUBARINFO);
+
+ func(AfxGetMainWnd()->GetSafeHwnd(), OBJID_MENU, 0, &info);
+
+ int menuHeight = GetSystemMetrics(SM_CYMENU);
+
+ if((info.rcBar.bottom - info.rcBar.top) > menuHeight) {
+ winSizeY += (info.rcBar.bottom - info.rcBar.top) - menuHeight + 1;
+ theApp.m_pMainWnd->SetWindowPos(
+ 0, //HWND_TOPMOST,
+ theApp.windowPositionX,
+ theApp.windowPositionY,
+ winSizeX,
+ winSizeY,
+ SWP_NOMOVE | SWP_SHOWWINDOW);
+ }
+ }
+#ifdef _AFXDLL
+ AfxFreeLibrary( hinstDll );
+#else
+ FreeLibrary( hinstDll );
+#endif
+ }
+}
+
+void VBA::updateWindowSize(int value)
+{
+ regSetDwordValue("video", value);
+
+ if(value == VIDEO_OTHER) {
+ regSetDwordValue("fsWidth", fsWidth);
+ regSetDwordValue("fsHeight", fsHeight);
+ regSetDwordValue("fsColorDepth", fsColorDepth);
+ }
+
+ if(((value >= VIDEO_320x240) &&
+ (videoOption != value)) ||
+ (videoOption >= VIDEO_320x240 &&
+ value <= VIDEO_4X) ||
+ fsForceChange) {
+ fsForceChange = false;
+ changingVideoSize = true;
+ shutdownDisplay();
+ if(input) {
+ delete input;
+ input = NULL;
+ }
+ m_pMainWnd->DragAcceptFiles(FALSE);
+ CWnd *pWnd = m_pMainWnd;
+ m_pMainWnd = NULL;
+ pWnd->DestroyWindow();
+ delete pWnd;
+ videoOption = value;
+ if(!initDisplay()) {
+ if(videoOption == VIDEO_320x240 ||
+ videoOption == VIDEO_640x480 ||
+ videoOption == VIDEO_800x600 ||
+ videoOption == VIDEO_1024x768 ||
+ videoOption == VIDEO_1280x1024 ||
+ videoOption == VIDEO_OTHER) {
+ regSetDwordValue("video", VIDEO_1X);
+ if(pVideoDriverGUID)
+ regSetDwordValue("defaultVideoDriver", TRUE);
+ }
+ changingVideoSize = false;
+ AfxPostQuitMessage(0);
+ return;
+ }
+ if(!initInput()) {
+ changingVideoSize = false;
+ AfxPostQuitMessage(0);
+ return;
+ }
+ input->checkKeys();
+ updateMenuBar();
+ changingVideoSize = FALSE;
+ updateWindowSize(videoOption);
+ return;
+ }
+
+ sizeX = 240;
+ sizeY = 160;
+
+ videoOption = value;
+
+ if(cartridgeType == IMAGE_GB) {
+ if(gbBorderOn) {
+ sizeX = 256;
+ sizeY = 224;
+ gbBorderLineSkip = 256;
+ gbBorderColumnSkip = 48;
+ gbBorderRowSkip = 40;
+ } else {
+ sizeX = 160;
+ sizeY = 144;
+ gbBorderLineSkip = 160;
+ gbBorderColumnSkip = 0;
+ gbBorderRowSkip = 0;
+ }
+ }
+
+ surfaceSizeX = sizeX;
+ surfaceSizeY = sizeY;
+
+ switch(videoOption) {
+ case VIDEO_1X:
+ surfaceSizeX = sizeX;
+ surfaceSizeY = sizeY;
+ break;
+ case VIDEO_2X:
+ surfaceSizeX = sizeX * 2;
+ surfaceSizeY = sizeY * 2;
+ break;
+ case VIDEO_3X:
+ surfaceSizeX = sizeX * 3;
+ surfaceSizeY = sizeY * 3;
+ break;
+ case VIDEO_4X:
+ surfaceSizeX = sizeX * 4;
+ surfaceSizeY = sizeY * 4;
+ break;
+ case VIDEO_320x240:
+ case VIDEO_640x480:
+ case VIDEO_800x600:
+ case VIDEO_1024x768:
+ case VIDEO_1280x1024:
+ case VIDEO_OTHER:
+ {
+ int scaleX = 1;
+ int scaleY = 1;
+ scaleX = (fsWidth / sizeX);
+ scaleY = (fsHeight / sizeY);
+ int min = scaleX < scaleY ? scaleX : scaleY;
+ if(fsMaxScale)
+ min = min > fsMaxScale ? fsMaxScale : min;
+ surfaceSizeX = min * sizeX;
+ surfaceSizeY = min * sizeY;
+ if((fullScreenStretch && (display != NULL &&
+ (display->getType() != DIRECT_3D)))
+ || (display != NULL && display->getType() >= DIRECT_3D)) {
+ surfaceSizeX = fsWidth;
+ surfaceSizeY = fsHeight;
+ }
+ }
+ break;
+ }
+
+ rect.right = sizeX;
+ rect.bottom = sizeY;
+
+ int winSizeX = sizeX;
+ int winSizeY = sizeY;
+
+ if(videoOption <= VIDEO_4X) {
+ dest.left = 0;
+ dest.top = 0;
+ dest.right = surfaceSizeX;
+ dest.bottom = surfaceSizeY;
+
+ DWORD style = WS_POPUP | WS_VISIBLE;
+
+ style |= WS_OVERLAPPEDWINDOW;
+
+ menuToggle = TRUE;
+ AdjustWindowRectEx(&dest, style, TRUE, 0); //WS_EX_TOPMOST);
+
+ winSizeX = dest.right-dest.left;
+ winSizeY = dest.bottom-dest.top;
+
+ if(skin == NULL) {
+ m_pMainWnd->SetWindowPos(0, //HWND_TOPMOST,
+ windowPositionX,
+ windowPositionY,
+ winSizeX,
+ winSizeY,
+ SWP_NOMOVE | SWP_SHOWWINDOW);
+
+ winCheckMenuBarInfo(winSizeX, winSizeY);
+ }
+ }
+
+ adjustDestRect();
+
+ updateIFB();
+ updateFilter();
+
+ if(display)
+ display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top);
+
+ m_pMainWnd->RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
+}
+
+bool VBA::initDisplay()
+{
+ return updateRenderMethod(false);
+}
+
+bool VBA::updateRenderMethod(bool force)
+{
+ Sm60FPS_Init();
+ bool res = updateRenderMethod0(force);
+
+ while(!res && renderMethod > 0) {
+ if( fsAdapter > 0 ) {
+ fsAdapter = 0;
+ } else {
+ if( videoOption > VIDEO_4X ) {
+ videoOption = VIDEO_1X;
+ force = true;
+ } else {
+ if(renderMethod == OPENGL) {
+ renderMethod = DIRECT_3D;
+ } else {
+ if(renderMethod == DIRECT_3D) {
+ renderMethod = DIRECT_DRAW;
+ } else {
+ if(renderMethod == DIRECT_DRAW) {
+ renderMethod = GDI;
+ }
+ }
+ }
+ }
+ }
+ res = updateRenderMethod(force);
+ }
+
+ return res;
+}
+
+
+bool VBA::updateRenderMethod0(bool force)
+{
+ bool initInput = false;
+ b16to32Video = false;
+
+ if(display) {
+ if(display->getType() != renderMethod || force) {
+ if(skin) {
+ delete skin;
+ skin = NULL;
+ }
+ initInput = true;
+ changingVideoSize = true;
+ shutdownDisplay();
+ if(input) {
+ delete input;
+ input = NULL;
+ }
+ CWnd *pWnd = m_pMainWnd;
+
+ m_pMainWnd = NULL;
+ pWnd->DragAcceptFiles(FALSE);
+ pWnd->DestroyWindow();
+ delete pWnd;
+
+ display = NULL;
+ regSetDwordValue("renderMethod", renderMethod);
+ }
+ }
+ if(display == NULL) {
+ switch(renderMethod) {
+ case GDI:
+ display = newGDIDisplay();
+ break;
+ case DIRECT_DRAW:
+ pVideoDriverGUID = NULL;
+ ZeroMemory( &videoDriverGUID, sizeof( GUID ) );
+ display = newDirectDrawDisplay();
+ break;
+ case DIRECT_3D:
+ display = newDirect3DDisplay();
+ break;
+ case OPENGL:
+ display = newOpenGLDisplay();
+ break;
+ }
+
+ if(display->initialize()) {
+ winUpdateSkin();
+ if(initInput) {
+ if(!this->initInput()) {
+ changingVideoSize = false;
+ AfxPostQuitMessage(0);
+ return false;
+ }
+ input->checkKeys();
+ updateMenuBar();
+ changingVideoSize = false;
+ updateWindowSize(videoOption);
+
+ m_pMainWnd->ShowWindow(SW_SHOW);
+ m_pMainWnd->UpdateWindow();
+ m_pMainWnd->SetFocus();
+
+ return true;
+ } else {
+ changingVideoSize = false;
+ return true;
+ }
+ }
+ changingVideoSize = false;
+ }
+ return true;
+}
+
+
+void VBA::winCheckFullscreen()
+{
+ if(videoOption > VIDEO_4X && tripleBuffering) {
+ if(display) {
+ display->checkFullScreen();
+ }
+ }
+}
+
+
+void VBA::shutdownDisplay()
+{
+ if(display != NULL) {
+ display->cleanup();
+ delete display;
+ display = NULL;
+ }
+}
+
+void VBA::directXMessage(const char *msg)
+{
+ systemMessage(IDS_DIRECTX_7_REQUIRED,
+ "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s",
+ msg);
+}
+
+void VBA::winUpdateSkin()
+{
+#ifndef NOSKINS
+ skinButtons = 0;
+ if(skin) {
+ delete skin;
+ skin = NULL;
+ }
+
+ if(!skinName.IsEmpty() && skinEnabled && display->isSkinSupported()) {
+ skin = new CSkin();
+ if(skin->Initialize(skinName)) {
+ skin->Hook(m_pMainWnd);
+ skin->Enable(true);
+ } else {
+ delete skin;
+ skin = NULL;
+ }
+ }
+
+ if(!skin) {
+ adjustDestRect();
+ updateMenuBar();
+ }
+#endif
+}
+
+void VBA::updatePriority()
+{
+ switch(threadPriority) {
+ case 0:
+ SetThreadPriority(THREAD_PRIORITY_HIGHEST);
+ break;
+ case 1:
+ SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
+ break;
+ case 3:
+ SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
+ break;
+ default:
+ SetThreadPriority(THREAD_PRIORITY_NORMAL);
+ }
+}
+
+#ifdef MMX
+bool VBA::detectMMX()
+{
+ bool support = false;
+ char brand[13];
+
+ // check for Intel chip
+ __try {
+ __asm {
+ mov eax, 0;
+ cpuid;
+ mov [dword ptr brand+0], ebx;
+ mov [dword ptr brand+4], edx;
+ mov [dword ptr brand+8], ecx;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ if(_exception_code() == STATUS_ILLEGAL_INSTRUCTION) {
+ return false;
+ }
+ return false;
+ }
+ // Check for Intel or AMD CPUs
+ if(strncmp(brand, "GenuineIntel", 12)) {
+ if(strncmp(brand, "AuthenticAMD", 12)) {
+ return false;
+ }
+ }
+
+ __asm {
+ mov eax, 1;
+ cpuid;
+ test edx, 00800000h;
+ jz NotFound;
+ mov [support], 1;
+ NotFound:
+ }
+ return support;
+}
+#endif
+
+void VBA::winSetLanguageOption(int option, bool force)
+{
+ if(((option == languageOption) && option != 2) && !force)
+ return;
+ switch(option) {
+ case 0:
+ {
+ char lbuffer[10];
+
+ if(GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SABBREVLANGNAME,
+ lbuffer, 10)) {
+ HINSTANCE l = winLoadLanguage(lbuffer);
+ if(l == NULL) {
+ LCID locIdBase = MAKELCID( MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANG_NEUTRAL ), SORT_DEFAULT );
+ if(GetLocaleInfo(locIdBase, LOCALE_SABBREVLANGNAME,
+ lbuffer, 10)) {
+ l = winLoadLanguage(lbuffer);
+ if(l == NULL) {
+ systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
+ "Failed to load library %s",
+ lbuffer);
+ return;
+ }
+ }
+ }
+ AfxSetResourceHandle(l);
+ if(languageModule != NULL)
+#ifdef _AFXDLL
+ AfxFreeLibrary( languageModule );
+#else
+ FreeLibrary( languageModule );
+#endif
+ languageModule = l;
+ } else {
+ systemMessage(IDS_FAILED_TO_GET_LOCINFO,
+ "Failed to get locale information");
+ return;
+ }
+ }
+ break;
+ case 1:
+ if(languageModule != NULL)
+#ifdef _AFXDLL
+ AfxFreeLibrary( languageModule );
+#else
+ FreeLibrary( languageModule );
+#endif
+ languageModule = NULL;
+ AfxSetResourceHandle(AfxGetInstanceHandle());
+ break;
+ case 2:
+ {
+ if(!force) {
+ LangSelect dlg;
+ if(dlg.DoModal()) {
+ HINSTANCE l = winLoadLanguage(languageName);
+ if(l == NULL) {
+ systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
+ "Failed to load library %s",
+ languageName);
+ return;
+ }
+ AfxSetResourceHandle(l);
+ if(languageModule != NULL)
+ {
+#ifdef _AFXDLL
+ AfxFreeLibrary( languageModule );
+#else
+ FreeLibrary( languageModule );
+#endif
+ }
+ languageModule = l;
+ }
+ } else {
+ if(languageName.IsEmpty())
+ return;
+ HINSTANCE l = winLoadLanguage(languageName);
+ if(l == NULL) {
+ systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
+ "Failed to load library %s",
+ languageName);
+ return;
+ }
+ AfxSetResourceHandle(l);
+ if(languageModule != NULL)
+ FreeLibrary(languageModule);
+ languageModule = l;
+ }
+ }
+ break;
+ }
+ languageOption = option;
+ updateMenuBar();
+}
+
+HINSTANCE VBA::winLoadLanguage(const char *name)
+{
+ CString buffer;
+
+ buffer.Format( _T("vba_%s.dll"), name);
+
+#ifdef _AFXDLL
+ HINSTANCE l = AfxLoadLibrary( buffer );
+#else
+ HMODULE l = LoadLibrary( buffer );
+#endif
+
+ if(l == NULL) {
+ if(strlen(name) == 3) {
+ char buffer2[3];
+ buffer2[0] = name[0];
+ buffer2[1] = name[1];
+ buffer2[2] = 0;
+ buffer.Format("vba_%s.dll", buffer2);
+
+#ifdef _AFXDLL
+ return AfxLoadLibrary( buffer );
+#else
+ return LoadLibrary( buffer );
+#endif
+ }
+ }
+ return l;
+}
+
+
+bool VBA::initInput()
+{
+ if(input)
+ delete input;
+ input = newDirectInput();
+ if(input->initialize()) {
+ input->loadSettings();
+ input->checkKeys();
+ return true;
+ }
+ delete input;
+ return false;
+}
+
+void VBA::winAddUpdateListener(IUpdateListener *l)
+{
+ updateList.AddTail(l);
+ updateCount++;
+}
+
+void VBA::winRemoveUpdateListener(IUpdateListener *l)
+{
+ POSITION pos = updateList.Find(l);
+ if(pos) {
+ updateList.RemoveAt(pos);
+ updateCount--;
+ if(updateCount < 0)
+ updateCount = 0;
+ }
+}
+
+CString VBA::winLoadFilter(UINT id)
+{
+ CString res = winResLoadString(id);
+ res.Replace('_','|');
+
+ return res;
+}
+
+void VBA::movieReadNext()
+{
+ if(movieFile) {
+ bool movieEnd = false;
+
+ if(fread(&moviePlayFrame, 1, sizeof(int), movieFile) == sizeof(int)) {
+ if(fread(&movieNextJoypad, 1, sizeof(u32), movieFile) == sizeof(int)) {
+ // make sure we don't have spurious entries on the movie that can
+ // cause us to play it forever
+ if(moviePlayFrame <= movieFrame)
+ movieEnd = true;
+ } else
+ movieEnd = true;
+ } else
+ movieEnd = true;
+ if(movieEnd) {
+ CString string = winResLoadString(IDS_END_OF_MOVIE);
+ systemScreenMessage(string);
+ moviePlaying = false;
+ fclose(movieFile);
+ movieFile = NULL;
+ return;
+ }
+ } else
+ moviePlaying = false;
+}
+
+void VBA::saveSettings()
+{
+ regSetDwordValue("language", languageOption);
+
+ regSetStringValue("languageName", languageName);
+
+ regSetDwordValue("frameSkip", frameSkip);
+
+ regSetDwordValue("gbFrameSkip", gbFrameSkip);
+
+ regSetDwordValue("autoFrameSkip", autoFrameSkip);
+
+ regSetDwordValue("vsync", vsync);
+ regSetDwordValue("synchronize", synchronize);
+ regSetDwordValue("stretch", fullScreenStretch);
+
+ regSetDwordValue("video", videoOption);
+
+ regSetDwordValue("defaultVideoDriver", pVideoDriverGUID == NULL);
+
+ if(pVideoDriverGUID) {
+ regSetBinaryValue("videoDriverGUID", (char *)&videoDriverGUID,
+ sizeof(GUID));
+ }
+
+
+ regSetDwordValue("fsAdapter", fsAdapter);
+ regSetDwordValue("fsWidth", fsWidth);
+ regSetDwordValue("fsHeight", fsHeight);
+ regSetDwordValue("fsColorDepth", fsColorDepth);
+ regSetDwordValue("fsFrequency", fsFrequency);
+
+ regSetDwordValue("renderMethod", renderMethod);
+
+ regSetDwordValue("windowX", windowPositionX);
+ regSetDwordValue("windowY", windowPositionY);
+
+ regSetDwordValue("useBios", useBiosFile);
+
+ regSetDwordValue("skipBios", skipBiosFile);
+
+ if(!biosFileName.IsEmpty())
+ regSetStringValue("biosFile", biosFileName);
+
+ regSetDwordValue("soundEnable", soundGetEnable() & 0x30f);
+
+ regSetDwordValue("soundOff", soundOffFlag);
+
+ regSetDwordValue("soundQuality", soundQuality);
+
+ regSetDwordValue("soundEcho", soundEcho);
+
+ regSetDwordValue("soundLowPass", soundLowPass);
+
+ regSetDwordValue("soundReverse", soundReverse);
+
+ regSetDwordValue("soundVolume", soundVolume);
+
+ regSetDwordValue("soundInterpolation", soundInterpolation);
+
+ regSetDwordValue("ddrawEmulationOnly", ddrawEmulationOnly);
+ regSetDwordValue("ddrawUseVideoMemory", ddrawUseVideoMemory);
+ regSetDwordValue("tripleBuffering", tripleBuffering);
+
+ regSetDwordValue("d3dFilter", d3dFilter);
+ regSetDwordValue("glFilter", glFilter);
+ regSetDwordValue("glType", glType);
+
+ regSetDwordValue("filter", filterType);
+
+ regSetDwordValue("LCDFilter", filterLCD);
+
+ regSetDwordValue("disableMMX", disableMMX);
+
+ regSetDwordValue("disableStatus", disableStatusMessage);
+
+ regSetDwordValue("showSpeed", showSpeed);
+
+ regSetDwordValue("showSpeedTransparent", showSpeedTransparent);
+
+ regSetDwordValue("gbPrinter", winGbPrinterEnabled);
+
+ regSetDwordValue("pauseWhenInactive", pauseWhenInactive);
+
+ regSetDwordValue("useOldSync", useOldSync);
+
+ regSetDwordValue("captureFormat", captureFormat);
+
+ regSetDwordValue("removeIntros", removeIntros);
+
+ regSetDwordValue("recentFreeze", recentFreeze);
+
+ regSetDwordValue("autoIPS", autoIPS);
+
+ regSetDwordValue("disableSfx", cpuDisableSfx);
+
+ regSetDwordValue("saveType", winSaveType);
+
+ regSetDwordValue("ifbType", ifbType);
+
+ regSetDwordValue("flashSize", winFlashSize);
+
+ regSetDwordValue("agbPrint", agbPrintIsEnabled());
+
+ regSetDwordValue("rtcEnabled", winRtcEnable);
+
+ regSetDwordValue("autoHideMenu", autoHideMenu);
+
+ regSetDwordValue("skinEnabled", skinEnabled);
+
+ regSetStringValue("skinName", skinName);
+
+ regSetDwordValue("borderOn", winGbBorderOn);
+ regSetDwordValue("borderAutomatic", gbBorderAutomatic);
+ regSetDwordValue("emulatorType", gbEmulatorType);
+ regSetDwordValue("colorOption", gbColorOption);
+
+ regSetDwordValue("priority", threadPriority);
+
+ regSetDwordValue("autoSaveCheatList", autoSaveLoadCheatList);
+
+ regSetDwordValue("gbPaletteOption", gbPaletteOption);
+
+ regSetBinaryValue("gbPalette", (char *)systemGbPalette,
+ 24*sizeof(u16));
+
+ regSetDwordValue("rewindTimer", rewindTimer/6);
+
+ CString buffer;
+ for(int i = 0; i < 10; i++) {
+ buffer.Format("recent%d", i);
+ regSetStringValue(buffer, recentFiles[i]);
+ }
+
+ regSetDwordValue("joypadDefault", joypadDefault);
+ regSetDwordValue("autoLoadMostRecent", autoLoadMostRecent);
+ regSetDwordValue("cheatsEnabled", cheatsEnabled);
+ regSetDwordValue("fsMaxScale", fsMaxScale);
+ regSetDwordValue("throttle", throttle);
+
+ regSetDwordValue("saveMoreCPU", Sm60FPS::bSaveMoreCPU);
+ regSetDwordValue("LinkTimeout", linktimeout);
+ regSetDwordValue("Linklog", linklog);
+ regSetDwordValue("RFU", adapter);
+}
+
+void winSignal(int, int)
+{
+}
+
+#define CPUReadByteQuick(addr) \
+ map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
+
+void winOutput(char *s, u32 addr)
+{
+ if(s) {
+ toolsLog(s);
+ } else {
+ CString str;
+ char c;
+
+ c = CPUReadByteQuick(addr);
+ addr++;
+ while(c) {
+ str += c;
+ c = CPUReadByteQuick(addr);
+ addr++;
+ }
+ toolsLog(str);
+ }
+}
+
+
+void Sm60FPS_Init()
+{
+ Sm60FPS::dwTimeElapse = 0;
+ Sm60FPS::fWantFPS = 60.f;
+ Sm60FPS::fCurFPS = 0.f;
+ Sm60FPS::nFrameCnt = 0;
+ Sm60FPS::bLastSkip = false;
+ Sm60FPS::nCurSpeed = 100;
+}
+
+
+bool Sm60FPS_CanSkipFrame()
+{
+ if( theApp.autoFrameSkip ) {
+ if( Sm60FPS::nFrameCnt == 0 ) {
+ Sm60FPS::nFrameCnt = 0;
+ Sm60FPS::dwTimeElapse = 0;
+ Sm60FPS::dwTime0 = timeGetTime();
+ } else {
+ if( Sm60FPS::nFrameCnt >= 10 ) {
+ Sm60FPS::nFrameCnt = 0;
+ Sm60FPS::dwTimeElapse = 0;
+
+ if( Sm60FPS::nCurSpeed > Sm60FPS::K_fCpuSpeed ) {
+ Sm60FPS::fWantFPS += 1;
+ if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps ){
+ Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps;
+ }
+ } else {
+ if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed - 5) ) {
+ Sm60FPS::fWantFPS -= 1;
+ if( Sm60FPS::fWantFPS < 30.f ) {
+ Sm60FPS::fWantFPS = 30.f;
+ }
+ }
+ }
+ } else { // between frame 1-10
+ Sm60FPS::dwTime1 = timeGetTime();
+ Sm60FPS::dwTimeElapse += (Sm60FPS::dwTime1 - Sm60FPS::dwTime0);
+ Sm60FPS::dwTime0 = Sm60FPS::dwTime1;
+ if( !Sm60FPS::bLastSkip &&
+ ( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU) ) {
+ Sm60FPS::fCurFPS = (float)Sm60FPS::nFrameCnt * 1000 / Sm60FPS::dwTimeElapse;
+ if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU ) {
+ Sm60FPS::bLastSkip = true;
+ Sm60FPS::nFrameCnt++;
+ return true;
+ }
+ }
+ }
+ }
+ Sm60FPS::bLastSkip = false;
+ Sm60FPS::nFrameCnt++;
+ }
+ return false;
+}
+
+
+void Sm60FPS_Sleep()
+{
+ if( theApp.autoFrameSkip ) {
+ u32 dwTimePass = Sm60FPS::dwTimeElapse + (timeGetTime() - Sm60FPS::dwTime0);
+ u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * Sm60FPS::K_fDT);
+ if( dwTimeShould > dwTimePass ) {
+ Sleep(dwTimeShould - dwTimePass);
+ }
+ }
+}
diff --git a/src/win32/VBA.h b/src/win32/VBA.h
index ee1916ca..1a7ba1fd 100644
--- a/src/win32/VBA.h
+++ b/src/win32/VBA.h
@@ -1,280 +1,279 @@
-// -*- C++ -*-
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-// VBA.h : main header file for the VBA application
-//
-
-#if !defined(AFX_VBA_H__57514A10_49F9_4B83_A928_0D8A4A7306A3__INCLUDED_)
-#define AFX_VBA_H__57514A10_49F9_4B83_A928_0D8A4A7306A3__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#ifndef __AFXWIN_H__
-#error include 'stdafx.h' before including this file for PCH
-#endif
-
-#include
-
-#include "AcceleratorManager.h"
-#include "..\..\res\resource.h" // main symbols
-#include "Display.h"
-#include "Input.h"
-#include "IUpdate.h"
-#include "Sound.h"
-#include "../System.h"
-
-/////////////////////////////////////////////////////////////////////////////
-// VBA:
-// See VBA.cpp for the implementation of this class
-//
-
-enum {
- VIDEO_1X, VIDEO_2X, VIDEO_3X, VIDEO_4X,
- VIDEO_320x240, VIDEO_640x480, VIDEO_800x600, VIDEO_1024x768, VIDEO_1280x1024,
- VIDEO_OTHER
-};
-
-enum pixelFilterType
-{
- FILTER_NONE,
-
- FILTER_SIMPLE2X, FILTER_PIXELATE, FILTER_TVMODE, FILTER_SCANLINES,
- FILTER_BILINEAR, FILTER_BILINEARPLUS, FILTER_MAMESCALE2X,
- FILTER_2XSAI, FILTER_SUPER2XSAI, FILTER_SUPEREAGLE, FILTER_LQ2X, FILTER_HQ2X,
-
- FILTER_SIMPLE3X, FILTER_HQ3X,
-
- FILTER_SIMPLE4X, FILTER_HQ4X
-};
-
-#define REWIND_SIZE 400000
-
-class AVIWrite;
-class WavWriter;
-
-class VBA : public CWinApp
-{
- public:
- CMenu m_menu;
- HMENU menu;
- HMENU popup;
- bool mode320Available;
- bool mode640Available;
- bool mode800Available;
- bool mode1024Available;
- bool mode1280Available;
- int windowPositionX;
- int windowPositionY;
- void (*filterFunction)(u8*,u32,u8*,u8*,u32,int,int);
- void (*ifbFunction)(u8*,u32,int,int);
- int ifbType;
- int filterType;
- int filterWidth;
- int filterHeight;
- int filterMagnification;
- int filterLCD;
- int fsWidth;
- int fsHeight;
- int fsColorDepth;
- int fsFrequency;
- int fsAdapter;
- bool fsForceChange;
- int sizeX;
- int sizeY;
- int surfaceSizeX;
- int surfaceSizeY;
- int videoOption;
- bool fullScreenStretch;
- bool disableStatusMessage;
- int showSpeed;
- BOOL showSpeedTransparent;
- int showRenderedFrames;
- bool screenMessage;
- CString screenMessageBuffer;
- DWORD screenMessageTime;
- u8 *delta[257*244*4];
- bool menuToggle;
- IDisplay *display;
- int cartridgeType;
- bool soundInitialized;
- bool useBiosFile;
- bool skipBiosFile;
- CString biosFileName;
- bool active;
- bool paused;
- CString recentFiles[10];
- bool recentFreeze;
- bool autoSaveLoadCheatList;
- FILE *winout;
- bool removeIntros;
- bool autoIPS;
- int winGbBorderOn;
- int winFlashSize;
- bool winRtcEnable;
- int winSaveType;
- char *rewindMemory;
- int rewindPos;
- int rewindTopPos;
- int rewindCounter;
- int rewindCount;
- bool rewindSaveNeeded;
- int rewindTimer;
- int captureFormat;
- bool tripleBuffering;
- bool autoHideMenu;
- int throttle;
- u32 throttleLastTime;
- u32 autoFrameSkipLastTime;
- bool autoFrameSkip;
- bool vsync;
- bool changingVideoSize;
- GUID videoDriverGUID;
- GUID *pVideoDriverGUID;
- DISPLAY_TYPE renderMethod;
- bool iconic;
- bool ddrawEmulationOnly;
- bool ddrawUsingEmulationOnly;
- bool ddrawDebug;
- bool ddrawUseVideoMemory;
- int d3dFilter;
- int glFilter;
- int glType;
- bool dinputKeyFocus;
- bool pauseWhenInactive;
- bool speedupToggle;
- bool useOldSync;
- bool winGbPrinterEnabled;
- int threadPriority;
- bool disableMMX;
- int languageOption;
- CString languageName;
- HINSTANCE languageModule;
- int renderedFrames;
- Input *input;
- int joypadDefault;
- int autoFire;
- bool autoFireToggle;
- bool winPauseNextFrame;
- bool soundRecording;
- WavWriter *soundRecorder;
- CString soundRecordName;
- ISound *sound;
- bool aviRecording;
- AVIWrite *aviRecorder;
- CString aviRecordName;
- int aviFrameNumber;
- bool painting;
- bool movieRecording;
- bool moviePlaying;
- int movieFrame;
- int moviePlayFrame;
- FILE *movieFile;
- u32 movieLastJoypad;
- u32 movieNextJoypad;
- int sensorX;
- int sensorY;
- int mouseCounter;
- bool wasPaused;
- int frameskipadjust;
- bool autoLoadMostRecent;
- int fsMaxScale;
- int romSize;
-
- CList updateList;
- int updateCount;
-
- CAcceleratorManager winAccelMgr;
- HACCEL hAccel;
-
- RECT rect;
- RECT dest;
-
- struct EmulatedSystem emulator;
-
- CString szFile;
- CString filename;
- CString dir;
-
- CString wndClass;
-
- public:
- VBA();
- ~VBA();
-
- void adjustDestRect();
- void updateIFB();
- void updateFilter();
- void updateMenuBar();
- void winAddUpdateListener(IUpdateListener *l);
- void winRemoveUpdateListener(IUpdateListener *l);
- CString winLoadFilter(UINT id);
-
- // Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(VBA)
- public:
- virtual BOOL InitInstance();
- virtual BOOL OnIdle(LONG lCount);
- //}}AFX_VIRTUAL
-
- // Implementation
-
- public:
- void saveSettings();
- void movieReadNext();
- bool initInput();
- HINSTANCE winLoadLanguage(const char *name);
- void winSetLanguageOption(int option, bool force);
- bool detectMMX();
-#ifdef MMX
-#endif
- void updatePriority();
- void directXMessage(const char *msg);
- void shutdownDisplay();
- void winCheckFullscreen();
- bool updateRenderMethod0(bool force);
- bool updateRenderMethod(bool force);
- bool initDisplay();
- void updateWindowSize(int value);
- void updateVideoSize(UINT id);
- void updateFrameSkip();
- void loadSettings();
- void addRecentFile(CString file);
- //{{AFX_MSG(VBA)
- afx_msg void OnAppAbout();
- // NOTE - the ClassWizard will add and remove member functions here.
- // DO NOT EDIT what you see in these blocks of generated code !
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
- };
-
- extern VBA theApp;
-
-#ifdef MMX
- extern "C" bool cpu_mmx;
-#endif
-
- /////////////////////////////////////////////////////////////////////////////
-
- //{{AFX_INSERT_LOCATION}}
- // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_VBA_H__57514A10_49F9_4B83_A928_0D8A4A7306A3__INCLUDED_)
+// -*- C++ -*-
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2005 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// VBA.h : main header file for the VBA application
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+#error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "stdafx.h"
+#include "resource.h"
+//#include
+
+#include "AcceleratorManager.h"
+#include "Display.h"
+#include "Input.h"
+#include "IUpdate.h"
+#include "Sound.h"
+#include "../System.h"
+#include "../Util.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// VBA:
+// See VBA.cpp for the implementation of this class
+//
+
+enum {
+ VIDEO_1X, VIDEO_2X, VIDEO_3X, VIDEO_4X,
+ VIDEO_320x240, VIDEO_640x480, VIDEO_800x600, VIDEO_1024x768, VIDEO_1280x1024,
+ VIDEO_OTHER
+};
+
+enum pixelFilterType
+{
+ FILTER_NONE,
+
+ FILTER_SIMPLE2X, FILTER_PIXELATE, FILTER_TVMODE, FILTER_SCANLINES,
+ FILTER_BILINEAR, FILTER_BILINEARPLUS, FILTER_MAMESCALE2X,
+ FILTER_2XSAI, FILTER_SUPER2XSAI, FILTER_SUPEREAGLE, FILTER_LQ2X, FILTER_HQ2X,
+
+ FILTER_SIMPLE3X, FILTER_HQ3X,
+
+ FILTER_SIMPLE4X, FILTER_HQ4X
+};
+
+#define REWIND_SIZE 400000
+
+class CSkin;
+class AVIWrite;
+class WavWriter;
+
+class VBA : public CWinApp
+{
+ public:
+ CMenu m_menu;
+ HMENU menu;
+ HMENU popup;
+ bool mode320Available;
+ bool mode640Available;
+ bool mode800Available;
+ bool mode1024Available;
+ bool mode1280Available;
+ int windowPositionX;
+ int windowPositionY;
+ void (*filterFunction)(u8*,u32,u8*,u8*,u32,int,int);
+ void (*ifbFunction)(u8*,u32,int,int);
+ int ifbType;
+ int filterType;
+ int filterWidth;
+ int filterHeight;
+ int filterMagnification;
+ int filterLCD;
+ int fsWidth;
+ int fsHeight;
+ int fsColorDepth;
+ int fsFrequency;
+ int fsAdapter;
+ bool fsForceChange;
+ int sizeX;
+ int sizeY;
+ int surfaceSizeX;
+ int surfaceSizeY;
+ int videoOption;
+ bool fullScreenStretch;
+ bool disableStatusMessage;
+ int showSpeed;
+ BOOL showSpeedTransparent;
+ int showRenderedFrames;
+ bool screenMessage;
+ CString screenMessageBuffer;
+ DWORD screenMessageTime;
+ u8 *delta[257*244*4];
+ bool menuToggle;
+ IDisplay *display;
+ IMAGE_TYPE cartridgeType;
+ bool soundInitialized;
+ bool useBiosFile;
+ bool skipBiosFile;
+ CString biosFileName;
+ bool active;
+ bool paused;
+ CString recentFiles[10];
+ bool recentFreeze;
+ bool autoSaveLoadCheatList;
+ FILE *winout;
+ bool removeIntros;
+ bool autoIPS;
+ int winGbBorderOn;
+ int winFlashSize;
+ bool winRtcEnable;
+ bool winGenericflashcardEnable;
+ int winSaveType;
+ char *rewindMemory;
+ int rewindPos;
+ int rewindTopPos;
+ int rewindCounter;
+ int rewindCount;
+ bool rewindSaveNeeded;
+ int rewindTimer;
+ int captureFormat;
+ bool tripleBuffering;
+ bool autoHideMenu;
+ int throttle;
+ u32 throttleLastTime;
+ u32 autoFrameSkipLastTime;
+ bool autoFrameSkip;
+ bool vsync;
+ bool changingVideoSize;
+ GUID videoDriverGUID;
+ GUID *pVideoDriverGUID;
+ DISPLAY_TYPE renderMethod;
+ bool iconic;
+ bool ddrawEmulationOnly;
+ bool ddrawUsingEmulationOnly;
+ bool ddrawDebug;
+ bool ddrawUseVideoMemory;
+ int d3dFilter;
+ int glFilter;
+ int glType;
+ bool dinputKeyFocus;
+ CSkin *skin;
+ CString skinName;
+ bool skinEnabled;
+ int skinButtons;
+ bool pauseWhenInactive;
+ bool speedupToggle;
+ bool useOldSync;
+ bool winGbPrinterEnabled;
+ int threadPriority;
+ bool disableMMX;
+ int languageOption;
+ CString languageName;
+ HMODULE languageModule;
+ int renderedFrames;
+ Input *input;
+ int joypadDefault;
+ int autoFire;
+ bool autoFireToggle;
+ bool winPauseNextFrame;
+ bool soundRecording;
+ WavWriter *soundRecorder;
+ CString soundRecordName;
+ bool dsoundDisableHardwareAcceleration;
+ ISound *sound;
+ bool aviRecording;
+ AVIWrite *aviRecorder;
+ CString aviRecordName;
+ int aviFrameNumber;
+ bool painting;
+ bool movieRecording;
+ bool moviePlaying;
+ int movieFrame;
+ int moviePlayFrame;
+ FILE *movieFile;
+ u32 movieLastJoypad;
+ u32 movieNextJoypad;
+ int sensorX;
+ int sensorY;
+ int mouseCounter;
+ bool wasPaused;
+ int frameskipadjust;
+ bool autoLoadMostRecent;
+ int fsMaxScale;
+ int romSize;
+
+ CList updateList;
+ int updateCount;
+
+ CAcceleratorManager winAccelMgr;
+ HACCEL hAccel;
+
+ RECT rect;
+ RECT dest;
+
+ struct EmulatedSystem emulator;
+
+ CString szFile;
+ CString filename;
+ CString dir;
+
+ CString wndClass;
+
+ public:
+ VBA();
+ ~VBA();
+
+ void adjustDestRect();
+ void updateIFB();
+ void updateFilter();
+ void updateMenuBar();
+ void winAddUpdateListener(IUpdateListener *l);
+ void winRemoveUpdateListener(IUpdateListener *l);
+ CString winLoadFilter(UINT id);
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(VBA)
+ public:
+ virtual BOOL InitInstance();
+ virtual BOOL OnIdle(LONG lCount);
+ //}}AFX_VIRTUAL
+
+ // Implementation
+
+ public:
+ void saveSettings();
+ void movieReadNext();
+ bool initInput();
+ HMODULE winLoadLanguage(const char *name);
+ void winSetLanguageOption(int option, bool force);
+#ifdef MMX
+ bool detectMMX();
+#endif
+ void updatePriority();
+ void winUpdateSkin();
+ void directXMessage(const char *msg);
+ void shutdownDisplay();
+ void winCheckFullscreen();
+ bool updateRenderMethod0(bool force);
+ bool updateRenderMethod(bool force);
+ bool initDisplay();
+ void updateWindowSize(int value);
+ void updateVideoSize(UINT id);
+ void updateFrameSkip();
+ void loadSettings();
+ void addRecentFile(CString file);
+ //{{AFX_MSG(VBA)
+ afx_msg void OnAppAbout();
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+ };
+
+ extern VBA theApp;
+ extern int emulating;
+
+#ifdef MMX
+ extern "C" bool cpu_mmx;
+#endif
\ No newline at end of file
diff --git a/res/VBA.rc b/src/win32/VBA.rc
similarity index 83%
rename from res/VBA.rc
rename to src/win32/VBA.rc
index d7b97664..f5cded1b 100644
--- a/res/VBA.rc
+++ b/src/win32/VBA.rc
@@ -8,30 +8,10 @@
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
+#include "resource2.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-// German (Germany) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
-#ifdef _WIN32
-LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
-#pragma code_page(1252)
-#endif //_WIN32
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_ICON ICON "VBA.ico"
-#endif // German (Germany) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
@@ -54,13 +34,13 @@ END
2 TEXTINCLUDE
BEGIN
- "#include ""afxres.h""\0"
+ "#include ""afxres.h""\r\n"
+ "#include ""resource2.h""\0"
END
3 TEXTINCLUDE
BEGIN
- "\r\n"
- "\0"
+ "#include ""vba.rc2""\0"
END
#endif // APSTUDIO_INVOKED
@@ -153,72 +133,73 @@ BEGIN
PUSHBUTTON "Cancel",IDCANCEL,90,102,50,14,WS_GROUP
END
-IDD_ABOUT DIALOGEX 0, 0, 172, 102
-STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_ABOUT DIALOGEX 0, 0, 157, 78
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW
CAPTION "About"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
- DEFPUSHBUTTON "OK",IDOK,6,84,162,12
- ICON IDI_ICON,IDC_STATIC,12,6,21,20,SS_CENTERIMAGE,WS_EX_TRANSPARENT
- CTEXT "VisualBoyAdvance Emulator",IDC_STATIC,42,6,126,8
- CTEXT "Copyright © 2005 Forgotten and the VBA team",IDC_STATIC,6,30,162,8
- CTEXT "http://vba.ngemu.com",IDC_URL,90,42,76,8
- CTEXT "Contribution by Costis",IDC_STATIC,6,42,78,8
- CTEXT "Version:",IDC_STATIC,42,18,42,8
- LTEXT "",IDC_VERSION,90,18,78,8
- CTEXT "Changes by Spacy:",IDC_URL2,6,60,162,8
- CTEXT "http://www.spacyhacks.de.vu",IDC_URL3,6,72,162,8
+ ICON 101,IDC_STATIC,6,6,20,20
+ CTEXT "VisualBoyAdvance Emulator",IDC_STATIC,30,6,120,8
+ CTEXT "Copyright © 2006 VBA development team",IDC_STATIC,6,36,144,8
+ CTEXT "http://vba.ngemu.com",IDC_URL,6,66,144,8
+ CTEXT "Contribution by Costis",IDC_STATIC,6,48,144,8
+ CTEXT "Version",IDC_STATIC,30,18,60,8
+ CTEXT "",IDC_VERSION,90,18,60,8,SS_NOPREFIX
END
-IDD_DIRECTORIES DIALOG 0, 0, 284, 129
+IDD_DIRECTORIES DIALOGEX 0, 0, 220, 301
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Directories"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
- PUSHBUTTON "Browse...",IDC_ROM_DIR,174,7,50,14
- PUSHBUTTON "Browse...",IDC_GBROM_DIR,174,26,50,14
- PUSHBUTTON "Browse...",IDC_BATTERY_DIR,174,45,50,14
- PUSHBUTTON "Browse...",IDC_SAVE_DIR,174,64,50,14
- PUSHBUTTON "Browse...",IDC_CAPTURE_DIR,174,83,50,14
- DEFPUSHBUTTON "OK",IDOK,88,108,50,14
- PUSHBUTTON "Cancel",IDCANCEL,145,108,50,14
- LTEXT "ROM:",IDC_STATIC,7,9,20,8
- LTEXT "Battery:",IDC_STATIC,7,47,25,8
- LTEXT "Save Game:",IDC_STATIC,7,66,40,8
- LTEXT "Capture:",IDC_STATIC,7,85,28,8
- EDITTEXT IDC_ROM_PATH,49,7,121,14,ES_AUTOHSCROLL | WS_DISABLED
- EDITTEXT IDC_BATTERY_PATH,49,45,121,14,ES_AUTOHSCROLL | WS_DISABLED
- EDITTEXT IDC_SAVE_PATH,49,64,121,14,ES_AUTOHSCROLL | WS_DISABLED
- EDITTEXT IDC_CAPTURE_PATH,49,83,121,14,ES_AUTOHSCROLL | WS_DISABLED
- LTEXT "GB ROM:",IDC_STATIC,7,28,32,8
- EDITTEXT IDC_GBROM_PATH,49,26,121,14,ES_AUTOHSCROLL | WS_DISABLED
- PUSHBUTTON "Reset",IDC_ROM_DIR_RESET,228,6,50,14
- PUSHBUTTON "Reset",IDC_GBROM_DIR_RESET,228,25,50,14
- PUSHBUTTON "Reset",IDC_BATTERY_DIR_RESET,228,45,50,14
- PUSHBUTTON "Reset",IDC_SAVE_DIR_RESET,228,64,50,14
- PUSHBUTTON "Reset",IDC_CAPTURE_DIR_RESET,228,83,50,14
+ PUSHBUTTON "Browse...",IDC_ROM_DIR,12,66,90,12
+ PUSHBUTTON "Browse...",IDC_GBROM_DIR,12,114,90,12
+ PUSHBUTTON "Browse...",IDC_BATTERY_DIR,12,162,90,12
+ PUSHBUTTON "Browse...",IDC_SAVE_DIR,12,210,90,12
+ PUSHBUTTON "Browse...",IDC_CAPTURE_DIR,12,258,90,12
+ DEFPUSHBUTTON "OK",IDOK,120,282,42,12
+ PUSHBUTTON "Cancel",IDCANCEL,168,282,42,12
+ EDITTEXT IDC_ROM_PATH,12,54,198,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_BATTERY_PATH,12,150,198,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_SAVE_PATH,12,198,198,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_CAPTURE_PATH,12,246,198,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_GBROM_PATH,12,102,198,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Reset",IDC_ROM_DIR_RESET,120,66,90,12
+ PUSHBUTTON "Reset",IDC_GBROM_DIR_RESET,120,114,84,12
+ PUSHBUTTON "Reset",IDC_BATTERY_DIR_RESET,120,162,90,12
+ PUSHBUTTON "Reset",IDC_SAVE_DIR_RESET,120,210,90,12
+ PUSHBUTTON "Reset",IDC_CAPTURE_DIR_RESET,120,258,90,12
+ CONTROL "You can either select or enter absolute paths to directories,\nor you can use relative paths by beginning with a . (point).\nExamples: c:\\emulation\\roms | .\\battery | ..\\snapshots\\gba",IDC_STATIC,
+ "Static",SS_LEFTNOWORDWRAP | WS_GROUP,6,6,210,30,WS_EX_STATICEDGE
+ GROUPBOX "Game Boy Advance ROM Images",IDC_STATIC,6,42,210,42
+ GROUPBOX "Game Boy / Game Boy Color ROM Images",IDC_STATIC,6,90,210,42
+ GROUPBOX "Game Boy Internal Battery Saves",IDC_STATIC,6,138,210,42
+ GROUPBOX "Visual Boy Advance Save Games",IDC_STATIC,6,186,210,42
+ GROUPBOX "Screenshots",IDC_STATIC,6,234,210,42
END
-IDD_CONFIG DIALOGEX 0, 0, 209, 230
+IDD_CONFIG DIALOGEX 0, 0, 221, 241
STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Joypad configuration"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
- EDITTEXT IDC_EDIT_UP,45,5,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_DOWN,45,19,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_LEFT,45,33,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_RIGHT,45,47,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_A,45,61,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_B,45,75,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_L,45,89,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_R,45,103,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_SELECT,45,117,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_START,45,131,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_SPEED,45,145,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_CAPTURE,45,159,157,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_BUTTON_GS,45,173,157,12,ES_AUTOHSCROLL
- PUSHBUTTON "OK",ID_OK,63,209,40,14
- PUSHBUTTON "Cancel",ID_CANCEL,113,209,40,14
+ EDITTEXT IDC_EDIT_UP,38,5,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_DOWN,38,19,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_LEFT,38,33,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_RIGHT,38,47,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_A,38,61,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_B,38,75,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_L,38,89,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_R,38,103,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_SELECT,38,117,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_START,38,131,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_SPEED,38,145,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_CAPTURE,38,159,176,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_BUTTON_GS,38,173,176,12,ES_AUTOHSCROLL
+ PUSHBUTTON "OK",ID_OK,61,220,40,14
+ PUSHBUTTON "Cancel",ID_CANCEL,115,220,40,14
LTEXT "Up:",IDC_STATIC,5,5,35,10
LTEXT "Down:",IDC_STATIC,5,19,35,10
LTEXT "Left:",IDC_STATIC,5,33,35,10
@@ -229,11 +210,11 @@ BEGIN
LTEXT "Button R:",IDC_STATIC,5,103,35,10
LTEXT "Select:",IDC_STATIC,5,117,35,10
LTEXT "Start:",IDC_STATIC,5,131,35,10
- LTEXT "Turbo:",IDC_STATIC,5,145,35,10
+ LTEXT "Speed:",IDC_STATIC,5,145,35,10
LTEXT "Capture:",IDC_STATIC,5,159,35,10
LTEXT "GS:",IDC_STATIC,5,173,35,10
CONTROL "Assign additional keys to functions",IDC_APPENDMODE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,47,193,135,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,47,197,135,10
END
IDD_CHEATS DIALOG 0, 0, 276, 253
@@ -331,28 +312,28 @@ BEGIN
GROUPBOX "GB Types",IDC_STATIC,3,3,50,69
END
-IDD_GBA_ROM_INFO DIALOGEX 0, 0, 208, 126
+IDD_GBA_ROM_INFO DIALOG 0, 0, 220, 142
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "ROM Header"
-FONT 8, "MS Sans Serif", 0, 0, 0x0
+CAPTION "Rom information"
+FONT 8, "MS Sans Serif"
BEGIN
- DEFPUSHBUTTON "OK",ID_OK,6,108,198,12
- RTEXT "Game Title:",IDC_STATIC,6,6,60,12
- RTEXT "Game Code:",IDC_STATIC,6,18,60,12
- RTEXT "Maker Code:",IDC_STATIC,6,30,60,12
- RTEXT "Main Unit Code:",IDC_STATIC,6,54,60,12
- RTEXT "Device Type:",IDC_STATIC,6,66,60,12
- RTEXT "ROM Version:",IDC_STATIC,6,78,60,12
- RTEXT "Complement:",IDC_STATIC,6,90,60,12
- LTEXT "",IDC_ROM_TITLE,78,6,126,12
- LTEXT "",IDC_ROM_GAME_CODE,78,18,126,12
- LTEXT "",IDC_ROM_MAKER_CODE,78,30,126,12
- LTEXT "",IDC_ROM_UNIT_CODE,78,54,126,12
- LTEXT "",IDC_ROM_DEVICE_TYPE,78,66,126,12
- LTEXT "",IDC_ROM_VERSION,78,78,126,12
- LTEXT "",IDC_ROM_CRC,78,90,126,12
- LTEXT "",IDC_ROM_MAKER_NAME,78,42,126,12
- RTEXT "Maker Name:",IDC_STATIC,6,42,60,12
+ DEFPUSHBUTTON "OK",ID_OK,84,121,50,14
+ LTEXT "Game title:",IDC_STATIC,7,10,60,8
+ LTEXT "Game code:",IDC_STATIC,7,24,60,8
+ LTEXT "Maker code:",IDC_STATIC,7,38,60,8
+ LTEXT "Main unit code:",IDC_STATIC,7,66,60,8
+ LTEXT "Device type:",IDC_STATIC,7,80,60,8
+ LTEXT "ROM version:",IDC_STATIC,7,94,60,8
+ LTEXT "CRC:",IDC_STATIC,7,108,60,8
+ LTEXT "Maker name:",IDC_STATIC,7,52,60,8
+ LTEXT "",IDC_ROM_TITLE,80,10,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_GAME_CODE,80,24,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_UNIT_CODE,80,66,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_DEVICE_TYPE,80,80,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_VERSION,80,94,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_CRC,80,108,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_MAKER_NAME,80,52,133,8,SS_NOPREFIX
END
IDD_GB_ROM_INFO DIALOG 0, 0, 220, 225
@@ -367,25 +348,25 @@ BEGIN
LTEXT "Cartridge type:",IDC_STATIC,7,82,60,8
LTEXT "ROM version:",IDC_STATIC,7,152,60,8
LTEXT "CRC:",IDC_STATIC,7,166,60,8
- LTEXT "",IDC_ROM_TITLE,80,10,133,8
- LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8
- LTEXT "",IDC_ROM_UNIT_CODE,80,68,133,8
- LTEXT "",IDC_ROM_DEVICE_TYPE,80,82,133,8
- LTEXT "",IDC_ROM_VERSION,80,152,133,8
- LTEXT "",IDC_ROM_CRC,80,166,133,8
+ LTEXT "",IDC_ROM_TITLE,80,10,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_MAKER_CODE,80,38,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_UNIT_CODE,80,68,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_DEVICE_TYPE,80,82,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_VERSION,80,152,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_CRC,80,166,133,8,SS_NOPREFIX
LTEXT "Color:",IDC_STATIC,7,24,60,8
- LTEXT "",IDC_ROM_COLOR,80,24,133,8
+ LTEXT "",IDC_ROM_COLOR,80,24,133,8,SS_NOPREFIX
LTEXT "ROM size:",IDC_STATIC,7,96,60,8
- LTEXT "",IDC_ROM_SIZE,80,96,133,8
+ LTEXT "",IDC_ROM_SIZE,80,96,133,8,SS_NOPREFIX
LTEXT "RAM size:",IDC_STATIC,7,110,60,8
- LTEXT "",IDC_ROM_RAM_SIZE,80,110,133,8
+ LTEXT "",IDC_ROM_RAM_SIZE,80,110,133,8,SS_NOPREFIX
LTEXT "Dest. code:",IDC_STATIC,7,124,60,8
- LTEXT "",IDC_ROM_DEST_CODE,80,124,133,8
+ LTEXT "",IDC_ROM_DEST_CODE,80,124,133,8,SS_NOPREFIX
LTEXT "License code:",IDC_STATIC,7,138,60,8
- LTEXT "",IDC_ROM_LIC_CODE,80,138,133,8
+ LTEXT "",IDC_ROM_LIC_CODE,80,138,133,8,SS_NOPREFIX
LTEXT "Checksum:",IDC_STATIC,7,180,60,8
- LTEXT "",IDC_ROM_CHECKSUM,80,180,133,8
- LTEXT "",IDC_ROM_MAKER_NAME2,80,52,133,8
+ LTEXT "",IDC_ROM_CHECKSUM,80,180,133,8,SS_NOPREFIX
+ LTEXT "",IDC_ROM_MAKER_NAME2,80,52,133,8,SS_NOPREFIX
LTEXT "Maker name:",IDC_STATIC,7,52,60,8
END
@@ -435,23 +416,23 @@ BEGIN
GROUPBOX "Print Size",IDC_STATIC,7,156,162,25
END
-IDD_MOTION_CONFIG DIALOGEX 0, 0, 219, 114
+IDD_MOTION_CONFIG DIALOGEX 0, 0, 234, 107
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Motion Sensor"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
- EDITTEXT IDC_EDIT_UP,49,2,163,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_DOWN,49,16,163,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_LEFT,49,30,163,12,ES_AUTOHSCROLL
- EDITTEXT IDC_EDIT_RIGHT,49,44,163,12,ES_AUTOHSCROLL
- PUSHBUTTON "OK",ID_OK,61,92,40,14
- PUSHBUTTON "Cancel",ID_CANCEL,115,92,40,14
+ EDITTEXT IDC_EDIT_UP,41,2,186,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_DOWN,41,16,186,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_LEFT,41,30,186,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_RIGHT,41,44,186,12,ES_AUTOHSCROLL
+ PUSHBUTTON "OK",ID_OK,64,86,40,14
+ PUSHBUTTON "Cancel",ID_CANCEL,118,86,40,14
LTEXT "Up:",IDC_STATIC,5,2,35,10
LTEXT "Down:",IDC_STATIC,5,16,35,10
LTEXT "Left:",IDC_STATIC,5,30,35,10
LTEXT "Right:",IDC_STATIC,5,44,35,10
CONTROL "Assign additional keys to functions",IDC_APPENDMODE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,47,70,135,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,46,66,135,10
END
IDD_LANG_SELECT DIALOG 0, 0, 186, 68
@@ -464,7 +445,7 @@ BEGIN
PUSHBUTTON "Cancel",ID_CANCEL,104,49,50,14
LTEXT "Current system language is:",IDC_STATIC,6,9,123,8
LTEXT "Enter language name (3 letter):",IDC_STATIC,6,30,127,8
- LTEXT "",IDC_LANG_NAME,140,9,40,8
+ LTEXT "",IDC_LANG_NAME,140,9,40,8,SS_NOPREFIX
END
IDD_CODE_SELECT DIALOG 0, 0, 316, 235
@@ -496,36 +477,36 @@ BEGIN
CONTROL "MapView",IDC_MAP_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,187,15,128,128
CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,148,64,64
CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,187,164,48,47
- LTEXT "",IDC_R,245,173,50,8
- LTEXT "",IDC_G,245,185,50,8
- LTEXT "",IDC_B,245,197,50,8
+ LTEXT "",IDC_R,245,173,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,245,185,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,245,197,50,8,SS_NOPREFIX
GROUPBOX "Frame",IDC_STATIC,7,11,63,37
GROUPBOX "Background",IDC_STATIC,7,52,63,67
- LTEXT "",IDC_XY,129,95,53,8
+ LTEXT "",IDC_XY,129,95,53,8,SS_NOPREFIX
LTEXT "Mode:",IDC_STATIC,80,15,34,8
- LTEXT "",IDC_MODE,130,15,53,8
+ LTEXT "",IDC_MODE,130,15,53,8,SS_NOPREFIX
LTEXT "Map Base:",IDC_STATIC,80,25,35,8
- LTEXT "",IDC_MAPBASE,130,25,53,8
+ LTEXT "",IDC_MAPBASE,130,25,53,8,SS_NOPREFIX
LTEXT "Char Base:",IDC_STATIC,80,35,36,8
- LTEXT "",IDC_CHARBASE,130,35,53,8
+ LTEXT "",IDC_CHARBASE,130,35,53,8,SS_NOPREFIX
LTEXT "Size:",IDC_STATIC,80,45,37,8
- LTEXT "",IDC_DIM,130,45,53,8
+ LTEXT "",IDC_DIM,130,45,53,8,SS_NOPREFIX
LTEXT "Colors:",IDC_STATIC,80,55,37,8
- LTEXT "",IDC_NUMCOLORS,130,55,53,8
+ LTEXT "",IDC_NUMCOLORS,130,55,53,8,SS_NOPREFIX
LTEXT "Priority:",IDC_STATIC,80,65,37,8
- LTEXT "",IDC_PRIORITY,130,65,53,8
+ LTEXT "",IDC_PRIORITY,130,65,53,8,SS_NOPREFIX
LTEXT "Mosaic:",IDC_STATIC,80,75,37,8
- LTEXT "",IDC_MOSAIC,130,75,53,8
+ LTEXT "",IDC_MOSAIC,130,75,53,8,SS_NOPREFIX
LTEXT "Overflow:",IDC_STATIC,80,85,37,8
- LTEXT "",IDC_OVERFLOW,130,85,53,8
+ LTEXT "",IDC_OVERFLOW,130,85,53,8,SS_NOPREFIX
LTEXT "Address:",IDC_STATIC,80,105,37,8
- LTEXT "",IDC_ADDRESS,130,105,53,8
+ LTEXT "",IDC_ADDRESS,130,105,53,8,SS_NOPREFIX
LTEXT "Tile:",IDC_STATIC,80,115,37,8
- LTEXT "",IDC_TILE_NUM,130,115,53,8
+ LTEXT "",IDC_TILE_NUM,130,115,53,8,SS_NOPREFIX
LTEXT "Flip:",IDC_STATIC,80,125,37,8
- LTEXT "",IDC_FLIP,130,125,53,8
+ LTEXT "",IDC_FLIP,130,125,53,8,SS_NOPREFIX
LTEXT "Palette:",IDC_STATIC,80,135,37,8
- LTEXT "",IDC_PALETTE_NUM,130,135,53,8
+ LTEXT "",IDC_PALETTE_NUM,130,135,53,8,SS_NOPREFIX
END
IDD_PALETTE_VIEW DIALOG 0, 0, 316, 266
@@ -537,11 +518,11 @@ BEGIN
PUSHBUTTON "Save OBJ...",IDC_SAVE_OBJ,98,245,50,14
PUSHBUTTON "&Refresh",IDC_REFRESH2,166,245,50,14
PUSHBUTTON "&Close",IDC_CLOSE,234,245,50,14
- LTEXT "",IDC_ADDRESS,53,168,50,8
- LTEXT "",IDC_R,53,180,50,8
- LTEXT "",IDC_G,53,192,50,8
- LTEXT "",IDC_B,53,204,50,8
- LTEXT "",IDC_VALUE,53,216,50,8
+ LTEXT "",IDC_ADDRESS,53,168,50,8,SS_NOPREFIX
+ LTEXT "",IDC_R,53,180,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,53,192,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,53,204,50,8,SS_NOPREFIX
+ LTEXT "",IDC_VALUE,53,216,50,8,SS_NOPREFIX
CONTROL "Custom1",IDC_COLOR,"VbaColorControl",WS_TABSTOP,161,168,50,50
CONTROL "PaletteViewBG",IDC_PALETTE_VIEW,"VbaPaletteViewControl",WS_TABSTOP,12,30,128,128
CONTROL "PaletteViewBG",IDC_PALETTE_VIEW_OBJ,
@@ -592,18 +573,18 @@ BEGIN
CONTROL "MapView",IDC_OAM_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,87,7,64,64
CONTROL "Zoom",IDC_OAM_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,163,7,64,64
CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,87,79,48,47
- LTEXT "",IDC_POS,31,47,50,8
- LTEXT "",IDC_MODE,31,57,50,8
- LTEXT "",IDC_COLORS,31,67,50,8
- LTEXT "",IDC_PALETTE,31,77,50,8
- LTEXT "",IDC_TILE,31,87,50,8
- LTEXT "",IDC_PRIO,31,97,50,8
- LTEXT "",IDC_SIZE2,31,107,50,8
- LTEXT "",IDC_ROT,31,117,50,8
- LTEXT "",IDC_FLAGS,31,127,50,8
- LTEXT "",IDC_R,145,88,50,8
- LTEXT "",IDC_G,145,100,50,8
- LTEXT "",IDC_B,145,112,50,8
+ LTEXT "",IDC_POS,31,47,50,8,SS_NOPREFIX
+ LTEXT "",IDC_MODE,31,57,50,8,SS_NOPREFIX
+ LTEXT "",IDC_COLORS,31,67,50,8,SS_NOPREFIX
+ LTEXT "",IDC_PALETTE,31,77,50,8,SS_NOPREFIX
+ LTEXT "",IDC_TILE,31,87,50,8,SS_NOPREFIX
+ LTEXT "",IDC_PRIO,31,97,50,8,SS_NOPREFIX
+ LTEXT "",IDC_SIZE2,31,107,50,8,SS_NOPREFIX
+ LTEXT "",IDC_ROT,31,117,50,8,SS_NOPREFIX
+ LTEXT "",IDC_FLAGS,31,127,50,8,SS_NOPREFIX
+ LTEXT "",IDC_R,145,88,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,145,100,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,145,112,50,8,SS_NOPREFIX
LTEXT "Pos:",IDC_STATIC,7,47,24,8
LTEXT "Mode:",IDC_STATIC,7,57,24,8
LTEXT "Colors:",IDC_STATIC,7,67,24,8
@@ -659,15 +640,15 @@ BEGIN
GROUPBOX "Char Base",IDC_STATIC,7,46,65,64
CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,174,64,64
CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,98,183,48,47
- LTEXT "",IDC_R,156,192,50,8
- LTEXT "",IDC_G,156,204,50,8
- LTEXT "",IDC_B,156,216,50,8
+ LTEXT "",IDC_R,156,192,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,156,204,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,156,216,50,8,SS_NOPREFIX
LTEXT "Palette:",IDC_STATIC,7,113,65,8
CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,160,71,10
LTEXT "Tile:",IDC_STATIC,79,14,41,8
LTEXT "Address:",IDC_STATIC,79,26,41,8
- LTEXT "",IDC_TILE_NUMBER,135,14,50,8
- LTEXT "",IDC_ADDRESS,135,26,50,8
+ LTEXT "",IDC_TILE_NUMBER,135,14,50,8,SS_NOPREFIX
+ LTEXT "",IDC_ADDRESS,135,26,50,8,SS_NOPREFIX
END
IDD_GB_COLORS DIALOG 0, 0, 169, 121
@@ -717,22 +698,22 @@ BEGIN
LTEXT "R5:",IDC_STATIC,309,47,18,8
LTEXT "R6:",IDC_STATIC,309,55,18,8
LTEXT "R7:",IDC_STATIC,309,63,18,8
- LTEXT "",IDC_R0,344,7,52,8
- LTEXT "",IDC_R1,344,15,52,8
- LTEXT "",IDC_R2,344,23,52,8
- LTEXT "",IDC_R3,344,31,52,8
- LTEXT "",IDC_R4,344,39,52,8
- LTEXT "",IDC_R5,344,47,52,8
- LTEXT "",IDC_R6,344,55,52,8
- LTEXT "",IDC_R7,344,63,52,8
- LTEXT "",IDC_R8,344,71,52,8
- LTEXT "",IDC_R9,344,79,52,8
- LTEXT "",IDC_R10,344,87,52,8
- LTEXT "",IDC_R11,344,95,52,8
- LTEXT "",IDC_R12,344,103,52,8
- LTEXT "",IDC_R13,344,111,52,8
- LTEXT "",IDC_R14,344,119,52,8
- LTEXT "",IDC_R15,344,127,52,8
+ LTEXT "",IDC_R0,344,7,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R1,344,15,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R2,344,23,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R3,344,31,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R4,344,39,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R5,344,47,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R6,344,55,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R7,344,63,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R8,344,71,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R9,344,79,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R10,344,87,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R11,344,95,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R12,344,103,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R13,344,111,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R14,344,119,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R15,344,127,52,8,SS_NOPREFIX
LTEXT "R8:",IDC_STATIC,309,71,18,8
LTEXT "R9:",IDC_STATIC,309,79,18,8
LTEXT "R10:",IDC_STATIC,309,87,18,8
@@ -741,7 +722,7 @@ BEGIN
LTEXT "R13:",IDC_STATIC,309,111,18,8
LTEXT "R14:",IDC_STATIC,309,119,18,8
LTEXT "R15:",IDC_STATIC,309,127,18,8
- LTEXT "",IDC_R16,344,135,52,8
+ LTEXT "",IDC_R16,344,135,52,8,SS_NOPREFIX
LTEXT "R16:",IDC_STATIC,309,135,20,8
CONTROL "N",IDC_N,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,309,146,21,10
CONTROL "Z",IDC_Z,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,309,156,21,10
@@ -751,7 +732,7 @@ BEGIN
CONTROL "I",IDC_I,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,342,146,18,10
CONTROL "T",IDC_T,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,342,166,21,10
LTEXT "Mode:",IDC_STATIC,341,176,21,8
- LTEXT "",IDC_MODE,376,176,20,8
+ LTEXT "",IDC_MODE,376,176,20,8,SS_NOPREFIX
SCROLLBAR IDC_VSCROLL,283,25,10,161,SBS_VERT
PUSHBUTTON "Goto R15",IDC_GOPC,7,204,50,14
END
@@ -774,7 +755,7 @@ FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "Cancel",ID_CANCEL,67,23,50,14
LTEXT "Waiting for connection on port:",IDC_STATIC,7,7,117,8
- LTEXT "",IDC_PORT,143,7,36,8
+ LTEXT "",IDC_PORT,143,7,36,8,SS_NOPREFIX
END
IDD_LOGGING DIALOG 0, 0, 366, 218
@@ -877,11 +858,13 @@ BEGIN
LTEXT "DE:",IDC_STATIC,250,45,18,8
LTEXT "HL:",IDC_STATIC,250,55,18,8
LTEXT "IFF:",IDC_STATIC,250,85,18,8
- LTEXT "",IDC_R0,285,25,52,8
- LTEXT "",IDC_R1,285,35,52,8
- LTEXT "",IDC_R2,285,45,52,8
- LTEXT "",IDC_R3,285,55,52,8
- LTEXT "",IDC_R6,285,85,52,8
+ LTEXT "LY:",IDC_STATIC,272,95,18,8
+ LTEXT "",IDC_R0,285,25,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R1,285,35,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R2,285,45,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R3,285,55,52,8,SS_NOPREFIX
+ LTEXT "",IDC_R6,285,85,52,8,SS_NOPREFIX
+ LTEXT "",IDC_LY,285,95,52,8,SS_NOPREFIX
CONTROL "N",IDC_N,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,109,21,10
CONTROL "Z",IDC_Z,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,97,21,10
CONTROL "C",IDC_C,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,250,133,21,10
@@ -889,9 +872,9 @@ BEGIN
SCROLLBAR IDC_VSCROLL,229,25,10,161,SBS_VERT
PUSHBUTTON "Goto PC",IDC_GOPC,7,204,50,14
LTEXT "SP:",IDC_STATIC,250,65,18,8
- LTEXT "",IDC_R4,285,65,52,8
+ LTEXT "",IDC_R4,285,65,52,8,SS_NOPREFIX
LTEXT "PC:",IDC_STATIC,250,75,18,8
- LTEXT "",IDC_R5,285,75,52,8
+ LTEXT "",IDC_R5,285,75,52,8,SS_NOPREFIX
END
IDD_GB_OAM_VIEW DIALOG 0, 0, 234, 185
@@ -908,15 +891,15 @@ BEGIN
CONTROL "MapView",IDC_OAM_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,87,7,64,64
CONTROL "Zoom",IDC_OAM_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,163,7,64,64
CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,87,79,48,47
- LTEXT "",IDC_POS,31,47,50,8
- LTEXT "",IDC_PALETTE,31,87,50,8
- LTEXT "",IDC_TILE,31,57,50,8
- LTEXT "",IDC_PRIO,31,67,50,8
- LTEXT "",IDC_OAP,31,77,50,8
- LTEXT "",IDC_FLAGS,31,97,50,8
- LTEXT "",IDC_R,145,88,50,8
- LTEXT "",IDC_G,145,100,50,8
- LTEXT "",IDC_B,145,112,50,8
+ LTEXT "",IDC_POS,31,47,50,8,SS_NOPREFIX
+ LTEXT "",IDC_PALETTE,31,87,50,8,SS_NOPREFIX
+ LTEXT "",IDC_TILE,31,57,50,8,SS_NOPREFIX
+ LTEXT "",IDC_PRIO,31,67,50,8,SS_NOPREFIX
+ LTEXT "",IDC_OAP,31,77,50,8,SS_NOPREFIX
+ LTEXT "",IDC_FLAGS,31,97,50,8,SS_NOPREFIX
+ LTEXT "",IDC_R,145,88,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,145,100,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,145,112,50,8,SS_NOPREFIX
LTEXT "Pos:",IDC_STATIC,7,47,24,8
LTEXT "Pal:",IDC_STATIC,7,87,24,8
LTEXT "Tile:",IDC_STATIC,7,57,24,8
@@ -925,7 +908,7 @@ BEGIN
LTEXT "Sprite:",IDC_STATIC,7,7,50,8
LTEXT "Flags:",IDC_STATIC,7,97,24,8
CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,150,71,10
- LTEXT "",IDC_BANK,31,107,50,8
+ LTEXT "",IDC_BANK,31,107,50,8,SS_NOPREFIX
LTEXT "Bank:",IDC_STATIC,7,107,24,8
END
@@ -947,15 +930,15 @@ BEGIN
GROUPBOX "Char Base",IDC_STATIC,7,46,65,35
CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,147,64,64
CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,98,156,48,47
- LTEXT "",IDC_R,156,164,50,8
- LTEXT "",IDC_G,156,176,50,8
- LTEXT "",IDC_B,156,188,50,8
+ LTEXT "",IDC_R,156,164,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,156,176,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,156,188,50,8,SS_NOPREFIX
LTEXT "Palette:",IDC_STATIC,7,86,65,8
CONTROL "Automatic update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,133,71,10
LTEXT "Tile:",IDC_STATIC,79,14,41,8
LTEXT "Address:",IDC_STATIC,79,26,41,8
- LTEXT "",IDC_TILE_NUMBER,135,14,50,8
- LTEXT "",IDC_ADDRESS,135,26,50,8
+ LTEXT "",IDC_TILE_NUMBER,135,14,50,8,SS_NOPREFIX
+ LTEXT "",IDC_ADDRESS,135,26,50,8,SS_NOPREFIX
CONTROL "Slider1",IDC_PALETTE_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,1,98,76,22
END
@@ -975,23 +958,23 @@ BEGIN
CONTROL "MapView",IDC_MAP_VIEW,"VbaBitmapControl",WS_GROUP | WS_TABSTOP,187,15,128,128
CONTROL "Zoom",IDC_MAP_VIEW_ZOOM,"VbaZoomControl",WS_GROUP | WS_TABSTOP,7,148,64,64
CONTROL "Color",IDC_COLOR,"VbaColorControl",WS_TABSTOP,187,164,48,47
- LTEXT "",IDC_R,245,173,50,8
- LTEXT "",IDC_G,245,185,50,8
- LTEXT "",IDC_B,245,197,50,8
+ LTEXT "",IDC_R,245,173,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,245,185,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,245,197,50,8,SS_NOPREFIX
GROUPBOX "Char Base",IDC_STATIC,7,11,63,37
GROUPBOX "Map Base",IDC_STATIC,7,52,63,41
CONTROL "Auto update",IDC_AUTO_UPDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,134,55,10
- LTEXT "",IDC_XY,129,18,53,8
+ LTEXT "",IDC_XY,129,18,53,8,SS_NOPREFIX
LTEXT "Priority:",IDC_STATIC,80,68,37,8
- LTEXT "",IDC_PRIORITY,130,68,53,8
+ LTEXT "",IDC_PRIORITY,130,68,53,8,SS_NOPREFIX
LTEXT "Address:",IDC_STATIC,80,28,37,8
- LTEXT "",IDC_ADDRESS,130,28,53,8
+ LTEXT "",IDC_ADDRESS,130,28,53,8,SS_NOPREFIX
LTEXT "Tile:",IDC_STATIC,80,38,37,8
- LTEXT "",IDC_TILE_NUM,130,38,53,8
+ LTEXT "",IDC_TILE_NUM,130,38,53,8,SS_NOPREFIX
LTEXT "Flip:",IDC_STATIC,80,48,37,8
- LTEXT "",IDC_FLIP,130,48,53,8
+ LTEXT "",IDC_FLIP,130,48,53,8,SS_NOPREFIX
LTEXT "Palette:",IDC_STATIC,80,58,37,8
- LTEXT "",IDC_PALETTE_NUM,130,58,53,8
+ LTEXT "",IDC_PALETTE_NUM,130,58,53,8,SS_NOPREFIX
END
IDD_GB_PALETTE_VIEW DIALOG 0, 0, 196, 234
@@ -1003,11 +986,11 @@ BEGIN
PUSHBUTTON "Save OBJ...",IDC_SAVE_OBJ,73,191,50,14
PUSHBUTTON "&Refresh",IDC_REFRESH2,139,191,50,14
PUSHBUTTON "&Close",IDC_CLOSE,73,213,50,14
- LTEXT "",IDC_ADDRESS,53,117,50,8
- LTEXT "",IDC_R,53,129,50,8
- LTEXT "",IDC_G,53,141,50,8
- LTEXT "",IDC_B,53,153,50,8
- LTEXT "",IDC_VALUE,53,165,50,8
+ LTEXT "",IDC_ADDRESS,53,117,50,8,SS_NOPREFIX
+ LTEXT "",IDC_R,53,129,50,8,SS_NOPREFIX
+ LTEXT "",IDC_G,53,141,50,8,SS_NOPREFIX
+ LTEXT "",IDC_B,53,153,50,8,SS_NOPREFIX
+ LTEXT "",IDC_VALUE,53,165,50,8,SS_NOPREFIX
CONTROL "Custom1",IDC_COLOR,"VbaColorControl",WS_TABSTOP,119,117,50,50
CONTROL "PaletteViewBG",IDC_PALETTE_VIEW,"VbaPaletteViewControl",WS_TABSTOP,11,30,64,64
CONTROL "PaletteViewBG",IDC_PALETTE_VIEW_OBJ,
@@ -1031,7 +1014,7 @@ BEGIN
DEFPUSHBUTTON "OK",ID_OK,31,36,50,14
PUSHBUTTON "Cancel",ID_CANCEL,103,36,50,14
CTEXT "Do you want to keep the current mode?",IDC_STATIC,7,7,172,8
- CTEXT "",IDC_TIMER,7,19,172,8
+ CTEXT "",IDC_TIMER,7,19,172,8,SS_NOPREFIX,WS_EX_TOOLWINDOW
END
IDD_REWIND_INTERVAL DIALOG 0, 0, 186, 68
@@ -1099,19 +1082,26 @@ BEGIN
DEFPUSHBUTTON "&Copy",IDC_COPY,87,164,50,14
END
-IDD_UNIVIDMODE DIALOGEX 0, 0, 268, 114
-STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "Video Mode"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
+IDD_GAME_OVERRIDES DIALOGEX 0, 0, 268, 132
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Game overrides"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
- DEFPUSHBUTTON "OK",IDOK,138,96,60,12
- PUSHBUTTON "Cancel",IDCANCEL,204,96,60,12
- CTEXT "API",IDC_APINAME,138,18,126,12,0,WS_EX_CLIENTEDGE
- LISTBOX IDC_LISTMODES,6,18,126,90,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
- CTEXT "Select video mode:",IDC_STATIC,6,6,126,8
- PUSHBUTTON "Device Name",IDC_DISPLAYDEVICE,138,36,126,12
- PUSHBUTTON "Max scale...",IDC_BUTTON_MAXSCALE,138,60,60,12
- CONTROL "Stretch to fit",IDC_CHECK_STRETCHTOFIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,60,60,12
+ COMBOBOX IDC_RTC,84,42,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_SAVE_TYPE,84,60,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_FLASH_SIZE,84,78,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_MIRRORING,84,96,180,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK",IDOK,6,114,72,12
+ PUSHBUTTON "Defaults",IDC_DEFAULTS,108,114,54,12
+ PUSHBUTTON "Cancel",IDCANCEL,192,114,72,12
+ LTEXT "Game Code",IDC_STATIC,6,6,72,12
+ EDITTEXT IDC_NAME,84,6,180,12,ES_AUTOHSCROLL | WS_DISABLED
+ LTEXT "Real Time Clock:",IDC_STATIC,6,42,72,12
+ LTEXT "Save Type:",IDC_STATIC,6,60,72,12
+ LTEXT "Flash Size:",IDC_STATIC,6,78,72,12
+ LTEXT "Mirroring:",IDC_STATIC,6,96,72,12
+ LTEXT "Comment",IDC_STATIC,6,24,72,12
+ EDITTEXT IDC_COMMENT,84,24,180,12,ES_AUTOHSCROLL
END
@@ -1123,12 +1113,6 @@ END
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
- IDD_LINKTAB, DIALOG
- BEGIN
- RIGHTMARGIN, 249
- BOTTOMMARGIN, 195
- END
-
IDD_OPENDLG, DIALOG
BEGIN
RIGHTMARGIN, 165
@@ -1137,25 +1121,25 @@ BEGIN
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 165
+ RIGHTMARGIN, 150
TOPMARGIN, 7
- BOTTOMMARGIN, 95
+ BOTTOMMARGIN, 71
END
IDD_DIRECTORIES, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 277
+ RIGHTMARGIN, 213
TOPMARGIN, 7
- BOTTOMMARGIN, 122
+ BOTTOMMARGIN, 294
END
IDD_CONFIG, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 202
+ RIGHTMARGIN, 214
TOPMARGIN, 7
- BOTTOMMARGIN, 223
+ BOTTOMMARGIN, 234
END
IDD_CHEATS, DIALOG
@@ -1193,9 +1177,9 @@ BEGIN
IDD_GBA_ROM_INFO, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 201
+ RIGHTMARGIN, 213
TOPMARGIN, 7
- BOTTOMMARGIN, 119
+ BOTTOMMARGIN, 135
END
IDD_GB_ROM_INFO, DIALOG
@@ -1233,9 +1217,9 @@ BEGIN
IDD_MOTION_CONFIG, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 212
+ RIGHTMARGIN, 227
TOPMARGIN, 7
- BOTTOMMARGIN, 107
+ BOTTOMMARGIN, 100
END
IDD_LANG_SELECT, DIALOG
@@ -1462,12 +1446,12 @@ BEGIN
BOTTOMMARGIN, 179
END
- IDD_UNIVIDMODE, DIALOG
+ IDD_GAME_OVERRIDES, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 261
TOPMARGIN, 7
- BOTTOMMARGIN, 107
+ BOTTOMMARGIN, 105
END
END
#endif // APSTUDIO_INVOKED
@@ -1482,12 +1466,12 @@ IDR_MENU MENU
BEGIN
POPUP "&File"
BEGIN
- MENUITEM "&Open GBA...", ID_FILE_OPEN
- MENUITEM "Open GB...", ID_FILE_OPENGAMEBOY
+ MENUITEM "Open...", ID_FILE_OPEN
+ MENUITEM "Open Gameboy...", ID_FILE_OPENGAMEBOY
MENUITEM SEPARATOR
- MENUITEM "&Load...", ID_FILE_LOAD
- MENUITEM "&Save...", ID_FILE_SAVE
- POPUP "Loa&d Game"
+ MENUITEM "Load...", ID_FILE_LOAD
+ MENUITEM "Save...", ID_FILE_SAVE
+ POPUP "Load Game"
BEGIN
MENUITEM "Most recent", ID_FILE_LOADGAME_MOSTRECENT
MENUITEM "Auto load most recent", ID_FILE_LOADGAME_AUTOLOADMOSTRECENT
@@ -1503,7 +1487,7 @@ BEGIN
MENUITEM "Slot #9", ID_FILE_LOADGAME_SLOT9
MENUITEM "Slot #10", ID_FILE_LOADGAME_SLOT10
END
- POPUP "S&ave Game"
+ POPUP "Save Game"
BEGIN
MENUITEM "Oldest slot", ID_FILE_SAVEGAME_OLDESTSLOT
MENUITEM SEPARATOR
@@ -1519,35 +1503,35 @@ BEGIN
MENUITEM "Slot #10", ID_FILE_SAVEGAME_SLOT10
END
MENUITEM SEPARATOR
- MENUITEM "&Pause", ID_FILE_PAUSE
- MENUITEM "&Reset", ID_FILE_RESET
+ MENUITEM "Pause", ID_FILE_PAUSE
+ MENUITEM "Reset", ID_FILE_RESET
MENUITEM SEPARATOR
- POPUP "Re¢"
+ POPUP "Recent"
BEGIN
MENUITEM "&Reset", ID_FILE_RECENT_RESET
MENUITEM "&Freeze", ID_FILE_RECENT_FREEZE
MENUITEM SEPARATOR
END
MENUITEM SEPARATOR
- POPUP "&Import"
+ POPUP "Import"
BEGIN
MENUITEM "&Battery file...", ID_FILE_IMPORT_BATTERYFILE
MENUITEM "Gameshark &code file...", ID_FILE_IMPORT_GAMESHARKCODEFILE
MENUITEM "&Gameshark Snapshot...", ID_FILE_IMPORT_GAMESHARKSNAPSHOT
END
- POPUP "E&xport"
+ POPUP "Export"
BEGIN
MENUITEM "&Battery file...", ID_FILE_EXPORT_BATTERYFILE
MENUITEM "&Gameshark Snapshot...", ID_FILE_EXPORT_GAMESHARKSNAPSHOT
END
MENUITEM SEPARATOR
- MENUITEM "S&creen capture...", ID_FILE_SCREENCAPTURE
- MENUITEM "RO&M Header...", ID_FILE_ROMINFORMATION
- MENUITEM "&Toggle menu", ID_FILE_TOGGLEMENU
+ MENUITEM "Screen capture...", ID_FILE_SCREENCAPTURE
+ MENUITEM "Rom information...", ID_FILE_ROMINFORMATION
+ MENUITEM "Toggle menu", ID_FILE_TOGGLEMENU
MENUITEM SEPARATOR
- MENUITEM "&Close", ID_FILE_CLOSE
+ MENUITEM "Close", ID_FILE_CLOSE
MENUITEM SEPARATOR
- MENUITEM "&Exit", ID_FILE_EXIT
+ MENUITEM "Exit", ID_FILE_EXIT
END
POPUP "&Options"
BEGIN
@@ -1777,10 +1761,8 @@ BEGIN
MENUITEM "EEPROM+Sensor", ID_OPTIONS_EMULATOR_SAVETYPE_EEPROMSENSOR
MENUITEM "None", ID_OPTIONS_EMULATOR_SAVETYPE_NONE
MENUITEM SEPARATOR
- MENUITEM "Flash 64K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K
- MENUITEM "Flash 128K", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M
- MENUITEM SEPARATOR
- MENUITEM "Enhanced detection", ID_OPTIONS_EMULATOR_SAVETYPE_ENHANCEDDETECTION
+ MENUITEM "Flash 64 KB", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH512K
+ MENUITEM "Flash 128 KB", ID_OPTIONS_EMULATOR_SAVETYPE_FLASH1M
END
MENUITEM SEPARATOR
MENUITEM "&Use BIOS file", ID_OPTIONS_EMULATOR_USEBIOSFILE
@@ -1792,13 +1774,13 @@ BEGIN
END
POPUP "&Gameboy"
BEGIN
- MENUITEM "B&order", ID_OPTIONS_GAMEBOY_BORDER
+ MENUITEM "&Border", ID_OPTIONS_GAMEBOY_BORDER
MENUITEM "&Printer", ID_OPTIONS_GAMEBOY_PRINTER
- MENUITEM "Border Au&tomatic", ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC
+ MENUITEM "Border Automatic", ID_OPTIONS_GAMEBOY_BORDERAUTOMATIC
MENUITEM SEPARATOR
MENUITEM "&Automatic", ID_OPTIONS_GAMEBOY_AUTOMATIC
MENUITEM "&GBA", ID_OPTIONS_GAMEBOY_GBA
- MENUITEM "GB&C", ID_OPTIONS_GAMEBOY_CGB
+ MENUITEM "&CGB/GBC", ID_OPTIONS_GAMEBOY_CGB
MENUITEM "&SGB", ID_OPTIONS_GAMEBOY_SGB
MENUITEM "SGB&2", ID_OPTIONS_GAMEBOY_SGB2
MENUITEM "G&B", ID_OPTIONS_GAMEBOY_GB
@@ -1827,11 +1809,10 @@ BEGIN
MENUITEM "&Search for cheats...", ID_CHEATS_SEARCHFORCHEATS
MENUITEM "&Cheat list...", ID_CHEATS_CHEATLIST
MENUITEM SEPARATOR
+ MENUITEM "&Automatic save/load cheats", ID_CHEATS_AUTOMATICSAVELOADCHEATS
+ MENUITEM "Disable cheats", ID_CHEATS_DISABLECHEATS
MENUITEM "&Load cheat list...", ID_CHEATS_LOADCHEATLIST
MENUITEM "Sa&ve cheat list...", ID_CHEATS_SAVECHEATLIST
- MENUITEM SEPARATOR
- MENUITEM "Disable cheats", ID_CHEATS_DISABLECHEATS
- MENUITEM "&Automatic save/load cheats", ID_CHEATS_AUTOMATICSAVELOADCHEATS
END
POPUP "&Tools"
BEGIN
@@ -1843,19 +1824,6 @@ BEGIN
MENUITEM "OAM Viewer...", ID_TOOLS_OAMVIEWER
MENUITEM "&Palette Viewer...", ID_TOOLS_PALETTEVIEW
MENUITEM "Tile Viewer...", ID_TOOLS_TILEVIEWER
- POPUP "Show"
- BEGIN
- MENUITEM "BG 0", ID_OPTIONS_VIDEO_LAYERS_BG0
- MENUITEM "BG 1", ID_OPTIONS_VIDEO_LAYERS_BG1
- MENUITEM "BG 2", ID_OPTIONS_VIDEO_LAYERS_BG2
- MENUITEM "BG 3", ID_OPTIONS_VIDEO_LAYERS_BG3
- MENUITEM "OBJ", ID_OPTIONS_VIDEO_LAYERS_OBJ
- MENUITEM "WIN 0", ID_OPTIONS_VIDEO_LAYERS_WIN0
- MENUITEM "WIN 1", ID_OPTIONS_VIDEO_LAYERS_WIN1
- MENUITEM "OBJ WIN", ID_OPTIONS_VIDEO_LAYERS_OBJWIN
- MENUITEM SEPARATOR
- MENUITEM "SFX", ID_OPTIONS_VIDEO_DISABLESFX
- END
MENUITEM SEPARATOR
MENUITEM "&Next frame", ID_DEBUG_NEXTFRAME
POPUP "GDB"
@@ -1888,6 +1856,7 @@ BEGIN
BEGIN
MENUITEM "Bug Report", ID_HELP_BUGREPORT
MENUITEM "FAQ (website)", ID_HELP_FAQ
+ MENUITEM "License...", ID_HELP_GNUPUBLICLICENSE
MENUITEM SEPARATOR
MENUITEM "&About...", ID_HELP_ABOUT
END
@@ -1956,47 +1925,6 @@ BEGIN
END
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,7,4,0
- PRODUCTVERSION 1,7,4,0
- FILEFLAGSMASK 0x37L
-#ifdef _DEBUG
- FILEFLAGS 0x21L
-#else
- FILEFLAGS 0x20L
-#endif
- FILEOS 0x4L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "Comments", "VisualBoyAdvance comes with NO WARRANTY. Use it at your own risk."
- VALUE "CompanyName", "Forgotten and the VBA team"
- VALUE "FileDescription", "VBA"
- VALUE "FileVersion", "1, 7, 4, 0"
- VALUE "InternalName", "VisualBoyAdvance"
- VALUE "LegalCopyright", "Copyright © 2005 Forgotten and the VBA team"
- VALUE "OriginalFilename", "VisualBoyAdvance.exe"
- VALUE "ProductName", "VisualBoyAdvance emulator"
- VALUE "ProductVersion", "S1.7.4"
- VALUE "SpecialBuild", "S - Changes by Spacy"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-
/////////////////////////////////////////////////////////////////////////////
//
// String Table
@@ -2025,7 +1953,7 @@ END
STRINGTABLE
BEGIN
IDS_ERROR_CREATING_FILE "Error creating file %s"
- IDS_FAILED_TO_READ_SGM "Failed to read complete save game %s (%d)"
+ IDS_FAILED_TO_READ_SGM "Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"
IDS_FAILED_TO_READ_RTC "Failed to read RTC from save game %s (continuing)"
IDS_UNSUPPORTED_VB_SGM "Unsupported VisualBoy save game version %d"
IDS_CANNOT_LOAD_SGM_FOR "Cannot load save game for %s. Playing %s"
@@ -2164,7 +2092,7 @@ BEGIN
IDS_FILTER_GBS "Gameboy Snapshot_*.GBS__"
IDS_FILTER_GCF "Gameshark Code File_*.GCF__"
IDS_SELECT_CODE_FILE "Select code file"
- IDS_SAVE_WILL_BE_LOST "Importing a snapshot file will erase any saved games and reset the emulator. Do you want to continue?"
+ IDS_SAVE_WILL_BE_LOST "Importing a snapshot file will erase any saved games. Do you want to continue?"
IDS_CONFIRM_ACTION "Please confirm action"
IDS_CODES_WILL_BE_LOST "Importing a code file will erase any entered codes. Do you want to continue?"
IDS_FILTER_SPC "Gameshark Code File_*.SPC;*.XPC__"
@@ -2192,6 +2120,7 @@ BEGIN
IDS_INVALID_THROTTLE_VALUE
"Invalid throttle value. Please enter a number between 5 and 1000."
IDS_FILTER_INI "Skin INI File_*.INI__"
+ IDS_SELECT_SKIN_FILE "Select the skin file name"
IDS_FILTER_VMV "VisualBoyAdvance Movie_*.VMV__"
IDS_SELECT_MOVIE_NAME "Select movie name"
IDS_BUG_REPORT "The bug report information is now available on the Windows Clipboard. Please paste it into any bug report made by email or on forums to help solve problems more easily."
@@ -2217,8 +2146,7 @@ END
//
// Generated from the TEXTINCLUDE 3 resource.
//
-
-
+#include "vba.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
diff --git a/src/win32/VideoMode.cpp b/src/win32/VideoMode.cpp
index 3e084ddc..7fec0cdc 100644
--- a/src/win32/VideoMode.cpp
+++ b/src/win32/VideoMode.cpp
@@ -1,365 +1,395 @@
-// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
-// Copyright (C) 1999-2003 Forgotten
-// Copyright (C) 2004 Forgotten and the VBA development team
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or(at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-// VideoMode.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "VBA.h"
-
-#define DIRECTDRAW_VERSION 0x0700
-#include
-
-#include "VideoMode.h"
-
-#include "../System.h"
-#include "..\..\res\resource.h"
-
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-#define MAX_DRIVERS 32 // 32 drivers maximum
-
-//-----------------------------------------------------------------------------
-// Local structures
-//-----------------------------------------------------------------------------
-// Keeps data on the available DDraw drivers
-struct
-{
- char szDescription[128];
- char szName[128];
- GUID *pGUID;
- GUID GUIDcopy;
- HMONITOR hm;
-} Drivers[MAX_DRIVERS];
-
-//-----------------------------------------------------------------------------
-// Local data
-//-----------------------------------------------------------------------------
-static int gDriverCnt = 0; // Total number of drivers
-static GUID *gpSelectedDriverGUID;
-
-//-----------------------------------------------------------------------------
-// Name: DDEnumCallbackEx()
-// Desc: This call back is used to determine the existing available DDraw
-// devices, so the user can pick which one to run on.
-//-----------------------------------------------------------------------------
-BOOL WINAPI
-DDEnumCallbackEx(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID pContext, HMONITOR hm)
-{
- if (pGUID)
- {
- Drivers[gDriverCnt].GUIDcopy = *pGUID;
- Drivers[gDriverCnt].pGUID = &Drivers[gDriverCnt].GUIDcopy;
- }
- else
- Drivers[gDriverCnt].pGUID = NULL;
- Drivers[gDriverCnt].szDescription[127] = '\0';
- Drivers[gDriverCnt].szName[127] = '\0';
- strncpy(Drivers[gDriverCnt].szDescription,pDescription,127);
- strncpy(Drivers[gDriverCnt].szName,pName,127);
- Drivers[gDriverCnt].hm = hm;
- if (gDriverCnt < MAX_DRIVERS)
- gDriverCnt++;
- else
- return DDENUMRET_CANCEL;
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DDEnumCallback()
-// Desc: This callback is used only with old versions of DDraw.
-//-----------------------------------------------------------------------------
-BOOL WINAPI
-DDEnumCallback(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID context)
-{
- return (DDEnumCallbackEx(pGUID, pDescription, pName, context, NULL));
-}
-
-static HRESULT WINAPI addVideoMode(LPDDSURFACEDESC2 surf, LPVOID lpContext)
-{
- HWND h = (HWND)lpContext;
- char buffer[50];
-
- switch(surf->ddpfPixelFormat.dwRGBBitCount) {
- case 16:
- case 24:
- case 32:
- if(surf->dwWidth >= 640 && surf->dwHeight >= 480) {
- sprintf(buffer, "%4dx%4dx%2d", surf->dwWidth, surf->dwHeight,
- surf->ddpfPixelFormat.dwRGBBitCount);
- int pos = ::SendMessage(h, LB_ADDSTRING, 0, (LPARAM)buffer);
- ::SendMessage(h, LB_SETITEMDATA, pos,
- (surf->ddpfPixelFormat.dwRGBBitCount << 24) |
- ((surf->dwWidth & 4095) << 12) |
- (surf->dwHeight & 4095));
- }
- }
-
- return DDENUMRET_OK;
-}
-
-int winVideoModeSelect(CWnd *pWnd, GUID **guid)
-{
- HINSTANCE h = LoadLibrary("ddraw.dll");
-
- // If ddraw.dll doesn't exist in the search path,
- // then DirectX probably isn't installed, so fail.
- if (!h)
- return -1;
-
- gDriverCnt = 0;
-
- // Note that you must know which version of the
- // function to retrieve (see the following text).
- // For this example, we use the ANSI version.
- LPDIRECTDRAWENUMERATEEX lpDDEnumEx;
- lpDDEnumEx = (LPDIRECTDRAWENUMERATEEX)
- GetProcAddress(h,"DirectDrawEnumerateExA");
-
- // If the function is there, call it to enumerate all display
- // devices attached to the desktop, and any non-display DirectDraw
- // devices.
- if (lpDDEnumEx)
- lpDDEnumEx(DDEnumCallbackEx, NULL,
- DDENUM_ATTACHEDSECONDARYDEVICES |
- DDENUM_NONDISPLAYDEVICES
- );
- else {
- /*
- * We must be running on an old version of DirectDraw.
- * Therefore MultiMon isn't supported. Fall back on
- * DirectDrawEnumerate to enumerate standard devices on a
- * single-monitor system.
- */
- BOOL (WINAPI *lpDDEnum)(LPDDENUMCALLBACK, LPVOID);
-
- lpDDEnum = (BOOL (WINAPI *)(LPDDENUMCALLBACK, LPVOID))
- GetProcAddress(h, "DirectDrawEnumerateA");
- if(lpDDEnum)
- lpDDEnum(DDEnumCallback,NULL);
-
- /* Note that it could be handy to let the OldCallback function
- * be a wrapper for a DDEnumCallbackEx.
- *
- * Such a function would look like:
- * BOOL FAR PASCAL OldCallback(GUID FAR *lpGUID,
- * LPSTR pDesc,
- * LPSTR pName,
- * LPVOID pContext)
- * {
- * return Callback(lpGUID,pDesc,pName,pContext,NULL);
- * }
- */
- }
-
- int selected = 0;
-
- if(gDriverCnt > 1) {
- VideoDriverSelect d(pWnd);
-
- selected = d.DoModal();
-
- if(selected == -1) {
- // If the library was loaded by calling LoadLibrary(),
- // then you must use FreeLibrary() to let go of it.
- FreeLibrary(h);
-
- return -1;
- }
- }
-
- HRESULT (WINAPI *DDrawCreateEx)(GUID *,LPVOID *,REFIID,IUnknown *);
- DDrawCreateEx = (HRESULT (WINAPI *)(GUID *,LPVOID *,REFIID,IUnknown *))
- GetProcAddress(h, "DirectDrawCreateEx");
-
- LPDIRECTDRAW7 ddraw = NULL;
- if(DDrawCreateEx) {
- HRESULT hret = DDrawCreateEx(Drivers[selected].pGUID,
- (void **)&ddraw,
- IID_IDirectDraw7,
- NULL);
- if(hret != DD_OK) {
- systemMessage(0, "Error during DirectDrawCreateEx: %08x", hret);
- FreeLibrary(h);
- return -1;
- }
- } else {
- // should not happen....
- systemMessage(0, "Error getting DirectDrawCreateEx");
- FreeLibrary(h);
- return -1;
- }
-
- VideoMode dlg(ddraw, pWnd);
-
- int res = dlg.DoModal();
-
- if(res != -1) {
- *guid = Drivers[selected].pGUID;
- }
- ddraw->Release();
- ddraw = NULL;
-
- // If the library was loaded by calling LoadLibrary(),
- // then you must use FreeLibrary() to let go of it.
- FreeLibrary(h);
-
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// VideoMode dialog
-
-
-VideoMode::VideoMode(LPDIRECTDRAW7 pDraw, CWnd* pParent /*=NULL*/)
- : CDialog(VideoMode::IDD, pParent)
-{
- //{{AFX_DATA_INIT(VideoMode)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- pDirectDraw = pDraw;
-}
-
-
-void VideoMode::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(VideoMode)
- DDX_Control(pDX, IDC_MODES, m_modes);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(VideoMode, CDialog)
- //{{AFX_MSG_MAP(VideoMode)
- ON_LBN_SELCHANGE(IDC_MODES, OnSelchangeModes)
- ON_BN_CLICKED(ID_CANCEL, OnCancel)
- ON_BN_CLICKED(ID_OK, OnOk)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
-// VideoMode message handlers
-
-void VideoMode::OnSelchangeModes()
-{
- int item = m_modes.GetCurSel();
-
- GetDlgItem(ID_OK)->EnableWindow(item != -1);
-}
-
-void VideoMode::OnCancel()
-{
- EndDialog(-1);
-}
-
-void VideoMode::OnOk()
-{
- int cur = m_modes.GetCurSel();
-
- if(cur != -1) {
- cur = m_modes.GetItemData(cur);
- }
- EndDialog(cur);
-}
-
-BOOL VideoMode::OnInitDialog()
-{
- CDialog::OnInitDialog();
-
- // check for available fullscreen modes
- pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, m_modes.m_hWnd,
- addVideoMode);
-
- GetDlgItem(ID_OK)->EnableWindow(FALSE);
- CenterWindow();
-
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// VideoDriverSelect dialog
-
-
-VideoDriverSelect::VideoDriverSelect(CWnd* pParent /*=NULL*/)
- : CDialog(VideoDriverSelect::IDD, pParent)
-{
- //{{AFX_DATA_INIT(VideoDriverSelect)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
-}
-
-
-void VideoDriverSelect::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(VideoDriverSelect)
- DDX_Control(pDX, IDC_DRIVERS, m_drivers);
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(VideoDriverSelect, CDialog)
- //{{AFX_MSG_MAP(VideoDriverSelect)
- ON_BN_CLICKED(ID_OK, OnOk)
- ON_BN_CLICKED(ID_CANCEL, OnCancel)
- ON_LBN_SELCHANGE(IDC_DRIVERS, OnSelchangeDrivers)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
-// VideoDriverSelect message handlers
-
-void VideoDriverSelect::OnCancel()
-{
- EndDialog(-1);
-}
-
-void VideoDriverSelect::OnOk()
-{
- EndDialog(m_drivers.GetCurSel());
-}
-
-BOOL VideoDriverSelect::OnInitDialog()
-{
- CDialog::OnInitDialog();
-
- for(int i = 0; i < gDriverCnt; i++) {
- m_drivers.AddString(Drivers[i].szDescription);
- }
-
- GetDlgItem(ID_OK)->EnableWindow(FALSE);
- CenterWindow();
-
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
-
-void VideoDriverSelect::OnSelchangeDrivers()
-{
- GetDlgItem(ID_OK)->EnableWindow(m_drivers.GetCurSel() != -1);
-}
+// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
+// Copyright (C) 1999-2003 Forgotten
+// Copyright (C) 2004 Forgotten and the VBA development team
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or(at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// VideoMode.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "VBA.h"
+
+#define DIRECTDRAW_VERSION 0x0700
+#include
+
+#include "VideoMode.h"
+
+#include "../System.h"
+#include "resource.h"
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define MAX_DRIVERS 32 // 32 drivers maximum
+
+//-----------------------------------------------------------------------------
+// Local structures
+//-----------------------------------------------------------------------------
+// Keeps data on the available DDraw drivers
+struct
+{
+ char szDescription[128];
+ char szName[128];
+ GUID *pGUID;
+ GUID GUIDcopy;
+ HMONITOR hm;
+} Drivers[MAX_DRIVERS];
+
+//-----------------------------------------------------------------------------
+// Local data
+//-----------------------------------------------------------------------------
+static int gDriverCnt = 0; // Total number of drivers
+static GUID *gpSelectedDriverGUID;
+
+//-----------------------------------------------------------------------------
+// Name: DDEnumCallbackEx()
+// Desc: This call back is used to determine the existing available DDraw
+// devices, so the user can pick which one to run on.
+//-----------------------------------------------------------------------------
+BOOL WINAPI
+DDEnumCallbackEx(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID pContext, HMONITOR hm)
+{
+ if (pGUID)
+ {
+ Drivers[gDriverCnt].GUIDcopy = *pGUID;
+ Drivers[gDriverCnt].pGUID = &Drivers[gDriverCnt].GUIDcopy;
+ }
+ else
+ Drivers[gDriverCnt].pGUID = NULL;
+ Drivers[gDriverCnt].szDescription[127] = '\0';
+ Drivers[gDriverCnt].szName[127] = '\0';
+ strncpy(Drivers[gDriverCnt].szDescription,pDescription,127);
+ strncpy(Drivers[gDriverCnt].szName,pName,127);
+ Drivers[gDriverCnt].hm = hm;
+ if (gDriverCnt < MAX_DRIVERS)
+ gDriverCnt++;
+ else
+ return DDENUMRET_CANCEL;
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DDEnumCallback()
+// Desc: This callback is used only with old versions of DDraw.
+//-----------------------------------------------------------------------------
+BOOL WINAPI
+DDEnumCallback(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID context)
+{
+ return (DDEnumCallbackEx(pGUID, pDescription, pName, context, NULL));
+}
+
+static HRESULT WINAPI addVideoMode(LPDDSURFACEDESC2 surf, LPVOID lpContext)
+{
+ HWND h = (HWND)lpContext;
+ char buffer[50];
+
+ switch( surf->ddpfPixelFormat.dwRGBBitCount )
+ {
+ case 16:
+ case 24:
+ case 32:
+ sprintf(
+ buffer,
+ _T("%4dx%4dx%2d"),
+ surf->dwWidth,
+ surf->dwHeight,
+ surf->ddpfPixelFormat.dwRGBBitCount
+ );
+ WPARAM pos = ::SendMessage( h, LB_ADDSTRING, 0, (LPARAM)buffer );
+ ::SendMessage(
+ h,
+ LB_SETITEMDATA,
+ pos,
+ (surf->ddpfPixelFormat.dwRGBBitCount << 24) |
+ ((surf->dwWidth & 4095) << 12) |
+ (surf->dwHeight & 4095)
+ );
+ break;
+ }
+
+ return DDENUMRET_OK;
+}
+
+int winVideoModeSelect(CWnd *pWnd, GUID **guid)
+{
+#ifdef _AFXDLL
+ HINSTANCE h = AfxLoadLibrary("ddraw.dll");
+#else
+ HMODULE h = LoadLibrary( _T("ddraw.dll") );
+#endif
+
+ // If ddraw.dll doesn't exist in the search path,
+ // then DirectX probably isn't installed, so fail.
+ if (!h)
+ return -1;
+
+ gDriverCnt = 0;
+
+ // Note that you must know which version of the
+ // function to retrieve (see the following text).
+ // For this example, we use the ANSI version.
+ LPDIRECTDRAWENUMERATEEX lpDDEnumEx;
+ lpDDEnumEx = (LPDIRECTDRAWENUMERATEEX)
+ GetProcAddress(h,"DirectDrawEnumerateExA");
+
+ // If the function is there, call it to enumerate all display
+ // devices attached to the desktop, and any non-display DirectDraw
+ // devices.
+ if (lpDDEnumEx)
+ lpDDEnumEx(DDEnumCallbackEx, NULL,
+ DDENUM_ATTACHEDSECONDARYDEVICES |
+ DDENUM_NONDISPLAYDEVICES
+ );
+ else {
+ /*
+ * We must be running on an old version of DirectDraw.
+ * Therefore MultiMon isn't supported. Fall back on
+ * DirectDrawEnumerate to enumerate standard devices on a
+ * single-monitor system.
+ */
+ BOOL (WINAPI *lpDDEnum)(LPDDENUMCALLBACK, LPVOID);
+
+ lpDDEnum = (BOOL (WINAPI *)(LPDDENUMCALLBACK, LPVOID))
+ GetProcAddress(h, "DirectDrawEnumerateA");
+ if(lpDDEnum)
+ lpDDEnum(DDEnumCallback,NULL);
+
+ /* Note that it could be handy to let the OldCallback function
+ * be a wrapper for a DDEnumCallbackEx.
+ *
+ * Such a function would look like:
+ * BOOL FAR PASCAL OldCallback(GUID FAR *lpGUID,
+ * LPSTR pDesc,
+ * LPSTR pName,
+ * LPVOID pContext)
+ * {
+ * return Callback(lpGUID,pDesc,pName,pContext,NULL);
+ * }
+ */
+ }
+
+ int selected = 0;
+
+ if(gDriverCnt > 1) {
+ VideoDriverSelect d(pWnd);
+
+ INT_PTR selected = d.DoModal();
+
+ if(selected == -1) {
+#ifdef _AFXDLL
+ AfxFreeLibrary( h );
+#else
+ FreeLibrary( h );
+#endif
+
+ return -1;
+ }
+ }
+
+ HRESULT (WINAPI *DDrawCreateEx)(GUID *,LPVOID *,REFIID,IUnknown *);
+ DDrawCreateEx = (HRESULT (WINAPI *)(GUID *,LPVOID *,REFIID,IUnknown *))
+ GetProcAddress(h, "DirectDrawCreateEx");
+
+ LPDIRECTDRAW7 ddraw = NULL;
+ if(DDrawCreateEx) {
+ HRESULT hret = DDrawCreateEx(Drivers[selected].pGUID,
+ (void **)&ddraw,
+ IID_IDirectDraw7,
+ NULL);
+ if(hret != DD_OK) {
+ systemMessage(0, "Error during DirectDrawCreateEx: %08x", hret);
+#ifdef _AFXDLL
+ AfxFreeLibrary( h );
+#else
+ FreeLibrary( h );
+#endif
+ return -1;
+ }
+ } else {
+ // should not happen....
+ systemMessage(0, "Error getting DirectDrawCreateEx");
+#ifdef _AFXDLL
+ AfxFreeLibrary( h );
+#else
+ FreeLibrary( h );
+#endif
+ return -1;
+ }
+
+ VideoMode dlg(ddraw, pWnd);
+
+ INT_PTR res = dlg.DoModal();
+
+ if(res != -1) {
+ *guid = Drivers[selected].pGUID;
+ }
+ ddraw->Release();
+ ddraw = NULL;
+
+ // If the library was loaded by calling LoadLibrary(),
+ // then you must use FreeLibrary() to let go of it.
+#ifdef _AFXDLL
+ AfxFreeLibrary( h );
+#else
+ FreeLibrary( h );
+#endif
+
+ return (int)res;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// VideoMode dialog
+
+
+VideoMode::VideoMode(LPDIRECTDRAW7 pDraw, CWnd* pParent /*=NULL*/)
+ : CDialog(VideoMode::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(VideoMode)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ pDirectDraw = pDraw;
+}
+
+
+void VideoMode::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(VideoMode)
+ DDX_Control(pDX, IDC_MODES, m_modes);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(VideoMode, CDialog)
+ //{{AFX_MSG_MAP(VideoMode)
+ ON_LBN_SELCHANGE(IDC_MODES, OnSelchangeModes)
+ ON_BN_CLICKED(ID_CANCEL, OnCancel)
+ ON_BN_CLICKED(ID_OK, OnOk)
+ //}}AFX_MSG_MAP
+ END_MESSAGE_MAP()
+
+ /////////////////////////////////////////////////////////////////////////////
+// VideoMode message handlers
+
+void VideoMode::OnSelchangeModes()
+{
+ int item = m_modes.GetCurSel();
+
+ GetDlgItem(ID_OK)->EnableWindow(item != -1);
+}
+
+void VideoMode::OnCancel()
+{
+ EndDialog(-1);
+}
+
+void VideoMode::OnOk()
+{
+ DWORD_PTR cur = m_modes.GetCurSel();
+
+ if(cur != -1) {
+ cur = m_modes.GetItemData((int)cur);
+ }
+ EndDialog((int)cur);
+}
+
+BOOL VideoMode::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // check for available fullscreen modes
+ pDirectDraw->EnumDisplayModes(
+ DDEDM_STANDARDVGAMODES,
+ NULL,
+ m_modes.m_hWnd,
+ addVideoMode);
+
+ GetDlgItem(ID_OK)->EnableWindow(FALSE);
+ CenterWindow();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// VideoDriverSelect dialog
+
+
+VideoDriverSelect::VideoDriverSelect(CWnd* pParent /*=NULL*/)
+ : CDialog(VideoDriverSelect::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(VideoDriverSelect)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void VideoDriverSelect::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(VideoDriverSelect)
+ DDX_Control(pDX, IDC_DRIVERS, m_drivers);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(VideoDriverSelect, CDialog)
+ //{{AFX_MSG_MAP(VideoDriverSelect)
+ ON_BN_CLICKED(ID_OK, OnOk)
+ ON_BN_CLICKED(ID_CANCEL, OnCancel)
+ ON_LBN_SELCHANGE(IDC_DRIVERS, OnSelchangeDrivers)
+ //}}AFX_MSG_MAP
+ END_MESSAGE_MAP()
+
+ /////////////////////////////////////////////////////////////////////////////
+// VideoDriverSelect message handlers
+
+void VideoDriverSelect::OnCancel()
+{
+ EndDialog(-1);
+}
+
+void VideoDriverSelect::OnOk()
+{
+ EndDialog(m_drivers.GetCurSel());
+}
+
+BOOL VideoDriverSelect::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ for(int i = 0; i < gDriverCnt; i++) {
+ m_drivers.AddString(Drivers[i].szDescription);
+ }
+
+ GetDlgItem(ID_OK)->EnableWindow(FALSE);
+ CenterWindow();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void VideoDriverSelect::OnSelchangeDrivers()
+{
+ GetDlgItem(ID_OK)->EnableWindow(m_drivers.GetCurSel() != -1);
+}
diff --git a/src/win32/ZoomControl.h b/src/win32/ZoomControl.h
index d70b4c98..7a6c7dcd 100644
--- a/src/win32/ZoomControl.h
+++ b/src/win32/ZoomControl.h
@@ -20,7 +20,7 @@
#if !defined(AFX_ZOOMCONTROL_H__BC193230_D2D6_4240_93AE_28C2EF2C641A__INCLUDED_)
#define AFX_ZOOMCONTROL_H__BC193230_D2D6_4240_93AE_28C2EF2C641A__INCLUDED_
-#include "..\System.h" // Added by ClassView
+#include "../System.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
diff --git a/src/win32/dependencies/CVS/Entries b/src/win32/dependencies/CVS/Entries
new file mode 100644
index 00000000..b2877be7
--- /dev/null
+++ b/src/win32/dependencies/CVS/Entries
@@ -0,0 +1,5 @@
+/info.txt/1.1/Fri May 12 21:26:37 2006//
+D/cximage////
+D/libpng////
+D/sdl////
+D/zlib////
diff --git a/src/win32/dependencies/CVS/Repository b/src/win32/dependencies/CVS/Repository
new file mode 100644
index 00000000..e7e98f4c
--- /dev/null
+++ b/src/win32/dependencies/CVS/Repository
@@ -0,0 +1 @@
+VisualBoyAdvance/win32/dependencies
diff --git a/src/win32/dependencies/CVS/Root b/src/win32/dependencies/CVS/Root
new file mode 100644
index 00000000..6ceab0dd
--- /dev/null
+++ b/src/win32/dependencies/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@vba.cvs.sourceforge.net:/cvsroot/vba
diff --git a/src/win32/dependencies/cximage/CVS/Entries b/src/win32/dependencies/cximage/CVS/Entries
new file mode 100644
index 00000000..60478339
--- /dev/null
+++ b/src/win32/dependencies/cximage/CVS/Entries
@@ -0,0 +1,55 @@
+/cximage.vcproj/1.3/Wed Aug 23 22:16:02 2006//
+/license.txt/1.1/Wed Aug 23 22:16:02 2006//
+/tif_xfile.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/xfile.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximabmp.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximabmp.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximacfg.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximadef.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximadsp.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaenc.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaexif.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximage.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximage.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximagif.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximagif.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximahist.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaico.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaico.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximainfo.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaint.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaiter.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximaj2k.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximaj2k.h/1.3/Wed Aug 23 22:16:02 2006//
+/ximajas.cpp/1.3/Wed Aug 23 22:16:02 2006//
+/ximajas.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximajbg.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximajbg.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximajpg.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximajpg.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximalpha.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximalyr.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximamng.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximamng.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximapal.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximapcx.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximapcx.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximapng.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximapng.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximasel.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximatga.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximatga.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximath.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximath.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximatif.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximatif.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximatran.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximawbmp.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximawbmp.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximawmf.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/ximawmf.h/1.3/Wed Aug 23 22:16:03 2006//
+/ximawnd.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/xiofile.h/1.3/Wed Aug 23 22:16:03 2006//
+/xmemfile.cpp/1.3/Wed Aug 23 22:16:03 2006//
+/xmemfile.h/1.3/Wed Aug 23 22:16:03 2006//
+D
diff --git a/src/win32/dependencies/cximage/CVS/Repository b/src/win32/dependencies/cximage/CVS/Repository
new file mode 100644
index 00000000..aa0db2ac
--- /dev/null
+++ b/src/win32/dependencies/cximage/CVS/Repository
@@ -0,0 +1 @@
+VisualBoyAdvance/win32/dependencies/cximage
diff --git a/src/win32/dependencies/cximage/CVS/Root b/src/win32/dependencies/cximage/CVS/Root
new file mode 100644
index 00000000..6ceab0dd
--- /dev/null
+++ b/src/win32/dependencies/cximage/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@vba.cvs.sourceforge.net:/cvsroot/vba
diff --git a/src/win32/dependencies/cximage/cximage.vcproj b/src/win32/dependencies/cximage/cximage.vcproj
new file mode 100644
index 00000000..9799829a
--- /dev/null
+++ b/src/win32/dependencies/cximage/cximage.vcproj
@@ -0,0 +1,367 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/win32/dependencies/cximage/license.txt b/src/win32/dependencies/cximage/license.txt
new file mode 100644
index 00000000..755e2c41
--- /dev/null
+++ b/src/win32/dependencies/cximage/license.txt
@@ -0,0 +1,48 @@
+This copy of the CxImage notices is provided for your convenience. In case of
+any discrepancy between this copy and the notices in the file ximage.h that is
+included in the CxImage distribution, the latter shall prevail.
+
+If you modify CxImage you may insert additional notices immediately following
+this sentence.
+
+--------------------------------------------------------------------------------
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+CxImage version 5.99c 17/Oct/2004
+
+CxImage : Copyright (C) 2001 - 2004, Davide Pizzolato
+
+Original CImage and CImageIterator implementation are:
+Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx)
+
+Covered code is provided under this license on an "as is" basis, without warranty
+of any kind, either expressed or implied, including, without limitation, warranties
+that the covered code is free of defects, merchantable, fit for a particular purpose
+or non-infringing. The entire risk as to the quality and performance of the covered
+code is with you. Should any covered code prove defective in any respect, you (not
+the initial developer or any other contributor) assume the cost of any necessary
+servicing, repair or correction. This disclaimer of warranty constitutes an essential
+part of this license. No use of any covered code is authorized hereunder except under
+this disclaimer.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, including commercial applications,
+freely and without fee, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+--------------------------------------------------------------------------------
+
+Other information: about CxImage, and the latest version, can be found at the
+CxImage home page: http://www.xdp.it
+
+--------------------------------------------------------------------------------
diff --git a/src/win32/dependencies/cximage/tif_xfile.cpp b/src/win32/dependencies/cximage/tif_xfile.cpp
new file mode 100644
index 00000000..edfc943e
--- /dev/null
+++ b/src/win32/dependencies/cximage/tif_xfile.cpp
@@ -0,0 +1,208 @@
+/*
+ * TIFF file IO, using CxFile.
+ */
+
+#ifdef WIN32
+ #include
+#endif
+#include
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_TIF
+
+#include "../tiff/tiffiop.h"
+
+#include "xfile.h"
+
+static tsize_t
+_tiffReadProcEx(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((CxFile*)fd)->Read(buf, 1, size);
+}
+
+static tsize_t
+_tiffWriteProcEx(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((CxFile*)fd)->Write(buf, 1, size);
+}
+
+static toff_t
+_tiffSeekProcEx(thandle_t fd, toff_t off, int whence)
+{
+ if ( off == 0xFFFFFFFF )
+ return 0xFFFFFFFF;
+ if (!((CxFile*)fd)->Seek(off, whence))
+ return 0xFFFFFFFF;
+ if (whence == SEEK_SET)
+ return off;
+
+ return (toff_t)((CxFile*)fd)->Tell();
+}
+
+// Return nonzero if error
+static int
+_tiffCloseProcEx(thandle_t fd)
+{
+// return !((CxFile*)fd)->Close(); // "//" needed for memory files
+ return 0;
+}
+
+#include
+
+static toff_t
+_tiffSizeProcEx(thandle_t fd)
+{
+ return ((CxFile*)fd)->Size();
+}
+
+static int
+_tiffMapProcEx(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProcEx(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+// Open a TIFF file descriptor for read/writing.
+/*
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ FILE* stream = fopen(name, mode);
+ if (stream == NULL)
+ {
+ TIFFError(module, "%s: Cannot open", name);
+ return NULL;
+ }
+ return (TIFFFdOpen((int)stream, name, mode));
+}
+*/
+
+TIFF*
+_TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProcEx, _tiffWriteProcEx, _tiffSeekProcEx, _tiffCloseProcEx,
+ _tiffSizeProcEx, _tiffMapProcEx, _tiffUnmapProcEx);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode)
+{
+ return (_TIFFFdOpen((int)stream, "TIFF IMAGE", mode));
+}
+
+#ifdef __GNUC__
+extern char* malloc();
+extern char* realloc();
+#else
+#include
+#endif
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+Win32WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifdef _DEBUG
+#if (!defined(_CONSOLE) && defined(WIN32))
+ LPTSTR szTitle;
+ LPTSTR szTmp;
+ LPCTSTR szTitleText = "%s Warning";
+ LPCTSTR szDefaultModule = "TIFFLIB";
+ szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module;
+ if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) +
+ lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL)
+ return;
+ wsprintf(szTitle, szTitleText, szTmp);
+ szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR);
+ wvsprintf(szTmp, fmt, ap);
+ MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+#endif
+}
+TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
+
+static void
+Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifdef _DEBUG
+#if (!defined(_CONSOLE) && defined(WIN32))
+ LPTSTR szTitle;
+ LPTSTR szTmp;
+ LPCTSTR szTitleText = "%s Error";
+ LPCTSTR szDefaultModule = "TIFFLIB";
+ szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module;
+ if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) +
+ lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL)
+ return;
+ wsprintf(szTitle, szTitleText, szTmp);
+ szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR);
+ wvsprintf(szTmp, fmt, ap);
+ MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+#endif
+}
+TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
+
+#endif
+
diff --git a/src/win32/dependencies/cximage/xfile.h b/src/win32/dependencies/cximage/xfile.h
new file mode 100644
index 00000000..af10b031
--- /dev/null
+++ b/src/win32/dependencies/cximage/xfile.h
@@ -0,0 +1,76 @@
+/*
+ * File: xfile.h
+ * Purpose: General Purpose File Class
+ */
+/*
+ --------------------------------------------------------------------------------
+
+ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+ CxFile (c) 11/May/2002 Davide Pizzolato - www.xdp.it
+ CxFile version 2.00 23/Aug/2002
+
+ Special thanks to Chris Shearer Cooper for new features, enhancements and bugfixes
+
+ Covered code is provided under this license on an "as is" basis, without warranty
+ of any kind, either expressed or implied, including, without limitation, warranties
+ that the covered code is free of defects, merchantable, fit for a particular purpose
+ or non-infringing. The entire risk as to the quality and performance of the covered
+ code is with you. Should any covered code prove defective in any respect, you (not
+ the initial developer or any other contributor) assume the cost of any necessary
+ servicing, repair or correction. This disclaimer of warranty constitutes an essential
+ part of this license. No use of any covered code is authorized hereunder except under
+ this disclaimer.
+
+ Permission is hereby granted to use, copy, modify, and distribute this
+ source code, or portions hereof, for any purpose, including commercial applications,
+ freely and without fee, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+ --------------------------------------------------------------------------------
+ */
+#if !defined(__xfile_h)
+#define __xfile_h
+
+#ifdef WIN32
+ #include
+#endif
+
+#include
+#include
+
+#include "ximadef.h"
+
+class DLL_EXP CxFile
+{
+public:
+ CxFile(void) { };
+ virtual ~CxFile() { };
+
+ virtual bool Close() = 0;
+ virtual size_t Read(void *buffer, size_t size, size_t count) = 0;
+ virtual size_t Write(const void *buffer, size_t size, size_t count) = 0;
+ virtual bool Seek(long offset, int origin) = 0;
+ virtual long Tell() = 0;
+ virtual long Size() = 0;
+ virtual bool Flush() = 0;
+ virtual bool Eof() = 0;
+ virtual long Error() = 0;
+ virtual bool PutC(unsigned char c)
+ {
+ // Default implementation
+ size_t nWrote = Write(&c, 1, 1);
+ return (bool)(nWrote == 1);
+ }
+ virtual long GetC() = 0;
+};
+
+#endif //__xfile_h
diff --git a/src/win32/dependencies/cximage/ximabmp.cpp b/src/win32/dependencies/cximage/ximabmp.cpp
new file mode 100644
index 00000000..f723ded2
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximabmp.cpp
@@ -0,0 +1,361 @@
+/*
+ * File: ximabmp.cpp
+ * Purpose: Platform Independent BMP Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximabmp.h"
+
+#if CXIMAGE_SUPPORT_BMP
+
+#include "ximaiter.h"
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageBMP::Encode(CxFile * hFile)
+{
+
+ if (EncodeSafeCheck(hFile)) return false;
+
+ BITMAPFILEHEADER hdr;
+
+ hdr.bfType = 0x4d42; // 'BM' WINDOWS_BITMAP_SIGNATURE
+ hdr.bfSize = GetSize() + 14 /*sizeof(BITMAPFILEHEADER)*/;
+ hdr.bfReserved1 = hdr.bfReserved2 = 0;
+ hdr.bfOffBits = 14 /*sizeof(BITMAPFILEHEADER)*/ + head.biSize + GetPaletteSize();
+
+ //copy attributes
+ memcpy(pDib,&head,sizeof(BITMAPINFOHEADER));
+ // Write the file header
+ hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1);
+ // Write the DIB header and the pixels
+ hFile->Write(pDib,GetSize(),1);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageBMP::Decode(CxFile * hFile)
+{
+ if (hFile == NULL) return false;
+
+ BITMAPFILEHEADER bf;
+ DWORD off = hFile->Tell(); //
+ try {
+ if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) throw "Not a BMP";
+ if (bf.bfType != BFT_BITMAP) { //do we have a RC HEADER?
+ bf.bfOffBits = 0L;
+ hFile->Seek(off,SEEK_SET);
+ }
+
+ BITMAPINFOHEADER bmpHeader;
+ if (!DibReadBitmapInfo(hFile,&bmpHeader)) throw "Error reading BMP info";
+ DWORD dwCompression=bmpHeader.biCompression;
+ DWORD dwBitCount=bmpHeader.biBitCount; //preserve for BI_BITFIELDS compression
+ bool bIsOldBmp = bmpHeader.biSize == sizeof(BITMAPCOREHEADER);
+
+ bool bTopDownDib = bmpHeader.biHeight<0; // check if it's a top-down bitmap
+ if (bTopDownDib) bmpHeader.biHeight=-bmpHeader.biHeight;
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = bmpHeader.biWidth;
+ head.biHeight = bmpHeader.biHeight;
+ throw "output dimensions returned";
+ }
+
+ if (!Create(bmpHeader.biWidth,bmpHeader.biHeight,bmpHeader.biBitCount,CXIMAGE_FORMAT_BMP))
+ throw "Can't allocate memory";
+
+ head.biXPelsPerMeter = bmpHeader.biXPelsPerMeter;
+ head.biYPelsPerMeter = bmpHeader.biYPelsPerMeter;
+ info.xDPI = (long) floor(bmpHeader.biXPelsPerMeter * 254.0 / 10000.0 + 0.5);
+ info.yDPI = (long) floor(bmpHeader.biYPelsPerMeter * 254.0 / 10000.0 + 0.5);
+
+ if (info.nEscape) throw "Cancelled"; // - cancel decoding
+
+ RGBQUAD *pRgb = GetPalette();
+ if (pRgb){
+ if (bIsOldBmp){
+ // convert a old color table (3 byte entries) to a new
+ // color table (4 byte entries)
+ hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1);
+ for (int i=DibNumColors(&head)-1; i>=0; i--){
+ pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed;
+ pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue;
+ pRgb[i].rgbGreen = ((RGBTRIPLE *)pRgb)[i].rgbtGreen;
+ pRgb[i].rgbReserved = (BYTE)0;
+ }
+ } else {
+ hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);
+ //force rgbReserved=0, to avoid problems with some WinXp bitmaps
+ for (unsigned int i=0; i - cancel decoding
+
+ switch (dwBitCount) {
+ case 32 :
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){
+ long imagesize=4*head.biHeight*head.biWidth;
+ BYTE* buff32=(BYTE*)malloc(imagesize);
+ if (buff32){
+ hFile->Read(buff32, imagesize,1); // read in the pixels
+ Bitfield2RGB(buff32,0,0,0,32);
+ free(buff32);
+ } else throw "can't allocate memory";
+ } else throw "unknown compression";
+ break;
+ case 24 :
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ if (dwCompression == BI_RGB){
+ hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
+ } else throw "unknown compression";
+ break;
+ case 16 :
+ {
+ DWORD bfmask[3];
+ if (dwCompression == BI_BITFIELDS)
+ {
+ hFile->Read(bfmask, 12, 1);
+ } else {
+ bfmask[0]=0x7C00; bfmask[1]=0x3E0; bfmask[2]=0x1F; //RGB555
+ }
+ // bf.bfOffBits required after the bitfield mask
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ // read in the pixels
+ hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1);
+ // transform into RGB
+ Bitfield2RGB(info.pImage,(WORD)bfmask[0],(WORD)bfmask[1],(WORD)bfmask[2],16);
+ break;
+ }
+ case 8 :
+ case 4 :
+ case 1 :
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ switch (dwCompression) {
+ case BI_RGB :
+ hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
+ break;
+ case BI_RLE4 :
+ {
+ BYTE status_byte = 0;
+ BYTE second_byte = 0;
+ int scanline = 0;
+ int bits = 0;
+ BOOL low_nibble = FALSE;
+ CImageIterator iter(this);
+
+ for (BOOL bContinue = TRUE; bContinue;) {
+ hFile->Read(&status_byte, sizeof(BYTE), 1);
+ switch (status_byte) {
+ case RLE_COMMAND :
+ hFile->Read(&status_byte, sizeof(BYTE), 1);
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ low_nibble = FALSE;
+ break;
+ case RLE_ENDOFBITMAP :
+ bContinue=FALSE;
+ break;
+ case RLE_DELTA :
+ {
+ // read the delta values
+ BYTE delta_x;
+ BYTE delta_y;
+ hFile->Read(&delta_x, sizeof(BYTE), 1);
+ hFile->Read(&delta_y, sizeof(BYTE), 1);
+ // apply them
+ bits += delta_x / 2;
+ scanline += delta_y;
+ break;
+ }
+ default :
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ BYTE *sline = iter.GetRow(scanline);
+ for (int i = 0; i < status_byte; i++) {
+ if (low_nibble) {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) |= (second_byte & 0x0F);
+ }
+ if (i != status_byte - 1)
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ bits++;
+ } else {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) = (BYTE)(second_byte & 0xF0);
+ }
+ }
+ low_nibble = !low_nibble;
+ }
+ if ((((status_byte+1) >> 1) & 1 )== 1)
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ break;
+ };
+ break;
+ default :
+ {
+ BYTE *sline = iter.GetRow(scanline);
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ for (unsigned i = 0; i < status_byte; i++) {
+ if (low_nibble) {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) |= (second_byte & 0x0F);
+ }
+ bits++;
+ } else {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) = (BYTE)(second_byte & 0xF0);
+ }
+ }
+ low_nibble = !low_nibble;
+ }
+ }
+ break;
+ };
+ }
+ break;
+ }
+ case BI_RLE8 :
+ {
+ BYTE status_byte = 0;
+ BYTE second_byte = 0;
+ int scanline = 0;
+ int bits = 0;
+ CImageIterator iter(this);
+
+ for (BOOL bContinue = TRUE; bContinue; ) {
+ hFile->Read(&status_byte, sizeof(BYTE), 1);
+ switch (status_byte) {
+ case RLE_COMMAND :
+ hFile->Read(&status_byte, sizeof(BYTE), 1);
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ break;
+ case RLE_ENDOFBITMAP :
+ bContinue=FALSE;
+ break;
+ case RLE_DELTA :
+ {
+ // read the delta values
+ BYTE delta_x;
+ BYTE delta_y;
+ hFile->Read(&delta_x, sizeof(BYTE), 1);
+ hFile->Read(&delta_y, sizeof(BYTE), 1);
+ // apply them
+ bits += delta_x;
+ scanline += delta_y;
+ break;
+ }
+ default :
+ hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(BYTE) * status_byte, 1);
+ // align run length to even number of bytes
+ if ((status_byte & 1) == 1)
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ bits += status_byte;
+ break;
+ };
+ break;
+ default :
+ BYTE *sline = iter.GetRow(scanline);
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ for (unsigned i = 0; i < status_byte; i++) {
+ if ((DWORD)bits
+
+ } catch (char *message) {
+ strncpy(info.szLastError,message,255);
+ if (info.nEscape==-1) return true;
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/* ReadDibBitmapInfo()
+ *
+ * Will read a file in DIB format and return a global HANDLE to its
+ * BITMAPINFO. This function will work with both "old" and "new"
+ * bitmap formats, but will always return a "new" BITMAPINFO.
+ */
+bool CxImageBMP::DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib)
+{
+ if ((fh==NULL)||(pdib==NULL)) return false;
+
+ if (fh->Read(pdib,sizeof(BITMAPINFOHEADER),1)==0) return false;
+
+ BITMAPCOREHEADER bc;
+
+ switch (pdib->biSize) // what type of bitmap info is this?
+ {
+ case sizeof(BITMAPINFOHEADER):
+ break;
+
+ case 64: //sizeof(OS2_BMP_HEADER):
+ fh->Seek((long)(64 - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+ break;
+
+ case sizeof(BITMAPCOREHEADER):
+ bc = *(BITMAPCOREHEADER*)pdib;
+ pdib->biSize = bc.bcSize;
+ pdib->biWidth = (DWORD)bc.bcWidth;
+ pdib->biHeight = (DWORD)bc.bcHeight;
+ pdib->biPlanes = bc.bcPlanes;
+ pdib->biBitCount = bc.bcBitCount;
+ pdib->biCompression = BI_RGB;
+ pdib->biSizeImage = 0;
+ pdib->biXPelsPerMeter = 0;
+ pdib->biYPelsPerMeter = 0;
+ pdib->biClrUsed = 0;
+ pdib->biClrImportant = 0;
+
+ fh->Seek((long)(sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER)), SEEK_CUR);
+
+ break;
+ default:
+ //give a last chance
+ if (pdib->biSize>(sizeof(BITMAPINFOHEADER))&&
+ (pdib->biSizeImage==(unsigned long)(pdib->biHeight*((((pdib->biBitCount*pdib->biWidth)+31)/32)*4)))&&
+ (pdib->biPlanes==1)&&(pdib->biCompression==BI_RGB)&&(pdib->biClrUsed==0))
+ {
+ fh->Seek((long)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+ break;
+ }
+ return false;
+ }
+
+ FixBitmapInfo(pdib);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_BMP
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/win32/dependencies/cximage/ximabmp.h b/src/win32/dependencies/cximage/ximabmp.h
new file mode 100644
index 00000000..2bda4feb
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximabmp.h
@@ -0,0 +1,79 @@
+/*
+ * File: ximabmp.h
+ * Purpose: BMP Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageBMP (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * original CImageBMP and CImageIterator implementation are:
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra
+ *
+ * ==========================================================
+ */
+
+#if !defined(__ximaBMP_h)
+#define __ximaBMP_h
+
+#include "ximage.h"
+
+const int RLE_COMMAND = 0;
+const int RLE_ENDOFLINE = 0;
+const int RLE_ENDOFBITMAP = 1;
+const int RLE_DELTA = 2;
+
+#if !defined(BI_RLE8)
+ #define BI_RLE8 1L
+#endif
+#if !defined(BI_RLE4)
+ #define BI_RLE4 2L
+#endif
+
+#if CXIMAGE_SUPPORT_BMP
+
+class CxImageBMP: public CxImage
+{
+public:
+ CxImageBMP(): CxImage(CXIMAGE_FORMAT_BMP) {};
+
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+protected:
+ bool DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib);
+};
+
+#define BFT_ICON 0x4349 /* 'IC' */
+#define BFT_BITMAP 0x4d42 /* 'BM' */
+#define BFT_CURSOR 0x5450 /* 'PT' */
+
+#ifndef WIDTHBYTES
+#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
+#endif
+
+#endif
+
+#define DibWidthBytesN(lpbi, n) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)(n))
+#define DibWidthBytes(lpbi) DibWidthBytesN(lpbi, (lpbi)->biBitCount)
+
+#define DibSizeImage(lpbi) ((lpbi)->biSizeImage == 0 \
+ ? ((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)(lpbi)->biHeight) \
+ : (lpbi)->biSizeImage)
+
+#define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
+ ? (int)(1 << (int)(lpbi)->biBitCount) \
+ : (int)(lpbi)->biClrUsed)
+
+#define FixBitmapInfo(lpbi) if ((lpbi)->biSizeImage == 0) \
+ (lpbi)->biSizeImage = DibSizeImage(lpbi); \
+ if ((lpbi)->biClrUsed == 0) \
+ (lpbi)->biClrUsed = DibNumColors(lpbi); \
+
+#endif
diff --git a/src/win32/dependencies/cximage/ximacfg.h b/src/win32/dependencies/cximage/ximacfg.h
new file mode 100644
index 00000000..a28b35ed
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximacfg.h
@@ -0,0 +1,52 @@
+#if !defined(__ximaCFG_h)
+#define __ximaCFG_h
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported features
+#define CXIMAGE_SUPPORT_ALPHA 1
+#define CXIMAGE_SUPPORT_SELECTION 1
+#define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#define CXIMAGE_SUPPORT_DSP 1
+#define CXIMAGE_SUPPORT_LAYERS 1
+#define CXIMAGE_SUPPORT_INTERPOLATION 1
+
+#define CXIMAGE_SUPPORT_DECODE 1
+#define CXIMAGE_SUPPORT_ENCODE 1 //
+#define CXIMAGE_SUPPORT_WINDOWS 1
+#define CXIMAGE_SUPPORT_WINCE 0 //
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported formats
+#define CXIMAGE_SUPPORT_BMP 1
+#define CXIMAGE_SUPPORT_GIF 1
+#define CXIMAGE_SUPPORT_JPG 0
+#define CXIMAGE_SUPPORT_PNG 0
+#define CXIMAGE_SUPPORT_MNG 0
+#define CXIMAGE_SUPPORT_ICO 1
+#define CXIMAGE_SUPPORT_TIF 0
+#define CXIMAGE_SUPPORT_TGA 1
+#define CXIMAGE_SUPPORT_PCX 1
+#define CXIMAGE_SUPPORT_WBMP 1
+#define CXIMAGE_SUPPORT_WMF 1
+#define CXIMAGE_SUPPORT_J2K 0 // Beta, use JP2
+#define CXIMAGE_SUPPORT_JBG 0 // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm
+
+#define CXIMAGE_SUPPORT_JP2 0
+#define CXIMAGE_SUPPORT_JPC 0
+#define CXIMAGE_SUPPORT_PGX 0
+#define CXIMAGE_SUPPORT_PNM 0
+#define CXIMAGE_SUPPORT_RAS 0
+
+
+/////////////////////////////////////////////////////////////////////////////
+#define CXIMAGE_MAX_MEMORY 256000000
+
+#define CXIMAGE_ERR_NOFILE "null file handler"
+#define CXIMAGE_ERR_NOIMAGE "null image!!!"
+
+/////////////////////////////////////////////////////////////////////////////
+//color to grey mapping
+//#define RGB2GRAY(r,g,b) (((b)*114 + (g)*587 + (r)*299)/1000)
+#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10)
+
+#endif
diff --git a/src/win32/dependencies/cximage/ximadef.h b/src/win32/dependencies/cximage/ximadef.h
new file mode 100644
index 00000000..6f3d10db
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximadef.h
@@ -0,0 +1,197 @@
+#if !defined(__ximadefs_h)
+#define __ximadefs_h
+
+#include "ximacfg.h"
+
+#if defined(_AFXDLL)||defined(_USRDLL)
+ #define DLL_EXP __declspec(dllexport)
+#elif defined(_MSC_VER)&&(_MSC_VER<1200)
+ #define DLL_EXP __declspec(dllimport)
+#else
+ #define DLL_EXP
+#endif
+
+#if CXIMAGE_SUPPORT_JP2 || CXIMAGE_SUPPORT_JPC || CXIMAGE_SUPPORT_PGX || CXIMAGE_SUPPORT_PNM || CXIMAGE_SUPPORT_RAS
+ #define CXIMAGE_SUPPORT_JASPER 1
+#else
+ #define CXIMAGE_SUPPORT_JASPER 0
+#endif
+
+#if CXIMAGE_SUPPORT_DSP
+#undef CXIMAGE_SUPPORT_TRANSFORMATION
+ #define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#endif
+
+#if CXIMAGE_SUPPORT_TRANSFORMATION || CXIMAGE_SUPPORT_TIF || CXIMAGE_SUPPORT_TGA || CXIMAGE_SUPPORT_BMP || CXIMAGE_SUPPORT_WINDOWS
+ #define CXIMAGE_SUPPORT_BASICTRANSFORMATIONS 1
+#endif
+
+#if CXIMAGE_SUPPORT_DSP || CXIMAGE_SUPPORT_TRANSFORMATION
+#undef CXIMAGE_SUPPORT_INTERPOLATION
+ #define CXIMAGE_SUPPORT_INTERPOLATION 1
+#endif
+
+#if CXIMAGE_SUPPORT_WINCE
+ #undef CXIMAGE_SUPPORT_WMF
+ #define CXIMAGE_SUPPORT_WMF 0
+ #undef CXIMAGE_SUPPORT_WINDOWS
+ #define CXIMAGE_SUPPORT_WINDOWS 0
+#endif
+
+#ifndef WIN32
+ #undef CXIMAGE_SUPPORT_WINDOWS
+ #define CXIMAGE_SUPPORT_WINDOWS 0
+#endif
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#ifndef PI
+ #define PI 3.141592653589793f
+#endif
+
+
+#ifdef WIN32
+#include
+#include
+#endif
+
+#include
+#include
+
+
+#ifdef __BORLANDC__
+
+#ifndef _COMPLEX_DEFINED
+
+typedef struct tagcomplex {
+ double x,y;
+} _complex;
+
+#endif
+
+#define _cabs(c) sqrt(c.x*c.x+c.y*c.y)
+
+#endif
+
+
+#ifndef WIN32
+
+#include
+#include
+#include
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef unsigned int UINT;
+
+typedef DWORD COLORREF;
+typedef unsigned int HANDLE;
+typedef void* HRGN;
+
+#ifndef BOOL
+#define BOOL bool
+#endif
+
+#ifndef TRUE
+#define TRUE true
+#endif
+
+#ifndef FALSE
+#define FALSE false
+#endif
+
+#ifndef TCHAR
+#define TCHAR char
+#define _T
+#endif
+
+typedef struct tagRECT
+{
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECT;
+
+typedef struct tagPOINT
+{
+ long x;
+ long y;
+} POINT;
+
+typedef struct tagRGBQUAD {
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+ BYTE rgbReserved;
+} RGBQUAD;
+
+#pragma pack(1)
+
+typedef struct tagBITMAPINFOHEADER{
+ DWORD biSize;
+ long biWidth;
+ long biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+ DWORD biCompression;
+ DWORD biSizeImage;
+ long biXPelsPerMeter;
+ long biYPelsPerMeter;
+ DWORD biClrUsed;
+ DWORD biClrImportant;
+} BITMAPINFOHEADER;
+
+typedef struct tagBITMAPFILEHEADER {
+ WORD bfType;
+ DWORD bfSize;
+ WORD bfReserved1;
+ WORD bfReserved2;
+ DWORD bfOffBits;
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPCOREHEADER {
+ DWORD bcSize;
+ WORD bcWidth;
+ WORD bcHeight;
+ WORD bcPlanes;
+ WORD bcBitCount;
+} BITMAPCOREHEADER;
+
+typedef struct tagRGBTRIPLE {
+ BYTE rgbtBlue;
+ BYTE rgbtGreen;
+ BYTE rgbtRed;
+} RGBTRIPLE;
+
+#pragma pack()
+
+#define BI_RGB 0L
+#define BI_RLE8 1L
+#define BI_RLE4 2L
+#define BI_BITFIELDS 3L
+
+#define GetRValue(rgb) ((BYTE)(rgb))
+#define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
+#define GetBValue(rgb) ((BYTE)((rgb)>>16))
+#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
+
+#ifndef _COMPLEX_DEFINED
+
+typedef struct tagcomplex {
+ double x,y;
+} _complex;
+
+#endif
+
+#define _cabs(c) sqrt(c.x*c.x+c.y*c.y)
+
+#endif
+
+#endif //__ximadefs
diff --git a/src/win32/dependencies/cximage/ximadsp.cpp b/src/win32/dependencies/cximage/ximadsp.cpp
new file mode 100644
index 00000000..d6a2ef56
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximadsp.cpp
@@ -0,0 +1,2370 @@
+// xImaDsp.cpp : DSP functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximage.h"
+
+#include "ximaiter.h"
+
+#if CXIMAGE_SUPPORT_DSP
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the image to B&W.
+ * The Mean() function can be used for calculating the optimal threshold.
+ * \param level: the lightness threshold.
+ * \return true if everything is ok
+ */
+bool CxImage::Threshold(BYTE level)
+{
+ if (!pDib) return false;
+ if (head.biBitCount == 1) return true;
+
+ GrayScale();
+
+ CxImage tmp(head.biWidth,head.biHeight,1);
+ if (!tmp.IsValid()) return false;
+
+ for (long y=0;ylevel)
+ tmp.SetPixelIndex(x,y,1);
+ else
+ tmp.SetPixelIndex(x,y,0);
+ }
+ }
+ tmp.SetPaletteColor(0,0,0,0);
+ tmp.SetPaletteColor(1,255,255,255);
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract RGB channels from the image. Each channel is an 8 bit grayscale image.
+ * \param r,g,b: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitRGB(CxImage* r,CxImage* g,CxImage* b)
+{
+ if (!pDib) return false;
+ if (r==NULL && g==NULL && b==NULL) return false;
+
+ CxImage tmpr(head.biWidth,head.biHeight,8);
+ CxImage tmpg(head.biWidth,head.biHeight,8);
+ CxImage tmpb(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(long y=0; yTransfer(tmpr);
+ if (g) g->Transfer(tmpg);
+ if (b) b->Transfer(tmpb);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract CMYK channels from the image. Each channel is an 8 bit grayscale image.
+ * \param c,m,y,k: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k)
+{
+ if (!pDib) return false;
+ if (c==NULL && m==NULL && y==NULL && k==NULL) return false;
+
+ CxImage tmpc(head.biWidth,head.biHeight,8);
+ CxImage tmpm(head.biWidth,head.biHeight,8);
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpk(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(long yy=0; yyTransfer(tmpc);
+ if (m) m->Transfer(tmpm);
+ if (y) y->Transfer(tmpy);
+ if (k) k->Transfer(tmpk);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract YUV channels from the image. Each channel is an 8 bit grayscale image.
+ * \param y,u,v: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitYUV(CxImage* y,CxImage* u,CxImage* v)
+{
+ if (!pDib) return false;
+ if (y==NULL && u==NULL && v==NULL) return false;
+
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpu(head.biWidth,head.biHeight,8);
+ CxImage tmpv(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(long yy=0; yyTransfer(tmpy);
+ if (u) u->Transfer(tmpu);
+ if (v) v->Transfer(tmpv);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract YIQ channels from the image. Each channel is an 8 bit grayscale image.
+ * \param y,i,q: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitYIQ(CxImage* y,CxImage* i,CxImage* q)
+{
+ if (!pDib) return false;
+ if (y==NULL && i==NULL && q==NULL) return false;
+
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpi(head.biWidth,head.biHeight,8);
+ CxImage tmpq(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(long yy=0; yyTransfer(tmpy);
+ if (i) i->Transfer(tmpi);
+ if (q) q->Transfer(tmpq);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract XYZ channels from the image. Each channel is an 8 bit grayscale image.
+ * \param x,y,z: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitXYZ(CxImage* x,CxImage* y,CxImage* z)
+{
+ if (!pDib) return false;
+ if (x==NULL && y==NULL && z==NULL) return false;
+
+ CxImage tmpx(head.biWidth,head.biHeight,8);
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpz(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(long yy=0; yyTransfer(tmpx);
+ if (y) y->Transfer(tmpy);
+ if (z) z->Transfer(tmpz);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract HSL channels from the image. Each channel is an 8 bit grayscale image.
+ * \param h,s,l: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitHSL(CxImage* h,CxImage* s,CxImage* l)
+{
+ if (!pDib) return false;
+ if (h==NULL && s==NULL && l==NULL) return false;
+
+ CxImage tmph(head.biWidth,head.biHeight,8);
+ CxImage tmps(head.biWidth,head.biHeight,8);
+ CxImage tmpl(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(long y=0; yTransfer(tmph);
+ if (s) s->Transfer(tmps);
+ if (l) l->Transfer(tmpl);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#define HSLMAX 255 /* H,L, and S vary over 0-HSLMAX */
+#define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */
+ /* HSLMAX BEST IF DIVISIBLE BY 6 */
+ /* RGBMAX, HSLMAX must each fit in a BYTE. */
+/* Hue is undefined if Saturation is 0 (grey-scale) */
+/* This value determines where the Hue scrollbar is */
+/* initially set for achromatic colors */
+#define HSLUNDEFINED (HSLMAX*2/3)
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoHSL(RGBQUAD lRGBColor)
+{
+ BYTE R,G,B; /* input RGB values */
+ BYTE H,L,S; /* output HSL values */
+ BYTE cMax,cMin; /* max and min RGB values */
+ WORD Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max*/
+
+ R = lRGBColor.rgbRed; /* get R, G, and B out of DWORD */
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+ cMax = max( max(R,G), B); /* calculate lightness */
+ cMin = min( min(R,G), B);
+ L = (BYTE)((((cMax+cMin)*HSLMAX)+RGBMAX)/(2*RGBMAX));
+
+ if (cMax==cMin){ /* r=g=b --> achromatic case */
+ S = 0; /* saturation */
+ H = HSLUNDEFINED; /* hue */
+ } else { /* chromatic case */
+ if (L <= (HSLMAX/2)) /* saturation */
+ S = (BYTE)((((cMax-cMin)*HSLMAX)+((cMax+cMin)/2))/(cMax+cMin));
+ else
+ S = (BYTE)((((cMax-cMin)*HSLMAX)+((2*RGBMAX-cMax-cMin)/2))/(2*RGBMAX-cMax-cMin));
+ /* hue */
+ Rdelta = (WORD)((((cMax-R)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+ Gdelta = (WORD)((((cMax-G)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+ Bdelta = (WORD)((((cMax-B)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+
+ if (R == cMax)
+ H = (BYTE)(Bdelta - Gdelta);
+ else if (G == cMax)
+ H = (BYTE)((HSLMAX/3) + Rdelta - Bdelta);
+ else /* B == cMax */
+ H = (BYTE)(((2*HSLMAX)/3) + Gdelta - Rdelta);
+
+// if (H < 0) H += HSLMAX; //always false
+ if (H > HSLMAX) H -= HSLMAX;
+ }
+ RGBQUAD hsl={L,S,H,0};
+ return hsl;
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::HueToRGB(float n1,float n2, float hue)
+{
+ // fixed implementation for HSL2RGB routine
+ float rValue;
+
+ if (hue > 360)
+ hue = hue - 360;
+ else if (hue < 0)
+ hue = hue + 360;
+
+ if (hue < 60)
+ rValue = n1 + (n2-n1)*hue/60.0f;
+ else if (hue < 180)
+ rValue = n2;
+ else if (hue < 240)
+ rValue = n1+(n2-n1)*(240-hue)/60;
+ else
+ rValue = n1;
+
+ return rValue;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::HSLtoRGB(COLORREF cHSLColor)
+{
+ return HSLtoRGB(RGBtoRGBQUAD(cHSLColor));
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::HSLtoRGB(RGBQUAD lHSLColor)
+{
+ // fixed implementation for HSL2RGB routine
+ float h,s,l;
+ float m1,m2;
+ BYTE r,g,b;
+
+ h = (float)lHSLColor.rgbRed * 360.0f/255.0f;
+ s = (float)lHSLColor.rgbGreen/255.0f;
+ l = (float)lHSLColor.rgbBlue/255.0f;
+
+ if (l <= 0.5) m2 = l * (1+s);
+ else m2 = l + s - l*s;
+
+ m1 = 2 * l - m2;
+
+ if (s == 0) {
+ r=g=b=(BYTE)(l*255.0f);
+ } else {
+ r = (BYTE)(HueToRGB(m1,m2,h+120) * 255.0f);
+ g = (BYTE)(HueToRGB(m1,m2,h) * 255.0f);
+ b = (BYTE)(HueToRGB(m1,m2,h-120) * 255.0f);
+ }
+
+ RGBQUAD rgb = {b,g,r,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::YUVtoRGB(RGBQUAD lYUVColor)
+{
+ int U,V,R,G,B;
+ float Y = lYUVColor.rgbRed;
+ U = lYUVColor.rgbGreen - 128;
+ V = lYUVColor.rgbBlue - 128;
+
+// R = (int)(1.164 * Y + 2.018 * U);
+// G = (int)(1.164 * Y - 0.813 * V - 0.391 * U);
+// B = (int)(1.164 * Y + 1.596 * V);
+ R = (int)( Y + 1.403f * V);
+ G = (int)( Y - 0.344f * U - 0.714f * V);
+ B = (int)( Y + 1.770f * U);
+
+ R= min(255,max(0,R));
+ G= min(255,max(0,G));
+ B= min(255,max(0,B));
+ RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoYUV(RGBQUAD lRGBColor)
+{
+ int Y,U,V,R,G,B;
+ R = lRGBColor.rgbRed;
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+// Y = (int)( 0.257 * R + 0.504 * G + 0.098 * B);
+// U = (int)( 0.439 * R - 0.368 * G - 0.071 * B + 128);
+// V = (int)(-0.148 * R - 0.291 * G + 0.439 * B + 128);
+ Y = (int)(0.299f * R + 0.587f * G + 0.114f * B);
+ U = (int)((B-Y) * 0.565f + 128);
+ V = (int)((R-Y) * 0.713f + 128);
+
+ Y= min(255,max(0,Y));
+ U= min(255,max(0,U));
+ V= min(255,max(0,V));
+ RGBQUAD yuv={(BYTE)V,(BYTE)U,(BYTE)Y,0};
+ return yuv;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::YIQtoRGB(RGBQUAD lYIQColor)
+{
+ int I,Q,R,G,B;
+ float Y = lYIQColor.rgbRed;
+ I = lYIQColor.rgbGreen - 128;
+ Q = lYIQColor.rgbBlue - 128;
+
+ R = (int)( Y + 0.956f * I + 0.621f * Q);
+ G = (int)( Y - 0.273f * I - 0.647f * Q);
+ B = (int)( Y - 1.104f * I + 1.701f * Q);
+
+ R= min(255,max(0,R));
+ G= min(255,max(0,G));
+ B= min(255,max(0,B));
+ RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoYIQ(RGBQUAD lRGBColor)
+{
+ int Y,I,Q,R,G,B;
+ R = lRGBColor.rgbRed;
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+ Y = (int)( 0.2992f * R + 0.5868f * G + 0.1140f * B);
+ I = (int)( 0.5960f * R - 0.2742f * G - 0.3219f * B + 128);
+ Q = (int)( 0.2109f * R - 0.5229f * G + 0.3120f * B + 128);
+
+ Y= min(255,max(0,Y));
+ I= min(255,max(0,I));
+ Q= min(255,max(0,Q));
+ RGBQUAD yiq={(BYTE)Q,(BYTE)I,(BYTE)Y,0};
+ return yiq;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::XYZtoRGB(RGBQUAD lXYZColor)
+{
+ int X,Y,Z,R,G,B;
+ X = lXYZColor.rgbRed;
+ Y = lXYZColor.rgbGreen;
+ Z = lXYZColor.rgbBlue;
+ double k=1.088751;
+
+ R = (int)( 3.240479f * X - 1.537150f * Y - 0.498535f * Z * k);
+ G = (int)( -0.969256f * X + 1.875992f * Y + 0.041556f * Z * k);
+ B = (int)( 0.055648f * X - 0.204043f * Y + 1.057311f * Z * k);
+
+ R= min(255,max(0,R));
+ G= min(255,max(0,G));
+ B= min(255,max(0,B));
+ RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoXYZ(RGBQUAD lRGBColor)
+{
+ int X,Y,Z,R,G,B;
+ R = lRGBColor.rgbRed;
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+ X = (int)( 0.412453f * R + 0.357580f * G + 0.180423f * B);
+ Y = (int)( 0.212671f * R + 0.715160f * G + 0.072169f * B);
+ Z = (int)((0.019334f * R + 0.119193f * G + 0.950227f * B)*0.918483657f);
+
+ //X= min(255,max(0,X));
+ //Y= min(255,max(0,Y));
+ //Z= min(255,max(0,Z));
+ RGBQUAD xyz={(BYTE)Z,(BYTE)Y,(BYTE)X,0};
+ return xyz;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Generates a "rainbow" palette with saturated colors
+ * \param correction: 1 generates a single hue spectrum. 0.75 is nice for scientific applications.
+ */
+void CxImage::HuePalette(float correction)
+{
+ if (head.biClrUsed==0) return;
+
+ for(DWORD j=0; j 1.0f) blend = 1.0f;
+ int a0 = (int)(256*blend);
+ int a1 = 256 - a0;
+
+ bool bFullBlend = false;
+ if (blend > 0.999f) bFullBlend = true;
+
+ RGBQUAD color,hsl;
+ if (head.biClrUsed==0){
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(long y=ymin; y>8);
+ color.rgbBlue = (BYTE)((hsl.rgbBlue * a0 + color.rgbBlue * a1)>>8);
+ color.rgbGreen = (BYTE)((hsl.rgbGreen * a0 + color.rgbGreen * a1)>>8);
+ SetPixelColor(x,y,color);
+ }
+ }
+ }
+ }
+ } else {
+ for(DWORD j=0; j
+ for (int i=0;i<256;i++) {
+ cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*c + brightness)));
+ }
+
+ return Lut(cTable);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return mean lightness of the image. Useful with Threshold() and Light()
+ */
+float CxImage::Mean()
+{
+ if (!pDib) return 0;
+
+ CxImage tmp(*this,true);
+ if (!tmp.IsValid()) return false;
+
+ tmp.GrayScale();
+ float sum=0;
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+ if (xmin==xmax || ymin==ymax) return (float)0.0;
+
+ BYTE *iSrc=tmp.info.pImage;
+ iSrc += tmp.info.dwEffWidth*ymin; // necessary for selections
+
+ for(long y=ymin; y
+ for(long x=xmin; x 0 && (y+kmax-1) < head.biHeight && x-k2 > 0 && (x+kmax-1) < head.biWidth)
+ {
+ b=0;
+ iCount = 0;
+ iY2 = ((y-k2)*info.dwEffWidth);
+ for(long j=-k2;j r) r=c.rgbRed;
+ if (c.rgbGreen > g) g=c.rgbGreen;
+ if (c.rgbBlue > b) b=c.rgbBlue;
+ }
+ }
+ c.rgbRed = r;
+ c.rgbGreen = g;
+ c.rgbBlue = b;
+ tmp.SetPixelColor(x,y,c);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enhance the variations between adjacent pixels.
+ * Similar results can be achieved using Filter(),
+ * but the algorithms are different both in Edge() and in Contour().
+ * \param Ksize: size of the kernel.
+ * \return true if everything is ok
+ */
+bool CxImage::Edge(long Ksize)
+{
+ if (!pDib) return false;
+
+ long k2 = Ksize/2;
+ long kmax= Ksize-k2;
+ BYTE r,g,b,rr,gg,bb;
+ RGBQUAD c;
+
+ CxImage tmp(*this,pSelection!=0,true,true);
+ if (!tmp.IsValid()) return false;
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(long y=ymin; y r) r=c.rgbRed;
+ if (c.rgbGreen > g) g=c.rgbGreen;
+ if (c.rgbBlue > b) b=c.rgbBlue;
+
+ if (c.rgbRed < rr) rr=c.rgbRed;
+ if (c.rgbGreen < gg) gg=c.rgbGreen;
+ if (c.rgbBlue < bb) bb=c.rgbBlue;
+ }
+ }
+ c.rgbRed = 255-abs(r-rr);
+ c.rgbGreen = 255-abs(g-gg);
+ c.rgbBlue = 255-abs(b-bb);
+ tmp.SetPixelColor(x,y,c);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Blends two images
+ * \param imgsrc2: image to be mixed with this
+ * \param op: blending method; see ImageOpType
+ * \param lXOffset, lYOffset: image displacement
+ * \param bMixAlpha: if true and imgsrc2 has a valid alpha layer, it will be mixed in the destination image.
+ * \return true if everything is ok
+ *
+ * thanks to Mwolski
+ */
+//
+void CxImage::Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset, long lYOffset, bool bMixAlpha)
+{
+ long lWide = min(GetWidth(),imgsrc2.GetWidth()-lXOffset);
+ long lHeight = min(GetHeight(),imgsrc2.GetHeight()-lYOffset);
+
+ bool bEditAlpha = imgsrc2.AlphaIsValid() & bMixAlpha;
+
+ if (bEditAlpha && AlphaIsValid()==false){
+ AlphaCreate();
+ }
+
+ RGBQUAD rgbBackgrnd = GetTransColor();
+ RGBQUAD rgb1, rgb2, rgbDest;
+
+ for(long lY=0;lY>8);
+ } else {
+ a=255;
+ }
+
+ if (a==0){ //transparent
+ rgbDest = rgb1;
+ } else if (a==255){ //opaque
+ rgbDest = rgb2;
+ } else { //blend
+ a1 = (BYTE)~a;
+ rgbDest.rgbBlue = (BYTE)((rgb1.rgbBlue*a1+rgb2.rgbBlue*a)>>8);
+ rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)>>8);
+ rgbDest.rgbRed = (BYTE)((rgb1.rgbRed*a1+rgb2.rgbRed*a)>>8);
+ }
+
+ if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(((1+rgb1.rgbReserved)*a)>>8);
+ }
+ break;
+ case OpSrcBlend:
+ if(memcmp(&rgb1,&rgbBackgrnd,sizeof(RGBQUAD))==0)
+ rgbDest = rgb2;
+ else
+ {
+ long lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd.rgbBlue);
+ long lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd.rgbGreen);
+ long lRDiff = abs(rgb1.rgbRed - rgbBackgrnd.rgbRed);
+
+ double lAverage = (lBDiff+lGDiff+lRDiff)/3;
+ double lThresh = 16;
+ double dLarge = lAverage/lThresh;
+ double dSmall = (lThresh-lAverage)/lThresh;
+ double dSmallAmt = dSmall*((double)rgb2.rgbBlue);
+
+ if( lAverage < lThresh+1){
+ rgbDest.rgbBlue = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbBlue) +
+ dSmallAmt)));
+ rgbDest.rgbGreen = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbGreen) +
+ dSmallAmt)));
+ rgbDest.rgbRed = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbRed) +
+ dSmallAmt)));
+ }
+ else
+ rgbDest = rgb1;
+ }
+ break;
+ default:
+ return;
+ }
+ SetPixelColor(lX,lY,rgbDest,bEditAlpha);
+ }
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+// thanks to Kenneth Ballard
+void CxImage::MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset)
+{
+ RGBQUAD rgbBackgrnd = imagesrc2.GetTransColor();
+ RGBQUAD rgb1;
+
+ long width = imagesrc2.GetWidth();
+ long height = imagesrc2.GetHeight();
+
+ int x, y;
+
+ for(x = 0; x < width; x++)
+ {
+ for(y = 0; y < height; y++)
+ {
+ rgb1 = imagesrc2.GetPixelColor(x, y);
+ if(memcmp(&rgb1, &rgbBackgrnd, sizeof(RGBQUAD)) != 0)
+ SetPixelColor(x + lXOffset, y + lYOffset, rgb1);
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adjusts separately the red, green, and blue values in the image.
+ * \param r, g, b: can be from -255 to +255.
+ * \return true if everything is ok
+ */
+bool CxImage::ShiftRGB(long r, long g, long b)
+{
+ if (!pDib) return false;
+ RGBQUAD color;
+ if (head.biClrUsed==0){
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(long y=ymin; y
+ for (int i=0;i<256;i++) {
+ cTable[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));
+ }
+
+ return Lut(cTable);
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_WINCE == 0
+/**
+ * Adjusts the intensity of each pixel to the median intensity of its surrounding pixels.
+ * \param Ksize: size of the kernel.
+ * \return true if everything is ok
+ */
+bool CxImage::Median(long Ksize)
+{
+ if (!pDib) return false;
+
+ long k2 = Ksize/2;
+ long kmax= Ksize-k2;
+ long i,j,k;
+
+ RGBQUAD* kernel = (RGBQUAD*)malloc(Ksize*Ksize*sizeof(RGBQUAD));
+
+ CxImage tmp(*this,pSelection!=0,true,true);
+ if (!tmp.IsValid()) return false;
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(long y=ymin; y
+ for(long x=xmin; xGetWidth();
+ h=srcReal->GetHeight();
+ } else {
+ w=srcImag->GetWidth();
+ h=srcImag->GetHeight();
+ }
+
+ bool bXpow2 = IsPowerof2(w);
+ bool bYpow2 = IsPowerof2(h);
+ //if bForceFFT, width AND height must be powers of 2
+ if (bForceFFT && !(bXpow2 && bYpow2)) {
+ long i;
+
+ i=0;
+ while((1< copy the image
+ if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false);
+ if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false);
+
+ // dst&&src are empty -> create new one, else turn to GrayScale
+ if (srcReal==0 && dstReal==0){
+ tmpReal = new CxImage(w,h,8);
+ tmpReal->Clear(0);
+ tmpReal->SetGrayPalette();
+ } else {
+ if (!tmpReal->IsGrayScale()) tmpReal->GrayScale();
+ }
+ if (srcImag==0 && dstImag==0){
+ tmpImag = new CxImage(w,h,8);
+ tmpImag->Clear(0);
+ tmpImag->SetGrayPalette();
+ } else {
+ if (!tmpImag->IsGrayScale()) tmpImag->GrayScale();
+ }
+
+ if (!(tmpReal->IsValid() && tmpImag->IsValid())){
+ if (srcReal==0 && dstReal==0) delete tmpReal;
+ if (srcImag==0 && dstImag==0) delete tmpImag;
+ return false;
+ }
+
+ //resample for FFT, if necessary
+ tmpReal->Resample(w,h,0);
+ tmpImag->Resample(w,h,0);
+
+ //ok, here we have 2 (w x h), grayscale images ready for a FFT
+
+ double* real;
+ double* imag;
+ long j,k,m;
+
+ _complex **grid;
+ //double mean = tmpReal->Mean();
+ /* Allocate memory for the grid */
+ grid = (_complex **)malloc(w * sizeof(_complex));
+ for (k=0;kGetPixelIndex(k,j)-128;
+ grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128;
+ }
+ }
+
+ //DFT buffers
+ double *real2,*imag2;
+ real2 = (double*)malloc(max(w,h) * sizeof(double));
+ imag2 = (double*)malloc(max(w,h) * sizeof(double));
+
+ /* Transform the rows */
+ real = (double *)malloc(w * sizeof(double));
+ imag = (double *)malloc(w * sizeof(double));
+
+ m=0;
+ while((1<SetPixelIndex(k,j,(BYTE)max(0,min(255,(nn*(3+log(_cabs(grid[k][j])))))));
+ if (grid[k][j].x==0){
+ tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn)))));
+ } else {
+ tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn)))));
+ }
+ } else {
+ tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].x*nn))));
+ tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].y*nn))));
+ }
+ }
+ }
+
+ for (k=0;k> 1;
+ j = 0;
+ for (i=0;i>= 1;
+ }
+ j += k;
+ }
+
+ /* Compute the FFT */
+ c1 = -1.0;
+ c2 = 0.0;
+ l2 = 1;
+ for (l=0;lGetWidth();
+ long h = r->GetHeight();
+
+ Create(w,h,24);
+
+ g->Resample(w,h);
+ b->Resample(w,h);
+
+ if (a) {
+ a->Resample(w,h);
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ RGBQUAD c;
+ for (long y=0;y
+ for (long x=0;xGetPixelIndex(x,y);
+ c.rgbGreen=g->GetPixelIndex(x,y);
+ c.rgbBlue=b->GetPixelIndex(x,y);
+ switch (colorspace){
+ case 1:
+ SetPixelColor(x,y,HSLtoRGB(c));
+ break;
+ case 2:
+ SetPixelColor(x,y,YUVtoRGB(c));
+ break;
+ case 3:
+ SetPixelColor(x,y,YIQtoRGB(c));
+ break;
+ case 4:
+ SetPixelColor(x,y,XYZtoRGB(c));
+ break;
+ default:
+ SetPixelColor(x,y,c);
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (a) AlphaSet(x,y,a->GetPixelIndex(x,y));
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Smart blurring to remove small defects, dithering or artifacts.
+ * \param radius: normally between 0.01 and 0.5
+ * \param niterations: should be trimmed with radius, to avoid blurring should be (radius*niterations)<1
+ * \param colorspace: 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ
+ * \return true if everything is ok
+ */
+bool CxImage::Repair(float radius, long niterations, long colorspace)
+{
+ if (!IsValid()) return false;
+
+ long w = GetWidth();
+ long h = GetHeight();
+
+ CxImage r,g,b;
+
+ r.Create(w,h,8);
+ g.Create(w,h,8);
+ b.Create(w,h,8);
+
+ switch (colorspace){
+ case 1:
+ SplitHSL(&r,&g,&b);
+ break;
+ case 2:
+ SplitYUV(&r,&g,&b);
+ break;
+ case 3:
+ SplitYIQ(&r,&g,&b);
+ break;
+ case 4:
+ SplitXYZ(&r,&g,&b);
+ break;
+ default:
+ SplitRGB(&r,&g,&b);
+ }
+
+ for (int i=0; iGetWidth()-1;
+ long h = ch->GetHeight()-1;
+
+ double correction,ix,iy,ixx,ixy,iyy,den,num;
+ int x,y,xy0,xp1,xm1,yp1,ym1;
+ for(x=1; xGetPixelIndex(x,y);
+ xm1 = ch->GetPixelIndex(x-1,y);
+ xp1 = ch->GetPixelIndex(x+1,y);
+ ym1 = ch->GetPixelIndex(x,y-1);
+ yp1 = ch->GetPixelIndex(x,y+1);
+
+ ix= (xp1-xm1)/2.0;
+ iy= (yp1-ym1)/2.0;
+ ixx= xp1 - 2.0 * xy0 + xm1;
+ iyy= yp1 - 2.0 * xy0 + ym1;
+ ixy=(ch->GetPixelIndex(x+1,y+1)+ch->GetPixelIndex(x-1,y-1)-
+ ch->GetPixelIndex(x-1,y+1)-ch->GetPixelIndex(x+1,y-1))/4.0;
+
+ num= (1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy;
+ den= 1.0+ix*ix+iy*iy;
+ correction = num/den;
+
+ tmp.SetPixelIndex(x,y,(BYTE)min(255,max(0,(xy0 + radius * correction))));
+ }
+ }
+
+ for (x=0;x<=w;x++){
+ tmp.SetPixelIndex(x,0,ch->GetPixelIndex(x,0));
+ tmp.SetPixelIndex(x,h,ch->GetPixelIndex(x,h));
+ }
+ for (y=0;y<=h;y++){
+ tmp.SetPixelIndex(0,y,ch->GetPixelIndex(0,y));
+ tmp.SetPixelIndex(w,y,ch->GetPixelIndex(w,y));
+ }
+ ch->Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enhance the variations between adjacent pixels.
+ * Similar results can be achieved using Filter(),
+ * but the algorithms are different both in Edge() and in Contour().
+ * \return true if everything is ok
+ */
+bool CxImage::Contour()
+{
+ if (!pDib) return false;
+
+ long Ksize = 3;
+ long k2 = Ksize/2;
+ long kmax= Ksize-k2;
+ long i,j,k;
+ BYTE maxr,maxg,maxb;
+ RGBQUAD pix1,pix2;
+
+ CxImage tmp(*this,pSelection!=0,true,true);
+ if (!tmp.IsValid()) return false;
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(long y=ymin; ymaxb) maxb = pix2.rgbBlue;
+ if ((pix2.rgbGreen-pix1.rgbGreen)>maxg) maxg = pix2.rgbGreen;
+ if ((pix2.rgbRed-pix1.rgbRed)>maxr) maxr = pix2.rgbRed;
+ }
+ }
+ pix1.rgbBlue=(BYTE)(255-maxb);
+ pix1.rgbGreen=(BYTE)(255-maxg);
+ pix1.rgbRed=(BYTE)(255-maxr);
+ tmp.SetPixelColor(x,y,pix1);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a random offset to each pixel in the image
+ * \param radius: maximum pixel displacement
+ * \return true if everything is ok
+ */
+bool CxImage::Jitter(long radius)
+{
+ if (!pDib) return false;
+
+ long nx,ny;
+
+ CxImage tmp(*this,pSelection!=0,true,true);
+ if (!tmp.IsValid()) return false;
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(long y=ymin; y y)
+ {
+ for (row = 0; row < y ; row++)
+ {
+ scale=0;
+ /* find the scale factor */
+ for (j = 0; j < y ; j++)
+ {
+ /* if the index is in bounds, add it to the scale counter */
+ if ((j + cmatrix_length/2 - row >= 0) &&
+ (j + cmatrix_length/2 - row < cmatrix_length))
+ scale += cmatrix[j + cmatrix_length/2 - row];
+ }
+ for (i = 0; i= row - cmatrix_length/2) &&
+ (j <= row + cmatrix_length/2))
+ sum += cur_col[j*bytes + i] * cmatrix[j];
+ }
+ dest_col[row*bytes + i] = (BYTE)(0.5f + sum / scale);
+ }
+ }
+ }
+ else
+ {
+ /* for the edge condition, we only use available info and scale to one */
+ for (row = 0; row < cmatrix_middle; row++)
+ {
+ /* find scale factor */
+ scale=0;
+ for (j = cmatrix_middle - row; j0; j--)
+ {
+ sum += *(ctable_p + *cur_col_p1);
+ cur_col_p1 += bytes;
+ ctable_p += 256;
+ }
+ cur_col_p++;
+ *(dest_col_p++) = (BYTE)(0.5f + sum);
+ }
+ }
+
+ /* for the edge condition , we only use available info, and scale to one */
+ for (; row < y; row++)
+ {
+ /* find scale factor */
+ scale=0;
+ for (j = 0; j< y-row + cmatrix_middle; j++)
+ scale += cmatrix[j];
+ for (i = 0; i 255) dest_row[u*3+v] = 255;
+ else dest_row[u*3+v] = value;
+ }
+ }
+ }
+
+ Transfer(tmp);
+
+ return TRUE;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Apply a look up table to the image.
+ * \param pLut: BYTE[256] look up table
+ * \return true if everything is ok
+ */
+bool CxImage::Lut(BYTE* pLut)
+{
+ if (!pDib || !pLut) return false;
+ RGBQUAD color;
+
+ double dbScaler;
+ if (head.biClrUsed==0){
+
+ long xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ // faster loop for full image
+ BYTE *iSrc=info.pImage;
+ for(unsigned long i=0; i < head.biSizeImage ; i++){
+ *iSrc++ = pLut[*iSrc];
+ }
+ return true;
+ }
+
+ dbScaler = 100.0/ymax;
+
+ for(long y=ymin; y
+ for(long x=xmin; x
+ if (!pDib) return false;
+ FloodFill2(x,y,GetPixelColor(x,y),FillColor);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::FloodFill2(int x, int y, RGBQUAD old_color, RGBQUAD new_color)
+{
+ // Fill in the actual pixels.
+ // Function steps recursively until it finds borders (color that is not old_color)
+ if (!IsInside(x,y)) return;
+
+ RGBQUAD r = GetPixelColor(x,y);
+ COLORREF cr = RGB(r.rgbRed,r.rgbGreen,r.rgbBlue);
+
+ if(cr == RGB(old_color.rgbRed,old_color.rgbGreen,old_color.rgbBlue)
+ && cr != RGB(new_color.rgbRed,new_color.rgbGreen,new_color.rgbBlue) ) {
+
+ // the above if statement, after && is there to prevent
+ // stack overflows. The program will continue to find
+ // colors if you flood-fill an entire region (entire picture)
+
+ SetPixelColor(x,y,new_color);
+
+ FloodFill2((x+1),y,old_color,new_color);
+ FloodFill2((x-1),y,old_color,new_color);
+ FloodFill2(x,(y+1),old_color,new_color);
+ FloodFill2(x,(y-1),old_color,new_color);
+ }
+}*/
+///////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DSP
diff --git a/src/win32/dependencies/cximage/ximaenc.cpp b/src/win32/dependencies/cximage/ximaenc.cpp
new file mode 100644
index 00000000..da95578b
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximaenc.cpp
@@ -0,0 +1,920 @@
+// xImaCodec.cpp : Encode Decode functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_JPG
+#include "ximajpg.h"
+#endif
+
+#if CXIMAGE_SUPPORT_GIF
+#include "ximagif.h"
+#endif
+
+#if CXIMAGE_SUPPORT_PNG
+#include "ximapng.h"
+#endif
+
+#if CXIMAGE_SUPPORT_MNG
+#include "ximamng.h"
+#endif
+
+#if CXIMAGE_SUPPORT_BMP
+#include "ximabmp.h"
+#endif
+
+#if CXIMAGE_SUPPORT_ICO
+#include "ximaico.h"
+#endif
+
+#if CXIMAGE_SUPPORT_TIF
+#include "ximatif.h"
+#endif
+
+#if CXIMAGE_SUPPORT_TGA
+#include "ximatga.h"
+#endif
+
+#if CXIMAGE_SUPPORT_PCX
+#include "ximapcx.h"
+#endif
+
+#if CXIMAGE_SUPPORT_WBMP
+#include "ximawbmp.h"
+#endif
+
+#if CXIMAGE_SUPPORT_WMF
+#include "ximawmf.h" // - WMF/EMF support
+#endif
+
+#if CXIMAGE_SUPPORT_J2K
+#include "ximaj2k.h"
+#endif
+
+#if CXIMAGE_SUPPORT_JBG
+#include "ximajbg.h"
+#endif
+
+#if CXIMAGE_SUPPORT_JASPER
+#include "ximajas.h"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::EncodeSafeCheck(CxFile *hFile)
+{
+ if (hFile==NULL) {
+ strcpy(info.szLastError,CXIMAGE_ERR_NOFILE);
+ return true;
+ }
+
+ if (pDib==NULL){
+ strcpy(info.szLastError,CXIMAGE_ERR_NOIMAGE);
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+//#ifdef WIN32
+//bool CxImage::Save(LPCWSTR filename, DWORD imagetype)
+//{
+// FILE* hFile; //file handle to write the image
+// if ((hFile=_wfopen(filename,L"wb"))==NULL) return false;
+// bool bOK = Encode(hFile,imagetype);
+// fclose(hFile);
+// return bOK;
+//}
+//#endif //WIN32
+////////////////////////////////////////////////////////////////////////////////
+// For UNICODE support: char -> TCHAR
+/**
+ * Saves to disk the image in a specific format.
+ * \param filename: file name
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Save(const TCHAR * filename, DWORD imagetype)
+{
+ FILE* hFile; //file handle to write the image
+
+#ifdef WIN32
+ if ((hFile=_tfopen(filename,_T("wb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(filename,"wb"))==NULL) return false;
+#endif
+
+ bool bOK = Encode(hFile,imagetype);
+ fclose(hFile);
+ return bOK;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk the image in a specific format.
+ * \param hFile: file handle, open and enabled for writing.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(FILE *hFile, DWORD imagetype)
+{
+ CxIOFile file(hFile);
+ return Encode(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to memory buffer the image in a specific format.
+ * \param buffer: output memory buffer pointer. Must be NULL,
+ * the function allocates and fill the memory,
+ * the application must free the buffer, see also FreeMemory().
+ * \param size: output memory buffer size.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(BYTE * &buffer, long &size, DWORD imagetype)
+{
+ if (buffer!=NULL){
+ strcpy(info.szLastError,"the buffer must be empty");
+ return false;
+ }
+ CxMemFile file;
+ file.Open();
+ if(Encode(&file,imagetype)){
+ buffer=file.GetBuffer();
+ size=file.Size();
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk the image in a specific format.
+ * \param hFile: file handle (implemented using CxMemFile or CxIOFile),
+ * open and enabled for writing.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ * \sa ENUM_CXIMAGE_FORMATS
+ */
+bool CxImage::Encode(CxFile *hFile, DWORD imagetype)
+{
+
+#if CXIMAGE_SUPPORT_BMP
+
+ if (imagetype==CXIMAGE_FORMAT_BMP){
+ CxImageBMP newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ if (imagetype==CXIMAGE_FORMAT_ICO){
+ CxImageICO newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ if (imagetype==CXIMAGE_FORMAT_TIF){
+ CxImageTIF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ if (imagetype==CXIMAGE_FORMAT_JPG){
+ CxImageJPG newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (imagetype==CXIMAGE_FORMAT_GIF){
+ CxImageGIF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ if (imagetype==CXIMAGE_FORMAT_PNG){
+ CxImagePNG newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ if (imagetype==CXIMAGE_FORMAT_MNG){
+ CxImageMNG newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ if (imagetype==CXIMAGE_FORMAT_TGA){
+ CxImageTGA newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ if (imagetype==CXIMAGE_FORMAT_PCX){
+ CxImagePCX newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ if (imagetype==CXIMAGE_FORMAT_WBMP){
+ CxImageWBMP newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // - WMF/EMF support
+ if (imagetype==CXIMAGE_FORMAT_WMF){
+ CxImageWMF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_J2K
+ if (imagetype==CXIMAGE_FORMAT_J2K){
+ CxImageJ2K newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ if (imagetype==CXIMAGE_FORMAT_JBG){
+ CxImageJBG newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+ if (
+ #if CXIMAGE_SUPPORT_JP2
+ imagetype==CXIMAGE_FORMAT_JP2 ||
+ #endif
+ #if CXIMAGE_SUPPORT_JPC
+ imagetype==CXIMAGE_FORMAT_JPC ||
+ #endif
+ #if CXIMAGE_SUPPORT_PGX
+ imagetype==CXIMAGE_FORMAT_PGX ||
+ #endif
+ #if CXIMAGE_SUPPORT_PNM
+ imagetype==CXIMAGE_FORMAT_PNM ||
+ #endif
+ #if CXIMAGE_SUPPORT_RAS
+ imagetype==CXIMAGE_FORMAT_RAS ||
+ #endif
+ false ){
+ CxImageJAS newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile,imagetype)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+
+ strcpy(info.szLastError,"Encode: Unknown format");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers.
+ * \param hFile: file handle.
+ * \param pImages: array of CxImage pointers.
+ * \param pagecount: number of images.
+ * \param imagetype: can be CXIMAGE_FORMAT_TIF or CXIMAGE_FORMAT_GIF.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(FILE * hFile, CxImage ** pImages, int pagecount, DWORD imagetype)
+{
+ CxIOFile file(hFile);
+ return Encode(&file, pImages, pagecount,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers.
+ * \param hFile: file handle (implemented using CxMemFile or CxIOFile).
+ * \param pImages: array of CxImage pointers.
+ * \param pagecount: number of images.
+ * \param imagetype: can be CXIMAGE_FORMAT_TIF or CXIMAGE_FORMAT_GIF.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(CxFile * hFile, CxImage ** pImages, int pagecount, DWORD imagetype)
+{
+#if CXIMAGE_SUPPORT_TIF
+ if (imagetype==CXIMAGE_FORMAT_TIF){
+ CxImageTIF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile,pImages,pagecount)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (imagetype==CXIMAGE_FORMAT_GIF){
+ CxImageGIF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile,pImages,pagecount)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+ strcpy(info.szLastError,"Multipage Encode, Unsupported operation for this format");
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * exports the image into a RGBA buffer, Useful for OpenGL applications.
+ * \param buffer: output memory buffer pointer. Must be NULL,
+ * the function allocates and fill the memory,
+ * the application must free the buffer, see also FreeMemory().
+ * \param size: output memory buffer size.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode2RGBA(BYTE * &buffer, long &size)
+{
+ if (buffer!=NULL){
+ strcpy(info.szLastError,"the buffer must be empty");
+ return false;
+ }
+ CxMemFile file;
+ file.Open();
+ if(Encode2RGBA(&file)){
+ buffer=file.GetBuffer();
+ size=file.Size();
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * exports the image into a RGBA buffer, Useful for OpenGL applications.
+ * \param hFile: file handle (implemented using CxMemFile or CxIOFile).
+ * \return true if everything is ok
+ */
+bool CxImage::Encode2RGBA(CxFile *hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ for (DWORD y = 0; yPutC(color.rgbRed);
+ hFile->PutC(color.rgbGreen);
+ hFile->PutC(color.rgbBlue);
+ hFile->PutC(color.rgbReserved);
+ }
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+// For UNICODE support: char -> TCHAR
+/**
+ * Reads from disk the image in a specific format.
+ * - If decoding fails using the specified image format,
+ * the function will try the automatic file format recognition.
+ *
+ * \param filename: file name
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Load(const TCHAR * filename, DWORD imagetype)
+//bool CxImage::Load(const char * filename, DWORD imagetype)
+{
+ /*FILE* hFile; //file handle to read the image
+ if ((hFile=fopen(filename,"rb"))==NULL) return false;
+ bool bOK = Decode(hFile,imagetype);
+ fclose(hFile);*/
+
+ /* automatic file type recognition */
+ bool bOK = false;
+ if ( imagetype > 0 && imagetype < CMAX_IMAGE_FORMATS ){
+ FILE* hFile; //file handle to read the image
+
+#ifdef WIN32
+ if ((hFile=_tfopen(filename,_T("rb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(filename,"rb"))==NULL) return false;
+#endif
+
+ bOK = Decode(hFile,imagetype);
+ fclose(hFile);
+ if (bOK) return bOK;
+ }
+
+ char szError[256];
+ strcpy(szError,info.szLastError); //save the first error
+
+ // if failed, try automatic recognition of the file...
+ FILE* hFile;
+
+#ifdef WIN32
+ if ((hFile=_tfopen(filename,_T("rb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(filename,"rb"))==NULL) return false;
+#endif
+
+ bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN);
+ fclose(hFile);
+
+ if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error
+
+ return bOK;
+}
+////////////////////////////////////////////////////////////////////////////////
+#ifdef WIN32
+//bool CxImage::Load(LPCWSTR filename, DWORD imagetype)
+//{
+// /*FILE* hFile; //file handle to read the image
+// if ((hFile=_wfopen(filename, L"rb"))==NULL) return false;
+// bool bOK = Decode(hFile,imagetype);
+// fclose(hFile);*/
+//
+// /* automatic file type recognition */
+// bool bOK = false;
+// if ( imagetype > 0 && imagetype < CMAX_IMAGE_FORMATS ){
+// FILE* hFile; //file handle to read the image
+// if ((hFile=_wfopen(filename,L"rb"))==NULL) return false;
+// bOK = Decode(hFile,imagetype);
+// fclose(hFile);
+// if (bOK) return bOK;
+// }
+//
+// char szError[256];
+// strcpy(szError,info.szLastError); //save the first error
+//
+// // if failed, try automatic recognition of the file...
+// FILE* hFile; //file handle to read the image
+// if ((hFile=_wfopen(filename,L"rb"))==NULL) return false;
+// bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN);
+// fclose(hFile);
+//
+// if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error
+//
+// return bOK;
+//}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from the application resources.
+ * \param hRes: the resource handle returned by FindResource().
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS.
+ * \param hModule: NULL for internal resource, or external application/DLL hinstance returned by LoadLibray.
+ * \return true if everything is ok
+ */
+bool CxImage::LoadResource(HRSRC hRes, DWORD imagetype, HMODULE hModule)
+{
+ DWORD rsize=SizeofResource(hModule,hRes);
+ HGLOBAL hMem=::LoadResource(hModule,hRes);
+ if (hMem){
+ char* lpVoid=(char*)LockResource(hMem);
+ if (lpVoid){
+ // FILE* fTmp=tmpfile(); doesn't work with network
+ /*char tmpPath[MAX_PATH] = {0};
+ char tmpFile[MAX_PATH] = {0};
+ GetTempPath(MAX_PATH,tmpPath);
+ GetTempFileName(tmpPath,"IMG",0,tmpFile);
+ FILE* fTmp=fopen(tmpFile,"w+b");
+ if (fTmp){
+ fwrite(lpVoid,rsize,1,fTmp);
+ fseek(fTmp,0,SEEK_SET);
+ bool bOK = Decode(fTmp,imagetype);
+ fclose(fTmp);
+ DeleteFile(tmpFile);
+ return bOK;
+ }*/
+
+ CxMemFile fTmp((BYTE*)lpVoid,rsize);
+ return Decode(&fTmp,imagetype);
+ }
+ } else strcpy(info.szLastError,"Unable to load resource!");
+ return false;
+}
+#endif //WIN32
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from file name, see Load()
+ * \param filename: file name
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+//
+// > filename: file name
+// > imagetype: specify the image format (CXIMAGE_FORMAT_BMP,...)
+// For UNICODE support: char -> TCHAR
+CxImage::CxImage(const TCHAR * filename, DWORD imagetype)
+//CxImage::CxImage(const char * filename, DWORD imagetype)
+{
+ Startup(imagetype);
+ Load(filename,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from file handle, see Decode()
+ * \param stream: file handle, with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(FILE * stream, DWORD imagetype)
+{
+ Startup(imagetype);
+ Decode(stream,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from CxFile object, see Decode()
+ * \param stream: file handle (implemented using CxMemFile or CxIOFile), with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(CxFile * stream, DWORD imagetype)
+{
+ Startup(imagetype);
+ Decode(stream,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from memory buffer, see Decode()
+ * \param buffer: memory buffer
+ * \param size: size of buffer
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(BYTE * buffer, DWORD size, DWORD imagetype)
+{
+ Startup(imagetype);
+ CxMemFile stream(buffer,size);
+ Decode(&stream,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from memory buffer
+ * \param buffer: memory buffer
+ * \param size: size of buffer
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Decode(BYTE * buffer, DWORD size, DWORD imagetype)
+{
+ CxMemFile file(buffer,size);
+ return Decode(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from file handle.
+ * \param hFile: file handle, with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Decode(FILE *hFile, DWORD imagetype)
+{
+ CxIOFile file(hFile);
+ return Decode(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from CxFile object
+ * \param hFile: file handle (implemented using CxMemFile or CxIOFile), with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ * \sa ENUM_CXIMAGE_FORMATS
+ */
+bool CxImage::Decode(CxFile *hFile, DWORD imagetype)
+{
+
+ if (imagetype==CXIMAGE_FORMAT_UNKNOWN){
+ DWORD pos = hFile->Tell();
+#if CXIMAGE_SUPPORT_BMP
+ { CxImageBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ { CxImageJPG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ { CxImageICO newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ { CxImageGIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ { CxImagePNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ { CxImageTIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ { CxImageMNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ { CxImageTGA newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ { CxImagePCX newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ { CxImageWBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
+ { CxImageWMF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_J2K
+ { CxImageJ2K newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ { CxImageJBG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+ { CxImageJAS newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+ }
+
+#if CXIMAGE_SUPPORT_BMP
+ if (imagetype==CXIMAGE_FORMAT_BMP){
+ CxImageBMP newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ if (imagetype==CXIMAGE_FORMAT_JPG){
+ CxImageJPG newima;
+ newima.CopyInfo(*this); //
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ if (imagetype==CXIMAGE_FORMAT_ICO){
+ CxImageICO newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ info.nNumFrames = newima.info.nNumFrames;
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (imagetype==CXIMAGE_FORMAT_GIF){
+ CxImageGIF newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ info.nNumFrames = newima.info.nNumFrames;
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ if (imagetype==CXIMAGE_FORMAT_PNG){
+ CxImagePNG newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ if (imagetype==CXIMAGE_FORMAT_TIF){
+ CxImageTIF newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ info.nNumFrames = newima.info.nNumFrames;
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ if (imagetype==CXIMAGE_FORMAT_MNG){
+ CxImageMNG newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ info.nNumFrames = newima.info.nNumFrames;
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ if (imagetype==CXIMAGE_FORMAT_TGA){
+ CxImageTGA newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ if (imagetype==CXIMAGE_FORMAT_PCX){
+ CxImagePCX newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ if (imagetype==CXIMAGE_FORMAT_WBMP){
+ CxImageWBMP newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // vho - WMF support
+ if (imagetype == CXIMAGE_FORMAT_WMF){
+ CxImageWMF newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_J2K
+ if (imagetype==CXIMAGE_FORMAT_J2K){
+ CxImageJ2K newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ if (imagetype==CXIMAGE_FORMAT_JBG){
+ CxImageJBG newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+ if (
+ #if CXIMAGE_SUPPORT_JP2
+ imagetype==CXIMAGE_FORMAT_JP2 ||
+ #endif
+ #if CXIMAGE_SUPPORT_JPC
+ imagetype==CXIMAGE_FORMAT_JPC ||
+ #endif
+ #if CXIMAGE_SUPPORT_PGX
+ imagetype==CXIMAGE_FORMAT_PGX ||
+ #endif
+ #if CXIMAGE_SUPPORT_PNM
+ imagetype==CXIMAGE_FORMAT_PNM ||
+ #endif
+ #if CXIMAGE_SUPPORT_RAS
+ imagetype==CXIMAGE_FORMAT_RAS ||
+ #endif
+ false ){
+ CxImageJAS newima;
+ newima.CopyInfo(*this);
+ if (newima.Decode(hFile,imagetype)){
+ Transfer(newima);
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+
+ strcpy(info.szLastError,"Decode: Unknown or wrong format");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/win32/dependencies/cximage/ximaexif.cpp b/src/win32/dependencies/cximage/ximaexif.cpp
new file mode 100644
index 00000000..17f962a1
--- /dev/null
+++ b/src/win32/dependencies/cximage/ximaexif.cpp
@@ -0,0 +1,873 @@
+/*
+ * File: ximaexif.cpp
+ * Purpose: EXIF reader
+ * 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ * based on jhead-1.8 by Matthias Wandel
+ */
+
+#include "ximajpg.h"
+
+#if CXIMAGEJPG_SUPPORT_EXIF
+
+////////////////////////////////////////////////////////////////////////////////
+CxImageJPG::CxExifInfo::CxExifInfo(EXIFINFO* info)
+{
+ if (info) {
+ m_exifinfo = info;
+ freeinfo = false;
+ } else {
+ m_exifinfo = new EXIFINFO;
+ memset(m_exifinfo,0,sizeof(EXIFINFO));
+ freeinfo = true;
+ }
+
+ m_szLastError[0]='\0';
+ ExifImageWidth = MotorolaOrder = 0;
+ SectionsRead=0;
+ memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t));
+}
+////////////////////////////////////////////////////////////////////////////////
+CxImageJPG::CxExifInfo::~CxExifInfo()
+{
+ for(int i=0;iGetC();
+
+ if (a != 0xff || hFile->GetC() != M_SOI){
+ return FALSE;
+ }
+
+ for(;;){
+ int itemlen;
+ int marker = 0;
+ int ll,lh, got;
+ BYTE * Data;
+
+ if (SectionsRead >= MAX_SECTIONS){
+ strcpy(m_szLastError,"Too many sections in jpg file");
+ return false;
+ }
+
+ for (a=0;a<7;a++){
+ marker = hFile->GetC();
+ if (marker != 0xff) break;
+
+ if (a >= 6){
+ printf("too many padding bytes\n");
+ return false;
+ }
+ }
+
+ if (marker == 0xff){
+ // 0xff is legal padding, but if we get that many, something's wrong.
+ strcpy(m_szLastError,"too many padding bytes!");
+ return false;
+ }
+
+ Sections[SectionsRead].Type = marker;
+
+ // Read the length of the section.
+ lh = hFile->GetC();
+ ll = hFile->GetC();
+
+ itemlen = (lh << 8) | ll;
+
+ if (itemlen < 2){
+ strcpy(m_szLastError,"invalid marker");
+ return false;
+ }
+
+ Sections[SectionsRead].Size = itemlen;
+
+ Data = (BYTE *)malloc(itemlen);
+ if (Data == NULL){
+ strcpy(m_szLastError,"Could not allocate memory");
+ return false;
+ }
+ Sections[SectionsRead].Data = Data;
+
+ // Store first two pre-read bytes.
+ Data[0] = (BYTE)lh;
+ Data[1] = (BYTE)ll;
+
+ got = hFile->Read(Data+2, 1, itemlen-2); // Read the whole section.
+ if (got != itemlen-2){
+ strcpy(m_szLastError,"Premature end of file?");
+ return false;
+ }
+ SectionsRead += 1;
+
+ switch(marker){
+
+ case M_SOS: // stop before hitting compressed data
+ // If reading entire image is requested, read the rest of the data.
+ if (nReadMode & EXIF_READ_IMAGE){
+ int cp, ep, size;
+ // Determine how much file is left.
+ cp = hFile->Tell();
+ hFile->Seek(0, SEEK_END);
+ ep = hFile->Tell();
+ hFile->Seek(cp, SEEK_SET);
+
+ size = ep-cp;
+ Data = (BYTE *)malloc(size);
+ if (Data == NULL){
+ strcpy(m_szLastError,"could not allocate data for entire image");
+ return false;
+ }
+
+ got = hFile->Read(Data, 1, size);
+ if (got != size){
+ strcpy(m_szLastError,"could not read the rest of the image");
+ return false;
+ }
+
+ Sections[SectionsRead].Data = Data;
+ Sections[SectionsRead].Size = size;
+ Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
+ SectionsRead ++;
+ }
+ return true;
+
+ case M_EOI: // in case it's a tables-only JPEG stream
+ printf("No image in jpeg!\n");
+ return FALSE;
+
+ case M_COM: // Comment section
+ if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0)){
+ // Discard this section.
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ }else{
+ process_COM(Data, itemlen);
+ HaveCom = TRUE;
+ }
+ break;
+
+ case M_JFIF:
+ // Regular jpegs always have this tag, exif images have the exif
+ // marker instead, althogh ACDsee will write images with both markers.
+ // this program will re-create this marker on absence of exif marker.
+ // hence no need to keep the copy from the file.
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ break;
+
+ case M_EXIF:
+ // Seen files from some 'U-lead' software with Vivitar scanner
+ // that uses marker 31 for non exif stuff. Thus make sure
+ // it says 'Exif' in the section before treating it as exif.
+ if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){
+ m_exifinfo->IsExif = process_EXIF((BYTE *)Data+2, itemlen);
+ }else{
+ // Discard this section.
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ }
+ break;
+
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ process_SOFn(Data, marker);
+ break;
+ default:
+ // Skip any other sections.
+ //if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);
+ break;
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Process a EXIF marker
+ Describes all the drivel that most digital cameras include...
+--------------------------------------------------------------------------*/
+bool CxImageJPG::CxExifInfo::process_EXIF(unsigned char * CharBuf, unsigned int length)
+{
+ m_exifinfo->FlashUsed = 0;
+ /* If it's from a digicam, and it used flash, it says so. */
+ m_exifinfo->Comments[0] = '\0'; /* Initial value - null string */
+
+ ExifImageWidth = 0;
+
+ { /* Check the EXIF header component */
+ static const unsigned char ExifHeader[] = "Exif\0\0";
+ if (memcmp(CharBuf+0, ExifHeader,6)){
+ strcpy(m_szLastError,"Incorrect Exif header");
+ return false;
+ }
+ }
+
+ if (memcmp(CharBuf+6,"II",2) == 0){
+ MotorolaOrder = 0;
+ }else{
+ if (memcmp(CharBuf+6,"MM",2) == 0){
+ MotorolaOrder = 1;
+ }else{
+ strcpy(m_szLastError,"Invalid Exif alignment marker.");
+ return false;
+ }
+ }
+
+ /* Check the next two values for correctness. */
+ if (Get16u(CharBuf+8) != 0x2a){
+ strcpy(m_szLastError,"Invalid Exif start (1)");
+ return false;
+ }
+
+ int FirstOffset = Get32u(CharBuf+10);
+ /*
+ if (FirstOffset < 8 || FirstOffset > 16){
+ // I used to ensure this was set to 8 (website I used indicated its 8)
+ // but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002)
+ strcpy(m_szLastError,"Suspicious offset of first IFD value");
+ return false;
+ }*/
+
+ unsigned char * LastExifRefd = CharBuf;
+
+ /* First directory starts 16 bytes in. Offsets start at 8 bytes in. */
+ if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))
+ return false;
+
+ /* give a chance for a second directory */
+ if (FirstOffset > 8) {
+ if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))
+ return false;
+ }
+
+ /* This is how far the interesting (non thumbnail) part of the exif went. */
+ // int ExifSettingsLength = LastExifRefd - CharBuf;
+
+ /* Compute the CCD width, in milimeters. */
+ if (m_exifinfo->FocalplaneXRes != 0){
+ m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);
+ }
+
+ return true;
+}
+//--------------------------------------------------------------------------
+// Get 16 bits motorola order (always) for jpeg header stuff.
+//--------------------------------------------------------------------------
+int CxImageJPG::CxExifInfo::Get16m(void * Short)
+{
+ return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Convert a 16 bit unsigned value from file's native byte order
+--------------------------------------------------------------------------*/
+int CxImageJPG::CxExifInfo::Get16u(void * Short)
+{
+ if (MotorolaOrder){
+ return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
+ }else{
+ return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0];
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Convert a 32 bit signed value from file's native byte order
+--------------------------------------------------------------------------*/
+long CxImageJPG::CxExifInfo::Get32s(void * Long)
+{
+ if (MotorolaOrder){
+ return ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16)
+ | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 );
+ }else{
+ return ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16)
+ | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 );
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Convert a 32 bit unsigned value from file's native byte order
+--------------------------------------------------------------------------*/
+unsigned long CxImageJPG::CxExifInfo::Get32u(void * Long)
+{
+ return (unsigned long)Get32s(Long) & 0xffffffff;
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/* Describes format descriptor */
+static const int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
+#define NUM_FORMATS 12
+
+#define FMT_BYTE 1
+#define FMT_STRING 2
+#define FMT_USHORT 3
+#define FMT_ULONG 4
+#define FMT_URATIONAL 5
+#define FMT_SBYTE 6
+#define FMT_UNDEFINED 7
+#define FMT_SSHORT 8
+#define FMT_SLONG 9
+#define FMT_SRATIONAL 10
+#define FMT_SINGLE 11
+#define FMT_DOUBLE 12
+
+/* Describes tag values */
+
+#define TAG_EXIF_VERSION 0x9000
+#define TAG_EXIF_OFFSET 0x8769
+#define TAG_INTEROP_OFFSET 0xa005
+
+#define TAG_MAKE 0x010F
+#define TAG_MODEL 0x0110
+
+#define TAG_ORIENTATION 0x0112
+#define TAG_XRESOLUTION 0x011A
+#define TAG_YRESOLUTION 0x011B
+#define TAG_RESOLUTIONUNIT 0x0128
+
+#define TAG_EXPOSURETIME 0x829A
+#define TAG_FNUMBER 0x829D
+
+#define TAG_SHUTTERSPEED 0x9201
+#define TAG_APERTURE 0x9202
+#define TAG_BRIGHTNESS 0x9203
+#define TAG_MAXAPERTURE 0x9205
+#define TAG_FOCALLENGTH 0x920A
+
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_USERCOMMENT 0x9286
+
+#define TAG_SUBJECT_DISTANCE 0x9206
+#define TAG_FLASH 0x9209
+
+#define TAG_FOCALPLANEXRES 0xa20E
+#define TAG_FOCALPLANEYRES 0xa20F
+#define TAG_FOCALPLANEUNITS 0xa210
+#define TAG_EXIF_IMAGEWIDTH 0xA002
+#define TAG_EXIF_IMAGELENGTH 0xA003
+
+/* the following is added 05-jan-2001 vcs */
+#define TAG_EXPOSURE_BIAS 0x9204
+#define TAG_WHITEBALANCE 0x9208
+#define TAG_METERING_MODE 0x9207
+#define TAG_EXPOSURE_PROGRAM 0x8822
+#define TAG_ISO_EQUIVALENT 0x8827
+#define TAG_COMPRESSION_LEVEL 0x9102
+
+#define TAG_THUMBNAIL_OFFSET 0x0201
+#define TAG_THUMBNAIL_LENGTH 0x0202
+
+
+/*--------------------------------------------------------------------------
+ Process one of the nested EXIF directories.
+--------------------------------------------------------------------------*/
+bool CxImageJPG::CxExifInfo::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
+ EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP )
+{
+ int de;
+ int a;
+ int NumDirEntries;
+ unsigned ThumbnailOffset = 0;
+ unsigned ThumbnailSize = 0;
+
+ NumDirEntries = Get16u(DirStart);
+
+ if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){
+ strcpy(m_szLastError,"Illegally sized directory");
+ return false;
+ }
+
+ for (de=0;de= NUM_FORMATS) {
+ /* (-1) catches illegal zero case as unsigned underflows to positive large */
+ strcpy(m_szLastError,"Illegal format code in EXIF dir");
+ return false;
+ }
+
+ ByteCount = Components * BytesPerFormat[Format];
+
+ if (ByteCount > 4){
+ unsigned OffsetVal;
+ OffsetVal = Get32u(DirEntry+8);
+ /* If its bigger than 4 bytes, the dir entry contains an offset.*/
+ if (OffsetVal+ByteCount > ExifLength){
+ /* Bogus pointer offset and / or bytecount value */
+ strcpy(m_szLastError,"Illegal pointer offset value in EXIF.");
+ return false;
+ }
+ ValuePtr = OffsetBase+OffsetVal;
+ }else{
+ /* 4 bytes or less and value is in the dir entry itself */
+ ValuePtr = DirEntry+8;
+ }
+
+ if (*LastExifRefdP < ValuePtr+ByteCount){
+ /* Keep track of last byte in the exif header that was
+ actually referenced. That way, we know where the
+ discardable thumbnail data begins.
+ */
+ *LastExifRefdP = ValuePtr+ByteCount;
+ }
+
+ /* Extract useful components of tag */
+ switch(Tag){
+
+ case TAG_MAKE:
+ strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31);
+ break;
+
+ case TAG_MODEL:
+ strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39);
+ break;
+
+ case TAG_EXIF_VERSION:
+ strncpy(m_exifinfo->Version,(char*)ValuePtr, 4);
+ break;
+
+ case TAG_DATETIME_ORIGINAL:
+ strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19);
+ break;
+
+ case TAG_USERCOMMENT:
+ // Olympus has this padded with trailing spaces. Remove these first.
+ for (a=ByteCount;;){
+ a--;
+ if (((char*)ValuePtr)[a] == ' '){
+ ((char*)ValuePtr)[a] = '\0';
+ }else{
+ break;
+ }
+ if (a == 0) break;
+ }
+
+ /* Copy the comment */
+ if (memcmp(ValuePtr, "ASCII",5) == 0){
+ for (a=5;a<10;a++){
+ char c;
+ c = ((char*)ValuePtr)[a];
+ if (c != '\0' && c != ' '){
+ strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199);
+ break;
+ }
+ }
+
+ }else{
+ strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199);
+ }
+ break;
+
+ case TAG_FNUMBER:
+ /* Simplest way of expressing aperture, so I trust it the most.
+ (overwrite previously computd value if there is one)
+ */
+ m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_APERTURE:
+ case TAG_MAXAPERTURE:
+ /* More relevant info always comes earlier, so only
+ use this field if we don't have appropriate aperture
+ information yet.
+ */
+ if (m_exifinfo->ApertureFNumber == 0){
+ m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)*0.5);
+ }
+ break;
+
+ case TAG_BRIGHTNESS:
+ m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_FOCALLENGTH:
+ /* Nice digital cameras actually save the focal length
+ as a function of how farthey are zoomed in.
+ */
+
+ m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_SUBJECT_DISTANCE:
+ /* Inidcates the distacne the autofocus camera is focused to.
+ Tends to be less accurate as distance increases.
+ */
+ m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_EXPOSURETIME:
+ /* Simplest way of expressing exposure time, so I
+ trust it most. (overwrite previously computd value
+ if there is one)
+ */
+ m_exifinfo->ExposureTime =
+ (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_SHUTTERSPEED:
+ /* More complicated way of expressing exposure time,
+ so only use this value if we don't already have it
+ from somewhere else.
+ */
+ if (m_exifinfo->ExposureTime == 0){
+ m_exifinfo->ExposureTime = (float)
+ (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)));
+ }
+ break;
+
+ case TAG_FLASH:
+ if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){
+ m_exifinfo->FlashUsed = 1;
+ }else{
+ m_exifinfo->FlashUsed = 0;
+ }
+ break;
+
+ case TAG_ORIENTATION:
+ m_exifinfo->Orientation = (int)ConvertAnyFormat(ValuePtr, Format);
+ if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){
+ strcpy(m_szLastError,"Undefined rotation value");
+ m_exifinfo->Orientation = 0;
+ }
+ break;
+
+ case TAG_EXIF_IMAGELENGTH:
+ case TAG_EXIF_IMAGEWIDTH:
+ /* Use largest of height and width to deal with images
+ that have been rotated to portrait format.
+ */
+ a = (int)ConvertAnyFormat(ValuePtr, Format);
+ if (ExifImageWidth < a) ExifImageWidth = a;
+ break;
+
+ case TAG_FOCALPLANEXRES:
+ m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_FOCALPLANEYRES:
+ m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_RESOLUTIONUNIT:
+ switch((int)ConvertAnyFormat(ValuePtr, Format)){
+ case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */
+ case 2: m_exifinfo->ResolutionUnit = 1.0f; break;
+ case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/
+ case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/
+ case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/
+ }
+ break;
+
+ case TAG_FOCALPLANEUNITS:
+ switch((int)ConvertAnyFormat(ValuePtr, Format)){
+ case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */
+ case 2: m_exifinfo->FocalplaneUnits = 1.0f; break;
+ case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/
+ case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/
+ case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/
+ }
+ break;
+
+ // Remaining cases contributed by: Volker C. Schoech
+
+ case TAG_EXPOSURE_BIAS:
+ m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_WHITEBALANCE:
+ m_exifinfo->Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_METERING_MODE:
+ m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_EXPOSURE_PROGRAM:
+ m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_ISO_EQUIVALENT:
+ m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
+ if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
+ break;
+
+ case TAG_COMPRESSION_LEVEL:
+ m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_XRESOLUTION:
+ m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_YRESOLUTION:
+ m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_THUMBNAIL_OFFSET:
+ ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_THUMBNAIL_LENGTH:
+ ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ }
+
+ if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){
+ unsigned char * SubdirStart;
+ unsigned Offset = Get32u(ValuePtr);
+ if (Offset>8){
+ SubdirStart = OffsetBase + Offset;
+ if (SubdirStart < OffsetBase ||
+ SubdirStart > OffsetBase+ExifLength){
+ strcpy(m_szLastError,"Illegal subdirectory link");
+ return false;
+ }
+ ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
+ }
+ continue;
+ }
+ }
+
+
+ {
+ /* In addition to linking to subdirectories via exif tags,
+ there's also a potential link to another directory at the end
+ of each directory. This has got to be the result of a
+ committee!
+ */
+ unsigned char * SubdirStart;
+ unsigned Offset;
+ Offset = Get16u(DirStart+2+12*NumDirEntries);
+ if (Offset){
+ SubdirStart = OffsetBase + Offset;
+ if (SubdirStart < OffsetBase
+ || SubdirStart > OffsetBase+ExifLength){
+ strcpy(m_szLastError,"Illegal subdirectory link");
+ return false;
+ }
+ ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
+ }
+ }
+
+
+ if (ThumbnailSize && ThumbnailOffset){
+ if (ThumbnailSize + ThumbnailOffset <= ExifLength){
+ /* The thumbnail pointer appears to be valid. Store it. */
+ m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
+ m_exifinfo->ThumbnailSize = ThumbnailSize;
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Evaluate number, be it int, rational, or float from directory.
+--------------------------------------------------------------------------*/
+double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int Format)
+{
+ double Value;
+ Value = 0;
+
+ switch(Format){
+ case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
+ case FMT_BYTE: Value = *(unsigned char *)ValuePtr; break;
+
+ case FMT_USHORT: Value = Get16u(ValuePtr); break;
+ case FMT_ULONG: Value = Get32u(ValuePtr); break;
+
+ case FMT_URATIONAL:
+ case FMT_SRATIONAL:
+ {
+ int Num,Den;
+ Num = Get32s(ValuePtr);
+ Den = Get32s(4+(char *)ValuePtr);
+ if (Den == 0){
+ Value = 0;
+ }else{
+ Value = (double)Num/Den;
+ }
+ break;
+ }
+
+ case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break;
+ case FMT_SLONG: Value = Get32s(ValuePtr); break;
+
+ /* Not sure if this is correct (never seen float used in Exif format)
+ */
+ case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
+ case FMT_DOUBLE: Value = *(double *)ValuePtr; break;
+ }
+ return Value;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageJPG::CxExifInfo::process_COM (const BYTE * Data, int length)
+{
+ int ch;
+ char Comment[MAX_COMMENT+1];
+ int nch;
+ int a;
+
+ nch = 0;
+
+ if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure.
+
+ for (a=2;aComments,Comment);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageJPG::CxExifInfo::process_SOFn (const BYTE * Data, int marker)
+{
+ int data_precision, num_components;
+
+ data_precision = Data[2];
+ m_exifinfo->Height = Get16m((void*)(Data+3));
+ m_exifinfo->Width = Get16m((void*)(Data+5));
+ num_components = Data[7];
+
+ if (num_components == 3){
+ m_exifinfo->IsColor = 1;
+ }else{
+ m_exifinfo->IsColor = 0;
+ }
+
+ m_exifinfo->Process = marker;
+
+ //if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
+ // ImageInfo.Width, ImageInfo.Height, num_components, data_precision);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * this will work only on a CxImageJPG object, if the image originally has valid EXIF data
+ \verbatim
+ CxImageJPG jpg;
+ CxIOFile in,out;
+ in.Open("D:\\exif_in.jpg","rb");
+ out.Open("D:\\exif_out.jpg","w+b");
+ jpg.Decode(&in);
+ if (jpg.IsValid()){
+ jpg.RotateLeft();
+ jpg.Encode(&out);
+ }
+ \endverbatim
+*/
+bool CxImageJPG::CxExifInfo::EncodeExif(CxFile * hFile)
+{
+ int a;
+
+ if (FindSection(M_SOS)==NULL){
+ strcpy(m_szLastError,"Can't write exif : didn't read all");
+ return false;
+ }
+
+ // Initial static jpeg marker.
+ hFile->PutC(0xff);
+ hFile->PutC(0xd8);
+
+ if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){
+ // The image must start with an exif or jfif marker. If we threw those away, create one.
+ static BYTE JfifHead[18] = {
+ 0xff, M_JFIF,
+ 0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01,
+ 0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00
+ };
+ hFile->Write(JfifHead, 18, 1);
+ }
+
+ // Write all the misc sections
+ for (a=0;a