Mercurial > vba-linux
diff src/common/movie.cpp @ 33:44974c3e093b
found source of problem for video recording
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 05 Mar 2012 01:25:11 -0600 |
parents | f9f4f1b99eed |
children | 6bde5b67a2b8 |
line wrap: on
line diff
1.1 --- a/src/common/movie.cpp Sun Mar 04 22:44:42 2012 -0600 1.2 +++ b/src/common/movie.cpp Mon Mar 05 01:25:11 2012 -0600 1.3 @@ -73,1613 +73,1628 @@ 1.4 // little-endian integer pop/push functions: 1.5 static inline uint32 Pop32(const uint8 * &ptr) 1.6 { 1.7 - uint32 v = (ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)); 1.8 - ptr += 4; 1.9 - return v; 1.10 + uint32 v = (ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)); 1.11 + ptr += 4; 1.12 + return v; 1.13 } 1.14 1.15 static inline uint16 Pop16(const uint8 * &ptr) /* const version */ 1.16 { 1.17 - uint16 v = (ptr[0] | (ptr[1] << 8)); 1.18 - ptr += 2; 1.19 - return v; 1.20 + uint16 v = (ptr[0] | (ptr[1] << 8)); 1.21 + ptr += 2; 1.22 + return v; 1.23 } 1.24 1.25 static inline uint16 Pop16(uint8 * &ptr) /* non-const version */ 1.26 { 1.27 - uint16 v = (ptr[0] | (ptr[1] << 8)); 1.28 - ptr += 2; 1.29 - return v; 1.30 + uint16 v = (ptr[0] | (ptr[1] << 8)); 1.31 + ptr += 2; 1.32 + return v; 1.33 } 1.34 1.35 static inline uint8 Pop8(const uint8 * &ptr) 1.36 { 1.37 - return *(ptr)++; 1.38 + return *(ptr)++; 1.39 } 1.40 1.41 static inline void Push32(uint32 v, uint8 * &ptr) 1.42 { 1.43 - ptr[0] = (uint8)(v & 0xff); 1.44 - ptr[1] = (uint8)((v >> 8) & 0xff); 1.45 - ptr[2] = (uint8)((v >> 16) & 0xff); 1.46 - ptr[3] = (uint8)((v >> 24) & 0xff); 1.47 - ptr += 4; 1.48 + ptr[0] = (uint8)(v & 0xff); 1.49 + ptr[1] = (uint8)((v >> 8) & 0xff); 1.50 + ptr[2] = (uint8)((v >> 16) & 0xff); 1.51 + ptr[3] = (uint8)((v >> 24) & 0xff); 1.52 + ptr += 4; 1.53 } 1.54 1.55 static inline void Push16(uint16 v, uint8 * &ptr) 1.56 { 1.57 - ptr[0] = (uint8)(v & 0xff); 1.58 - ptr[1] = (uint8)((v >> 8) & 0xff); 1.59 - ptr += 2; 1.60 + ptr[0] = (uint8)(v & 0xff); 1.61 + ptr[1] = (uint8)((v >> 8) & 0xff); 1.62 + ptr += 2; 1.63 } 1.64 1.65 static inline void Push8(uint8 v, uint8 * &ptr) 1.66 { 1.67 - *ptr++ = v; 1.68 + *ptr++ = v; 1.69 } 1.70 1.71 // little-endian integer read/write functions: 1.72 static inline uint16 Read16(const uint8 *ptr) 1.73 { 1.74 - return ptr[0] | (ptr[1] << 8); 1.75 + return ptr[0] | (ptr[1] << 8); 1.76 } 1.77 1.78 static inline void Write16(uint16 v, uint8 *ptr) 1.79 { 1.80 - ptr[0] = uint8(v & 0xff); 1.81 - ptr[1] = uint8((v >> 8) & 0xff); 1.82 + ptr[0] = uint8(v & 0xff); 1.83 + ptr[1] = uint8((v >> 8) & 0xff); 1.84 } 1.85 1.86 static long file_length(FILE *fp) 1.87 { 1.88 - long cur_pos = ftell(fp); 1.89 - fseek(fp, 0, SEEK_END); 1.90 - long length = ftell(fp); 1.91 - fseek(fp, cur_pos, SEEK_SET); 1.92 - return length; 1.93 + long cur_pos = ftell(fp); 1.94 + fseek(fp, 0, SEEK_END); 1.95 + long length = ftell(fp); 1.96 + fseek(fp, cur_pos, SEEK_SET); 1.97 + return length; 1.98 } 1.99 1.100 static int bytes_per_frame(SMovie &mov) 1.101 { 1.102 - int num_controllers = 0; 1.103 + int num_controllers = 0; 1.104 1.105 - for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.106 - if (mov.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.107 - ++num_controllers; 1.108 + for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.109 + if (mov.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.110 + ++num_controllers; 1.111 1.112 - return CONTROLLER_DATA_SIZE * num_controllers; 1.113 + return CONTROLLER_DATA_SIZE * num_controllers; 1.114 } 1.115 1.116 static void reserve_buffer_space(uint32 space_needed) 1.117 { 1.118 - if (space_needed > Movie.inputBufferSize) 1.119 - { 1.120 - uint32 ptr_offset = Movie.inputBufferPtr - Movie.inputBuffer; 1.121 - uint32 alloc_chunks = (space_needed - 1) / BUFFER_GROWTH_SIZE + 1; 1.122 - uint32 old_size = Movie.inputBufferSize; 1.123 - Movie.inputBufferSize = BUFFER_GROWTH_SIZE * alloc_chunks; 1.124 - Movie.inputBuffer = (uint8 *)realloc(Movie.inputBuffer, Movie.inputBufferSize); 1.125 - // FIXME: this only fixes the random input problem during dma-frame-skip, but not the skip 1.126 - memset(Movie.inputBuffer + old_size, 0, Movie.inputBufferSize - old_size); 1.127 - Movie.inputBufferPtr = Movie.inputBuffer + ptr_offset; 1.128 - } 1.129 + if (space_needed > Movie.inputBufferSize) 1.130 + { 1.131 + uint32 ptr_offset = Movie.inputBufferPtr - Movie.inputBuffer; 1.132 + uint32 alloc_chunks = (space_needed - 1) / BUFFER_GROWTH_SIZE + 1; 1.133 + uint32 old_size = Movie.inputBufferSize; 1.134 + Movie.inputBufferSize = BUFFER_GROWTH_SIZE * alloc_chunks; 1.135 + Movie.inputBuffer = (uint8 *)realloc(Movie.inputBuffer, Movie.inputBufferSize); 1.136 + // FIXME: this only fixes the random input problem during dma-frame-skip, but not the skip 1.137 + memset(Movie.inputBuffer + old_size, 0, Movie.inputBufferSize - old_size); 1.138 + Movie.inputBufferPtr = Movie.inputBuffer + ptr_offset; 1.139 + } 1.140 } 1.141 1.142 static int read_movie_header(FILE *file, SMovie &movie) 1.143 { 1.144 - assert(file != NULL); 1.145 - assert(VBM_HEADER_SIZE == sizeof(SMovieFileHeader)); // sanity check on the header type definition 1.146 + assert(file != NULL); 1.147 + assert(VBM_HEADER_SIZE == sizeof(SMovieFileHeader)); // sanity check on the header type definition 1.148 1.149 - uint8 headerData [VBM_HEADER_SIZE]; 1.150 + uint8 headerData [VBM_HEADER_SIZE]; 1.151 1.152 - if (fread(headerData, 1, VBM_HEADER_SIZE, file) != VBM_HEADER_SIZE) 1.153 - return MOVIE_WRONG_FORMAT; // if we failed to read in all VBM_HEADER_SIZE bytes of the header 1.154 + if (fread(headerData, 1, VBM_HEADER_SIZE, file) != VBM_HEADER_SIZE) 1.155 + return MOVIE_WRONG_FORMAT; // if we failed to read in all VBM_HEADER_SIZE bytes of the header 1.156 1.157 - const uint8 * ptr = headerData; 1.158 - SMovieFileHeader &header = movie.header; 1.159 + const uint8 * ptr = headerData; 1.160 + SMovieFileHeader &header = movie.header; 1.161 1.162 - header.magic = Pop32(ptr); 1.163 - if (header.magic != VBM_MAGIC) 1.164 - return MOVIE_WRONG_FORMAT; 1.165 + header.magic = Pop32(ptr); 1.166 + if (header.magic != VBM_MAGIC) 1.167 + return MOVIE_WRONG_FORMAT; 1.168 1.169 - header.version = Pop32(ptr); 1.170 - if (header.version != VBM_VERSION) 1.171 - return MOVIE_WRONG_VERSION; 1.172 + header.version = Pop32(ptr); 1.173 + if (header.version != VBM_VERSION) 1.174 + return MOVIE_WRONG_VERSION; 1.175 1.176 - header.uid = Pop32(ptr); 1.177 - header.length_frames = Pop32(ptr) + 1; // HACK: add 1 to the length for compatibility 1.178 - header.rerecord_count = Pop32(ptr); 1.179 + header.uid = Pop32(ptr); 1.180 + header.length_frames = Pop32(ptr) + 1; // HACK: add 1 to the length for compatibility 1.181 + header.rerecord_count = Pop32(ptr); 1.182 1.183 - header.startFlags = Pop8(ptr); 1.184 - header.controllerFlags = Pop8(ptr); 1.185 - header.typeFlags = Pop8(ptr); 1.186 - header.optionFlags = Pop8(ptr); 1.187 + header.startFlags = Pop8(ptr); 1.188 + header.controllerFlags = Pop8(ptr); 1.189 + header.typeFlags = Pop8(ptr); 1.190 + header.optionFlags = Pop8(ptr); 1.191 1.192 - header.saveType = Pop32(ptr); 1.193 - header.flashSize = Pop32(ptr); 1.194 - header.gbEmulatorType = Pop32(ptr); 1.195 + header.saveType = Pop32(ptr); 1.196 + header.flashSize = Pop32(ptr); 1.197 + header.gbEmulatorType = Pop32(ptr); 1.198 1.199 - for (int i = 0; i < 12; i++) 1.200 - header.romTitle[i] = Pop8(ptr); 1.201 + for (int i = 0; i < 12; i++) 1.202 + header.romTitle[i] = Pop8(ptr); 1.203 1.204 - header.minorVersion = Pop8(ptr); 1.205 + header.minorVersion = Pop8(ptr); 1.206 1.207 - header.romCRC = Pop8(ptr); 1.208 - header.romOrBiosChecksum = Pop16(ptr); 1.209 - header.romGameCode = Pop32(ptr); 1.210 + header.romCRC = Pop8(ptr); 1.211 + header.romOrBiosChecksum = Pop16(ptr); 1.212 + header.romGameCode = Pop32(ptr); 1.213 1.214 - header.offset_to_savestate = Pop32(ptr); 1.215 - header.offset_to_controller_data = Pop32(ptr); 1.216 + header.offset_to_savestate = Pop32(ptr); 1.217 + header.offset_to_controller_data = Pop32(ptr); 1.218 1.219 - return MOVIE_SUCCESS; 1.220 + return MOVIE_SUCCESS; 1.221 } 1.222 1.223 static void write_movie_header(FILE *file, const SMovie &movie) 1.224 { 1.225 - assert(ftell(file) == 0); // we assume file points to beginning of movie file 1.226 + assert(ftell(file) == 0); // we assume file points to beginning of movie file 1.227 1.228 - uint8 headerData [VBM_HEADER_SIZE]; 1.229 - uint8 *ptr = headerData; 1.230 - const SMovieFileHeader &header = movie.header; 1.231 + uint8 headerData [VBM_HEADER_SIZE]; 1.232 + uint8 *ptr = headerData; 1.233 + const SMovieFileHeader &header = movie.header; 1.234 1.235 - Push32(header.magic, ptr); 1.236 - Push32(header.version, ptr); 1.237 + Push32(header.magic, ptr); 1.238 + Push32(header.version, ptr); 1.239 1.240 - Push32(header.uid, ptr); 1.241 - Push32(header.length_frames - 1, ptr); // HACK: reduce the length by 1 for compatibility with certain faulty old tools 1.242 - // like TME 1.243 - Push32(header.rerecord_count, ptr); 1.244 + Push32(header.uid, ptr); 1.245 + Push32(header.length_frames - 1, ptr); // HACK: reduce the length by 1 for compatibility with certain faulty old tools 1.246 + // like TME 1.247 + Push32(header.rerecord_count, ptr); 1.248 1.249 - Push8(header.startFlags, ptr); 1.250 - Push8(header.controllerFlags, ptr); 1.251 - Push8(header.typeFlags, ptr); 1.252 - Push8(header.optionFlags, ptr); 1.253 + Push8(header.startFlags, ptr); 1.254 + Push8(header.controllerFlags, ptr); 1.255 + Push8(header.typeFlags, ptr); 1.256 + Push8(header.optionFlags, ptr); 1.257 1.258 - Push32(header.saveType, ptr); 1.259 - Push32(header.flashSize, ptr); 1.260 - Push32(header.gbEmulatorType, ptr); 1.261 + Push32(header.saveType, ptr); 1.262 + Push32(header.flashSize, ptr); 1.263 + Push32(header.gbEmulatorType, ptr); 1.264 1.265 - for (int i = 0; i < 12; ++i) 1.266 - Push8(header.romTitle[i], ptr); 1.267 + for (int i = 0; i < 12; ++i) 1.268 + Push8(header.romTitle[i], ptr); 1.269 1.270 - Push8(header.minorVersion, ptr); 1.271 + Push8(header.minorVersion, ptr); 1.272 1.273 - Push8(header.romCRC, ptr); 1.274 - Push16(header.romOrBiosChecksum, ptr); 1.275 - Push32(header.romGameCode, ptr); 1.276 + Push8(header.romCRC, ptr); 1.277 + Push16(header.romOrBiosChecksum, ptr); 1.278 + Push32(header.romGameCode, ptr); 1.279 1.280 - Push32(header.offset_to_savestate, ptr); 1.281 - Push32(header.offset_to_controller_data, ptr); 1.282 + Push32(header.offset_to_savestate, ptr); 1.283 + Push32(header.offset_to_controller_data, ptr); 1.284 1.285 - fwrite(headerData, 1, VBM_HEADER_SIZE, file); 1.286 + fwrite(headerData, 1, VBM_HEADER_SIZE, file); 1.287 } 1.288 1.289 static void flush_movie_header() 1.290 { 1.291 - assert(Movie.file != 0 && "logical error!"); 1.292 - if (!Movie.file) 1.293 - return; 1.294 + assert(Movie.file != 0 && "logical error!"); 1.295 + if (!Movie.file) 1.296 + return; 1.297 1.298 - long originalPos = ftell(Movie.file); 1.299 + long originalPos = ftell(Movie.file); 1.300 1.301 - // (over-)write the header 1.302 - fseek(Movie.file, 0, SEEK_SET); 1.303 - write_movie_header(Movie.file, Movie); 1.304 + // (over-)write the header 1.305 + fseek(Movie.file, 0, SEEK_SET); 1.306 + write_movie_header(Movie.file, Movie); 1.307 1.308 - fflush(Movie.file); 1.309 + fflush(Movie.file); 1.310 1.311 - fseek(Movie.file, originalPos, SEEK_SET); 1.312 + fseek(Movie.file, originalPos, SEEK_SET); 1.313 } 1.314 1.315 static void flush_movie_frames() 1.316 { 1.317 - assert(Movie.file && "logical error!"); 1.318 - if (!Movie.file) 1.319 - return; 1.320 + assert(Movie.file && "logical error!"); 1.321 + if (!Movie.file) 1.322 + return; 1.323 1.324 - long originalPos = ftell(Movie.file); 1.325 + long originalPos = ftell(Movie.file); 1.326 1.327 - // overwrite the controller data 1.328 - fseek(Movie.file, Movie.header.offset_to_controller_data, SEEK_SET); 1.329 - fwrite(Movie.inputBuffer, 1, Movie.bytesPerFrame * Movie.header.length_frames, Movie.file); 1.330 + // overwrite the controller data 1.331 + fseek(Movie.file, Movie.header.offset_to_controller_data, SEEK_SET); 1.332 + fwrite(Movie.inputBuffer, 1, Movie.bytesPerFrame * Movie.header.length_frames, Movie.file); 1.333 1.334 - fflush(Movie.file); 1.335 + fflush(Movie.file); 1.336 1.337 - fseek(Movie.file, originalPos, SEEK_SET); 1.338 + fseek(Movie.file, originalPos, SEEK_SET); 1.339 } 1.340 1.341 static void truncate_movie(long length) 1.342 { 1.343 - // truncate movie to length 1.344 - // NOTE: it's certain that the savestate block is never after the 1.345 - // controller data block, because the VBM format decrees it. 1.346 + // truncate movie to length 1.347 + // NOTE: it's certain that the savestate block is never after the 1.348 + // controller data block, because the VBM format decrees it. 1.349 1.350 - assert(Movie.file && length >= 0); 1.351 - if (!Movie.file || length < 0) 1.352 - return; 1.353 + assert(Movie.file && length >= 0); 1.354 + if (!Movie.file || length < 0) 1.355 + return; 1.356 1.357 - assert(Movie.header.offset_to_savestate <= Movie.header.offset_to_controller_data); 1.358 - if (Movie.header.offset_to_savestate > Movie.header.offset_to_controller_data) 1.359 - return; 1.360 + assert(Movie.header.offset_to_savestate <= Movie.header.offset_to_controller_data); 1.361 + if (Movie.header.offset_to_savestate > Movie.header.offset_to_controller_data) 1.362 + return; 1.363 1.364 - Movie.header.length_frames = length; 1.365 - flush_movie_header(); 1.366 - const long truncLen = long(Movie.header.offset_to_controller_data + Movie.bytesPerFrame * length); 1.367 - if (file_length(Movie.file) != truncLen) 1.368 - { 1.369 - ftruncate(fileno(Movie.file), truncLen); 1.370 - } 1.371 + Movie.header.length_frames = length; 1.372 + flush_movie_header(); 1.373 + const long truncLen = long(Movie.header.offset_to_controller_data + Movie.bytesPerFrame * length); 1.374 + if (file_length(Movie.file) != truncLen) 1.375 + { 1.376 + ftruncate(fileno(Movie.file), truncLen); 1.377 + } 1.378 } 1.379 1.380 static void remember_input_state() 1.381 { 1.382 - for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.383 + for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.384 + { 1.385 + if (systemCartridgeType == 0) 1.386 { 1.387 - if (systemCartridgeType == 0) 1.388 - { 1.389 - initialInputs[i] = u16(~P1 & 0x03FF); 1.390 - } 1.391 - else 1.392 - { 1.393 - extern int32 gbJoymask[4]; 1.394 - for (int i = 0; i < 4; ++i) 1.395 - initialInputs[i] = u16(gbJoymask[i] & 0xFFFF); 1.396 - } 1.397 + initialInputs[i] = u16(~P1 & 0x03FF); 1.398 } 1.399 + else 1.400 + { 1.401 + extern int32 gbJoymask[4]; 1.402 + for (int i = 0; i < 4; ++i) 1.403 + initialInputs[i] = u16(gbJoymask[i] & 0xFFFF); 1.404 + } 1.405 + } 1.406 } 1.407 1.408 static void change_state(MovieState new_state) 1.409 { 1.410 #if (defined(WIN32) && !defined(SDL)) 1.411 - theApp.frameSearching = false; 1.412 - theApp.frameSearchSkipping = false; 1.413 + theApp.frameSearching = false; 1.414 + theApp.frameSearchSkipping = false; 1.415 #endif 1.416 1.417 - if (new_state == MOVIE_STATE_NONE) 1.418 + if (new_state == MOVIE_STATE_NONE) 1.419 + { 1.420 + Movie.pauseFrame = -1; 1.421 + 1.422 + if (Movie.state == MOVIE_STATE_NONE) 1.423 + return; 1.424 + 1.425 + truncate_movie(Movie.header.length_frames); 1.426 + 1.427 + fclose(Movie.file); 1.428 + Movie.file = NULL; 1.429 + Movie.currentFrame = 0; 1.430 +#if (defined(WIN32) && !defined(SDL)) 1.431 + // undo changes to border settings 1.432 + { 1.433 + gbBorderOn = prevBorder; 1.434 + theApp.winGbBorderOn = prevWinBorder; 1.435 + gbBorderAutomatic = prevBorderAuto; 1.436 + systemGbBorderOn(); 1.437 + } 1.438 +#endif 1.439 + gbEmulatorType = prevEmulatorType; 1.440 + 1.441 + extern int32 gbDMASpeedVersion; 1.442 + gbDMASpeedVersion = 1; 1.443 + 1.444 + extern int32 gbEchoRAMFixOn; 1.445 + gbEchoRAMFixOn = 1; 1.446 + 1.447 + gbNullInputHackTempEnabled = gbNullInputHackEnabled; 1.448 + 1.449 + if (Movie.inputBuffer) 1.450 { 1.451 - Movie.pauseFrame = -1; 1.452 + free(Movie.inputBuffer); 1.453 + Movie.inputBuffer = NULL; 1.454 + } 1.455 + } 1.456 + else if (new_state == MOVIE_STATE_PLAY) 1.457 + { 1.458 + assert(Movie.file); 1.459 1.460 - if (Movie.state == MOVIE_STATE_NONE) 1.461 - return; 1.462 + // this would cause problems if not dealt with 1.463 + if (Movie.currentFrame >= Movie.header.length_frames) 1.464 + { 1.465 + new_state = MOVIE_STATE_END; 1.466 + Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * Movie.header.length_frames; 1.467 + } 1.468 + } 1.469 + else if (new_state == MOVIE_STATE_RECORD) 1.470 + { 1.471 + assert(Movie.file); 1.472 1.473 - truncate_movie(Movie.header.length_frames); 1.474 - 1.475 - fclose(Movie.file); 1.476 - Movie.file = NULL; 1.477 - Movie.currentFrame = 0; 1.478 -#if (defined(WIN32) && !defined(SDL)) 1.479 - // undo changes to border settings 1.480 - { 1.481 - gbBorderOn = prevBorder; 1.482 - theApp.winGbBorderOn = prevWinBorder; 1.483 - gbBorderAutomatic = prevBorderAuto; 1.484 - systemGbBorderOn(); 1.485 - } 1.486 -#endif 1.487 - gbEmulatorType = prevEmulatorType; 1.488 - 1.489 - extern int32 gbDMASpeedVersion; 1.490 - gbDMASpeedVersion = 1; 1.491 - 1.492 - extern int32 gbEchoRAMFixOn; 1.493 - gbEchoRAMFixOn = 1; 1.494 - 1.495 - gbNullInputHackTempEnabled = gbNullInputHackEnabled; 1.496 - 1.497 - if (Movie.inputBuffer) 1.498 - { 1.499 - free(Movie.inputBuffer); 1.500 - Movie.inputBuffer = NULL; 1.501 - } 1.502 - } 1.503 - else if (new_state == MOVIE_STATE_PLAY) 1.504 + // this would cause problems if not dealt with 1.505 + if (Movie.currentFrame > Movie.header.length_frames) 1.506 { 1.507 - assert(Movie.file); 1.508 - 1.509 - // this would cause problems if not dealt with 1.510 - if (Movie.currentFrame >= Movie.header.length_frames) 1.511 - { 1.512 - new_state = MOVIE_STATE_END; 1.513 - Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * Movie.header.length_frames; 1.514 - } 1.515 - } 1.516 - else if (new_state == MOVIE_STATE_RECORD) 1.517 - { 1.518 - assert(Movie.file); 1.519 - 1.520 - // this would cause problems if not dealt with 1.521 - if (Movie.currentFrame > Movie.header.length_frames) 1.522 - { 1.523 - new_state = MOVIE_STATE_END; 1.524 - Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * Movie.header.length_frames; 1.525 - } 1.526 - 1.527 - fseek(Movie.file, Movie.header.offset_to_controller_data + Movie.bytesPerFrame * Movie.currentFrame, SEEK_SET); 1.528 + new_state = MOVIE_STATE_END; 1.529 + Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * Movie.header.length_frames; 1.530 } 1.531 1.532 - if (new_state == MOVIE_STATE_END && Movie.state != MOVIE_STATE_END) 1.533 + fseek(Movie.file, Movie.header.offset_to_controller_data + Movie.bytesPerFrame * Movie.currentFrame, SEEK_SET); 1.534 + } 1.535 + 1.536 + if (new_state == MOVIE_STATE_END && Movie.state != MOVIE_STATE_END) 1.537 + { 1.538 +#if defined(SDL) 1.539 + systemClearJoypads(); 1.540 +#endif 1.541 + systemScreenMessage("Movie end"); 1.542 + } 1.543 + 1.544 + Movie.state = new_state; 1.545 + 1.546 + // checking for movie end 1.547 + bool willPause = false; 1.548 + 1.549 + // if the movie's been set to pause at a certain frame 1.550 + if (Movie.state != MOVIE_STATE_NONE && Movie.pauseFrame >= 0 && Movie.currentFrame == (uint32)Movie.pauseFrame) 1.551 + { 1.552 + Movie.pauseFrame = -1; 1.553 + willPause = true; 1.554 + } 1.555 + 1.556 + if (Movie.state == MOVIE_STATE_END) 1.557 + { 1.558 + if (Movie.currentFrame == Movie.header.length_frames) 1.559 { 1.560 -#if defined(SDL) 1.561 - systemClearJoypads(); 1.562 -#endif 1.563 - systemScreenMessage("Movie end"); 1.564 - } 1.565 - 1.566 - Movie.state = new_state; 1.567 - 1.568 - // checking for movie end 1.569 - bool willPause = false; 1.570 - 1.571 - // if the movie's been set to pause at a certain frame 1.572 - if (Movie.state != MOVIE_STATE_NONE && Movie.pauseFrame >= 0 && Movie.currentFrame == (uint32)Movie.pauseFrame) 1.573 - { 1.574 - Movie.pauseFrame = -1; 1.575 - willPause = true; 1.576 - } 1.577 - 1.578 - if (Movie.state == MOVIE_STATE_END) 1.579 - { 1.580 - if (Movie.currentFrame == Movie.header.length_frames) 1.581 - { 1.582 #if (defined(WIN32) && !defined(SDL)) 1.583 - if (theApp.movieOnEndPause) 1.584 - { 1.585 - willPause = true; 1.586 - } 1.587 + if (theApp.movieOnEndPause) 1.588 + { 1.589 + willPause = true; 1.590 + } 1.591 #else 1.592 - // SDL FIXME 1.593 + // SDL FIXME 1.594 #endif 1.595 1.596 #if (defined(WIN32) && !defined(SDL)) 1.597 - switch (theApp.movieOnEndBehavior) 1.598 - { 1.599 - case 1: 1.600 - // the old behavior 1.601 - //VBAMovieRestart(); 1.602 - break; 1.603 - case 2: 1.604 + switch (theApp.movieOnEndBehavior) 1.605 + { 1.606 + case 1: 1.607 + // the old behavior 1.608 + //VBAMovieRestart(); 1.609 + break; 1.610 + case 2: 1.611 #else 1.612 - // SDL FIXME 1.613 + // SDL FIXME 1.614 #endif 1.615 - if (Movie.RecordedThisSession) 1.616 - { 1.617 - // if user has been recording this movie since the last time it started playing, 1.618 - // they probably don't want the movie to end now during playback, 1.619 - // so switch back to recording when it reaches the end 1.620 - VBAMovieSwitchToRecording(); 1.621 - systemScreenMessage("Recording resumed"); 1.622 - willPause = true; 1.623 - } 1.624 + if (Movie.RecordedThisSession) 1.625 + { 1.626 + // if user has been recording this movie since the last time it started playing, 1.627 + // they probably don't want the movie to end now during playback, 1.628 + // so switch back to recording when it reaches the end 1.629 + VBAMovieSwitchToRecording(); 1.630 + systemScreenMessage("Recording resumed"); 1.631 + willPause = true; 1.632 + } 1.633 #if (defined(WIN32) && !defined(SDL)) 1.634 - break; 1.635 - case 3: 1.636 - // keep open 1.637 - break; 1.638 - case 0: 1.639 - // fall through 1.640 - default: 1.641 - // close movie 1.642 - //VBAMovieStop(false); 1.643 - break; 1.644 - } 1.645 + break; 1.646 + case 3: 1.647 + // keep open 1.648 + break; 1.649 + case 0: 1.650 + // fall through 1.651 + default: 1.652 + // close movie 1.653 + //VBAMovieStop(false); 1.654 + break; 1.655 + } 1.656 #else 1.657 - // SDL FIXME 1.658 + // SDL FIXME 1.659 #endif 1.660 - } 1.661 + } 1.662 #if 1 1.663 - else if (Movie.currentFrame > Movie.header.length_frames) 1.664 - { 1.665 + else if (Movie.currentFrame > Movie.header.length_frames) 1.666 + { 1.667 #if (defined(WIN32) && !defined(SDL)) 1.668 - switch (theApp.movieOnEndBehavior) 1.669 - { 1.670 - case 1: 1.671 - // FIXME: this should be delayed till the current frame ends 1.672 - VBAMovieRestart(); 1.673 - break; 1.674 - case 2: 1.675 - // nothing 1.676 - break; 1.677 - case 3: 1.678 - // keep open 1.679 - break; 1.680 - case 0: 1.681 - // fall through 1.682 - default: 1.683 - // close movie 1.684 - VBAMovieStop(false); 1.685 - break; 1.686 - } 1.687 + switch (theApp.movieOnEndBehavior) 1.688 + { 1.689 + case 1: 1.690 + // FIXME: this should be delayed till the current frame ends 1.691 + VBAMovieRestart(); 1.692 + break; 1.693 + case 2: 1.694 + // nothing 1.695 + break; 1.696 + case 3: 1.697 + // keep open 1.698 + break; 1.699 + case 0: 1.700 + // fall through 1.701 + default: 1.702 + // close movie 1.703 + VBAMovieStop(false); 1.704 + break; 1.705 + } 1.706 #else 1.707 - // SDLFIXME 1.708 + // SDLFIXME 1.709 #endif 1.710 - } 1.711 + } 1.712 #endif 1.713 - } // end if (Movie.state == MOVIE_STATE_END) 1.714 + } // end if (Movie.state == MOVIE_STATE_END) 1.715 1.716 - if (willPause) 1.717 - { 1.718 - systemSetPause(true); 1.719 - } 1.720 + if (willPause) 1.721 + { 1.722 + systemSetPause(true); 1.723 + } 1.724 } 1.725 1.726 void VBAMovieInit() 1.727 { 1.728 - memset(&Movie, 0, sizeof(Movie)); 1.729 - Movie.state = MOVIE_STATE_NONE; 1.730 - Movie.pauseFrame = -1; 1.731 + memset(&Movie, 0, sizeof(Movie)); 1.732 + Movie.state = MOVIE_STATE_NONE; 1.733 + Movie.pauseFrame = -1; 1.734 1.735 - resetSignaled = false; 1.736 - resetSignaledLast = false; 1.737 + resetSignaled = false; 1.738 + resetSignaledLast = false; 1.739 } 1.740 1.741 void VBAMovieGetRomInfo(const SMovie &movieInfo, char romTitle [12], uint32 &romGameCode, uint16 &checksum, uint8 &crc) 1.742 { 1.743 - if (systemCartridgeType == 0) // GBA 1.744 - { 1.745 - extern u8 *bios, *rom; 1.746 - memcpy(romTitle, &rom[0xa0], 12); // GBA TITLE 1.747 - memcpy(&romGameCode, &rom[0xac], 4); // GBA ROM GAME CODE 1.748 - if ((movieInfo.header.optionFlags & MOVIE_SETTING_USEBIOSFILE) != 0) 1.749 - checksum = utilCalcBIOSChecksum(bios, 4); // GBA BIOS CHECKSUM 1.750 - else 1.751 - checksum = 0; 1.752 - crc = rom[0xbd]; // GBA ROM CRC 1.753 - } 1.754 - else // non-GBA 1.755 - { 1.756 - extern u8 *gbRom; 1.757 - memcpy(romTitle, &gbRom[0x134], 12); // GB TITLE (note this can be 15 but is truncated to 12) 1.758 - romGameCode = (uint32)gbRom[0x146]; // GB ROM UNIT CODE 1.759 + if (systemCartridgeType == 0) // GBA 1.760 + { 1.761 + extern u8 *bios, *rom; 1.762 + memcpy(romTitle, &rom[0xa0], 12); // GBA TITLE 1.763 + memcpy(&romGameCode, &rom[0xac], 4); // GBA ROM GAME CODE 1.764 + if ((movieInfo.header.optionFlags & MOVIE_SETTING_USEBIOSFILE) != 0) 1.765 + checksum = utilCalcBIOSChecksum(bios, 4); // GBA BIOS CHECKSUM 1.766 + else 1.767 + checksum = 0; 1.768 + crc = rom[0xbd]; // GBA ROM CRC 1.769 + } 1.770 + else // non-GBA 1.771 + { 1.772 + extern u8 *gbRom; 1.773 + memcpy(romTitle, &gbRom[0x134], 12); // GB TITLE (note this can be 15 but is truncated to 12) 1.774 + romGameCode = (uint32)gbRom[0x146]; // GB ROM UNIT CODE 1.775 1.776 - checksum = (gbRom[0x14e] << 8) | gbRom[0x14f]; // GB ROM CHECKSUM, read from big-endian 1.777 - crc = gbRom[0x14d]; // GB ROM CRC 1.778 - } 1.779 + checksum = (gbRom[0x14e] << 8) | gbRom[0x14f]; // GB ROM CHECKSUM, read from big-endian 1.780 + crc = gbRom[0x14d]; // GB ROM CRC 1.781 + } 1.782 } 1.783 1.784 #ifdef SDL 1.785 static void GetBatterySaveName(char *buffer) 1.786 { 1.787 - extern char batteryDir[2048], filename[2048]; // from SDL.cpp 1.788 - extern char *sdlGetFilename(char *name); // from SDL.cpp 1.789 - if (batteryDir[0]) 1.790 - sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); 1.791 - else 1.792 - sprintf(buffer, "%s.sav", filename); 1.793 + extern char batteryDir[2048], filename[2048]; // from SDL.cpp 1.794 + extern char *sdlGetFilename(char *name); // from SDL.cpp 1.795 + if (batteryDir[0]) 1.796 + sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); 1.797 + else 1.798 + sprintf(buffer, "%s.sav", filename); 1.799 } 1.800 1.801 #endif 1.802 1.803 static void SetPlayEmuSettings() 1.804 { 1.805 - prevEmulatorType = gbEmulatorType; 1.806 - gbEmulatorType = Movie.header.gbEmulatorType; 1.807 + prevEmulatorType = gbEmulatorType; 1.808 + gbEmulatorType = Movie.header.gbEmulatorType; 1.809 1.810 #if (defined(WIN32) && !defined(SDL)) 1.811 -// theApp.removeIntros = false; 1.812 - theApp.skipBiosFile = (Movie.header.optionFlags & MOVIE_SETTING_SKIPBIOSFILE) != 0; 1.813 - theApp.useBiosFile = (Movie.header.optionFlags & MOVIE_SETTING_USEBIOSFILE) != 0; 1.814 + // theApp.removeIntros = false; 1.815 + theApp.skipBiosFile = (Movie.header.optionFlags & MOVIE_SETTING_SKIPBIOSFILE) != 0; 1.816 + theApp.useBiosFile = (Movie.header.optionFlags & MOVIE_SETTING_USEBIOSFILE) != 0; 1.817 #else 1.818 - extern int saveType, sdlRtcEnable, sdlFlashSize; // from SDL.cpp 1.819 - extern bool8 useBios, skipBios, removeIntros; // from SDL.cpp 1.820 - useBios = (Movie.header.optionFlags & MOVIE_SETTING_USEBIOSFILE) != 0; 1.821 - skipBios = (Movie.header.optionFlags & MOVIE_SETTING_SKIPBIOSFILE) != 0; 1.822 - removeIntros = false /*(Movie.header.optionFlags & MOVIE_SETTING_REMOVEINTROS) != 0*/; 1.823 + extern int saveType, sdlRtcEnable, sdlFlashSize; // from SDL.cpp 1.824 + extern bool8 useBios, skipBios, removeIntros; // from SDL.cpp 1.825 + useBios = (Movie.header.optionFlags & MOVIE_SETTING_USEBIOSFILE) != 0; 1.826 + skipBios = (Movie.header.optionFlags & MOVIE_SETTING_SKIPBIOSFILE) != 0; 1.827 + removeIntros = false /*(Movie.header.optionFlags & MOVIE_SETTING_REMOVEINTROS) != 0*/; 1.828 #endif 1.829 1.830 - extern void SetPrefetchHack(bool); 1.831 - if (systemCartridgeType == 0) // lag disablement applies only to GBA 1.832 - SetPrefetchHack((Movie.header.optionFlags & MOVIE_SETTING_LAGHACK) != 0); 1.833 + extern void SetPrefetchHack(bool); 1.834 + if (systemCartridgeType == 0) // lag disablement applies only to GBA 1.835 + SetPrefetchHack((Movie.header.optionFlags & MOVIE_SETTING_LAGHACK) != 0); 1.836 1.837 - gbNullInputHackTempEnabled = ((Movie.header.optionFlags & MOVIE_SETTING_GBINPUTHACK) != 0); 1.838 + gbNullInputHackTempEnabled = ((Movie.header.optionFlags & MOVIE_SETTING_GBINPUTHACK) != 0); 1.839 1.840 - // some GB/GBC games depend on the sound rate, so just use the highest one 1.841 - systemSoundSetQuality(1); 1.842 - useOldFrameTiming = false; 1.843 + // some GB/GBC games depend on the sound rate, so just use the highest one 1.844 + systemSoundSetQuality(1); 1.845 + useOldFrameTiming = false; 1.846 1.847 - extern int32 gbDMASpeedVersion; 1.848 - if ((Movie.header.optionFlags & MOVIE_SETTING_GBCFF55FIX) != 0) 1.849 - gbDMASpeedVersion = 1; 1.850 - else 1.851 - gbDMASpeedVersion = 0; // old CGB HDMA5 timing was used 1.852 + extern int32 gbDMASpeedVersion; 1.853 + if ((Movie.header.optionFlags & MOVIE_SETTING_GBCFF55FIX) != 0) 1.854 + gbDMASpeedVersion = 1; 1.855 + else 1.856 + gbDMASpeedVersion = 0; // old CGB HDMA5 timing was used 1.857 1.858 - extern int32 gbEchoRAMFixOn; 1.859 - if ((Movie.header.optionFlags & MOVIE_SETTING_GBECHORAMFIX) != 0) 1.860 - gbEchoRAMFixOn = 1; 1.861 - else 1.862 - gbEchoRAMFixOn = 0; 1.863 + extern int32 gbEchoRAMFixOn; 1.864 + if ((Movie.header.optionFlags & MOVIE_SETTING_GBECHORAMFIX) != 0) 1.865 + gbEchoRAMFixOn = 1; 1.866 + else 1.867 + gbEchoRAMFixOn = 0; 1.868 1.869 #if (defined(WIN32) && !defined(SDL)) 1.870 - rtcEnable((Movie.header.optionFlags & MOVIE_SETTING_RTCENABLE) != 0); 1.871 - theApp.winSaveType = Movie.header.saveType; 1.872 - theApp.winFlashSize = Movie.header.flashSize; 1.873 + rtcEnable((Movie.header.optionFlags & MOVIE_SETTING_RTCENABLE) != 0); 1.874 + theApp.winSaveType = Movie.header.saveType; 1.875 + theApp.winFlashSize = Movie.header.flashSize; 1.876 1.877 - prevBorder = gbBorderOn; 1.878 - prevWinBorder = theApp.winGbBorderOn; 1.879 - prevBorderAuto = gbBorderAutomatic; 1.880 - if ((gbEmulatorType == 2 || gbEmulatorType == 5) 1.881 - && !theApp.hideMovieBorder) // games played in SGB mode can have a border 1.882 + prevBorder = gbBorderOn; 1.883 + prevWinBorder = theApp.winGbBorderOn; 1.884 + prevBorderAuto = gbBorderAutomatic; 1.885 + if ((gbEmulatorType == 2 || gbEmulatorType == 5) 1.886 + && !theApp.hideMovieBorder) // games played in SGB mode can have a border 1.887 + { 1.888 + gbBorderOn = true; 1.889 + theApp.winGbBorderOn = true; 1.890 + gbBorderAutomatic = false; 1.891 + } 1.892 + else 1.893 + { 1.894 + gbBorderOn = false; 1.895 + theApp.winGbBorderOn = false; 1.896 + gbBorderAutomatic = false; 1.897 + if (theApp.hideMovieBorder) 1.898 { 1.899 - gbBorderOn = true; 1.900 - theApp.winGbBorderOn = true; 1.901 - gbBorderAutomatic = false; 1.902 + theApp.hideMovieBorder = false; 1.903 + prevBorder = false; // it might be expected behaviour that it stays hidden after the movie 1.904 } 1.905 - else 1.906 - { 1.907 - gbBorderOn = false; 1.908 - theApp.winGbBorderOn = false; 1.909 - gbBorderAutomatic = false; 1.910 - if (theApp.hideMovieBorder) 1.911 - { 1.912 - theApp.hideMovieBorder = false; 1.913 - prevBorder = false; // it might be expected behaviour that it stays hidden after the movie 1.914 - } 1.915 - } 1.916 - systemGbBorderOn(); 1.917 + } 1.918 + systemGbBorderOn(); 1.919 #else 1.920 - sdlRtcEnable = (Movie.header.optionFlags & MOVIE_SETTING_RTCENABLE) != 0; 1.921 - saveType = Movie.header.saveType; 1.922 - sdlFlashSize = Movie.header.flashSize; 1.923 + sdlRtcEnable = (Movie.header.optionFlags & MOVIE_SETTING_RTCENABLE) != 0; 1.924 + saveType = Movie.header.saveType; 1.925 + sdlFlashSize = Movie.header.flashSize; 1.926 #endif 1.927 } 1.928 1.929 static void HardResetAndSRAMClear() 1.930 { 1.931 #if (defined(WIN32) && !defined(SDL)) 1.932 - winEraseBatteryFile(); // delete the damn SRAM file and keep it from being resurrected from RAM 1.933 - MainWnd *temp = ((MainWnd *)theApp.m_pMainWnd); 1.934 - if (!temp->winFileRun(true)) // restart running the game 1.935 - { 1.936 - temp->winFileClose(); 1.937 - } 1.938 + winEraseBatteryFile(); // delete the damn SRAM file and keep it from being resurrected from RAM 1.939 + MainWnd *temp = ((MainWnd *)theApp.m_pMainWnd); 1.940 + if (!temp->winFileRun(true)) // restart running the game 1.941 + { 1.942 + temp->winFileClose(); 1.943 + } 1.944 #else 1.945 - char fname [1024]; 1.946 - GetBatterySaveName(fname); 1.947 - remove(fname); // delete the damn SRAM file 1.948 + char fname [1024]; 1.949 + GetBatterySaveName(fname); 1.950 + remove(fname); // delete the damn SRAM file 1.951 1.952 - // Henceforth, emuCleanUp means "clear out SRAM" 1.953 - //theEmulator.emuCleanUp(); // keep it from being resurrected from RAM <--This is wrong, it'll deallocate all variables --Felipe 1.954 + // Henceforth, emuCleanUp means "clear out SRAM" 1.955 + //theEmulator.emuCleanUp(); // keep it from being resurrected from RAM <--This is wrong, it'll deallocate all variables --Felipe 1.956 1.957 - /// FIXME the correct SDL code to call for a full restart isn't in a function yet 1.958 - theEmulator.emuReset(false); 1.959 + /// FIXME the correct SDL code to call for a full restart isn't in a function yet 1.960 + theEmulator.emuReset(false); 1.961 #endif 1.962 } 1.963 1.964 int VBAMovieOpen(const char *filename, bool8 read_only) 1.965 { 1.966 - loadingMovie = true; 1.967 - uint8 movieReadOnly = read_only ? 1 : 0; 1.968 + loadingMovie = true; 1.969 + uint8 movieReadOnly = read_only ? 1 : 0; 1.970 1.971 - FILE * file; 1.972 - STREAM stream; 1.973 - int result; 1.974 - int fn; 1.975 + FILE * file; 1.976 + STREAM stream; 1.977 + int result; 1.978 + int fn; 1.979 1.980 - char movie_filename[_MAX_PATH]; 1.981 + char movie_filename[_MAX_PATH]; 1.982 #ifdef WIN32 1.983 - _fullpath(movie_filename, filename, _MAX_PATH); 1.984 + _fullpath(movie_filename, filename, _MAX_PATH); 1.985 #else 1.986 - // SDL FIXME: convert to fullpath 1.987 - strncpy(movie_filename, filename, _MAX_PATH); 1.988 - movie_filename[_MAX_PATH - 1] = '\0'; 1.989 + // SDL FIXME: convert to fullpath 1.990 + strncpy(movie_filename, filename, _MAX_PATH); 1.991 + movie_filename[_MAX_PATH - 1] = '\0'; 1.992 #endif 1.993 1.994 - if (movie_filename[0] == '\0') 1.995 - { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.996 + if (movie_filename[0] == '\0') 1.997 + { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.998 1.999 - if (!emulating) 1.1000 - { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1001 + if (!emulating) 1.1002 + { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1003 1.1004 -// bool alreadyOpen = (Movie.file != NULL && _stricmp(movie_filename, Movie.filename) == 0); 1.1005 + // bool alreadyOpen = (Movie.file != NULL && _stricmp(movie_filename, Movie.filename) == 0); 1.1006 1.1007 -// if (alreadyOpen) 1.1008 - change_state(MOVIE_STATE_NONE); // have to stop current movie before trying to re-open it 1.1009 + // if (alreadyOpen) 1.1010 + change_state(MOVIE_STATE_NONE); // have to stop current movie before trying to re-open it 1.1011 1.1012 - if (!(file = fopen(movie_filename, "rb+"))) 1.1013 - if (!(file = fopen(movie_filename, "rb"))) 1.1014 - { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1015 - //else 1.1016 - // movieReadOnly = 2; // we have to open the movie twice, no need to do this both times 1.1017 + if (!(file = fopen(movie_filename, "rb+"))) 1.1018 + if (!(file = fopen(movie_filename, "rb"))) 1.1019 + { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1020 + //else 1.1021 + // movieReadOnly = 2; // we have to open the movie twice, no need to do this both times 1.1022 1.1023 -// if (!alreadyOpen) 1.1024 -// change_state(MOVIE_STATE_NONE); // stop current movie when we're able to open the other one 1.1025 -// 1.1026 -// if (!(file = fopen(movie_filename, "rb+"))) 1.1027 -// if(!(file = fopen(movie_filename, "rb"))) 1.1028 -// {loadingMovie = false; return MOVIE_FILE_NOT_FOUND;} 1.1029 -// else 1.1030 -// movieReadOnly = 2; 1.1031 + // if (!alreadyOpen) 1.1032 + // change_state(MOVIE_STATE_NONE); // stop current movie when we're able to open the other one 1.1033 + // 1.1034 + // if (!(file = fopen(movie_filename, "rb+"))) 1.1035 + // if(!(file = fopen(movie_filename, "rb"))) 1.1036 + // {loadingMovie = false; return MOVIE_FILE_NOT_FOUND;} 1.1037 + // else 1.1038 + // movieReadOnly = 2; 1.1039 1.1040 - // clear out the current movie 1.1041 - VBAMovieInit(); 1.1042 + // clear out the current movie 1.1043 + VBAMovieInit(); 1.1044 1.1045 - // read header 1.1046 - if ((result = read_movie_header(file, Movie)) != MOVIE_SUCCESS) 1.1047 - { 1.1048 - fclose(file); 1.1049 - { loadingMovie = false; return result; } 1.1050 - } 1.1051 + // read header 1.1052 + if ((result = read_movie_header(file, Movie)) != MOVIE_SUCCESS) 1.1053 + { 1.1054 + fclose(file); 1.1055 + { loadingMovie = false; return result; } 1.1056 + } 1.1057 1.1058 - // set emulator settings that make the movie more likely to stay synchronized 1.1059 - SetPlayEmuSettings(); 1.1060 + // set emulator settings that make the movie more likely to stay synchronized 1.1061 + SetPlayEmuSettings(); 1.1062 1.1063 -// extern bool systemLoadBIOS(); 1.1064 -// if (!systemLoadBIOS()) 1.1065 -// { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1066 + // extern bool systemLoadBIOS(); 1.1067 + // if (!systemLoadBIOS()) 1.1068 + // { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1069 1.1070 - // read the metadata / author info from file 1.1071 - fread(Movie.authorInfo, 1, MOVIE_METADATA_SIZE, file); 1.1072 - fn = dup(fileno(file)); // XXX: why does this fail?? it returns -1 but errno == 0 1.1073 - fclose(file); 1.1074 + // read the metadata / author info from file 1.1075 + fread(Movie.authorInfo, 1, MOVIE_METADATA_SIZE, file); 1.1076 + fn = dup(fileno(file)); // XXX: why does this fail?? it returns -1 but errno == 0 1.1077 + fclose(file); 1.1078 1.1079 - // apparently this lseek is necessary 1.1080 - lseek(fn, Movie.header.offset_to_savestate, SEEK_SET); 1.1081 - if (!(stream = utilGzReopen(fn, "rb"))) 1.1082 - if (!(stream = utilGzOpen(movie_filename, "rb"))) 1.1083 - { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1084 - else 1.1085 - fn = dup(fileno(file)); 1.1086 - // in case the above dup failed but opening the file normally doesn't fail 1.1087 + // apparently this lseek is necessary 1.1088 + lseek(fn, Movie.header.offset_to_savestate, SEEK_SET); 1.1089 + if (!(stream = utilGzReopen(fn, "rb"))) 1.1090 + if (!(stream = utilGzOpen(movie_filename, "rb"))) 1.1091 + { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1092 + else 1.1093 + fn = dup(fileno(file)); 1.1094 + // in case the above dup failed but opening the file normally doesn't fail 1.1095 1.1096 - if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT) 1.1097 - { 1.1098 - // load the snapshot 1.1099 - result = theEmulator.emuReadStateFromStream(stream) ? MOVIE_SUCCESS : MOVIE_WRONG_FORMAT; 1.1100 + if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT) 1.1101 + { 1.1102 + // load the snapshot 1.1103 + result = theEmulator.emuReadStateFromStream(stream) ? MOVIE_SUCCESS : MOVIE_WRONG_FORMAT; 1.1104 1.1105 - // FIXME: Kludge for conversion 1.1106 - remember_input_state(); 1.1107 - } 1.1108 - else if (Movie.header.startFlags & MOVIE_START_FROM_SRAM) 1.1109 - { 1.1110 - // 'soft' reset: 1.1111 - theEmulator.emuReset(false); 1.1112 + // FIXME: Kludge for conversion 1.1113 + remember_input_state(); 1.1114 + } 1.1115 + else if (Movie.header.startFlags & MOVIE_START_FROM_SRAM) 1.1116 + { 1.1117 + // 'soft' reset: 1.1118 + theEmulator.emuReset(false); 1.1119 1.1120 - // load the SRAM 1.1121 - result = theEmulator.emuReadBatteryFromStream(stream) ? MOVIE_SUCCESS : MOVIE_WRONG_FORMAT; 1.1122 - } 1.1123 - else 1.1124 - { 1.1125 - HardResetAndSRAMClear(); 1.1126 - } 1.1127 + // load the SRAM 1.1128 + result = theEmulator.emuReadBatteryFromStream(stream) ? MOVIE_SUCCESS : MOVIE_WRONG_FORMAT; 1.1129 + } 1.1130 + else 1.1131 + { 1.1132 + HardResetAndSRAMClear(); 1.1133 + } 1.1134 1.1135 - utilGzClose(stream); 1.1136 + utilGzClose(stream); 1.1137 1.1138 - if (result != MOVIE_SUCCESS) 1.1139 - { loadingMovie = false; return result; } 1.1140 + if (result != MOVIE_SUCCESS) 1.1141 + { loadingMovie = false; return result; } 1.1142 1.1143 -// if (!(file = fopen(movie_filename, /*read_only ? "rb" :*/ "rb+"))) // want to be able to switch out of read-only later 1.1144 -// { 1.1145 -// if(!Movie.readOnly || !(file = fopen(movie_filename, "rb"))) // try read-only if failed 1.1146 -// return MOVIE_FILE_NOT_FOUND; 1.1147 -// } 1.1148 - if (!(file = fopen(movie_filename, "rb+"))) 1.1149 - if (!(file = fopen(movie_filename, "rb"))) 1.1150 - { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1151 - else 1.1152 - movieReadOnly = 2; 1.1153 + // if (!(file = fopen(movie_filename, /*read_only ? "rb" :*/ "rb+"))) // want to be able to switch out of read-only later 1.1154 + // { 1.1155 + // if(!Movie.readOnly || !(file = fopen(movie_filename, "rb"))) // try read-only if failed 1.1156 + // return MOVIE_FILE_NOT_FOUND; 1.1157 + // } 1.1158 + if (!(file = fopen(movie_filename, "rb+"))) 1.1159 + if (!(file = fopen(movie_filename, "rb"))) 1.1160 + { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1161 + else 1.1162 + movieReadOnly = 2; 1.1163 1.1164 - // recalculate length of movie from the file size 1.1165 - Movie.bytesPerFrame = bytes_per_frame(Movie); 1.1166 - fseek(file, 0, SEEK_END); 1.1167 - long fileSize = ftell(file); 1.1168 - Movie.header.length_frames = (fileSize - Movie.header.offset_to_controller_data) / Movie.bytesPerFrame; 1.1169 + // recalculate length of movie from the file size 1.1170 + Movie.bytesPerFrame = bytes_per_frame(Movie); 1.1171 + fseek(file, 0, SEEK_END); 1.1172 + long fileSize = ftell(file); 1.1173 + Movie.header.length_frames = (fileSize - Movie.header.offset_to_controller_data) / Movie.bytesPerFrame; 1.1174 1.1175 - if (fseek(file, Movie.header.offset_to_controller_data, SEEK_SET)) 1.1176 - { fclose(file); loadingMovie = false; return MOVIE_WRONG_FORMAT; } 1.1177 + if (fseek(file, Movie.header.offset_to_controller_data, SEEK_SET)) 1.1178 + { fclose(file); loadingMovie = false; return MOVIE_WRONG_FORMAT; } 1.1179 1.1180 - strcpy(Movie.filename, movie_filename); 1.1181 - Movie.file = file; 1.1182 - Movie.inputBufferPtr = Movie.inputBuffer; 1.1183 - Movie.currentFrame = 0; 1.1184 - Movie.readOnly = movieReadOnly; 1.1185 - Movie.RecordedThisSession = false; 1.1186 + strcpy(Movie.filename, movie_filename); 1.1187 + Movie.file = file; 1.1188 + Movie.inputBufferPtr = Movie.inputBuffer; 1.1189 + Movie.currentFrame = 0; 1.1190 + Movie.readOnly = movieReadOnly; 1.1191 + Movie.RecordedThisSession = false; 1.1192 1.1193 - // read controller data 1.1194 - uint32 to_read = Movie.bytesPerFrame * Movie.header.length_frames; 1.1195 - reserve_buffer_space(to_read); 1.1196 - fread(Movie.inputBuffer, 1, to_read, file); 1.1197 + // read controller data 1.1198 + uint32 to_read = Movie.bytesPerFrame * Movie.header.length_frames; 1.1199 + reserve_buffer_space(to_read); 1.1200 + fread(Movie.inputBuffer, 1, to_read, file); 1.1201 1.1202 - change_state(MOVIE_STATE_PLAY); 1.1203 + change_state(MOVIE_STATE_PLAY); 1.1204 1.1205 - char messageString[64] = "Movie "; 1.1206 - bool converted = false; 1.1207 - if (autoConvertMovieWhenPlaying) 1.1208 - { 1.1209 - int result = VBAMovieConvertCurrent(); 1.1210 - if (result == MOVIE_SUCCESS) 1.1211 - strcat(messageString, "converted and "); 1.1212 - else if (result == MOVIE_WRONG_VERSION) 1.1213 - strcat(messageString, "higher revision "); 1.1214 - } 1.1215 + char messageString[64] = "Movie "; 1.1216 + bool converted = false; 1.1217 + if (autoConvertMovieWhenPlaying) 1.1218 + { 1.1219 + int result = VBAMovieConvertCurrent(); 1.1220 + if (result == MOVIE_SUCCESS) 1.1221 + strcat(messageString, "converted and "); 1.1222 + else if (result == MOVIE_WRONG_VERSION) 1.1223 + strcat(messageString, "higher revision "); 1.1224 + } 1.1225 1.1226 - if (Movie.state == MOVIE_STATE_PLAY) 1.1227 - strcat(messageString, "replaying "); 1.1228 - else 1.1229 - strcat(messageString, "finished "); 1.1230 - if (Movie.readOnly) 1.1231 - strcat(messageString, "(read)"); 1.1232 - else 1.1233 - strcat(messageString, "(edit)"); 1.1234 - systemScreenMessage(messageString); 1.1235 + if (Movie.state == MOVIE_STATE_PLAY) 1.1236 + strcat(messageString, "replaying "); 1.1237 + else 1.1238 + strcat(messageString, "finished "); 1.1239 + if (Movie.readOnly) 1.1240 + strcat(messageString, "(read)"); 1.1241 + else 1.1242 + strcat(messageString, "(edit)"); 1.1243 + systemScreenMessage(messageString); 1.1244 1.1245 - VBAUpdateButtonPressDisplay(); 1.1246 - VBAUpdateFrameCountDisplay(); 1.1247 - systemRefreshScreen(); 1.1248 + VBAUpdateButtonPressDisplay(); 1.1249 + VBAUpdateFrameCountDisplay(); 1.1250 + systemRefreshScreen(); 1.1251 1.1252 - { loadingMovie = false; return MOVIE_SUCCESS; } 1.1253 + { loadingMovie = false; return MOVIE_SUCCESS; } 1.1254 } 1.1255 1.1256 static void SetRecordEmuSettings() 1.1257 { 1.1258 - Movie.header.optionFlags = 0; 1.1259 + Movie.header.optionFlags = 0; 1.1260 #if (defined(WIN32) && !defined(SDL)) 1.1261 - if (theApp.useBiosFile) 1.1262 - Movie.header.optionFlags |= MOVIE_SETTING_USEBIOSFILE; 1.1263 - if (theApp.skipBiosFile) 1.1264 - Movie.header.optionFlags |= MOVIE_SETTING_SKIPBIOSFILE; 1.1265 - if (rtcIsEnabled()) 1.1266 - Movie.header.optionFlags |= MOVIE_SETTING_RTCENABLE; 1.1267 - Movie.header.saveType = theApp.winSaveType; 1.1268 - Movie.header.flashSize = theApp.winFlashSize; 1.1269 + if (theApp.useBiosFile) 1.1270 + Movie.header.optionFlags |= MOVIE_SETTING_USEBIOSFILE; 1.1271 + if (theApp.skipBiosFile) 1.1272 + Movie.header.optionFlags |= MOVIE_SETTING_SKIPBIOSFILE; 1.1273 + if (rtcIsEnabled()) 1.1274 + Movie.header.optionFlags |= MOVIE_SETTING_RTCENABLE; 1.1275 + Movie.header.saveType = theApp.winSaveType; 1.1276 + Movie.header.flashSize = theApp.winFlashSize; 1.1277 #else 1.1278 - extern int saveType, sdlRtcEnable, sdlFlashSize; // from SDL.cpp 1.1279 - extern bool8 useBios, skipBios; // from SDL.cpp 1.1280 - if (useBios) 1.1281 - Movie.header.optionFlags |= MOVIE_SETTING_USEBIOSFILE; 1.1282 - if (skipBios) 1.1283 - Movie.header.optionFlags |= MOVIE_SETTING_SKIPBIOSFILE; 1.1284 - if (sdlRtcEnable) 1.1285 - Movie.header.optionFlags |= MOVIE_SETTING_RTCENABLE; 1.1286 - Movie.header.saveType = saveType; 1.1287 - Movie.header.flashSize = sdlFlashSize; 1.1288 + extern int saveType, sdlRtcEnable, sdlFlashSize; // from SDL.cpp 1.1289 + extern bool8 useBios, skipBios; // from SDL.cpp 1.1290 + if (useBios) 1.1291 + Movie.header.optionFlags |= MOVIE_SETTING_USEBIOSFILE; 1.1292 + if (skipBios) 1.1293 + Movie.header.optionFlags |= MOVIE_SETTING_SKIPBIOSFILE; 1.1294 + if (sdlRtcEnable) 1.1295 + Movie.header.optionFlags |= MOVIE_SETTING_RTCENABLE; 1.1296 + Movie.header.saveType = saveType; 1.1297 + Movie.header.flashSize = sdlFlashSize; 1.1298 #endif 1.1299 - prevEmulatorType = Movie.header.gbEmulatorType = gbEmulatorType; 1.1300 + prevEmulatorType = Movie.header.gbEmulatorType = gbEmulatorType; 1.1301 1.1302 - if (!memLagTempEnabled) 1.1303 - Movie.header.optionFlags |= MOVIE_SETTING_LAGHACK; 1.1304 + if (!memLagTempEnabled) 1.1305 + Movie.header.optionFlags |= MOVIE_SETTING_LAGHACK; 1.1306 1.1307 - if (gbNullInputHackTempEnabled) 1.1308 - Movie.header.optionFlags |= MOVIE_SETTING_GBINPUTHACK; 1.1309 + if (gbNullInputHackTempEnabled) 1.1310 + Movie.header.optionFlags |= MOVIE_SETTING_GBINPUTHACK; 1.1311 1.1312 - Movie.header.optionFlags |= MOVIE_SETTING_GBCFF55FIX; 1.1313 - extern int32 gbDMASpeedVersion; 1.1314 - gbDMASpeedVersion = 1; 1.1315 + Movie.header.optionFlags |= MOVIE_SETTING_GBCFF55FIX; 1.1316 + extern int32 gbDMASpeedVersion; 1.1317 + gbDMASpeedVersion = 1; 1.1318 1.1319 - Movie.header.optionFlags |= MOVIE_SETTING_GBECHORAMFIX; 1.1320 - extern int32 gbEchoRAMFixOn; 1.1321 - gbEchoRAMFixOn = 1; 1.1322 + Movie.header.optionFlags |= MOVIE_SETTING_GBECHORAMFIX; 1.1323 + extern int32 gbEchoRAMFixOn; 1.1324 + gbEchoRAMFixOn = 1; 1.1325 1.1326 - // some GB/GBC games depend on the sound rate, so just use the highest one 1.1327 - systemSoundSetQuality(1); 1.1328 + // some GB/GBC games depend on the sound rate, so just use the highest one 1.1329 + systemSoundSetQuality(1); 1.1330 1.1331 - useOldFrameTiming = false; 1.1332 + useOldFrameTiming = false; 1.1333 1.1334 #if (defined(WIN32) && !defined(SDL)) 1.1335 -// theApp.removeIntros = false; 1.1336 + // theApp.removeIntros = false; 1.1337 1.1338 - prevBorder = gbBorderOn; 1.1339 - prevWinBorder = theApp.winGbBorderOn; 1.1340 - prevBorderAuto = gbBorderAutomatic; 1.1341 - if (gbEmulatorType == 2 || gbEmulatorType == 5) // only games played in SGB mode will have a border 1.1342 - { 1.1343 - gbBorderOn = true; 1.1344 - theApp.winGbBorderOn = true; 1.1345 - gbBorderAutomatic = false; 1.1346 - } 1.1347 - else 1.1348 - { 1.1349 - gbBorderOn = false; 1.1350 - theApp.winGbBorderOn = false; 1.1351 - gbBorderAutomatic = false; 1.1352 - } 1.1353 - systemGbBorderOn(); 1.1354 + prevBorder = gbBorderOn; 1.1355 + prevWinBorder = theApp.winGbBorderOn; 1.1356 + prevBorderAuto = gbBorderAutomatic; 1.1357 + if (gbEmulatorType == 2 || gbEmulatorType == 5) // only games played in SGB mode will have a border 1.1358 + { 1.1359 + gbBorderOn = true; 1.1360 + theApp.winGbBorderOn = true; 1.1361 + gbBorderAutomatic = false; 1.1362 + } 1.1363 + else 1.1364 + { 1.1365 + gbBorderOn = false; 1.1366 + theApp.winGbBorderOn = false; 1.1367 + gbBorderAutomatic = false; 1.1368 + } 1.1369 + systemGbBorderOn(); 1.1370 #else 1.1371 - /// SDLFIXME 1.1372 + /// SDLFIXME 1.1373 #endif 1.1374 } 1.1375 1.1376 uint16 VBAMovieGetCurrentInputOf(int controllerNum, bool normalOnly) 1.1377 { 1.1378 - if (controllerNum < 0 || controllerNum >= MOVIE_NUM_OF_POSSIBLE_CONTROLLERS) 1.1379 - return 0; 1.1380 + if (controllerNum < 0 || controllerNum >= MOVIE_NUM_OF_POSSIBLE_CONTROLLERS) 1.1381 + return 0; 1.1382 1.1383 - return normalOnly ? (currentButtons[controllerNum] & BUTTON_REGULAR_MASK) : currentButtons[controllerNum]; 1.1384 + return normalOnly ? (currentButtons[controllerNum] & BUTTON_REGULAR_MASK) : currentButtons[controllerNum]; 1.1385 } 1.1386 1.1387 int VBAMovieCreate(const char *filename, const char *authorInfo, uint8 startFlags, uint8 controllerFlags, uint8 typeFlags) 1.1388 { 1.1389 - // make sure at least one controller is enabled 1.1390 - if ((controllerFlags & MOVIE_CONTROLLERS_ANY_MASK) == 0) 1.1391 - return MOVIE_WRONG_FORMAT; 1.1392 + // make sure at least one controller is enabled 1.1393 + if ((controllerFlags & MOVIE_CONTROLLERS_ANY_MASK) == 0) 1.1394 + return MOVIE_WRONG_FORMAT; 1.1395 1.1396 - if (!emulating) 1.1397 - return MOVIE_UNKNOWN_ERROR; 1.1398 + if (!emulating) 1.1399 + return MOVIE_UNKNOWN_ERROR; 1.1400 1.1401 - loadingMovie = true; 1.1402 + loadingMovie = true; 1.1403 1.1404 - FILE * file; 1.1405 - STREAM stream; 1.1406 - int fn; 1.1407 + FILE * file; 1.1408 + STREAM stream; 1.1409 + int fn; 1.1410 1.1411 - char movie_filename [_MAX_PATH]; 1.1412 + char movie_filename [_MAX_PATH]; 1.1413 #ifdef WIN32 1.1414 - _fullpath(movie_filename, filename, _MAX_PATH); 1.1415 + _fullpath(movie_filename, filename, _MAX_PATH); 1.1416 #else 1.1417 - // FIXME: convert to fullpath 1.1418 - strncpy(movie_filename, filename, _MAX_PATH); 1.1419 - movie_filename[_MAX_PATH - 1] = '\0'; 1.1420 + // FIXME: convert to fullpath 1.1421 + strncpy(movie_filename, filename, _MAX_PATH); 1.1422 + movie_filename[_MAX_PATH - 1] = '\0'; 1.1423 #endif 1.1424 1.1425 - bool alreadyOpen = (Movie.file != NULL && stricmp(movie_filename, Movie.filename) == 0); 1.1426 + bool alreadyOpen = (Movie.file != NULL && stricmp(movie_filename, Movie.filename) == 0); 1.1427 1.1428 - if (alreadyOpen) 1.1429 - change_state(MOVIE_STATE_NONE); // have to stop current movie before trying to re-open it 1.1430 + if (alreadyOpen) 1.1431 + change_state(MOVIE_STATE_NONE); // have to stop current movie before trying to re-open it 1.1432 1.1433 - if (movie_filename[0] == '\0') 1.1434 + if (movie_filename[0] == '\0') 1.1435 + { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1436 + 1.1437 + if (!(file = fopen(movie_filename, "wb"))) 1.1438 + { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1439 + 1.1440 + if (!alreadyOpen) 1.1441 + change_state(MOVIE_STATE_NONE); // stop current movie when we're able to open the other one 1.1442 + 1.1443 + // clear out the current movie 1.1444 + printf("RLM: movie init\n"); 1.1445 + 1.1446 + VBAMovieInit(); 1.1447 + 1.1448 + // fill in the movie's header 1.1449 + Movie.header.uid = (uint32)time(NULL); 1.1450 + Movie.header.magic = VBM_MAGIC; 1.1451 + Movie.header.version = VBM_VERSION; 1.1452 + Movie.header.rerecord_count = 0; 1.1453 + Movie.header.length_frames = 0; 1.1454 + Movie.header.startFlags = startFlags; 1.1455 + Movie.header.controllerFlags = controllerFlags; 1.1456 + Movie.header.typeFlags = typeFlags; 1.1457 + Movie.header.minorVersion = VBM_REVISION; 1.1458 + 1.1459 + // set emulator settings that make the movie more likely to stay synchronized when it's later played back 1.1460 + SetRecordEmuSettings(); 1.1461 + 1.1462 + // set ROM and BIOS checksums and stuff 1.1463 + VBAMovieGetRomInfo(Movie, Movie.header.romTitle, Movie.header.romGameCode, Movie.header.romOrBiosChecksum, Movie.header.romCRC); 1.1464 + 1.1465 + printf("RLM: Writing movie header\n"); 1.1466 + // write the header to file 1.1467 + write_movie_header(file, Movie); 1.1468 + 1.1469 + printf("RLM: setting metadata\n"); 1.1470 + 1.1471 + // copy over the metadata / author info 1.1472 + VBAMovieSetMetadata("________________Robert McIntyre______________________________________________________________________________________________________________________________________________________________________________________________________________________"); 1.1473 + 1.1474 + printf("RLM: writing metadata\n"); 1.1475 + 1.1476 + // write the metadata / author info to file 1.1477 + 1.1478 + 1.1479 + fwrite(Movie.authorInfo, 1, sizeof(char) * MOVIE_METADATA_SIZE, file); 1.1480 + 1.1481 + // write snapshot or SRAM if applicable 1.1482 + if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT 1.1483 + || Movie.header.startFlags & MOVIE_START_FROM_SRAM) 1.1484 + { 1.1485 + Movie.header.offset_to_savestate = (uint32)ftell(file); 1.1486 + 1.1487 + // close the file and reopen it as a stream: 1.1488 + 1.1489 + fn = dup(fileno(file)); 1.1490 + fclose(file); 1.1491 + 1.1492 + if (!(stream = utilGzReopen(fn, "ab"))) // append mode to start at end, no seek necessary 1.1493 { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1494 1.1495 - if (!(file = fopen(movie_filename, "wb"))) 1.1496 + // write the save data: 1.1497 + if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT) 1.1498 + { 1.1499 + // save snapshot 1.1500 + if (!theEmulator.emuWriteStateToStream(stream)) 1.1501 + { 1.1502 + utilGzClose(stream); 1.1503 + { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1504 + } 1.1505 + } 1.1506 + else if (Movie.header.startFlags & MOVIE_START_FROM_SRAM) 1.1507 + { 1.1508 + // save SRAM 1.1509 + if (!theEmulator.emuWriteBatteryToStream(stream)) 1.1510 + { 1.1511 + utilGzClose(stream); 1.1512 + { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1513 + } 1.1514 + 1.1515 + // 'soft' reset: 1.1516 + theEmulator.emuReset(false); 1.1517 + } 1.1518 + 1.1519 + utilGzClose(stream); 1.1520 + 1.1521 + // reopen the file and seek back to the end 1.1522 + 1.1523 + if (!(file = fopen(movie_filename, "rb+"))) 1.1524 { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1525 1.1526 - if (!alreadyOpen) 1.1527 - change_state(MOVIE_STATE_NONE); // stop current movie when we're able to open the other one 1.1528 + fseek(file, 0, SEEK_END); 1.1529 + } 1.1530 + else // no snapshot or SRAM 1.1531 + { 1.1532 + HardResetAndSRAMClear(); 1.1533 + } 1.1534 1.1535 - // clear out the current movie 1.1536 - VBAMovieInit(); 1.1537 + Movie.header.offset_to_controller_data = (uint32)ftell(file); 1.1538 1.1539 - // fill in the movie's header 1.1540 - Movie.header.uid = (uint32)time(NULL); 1.1541 - Movie.header.magic = VBM_MAGIC; 1.1542 - Movie.header.version = VBM_VERSION; 1.1543 - Movie.header.rerecord_count = 0; 1.1544 - Movie.header.length_frames = 0; 1.1545 - Movie.header.startFlags = startFlags; 1.1546 - Movie.header.controllerFlags = controllerFlags; 1.1547 - Movie.header.typeFlags = typeFlags; 1.1548 - Movie.header.minorVersion = VBM_REVISION; 1.1549 + strcpy(Movie.filename, movie_filename); 1.1550 + Movie.file = file; 1.1551 + Movie.bytesPerFrame = bytes_per_frame(Movie); 1.1552 + Movie.inputBufferPtr = Movie.inputBuffer; 1.1553 + Movie.currentFrame = 0; 1.1554 + Movie.readOnly = false; 1.1555 + Movie.RecordedThisSession = true; 1.1556 1.1557 - // set emulator settings that make the movie more likely to stay synchronized when it's later played back 1.1558 - SetRecordEmuSettings(); 1.1559 + change_state(MOVIE_STATE_RECORD); 1.1560 1.1561 - // set ROM and BIOS checksums and stuff 1.1562 - VBAMovieGetRomInfo(Movie, Movie.header.romTitle, Movie.header.romGameCode, Movie.header.romOrBiosChecksum, Movie.header.romCRC); 1.1563 - 1.1564 - // write the header to file 1.1565 - write_movie_header(file, Movie); 1.1566 - 1.1567 - // copy over the metadata / author info 1.1568 - VBAMovieSetMetadata(authorInfo); 1.1569 - 1.1570 - // write the metadata / author info to file 1.1571 - fwrite(Movie.authorInfo, 1, sizeof(char) * MOVIE_METADATA_SIZE, file); 1.1572 - 1.1573 - // write snapshot or SRAM if applicable 1.1574 - if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT 1.1575 - || Movie.header.startFlags & MOVIE_START_FROM_SRAM) 1.1576 - { 1.1577 - Movie.header.offset_to_savestate = (uint32)ftell(file); 1.1578 - 1.1579 - // close the file and reopen it as a stream: 1.1580 - 1.1581 - fn = dup(fileno(file)); 1.1582 - fclose(file); 1.1583 - 1.1584 - if (!(stream = utilGzReopen(fn, "ab"))) // append mode to start at end, no seek necessary 1.1585 - { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1586 - 1.1587 - // write the save data: 1.1588 - if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT) 1.1589 - { 1.1590 - // save snapshot 1.1591 - if (!theEmulator.emuWriteStateToStream(stream)) 1.1592 - { 1.1593 - utilGzClose(stream); 1.1594 - { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1595 - } 1.1596 - } 1.1597 - else if (Movie.header.startFlags & MOVIE_START_FROM_SRAM) 1.1598 - { 1.1599 - // save SRAM 1.1600 - if (!theEmulator.emuWriteBatteryToStream(stream)) 1.1601 - { 1.1602 - utilGzClose(stream); 1.1603 - { loadingMovie = false; return MOVIE_UNKNOWN_ERROR; } 1.1604 - } 1.1605 - 1.1606 - // 'soft' reset: 1.1607 - theEmulator.emuReset(false); 1.1608 - } 1.1609 - 1.1610 - utilGzClose(stream); 1.1611 - 1.1612 - // reopen the file and seek back to the end 1.1613 - 1.1614 - if (!(file = fopen(movie_filename, "rb+"))) 1.1615 - { loadingMovie = false; return MOVIE_FILE_NOT_FOUND; } 1.1616 - 1.1617 - fseek(file, 0, SEEK_END); 1.1618 - } 1.1619 - else // no snapshot or SRAM 1.1620 - { 1.1621 - HardResetAndSRAMClear(); 1.1622 - } 1.1623 - 1.1624 - Movie.header.offset_to_controller_data = (uint32)ftell(file); 1.1625 - 1.1626 - strcpy(Movie.filename, movie_filename); 1.1627 - Movie.file = file; 1.1628 - Movie.bytesPerFrame = bytes_per_frame(Movie); 1.1629 - Movie.inputBufferPtr = Movie.inputBuffer; 1.1630 - Movie.currentFrame = 0; 1.1631 - Movie.readOnly = false; 1.1632 - Movie.RecordedThisSession = true; 1.1633 - 1.1634 - change_state(MOVIE_STATE_RECORD); 1.1635 - 1.1636 - systemScreenMessage("Recording movie..."); 1.1637 - { loadingMovie = false; return MOVIE_SUCCESS; } 1.1638 + systemScreenMessage("Recording movie..."); 1.1639 + { loadingMovie = false; return MOVIE_SUCCESS; } 1.1640 } 1.1641 1.1642 void VBAUpdateButtonPressDisplay() 1.1643 { 1.1644 - uint32 keys = currentButtons[0] & BUTTON_REGULAR_RECORDING_MASK; 1.1645 + uint32 keys = currentButtons[0] & BUTTON_REGULAR_RECORDING_MASK; 1.1646 1.1647 - const static char KeyMap[] = { 'A', 'B', 's', 'S', '>', '<', '^', 'v', 'R', 'L', '!', '?', '{', '}', 'v', '^' }; 1.1648 - const static int KeyOrder[] = { 5, 6, 4, 7, 0, 1, 9, 8, 3, 2, 12, 15, 13, 14, 11, 10 }; // < ^ > v A B L R S s { = } _ 1.1649 - // ? ! 1.1650 - char buffer[256]; 1.1651 - sprintf(buffer, " "); 1.1652 + const static char KeyMap[] = { 'A', 'B', 's', 'S', '>', '<', '^', 'v', 'R', 'L', '!', '?', '{', '}', 'v', '^' }; 1.1653 + const static int KeyOrder[] = { 5, 6, 4, 7, 0, 1, 9, 8, 3, 2, 12, 15, 13, 14, 11, 10 }; // < ^ > v A B L R S s { = } _ 1.1654 + // ? ! 1.1655 + char buffer[256]; 1.1656 + sprintf(buffer, " "); 1.1657 1.1658 #ifndef WIN32 1.1659 - // don't bother color-coding autofire and such 1.1660 - int i; 1.1661 - for (i = 0; i < 15; i++) 1.1662 + // don't bother color-coding autofire and such 1.1663 + int i; 1.1664 + for (i = 0; i < 15; i++) 1.1665 + { 1.1666 + int j = KeyOrder[i]; 1.1667 + int mask = (1 << (j)); 1.1668 + buffer[strlen(" ") + i] = ((keys & mask) != 0) ? KeyMap[j] : ' '; 1.1669 + } 1.1670 + 1.1671 + systemScreenMessage(buffer, 2, -1); 1.1672 +#else 1.1673 + const bool eraseAll = !theApp.inputDisplay; 1.1674 + uint32 autoHeldKeys = eraseAll ? 0 : theApp.autoHold & BUTTON_REGULAR_RECORDING_MASK; 1.1675 + uint32 autoFireKeys = eraseAll ? 0 : (theApp.autoFire | theApp.autoFire2) & BUTTON_REGULAR_RECORDING_MASK; 1.1676 + uint32 pressedKeys = eraseAll ? 0 : keys; 1.1677 + 1.1678 + char colorList[64]; 1.1679 + memset(colorList, 1, strlen(buffer)); 1.1680 + 1.1681 + if (!eraseAll) 1.1682 + { 1.1683 + for (int i = 0; i < 15; i++) 1.1684 { 1.1685 - int j = KeyOrder[i]; 1.1686 - int mask = (1 << (j)); 1.1687 - buffer[strlen(" ") + i] = ((keys & mask) != 0) ? KeyMap[j] : ' '; 1.1688 + const int j = KeyOrder[i]; 1.1689 + const int mask = (1 << (j)); 1.1690 + bool pressed = (pressedKeys & mask) != 0; 1.1691 + const bool autoHeld = (autoHeldKeys & mask) != 0; 1.1692 + const bool autoFired = (autoFireKeys & mask) != 0; 1.1693 + const bool erased = (lastKeys & mask) != 0 && (!pressed && !autoHeld && !autoFired); 1.1694 + extern int textMethod; 1.1695 + if (textMethod != 2 && (autoHeld || (autoFired && !pressed) || erased)) 1.1696 + { 1.1697 + int colorNum = 1; // default is white 1.1698 + if (autoHeld) 1.1699 + colorNum += (pressed ? 2 : 1); // yellow if pressed, red if not 1.1700 + else if (autoFired) 1.1701 + colorNum += 5; // blue if autofired and not currently pressed 1.1702 + else if (erased) 1.1703 + colorNum += 8; // black on black 1.1704 + 1.1705 + colorList[strlen(" ") + i] = colorNum; 1.1706 + pressed = true; 1.1707 + } 1.1708 + buffer[strlen(" ") + i] = pressed ? KeyMap[j] : ' '; 1.1709 } 1.1710 + } 1.1711 1.1712 - systemScreenMessage(buffer, 2, -1); 1.1713 -#else 1.1714 - const bool eraseAll = !theApp.inputDisplay; 1.1715 - uint32 autoHeldKeys = eraseAll ? 0 : theApp.autoHold & BUTTON_REGULAR_RECORDING_MASK; 1.1716 - uint32 autoFireKeys = eraseAll ? 0 : (theApp.autoFire | theApp.autoFire2) & BUTTON_REGULAR_RECORDING_MASK; 1.1717 - uint32 pressedKeys = eraseAll ? 0 : keys; 1.1718 + lastKeys = currentButtons[0]; 1.1719 + lastKeys |= theApp.autoHold & BUTTON_REGULAR_RECORDING_MASK; 1.1720 + lastKeys |= (theApp.autoFire | theApp.autoFire2) & BUTTON_REGULAR_RECORDING_MASK; 1.1721 1.1722 - char colorList[64]; 1.1723 - memset(colorList, 1, strlen(buffer)); 1.1724 - 1.1725 - if (!eraseAll) 1.1726 - { 1.1727 - for (int i = 0; i < 15; i++) 1.1728 - { 1.1729 - const int j = KeyOrder[i]; 1.1730 - const int mask = (1 << (j)); 1.1731 - bool pressed = (pressedKeys & mask) != 0; 1.1732 - const bool autoHeld = (autoHeldKeys & mask) != 0; 1.1733 - const bool autoFired = (autoFireKeys & mask) != 0; 1.1734 - const bool erased = (lastKeys & mask) != 0 && (!pressed && !autoHeld && !autoFired); 1.1735 - extern int textMethod; 1.1736 - if (textMethod != 2 && (autoHeld || (autoFired && !pressed) || erased)) 1.1737 - { 1.1738 - int colorNum = 1; // default is white 1.1739 - if (autoHeld) 1.1740 - colorNum += (pressed ? 2 : 1); // yellow if pressed, red if not 1.1741 - else if (autoFired) 1.1742 - colorNum += 5; // blue if autofired and not currently pressed 1.1743 - else if (erased) 1.1744 - colorNum += 8; // black on black 1.1745 - 1.1746 - colorList[strlen(" ") + i] = colorNum; 1.1747 - pressed = true; 1.1748 - } 1.1749 - buffer[strlen(" ") + i] = pressed ? KeyMap[j] : ' '; 1.1750 - } 1.1751 - } 1.1752 - 1.1753 - lastKeys = currentButtons[0]; 1.1754 - lastKeys |= theApp.autoHold & BUTTON_REGULAR_RECORDING_MASK; 1.1755 - lastKeys |= (theApp.autoFire | theApp.autoFire2) & BUTTON_REGULAR_RECORDING_MASK; 1.1756 - 1.1757 - systemScreenMessage(buffer, 2, -1, colorList); 1.1758 + systemScreenMessage(buffer, 2, -1, colorList); 1.1759 #endif 1.1760 } 1.1761 1.1762 void VBAUpdateFrameCountDisplay() 1.1763 { 1.1764 - const int MAGICAL_NUMBER = 64; // FIXME: this won't do any better, but only to remind you of sz issues 1.1765 - char frameDisplayString[MAGICAL_NUMBER]; 1.1766 - char lagFrameDisplayString[MAGICAL_NUMBER]; 1.1767 - char extraCountDisplayString[MAGICAL_NUMBER]; 1.1768 + const int MAGICAL_NUMBER = 64; // FIXME: this won't do any better, but only to remind you of sz issues 1.1769 + char frameDisplayString[MAGICAL_NUMBER]; 1.1770 + char lagFrameDisplayString[MAGICAL_NUMBER]; 1.1771 + char extraCountDisplayString[MAGICAL_NUMBER]; 1.1772 1.1773 #if (defined(WIN32) && !defined(SDL)) 1.1774 - if (theApp.frameCounter) 1.1775 + if (theApp.frameCounter) 1.1776 +#else 1.1777 + /// SDL FIXME 1.1778 +#endif 1.1779 + { 1.1780 + switch (Movie.state) 1.1781 + { 1.1782 + case MOVIE_STATE_PLAY: 1.1783 + case MOVIE_STATE_END: 1.1784 + { 1.1785 + sprintf(frameDisplayString, "%d / %d", Movie.currentFrame, Movie.header.length_frames); 1.1786 + if (!Movie.readOnly) 1.1787 + strcat(frameDisplayString, " (edit)"); 1.1788 + break; 1.1789 + } 1.1790 + case MOVIE_STATE_RECORD: 1.1791 + { 1.1792 + sprintf(frameDisplayString, "%d (record)", Movie.currentFrame); 1.1793 + break; 1.1794 + } 1.1795 + default: 1.1796 + { 1.1797 + sprintf(frameDisplayString, "%d (no movie)", systemCounters.frameCount); 1.1798 + break; 1.1799 + } 1.1800 + } 1.1801 + 1.1802 +#if (defined(WIN32) && !defined(SDL)) 1.1803 + if (theApp.lagCounter) 1.1804 #else 1.1805 /// SDL FIXME 1.1806 #endif 1.1807 { 1.1808 - switch (Movie.state) 1.1809 - { 1.1810 - case MOVIE_STATE_PLAY: 1.1811 - case MOVIE_STATE_END: 1.1812 - { 1.1813 - sprintf(frameDisplayString, "%d / %d", Movie.currentFrame, Movie.header.length_frames); 1.1814 - if (!Movie.readOnly) 1.1815 - strcat(frameDisplayString, " (edit)"); 1.1816 - break; 1.1817 - } 1.1818 - case MOVIE_STATE_RECORD: 1.1819 - { 1.1820 - sprintf(frameDisplayString, "%d (record)", Movie.currentFrame); 1.1821 - break; 1.1822 - } 1.1823 - default: 1.1824 - { 1.1825 - sprintf(frameDisplayString, "%d (no movie)", systemCounters.frameCount); 1.1826 - break; 1.1827 - } 1.1828 - } 1.1829 + // sprintf(lagFrameDisplayString, " %c %d", systemCounters.laggedLast ? '*' : '|', systemCounters.lagCount); 1.1830 + sprintf(lagFrameDisplayString, " | %d%s", systemCounters.lagCount, systemCounters.laggedLast ? " *" : ""); 1.1831 + strcat(frameDisplayString, lagFrameDisplayString); 1.1832 + } 1.1833 1.1834 #if (defined(WIN32) && !defined(SDL)) 1.1835 - if (theApp.lagCounter) 1.1836 -#else 1.1837 - /// SDL FIXME 1.1838 -#endif 1.1839 - { 1.1840 -// sprintf(lagFrameDisplayString, " %c %d", systemCounters.laggedLast ? '*' : '|', systemCounters.lagCount); 1.1841 - sprintf(lagFrameDisplayString, " | %d%s", systemCounters.lagCount, systemCounters.laggedLast ? " *" : ""); 1.1842 - strcat(frameDisplayString, lagFrameDisplayString); 1.1843 - } 1.1844 - 1.1845 -#if (defined(WIN32) && !defined(SDL)) 1.1846 - if (theApp.extraCounter) 1.1847 -#else 1.1848 - /// SDL FIXME 1.1849 -#endif 1.1850 - { 1.1851 - sprintf(extraCountDisplayString, " | %d", systemCounters.frameCount - systemCounters.extraCount); 1.1852 - strcat(frameDisplayString, extraCountDisplayString); 1.1853 - } 1.1854 - } 1.1855 -#if (defined(WIN32) && !defined(SDL)) 1.1856 - else 1.1857 - { 1.1858 - frameDisplayString[0] = '\0'; 1.1859 - } 1.1860 + if (theApp.extraCounter) 1.1861 #else 1.1862 /// SDL FIXME 1.1863 #endif 1.1864 - systemScreenMessage(frameDisplayString, 1, -1); 1.1865 + { 1.1866 + sprintf(extraCountDisplayString, " | %d", systemCounters.frameCount - systemCounters.extraCount); 1.1867 + strcat(frameDisplayString, extraCountDisplayString); 1.1868 + } 1.1869 + } 1.1870 +#if (defined(WIN32) && !defined(SDL)) 1.1871 + else 1.1872 + { 1.1873 + frameDisplayString[0] = '\0'; 1.1874 + } 1.1875 +#else 1.1876 + /// SDL FIXME 1.1877 +#endif 1.1878 + systemScreenMessage(frameDisplayString, 1, -1); 1.1879 } 1.1880 1.1881 // this function should only be called once every frame 1.1882 void VBAMovieUpdateState() 1.1883 { 1.1884 - ++Movie.currentFrame; 1.1885 - 1.1886 - if (Movie.state == MOVIE_STATE_PLAY) 1.1887 + ++Movie.currentFrame; 1.1888 + printf("RLM: inside updateState\n"); 1.1889 + if (Movie.state == MOVIE_STATE_PLAY) 1.1890 + { 1.1891 + Movie.inputBufferPtr += Movie.bytesPerFrame; 1.1892 + if (Movie.currentFrame >= Movie.header.length_frames) 1.1893 { 1.1894 - Movie.inputBufferPtr += Movie.bytesPerFrame; 1.1895 - if (Movie.currentFrame >= Movie.header.length_frames) 1.1896 - { 1.1897 - // the movie ends anyway; what to do next depends on the settings 1.1898 - change_state(MOVIE_STATE_END); 1.1899 - } 1.1900 + // the movie ends anyway; what to do next depends on the settings 1.1901 + change_state(MOVIE_STATE_END); 1.1902 } 1.1903 - else if (Movie.state == MOVIE_STATE_RECORD) 1.1904 - { 1.1905 - // use first fseek? 1.1906 - fwrite(Movie.inputBufferPtr, 1, Movie.bytesPerFrame, Movie.file); 1.1907 - Movie.header.length_frames = Movie.currentFrame; 1.1908 - Movie.inputBufferPtr += Movie.bytesPerFrame; 1.1909 - Movie.RecordedThisSession = true; 1.1910 - flush_movie_header(); 1.1911 - } 1.1912 - else if (Movie.state == MOVIE_STATE_END) 1.1913 - { 1.1914 - change_state(MOVIE_STATE_END); 1.1915 - } 1.1916 + } 1.1917 + else if (Movie.state == MOVIE_STATE_RECORD) 1.1918 + { 1.1919 + printf("RLM: Movie_STATE_RECORD\n"); 1.1920 + // use first fseek? 1.1921 + //TODO: THis is the problem. 1.1922 + //fwrite(Movie.inputBufferPtr, 1, Movie.bytesPerFrame, Movie.file); 1.1923 + printf("RLM: fuck.\n"); 1.1924 + Movie.header.length_frames = Movie.currentFrame; 1.1925 + Movie.inputBufferPtr += Movie.bytesPerFrame; 1.1926 + Movie.RecordedThisSession = true; 1.1927 + flush_movie_header(); 1.1928 + } 1.1929 + else if (Movie.state == MOVIE_STATE_END) 1.1930 + { 1.1931 + change_state(MOVIE_STATE_END); 1.1932 + } 1.1933 } 1.1934 1.1935 void VBAMovieRead(int i, bool /*sensor*/) 1.1936 { 1.1937 - if (Movie.state != MOVIE_STATE_PLAY) 1.1938 - return; 1.1939 + if (Movie.state != MOVIE_STATE_PLAY) 1.1940 + return; 1.1941 1.1942 - if (i < 0 || i >= MOVIE_NUM_OF_POSSIBLE_CONTROLLERS) 1.1943 - return; // not a controller we're recognizing 1.1944 + if (i < 0 || i >= MOVIE_NUM_OF_POSSIBLE_CONTROLLERS) 1.1945 + return; // not a controller we're recognizing 1.1946 1.1947 - if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.1948 - { 1.1949 - currentButtons[i] = Read16(Movie.inputBufferPtr + CONTROLLER_DATA_SIZE * i); 1.1950 - } 1.1951 - else 1.1952 - { 1.1953 - currentButtons[i] = 0; // pretend the controller is disconnected 1.1954 - } 1.1955 + if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.1956 + { 1.1957 + currentButtons[i] = Read16(Movie.inputBufferPtr + CONTROLLER_DATA_SIZE * i); 1.1958 + } 1.1959 + else 1.1960 + { 1.1961 + currentButtons[i] = 0; // pretend the controller is disconnected 1.1962 + } 1.1963 1.1964 - if ((currentButtons[i] & BUTTON_MASK_NEW_RESET) != 0) 1.1965 - resetSignaled = true; 1.1966 + if ((currentButtons[i] & BUTTON_MASK_NEW_RESET) != 0) 1.1967 + resetSignaled = true; 1.1968 } 1.1969 1.1970 void VBAMovieWrite(int i, bool /*sensor*/) 1.1971 { 1.1972 - if (Movie.state != MOVIE_STATE_RECORD) 1.1973 - return; 1.1974 + if (Movie.state != MOVIE_STATE_RECORD) 1.1975 + return; 1.1976 1.1977 - if (i < 0 || i >= MOVIE_NUM_OF_POSSIBLE_CONTROLLERS) 1.1978 - return; // not a controller we're recognizing 1.1979 + if (i < 0 || i >= MOVIE_NUM_OF_POSSIBLE_CONTROLLERS) 1.1980 + return; // not a controller we're recognizing 1.1981 1.1982 - reserve_buffer_space((uint32)((Movie.inputBufferPtr - Movie.inputBuffer) + Movie.bytesPerFrame)); 1.1983 + reserve_buffer_space((uint32)((Movie.inputBufferPtr - Movie.inputBuffer) + Movie.bytesPerFrame)); 1.1984 1.1985 - if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.1986 + if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.1987 + { 1.1988 + // get the current controller data 1.1989 + uint16 buttonData = currentButtons[i]; 1.1990 + 1.1991 + // mask away the irrelevent bits 1.1992 + buttonData &= BUTTON_REGULAR_MASK | BUTTON_MOTION_MASK; 1.1993 + 1.1994 + // soft-reset "button" for 1 frame if the game is reset while recording 1.1995 + if (resetSignaled) 1.1996 { 1.1997 - // get the current controller data 1.1998 - uint16 buttonData = currentButtons[i]; 1.1999 + buttonData |= BUTTON_MASK_NEW_RESET; 1.2000 + } 1.2001 1.2002 - // mask away the irrelevent bits 1.2003 - buttonData &= BUTTON_REGULAR_MASK | BUTTON_MOTION_MASK; 1.2004 + // backward compatibility kludge 1.2005 + if (resetSignaledLast) 1.2006 + { 1.2007 + buttonData |= BUTTON_MASK_OLD_RESET; 1.2008 + } 1.2009 1.2010 - // soft-reset "button" for 1 frame if the game is reset while recording 1.2011 - if (resetSignaled) 1.2012 - { 1.2013 - buttonData |= BUTTON_MASK_NEW_RESET; 1.2014 - } 1.2015 + Write16(buttonData, Movie.inputBufferPtr + CONTROLLER_DATA_SIZE * i); 1.2016 1.2017 - // backward compatibility kludge 1.2018 - if (resetSignaledLast) 1.2019 - { 1.2020 - buttonData |= BUTTON_MASK_OLD_RESET; 1.2021 - } 1.2022 - 1.2023 - Write16(buttonData, Movie.inputBufferPtr + CONTROLLER_DATA_SIZE * i); 1.2024 - 1.2025 - // and for display 1.2026 - currentButtons[i] = buttonData; 1.2027 - } 1.2028 - else 1.2029 - { 1.2030 - // pretend the controller is disconnected (otherwise input it gives could cause desync since we're not writing it to the 1.2031 - // movie) 1.2032 - currentButtons[i] = 0; 1.2033 - } 1.2034 + // and for display 1.2035 + currentButtons[i] = buttonData; 1.2036 + } 1.2037 + else 1.2038 + { 1.2039 + // pretend the controller is disconnected (otherwise input it gives could cause desync since we're not writing it to the 1.2040 + // movie) 1.2041 + currentButtons[i] = 0; 1.2042 + } 1.2043 } 1.2044 1.2045 void VBAMovieStop(bool8 suppress_message) 1.2046 { 1.2047 - if (Movie.state != MOVIE_STATE_NONE) 1.2048 - { 1.2049 - change_state(MOVIE_STATE_NONE); 1.2050 - if (!suppress_message) 1.2051 - systemScreenMessage("Movie stop"); 1.2052 - } 1.2053 + if (Movie.state != MOVIE_STATE_NONE) 1.2054 + { 1.2055 + change_state(MOVIE_STATE_NONE); 1.2056 + if (!suppress_message) 1.2057 + systemScreenMessage("Movie stop"); 1.2058 + } 1.2059 } 1.2060 1.2061 int VBAMovieGetInfo(const char *filename, SMovie *info) 1.2062 { 1.2063 - assert(info != NULL); 1.2064 - if (info == NULL) 1.2065 - return -1; 1.2066 + assert(info != NULL); 1.2067 + if (info == NULL) 1.2068 + return -1; 1.2069 1.2070 - FILE * file; 1.2071 - int result; 1.2072 - SMovie &local_movie = *info; 1.2073 + FILE * file; 1.2074 + int result; 1.2075 + SMovie &local_movie = *info; 1.2076 1.2077 - memset(info, 0, sizeof(*info)); 1.2078 - if (filename[0] == '\0') 1.2079 - return MOVIE_FILE_NOT_FOUND; 1.2080 - if (!(file = fopen(filename, "rb"))) 1.2081 - return MOVIE_FILE_NOT_FOUND; 1.2082 + memset(info, 0, sizeof(*info)); 1.2083 + if (filename[0] == '\0') 1.2084 + return MOVIE_FILE_NOT_FOUND; 1.2085 + if (!(file = fopen(filename, "rb"))) 1.2086 + return MOVIE_FILE_NOT_FOUND; 1.2087 1.2088 - // read header 1.2089 - if ((result = (read_movie_header(file, local_movie))) != MOVIE_SUCCESS) 1.2090 - { 1.2091 - fclose(file); 1.2092 - return result; 1.2093 - } 1.2094 + // read header 1.2095 + if ((result = (read_movie_header(file, local_movie))) != MOVIE_SUCCESS) 1.2096 + { 1.2097 + fclose(file); 1.2098 + return result; 1.2099 + } 1.2100 1.2101 - // read the metadata / author info from file 1.2102 - fread(local_movie.authorInfo, 1, sizeof(char) * MOVIE_METADATA_SIZE, file); 1.2103 + // read the metadata / author info from file 1.2104 + fread(local_movie.authorInfo, 1, sizeof(char) * MOVIE_METADATA_SIZE, file); 1.2105 1.2106 - strncpy(local_movie.filename, filename, _MAX_PATH); 1.2107 - local_movie.filename[_MAX_PATH - 1] = '\0'; 1.2108 + strncpy(local_movie.filename, filename, _MAX_PATH); 1.2109 + local_movie.filename[_MAX_PATH - 1] = '\0'; 1.2110 1.2111 - if (Movie.file != NULL && stricmp(local_movie.filename, Movie.filename) == 0) // alreadyOpen 1.2112 - { 1.2113 - local_movie.bytesPerFrame = Movie.bytesPerFrame; 1.2114 - local_movie.header.length_frames = Movie.header.length_frames; 1.2115 - } 1.2116 - else 1.2117 - { 1.2118 - // recalculate length of movie from the file size 1.2119 - local_movie.bytesPerFrame = bytes_per_frame(local_movie); 1.2120 - fseek(file, 0, SEEK_END); 1.2121 - int fileSize = ftell(file); 1.2122 - local_movie.header.length_frames = 1.2123 - (fileSize - local_movie.header.offset_to_controller_data) / local_movie.bytesPerFrame; 1.2124 - } 1.2125 + if (Movie.file != NULL && stricmp(local_movie.filename, Movie.filename) == 0) // alreadyOpen 1.2126 + { 1.2127 + local_movie.bytesPerFrame = Movie.bytesPerFrame; 1.2128 + local_movie.header.length_frames = Movie.header.length_frames; 1.2129 + } 1.2130 + else 1.2131 + { 1.2132 + // recalculate length of movie from the file size 1.2133 + local_movie.bytesPerFrame = bytes_per_frame(local_movie); 1.2134 + fseek(file, 0, SEEK_END); 1.2135 + int fileSize = ftell(file); 1.2136 + local_movie.header.length_frames = 1.2137 + (fileSize - local_movie.header.offset_to_controller_data) / local_movie.bytesPerFrame; 1.2138 + } 1.2139 1.2140 - fclose(file); 1.2141 + fclose(file); 1.2142 1.2143 - if (access(filename, W_OK)) 1.2144 - info->readOnly = true; 1.2145 + if (access(filename, W_OK)) 1.2146 + info->readOnly = true; 1.2147 1.2148 - return MOVIE_SUCCESS; 1.2149 + return MOVIE_SUCCESS; 1.2150 } 1.2151 1.2152 bool8 VBAMovieActive() 1.2153 { 1.2154 - return (Movie.state != MOVIE_STATE_NONE); 1.2155 + return (Movie.state != MOVIE_STATE_NONE); 1.2156 } 1.2157 1.2158 bool8 VBAMovieLoading() 1.2159 { 1.2160 - return loadingMovie; 1.2161 + return loadingMovie; 1.2162 } 1.2163 1.2164 bool8 VBAMoviePlaying() 1.2165 { 1.2166 - return (Movie.state == MOVIE_STATE_PLAY); 1.2167 + return (Movie.state == MOVIE_STATE_PLAY); 1.2168 } 1.2169 1.2170 bool8 VBAMovieRecording() 1.2171 { 1.2172 - return (Movie.state == MOVIE_STATE_RECORD); 1.2173 + return (Movie.state == MOVIE_STATE_RECORD); 1.2174 } 1.2175 1.2176 bool8 VBAMovieReadOnly() 1.2177 { 1.2178 - if (!VBAMovieActive()) 1.2179 - return false; 1.2180 + if (!VBAMovieActive()) 1.2181 + return false; 1.2182 1.2183 - return Movie.readOnly; 1.2184 + return Movie.readOnly; 1.2185 } 1.2186 1.2187 void VBAMovieToggleReadOnly() 1.2188 { 1.2189 - if (!VBAMovieActive()) 1.2190 - return; 1.2191 + if (!VBAMovieActive()) 1.2192 + return; 1.2193 1.2194 - if (Movie.readOnly != 2) 1.2195 - { 1.2196 - Movie.readOnly = !Movie.readOnly; 1.2197 + if (Movie.readOnly != 2) 1.2198 + { 1.2199 + Movie.readOnly = !Movie.readOnly; 1.2200 1.2201 - systemScreenMessage(Movie.readOnly ? "Movie now read-only" : "Movie now editable"); 1.2202 - } 1.2203 - else 1.2204 - { 1.2205 - systemScreenMessage("Can't toggle read-only movie"); 1.2206 - } 1.2207 + systemScreenMessage(Movie.readOnly ? "Movie now read-only" : "Movie now editable"); 1.2208 + } 1.2209 + else 1.2210 + { 1.2211 + systemScreenMessage("Can't toggle read-only movie"); 1.2212 + } 1.2213 } 1.2214 1.2215 uint32 VBAMovieGetVersion() 1.2216 { 1.2217 - if (!VBAMovieActive()) 1.2218 - return 0; 1.2219 + if (!VBAMovieActive()) 1.2220 + return 0; 1.2221 1.2222 - return Movie.header.version; 1.2223 + return Movie.header.version; 1.2224 } 1.2225 1.2226 uint32 VBAMovieGetMinorVersion() 1.2227 { 1.2228 - if (!VBAMovieActive()) 1.2229 - return 0; 1.2230 + if (!VBAMovieActive()) 1.2231 + return 0; 1.2232 1.2233 - return Movie.header.minorVersion; 1.2234 + return Movie.header.minorVersion; 1.2235 } 1.2236 1.2237 uint32 VBAMovieGetId() 1.2238 { 1.2239 - if (!VBAMovieActive()) 1.2240 - return 0; 1.2241 + if (!VBAMovieActive()) 1.2242 + return 0; 1.2243 1.2244 - return Movie.header.uid; 1.2245 + return Movie.header.uid; 1.2246 } 1.2247 1.2248 uint32 VBAMovieGetLength() 1.2249 { 1.2250 - if (!VBAMovieActive()) 1.2251 - return 0; 1.2252 + if (!VBAMovieActive()) 1.2253 + return 0; 1.2254 1.2255 - return Movie.header.length_frames; 1.2256 + return Movie.header.length_frames; 1.2257 } 1.2258 1.2259 uint32 VBAMovieGetFrameCounter() 1.2260 { 1.2261 - if (!VBAMovieActive()) 1.2262 - return 0; 1.2263 + if (!VBAMovieActive()) 1.2264 + return 0; 1.2265 1.2266 - return Movie.currentFrame; 1.2267 + return Movie.currentFrame; 1.2268 } 1.2269 1.2270 uint32 VBAMovieGetRerecordCount() 1.2271 { 1.2272 - if (!VBAMovieActive()) 1.2273 - return 0; 1.2274 + if (!VBAMovieActive()) 1.2275 + return 0; 1.2276 1.2277 - return Movie.header.rerecord_count; 1.2278 + return Movie.header.rerecord_count; 1.2279 } 1.2280 1.2281 uint32 VBAMovieSetRerecordCount(uint32 newRerecordCount) 1.2282 { 1.2283 - uint32 oldRerecordCount = 0; 1.2284 - if (!VBAMovieActive()) 1.2285 - return 0; 1.2286 + uint32 oldRerecordCount = 0; 1.2287 + if (!VBAMovieActive()) 1.2288 + return 0; 1.2289 1.2290 - oldRerecordCount = Movie.header.rerecord_count; 1.2291 - Movie.header.rerecord_count = newRerecordCount; 1.2292 - return oldRerecordCount; 1.2293 + oldRerecordCount = Movie.header.rerecord_count; 1.2294 + Movie.header.rerecord_count = newRerecordCount; 1.2295 + return oldRerecordCount; 1.2296 } 1.2297 1.2298 std::string VBAMovieGetAuthorInfo() 1.2299 { 1.2300 - if (!VBAMovieActive()) 1.2301 - return ""; 1.2302 + if (!VBAMovieActive()) 1.2303 + return ""; 1.2304 1.2305 - return Movie.authorInfo; 1.2306 + return Movie.authorInfo; 1.2307 } 1.2308 1.2309 std::string VBAMovieGetFilename() 1.2310 { 1.2311 - if (!VBAMovieActive()) 1.2312 - return ""; 1.2313 + if (!VBAMovieActive()) 1.2314 + return ""; 1.2315 1.2316 - return Movie.filename; 1.2317 + return Movie.filename; 1.2318 } 1.2319 1.2320 void VBAMovieFreeze(uint8 * *buf, uint32 *size) 1.2321 { 1.2322 - // sanity check 1.2323 - if (!VBAMovieActive()) 1.2324 - { 1.2325 - return; 1.2326 - } 1.2327 + // sanity check 1.2328 + if (!VBAMovieActive()) 1.2329 + { 1.2330 + return; 1.2331 + } 1.2332 1.2333 - *buf = NULL; 1.2334 - *size = 0; 1.2335 + *buf = NULL; 1.2336 + *size = 0; 1.2337 1.2338 - // compute size needed for the buffer 1.2339 - // room for header.uid, currentFrame, and header.length_frames 1.2340 - uint32 size_needed = sizeof(Movie.header.uid) + sizeof(Movie.currentFrame) + sizeof(Movie.header.length_frames); 1.2341 - size_needed += (uint32)(Movie.bytesPerFrame * Movie.header.length_frames); 1.2342 - *buf = new uint8[size_needed]; 1.2343 - *size = size_needed; 1.2344 + // compute size needed for the buffer 1.2345 + // room for header.uid, currentFrame, and header.length_frames 1.2346 + uint32 size_needed = sizeof(Movie.header.uid) + sizeof(Movie.currentFrame) + sizeof(Movie.header.length_frames); 1.2347 + size_needed += (uint32)(Movie.bytesPerFrame * Movie.header.length_frames); 1.2348 + *buf = new uint8[size_needed]; 1.2349 + *size = size_needed; 1.2350 1.2351 - uint8 *ptr = *buf; 1.2352 - if (!ptr) 1.2353 - { 1.2354 - return; 1.2355 - } 1.2356 + uint8 *ptr = *buf; 1.2357 + if (!ptr) 1.2358 + { 1.2359 + return; 1.2360 + } 1.2361 1.2362 - Push32(Movie.header.uid, ptr); 1.2363 - Push32(Movie.currentFrame, ptr); 1.2364 - Push32(Movie.header.length_frames - 1, ptr); // HACK: shorten the length by 1 for backward compatibility 1.2365 + Push32(Movie.header.uid, ptr); 1.2366 + Push32(Movie.currentFrame, ptr); 1.2367 + Push32(Movie.header.length_frames - 1, ptr); // HACK: shorten the length by 1 for backward compatibility 1.2368 1.2369 - memcpy(ptr, Movie.inputBuffer, Movie.bytesPerFrame * Movie.header.length_frames); 1.2370 + memcpy(ptr, Movie.inputBuffer, Movie.bytesPerFrame * Movie.header.length_frames); 1.2371 } 1.2372 1.2373 int VBAMovieUnfreeze(const uint8 *buf, uint32 size) 1.2374 { 1.2375 - // sanity check 1.2376 - if (!VBAMovieActive()) 1.2377 + // sanity check 1.2378 + if (!VBAMovieActive()) 1.2379 + { 1.2380 + return MOVIE_NOT_FROM_A_MOVIE; 1.2381 + } 1.2382 + 1.2383 + const uint8 *ptr = buf; 1.2384 + if (size < sizeof(Movie.header.uid) + sizeof(Movie.currentFrame) + sizeof(Movie.header.length_frames)) 1.2385 + { 1.2386 + return MOVIE_WRONG_FORMAT; 1.2387 + } 1.2388 + 1.2389 + uint32 movie_id = Pop32(ptr); 1.2390 + uint32 current_frame = Pop32(ptr); 1.2391 + uint32 end_frame = Pop32(ptr) + 1; // HACK: restore the length for backward compatibility 1.2392 + uint32 space_needed = Movie.bytesPerFrame * end_frame; 1.2393 + 1.2394 + if (movie_id != Movie.header.uid) 1.2395 + return MOVIE_NOT_FROM_THIS_MOVIE; 1.2396 + 1.2397 + if (space_needed > size) 1.2398 + return MOVIE_WRONG_FORMAT; 1.2399 + 1.2400 + if (Movie.readOnly) 1.2401 + { 1.2402 + // here, we are going to keep the input data from the movie file 1.2403 + // and simply rewind to the currentFrame pointer 1.2404 + // this will cause a desync if the savestate is not in sync // <-- NOT ANYMORE 1.2405 + // with the on-disk recording data, but it's easily solved 1.2406 + // by loading another savestate or playing the movie from the beginning 1.2407 + 1.2408 + // don't allow loading a state inconsistent with the current movie 1.2409 + uint32 length_history = min(current_frame, Movie.header.length_frames); 1.2410 + if (end_frame < length_history) 1.2411 + return MOVIE_SNAPSHOT_INCONSISTENT; 1.2412 + 1.2413 + uint32 space_shared = Movie.bytesPerFrame * length_history; 1.2414 + if (memcmp(Movie.inputBuffer, ptr, space_shared)) 1.2415 + return MOVIE_SNAPSHOT_INCONSISTENT; 1.2416 + 1.2417 + Movie.currentFrame = current_frame; 1.2418 + Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * min(current_frame, Movie.header.length_frames); 1.2419 + } 1.2420 + else 1.2421 + { 1.2422 + // here, we are going to take the input data from the savestate 1.2423 + // and make it the input data for the current movie, then continue 1.2424 + // writing new input data at the currentFrame pointer 1.2425 + Movie.currentFrame = current_frame; 1.2426 + Movie.header.length_frames = end_frame; 1.2427 + if (!VBALuaRerecordCountSkip()) 1.2428 + ++Movie.header.rerecord_count; 1.2429 + 1.2430 + Movie.RecordedThisSession = true; 1.2431 + 1.2432 + // do this before calling reserve_buffer_space() 1.2433 + Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * min(current_frame, Movie.header.length_frames); 1.2434 + reserve_buffer_space(space_needed); 1.2435 + memcpy(Movie.inputBuffer, ptr, space_needed); 1.2436 + 1.2437 + // for consistency, no auto movie conversion here since we don't auto convert the corresponding savestate 1.2438 + flush_movie_header(); 1.2439 + flush_movie_frames(); 1.2440 + } 1.2441 + 1.2442 + change_state(MOVIE_STATE_PLAY); // check for movie end 1.2443 + 1.2444 + // necessary! 1.2445 + resetSignaled = false; 1.2446 + resetSignaledLast = false; 1.2447 + 1.2448 + // necessary to check if there's a reset signal at the previous frame 1.2449 + if (current_frame > 0) 1.2450 + { 1.2451 + const u8 NEW_RESET = u8(BUTTON_MASK_NEW_RESET >> 8); 1.2452 + for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.2453 { 1.2454 - return MOVIE_NOT_FROM_A_MOVIE; 1.2455 + if ((Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) && (*(Movie.inputBufferPtr+1- Movie.bytesPerFrame) & NEW_RESET)) 1.2456 + { 1.2457 + resetSignaledLast = true; 1.2458 + break; 1.2459 + } 1.2460 } 1.2461 + } 1.2462 1.2463 - const uint8 *ptr = buf; 1.2464 - if (size < sizeof(Movie.header.uid) + sizeof(Movie.currentFrame) + sizeof(Movie.header.length_frames)) 1.2465 - { 1.2466 - return MOVIE_WRONG_FORMAT; 1.2467 - } 1.2468 - 1.2469 - uint32 movie_id = Pop32(ptr); 1.2470 - uint32 current_frame = Pop32(ptr); 1.2471 - uint32 end_frame = Pop32(ptr) + 1; // HACK: restore the length for backward compatibility 1.2472 - uint32 space_needed = Movie.bytesPerFrame * end_frame; 1.2473 - 1.2474 - if (movie_id != Movie.header.uid) 1.2475 - return MOVIE_NOT_FROM_THIS_MOVIE; 1.2476 - 1.2477 - if (space_needed > size) 1.2478 - return MOVIE_WRONG_FORMAT; 1.2479 - 1.2480 - if (Movie.readOnly) 1.2481 - { 1.2482 - // here, we are going to keep the input data from the movie file 1.2483 - // and simply rewind to the currentFrame pointer 1.2484 - // this will cause a desync if the savestate is not in sync // <-- NOT ANYMORE 1.2485 - // with the on-disk recording data, but it's easily solved 1.2486 - // by loading another savestate or playing the movie from the beginning 1.2487 - 1.2488 - // don't allow loading a state inconsistent with the current movie 1.2489 - uint32 length_history = min(current_frame, Movie.header.length_frames); 1.2490 - if (end_frame < length_history) 1.2491 - return MOVIE_SNAPSHOT_INCONSISTENT; 1.2492 - 1.2493 - uint32 space_shared = Movie.bytesPerFrame * length_history; 1.2494 - if (memcmp(Movie.inputBuffer, ptr, space_shared)) 1.2495 - return MOVIE_SNAPSHOT_INCONSISTENT; 1.2496 - 1.2497 - Movie.currentFrame = current_frame; 1.2498 - Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * min(current_frame, Movie.header.length_frames); 1.2499 - } 1.2500 - else 1.2501 - { 1.2502 - // here, we are going to take the input data from the savestate 1.2503 - // and make it the input data for the current movie, then continue 1.2504 - // writing new input data at the currentFrame pointer 1.2505 - Movie.currentFrame = current_frame; 1.2506 - Movie.header.length_frames = end_frame; 1.2507 - if (!VBALuaRerecordCountSkip()) 1.2508 - ++Movie.header.rerecord_count; 1.2509 - 1.2510 - Movie.RecordedThisSession = true; 1.2511 - 1.2512 - // do this before calling reserve_buffer_space() 1.2513 - Movie.inputBufferPtr = Movie.inputBuffer + Movie.bytesPerFrame * min(current_frame, Movie.header.length_frames); 1.2514 - reserve_buffer_space(space_needed); 1.2515 - memcpy(Movie.inputBuffer, ptr, space_needed); 1.2516 - 1.2517 - // for consistency, no auto movie conversion here since we don't auto convert the corresponding savestate 1.2518 - flush_movie_header(); 1.2519 - flush_movie_frames(); 1.2520 - } 1.2521 - 1.2522 - change_state(MOVIE_STATE_PLAY); // check for movie end 1.2523 - 1.2524 - // necessary! 1.2525 - resetSignaled = false; 1.2526 - resetSignaledLast = false; 1.2527 - 1.2528 - // necessary to check if there's a reset signal at the previous frame 1.2529 - if (current_frame > 0) 1.2530 - { 1.2531 - const u8 NEW_RESET = u8(BUTTON_MASK_NEW_RESET >> 8); 1.2532 - for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.2533 - { 1.2534 - if ((Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) && (*(Movie.inputBufferPtr+1- Movie.bytesPerFrame) & NEW_RESET)) 1.2535 - { 1.2536 - resetSignaledLast = true; 1.2537 - break; 1.2538 - } 1.2539 - } 1.2540 - } 1.2541 - 1.2542 - return MOVIE_SUCCESS; 1.2543 + return MOVIE_SUCCESS; 1.2544 } 1.2545 1.2546 bool VBAMovieEnded() 1.2547 { 1.2548 - return (Movie.state == MOVIE_STATE_END); 1.2549 -// return (Movie.state != MOVIE_STATE_NONE && Movie.currentFrame >= Movie.header.length_frames); 1.2550 + return (Movie.state == MOVIE_STATE_END); 1.2551 + // return (Movie.state != MOVIE_STATE_NONE && Movie.currentFrame >= Movie.header.length_frames); 1.2552 } 1.2553 1.2554 bool VBAMovieAllowsRerecording() 1.2555 { 1.2556 - bool allows = (Movie.state != MOVIE_STATE_NONE) && (Movie.currentFrame <= Movie.header.length_frames); 1.2557 - return /*!VBAMovieReadOnly() &&*/ allows; 1.2558 + bool allows = (Movie.state != MOVIE_STATE_NONE) && (Movie.currentFrame <= Movie.header.length_frames); 1.2559 + return /*!VBAMovieReadOnly() &&*/ allows; 1.2560 } 1.2561 1.2562 bool VBAMovieSwitchToPlaying() 1.2563 { 1.2564 - if (!VBAMovieActive()) 1.2565 - return false; 1.2566 + if (!VBAMovieActive()) 1.2567 + return false; 1.2568 1.2569 - if (!Movie.readOnly) 1.2570 - { 1.2571 - VBAMovieToggleReadOnly(); 1.2572 - } 1.2573 + if (!Movie.readOnly) 1.2574 + { 1.2575 + VBAMovieToggleReadOnly(); 1.2576 + } 1.2577 1.2578 - change_state(MOVIE_STATE_PLAY); 1.2579 - if (Movie.state == MOVIE_STATE_PLAY) 1.2580 - systemScreenMessage("Movie replay (continue)"); 1.2581 - else 1.2582 - systemScreenMessage("Movie end"); 1.2583 + change_state(MOVIE_STATE_PLAY); 1.2584 + if (Movie.state == MOVIE_STATE_PLAY) 1.2585 + systemScreenMessage("Movie replay (continue)"); 1.2586 + else 1.2587 + systemScreenMessage("Movie end"); 1.2588 1.2589 - return true; 1.2590 + return true; 1.2591 } 1.2592 1.2593 bool VBAMovieSwitchToRecording() 1.2594 { 1.2595 - if (!VBAMovieAllowsRerecording()) 1.2596 - return false; 1.2597 + if (!VBAMovieAllowsRerecording()) 1.2598 + return false; 1.2599 1.2600 - if (Movie.readOnly) 1.2601 - { 1.2602 - VBAMovieToggleReadOnly(); 1.2603 - } 1.2604 + if (Movie.readOnly) 1.2605 + { 1.2606 + VBAMovieToggleReadOnly(); 1.2607 + } 1.2608 1.2609 - if (!VBALuaRerecordCountSkip()) 1.2610 - ++Movie.header.rerecord_count; 1.2611 + if (!VBALuaRerecordCountSkip()) 1.2612 + ++Movie.header.rerecord_count; 1.2613 1.2614 - change_state(MOVIE_STATE_RECORD); 1.2615 - systemScreenMessage("Movie re-record"); 1.2616 + change_state(MOVIE_STATE_RECORD); 1.2617 + systemScreenMessage("Movie re-record"); 1.2618 1.2619 - //truncate_movie(Movie.currentFrame); 1.2620 + //truncate_movie(Movie.currentFrame); 1.2621 1.2622 - return true; 1.2623 + return true; 1.2624 } 1.2625 1.2626 uint32 VBAMovieGetState() 1.2627 { 1.2628 - // ? 1.2629 - if (!VBAMovieActive()) 1.2630 - return MOVIE_STATE_NONE; 1.2631 + // ? 1.2632 + if (!VBAMovieActive()) 1.2633 + return MOVIE_STATE_NONE; 1.2634 1.2635 - return Movie.state; 1.2636 + return Movie.state; 1.2637 } 1.2638 1.2639 void VBAMovieSignalReset() 1.2640 { 1.2641 - if (VBAMovieActive()) 1.2642 - resetSignaled = true; 1.2643 + if (VBAMovieActive()) 1.2644 + resetSignaled = true; 1.2645 } 1.2646 1.2647 void VBAMovieResetIfRequested() 1.2648 { 1.2649 - if (resetSignaled) 1.2650 - { 1.2651 - theEmulator.emuReset(false); 1.2652 - resetSignaled = false; 1.2653 - resetSignaledLast = true; 1.2654 - } 1.2655 - else 1.2656 - { 1.2657 - resetSignaledLast = false; 1.2658 - } 1.2659 + if (resetSignaled) 1.2660 + { 1.2661 + theEmulator.emuReset(false); 1.2662 + resetSignaled = false; 1.2663 + resetSignaledLast = true; 1.2664 + } 1.2665 + else 1.2666 + { 1.2667 + resetSignaledLast = false; 1.2668 + } 1.2669 } 1.2670 1.2671 void VBAMovieSetMetadata(const char *info) 1.2672 { 1.2673 - if (!memcmp(Movie.authorInfo, info, MOVIE_METADATA_SIZE)) 1.2674 - return; 1.2675 + if (!memcmp(Movie.authorInfo, info, MOVIE_METADATA_SIZE)) 1.2676 + return; 1.2677 1.2678 - memcpy(Movie.authorInfo, info, MOVIE_METADATA_SIZE); // strncpy would omit post-0 bytes 1.2679 - Movie.authorInfo[MOVIE_METADATA_SIZE - 1] = '\0'; 1.2680 + memcpy(Movie.authorInfo, info, MOVIE_METADATA_SIZE); // strncpy would omit post-0 bytes 1.2681 + Movie.authorInfo[MOVIE_METADATA_SIZE - 1] = '\0'; 1.2682 1.2683 - if (Movie.file) 1.2684 - { 1.2685 - // (over-)write the header 1.2686 - fseek(Movie.file, 0, SEEK_SET); 1.2687 - write_movie_header(Movie.file, Movie); 1.2688 + if (Movie.file) 1.2689 + { 1.2690 + // (over-)write the header 1.2691 + fseek(Movie.file, 0, SEEK_SET); 1.2692 1.2693 - // write the metadata / author info to file 1.2694 - fwrite(Movie.authorInfo, 1, sizeof(char) * MOVIE_METADATA_SIZE, Movie.file); 1.2695 + write_movie_header(Movie.file, Movie); 1.2696 1.2697 - fflush(Movie.file); 1.2698 - } 1.2699 + // write the metadata / author info to file 1.2700 + fwrite(Movie.authorInfo, 1, sizeof(char) * MOVIE_METADATA_SIZE, Movie.file); 1.2701 + 1.2702 + fflush(Movie.file); 1.2703 + } 1.2704 + printf("RLM: setMetadata called\n"); 1.2705 + 1.2706 } 1.2707 1.2708 void VBAMovieRestart() 1.2709 { 1.2710 - if (VBAMovieActive()) 1.2711 - { 1.2712 - systemSoundClearBuffer(); 1.2713 + if (VBAMovieActive()) 1.2714 + { 1.2715 + systemSoundClearBuffer(); 1.2716 1.2717 - bool8 modified = Movie.RecordedThisSession; 1.2718 + bool8 modified = Movie.RecordedThisSession; 1.2719 1.2720 - VBAMovieStop(true); 1.2721 + VBAMovieStop(true); 1.2722 1.2723 - char movieName [_MAX_PATH]; 1.2724 - strncpy(movieName, Movie.filename, _MAX_PATH); 1.2725 - movieName[_MAX_PATH - 1] = '\0'; 1.2726 - VBAMovieOpen(movieName, Movie.readOnly); // can't just pass in Movie.filename, since VBAMovieOpen clears out Movie's 1.2727 - // variables 1.2728 + char movieName [_MAX_PATH]; 1.2729 + strncpy(movieName, Movie.filename, _MAX_PATH); 1.2730 + movieName[_MAX_PATH - 1] = '\0'; 1.2731 + VBAMovieOpen(movieName, Movie.readOnly); // can't just pass in Movie.filename, since VBAMovieOpen clears out Movie's 1.2732 + // variables 1.2733 1.2734 - Movie.RecordedThisSession = modified; 1.2735 + Movie.RecordedThisSession = modified; 1.2736 1.2737 - systemScreenMessage("Movie replay (restart)"); 1.2738 - } 1.2739 + systemScreenMessage("Movie replay (restart)"); 1.2740 + } 1.2741 } 1.2742 1.2743 int VBAMovieGetPauseAt() 1.2744 { 1.2745 - return Movie.pauseFrame; 1.2746 + return Movie.pauseFrame; 1.2747 } 1.2748 1.2749 void VBAMovieSetPauseAt(int at) 1.2750 { 1.2751 - Movie.pauseFrame = at; 1.2752 + Movie.pauseFrame = at; 1.2753 } 1.2754 1.2755 /////////////////////// 1.2756 @@ -1688,85 +1703,85 @@ 1.2757 // FIXME: is it safe to convert/flush a movie while recording it (considering fseek() problem)? 1.2758 int VBAMovieConvertCurrent() 1.2759 { 1.2760 - if (!VBAMovieActive()) 1.2761 + if (!VBAMovieActive()) 1.2762 + { 1.2763 + return MOVIE_NOTHING; 1.2764 + } 1.2765 + 1.2766 + if (Movie.header.minorVersion > VBM_REVISION) 1.2767 + { 1.2768 + return MOVIE_WRONG_VERSION; 1.2769 + } 1.2770 + 1.2771 + if (Movie.header.minorVersion == VBM_REVISION) 1.2772 + { 1.2773 + return MOVIE_NOTHING; 1.2774 + } 1.2775 + 1.2776 + Movie.header.minorVersion = VBM_REVISION; 1.2777 + 1.2778 + if (Movie.header.length_frames == 0) // this could happen 1.2779 + { 1.2780 + truncate_movie(0); 1.2781 + return MOVIE_SUCCESS; 1.2782 + } 1.2783 + 1.2784 + // fix movies recorded from snapshots 1.2785 + if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT) 1.2786 + { 1.2787 + uint8 *firstFramePtr = Movie.inputBuffer; 1.2788 + for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.2789 { 1.2790 - return MOVIE_NOTHING; 1.2791 + if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.2792 + { 1.2793 + Push16(initialInputs[i], firstFramePtr); 1.2794 + // note: this is correct since Push16 advances the dest pointer by sizeof u16 1.2795 + } 1.2796 } 1.2797 + } 1.2798 1.2799 - if (Movie.header.minorVersion > VBM_REVISION) 1.2800 + // convert old resets to new ones 1.2801 + const u8 OLD_RESET = u8(BUTTON_MASK_OLD_RESET >> 8); 1.2802 + const u8 NEW_RESET = u8(BUTTON_MASK_NEW_RESET >> 8); 1.2803 + for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.2804 + { 1.2805 + if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.2806 { 1.2807 - return MOVIE_WRONG_VERSION; 1.2808 + uint8 *startPtr = Movie.inputBuffer + sizeof(u16) * i + 1; 1.2809 + uint8 *endPtr = Movie.inputBuffer + Movie.bytesPerFrame * (Movie.header.length_frames - 1); 1.2810 + for (; startPtr < endPtr; startPtr += Movie.bytesPerFrame) 1.2811 + { 1.2812 + if (startPtr[Movie.bytesPerFrame] & OLD_RESET) 1.2813 + { 1.2814 + startPtr[0] |= NEW_RESET; 1.2815 + } 1.2816 + } 1.2817 } 1.2818 + } 1.2819 1.2820 - if (Movie.header.minorVersion == VBM_REVISION) 1.2821 - { 1.2822 - return MOVIE_NOTHING; 1.2823 - } 1.2824 - 1.2825 - Movie.header.minorVersion = VBM_REVISION; 1.2826 - 1.2827 - if (Movie.header.length_frames == 0) // this could happen 1.2828 - { 1.2829 - truncate_movie(0); 1.2830 - return MOVIE_SUCCESS; 1.2831 - } 1.2832 - 1.2833 - // fix movies recorded from snapshots 1.2834 - if (Movie.header.startFlags & MOVIE_START_FROM_SNAPSHOT) 1.2835 - { 1.2836 - uint8 *firstFramePtr = Movie.inputBuffer; 1.2837 - for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.2838 - { 1.2839 - if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.2840 - { 1.2841 - Push16(initialInputs[i], firstFramePtr); 1.2842 - // note: this is correct since Push16 advances the dest pointer by sizeof u16 1.2843 - } 1.2844 - } 1.2845 - } 1.2846 - 1.2847 - // convert old resets to new ones 1.2848 - const u8 OLD_RESET = u8(BUTTON_MASK_OLD_RESET >> 8); 1.2849 - const u8 NEW_RESET = u8(BUTTON_MASK_NEW_RESET >> 8); 1.2850 - for (int i = 0; i < MOVIE_NUM_OF_POSSIBLE_CONTROLLERS; ++i) 1.2851 - { 1.2852 - if (Movie.header.controllerFlags & MOVIE_CONTROLLER(i)) 1.2853 - { 1.2854 - uint8 *startPtr = Movie.inputBuffer + sizeof(u16) * i + 1; 1.2855 - uint8 *endPtr = Movie.inputBuffer + Movie.bytesPerFrame * (Movie.header.length_frames - 1); 1.2856 - for (; startPtr < endPtr; startPtr += Movie.bytesPerFrame) 1.2857 - { 1.2858 - if (startPtr[Movie.bytesPerFrame] & OLD_RESET) 1.2859 - { 1.2860 - startPtr[0] |= NEW_RESET; 1.2861 - } 1.2862 - } 1.2863 - } 1.2864 - } 1.2865 - 1.2866 - flush_movie_header(); 1.2867 - flush_movie_frames(); 1.2868 - return MOVIE_SUCCESS; 1.2869 + flush_movie_header(); 1.2870 + flush_movie_frames(); 1.2871 + return MOVIE_SUCCESS; 1.2872 } 1.2873 1.2874 bool VBAMovieTuncateAtCurrentFrame() 1.2875 { 1.2876 - if (!VBAMovieActive()) 1.2877 - return false; 1.2878 + if (!VBAMovieActive()) 1.2879 + return false; 1.2880 1.2881 - truncate_movie(Movie.currentFrame); 1.2882 - change_state(MOVIE_STATE_END); 1.2883 - systemScreenMessage("Movie truncated"); 1.2884 + truncate_movie(Movie.currentFrame); 1.2885 + change_state(MOVIE_STATE_END); 1.2886 + systemScreenMessage("Movie truncated"); 1.2887 1.2888 - return true; 1.2889 + return true; 1.2890 } 1.2891 1.2892 bool VBAMovieFixHeader() 1.2893 { 1.2894 - if (!VBAMovieActive()) 1.2895 - return false; 1.2896 + if (!VBAMovieActive()) 1.2897 + return false; 1.2898 1.2899 - flush_movie_header(); 1.2900 - systemScreenMessage("Movie header fixed"); 1.2901 - return true; 1.2902 + flush_movie_header(); 1.2903 + systemScreenMessage("Movie header fixed"); 1.2904 + return true; 1.2905 }