Fixed subtitles when used with chapters. Enhanced messages. Fixed previous chapter seek later bug. Previous chapter when none left restarts play. Increased previous chapter previous chapter threshold.
This commit is contained in:
@@ -37,94 +37,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#include "numconv.h"
|
||||
|
||||
|
||||
/*
|
||||
Nach's insane subtitle library for movies files :)
|
||||
|
||||
The filename would be gamename.sub in the same directory the ZMV would be in.
|
||||
If you're playing gamename.zm1, then the sub file will be gamename.su1 etc...
|
||||
|
||||
Format of the sub file:
|
||||
Start Frame:Frame Duration:Message
|
||||
|
||||
Example:
|
||||
1:180:Hi how are you?
|
||||
300:180:Isn't this cool?
|
||||
700:180:This is great :)
|
||||
2500:375:Kill 'em!
|
||||
3500:20:Did you see this?
|
||||
*/
|
||||
|
||||
static struct
|
||||
{
|
||||
FILE *fp;
|
||||
char linebuf[256];
|
||||
size_t frame_current;
|
||||
size_t message_start;
|
||||
size_t message_duration;
|
||||
} MovieSub;
|
||||
|
||||
static void MovieSub_Open(const char *filename)
|
||||
{
|
||||
MovieSub.fp = fopen(filename, "r");
|
||||
MovieSub.frame_current = 0;
|
||||
MovieSub.message_start = 0;
|
||||
MovieSub.message_duration = 0;
|
||||
}
|
||||
|
||||
static void MovieSub_Close()
|
||||
{
|
||||
if (MovieSub.fp)
|
||||
{
|
||||
fclose(MovieSub.fp);
|
||||
MovieSub.fp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char *MovieSub_GetData()
|
||||
{
|
||||
if (MovieSub.fp)
|
||||
{
|
||||
char *i, *num;
|
||||
|
||||
MovieSub.frame_current++;
|
||||
|
||||
if (MovieSub.frame_current > MovieSub.message_start + MovieSub.message_duration)
|
||||
{
|
||||
MovieSub.message_duration = 0;
|
||||
fgets(MovieSub.linebuf, 256, MovieSub.fp);
|
||||
if (!(num = strtok(MovieSub.linebuf, ":"))) { return(0); }
|
||||
for (i = num; *i; i++)
|
||||
{
|
||||
if (!isdigit(*i)) { return(0); }
|
||||
}
|
||||
MovieSub.message_start = atoi(num);
|
||||
if (!(num = strtok(0, ":"))) { return(0); }
|
||||
for (i = num; *i; i++)
|
||||
{
|
||||
if (!isdigit(*i))
|
||||
{
|
||||
MovieSub.message_start = 0;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
MovieSub.message_duration = atoi(num);
|
||||
}
|
||||
|
||||
if (MovieSub.frame_current == MovieSub.message_start)
|
||||
{
|
||||
return(strtok(0, ":"));
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static size_t MovieSub_GetDuration()
|
||||
{
|
||||
return(MovieSub.message_duration);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
extern unsigned int versionNumber;
|
||||
extern unsigned int CRC32;
|
||||
@@ -676,6 +588,7 @@ static struct
|
||||
unsigned short external_chapter_count;
|
||||
unsigned int frames_replayed;
|
||||
size_t last_chapter_frame;
|
||||
size_t input_start_pos;
|
||||
} zmv_open_vars; //Additional vars for open/replay of a ZMV
|
||||
|
||||
static bool zmv_open(char *filename)
|
||||
@@ -687,7 +600,6 @@ static bool zmv_open(char *filename)
|
||||
if (zmv_vars.fp && zmv_header_read(&zmv_vars.header, zmv_vars.fp) &&
|
||||
!strncmp(zmv_vars.header.magic, "ZMV", 3))
|
||||
{
|
||||
size_t input_start_pos;
|
||||
unsigned short i;
|
||||
|
||||
if (zmv_vars.header.zsnes_version != (versionNumber & 0xFFFF))
|
||||
@@ -701,7 +613,7 @@ static bool zmv_open(char *filename)
|
||||
}
|
||||
|
||||
zst_load(zmv_vars.fp);
|
||||
input_start_pos = ftell(zmv_vars.fp);
|
||||
zmv_open_vars.input_start_pos = ftell(zmv_vars.fp);
|
||||
|
||||
fseek(zmv_vars.fp, -2, SEEK_END);
|
||||
zmv_open_vars.external_chapter_count = fread2(zmv_vars.fp);
|
||||
@@ -716,7 +628,7 @@ static bool zmv_open(char *filename)
|
||||
internal_chapter_add_offset(&zmv_open_vars.external_chapters, fread4(zmv_vars.fp));
|
||||
}
|
||||
|
||||
fseek(zmv_vars.fp, input_start_pos, SEEK_SET);
|
||||
fseek(zmv_vars.fp, zmv_open_vars.input_start_pos, SEEK_SET);
|
||||
|
||||
return(true);
|
||||
}
|
||||
@@ -773,7 +685,7 @@ static bool zmv_replay()
|
||||
return(false);
|
||||
}
|
||||
|
||||
static void zmv_next_chapter()
|
||||
static bool zmv_next_chapter()
|
||||
{
|
||||
size_t current_loc = ftell(zmv_vars.fp);
|
||||
|
||||
@@ -818,7 +730,17 @@ static void zmv_next_chapter()
|
||||
|
||||
fseek(zmv_vars.fp, next_external, SEEK_SET);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
static void zmv_rewind_playback()
|
||||
{
|
||||
fseek(zmv_vars.fp, zmv_open_vars.input_start_pos - cur_zst_size, SEEK_SET);
|
||||
zst_load(zmv_vars.fp);
|
||||
zmv_open_vars.frames_replayed = 0;
|
||||
zmv_open_vars.last_chapter_frame = 0;
|
||||
}
|
||||
|
||||
static void zmv_prev_chapter()
|
||||
@@ -843,13 +765,25 @@ static void zmv_prev_chapter()
|
||||
prev = prev_external;
|
||||
}
|
||||
|
||||
if (!prev)
|
||||
{
|
||||
zmv_rewind_playback();
|
||||
return;
|
||||
}
|
||||
|
||||
//Code to go back before the previous chapter if the previous chapter was loaded recently
|
||||
if (zmv_open_vars.frames_replayed - zmv_open_vars.last_chapter_frame < 90) //1.5 seconds NTSC
|
||||
if (zmv_open_vars.frames_replayed - zmv_open_vars.last_chapter_frame < 150) //2.5 seconds NTSC
|
||||
{
|
||||
size_t pprev = prev-1;
|
||||
size_t pprev_internal = internal_chapter_lesser(&zmv_vars.internal_chapters, pprev);
|
||||
size_t pprev_external = internal_chapter_lesser(&zmv_open_vars.external_chapters, pprev);
|
||||
|
||||
if ((pprev_internal == pprev) && (pprev_external == pprev))
|
||||
{
|
||||
zmv_rewind_playback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pprev_internal != pprev)
|
||||
{
|
||||
prev = prev_internal = pprev_internal;
|
||||
@@ -864,8 +798,6 @@ static void zmv_prev_chapter()
|
||||
}
|
||||
}
|
||||
|
||||
if (prev)
|
||||
{
|
||||
if (prev == prev_internal)
|
||||
{
|
||||
fseek(zmv_vars.fp, prev_internal, SEEK_SET);
|
||||
@@ -888,7 +820,6 @@ static void zmv_prev_chapter()
|
||||
fseek(zmv_vars.fp, prev_external, SEEK_SET);
|
||||
}
|
||||
zmv_open_vars.last_chapter_frame = zmv_open_vars.frames_replayed;
|
||||
}
|
||||
}
|
||||
|
||||
static void zmv_add_chapter()
|
||||
@@ -897,9 +828,11 @@ static void zmv_add_chapter()
|
||||
{
|
||||
size_t current_loc = ftell(zmv_vars.fp);
|
||||
|
||||
//Check if previous input contained internal chapter to here, or if there is external here already
|
||||
if ((internal_chapter_pos(&zmv_vars.internal_chapters, current_loc-(INT_CHAP_SIZE)) == ~0) &&
|
||||
(internal_chapter_pos(&zmv_open_vars.external_chapters, current_loc)) == ~0)
|
||||
{
|
||||
//Check if we have internal right here
|
||||
unsigned char flag;
|
||||
fread(&flag, 1, 1, zmv_vars.fp);
|
||||
|
||||
@@ -918,7 +851,7 @@ static void zmv_add_chapter()
|
||||
|
||||
fseek(zmv_vars.fp, current_loc, SEEK_SET);
|
||||
}
|
||||
else
|
||||
else //Just skip the internal
|
||||
{
|
||||
fseek(zmv_vars.fp, INT_CHAP_SIZE, SEEK_CUR);
|
||||
}
|
||||
@@ -935,6 +868,104 @@ static void zmv_replay_finished()
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
Nach's insane subtitle library for movies files :)
|
||||
|
||||
The filename would be gamename.sub in the same directory the ZMV would be in.
|
||||
If you're playing gamename.zm1, then the sub file will be gamename.su1 etc...
|
||||
|
||||
Format of the sub file:
|
||||
Start Frame:Frame Duration:Message
|
||||
|
||||
Example:
|
||||
1:180:Hi how are you?
|
||||
300:180:Isn't this cool?
|
||||
700:180:This is great :)
|
||||
2500:375:Kill 'em!
|
||||
3500:20:Did you see this? Of course not
|
||||
*/
|
||||
|
||||
static struct
|
||||
{
|
||||
FILE *fp;
|
||||
char linebuf[256];
|
||||
size_t message_start;
|
||||
size_t message_duration;
|
||||
} MovieSub;
|
||||
|
||||
static void MovieSub_Open(const char *filename)
|
||||
{
|
||||
memset(&MovieSub, 0, sizeof(MovieSub));
|
||||
MovieSub.fp = fopen(filename, "r");
|
||||
}
|
||||
|
||||
static void MovieSub_Close()
|
||||
{
|
||||
if (MovieSub.fp)
|
||||
{
|
||||
fclose(MovieSub.fp);
|
||||
MovieSub.fp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char *MovieSub_GetData()
|
||||
{
|
||||
if (MovieSub.fp)
|
||||
{
|
||||
char *i, *num;
|
||||
|
||||
if (zmv_open_vars.frames_replayed > MovieSub.message_start + MovieSub.message_duration)
|
||||
{
|
||||
MovieSub.message_duration = 0;
|
||||
do
|
||||
{
|
||||
if (!fgets(MovieSub.linebuf, 256, MovieSub.fp))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
if (!(num = strtok(MovieSub.linebuf, ":"))) { return(0); }
|
||||
for (i = num; *i; i++)
|
||||
{
|
||||
if (!isdigit(*i)) { return(0); }
|
||||
}
|
||||
MovieSub.message_start = atoi(num);
|
||||
} while(MovieSub.message_start < zmv_open_vars.frames_replayed );
|
||||
if (!(num = strtok(0, ":"))) { return(0); }
|
||||
for (i = num; *i; i++)
|
||||
{
|
||||
if (!isdigit(*i))
|
||||
{
|
||||
MovieSub.message_start = 0;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
MovieSub.message_duration = atoi(num);
|
||||
}
|
||||
|
||||
if (zmv_open_vars.frames_replayed == MovieSub.message_start)
|
||||
{
|
||||
return(strtok(0, ":"));
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static size_t MovieSub_GetDuration()
|
||||
{
|
||||
return(MovieSub.message_duration);
|
||||
}
|
||||
|
||||
static void MovieSub_ResetStream()
|
||||
{
|
||||
rewind(MovieSub.fp);
|
||||
MovieSub.message_start = 0;
|
||||
MovieSub.message_duration = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
ZSNES movie related vars:
|
||||
|
||||
@@ -949,13 +980,6 @@ MovieProcessing
|
||||
|
||||
extern unsigned int MsgCount, MessageOn;
|
||||
extern unsigned char MovieProcessing, *Msgptr;
|
||||
char *txtmovieended = "MOVIE FINISHED.";
|
||||
char *txtaddintchap = "INTERNAL CHAPTER ADDED.";
|
||||
char *txtaddextchap = "EXTERNAL CHAPTER ADDED.";
|
||||
char *txtnomovie = "NO MOVIE PROCESSING.";
|
||||
char *txtseeknext = "NEXT CHAPTER LOADED.";
|
||||
char *txtseekprev = "PREVIOUS CHAPTER LOADED.";
|
||||
char *txtseekrecord = "NO SEEKING DURING RECORD.";
|
||||
|
||||
void MovieInsertChapter()
|
||||
{
|
||||
@@ -963,14 +987,14 @@ void MovieInsertChapter()
|
||||
{
|
||||
case 1: // replaying - external
|
||||
zmv_add_chapter();
|
||||
Msgptr = txtaddextchap;
|
||||
Msgptr = "INTERNAL CHAPTER ADDED.";
|
||||
break;
|
||||
case 2: // recording - internal
|
||||
zmv_insert_chapter();
|
||||
Msgptr = txtaddintchap;
|
||||
Msgptr = "INTERNAL CHAPTER ADDED.";
|
||||
break;
|
||||
default: // no movie processing
|
||||
Msgptr = txtnomovie;
|
||||
Msgptr = "NO MOVIE PROCESSING.";
|
||||
}
|
||||
|
||||
MessageOn = MsgCount;
|
||||
@@ -978,36 +1002,31 @@ void MovieInsertChapter()
|
||||
|
||||
void MovieSeekAhead()
|
||||
{
|
||||
switch (MovieProcessing)
|
||||
if (MovieProcessing == 1) // replaying only - record can use ZMTs
|
||||
{
|
||||
case 1: // replaying ok
|
||||
zmv_next_chapter();
|
||||
Msgptr = txtseeknext;
|
||||
break;
|
||||
case 2: // recording will use MZTs
|
||||
Msgptr = txtseekrecord;
|
||||
break;
|
||||
default: // can't seek without a movie
|
||||
Msgptr = txtnomovie;
|
||||
if (zmv_next_chapter())
|
||||
{
|
||||
Msgptr = "NEXT CHAPTER LOADED.";
|
||||
}
|
||||
else
|
||||
{
|
||||
Msgptr = "NO CHAPTERS AHEAD.";
|
||||
}
|
||||
}
|
||||
else { Msgptr = "NO MOVIE PROCESSING."; }
|
||||
|
||||
MessageOn = MsgCount;
|
||||
}
|
||||
|
||||
void MovieSeekBehind()
|
||||
{
|
||||
switch (MovieProcessing)
|
||||
if (MovieProcessing == 1) // replaying only - record can use ZMTs
|
||||
{
|
||||
case 1: // replaying ok
|
||||
zmv_prev_chapter();
|
||||
Msgptr = txtseekprev;
|
||||
break;
|
||||
case 2: // recording will use MZTs
|
||||
Msgptr = txtseekrecord;
|
||||
break;
|
||||
default: // can't seek without a movie
|
||||
Msgptr = txtnomovie;
|
||||
MovieSub_ResetStream();
|
||||
Msgptr = "PREVIOUS CHAPTER LOADED.";
|
||||
}
|
||||
else { Msgptr = "NO MOVIE PROCESSING."; }
|
||||
|
||||
MessageOn = MsgCount;
|
||||
}
|
||||
@@ -1025,7 +1044,7 @@ void Replay()
|
||||
}
|
||||
else
|
||||
{
|
||||
Msgptr = txtmovieended;
|
||||
Msgptr = "MOVIE FINISHED.";
|
||||
MessageOn = MsgCount;
|
||||
MovieProcessing = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user