diff --git a/mess/tmpc.lua b/mess/tmpc.lua index 689c7e2..16906a8 100644 --- a/mess/tmpc.lua +++ b/mess/tmpc.lua @@ -27,6 +27,54 @@ settings.define("mplayer.colors.status", { default = 0x80EF80, -- #80EF80 type = number }) +local drive = peripheral.find("disk_drive") +if not drive then + printError("No drive found, starting in dummy mode") + local fp = io.open("noita.dfpwm", "rb") + if fp == nil then + printError("No sample file found, are you running it on a real* computer without a tape drive?") + return + end + local size = fp:seek("end", 0) + fp:seek("set", 0) + drive = { + _pos = 0, + _fp = fp, + _state = "STOPPED", + seek = function(howMuch) + drive._pos = math.min(drive.getSize(), math.max(0, drive._pos + howMuch)) + end, + getPosition = function() + return drive._pos + end, + read = function(n) + local out = { drive._fp:read(n) } + drive.seek(n or 1) + return table.unpack(out) + end, + getSize = function() + return size + end, + getState = function() + return drive._state + end, + play = function() + drive._state = "PLAYING" + end, + stop = function() + drive._state = "STOPPED" + end, + isReady = function() + return true + end, + _tick = function() + if drive._state == "PLAYING" then + drive.read(600) + end + end, + } + os.sleep(1) +end local function time2str(ti) ti = math.floor(ti) @@ -34,36 +82,15 @@ local function time2str(ti) return string.format("%02d:%02d", m, s) end -local function read32(fp) +local function read32() local v = 0 for i = 1, 4 do - local b = string.byte(fp:read(1), 1) + local b = string.byte(drive.read(1), 1) v = bit32.bor(bit32.lshift(v, 8), b) end return v end -local drive = peripheral.find("disk_drive") -if not drive then - printError("No drive found, starting in dummy mode") - drive = { - _pos = 0, - seek = function(howMuch) - drive._pos = math.min(drive.getSize(), math.max(0, drive._pos + howMuch)) - end, - getPosition = function() - return drive._pos - end, - getSize = function() - return 360000 * 64 - end, - _tick = function() - drive._pos = drive._pos + 600 - end - } - os.sleep(1) -end - local help = {} for line in ([[# Movement: @@ -198,6 +225,7 @@ local mplayer = { elseif key == keys.enter then drive.seek(-drive.getSize()) drive.seek(self.songs[self.screens[2].cursor].offset) + drive.play() self.currentSong = self.screens[2].cursor end end, @@ -263,21 +291,6 @@ local function setupTerminal() term.clear() end -local fp = io.open("noita.dfpwm", "rb") -if fp ~= nil then - for i = 1, 24 do - local offset = read32(fp) - local length = read32(fp) - local title = fp:read(117) - local zero = math.min(64, title:find("\x00") or 0) - title = title:sub(1, zero) - if length > 0 and offset > 0 then - mplayer.songs[i] = { offset = offset, length = length, title = title } - end - end - fp:close() -end - setupTerminal() local tw, th = term.getSize() @@ -309,31 +322,34 @@ function() -- Statusline term.setCursorPos(1, th) term.clearLine() - term.setTextColor(mplayer.colors.status) - term.write("Playing: ") -- 9 characters - -- Progressbar - local lw = math.floor(tw * time / duration) - term.setCursorPos(1, th - 1) - term.setTextColor(mplayer.colors.current) - term.clearLine() - term.write(string.rep("=", lw)) - term.write(">") - term.setTextColor(mplayer.colors.cursor) - term.write(string.rep("-", tw - lw - 1)) - - -- Statusline text - term.setCursorPos(10, th) local timeString = string.format("[%s:%s]", time2str(time), time2str(duration)) - local w = tw - #timeString - 10 -- "Playing: " plus extra space + if drive.getState() == "PLAYING" then + term.setTextColor(mplayer.colors.status) + term.write("Playing: ") -- 9 characters - term.setTextColor(mplayer.colors.current) - if #title <= w then - term.write(title) - else - local off = (mplayer.statusLineScroll % (#title + 5)) + 1 - local txt = title .. " ::: " .. title - term.write(txt:sub(off, off + w - 1)) + -- Progressbar + local lw = math.floor(tw * time / duration) + term.setCursorPos(1, th - 1) + term.setTextColor(mplayer.colors.current) + term.clearLine() + term.write(string.rep("=", lw)) + term.write(">") + term.setTextColor(mplayer.colors.cursor) + term.write(string.rep("-", tw - lw - 1)) + + -- Statusline text + term.setCursorPos(10, th) + local w = tw - #timeString - 10 -- "Playing: " plus extra space + + term.setTextColor(mplayer.colors.current) + if #title <= w then + term.write(title) + else + local off = (mplayer.statusLineScroll % (#title + 5)) + 1 + local txt = title .. " ::: " .. title + term.write(txt:sub(off, off + w - 1)) + end end term.setTextColor(mplayer.colors.status) term.setCursorPos(tw - #timeString + 1, th) @@ -396,6 +412,24 @@ function() end elseif ev == "term_resize" then tw, th = term.getSize() + elseif ev == "tape_removed" then + mplayer.songs = {} + elseif ev == "tape_inserted" then + drive.stop() + drive.seek(-drive.getSize()) + for i = 1, 48 do + local offset = read32() + local length = read32() + local title = drive.read(117) + title = title:sub(1, title:find("\x00")) + if length > 0 and offset > 0 then + mplayer.songs[i] = { + title = title, + offset = offset, + length = length + } + end + end elseif ev ~= "timer" then local m = term.redirect(peripheral.wrap("right")) io.write(ev .. " ") @@ -413,19 +447,36 @@ function() end, function() local oldSong = nil + local oldDriveState = nil + local oldTapeState = nil while true do mplayer.currentSong = 0 - if drive._tick then drive._tick() end + if drive._tick then drive._tick() end -- dummy mode + + local tapeState = drive.isReady() + if tapeState ~= oldTapeState then + os.queueEvent(tapeState and "tape_inserted" or "tape_removed") + oldTapeState = tapeState + end + + local driveState = drive.getState() + if driveState ~= oldDriveState then + os.queueEvent("drive_state", driveState) + oldDriveState = driveState + end + local pos = drive.getPosition() for i, song in ipairs(mplayer.songs) do if pos >= song.offset and pos < (song.offset + song.length) then mplayer.currentSong = i end end + if oldSong ~= mplayer.currentSong then os.queueEvent("song_change") oldSong = mplayer.currentSong end + os.sleep(0.1) end end