2006-07-19 05:57:00 +00:00
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file :
* Copyright ( C ) 2002 Ben Parnell
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "common.h"
# include "..\..\types.h"
2006-07-24 05:19:59 +00:00
# include "..\..\debug.h"
2006-07-19 05:57:00 +00:00
# include "..\..\fceu.h"
# include "..\..\cheat.h"
# include "..\..\cart.h"
# include "..\..\ines.h"
2006-07-24 06:03:57 +00:00
# include "memview.h"
# include "debugger.h"
# include "cdlogger.h"
2006-07-19 05:57:00 +00:00
# include "memviewsp.h"
2006-07-24 06:03:57 +00:00
# include "cheat.h"
2006-07-19 05:57:00 +00:00
# include <assert.h>
//#include "string.h"
# define MODE_NES_MEMORY 0
# define MODE_NES_PPU 1
# define MODE_NES_FILE 2
// This defines all of our right click popup menus
struct
{
int minaddress ; //The minimum address where this popup will appear
int maxaddress ; //The maximum address where this popup will appear
int editingmode ; //The editing mode which this popup appears in
int id ; //The menu ID for this popup
char * text ; //the text for the menu item (some of these need to be dynamic)
}
popupmenu [ ] =
{
{ 0 , 0x2000 , 0 , 1 , " Freeze/Unfreeze This Address " } ,
{ 0x6000 , 0x7FFF , 0 , 1 , " Freeze/Unfreeze This Address " } ,
{ 0 , 0xFFFF , 0 , 2 , " Add Debugger Read Breakpoint " } ,
{ 0 , 0x3FFF , 1 , 2 , " Add Debugger Read Breakpoint " } ,
{ 0 , 0xFFFF , 0 , 3 , " Add Debugger Write Breakpoint " } ,
{ 0 , 0x3FFF , 1 , 3 , " Add Debugger Write Breakpoint " } ,
{ 0 , 0xFFFF , 0 , 4 , " Add Debugger Execute Breakpoint " } ,
{ 0x8000 , 0xFFFF , 0 , 5 , " Go Here In Rom File " } ,
{ 0x8000 , 0xFFFF , 0 , 6 , " Create Game Genie Code At This Address " } ,
//{0,0xFFFFFF,2,7,"Create Game Genie Code At This Address"}
// ################################## Start of SP CODE ###########################
{ 0 , 0xFFFF , 0 , 20 , " Add / Remove bookmark " } ,
// ################################## End of SP CODE ###########################
} ;
# define POPUPNUM (sizeof popupmenu / sizeof popupmenu[0])
int LoadTableFile ( ) ;
void UnloadTableFile ( ) ;
void InputData ( char * input ) ;
int GetMemViewData ( int i ) ;
void UpdateCaption ( ) ;
int UpdateCheatColorCallB ( char * name , uint32 a , uint8 v , int compare , int s , int type , void * data ) ; //mbg merge 6/29/06 - added arg
int DeleteCheatCallB ( char * name , uint32 a , uint8 v , int compare , int s , int type ) ; //mbg merge 6/29/06 - added arg
// ################################## Start of SP CODE ###########################
void FreezeRam ( int address , int mode , int final ) ;
// ################################## End of SP CODE ###########################
int GetHexScreenCoordx ( int offset ) ;
int GetHexScreenCoordy ( int offset ) ;
int GetAddyFromCoord ( int x , int y ) ;
void AutoScrollFromCoord ( int x , int y ) ;
LRESULT CALLBACK MemViewCallB ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam ) ;
BOOL CALLBACK MemFindCallB ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ) ;
void FindNext ( ) ;
void OpenFindDialog ( ) ;
HWND hMemView , hMemFind ;
HDC mDC ;
//int tempdummy;
//char dummystr[100];
HFONT hMemFont ;
int CurOffset ;
int MemFontHeight ;
int MemFontWidth ;
int ClientHeight ;
int NoColors ;
int EditingMode ;
int EditingText ;
int AddyWasText ; //used by the GetAddyFromCoord() function.
int TableFileLoaded ;
char chartable [ 256 ] ;
//SCROLLINFO memsi;
//HBITMAP HDataBmp;
//HGDIOBJ HDataObj;
HDC HDataDC ;
int CursorX = 2 , CursorY = 9 ;
int CursorStartAddy , CursorEndAddy = - 1 ;
int CursorDragPoint ; //, CursorShiftPoint = -1;
//int CursorStartNibble=1, CursorEndNibble; //1 means that only half of the byte is selected
int TempData = - 1 ;
int DataAmount ;
int MaxSize ;
COLORREF * BGColorList ;
COLORREF * TextColorList ;
int * OldValues ; //this will be used for a speed hack
int OldCurOffset ;
int lbuttondown , lbuttondownx , lbuttondowny ;
int mousex , mousey ;
int FindAsText ;
int FindDirectionUp ;
char FindTextBox [ 60 ] ;
extern iNES_HEADER head ;
//undo structure
struct UNDOSTRUCT {
int addr ;
int size ;
unsigned char * data ;
UNDOSTRUCT * last ; //mbg merge 7/18/06 removed struct qualifier
} ;
struct UNDOSTRUCT * undo_list = 0 ;
void ApplyPatch ( int addr , int size , uint8 * data ) {
UNDOSTRUCT * tmp = ( UNDOSTRUCT * ) malloc ( sizeof ( UNDOSTRUCT ) ) ; //mbg merge 7/18/06 removed struct qualifiers and added cast
int i ;
//while(tmp != 0){tmp=tmp->next;x++;};
//tmp = malloc(sizeof(struct UNDOSTRUCT));
//sprintf(str,"%d",x);
//MessageBox(hMemView,str,"info", MB_OK);
tmp - > addr = addr ;
tmp - > size = size ;
tmp - > data = ( uint8 * ) malloc ( sizeof ( uint8 ) * size ) ;
tmp - > last = undo_list ;
for ( i = 0 ; i < size ; i + + ) {
tmp - > data [ i ] = GetFileData ( addr + i ) ;
WriteFileData ( addr + i , data [ i ] ) ;
}
undo_list = tmp ;
//UpdateColorTable();
return ;
}
void UndoLastPatch ( ) {
struct UNDOSTRUCT * tmp = undo_list ;
int i ;
if ( undo_list = = 0 ) return ;
//while(tmp->next != 0){tmp=tmp->next;}; //traverse to the one before the last one
for ( i = 0 ; i < tmp - > size ; i + + ) {
WriteFileData ( tmp - > addr + i , tmp - > data [ i ] ) ;
}
undo_list = undo_list - > last ;
ChangeMemViewFocus ( 2 , tmp - > addr , - 1 ) ; //move to the focus to where we are undoing at.
free ( tmp - > data ) ;
free ( tmp ) ;
return ;
}
void FlushUndoBuffer ( ) {
struct UNDOSTRUCT * tmp ;
while ( undo_list ! = 0 ) {
tmp = undo_list ;
undo_list = undo_list - > last ;
free ( tmp - > data ) ;
free ( tmp ) ;
}
UpdateColorTable ( ) ;
return ;
}
int GetFileData ( int offset ) {
if ( offset < 16 ) return * ( ( unsigned char * ) & head + offset ) ;
if ( offset < 16 + PRGsize [ 0 ] ) return PRGptr [ 0 ] [ offset - 16 ] ;
if ( offset < 16 + PRGsize [ 0 ] + CHRsize [ 0 ] ) return CHRptr [ 0 ] [ offset - 16 - PRGsize [ 0 ] ] ;
return - 1 ;
}
int WriteFileData ( int addr , int data ) {
if ( addr < 16 ) MessageBox ( hMemView , " Sorry " , " Go bug bbit if you really want to edit the header. " , MB_OK ) ;
if ( ( addr > = 16 ) & & ( addr < PRGsize [ 0 ] + 16 ) ) * ( uint8 * ) ( GetNesPRGPointer ( addr - 16 ) ) = data ;
if ( ( addr > = PRGsize [ 0 ] + 16 ) & & ( addr < CHRsize [ 0 ] + PRGsize [ 0 ] + 16 ) ) * ( uint8 * ) ( GetNesCHRPointer ( addr - 16 - PRGsize [ 0 ] ) ) = data ;
return 0 ;
}
int GetRomFileSize ( ) { //todo: fix or remove this?
return 0 ;
}
//should return -1, otherwise returns the line number it had the error on
int LoadTableFile ( ) {
char str [ 50 ] ;
FILE * FP ;
int i , line , charcode1 , charcode2 ;
const char filter [ ] = " Table Files (*.TBL) \0 *.tbl \0 " ;
char nameo [ 2048 ] ; //todo: possibly no need for this? can lpstrfilter point to loadedcdfile instead?
OPENFILENAME ofn ;
StopSound ( ) ;
memset ( & ofn , 0 , sizeof ( ofn ) ) ;
ofn . lStructSize = sizeof ( ofn ) ;
ofn . hInstance = fceu_hInstance ;
ofn . lpstrTitle = " Load Table File... " ;
ofn . lpstrFilter = filter ;
nameo [ 0 ] = 0 ;
ofn . lpstrFile = nameo ;
ofn . nMaxFile = 256 ;
ofn . Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ;
ofn . hwndOwner = hCDLogger ;
if ( ! GetOpenFileName ( & ofn ) ) return - 1 ;
for ( i = 0 ; i < 256 ; i + + ) {
chartable [ i ] = 0 ;
}
FP = fopen ( nameo , " r " ) ;
line = 0 ;
while ( ( fgets ( str , 45 , FP ) ) ! = NULL ) { /* get one line from the file */
line + + ;
if ( strlen ( str ) < 3 ) continue ;
charcode1 = charcode2 = - 1 ;
if ( ( str [ 0 ] > = ' a ' ) & & ( str [ 0 ] < = ' f ' ) ) charcode1 = str [ 0 ] - ( ' a ' - 0xA ) ;
if ( ( str [ 0 ] > = ' A ' ) & & ( str [ 0 ] < = ' F ' ) ) charcode1 = str [ 0 ] - ( ' A ' - 0xA ) ;
if ( ( str [ 0 ] > = ' 0 ' ) & & ( str [ 0 ] < = ' 9 ' ) ) charcode1 = str [ 0 ] - ' 0 ' ;
if ( ( str [ 1 ] > = ' a ' ) & & ( str [ 1 ] < = ' f ' ) ) charcode2 = str [ 1 ] - ( ' a ' - 0xA ) ;
if ( ( str [ 1 ] > = ' A ' ) & & ( str [ 1 ] < = ' F ' ) ) charcode2 = str [ 1 ] - ( ' A ' - 0xA ) ;
if ( ( str [ 1 ] > = ' 0 ' ) & & ( str [ 1 ] < = ' 9 ' ) ) charcode2 = str [ 1 ] - ' 0 ' ;
if ( charcode1 = = - 1 ) {
UnloadTableFile ( ) ;
fclose ( FP ) ;
return line ; //we have an error getting the first input
}
if ( charcode2 ! = - 1 ) charcode1 = ( charcode1 < < 4 ) | charcode2 ;
for ( i = 0 ; i < ( int ) strlen ( str ) ; i + + ) if ( str [ i ] = = ' = ' ) break ;
if ( i = = strlen ( str ) ) {
UnloadTableFile ( ) ;
fclose ( FP ) ;
return line ; //error no '=' found
}
i + + ;
//ORing i with 32 just converts it to lowercase if it isn't
if ( ( ( str [ i ] | 32 ) = = ' r ' ) & & ( ( str [ i + 1 ] | 32 ) = = ' e ' ) & & ( ( str [ i + 2 ] | 32 ) = = ' t ' ) )
charcode2 = 0x0D ;
else charcode2 = str [ i ] ;
chartable [ charcode1 ] = charcode2 ;
}
TableFileLoaded = 1 ;
fclose ( FP ) ;
return - 1 ;
}
void UnloadTableFile ( ) {
int i , j ;
for ( i = 0 ; i < 256 ; i + + ) {
j = i ;
if ( j < 0x20 ) j = 0x2E ;
if ( j > 0x7e ) j = 0x2E ;
chartable [ i ] = j ;
}
TableFileLoaded = 0 ;
return ;
}
void UpdateMemoryView ( int draw_all ) {
int i , j ;
//LPVOID lpMsgBuf;
//int curlength;
char str [ 100 ] ;
char str2 [ 100 ] ;
if ( ! hMemView ) return ;
/*
if ( draw_all ) {
for ( i = CurOffset ; i < CurOffset + DataAmount ; i + = 16 ) {
MoveToEx ( HDataDC , 0 , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ;
sprintf ( str , " %06X: " , i ) ;
for ( j = 0 ; j < 16 ; j + + ) {
sprintf ( str2 , " %02X " , GetMem ( i + j ) ) ;
strcat ( str , str2 ) ;
}
strcat ( str , " : " ) ;
k = strlen ( str ) ;
for ( j = 0 ; j < 16 ; j + + ) {
str [ k + j ] = GetMem ( i + j ) ;
if ( str [ k + j ] < 0x20 ) str [ k + j ] = 0x2E ;
if ( str [ k + j ] > 0x7e ) str [ k + j ] = 0x2E ;
}
str [ k + 16 ] = 0 ;
TextOut ( HDataDC , 0 , 0 , str , strlen ( str ) ) ;
}
} else { */
for ( i = CurOffset ; i < CurOffset + DataAmount ; i + = 16 ) {
if ( ( OldCurOffset ! = CurOffset ) | | draw_all ) {
MoveToEx ( HDataDC , 0 , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ;
SetTextColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
SetBkColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
sprintf ( str , " %06X: " , i ) ;
TextOut ( HDataDC , 0 , 0 , str , strlen ( str ) ) ;
}
for ( j = 0 ; j < 16 ; j + + ) {
if ( ( CursorEndAddy = = - 1 ) & & ( CursorStartAddy = = i + j ) ) { //print up single highlighted text
sprintf ( str , " %02X " , GetMemViewData ( CursorStartAddy ) ) ;
OldValues [ i + j - CurOffset ] = - 1 ; //set it to redraw this one next time
MoveToEx ( HDataDC , 8 * MemFontWidth + ( j * 3 * MemFontWidth ) , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ;
if ( TempData ! = - 1 ) {
sprintf ( str2 , " %X " , TempData ) ;
SetBkColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
SetTextColor ( HDataDC , RGB ( 255 , 0 , 0 ) ) ;
TextOut ( HDataDC , 0 , 0 , str2 , 1 ) ;
SetTextColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
SetBkColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
TextOut ( HDataDC , 0 , 0 , & str [ 1 ] , 1 ) ;
} else {
SetTextColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
SetBkColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
TextOut ( HDataDC , 0 , 0 , str , 1 ) ;
SetTextColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
SetBkColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
TextOut ( HDataDC , 0 , 0 , & str [ 1 ] , 1 ) ;
}
TextOut ( HDataDC , 0 , 0 , " " , 1 ) ;
SetTextColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
SetBkColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
MoveToEx ( HDataDC , ( 59 + j ) * MemFontWidth , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ; //todo: try moving this above the for loop
str [ 0 ] = chartable [ GetMemViewData ( i + j ) ] ;
if ( str [ 0 ] < 0x20 ) str [ 0 ] = 0x2E ;
if ( str [ 0 ] > 0x7e ) str [ 0 ] = 0x2E ;
str [ 1 ] = 0 ;
TextOut ( HDataDC , 0 , 0 , str , 1 ) ;
continue ;
}
if ( ( OldValues [ i + j - CurOffset ] ! = GetMemViewData ( i + j ) ) | | draw_all ) {
MoveToEx ( HDataDC , 8 * MemFontWidth + ( j * 3 * MemFontWidth ) , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ;
SetTextColor ( HDataDC , TextColorList [ i + j - CurOffset ] ) ; //(8+j*3)*MemFontWidth
SetBkColor ( HDataDC , BGColorList [ i + j - CurOffset ] ) ;
sprintf ( str , " %02X " , GetMemViewData ( i + j ) ) ;
TextOut ( HDataDC , 0 , 0 , str , strlen ( str ) ) ;
MoveToEx ( HDataDC , ( 59 + j ) * MemFontWidth , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ; //todo: try moving this above the for loop
str [ 0 ] = chartable [ GetMemViewData ( i + j ) ] ;
if ( str [ 0 ] < 0x20 ) str [ 0 ] = 0x2E ;
if ( str [ 0 ] > 0x7e ) str [ 0 ] = 0x2E ;
str [ 1 ] = 0 ;
TextOut ( HDataDC , 0 , 0 , str , 1 ) ;
if ( CursorStartAddy ! = i + j ) OldValues [ i + j - CurOffset ] = GetMemViewData ( i + j ) ;
}
}
if ( draw_all ) {
MoveToEx ( HDataDC , 56 * MemFontWidth , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ;
SetTextColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
SetBkColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
TextOut ( HDataDC , 0 , 0 , " : " , 3 ) ;
} /*
for ( j = 0 ; j < 16 ; j + + ) {
if ( ( OldValues [ i + j - CurOffset ] ! = GetMem ( i + j ) ) | | draw_all ) {
MoveToEx ( HDataDC , ( 59 + j ) * MemFontWidth , MemFontHeight * ( ( i - CurOffset ) / 16 ) , NULL ) ; //todo: try moving this above the for loop
SetTextColor ( HDataDC , TextColorList [ i + j - CurOffset ] ) ;
SetBkColor ( HDataDC , BGColorList [ i + j - CurOffset ] ) ;
str [ 0 ] = GetMem ( i + j ) ;
if ( str [ 0 ] < 0x20 ) str [ 0 ] = 0x2E ;
if ( str [ 0 ] > 0x7e ) str [ 0 ] = 0x2E ;
str [ 1 ] = 0 ;
TextOut ( HDataDC , 0 , 0 , str , 1 ) ;
if ( CursorStartAddy ! = i + j ) OldValues [ i + j - CurOffset ] = GetMem ( i + j ) ;
}
} */
}
// }
SetTextColor ( HDataDC , RGB ( 0 , 0 , 0 ) ) ;
SetBkColor ( HDataDC , RGB ( 255 , 255 , 255 ) ) ;
MoveToEx ( HDataDC , 0 , 0 , NULL ) ;
OldCurOffset = CurOffset ;
return ;
}
void UpdateCaption ( ) {
char str [ 100 ] ;
char EditString [ 3 ] [ 20 ] = { " RAM " , " PPU Memory " , " ROM " } ;
if ( CursorEndAddy = = - 1 ) {
sprintf ( str , " Hex Editor - Editing %s Offset 0x%06x " , EditString [ EditingMode ] , CursorStartAddy ) ;
} else {
sprintf ( str , " Hex Editor - Editing %s Offset 0x%06x - 0x%06x, 0x%x bytes selected " ,
EditString [ EditingMode ] , CursorStartAddy , CursorEndAddy , CursorEndAddy - CursorStartAddy + 1 ) ;
}
SetWindowText ( hMemView , str ) ;
return ;
}
int GetMemViewData ( int i ) {
if ( EditingMode = = 0 ) return GetMem ( i ) ;
if ( EditingMode = = 1 ) {
i & = 0x3FFF ;
if ( i < 0x2000 ) return VPage [ ( i ) > > 10 ] [ ( i ) ] ;
if ( i < 0x3F00 ) return vnapage [ ( i > > 10 ) & 0x3 ] [ i & 0x3FF ] ;
return PALRAM [ i & 0x1F ] ;
}
if ( EditingMode = = 2 ) { //todo: use getfiledata() here
if ( i < 16 ) return * ( ( unsigned char * ) & head + i ) ;
if ( i < 16 + PRGsize [ 0 ] ) return PRGptr [ 0 ] [ i - 16 ] ;
if ( i < 16 + PRGsize [ 0 ] + CHRsize [ 0 ] ) return CHRptr [ 0 ] [ i - 16 - PRGsize [ 0 ] ] ;
}
return 0 ;
}
void UpdateColorTable ( ) {
UNDOSTRUCT * tmp ; //mbg merge 7/18/06 removed struct qualifier
int i , j ;
if ( ! hMemView ) return ;
for ( i = 0 ; i < DataAmount ; i + + ) {
if ( ( i + CurOffset > = CursorStartAddy ) & & ( i + CurOffset < = CursorEndAddy ) ) {
BGColorList [ i ] = RGB ( 0 , 0 , 0 ) ;
TextColorList [ i ] = RGB ( 255 , 255 , 255 ) ;
continue ;
}
BGColorList [ i ] = RGB ( 255 , 255 , 255 ) ;
TextColorList [ i ] = RGB ( 0 , 0 , 0 ) ;
}
//mbg merge 6/29/06 - added argument
if ( EditingMode = = 0 ) FCEUI_ListCheats ( UpdateCheatColorCallB , 0 ) ;
// ################################## Start of SP CODE ###########################
for ( j = 0 ; j < nextBookmark ; j + + )
{
if ( ( hexBookmarks [ j ] . address > = CurOffset ) & & ( hexBookmarks [ j ] . address < CurOffset + DataAmount ) )
TextColorList [ hexBookmarks [ j ] . address - CurOffset ] = RGB ( 0 , 0xCC , 0 ) ;
}
// ################################## End of SP CODE ###########################
if ( EditingMode = = 2 ) {
if ( cdloggerdata ) {
for ( i = 0 ; i < DataAmount ; i + + ) {
if ( ( CurOffset + i > = 16 ) & & ( CurOffset + i < 16 + PRGsize [ 0 ] ) ) {
if ( ( cdloggerdata [ i + CurOffset - 16 ] & 3 ) = = 3 ) TextColorList [ i ] = RGB ( 0 , 192 , 0 ) ;
if ( ( cdloggerdata [ i + CurOffset - 16 ] & 3 ) = = 1 ) TextColorList [ i ] = RGB ( 192 , 192 , 0 ) ;
if ( ( cdloggerdata [ i + CurOffset - 16 ] & 3 ) = = 2 ) TextColorList [ i ] = RGB ( 0 , 0 , 192 ) ;
}
}
}
tmp = undo_list ;
while ( tmp ! = 0 ) {
//if((tmp->addr < CurOffset+DataAmount) && (tmp->addr+tmp->size > CurOffset))
for ( i = tmp - > addr ; i < tmp - > addr + tmp - > size ; i + + ) {
if ( ( i > CurOffset ) & & ( i < CurOffset + DataAmount ) )
TextColorList [ i - CurOffset ] = RGB ( 255 , 0 , 0 ) ;
}
tmp = tmp - > last ;
}
}
UpdateMemoryView ( 1 ) ; //anytime the colors change, the memory viewer needs to be completely redrawn
}
//mbg merge 6/29/06 - added argument
int UpdateCheatColorCallB ( char * name , uint32 a , uint8 v , int compare , int s , int type , void * data ) {
if ( ( a > = CurOffset ) & & ( a < CurOffset + DataAmount ) ) {
if ( s ) TextColorList [ a - CurOffset ] = RGB ( 0 , 0 , 255 ) ;
}
return 1 ;
}
int addrtodelete ; // This is a very ugly hackish method of doing this
int cheatwasdeleted ; // but it works and that is all that matters here.
int DeleteCheatCallB ( char * name , uint32 a , uint8 v , int compare , int s , int type , void * data ) { //mbg merge 6/29/06 - added arg
if ( cheatwasdeleted = = - 1 ) return 1 ;
cheatwasdeleted + + ;
if ( a = = addrtodelete ) {
FCEUI_DelCheat ( cheatwasdeleted - 1 ) ;
cheatwasdeleted = - 1 ;
return 0 ;
}
return 1 ;
}
// ################################## Start of SP CODE ###########################
void dumpToFile ( const char * buffer , unsigned int size )
{
char name [ 257 ] = { 0 } ;
OPENFILENAME ofn ;
memset ( & ofn , 0 , sizeof ( ofn ) ) ;
ofn . lStructSize = sizeof ( ofn ) ;
ofn . hInstance = fceu_hInstance ;
ofn . lpstrTitle = " Save to file ... " ;
ofn . lpstrFilter = " All files (*.*) \0 *.* \0 " ;
ofn . lpstrFile = name ;
ofn . nMaxFile = 256 ;
ofn . Flags = OFN_EXPLORER | OFN_HIDEREADONLY ;
if ( GetOpenFileName ( & ofn ) )
{
FILE * memfile = fopen ( ofn . lpstrFile , " wb " ) ;
if ( ! memfile | | fwrite ( buffer , 1 , size , memfile ) ! = size )
{
MessageBox ( 0 , " Saving failed " , " Error " , 0 ) ;
}
if ( memfile )
fclose ( memfile ) ;
}
}
void FreezeRam ( int address , int mode , int final ) {
// mode: -1 == Unfreeze; 0 == Toggle; 1 == Freeze
// ################################## End of SP CODE ###########################
if ( ( address < 0x2000 ) | | ( ( address > = 0x6000 ) & & ( address < = 0x7FFF ) ) ) {
addrtodelete = address ;
cheatwasdeleted = 0 ;
// ################################## Start of SP CODE ###########################
if ( mode = = 0 | | mode = = - 1 )
{
//mbg merge 6/29/06 - added argument
FCEUI_ListCheats ( DeleteCheatCallB , 0 ) ;
if ( mode = = 0 & & cheatwasdeleted ! = - 1 ) FCEUI_AddCheat ( " " , address , GetMem ( address ) , - 1 , 1 ) ;
}
else
{
//mbg merge 6/29/06 - added argument
FCEUI_ListCheats ( DeleteCheatCallB , 0 ) ;
FCEUI_AddCheat ( " " , address , GetMem ( address ) , - 1 , 1 ) ;
}
// ################################## End of SP CODE ###########################
/*if (final)
{
if ( hCheat ) RedoCheatsLB ( hCheat ) ;
UpdateColorTable ( ) ;
} */
//mbg merge 6/29/06 - WTF
}
}
//input is expected to be an ASCII string
void InputData ( char * input ) {
//CursorEndAddy = -1;
int addr , i , j , datasize = 0 ;
unsigned char * data ;
char inputc ;
//char str[100];
//mbg merge 7/18/06 added cast:
data = ( uint8 * ) malloc ( strlen ( input ) ) ; //it can't be larger than the input string, so use that as the size
for ( i = 0 ; input [ i ] ! = 0 ; i + + ) {
if ( ! EditingText ) {
inputc = - 1 ;
if ( ( input [ i ] > = ' a ' ) & & ( input [ i ] < = ' f ' ) ) inputc = input [ i ] - ( ' a ' - 0xA ) ;
if ( ( input [ i ] > = ' A ' ) & & ( input [ i ] < = ' F ' ) ) inputc = input [ i ] - ( ' A ' - 0xA ) ;
if ( ( input [ i ] > = ' 0 ' ) & & ( input [ i ] < = ' 9 ' ) ) inputc = input [ i ] - ' 0 ' ;
if ( inputc = = - 1 ) continue ;
if ( TempData ! = - 1 ) {
data [ datasize + + ] = inputc | ( TempData < < 4 ) ;
TempData = - 1 ;
} else {
TempData = inputc ;
}
} else {
for ( j = 0 ; j < 256 ; j + + ) if ( chartable [ j ] = = input [ i ] ) break ;
if ( j = = 256 ) continue ;
data [ datasize + + ] = j ;
}
}
if ( datasize + CursorStartAddy > = MaxSize ) { //too big
datasize = MaxSize - CursorStartAddy ;
//free(data);
//return;
}
//its possible for this loop not to get executed at all
// for(addr = CursorStartAddy;addr < datasize+CursorStartAddy;addr++){
//sprintf(str,"datasize = %d",datasize);
//MessageBox(hMemView,str, "debug", MB_OK);
for ( i = 0 ; i < datasize ; i + + ) {
addr = CursorStartAddy + i ;
if ( EditingMode = = 0 ) BWrite [ addr ] ( addr , data [ i ] ) ;
if ( EditingMode = = 1 ) {
addr & = 0x3FFF ;
if ( addr < 0x2000 ) VPage [ addr > > 10 ] [ addr ] = data [ i ] ; //todo: detect if this is vrom and turn it red if so
if ( ( addr > 0x2000 ) & & ( addr < 0x3F00 ) ) vnapage [ ( addr > > 10 ) & 0x3 ] [ addr & 0x3FF ] = data [ i ] ; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
if ( ( addr > 0x3F00 ) & & ( addr < 0x3FFF ) ) PALRAM [ addr & 0x1F ] = data [ i ] ;
}
if ( EditingMode = = 2 ) {
ApplyPatch ( addr , datasize , data ) ;
break ;
}
}
CursorStartAddy + = datasize ;
CursorEndAddy = - 1 ;
if ( CursorStartAddy > = MaxSize ) CursorStartAddy = MaxSize - 1 ;
free ( data ) ;
ChangeMemViewFocus ( EditingMode , CursorStartAddy , - 1 ) ;
UpdateColorTable ( ) ;
return ;
}
/*
if ( ! EditingText ) {
if ( ( input > = ' a ' ) & & ( input < = ' f ' ) ) input - = ( ' a ' - 0xA ) ;
if ( ( input > = ' A ' ) & & ( input < = ' F ' ) ) input - = ( ' A ' - 0xA ) ;
if ( ( input > = ' 0 ' ) & & ( input < = ' 9 ' ) ) input - = ' 0 ' ;
if ( input > 0xF ) return ;
if ( TempData ! = - 1 ) {
addr = CursorStartAddy ;
data = input | ( TempData < < 4 ) ;
if ( EditingMode = = 0 ) BWrite [ addr ] ( addr , data ) ;
if ( EditingMode = = 1 ) {
addr & = 0x3FFF ;
if ( addr < 0x2000 ) VPage [ addr > > 10 ] [ addr ] = data ; //todo: detect if this is vrom and turn it red if so
if ( ( addr > 0x2000 ) & & ( addr < 0x3F00 ) ) vnapage [ ( addr > > 10 ) & 0x3 ] [ addr & 0x3FF ] = data ; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct?
if ( ( addr > 0x3F00 ) & & ( addr < 0x3FFF ) ) PALRAM [ addr & 0x1F ] = data ;
}
if ( EditingMode = = 2 ) ApplyPatch ( addr , 1 , ( uint8 * ) & data ) ;
CursorStartAddy + + ;
TempData = - 1 ;
} else {
TempData = input ;
}
} else {
for ( i = 0 ; i < 256 ; i + + ) if ( chartable [ i ] = = input ) break ;
if ( i = = 256 ) return ;
addr = CursorStartAddy ;
data = i ;
if ( EditingMode = = 0 ) BWrite [ addr ] ( addr , data ) ;
if ( EditingMode = = 2 ) ApplyPatch ( addr , 1 , ( uint8 * ) & data ) ;
CursorStartAddy + + ;
}
*/
void ChangeMemViewFocus ( int newEditingMode , int StartOffset , int EndOffset ) {
SCROLLINFO si ;
if ( GI - > type = = GIT_NSF ) {
FCEUD_PrintError ( " Sorry, you can't yet use the Memory Viewer with NSFs. " ) ;
return ;
}
if ( ! hMemView ) DoMemView ( ) ;
if ( EditingMode ! = newEditingMode )
MemViewCallB ( hMemView , WM_COMMAND , 300 + newEditingMode , 0 ) ; //let the window handler change this for us
if ( ( EndOffset = = StartOffset ) | | ( EndOffset = = - 1 ) ) {
CursorEndAddy = - 1 ;
CursorStartAddy = StartOffset ;
} else {
CursorStartAddy = min ( StartOffset , EndOffset ) ;
CursorEndAddy = max ( StartOffset , EndOffset ) ;
}
if ( min ( StartOffset , EndOffset ) > = MaxSize ) return ; //this should never happen
if ( StartOffset < CurOffset ) {
CurOffset = ( StartOffset / 16 ) * 16 ;
}
if ( StartOffset > = CurOffset + DataAmount ) {
CurOffset = ( ( StartOffset / 16 ) * 16 ) - DataAmount + 0x10 ;
if ( CurOffset < 0 ) CurOffset = 0 ;
}
SetFocus ( hMemView ) ;
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_POS ;
si . cbSize = sizeof ( SCROLLINFO ) ;
si . nPos = CurOffset / 16 ;
SetScrollInfo ( hMemView , SB_VERT , & si , TRUE ) ;
UpdateCaption ( ) ;
UpdateColorTable ( ) ;
return ;
}
int GetHexScreenCoordx ( int offset ) {
return ( 8 * MemFontWidth ) + ( ( offset % 16 ) * 3 * MemFontWidth ) ; //todo: add Curoffset to this and to below function
}
int GetHexScreenCoordy ( int offset ) {
return ( offset / 16 ) * MemFontHeight ;
}
//0000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
//if the mouse is in the text field, this function will set AddyWasText to 1 otherwise it is 0
//if the mouse wasn't in any range, this function returns -1
int GetAddyFromCoord ( int x , int y ) {
if ( y < 0 ) y = 0 ;
if ( x < 8 * MemFontWidth ) x = 8 * MemFontWidth + 1 ;
if ( y > DataAmount * MemFontHeight ) return - 1 ;
if ( x < 55 * MemFontWidth ) {
AddyWasText = 0 ;
return ( ( y / MemFontHeight ) * 16 ) + ( ( x - ( 8 * MemFontWidth ) ) / ( 3 * MemFontWidth ) ) + CurOffset ;
}
if ( ( x > 59 * MemFontWidth ) & & ( x < 75 * MemFontWidth ) ) {
AddyWasText = 1 ;
return ( ( y / MemFontHeight ) * 16 ) + ( ( x - ( 59 * MemFontWidth ) ) / ( MemFontWidth ) ) + CurOffset ;
}
return - 1 ;
}
void AutoScrollFromCoord ( int x , int y ) {
SCROLLINFO si ;
if ( y < 0 ) {
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_ALL ;
si . cbSize = sizeof ( SCROLLINFO ) ;
GetScrollInfo ( hMemView , SB_VERT , & si ) ;
si . nPos + = y / 16 ;
if ( si . nPos < si . nMin ) si . nPos = si . nMin ;
if ( ( si . nPos + si . nPage ) > si . nMax ) si . nPos = si . nMax - si . nPage ;
CurOffset = si . nPos * 16 ;
SetScrollInfo ( hMemView , SB_VERT , & si , TRUE ) ;
return ;
}
if ( y > ClientHeight ) {
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_ALL ;
si . cbSize = sizeof ( SCROLLINFO ) ;
GetScrollInfo ( hMemView , SB_VERT , & si ) ;
si . nPos - = ( ClientHeight - y ) / 16 ;
if ( si . nPos < si . nMin ) si . nPos = si . nMin ;
if ( ( si . nPos + si . nPage ) > si . nMax ) si . nPos = si . nMax - si . nPage ;
CurOffset = si . nPos * 16 ;
SetScrollInfo ( hMemView , SB_VERT , & si , TRUE ) ;
return ;
}
}
void KillMemView ( ) {
DeleteObject ( hMemFont ) ;
ReleaseDC ( hMemView , mDC ) ;
DestroyWindow ( hMemView ) ;
UnregisterClass ( " MEMVIEW " , fceu_hInstance ) ;
hMemView = 0 ;
return ;
}
LRESULT CALLBACK MemViewCallB ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam ) {
HDC hdc ;
HGLOBAL hGlobal ;
PTSTR pGlobal ;
HMENU hMenu ;
MENUITEMINFO MenuInfo ;
POINT point ;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
SCROLLINFO si ;
int x , y , i , j ;
char c [ 2 ] ;
char str [ 100 ] ;
// ################################## Start of SP CODE ###########################
extern int debuggerWasActive ;
// ################################## End of SP CODE ###########################
switch ( message ) {
case WM_ENTERMENULOOP : StopSound ( ) ; return 0 ;
case WM_INITMENUPOPUP :
if ( undo_list ! = 0 ) EnableMenuItem ( GetMenu ( hMemView ) , 200 , MF_BYCOMMAND | MF_ENABLED ) ;
else EnableMenuItem ( GetMenu ( hMemView ) , 200 , MF_BYCOMMAND | MF_GRAYED ) ;
if ( TableFileLoaded ) EnableMenuItem ( GetMenu ( hMemView ) , 103 , MF_BYCOMMAND | MF_ENABLED ) ;
else EnableMenuItem ( GetMenu ( hMemView ) , 103 , MF_BYCOMMAND | MF_GRAYED ) ;
return 0 ;
case WM_CREATE :
// ################################## Start of SP CODE ###########################
debuggerWasActive = 1 ;
// ################################## End of SP CODE ###########################
mDC = GetDC ( hwnd ) ;
HDataDC = mDC ; //deleteme
hMemFont = CreateFont ( 13 , 8 , /*Height,Width*/
0 , 0 , /*escapement,orientation*/
400 , FALSE , FALSE , FALSE , /*weight, italic,, underline, strikeout*/
ANSI_CHARSET , OUT_DEVICE_PRECIS , CLIP_MASK , /*charset, precision, clipping*/
DEFAULT_QUALITY , DEFAULT_PITCH , /*quality, and pitch*/
" Courier " ) ; /*font name*/
SelectObject ( HDataDC , hMemFont ) ;
SetTextAlign ( HDataDC , TA_UPDATECP | TA_TOP | TA_LEFT ) ;
GetTextMetrics ( HDataDC , & tm ) ;
MemFontWidth = 8 ;
MemFontHeight = 13 ;
MaxSize = 0x10000 ;
//Allocate Memory for color lists
DataAmount = 0x100 ;
//mbg merge 7/18/06 added casts:
TextColorList = ( COLORREF * ) malloc ( DataAmount * sizeof ( COLORREF ) ) ;
BGColorList = ( COLORREF * ) malloc ( DataAmount * sizeof ( COLORREF ) ) ;
OldValues = ( int * ) malloc ( DataAmount * sizeof ( int ) ) ;
EditingText = EditingMode = CurOffset = 0 ;
//set the default table
UnloadTableFile ( ) ;
UpdateColorTable ( ) ; //draw it
updateBookmarkMenus ( GetSubMenu ( GetMenu ( hwnd ) , 3 ) ) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint ( hwnd , & ps ) ;
EndPaint ( hwnd , & ps ) ;
UpdateMemoryView ( 1 ) ;
return 0 ;
case WM_VSCROLL :
StopSound ( ) ;
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_ALL ;
si . cbSize = sizeof ( SCROLLINFO ) ;
GetScrollInfo ( hwnd , SB_VERT , & si ) ;
switch ( LOWORD ( wParam ) ) {
case SB_ENDSCROLL :
case SB_TOP :
case SB_BOTTOM : break ;
case SB_LINEUP : si . nPos - - ; break ;
case SB_LINEDOWN : si . nPos + + ; break ;
case SB_PAGEUP : si . nPos - = si . nPage ; break ;
case SB_PAGEDOWN : si . nPos + = si . nPage ; break ;
case SB_THUMBPOSITION : //break;
case SB_THUMBTRACK : si . nPos = si . nTrackPos ; break ;
}
if ( si . nPos < si . nMin ) si . nPos = si . nMin ;
if ( ( si . nPos + ( int ) si . nPage ) > si . nMax ) si . nPos = si . nMax - si . nPage ; //mbg merge 7/18/06 added cast
CurOffset = si . nPos * 16 ;
SetScrollInfo ( hwnd , SB_VERT , & si , TRUE ) ;
UpdateColorTable ( ) ;
return 0 ;
case WM_CHAR :
if ( GetKeyState ( VK_CONTROL ) & 0x8000 ) return 0 ; //prevents input when pressing ctrl+c
c [ 0 ] = ( char ) ( wParam & 0xFF ) ;
c [ 1 ] = 0 ;
//sprintf(str,"c[0] = %c c[1] = %c",c[0],c[1]);
//MessageBox(hMemView,str, "debug", MB_OK);
InputData ( c ) ;
UpdateColorTable ( ) ;
UpdateCaption ( ) ;
return 0 ;
case WM_KEYDOWN :
//if((wParam >= 0x30) && (wParam <= 0x39))InputData(wParam-0x30);
//if((wParam >= 0x41) && (wParam <= 0x46))InputData(wParam-0x41+0xA);
/*if(!((GetKeyState(VK_LSHIFT) & 0x8000) || (GetKeyState(VK_RSHIFT) & 0x8000))){
//MessageBox(hMemView,"nobody", "mouse wheel dance!", MB_OK);
CursorShiftPoint = - 1 ;
}
if ( ( ( GetKeyState ( VK_LSHIFT ) & 0x8000 ) | | ( GetKeyState ( VK_RSHIFT ) & 0x8000 ) ) & &
( CursorShiftPoint = = - 1 ) ) {
CursorShiftPoint = CursorStartAddy ;
//MessageBox(hMemView,"somebody", "mouse wheel dance!", MB_OK);
} */
if ( GetKeyState ( VK_CONTROL ) & 0x8000 ) {
// ################################## Start of SP CODE ###########################
if ( wParam > = ' 0 ' & & wParam < = ' 9 ' )
{
int newValue = handleBookmarkMenu ( wParam - ' 0 ' ) ;
if ( newValue ! = - 1 )
{
CurOffset = newValue ;
CursorEndAddy = - 1 ;
CursorStartAddy = hexBookmarks [ wParam - ' 0 ' ] . address ;
UpdateColorTable ( ) ;
}
}
// ################################## End of SP CODE ###########################
switch ( wParam ) {
case 0x43 : //Ctrl+C
MemViewCallB ( hMemView , WM_COMMAND , 201 , 0 ) ; //recursion at work
return 0 ;
case 0x56 : //Ctrl+V
MemViewCallB ( hMemView , WM_COMMAND , 202 , 0 ) ;
return 0 ;
case 0x5a : //Ctrl+Z
UndoLastPatch ( ) ;
}
}
//if(CursorShiftPoint == -1){
if ( wParam = = VK_LEFT ) CursorStartAddy - - ;
if ( wParam = = VK_RIGHT ) CursorStartAddy + + ;
if ( wParam = = VK_UP ) CursorStartAddy - = 16 ;
if ( wParam = = VK_DOWN ) CursorStartAddy + = 16 ;
/*} else {
if ( wParam = = VK_LEFT ) CursorShiftPoint - - ;
if ( wParam = = VK_RIGHT ) CursorShiftPoint + + ;
if ( wParam = = VK_UP ) CursorShiftPoint - = 16 ;
if ( wParam = = VK_DOWN ) CursorShiftPoint + = 16 ;
if ( CursorShiftPoint < CursorStartAddy ) {
if ( CursorEndAddy = = - 1 ) CursorEndAddy = CursorStartAddy ;
CursorStartAddy = CursorShiftPoint ;
}
//if(CursorShiftPoint > CursorEndAddy)CursorEndAddy = CursorShiftPoint;
} */
//if(CursorStartAddy == CursorEndAddy)CursorEndAddy = -1;
if ( CursorStartAddy < 0 ) CursorStartAddy = 0 ;
if ( CursorStartAddy > = MaxSize ) CursorStartAddy = MaxSize - 1 ; //todo: fix this up when I add support for editing more stuff
if ( ( wParam = = VK_DOWN ) | | ( wParam = = VK_UP ) | |
( wParam = = VK_RIGHT ) | | ( wParam = = VK_LEFT ) ) {
CursorEndAddy = - 1 ;
TempData = - 1 ;
if ( CursorStartAddy < CurOffset ) CurOffset = ( CursorStartAddy / 16 ) * 16 ;
if ( CursorStartAddy > CurOffset + DataAmount - 0x10 ) CurOffset = ( ( CursorStartAddy - DataAmount + 0x10 ) / 16 ) * 16 ;
}
if ( wParam = = VK_PRIOR ) CurOffset - = DataAmount ;
if ( wParam = = VK_NEXT ) CurOffset + = DataAmount ;
if ( CurOffset < 0 ) CurOffset = 0 ;
if ( CurOffset > = MaxSize ) CurOffset = MaxSize - 1 ;
/*
if ( ( wParam = = VK_PRIOR ) | | ( wParam = = VK_NEXT ) ) {
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_ALL ;
si . cbSize = sizeof ( SCROLLINFO ) ;
GetScrollInfo ( hwnd , SB_VERT , & si ) ;
if ( wParam = = VK_PRIOR ) si . nPos - = si . nPage ;
if ( wParam = = VK_NEXT ) si . nPos + = si . nPage ;
if ( si . nPos < si . nMin ) si . nPos = si . nMin ;
if ( ( si . nPos + si . nPage ) > si . nMax ) si . nPos = si . nMax - si . nPage ;
CurOffset = si . nPos * 16 ;
}
*/
//This updates the scroll bar to curoffset
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_POS ;
si . cbSize = sizeof ( SCROLLINFO ) ;
si . nPos = CurOffset / 16 ;
SetScrollInfo ( hwnd , SB_VERT , & si , TRUE ) ;
UpdateColorTable ( ) ;
UpdateCaption ( ) ;
return 0 ;
/* case WM_KEYUP:
if ( ( wParam = = VK_LSHIFT ) | | ( wParam = = VK_RSHIFT ) ) {
CursorShiftPoint = - 1 ;
}
return 0 ; */
case WM_LBUTTONDOWN :
//CursorShiftPoint = -1;
SetCapture ( hwnd ) ;
lbuttondown = 1 ;
x = GET_X_LPARAM ( lParam ) ;
y = GET_Y_LPARAM ( lParam ) ;
if ( ( i = GetAddyFromCoord ( x , y ) ) = = - 1 ) return 0 ;
EditingText = AddyWasText ;
lbuttondownx = x ;
lbuttondowny = y ;
CursorStartAddy = CursorDragPoint = i ;
CursorEndAddy = - 1 ;
UpdateCaption ( ) ;
UpdateColorTable ( ) ;
return 0 ;
case WM_MOUSEMOVE :
mousex = x = GET_X_LPARAM ( lParam ) ;
mousey = y = GET_Y_LPARAM ( lParam ) ;
if ( lbuttondown ) {
AutoScrollFromCoord ( x , y ) ;
i = GetAddyFromCoord ( x , y ) ;
if ( i > = MaxSize ) i = MaxSize - 1 ;
EditingText = AddyWasText ;
if ( i ! = - 1 ) {
CursorStartAddy = min ( i , CursorDragPoint ) ;
CursorEndAddy = max ( i , CursorDragPoint ) ;
if ( CursorEndAddy = = CursorStartAddy ) CursorEndAddy = - 1 ;
}
UpdateCaption ( ) ;
UpdateColorTable ( ) ;
}
//sprintf(str,"%d %d",mousex, mousey);
//SetWindowText(hMemView,str);
return 0 ;
case WM_LBUTTONUP :
lbuttondown = 0 ;
if ( CursorEndAddy = = CursorStartAddy ) CursorEndAddy = - 1 ;
if ( ( CursorEndAddy < CursorStartAddy ) & & ( CursorEndAddy ! = - 1 ) ) { //this reverses them if they're not right
i = CursorStartAddy ;
CursorStartAddy = CursorEndAddy ;
CursorEndAddy = i ;
}
UpdateCaption ( ) ;
UpdateColorTable ( ) ;
ReleaseCapture ( ) ;
return 0 ;
case WM_CONTEXTMENU :
point . x = x = GET_X_LPARAM ( lParam ) ;
point . y = y = GET_Y_LPARAM ( lParam ) ;
ScreenToClient ( hMemView , & point ) ;
mousex = point . x ;
mousey = point . y ;
j = GetAddyFromCoord ( mousex , mousey ) ;
//sprintf(str,"x = %d, y = %d, j = %d",mousex,mousey,j);
//MessageBox(hMemView,str, "mouse wheel dance!", MB_OK);
hMenu = CreatePopupMenu ( ) ;
for ( i = 0 ; i < POPUPNUM ; i + + ) {
if ( ( j > = popupmenu [ i ] . minaddress ) & & ( j < = popupmenu [ i ] . maxaddress )
& & ( EditingMode = = popupmenu [ i ] . editingmode ) ) {
memset ( & MenuInfo , 0 , sizeof ( MENUITEMINFO ) ) ;
switch ( popupmenu [ i ] . id ) { //this will set the text for the menu dynamically based on the id
// ################################## Start of SP CODE ###########################
case 1 :
{
HMENU sub = CreatePopupMenu ( ) ;
AppendMenu ( hMenu , MF_POPUP | MF_STRING , ( UINT ) sub , " Freeze / Unfreeze Address " ) ;
AppendMenu ( sub , MF_STRING , 1 , " Toggle state " ) ;
AppendMenu ( sub , MF_STRING , 50 , " Freeze " ) ;
AppendMenu ( sub , MF_STRING , 51 , " Unfreeze " ) ;
AppendMenu ( sub , MF_SEPARATOR , 52 , " - " ) ;
AppendMenu ( sub , MF_STRING , 53 , " Unfreeze all " ) ;
continue ;
}
// ################################## End of SP CODE ###########################
case 2 : //We want this to give the address to add the read breakpoint for
if ( ( j < = CursorEndAddy ) & & ( j > = CursorStartAddy ) )
sprintf ( str , " Add Read Breakpoint For Address 0x%04X-0x%04X " , CursorStartAddy , CursorEndAddy ) ;
else
sprintf ( str , " Add Read Breakpoint For Address 0x%04X " , j ) ;
popupmenu [ i ] . text = str ;
break ;
case 3 :
if ( ( j < = CursorEndAddy ) & & ( j > = CursorStartAddy ) )
sprintf ( str , " Add Write Breakpoint For Address 0x%04X-0x%04X " , CursorStartAddy , CursorEndAddy ) ;
else
sprintf ( str , " Add Write Breakpoint For Address 0x%04X " , j ) ;
popupmenu [ i ] . text = str ;
break ;
case 4 :
if ( ( j < = CursorEndAddy ) & & ( j > = CursorStartAddy ) )
sprintf ( str , " Add Execute Breakpoint For Address 0x%04X-0x%04X " , CursorStartAddy , CursorEndAddy ) ;
else
sprintf ( str , " Add Execute Breakpoint For Address 0x%04X " , j ) ;
popupmenu [ i ] . text = str ;
break ;
}
MenuInfo . cbSize = sizeof ( MENUITEMINFO ) ;
MenuInfo . fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA ;
MenuInfo . fType = MF_STRING ;
MenuInfo . dwTypeData = popupmenu [ i ] . text ;
MenuInfo . cch = strlen ( popupmenu [ i ] . text ) ;
MenuInfo . wID = popupmenu [ i ] . id ;
InsertMenuItem ( hMenu , i + 1 , 1 , & MenuInfo ) ;
}
}
//InsertMenu(hMenu, 1, MF_STRING, 892, "Test");
if ( i ! = 0 ) i = TrackPopupMenuEx ( hMenu , TPM_RETURNCMD , x , y , hMemView , NULL ) ;
switch ( i ) {
case 1 : //1 = Freeze Ram Address
// ################################## Start of SP CODE ###########################
{
int n ;
for ( n = CursorStartAddy ; ( CursorEndAddy = = - 1 & & n = = CursorStartAddy ) | | n < = CursorEndAddy ; n + + )
{
FreezeRam ( n , 0 , n = = CursorEndAddy ) ;
}
break ;
}
case 50 :
{
int n ;
for ( n = CursorStartAddy ; ( CursorEndAddy = = - 1 & & n = = CursorStartAddy ) | | n < = CursorEndAddy ; n + + )
{
FreezeRam ( n , 1 , n = = CursorEndAddy ) ;
}
break ;
}
case 51 :
{
int n ;
for ( n = CursorStartAddy ; ( CursorEndAddy = = - 1 & & n = = CursorStartAddy ) | | n < = CursorEndAddy ; n + + )
{
FreezeRam ( n , - 1 , n = = CursorEndAddy ) ;
}
break ;
}
case 53 :
{
int n ;
for ( n = 0 ; n < 0x2000 ; n + + )
{
FreezeRam ( n , - 1 , 0 ) ;
}
for ( n = 0x6000 ; n < 0x8000 ; n + + )
{
FreezeRam ( n , - 1 , n = = 0x7FFF ) ;
}
break ;
}
// ################################## End of SP CODE ###########################
break ;
case 2 : //2 = Add Read Breakpoint
watchpoint [ numWPs ] . flags = WP_E | WP_R ;
if ( EditingMode = = 1 ) watchpoint [ numWPs ] . flags | = BT_P ;
if ( ( j < = CursorEndAddy ) & & ( j > = CursorStartAddy ) ) {
watchpoint [ numWPs ] . address = CursorStartAddy ;
watchpoint [ numWPs ] . endaddress = CursorEndAddy ;
}
else {
watchpoint [ numWPs ] . address = j ;
watchpoint [ numWPs ] . endaddress = 0 ;
}
numWPs + + ;
// ################################## Start of SP CODE ###########################
{ extern int myNumWPs ;
myNumWPs + + ; }
// ################################## End of SP CODE ###########################
if ( hDebug ) AddBreakList ( ) ;
else DoDebug ( 0 ) ;
break ;
case 3 : //3 = Add Write Breakpoint
watchpoint [ numWPs ] . flags = WP_E | WP_W ;
if ( EditingMode = = 1 ) watchpoint [ numWPs ] . flags | = BT_P ;
if ( ( j < = CursorEndAddy ) & & ( j > = CursorStartAddy ) ) {
watchpoint [ numWPs ] . address = CursorStartAddy ;
watchpoint [ numWPs ] . endaddress = CursorEndAddy ;
}
else {
watchpoint [ numWPs ] . address = j ;
watchpoint [ numWPs ] . endaddress = 0 ;
}
numWPs + + ;
// ################################## Start of SP CODE ###########################
{ extern int myNumWPs ;
myNumWPs + + ; }
// ################################## End of SP CODE ###########################
if ( hDebug ) AddBreakList ( ) ;
else DoDebug ( 0 ) ;
break ;
case 4 : //4 = Add Execute Breakpoint
watchpoint [ numWPs ] . flags = WP_E | WP_X ;
if ( ( j < = CursorEndAddy ) & & ( j > = CursorStartAddy ) ) {
watchpoint [ numWPs ] . address = CursorStartAddy ;
watchpoint [ numWPs ] . endaddress = CursorEndAddy ;
}
else {
watchpoint [ numWPs ] . address = j ;
watchpoint [ numWPs ] . endaddress = 0 ;
}
numWPs + + ;
// ################################## Start of SP CODE ###########################
{ extern int myNumWPs ;
myNumWPs + + ; }
// ################################## End of SP CODE ###########################
if ( hDebug ) AddBreakList ( ) ;
else DoDebug ( 0 ) ;
break ;
case 5 : //5 = Go Here In Rom File
ChangeMemViewFocus ( 2 , GetNesFileAddress ( j ) , - 1 ) ;
break ;
case 6 : //6 = Create GG Code
SetGGConvFocus ( j , GetMem ( j ) ) ;
break ;
// ################################## Start of SP CODE ###########################
case 20 :
{
if ( toggleBookmark ( hwnd , CursorStartAddy ) )
{
MessageBox ( hDebug , " Can't set more than 64 breakpoints " , " Error " , MB_OK | MB_ICONERROR ) ;
}
else
{
updateBookmarkMenus ( GetSubMenu ( GetMenu ( hwnd ) , 3 ) ) ;
UpdateColorTable ( ) ;
}
}
break ;
// ################################## End of SP CODE ###########################
}
//6 = Create GG Code
return 0 ;
case WM_MBUTTONDOWN :
x = GET_X_LPARAM ( lParam ) ;
y = GET_Y_LPARAM ( lParam ) ;
i = GetAddyFromCoord ( x , y ) ;
if ( i = = - 1 ) return 0 ;
// ################################## Start of SP CODE ###########################
FreezeRam ( i , 0 , 1 ) ;
// ################################## End of SP CODE ###########################
return 0 ;
case WM_MOUSEWHEEL :
i = ( short ) HIWORD ( wParam ) ; ///WHEEL_DELTA;
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . fMask = SIF_ALL ;
si . cbSize = sizeof ( SCROLLINFO ) ;
GetScrollInfo ( hwnd , SB_VERT , & si ) ;
if ( i < 0 ) si . nPos + = si . nPage ;
if ( i > 0 ) si . nPos - = si . nPage ;
if ( si . nPos < si . nMin ) si . nPos = si . nMin ;
if ( ( si . nPos + ( int ) si . nPage ) > si . nMax ) si . nPos = si . nMax - si . nPage ; //added cast
CurOffset = si . nPos * 16 ;
SetScrollInfo ( hwnd , SB_VERT , & si , TRUE ) ;
UpdateColorTable ( ) ;
return 0 ;
case WM_SIZE :
StopSound ( ) ;
ClientHeight = HIWORD ( lParam ) ;
if ( DataAmount ! = ( ( ClientHeight / MemFontHeight ) * 16 ) ) {
DataAmount = ( ( ClientHeight / MemFontHeight ) * 16 ) ;
if ( DataAmount + CurOffset > MaxSize ) CurOffset = MaxSize - DataAmount ;
//mbg merge 7/18/06 added casts:
TextColorList = ( COLORREF * ) realloc ( TextColorList , DataAmount * sizeof ( COLORREF ) ) ;
BGColorList = ( COLORREF * ) realloc ( BGColorList , DataAmount * sizeof ( COLORREF ) ) ;
OldValues = ( int * ) realloc ( OldValues , ( DataAmount ) * sizeof ( int ) ) ;
for ( i = 0 ; i < DataAmount ; i + + ) OldValues [ i ] = - 1 ;
}
//Set vertical scroll bar range and page size
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . cbSize = sizeof ( si ) ;
si . fMask = ( SIF_RANGE | SIF_PAGE ) ;
si . nMin = 0 ;
si . nMax = MaxSize / 16 ;
si . nPage = ClientHeight / MemFontHeight ;
SetScrollInfo ( hwnd , SB_VERT , & si , TRUE ) ;
UpdateColorTable ( ) ;
return 0 ;
case WM_COMMAND :
StopSound ( ) ;
// ################################## Start of SP CODE ###########################
if ( wParam > = 30 & & wParam < = 39 )
{
int newValue = handleBookmarkMenu ( wParam - 30 ) ;
if ( newValue ! = - 1 )
{
CurOffset = newValue ;
CursorEndAddy = - 1 ;
CursorStartAddy = hexBookmarks [ wParam - 30 ] . address ;
UpdateColorTable ( ) ;
}
}
else if ( wParam = = 400 )
{
removeAllBookmarks ( GetSubMenu ( GetMenu ( hwnd ) , 3 ) ) ;
UpdateColorTable ( ) ;
}
else if ( wParam = = 600 )
{
MessageBox ( 0 , " " , " " , 0 ) ;
}
// ################################## End of SP CODE ###########################
switch ( wParam )
{
case 100 :
FlushUndoBuffer ( ) ;
iNesSave ( ) ;
UpdateColorTable ( ) ;
return 0 ;
case 101 :
return 0 ;
case 102 :
if ( ( i = LoadTableFile ( ) ) ! = - 1 ) {
sprintf ( str , " Error Loading Table File At Line %d " , i ) ;
MessageBox ( hMemView , str , " error " , MB_OK ) ;
}
UpdateColorTable ( ) ;
return 0 ;
case 103 :
UnloadTableFile ( ) ;
UpdateColorTable ( ) ;
return 0 ;
// ################################## Start of SP CODE ###########################
case 104 :
{
char bar [ 0x800 ] ;
unsigned int i ;
for ( i = 0 ; i < sizeof ( bar ) ; i + + ) bar [ i ] = GetMem ( i ) ;
dumpToFile ( bar , sizeof ( bar ) ) ;
return 0 ;
}
case 105 :
{
char bar [ 0x4000 ] ;
unsigned int i ;
for ( i = 0 ; i < sizeof ( bar ) ; i + + )
{
// bar[i] = GetPPUMem(i);
i & = 0x3FFF ;
if ( i < 0x2000 ) bar [ i ] = VPage [ ( i ) > > 10 ] [ ( i ) ] ;
else if ( i < 0x3F00 ) bar [ i ] = vnapage [ ( i > > 10 ) & 0x3 ] [ i & 0x3FF ] ;
else bar [ i ] = PALRAM [ i & 0x1F ] ;
}
dumpToFile ( bar , sizeof ( bar ) ) ;
return 0 ;
}
// ################################## End of SP CODE ###########################
case 200 : //undo
UndoLastPatch ( ) ;
return 0 ;
case 201 : //copy
if ( CursorEndAddy = = - 1 ) i = 1 ;
else i = CursorEndAddy - CursorStartAddy + 1 ;
hGlobal = GlobalAlloc ( GHND ,
( i * 2 ) + 1 ) ; //i*2 is two characters per byte, plus terminating null
pGlobal = ( char * ) GlobalLock ( hGlobal ) ; //mbg merge 7/18/06 added cast
if ( ! EditingText ) {
for ( j = 0 ; j < i ; j + + ) {
str [ 0 ] = 0 ;
sprintf ( str , " %02X " , GetMemViewData ( j + CursorStartAddy ) ) ;
strcat ( pGlobal , str ) ;
}
} else {
for ( j = 0 ; j < i ; j + + ) {
str [ 0 ] = 0 ;
sprintf ( str , " %c " , chartable [ GetMemViewData ( j + CursorStartAddy ) ] ) ;
strcat ( pGlobal , str ) ;
}
}
GlobalUnlock ( hGlobal ) ;
OpenClipboard ( hwnd ) ;
EmptyClipboard ( ) ;
SetClipboardData ( CF_TEXT , hGlobal ) ;
CloseClipboard ( ) ;
return 0 ;
case 202 : //paste
OpenClipboard ( hwnd ) ;
hGlobal = GetClipboardData ( CF_TEXT ) ;
if ( hGlobal = = NULL ) {
CloseClipboard ( ) ;
return 0 ;
}
pGlobal = ( char * ) GlobalLock ( hGlobal ) ; //mbg merge 7/18/06 added cast
//for(i = 0;pGlobal[i] != 0;i++){
InputData ( pGlobal ) ;
//}
GlobalUnlock ( hGlobal ) ;
CloseClipboard ( ) ;
return 0 ;
return 0 ;
case 203 : //find
OpenFindDialog ( ) ;
return 0 ;
case 300 :
case 301 :
case 302 :
EditingMode = wParam - 300 ;
for ( i = 0 ; i < 3 ; i + + ) {
if ( EditingMode = = i ) CheckMenuItem ( GetMenu ( hMemView ) , 300 + i , MF_CHECKED ) ;
else CheckMenuItem ( GetMenu ( hMemView ) , 300 + i , MF_UNCHECKED ) ;
}
if ( EditingMode = = 0 ) MaxSize = 0x10000 ;
if ( EditingMode = = 1 ) MaxSize = 0x4000 ;
if ( EditingMode = = 2 ) MaxSize = 16 + CHRsize [ 0 ] + PRGsize [ 0 ] ; //todo: add trainer size
if ( DataAmount + CurOffset > MaxSize ) CurOffset = MaxSize - DataAmount ;
if ( CursorEndAddy > MaxSize ) CursorEndAddy = - 1 ;
if ( CursorStartAddy > MaxSize ) CursorStartAddy = MaxSize - 1 ;
//Set vertical scroll bar range and page size
ZeroMemory ( & si , sizeof ( SCROLLINFO ) ) ;
si . cbSize = sizeof ( si ) ;
si . fMask = ( SIF_RANGE | SIF_PAGE ) ;
si . nMin = 0 ;
si . nMax = MaxSize / 16 ;
si . nPage = ClientHeight / MemFontHeight ;
SetScrollInfo ( hwnd , SB_VERT , & si , TRUE ) ;
for ( i = 0 ; i < DataAmount ; i + + ) OldValues [ i ] = - 1 ;
UpdateColorTable ( ) ;
return 0 ;
}
case WM_MOVE :
StopSound ( ) ;
return 0 ;
case WM_DESTROY :
KillMemView ( ) ;
//ReleaseDC (hwnd, mDC) ;
//DestroyWindow(hMemView);
//UnregisterClass("MEMVIEW",fceu_hInstance);
//hMemView = 0;
return 0 ;
}
return DefWindowProc ( hwnd , message , wParam , lParam ) ;
}
void DoMemView ( ) {
WNDCLASSEX wndclass ;
//static RECT al;
if ( ! GI ) {
FCEUD_PrintError ( " You must have a game loaded before you can use the Memory Viewer. " ) ;
return ;
}
if ( GI - > type = = GIT_NSF ) {
FCEUD_PrintError ( " Sorry, you can't yet use the Memory Viewer with NSFs. " ) ;
return ;
}
if ( ! hMemView ) {
memset ( & wndclass , 0 , sizeof ( wndclass ) ) ;
wndclass . cbSize = sizeof ( WNDCLASSEX ) ;
wndclass . style = CS_HREDRAW | CS_VREDRAW ;
wndclass . lpfnWndProc = MemViewCallB ;
wndclass . cbClsExtra = 0 ;
wndclass . cbWndExtra = 0 ;
wndclass . hInstance = fceu_hInstance ;
wndclass . hIcon = LoadIcon ( fceu_hInstance , " FCEUXD_ICON " ) ;
wndclass . hIconSm = LoadIcon ( fceu_hInstance , " FCEUXD_ICON " ) ;
wndclass . hCursor = LoadCursor ( NULL , IDC_ARROW ) ;
wndclass . hbrBackground = ( HBRUSH ) GetStockObject ( WHITE_BRUSH ) ;
wndclass . lpszMenuName = " MEMVIEWMENU " ; //TODO: add a menu
wndclass . lpszClassName = " MEMVIEW " ;
if ( ! RegisterClassEx ( & wndclass ) ) { FCEUD_PrintError ( " Error Registering MEMVIEW Window Class. " ) ; return ; }
hMemView = CreateWindowEx ( 0 , " MEMVIEW " , " Memory Editor " ,
//WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */
WS_SYSMENU | WS_THICKFRAME | WS_VSCROLL ,
CW_USEDEFAULT , CW_USEDEFAULT , 625 , 242 , /* X,Y ; Width, Height */
NULL , NULL , fceu_hInstance , NULL ) ;
ShowWindow ( hMemView , SW_SHOW ) ;
UpdateCaption ( ) ;
//hMemView = CreateDialog(fceu_hInstance,"MEMVIEW",NULL,MemViewCallB);
}
if ( hMemView ) {
SetWindowPos ( hMemView , HWND_TOP , 0 , 0 , 0 , 0 , SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER ) ;
//UpdateMemView(0);
//MemViewDoBlit();
}
}
BOOL CALLBACK MemFindCallB ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam ) {
switch ( uMsg ) {
case WM_INITDIALOG :
if ( FindDirectionUp ) CheckDlgButton ( hwndDlg , 1003 , BST_CHECKED ) ;
else CheckDlgButton ( hwndDlg , 1004 , BST_CHECKED ) ;
if ( FindAsText ) CheckDlgButton ( hwndDlg , 1002 , BST_CHECKED ) ;
else CheckDlgButton ( hwndDlg , 1001 , BST_CHECKED ) ;
if ( FindTextBox [ 0 ] ) SetDlgItemText ( hwndDlg , 1000 , FindTextBox ) ;
SendDlgItemMessage ( hwndDlg , 1000 , EM_SETLIMITTEXT , 59 , 0 ) ;
break ;
case WM_CREATE :
break ;
case WM_PAINT :
break ;
case WM_CLOSE :
case WM_QUIT :
GetDlgItemText ( hMemFind , 1000 , FindTextBox , 59 ) ;
DestroyWindow ( hMemFind ) ;
hMemFind = 0 ;
break ;
case WM_MOVING :
break ;
case WM_MOVE :
break ;
case WM_RBUTTONDBLCLK :
case WM_RBUTTONDOWN :
break ;
case WM_MOUSEMOVE :
break ;
case WM_COMMAND :
switch ( HIWORD ( wParam ) ) {
case BN_CLICKED :
switch ( LOWORD ( wParam ) ) {
case 1001 :
FindAsText = 0 ;
break ;
case 1002 :
FindAsText = 1 ;
break ;
case 1003 :
FindDirectionUp = 1 ;
break ;
case 1004 :
FindDirectionUp = 0 ;
break ;
case 1005 :
FindNext ( ) ;
break ;
}
break ;
}
break ;
case WM_HSCROLL :
break ;
}
return FALSE ;
}
void FindNext ( ) {
char str [ 60 ] ;
unsigned char data [ 60 ] ;
int datasize = 0 , i , j , inputc = - 1 , found ;
if ( hMemFind ) GetDlgItemText ( hMemFind , 1000 , str , 59 ) ;
else strcpy ( str , FindTextBox ) ;
for ( i = 0 ; str [ i ] ! = 0 ; i + + ) {
if ( ! FindAsText ) {
if ( inputc = = - 1 ) {
if ( ( str [ i ] > = ' a ' ) & & ( str [ i ] < = ' f ' ) ) inputc = str [ i ] - ( ' a ' - 0xA ) ;
if ( ( str [ i ] > = ' A ' ) & & ( str [ i ] < = ' F ' ) ) inputc = str [ i ] - ( ' A ' - 0xA ) ;
if ( ( str [ i ] > = ' 0 ' ) & & ( str [ i ] < = ' 9 ' ) ) inputc = str [ i ] - ' 0 ' ;
} else {
if ( ( str [ i ] > = ' a ' ) & & ( str [ i ] < = ' f ' ) ) inputc = ( inputc < < 4 ) | ( str [ i ] - ( ' a ' - 0xA ) ) ;
if ( ( str [ i ] > = ' A ' ) & & ( str [ i ] < = ' F ' ) ) inputc = ( inputc < < 4 ) | ( str [ i ] - ( ' A ' - 0xA ) ) ;
if ( ( str [ i ] > = ' 0 ' ) & & ( str [ i ] < = ' 9 ' ) ) inputc = ( inputc < < 4 ) | ( str [ i ] - ' 0 ' ) ;
if ( ( ( str [ i ] > = ' a ' ) & & ( str [ i ] < = ' f ' ) ) | |
( ( str [ i ] > = ' A ' ) & & ( str [ i ] < = ' F ' ) ) | |
( ( str [ i ] > = ' 0 ' ) & & ( str [ i ] < = ' 9 ' ) ) ) {
data [ datasize + + ] = inputc ;
inputc = - 1 ;
}
}
} else {
for ( j = 0 ; j < 256 ; j + + ) if ( chartable [ j ] = = str [ i ] ) break ;
if ( j = = 256 ) continue ;
data [ datasize + + ] = j ;
}
}
if ( datasize < 1 ) {
MessageBox ( hMemView , " Invalid String " , " Error " , MB_OK ) ;
return ;
}
if ( ! FindDirectionUp ) {
for ( i = CursorStartAddy + 1 ; i + datasize < MaxSize ; i + + ) {
found = 1 ;
for ( j = 0 ; j < datasize ; j + + ) {
if ( GetMemViewData ( i + j ) ! = data [ j ] ) found = 0 ;
}
if ( found = = 1 ) {
ChangeMemViewFocus ( EditingMode , i , i + datasize - 1 ) ;
return ;
}
}
for ( i = 0 ; i < CursorStartAddy ; i + + ) {
found = 1 ;
for ( j = 0 ; j < datasize ; j + + ) {
if ( GetMemViewData ( i + j ) ! = data [ j ] ) found = 0 ;
}
if ( found = = 1 ) {
ChangeMemViewFocus ( EditingMode , i , i + datasize - 1 ) ;
return ;
}
}
} else { //FindDirection is up
for ( i = CursorStartAddy - 1 ; i > 0 ; i - - ) {
found = 1 ;
for ( j = 0 ; j < datasize ; j + + ) {
if ( GetMemViewData ( i + j ) ! = data [ j ] ) found = 0 ;
}
if ( found = = 1 ) {
ChangeMemViewFocus ( EditingMode , i , i + datasize - 1 ) ;
return ;
}
}
for ( i = MaxSize - datasize ; i > CursorStartAddy ; i - - ) {
found = 1 ;
for ( j = 0 ; j < datasize ; j + + ) {
if ( GetMemViewData ( i + j ) ! = data [ j ] ) found = 0 ;
}
if ( found = = 1 ) {
ChangeMemViewFocus ( EditingMode , i , i + datasize - 1 ) ;
return ;
}
}
}
MessageBox ( hMemView , " String Not Found " , " Error " , MB_OK ) ;
return ;
}
void OpenFindDialog ( ) {
if ( ( ! hMemView ) | | ( hMemFind ) ) return ;
hMemFind = CreateDialog ( fceu_hInstance , " MEMVIEWFIND " , hMemView , MemFindCallB ) ;
return ;
}