tas editor rough draft
This commit is contained in:
parent
886bae8b5a
commit
d1cc70c7c4
|
@ -36,6 +36,7 @@
|
|||
#include "../../fceu.h"
|
||||
#include "../../state.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../movie.h"
|
||||
#include "input.h"
|
||||
#include "netplay.h"
|
||||
#include "memwatch.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include "tracer.h"
|
||||
#include "cdlogger.h"
|
||||
#include "throttle.h"
|
||||
#include "tasedit.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "basicbot.h"
|
||||
|
@ -297,6 +299,7 @@ int BlockingCheck()
|
|||
{
|
||||
//other accelerator capable dialogs could be added here
|
||||
extern HWND hwndMemWatch;
|
||||
extern HWND hwndTasEdit;
|
||||
int handled = 0;
|
||||
if(hwndMemWatch)
|
||||
{
|
||||
|
@ -305,6 +308,11 @@ int BlockingCheck()
|
|||
if(!handled)
|
||||
handled = IsDialogMessage(hwndMemWatch,&msg);
|
||||
}
|
||||
if(!handled && hwndTasEdit)
|
||||
{
|
||||
if(IsChild(hwndTasEdit,msg.hwnd))
|
||||
handled = TranslateAccelerator(hwndTasEdit,fceu_hAccel,&msg);
|
||||
}
|
||||
|
||||
if(!handled)
|
||||
if(msg.hwnd == hAppWnd)
|
||||
|
@ -689,6 +697,8 @@ doloopy:
|
|||
FCEU_UpdateBot();
|
||||
|
||||
FCEUI_Emulate(&gfx, &sound, &ssize, 0); //emulate a single frame
|
||||
currMovieData.TryDumpIncremental();
|
||||
|
||||
FCEUD_Update(gfx, sound, ssize); //update displays and debug tools
|
||||
|
||||
//mbg 6/30/06 - close game if we were commanded to by calls nested in FCEUI_Emulate()
|
||||
|
@ -766,6 +776,7 @@ void _updateWindow()
|
|||
UpdateMemWatch();
|
||||
NTViewDoBlit(0);
|
||||
UpdateCheatList();
|
||||
UpdateTasEdit();
|
||||
}
|
||||
|
||||
//void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "memwatch.h"
|
||||
#include "../../debug.h"
|
||||
#include "debugger.h"
|
||||
#include "../../utils/xstring.h"
|
||||
|
||||
const int NUMWATCHES = 24;
|
||||
const int LABELLENGTH = 64;
|
||||
|
@ -48,11 +49,6 @@ const unsigned int MEMW_MAX_NUMBER_OF_RECENT_FILES = sizeof(memw_recent_files)/s
|
|||
|
||||
static HMENU memwrecentmenu, memwrecentdmenu;
|
||||
|
||||
//mbg 5/12/08
|
||||
//for the curious, I tested U16ToHexStr and it was 10x faster than printf.
|
||||
//so the author of these dedicated functions is not insane, and I will leave them.
|
||||
|
||||
|
||||
void UpdateMemw_RMenu(HMENU menu, char **strs, unsigned int mitem, unsigned int baseid)
|
||||
{
|
||||
MENUITEMINFO moo;
|
||||
|
@ -178,87 +174,6 @@ void MemwAddRecentFile(const char *filename)
|
|||
UpdateMemwRecentArray(filename, memw_recent_files, MEMW_MAX_NUMBER_OF_RECENT_FILES, memwrecentmenu, ID_FILE_RECENT, MEMW_MENU_FIRST_RECENT_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a directory to the recent directories list.
|
||||
*
|
||||
* @param dirname Name of the directory to add.
|
||||
**/
|
||||
|
||||
static char *U8ToStr(uint8 a)
|
||||
{
|
||||
static char TempArray[8];
|
||||
TempArray[0] = '0' + a/100;
|
||||
TempArray[1] = '0' + (a%100)/10;
|
||||
TempArray[2] = '0' + (a%10);
|
||||
TempArray[3] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
//I don't trust scanf for speed
|
||||
static uint16 FastStrToU16(char* s, bool& valid)
|
||||
{
|
||||
int i;
|
||||
uint16 v=0;
|
||||
for(i=0; i < 4; i++)
|
||||
{
|
||||
if(s[i] == 0) return v;
|
||||
v<<=4;
|
||||
if(s[i] >= '0' && s[i] <= '9')
|
||||
{
|
||||
v+=s[i]-'0';
|
||||
}
|
||||
else if(s[i] >= 'a' && s[i] <= 'f')
|
||||
{
|
||||
v+=s[i]-'a'+10;
|
||||
}
|
||||
else if(s[i] >= 'A' && s[i] <= 'F')
|
||||
{
|
||||
v+=s[i]-'A'+10;
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
return 0xFFFF;
|
||||
}
|
||||
}
|
||||
valid = true;
|
||||
return v;
|
||||
}
|
||||
|
||||
static char *U16ToDecStr(uint16 a)
|
||||
{
|
||||
static char TempArray[8];
|
||||
TempArray[0] = '0' + a/10000;
|
||||
TempArray[1] = '0' + (a%10000)/1000;
|
||||
TempArray[2] = '0' + (a%1000)/100;
|
||||
TempArray[3] = '0' + (a%100)/10;
|
||||
TempArray[4] = '0' + (a%10);
|
||||
TempArray[5] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
|
||||
static char *U16ToHexStr(uint16 a)
|
||||
{
|
||||
static char TempArray[8];
|
||||
TempArray[0] = a/4096 > 9?'A'+a/4096-10:'0' + a/4096;
|
||||
TempArray[1] = (a%4096)/256 > 9?'A'+(a%4096)/256 - 10:'0' + (a%4096)/256;
|
||||
TempArray[2] = (a%256)/16 > 9?'A'+(a%256)/16 - 10:'0' + (a%256)/16;
|
||||
TempArray[3] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
|
||||
TempArray[4] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
static char *U8ToHexStr(uint8 a)
|
||||
{
|
||||
static char TempArray[8];
|
||||
TempArray[0] = a/16 > 9?'A'+a/16 - 10:'0' + a/16;
|
||||
TempArray[1] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
|
||||
TempArray[2] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
|
||||
static const int MW_ADDR_Lookup[] = {
|
||||
MW_ADDR00,MW_ADDR01,MW_ADDR02,MW_ADDR03,
|
||||
MW_ADDR04,MW_ADDR05,MW_ADDR06,MW_ADDR07,
|
||||
|
@ -352,7 +267,7 @@ void UpdateMemWatch()
|
|||
}
|
||||
else
|
||||
{
|
||||
text = U8ToStr(GetMem(mwrec.addr));
|
||||
text = U8ToDecStr(GetMem(mwrec.addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1264,12 +1264,14 @@ BEGIN
|
|||
EDITTEXT IDC_EDIT_STOPFRAME,119,38,35,12,ES_AUTOHSCROLL | ES_NUMBER
|
||||
END
|
||||
|
||||
TASEDIT DIALOGEX 0, 0, 374, 348
|
||||
TASEDIT DIALOGEX 0, 0, 470, 349
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "TAS Editor"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_LIST1,"SysListView32",LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP,7,7,273,296
|
||||
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,273,296
|
||||
PUSHBUTTON "Hacky add 1000 frames",IDC_HACKY2,318,73,124,38
|
||||
PUSHBUTTON "Hacky truncate after current frame",IDC_HACKY1,313,31,124,38
|
||||
END
|
||||
|
||||
|
||||
|
@ -1372,9 +1374,9 @@ BEGIN
|
|||
"TASEDIT", DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 367
|
||||
RIGHTMARGIN, 463
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 341
|
||||
BOTTOMMARGIN, 342
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
@ -1610,9 +1612,18 @@ END
|
|||
|
||||
IDR_ACCELERATOR1 ACCELERATORS
|
||||
BEGIN
|
||||
"E", ACCEL_CTRL_E, VIRTKEY, CONTROL, NOINVERT
|
||||
"O", ACCEL_CTRL_O, VIRTKEY, CONTROL, NOINVERT
|
||||
"W", ACCEL_CTRL_W, VIRTKEY, CONTROL, NOINVERT
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
IDB_TE_ARROW BITMAP "res\\te_arrow.bmp"
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -26,6 +26,8 @@
|
|||
#define MENU_SAVE_STATE 110
|
||||
#define CB_ASK_EXIT 110
|
||||
#define COMBO_FAM 110
|
||||
#define IDB_BITMAP1 110
|
||||
#define IDB_TE_ARROW 110
|
||||
#define MENU_LOAD_STATE 111
|
||||
#define CB_DISABLE_SCREEN_SAVER 111
|
||||
#define BTN_FAM 111
|
||||
|
@ -240,6 +242,8 @@
|
|||
#define BTN_PRESET_EXPORT2 1126
|
||||
#define BTN_PRESET_EXPORT3 1127
|
||||
#define IDC_LIST1 1130
|
||||
#define IDC_HACKY2 1131
|
||||
#define IDC_HACKY1 1132
|
||||
#define MENU_NETWORK 40040
|
||||
#define MENU_PALETTE 40041
|
||||
#define MENU_SOUND 40042
|
||||
|
@ -333,6 +337,8 @@
|
|||
#define ID_CONFIG_PAUSEAFTERPLAYBACK 40125
|
||||
#define MENU_PAUSEAFTERPLAYBACK 40126
|
||||
#define ACCEL_CTRL_O 40130
|
||||
#define ACCEL_CTRL_E 40131
|
||||
#define ACCEL_CTRL_W 40132
|
||||
#define MW_ValueLabel2 65423
|
||||
#define MW_ValueLabel1 65426
|
||||
#define GUI_BOT_DEBUG 65436
|
||||
|
@ -343,9 +349,9 @@
|
|||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 110
|
||||
#define _APS_NEXT_COMMAND_VALUE 40131
|
||||
#define _APS_NEXT_CONTROL_VALUE 1131
|
||||
#define _APS_NEXT_RESOURCE_VALUE 111
|
||||
#define _APS_NEXT_COMMAND_VALUE 40134
|
||||
#define _APS_NEXT_CONTROL_VALUE 1132
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,27 +1,265 @@
|
|||
#include "common.h"
|
||||
#include "tasedit.h"
|
||||
#include "../../fceu.h"
|
||||
#include "debugger.h"
|
||||
#include "../../movie.h"
|
||||
#include "../../utils/xstring.h"
|
||||
|
||||
//to change header font
|
||||
//http://forums.devx.com/archive/index.php/t-37234.html
|
||||
|
||||
HWND hwndTasEdit = 0;
|
||||
static int lastCursor;
|
||||
static HWND hwndList;
|
||||
|
||||
//hacky.. we need to think about how to convey information from the driver to the movie code.
|
||||
//add a new fceud_ function?? blehhh maybe
|
||||
bool moviePleaseLogSavestates = false;
|
||||
|
||||
static void GetDispInfo(NMLVDISPINFO* nmlvDispInfo)
|
||||
{
|
||||
LVITEM& item = nmlvDispInfo->item;
|
||||
if(item.mask & LVIF_TEXT)
|
||||
{
|
||||
switch(item.iSubItem)
|
||||
{
|
||||
case 0:
|
||||
if(item.iImage == I_IMAGECALLBACK && item.iItem == currFrameCounter)
|
||||
item.iImage = 0;
|
||||
else
|
||||
item.iImage = -1;
|
||||
break;
|
||||
case 1:
|
||||
U32ToDecStr(item.pszText,item.iItem);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9: {
|
||||
int bit = (item.iSubItem - 2);
|
||||
uint8 data = currMovieData.records[item.iItem].joysticks[0];
|
||||
if(data & (1<<bit))
|
||||
{
|
||||
item.pszText[0] = MovieRecord::mnemonics[bit];
|
||||
item.pszText[1] = 0;
|
||||
} else
|
||||
item.pszText[1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CDDS_ITEMPREPAINT (CDDS_ITEM | CDDS_PREPAINT)
|
||||
#define CDDS_ITEMPOSTPAINT (CDDS_ITEM | CDDS_POSTPAINT)
|
||||
#define CDDS_ITEMPREERASE (CDDS_ITEM | CDDS_PREERASE)
|
||||
#define CDDS_ITEMPOSTERASE (CDDS_ITEM | CDDS_POSTERASE)
|
||||
#define CDDS_SUBITEMPREPAINT (CDDS_SUBITEM | CDDS_ITEMPREPAINT)
|
||||
#define CDDS_SUBITEMPOSTPAINT (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT)
|
||||
#define CDDS_SUBITEMPREERASE (CDDS_SUBITEM | CDDS_ITEMPREERASE)
|
||||
#define CDDS_SUBITEMPOSTERASE (CDDS_SUBITEM | CDDS_ITEMPOSTERASE)
|
||||
|
||||
static LONG CustomDraw(NMLVCUSTOMDRAW* msg)
|
||||
{
|
||||
switch(msg->nmcd.dwDrawStage)
|
||||
{
|
||||
case CDDS_PREPAINT:
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
case CDDS_ITEMPREPAINT:
|
||||
return CDRF_NOTIFYSUBITEMDRAW;
|
||||
case CDDS_SUBITEMPREPAINT:
|
||||
SelectObject(msg->nmcd.hdc,debugSystem->hFixedFont);
|
||||
if((int)msg->nmcd.dwItemSpec < currMovieData.greenZoneCount)
|
||||
msg->clrTextBk = RGB(192,255,192);
|
||||
return CDRF_DODEFAULT;
|
||||
default:
|
||||
return CDRF_DODEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
// called from the rest of the emulator when things happen and the tasedit should change to reflect it
|
||||
void UpdateTasEdit()
|
||||
{
|
||||
if(!hwndTasEdit) return;
|
||||
|
||||
//update the number of items
|
||||
ListView_SetItemCountEx(hwndList,currMovieData.getNumRecords(),LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL);
|
||||
|
||||
//update the cursor
|
||||
int newCursor = currFrameCounter;
|
||||
if(newCursor != lastCursor)
|
||||
{
|
||||
//scroll to the row
|
||||
ListView_EnsureVisible(hwndList,newCursor,FALSE);
|
||||
//select the row
|
||||
ListView_SetItemState(hwndList,newCursor,LVIS_FOCUSED|LVIS_SELECTED,LVIS_FOCUSED|LVIS_SELECTED);
|
||||
|
||||
//update the old and new rows
|
||||
ListView_Update(hwndList,lastCursor);
|
||||
ListView_Update(hwndList,newCursor);
|
||||
|
||||
lastCursor = newCursor;
|
||||
}
|
||||
}
|
||||
|
||||
void RedrawList()
|
||||
{
|
||||
InvalidateRect(hwndList,0,FALSE);
|
||||
}
|
||||
|
||||
void DoubleClick(LPNMITEMACTIVATE info)
|
||||
{
|
||||
int index = info->iItem;
|
||||
|
||||
//stray click
|
||||
if(index == -1)
|
||||
return;
|
||||
|
||||
//if the icon or frame columns were double clicked:
|
||||
if(info->iSubItem == 0 || info->iSubItem == 1)
|
||||
{
|
||||
//if the row is in the green zone, then move to it
|
||||
if(index < currMovieData.greenZoneCount)
|
||||
{
|
||||
MovieData::loadSavestateFrom(&currMovieData.records[index].savestate);
|
||||
}
|
||||
}
|
||||
else //if an input column was clicked:
|
||||
{
|
||||
//toggle the bit
|
||||
int bit = (info->iSubItem-2);
|
||||
currMovieData.records[index].toggleBit(0,bit);
|
||||
|
||||
//update the row
|
||||
ListView_Update(hwndList,index);
|
||||
|
||||
//reduce the green zone
|
||||
currMovieData.greenZoneCount = std::min(index+1,currMovieData.greenZoneCount);
|
||||
|
||||
//redraw everything to show the reduced green zone
|
||||
RedrawList();
|
||||
}
|
||||
}
|
||||
|
||||
void InitDialog()
|
||||
{
|
||||
ListView_SetExtendedListViewStyleEx(hwndList,
|
||||
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES ,
|
||||
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES );
|
||||
|
||||
|
||||
HIMAGELIST himglist = ImageList_Create(12,12,ILC_COLOR32 | ILC_MASK,1,1);
|
||||
HBITMAP bmp = LoadBitmap(fceu_hInstance,MAKEINTRESOURCE(IDB_TE_ARROW));
|
||||
ImageList_AddMasked(himglist, bmp, RGB(255,0,255));
|
||||
DeleteObject(bmp);
|
||||
ListView_SetImageList(hwndList,himglist,LVSIL_SMALL);
|
||||
|
||||
//doesnt work well??
|
||||
//HIMAGELIST himglist = ImageList_LoadImage(fceu_hInstance,MAKEINTRESOURCE(IDB_TE_ARROW),12,1,RGB(255,0,255),IMAGE_BITMAP,LR_DEFAULTCOLOR);
|
||||
|
||||
//setup columns
|
||||
LVCOLUMN lvc;
|
||||
int colidx=0;
|
||||
lvc.mask = LVCF_WIDTH;
|
||||
lvc.cx = 12;
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.mask = LVCF_WIDTH | LVCF_TEXT;
|
||||
lvc.cx = 95;
|
||||
lvc.pszText = "Frame#";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.cx = 20;
|
||||
lvc.pszText = "A";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "B";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "S";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "T";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "U";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "D";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "L";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
lvc.pszText = "R";
|
||||
ListView_InsertColumn(hwndList, colidx++, &lvc);
|
||||
//-----------------------------
|
||||
|
||||
//the initial update
|
||||
UpdateTasEdit();
|
||||
}
|
||||
|
||||
HWND hTasEdit = 0;
|
||||
|
||||
void KillTasEdit()
|
||||
{
|
||||
DestroyWindow(hTasEdit);
|
||||
hTasEdit = 0;
|
||||
DestroyWindow(hwndTasEdit);
|
||||
hwndTasEdit = 0;
|
||||
moviePleaseLogSavestates = false;
|
||||
}
|
||||
|
||||
|
||||
BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
hwndList = GetDlgItem(hwndDlg,IDC_LIST1);
|
||||
InitDialog();
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
switch(wParam)
|
||||
{
|
||||
case IDC_LIST1:
|
||||
switch(((LPNMHDR)lParam)->code)
|
||||
{
|
||||
case NM_CUSTOMDRAW:
|
||||
SetWindowLong(hwndDlg, DWL_MSGRESULT, CustomDraw((NMLVCUSTOMDRAW*)lParam));
|
||||
return TRUE;
|
||||
case LVN_GETDISPINFO:
|
||||
GetDispInfo((NMLVDISPINFO*)lParam);
|
||||
break;
|
||||
case NM_CLICK:
|
||||
break;
|
||||
case NM_DBLCLK:
|
||||
DoubleClick((LPNMITEMACTIVATE)lParam);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
case WM_QUIT:
|
||||
KillTasEdit();
|
||||
break;
|
||||
|
||||
/* case WM_NOTIFY:
|
||||
case LVN_GETDISPINFO:*/
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_HACKY1:
|
||||
//hacky1: delete all items after the current selection
|
||||
currMovieData.records.resize(currFrameCounter+1);
|
||||
UpdateTasEdit();
|
||||
break;
|
||||
case IDC_HACKY2:
|
||||
//hacky1: delete all items after the current selection
|
||||
currMovieData.records.resize(currMovieData.records.size()+1000);
|
||||
currMovieData.clearRecordRange(currMovieData.records.size()-1000,1000);
|
||||
UpdateTasEdit();
|
||||
break;
|
||||
|
||||
case ACCEL_CTRL_W:
|
||||
KillTasEdit();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -29,13 +267,13 @@ BOOL CALLBACK WndprocTasEdit(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
|
||||
void DoTasEdit()
|
||||
{
|
||||
if(!hTasEdit)
|
||||
hTasEdit = CreateDialog(fceu_hInstance,"TASEDIT",NULL,WndprocTasEdit);
|
||||
lastCursor = -1;
|
||||
if(!hwndTasEdit)
|
||||
hwndTasEdit = CreateDialog(fceu_hInstance,"TASEDIT",NULL,WndprocTasEdit);
|
||||
|
||||
if(hTasEdit)
|
||||
if(hwndTasEdit)
|
||||
{
|
||||
SetWindowPos(hTasEdit,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
|
||||
//update?
|
||||
//FCEUD_UpdatePPUView(-1,1);
|
||||
moviePleaseLogSavestates = true;
|
||||
SetWindowPos(hwndTasEdit,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
void DoTasEdit();
|
||||
void DoTasEdit();
|
||||
void UpdateTasEdit();
|
|
@ -857,6 +857,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|||
UpdateCheckedMenuItems();
|
||||
break;
|
||||
|
||||
case ACCEL_CTRL_E:
|
||||
case MENU_TASEDIT:
|
||||
DoTasEdit();
|
||||
break;
|
||||
|
|
328
src/movie.cpp
328
src/movie.cpp
|
@ -3,9 +3,6 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
@ -27,6 +24,7 @@
|
|||
|
||||
extern char FileBase[];
|
||||
extern int EmulationPaused;
|
||||
extern bool moviePleaseLogSavestates;
|
||||
|
||||
|
||||
//TODO - remove the synchack stuff from the replay gui and require it to be put into the fm2 file
|
||||
|
@ -66,167 +64,135 @@ SFORMAT FCEUMOV_STATEINFO[]={
|
|||
};
|
||||
|
||||
char curMovieFilename[512] = {0};
|
||||
MovieData currMovieData;
|
||||
|
||||
class MovieRecord
|
||||
void MovieData::clearRecordRange(int start, int len)
|
||||
{
|
||||
public:
|
||||
ValueArray<uint8,4> joysticks;
|
||||
for(int i=0;i<len;i++)
|
||||
records[i+start].clear();
|
||||
}
|
||||
|
||||
void dump(FILE* fp, int index)
|
||||
{
|
||||
//todo: if we want frame numbers in the output (which we dont since we couldnt cut and paste in movies)
|
||||
//but someone would need to change the parser to ignore it
|
||||
//fputc('|',fp);
|
||||
//fprintf(fp,"%08d",index);
|
||||
|
||||
fputc('|',fp);
|
||||
|
||||
//for each joystick
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
//these are mnemonics for each joystick bit.
|
||||
//since we usually use the regular joypad, these will be more helpful.
|
||||
//but any character other than ' ' should count as a set bit
|
||||
//maybe other input types will need to be encoded another way..
|
||||
const char mnemonics[] = {'A','B','S','T','U','D','L','R'};
|
||||
for(int bit=7;bit>=0;bit--)
|
||||
{
|
||||
uint8 &joystate = joysticks[i];
|
||||
int bitmask = (1<<bit);
|
||||
char mnemonic = mnemonics[bit];
|
||||
//if the bit is set write the mnemonic
|
||||
if(joystate & bitmask)
|
||||
fputc(mnemonic,fp);
|
||||
else //otherwise write a space
|
||||
fputc(' ',fp);
|
||||
}
|
||||
|
||||
//separate the joysticks
|
||||
if(i != 3) fputc('|',fp);
|
||||
}
|
||||
|
||||
//each frame is on a new line
|
||||
fputc('\n',fp);
|
||||
}
|
||||
};
|
||||
|
||||
class MovieData
|
||||
void MovieData::TryDumpIncremental()
|
||||
{
|
||||
public:
|
||||
MovieData()
|
||||
: version(MOVIE_VERSION)
|
||||
, emuVersion(FCEU_VERSION_NUMERIC)
|
||||
, palFlag(false)
|
||||
, poweronFlag(false)
|
||||
, resetFlag(false)
|
||||
, recordCount(1)
|
||||
if(moviePleaseLogSavestates)
|
||||
{
|
||||
memset(&romChecksum,0,sizeof(MD5DATA));
|
||||
}
|
||||
|
||||
int emuVersion;
|
||||
int version;
|
||||
//todo - somehow force mutual exclusion for poweron and reset (with an error in the parser)
|
||||
bool palFlag;
|
||||
bool poweronFlag;
|
||||
bool resetFlag;
|
||||
MD5DATA romChecksum;
|
||||
std::string romFilename;
|
||||
std::vector<char> savestate;
|
||||
std::vector<MovieRecord> records;
|
||||
int recordCount;
|
||||
|
||||
FCEU_Guid guid;
|
||||
|
||||
//the entire contents of the disk file that was loaded
|
||||
std::vector<char> serializedFile;
|
||||
|
||||
void truncateAt(int frame)
|
||||
{
|
||||
records.resize(frame);
|
||||
}
|
||||
|
||||
class TDictionary : public std::map<std::string,std::string>
|
||||
{
|
||||
public:
|
||||
bool containsKey(std::string key)
|
||||
//only log the savestate if we are appending to the green zone
|
||||
if(currFrameCounter == currMovieData.greenZoneCount)
|
||||
{
|
||||
return find(key) != end();
|
||||
}
|
||||
|
||||
void tryInstallBool(std::string key, bool& val)
|
||||
{
|
||||
if(containsKey(key))
|
||||
val = atoi(operator [](key).c_str())!=0;
|
||||
}
|
||||
|
||||
void tryInstallString(std::string key, std::string& val)
|
||||
{
|
||||
if(containsKey(key))
|
||||
val = operator [](key);
|
||||
}
|
||||
|
||||
void tryInstallInt(std::string key, int& val)
|
||||
{
|
||||
if(containsKey(key))
|
||||
val = atoi(operator [](key).c_str());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void installDictionary(TDictionary& dictionary)
|
||||
{
|
||||
dictionary.tryInstallInt("version",version);
|
||||
dictionary.tryInstallInt("emuVersion",emuVersion);
|
||||
dictionary.tryInstallInt("recordCount",recordCount);
|
||||
dictionary.tryInstallBool("palFlag",palFlag);
|
||||
dictionary.tryInstallBool("poweronFlag",poweronFlag);
|
||||
dictionary.tryInstallBool("resetFlag",resetFlag);
|
||||
dictionary.tryInstallString("romFilename",romFilename);
|
||||
if(dictionary.containsKey("romChecksum"))
|
||||
StringToBytes(dictionary["romChecksum"],&romChecksum,MD5DATA::size);
|
||||
if(dictionary.containsKey("guid"))
|
||||
guid = FCEU_Guid::fromString(dictionary["guid"]);
|
||||
if(dictionary.containsKey("savestate"))
|
||||
{
|
||||
std::string& str = dictionary["savestate"];
|
||||
int len = HexStringToBytesLength(str);
|
||||
if(len >= 1)
|
||||
if(currFrameCounter < (int)currMovieData.records.size())
|
||||
{
|
||||
savestate.resize(len);
|
||||
StringToBytes(str,&savestate[0],len);
|
||||
MovieData::dumpSavestateTo(&currMovieData.records[currFrameCounter].savestate);
|
||||
currMovieData.greenZoneCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int dumpLen()
|
||||
const char MovieRecord::mnemonics[8] = {'A','B','S','T','U','D','L','R'};
|
||||
void MovieRecord::dump(FILE* fp, int index)
|
||||
{
|
||||
//todo: if we want frame numbers in the output (which we dont since we couldnt cut and paste in movies)
|
||||
//but someone would need to change the parser to ignore it
|
||||
//fputc('|',fp);
|
||||
//fprintf(fp,"%08d",index);
|
||||
|
||||
fputc('|',fp);
|
||||
|
||||
//for each joystick
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
FILE* tmp = tmpfile();
|
||||
dump(tmp);
|
||||
int len = ftell(tmp);
|
||||
fclose(tmp);
|
||||
return len;
|
||||
//these are mnemonics for each joystick bit.
|
||||
//since we usually use the regular joypad, these will be more helpful.
|
||||
//but any character other than ' ' should count as a set bit
|
||||
//maybe other input types will need to be encoded another way..
|
||||
for(int bit=7;bit>=0;bit--)
|
||||
{
|
||||
uint8 &joystate = joysticks[i];
|
||||
int bitmask = (1<<bit);
|
||||
char mnemonic = mnemonics[bit];
|
||||
//if the bit is set write the mnemonic
|
||||
if(joystate & bitmask)
|
||||
fputc(mnemonic,fp);
|
||||
else //otherwise write a space
|
||||
fputc(' ',fp);
|
||||
}
|
||||
|
||||
//separate the joysticks
|
||||
if(i != 3) fputc('|',fp);
|
||||
}
|
||||
|
||||
void dump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"version %d\n", version);
|
||||
fprintf(fp,"emuVersion %d\n", emuVersion);
|
||||
fprintf(fp,"recordCount %d\n", recordCount);
|
||||
fprintf(fp,"palFlag %d\n", palFlag?1:0);
|
||||
fprintf(fp,"poweronFlag %d\n", poweronFlag?1:0);
|
||||
fprintf(fp,"resetFlag %d\n", resetFlag?1:0);
|
||||
fprintf(fp,"romFilename %s\n", romFilename.c_str());
|
||||
fprintf(fp,"romChecksum %s\n", BytesToString(romChecksum.data,MD5DATA::size).c_str());
|
||||
fprintf(fp,"guid %s\n", guid.toString().c_str());
|
||||
if(savestate.size() != 0)
|
||||
fprintf(fp,"savestate %s\n", BytesToString(&savestate[0],savestate.size()).c_str());
|
||||
for(int i=0;i<(int)records.size();i++)
|
||||
records[i].dump(fp,i);
|
||||
}
|
||||
//each frame is on a new line
|
||||
fputc('\n',fp);
|
||||
}
|
||||
|
||||
MovieData::MovieData()
|
||||
: version(MOVIE_VERSION)
|
||||
, emuVersion(FCEU_VERSION_NUMERIC)
|
||||
, palFlag(false)
|
||||
, poweronFlag(false)
|
||||
, resetFlag(false)
|
||||
, recordCount(1)
|
||||
, greenZoneCount(0)
|
||||
{
|
||||
memset(&romChecksum,0,sizeof(MD5DATA));
|
||||
}
|
||||
|
||||
void MovieData::truncateAt(int frame)
|
||||
{
|
||||
records.resize(frame);
|
||||
}
|
||||
|
||||
void MovieData::installDictionary(TDictionary& dictionary)
|
||||
{
|
||||
dictionary.tryInstallInt("version",version);
|
||||
dictionary.tryInstallInt("emuVersion",emuVersion);
|
||||
dictionary.tryInstallInt("recordCount",recordCount);
|
||||
dictionary.tryInstallBool("palFlag",palFlag);
|
||||
dictionary.tryInstallBool("poweronFlag",poweronFlag);
|
||||
dictionary.tryInstallBool("resetFlag",resetFlag);
|
||||
dictionary.tryInstallString("romFilename",romFilename);
|
||||
if(dictionary.containsKey("romChecksum"))
|
||||
StringToBytes(dictionary["romChecksum"],&romChecksum,MD5DATA::size);
|
||||
if(dictionary.containsKey("guid"))
|
||||
guid = FCEU_Guid::fromString(dictionary["guid"]);
|
||||
if(dictionary.containsKey("savestate"))
|
||||
{
|
||||
std::string& str = dictionary["savestate"];
|
||||
int len = HexStringToBytesLength(str);
|
||||
if(len >= 1)
|
||||
{
|
||||
savestate.resize(len);
|
||||
StringToBytes(str,&savestate[0],len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovieData::dump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"version %d\n", version);
|
||||
fprintf(fp,"emuVersion %d\n", emuVersion);
|
||||
fprintf(fp,"recordCount %d\n", recordCount);
|
||||
fprintf(fp,"palFlag %d\n", palFlag?1:0);
|
||||
fprintf(fp,"poweronFlag %d\n", poweronFlag?1:0);
|
||||
fprintf(fp,"resetFlag %d\n", resetFlag?1:0);
|
||||
fprintf(fp,"romFilename %s\n", romFilename.c_str());
|
||||
fprintf(fp,"romChecksum %s\n", BytesToString(romChecksum.data,MD5DATA::size).c_str());
|
||||
fprintf(fp,"guid %s\n", guid.toString().c_str());
|
||||
if(savestate.size() != 0)
|
||||
fprintf(fp,"savestate %s\n", BytesToString(&savestate[0],savestate.size()).c_str());
|
||||
for(int i=0;i<(int)records.size();i++)
|
||||
records[i].dump(fp,i);
|
||||
}
|
||||
|
||||
int MovieData::dumpLen()
|
||||
{
|
||||
FILE* tmp = tmpfile();
|
||||
dump(tmp);
|
||||
int len = ftell(tmp);
|
||||
fclose(tmp);
|
||||
return len;
|
||||
}
|
||||
|
||||
} currMovieData;
|
||||
//---------
|
||||
|
||||
int FCEUMOV_GetFrame(void)
|
||||
{
|
||||
|
@ -259,16 +225,6 @@ int FCEUMOV_IsRecording(void)
|
|||
//yuck... another custom text parser.
|
||||
void LoadFM2(MovieData& movieData, FILE *fp)
|
||||
{
|
||||
//read the entire file so we can keep it handy.
|
||||
//we could parse from that instead of the disk again...
|
||||
|
||||
fseek(fp,0,SEEK_END);
|
||||
int len = ftell(fp);
|
||||
fseek(fp,0,SEEK_SET);
|
||||
movieData.serializedFile.resize(len);
|
||||
fread(&movieData.serializedFile[0],1,len,fp);
|
||||
fseek(fp,0,SEEK_SET);
|
||||
|
||||
MovieData::TDictionary dictionary;
|
||||
|
||||
std::string key,value;
|
||||
|
@ -406,6 +362,33 @@ static void ResetInputTypes()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool MovieData::loadSavestateFrom(std::vector<uint8>* buf)
|
||||
{
|
||||
//dump the savestate to disk
|
||||
FILE* fp = tmpfile();
|
||||
fwrite(&(*buf)[0],1,buf->size(),fp);
|
||||
fseek(fp,0,SEEK_SET);
|
||||
|
||||
//and load the state
|
||||
bool success = FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP);
|
||||
fclose(fp);
|
||||
return success;
|
||||
}
|
||||
|
||||
void MovieData::dumpSavestateTo(std::vector<uint8>* buf)
|
||||
{
|
||||
//dump a savestate to a tempfile..
|
||||
FILE* tmp = tmpfile();
|
||||
FCEUSS_SaveFP(tmp);
|
||||
|
||||
//reloading the savestate into the data structure
|
||||
fseek(tmp,0,SEEK_END);
|
||||
int len = (int)ftell(tmp);
|
||||
fseek(tmp,0,SEEK_SET);
|
||||
buf->resize(len);
|
||||
fread(&(*buf)[0],1,len,tmp);
|
||||
fclose(tmp);
|
||||
}
|
||||
|
||||
//begin playing an existing movie
|
||||
void FCEUI_LoadMovie(char *fname, bool _read_only, int _pauseframe)
|
||||
|
@ -447,16 +430,8 @@ void FCEUI_LoadMovie(char *fname, bool _read_only, int _pauseframe)
|
|||
//WE NEED TO LOAD A SAVESTATE
|
||||
if(!currMovieData.poweronFlag)
|
||||
{
|
||||
//dump the savestate to disk
|
||||
FILE* fp = tmpfile();
|
||||
fwrite(&currMovieData.savestate[0],1,currMovieData.savestate.size(),fp);
|
||||
fseek(fp,0,SEEK_SET);
|
||||
|
||||
//and load the state
|
||||
bool success = FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
bool success = MovieData::loadSavestateFrom(&currMovieData.savestate);
|
||||
if(!success) return;
|
||||
}
|
||||
|
||||
|
@ -478,6 +453,8 @@ void FCEUI_LoadMovie(char *fname, bool _read_only, int _pauseframe)
|
|||
movie_readonly = _read_only;
|
||||
movieMode = MOVIEMODE_PLAY;
|
||||
|
||||
currMovieData.TryDumpIncremental();
|
||||
|
||||
if(movie_readonly)
|
||||
FCEU_DispMessage("Replay started Read-Only.");
|
||||
else
|
||||
|
@ -498,7 +475,6 @@ static void openRecordingMovie(const char* fname)
|
|||
strcpy(curMovieFilename, fname);
|
||||
}
|
||||
|
||||
|
||||
//begin recording a new movie
|
||||
void FCEUI_SaveMovie(char *fname, uint8 flags)
|
||||
{
|
||||
|
@ -545,17 +521,7 @@ void FCEUI_SaveMovie(char *fname, uint8 flags)
|
|||
}
|
||||
else
|
||||
{
|
||||
//dump a savestate to a tempfile..
|
||||
FILE* tmp = tmpfile();
|
||||
FCEUSS_SaveFP(tmp);
|
||||
|
||||
//reloading the savestate into the data structure
|
||||
fseek(tmp,0,SEEK_END);
|
||||
int len = (int)ftell(tmp);
|
||||
fseek(tmp,0,SEEK_SET);
|
||||
currMovieData.savestate.resize(len);
|
||||
fread(&currMovieData.savestate[0],1,len,tmp);
|
||||
fclose(tmp);
|
||||
MovieData::dumpSavestateTo(&currMovieData.savestate);
|
||||
}
|
||||
|
||||
//we are going to go ahead and dump the header. from now on we will only be appending frames
|
||||
|
@ -583,8 +549,6 @@ void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
|
|||
{
|
||||
if(movieMode == MOVIEMODE_PLAY)
|
||||
{
|
||||
//TODO - rock solid stability and error detection
|
||||
|
||||
//stop when we run out of frames
|
||||
if(currFrameCounter == currMovieData.records.size())
|
||||
{
|
||||
|
|
99
src/movie.h
99
src/movie.h
|
@ -1,6 +1,10 @@
|
|||
#ifndef __MOVIE_H_
|
||||
#define __MOVIE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
void FCEUMOV_AddJoy(uint8 *, int SkipFlush);
|
||||
void FCEUMOV_AddCommand(int cmd);
|
||||
void FCEU_DrawMovies(uint8 *);
|
||||
|
@ -13,6 +17,97 @@ int FCEUMOV_WriteState(FILE* st);
|
|||
bool FCEUMOV_ReadState(FILE* st, uint32 size);
|
||||
void FCEUMOV_PreLoad(void);
|
||||
int FCEUMOV_PostLoad(void);
|
||||
void MovieFlushHeader(void);
|
||||
|
||||
#endif /* __MOVIE_H_ */
|
||||
|
||||
class MovieRecord
|
||||
{
|
||||
public:
|
||||
ValueArray<uint8,4> joysticks;
|
||||
|
||||
void toggleBit(int joy, int bit)
|
||||
{
|
||||
int mask = (1<<bit);
|
||||
joysticks[joy] ^= mask;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
*(uint32*)&joysticks = 0;
|
||||
}
|
||||
|
||||
//a waste of memory in lots of cases.. maybe make it a pointer later?
|
||||
std::vector<uint8> savestate;
|
||||
|
||||
void dump(FILE* fp, int index);
|
||||
|
||||
static const char mnemonics[8];
|
||||
};
|
||||
|
||||
class MovieData
|
||||
{
|
||||
public:
|
||||
MovieData();
|
||||
|
||||
|
||||
int emuVersion;
|
||||
int version;
|
||||
//todo - somehow force mutual exclusion for poweron and reset (with an error in the parser)
|
||||
bool palFlag;
|
||||
bool poweronFlag;
|
||||
bool resetFlag;
|
||||
MD5DATA romChecksum;
|
||||
std::string romFilename;
|
||||
std::vector<uint8> savestate;
|
||||
std::vector<MovieRecord> records;
|
||||
int recordCount;
|
||||
FCEU_Guid guid;
|
||||
|
||||
//----TasEdit stuff---
|
||||
int greenZoneCount;
|
||||
//----
|
||||
|
||||
int getNumRecords() { return records.size(); }
|
||||
|
||||
class TDictionary : public std::map<std::string,std::string>
|
||||
{
|
||||
public:
|
||||
bool containsKey(std::string key)
|
||||
{
|
||||
return find(key) != end();
|
||||
}
|
||||
|
||||
void tryInstallBool(std::string key, bool& val)
|
||||
{
|
||||
if(containsKey(key))
|
||||
val = atoi(operator [](key).c_str())!=0;
|
||||
}
|
||||
|
||||
void tryInstallString(std::string key, std::string& val)
|
||||
{
|
||||
if(containsKey(key))
|
||||
val = operator [](key);
|
||||
}
|
||||
|
||||
void tryInstallInt(std::string key, int& val)
|
||||
{
|
||||
if(containsKey(key))
|
||||
val = atoi(operator [](key).c_str());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void truncateAt(int frame);
|
||||
void MovieData::installDictionary(TDictionary& dictionary);
|
||||
void dump(FILE *fp);
|
||||
int dumpLen();
|
||||
void clearRecordRange(int start, int len);
|
||||
|
||||
static bool loadSavestateFrom(std::vector<uint8>* buf);
|
||||
static void dumpSavestateTo(std::vector<uint8>* buf);
|
||||
void TryDumpIncremental();
|
||||
};
|
||||
|
||||
extern MovieData currMovieData;
|
||||
extern int currFrameCounter;
|
||||
//---------
|
||||
|
||||
#endif //__MOVIE_H_
|
||||
|
|
|
@ -359,7 +359,8 @@ bool FCEUSS_SaveFP(FILE *st)
|
|||
//compress it
|
||||
uint8* cbuf = new uint8[len*2]; //worst case compression, lets say twice the input buffer size
|
||||
uLongf comprlen = len*2;
|
||||
int error = compress2(cbuf,&comprlen,&buf[0],len,Z_BEST_COMPRESSION);
|
||||
//int error = compress2(cbuf,&comprlen,&buf[0],len,Z_BEST_COMPRESSION);
|
||||
int error = compress2(cbuf,&comprlen,&buf[0],len,Z_BEST_SPEED);
|
||||
|
||||
//dump the header
|
||||
uint8 header[16]="FCSX";
|
||||
|
|
|
@ -202,4 +202,4 @@ struct FCEU_Guid : public ValueArray<uint8,16>
|
|||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -363,4 +363,98 @@ void splitpath(const char* path, char* drv, char* dir, char* name, char* ext)
|
|||
|
||||
*dir = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
//mbg 5/12/08
|
||||
//for the curious, I tested U16ToHexStr and it was 10x faster than printf.
|
||||
//so the author of these dedicated functions is not insane, and I will leave them.
|
||||
|
||||
static char TempArray[11];
|
||||
|
||||
uint16 FastStrToU16(char* s, bool& valid)
|
||||
{
|
||||
int i;
|
||||
uint16 v=0;
|
||||
for(i=0; i < 4; i++)
|
||||
{
|
||||
if(s[i] == 0) return v;
|
||||
v<<=4;
|
||||
if(s[i] >= '0' && s[i] <= '9')
|
||||
{
|
||||
v+=s[i]-'0';
|
||||
}
|
||||
else if(s[i] >= 'a' && s[i] <= 'f')
|
||||
{
|
||||
v+=s[i]-'a'+10;
|
||||
}
|
||||
else if(s[i] >= 'A' && s[i] <= 'F')
|
||||
{
|
||||
v+=s[i]-'A'+10;
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
return 0xFFFF;
|
||||
}
|
||||
}
|
||||
valid = true;
|
||||
return v;
|
||||
}
|
||||
|
||||
char *U8ToDecStr(uint8 a)
|
||||
{
|
||||
TempArray[0] = '0' + a/100;
|
||||
TempArray[1] = '0' + (a%100)/10;
|
||||
TempArray[2] = '0' + (a%10);
|
||||
TempArray[3] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
char *U16ToDecStr(uint16 a)
|
||||
{
|
||||
TempArray[0] = '0' + a/10000;
|
||||
TempArray[1] = '0' + (a%10000)/1000;
|
||||
TempArray[2] = '0' + (a%1000)/100;
|
||||
TempArray[3] = '0' + (a%100)/10;
|
||||
TempArray[4] = '0' + (a%10);
|
||||
TempArray[5] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
char *U32ToDecStr(char* buf, uint32 a)
|
||||
{
|
||||
buf[0] = '0' + a/1000000000;
|
||||
buf[1] = '0' + (a%1000000000)/100000000;
|
||||
buf[2] = '0' + (a%100000000)/10000000;
|
||||
buf[3] = '0' + (a%10000000)/1000000;
|
||||
buf[4] = '0' + (a%1000000)/100000;
|
||||
buf[5] = '0' + (a%100000)/10000;
|
||||
buf[6] = '0' + (a%10000)/1000;
|
||||
buf[7] = '0' + (a%1000)/100;
|
||||
buf[8] = '0' + (a%100)/10;
|
||||
buf[9] = '0' + (a%10);
|
||||
buf[10] = 0;
|
||||
return buf;
|
||||
}
|
||||
char *U32ToDecStr(uint32 a)
|
||||
{
|
||||
return U32ToDecStr(TempArray,a);
|
||||
}
|
||||
|
||||
char *U16ToHexStr(uint16 a)
|
||||
{
|
||||
TempArray[0] = a/4096 > 9?'A'+a/4096-10:'0' + a/4096;
|
||||
TempArray[1] = (a%4096)/256 > 9?'A'+(a%4096)/256 - 10:'0' + (a%4096)/256;
|
||||
TempArray[2] = (a%256)/16 > 9?'A'+(a%256)/16 - 10:'0' + (a%256)/16;
|
||||
TempArray[3] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
|
||||
TempArray[4] = 0;
|
||||
return TempArray;
|
||||
}
|
||||
|
||||
char *U8ToHexStr(uint8 a)
|
||||
{
|
||||
TempArray[0] = a/16 > 9?'A'+a/16 - 10:'0' + a/16;
|
||||
TempArray[1] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
|
||||
TempArray[2] = 0;
|
||||
return TempArray;
|
||||
}
|
|
@ -22,12 +22,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
//definitions for str_strip() flags
|
||||
#define STRIP_SP 0x01 /* space */
|
||||
#define STRIP_TAB 0x02 /* tab */
|
||||
#define STRIP_CR 0x04 /* carriage return */
|
||||
#define STRIP_LF 0x08 /* line feed */
|
||||
#define STRIP_SP 0x01 // space
|
||||
#define STRIP_TAB 0x02 // tab
|
||||
#define STRIP_CR 0x04 // carriage return
|
||||
#define STRIP_LF 0x08 // line feed
|
||||
|
||||
|
||||
int str_ucase(char *str);
|
||||
|
@ -43,4 +44,12 @@ std::string BytesToString(void* data, int len);
|
|||
bool StringToBytes(std::string& str, void* data, int len);
|
||||
|
||||
std::vector<std::string> tokenize_str(const std::string & str,const std::string & delims);
|
||||
void splitpath(const char* path, char* drv, char* dir, char* name, char* ext);
|
||||
void splitpath(const char* path, char* drv, char* dir, char* name, char* ext);
|
||||
|
||||
uint16 FastStrToU16(char* s, bool& valid);
|
||||
char *U16ToDecStr(uint16 a);
|
||||
char *U32ToDecStr(uint32 a);
|
||||
char *U32ToDecStr(char* buf, uint32 a);
|
||||
char *U8ToDecStr(uint8 a);
|
||||
char *U8ToHexStr(uint8 a);
|
||||
char *U16ToHexStr(uint16 a);
|
Loading…
Reference in New Issue