User File #638301006361901434

Upload All User Files

#638301006361901434 - [DQ9] Live Hoimi Table for DeSmuME (JP)

DQ9 Live Hoimi Table.lua
39 downloads
Uploaded 9/12/2023 7:30 AM by TKG (see all 4)
press start to toggle the table on/off
-- Live Hoimi Table by TKG


-- How to use:
-- Run the script in DeSmuME (tools > lua scripting > new lua script window)
-- Press Start to toggle the visibility on/off


-- Addresses:
-- 0x04000130 = face button inputs (US and JP)
-- 0x02108DE0 = BT highbyte (US)
-- 0x02108DDC = BT lowbyte (US)
-- 0x02108D24 = BT highbyte (JP)
-- 0x02108D20 = BT lowbyte (JP)


-- Original BT code:
-- rand()
-- {
--    rand_seed = rand_seed * 0x5d588b656c078965 + 0x269ec3
--    return (rand_seed >> 32) & 0xffffffff
-- }


-- Colours based on Yab's hoimi table (in dark mode):
whiteStroke = "#CCCCCC"
greyStroke = "#444444"
indigoFill = "#000044"
redStroke = "#DD66CC"
redFill = "#880000"
redText = "#FFBBDD"
blueStroke = "#0088FF"
blueFill = "#000088"
blueText = "#88CCFF"


-- Other stuff:
count = 0 -- frame counter for the toggle button
BT = {}   -- table for BT positions


-- My attempt at 64 bit multiplication with 16 bit math
function bt_rand()

   -- BTlowHi_aLo = higher 16 bits of BT's lowbyte * lowbyte of multiplier "a"
   -- BTlowLo_aLo = lower 16 bits of BT's lowbyte * lowbyte of multiplier "a"
   BTlowHi_aLo = bit.rshift(lowbyte, 16) * 0x6C078965
   BTlowLo_aLo = bit.band(lowbyte, 0xFFFF) * 0x6C078965

   -- total_1 = lowest 16 bits of BTlowLo_aLo + lower 16 bits of increment "c"
   -- total_2 = carry from total_1 + lower 16 bits of BTlowHi_aLo + middle 16 bits of BTlowLo_aLo + higher 16 bits of increment "c"
   -- total_3 = carry from total_2 + middle 16 bits of BTlowHi_aLo + highest 16 bits of BTlowLo_aLo
   -- total_4 = carry from total_3 + highest 16 bits of BTlowHi_aLo
   total_1 = bit.band(BTlowLo_aLo, 0xFFFF) + 0x9EC3
   total_2 = bit.rshift(total_1, 16) + bit.band(BTlowHi_aLo, 0xFFFF) + bit.rshift(BTlowLo_aLo, 16) + 0x0026
   total_3 = bit.rshift(total_2, 16) + bit.rshift(BTlowHi_aLo, 16) + math.floor(BTlowLo_aLo / 0xFFFFFFFF)
   total_4 = bit.rshift(total_3, 16) + math.floor(BTlowHi_aLo / 0xFFFFFFFF)

   -- BTlowHi_aHi = higher 16 bits of BT's lowbyte * highbyte of multiplier "a"
   -- BTlowLo_aHi = lower 16 bits of BT's lowbyte * highbyte of multiplier "a"
   -- BTlow_aHi = combine higher and lower results
   BTlowHi_aHi = bit.rshift(lowbyte, 16) * 0x5D588B65
   BTlowLo_aHi = bit.band(lowbyte, 0xFFFF) * 0x5D588B65
   BTlow_aHi = bit.lshift(BTlowHi_aHi, 16) + BTlowLo_aHi

   -- BThighHi_aLo = higher 16 bits of BT's highbyte * lowbyte of multiplier "a"
   -- BThighLo_aLo = lower 16 bits of BT's highbyte * lowbyte of multiplier "a"
   -- BThigh_aLo = combine higher and lower results
   BThighHi_aLo = bit.rshift(highbyte, 16) * 0x6C078965
   BThighLo_aLo = bit.band(highbyte, 0xFFFF) * 0x6C078965
   BThigh_aLo = bit.lshift(BThighHi_aLo, 16) + BThighLo_aLo

   -- total_5 = lower 16 bits of BThigh_aLo + lower 16 bits of BTlow_aHi + lower 16 bits of total_3
   -- total_6 = carry from total_5 + higher 16 bits of BThigh_aLo + higher 16 bits of BTlow_aHi + total_4
   total_5 = bit.band(BThigh_aLo, 0xFFFF) + bit.band(BTlow_aHi, 0xFFFF) + bit.band(total_3, 0xFFFF)
   total_6 = bit.rshift(total_5, 16) + bit.rshift(BThigh_aLo, 16) + bit.rshift(BTlow_aHi, 16) + total_4

   -- combine higher and lower 16 bits to complete the next highbyte/lowbyte
   lowbyte = bit.bor(bit.lshift(bit.band(total_2, 0xFFFF), 16), bit.band(total_1, 0xFFFF))
   highbyte = bit.bor(bit.lshift(total_6, 16), bit.band(total_5, 0xFFFF))

   return highbyte

end


-- getResult: calculate the percentage/healing value from the output
-- rand = BT output
-- ratio = 100 for percentage or 10 for heal/hoimi spell
function getResult(rand, ratio)

   result = rand / ((2 ^ 32) / ratio)

   if result < 0 then result = result + ratio end -- signed to unsigned

   if ratio == 100 then
      return result
   elseif ratio == 10 then
      return math.floor(result + 0.5) + 30 -- base hoimi = 30 (rounded to nearest whole number)
   end

end


-- getColour: set text and fill colours for each square on the table
function getColour(percentage, attribute)

   if attribute == "fill" then
      if percentage < 2 then colour = redFill
      elseif percentage < 10 then colour = blueFill
      else colour = "black"
      end

   elseif attribute == "text" then
      if percentage < 2 then colour = redText
      elseif percentage < 10 then colour = blueText
      else colour = "white"
      end

   end

   return colour

end


function main()

   -- Read face button input (low nibble)
   -- 7 = start button
   buttonInput = bit.band(memory.readbyte(0x04000130), 0xF)

   -- If start is pressed, the frame counter starts
   -- The input would have to be frame perfect otherwise(?)
   -- The toggle gets triggered when the counter hits 1
   if buttonInput == 7 then
      count = count + 1
      if count == 1 then toggle = not toggle end
   else
      count = 0
   end

   if toggle then

      -- ones = numbers on the top row
      -- tens = numbers on the leftmost column
      -- position = BT position 0-89
      ones, tens, position = -1, -10, 0

      -- Create squares/labels for the top row
      for x = 15, 231, 24 do
         ones = ones + 1
         gui.box(x, -192, x + 24, -181, indigoFill, greyStroke)
         gui.text(x+9, -189, ones, "white", "clear")
      end

      -- Create squares/labels for the leftmost column
      for y = -181, -21, 20 do
         tens = tens + 10
         if tens == 0 then tens = " " .. tens end
         gui.box(0, y, 15, y + 20, indigoFill, greyStroke)
         gui.text(2, y+7, tens, "white", "clear")
      end

      -- Create square for the top left corner
      gui.box(0, -192, 15, -181, indigoFill, greyStroke)


      highbyte = memory.readdword(0x02108D24) -- read the address for BT's highbyte (32 bits)
      lowbyte = memory.readdword(0x02108D20)  -- read the address for BT's lowbyte (32 bits)
      BT[1] = highbyte                        -- add the current highbyte value to the table as position 0
      BT[2] = bt_rand(highbyte, lowbyte)      -- calculate and add position 1 to the table

      for i = 3, 90 do BT[i] = bt_rand() end -- calculate and add positions 2-89 to the table

      -- Create the main table
      for y = -181, -21, 20 do  -- 9 rows

         for x = 15, 231, 24 do -- 10 columns

            position = position + 1

            percent = getResult(BT[position], 100)
            hoimi = getResult(BT[position], 10)

            int = string.format("%02d", percent) -- split up integer/decimals so they can fit in each box
            dec = string.format("%.2f", percent)
            text = getColour(percent, "text")

            gui.box(x, y, x+24, y+20, getColour(percent, "fill"), greyStroke)
            gui.text(x+3, y+3, int, text, "clear")
            gui.text(x+16, y+3, string.sub(dec, -2, -2), text, "clear")
            gui.pixel(x+15, y+9, text, "clear") -- the decimal point
            gui.text(x+3, y+11, hoimi, text, "clear")

         end

      end

      gui.box(16, -180, 38, -162, "clear", whiteStroke) -- position 0 outline
      gui.box(40, -180, 62, -162, "clear", redStroke)   -- position 1 outline
      gui.box(64, -180, 86, -162, "clear", blueStroke)  -- position 2 outline

   end

end

gui.register(main)