Module:MemoryAddress/PCToSnes/LoROM

From ALttPR Wiki
Jump to navigation Jump to search

local floor = math.floor

local OR, AND, LSHIFT, RSHIFT = 1, 4, 5, 6

local function isnum(n)

 return type(n) == "number"

end

local function blshift(x, bits)

 return floor(x) * (2^bits)

end

local function brshift(x, bits)

 return floor(floor(x) / (2^bits))

end

local function BitAND(a,b)--Bitwise and

 local p,c=1,0
 while a>0 and b>0 do
   local ra,rb=a%2,b%2
   if ra+rb>1 then c=c+p end
   a,b,p=(a-ra)/2,(b-rb)/2,p*2
 end
 return c

end

local function BitOR(a,b)--Bitwise or

 local p,c=1,0
 while a+b>0 do
   local ra,rb=a%2,b%2
   if ra+rb>0 then c=c+p end
   a,b,p=(a-ra)/2,(b-rb)/2,p*2
 end
 return c

end

local function bitoper(a, b, oper)

 local r = 0
 if oper == 1 then -- OR
   r = BitOR(a, b)
 elseif oper == 4 then -- AND
   r = BitAND(a, b)
 elseif oper == 5 then -- LSHIFT
   r = blshift(a, b)
 elseif oper == 6 then -- RSHIFT
   r = brshift(a, b)
 end
 return r

end

local p = {}

-- SNES to PC function p._convert(n)

 if not isnum(n) then
   if string.find(string.upper(n),"0X") then
     n = string.upper(n):gsub("0X", "")
   end
 end
 n = tonumber(n,16)
 -- ((n << 1) & 0x7F0000) | (n & 0x7FFF) | 0x8000;
 return bitoper(
          bitoper(
            bitoper(
              bitoper(
                      n,
                      1,
                      LSHIFT
              ),
              0x7F0000,
              AND
            ),
            bitoper(
                    n,
                    0x7FFF,
                    AND
            ),
            OR
          ),
          0x8000,
          OR
        )

end

function p.convert(frame)

 -- Allow for invocation via #invoke or directly from another module
 local args
 if frame == mw.getCurrentFrame() then
   args = frame.args
 else
   args = frame
 end
 local n = args[1]
 return p._convert(n)

end

return p