[Build] 32-bit: Refactor the Tupfile into Lua

A perfect `tup refactor`, already featuring most of the structure we're
going to use for the merged 32-bit and 16-bit build.
Also, inlining all the BCC32 stuff because we're no longer going to use
this compiler anyway.

Part of P0003, funded by GhostPhanom.
This commit is contained in:
nmlgc 2024-06-05 11:44:30 +02:00
parent f1318782f3
commit 5a79ea574c
3 changed files with 432 additions and 181 deletions

1
.gitattributes vendored
View File

@ -2,4 +2,5 @@
*.bat text eol=crlf
*.[ch]* text eol=lf
*.mak text eol=lf
*.lua text eol=lf
zun.txt -text

181
Tupfile
View File

@ -1,181 +0,0 @@
# Tupfile for the 32-part of the build process
# --------------------------------------------
# ⚠️ CAUTION! ⚠️
# You are on the `master` branch, which builds PC-98 DOS binaries that are
# identical to ZUN's originally released binaries. If you want to port the game
# to other architectures or develop a mod that doesn't need to be byte-for-byte
# comparable to the original binary, start from the cleaned-up `debloated`
# branch instead. That branch is easier to read and modify, and builds smaller
# and slightly faster PC-98 binaries while leaving all bugs and quirks from
# ZUN's original code in place.
# Seriously, you'd just be torturing yourself if you do anything nontrivial
# based on this branch.
# ⚠️ CAUTION! ⚠️
AS = tasm32 /m /mx /kh32768 /t
CXX32 = bcc32
# Silence incorrect warnings for Borland C++ 5.5
# ----------------------------------------------
# 'identifier' is assigned a value that is never used
CXX32FLAGS += -w-8004
# Comparing signed and unsigned values
CXX32FLAGS += -w-8012
# ----------------------------------------------
CXX32FLAGS += -O2 -v- -x-
# Backslashes necessary for the .bat file generated by `tup generate`!
BMP2ARR = bin\Pipeline\bmp2arr.exe
: Pipeline\\bmp2arr.c Pipeline\\bmp2arrl.c \
|> $(CXX32) $(CXX32FLAGS) -nbin/Pipeline/ %f \
|> bin/Pipeline/bmp2arrl.obj \
bin/Pipeline/bmp2arr.obj \
bin/Pipeline/bmp2arr.tds \
$(BMP2ARR)
!bmp2arr = | $(BMP2ARR) |> $(BMP2ARR) -q -i %f -o %o |> %o
: th01/sprites/leaf_s.bmp |> !bmp2arr -sym sSPARK -of cpp -sw 8 -sh 8 |> th01/sprites/leaf_s.csp
: th01/sprites/leaf_l.bmp |> !bmp2arr -sym sLEAF_LEFT -of cpp -sw 8 -sh 8 |> th01/sprites/leaf_l.csp
: th01/sprites/leaf_r.bmp |> !bmp2arr -sym sLEAF_RIGHT -of cpp -sw 8 -sh 8 |> th01/sprites/leaf_r.csp
: th01/sprites/ileave_m.bmp |> !bmp2arr -sym sINTERLEAVE_MASKS -of cpp -sw 8 -sh 8 |> th01/sprites/ileave_m.csp
# ZUN bug: Supposed to be 8 preshifted sprites, with a height of 1 and a width
# of SHOOTOUT_LASER_MAX_W pixels each, but ZUN messed up a single pixel in the
# first pre-shifted sprite. So, we're forced to manually unroll them…
: th01/sprites/laser_s.bmp |> !bmp2arr -sym sSHOOTOUT_LASER -of cpp -sw 16 -sh 8 |> th01/sprites/laser_s.csp
: th01/sprites/mousecur.bmp |> !bmp2arr -sym sMOUSE_CURSOR -of cpp -sw 16 -sh 16 |> th01/sprites/mousecur.csp
: th01/sprites/pellet.bmp |> !bmp2arr -sym sPELLET -of cpp -sw 8 -sh 8 -pshf inner |> th01/sprites/pellet.csp
: th01/sprites/pellet_c.bmp |> !bmp2arr -sym sPELLET_CLOUD -of cpp -sw 16 -sh 16 |> th01/sprites/pellet_c.csp
: th01/sprites/pillar.bmp |> !bmp2arr -sym sPILLAR -of cpp -sw 32 -sh 8 |> th01/sprites/pillar.csp
: th01/sprites/shape8x8.bmp |> !bmp2arr -sym sSHAPE8X8 -of cpp -sw 8 -sh 8 |> th01/sprites/shape8x8.csp
: th01/sprites/bonusbox.bmp |> !bmp2arr -sym sSTAGEBONUS_BOX -of cpp -sw 8 -sh 4 |> th01/sprites/bonusbox.csp
: th02/sprites/bombpart.bmp |> !bmp2arr -sym _sBOMB_PARTICLES -of asm -sw 8 -sh 8 |> th02/sprites/bombpart.asp
: th02/sprites/pellet.bmp |> !bmp2arr -sym _sPELLET -of asm -sw 8 -sh 8 -pshf outer |> th02/sprites/pellet.asp
: th02/sprites/sparks.bmp |> !bmp2arr -sym _sSPARKS -of asm -sw 8 -sh 8 -pshf outer |> th02/sprites/sparks.asp
: th02/sprites/pointnum.bmp |> !bmp2arr -sym _sPOINTNUMS -of asm -sw 8 -sh 8 |> th02/sprites/pointnum.asp
: th02/sprites/verdict.bmp |> !bmp2arr -sym sVERDICT_MASKS -of cpp -sw 16 -sh 16 |> th02/sprites/verdict.csp
: th03/sprites/score.bmp |> !bmp2arr -sym _sSCORE_FONT -of asm -sw 8 -sh 8 -u |> th03/sprites/score.asp
: th04/sprites/pelletbt.bmp |> !bmp2arr -sym _sPELLET_BOTTOM -of asm -sw 8 -sh 4 -pshf outer |> th04/sprites/pelletbt.asp
: th04/sprites/pointnum.bmp |> !bmp2arr -sym _sPOINTNUMS -of asm -sw 8 -sh 8 -pshf inner |> th04/sprites/pointnum.asp
: th05/sprites/gaiji.bmp |> !bmp2arr -sym _sGAIJI -of asm -sw 16 -sh 16 |> th05/sprites/gaiji.asp
: th05/sprites/piano_l.bmp |> !bmp2arr -sym _sPIANO_LABEL_FONT -of asm -sw 8 -sh 8 |> th05/sprites/piano_l.asp
: Research/blitperf.bmp |> !bmp2arr -sym sBLITPERF -of cpp -sw 16 -sh 16 |> Research/blitperf.csp
!as = |> $(AS) %f %o |> obj\\%B.obj
!as2 = |> $(AS) /dGAME=2 th02\%b %o |> obj\\th02\\%B.obj
!as3 = |> $(AS) /dGAME=3 th03\%b %o |> obj\\th03\\%B.obj
!as4 = |> $(AS) /dGAME=4 th04\%b %o |> obj\\th04\\%B.obj
!as5 = |> $(AS) /dGAME=5 th05\%b %o |> obj\\th05\\%B.obj
# Third-party libraries
: libs\\piloadc\\piloadc.asm |> $(AS) /ml libs\piloadc\%b %o |> obj\\%B.obj
# ZUN.COM
: Pipeline\\zun_stub.asm |> $(AS) Pipeline\%b %o |> obj\\Pipeline\\%B.obj
: Pipeline\\cstmstub.asm |> $(AS) Pipeline\%b %o |> obj\\Pipeline\\%B.obj
: th01_op.asm |> $(AS) /dGAME=1 %f %o |> obj\\th01\\op.obj
: th01_reiiden.asm |> $(AS) /dGAME=1 %f %o |> obj\\th01\\reiiden.obj
: th01_fuuin.asm |> $(AS) /dGAME=1 %f %o |> obj\\th01\\fuuin.obj
: th02_zuninit.asm |> $(AS) /dGAME=2 %f %o |> obj\\th02\\zuninit.obj
: th02_op.asm |> $(AS) /dGAME=2 %f %o |> obj\\th02\\op.obj
: th02_main.asm | \
th02/sprites/bombpart.asp \
th02/sprites/pellet.asp \
th02/sprites/sparks.asp \
th02/sprites/pointnum.asp \
|> $(AS) /dGAME=2 %f %o |> obj\\th02\\main.obj
: th02_maine.asm |> $(AS) /dGAME=2 %f %o |> obj\\th02\\maine.obj
: libs/sprite16/sprite16.asm |> $(AS) /dTHIEF libs\sprite16\sprite16.asm %o |> obj\\th03\\zunsp.obj
: th03\\cdg_put.asm |> !as3 |>
: th03\\cdg_p_na.asm |> !as3 |>
: th03\\hfliplut.asm |> !as3 |>
: th03\\collmap.asm |> !as3 |>
: th03_op.asm |> $(AS) /dGAME=3 %f %o |> obj\\th03\\op.obj
: th03_op2.asm |> $(AS) /dGAME=3 %f %o |> obj\\th03\\op2.obj
: th03_main.asm | \
th03/sprites/score.asp \
|> $(AS) /dGAME=3 %f %o |> obj\\th03\\main.obj
: th03_mainl.asm |> $(AS) /dGAME=3 %f %o |> obj\\th03\\mainl.obj
: th04_zuninit.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\zuninit.obj
: th04_memchk.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\memchk.obj
: th04\\scoreupd.asm |> !as4 |>
: th04\\cdg_put.asm |> !as4 |>
: th04\\cdg_p_nc.asm |> !as4 |>
: th04\\cdg_p_pl.asm |> !as4 |>
: th04\\cdg_p_pr.asm |> !as4 |>
: th04\\input_s.asm |> !as4 |>
: th04\\cdg_load.asm |> !as4 |>
: th04\\bgimager.asm |> !as4 |>
: th04\\motion_3.asm |> !as4 |>
: th04\\spark_a.asm |> !as4 |>
: th04\\vector2n.asm |> !as4 |>
: th04\\grppsafx.asm |> !as4 |>
: th04_op.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\op.obj
: th04_op2.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\op2.obj
: th04_op_master.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\opm.obj
: th04_main.asm | \
th02/sprites/pellet.asp \
th04/sprites/pelletbt.asp \
th02/sprites/sparks.asp \
th04/sprites/pointnum.asp \
|> $(AS) /dGAME=4 %f %o |> obj\\th04\\main.obj
: th04_maine_master.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\mainem.obj
: th04_maine.asm |> $(AS) /dGAME=4 %f %o |> obj\\th04\\maine.obj
: th05_zuninit.asm |> $(AS) /dGAME=5 %f %o |> obj\\th05\\zuninit.obj
: th05_gjinit.asm | \
th05/sprites/gaiji.asp \
|> $(AS) /dGAME=5 %f %o |> obj\\th05\\gjinit.obj
: th05_memchk.asm |> $(AS) /dGAME=5 %f %o |> obj\\th05\\memchk.obj
: th05\\scoreupd.asm |> !as5 |>
: th05\\player.asm |> !as5 |>
: th05\\hud_bar.asm |> !as5 |>
: th05\\bullet_1.asm |> !as5 |>
: th05\\bullet.asm |> !as5 |>
: th05\\input_s.asm |> !as5 |>
: th05\\cdg_put.asm |> !as5 |>
: th05\\musicp_a.asm |> !as5 |>
: th05\\bgimager.asm |> !as5 |>
: th05\\pi_asm_1.asm |> !as5 |>
: th05\\pi_asm_2.asm |> !as5 |>
: th05\\spark_a.asm |> !as5 |>
: th05_op.asm |> $(AS) /dGAME=5 %f %o |> obj\\th05\\op.obj
: th05_op2.asm | \
th05/sprites/piano_l.asp \
|> $(AS) /dGAME=5 %f %o |> obj\\th05\\op2.obj
: th05_op_master.asm |> $(AS) /dGAME=5 %f %o |> obj\\th05\\opm.obj
: th05_main.asm | \
th02/sprites/pellet.asp \
th04/sprites/pelletbt.asp \
th02/sprites/sparks.asp \
th04/sprites/pointnum.asp \
|> $(AS) /dGAME=5 %f %o |> obj\\th05\\main.obj
: th05_maine_master.asm |> $(AS) /dGAME=5 %f %o |> obj\\th05\\mainem.obj
: th05_maine.asm |> $(AS) /dGAME=5 %f %o |> obj\\th05\\maine.obj

431
Tupfile.lua Normal file
View File

@ -0,0 +1,431 @@
-- Tupfile for the 32-part of the build process
-- --------------------------------------------
--[[
CAUTION!
You are on the `master` branch, which builds PC-98 DOS binaries that are
identical to ZUN's originally released binaries. If you want to port the game
to other architectures or develop a mod that doesn't need to be byte-for-byte
comparable to the original binary, start from the cleaned-up `debloated` branch
instead. That branch is easier to read and modify, and builds smaller and
slightly faster PC-98 binaries while leaving all bugs and quirks from ZUN's
original code in place.
Seriously, you'd just be torturing yourself if you do anything nontrivial based
on this branch.
CAUTION!
--]]
---@alias TupInput string | { [1]: string, extra_inputs: string | string[] }
---@alias ReC98Input string | { [1]: string, extra_inputs: string | string[], o?: string}
---@class (exact) ConfigShape
---@field obj_root? string Root directory for all intermediate files
---@field bin_root? string Root directory for shipped binaries
---@field aflags? string
---@class Config
local Config = {
obj_root = "obj/",
bin_root = "bin/",
aflags = "/m /mx /kh32768 /t",
}
Config.__index = Config
---Generates a ConfigShape for an output subdirectory.
---@param dir string
---@return ConfigShape
function Subdir(dir)
return { obj_root = dir, bin_root = dir }
end
---Maps each source filename to its compiled object file. Allows the same
---source file to be listed in multiple binaries later occurrences get
---replaced with the previous build output.
---@type { [string]: string }
local PreviousOutputForSource = {}
---@param ... ConfigShape
function Config:branch(...)
local arg = { ... }
---@class Config
local ret = setmetatable({}, self)
ret.__index = self
for field, value in pairs(self) do
ret[field] = value
for _, other in pairs(arg) do
if other[field] then
-- By only space-separating flags, we allow custom directories.
if (field:sub(-5) == "flags") then
ret[field] = (ret[field] .. " " .. other[field])
else
ret[field] = (ret[field] .. other[field])
end
end
end
end
return ret
end
---@param input ReC98Input
function Config:build_uncached(input)
local fn = ((type(input) == "string" and input) or input[1])
local out_basename = (tup.base(fn):gsub("th0%d_", "") .. ".obj")
if input.o then
out_basename = input.o
input.o = nil
end
local out_file = (self.obj_root .. out_basename)
local ext = tup.ext(fn)
if (ext == "asm") then
-- We can't use %f since TASM32 wants backslashes and Tup would
-- automatically rewrite them to slashes.
local cmd = string.format(
"tasm32 %s %s %%o", self.aflags, fn:gsub("/", "\\")
)
return tup.rule(input, cmd, out_file:gsub("/", "\\"))[1]
end
error(string.format("Unknown file extension, can't build: `%s`", fn))
end
---@param inputs ReC98Input[]
---@return string[]
function Config:build(inputs)
local ret = {}
for _, input in pairs(inputs) do
local fn = ((type(input) == "string" and input) or input[1])
local output = PreviousOutputForSource[fn]
if (output == nil) then
output = self:build_uncached(input)
PreviousOutputForSource[fn] = output
end
end
return ret
end
---@param inputs ReC98Input[]
function Config:link(exe_stem, inputs)
local objs = self:build(inputs)
end
-- Pipeline
-- --------
local pipeline_cfg = Config:branch(Subdir("Pipeline/"), {
cflags = "-IPipeline/",
})
local bmp2arr = tup.rule(
{ "Pipeline/bmp2arr.c", "Pipeline/bmp2arrl.c" },
"bcc32 -w-8004 -w-8012 -O2 -v- -x- -nbin/Pipeline/ %f",
{ "bin/Pipeline/bmp2arr.exe", extra_outputs = {
"%O.tds", "bin/Pipeline/%1B.obj", "bin/Pipeline/%2B.obj"
} }
)[1]
---@class BMPShape
---@field [1] string Input .BMP file
---@field [2] "asm" | "cpp" Output format
---@field [3] string Symbol
---@field [4] integer Width
---@field [5] integer Height
---@field [6] string? Additional arguments
---@param bmp BMPShape
---@return string
function BMP(bmp)
local out_fn = bmp[1]:gsub("%..+$", (bmp[2] == "asm" and ".asp" or ".csp"))
local inputs = { bmp[1], extra_inputs = bmp2arr }
local sym = ((bmp[2] == "asm" and "_" or "") .. bmp[3])
local additional = ((bmp[6] and (" " .. bmp[6])) or "")
local cmd = string.format(
"%s -q -i %%f -o %%o -sym %s -of %s -sw %d -sh %d%s",
bmp2arr:gsub("/", "\\"), sym, bmp[2], bmp[4], bmp[5], additional
)
return tup.rule(inputs, cmd, out_fn)[1]
end
---@param bmps BMPShape[]
---@return table<string, string> sprites Sprite basename → source file
function Sprites(bmps)
local ret = {}
for _, bmp in pairs(bmps) do
ret[tup.base(bmp[1])] = BMP(bmp)
end
return ret
end
local zun_stub = pipeline_cfg:build({ "Pipeline/zun_stub.asm" })
local cstmstub = pipeline_cfg:build({ "Pipeline/cstmstub.asm" })
---@param bin_fn string
---@param procs [string, string][] [Menu name, input filename]
function Config:zungen(bin_fn, procs)
end
-- --------
-- Third-party libraries
-- ---------------------
local piloadc = Config:branch({ aflags = "/ml" }):build({
"libs/piloadc/piloadc.asm"
})[1]
local sprite16 = Config:branch({ aflags = "/dTHIEF" }):build({
{ "libs/sprite16/sprite16.asm", o = "th03/zunsp.obj" }
})[1]
-- ---------------------
-- Games
-- -----
---@param game number
function GameShape(game)
local ret = Subdir(string.format("th0%d/", game))
ret.aflags = string.format("/dGAME=%d", game)
return ret
end
local th01 = Config:branch(GameShape(1))
local th02 = Config:branch(GameShape(2))
local th03 = Config:branch(GameShape(3))
local th04 = Config:branch(GameShape(4))
local th05 = Config:branch(GameShape(5))
-- -----
-- TH01
-- ----
local th01_sprites = Sprites({
{ "th01/sprites/leaf_s.bmp", "cpp", "sSPARK", 8, 8 },
{ "th01/sprites/leaf_l.bmp", "cpp", "sLEAF_LEFT", 8, 8 },
{ "th01/sprites/leaf_r.bmp", "cpp", "sLEAF_RIGHT", 8, 8 },
{ "th01/sprites/ileave_m.bmp", "cpp", "sINTERLEAVE_MASKS", 8, 8 },
-- ZUN bug: Supposed to be 8 preshifted sprites, with a height of 1 and a
-- width of SHOOTOUT_LASER_MAX_W pixels each, but ZUN messed up a single
-- pixel in the first pre-shifted sprite.
-- So, we're forced to manually unroll them…
{ "th01/sprites/laser_s.bmp", "cpp", "sSHOOTOUT_LASER", 16, 8 },
{ "th01/sprites/mousecur.bmp", "cpp", "sMOUSE_CURSOR", 16, 16 },
{ "th01/sprites/pellet.bmp", "cpp", "sPELLET", 8, 8, "-pshf inner" },
{ "th01/sprites/pellet_c.bmp", "cpp", "sPELLET_CLOUD", 16, 16 },
{ "th01/sprites/pillar.bmp", "cpp", "sPILLAR", 32, 8 },
{ "th01/sprites/shape8x8.bmp", "cpp", "sSHAPE8X8", 8, 8 },
{ "th01/sprites/bonusbox.bmp", "cpp", "sSTAGEBONUS_BOX", 8, 4 },
})
th01:link("op", {
"th01_op.asm",
})
th01:link("reiiden", {
"th01_reiiden.asm",
})
th01:link("fuuin", {
"th01_fuuin.asm",
})
-- ----
-- TH02
-- ----
local th02_sprites = Sprites({
{ "th02/sprites/bombpart.bmp", "asm", "sBOMB_PARTICLES", 8, 8 },
{ "th02/sprites/pellet.bmp", "asm", "sPELLET", 8, 8, "-pshf outer" },
{ "th02/sprites/sparks.bmp", "asm", "sSPARKS", 8, 8, "-pshf outer" },
{ "th02/sprites/pointnum.bmp", "asm", "sPOINTNUMS", 8, 8 },
{ "th02/sprites/verdict.bmp", "cpp", "sVERDICT_MASKS", 16, 16 },
})
local th02_zuninit = th02:link("zuninit", {
"th02_zuninit.asm",
})
th02:link("op", {
"th02_op.asm",
})
th02:link("main", {
{ "th02_main.asm", extra_inputs = {
th02_sprites["pellet"],
th02_sprites["bombpart"],
th02_sprites["sparks"],
th02_sprites["pointnum"],
} },
})
th02:link("maine", {
"th02_maine.asm",
})
-- ----
-- TH03
-- ----
local th03_sprites = Sprites({
{ "th03/sprites/score.bmp", "asm", "sSCORE_FONT", 8, 8, "-u" },
})
th03:zungen("bin/th03/zun.com", {
{ "-4", th03:link("zunsp", { sprite16 }) },
})
th03:link("op", {
"th03_op2.asm",
"th03_op.asm",
"th03/cdg_put.asm",
"th03/cdg_p_na.asm",
"th03/hfliplut.asm",
})
th03:link("main", {
{ "th03_main.asm", extra_inputs = th03_sprites["score"] },
"th03/collmap.asm",
"th03/hfliplut.asm",
})
th03:link("mainl", {
"th03_mainl.asm",
"th03/cdg_put.asm",
"th03/cdg_p_na.asm",
"th03/hfliplut.asm",
})
-- ----
-- TH04
-- ----
local th04_sprites = Sprites({
{"th04/sprites/pelletbt.bmp", "asm", "sPELLET_BOTTOM", 8, 4, "-pshf outer"},
{"th04/sprites/pointnum.bmp", "asm", "sPOINTNUMS", 8, 8, "-pshf inner"},
})
local th04_zuncom = th04:zungen("obj/th04/zuncom.bin", {
{ "-I", th04:link("zuninit", { "th04_zuninit.asm" }) },
{ "-M", th04:link("memchk", { "th04_memchk.asm" }) },
})
th04:link("op", {
{ "th04_op_master.asm", o = "opm.obj" },
"th03/hfliplut.asm",
"th04/cdg_p_nc.asm",
"th04/grppsafx.asm",
"th04_op2.asm",
"th04/cdg_put.asm",
"th04/input_s.asm",
"th04/bgimager.asm",
"th04/cdg_load.asm",
"th04_op.asm",
})
th04:link("main", {
{ "th04_main.asm", extra_inputs = {
th02_sprites["pellet"],
th02_sprites["sparks"],
th04_sprites["pelletbt"],
th04_sprites["pointnum"],
} },
"th04/scoreupd.asm",
"th03/hfliplut.asm",
"th04/cdg_put.asm",
"th04/cdg_p_pr.asm",
"th04/input_s.asm",
"th04/cdg_load.asm",
"th04/motion_3.asm",
"th04/vector2n.asm",
"th04/spark_a.asm",
})
th04:link("maine", {
{ "th04_maine_master.asm", o = "mainem.obj" },
"th03/hfliplut.asm",
"th04/cdg_p_pl.asm",
"th04/grppsafx.asm",
"th04_maine.asm",
"th04/cdg_put.asm",
"th04/input_s.asm",
"th04/bgimager.asm",
"th04/cdg_load.asm",
})
-- ----
-- TH05
-- ----
local th05_sprites = Sprites({
{ "th05/sprites/gaiji.bmp", "asm", "sGAIJI", 16, 16 },
{ "th05/sprites/piano_l.bmp", "asm", "sPIANO_LABEL_FONT", 8, 8 },
})
local th05_zuncom = th05:zungen("obj/th05/zuncom.bin", {
{ "-I", th05:link("zuninit", { "th05_zuninit.asm" }) },
{ "-G", th05:link("gjinit", {
{ "th05_gjinit.asm", extra_inputs = th05_sprites["gaiji"] },
}) },
{ "-M", th05:link("memchk", { "th05_memchk.asm" }) },
})
th05:link("op", {
{ "th05_op_master.asm", o = "opm.obj" },
"th03/hfliplut.asm",
"th04/grppsafx.asm",
{ "th05_op2.asm", extra_inputs = th05_sprites["piano_l"] },
"th05/cdg_put.asm",
"th05/musicp_a.asm",
"th05/bgimager.asm",
"th05/pi_asm_1.asm",
"th05/pi_asm_2.asm",
"th05/input_s.asm",
"th04/cdg_load.asm",
"th05_op.asm",
})
th05:link("main", {
{ "th05_main.asm", extra_inputs = {
th02_sprites["pellet"],
th02_sprites["sparks"],
th04_sprites["pelletbt"],
th04_sprites["pointnum"],
} },
"th05/player.asm",
"th05/hud_bar.asm",
"th05/scoreupd.asm",
"th04/vector2n.asm",
"th05/spark_a.asm",
"th05/bullet_1.asm",
"th05/bullet.asm",
"th03/hfliplut.asm",
"th05/cdg_put.asm",
"th05/input_s.asm",
"th04/cdg_load.asm",
"th04/motion_3.asm",
})
th05:link("maine", {
{ "th05_maine_master.asm", o = "mainem.obj" },
"th03/hfliplut.asm",
"th04/grppsafx.asm",
"th05_maine.asm",
"th05/bgimager.asm",
"th05/pi_asm_1.asm",
"th05/pi_asm_2.asm",
"th05/input_s.asm",
"th04/cdg_load.asm",
})
-- ----
-- Research
-- --------
local research_sprites = Sprites({
{ "Research/blitperf.bmp", "cpp", "sBLITPERF", 16, 16 }
})
-- --------