--
-- ***This Lua script uses Lua 5.4 bit operators and requires BizHawk 2.9.1 (or standalone Lua 5.4)***
--
console.clear()
local function code_to_level(code)
local num=code --39 bits
num=num ~ 0x2AAAAAAAAA
local level= (num>>26)&0x3F
level=level+((num&0x1FFFFF)<<6)
level=(level+115128986)%134217728
--check involves 27 bits
local check=level-1
if (num>>38)%2 == 0 then
check=(check+0x7654321)%134217728
end
-- note: the below code which is commented out is equivalent, based on a checksum algorithm used by https://pastebin.com/cnyKdTCr
-- local checkpass=false
-- for i=1,1 do
-- if ((num>>37) + (check>>6) + (check>>23))%2 == 0 then break end
-- if ((num>>36) + (check>>5) + (check>>22) + (check>>17) + check)%2 == 0 then break end
-- if ((num>>35) + (check>>4) + (check>>21) + (check>>16))%2 == 0 then break end
-- if ((num>>34) + (check>>3) + (check>>20))%2 == 0 then break end
-- if ((num>>33) + (check>>2) + (check>>19))%2 == 0 then break end
-- if ((num>>32) + (check>>1) + (check>>18))%2 == 0 then break end
--
-- if ((num>>25) + (check>>11) + (check>>16))%2 == 1 then break end
-- if ((num>>24) + (check>>10))%2 == 1 then break end
-- if ((num>>23) + (check>>9) + (check>>26))%2 == 1 then break end
-- if ((num>>22) + (check>>8) + (check>>25))%2 == 1 then break end
-- if ((num>>21) + (check>>7) + (check>>24))%2 == 1 then break end
--
-- checkpass=true
-- end
local checksum = ((num>>32)&0x3F)
checksum=checksum+ (((num>>21)&0x1F)<<6)
local verifynum = ((check>>1) ~ (check>>18) ~ (((check>>16)&3)<<3) ~ ((check&1)<<4) ~ (((check>>16)&1)<<10) ~ 0x3F) & 0x7FF
if checksum==verifynum then return level else return -1 end
end
-- password when locked onto Sonic 1
local function level_to_code_soniccart(level)
local check=level-1
local checksum = ((check>>1) ~ (check>>18) ~ (((check>>16)&3)<<3) ~ ((check&1)<<4) ~ (((check>>16)&1)<<10) ~ 0x3F) & 0x7FF
local num=(level+19088742)%134217728
local code = ((num>>6)&0x1FFFFF) + (((checksum>>6)&0x1F)<<21) + ((num&0x3F)<<26) + ((checksum&0x3F)<<32) + (1<<38)
code=code ~ 0x2AAAAAAAAA
return code
end
-- password when not locked onto Sonic 1
local function level_to_code_notsoniccart(level)
local check=level-1
check=(check+0x7654321)%134217728
local checksum = ((check>>1) ~ (check>>18) ~ (((check>>16)&3)<<3) ~ ((check&1)<<4) ~ (((check>>16)&1)<<10) ~ 0x3F) & 0x7FF
local num=(level+19088742)%134217728
local code = ((num>>6)&0x1FFFFF) + (((checksum>>6)&0x1F)<<21) + ((num&0x3F)<<26) + ((checksum&0x3F)<<32)
code=code ~ 0x2AAAAAAAAA
return code
end
local function level_to_stage(level)
local quad1=(level-1)%128
local quad2=(3*level-2)%127
local quad3=(5*level-3)%126
local quad4=(7*level-4)%125
return (quad1<<21) + (quad2<<14) + (quad3<<7) + quad4
end
local function stage_to_level(stage)
local quad1=(stage>>21)&0x7F
local quad2=(stage>>14)&0x7F
local quad3=(stage>>7)&0x7F
local quad4=stage&0x7F
if quad2>126 or quad3>125 or quad4>124 then return -1 end
if quad1%2~=quad3%2 then return -1 end
local val=quad1+1
val = val + (85*(quad2-(3*val-2))%127)*128
val = val + (38*((quad3-(5*val-3))>>1)%63)*128*127
val = val + (6*(quad4-(7*val-4))%125)*128*127*63
return val
end
ff=stage_to_level((7<<21)+(7<<14)+(7<<7)+7)
console.write(level_to_code_soniccart(ff) .. " ".. level_to_code_notsoniccart(ff))
console.write("\nDone.")