summaryrefslogtreecommitdiff
Diffstat
-rw-r--r--.gitignore17
-rw-r--r--INSTALL92
-rw-r--r--Makefile38
-rw-r--r--content/develmanifest.lua10
-rw-r--r--content/scion/CombatMode.lua12
-rw-r--r--content/scion/Combatant.lua10
-rw-r--r--content/scion/ContextMenu.lua2
-rw-r--r--content/scion/Field.lua1
-rw-r--r--content/scion/LevelLoader.lua18
-rw-r--r--content/scion/MainMenu.lua4
-rw-r--r--content/scion/Preloader.lua4
-rw-r--r--content/scion/Slideshow.lua2
-rw-r--r--content/start.lua5
-rw-r--r--content/test/spellbench.lua2
m---------ult0
15 files changed, 175 insertions, 42 deletions
diff --git a/.gitignore b/.gitignore
index 48d338f..c5f2761 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,8 @@
*~
-ult
-ult.exe
-/scion
-scion.exe
-*.pak
-.build
*.dll
-mingw.options
-userdata
-stdout.txt
-stderr.txt
-ultwin/*
+/scion
+/scion.exe
+/data
+/stdout.txt
+/stderr.txt
+/userdata
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..694a63b
--- a/dev/null
+++ b/INSTALL
@@ -0,0 +1,92 @@
+
+Summary
+=======
+
+You need Lua 5.1, SDL, SDL_image, SDL_mixer, Freetype, Zlib, Zip, OpenGL.
+There's no ./configure. If needed, use 'make' options or edit ult/config.mk.
+
+make PREFIX=/usr
+sudo make install
+
+
+Requirements
+============
+
+C99 compiler
+Lua 5.1 - www.lua.org
+SDL - www.libsdl.org
+SDL_image - www.libsdl.org/projects/SDL_image
+SDL_mixer - www.libsdl.org/projects/SDL_mixer
+Freetype - www.freetype.org or gnuwin32.sf.net
+Zlib - www.zlib.net
+Zip - www.info-zip.org
+OpenGL and GLU
+
+
+Building with GNU make
+======================
+
+This project doesn't use autoconf and automake. A custom configure script
+was used for some time, but it was abandoned in favor of simple Makefiles.
+See ult/config.mk for rationale and information.
+
+To compile the package, use:
+
+make OPTION1=value1 OPTION2=value2 ...
+
+A list of options and their default values is in ult/config.mk. If it
+exists, ult/myconfig.mk will be read instead. You can specify another
+config file with 'make CONFIG=file.mk'. The default ult/config.mk uses
+pkg-config and similar tools to provide good cross-platform defaults,
+so you probably won't have to provide any options.
+
+To install the program, use:
+
+make install
+
+Installing is optional - the software looks for data files in the current
+directory as well. You can use DESTDIR=/alternate/root for staged installs.
+
+
+Building with MinGW and MSYS
+============================
+
+To build this under MinGW, you need
+(1) required libraries installed in /mingw,
+(2) .dll files copied to the project directory,
+(3) MinGW-specific compile flags (e.g. -lopengl32 instead of -lGL),
+
+You can run ult/mingw-get-libs.sh to download and install all libraries.
+Then, compile with the config file 'make CONFIG=ult/mingw.mk', which takes
+care of (2) and (3). You may want to do 'cp ult/mingw.mk ult/myconfig.mk' to
+make the choice persistent.
+
+
+Manual build
+============
+
+Here's what to do when using another build system.
+
+The software uses Lua to generate C source code. Run these commands in ult/:
+
+lua lgllib.lua -I/header/path/to/SDL_opengl.h/ -I/and/GL.h/ -I/and/GLU.h/
+lua lsdllib.lua -I/path/to/SDL.h/ -I/and/SDL_image.h/ -I/and/SDL_mixer.h/
+# omit datadir=... and the program will look for data in ./data/
+# line wrapped for clarity
+lua generate.lua launcher datadir=/data/files/location/ \
+ product=Scion <launcher.lua >chunks.h
+lua generate.lua FS <FS.lua >>chunks.h
+# when linking with LuaJIT, run this too:
+#lua generate.lua jit.opt <.../LuaJIT/lib/opt.lua >>chunks.h
+#lua generate.lua jit.opt_inline <.../LuaJIT/lib/opt_inline.lua >>chunks.h
+
+Compile all *.c files in ult/ (including generated ones) and all required
+libraries (see above) into a single binary named 'scion'.
+
+Then, using the binary, run this in the top-level directory:
+
+./scion --userdir=. --datadir=. --run=content.makedata
+
+To install the software, copy the binary to /usr/bin and data/ to
+/data/files/location/.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..70d37a2
--- a/dev/null
+++ b/Makefile
@@ -0,0 +1,38 @@
+
+all: scion data/scion.pak
+
+export DATADIR = $(PREFIX)/share/games/scion
+
+# using $(abspath) allows including CONFIG from ult/Makefile
+override CONFIG := $(abspath $(or $(CONFIG),$(wildcard ult/myconfig.mk),ult/config.mk))
+include $(CONFIG)
+
+scion:
+ $(MAKE) -C ult target=../scion product=Scion CONFIG=$(CONFIG)
+
+data/manifest.lua data/scion.pak: scion content/makedata.lua
+ ./scion --userdir=. --datadir=. --run=content.makedata
+
+install: all
+ $(INSTALL) -d $(DESTDIR)$(BINDIR)
+ $(INSTALL) -m755 scion $(DESTDIR)$(BINDIR)
+ $(INSTALL) -d $(DESTDIR)$(DATADIR)
+ $(INSTALL) -m644 data/scion.pak $(DESTDIR)$(DATADIR)
+ [ -f data/music.pak ] && $(INSTALL) -m644 data/music.pak $(DESTDIR)$(DATADIR)
+ $(INSTALL) -m644 data/manifest.lua $(DESTDIR)$(DATADIR)
+
+uninstall:
+ $(RM) $(DESTDIR)$(BINDIR)/scion
+ -rmdir $(DESTDIR)$(BINDIR)
+ $(RM) $(DESTDIR)$(DATADIR)/scion.pak
+ $(RM) $(DESTDIR)$(DATADIR)/music.pak
+ $(RM) $(DESTDIR)$(DATADIR)/manifest.lua
+ -rmdir $(DESTDIR)$(DATADIR)
+
+clean distclean:
+ -$(RM) stdout.txt stderr.txt data/manifest.lua data/scion.pak data/music.pak
+ -rmdir data
+ $(MAKE) -C ult target=../scion CONFIG=$(CONFIG) $@
+
+.PHONY: all scion install uninstall clean distclean
+
diff --git a/content/develmanifest.lua b/content/develmanifest.lua
new file mode 100644
index 0000000..c0bdc1a
--- a/dev/null
+++ b/content/develmanifest.lua
@@ -0,0 +1,10 @@
+function FS.runConfig(fname, body)
+ local chunk = assert(loadstring(body or assert(FS.load(fname):read()), '@'..fname))
+ local env = {}
+ _G.setfenv(chunk, env)
+ chunk()
+ return env
+end
+
+FS.DataDirectory:new{ id = 'ult', path = 'ult/content' }:appendToActiveList()
+require 'test.compat'
diff --git a/content/scion/CombatMode.lua b/content/scion/CombatMode.lua
index 20dd504..ff6fa84 100644
--- a/content/scion/CombatMode.lua
+++ b/content/scion/CombatMode.lua
@@ -118,7 +118,7 @@ function CombatMode:inserted()
v.layer = L_ENEMIES; v.position = i; self:addChild(v) end
self:addChild(StatusMessage:new{ frames = 5 })
- self:addChild(Overlay:new{ layer = L_INTERFACE, texture = 'scion/gfx/caveoverlay.png{^2}' })
+ self:addChild(Overlay:new{ layer = L_INTERFACE, texture = 'gfx/caveoverlay.png{^2}' })
self:addChild(Overlay:new{ layer = L_BACKGROUND, texture = self.bg_texture })
self:addChild(InputGrid:new{})
self:addChild(_G.scion.Cursor:new{})
@@ -247,7 +247,7 @@ function SpellAnim:initialize()
_G.Node.initialize(self)
assert(self.name)
local _; self.anim = {}
- for i,v in ipairs(_G.FS.matchFiles('^/scion/gfx/spells/'..self.name..'/..')) do
+ for i,v in ipairs(_G.FS.matchFiles('^/gfx/spells/'..self.name)) do
_, self.anim[i] = Textures.bind(v..'{^2}')
end
self.w, self.h = self.anim[1].origw, self.anim[1].origh
@@ -337,7 +337,7 @@ function InputIcon:displayContent()
local active = (action == 'attack' or action == 'defend' or
self.parent.parent.queue[1].words[action] or
(action == 'heal' and _G.PERSISTENT.plants > 0))
- Textures.bind('scion/gfx/words'..(active and '' or '_inactive')..'.png'..
+ Textures.bind('gfx/words'..(active and '' or '_inactive')..'.png'..
'{'..((self.x-1)*32)..','..((self.y-1)*32)..',32,32}')
drawQuad{ x = self.draw_x, y = self.draw_y, vert = { 2, 2, 34, 34 } }
self:displayChildren()
@@ -399,7 +399,7 @@ InputGrid.isInput = true
InputGrid.layer = L_INTERFACE
function InputGrid:inserted()
- self:addChild(Overlay:new{ texture = 'scion/gfx/battleoverlay.png{^2}' })
+ self:addChild(Overlay:new{ texture = 'gfx/battleoverlay.png{^2}' })
for y = 1, 3 do for x = 1, 5 do
self:addChild(InputIcon:new{ x = x, y = y }) end end
end
@@ -407,7 +407,7 @@ end
function InputGrid:displayContent()
-- spell icons
if self.showSpell then
- Textures.bind('scion/gfx/words.png{'..((self.showSpell[1]-1)*32)..','..((self.showSpell[2]-1)*32)..',32,32}')
+ Textures.bind('gfx/words.png{'..((self.showSpell[1]-1)*32)..','..((self.showSpell[2]-1)*32)..',32,32}')
drawQuad{ x = _G.WIDTH/2 + (5*36)/2 + 36*2, y = 0, vert = { 0, 0, 32, 32 } }
gl.Translate(32, 0, 0)
gl.Color(0.8, 0.8, 0.8)
@@ -417,7 +417,7 @@ function InputGrid:displayContent()
gl.Vertex(0, 16); gl.Vertex(16, 16)
gl.End()
gl.Translate(16, 0, 0)
- Textures.bind('scion/gfx/words.png{'..((self.showSpell[3]-1)*32)..','..((self.showSpell[4]-1)*32)..',32,32}')
+ Textures.bind('gfx/words.png{'..((self.showSpell[3]-1)*32)..','..((self.showSpell[4]-1)*32)..',32,32}')
drawQuad{ vert = { 0, 0, 32, 32 } }
end
diff --git a/content/scion/Combatant.lua b/content/scion/Combatant.lua
index 6a6fa39..913870d 100644
--- a/content/scion/Combatant.lua
+++ b/content/scion/Combatant.lua
@@ -113,7 +113,7 @@ Combatant.attack_frame_damage = nil
EnemyData = {}
_G.setmetatable(EnemyData, { __index = function (t, enemy)
- EnemyData[enemy] = _G.assert(_G.FS.runConfig('scion/enemies/'..enemy..'.lua'))
+ EnemyData[enemy] = _G.assert(_G.FS.runConfig('enemies/'..enemy..'.lua'))
return EnemyData[enemy]
end })
@@ -131,7 +131,7 @@ end
function Combatant:initialize()
_G.Node.initialize(self)
- local path = '/scion/gfx/'..(self.isEnemy and 'enemies/' or '')..(self.shape or self.name)
+ local path = '/gfx/'..(self.isEnemy and 'enemies/' or '')..(self.shape or self.name)
if self.isEnemy then
_G.assert(self.resistance)
if not self.attack_frame_damage then self.attack_frame_damage = 4 end
@@ -350,7 +350,7 @@ function Combatant:displayContent()
gl.End()
if self.protected and not self.eff_anim.parent then
- Textures.bind'scion/gfx/spells/protect/04.png'
+ Textures.bind'gfx/spells/protect/04.png'
gl.Begin(gl.QUADS)
gl.TexCoord(0, 0); gl.Vertex(0, 0)
gl.TexCoord(0, 1); gl.Vertex(0, 64)
@@ -359,7 +359,7 @@ function Combatant:displayContent()
gl.End()
end
if self.invincible and not self.eff_anim.parent then
- Textures.bind'scion/gfx/spells/invincibility/04.png'
+ Textures.bind'gfx/spells/invincibility/04.png'
gl.Begin(gl.QUADS)
gl.TexCoord(0, 0); gl.Vertex(0, 0)
gl.TexCoord(0, 1); gl.Vertex(0, 64)
@@ -368,7 +368,7 @@ function Combatant:displayContent()
gl.End()
end
if self.autolife and not self.eff_anim.parent then
- local _, td = Textures.bind'scion/gfx/spells/autolife/03.png{^2}'
+ local _, td = Textures.bind'gfx/spells/autolife/03.png{^2}'
gl.Color(1, 1, 1, 0.4)
gl.Begin(gl.QUADS)
gl.TexCoord(0, 0); gl.Vertex(0, 0)
diff --git a/content/scion/ContextMenu.lua b/content/scion/ContextMenu.lua
index e43a01c..a9c5e46 100644
--- a/content/scion/ContextMenu.lua
+++ b/content/scion/ContextMenu.lua
@@ -183,7 +183,7 @@ function ContextMenu:inserted()
color = {1,1,1,0.8}, isOffset = false, x = x, y = yWords })
for wx = 1, 4 do for wy = 1, 3 do
local word = _G.scion.CombatMode.GridActions[wy][wx+1]
- local function getTexid() return Textures.bind('scion/gfx/words'..
+ local function getTexid() return Textures.bind('gfx/words'..
(character.words[word] and '' or '_inactive')..'.png'..
'{'..((wx+1-1)*32)..','..((wy-1)*32)..',32,32}') end
self:addChild(IconButton:new{ wx = wx, wy = wy, charid = charid,
diff --git a/content/scion/Field.lua b/content/scion/Field.lua
index 537b513..acb8ac0 100644
--- a/content/scion/Field.lua
+++ b/content/scion/Field.lua
@@ -15,6 +15,7 @@ local math = math
local SDL, gl = SDL, gl
local MainLoop, Controls, CombatMode, Combatant, TextInput =
MainLoop, scion.Controls, scion.CombatMode, scion.Combatant, TextInput
+local Textures = Textures
module(...)
diff --git a/content/scion/LevelLoader.lua b/content/scion/LevelLoader.lua
index bfd9f4f..4abe52a 100644
--- a/content/scion/LevelLoader.lua
+++ b/content/scion/LevelLoader.lua
@@ -11,7 +11,7 @@ local function loadChar(dname, animations, chartexid)
-- TODO cleanup hardcoded parts
if dname == 'ged' then
for _,d in ipairs({1, 2, 10, 11, 12, 20, 21, 22}) do
- local base = 'scion/gfx/'..dname..'/'..('%03d'):format(d)
+ local base = 'gfx/'..dname..'/'..('%03d'):format(d)
local animid = Textures.bind(base..'walk1.png{^2}')
chartexid[d] = Textures.bind(base..'.png{^2}')
chartexid[d+100] = animid
@@ -25,14 +25,14 @@ local function loadChar(dname, animations, chartexid)
end
elseif dname == 'ship' then
for _,d in ipairs({1, 2, 10, 11, 12, 20, 21, 22}) do
- local base = 'scion/gfx/'..dname..'/'..('%03d'):format(d)
+ local base = 'gfx/'..dname..'/'..('%03d'):format(d)
chartexid[d] = Textures.bind(base..'.png{^2}')
chartexid[d+100] = Textures.bind(base..'.png{^2}')
end
chartexid.w, chartexid.h = 32, 32
else
for _,d in ipairs({1, 2, 10, 11, 12, 20, 21, 22}) do
- local base = 'scion/gfx/'..dname..'/'..('%03d'):format(d)
+ local base = 'gfx/'..dname..'/'..('%03d'):format(d)
local animid = Textures.bind(base..'s1.png{^2}')
chartexid[d] = animid
chartexid[d+100] = Textures.bind(base..'walk1.png{^2}')
@@ -50,7 +50,7 @@ end
-- TODO: (maybe) cache loaded levels?
function load(proto)
- local map = _G.assert(_G.FS.runConfig('scion/maps/'..proto.mapname..'.lua')).map
+ local map = _G.assert(_G.FS.runConfig('maps/'..proto.mapname..'.lua')).map
local W, H = map.width, map.height
for k,v in _G.pairs(map.properties or {}) do proto[k] = _G.tonumber(v) or v end
@@ -62,12 +62,12 @@ function load(proto)
for _,ts in ipairs(map.tilesets) do
local firstgid = ts.firstgid
if ts.source then
- ts = _G.assert(_G.FS.runConfig('scion/maps/'..ts.source:sub(1, -5)..'.lua')).map.tilesets[1]
+ ts = _G.assert(_G.FS.runConfig('maps/'..ts.source:sub(1, -5)..'.lua')).map.tilesets[1]
ts.firstgid = firstgid
end
local image = nil
for j,v in ipairs(ts) do
- if v.label == 'image' then image = 'scion/gfx/'..v.source end
+ if v.label == 'image' then image = 'gfx/'..v.source end
if v.label == 'tile' then tileprop[firstgid+v.id] = v.properties end
end
_G.assert(image)
@@ -111,7 +111,7 @@ function load(proto)
local finfo = proto.fields[y][x]
if texids[gid] then finfo.display = texids[gid] end
if (tileprop[gid] or {}).noaccess then finfo.access = false end
- if (tileprop[gid] or {}).plant then finfo.plant = Textures.bind('scion/gfx/'..tileprop[gid].plant) end
+ if (tileprop[gid] or {}).plant then finfo.plant = Textures.bind('gfx/'..tileprop[gid].plant) end
if (tileprop[gid] or {}).stairs then finfo.stairs = true; finfo.access = false end
x = x + 1; if x >= W then x = 0; y = y + 1 end
end
@@ -131,9 +131,9 @@ function load(proto)
end end
proto.texid_overlay = (proto.overlay and
- Textures.bind('scion/gfx/'..proto.overlay..'{^2}'))
+ Textures.bind('gfx/'..proto.overlay..'{^2}'))
- proto.battlebg = 'scion/gfx/'..(proto.battlebg or 'bbg_ow.png')..'{^2}'
+ proto.battlebg = 'gfx/'..(proto.battlebg or 'bbg_ow.png')..'{^2}'
local defGroupSize = nil
local wildlife = proto.wildlife or 'C0'
diff --git a/content/scion/MainMenu.lua b/content/scion/MainMenu.lua
index ad78c6e..83ee595 100644
--- a/content/scion/MainMenu.lua
+++ b/content/scion/MainMenu.lua
@@ -46,7 +46,7 @@ MainMenu.logo_speed = 0.5
MainMenu.initialized_lines = false
-MainMenu.music_list = { _G.FS.lookupFile('/music/field/song5.ogg') and '/music/field/song5.ogg' }
+MainMenu.music_list = { _G.FS.listFiles('/music/field')['song5.ogg'] and '/music/field/song5.ogg' }
function MainMenu:initialize()
MainLoop.initialize(self)
@@ -139,7 +139,7 @@ function MainMenu:display()
gl.Clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT)
gl.LoadIdentity()
- local _, tinfo = Textures.bind'scion/gfx/menubg.png{^2}'
+ local _, tinfo = Textures.bind'gfx/menubg.png{^2}'
gl.Color(1, 1, 1)
gl.Begin(gl.QUADS)
gl.TexCoord(0, 0); gl.Vertex(0, 0)
diff --git a/content/scion/Preloader.lua b/content/scion/Preloader.lua
index 84ad2e5..8f2121b 100644
--- a/content/scion/Preloader.lua
+++ b/content/scion/Preloader.lua
@@ -30,10 +30,10 @@ function Preloader:initialize()
self.font = _G.Fonts['fonts/BROOKLNN.ttf:26']
self:setString("načítava sa...")
- local images = _G.FS.matchFiles('^/scion/gfx/spells/.*%.')
+ local images = _G.FS.matchFiles('^/gfx/spells/.*%.')
local music = _G.FS.matchFiles('^/music/.*%.')
self.preload = {}
- for i,v in _G.ipairs(_G.FS.matchFiles('^/scion/gfx/spells/.*%.')) do
+ for i,v in _G.ipairs(_G.FS.matchFiles('^/gfx/spells/.*%.')) do
_G.table.insert(self.preload, { f=_G.Textures.bind, v..'{^2}' })
end
for i,v in _G.ipairs(_G.FS.matchFiles('^/music/.*%.')) do
diff --git a/content/scion/Slideshow.lua b/content/scion/Slideshow.lua
index 76bb5f0..7f6b917 100644
--- a/content/scion/Slideshow.lua
+++ b/content/scion/Slideshow.lua
@@ -26,7 +26,7 @@ Slideshow.pressedEsc = false
function Slideshow:initialize()
MainLoop.initialize(self)
if not self.slides then
- self.slides = _G.FS.matchFiles('scion/gfx/'..self.name)
+ self.slides = _G.FS.matchFiles('gfx/'..self.name)
_G.table.sort(self.slides)
end
end
diff --git a/content/start.lua b/content/start.lua
index 6219c02..d7342f6 100644
--- a/content/start.lua
+++ b/content/start.lua
@@ -2,9 +2,6 @@
require 'strict'
require 'extlib'
-if (_ARG[1] or ''):sub(1,5) == 'test.' then return require(_ARG[1]) end
-if _ARG[1] == 'karel' then return require'karel.Main' end
-
require 'scion.Preloader'
require 'scion.MainMenu'
@@ -40,5 +37,5 @@ gl.Ortho(0, WIDTH, 0, HEIGHT, -1, 1)
gl.MatrixMode(gl.MODELVIEW); gl.LoadIdentity()
PERSISTENT = {}
-if _ARG[1] == '--pdebug' then return scion.MainMenu:new{}:run() end
+if arg[1] == '--pdebug' then return scion.MainMenu:new{}:run() end
scion.Preloader:new{}:run()
diff --git a/content/test/spellbench.lua b/content/test/spellbench.lua
index 5e05166..5307d11 100644
--- a/content/test/spellbench.lua
+++ b/content/test/spellbench.lua
@@ -1,4 +1,4 @@
require'test.nehe.nehelib'; initScreen() --[[ to be able to use gl.* ]]
-local G,A,S,T,t=SDL.GetTicks,FS.matchFiles'^/scion/gfx/spells.*%.',0
+local G,A,S,T,t=SDL.GetTicks,FS.matchFiles'^/gfx/spells.*%.',0
T=G(); for i,v in ipairs(A) do t=G(); Textures.bind(v..'{^2}')
t=G()-t; S=S+t; print(t, v) end; print(S, G()-T)
diff --git a/ult b/ult
-Subproject 957ab96c21fbe5d4ade91b4805232f4c0189be2
+Subproject 3efeb57caea4d4389f12061fef475a7e95c0d6e