mirror of
https://github.com/dborth/fceugx.git
synced 2024-12-25 16:11:54 +01:00
278 lines
5.0 KiB
C
278 lines
5.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "types.h"
|
|
#include "input.h"
|
|
#include "fceu.h"
|
|
#include "driver.h"
|
|
#include "state.h"
|
|
#include "general.h"
|
|
#include "video.h"
|
|
|
|
static int current = 0; // > 0 for recording, < 0 for playback
|
|
static FILE *slots[10]={0};
|
|
static uint8 joop[4];
|
|
static uint32 framets;
|
|
|
|
/* Cache variables used for playback. */
|
|
static uint32 nextts;
|
|
static int nextd;
|
|
|
|
|
|
static int CurrentMovie = 0;
|
|
static int MovieShow = 0;
|
|
|
|
static int MovieStatus[10];
|
|
|
|
static void DoEncode(int joy, int button, int);
|
|
|
|
int FCEUMOV_IsPlaying(void)
|
|
{
|
|
if(current < 0) return(1);
|
|
else return(0);
|
|
}
|
|
|
|
void FCEUI_SaveMovie(char *fname)
|
|
{
|
|
FILE *fp;
|
|
char *fn;
|
|
|
|
if(current < 0) /* Can't interrupt playback.*/
|
|
return;
|
|
|
|
if(current > 0) /* Stop saving. */
|
|
{
|
|
DoEncode(0,0,1); /* Write a dummy timestamp value so that the movie will keep
|
|
"playing" after user input has stopped.
|
|
*/
|
|
fclose(slots[current-1]);
|
|
MovieStatus[current - 1] = 1;
|
|
current=0;
|
|
FCEU_DispMessage("Movie recording stopped.");
|
|
return;
|
|
}
|
|
|
|
current=CurrentMovie;
|
|
|
|
if(fname)
|
|
fp = FCEUD_UTF8fopen(fname, "wb");
|
|
else
|
|
{
|
|
fp=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0),"wb");
|
|
free(fn);
|
|
}
|
|
|
|
if(!fp) return;
|
|
|
|
FCEUSS_SaveFP(fp);
|
|
fseek(fp, 0, SEEK_END);
|
|
slots[current] = fp;
|
|
memset(joop,0,sizeof(joop));
|
|
current++;
|
|
framets=0;
|
|
FCEUI_SelectMovie(CurrentMovie); /* Quick hack to display status. */
|
|
}
|
|
|
|
static void StopPlayback(void)
|
|
{
|
|
fclose(slots[-1 - current]);
|
|
current=0;
|
|
FCEU_DispMessage("Movie playback stopped.");
|
|
}
|
|
|
|
void FCEUMOV_Stop(void)
|
|
{
|
|
if(current < 0) StopPlayback();
|
|
}
|
|
|
|
void FCEUI_LoadMovie(char *fname)
|
|
{
|
|
FILE *fp;
|
|
char *fn;
|
|
|
|
if(current > 0) /* Can't interrupt recording.*/
|
|
return;
|
|
|
|
if(current < 0) /* Stop playback. */
|
|
{
|
|
StopPlayback();
|
|
return;
|
|
}
|
|
|
|
if(fname)
|
|
fp = FCEUD_UTF8fopen(fname, "rb");
|
|
else
|
|
{
|
|
fp=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0),"rb");
|
|
free(fn);
|
|
}
|
|
if(!fp) return;
|
|
|
|
if(!FCEUSS_LoadFP(fp)) return;
|
|
|
|
current = CurrentMovie;
|
|
slots[current] = fp;
|
|
|
|
memset(joop,0,sizeof(joop));
|
|
current = -1 - current;
|
|
framets=0;
|
|
nextts=0;
|
|
nextd = -1;
|
|
MovieStatus[CurrentMovie] = 1;
|
|
FCEUI_SelectMovie(CurrentMovie); /* Quick hack to display status. */
|
|
}
|
|
|
|
|
|
static void DoEncode(int joy, int button, int dummy)
|
|
{
|
|
uint8 d;
|
|
|
|
d = 0;
|
|
|
|
if(framets >= 65536)
|
|
d = 3 << 5;
|
|
else if(framets >= 256)
|
|
d = 2 << 5;
|
|
else if(framets > 0)
|
|
d = 1 << 5;
|
|
|
|
if(dummy) d|=0x80;
|
|
|
|
d |= joy << 3;
|
|
d |= button;
|
|
|
|
fputc(d, slots[current - 1]);
|
|
//printf("Wr: %02x, %d\n",d,slots[current-1]);
|
|
while(framets)
|
|
{
|
|
fputc(framets & 0xff, slots[current - 1]);
|
|
//printf("Wrts: %02x\n",framets & 0xff);
|
|
framets >>= 8;
|
|
}
|
|
}
|
|
|
|
void FCEUMOV_AddJoy(uint8 *js)
|
|
{
|
|
int x,y;
|
|
|
|
if(!current) return; /* Not playback nor recording. */
|
|
|
|
if(current < 0) /* Playback */
|
|
{
|
|
while(nextts == framets)
|
|
{
|
|
int tmp,ti;
|
|
uint8 d;
|
|
|
|
if(nextd != -1)
|
|
{
|
|
if(nextd&0x80)
|
|
{
|
|
//puts("Egads");
|
|
FCEU_DoSimpleCommand(nextd&0x1F);
|
|
}
|
|
else
|
|
joop[(nextd >> 3)&0x3] ^= 1 << (nextd&0x7);
|
|
}
|
|
|
|
|
|
tmp = fgetc(slots[-1 - current]);
|
|
d = tmp;
|
|
|
|
if(tmp < 0)
|
|
{
|
|
StopPlayback();
|
|
return;
|
|
}
|
|
|
|
nextts = 0;
|
|
tmp >>= 5;
|
|
tmp &= 0x3;
|
|
ti=0;
|
|
|
|
int tmpfix = tmp;
|
|
while(tmp--) { nextts |= fgetc(slots[-1 - current]) << (ti * 8); ti++; }
|
|
|
|
// This fixes a bug in movies recorded before version 0.98.11
|
|
// It's probably not necessary, but it may keep away CRAZY PEOPLE who recorded
|
|
// movies on <= 0.98.10 and don't work on playback.
|
|
if(tmpfix == 1 && !nextts)
|
|
{nextts |= fgetc(slots[-1 - current])<<8; }
|
|
else if(tmpfix == 2 && !nextts) {nextts |= fgetc(slots[-1 - current])<<16; }
|
|
|
|
framets = 0;
|
|
nextd = d;
|
|
}
|
|
memcpy(js,joop,4);
|
|
}
|
|
else /* Recording */
|
|
{
|
|
for(x=0;x<4;x++)
|
|
{
|
|
if(js[x] != joop[x])
|
|
{
|
|
for(y=0;y<8;y++)
|
|
if((js[x] ^ joop[x]) & (1 << y))
|
|
DoEncode(x, y, 0);
|
|
joop[x] = js[x];
|
|
}
|
|
else if(framets == ((1<<24)-1)) DoEncode(0,0,1); /* Overflow will happen, so do dummy update. */
|
|
}
|
|
}
|
|
framets++;
|
|
}
|
|
|
|
void FCEUMOV_AddCommand(int cmd)
|
|
{
|
|
if(current <= 0) return; /* Return if not recording a movie */
|
|
//printf("%d\n",cmd);
|
|
DoEncode((cmd>>3)&0x3,cmd&0x7,1);
|
|
}
|
|
|
|
void FCEUMOV_CheckMovies(void)
|
|
{
|
|
FILE *st=NULL;
|
|
char *fn;
|
|
int ssel;
|
|
|
|
for(ssel=0;ssel<10;ssel++)
|
|
{
|
|
st=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_MOVIE,ssel,0),"rb");
|
|
free(fn);
|
|
if(st)
|
|
{
|
|
MovieStatus[ssel]=1;
|
|
fclose(st);
|
|
}
|
|
else
|
|
MovieStatus[ssel]=0;
|
|
}
|
|
|
|
}
|
|
|
|
void FCEUI_SelectMovie(int w)
|
|
{
|
|
if(w == -1) { MovieShow = 0; return; }
|
|
FCEUI_SelectState(-1);
|
|
|
|
CurrentMovie=w;
|
|
MovieShow=180;
|
|
|
|
if(current > 0)
|
|
FCEU_DispMessage("-recording movie %d-",current-1);
|
|
else if (current < 0)
|
|
FCEU_DispMessage("-playing movie %d-",-1 - current);
|
|
else
|
|
FCEU_DispMessage("-select movie-");
|
|
}
|
|
|
|
void FCEU_DrawMovies(uint8 *XBuf)
|
|
{
|
|
if(!MovieShow) return;
|
|
|
|
FCEU_DrawNumberRow(XBuf,MovieStatus, CurrentMovie);
|
|
MovieShow--;
|
|
}
|
|
|