Add new field 'rtcStart' to the movie. It specifies the time of RTC at the beginning of the movie. (needs more test!)
TODO: record firmware settings as well.
This commit is contained in:
parent
196170a5c0
commit
1d0743861b
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "aggdraw.h"
|
||||
#include "movie.h"
|
||||
#include "rtc.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "mic.h"
|
||||
#include "saves.h"
|
||||
|
|
|
@ -189,7 +189,7 @@ void CommandLine::process_movieCommands()
|
|||
}
|
||||
else if(record_movie_file != "")
|
||||
{
|
||||
FCEUI_SaveMovie(record_movie_file.c_str(), L"", 0, NULL);
|
||||
FCEUI_SaveMovie(record_movie_file.c_str(), L"", 0, NULL, FCEUI_MovieGetRTCDefault());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -763,7 +763,7 @@ static void RecordMovieDialog()
|
|||
switch(gtk_dialog_run(GTK_DIALOG(pFileSelection))) {
|
||||
case GTK_RESPONSE_OK:
|
||||
sPath = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection));
|
||||
FCEUI_SaveMovie(sPath,L"",0,NULL);
|
||||
FCEUI_SaveMovie(sPath,L"",0,NULL, FCEUI_MovieGetRTCDefault());
|
||||
g_free(sPath);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include "utils/guid.h"
|
||||
#include "utils/xstring.h"
|
||||
#include "movie.h"
|
||||
|
@ -166,12 +168,37 @@ void MovieRecord::dump(MovieData* md, EMUFILE* fp, int index)
|
|||
fp->fputc('\n');
|
||||
}
|
||||
|
||||
time_t FCEUI_MovieGetRTCDefault()
|
||||
{
|
||||
time_t timer;
|
||||
|
||||
// compatible with old desmume
|
||||
struct tm t;
|
||||
t.tm_year = 109; // 2009
|
||||
t.tm_mon = 0; // 1 (Jan)
|
||||
t.tm_mday = 1;
|
||||
t.tm_wday = 4;
|
||||
t.tm_hour = 12;
|
||||
t.tm_min = 0;
|
||||
t.tm_sec = 0;
|
||||
t.tm_isdst= -1;
|
||||
timer = gmmktime(&t);
|
||||
|
||||
// current time
|
||||
//timer = time(NULL);
|
||||
//struct tm *tp = localtime(&timer);
|
||||
//timer = gmmktime(tp);
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
MovieData::MovieData()
|
||||
: version(MOVIE_VERSION)
|
||||
, emuVersion(EMU_DESMUME_VERSION_NUMERIC())
|
||||
, romChecksum(0)
|
||||
, rerecordCount(0)
|
||||
, binaryFlag(false)
|
||||
, rtcStart(FCEUI_MovieGetRTCDefault())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -199,6 +226,30 @@ void MovieData::installValue(std::string& key, std::string& val)
|
|||
romSerial = val;
|
||||
else if(key == "guid")
|
||||
guid = Desmume_Guid::fromString(val);
|
||||
else if(key == "rtcStart") {
|
||||
// sloppy format check and parse
|
||||
char *validFormatStr = "####-##-##T##:##:##Z";
|
||||
bool validFormat = true;
|
||||
for (int i = 0; validFormatStr[i] != '\0'; i++) {
|
||||
if (validFormatStr[i] != val[i] &&
|
||||
!(validFormatStr[i] == '#' && isdigit(val[i]))) {
|
||||
validFormat = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (validFormat) {
|
||||
struct tm t;
|
||||
const char *s = val.data();
|
||||
t.tm_year = atoi(&s[0]) - 1900;
|
||||
t.tm_mon = atoi(&s[5]) - 1;
|
||||
t.tm_mday = atoi(&s[8]);
|
||||
t.tm_hour = atoi(&s[11]);
|
||||
t.tm_min = atoi(&s[14]);
|
||||
t.tm_sec = atoi(&s[17]);
|
||||
t.tm_isdst= -1;
|
||||
rtcStart = gmmktime(&t);
|
||||
}
|
||||
}
|
||||
else if(key == "comment")
|
||||
comments.push_back(mbstowcs(val));
|
||||
else if(key == "binary")
|
||||
|
@ -242,12 +293,17 @@ int MovieData::dump(EMUFILE* fp, bool binary)
|
|||
if(CommonSettings.UseExtBIOS)
|
||||
fp->fprintf("swiFromBios %d\n", CommonSettings.SWIFromBIOS);
|
||||
|
||||
char timestr[32];
|
||||
struct tm *tm = gmtime(&rtcStart);
|
||||
strftime(timestr, 32, "%Y-%m-%dT%H:%M:%SZ", tm);
|
||||
fp->fprintf("rtcStart %s\n", timestr);
|
||||
|
||||
for(uint32 i=0;i<comments.size();i++)
|
||||
fp->fprintf("comment %s\n", wcstombs(comments[i]).c_str());
|
||||
|
||||
if(binary)
|
||||
fp->fprintf("binary 1\n");
|
||||
|
||||
|
||||
if(savestate.size() != 0)
|
||||
fp->fprintf("savestate %s\n", BytesToString(&savestate[0],savestate.size()).c_str());
|
||||
if(sram.size() != 0)
|
||||
|
@ -495,7 +551,6 @@ const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tas
|
|||
movie_readonly = _read_only;
|
||||
movieMode = MOVIEMODE_PLAY;
|
||||
currRerecordCount = currMovieData.rerecordCount;
|
||||
InitMovieTime();
|
||||
MMU_new.backupDevice.movie_mode();
|
||||
if(currMovieData.sram.size() != 0)
|
||||
{
|
||||
|
@ -564,7 +619,7 @@ bool MovieData::loadSramFrom(std::vector<u8>* buf)
|
|||
|
||||
//begin recording a new movie
|
||||
//TODO - BUG - the record-from-another-savestate doesnt work.
|
||||
void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname)
|
||||
void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, time_t rtcstart)
|
||||
{
|
||||
//if(!FCEU_IsValidUI(FCEUI_RECORDMOVIE))
|
||||
// return;
|
||||
|
@ -585,7 +640,8 @@ void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, s
|
|||
currMovieData.romChecksum = gameInfo.crc;
|
||||
currMovieData.romSerial = gameInfo.ROMserial;
|
||||
currMovieData.romFilename = path.GetRomName();
|
||||
|
||||
currMovieData.rtcStart = rtcstart;
|
||||
|
||||
NDS_Reset();
|
||||
|
||||
//todo ?
|
||||
|
@ -608,7 +664,6 @@ void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, s
|
|||
movieMode = MOVIEMODE_RECORD;
|
||||
movie_readonly = false;
|
||||
currRerecordCount = 0;
|
||||
InitMovieTime();
|
||||
MMU_new.backupDevice.movie_mode();
|
||||
|
||||
if(currMovieData.sram.size() != 0)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "emufile.h"
|
||||
|
||||
#include "utils/guid.h"
|
||||
|
@ -128,6 +129,8 @@ public:
|
|||
int rerecordCount;
|
||||
Desmume_Guid guid;
|
||||
|
||||
s64 rtcStart; // (time_t) it always means gmtime, not localtime.
|
||||
|
||||
//was the frame data stored in binary?
|
||||
bool binaryFlag;
|
||||
|
||||
|
@ -192,7 +195,7 @@ extern MovieData currMovieData; //adelikat: main needs this for frame counter d
|
|||
extern bool movie_reset_command;
|
||||
|
||||
bool FCEUI_MovieGetInfo(EMUFILE* fp, MOVIE_INFO& info, bool skipFrameCount);
|
||||
void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname);
|
||||
void _CDECL_ FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, time_t rtcstart);
|
||||
const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe); // returns NULL on success, errmsg on failure
|
||||
void FCEUI_StopMovie();
|
||||
void FCEUMOV_AddInputState();
|
||||
|
@ -205,4 +208,5 @@ bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader);
|
|||
extern bool movie_readonly;
|
||||
extern bool ShowInputDisplay;
|
||||
void FCEUI_MakeBackupMovie(bool dispMessage);
|
||||
time_t FCEUI_MovieGetRTCDefault();
|
||||
#endif
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "armcpu.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "saves.h"
|
||||
#ifdef WIN32
|
||||
|
@ -36,6 +35,23 @@
|
|||
#endif
|
||||
#include "movie.h"
|
||||
|
||||
static time_t CalcTimeDifference(void)
|
||||
{
|
||||
time_t t1, t2;
|
||||
tm *tm_tmp;
|
||||
|
||||
time(&t1);
|
||||
tm_tmp = gmtime(&t1);
|
||||
t2 = mktime(tm_tmp);
|
||||
|
||||
return (t2 - t1);
|
||||
}
|
||||
|
||||
time_t gmmktime(struct tm *timeptr)
|
||||
{
|
||||
return mktime(timeptr) - CalcTimeDifference();
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// RTC registers
|
||||
|
@ -94,50 +110,38 @@ static const u8 kDefaultCmdBitsSize[8] = {8, 8, 56, 24, 0, 24, 8, 8};
|
|||
|
||||
#define toBCD(x) ((x / 10) << 4) | (x % 10);
|
||||
|
||||
struct movietime {
|
||||
|
||||
int sec;
|
||||
int minute;
|
||||
int hour;
|
||||
int monthday;
|
||||
int month;
|
||||
int year;
|
||||
int weekday;
|
||||
};
|
||||
|
||||
struct movietime movie;
|
||||
|
||||
bool moviemode=false;
|
||||
|
||||
void InitMovieTime(void)
|
||||
struct tm* rtcGetTime(void)
|
||||
{
|
||||
movie.year=9;
|
||||
movie.month=1;
|
||||
movie.monthday=1;
|
||||
movie.weekday=4;
|
||||
}
|
||||
if(movieMode == MOVIEMODE_INACTIVE) {
|
||||
time_t timer;
|
||||
time(&timer);
|
||||
return localtime(&timer);
|
||||
}
|
||||
else {
|
||||
//now, you might think it is silly to go through all these conniptions
|
||||
//when we could just assume that there are 60fps and base the seconds on frameCounter/60
|
||||
//but, we were imagining that one day we might need more precision
|
||||
|
||||
static void MovieTime(void) {
|
||||
const u32 arm9rate_unitsperframe = 560190<<1;
|
||||
const u32 arm9rate_unitspersecond = (u32)(arm9rate_unitsperframe * 59.8261);
|
||||
|
||||
//now, you might think it is silly to go through all these conniptions
|
||||
//when we could just assume that there are 60fps and base the seconds on frameCounter/60
|
||||
//but, we were imagining that one day we might need more precision
|
||||
u64 totalcycles = (u64)arm9rate_unitsperframe * currFrameCounter;
|
||||
u64 totalseconds=totalcycles/arm9rate_unitspersecond;
|
||||
|
||||
const u32 arm9rate_unitsperframe = 560190<<1;
|
||||
const u32 arm9rate_unitspersecond = (u32)(arm9rate_unitsperframe * 59.8261);
|
||||
const u64 noon = (u64)arm9rate_unitspersecond * 60 * 60 * 12;
|
||||
|
||||
u64 frameCycles = (u64)arm9rate_unitsperframe * currFrameCounter;
|
||||
u64 totalcycles = frameCycles + noon;
|
||||
u64 totalseconds=totalcycles/arm9rate_unitspersecond;
|
||||
time_t timer;
|
||||
struct tm t;
|
||||
|
||||
movie.sec=(int)(totalseconds % 60);
|
||||
movie.minute=(int)(totalseconds/60);
|
||||
movie.hour=movie.minute/60;
|
||||
|
||||
//convert to sane numbers
|
||||
movie.minute=movie.minute % 60;
|
||||
movie.hour=movie.hour % 24;
|
||||
// store start time into structure tm
|
||||
timer = (time_t) currMovieData.rtcStart;
|
||||
memcpy(&t, gmtime(&timer), sizeof(struct tm));
|
||||
// advance it according to the frame counter
|
||||
t.tm_sec += totalseconds;
|
||||
// then, normalize it
|
||||
timer = gmmktime(&t);
|
||||
return gmtime(&timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtcRecv()
|
||||
|
@ -160,67 +164,26 @@ static void rtcRecv()
|
|||
case 2: // date & time
|
||||
{
|
||||
//INFO("RTC: read date & time\n");
|
||||
time_t tm;
|
||||
time(&tm);
|
||||
struct tm *tm_local= localtime(&tm);
|
||||
tm_local->tm_year %= 100;
|
||||
tm_local->tm_mon++;
|
||||
|
||||
if(movieMode != MOVIEMODE_INACTIVE) {
|
||||
|
||||
MovieTime();
|
||||
|
||||
rtc.data[0]=toBCD(movie.year);
|
||||
rtc.data[1]=toBCD(movie.month);
|
||||
rtc.data[2]=toBCD(movie.monthday);
|
||||
rtc.data[3]=(movie.weekday + 7) & 7;
|
||||
if (rtc.data[3] == 7) rtc.data[3] = 6;
|
||||
if (!(rtc.regStatus1 & 0x02)) movie.hour %= 12;
|
||||
rtc.data[4] = ((movie.hour < 12) ? 0x00 : 0x40) | toBCD(movie.hour);
|
||||
rtc.data[5]=toBCD(movie.minute);
|
||||
rtc.data[6]=toBCD(movie.sec);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
||||
rtc.data[0] = toBCD(tm_local->tm_year);
|
||||
rtc.data[1] = toBCD(tm_local->tm_mon);
|
||||
rtc.data[2] = toBCD(tm_local->tm_mday);
|
||||
rtc.data[3] = (tm_local->tm_wday + 7) & 7;
|
||||
if (rtc.data[3] == 7) rtc.data[3] = 6;
|
||||
if (!(rtc.regStatus1 & 0x02)) tm_local->tm_hour %= 12;
|
||||
rtc.data[4] = ((tm_local->tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm_local->tm_hour);
|
||||
rtc.data[5] = toBCD(tm_local->tm_min);
|
||||
rtc.data[6] = toBCD(tm_local->tm_sec);
|
||||
break;
|
||||
}
|
||||
struct tm *tm = rtcGetTime();
|
||||
rtc.data[0] = toBCD(tm->tm_year % 100);
|
||||
rtc.data[1] = toBCD(tm->tm_mon + 1);
|
||||
rtc.data[2] = toBCD(tm->tm_mday);
|
||||
rtc.data[3] = (tm->tm_wday + 7) & 7;
|
||||
if (rtc.data[3] == 7) rtc.data[3] = 6;
|
||||
if (!(rtc.regStatus1 & 0x02)) tm->tm_hour %= 12;
|
||||
rtc.data[4] = ((tm->tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm->tm_hour);
|
||||
rtc.data[5] = toBCD(tm->tm_min);
|
||||
rtc.data[6] = toBCD(tm->tm_sec);
|
||||
break;
|
||||
}
|
||||
case 3: // time
|
||||
{
|
||||
//INFO("RTC: read time\n");
|
||||
time_t tm;
|
||||
time(&tm);
|
||||
struct tm *tm_local= localtime(&tm);
|
||||
|
||||
if(movieMode != MOVIEMODE_INACTIVE) {
|
||||
|
||||
MovieTime();
|
||||
|
||||
if (!(rtc.regStatus1 & 0x02)) movie.hour %= 12;
|
||||
rtc.data[0] = ((movie.hour < 12) ? 0x00 : 0x40) | toBCD(movie.hour);
|
||||
rtc.data[1] = toBCD(movie.minute);
|
||||
rtc.data[2] = toBCD(movie.sec);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
||||
if (!(rtc.regStatus1 & 0x02)) tm_local->tm_hour %= 12;
|
||||
rtc.data[0] = ((tm_local->tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm_local->tm_hour);
|
||||
rtc.data[1] = toBCD(tm_local->tm_min);
|
||||
rtc.data[2] = toBCD(tm_local->tm_sec);
|
||||
break;
|
||||
}
|
||||
struct tm *tm = rtcGetTime();
|
||||
if (!(rtc.regStatus1 & 0x02)) tm->tm_hour %= 12;
|
||||
rtc.data[0] = ((tm->tm_hour < 12) ? 0x00 : 0x40) | toBCD(tm->tm_hour);
|
||||
rtc.data[1] = toBCD(tm->tm_min);
|
||||
rtc.data[2] = toBCD(tm->tm_sec);
|
||||
break;
|
||||
}
|
||||
case 4: // freq/alarm 1
|
||||
|
|
|
@ -25,11 +25,14 @@
|
|||
#ifndef _RTC_H_
|
||||
#define _RTC_H_
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "types.h"
|
||||
|
||||
extern time_t gmmktime(struct tm *timeptr);
|
||||
|
||||
struct tm* rtcGetTime(void);
|
||||
|
||||
extern void rtcInit();
|
||||
extern u16 rtcRead();
|
||||
extern void rtcWrite(u16 val);
|
||||
|
||||
void InitMovieTime(void);
|
||||
#endif
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
|
||||
#include <io.h>
|
||||
#include <fstream>
|
||||
#include <time.h>
|
||||
#include "resource.h"
|
||||
#include "replay.h"
|
||||
#include "common.h"
|
||||
#include "main.h"
|
||||
#include "movie.h"
|
||||
#include "rtc.h"
|
||||
#include "utils/xstring.h"
|
||||
|
||||
bool replayreadonly=1;
|
||||
|
@ -248,12 +250,28 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
|
|||
static struct CreateMovieParameters* p = NULL;
|
||||
std::wstring author = L"";
|
||||
std::string fname;
|
||||
SYSTEMTIME systime;
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
case WM_INITDIALOG: {
|
||||
CheckDlgButton(hwndDlg, IDC_START_FROM_SRAM, ((flag == 1) ? BST_CHECKED : BST_UNCHECKED));
|
||||
SetFocus(GetDlgItem(hwndDlg, IDC_EDIT_FILENAME));
|
||||
|
||||
time_t timer = FCEUI_MovieGetRTCDefault();
|
||||
struct tm *t = gmtime(&timer);
|
||||
ZeroMemory(&systime, sizeof(systime));
|
||||
systime.wYear = t->tm_year + 1900;
|
||||
systime.wMonth = t->tm_mon + 1;
|
||||
systime.wDay = t->tm_mday;
|
||||
systime.wDayOfWeek = t->tm_wday;
|
||||
systime.wHour = t->tm_hour;
|
||||
systime.wMinute = t->tm_min;
|
||||
systime.wSecond = t->tm_sec;
|
||||
systime.wMilliseconds = 0;
|
||||
DateTime_SetSystemtime(GetDlgItem(hwndDlg, IDC_DTP_DATE), GDT_VALID, &systime);
|
||||
DateTime_SetSystemtime(GetDlgItem(hwndDlg, IDC_DTP_TIME), GDT_VALID, &systime);
|
||||
return false;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
|
@ -264,7 +282,22 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
|
|||
std::string sramfname = GetDlgItemText<MAX_PATH>(hwndDlg,IDC_EDIT_SRAMFILENAME);
|
||||
if (fname.length())
|
||||
{
|
||||
FCEUI_SaveMovie(fname.c_str(), author, flag, sramfname);
|
||||
time_t rtcstart;
|
||||
struct tm t;
|
||||
|
||||
DateTime_GetSystemtime(GetDlgItem(hwndDlg, IDC_DTP_DATE), &systime);
|
||||
t.tm_year = systime.wYear - 1900;
|
||||
t.tm_mon = systime.wMonth - 1;
|
||||
t.tm_mday = systime.wDay;
|
||||
t.tm_wday = systime.wDayOfWeek;
|
||||
DateTime_GetSystemtime(GetDlgItem(hwndDlg, IDC_DTP_TIME), &systime);
|
||||
t.tm_hour = systime.wHour;
|
||||
t.tm_min = systime.wMinute;
|
||||
t.tm_sec = systime.wSecond;
|
||||
t.tm_isdst= -1;
|
||||
rtcstart = gmmktime(&t);
|
||||
|
||||
FCEUI_SaveMovie(fname.c_str(), author, flag, sramfname, rtcstart);
|
||||
EndDialog(hwndDlg, 0);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -353,8 +353,10 @@
|
|||
#define IDC_CAP1_CURDAD 1026
|
||||
#define IDC_CHECBOX_ADVANCEDTIMING 1026
|
||||
#define IDC_DEFAULT 1027
|
||||
#define IDC_DTP_DATE 1027
|
||||
#define IDC_3DCORE 1028
|
||||
#define IDC_SNDCTRL_ENABLE 1028
|
||||
#define IDC_DTP_TIME 1028
|
||||
#define IDC_TXT_COMPILED 1029
|
||||
#define IDC_SNDCTRL_CH1NOMIX 1029
|
||||
#define IDC_TXT_VERSION 1030
|
||||
|
@ -908,7 +910,7 @@
|
|||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 121
|
||||
#define _APS_NEXT_COMMAND_VALUE 40078
|
||||
#define _APS_NEXT_CONTROL_VALUE 1027
|
||||
#define _APS_NEXT_CONTROL_VALUE 1029
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue