This file is indexed.

/usr/share/fceux/luaScripts/Multitrack2.lua is in fceux 2.2.2+dfsg0-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
-- Multitrack v2 for FCEUX by FatRatKnight
-- Recent addition: Experimental save. Same format as in .fm2
-- Did not include support to not have it trigger on script exit. Sorry...
-- Additionally, there's no *loading* mechanism in this script. Eh...


--***************
local players= 2           -- You may tweak the number of players here.
--***************


-- Rewind options
local saveMax= 50          -- How many save states to keep? Set to 0 to disable
local SaveBuf= 12          -- How many frames between saves? Don't use 0, ever.
local rewind= "numpad0"    -- What key do you wish to hit for rewind?

--Keep in mind: Higher saveMax, more savestates, more memory needed.


--Control
local PlayerSwitch= "home" -- For selecting other players
local opt= "end"           -- For changing control options

local BackupReadSwitch=  "numpad-" -- Revert to backup copy
local BackupWriteSwitch= "numpad+" -- Copy input into backup

local key = {"right", "left", "down", "up",   "L",      "O",   "J", "K"}
local btn = {"right", "left", "down", "up", "start", "select", "B", "A"}

--Try to avoid changing btn. You may reorder btn's stuff if you don't
--like the default order, however. Line up with key for good reasons.
--key is the actual keyboard control over the buttons. Change that!


--Insertions and deletions
local Insert= "insert"     -- Inserts a frame at the frame you're at
local Delete= "delete"     -- Eliminates current frame


--Display
local BackupDisplaySwitch= "numpad." -- Care to see the backup?

local solid= "pageup"      -- Make the display less
local clear= "pagedown"    -- or more transparant.

local DispN= "numpad8"
local DispS= "numpad2"     -- For moving the
local DispE= "numpad6"     -- display around.
local DispW= "numpad4"

local MoreFutr= "numpad3"
local LessFutr= "numpad1"  -- These will determine
local MorePast= "numpad7"  -- how many frames you
local LessPast= "numpad9"  -- want to display.
local ResetFP=  "numpad5"


--Control options by keyboard
local OptUp= "numpad8"
local OptDn= "numpad2"     -- Controls for changing
local OptRt= "numpad6"     -- options by keyboard.
local OptLf= "numpad4"
local OptHit="numpad5"



--Various colors I'm using. If you wish to bother, go ahead.
local shade= 0x00000080
local white= "#FFFFFFFF"
local red=   "#FF2000FF"
local green= 0x00FF00FF
local blue=  0x0040FFFF
local orange="#FFC000FF"
local yellow="#FFFF00FF"
local cyan=  0x00FFFFFF
local purple="#8020FFFF"

--Default display stuff. Try to keep Past negative.
local DispX, DispY= 190, 70     --Position on screen to appear
local Past, Future= -12, 20     --How much input to see
local Opaque= 1                 --0=unseen   1=visible   Decimal in between works


local ListOfBtnClr= {  -- Colors for individual buttons
--NotExist Off      Ignored  On

  white,   red,     orange,  green,    -- No backup to display
  white,   red,     orange,  green,    -- Backup button is off
  blue,    blue,    purple,  cyan,     -- Backup button is on

  white,   red,     orange,  green,    -- Same stuff as above.
  white,   red,     orange,  green,    -- However, we're reading
  blue,    blue,    purple,  cyan,     -- from backup here.

  white,   red,     orange,  green,    -- Likewise, but instead
  white,   red,     orange,  green,    -- of read, we're writing
  blue,    blue,    purple,  cyan      -- to the backup. Joy...
}

local ListOfChangesClr= {  -- Colors for backup-main comparisons
--NoMain   NoMatch  Equal

  white,   green,   blue,              -- Backup just sits there...
  white,   orange,  green,             -- Reading from backup...
  white,   yellow,  purple             -- Writing to backup...
}



local BackupFileLimit= 9


--*****************************************************************************
--Please do not change the following, unless you plan to change the code:

local plmin , plmax= 1 , 1
local fc= movie.framecount()
local LastLoad= movie.framecount()
local saveCount= 0
local saveArray= {}
local rewinding= false

local BackupList= {}
local BackupOverride= {}
local DisplayBackup= true

local InputList= {}
local ThisInput= {}
local BufInput= {}
local BufLen= {}
local TrueSwitch, FalseSwitch= {}, {}
local ReadList= {}
local ScriptEdit= {}

for pl= 1, players do
    InputList[pl]= {}
    BackupList[pl]= {}
    BackupOverride[pl]= false
    ThisInput[pl]= {}
    BufInput[pl]= {}
    BufLen[pl]= 0

    TrueSwitch[pl]= {}
    FalseSwitch[pl]= {}
    ReadList[pl]= {}
    ScriptEdit[pl]= {}
    for i= 1, 8 do
        TrueSwitch[pl][i]= "inv"
        FalseSwitch[pl][i]= nil
        ReadList[pl][i]= true
        ScriptEdit[pl][i]= false
    end
end

--*****************************************************************************
-- Just painting instructions here.

print("Running Multitrack Script made by FatRatKnight.",
  "\r\nIts primary use is to preserve input after a loadstate.",
  "\r\nIt also gives precise control on changing this stored input.",
  "\r\nEdit the script if you need to change stuff. All options are near the top.",
  "\r\nThe script is currently set as follows:\r\n")

print("Players:",players)
if players > 1 then
    print("Player Switch key:",PlayerSwitch,
    "\r\nThere is an All Players view as well, beyond the last player.\r\n")
else
    print("With only one player, the PlayerSwitch button is disabled.\r\n")
end

print("Maximum rewind states:",saveMax)
local CalcSeconds= math.floor(saveMax*SaveBuf*100/60)/100
if saveMax > 0 then
    print("Frames between saves:",SaveBuf,
      "\r\nRewind key:",rewind,
      "\r\nThis can go backwards up to about",CalcSeconds,"seconds.",
      "\r\nRewind is a quick and easy way to back up just a few frames.",
      "\r\nJust hit",rewind,"and back you go!\r\n")
else
    print("Rewind function is disabled. Cheap on memory!\r\n")
end

print("Hold >",opt,"< to view control options.",
  "\r\nYou may use the mouse or keyboard to toggle options.",
  "\r\nFor keyboard, use",OptUp,OptDn,OptRt,OptLf,"to choose an option and",
  OptHit,"to toggle the option.",
  "\r\nFor mouse, it's as simple at point and click.",
  "\r\nIf viewing All Players, changing options will affect all players.\r\n")

print("For the frame display, you can drag it around with the mouse.",
  "\r\nTo move it by keyboard:",DispN,DispS,DispE,DispW,
  "\r\nTo change frames to display:",MoreFutr,LessFutr,MorePast,LessPast,
  "\r\nTo recenter display around current frame:",ResetFP,
  "\r\nLastly, hide it with >",clear,"< and show it with >",solid,"<\r\n")

print("Insert frame:",Insert,
  "\r\nDelete frame:",Delete,
  "\r\nThese keys allow you to shift frames around the current frame.",
      "Perhaps you found an improvement to a segment and want to delete frames.",
      "Or this small trick you wanted to add requires shifting a few frames forward.",
      "These buttons let you shift frames around without forcing you to",
      "modify each and every one of them individually.\r\n")


print("Script keys:",
  "\r\nJoy - Keyboard",
  "\r\n------------")
for i= 1, 8 do
    print(btn[i],"-",key[i])
end
print("By default, these are disabled. Enable them through the control options.",
  "\r\nThey are a one-tap joypad switch for precision control.",
  "\r\nIt will affect the currently displayed player, or all of them if",
      "it's displaying All Players.\r\n")

print("If you want to \"load\" an fm2 into this script, run the play file",
      "while running this script. As the movie on read-only plays out, the",
      "script will pick up its input. The script does not need to start from",
      "frame 1 -- Load a state near the end of a movie if you so wish!",
      "Once input is loaded, you may continue whatever you were doing.\r\n")

print("Remember, edit the script if you don't like the current options. All",
      "the options you should care about are near the top, clearly marked.",
      "Change the control keys through there, as well as number of players or rewind limits.",
  "\r\nThis script works with the joypad you actually set from FCEUX's config,",
      "and they can even cancel input stored in this script.",

"\r\n\r\nAnd have fun with this script. I hope your experiments with this script goes well.",
"\r\n\r\nLeeland Kirwan, the FatRatKnight.")

print("Players:",players,"  - -  ",CalcSeconds,"seconds of rewind.")



--*****************************************************************************
function FBoxOld(x1, y1, x2, y2, color)
--*****************************************************************************
-- Gets around FCEUX's problem of double-painting the corners.
-- The double-paint is visible with non-opaque drawing.
-- It acts like the old-style border-only box.
-- Slightly messes up when x2 or y2 are less than their counterparts.

    if     (x1 == x2) and (y1 == y2) then
        gui.pixel(x1,y1,color)

    elseif (x1 == x2) or  (y1 == y2) then
        gui.line(x1,y1,x2,y2,color)

    else --(x1 ~= x2) and (y1 ~= y2)
        gui.line(x1  ,y1  ,x2-1,y1  ,color) -- top
        gui.line(x2  ,y1  ,x2  ,y2-1,color) -- right
        gui.line(x1+1,y2  ,x2  ,y2  ,color) -- bottom
        gui.line(x1  ,y1+1,x1  ,y2  ,color) -- left
    end
end


--*****************************************************************************
function FakeBox(x1, y1, x2, y2, Fill, Border)
--*****************************************************************************
-- Gets around FCEUX's problem of double-painting the corners.
-- It acts like the new-style fill-and-border box.

if not Border then   Border= Fill   end

    gui.box(x1,y1,x2,y2,Fill,0)
    FBoxOld(x1,y1,x2,y2,Border)
end


--*****************************************************************************
local Draw= {}   --Draw[button]( Left , Top , color )
--*****************************************************************************

function Draw.right(x,y,color)       --    ##
    gui.line(x  ,y  ,x+1,y  ,color)  --      #
    gui.line(x  ,y+2,x+1,y+2,color)  --    ##
    gui.pixel(x+2,y+1,color)
end

function Draw.left(x,y,color)        --     ##
    gui.line(x+1,y  ,x+2,y  ,color)  --    #
    gui.line(x+1,y+2,x+2,y+2,color)  --     ##
    gui.pixel(x  ,y+1,color)
end

function Draw.up(x,y,color)          --     #
    gui.line(x  ,y+1,x  ,y+2,color)  --    # #
    gui.line(x+2,y+1,x+2,y+2,color)  --    # #
    gui.pixel(x+1,y  ,color)
end

function Draw.down(x,y,color)        --    # #
    gui.line(x  ,y  ,x  ,y+1,color)  --    # #
    gui.line(x+2,y  ,x+2,y+1,color)  --     #
    gui.pixel(x+1,y+2,color)
end

function Draw.start(x,y,color)       --     #
    gui.line(x+1,y  ,x+1,y+2,color)  --    ###
    gui.pixel(x  ,y+1,color)         --     #
    gui.pixel(x+2,y+1,color)
end

function Draw.select(x,y,color)      --    ###
    FBoxOld(x  ,y  ,x+2,y+2,color)   --    # #
end                                  --    ###

function Draw.A(x,y,color)           --    ###
    FBoxOld(x  ,y  ,x+2,y+1,color)   --    ###
    gui.pixel(x  ,y+2,color)         --    # #
    gui.pixel(x+2,y+2,color)
end

function Draw.B(x,y,color)           --    # #
    gui.line(x  ,y  ,x  ,y+2,color)  --    ##
    gui.line(x+1,y+1,x+2,y+2,color)  --    # #
    gui.pixel(x+2,y  ,color)
end



function Draw.D0(left, top, color)
    gui.line(left  ,top  ,left  ,top+4,color)
    gui.line(left+2,top  ,left+2,top+4,color)
    gui.pixel(left+1,top  ,color)
    gui.pixel(left+1,top+4,color)
end

function Draw.D1(left, top, color)
    gui.line(left  ,top+4,left+2,top+4,color)
    gui.line(left+1,top  ,left+1,top+3,color)
    gui.pixel(left  ,top+1,color)
end

function Draw.D2(left, top, color)
    gui.line(left  ,top  ,left+2,top  ,color)
    gui.line(left  ,top+3,left+2,top+1,color)
    gui.line(left  ,top+4,left+2,top+4,color)
    gui.pixel(left  ,top+2,color)
    gui.pixel(left+2,top+2,color)
end

function Draw.D3(left, top, color)
    gui.line(left  ,top  ,left+1,top  ,color)
    gui.line(left  ,top+2,left+1,top+2,color)
    gui.line(left  ,top+4,left+1,top+4,color)
    gui.line(left+2,top  ,left+2,top+4,color)
end

function Draw.D4(left, top, color)
    gui.line(left  ,top  ,left  ,top+2,color)
    gui.line(left+2,top  ,left+2,top+4,color)
    gui.pixel(left+1,top+2,color)
end

function Draw.D5(left, top, color)
    gui.line(left  ,top  ,left+2,top  ,color)
    gui.line(left  ,top+1,left+2,top+3,color)
    gui.line(left  ,top+4,left+2,top+4,color)
    gui.pixel(left  ,top+2,color)
    gui.pixel(left+2,top+2,color)
end

function Draw.D6(left, top, color)
    gui.line(left  ,top  ,left+2,top  ,color)
    gui.line(left  ,top+1,left  ,top+4,color)
    gui.line(left+2,top+2,left+2,top+4,color)
    gui.pixel(left+1,top+2,color)
    gui.pixel(left+1,top+4,color)
end

function Draw.D7(left, top, color)
    gui.line(left  ,top  ,left+1,top  ,color)
    gui.line(left+2,top  ,left+1,top+4,color)
end

function Draw.D8(left, top, color)
    gui.line(left  ,top  ,left  ,top+4,color)
    gui.line(left+2,top  ,left+2,top+4,color)
    gui.pixel(left+1,top  ,color)
    gui.pixel(left+1,top+2,color)
    gui.pixel(left+1,top+4,color)
end

function Draw.D9(left, top, color)
    gui.line(left  ,top  ,left  ,top+2,color)
    gui.line(left+2,top  ,left+2,top+3,color)
    gui.line(left  ,top+4,left+2,top+4,color)
    gui.pixel(left+1,top  ,color)
    gui.pixel(left+1,top+2,color)
end


Draw[0],Draw[1],Draw[2],Draw[3],Draw[4]=Draw.D0,Draw.D1,Draw.D2,Draw.D3,Draw.D4
Draw[5],Draw[6],Draw[7],Draw[8],Draw[9]=Draw.D5,Draw.D6,Draw.D7,Draw.D8,Draw.D9
--*****************************************************************************
function DrawNum(right, top, Number, color, bkgnd)
--*****************************************************************************
-- Paints the input number as right-aligned.
-- Returns the x position where it would paint another digit.
-- It only works with integers. Rounds fractions toward zero.

    local Digit= {}
    local Negative= false
    if Number < 0 then
        Number= -Number
        Negative= true
    end

    Number= math.floor(Number)
    if not color then color= "white" end
    if not bkgnd then bkgnd= "clear" end

    local i= 0
    if Number < 1 then
        Digit[1]= 0
        i= 1
    end

    while (Number >= 1) do
        i= i+1
        Digit[i]= Number % 10
        Number= math.floor(Number/10)
    end

    if Negative then  i= i+1  end
    local left= right - i*4
    FakeBox(left+1, top-1, right+1, top+5,bkgnd,bkgnd)

    i= 1
    while Draw[Digit[i]] do
        Draw[Digit[i]](right-2,top,color)
        right= right-4
        i=i+1
    end

    if Negative then
        gui.line(right, top+2,right-2,top+2,color)
        right= right-4
    end
    return right
end


--*****************************************************************************
function limits( value , low , high )  -- Expects numbers
--*****************************************************************************
-- Returns value, low, or high. high is returned if value exceeds high,
-- and low is returned if value is beneath low.

    return math.max(math.min(value,high),low)
end

--*****************************************************************************
function within( value , low , high )  -- Expects numbers
--*****************************************************************************
-- Returns true if value is between low and high. False otherwise.

    return ( value >= low ) and ( value <= high )
end


local keys, lastkeys= {}, {}
--*****************************************************************************
function press(button)  -- Expects a key
--*****************************************************************************
-- Returns true or false.
-- Generally, if keys is pressed, the next loop around will set lastkeys,
-- and thus prevent returning true more than once if held.

    return (keys[button] and not lastkeys[button])
end

local repeater= 0
--*****************************************************************************
function pressrepeater(button)  -- Expects a key
--*****************************************************************************
--DarkKobold & FatRatKnight
-- Returns true or false.
-- Acts much like press if you don't hold the key down. Once held long enough,
-- it will repeatedly return true.
-- Try not to call this function more than once per main loop, since I've only
-- set one repeater variable. Inside a for loop is real bad.

    if keys[button] then
       if not lastkeys[button] or repeater >= 3 then
           return true
       else
           repeater = repeater + 1;
       end

    elseif lastkeys[button] then   -- To allow more calls for other buttons
       repeater= 0
    end;
    return false
end



--*****************************************************************************
function JoyToNum(Joys)  -- Expects a table containing joypad buttons
--*****************************************************************************
-- Returns a number from 0 to 255, representing button presses.
-- These numbers are the primary storage for this version of this script.

    local joynum= 0

    for i= 1, 8 do
        if Joys[btn[i]] then
            joynum= bit.bor(joynum, bit.rshift(0x100,i))
        end
    end

    return joynum
end

--*****************************************************************************
function ReadJoynum(input, button)  -- Expects... Certain numbers!
--*****************************************************************************
-- Returns true or false. True if the indicated button is pressed
-- according to the input. False otherwise.
-- Helper function
    return ( bit.band(input , bit.rshift( 0x100,button )) ~= 0 )
end


--*****************************************************************************
function RewindThis()
--*****************************************************************************
--DarkKobold & FatRatKnight; Original concept by Antony Lavelle

    if saveCount <= 0 then
        return false    -- Failed to rewind
    else
        savestate.load(saveArray[saveCount]);
        saveCount = saveCount-1;
    end;
    return true         -- Yay, rewind!
end


--*****************************************************************************
function ShowOnePlayer(x,y,color,button,pl)
--*****************************************************************************
-- Displays an individual button.
-- Helper function for DisplayInput.

    x= x + 4*button - 3
    Draw[btn[button]](x,y,color)
end

--*****************************************************************************
function ShowManyPlayers(x,y,color,button,pl)
--*****************************************************************************
-- Displays an individual button. Uses 2x3 boxes instead of button graphics.
-- Helper function for DisplayInput.

    x= x + (2*players + 1)*(button - 1) + 2*pl - 1
    FBoxOld(x,y,x+1,y+2,color)
end


Future= limits(Future,Past,Past+53) --Idiot-proofing
--*****************************************************************************
function DisplayOptions(width)  -- Expects width calculated by DisplayInput
--*****************************************************************************
-- Returns true if Opaque is 0, as a signal to don't bother painting.
-- Separated from DisplayInput to make it clear which half is doing what.


-- Change opacity?
    if pressrepeater(solid) then Opaque= Opaque + 1/8 end
    if pressrepeater(clear) then Opaque= Opaque - 1/8 end
    Opaque= limits(Opaque,0,1)

    gui.opacity(Opaque)
    if Opaque == 0 then  return true  end
    -- Don't bother processing display if there's none to see.

-- How many frames to show?
    if pressrepeater(LessFutr) then
        Future= Future-1
        if Future < Past then Past= Future end
    end
    if pressrepeater(MoreFutr) then
        Future= Future+1
        if Future > Past+53 then Past= Future-53 end
    end
    if pressrepeater(MorePast) then
        Past= Past-1
        if Past < Future-53 then Future= Past+53 end
    end
    if pressrepeater(LessPast) then
        Past= Past+1
        if Past > Future then Future= Past end
    end

    if press(ResetFP) then Past= -12;  Future= 12   end


-- Move the display around?
    if pressrepeater(DispS) then DispY= DispY+1 end
    if pressrepeater(DispW) then DispX= DispX-1 end
    if pressrepeater(DispE) then DispX= DispX+1 end
    if pressrepeater(DispN) then DispY= DispY-1 end

    if keys["leftclick"] and lastkeys["leftclick"] then
        DispX= DispX + keys.xmouse - lastkeys.xmouse
        DispY= DispY + keys.ymouse - lastkeys.ymouse
    end

--Miscellaneous
    if press(BackupDisplaySwitch) then DisplayBackup= not DisplayBackup end
    DispX= limits(DispX,2,254-width)
    DispY= limits(DispY,3-4*Past,218-4*Future)


    return nil -- Signal to display the input
end


--*****************************************************************************
function DisplayInput()
--*****************************************************************************
-- Paints on the screen the current input stored within the script's list.

--Are we showing all players or just one?
    local HighlightButton= ShowOnePlayer
    local width= 32
    if plmin ~= plmax then
        HighlightButton= ShowManyPlayers
        width= 16*players + 8
    end

--For both setting options and asking if we should bother displaying ourselves
    if DisplayOptions(width) then  return  end

--Display frame offsets we're looking at.
    local RtDigit= DispX + width + 22
    if RtDigit > 254 then  RtDigit= DispX - 4  end
    local TpDigit= DispY + 4*Past - 2
    DrawNum(RtDigit,TpDigit,Past,white,shade)

    if Future > Past+1 then
        TpDigit= DispY + 4*Future
        DrawNum(RtDigit,TpDigit,Future,white,shade)
    end

--Show cute little box around current frame
    if Past <= 0 and Future >= 0 then
        local color= blue
        for pl= plmin, plmax do
            local ThisFrame= InputList[pl][fc-BufLen[pl]]
            if BufLen[pl] > 0 then  ThisFrame= BufInput[pl][1]  end
            if ThisFrame ~= JoyToNum(ThisInput[pl]) then  color= green  end
        end
        FBoxOld(DispX-1,DispY-2,DispX+width+1,DispY+4,color)
    end

--Shade the proper regions efficiently
    if Past < 0 then
        local Y1= DispY + 4*Past -3
        local Y2= DispY - 3
        if Future < -1 then  Y2= DispY + 4*Future +1  end
        FakeBox(DispX,Y1,DispX+width,Y2,shade,shade)
    end
    if Future > 0 then
        local Y1= DispY + 5
        local Y2= DispY + 4*Future+5
        if Past > 1 then  Y1= DispY + 4*Past +1  end
        FakeBox(DispX,Y1,DispX+width,Y2,shade,shade)
    end
    if  Past <= 0  and  Future >= 0  then
        FakeBox(DispX,DispY-1,DispX+width,DispY+3,shade,shade)
    end

--Finally, we get to show the actual buttons!
    for i= Past, Future do
        local Y= DispY + 4*i
        if     i < 0 then  Y=Y-2
        elseif i > 0 then  Y=Y+2 end

        local BackupColor= nil -- For displaying a line for backup
        for pl= plmin, plmax do
            local scanz
            if     i  < 0 then scanz= InputList[pl][fc+i]
            elseif i == 0 then scanz= JoyToNum(ThisInput[pl])
            elseif i  < BufLen[pl]  then
                               scanz= BufInput[pl][i+1]
            else               scanz= InputList[pl][fc+i-BufLen[pl]]
            end
            for button= 1, 8 do

-- Take a number, oh mighty color. There's too much of ya!
                local color
                if not scanz then
                    color= 1        --Does not exist
                elseif ReadJoynum(scanz,button) then
                    if (i <= 0) or (ReadList[pl][button]) then
                        color= 4    --Button on
                    else
                        color= 3    --Button on, will be ignored
                    end
                else
                    color= 2        --Button off
                end

                if DisplayBackup then
                    if BackupList[pl][fc+i] then
                        if ReadJoynum(BackupList[pl][fc+i],button) then
                            color= color+8
                        else
                            color= color+4
                        end
                    end
                    if     BackupOverride[pl] == "read"  then
                        color= color+12
                    elseif BackupOverride[pl] == "write" then
                        color= color+24
                    end
                end

                HighlightButton(DispX,Y,ListOfBtnClr[color],button,pl)

            end -- button loop

-- Draw cute lines if we wish to see the backup
            if DisplayBackup and BackupList[pl][fc+i] then
                if not BackUpColor then
                    if not scanz then
                        BackupColor= 1
                    elseif scanz == BackupList[pl][fc+i] then
                        BackupColor= 3
                    else
                        BackupColor= 2
                    end
                    if     BackupOverride[pl] == "read"  then
                        BackupColor= BackupColor+3
                    elseif BackupOverride[pl] == "write" then
                        BackupColor= BackupColor+6
                    end

                else -- Eh, we already have a BackupColor?
                    local CheckColor= (BackupColor-1)%3
                    if not scanz then
                        BackupColor= BackupColor - CheckColor
                    elseif (scanz ~= BackupList[pl][fc+i]) and (CheckColor == 2) then
                        BackupColor= BackupColor - 1
                    end
                end
            end

        end -- player loop

        if BackupColor then
            gui.line(DispX-2,Y,DispX-2,Y+2,ListOfChangesClr[BackupColor])
        end
    end -- loop from Past to Future
end --function


--*****************************************************************************
function SetInput()
--*****************************************************************************
-- Prepares ThisInput for joypad use.

    for pl= 1, players do
        local temp
        if BackupOverride[pl] == "read" then
            temp= BackupList[pl][fc]
        else
            if BufLen[pl] > 0 then
                temp= BufInput[pl][1]
            else
                temp= InputList[pl][fc-BufLen[pl]]
            end
        end

        for i= 1, 8 do
            if temp and ReadJoynum(temp,i) and ReadList[pl][i] then
                ThisInput[pl][btn[i]]= TrueSwitch[pl][i]
            else
                ThisInput[pl][btn[i]]= FalseSwitch[pl][i]
            end
        end
    end
end


--*****************************************************************************
function ApplyInput()
--*****************************************************************************
-- Shoves ThisInput into the actual emulator joypads.

    if movie.mode() ~= "playback" then
        for pl= 1, players do
            joypad.set(pl, ThisInput[pl])
        end
    end
end


--*****************************************************************************
function InputSnap()
--*****************************************************************************
-- Will shove the input list over.
-- Might end up freezing for a moment if there's a few thousand frames to shift

    for pl= 1, players do

       if BufLen[pl] < 0 then  -- Squish!
           local pointer= fc
           while InputList[pl][pointer] do
               InputList[pl][pointer]= InputList[pl][pointer-BufLen[pl]]
               pointer= pointer+1
           end
       end


       if BufLen[pl] > 0 then -- Foom!
           local pointer= fc
           while InputList[pl][pointer] do
               pointer= pointer+1
           end
           -- pointer is now looking at a null frame.
           -- Assume later frames are also null.

           while pointer > fc do
               pointer= pointer-1
               InputList[pl][pointer+BufLen[pl]]= InputList[pl][pointer]
           end
           -- pointer should now match fc.
           -- Everything at fc and beyond should be moved over by BufLen.

           for i=0, BufLen[pl]-1 do
               InputList[pl][fc +i]= table.remove(BufInput[pl],1)
           end
       end

       BufLen[pl]= 0 -- If it ain't zero before, we want it zero now!

    end
end




local XStart, XDiff= 30, 25
local YStart, YDiff= 12, 15
local Status= { {},{},{},{} }
local TargA= {FalseSwitch,TrueSwitch,ReadList,ScriptEdit}
local TrueA= {   nil     ,   "inv"  ,  true  ,  true    }
local FalsA= {   false   ,   true   ,  false ,  false   }
local BtnX, BtnY= 0, 0

local BasicText= {
"Activate: Lets the joypad activate input.",
"Remove: Allows the joypad to remove input.",
"List: Should the script remember button presses?",
"Keys: Allow the script-specific keys to work?"}

local AdvText= {
{"With both joypad options on, you have full control.",
 "Held buttons will toggle the script's stored input."}, -- 1

{"With this on-off set-up, auto-hold will not",
 "accidentally cancel input, such as from load state."}, -- 2

{"With this off-on set, you can use auto-hold to",
 "elegantly strip off unwanted input."},                 -- 3

{"With both joypad options off, you ensure you can't",
 "accidentally change what's stored in the script."},    -- 4

{"List on: Script will apply input stored within.",
 "This is the whole point of the script, ya know."},     -- 5

{"List off: Stored input is ignored. A good idea if",
 "you don't want the script interfering."},              -- 6

{"Keys on: Script keys will toggle the button press",
 "for the current frame. Meant for precise edits."},     -- 7

{"Keys off: Script-specific keys are no longer a",
 "factor. Long-term control is meant for joypad!"},      -- 8

{"Apparently, you've selected 'All players'",
 "and they have different options set."},                -- 9

{"This is the 'All' button. Selecting this will set",
 "all 'Yes' or all 'No' for this particular option."}    --10
}

--*****************************************************************************
function ControlOptions()
--*****************************************************************************
-- Lets the user make adjustments on the various controls of this script.
-- The interface, apparently, is most of the work!


-- Button selection
    if (keys.xmouse ~= lastkeys.xmouse) or (keys.ymouse ~= lastkeys.ymouse) then
        BtnX= math.floor((keys.xmouse- XStart+4)/XDiff)
        BtnY= math.floor((keys.ymouse- YStart-6)/YDiff)
    else
        if press(OptUp) then
            BtnX= limits(BtnX  ,1,4)
            BtnY= limits(BtnY-1,1,9)
        end
        if press(OptDn) then
            BtnX= limits(BtnX  ,1,4)
            BtnY= limits(BtnY+1,1,9)
        end
        if press(OptRt) then
            BtnX= limits(BtnX+1,1,4)
            BtnY= limits(BtnY  ,1,9)
        end
        if press(OptLf) then
            BtnX= limits(BtnX-1,1,4)
            BtnY= limits(BtnY  ,1,9)
        end
    end


--Did you punch something?
    if press("leftclick") or press(OptHit) then
        if within( BtnY , 1 , 9 ) then
            if within( BtnX , 1 , 4 ) then
                local LoopS, LoopF= 1, 8
                if BtnY ~= 9 then
                    LoopS, LoopF= BtnY, BtnY
                end

                local Target, TstT, TstF= TargA[BtnX], TrueA[BtnX], FalsA[BtnX]

                for pl= plmin, plmax do
                    for Loop= LoopS, LoopF do
                        if Target[plmax][LoopF] == TstT then
                            Target[pl][Loop]= TstF
                        else
                            Target[pl][Loop]= TstT
                        end
                    end
                end

            end
        end
    end


--Figure out the status
    for i= 1, 4 do
        for j= 1, 8 do
            Status[i][j]= TargA[i][plmin][j]
            local pl= plmin+1
            while (pl <= plmax) do
                if Status[i][j] ~= TargA[i][pl][j] then
                    Status[i][j]= "???"
                    break
                end
                pl= pl+1
            end
            if     Status[i][j] == TrueA[i] then  Status[i][j]= "Yes"
            elseif Status[i][j] == FalsA[i] then  Status[i][j]= "No" end
        end
    end

--=============================================================================
--Begin drawing. Finally...


--Shade the whole freaking screen
    FakeBox(0,0,255,223,shade,shade)

-- Silly little graphics
-- Perhaps I shouldn't always assume that button right is a right arrow...
    Draw.B(     XStart + XDiff     ,YStart,red)
    Draw.right( XStart + XDiff  + 5,YStart,white)
    Draw.B(     XStart + XDiff  +10,YStart,green)

    Draw.B(     XStart + XDiff*2   ,YStart,green)
    Draw.right( XStart + XDiff*2+ 5,YStart,white)
    Draw.B(     XStart + XDiff*2+10,YStart,red)

    Draw[btn[1]](XStart + XDiff*3   ,YStart  ,green)
    Draw[btn[1]](XStart + XDiff*3   ,YStart+4,green)
    Draw[btn[2]](XStart + XDiff*3+ 4,YStart  ,green)
    Draw[btn[2]](XStart + XDiff*3+ 4,YStart+4,red)
    Draw[btn[3]](XStart + XDiff*3+ 8,YStart  ,red)
    Draw[btn[3]](XStart + XDiff*3+ 8,YStart+4,green)
    Draw[btn[4]](XStart + XDiff*3+12,YStart  ,red)
    Draw[btn[4]](XStart + XDiff*3+12,YStart+4,red)

    gui.box(XStart+XDiff*4,YStart,XStart+XDiff*4+14,YStart+6,0,green)
    Draw[btn[6]](XStart + XDiff*4+ 2,YStart+2,green)
    Draw[btn[7]](XStart + XDiff*4+ 6,YStart+2,green)
    Draw[btn[8]](XStart + XDiff*4+10,YStart+2,green)


--Highlight button
    if within( BtnY , 1 , 9 ) then
        if within( BtnX , 1 , 4 ) then
            local LowX=BtnX*XDiff +XStart -4
            local LowY=BtnY*YDiff +YStart -3
            gui.box(LowX,LowY,LowX+XDiff-2,LowY+YDiff-2,blue,blue)

--Handle text. Feels sort of hard-coded, however
            gui.text(1,160,BasicText[BtnX])

            local adv
            if BtnY == 9 then
                adv= 10
            elseif Status[BtnX][BtnY] == "???" then
                adv=  9
            elseif within(BtnX,1,2) and ((Status[3-BtnX][BtnY] == "???")) then
                adv=  9
            elseif within(BtnX,1,2) then
                adv=  1
                if Status[2][BtnY] == "No" then
                    adv= adv + 1
                end
                if Status[1][BtnY] == "No" then
                    adv= adv + 2
                end
            else
                adv= 5
                if BtnX == 4 then
                    adv= adv+2
                end
                if Status[BtnX][BtnY] == "No" then
                    adv= adv+1
                end
            end
            gui.text(1,175,AdvText[adv][1])
            gui.text(1,183,AdvText[adv][2])
        end
    end


--Lines!
    for i= 1, 5 do
        local Xpos= XStart + XDiff*i -5
        gui.line(Xpos,0,Xpos,YStart + YDiff*10-4,green)
    end

    for j= 1, 9 do
        local Ypos= YStart + YDiff*j -4
        gui.line( 0, Ypos, XStart + XDiff*5-5, Ypos, green)
    end
    gui.line(XStart+XDiff-4, YStart + YDiff*10-4, XStart + XDiff*5-5, YStart + YDiff*10-4, green)


--Button labels!
    for j= 1, 8 do
        local Ypos= YStart + YDiff*j
        gui.text( 1, Ypos, btn[j])
        Draw[btn[j]](XStart + XDiff - 12, Ypos, green)

        for i= 1, 4 do
            gui.text(XStart + XDiff*i, Ypos, Status[i][j])
        end
    end

    for i= 1, 4 do
        gui.text(XStart + XDiff*i, YStart + YDiff*9, "All")
    end

end


--*****************************************************************************
function CatchInput()
--*****************************************************************************
-- For use with registerbefore. It will get the input and paste it into
-- the input list.

    fc= movie.framecount()
    for pl= 1, players do
        if BufLen[pl] > 0 then
            table.remove(BufInput[pl],1)
            table.insert(BufInput[pl],InputList[pl][fc-1])
        end
        local NewJoy= JoyToNum(joypad.get(pl))
        InputList[pl][fc-1]= NewJoy
        if not BackupList[pl][fc-1]  or  (BackupOverride[pl] == "write") then
            BackupList[pl][fc-1]= NewJoy
        end
    end
    SetInput()
end
emu.registerbefore(CatchInput)


--*****************************************************************************
function OnLoad()
--*****************************************************************************
-- For use with registerload. It updates ThisInput so we're not stuck with
-- junk being carried over when we load something.
-- Also clears whatever rewind stuff is stored.

    InputSnap()
    for pl= 1, players do    --Assume user is done messing with backup on load
        BackupOverride[pl]= false
    end

    fc= movie.framecount()
    LastLoad= fc
    saveCount= 0
    SetInput()
    ApplyInput() -- Sanity versus unpaused stateload
end
savestate.registerload(OnLoad)


--*****************************************************************************
function ItIsYourTurn()
--*****************************************************************************
-- For use with gui.register. I need to catch input while paused!
-- Needed for a half-decent interface.

--Ensure things are nice, shall we?
    local fc_= movie.framecount()
    lastkeys= keys
    keys= input.get()

    if fc ~= fc_ then -- Sanity versus unusual jump (Reset cycle?)
        OnLoad()
    end

--Process Rewind
 if saveMax > 0 then  -- Don't process if Rewind is disabled
    if pressrepeater(rewind) or rewinding then
        rewinding= false
        if RewindThis() then
            InputSnap()
            movie.rerecordcounting(true)
            fc= movie.framecount()
            SetInput()
            if saveCount < 1 then  emu.pause()  end
        end
    end
 end

--Should we bother the backups today?
    for pl= plmin, plmax do
        if press(BackupReadSwitch) then
                if BackupOverride[pl] ~= "read" then
                    BackupOverride[pl]= "read"
                else
                    BackupOverride[pl]= false
                end
        end
        if press(BackupWriteSwitch) then
            if BackupOverride[pl] ~= "write" then
                BackupOverride[pl]= "write"
            else
                BackupOverride[pl]= false
            end
        end
    end

    if keys[BackupReadSwitch] and keys[BackupWriteSwitch] then
        gui.text(30,1,"Hey, quit holding both buttons!")
    elseif keys[BackupReadSwitch] then
        gui.text(30,1,"This lets the script revert to the backup.")
    elseif keys[BackupWriteSwitch] then
        gui.text(30,1,"This stores input into the backup.")
    end

--Switch players on keypress
    if press(PlayerSwitch) then
        if plmin ~= plmax then
            plmax= 1
        elseif plmin == players then
            plmin= 1
        else
            plmin= plmin+1
            plmax= plmax+1
        end
    end

--Display which player we're selecting. Upperleft corner seems good.
    if plmin == plmax then
        gui.text(1,2,plmin)
        gui.text(11,2,BufLen[plmin])
    else
        gui.text(1,2,"A")
    end

--Check if we want to see control options
    if keys[opt] then
        gui.opacity(1)
        ControlOptions()
        SetInput()

--Otherwise, handle what we can see
    else

--Inserts and deletes.
--table functions don't work well on tables that don't connect from 1.
        if pressrepeater(Insert) then
            for pl= plmin, plmax do
                BufLen[pl]= BufLen[pl] + 1
                if BufLen[pl] > 0 then
                    table.insert(BufInput[pl],1,0)
                end
            end
            SetInput()
        end
        if pressrepeater(Delete) then
            for pl= plmin, plmax do
                if BufLen[pl] > 0 then
                    table.remove(BufInput[pl],1)
                end
                BufLen[pl]= BufLen[pl] - 1
            end
            SetInput()
        end

--Script key handler
        for pl= plmin, plmax do
            for i= 1, 8 do
                if press(key[i]) and ScriptEdit[pl][i] then
                    if ThisInput[pl][btn[i]] then
                        ThisInput[pl][btn[i]]= FalseSwitch[pl][i]
                    else
                        ThisInput[pl][btn[i]]= TrueSwitch[pl][i]
                    end
                end
            end
        end

        DisplayInput()
    end

--Last bits of odds and ends
    ApplyInput()

    collectgarbage("collect")
end
gui.register(ItIsYourTurn)


--*****************************************************************************
function Rewinder()
--*****************************************************************************
-- Contains the saving part of the Rewind engine.
-- Original by Antony Lavelle, added by DarkKobold, messed by FatRatKnight
 if saveMax > 0 then  -- Don't process if Rewind is disabled
    if keys[rewind] and saveCount > 0 then
        rewinding= true

    elseif (fc - LastLoad)%SaveBuf == 0 then
        if saveCount >= saveMax then
            table.remove(saveArray,1)
        else
            saveCount= saveCount+1
        end

        if saveArray[saveCount] == nil then
            saveArray[saveCount]= savestate.create();
        end

        savestate.save(saveArray[saveCount]);

        movie.rerecordcounting(false)
    end
 end

end

--emu.registerafter(Rewinder)








local TestNumOfDoom= 0
local TestFile= io.open("Backup" .. TestNumOfDoom .. ".txt" , "r")
while TestFile do
    TestFile:close()
    TestNumOfDoom= TestNumOfDoom+1
    if TestNumOfDoom >= BackupFileLimit then break end
    TestFile= io.open("Backup" .. TestNumOfDoom .. ".txt" , "r")
end




local FCEUXbtn= {"right", "left", "down", "up", "start", "select", "B", "A"}
local FCEUXfrm= {"R","L","D","U","T","S","B","A"}
local FCEUXorder= {}

for i= 1, 8 do
    for j= 1, 8 do
        if btn[i] == FCEUXbtn[j] then
            FCEUXorder[j]= i
            break
        end
    end
end

--*****************************************************************************
function SaveToFile()
--*****************************************************************************
-- Creates a file that, effectively, stores whatever's in the script at the
-- time.
-- List of known glitches:
--   It only reads player 1 when deciding when to start or stop.

    InputSnap()
    local LatestIndex= 0
    local EarliestIndex= math.huge
    for Frame, Pads in pairs(InputList[1]) do
        LatestIndex= math.max(LatestIndex,Frame)
        EarliestIndex= math.min(EarliestIndex,Frame)
    end


    local BFile = io.open("Backup" .. TestNumOfDoom .. ".txt" , "w")
    BFile:write("StartFrame: " .. EarliestIndex .. "\n")

    for Frame= EarliestIndex, LatestIndex do
        BFile:write("|0")
        for pl= 1, 4 do
            BFile:write("|")
            if InputList[pl] then
                if InputList[pl][Frame] then
                    local Pads= InputList[pl][Frame]
                    for i= 1, 8 do
                        if ReadJoynum(Pads,FCEUXorder[i]) then
                            BFile:write(FCEUXfrm[i])
                        else
                            BFile:write(".")
                        end
                    end
                else
                    BFile:write("        ")
                end
            end
        end
        BFile:write("\n")
    end
    BFile:close()

end

emu.registerexit(SaveToFile)











emu.pause()

while true do
    Rewinder()

    emu.frameadvance()
end