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:
skidau 2015-04-02 05:53:57 +00:00
parent 7722a59670
commit 55e1dad514
36 changed files with 8474 additions and 235 deletions

View File

@ -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

View File

@ -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"
>

View File

@ -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" />

View File

@ -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>

View File

@ -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" />

View File

@ -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>

View File

@ -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();
}
*/

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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 *);

View File

@ -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

View File

@ -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

View File

@ -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;

67
src/gba/debugger-expr.l Normal file
View File

@ -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);
}

164
src/gba/debugger-expr.y Normal file
View File

@ -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);
}
}
}

File diff suppressed because it is too large Load Diff

79
src/gba/remote.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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 },

View File

@ -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);
}
//}
}
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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();

View File

@ -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()

View File

@ -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);

View File

@ -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();

View File

@ -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"

View File

@ -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

View File

@ -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;