singe/assets/Menu.singe
2023-10-23 19:38:18 -05:00

361 lines
8.7 KiB
Text

--[[
*
* Singe 2
* Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
--]]
dofile("Singe/Framework.singe")
lfs = require("lfs")
function compareTitles(a, b)
return a.TITLE < b.TITLE
end
function loadGameAssets(firstGame)
if not firstGame then
spriteUnload(SPRITE_CABINET)
spriteUnload(SPRITE_MARQUEE)
videoUnload(VIDEO_ATTRACT)
for _, handle in ipairs(TEXT_SPRITE_LIST) do
if handle >= 0 then
spriteUnload(handle)
end
end
TEXT_SPRITE_LIST = {}
end
SPRITE_CABINET = spriteLoad(GAME_LIST[GAME_SELECTED].CABINET)
SPRITE_MARQUEE = spriteLoad(GAME_LIST[GAME_SELECTED].MARQUEE)
VIDEO_ATTRACT = videoLoad(GAME_LIST[GAME_SELECTED].ATTRACT)
videoPlay(VIDEO_ATTRACT)
videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START)
videoSetVolume(VIDEO_ATTRACT, 0, 0)
-- Build text sprites
local textBox = GAME_LIST[GAME_SELECTED].DESCRIPTION .. WRAP_BREAK .. WRAP_BREAK ..
"Year: " .. GAME_LIST[GAME_SELECTED].YEAR .. WRAP_BREAK ..
"Genre: " .. GAME_LIST[GAME_SELECTED].GENRE .. WRAP_BREAK ..
"Platform: " .. GAME_LIST[GAME_SELECTED].PLATFORM .. WRAP_BREAK ..
"Developer: " .. GAME_LIST[GAME_SELECTED].DEVELOPER .. WRAP_BREAK ..
"Publisher: " .. GAME_LIST[GAME_SELECTED].PUBLISHER .. WRAP_BREAK .. WRAP_BREAK ..
"Singe Port: " .. GAME_LIST[GAME_SELECTED].CREATOR .. WRAP_BREAK ..
"Source: " .. GAME_LIST[GAME_SELECTED].SOURCE
wrapText(textBox, TEXT_W)
TEXT_LINE_COUNT = utilGetTableSize(TEXT_SPRITE_LIST)
TEXT_LINE_TOP = 1
end
function onInputPressed(what)
-- Are we displaying the grid background?
if (discGetFrame() >= DISC_GRID_START) then
if what == SWITCH_UP then
if TEXT_LINE_TOP > 1 then
TEXT_LINE_TOP = TEXT_LINE_TOP - 1
end
end
if what == SWITCH_DOWN then
if TEXT_LINE_TOP < TEXT_LINE_COUNT - TEXT_LINE_LIMIT + 1 then
TEXT_LINE_TOP = TEXT_LINE_TOP + 1
end
end
if what == SWITCH_LEFT then
GAME_SELECTED = GAME_SELECTED - 1
if GAME_SELECTED < 1 then
GAME_SELECTED = GAME_COUNT
end
loadGameAssets(false)
end
if what == SWITCH_RIGHT then
GAME_SELECTED = GAME_SELECTED + 1
if GAME_SELECTED > GAME_COUNT then
GAME_SELECTED = 1
end
loadGameAssets(false)
end
if what == SWITCH_START1 or what == SWITCH_START2 or what == SWITCH_BUTTON1 or what == SWITCH_BUTTON2 or what == SWITCH_BUTTON3 or what == SWITCH_BUTTON4 then
-- Start next game
SHUTDOWN_FROM_PUSH = true
scriptPush(GAME_LIST[GAME_SELECTED])
end
end
end
function onOverlayUpdate()
local x = 0
local y = 0
local c = 0
local t = 0
overlayClear()
-- Are we displaying the grid background?
if (discGetFrame() >= DISC_GRID_START) then
-- Cabinet image
x = CABINET_X + (CABINET_W - spriteGetWidth(SPRITE_CABINET)) * 0.5
y = CABINET_Y + (CABINET_H - spriteGetHeight(SPRITE_CABINET)) * 0.5
spriteDraw(x, y, SPRITE_CABINET)
-- Marquee Image
x = MARQUEE_X + (MARQUEE_W - spriteGetWidth(SPRITE_MARQUEE)) * 0.5
y = MARQUEE_Y + (MARQUEE_H - spriteGetHeight(SPRITE_MARQUEE)) * 0.5
spriteDraw(x, y, SPRITE_MARQUEE)
-- Attract Mode Video
videoDraw(VIDEO_ATTRACT, VIDEO_X, VIDEO_Y, VIDEO_X + VIDEO_W, VIDEO_Y + VIDEO_H)
if videoGetFrame(VIDEO_ATTRACT) > GAME_LIST[GAME_SELECTED].ATTRACT_END then
videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START)
end
-- Game Description
colorForeground(255, 255, 255, 255)
y = TEXT_Y
c = 0
t = 1
for _, handle in ipairs(TEXT_SPRITE_LIST) do
-- Find height of font and number of lines that fit
if TEXT_LINE_HEIGHT == 0 then
if (handle >= 0) then
TEXT_LINE_HEIGHT = spriteGetHeight(handle)
TEXT_LINE_LIMIT = math.floor(TEXT_H / TEXT_LINE_HEIGHT)
end
end
-- Only display what is visible in the window
if (t >= TEXT_LINE_TOP) then
if (c < TEXT_LINE_LIMIT) then
if (handle >= 0) then
spriteDraw(TEXT_X, y, handle)
end
y = y + TEXT_LINE_HEIGHT + 1
c = c + 1
end
end
t = t + 1
end
end
-- Loop video?
if (discGetFrame() >= DISC_LAST_FRAME) then
discSkipToFrame(DISC_GRID_START)
end
return(OVERLAY_UPDATED)
end
function onShutdown()
saveConfig(not SHUTDOWN_FROM_PUSH)
end
function saveConfig(showIntro)
if GAME_COUNT > 0 then
-- Save what game we're currently viewing
local cfg = io.open(CONFIG_FILE, "w")
cfg:write("GAME_SELECTED = " .. GAME_SELECTED .. "\n")
cfg:write("SHOW_INTRO = " .. tostring(showIntro) .. "\n")
cfg:close()
end
end
function wrapText(text, maxWidth)
local words = {}
local toWrap = ""
local line = ""
local lastLine = ""
local fragment = ""
local doBreak = false
local spriteTemp = -1
local trimBreak = utilTrim(WRAP_BREAK)
-- Break input into words
toWrap = text .. WRAP_BREAK
for w in toWrap:gmatch("%S+") do
words[#words+1] = w
end
-- Iterate over words and try to fit them in the space given
for _, word in ipairs(words) do
-- Is this an intentional break?
if word == trimBreak then
doBreak = true
else
-- Add this word to the line
line = utilTrim(line .. " " .. word)
-- Do we even have text?
if string.len(line) > 0 then
-- Is the line too long to fit now?
spriteTemp = fontToSprite(line)
if spriteGetWidth(spriteTemp) > maxWidth then
doBreak = true
fragment = word
line = lastLine
else
fragment = ""
end
spriteUnload(spriteTemp)
end
end
lastLine = line
-- Did we find a break?
if doBreak then
-- Did we get anything to print?
if string.len(line) > 0 then
table.insert(TEXT_SPRITE_LIST, fontToSprite(line))
else
-- Blank line
table.insert(TEXT_SPRITE_LIST, -1)
end
-- Reset for next line
line = fragment
fragment = ""
doBreak = false
end
end
end
-- Search for games.dat files in subdirectories
GAME_LIST = {}
GAME_COUNT = 0
for dir in lfs.dir(".") do
if dir ~= "." and dir ~= ".." then
local dirattr = lfs.attributes(dir)
if dirattr.mode == "directory" then
for file in lfs.dir(dir .. "/.") do
if file == "games.dat" then
-- Load games.dat
dofile(dir .. "/games.dat")
for key,value in pairs(GAMES) do
table.insert(GAME_LIST, value)
GAME_COUNT = GAME_COUNT + 1
end
GAMES = {}
end
end
end
end
end
table.sort(GAME_LIST, compareTitles)
if GAME_COUNT == 0 then
debugPrint("No games found! Exiting.")
singeQuit()
else
overlaySetResolution(vldpGetWidth(), vldpGetHeight())
freeSans18 = fontLoad("Singe/FreeSansBold.ttf", 18)
fontQuality(FONT_QUALITY_BLENDED)
fontSelect(freeSans18)
DISC_GRID_START = 180
DISC_LAST_FRAME = 359
MARGIN_X = 25
MARGIN_Y = 25
VIDEO_W = 320
VIDEO_H = 200
MARQUEE_H = 75
MARQUEE_W = VIDEO_W
MARQUEE_X = overlayGetWidth() - MARGIN_X - MARQUEE_W
MARQUEE_Y = MARGIN_Y
VIDEO_X = overlayGetWidth() - MARGIN_X - VIDEO_W
VIDEO_Y = MARGIN_Y + MARQUEE_H + MARGIN_Y
TEXT_W = VIDEO_W
TEXT_X = overlayGetWidth() - MARGIN_X - TEXT_W
TEXT_Y = VIDEO_Y + VIDEO_H + MARGIN_Y
TEXT_H = overlayGetHeight() - MARGIN_Y - TEXT_Y
CABINET_X = MARGIN_X
CABINET_Y = MARGIN_Y
CABINET_W = VIDEO_X - MARGIN_X - CABINET_X
CABINET_H = overlayGetHeight() - MARGIN_Y - CABINET_Y
--[[
Cabinet is 325x430
Marquee is 320x75
Video is 320x200
Text is 320x105
--]]
--[[
debugPrint("Cabinet is " .. CABINET_W .. "x" .. CABINET_H)
debugPrint("Marquee is " .. MARQUEE_W .. "x" .. MARQUEE_H)
debugPrint(" Video is " .. VIDEO_W .. "x" .. VIDEO_H)
debugPrint(" Text is " .. TEXT_W .. "x" .. TEXT_H)
--]]
WRAP_BREAK = " [!wb!] "
TEXT_LINE_TOP = 1
TEXT_LINE_LIMIT = 0
TEXT_LINE_COUNT = 0
TEXT_LINE_HEIGHT = 0
TEXT_SPRITE_LIST = {}
SHUTDOWN_FROM_PUSH = false
-- Load configuration
SHOW_INTRO = true
CONFIG_FILE = singeGetDataPath() .. "menu.dat"
local confattr = lfs.attributes(CONFIG_FILE)
if confattr then
dofile(CONFIG_FILE)
if GAME_SELECTED > GAME_COUNT then
GAME_SELECTED = GAME_COUNT
end
else
GAME_SELECTED = 1
end
discPlay()
if (not SHOW_INTRO) then
discSkipToFrame(DISC_GRID_START)
end
-- Prime the pump
loadGameAssets(true)
end