Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Custom Bit Library for ComputerCraft
- local bit = {}
- function bit.band(a, b)
- local result = 0
- local bitval = 1
- while a > 0 and b > 0 do
- if a % 2 == 1 and b % 2 == 1 then result = result + bitval end
- bitval = bitval * 2
- a = math.floor(a / 2)
- b = math.floor(b / 2)
- end
- return result
- end
- function bit.bor(a, b)
- local result = 0
- local bitval = 1
- while a > 0 or b > 0 do
- if a % 2 == 1 or b % 2 == 1 then result = result + bitval end
- bitval = bitval * 2
- a = math.floor(a / 2)
- b = math.floor(b / 2)
- end
- return result
- end
- function bit.bxor(a, b)
- local result = 0
- local bitval = 1
- while a > 0 or b > 0 do
- if a % 2 ~= b % 2 then result = result + bitval end
- bitval = bitval * 2
- a = math.floor(a / 2)
- b = math.floor(b / 2)
- end
- return result
- end
- function bit.bnot(n)
- return (-n) - 1
- end
- function bit.blshift(n, bits)
- return n * (2 ^ bits)
- end
- function bit.brshift(n, bits)
- return math.floor(n / (2 ^ bits))
- end
- function bit.blogic_rshift(n, bits)
- if n >= 0 then
- return bit.brshift(n, bits)
- else
- return bit.brshift((n + 0x100000000), bits)
- end
- end
- -- Z-machine implementation
- local memory = {}
- local pc = 1
- local stack = {}
- local sp = 1
- local locals = {}
- local globals = {}
- local version = 0
- -- Initialize memory
- for i = 1, 65536 do
- memory[i] = 0
- end
- -- Helper functions
- local function readByte(addr)
- return memory[addr]
- end
- local function readWord(addr)
- return (memory[addr] * 256) + memory[addr + 1]
- end
- local function writeByte(addr, value)
- memory[addr] = value % 256
- end
- local function writeWord(addr, value)
- memory[addr] = math.floor(value / 256)
- memory[addr + 1] = value % 256
- end
- local function pushStack(value)
- stack[sp] = value
- sp = sp + 1
- end
- local function popStack()
- sp = sp - 1
- return stack[sp]
- end
- -- ZSCII decoding (simplified)
- local function decodeZSCII(addr)
- local result = ""
- local i = addr
- while true do
- local word = readWord(i)
- for j = 1, 3 do
- local char = bit.band(bit.brshift(word, (3-j)*5), 0x1F)
- if char ~= 0 then
- result = result .. string.char(char + 96)
- end
- end
- if bit.band(word, 0x8000) ~= 0 then break end
- i = i + 2
- end
- return result
- end
- -- Operand types
- local OP_LARGE = 0
- local OP_SMALL = 1
- local OP_VAR = 2
- local OP_OMITTED = 3
- -- Fetch and decode operands
- local function fetchOperands(opcode)
- local operandTypes = {}
- local operands = {}
- if opcode < 0x80 then -- 2OP
- operandTypes[1] = bit.band(bit.brshift(opcode, 6), 0x03)
- operandTypes[2] = bit.band(bit.brshift(opcode, 4), 0x03)
- elseif opcode < 0xB0 then -- 1OP
- operandTypes[1] = bit.band(bit.brshift(opcode, 4), 0x03)
- elseif opcode < 0xC0 then -- 0OP
- -- No operands
- else -- VAR
- local specifier = readByte(pc)
- pc = pc + 1
- for i = 1, 4 do
- local type = bit.band(bit.brshift(specifier, (4-i)*2), 0x03)
- if type ~= OP_OMITTED then
- table.insert(operandTypes, type)
- end
- end
- end
- for _, type in ipairs(operandTypes) do
- if type == OP_LARGE then
- table.insert(operands, readWord(pc))
- pc = pc + 2
- elseif type == OP_SMALL then
- table.insert(operands, readByte(pc))
- pc = pc + 1
- elseif type == OP_VAR then
- local var = readByte(pc)
- pc = pc + 1
- if var == 0 then
- table.insert(operands, popStack())
- elseif var < 16 then
- table.insert(operands, locals[var])
- else
- table.insert(operands, globals[var - 16])
- end
- end
- end
- return operands
- end
- -- Opcode implementations
- local opcodes = {
- [0x00] = function() return 1 end, -- RTRUE
- [0x01] = function() return 0 end, -- RFALSE
- [0x02] = function(value) return value end, -- PRINT
- [0x03] = function(value) print(value) return 1 end, -- PRINT_RET
- [0x04] = function() end, -- NOP
- [0x05] = function(a) -- SAVE
- local result = saveGame("z_save.dat")
- if version <= 3 then
- pc = a
- return result and 1 or 0
- else
- return result and 1 or 0
- end
- end,
- [0x06] = function(a) -- RESTORE
- local result = restoreGame("z_save.dat")
- if version <= 3 then
- pc = a
- return result and 2 or 0
- else
- return result and 2 or 0
- end
- end,
- [0x07] = function() pc = 1 end, -- RESTART
- [0x08] = function() return popStack() end, -- RET_POPPED
- [0x09] = function() popStack() end, -- POP
- [0x0A] = function() error("QUIT instruction executed") end, -- QUIT
- [0x0B] = function() print() end, -- NEW_LINE
- [0x0C] = function(a) return a end, -- SHOW_STATUS
- [0x0D] = function(a) return a end, -- VERIFY
- [0x0E] = function() -- EXTENDED
- local opcode = readByte(pc)
- pc = pc + 1
- -- Implement extended opcodes here
- end,
- [0x0F] = function(a) -- PIRACY
- if version <= 3 then pc = a end
- return 0
- end,
- -- Add more opcodes here
- [0x80] = function(a, b) if a == b then return 1 else return 0 end end, -- JE
- [0x81] = function(a, b) if a ~= b then return 1 else return 0 end end, -- JL
- [0x82] = function(a, b) if a < b then return 1 else return 0 end end, -- JG
- [0x83] = function(a, b) if a >= b then return 1 else return 0 end end, -- DEC_CHK
- [0x84] = function(a, b) if a <= b then return 1 else return 0 end end, -- INC_CHK
- [0x85] = function(a, b) if a > b then return 1 else return 0 end end, -- JIN
- [0x86] = function(a, b) return math.random(a, b) end, -- TEST
- [0x87] = function(a, b) return bit.bor(a, b) end, -- OR
- [0x88] = function(a, b) return bit.band(a, b) end, -- AND
- [0x89] = function(a, b) if bit.band(a, b) ~= 0 then return 1 else return 0 end end, -- TEST_ATTR
- -- Add more opcodes as needed
- }
- -- Main execution loop
- local function execute()
- while true do
- local opcode = readByte(pc)
- pc = pc + 1
- local operands = fetchOperands(opcode)
- if opcode == 0x0E then -- EXTENDED opcode
- opcode = readByte(pc)
- pc = pc + 1
- operands = fetchOperands(opcode)
- -- Handle extended opcodes here
- end
- if opcodes[opcode] then
- local result = opcodes[opcode](table.unpack(operands))
- if result ~= nil then
- return result
- end
- else
- error("Unknown opcode: " .. opcode)
- end
- end
- end
- -- Load game file
- local function loadGame(filename)
- local file = fs.open(filename, "rb")
- if not file then
- error("Could not open file: " .. filename)
- end
- local content = file.readAll()
- file.close()
- for i = 1, #content do
- memory[i] = string.byte(content, i)
- end
- version = memory[0]
- pc = readWord(0x06)
- end
- -- Save game state
- local function saveGame(filename)
- local file = fs.open(filename, "w")
- if not file then
- return false
- end
- file.write(textutils.serialize(memory))
- file.write(textutils.serialize(stack))
- local state = {
- pc = pc,
- sp = sp,
- locals = locals,
- globals = globals,
- version = version
- }
- file.write(textutils.serialize(state))
- file.close()
- return true
- end
- -- Restore game state
- local function restoreGame(filename)
- local file = fs.open(filename, "r")
- if not file then
- return false
- end
- memory = textutils.unserialize(file.readLine())
- stack = textutils.unserialize(file.readLine())
- local state = textutils.unserialize(file.readLine())
- pc = state.pc
- sp = state.sp
- locals = state.locals
- globals = state.globals
- version = state.version
- file.close()
- return true
- end
- -- Download Zork 3
- local function downloadZork3()
- local url = "https://eblong.com/infocom/gamefiles/zork3-r16-s830410.z3"
- local response = http.get(url)
- if response then
- local content = response.readAll()
- response.close()
- local file = fs.open("zork3.z3", "wb")
- file.write(content)
- file.close()
- return true
- else
- return false
- end
- end
- -- GUI
- local function drawGUI()
- term.clear()
- term.setCursorPos(1, 1)
- term.write("Advanced Z-machine for ComputerCraft")
- term.setCursorPos(1, 3)
- term.write("1. Download Zork 3")
- term.setCursorPos(1, 4)
- term.write("2. Play Zork 3")
- term.setCursorPos(1, 5)
- term.write("3. Exit")
- end
- -- Main function
- local function main()
- while true do
- drawGUI()
- term.setCursorPos(1, 7)
- term.write("Enter your choice: ")
- local choice = read()
- if choice == "1" then
- term.setCursorPos(1, 9)
- term.write("Downloading Zork 3...")
- if downloadZork3() then
- term.setCursorPos(1, 10)
- term.write("Download complete!")
- else
- term.setCursorPos(1, 10)
- term.write("Download failed.")
- end
- os.sleep(2)
- elseif choice == "2" then
- if fs.exists("zork3.z3") then
- term.clear()
- term.setCursorPos(1, 1)
- loadGame("zork3.z3")
- local result = execute()
- term.setCursorPos(1, 23)
- term.write("Game finished with result: " .. result)
- term.setCursorPos(1, 24)
- term.write("Press any key to continue...")
- os.pullEvent("key")
- else
- term.setCursorPos(1, 9)
- term.write("Zork 3 not found. Please download it first.")
- os.sleep(2)
- end
- elseif choice == "3" then
- term.clear()
- term.setCursorPos(1, 1)
- term.write("Goodbye!")
- break
- else
- term.setCursorPos(1, 9)
- term.write("Invalid choice. Please try again.")
- os.sleep(2)
- end
- end
- end
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement