@@ -26,30 +26,6 @@ Ppu *g_ppu, *g_my_ppu;
2626Dma * g_dma ;
2727bool g_custom_music ;
2828
29- static uint8 * g_rtl_memory_ptr ;
30- static RunFrameFunc * g_rtl_runframe ;
31- static SyncAllFunc * g_rtl_syncall ;
32-
33- void RtlSetupEmuCallbacks (uint8 * emu_ram , RunFrameFunc * func , SyncAllFunc * sync_all ) {
34- g_rtl_memory_ptr = emu_ram ;
35- g_rtl_runframe = func ;
36- g_rtl_syncall = sync_all ;
37- }
38-
39- static void RtlSynchronizeWholeState (void ) {
40- if (g_rtl_syncall )
41- g_rtl_syncall ();
42- }
43-
44- // |ptr| must be a pointer into g_ram, will synchronize the RAM memory with the
45- // emulator.
46- static void RtlSyncMemoryRegion (void * ptr , size_t n ) {
47- uint8 * data = (uint8 * )ptr ;
48- assert (data >= g_ram && data < g_ram + 0x20000 );
49- if (g_rtl_memory_ptr )
50- memcpy (g_rtl_memory_ptr + (data - g_ram ), data , n );
51- }
52-
5329void ByteArray_AppendVl (ByteArray * arr , uint32 v ) {
5430 for (; v >= 255 ; v -= 255 )
5531 ByteArray_AppendByte (arr , 255 );
@@ -81,15 +57,14 @@ void loadFunc(SaveLoadInfo *sli, void *data, size_t data_size) {
8157static void LoadSnesState (SaveLoadInfo * sli ) {
8258 // Do the actual loading
8359 snes_saveload (g_snes , sli );
84- RtlSynchronizeWholeState ();
8560}
8661
8762static void SaveSnesState (SaveLoadInfo * sli ) {
8863 snes_saveload (g_snes , sli );
8964}
9065
9166typedef struct StateRecorder {
92- uint16 last_inputs ;
67+ uint32 last_inputs ;
9368 uint32 frames_since_last ;
9469 uint32 total_frames ;
9570
@@ -100,6 +75,7 @@ typedef struct StateRecorder {
10075 uint32 snapshot_flags ;
10176 uint8 replay_cmd ;
10277 bool replay_mode ;
78+ uint8 cur_player ;
10379
10480 ByteArray log ;
10581 ByteArray base_snapshot ;
@@ -122,25 +98,31 @@ void StateRecorder_RecordCmd(StateRecorder *sr, uint8 cmd) {
12298 ByteArray_AppendVl (& sr -> log , frames - x );
12399}
124100
125- void StateRecorder_Record (StateRecorder * sr , uint16 inputs ) {
126- uint16 diff = inputs ^ sr -> last_inputs ;
127- if (diff != 0 ) {
128- sr -> last_inputs = inputs ;
129- // printf("0x%.4x %d: ", diff, sr->frames_since_last);
130- // size_t lb = sr->log.size;
131- for (int i = 0 ; i < 12 ; i ++ ) {
132- if ((diff >> i ) & 1 )
133- StateRecorder_RecordCmd (sr , i << 4 );
101+ static void StateRecorder_RecordKeyDiff (StateRecorder * sr , uint32 diff ) {
102+ for (int i = 0 ; diff ; i ++ , diff >>= 1 ) {
103+ if (diff & 1 ) {
104+ int player = (i >= 12 );
105+ i -= player * 12 ;
106+ if (player != sr -> cur_player ) {
107+ sr -> cur_player = player ;
108+ ByteArray_AppendByte (& sr -> log , 0xfc + player );
109+ }
110+ StateRecorder_RecordCmd (sr , i << 4 );
134111 }
135- // while (lb < sr->log.size)
136- // printf("%.2x ", sr->log.data[lb++]);
137- // printf("\n");
138112 }
113+ }
114+
115+ void StateRecorder_Record (StateRecorder * sr , uint32 inputs ) {
116+ uint32 diff = (inputs ^ sr -> last_inputs ) & 0xffffff ;
117+ sr -> last_inputs = inputs ;
118+ if (diff )
119+ StateRecorder_RecordKeyDiff (sr , diff );
139120 sr -> frames_since_last ++ ;
140121 sr -> total_frames ++ ;
141122}
142123
143- void StateRecorder_RecordPatchByte (StateRecorder * sr , uint32 addr , const uint8 * value , int num ) {
124+ void StateRecorder_RecordPatchByte (StateRecorder * sr , const uint8 * value , int num ) {
125+ uint32 addr = value - g_ram ;
144126 assert (addr < 0x20000 );
145127
146128 // printf("%d: PatchByte(0x%x, 0x%x. %d): ", sr->frames_since_last, addr, *value, num);
@@ -174,8 +156,6 @@ void RtlReset(int mode) {
174156 RtlRestoreMusicAfterLoad_Locked (true);
175157 RtlApuUnlock ();
176158
177- RtlSynchronizeWholeState ();
178-
179159 if ((mode & 2 ) == 0 )
180160 StateRecorder_Init (& state_recorder );
181161}
@@ -216,6 +196,7 @@ void StateRecorder_Load(StateRecorder *sr, FILE *f, bool replay_mode) {
216196 sr -> snapshot_flags = hdr [9 ];
217197 sr -> replay_next_cmd_at = 0 ;
218198 sr -> replay_mode = replay_mode ;
199+ sr -> cur_player = 0 ;
219200 if (replay_mode ) {
220201 sr -> frames_since_last = 0 ;
221202 sr -> last_inputs = 0 ;
@@ -269,6 +250,12 @@ void StateRecorder_Save(StateRecorder *sr, FILE *f, bool saving_with_bug) {
269250 assert (sr -> base_snapshot .size == 0 ||
270251 sr -> base_snapshot .size == savest .array .size || sr -> base_snapshot .size == g_sram_size );
271252
253+ // Before saving, reset the cur player
254+ if (sr -> cur_player ) {
255+ sr -> cur_player = 0 ;
256+ ByteArray_AppendVl (& sr -> log , 0xfc );
257+ }
258+
272259 hdr [0 ] = 2 ;
273260 hdr [1 ] = sr -> total_frames ;
274261 hdr [2 ] = (uint32 )sr -> log .size ;
@@ -305,12 +292,9 @@ void StateRecorder_ClearKeyLog(StateRecorder *sr) {
305292 memset (& sr -> log , 0 , sizeof (sr -> log ));
306293 // If there are currently any active inputs, record them initially at timestamp 0.
307294 sr -> frames_since_last = 0 ;
308- if (sr -> last_inputs ) {
309- for (int i = 0 ; i < 12 ; i ++ ) {
310- if ((sr -> last_inputs >> i ) & 1 )
311- StateRecorder_RecordCmd (sr , i << 4 );
312- }
313- }
295+ sr -> cur_player = 0 ;
296+ StateRecorder_RecordKeyDiff (sr , sr -> last_inputs );
297+
314298 if (sr -> replay_mode ) {
315299 // When clearing the key log while in replay mode, we want to keep
316300 // replaying but discarding all key history up until this point.
@@ -340,7 +324,7 @@ uint16 StateRecorder_ReadNextReplayState(StateRecorder *sr) {
340324 // Apply next command
341325 sr -> frames_since_last = 0 ;
342326 if (sr -> replay_cmd < 0xc0 ) {
343- sr -> last_inputs ^= 1 << (sr -> replay_cmd >> 4 );
327+ sr -> last_inputs ^= 1 << (( sr -> replay_cmd >> 4 ) + sr -> cur_player * 12 );
344328 } else if (sr -> replay_cmd < 0xd0 ) {
345329 int nb = 1 + ((sr -> replay_cmd >> 2 ) & 3 );
346330 uint8 t ;
@@ -352,7 +336,6 @@ uint16 StateRecorder_ReadNextReplayState(StateRecorder *sr) {
352336 addr |= sr -> log .data [replay_pos ++ ];
353337 do {
354338 g_ram [addr & 0x1ffff ] = sr -> log .data [replay_pos ++ ];
355- RtlSyncMemoryRegion (& g_ram [addr & 0x1ffff ], 1 );
356339 } while (addr ++ , -- nb );
357340 } else {
358341 assert (0 );
@@ -365,7 +348,20 @@ uint16 StateRecorder_ReadNextReplayState(StateRecorder *sr) {
365348 break ;
366349 }
367350 // Read the next one
368- uint8 cmd = sr -> log .data [replay_pos ++ ], t ;
351+ uint8 cmd , t ;
352+
353+ for (;;) {
354+ cmd = sr -> log .data [replay_pos ++ ];
355+ if (cmd < 0xfc )
356+ break ;
357+ switch (cmd ) {
358+ case 0xfc :
359+ case 0xfd : sr -> cur_player = cmd - 0xfc ; break ;
360+ default :
361+ assert (0 );
362+ }
363+ }
364+
369365 int mask = (cmd < 0xc0 ) ? 0xf : 0x1 ;
370366 int frames = cmd & mask ;
371367 if (frames == mask ) do {
@@ -400,7 +396,8 @@ void RtlStopReplay(void) {
400396 StateRecorder_StopReplay (& state_recorder );
401397}
402398
403- bool RtlRunFrame (int inputs ) {
399+ bool RtlRunFrame (uint32 inputs ) {
400+
404401 if (g_did_finish_level_hook ) {
405402 if (game_id == kGameID_SMW && !state_recorder .replay_mode && g_config .save_playthrough ) {
406403 SmwSavePlaythroughSnapshot ();
@@ -414,6 +411,9 @@ bool RtlRunFrame(int inputs) {
414411 // Avoid up/down and left/right from being pressed at the same time
415412 if ((inputs & 0x30 ) == 0x30 ) inputs ^= 0x30 ;
416413 if ((inputs & 0xc0 ) == 0xc0 ) inputs ^= 0xc0 ;
414+ // Player2
415+ if ((inputs & 0x30000 ) == 0x30000 ) inputs ^= 0x30000 ;
416+ if ((inputs & 0xc0000 ) == 0xc0000 ) inputs ^= 0xc0000 ;
417417
418418 bool is_replay = state_recorder .replay_mode ;
419419
@@ -433,12 +433,21 @@ bool RtlRunFrame(int inputs) {
433433 uint8 apui02 = RtlApuReadReg (2 );
434434 if (apui02 != g_ram [kSmwRam_APUI02 ]) {
435435 g_ram [kSmwRam_APUI02 ] = apui02 ;
436- StateRecorder_RecordPatchByte (& state_recorder , kSmwRam_APUI02 , & apui02 , 1 );
436+ StateRecorder_RecordPatchByte (& state_recorder , & g_ram [kSmwRam_APUI02 ], 1 );
437+ }
438+ // Whether controllers are plugged in.
439+ uint32 new_my_flags = inputs >> 30 ;
440+ if (new_my_flags != g_ram [kSmwRam_my_flags ]) {
441+ assert (new_my_flags <= 255 );
442+ g_ram [kSmwRam_my_flags ] = new_my_flags ;
443+ StateRecorder_RecordPatchByte (& state_recorder , & g_ram [kSmwRam_my_flags ], 1 );
437444 }
438445 }
439446 }
447+ g_snes -> input1_currentState = inputs & 0xfff ;
448+ g_snes -> input2_currentState = (inputs >> 12 ) & 0xfff ;
440449
441- g_rtl_runframe ( inputs , 0 );
450+ RtlRunFrameCompare ( );
442451
443452 snes_frame_counter ++ ;
444453
@@ -462,7 +471,6 @@ static void RtlLoadFromFile(FILE *f, bool replay) {
462471 ppu_copy (g_my_ppu , g_snes -> ppu );
463472
464473 RtlApuUnlock ();
465- RtlSynchronizeWholeState ();
466474}
467475
468476static const char * const kBugSaves [] = {
@@ -789,7 +797,6 @@ void RtlReadSram(void) {
789797 if (fread (g_sram , 1 , g_sram_size , f ) != g_sram_size )
790798 fprintf (stderr , "Error reading %s\n" , filename );
791799 fclose (f );
792- RtlSynchronizeWholeState ();
793800 ByteArray_Resize (& state_recorder .base_snapshot , g_sram_size );
794801 memcpy (state_recorder .base_snapshot .data , g_sram , g_sram_size );
795802 }
0 commit comments