Integrated the VBA-SDL-H2 code into the GDB function.
This allows breakpoints, memory views and watches to be controlled from the GDB interface. The VBA-SDL-H2 commands can be entered via the GDB monitor (type "help" into the monitor for a list of commands). Made minor changes to the GDB interface so that the GDB port does not need to be entered every session. A "Break on Load" option has been added allowing GDB to be connected before the ROM starts executing. VBA-SDL-H2 credits: Labmaster, kenobi, DevZ, richq, JPAN, Griever
This commit is contained in:
parent
7722a59670
commit
55e1dad514
|
@ -197,8 +197,11 @@ endif(ENABLE_FFMPEG)
|
|||
SET(SRC_GBA
|
||||
src/gba/agbprint.cpp
|
||||
src/gba/bios.cpp
|
||||
src/gba/BreakpointStructures.cpp
|
||||
src/gba/Cheats.cpp
|
||||
src/gba/CheatSearch.cpp
|
||||
src/gba/debugger-expr-lex.cpp
|
||||
src/gba/debugger-expr-yacc.cpp
|
||||
src/gba/EEprom.cpp
|
||||
src/gba/ereader.cpp
|
||||
src/gba/Flash.cpp
|
||||
|
@ -243,7 +246,6 @@ SET(SRC_APU
|
|||
)
|
||||
|
||||
SET(SRC_SDL
|
||||
src/sdl/debugger.cpp
|
||||
src/sdl/SDL.cpp
|
||||
src/sdl/filters.cpp
|
||||
src/sdl/text.cpp
|
||||
|
|
|
@ -446,6 +446,26 @@
|
|||
RelativePath="..\..\src\gba\bios.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gba\BreakpointStructures.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gba\BreakpointStructures.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gba\debugger-expr-lex.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gba\debugger-expr-yacc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gba\debugger-expr-yacc.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gba\EEprom.cpp"
|
||||
>
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..\..\src;..\..\fex;..\..\..\dependencies\libpng;..\..\..\dependencies\msvc;..\..\..\dependencies\SFML\include;..\..\..\dependencies\SubWCRev;..\..\..\dependencies\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NO_OAL;NDEBUG;GBA_LOGGING;OEMRESOURCE;MMX;ASM;FINAL_VERSION;BKPT_SUPPORT;_CRT_SECURE_NO_DEPRECATE;HAS_FILE_EXTRACTOR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;GBA_LOGGING;OEMRESOURCE;MMX;ASM;FINAL_VERSION;BKPT_SUPPORT;_CRT_SECURE_NO_DEPRECATE;HAS_FILE_EXTRACTOR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
|
@ -167,7 +167,9 @@
|
|||
<ClInclude Include="..\..\src\apu\Multi_Buffer.h" />
|
||||
<ClInclude Include="..\..\src\gba\agbprint.h" />
|
||||
<ClInclude Include="..\..\src\gba\ereader.h" />
|
||||
<ClInclude Include="..\..\src\gba\BreakpointStructures.h" />
|
||||
<ClInclude Include="..\..\src\gba\bios.h" />
|
||||
<ClInclude Include="..\..\src\gba\debugger-expr-yacc.hpp" />
|
||||
<ClInclude Include="..\..\src\gba\EEprom.h" />
|
||||
<ClInclude Include="..\..\src\gba\elf.h" />
|
||||
<ClInclude Include="..\..\src\gba\Flash.h" />
|
||||
|
@ -295,6 +297,9 @@
|
|||
<ClCompile Include="..\..\src\apu\Multi_Buffer.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\agbprint.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\bios.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\BreakpointStructures.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-lex.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-yacc.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\EEprom.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\elf.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\ereader.cpp" />
|
||||
|
|
|
@ -115,6 +115,12 @@
|
|||
<ClInclude Include="..\..\src\gba\bios.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gba\BreakpointStructures.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gba\debugger-expr-yacc.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gba\EEprom.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
|
@ -484,6 +490,15 @@
|
|||
<ClCompile Include="..\..\src\gba\bios.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\BreakpointStructures.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-lex.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-yacc.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\EEprom.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -174,6 +174,8 @@
|
|||
<ClInclude Include="..\..\src\apu\Multi_Buffer.h" />
|
||||
<ClInclude Include="..\..\src\gba\agbprint.h" />
|
||||
<ClInclude Include="..\..\src\gba\bios.h" />
|
||||
<ClInclude Include="..\..\src\gba\BreakpointStructures.h" />
|
||||
<ClInclude Include="..\..\src\gba\debugger-expr-yacc.hpp" />
|
||||
<ClInclude Include="..\..\src\gba\EEprom.h" />
|
||||
<ClInclude Include="..\..\src\gba\elf.h" />
|
||||
<ClInclude Include="..\..\src\gba\ereader.h" />
|
||||
|
@ -302,6 +304,9 @@
|
|||
<ClCompile Include="..\..\src\apu\Multi_Buffer.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\agbprint.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\bios.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\BreakpointStructures.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-lex.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-yacc.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\EEprom.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\elf.cpp" />
|
||||
<ClCompile Include="..\..\src\gba\ereader.cpp" />
|
||||
|
|
|
@ -112,6 +112,12 @@
|
|||
<ClInclude Include="..\..\src\gba\bios.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gba\BreakpointStructures.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gba\debugger-expr-yacc.hpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gba\EEprom.h">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClInclude>
|
||||
|
@ -484,6 +490,15 @@
|
|||
<ClCompile Include="..\..\src\gba\bios.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\BreakpointStructures.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-lex.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\debugger-expr-yacc.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gba\EEprom.cpp">
|
||||
<Filter>Core\GBA</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -0,0 +1,856 @@
|
|||
/*New code made for the new breakpoint system.
|
||||
|
||||
Each breakpoint is now marked by a halfword in an array on map,
|
||||
breakpoint array. Each bit means one different type of breakpoint.
|
||||
Bit Value
|
||||
0 - write
|
||||
1 - read
|
||||
2 - ARM
|
||||
3 - THUMB
|
||||
4 - Always on Write
|
||||
5 - Always on Read
|
||||
6 - Always on ARM
|
||||
7 - Always on THUMB
|
||||
|
||||
Each flag is independant, and can be used as such, as well as together.
|
||||
You can define a break on access (0xf), break on IO (0x3), break on
|
||||
execution(0xc) or any other combination you need. 0xf0 will always break on
|
||||
any passage through the address
|
||||
|
||||
This structure is accompanied by two other structures for the accesses.
|
||||
One of them is the Conditional structure. It's available for all types.
|
||||
|
||||
The breaking address header is placed at ConditionalBreak. The type_flags
|
||||
indicate the type of break, in the format indicated above.
|
||||
Then, it links to the several conditions needed for the break to take place.
|
||||
|
||||
Those conditions are then sequentially executed, and if all are true, the
|
||||
break takes place.
|
||||
They are composed of an address to test, a value to test against, the value's
|
||||
type, the flag conditons to test and a link to the next condition to test if
|
||||
that was true. Address and value are stored as Evaluatable expressions,
|
||||
according to the already defined eval from expr.c
|
||||
However, be reminded that sometimes registers and memory positions may contain
|
||||
values that are not addresses at some times. If such is the case, the program
|
||||
will show garbage results or crash.
|
||||
|
||||
The flags are bit-based
|
||||
Bit Value
|
||||
0 - equal
|
||||
1 - greater
|
||||
2 - lesser
|
||||
3 - force Signed comparison
|
||||
|
||||
Bit Value
|
||||
0,1 - addr is: 00 - byte, 01 - halfword, 10 - word, 11 - undefined, assume word
|
||||
2 - addr_is_signed
|
||||
3 - addr_is_array of values (not implemented yet)
|
||||
4,5 - 00 is byte, 01 is halfword, 10 is word, 11 undefined
|
||||
6 - val_is_signed
|
||||
7 - val_is_array (also not implemented)
|
||||
Usage:
|
||||
Instructions that accept this kind of implementation will follow this pattern
|
||||
if <EXP_addr> <addr_type><op><val_type> <EXP_val> [<;>OR<||>OR<&&> [repeat]
|
||||
if indicates that the following there is a condition. no If counts as always break
|
||||
<EXP_addr> is the first value expression, that unlike what the name implies, may be
|
||||
anything.
|
||||
<op> is one of the comparation Operands. Full list bellow
|
||||
<EXP_val> is the value to compare to.
|
||||
Following can be a ||(or), that adds a second, independant break condition, or
|
||||
a &&(and), that specifies that the next condition is a conjoined requisite to the break.
|
||||
EX: [0x03005000] == 0x77777777 && 0x50 == [0x03005000]
|
||||
Would be impossible, but tested anyway, and make it never break due to this condition.
|
||||
[0x03005000] == 0x77777777 || 0x50 == [0x03005000]
|
||||
Would make it break when the contents of 0x03005000 were either 0x77777777 or 0x50
|
||||
|
||||
Ex: to implement stop only when r2 is 0xf, use
|
||||
if r2 == 0xf
|
||||
to implement stop when PC is above 0x08005000 and 0x03005000 is signed halfword 0x2500
|
||||
if pc > 0x08005000 && 0x03005000 == +0x2500
|
||||
*/
|
||||
|
||||
/*
|
||||
Full Operands lists
|
||||
Op1, op2, ...,opN --> Meaning
|
||||
|
||||
== , =, eq --> equal
|
||||
|
||||
<, lt --> lesser than
|
||||
|
||||
<=, le --> less or equal to
|
||||
|
||||
> gt --> greater than
|
||||
|
||||
>=, ge --> greater or equal to
|
||||
|
||||
!=, <>, ne --> not equal to
|
||||
|
||||
|
||||
valid content types
|
||||
b, byte, u8 --> byte
|
||||
sb, sbyte, s8 --> signed byte
|
||||
h,hw, halfword, u16, ushort --> halfword
|
||||
sh, shw, shalfword, s16 short --> signed halfword
|
||||
w, word, u32 --> word
|
||||
sw, sword, s32, int --> signed word
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "BreakpointStructures.h"
|
||||
#include "remote.h"
|
||||
|
||||
extern bool dexp_eval(char *, u32*);
|
||||
|
||||
//struct intToString{
|
||||
// int value;
|
||||
// char mapping[20];
|
||||
//};
|
||||
|
||||
struct ConditionalBreak* conditionals[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
|
||||
//struct intToString breakFlagMapping[] = {
|
||||
// {0x80,"Thumb"},
|
||||
// {0x40,"ARM"},
|
||||
// {0x20,"Read"},
|
||||
// {0x10,"Write"},
|
||||
// {0x8,"Thumb"},
|
||||
// {0x4,"ARM"},
|
||||
// {0x2,"Read"},
|
||||
// {0x1,"Write"},
|
||||
// {0x0,"None"}
|
||||
//};
|
||||
/*
|
||||
struct intToString compareFlagMapping[] = {
|
||||
{0x7,"Always"},
|
||||
{0x6,"!="},
|
||||
{0x5,"<="},
|
||||
{0x4,"<"},
|
||||
{0x3,">="},
|
||||
{0x2,">"},
|
||||
{0x1,"=="},
|
||||
{0x0,"Never"}
|
||||
};*/
|
||||
|
||||
//char* typeMapping[] = {"'u8","'u16","'u32","'u32","'s8","'s16","'s32","'s32"};
|
||||
//
|
||||
//char* compareFlagMapping[] = {"Never","==",">",">=","<","<=","!=","<=>"};
|
||||
|
||||
|
||||
|
||||
|
||||
//Constructors
|
||||
//case '*': flag = 0xf; break;
|
||||
//case 't': flag = 0x8; break; // thumb
|
||||
//case 'a': flag = 0x4; break; // arm
|
||||
//case 'x': flag = 0xC; break;
|
||||
//case 'r': flag = 0x2; break; // mem read
|
||||
//case 'w': flag = 0x1; break; // mem write
|
||||
//case 'i': flag = 0x3; break;
|
||||
struct ConditionalBreak* addConditionalBreak(u32 address, u8 flag){
|
||||
u8 condIndex = address>>24;
|
||||
struct ConditionalBreak* cond = NULL;
|
||||
BreakSet((&map[condIndex])->breakPoints,address & (&map[condIndex])->mask,((flag&0xf)|(flag>>4)));
|
||||
if(flag & 0xf0){
|
||||
struct ConditionalBreak* base = conditionals[condIndex];
|
||||
struct ConditionalBreak* prev = conditionals[condIndex];
|
||||
if(conditionals[condIndex]){
|
||||
while((base) && (address >= base->break_address)){
|
||||
if(base->break_address == address){
|
||||
if(base->type_flags & 0xf0){
|
||||
base->type_flags |= (flag&0xf0);
|
||||
flag &= 0xf;
|
||||
cond = base;
|
||||
goto addCB_nextHandle;
|
||||
}else{
|
||||
goto condCreateForFlagAlways;
|
||||
}
|
||||
}else{
|
||||
prev = base;
|
||||
base = base->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
condCreateForFlagAlways:
|
||||
cond = (struct ConditionalBreak*)malloc(sizeof(struct ConditionalBreak));
|
||||
cond->break_address = address;
|
||||
cond->type_flags = flag&0xf0;
|
||||
cond->next = base;
|
||||
cond->firstCond = NULL;
|
||||
if(prev == conditionals[condIndex])
|
||||
conditionals[condIndex] = cond;
|
||||
else
|
||||
prev->next = cond;
|
||||
}
|
||||
flag &= 0xf;
|
||||
|
||||
addCB_nextHandle:
|
||||
if(flag == 0)
|
||||
return cond;
|
||||
|
||||
cond = (struct ConditionalBreak*)malloc(sizeof(struct ConditionalBreak));
|
||||
cond->break_address = address;
|
||||
cond->type_flags = flag;
|
||||
cond->next = NULL;
|
||||
cond->firstCond = NULL;
|
||||
if(conditionals[condIndex] == NULL){
|
||||
conditionals[condIndex] = cond;
|
||||
return cond;
|
||||
}else{
|
||||
struct ConditionalBreak *curr, *prev;
|
||||
curr = conditionals[condIndex];
|
||||
prev = conditionals[condIndex];
|
||||
while(curr){
|
||||
if(curr->break_address > address){
|
||||
if(prev == curr){
|
||||
conditionals[condIndex] = cond;
|
||||
}else{
|
||||
prev->next = cond;
|
||||
}
|
||||
cond->next = curr;
|
||||
return cond;
|
||||
}
|
||||
prev = curr;
|
||||
curr = prev->next;
|
||||
}
|
||||
prev->next = cond;
|
||||
return cond;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addCondition(struct ConditionalBreak* base, struct ConditionalBreakNode* toAdd){
|
||||
if(base->firstCond){
|
||||
struct ConditionalBreakNode* curr, *prev;
|
||||
curr = base->firstCond;
|
||||
prev = base->firstCond;
|
||||
while(curr){
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
prev->next = toAdd;
|
||||
}else{
|
||||
base->firstCond = toAdd;
|
||||
}
|
||||
}
|
||||
|
||||
//destructors
|
||||
void freeConditionalBreak(struct ConditionalBreak* toFree){
|
||||
struct ConditionalBreakNode* freeMe;
|
||||
while(toFree->firstCond){
|
||||
freeMe = toFree->firstCond;
|
||||
toFree->firstCond = toFree->firstCond->next;
|
||||
free(freeMe);
|
||||
}
|
||||
free(toFree);
|
||||
}
|
||||
|
||||
void freeConditionalNode(struct ConditionalBreakNode* toDel){
|
||||
if(toDel->next)
|
||||
freeConditionalNode(toDel->next);
|
||||
if(toDel->address)
|
||||
free(toDel->address);
|
||||
if(toDel->value)
|
||||
free(toDel->value);
|
||||
free(toDel);
|
||||
}
|
||||
|
||||
void freeAllConditionals(){
|
||||
for(int i = 0; i<16; i++){
|
||||
while(conditionals[i]){
|
||||
struct ConditionalBreak* tmp = conditionals[i];
|
||||
conditionals[i] = conditionals[i]->next;
|
||||
freeConditionalBreak(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int removeConditionalBreak(struct ConditionalBreak* toDelete){
|
||||
if(toDelete){
|
||||
u8 condIndex = toDelete->break_address>>24;
|
||||
struct ConditionalBreak* base = conditionals[condIndex];
|
||||
struct ConditionalBreak* prev = conditionals[condIndex];
|
||||
while(base){
|
||||
if(base == toDelete){
|
||||
if(base == prev){
|
||||
conditionals[condIndex] = base->next;
|
||||
}else{
|
||||
prev->next = base->next;
|
||||
}
|
||||
freeConditionalBreak(toDelete);
|
||||
return 0;
|
||||
}
|
||||
prev = base;
|
||||
base = base->next;
|
||||
}
|
||||
return -1; //failed to remove
|
||||
}
|
||||
return -2; //delete failed because container was not there
|
||||
}
|
||||
|
||||
/*
|
||||
int removeConditionalBreak(u32 address, u8 num, u8 flag){
|
||||
u8 condIndex = address>>24;
|
||||
struct ConditionalBreak* base = conditionals[condIndex];
|
||||
struct ConditionalBreak* prev = conditionals[condIndex];
|
||||
u8 counter = 0;
|
||||
while(base){
|
||||
if(base->break_address > address)
|
||||
return -2; //failed to remove
|
||||
if(base->break_address == address){
|
||||
counter++;
|
||||
}
|
||||
if(counter == num){
|
||||
base->type_flags &= ~flag;
|
||||
if(base->type_flags == 0){
|
||||
if(prev == base){
|
||||
conditionals[condIndex] = base->next;
|
||||
}else{
|
||||
prev->next = base->next;
|
||||
}
|
||||
freeConditionalBreak(base);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
prev = base;
|
||||
base = base->next;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
bool removeCondition(struct ConditionalBreak* base, struct ConditionalBreakNode* toDel){
|
||||
if(base->firstCond){
|
||||
if(toDel == base->firstCond){
|
||||
base->firstCond = toDel->next;
|
||||
freeConditionalNode(toDel);
|
||||
return true;
|
||||
}
|
||||
struct ConditionalBreakNode* curr, *prev;
|
||||
curr = base->firstCond;
|
||||
prev = base->firstCond;
|
||||
while(curr){
|
||||
if(curr == toDel){
|
||||
prev->next = curr->next;
|
||||
freeConditionalNode(toDel);
|
||||
return true;
|
||||
}
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
freeConditionalNode(toDel);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool removeCondition(u32 address, u8 flags, u8 num){
|
||||
struct ConditionalBreak* base = conditionals[address>>24];
|
||||
while(base && base->break_address < address){
|
||||
base = base->next;
|
||||
}
|
||||
if(base && base->break_address == address){
|
||||
struct ConditionalBreakNode* curr = base->firstCond;
|
||||
for(int i = 0; i < num; i++){
|
||||
if(!curr && ((!base) || (!base->next))){
|
||||
return false;
|
||||
}if(!curr){
|
||||
while(!curr){
|
||||
base = base->next;
|
||||
if(base->break_address > address)
|
||||
return false;
|
||||
|
||||
curr = base->firstCond;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
int removeAllConditions(u32 address, u8 flags){
|
||||
struct ConditionalBreak* base = conditionals[address>>24];
|
||||
while(base && base->break_address < address){
|
||||
base = base->next;
|
||||
}
|
||||
struct ConditionalBreak* curr = base;
|
||||
while(base && base->break_address == address){
|
||||
base->type_flags &= ~flags;
|
||||
if(!base->type_flags){
|
||||
curr = base;
|
||||
base = base->next;
|
||||
removeCondition(base);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}*/
|
||||
|
||||
void recountFlagsForAddress(u32 address){
|
||||
struct ConditionalBreak* base = conditionals[address>>24];
|
||||
u8 flags = 0;
|
||||
while(base){
|
||||
if(base->break_address < address){
|
||||
base = base->next;
|
||||
}else{
|
||||
if(base->break_address == address){
|
||||
flags |= base->type_flags;
|
||||
}else{
|
||||
BreakClear((&map[address>>24])->breakPoints,address & (&map[address>>24])->mask,0xff);
|
||||
BreakSet((&map[address>>24])->breakPoints,address & (&map[address>>24])->mask,((flags>>4) | (flags&0x8)));
|
||||
return;
|
||||
}
|
||||
base = base->next;
|
||||
}
|
||||
}
|
||||
BreakClear((&map[address>>24])->breakPoints,address & (&map[address>>24])->mask,0xff);
|
||||
BreakSet((&map[address>>24])->breakPoints,address & (&map[address>>24])->mask,((flags>>4) | (flags&0x8)));
|
||||
}
|
||||
|
||||
|
||||
//Removers
|
||||
int removeConditionalBreakNo(u32 addrNo, u8 number){
|
||||
if(conditionals[addrNo>>24]){
|
||||
struct ConditionalBreak* base = conditionals[addrNo>>24];
|
||||
struct ConditionalBreak* curr = conditionals[addrNo>>24];
|
||||
u8 count = 1;
|
||||
while (curr->break_address < addrNo){
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
if(curr->break_address == addrNo){
|
||||
if(number == 1){
|
||||
if(base == curr){
|
||||
conditionals[addrNo>>24] = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
}else{
|
||||
base->next = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
}
|
||||
recountFlagsForAddress(addrNo);
|
||||
return 0;
|
||||
}else{
|
||||
int count = 1;
|
||||
while(curr && (curr->break_address == addrNo)){
|
||||
if(count == number){
|
||||
base->next = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
recountFlagsForAddress(addrNo);
|
||||
return 1;
|
||||
}
|
||||
count++;
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int removeFlagFromConditionalBreakNo(u32 addrNo, u8 number, u8 flag){
|
||||
if(conditionals[addrNo>>24]){
|
||||
struct ConditionalBreak* base = conditionals[addrNo>>24];
|
||||
struct ConditionalBreak* curr = conditionals[addrNo>>24];
|
||||
u8 count = 1;
|
||||
while (curr->break_address < addrNo){
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
if(curr->break_address == addrNo){
|
||||
if(number == 1){
|
||||
curr->type_flags &= ~flag;
|
||||
if(curr->type_flags == 0){
|
||||
if(base == curr){
|
||||
conditionals[addrNo>>24] = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
}else{
|
||||
base->next = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
}
|
||||
}
|
||||
recountFlagsForAddress(addrNo);
|
||||
return 0;
|
||||
}else{
|
||||
int count = 1;
|
||||
while(curr && (curr->break_address == addrNo)){
|
||||
if(count == number){
|
||||
curr->type_flags &= ~flag;
|
||||
if(!curr->type_flags){
|
||||
base->next = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
recountFlagsForAddress(addrNo);
|
||||
return 1;
|
||||
}
|
||||
recountFlagsForAddress(addrNo);
|
||||
return 0;
|
||||
}
|
||||
count++;
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int removeConditionalWithAddress(u32 address){
|
||||
u8 addrNo = address>>24;
|
||||
if(conditionals[addrNo] != NULL){
|
||||
struct ConditionalBreak* base = conditionals[addrNo];
|
||||
struct ConditionalBreak* curr = conditionals[addrNo];
|
||||
u8 count = 0;
|
||||
u8 flags = 0;
|
||||
while(curr && address >= curr->break_address){
|
||||
if(curr->break_address == address){
|
||||
base->next = curr->next;
|
||||
flags |= curr->type_flags;
|
||||
freeConditionalBreak(curr);
|
||||
curr = base->next;
|
||||
count++;
|
||||
}else{
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
BreakClear((&map[address>>24])->breakPoints,address & (&map[address>>24])->mask,((flags&0xf)|(flags>>4)));
|
||||
return count;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int removeConditionalWithFlag(u8 flag, bool orMode){
|
||||
for(u8 addrNo = 0; addrNo < 16;addrNo++){
|
||||
if(conditionals[addrNo] != NULL){
|
||||
struct ConditionalBreak* base = conditionals[addrNo];
|
||||
struct ConditionalBreak* curr = conditionals[addrNo];
|
||||
u8 count = 0;
|
||||
while(curr){
|
||||
if(((curr->type_flags & flag) == curr->type_flags) || (orMode && (curr->type_flags & flag))){
|
||||
curr->type_flags &= ~flag;
|
||||
BreakClear((&map[addrNo])->breakPoints,curr->break_address & (&map[addrNo])->mask,((flag&0xf)|(flag>>4)));
|
||||
if(curr->type_flags == 0){
|
||||
if(base == conditionals[addrNo]){
|
||||
conditionals[addrNo]= curr->next;
|
||||
base = curr->next;
|
||||
curr = base;
|
||||
}
|
||||
else{
|
||||
base->next = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
curr = base->next;
|
||||
}
|
||||
count++;
|
||||
}else{
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}else{
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int removeConditionalWithAddressAndFlag(u32 address, u8 flag, bool orMode){
|
||||
u8 addrNo = address>>24;
|
||||
if(conditionals[addrNo] != NULL){
|
||||
struct ConditionalBreak* base = conditionals[addrNo];
|
||||
struct ConditionalBreak* curr = conditionals[addrNo];
|
||||
u8 count = 0;
|
||||
while(curr && address >= curr->break_address){
|
||||
if((curr->break_address == address) &&
|
||||
(((curr->type_flags & flag) == curr->type_flags) || (orMode && (curr->type_flags & flag)))){
|
||||
curr->type_flags &= ~flag;
|
||||
BreakClear((&map[address>>24])->breakPoints,curr->break_address & (&map[address>>24])->mask,((flag&0xf)|(flag>>4)));
|
||||
if(curr->type_flags == 0){
|
||||
if(curr == conditionals[addrNo]){
|
||||
conditionals[addrNo] = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
curr = conditionals[addrNo];
|
||||
}
|
||||
else{
|
||||
base->next = curr->next;
|
||||
freeConditionalBreak(curr);
|
||||
curr = base->next;
|
||||
}
|
||||
count++;
|
||||
}else{
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}else{
|
||||
base = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//true creating code for a given expression.
|
||||
//It assumes an if was found, and that all up to the if was removed.
|
||||
//receives an array of chars following the pattern:
|
||||
//{'<expType>,<exp>,<op>,'<expType>,<exp>,<And_symbol|or_symbol>, (repeats)
|
||||
//<expType is optional, and always assumes int-compare as default.
|
||||
u8 parseExpressionType(char* type);
|
||||
u8 parseConditionOperand(char* type);
|
||||
void parseAndCreateConditionalBreaks(u32 address, u8 flags, char** exp, int n){
|
||||
struct ConditionalBreak *workBreak = addConditionalBreak(address, flags);
|
||||
flags &= 0xf;
|
||||
if(!flags)
|
||||
return;
|
||||
bool notBk = true;
|
||||
struct ConditionalBreakNode* now = (struct ConditionalBreakNode*)malloc(sizeof(struct ConditionalBreakNode));
|
||||
struct ConditionalBreakNode* toAdd = now;
|
||||
for(int i = 0; i < n; i++){
|
||||
now->next = 0;
|
||||
now->exp_type_flags = 0;
|
||||
if(exp[i][0] == '\''){
|
||||
now->exp_type_flags |= parseExpressionType(&exp[i][1]);
|
||||
i++;
|
||||
if(i >= n) goto fail;
|
||||
}else{
|
||||
now->exp_type_flags |= 6; //assume signed word
|
||||
}
|
||||
now->address = strdup(exp[i]);
|
||||
i++;
|
||||
if(i >= n) goto fail;
|
||||
char* operandName = exp[i];
|
||||
now->cond_flags = parseConditionOperand(exp[i]);
|
||||
i++;
|
||||
if(i >= n) goto fail;
|
||||
|
||||
if(exp[i][0] == '\''){
|
||||
now->exp_type_flags |= (parseExpressionType(&exp[i][1])<<4);
|
||||
i++;
|
||||
if(i >= n) goto fail;
|
||||
}else{
|
||||
now->exp_type_flags |= 0x60; //assume signed word
|
||||
}
|
||||
now->value = strdup(exp[i]);
|
||||
i++;
|
||||
u32 val;
|
||||
if(!dexp_eval(now->value, &val) || !dexp_eval(now->address, &val)){
|
||||
printf("Invalid expression.\n");
|
||||
if(workBreak)
|
||||
removeConditionalBreak(workBreak);
|
||||
return;
|
||||
}
|
||||
if(i < n){
|
||||
if(strcmp(exp[i], "&&") == 0){
|
||||
now = (struct ConditionalBreakNode*)malloc(sizeof(struct ConditionalBreakNode));
|
||||
toAdd->next = now;
|
||||
}else if (strcmp(exp[i], "||") == 0){
|
||||
addCondition(workBreak,toAdd);
|
||||
printf("Added break on address %08x, with condition:\n%s %s %s\n", address, now->address, operandName,now->value);
|
||||
workBreak = addConditionalBreak(address, flags);
|
||||
now = (struct ConditionalBreakNode*)malloc(sizeof(struct ConditionalBreakNode));
|
||||
toAdd = now;
|
||||
}
|
||||
}else{
|
||||
addCondition(workBreak,toAdd);
|
||||
printf("Added break on address %08x, ending with condition: \n%s %s %s\n", address, now->address, operandName,now->value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
fail:
|
||||
printf("Not enough material (expressions) to work with.");
|
||||
removeConditionalBreak(workBreak);
|
||||
return;
|
||||
}
|
||||
|
||||
//aux
|
||||
u8 parseExpressionType(char* given_type){
|
||||
u8 flags = 0;
|
||||
//for such a small string, pays off to convert first
|
||||
char* type = strdup(given_type);
|
||||
for(int i = 0; type[i] != '\0'; i++){
|
||||
type[i] = toupper(type[i]);
|
||||
}
|
||||
if((type[0] == 'S') || type[0] == 'U'){
|
||||
flags |= (4 - ((type[0]-'S')<<1));
|
||||
type++;
|
||||
if(type[0] == 'H'){
|
||||
type[0] = '1';
|
||||
type[1] = '6';
|
||||
type[2] = '\0';
|
||||
}else if(type[0] == 'W'){
|
||||
type[0] = '3';
|
||||
type[1] = '2';
|
||||
type[2] = '\0';
|
||||
}else if(type[0] == 'B'){
|
||||
type[0] = '8';
|
||||
type[1] = '\0';
|
||||
}
|
||||
int size;
|
||||
sscanf(type, "%d",&size);
|
||||
size = (size>>3) - 1;
|
||||
flags |= (size >= 2 ? 2: ((u8)size));
|
||||
free(type);
|
||||
return flags;
|
||||
}
|
||||
if(strcmp(type, "INT")==0){
|
||||
flags = 6;
|
||||
}
|
||||
if(type[0] == 'H'){
|
||||
flags = 1;
|
||||
}else if(type[0] == 'W'){
|
||||
flags = 2;
|
||||
}else if(type[0] == 'B'){
|
||||
flags = 0;
|
||||
}else{
|
||||
flags = 6;
|
||||
}
|
||||
free(type);
|
||||
return flags;
|
||||
}
|
||||
|
||||
u8 parseConditionOperand(char* type){
|
||||
u8 flag = 0;
|
||||
if(toupper(type[0]) == 'S'){
|
||||
flag = 8;
|
||||
type++;
|
||||
}
|
||||
switch(type[0]){
|
||||
case '!': if(type[1] == '=' || type[1] == '\0')
|
||||
return flag | 0x6;
|
||||
break;
|
||||
case '=': if(type[1] == '=' || type[1] == '\0')
|
||||
return flag | 0x1;
|
||||
break;
|
||||
case '<': if(type[1] == '>')
|
||||
return flag | 0x6;
|
||||
if(type[1] == '=')
|
||||
return flag | 0x5;
|
||||
if(type[1] == '\0')
|
||||
return flag | 0x4;
|
||||
break;
|
||||
case '>': if(type[1] == '<')
|
||||
return flag | 0x6;
|
||||
if(type[1] == '=')
|
||||
return flag | 0x3;
|
||||
if(type[1] == '\0')
|
||||
return flag | 0x2;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
switch(tolower(type[0])){
|
||||
case 'l': if(tolower(type[1]) == 'e')
|
||||
return flag | 0x5;
|
||||
if(tolower(type[1]) == 't')
|
||||
return flag | 0x4;
|
||||
break;
|
||||
case 'g': if(tolower(type[1]) == 'e')
|
||||
return flag | 0x3;
|
||||
if(tolower(type[1]) == 't')
|
||||
return flag | 0x2;
|
||||
|
||||
case 'e': if(tolower(type[1]) == 'q')
|
||||
return flag | 0x1;
|
||||
if(type[1] == '\0')
|
||||
return flag | 0x1;
|
||||
case 'n': if(tolower(type[1]) == 'e')
|
||||
return flag | 0x6;
|
||||
default:;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
u32 calculateFinalValue(char* expToEval, u8 type_of_flags){
|
||||
u32 val;
|
||||
if(!dexp_eval(expToEval, &val)){
|
||||
printf("Invalid expression.\n");
|
||||
return 0;
|
||||
}
|
||||
if(type_of_flags&0x4){
|
||||
switch(type_of_flags&0x3){
|
||||
case 0: return (s8)(val&0xff);
|
||||
case 1: return (s16)(val&0xffff);
|
||||
default: return (int)val;
|
||||
}
|
||||
}else{
|
||||
switch(type_of_flags&0x3){
|
||||
case 0: return (u8)(val&0xff);
|
||||
case 1: return (u16)(val&0xffff);
|
||||
default: return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for execution
|
||||
bool isCorrectBreak(struct ConditionalBreak* toTest, u8 accessType){
|
||||
|
||||
return (toTest->type_flags & accessType);
|
||||
}
|
||||
|
||||
|
||||
bool doBreak(struct ConditionalBreak* toTest){
|
||||
struct ConditionalBreakNode* toExamine = toTest->firstCond;
|
||||
|
||||
bool globalVeredict = true;
|
||||
bool veredict = false;
|
||||
while(toExamine && globalVeredict){
|
||||
u32 address = calculateFinalValue(toExamine->address, toExamine->exp_type_flags&0xf);
|
||||
u32 value = calculateFinalValue(toExamine->value, toExamine->exp_type_flags>>4);
|
||||
if((toExamine->cond_flags &0x7) != 0){
|
||||
veredict = veredict || ((toExamine->cond_flags&1)? (address == value):false);
|
||||
veredict = veredict || ((toExamine->cond_flags&4)? ((toExamine->cond_flags&8)? ((int)address < (int)value) : (address < value)) : false);
|
||||
veredict = veredict || ((toExamine->cond_flags&2)? ((toExamine->cond_flags&8)? ((int)address > (int)value) : (address > value)) : false);
|
||||
}
|
||||
toExamine = toExamine->next;
|
||||
globalVeredict = veredict && globalVeredict;
|
||||
|
||||
}
|
||||
return globalVeredict;
|
||||
}
|
||||
|
||||
bool doesBreak(u32 address, u8 allowedFlags){
|
||||
u8 addrNo = address>>24;
|
||||
if(conditionals[addrNo]){
|
||||
struct ConditionalBreak* base = conditionals[addrNo];
|
||||
while(base && base->break_address < address){
|
||||
base = base->next;
|
||||
}
|
||||
while(base && base->break_address == address){
|
||||
if(base->type_flags & allowedFlags &0xf0){
|
||||
return true;
|
||||
}
|
||||
if(isCorrectBreak(base,allowedFlags) && doBreak(base)){
|
||||
return true;
|
||||
}
|
||||
base = base->next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
//Test main
|
||||
int main (int argc, char** args){
|
||||
char* argv[] = {"r7","s==","0", "||","'byte","0x25","ge","'hword","0x0001"};
|
||||
parseAndCreateConditionalBreaks(0x0203fd00, 0x1f, argv, 9);
|
||||
parseAndCreateConditionalBreaks(0x0203fd00, 0x10, argv, 9);
|
||||
parseAndCreateConditionalBreaks(0x0203fd00, 0x40, argv, 9);
|
||||
parseAndCreateConditionalBreaks(0x0203fd04, 0x04, argv, 9);
|
||||
printAllFlagConditionals(0xff, true);
|
||||
removeFlagFromConditionalBreakNo(0x0203fd00, 0x3,0xff);
|
||||
printf("after\n");
|
||||
printAllFlagConditionals(0xff, true);
|
||||
|
||||
getchar();
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef VBA_BKS_H
|
||||
#define VBA_BKS_H
|
||||
|
||||
#include "../common/Types.h"
|
||||
|
||||
#define readWord(addr) \
|
||||
((map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])+\
|
||||
((map[(addr+1)>>24].address[(addr+1) & map[(addr+1)>>24].mask])<<8)+\
|
||||
((map[(addr+2)>>24].address[(addr+2) & map[(addr+2)>>24].mask])<<16)+\
|
||||
((map[(addr+3)>>24].address[(addr+3) & map[(addr+3)>>24].mask])<<24))
|
||||
|
||||
#define readHalfWord(addr) \
|
||||
((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])+\
|
||||
((&map[(addr+1)>>24].address[(addr+1) & map[(addr+1)>>24].mask])<<8))
|
||||
|
||||
#define readByte(addr) \
|
||||
map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
|
||||
|
||||
|
||||
struct ConditionalBreakNode{
|
||||
char* address;
|
||||
char* value;
|
||||
u8 cond_flags;
|
||||
u8 exp_type_flags;
|
||||
struct ConditionalBreakNode* next;
|
||||
};
|
||||
|
||||
struct ConditionalBreak{
|
||||
u32 break_address;
|
||||
u8 type_flags;
|
||||
struct ConditionalBreakNode* firstCond;
|
||||
struct ConditionalBreak* next;
|
||||
};
|
||||
|
||||
extern struct ConditionalBreak* conditionals[16];
|
||||
|
||||
//conditional break manipulators
|
||||
//case '*': flag = 0xf; break;
|
||||
//case 't': flag = 0x8; break; // thumb
|
||||
//case 'a': flag = 0x4; break; // arm
|
||||
//case 'x': flag = 0xC; break;
|
||||
//case 'r': flag = 0x2; break; // mem read
|
||||
//case 'w': flag = 0x1; break; // mem write
|
||||
//case 'i': flag = 0x3; break;
|
||||
struct ConditionalBreak* addConditionalBreak(u32 address, u8 flag);
|
||||
|
||||
int removeConditionalBreakNo(u32 address, u8 number);
|
||||
int removeFlagFromConditionalBreakNo(u32 address, u8 number, u8 flag);
|
||||
int removeConditionalWithAddress(u32 address);
|
||||
int removeConditionalWithFlag(u8 flag, bool orMode);
|
||||
int removeConditionalWithAddressAndFlag(u32 address, u8 flag, bool orMode);
|
||||
//void freeConditionalBreak(struct ConditionalBreak* toFree);
|
||||
|
||||
void addCondition(struct ConditionalBreak* base, struct ConditionalBreakNode* toAdd);
|
||||
//bool removeCondition(struct ConditionalBreak* base, struct ConditionalBreakNode* toDel);
|
||||
//bool removeCondition(u32 address, u8 flags, u8 num);
|
||||
|
||||
void freeConditionalNode(struct ConditionalBreakNode* toDel);
|
||||
|
||||
|
||||
void parseAndCreateConditionalBreaks(u32 address, u8 flags, char** exp, int n);
|
||||
|
||||
bool isCorrectBreak(struct ConditionalBreak* toTest, u8 accessType);
|
||||
bool doesBreak(u32 address, u8 allowedFlags);
|
||||
bool doBreak(struct ConditionalBreak* toTest);
|
||||
|
||||
//printing the structure(AKA list Breaks)
|
||||
//void printConditionalBreak(struct ConditionalBreak* toPrint, bool printAddress);
|
||||
//void printAllConditionals();
|
||||
//u8 printConditionalsFromAddress(u32 address);
|
||||
//void printAllFlagConditionals(u8 flag, bool orMode);
|
||||
//void printAllFlagConditionalsWithAddress(u32 address, u8 flag, bool orMode);
|
||||
#endif
|
|
@ -2846,7 +2846,6 @@ static u8 cheatsGetType(u32 address)
|
|||
void cheatsWriteMemory(u32 address, u32 value)
|
||||
{
|
||||
#ifdef BKPT_SUPPORT
|
||||
#ifdef SDL
|
||||
if(cheatsNumber == 0) {
|
||||
int type = cheatsGetType(address);
|
||||
u32 oldValue = debuggerReadMemory(address);
|
||||
|
@ -2857,13 +2856,11 @@ void cheatsWriteMemory(u32 address, u32 value)
|
|||
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);
|
||||
|
@ -2874,17 +2871,11 @@ void cheatsWriteHalfWord(u32 address, u16 value)
|
|||
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);
|
||||
|
@ -2895,6 +2886,5 @@ void cheatsWriteByte(u32, u8)
|
|||
debuggerWriteByte(address, value);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "../Util.h"
|
||||
#include "../System.h"
|
||||
#include "agbprint.h"
|
||||
#include "remote.h"
|
||||
|
||||
#ifdef PROFILING
|
||||
#include "prof/prof.h"
|
||||
#endif
|
||||
|
@ -2890,8 +2892,20 @@ int armExecute()
|
|||
#endif
|
||||
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 4;
|
||||
ARM_PREFETCH_NEXT;
|
||||
reg[15].I += 4;
|
||||
ARM_PREFETCH_NEXT;
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
u32 memAddr = armNextPC;
|
||||
memoryMap *m = &map[memAddr >> 24];
|
||||
if (m->breakPoints && BreakARMCheck(m->breakPoints, memAddr & m->mask)) {
|
||||
if (debuggerBreakOnExecution(memAddr, armState)){
|
||||
// Revert tickcount?
|
||||
debugger = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int cond = opcode >> 28;
|
||||
bool cond_res = true;
|
||||
|
@ -2955,13 +2969,50 @@ int armExecute()
|
|||
#ifdef INSN_COUNTER
|
||||
count(opcode, cond_res);
|
||||
#endif
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
if (enableRegBreak){
|
||||
if (lowRegBreakCounter[0])
|
||||
breakReg_check(0);
|
||||
if (lowRegBreakCounter[1])
|
||||
breakReg_check(1);
|
||||
if (lowRegBreakCounter[2])
|
||||
breakReg_check(2);
|
||||
if (lowRegBreakCounter[3])
|
||||
breakReg_check(3);
|
||||
if (medRegBreakCounter[0])
|
||||
breakReg_check(4);
|
||||
if (medRegBreakCounter[1])
|
||||
breakReg_check(5);
|
||||
if (medRegBreakCounter[2])
|
||||
breakReg_check(6);
|
||||
if (medRegBreakCounter[3])
|
||||
breakReg_check(7);
|
||||
if (highRegBreakCounter[0])
|
||||
breakReg_check(8);
|
||||
if (highRegBreakCounter[1])
|
||||
breakReg_check(9);
|
||||
if (highRegBreakCounter[2])
|
||||
breakReg_check(10);
|
||||
if (highRegBreakCounter[3])
|
||||
breakReg_check(11);
|
||||
if (statusRegBreakCounter[0])
|
||||
breakReg_check(12);
|
||||
if (statusRegBreakCounter[1])
|
||||
breakReg_check(13);
|
||||
if (statusRegBreakCounter[2])
|
||||
breakReg_check(14);
|
||||
if (statusRegBreakCounter[3])
|
||||
breakReg_check(15);
|
||||
}
|
||||
#endif
|
||||
if (clockTicks < 0)
|
||||
return 0;
|
||||
if (clockTicks == 0)
|
||||
clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC);
|
||||
cpuTotalTicks += clockTicks;
|
||||
|
||||
} while (cpuTotalTicks<cpuNextEvent && armState && !holdState && !SWITicks);
|
||||
} while (cpuTotalTicks<cpuNextEvent && armState && !holdState && !SWITicks && !debugger);
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
#include "../Util.h"
|
||||
#include "../System.h"
|
||||
#include "agbprint.h"
|
||||
#include "remote.h"
|
||||
|
||||
#ifdef PROFILING
|
||||
#include "prof/prof.h"
|
||||
#endif
|
||||
|
@ -2317,14 +2319,64 @@ int thumbExecute()
|
|||
reg[15].I += 2;
|
||||
THUMB_PREFETCH_NEXT;
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
u32 memAddr = armNextPC;
|
||||
memoryMap *m = &map[memAddr >> 24];
|
||||
if (m->breakPoints && BreakThumbCheck(m->breakPoints, memAddr & m->mask)) {
|
||||
if (debuggerBreakOnExecution(memAddr, armState)){
|
||||
// Revert tickcount?
|
||||
debugger = true;
|
||||
return 0 ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
(*thumbInsnTable[opcode>>6])(opcode);
|
||||
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
if (enableRegBreak){
|
||||
if (lowRegBreakCounter[0])
|
||||
breakReg_check(0);
|
||||
if (lowRegBreakCounter[1])
|
||||
breakReg_check(1);
|
||||
if (lowRegBreakCounter[2])
|
||||
breakReg_check(2);
|
||||
if (lowRegBreakCounter[3])
|
||||
breakReg_check(3);
|
||||
if (medRegBreakCounter[0])
|
||||
breakReg_check(4);
|
||||
if (medRegBreakCounter[1])
|
||||
breakReg_check(5);
|
||||
if (medRegBreakCounter[2])
|
||||
breakReg_check(6);
|
||||
if (medRegBreakCounter[3])
|
||||
breakReg_check(7);
|
||||
if (highRegBreakCounter[0])
|
||||
breakReg_check(8);
|
||||
if (highRegBreakCounter[1])
|
||||
breakReg_check(9);
|
||||
if (highRegBreakCounter[2])
|
||||
breakReg_check(10);
|
||||
if (highRegBreakCounter[3])
|
||||
breakReg_check(11);
|
||||
if (statusRegBreakCounter[0])
|
||||
breakReg_check(12);
|
||||
if (statusRegBreakCounter[1])
|
||||
breakReg_check(13);
|
||||
if (statusRegBreakCounter[2])
|
||||
breakReg_check(14);
|
||||
if (statusRegBreakCounter[3])
|
||||
breakReg_check(15);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (clockTicks < 0)
|
||||
return 0;
|
||||
if (clockTicks==0)
|
||||
clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1;
|
||||
cpuTotalTicks += clockTicks;
|
||||
|
||||
} while (cpuTotalTicks < cpuNextEvent && !armState && !holdState && !SWITicks);
|
||||
} while (cpuTotalTicks < cpuNextEvent && !armState && !holdState && !SWITicks && !debugger);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#endif
|
||||
|
||||
extern int emulating;
|
||||
bool debugger;
|
||||
|
||||
int SWITicks = 0;
|
||||
int IRQTicks = 0;
|
||||
|
@ -1600,6 +1601,40 @@ int CPULoadRom(const char *szFile)
|
|||
|
||||
CPUUpdateRenderBuffers(true);
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
map[0].size = 0x4000;
|
||||
map[1].size = 0x0;
|
||||
map[2].size = 0x40000;
|
||||
map[3].size = 0x8000;
|
||||
map[4].size = 0x400;
|
||||
map[5].size = 0x400;
|
||||
map[6].size = 0x18000;
|
||||
map[7].size = 0x400;
|
||||
map[8].size = 0x01000000;
|
||||
map[9].size = 0x01000000;
|
||||
map[14].size = 0x10000;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (map[i].size > 0) {
|
||||
map[i].trace = (u8 *)calloc(map[i].size >> 3, sizeof(u8));
|
||||
|
||||
map[i].breakPoints = (u8 *)calloc(map[i].size >> 1, sizeof(u8)); //\\
|
||||
|
||||
if (map[i].trace == NULL || map[i].breakPoints == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
"TRACE");
|
||||
}
|
||||
}
|
||||
else {
|
||||
map[i].trace = NULL;
|
||||
map[i].breakPoints = NULL; //\\
|
||||
|
||||
}
|
||||
}
|
||||
clearBreakRegList();
|
||||
|
||||
#endif
|
||||
|
||||
return romSize;
|
||||
}
|
||||
|
||||
|
@ -3644,6 +3679,7 @@ void CPULoop(int ticks)
|
|||
{
|
||||
int clockTicks;
|
||||
int timerOverflow = 0;
|
||||
u32 memAddr = 0;
|
||||
// variable used by the CPU core
|
||||
cpuTotalTicks = 0;
|
||||
|
||||
|
@ -3690,10 +3726,14 @@ void CPULoop(int ticks)
|
|||
armOpcodeCount++;
|
||||
if (!armExecute())
|
||||
return;
|
||||
if (debugger)
|
||||
return;
|
||||
} else {
|
||||
thumbOpcodeCount++;
|
||||
if (!thumbExecute())
|
||||
return;
|
||||
if (debugger)
|
||||
return;
|
||||
}
|
||||
clockTicks = 0;
|
||||
} else
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
typedef struct {
|
||||
u8 *address;
|
||||
u32 mask;
|
||||
#ifdef BKPT_SUPPORT
|
||||
u8 *breakPoints;
|
||||
u8 *searchMatch;
|
||||
u8* trace;
|
||||
u32 size;
|
||||
#endif
|
||||
} memoryMap;
|
||||
|
||||
typedef union {
|
||||
|
@ -54,16 +60,8 @@ typedef union {
|
|||
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);
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
|
@ -75,6 +73,7 @@ extern u8 freezePRAM[0x400];
|
|||
extern bool debugger_last;
|
||||
extern int oldreg[18];
|
||||
extern char oldbuffer[10];
|
||||
extern bool debugger;
|
||||
#endif
|
||||
|
||||
extern bool CPUReadGSASnapshot(const char *);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "agbprint.h"
|
||||
#include "GBAcpu.h"
|
||||
#include "GBALink.h"
|
||||
#include "remote.h"
|
||||
|
||||
extern const u32 objTilesAddress[3];
|
||||
|
||||
|
@ -44,8 +45,18 @@ extern int cpuTotalTicks;
|
|||
#define CPUReadMemoryQuick(addr) \
|
||||
READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
||||
|
||||
extern u32 myROM[];
|
||||
|
||||
static inline u32 CPUReadMemory(u32 address)
|
||||
{
|
||||
#ifdef BKPT_SUPPORT
|
||||
memoryMap *m = &map[address >> 24];
|
||||
if (m->breakPoints && BreakReadCheck(m->breakPoints, address & m->mask)) {
|
||||
if (debuggerBreakOnRead(address, 2)){
|
||||
//CPU_BREAK_LOOP_2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
u32 value;
|
||||
u32 oldAddress = address;
|
||||
|
||||
|
@ -184,10 +195,17 @@ unreadable:
|
|||
return value;
|
||||
}
|
||||
|
||||
extern u32 myROM[];
|
||||
|
||||
static inline u32 CPUReadHalfWord(u32 address)
|
||||
{
|
||||
#ifdef BKPT_SUPPORT
|
||||
memoryMap *m = &map[address >> 24];
|
||||
if (m->breakPoints && BreakReadCheck(m->breakPoints, address & m->mask)) {
|
||||
if (debuggerBreakOnRead(address, 1)){
|
||||
//CPU_BREAK_LOOP_2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
u32 value;
|
||||
u32 oldAddress = address;
|
||||
|
||||
|
@ -334,6 +352,15 @@ static inline s16 CPUReadHalfWordSigned(u32 address)
|
|||
|
||||
static inline u8 CPUReadByte(u32 address)
|
||||
{
|
||||
#ifdef BKPT_SUPPORT
|
||||
memoryMap *m = &map[address >> 24];
|
||||
if (m->breakPoints && BreakReadCheck(m->breakPoints, address & m->mask)) {
|
||||
if (debuggerBreakOnRead(address, 0)){
|
||||
//CPU_BREAK_LOOP_2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(address >> 24) {
|
||||
case 0:
|
||||
if (reg[15].I >> 24) {
|
||||
|
@ -428,6 +455,15 @@ static inline void CPUWriteMemory(u32 address, u32 value)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
memoryMap *m = &map[address >> 24];
|
||||
if (m->breakPoints && BreakWriteCheck(m->breakPoints, address & m->mask)) {
|
||||
if (debuggerBreakOnWrite(address, value, 1)){
|
||||
//CPU_BREAK_LOOP_2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
address &= 0xFFFFFFFC;
|
||||
|
||||
switch(address >> 24) {
|
||||
|
@ -528,6 +564,15 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
memoryMap *m = &map[address >> 24];
|
||||
if (m->breakPoints && BreakWriteCheck(m->breakPoints, address & m->mask)) {
|
||||
if (debuggerBreakOnWrite(address, value, 1)){
|
||||
//CPU_BREAK_LOOP_2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
address &= 0xFFFFFFFE;
|
||||
|
||||
switch(address >> 24) {
|
||||
|
@ -622,6 +667,15 @@ unwritable:
|
|||
|
||||
static inline void CPUWriteByte(u32 address, u8 b)
|
||||
{
|
||||
#ifdef BKPT_SUPPORT
|
||||
memoryMap *m = &map[address >> 24];
|
||||
if (m->breakPoints && BreakWriteCheck(m->breakPoints, address & m->mask)) {
|
||||
if (debuggerBreakOnWrite(address, b, 1)){
|
||||
//CPU_BREAK_LOOP_2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(address >> 24) {
|
||||
case 2:
|
||||
#ifdef BKPT_SUPPORT
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "debugger-expr-lex.cpp"
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,105 @@
|
|||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
TOK_PLUS = 258,
|
||||
TOK_MINUS = 259,
|
||||
TOK_DIVIDE = 260,
|
||||
TOK_MULTIPLY = 261,
|
||||
TOK_LSHIFT = 262,
|
||||
TOK_RSHIFT = 263,
|
||||
TOK_LPAREN = 264,
|
||||
TOK_RPAREN = 265,
|
||||
TOK_OR = 266,
|
||||
TOK_AND = 267,
|
||||
TOK_XOR = 268,
|
||||
TOK_NEGATE = 269,
|
||||
TOK_BBRACKET = 270,
|
||||
TOK_HBRACKET = 271,
|
||||
TOK_WBRACKET = 272,
|
||||
TOK_LBRACKET = 273,
|
||||
TOK_RBRACKET = 274,
|
||||
TOK_REGISTER = 275,
|
||||
TOK_NUMBER = 276,
|
||||
TOK_ID = 277
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define TOK_PLUS 258
|
||||
#define TOK_MINUS 259
|
||||
#define TOK_DIVIDE 260
|
||||
#define TOK_MULTIPLY 261
|
||||
#define TOK_LSHIFT 262
|
||||
#define TOK_RSHIFT 263
|
||||
#define TOK_LPAREN 264
|
||||
#define TOK_RPAREN 265
|
||||
#define TOK_OR 266
|
||||
#define TOK_AND 267
|
||||
#define TOK_XOR 268
|
||||
#define TOK_NEGATE 269
|
||||
#define TOK_BBRACKET 270
|
||||
#define TOK_HBRACKET 271
|
||||
#define TOK_WBRACKET 272
|
||||
#define TOK_LBRACKET 273
|
||||
#define TOK_RBRACKET 274
|
||||
#define TOK_REGISTER 275
|
||||
#define TOK_NUMBER 276
|
||||
#define TOK_ID 277
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 44 "src/sdl/debugger-expr.y"
|
||||
{
|
||||
unsigned int number;
|
||||
char *string;
|
||||
}
|
||||
/* Line 1489 of yacc.c. */
|
||||
#line 98 "src/sdl/debugger-expr-yacc.hpp"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "debugger-expr-yacc.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define YY_NO_UNISTD_H
|
||||
#include <io.h>
|
||||
#define isatty _isatty
|
||||
#endif
|
||||
|
||||
extern YYSTYPE dexp_lval;
|
||||
|
||||
char *dexprString;
|
||||
int dexprCol;
|
||||
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
{ \
|
||||
int c = *dexprString++; \
|
||||
dexprCol++;\
|
||||
result = (c == 0) ? YY_NULL : (buf[0] = c, 1); \
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%option nomain
|
||||
%option noyywrap
|
||||
|
||||
HEX [0-9a-fA-F]
|
||||
|
||||
%%
|
||||
r(0?[0-9]|1[0-5]) dexp_lval.number=atoi((char *)(dexp_text+1)); return TOK_REGISTER;
|
||||
[sS][pP] dexp_lval.number = 13; return TOK_REGISTER;
|
||||
[lL][rR] dexp_lval.number = 14; return TOK_REGISTER;
|
||||
[pP][cC] dexp_lval.number = 15; return TOK_REGISTER;
|
||||
[bB]"[" return TOK_BBRACKET;
|
||||
[hH]"[" return TOK_HBRACKET;
|
||||
[wW]"[" return TOK_WBRACKET;
|
||||
"]" return TOK_RBRACKET;
|
||||
"[" return TOK_LBRACKET;
|
||||
[1-9][0-9]* dexp_lval.number=atoi(dexp_text); return TOK_NUMBER;
|
||||
0{HEX}* sscanf(dexp_text, "%x", &dexp_lval.number); return TOK_NUMBER;
|
||||
0[xX]{HEX}+ sscanf((char *)(dexp_text + 2), "%x", &dexp_lval.number); return TOK_NUMBER;
|
||||
"$"{HEX}+ sscanf((char *)(dexp_text + 1), "%x", &dexp_lval.number); return TOK_NUMBER;
|
||||
"+" return TOK_PLUS;
|
||||
"-" return TOK_MINUS;
|
||||
"/" return TOK_DIVIDE;
|
||||
"*" return TOK_MULTIPLY;
|
||||
"<<" return TOK_LSHIFT;
|
||||
">>" return TOK_RSHIFT;
|
||||
"(" return TOK_LPAREN;
|
||||
")" return TOK_RPAREN;
|
||||
"|" return TOK_OR;
|
||||
"&" return TOK_AND;
|
||||
"^" return TOK_XOR;
|
||||
"!" return TOK_NEGATE;
|
||||
"~" return TOK_NEGATE;
|
||||
" " ;
|
||||
. printf("Unrecognised token: %s\n", dexp_text);
|
||||
[A-Za-z_][A-Za-z0-9_]* dexp_lval.string=dexp_text; return TOK_ID;
|
||||
|
||||
%%
|
||||
|
||||
void dexp_flush()
|
||||
{
|
||||
dexp__flush_buffer(YY_CURRENT_BUFFER);
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
%{
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../System.h"
|
||||
#include "GBA.h"
|
||||
#include "../Port.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
unsigned int dexp_result = 0;
|
||||
extern int dexp_error(char *);
|
||||
extern int dexp_lex();
|
||||
extern char *dexp_text;
|
||||
|
||||
std::map<std::string, u32> dexp_vars;
|
||||
|
||||
#define readWord(addr) \
|
||||
READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
||||
|
||||
#define readHalfWord(addr) \
|
||||
READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
||||
|
||||
#define readByte(addr) \
|
||||
map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%token TOK_PLUS TOK_MINUS
|
||||
%token TOK_DIVIDE TOK_MULTIPLY TOK_LSHIFT TOK_RSHIFT
|
||||
%token TOK_LPAREN TOK_RPAREN TOK_OR TOK_AND TOK_XOR TOK_NEGATE
|
||||
%token TOK_BBRACKET TOK_HBRACKET TOK_WBRACKET
|
||||
%token TOK_LBRACKET TOK_RBRACKET
|
||||
%left TOK_MINUS TOK_PLUS TOK_NEGATE
|
||||
%left TOK_MULTIPLY TOK_DIVIDE
|
||||
%left TOK_LSHIFT TOK_RSHIFT
|
||||
%left TOK_OR
|
||||
%left TOK_AND
|
||||
%left TOK_XOR
|
||||
|
||||
%union
|
||||
{
|
||||
unsigned int number;
|
||||
char *string;
|
||||
}
|
||||
|
||||
%token <number> TOK_REGISTER
|
||||
%token <number> TOK_NUMBER
|
||||
%token <string> TOK_ID
|
||||
%type <number> final
|
||||
%type <number> exp
|
||||
%%
|
||||
|
||||
final: exp {dexp_result = $1;}
|
||||
;
|
||||
|
||||
exp: TOK_NUMBER { $$ = $1; }
|
||||
| TOK_ID {
|
||||
std::string v($1);
|
||||
if (dexp_vars.count(v) == 0) {
|
||||
printf("Variable %s not defined.\n", $1);
|
||||
YYABORT;
|
||||
}
|
||||
$$ = dexp_vars[v];
|
||||
}
|
||||
| exp TOK_PLUS exp { $$ = $1 + $3; }
|
||||
| exp TOK_MINUS exp { $$ = $1 - $3;}
|
||||
| TOK_MINUS exp { $$ = -$2;}
|
||||
| TOK_NEGATE exp { $$ = ~$2;}
|
||||
| exp TOK_DIVIDE exp { $$ = $1 / $3;}
|
||||
| exp TOK_MULTIPLY exp { $$ = $1 * $3;}
|
||||
| exp TOK_LSHIFT exp { $$ = $1 << $3;}
|
||||
| exp TOK_RSHIFT exp { $$ = $1 >> $3;}
|
||||
| TOK_LPAREN exp TOK_RPAREN { $$=$2;}
|
||||
| exp TOK_AND exp { $$ = $1 & $3;}
|
||||
| exp TOK_OR exp { $$ = $1 | $3;}
|
||||
| exp TOK_XOR exp { $$ = $1 ^ $3; }
|
||||
| TOK_REGISTER { $$ = reg[$1].I; }
|
||||
| TOK_BBRACKET exp TOK_RBRACKET { $$ = readByte($2); }
|
||||
| TOK_HBRACKET exp TOK_RBRACKET { $$ = readHalfWord($2); }
|
||||
| TOK_WBRACKET exp TOK_RBRACKET { $$ = readWord($2); }
|
||||
| TOK_LBRACKET exp TOK_RBRACKET { $$ = readWord($2); }
|
||||
;
|
||||
%%
|
||||
|
||||
bool dexp_eval(char *expr, u32 *result)
|
||||
{
|
||||
extern void dexp_flush();
|
||||
extern char *dexprString;
|
||||
extern int dexprCol;
|
||||
|
||||
dexp_flush();
|
||||
|
||||
|
||||
dexprString = expr;
|
||||
dexprCol = 0;
|
||||
|
||||
if(!dexp_parse()) {
|
||||
*result = dexp_result;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int dexp_error(char *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dexp_setVar(char *name, u32 value)
|
||||
{
|
||||
std::string a(name);
|
||||
dexp_vars[a] = value;
|
||||
}
|
||||
|
||||
void dexp_listVars()
|
||||
{
|
||||
std::map<std::string, u32>::iterator iter;
|
||||
|
||||
for (iter = dexp_vars.begin(); iter != dexp_vars.end(); iter++) {
|
||||
printf("%s = %08X\n", iter->first.c_str(), iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
void dexp_saveVars(char *file)
|
||||
{
|
||||
std::map<std::string, u32>::iterator iter;
|
||||
|
||||
FILE *f = fopen(file, "w");
|
||||
if (!f) {
|
||||
printf("Could not open file %s\n", file);
|
||||
return;
|
||||
}
|
||||
|
||||
for (iter = dexp_vars.begin(); iter != dexp_vars.end(); iter++) {
|
||||
fprintf(f, "%s = %08X\n", iter->first.c_str(), iter->second);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void dexp_loadVars(char *file)
|
||||
{
|
||||
std::map<std::string, u32>::iterator iter;
|
||||
char buffer[500];
|
||||
char name[500];
|
||||
u32 val;
|
||||
|
||||
FILE *f = fopen(file, "r");
|
||||
if (!f) {
|
||||
printf("Could not open file %s\n", file);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, 500, f) != NULL) {
|
||||
if (sscanf(buffer, "%s = %x",name,&val) == 2) {
|
||||
dexp_setVar(name, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
3000
src/gba/remote.cpp
3000
src/gba/remote.cpp
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,79 @@
|
|||
#ifndef REMOTE_H
|
||||
#define REMOTE_H
|
||||
|
||||
#include "../common/Types.h"
|
||||
#include "GBA.h"
|
||||
|
||||
#define BitSet(array, bit) \
|
||||
((u8 *)(array))[(bit) >> 3] |= (1 << ((bit) & 7))
|
||||
|
||||
#define BitClear(array, bit) \
|
||||
((u8 *)(array))[(bit) >> 3] &= ~(1 << ((bit) & 7))
|
||||
|
||||
#define BitGet(array, bit) \
|
||||
((u8)((array)[(bit) >> 3]) & (u8)(1 <<((bit) & 7)))
|
||||
|
||||
#define BreakSet(array, addr, flag) \
|
||||
((u8 *)(array))[(addr)>>1] |= ((addr&1) ? (flag<<4) : (flag&0xf))
|
||||
|
||||
#define BreakClear(array, addr, flag) \
|
||||
((u8 *)(array))[(addr)>>1] &= ~((addr&1) ? (flag<<4) : (flag&0xf))
|
||||
|
||||
//check
|
||||
#define BreakThumbCheck(array, addr) \
|
||||
((u8 *)(array))[(addr)>>1] &((addr&1) ? 0x80 : 0x8 )
|
||||
|
||||
#define BreakARMCheck(array, addr) \
|
||||
((u8 *)(array))[(addr)>>1] & ((addr&1) ? 0x40 : 0x4 )
|
||||
|
||||
#define BreakReadCheck(array, addr) \
|
||||
((u8 *)(array))[(addr)>>1] & ((addr&1) ? 0x20 : 0x2 )
|
||||
|
||||
#define BreakWriteCheck(array, addr) \
|
||||
((u8 *)(array))[(addr)>>1] & ((addr&1) ? 0x10 : 0x1 )
|
||||
|
||||
#define BreakCheck(array, addr, flag) \
|
||||
((u8 *)(array))[(addr)>>1] & ((addr&1) ? (flag<<4) : (flag&0xf))
|
||||
|
||||
extern bool debugger;
|
||||
|
||||
extern bool dexp_eval(char *, u32*);
|
||||
extern void dexp_setVar(char *, u32);
|
||||
extern void dexp_listVars();
|
||||
extern void dexp_saveVars(char *);
|
||||
extern void dexp_loadVars(char *);
|
||||
|
||||
bool debuggerBreakOnExecution(u32 address, u8 state);
|
||||
bool debuggerBreakOnWrite(u32 address, u32 value, int size);
|
||||
void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value, int size, int t);
|
||||
bool debuggerBreakOnRead(u32 address, int size);
|
||||
|
||||
struct regBreak{
|
||||
//u8 regNum; /No longer needed
|
||||
// bit 0 = equal
|
||||
// bit 1 = greater
|
||||
// bit 2 = smaller
|
||||
// bit 3 = signed
|
||||
u8 flags;
|
||||
u32 intVal;
|
||||
struct regBreak* next;
|
||||
};
|
||||
extern u8 lowRegBreakCounter[4]; //(r0-r3)
|
||||
extern u8 medRegBreakCounter[4]; //(r4-r7)
|
||||
extern u8 highRegBreakCounter[4]; //(r8-r11)
|
||||
extern u8 statusRegBreakCounter[4]; //(r12-r15)
|
||||
|
||||
extern bool enableRegBreak;
|
||||
extern regBreak* breakRegList[16];
|
||||
extern void breakReg_check(int i);
|
||||
|
||||
struct regBreak* getFromBreakRegList(u8 regnum, int location);
|
||||
|
||||
void clearBreakRegList();
|
||||
void clearParticularRegListBreaks(int reg);
|
||||
void deleteFromBreakRegList(u8 regnum, int location);
|
||||
|
||||
void addBreakRegToList(u8 regnum, u8 flags, u32 value);
|
||||
void printBreakRegList(bool verbose);
|
||||
|
||||
#endif // REMOTE_H
|
|
@ -181,10 +181,6 @@ void debuggerOutput(const char *, u32)
|
|||
{
|
||||
}
|
||||
|
||||
void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value, int size, int t)
|
||||
{
|
||||
}
|
||||
|
||||
void (*dbgMain)() = debuggerMain;
|
||||
void (*dbgSignal)(int, int) = debuggerSignal;
|
||||
void (*dbgOutput)(const char *, u32) = debuggerOutput;
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "../gb/gbSound.h"
|
||||
#include "../Util.h"
|
||||
|
||||
#include "debugger.h"
|
||||
#include "filters.h"
|
||||
#include "text.h"
|
||||
#include "inputSDL.h"
|
||||
|
@ -211,7 +210,6 @@ int showSpeedTransparent = 1;
|
|||
bool disableStatusMessages = false;
|
||||
bool paused = false;
|
||||
bool pauseNextFrame = false;
|
||||
bool debugger = false;
|
||||
bool debuggerStub = false;
|
||||
int fullscreen = 0;
|
||||
int sdlFlashSize = 0;
|
||||
|
@ -225,9 +223,9 @@ static int ignore_first_resize_event = 0;
|
|||
/* forward */
|
||||
void systemConsoleMessage(const char*);
|
||||
|
||||
void (*dbgMain)() = debuggerMain;
|
||||
void (*dbgSignal)(int,int) = debuggerSignal;
|
||||
void (*dbgOutput)(const char *, u32) = debuggerOutput;
|
||||
void (*dbgMain)();
|
||||
void (*dbgSignal)(int,int);
|
||||
void (*dbgOutput)(const char *, u32);
|
||||
|
||||
int mouseCounter = 0;
|
||||
|
||||
|
@ -1555,7 +1553,7 @@ void sdlPollEvents()
|
|||
}
|
||||
break;
|
||||
case SDLK_F11:
|
||||
if(dbgMain != debuggerMain) {
|
||||
if(dbgMain == remoteStubMain) {
|
||||
if(armState) {
|
||||
armNextPC -= 4;
|
||||
reg[15].I -= 4;
|
||||
|
|
|
@ -1058,25 +1058,6 @@ static void debuggerBreakArm(int n, char **args)
|
|||
debuggerUsage("ba");
|
||||
}
|
||||
|
||||
/*extern*/ void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value,
|
||||
int size, int t)
|
||||
{
|
||||
const char *type = "write";
|
||||
if(t == 2)
|
||||
type = "change";
|
||||
|
||||
if(size == 2)
|
||||
printf("Breakpoint (on %s) address %08x old:%08x new:%08x\n",
|
||||
type, address, oldvalue, value);
|
||||
else if(size == 1)
|
||||
printf("Breakpoint (on %s) address %08x old:%04x new:%04x\n",
|
||||
type, address, (u16)oldvalue,(u16)value);
|
||||
else
|
||||
printf("Breakpoint (on %s) address %08x old:%02x new:%02x\n",
|
||||
type, address, (u8)oldvalue, (u8)value);
|
||||
debugger = true;
|
||||
}
|
||||
|
||||
static void debuggerBreakWriteClear(int n, char **args)
|
||||
{
|
||||
if(n == 3) {
|
||||
|
|
|
@ -176,7 +176,8 @@ struct {
|
|||
{ "CheatsSave", ID_CHEATS_SAVECHEATLIST },
|
||||
{ "CheatsDisable", ID_CHEATS_DISABLECHEATS },
|
||||
{ "ToolsDebugGDB", ID_TOOLS_DEBUG_GDB },
|
||||
{ "ToolsDebugGDBLoad", ID_TOOLS_DEBUG_LOADANDWAIT },
|
||||
{ "ToolsDebugGDBConfigurePort", ID_TOOLS_DEBUG_CONFIGUREPORT },
|
||||
{ "ToolsDebugGDBBreakOnLoad", ID_TOOLS_DEBUG_BREAKONLOAD },
|
||||
{ "ToolsDebugGDBBreak", ID_TOOLS_DEBUG_BREAK },
|
||||
{ "ToolsDebugGDBDisconnect", ID_TOOLS_DEBUG_DISCONNECT },
|
||||
{ "ToolsDisassemble", ID_TOOLS_DISASSEMBLE },
|
||||
|
|
|
@ -24,7 +24,10 @@ GDBPortDlg::GDBPortDlg(CWnd* pParent /*=NULL*/)
|
|||
//{{AFX_DATA_INIT(GDBPortDlg)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
port = 55555;
|
||||
if (theApp.gdbPort == 0)
|
||||
port = 55555;
|
||||
else
|
||||
port = theApp.gdbPort;
|
||||
sock = INVALID_SOCKET;
|
||||
|
||||
if(!initialized) {
|
||||
|
@ -97,30 +100,8 @@ void GDBPortDlg::OnOk()
|
|||
address.sin_port = htons(atoi(buffer));
|
||||
port = ntohs(address.sin_port);
|
||||
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if(s != INVALID_SOCKET) {
|
||||
int error = bind(s, (sockaddr *)&address, sizeof(address));
|
||||
|
||||
if(error) {
|
||||
systemMessage(IDS_ERROR_BINDING, "Error binding socket. Port probably in use.");
|
||||
error = closesocket(s);
|
||||
EndDialog(FALSE);
|
||||
} else {
|
||||
error = listen(s, 1);
|
||||
if(!error) {
|
||||
sock = s;
|
||||
EndDialog(TRUE);
|
||||
} else {
|
||||
systemMessage(IDS_ERROR_LISTENING, "Error listening on socket.");
|
||||
closesocket(s);
|
||||
EndDialog(FALSE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
systemMessage(IDS_ERROR_CREATING_SOCKET, "Error creating socket.");
|
||||
EndDialog(FALSE);
|
||||
}
|
||||
theApp.gdbPort = port;
|
||||
EndDialog(TRUE);
|
||||
}
|
||||
|
||||
void GDBPortDlg::OnCancel()
|
||||
|
@ -136,11 +117,45 @@ void GDBPortDlg::OnClose()
|
|||
// GDBWaitingDlg dialog
|
||||
|
||||
|
||||
GDBWaitingDlg::GDBWaitingDlg(SOCKET s, int p, CWnd* pParent /*=NULL*/)
|
||||
GDBWaitingDlg::GDBWaitingDlg(int p, CWnd* pParent /*=NULL*/)
|
||||
: CDialog(GDBWaitingDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(GDBWaitingDlg)
|
||||
//}}AFX_DATA_INIT
|
||||
sockaddr_in address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = inet_addr("0.0.0.0");
|
||||
address.sin_port = htons(p);
|
||||
port = ntohs(address.sin_port);
|
||||
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (s != INVALID_SOCKET) {
|
||||
int error = bind(s, (sockaddr *)&address, sizeof(address));
|
||||
|
||||
if (error) {
|
||||
systemMessage(IDS_ERROR_BINDING, "Error binding socket. Port probably in use.");
|
||||
error = closesocket(s);
|
||||
//EndDialog(FALSE);
|
||||
}
|
||||
else {
|
||||
error = listen(s, 1);
|
||||
if (!error) {
|
||||
sock = s;
|
||||
//EndDialog(TRUE);
|
||||
}
|
||||
else {
|
||||
systemMessage(IDS_ERROR_LISTENING, "Error listening on socket.");
|
||||
closesocket(s);
|
||||
//EndDialog(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
systemMessage(IDS_ERROR_CREATING_SOCKET, "Error creating socket.");
|
||||
//EndDialog(FALSE);
|
||||
}
|
||||
|
||||
port = p & 65535;
|
||||
listenSocket = s;
|
||||
}
|
||||
|
@ -199,13 +214,13 @@ LRESULT GDBWaitingDlg::OnSocketAccept(WPARAM wParam, LPARAM lParam)
|
|||
if(s != INVALID_SOCKET) {
|
||||
char dummy;
|
||||
recv(s, &dummy, 1, 0);
|
||||
if(dummy != '+') {
|
||||
systemMessage(IDS_ACK_NOT_RECEIVED, "ACK not received from GDB.");
|
||||
OnClose(); // calls EndDialog
|
||||
} else {
|
||||
//if(dummy != '+') {
|
||||
// systemMessage(IDS_ACK_NOT_RECEIVED, "ACK not received from GDB.");
|
||||
// OnClose(); // calls EndDialog
|
||||
//} else {
|
||||
sock = s;
|
||||
EndDialog(TRUE);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ class GDBWaitingDlg : public CDialog
|
|||
SOCKET getSocket();
|
||||
SOCKET getListenSocket();
|
||||
afx_msg LRESULT OnSocketAccept(WPARAM wParam, LPARAM lParam);
|
||||
GDBWaitingDlg(SOCKET s,int p, CWnd* pParent = NULL); // standard constructor
|
||||
GDBWaitingDlg(int p, CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(GDBWaitingDlg)
|
||||
|
|
|
@ -279,10 +279,10 @@ BEGIN_MESSAGE_MAP(MainWnd, CWnd)
|
|||
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_CONFIGUREPORT, OnToolsDebugConfigurePort)
|
||||
ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_CONFIGUREPORT, OnUpdateToolsDebugConfigurePort)
|
||||
ON_COMMAND(ID_TOOLS_DEBUG_BREAKONLOAD, OnToolsDebugBreakOnLoad)
|
||||
ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_BREAKONLOAD, OnUpdateToolsDebugBreakOnLoad)
|
||||
ON_COMMAND(ID_TOOLS_DEBUG_BREAK, OnToolsDebugBreak)
|
||||
ON_UPDATE_COMMAND_UI(ID_TOOLS_DEBUG_BREAK, OnUpdateToolsDebugBreak)
|
||||
ON_COMMAND(ID_TOOLS_DEBUG_DISCONNECT, OnToolsDebugDisconnect)
|
||||
|
@ -632,6 +632,10 @@ bool MainWnd::FileRun()
|
|||
if (theApp.linkAuto)
|
||||
BootLink(theApp.linkMode, theApp.linkHostAddr, theApp.linkTimeout, theApp.linkHacks, theApp.linkNumPlayers);
|
||||
#endif
|
||||
|
||||
if (theApp.gdbBreakOnLoad)
|
||||
OnToolsDebugBreak();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -281,10 +281,10 @@ protected:
|
|||
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 OnToolsDebugConfigurePort();
|
||||
afx_msg void OnUpdateToolsDebugConfigurePort(CCmdUI* pCmdUI);
|
||||
afx_msg void OnToolsDebugBreakOnLoad();
|
||||
afx_msg void OnUpdateToolsDebugBreakOnLoad(CCmdUI* pCmdUI);
|
||||
afx_msg void OnToolsDebugBreak();
|
||||
afx_msg void OnUpdateToolsDebugBreak(CCmdUI* pCmdUI);
|
||||
afx_msg void OnToolsDebugDisconnect();
|
||||
|
|
|
@ -177,84 +177,68 @@ void MainWnd::OnDebugNextframe()
|
|||
theApp.winPauseNextFrame = true;
|
||||
}
|
||||
|
||||
void MainWnd::OnToolsDebugGdb()
|
||||
void MainWnd::OnToolsDebugConfigurePort()
|
||||
{
|
||||
GDBPortDlg dlg;
|
||||
GDBPortDlg dlg;
|
||||
|
||||
if(dlg.DoModal()) {
|
||||
GDBWaitingDlg wait(dlg.getSocket(), dlg.getPort());
|
||||
if(wait.DoModal()) {
|
||||
remoteSetSockets(wait.getListenSocket(), wait.getSocket());
|
||||
debugger = true;
|
||||
emulating = 1;
|
||||
theApp.cartridgeType = IMAGE_GBA;
|
||||
theApp.filename = "\\gnu_stub";
|
||||
rom = (u8 *)malloc(0x2000000);
|
||||
workRAM = (u8 *)calloc(1, 0x40000);
|
||||
bios = (u8 *)calloc(1,0x4000);
|
||||
internalRAM = (u8 *)calloc(1,0x8000);
|
||||
paletteRAM = (u8 *)calloc(1,0x400);
|
||||
vram = (u8 *)calloc(1, 0x20000);
|
||||
oam = (u8 *)calloc(1, 0x400);
|
||||
pix = (u8 *)calloc(1, 4 * 241 * 162);
|
||||
ioMem = (u8 *)calloc(1, 0x400);
|
||||
|
||||
theApp.emulator = GBASystem;
|
||||
|
||||
CPUInit(theApp.biosFileNameGBA, theApp.useBiosFileGBA);
|
||||
CPUReset();
|
||||
if(dlg.DoModal()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateToolsDebugGdb(CCmdUI* pCmdUI)
|
||||
void MainWnd::OnUpdateToolsDebugConfigurePort(CCmdUI* pCmdUI)
|
||||
{
|
||||
pCmdUI->Enable(theApp.videoOption <= VIDEO_6X && remoteSocket == -1);
|
||||
}
|
||||
|
||||
void MainWnd::OnToolsDebugLoadandwait()
|
||||
void MainWnd::OnToolsDebugBreakOnLoad()
|
||||
{
|
||||
if(fileOpenSelect(0)) {
|
||||
if(FileRun()) {
|
||||
if(theApp.cartridgeType != 0) {
|
||||
systemMessage(IDS_ERROR_NOT_GBA_IMAGE, "Error: not a GBA image");
|
||||
OnFileClose();
|
||||
return;
|
||||
}
|
||||
GDBPortDlg dlg;
|
||||
|
||||
if(dlg.DoModal()) {
|
||||
GDBWaitingDlg wait(dlg.getSocket(), dlg.getPort());
|
||||
if(wait.DoModal()) {
|
||||
remoteSetSockets(wait.getListenSocket(), wait.getSocket());
|
||||
debugger = true;
|
||||
emulating = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
theApp.gdbBreakOnLoad = !theApp.gdbBreakOnLoad;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateToolsDebugLoadandwait(CCmdUI* pCmdUI)
|
||||
void MainWnd::OnUpdateToolsDebugBreakOnLoad(CCmdUI* pCmdUI)
|
||||
{
|
||||
pCmdUI->Enable(theApp.videoOption <= VIDEO_6X && remoteSocket == -1);
|
||||
pCmdUI->SetCheck(theApp.gdbBreakOnLoad);
|
||||
}
|
||||
|
||||
void MainWnd::OnToolsDebugBreak()
|
||||
{
|
||||
if(armState) {
|
||||
armNextPC -= 4;
|
||||
reg[15].I -= 4;
|
||||
} else {
|
||||
armNextPC -= 2;
|
||||
reg[15].I -= 2;
|
||||
}
|
||||
debugger = true;
|
||||
GDBPortDlg dlg;
|
||||
|
||||
int port = theApp.gdbPort;
|
||||
if (port == 0)
|
||||
{
|
||||
if (dlg.DoModal()) {
|
||||
port = dlg.getPort();
|
||||
}
|
||||
}
|
||||
|
||||
if (port != 0) {
|
||||
if (remoteSocket == -1)
|
||||
{
|
||||
GDBWaitingDlg wait(port);
|
||||
if (wait.DoModal()) {
|
||||
remoteSetSockets(wait.getListenSocket(), wait.getSocket());
|
||||
debugger = true;
|
||||
emulating = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (armState) {
|
||||
armNextPC -= 4;
|
||||
reg[15].I -= 4;
|
||||
}
|
||||
else {
|
||||
armNextPC -= 2;
|
||||
reg[15].I -= 2;
|
||||
}
|
||||
debugger = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateToolsDebugBreak(CCmdUI* pCmdUI)
|
||||
{
|
||||
pCmdUI->Enable(theApp.videoOption <= VIDEO_6X && remoteSocket != -1);
|
||||
pCmdUI->Enable(theApp.videoOption <= VIDEO_6X && emulating != 0);
|
||||
}
|
||||
|
||||
void MainWnd::OnToolsDebugDisconnect()
|
||||
|
|
|
@ -129,7 +129,6 @@ static char THIS_FILE[] = __FILE__;
|
|||
#endif
|
||||
|
||||
int emulating = 0;
|
||||
bool debugger = false;
|
||||
int RGB_LOW_BITS_MASK = 0;
|
||||
bool b16to32Video = false;
|
||||
int systemFrameSkip = 0;
|
||||
|
@ -290,6 +289,7 @@ VBA::VBA()
|
|||
pauseWhenInactive = true;
|
||||
speedupToggle = false;
|
||||
winGbPrinterEnabled = false;
|
||||
gdbBreakOnLoad = false;
|
||||
threadPriority = 2;
|
||||
disableMMX = false;
|
||||
languageOption = 0;
|
||||
|
@ -1339,7 +1339,8 @@ BOOL VBA::OnIdle(LONG lCount)
|
|||
return TRUE; // continue loop
|
||||
return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
|
||||
} else if(emulating && active && !paused) {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
for(int i = 0; i < 2; i++) { // Why is this loop here?
|
||||
if (!debugger)
|
||||
emulator.emuMain(emulator.emuCount);
|
||||
|
||||
#ifndef NO_LINK
|
||||
|
@ -1731,6 +1732,9 @@ void VBA::loadSettings()
|
|||
linkNumPlayers = regQueryDwordValue("LinkNumPlayers", 2);
|
||||
#endif
|
||||
|
||||
gdbPort = regQueryDwordValue("gdbPort", 55555);
|
||||
gdbBreakOnLoad = regQueryDwordValue("gdbBreakOnLoad", false) ? true : false;
|
||||
|
||||
Sm60FPS::bSaveMoreCPU = regQueryDwordValue("saveMoreCPU", 0);
|
||||
|
||||
#ifndef NO_OAL
|
||||
|
@ -2665,6 +2669,9 @@ void VBA::saveSettings()
|
|||
regSetDwordValue("LinkNumPlayers", linkNumPlayers);
|
||||
#endif
|
||||
|
||||
regSetDwordValue("gdbPort", gdbPort);
|
||||
regSetDwordValue("gdbBreakOnLoad", gdbBreakOnLoad);
|
||||
|
||||
regSetDwordValue("lastFullscreen", lastFullscreen);
|
||||
regSetDwordValue("pauseWhenInactive", pauseWhenInactive);
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ class VBA : public CWinApp
|
|||
int rewindCount;
|
||||
bool rewindSaveNeeded;
|
||||
int rewindTimer;
|
||||
bool gdbBreakOnLoad;
|
||||
int captureFormat;
|
||||
bool tripleBuffering;
|
||||
unsigned short throttle;
|
||||
|
@ -218,6 +219,8 @@ class VBA : public CWinApp
|
|||
BOOL linkHacks;
|
||||
int linkNumPlayers;
|
||||
|
||||
int gdbPort;
|
||||
|
||||
public:
|
||||
VBA();
|
||||
~VBA();
|
||||
|
|
|
@ -795,7 +795,7 @@ CAPTION "Waiting..."
|
|||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
PUSHBUTTON "Cancel",ID_CANCEL,67,23,50,14
|
||||
LTEXT "Waiting for connection on port:",IDC_STATIC,7,7,117,8
|
||||
LTEXT "Waiting for GDB on port:",IDC_STATIC,7,7,117,8
|
||||
LTEXT "",IDC_PORT,143,7,36,8,SS_NOPREFIX
|
||||
END
|
||||
|
||||
|
@ -1957,10 +1957,10 @@ BEGIN
|
|||
MENUITEM "&Next frame", ID_DEBUG_NEXTFRAME
|
||||
POPUP "GDB"
|
||||
BEGIN
|
||||
MENUITEM "Wait for connection...", ID_TOOLS_DEBUG_GDB
|
||||
MENUITEM "Load and wait...", ID_TOOLS_DEBUG_LOADANDWAIT
|
||||
MENUITEM "Break into GDB", ID_TOOLS_DEBUG_BREAK
|
||||
MENUITEM "Disconnect", ID_TOOLS_DEBUG_DISCONNECT
|
||||
MENUITEM "Break on load", ID_TOOLS_DEBUG_BREAKONLOAD
|
||||
MENUITEM "Configure port...", ID_TOOLS_DEBUG_CONFIGUREPORT
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
POPUP "Record"
|
||||
|
|
|
@ -711,7 +711,8 @@
|
|||
#define ID_OPTIONS_GAMEBOY_COLORS 40147
|
||||
#define ID_TOOLS_DISASSEMBLE 40151
|
||||
#define ID_TOOLS_DEBUG_GDB 40152
|
||||
#define ID_TOOLS_DEBUG_LOADANDWAIT 40153
|
||||
#define ID_TOOLS_DEBUG_CONFIGUREPORT 40153
|
||||
#define ID_TOOLS_DEBUG_BREAKONLOAD 40159
|
||||
#define ID_TOOLS_DEBUG_DISCONNECT 40154
|
||||
#define ID_TOOLS_DEBUG_BREAK 40155
|
||||
#define ID_TOOLS_LOGGING 40156
|
||||
|
|
|
@ -1125,15 +1125,11 @@ void debuggerMain()
|
|||
{
|
||||
}
|
||||
|
||||
bool debugger;
|
||||
//bool debugger;
|
||||
|
||||
void (*dbgOutput)(const char *s, u32 addr) = debuggerOutput;
|
||||
void (*dbgSignal)(int sig,int number) = debuggerSignal;
|
||||
|
||||
void debuggerBreakOnWrite(u32 address, u32 oldvalue, u32 value, int size, int t)
|
||||
{
|
||||
}
|
||||
|
||||
void log(const char *defaultMsg, ...)
|
||||
{
|
||||
static FILE *out = NULL;
|
||||
|
|
Loading…
Reference in New Issue