609 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Lua
		
	
	
	
			
		
		
	
	
			609 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Lua
		
	
	
	
| --Shamelessly based off the FF1 lua
 | |
| 
 | |
| local socket = require("socket")
 | |
| local json = require('json')
 | |
| local math = require('math')
 | |
| require("common")
 | |
| local STATE_OK = "Ok"
 | |
| local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
 | |
| local STATE_INITIAL_CONNECTION_MADE = "Initial Connection Made"
 | |
| local STATE_UNINITIALIZED = "Uninitialized"
 | |
| 
 | |
| local consumableStacks = nil
 | |
| local prevstate = ""
 | |
| local curstate =  STATE_UNINITIALIZED
 | |
| local zeldaSocket = nil
 | |
| local frame = 0
 | |
| local gameMode = 0
 | |
| 
 | |
| local cave_index
 | |
| local triforce_byte
 | |
| local game_state
 | |
| 
 | |
| local isNesHawk = false
 | |
| 
 | |
| local shopsChecked = {}
 | |
| local shopSlotLeft       = 0x0628
 | |
| local shopSlotMiddle     = 0x0629
 | |
| local shopSlotRight      = 0x062A
 | |
| 
 | |
| --N.B.: you won't find these in a RAM map. They're flag values that the base patch derives from the cave ID.
 | |
| local blueRingShopBit       = 0x40
 | |
| local potionShopBit         = 0x02
 | |
| local arrowShopBit          = 0x08
 | |
| local candleShopBit         = 0x10
 | |
| local shieldShopBit         = 0x20
 | |
| local takeAnyCaveBit        = 0x01
 | |
| 
 | |
| 
 | |
| local sword                 = 0x0657
 | |
| local bombs                 = 0x0658
 | |
| local maxBombs              = 0x067C
 | |
| local keys                  = 0x066E
 | |
| local arrow                 = 0x0659
 | |
| local bow                   = 0x065A
 | |
| local candle                = 0x065B
 | |
| local recorder              = 0x065C
 | |
| local food                  = 0x065D
 | |
| local waterOfLife           = 0x065E
 | |
| local magicalRod            = 0x065F
 | |
| local raft                  = 0x0660
 | |
| local bookOfMagic           = 0x0661
 | |
| local ring                  = 0x0662
 | |
| local stepladder            = 0x0663
 | |
| local magicalKey            = 0x0664
 | |
| local powerBracelet         = 0x0665
 | |
| local letter                = 0x0666
 | |
| local clockItem             = 0x066C
 | |
| local heartContainers       = 0x066F
 | |
| local partialHearts         = 0x0670
 | |
| local triforceFragments     = 0x0671
 | |
| local boomerang             = 0x0674
 | |
| local magicalBoomerang      = 0x0675
 | |
| local magicalShield         = 0x0676
 | |
| local rupeesToAdd           = 0x067D
 | |
| local rupeesToSubtract      = 0x067E
 | |
| local itemsObtained         = 0x0677
 | |
| local takeAnyCavesChecked   = 0x0678
 | |
| local localTriforce         = 0x0679
 | |
| local bonusItemsObtained    = 0x067A
 | |
| 
 | |
| itemAPids = {
 | |
|     ["Boomerang"] = 7100,
 | |
|     ["Bow"] = 7101,
 | |
|     ["Magical Boomerang"] = 7102,
 | |
|     ["Raft"] = 7103,
 | |
|     ["Stepladder"] = 7104,
 | |
|     ["Recorder"] = 7105,
 | |
|     ["Magical Rod"] = 7106,
 | |
|     ["Red Candle"] = 7107,
 | |
|     ["Book of Magic"] = 7108,
 | |
|     ["Magical Key"] = 7109,
 | |
|     ["Red Ring"] = 7110,
 | |
|     ["Silver Arrow"] = 7111,
 | |
|     ["Sword"] = 7112,
 | |
|     ["White Sword"] = 7113,
 | |
|     ["Magical Sword"] = 7114,
 | |
|     ["Heart Container"] = 7115,
 | |
|     ["Letter"] = 7116,
 | |
|     ["Magical Shield"] = 7117,
 | |
|     ["Candle"] = 7118,
 | |
|     ["Arrow"] = 7119,
 | |
|     ["Food"] = 7120,
 | |
|     ["Water of Life (Blue)"] = 7121,
 | |
|     ["Water of Life (Red)"] = 7122,
 | |
|     ["Blue Ring"] = 7123,
 | |
|     ["Triforce Fragment"] = 7124,
 | |
|     ["Power Bracelet"] = 7125,
 | |
|     ["Small Key"] = 7126,
 | |
|     ["Bomb"] = 7127,
 | |
|     ["Recovery Heart"] = 7128,
 | |
|     ["Five Rupees"] = 7129,
 | |
|     ["Rupee"] = 7130,
 | |
|     ["Clock"] = 7131,
 | |
|     ["Fairy"] = 7132
 | |
| }
 | |
| 
 | |
| itemCodes = {
 | |
|     ["Boomerang"] = 0x1D,
 | |
|     ["Bow"] = 0x0A,
 | |
|     ["Magical Boomerang"] = 0x1E,
 | |
|     ["Raft"] = 0x0C,
 | |
|     ["Stepladder"] = 0x0D,
 | |
|     ["Recorder"] = 0x05,
 | |
|     ["Magical Rod"] = 0x10,
 | |
|     ["Red Candle"] = 0x07,
 | |
|     ["Book of Magic"] = 0x11,
 | |
|     ["Magical Key"] = 0x0B,
 | |
|     ["Red Ring"] = 0x13,
 | |
|     ["Silver Arrow"] = 0x09,
 | |
|     ["Sword"] = 0x01,
 | |
|     ["White Sword"] = 0x02,
 | |
|     ["Magical Sword"] = 0x03,
 | |
|     ["Heart Container"] = 0x1A,
 | |
|     ["Letter"] = 0x15,
 | |
|     ["Magical Shield"] = 0x1C,
 | |
|     ["Candle"] = 0x06,
 | |
|     ["Arrow"] = 0x08,
 | |
|     ["Food"] = 0x04,
 | |
|     ["Water of Life (Blue)"] = 0x1F,
 | |
|     ["Water of Life (Red)"] = 0x20,
 | |
|     ["Blue Ring"] = 0x12,
 | |
|     ["Triforce Fragment"] = 0x1B,
 | |
|     ["Power Bracelet"] = 0x14,
 | |
|     ["Small Key"] = 0x19,
 | |
|     ["Bomb"] = 0x00,
 | |
|     ["Recovery Heart"] = 0x22,
 | |
|     ["Five Rupees"] = 0x0F,
 | |
|     ["Rupee"] = 0x18,
 | |
|     ["Clock"] = 0x21,
 | |
|     ["Fairy"] = 0x23
 | |
| }
 | |
| 
 | |
| 
 | |
| --Sets correct memory access functions based on whether NesHawk or QuickNES is loaded
 | |
| local function defineMemoryFunctions()
 | |
| 	local memDomain = {}
 | |
| 	local domains = memory.getmemorydomainlist()
 | |
| 	if domains[1] == "System Bus" then
 | |
| 		--NesHawk
 | |
| 		isNesHawk = true
 | |
| 		memDomain["systembus"] = function() memory.usememorydomain("System Bus") end
 | |
|         memDomain["ram"]       = function() memory.usememorydomain("RAM") end
 | |
| 		memDomain["saveram"]   = function() memory.usememorydomain("Battery RAM") end
 | |
| 		memDomain["rom"]       = function() memory.usememorydomain("PRG ROM") end
 | |
| 	elseif domains[1] == "WRAM" then
 | |
| 		--QuickNES
 | |
| 		memDomain["systembus"] = function() memory.usememorydomain("System Bus") end
 | |
|         memDomain["ram"]       = function() memory.usememorydomain("RAM") end
 | |
| 		memDomain["saveram"]   = function() memory.usememorydomain("WRAM") end
 | |
| 		memDomain["rom"]       = function() memory.usememorydomain("PRG ROM") end
 | |
| 	end
 | |
| 	return memDomain
 | |
| end
 | |
| 
 | |
| local memDomain = defineMemoryFunctions()
 | |
| u8 = memory.read_u8
 | |
| wU8 = memory.write_u8
 | |
| uRange = memory.readbyterange
 | |
| 
 | |
| itemIDNames = {}
 | |
| 
 | |
| for key, value in pairs(itemAPids) do
 | |
|     itemIDNames[value] = key
 | |
| end
 | |
| 
 | |
| 
 | |
| 
 | |
| local function determineItem(array)
 | |
|     memdomain.ram()
 | |
|     currentItemsObtained = u8(itemsObtained)
 | |
|     
 | |
| end
 | |
| 
 | |
| local function gotSword()
 | |
|     local currentSword = u8(sword)
 | |
|     wU8(sword, math.max(currentSword, 1))
 | |
| end
 | |
| 
 | |
| local function gotWhiteSword()
 | |
|     local currentSword = u8(sword)
 | |
|     wU8(sword, math.max(currentSword, 2))
 | |
| end
 | |
| 
 | |
| local function gotMagicalSword()
 | |
|     wU8(sword, 3)
 | |
| end
 | |
| 
 | |
| local function gotBomb()
 | |
|     local currentBombs = u8(bombs)
 | |
|     local currentMaxBombs = u8(maxBombs)
 | |
|     wU8(bombs, math.min(currentBombs + 4, currentMaxBombs))
 | |
|     wU8(0x505, 0x29) -- Fake bomb to show item get.
 | |
| end
 | |
| 
 | |
| local function gotArrow()
 | |
|     local currentArrow = u8(arrow)
 | |
|     wU8(arrow, math.max(currentArrow, 1))
 | |
| end
 | |
| 
 | |
| local function gotSilverArrow()
 | |
|     wU8(arrow, 2)
 | |
| end
 | |
| 
 | |
| local function gotBow()
 | |
|     wU8(bow, 1)
 | |
| end
 | |
| 
 | |
| local function gotCandle()
 | |
|     local currentCandle = u8(candle)
 | |
|     wU8(candle, math.max(currentCandle, 1))
 | |
| end
 | |
| 
 | |
| local function gotRedCandle()
 | |
|     wU8(candle, 2)
 | |
| end
 | |
| 
 | |
| local function gotRecorder()
 | |
|     wU8(recorder, 1)
 | |
| end
 | |
| 
 | |
| local function gotFood()
 | |
|     wU8(food, 1)
 | |
| end
 | |
| 
 | |
| local function gotWaterOfLifeBlue()
 | |
|     local currentWaterOfLife = u8(waterOfLife)
 | |
|     wU8(waterOfLife, math.max(currentWaterOfLife, 1))
 | |
| end
 | |
| 
 | |
| local function gotWaterOfLifeRed()
 | |
|     wU8(waterOfLife, 2)
 | |
| end
 | |
| 
 | |
| local function gotMagicalRod()
 | |
|     wU8(magicalRod, 1)
 | |
| end
 | |
| 
 | |
| local function gotBookOfMagic()
 | |
|     wU8(bookOfMagic, 1)
 | |
| end
 | |
| 
 | |
| local function gotRaft()
 | |
|     wU8(raft, 1)
 | |
| end
 | |
| 
 | |
| local function gotBlueRing()
 | |
|     local currentRing = u8(ring)
 | |
|     wU8(ring, math.max(currentRing, 1))
 | |
|     memDomain.saveram()
 | |
|     local currentTunicColor = u8(0x0B92)
 | |
|     if currentTunicColor == 0x29 then 
 | |
|         wU8(0x0B92, 0x32)
 | |
|         wU8(0x0804, 0x32)
 | |
|     end
 | |
| end
 | |
| 
 | |
| local function gotRedRing()
 | |
|     wU8(ring, 2)
 | |
|     memDomain.saveram()
 | |
|     wU8(0x0B92, 0x16)
 | |
|     wU8(0x0804, 0x16)
 | |
| end
 | |
| 
 | |
| local function gotStepladder()
 | |
|     wU8(stepladder, 1)
 | |
| end
 | |
| 
 | |
| local function gotMagicalKey()
 | |
|     wU8(magicalKey, 1)
 | |
| end
 | |
| 
 | |
| local function gotPowerBracelet()
 | |
|     wU8(powerBracelet, 1)
 | |
| end
 | |
| 
 | |
| local function gotLetter()
 | |
|     wU8(letter, 1)
 | |
| end
 | |
| 
 | |
| local function gotHeartContainer()
 | |
|     local currentHeartContainers = bit.rshift(bit.band(u8(heartContainers), 0xF0), 4)
 | |
|     if currentHeartContainers < 16 then
 | |
|         currentHeartContainers = math.min(currentHeartContainers + 1, 16)
 | |
|         local currentHearts = bit.band(u8(heartContainers), 0x0F) + 1
 | |
|         wU8(heartContainers, bit.lshift(currentHeartContainers, 4) + currentHearts)
 | |
|     end
 | |
| end
 | |
| 
 | |
| local function gotTriforceFragment()
 | |
|     local triforceByte = 0xFF
 | |
|     local newTriforceCount = u8(localTriforce) + 1
 | |
|     wU8(localTriforce, newTriforceCount)
 | |
| end
 | |
| 
 | |
| local function gotBoomerang()
 | |
|     wU8(boomerang, 1)
 | |
| end
 | |
| 
 | |
| local function gotMagicalBoomerang()
 | |
|     wU8(magicalBoomerang, 1)
 | |
| end
 | |
| 
 | |
| local function gotMagicalShield()
 | |
|     wU8(magicalShield, 1)
 | |
| end
 | |
| 
 | |
| local function gotRecoveryHeart()
 | |
|     local currentHearts = bit.band(u8(heartContainers), 0x0F)
 | |
|     local currentHeartContainers = bit.rshift(bit.band(u8(heartContainers), 0xF0), 4)
 | |
|     if currentHearts < currentHeartContainers then 
 | |
|         currentHearts = currentHearts + 1 
 | |
|     else
 | |
|         wU8(partialHearts, 0xFF)
 | |
|     end
 | |
|     currentHearts = bit.bor(bit.band(u8(heartContainers), 0xF0), currentHearts)
 | |
|     wU8(heartContainers, currentHearts)
 | |
| end
 | |
| 
 | |
| local function gotFairy()
 | |
|     local currentHearts = bit.band(u8(heartContainers), 0x0F)
 | |
|     local currentHeartContainers = bit.rshift(bit.band(u8(heartContainers), 0xF0), 4)
 | |
|     if currentHearts < currentHeartContainers then 
 | |
|         currentHearts = currentHearts + 3
 | |
|         if currentHearts > currentHeartContainers then
 | |
|             currentHearts = currentHeartContainers
 | |
|             wU8(partialHearts, 0xFF)
 | |
|         end
 | |
|     else
 | |
|         wU8(partialHearts, 0xFF)
 | |
|     end
 | |
|     currentHearts = bit.bor(bit.band(u8(heartContainers), 0xF0), currentHearts)
 | |
|     wU8(heartContainers, currentHearts)
 | |
| end
 | |
| 
 | |
| local function gotClock()
 | |
|     wU8(clockItem, 1)
 | |
| end
 | |
| 
 | |
| local function gotFiveRupees()
 | |
|     local currentRupeesToAdd = u8(rupeesToAdd)
 | |
|     wU8(rupeesToAdd, math.min(currentRupeesToAdd + 5, 255))
 | |
| end
 | |
| 
 | |
| local function gotSmallKey()
 | |
|     wU8(keys, math.min(u8(keys) + 1, 9))
 | |
| end
 | |
| 
 | |
| local function gotItem(item)
 | |
|     --Write itemCode to itemToLift
 | |
|     --Write 128 to itemLiftTimer
 | |
|     --Write 4 to sound effect queue
 | |
|     itemName = itemIDNames[item]
 | |
|     itemCode = itemCodes[itemName]
 | |
|     wU8(0x505, itemCode)
 | |
|     wU8(0x506, 128)
 | |
|     wU8(0x602, 4)
 | |
|     numberObtained = u8(itemsObtained) + 1
 | |
|     wU8(itemsObtained, numberObtained)
 | |
|     if itemName == "Boomerang" then gotBoomerang() end
 | |
|     if itemName == "Bow" then gotBow() end
 | |
|     if itemName == "Magical Boomerang" then gotMagicalBoomerang() end
 | |
|     if itemName == "Raft" then gotRaft() end
 | |
|     if itemName == "Stepladder" then gotStepladder() end
 | |
|     if itemName == "Recorder" then gotRecorder() end
 | |
|     if itemName == "Magical Rod" then gotMagicalRod() end
 | |
|     if itemName == "Red Candle" then gotRedCandle() end
 | |
|     if itemName == "Book of Magic" then gotBookOfMagic() end
 | |
|     if itemName == "Magical Key" then gotMagicalKey() end
 | |
|     if itemName == "Red Ring" then gotRedRing() end
 | |
|     if itemName == "Silver Arrow" then gotSilverArrow() end
 | |
|     if itemName == "Sword" then gotSword() end
 | |
|     if itemName == "White Sword" then gotWhiteSword() end
 | |
|     if itemName == "Magical Sword" then gotMagicalSword() end
 | |
|     if itemName == "Heart Container" then gotHeartContainer() end
 | |
|     if itemName == "Letter" then gotLetter() end
 | |
|     if itemName == "Magical Shield" then gotMagicalShield() end
 | |
|     if itemName == "Candle" then gotCandle() end
 | |
|     if itemName == "Arrow" then gotArrow() end
 | |
|     if itemName == "Food" then gotFood() end
 | |
|     if itemName == "Water of Life (Blue)" then gotWaterOfLifeBlue() end
 | |
|     if itemName == "Water of Life (Red)" then gotWaterOfLifeRed() end
 | |
|     if itemName == "Blue Ring" then gotBlueRing() end
 | |
|     if itemName == "Triforce Fragment" then gotTriforceFragment() end
 | |
|     if itemName == "Power Bracelet" then gotPowerBracelet() end
 | |
|     if itemName == "Small Key" then gotSmallKey() end
 | |
|     if itemName == "Bomb" then gotBomb() end
 | |
|     if itemName == "Recovery Heart" then gotRecoveryHeart() end
 | |
|     if itemName == "Five Rupees" then gotFiveRupees() end
 | |
|     if itemName == "Fairy" then gotFairy() end
 | |
|     if itemName == "Clock" then gotClock() end
 | |
| end
 | |
| 
 | |
| 
 | |
| local function StateOKForMainLoop()
 | |
|     memDomain.ram()
 | |
|     local gameMode = u8(0x12) 
 | |
|     return gameMode == 5 
 | |
| end
 | |
| 
 | |
| local function checkCaveItemObtained()
 | |
|     memDomain.ram() 
 | |
|     local returnTable = {}
 | |
|     returnTable["slot1"] = u8(shopSlotLeft)
 | |
|     returnTable["slot2"] = u8(shopSlotMiddle)
 | |
|     returnTable["slot3"] = u8(shopSlotRight)
 | |
|     returnTable["takeAnys"] = u8(takeAnyCavesChecked)
 | |
|     return returnTable
 | |
| end
 | |
| 
 | |
| function generateOverworldLocationChecked()
 | |
|     memDomain.ram()
 | |
|     data = uRange(0x067E, 0x81)
 | |
|     data[0] = nil
 | |
|     return data
 | |
| end
 | |
| 
 | |
| function getHCLocation()
 | |
|     memDomain.rom()
 | |
|     data = u8(0x1789A)
 | |
|     return data
 | |
| end
 | |
| 
 | |
| function getPBLocation()
 | |
|     memDomain.rom()
 | |
|     data = u8(0x10CB2)
 | |
|     return data
 | |
| end
 | |
| 
 | |
| function generateUnderworld16LocationChecked()
 | |
|     memDomain.ram()
 | |
|     data = uRange(0x06FE, 0x81)
 | |
|     data[0] = nil
 | |
|     return data
 | |
| end
 | |
| 
 | |
| function generateUnderworld79LocationChecked()
 | |
|     memDomain.ram()
 | |
|     data = uRange(0x077E, 0x81)
 | |
|     data[0] = nil
 | |
|     return data
 | |
| end
 | |
| 
 | |
| function updateTriforceFragments()
 | |
|     memDomain.ram()
 | |
|     local triforceByte = 0xFF
 | |
|     totalTriforceCount = u8(localTriforce)
 | |
|     local currentPieces = bit.rshift(triforceByte, 8 - math.min(8, totalTriforceCount))
 | |
|     wU8(triforceFragments, currentPieces)
 | |
| end
 | |
| 
 | |
| function processBlock(block)
 | |
|     if block ~= nil then
 | |
|         local msgBlock = block['messages']
 | |
|         if msgBlock ~= nil then
 | |
|             for i, v in pairs(msgBlock) do
 | |
|                 if itemMessages[i] == nil then
 | |
|                     local msg = {TTL=450, message=v, color=0xFFFF0000}
 | |
|                     itemMessages[i] = msg
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
|         local bonusItems = block["bonusItems"]
 | |
|         if bonusItems ~= nil and isInGame then
 | |
|             for i, item in ipairs(bonusItems) do
 | |
|                 memDomain.ram()
 | |
|                 if i > u8(bonusItemsObtained) then
 | |
|                     if u8(0x505) == 0 then
 | |
|                         gotItem(item)
 | |
|                         wU8(itemsObtained, u8(itemsObtained) - 1)
 | |
|                         wU8(bonusItemsObtained, u8(bonusItemsObtained) + 1)
 | |
|                     end
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
|         local itemsBlock = block["items"]
 | |
|         memDomain.saveram()
 | |
|         isInGame = StateOKForMainLoop()
 | |
|         updateTriforceFragments()
 | |
|         if itemsBlock ~= nil and isInGame then
 | |
|             memDomain.ram()
 | |
|             --get item from item code
 | |
|             --get function from item
 | |
|             --do function
 | |
|             for i, item in ipairs(itemsBlock) do
 | |
|                 memDomain.ram()
 | |
|                 if u8(0x505) == 0 then
 | |
|                     if i > u8(itemsObtained) then
 | |
|                         gotItem(item)
 | |
|                     end
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
|         local shopsBlock = block["shops"]
 | |
|         if shopsBlock ~= nil then
 | |
|             wU8(shopSlotLeft, bit.bor(u8(shopSlotLeft), shopsBlock["left"]))
 | |
|             wU8(shopSlotMiddle, bit.bor(u8(shopSlotMiddle), shopsBlock["middle"]))
 | |
|             wU8(shopSlotRight, bit.bor(u8(shopSlotRight), shopsBlock["right"]))
 | |
|         end
 | |
|     end
 | |
| end
 | |
| 
 | |
| function receive()
 | |
|     l, e = zeldaSocket:receive()
 | |
|     if e == 'closed' then
 | |
|         if curstate == STATE_OK then
 | |
|             print("Connection closed")
 | |
|         end
 | |
|         curstate = STATE_UNINITIALIZED
 | |
|         return
 | |
|     elseif e == 'timeout' then
 | |
|         print("timeout")
 | |
|         return
 | |
|     elseif e ~= nil then
 | |
|         print(e)
 | |
|         curstate = STATE_UNINITIALIZED
 | |
|         return
 | |
|     end
 | |
|     processBlock(json.decode(l))
 | |
| 
 | |
|     -- Determine Message to send back
 | |
|     memDomain.rom()
 | |
|     local playerName = uRange(0x1F, 0x11)
 | |
|     playerName[0] = nil
 | |
|     local retTable = {}
 | |
|     retTable["playerName"] = playerName
 | |
|     if StateOKForMainLoop() then
 | |
|         retTable["overworld"] = generateOverworldLocationChecked()
 | |
|         retTable["underworld1"] = generateUnderworld16LocationChecked()
 | |
|         retTable["underworld2"] = generateUnderworld79LocationChecked()
 | |
|     end
 | |
|     retTable["caves"] = checkCaveItemObtained()
 | |
|     memDomain.ram()
 | |
|     if gameMode ~= 19 then
 | |
|         gameMode = u8(0x12)
 | |
|     end
 | |
|     retTable["gameMode"] = gameMode
 | |
|     retTable["overworldHC"] = getHCLocation()
 | |
|     retTable["overworldPB"] = getPBLocation()
 | |
|     retTable["itemsObtained"] = u8(itemsObtained)
 | |
|     msg = json.encode(retTable).."\n"
 | |
|     local ret, error = zeldaSocket:send(msg)
 | |
|     if ret == nil then
 | |
|         print(error)
 | |
|     elseif curstate == STATE_INITIAL_CONNECTION_MADE then
 | |
|         curstate = STATE_TENTATIVELY_CONNECTED
 | |
|     elseif curstate == STATE_TENTATIVELY_CONNECTED then
 | |
|         print("Connected!")
 | |
|         itemMessages["(0,0)"] = {TTL=240, message="Connected", color="green"}
 | |
|         curstate = STATE_OK
 | |
|     end
 | |
| end
 | |
| 
 | |
| function main()
 | |
|     if not checkBizHawkVersion() then
 | |
|         return
 | |
|     end
 | |
|     server, error = socket.bind('localhost', 52980)
 | |
| 
 | |
|     while true do
 | |
|         gui.drawEllipse(248, 9, 6, 6, "Black", "Yellow")
 | |
|         frame = frame + 1
 | |
|         drawMessages()
 | |
|         if not (curstate == prevstate) then
 | |
|             -- console.log("Current state: "..curstate)
 | |
|             prevstate = curstate
 | |
|         end
 | |
|         if (curstate == STATE_OK) or (curstate == STATE_INITIAL_CONNECTION_MADE) or (curstate == STATE_TENTATIVELY_CONNECTED) then
 | |
|             if (frame % 60 == 0) then
 | |
|                 gui.drawEllipse(248, 9, 6, 6, "Black", "Blue")
 | |
|                 receive()
 | |
|             else
 | |
|                 gui.drawEllipse(248, 9, 6, 6, "Black", "Green")
 | |
|             end
 | |
|         elseif (curstate == STATE_UNINITIALIZED) then
 | |
|             gui.drawEllipse(248, 9, 6, 6, "Black", "White")
 | |
|             if  (frame % 60 == 0) then
 | |
|                 gui.drawEllipse(248, 9, 6, 6, "Black", "Yellow")
 | |
| 
 | |
|                 drawText(5, 8, "Waiting for client", 0xFFFF0000)
 | |
|                 drawText(5, 32, "Please start Zelda1Client.exe", 0xFFFF0000)
 | |
| 
 | |
|                 -- Advance so the messages are drawn
 | |
|                 emu.frameadvance()
 | |
|                 server:settimeout(2)
 | |
|                 print("Attempting to connect")
 | |
|                 local client, timeout = server:accept()
 | |
|                 if timeout == nil then
 | |
|                     -- print('Initial Connection Made')
 | |
|                     curstate = STATE_INITIAL_CONNECTION_MADE
 | |
|                     zeldaSocket = client
 | |
|                     zeldaSocket:settimeout(0)
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
|         emu.frameadvance()
 | |
|     end
 | |
| end
 | |
| 
 | |
| main() |