--[[ ⚠️ 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 ReC98Input string | { [1]: string, extra_inputs: string | string[], o?: string} tup.include("Pipeline/rules.lua") ---@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 ---@field cflags? string ---@field lflags? string ---@class Config local Config = { obj_root = "obj/", bin_root = "bin/", aflags = "/m /mx /kh32768 /t", cflags = "-I. -O -b- -3 -Z -d", lflags = "-s", } Config.__index = Config local Rules = NewRules(Config.obj_root) MODEL_ASM = { lflags = "-t -3" } MODEL_TINY = { cflags = "-mt", lflags = "-t" } MODEL_SMALL = { cflags = "-ms" } -- Currently, it only makes sense to enable extended dictionary processing for -- binaries that don't link the original binary release of MASTERS.LIB, which -- doesn't come with them. MODEL_LARGE = { cflags = "-ml", lflags = "-E" } ---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 args = string.format("%s %s %%o", self.aflags, fn:gsub("/", "\\")) return Rules:add_32(input, "tasm32", args, out_file:gsub("/", "\\"))[1] elseif ((ext == "c") or (ext == "cpp")) then local args = string.format("-c %s -n%s %%f", self.cflags, self.obj_root) return Rules:add_16(input, "tcc", args, out_file)[1] elseif ((ext == "obj") or (ext == "lib")) then return fn 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 ret += { output } end return ret end ---@param exe_stem string ---@param inputs ReC98Input[] function Config:link(exe_stem, inputs) local model_c = self.cflags:match("-m([tsmclh])") local objs = self:build(inputs) local obj_root = self.obj_root:gsub("/", "\\") local bin_root = self.bin_root:gsub("/", "\\") local ext = (self.lflags:find("-t") and ".com" or ".exe") local rsp_fn = string.format("%s%s.@l", obj_root, exe_stem) local map_fn = string.format("%s%s.map", obj_root, exe_stem) local bin_fn = string.format("%s%s%s", bin_root, exe_stem, ext) -- When TCC spawns TLINK, it writes the entire link command line into a -- file with the fixed name `turboc.$ln`. This can't ever work with -- parallel builds, so we have to replicate TCC's response file generation -- ourselves here. -- This not only saves one emulated process spawn call, but also gives us -- full control over the linker command line, allowing us to place the map -- file under `obj/` rather than next to the binary in `bin/`. -- Thankfully, we can even omit the directory for Borland's C standard -- library and rely on `TLINK.CFG` to supply it. Deriving it from the -- `PATH` would be quite annoying on Windows 9x… local lflags = string.format("-c %s ", self.lflags) if model_c then lflags = string.format("%sc0%s.obj", lflags, model_c) end -- Can't use %f because we need backslashes… local libs = "" for _, obj in pairs(objs) do if (obj:sub(-4) == ".lib") then libs = (libs .. obj:gsub("/", "\\") .. " ") else lflags = (lflags .. " " .. obj:gsub("/", "\\")) end end lflags = string.format("%s, %s, %s, %s", lflags, bin_fn, map_fn, libs) if model_c then local model_math = (model_c == "t" and "s" or model_c) lflags = string.format( "%semu.lib math%s.lib c%s.lib", lflags, model_math, model_c ) end objs += Rules:add_32({}, "echo", (lflags .. ">%o"), rsp_fn) local outputs = { bin_fn, map_fn } return Rules:add_16(objs, "tlink", ("@" .. rsp_fn), outputs)[1] end -- Additional generally good compilation flags. Should be used for all code -- that does not need to match the original binaries. local optimized_cfg = Config:branch({ cflags = "-G -k- -p -x-" }) -- Pipeline -- -------- local pipeline_cfg = optimized_cfg:branch(Subdir("Pipeline/"), { cflags = "-IPipeline/", }) local pipeline_tool_cfg = pipeline_cfg:branch(MODEL_TINY) local pipeline_stub_cfg = pipeline_cfg:branch(MODEL_ASM) pipeline_tool_cfg:link("grzview", { "Pipeline/grzview.cpp", "th01/formats/grz.cpp", "platform/x86real/pc98/palette.cpp", "bin/masters.lib", }) local bmp2arr = pipeline_tool_cfg:link("bmp2arr", { "Pipeline/bmp2arrl.c", "Pipeline/bmp2arr.c", }) ---@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 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 args = string.format( "-q -i %%f -o %%o -sym %s -of %s -sw %d -sh %d%s", sym, bmp[2], bmp[4], bmp[5], additional ) return Rules:add_16(inputs, bmp2arr, args, out_fn)[1] end ---@param bmps BMPShape[] ---@return table 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 ---@param input string function Config:stub(input) local obj_fn = self:build({ input })[1] local bin_fn = obj_fn:gsub("%..+$", ".bin") local args = string.format("-x -t %s, %s", obj_fn, bin_fn) return Rules:add_16(obj_fn, "tlink", args:gsub("/", "\\"), bin_fn)[1] end local zungen = pipeline_tool_cfg:link("zungen", { "Pipeline/zungen.c" }) local comcstm = pipeline_tool_cfg:link("comcstm", { "Pipeline/comcstm.c" }) local zun_stub = pipeline_stub_cfg:stub("Pipeline/zun_stub.asm") local cstmstub = pipeline_stub_cfg:stub("Pipeline/cstmstub.asm") ---@param bin_fn string ---@param procs [string, string][] [Menu name, input filename] function Config:zungen(bin_fn, procs) local rsp_fn = string.format( "%s%s.@z", self.obj_root, tup.base(bin_fn) ):gsub("/", "\\") local inputs = { extra_inputs = { zungen, zun_stub, rsp_fn }} local names = "" local fns = "" for _, proc in pairs(procs) do inputs += { proc[2] } names = string.format("%s %s", names, proc[1]) fns = string.format("%s %s", fns, proc[2]) end Rules:add_32( {}, "echo", string.format("%d%s%s>%%o", #procs, names, fns), rsp_fn ) return Rules:add_16(inputs, zungen, "%2i %3i %o", bin_fn)[1] end ---@param out_basename string ---@param prog_fn string ---@param usage_fn string ---@param timestamp number function Config:comcstm(out_basename, usage_fn, prog_fn, timestamp) local inputs = { comcstm, usage_fn, prog_fn, cstmstub } local cmd = string.format("%%2f %%3f %%4f %d %%o", timestamp) return Rules:add_16( inputs, comcstm, cmd, (self.bin_root .. out_basename) )[1] 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) ret.cflags = 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 }, }) local th01_zunsoft = th01:branch(MODEL_TINY):link("zunsoft", { "th01/zunsoft.cpp", "bin/masters.lib", }) th01:branch(MODEL_LARGE, { cflags = "-DBINARY='O'" }):link("op", { piloadc, "th01/op_01.cpp", "th01/frmdelay.cpp", { "th01/vsync.cpp", extra_inputs = th01_sprites["mousecur"] }, "th01/ztext.cpp", "th01/initexit.cpp", "th01/graph.cpp", "th01/ptn_0to1.cpp", "th01/vplanset.cpp", "th01/op_07.cpp", "th01/grp_text.cpp", "th01/ptn.cpp", "th01/op_09.cpp", "th01/f_imgd.cpp", "th01/grz.cpp", "th01_op.asm", "th01/resstuff.cpp", "th01/mdrv2.cpp", "th01/pf.cpp", }) th01:branch(MODEL_LARGE, { cflags = "-DBINARY='M'" }):link("reiiden", { piloadc, "th01/main_01.cpp", "th01/frmdelay.cpp", { "th01/vsync.cpp", extra_inputs = th01_sprites["mousecur"] }, "th01/ztext.cpp", "th01/initexit.cpp", "th01/graph.cpp", "th01/ptn_0to1.cpp", "th01/vplanset.cpp", "th01/main_07.cpp", "th01/ptn.cpp", "th01/main_08.cpp", "th01/f_imgd.cpp", "th01/grz.cpp", "th01_reiiden.asm", { "th01/main_09.cpp", extra_inputs = th01_sprites["pellet_c"] }, "th01/bullet_l.cpp", "th01/grpinv32.cpp", "th01/resstuff.cpp", "th01/scrollup.cpp", "th01/egcrows.cpp", { "th01/pgtrans.cpp", extra_inputs = th01_sprites["ileave_m"] }, "th01/2x_main.cpp", "th01/egcwave.cpp", "th01/grph1to0.cpp", "th01/main_14.cpp", { "th01/main_15.cpp", extra_inputs = th01_sprites["laser_s"] }, "th01/mdrv2.cpp", "th01/main_17.cpp", { "th01/main_18.cpp", extra_inputs = th01_sprites["bonusbox"] }, "th01/main_19.cpp", "th01/main_20.cpp", "th01/main_21.cpp", "th01/pf.cpp", { "th01/main_23.cpp", extra_inputs = th01_sprites["shape8x8"] }, "th01/main_24.cpp", "th01/main_25.cpp", "th01/main_26.cpp", "th01/main_27.cpp", "th01/main_28.cpp", { "th01/main_29.cpp", extra_inputs = th01_sprites["pillar"] }, "th01/main_30.cpp", "th01/main_31.cpp", "th01/main_32.cpp", "th01/main_33.cpp", "th01/main_34.cpp", "th01/main_35.cpp", { "th01/main_36.cpp", extra_inputs = { th01_sprites["leaf_s"], th01_sprites["leaf_l"], th01_sprites["leaf_r"], } }, "th01/main_37.cpp", { "th01/main_38.cpp", extra_inputs = th01_sprites["pellet"] }, }) th01:branch(MODEL_LARGE, { cflags = "-DBINARY='E'" }):link("fuuin", { piloadc, "th01/fuuin_01.cpp", "th01/input_mf.cpp", "th01/fuuin_02.cpp", "th01/fuuin_03.cpp", "th01/fuuin_04.cpp", { "th01/vsync.cpp", extra_inputs = th01_sprites["mousecur"] }, "th01/ztext.cpp", "th01/initexit.cpp", "th01/graph.cpp", "th01/grp_text.cpp", "th01/fuuin_10.cpp", "th01/f_imgd_f.cpp", "th01/vplanset.cpp", "th01/fuuin_11.cpp", "th01/2x_fuuin.cpp", "th01/mdrv2.cpp", "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:branch(MODEL_ASM):link("zuninit", { "th02_zuninit.asm", }) th02:zungen("bin/th02/zun.com", { { "ONGCHK", "libs/kaja/ongchk.com" }, { "ZUNINIT", th02_zuninit }, { "ZUN_RES", th02:branch(MODEL_TINY):link("zun_res", { "th02/zun_res1.cpp", "th02/zun_res2.cpp", "bin/masters.lib", }) }, { "ZUNSOFT", th01_zunsoft }, }) th02:branch(MODEL_LARGE):link("op", { "th02/op_01.cpp", "th02/exit_dos.cpp", "th02/zunerror.cpp", "th02/grppsafx.cpp", "th02_op.asm", "th01/vplanset.cpp", "th02/pi_load.cpp", "th02/grp_rect.cpp", "th02/frmdely2.cpp", "th02/input_rs.cpp", "th02/initop.cpp", "th02/exit.cpp", "th02/snd_mmdr.c", "th02/snd_mode.c", "th02/snd_pmdr.c", "th02/snd_load.cpp", "th02/pi_put.cpp", "th02/snd_kaja.cpp", "th02/op_02_3.cpp", "th02/snd_se_r.cpp", "th02/snd_se.cpp", "th02/frmdely1.cpp", "th02/op_03.cpp", "th02/globals.cpp", "th02/op_04.cpp", "th02/op_05.cpp", "th02/op_music.cpp", }) th02:branch(MODEL_LARGE, { cflags = "-DBINARY='M'" }):link("main", { { "th02_main.asm", extra_inputs = { th02_sprites["pellet"], th02_sprites["bombpart"], th02_sprites["sparks"], th02_sprites["pointnum"], } }, "th02/tile.cpp", "th02/pointnum.cpp", "th02/item.cpp", "th02/hud.cpp", "th02/player_b.cpp", "th02/zunerror.cpp", "th02/keydelay.cpp", "th02/main02_1.cpp", "th01/vplanset.cpp", "th02/pi_load.cpp", "th02/vector.cpp", "th02/frmdely1.cpp", "th02/input_rs.cpp", "th02/exit.cpp", "th02/snd_mmdr.c", "th02/snd_mode.c", "th02/snd_pmdr.c", "th02/snd_dlyv.c", "th02/snd_load.cpp", "th02/mpn_l_i.cpp", "th02/initmain.cpp", "th02/pi_put.cpp", "th02/snd_kaja.cpp", "th02/snd_dlym.cpp", "th02/snd_se_r.cpp", "th02/snd_se.cpp", "th02/main_03.cpp", "th02/hud_ovrl.cpp", "th02/dialog.cpp", "th02/boss_5.cpp", "th02/regist_m.cpp", }) th02:branch(MODEL_LARGE, { cflags = "-DBINARY='E'" }):link("maine", { { "th02/end.cpp", extra_inputs = th02_sprites["verdict"] }, "th02_maine.asm", "th02/grppsafx.cpp", "th02/keydelay.cpp", "th01/vplanset.cpp", "th02/pi_load.cpp", "th02/frmdely1.cpp", "th02/maine022.cpp", "th02/input_rs.cpp", "th02/exit.cpp", "th02/snd_mmdr.c", "th02/snd_mode.c", "th02/snd_pmdr.c", "th02/snd_load.cpp", "th02/initmain.cpp", "th02/pi_put.cpp", "th02/snd_kaja.cpp", "th02/snd_dlym.cpp", "th02/globals.cpp", "th02/maine_03.cpp", "th02/maine_04.cpp", "th02/staff.cpp", }) -- ---- -- TH03 -- ---- local th03_sprites = Sprites({ { "th03/sprites/score.bmp", "asm", "sSCORE_FONT", 8, 8, "-u" }, }) th03:zungen("bin/th03/zun.com", { { "-1", "libs/kaja/ongchk.com" }, { "-2", th02_zuninit }, { "-3", th01_zunsoft }, { "-4", th03:branch(MODEL_ASM):link("zunsp", { sprite16 }) }, { "-5", th03:branch(MODEL_TINY):link("res_yume", { "th03/res_yume.cpp", "bin/masters.lib", })} }) th03:branch(MODEL_LARGE, { cflags = "-DBINARY='O'" }):link("op", { "th03/op_01.cpp", "th03_op2.asm", "th03/op_music.cpp", "th03/op_02.cpp", "th03/scoredat.cpp", "th03/op_03.cpp", "th03_op.asm", "th02/exit_dos.cpp", "th01/vplanset.cpp", "th02/snd_mode.c", "th02/snd_pmdr.c", "th02/snd_load.cpp", "th03/exit.cpp", "th03/polar.cpp", "th03/cdg_put.asm", "th02/frmdely1.cpp", "th03/input_s.cpp", "th03/pi_put.cpp", "th03/snd_kaja.cpp", "th03/initop.cpp", "th03/cdg_load.cpp", "th03/grppsafx.cpp", "th03/pi_load.cpp", "th03/inp_m_w.cpp", "th03/cdg_p_na.asm", "th03/hfliplut.asm", "th02/frmdely2.cpp", }) th03:branch(MODEL_LARGE):link("main", { { "th03_main.asm", extra_inputs = th03_sprites["score"] }, "th03/playfld.cpp", "th03/cfg_lres.cpp", "th03/hitcirc.cpp", "th03/player_m.cpp", "th03/main_010.cpp", "th03/main_011.cpp", "th01/vplanset.cpp", "th02/snd_mode.c", "th02/snd_pmdr.c", "th03/vector.cpp", "th03/exit.cpp", "th03/polar.cpp", "th02/frmdely1.cpp", "th03/input_s.cpp", "th02/snd_se_r.cpp", "th03/snd_se.cpp", "th03/snd_kaja.cpp", "th03/initmain.cpp", "th03/pi_load.cpp", "th03/inp_m_w.cpp", "th03/collmap.asm", "th03/hfliplut.asm", "th03/mrs.cpp", "th03/sprite16.cpp", }) th03:branch(MODEL_LARGE, { cflags = "-DBINARY='L'" }):link("mainl", { "th03/cfg_lres.cpp", "th03/mainl_sc.cpp", "th03_mainl.asm", "th03/cutscene.cpp", "th03/scoredat.cpp", "th03/regist.cpp", "th01/vplanset.cpp", "th02/snd_mode.c", "th02/snd_pmdr.c", "th02/snd_dlyv.c", "th02/snd_load.cpp", "th03/vector.cpp", "th03/exit.cpp", "th03/cdg_put.asm", "th02/frmdely1.cpp", "th03/input_s.cpp", "th03/pi_put.cpp", "th03/pi_put_i.cpp", "th02/snd_se_r.cpp", "th03/snd_se.cpp", "th03/snd_kaja.cpp", "th03/initmain.cpp", "th03/cdg_load.cpp", "th03/exitmain.cpp", "th03/grppsafx.cpp", "th03/snd_dlym.cpp", "th03/inp_wait.cpp", "th03/pi_load.cpp", "th03/pi_put_q.cpp", "th03/inp_m_w.cpp", "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", { { "-O", "libs/kaja/ongchk.com" }, { "-I", th04:branch(MODEL_ASM):link("zuninit", { "th04_zuninit.asm" }) }, { "-S", th04:branch(MODEL_TINY):link("res_huma", { "th04/res_huma.cpp", "bin/masters.lib", }) }, { "-M", th04:branch(MODEL_TINY):link("memchk", { "th04_memchk.asm" }) }, }) th04:comcstm("zun.com", "th04/zun.txt", th04_zuncom, 621381155) th04:branch(MODEL_LARGE):link("op", { "th04/op_main.cpp", { "th04_op_master.asm", o = "opm.obj" }, "th01/vplanset.cpp", "th02/frmdely1.cpp", "th03/pi_put.cpp", "th03/pi_load.cpp", "th03/hfliplut.asm", "th04/input_w.cpp", "th04/vector.cpp", "th04/snd_pmdr.c", "th04/snd_mmdr.c", "th04/snd_kaja.cpp", "th04/cdg_p_nc.asm", "th04/snd_mode.cpp", "th04/snd_dlym.cpp", "th02/exit_dos.cpp", "th04/snd_load.cpp", "th04/grppsafx.asm", "th04_op2.asm", "th04/cdg_put.asm", "th04/exit.cpp", "th04/initop.cpp", "th04/cdg_p_na.cpp", "th04/input_s.asm", "th02/snd_se_r.cpp", "th04/snd_se.cpp", "th04/egcrect.cpp", "th04/bgimage.cpp", "th04/bgimager.asm", "th04/cdg_load.asm", "th02/frmdely2.cpp", "th04/op_setup.cpp", "th04/zunsoft.cpp", "th04/op_music.cpp", "th04_op.asm", "th04/m_char.cpp", }) th04:branch(MODEL_LARGE):link("main", { { "th04_main.asm", extra_inputs = { th02_sprites["pellet"], th02_sprites["sparks"], th04_sprites["pelletbt"], th04_sprites["pointnum"], } }, "th04/slowdown.cpp", "th04/demo.cpp", "th04/ems.cpp", "th04/tile_set.cpp", "th04/std.cpp", "th04/tile.cpp", "th04/playfld.cpp", "th04/midboss4.cpp", "th04/f_dialog.cpp", "th04/dialog.cpp", "th04/boss_exp.cpp", "th04/stages.cpp", "th04/player_m.cpp", "th04/player_p.cpp", "th04/scoreupd.asm", "th04/hud_ovrl.cpp", "th04/cfg_lres.cpp", "th04/checkerb.cpp", "th04/mb_inv.cpp", "th04/boss_bd.cpp", "th01/vplanset.cpp", "th03/vector.cpp", "th02/frmdely1.cpp", "th03/hfliplut.asm", "th04/mpn_free.cpp", "th04/input_w.cpp", "th04/mpn_l_i.cpp", "th04/vector.cpp", "th04/snd_pmdr.c", "th04/snd_mmdr.c", "th04/snd_kaja.cpp", "th04/snd_mode.cpp", "th04/snd_load.cpp", "th04/cdg_put.asm", "th04/exit.cpp", "th04/initmain.cpp", "th04/cdg_p_na.cpp", "th04/cdg_p_pr.asm", "th04/input_s.asm", "th02/snd_se_r.cpp", "th04/snd_se.cpp", "th04/cdg_load.asm", "th04/gather.cpp", "th04/scrolly3.cpp", "th04/motion_3.asm", "th04/midboss.cpp", "th04/hud_hp.cpp", "th04/mb_dft.cpp", "th04/vector2n.asm", "th04/spark_a.asm", "th04/grcg_3.cpp", "th04/it_spl_u.cpp", "th04/boss_4m.cpp", "th04/bullet_u.cpp", "th04/bullet_a.cpp", "th04/boss.cpp", "th04/boss_4r.cpp", "th04/boss_x2.cpp", }) th04:branch(MODEL_LARGE):link("maine", { "th04/maine_e.cpp", { "th04_maine_master.asm", o = "mainem.obj" }, "th01/vplanset.cpp", "th02/frmdely1.cpp", "th03/pi_put.cpp", "th03/pi_load.cpp", "th03/pi_put_q.cpp", "th03/hfliplut.asm", "th04/input_w.cpp", "th04/vector.cpp", "th04/snd_pmdr.c", "th04/snd_mmdr.c", "th04/snd_kaja.cpp", "th04/snd_mode.cpp", "th04/snd_dlym.cpp", "th04/cdg_p_pl.asm", "th04/snd_load.cpp", "th04/grppsafx.asm", "th04_maine.asm", "th04/cdg_put.asm", "th04/exit.cpp", "th04/initmain.cpp", "th04/input_s.asm", "th02/snd_se_r.cpp", "th04/snd_se.cpp", "th04/bgimage.cpp", "th04/bgimager.asm", "th04/cdg_load.asm", "th04/cutscene.cpp", "th04/staff.cpp", }) -- ---- -- 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", { { "-O", "libs/kaja/ongchk.com" }, { "-I", th05:branch(MODEL_ASM):link("zuninit", { "th05_zuninit.asm" }) }, { "-S", th05:branch(MODEL_TINY):link("res_kso", { "th05/res_kso.cpp", "bin/masters.lib", }) }, { "-G", th05:branch(MODEL_ASM):link("gjinit", { { "th05_gjinit.asm", extra_inputs = th05_sprites["gaiji"] }, }) }, { "-M", th05:branch(MODEL_ASM):link("memchk", { "th05_memchk.asm" }) }, }) th05:comcstm("zun.com", "th05/zun.txt", th05_zuncom, 628731748) th05:branch(MODEL_LARGE):link("op", { "th05/op_main.cpp", { "th05_op_master.asm", o = "opm.obj" }, "th03/hfliplut.asm", "th04/snd_pmdr.c", "th04/snd_mmdr.c", "th04/snd_mode.cpp", "th02/exit_dos.cpp", "th04/grppsafx.asm", { "th05_op2.asm", extra_inputs = th05_sprites["piano_l"] }, "th04/cdg_p_na.cpp", "th02/snd_se_r.cpp", "th04/snd_se.cpp", "th04/bgimage.cpp", "th05/cdg_put.asm", "th04/exit.cpp", "th05/vector.cpp", "th05/musicp_c.cpp", "th05/musicp_a.asm", "th05/bgimager.asm", "th05/snd_load.cpp", "th05/snd_kaja.cpp", "th05/pi_cpp_1.cpp", "th05/pi_asm_1.asm", "th05/pi_cpp_2.cpp", "th05/pi_asm_2.asm", "th05/initop.cpp", "th05/input_s.asm", "th05/inp_h_w.cpp", "th05/snd_dlym.cpp", "th05/cdg_p_nc.cpp", "th05/frmdelay.cpp", "th04/cdg_load.asm", "th05/egcrect.cpp", "th05/op_setup.cpp", "th04/zunsoft.cpp", "th05/cfg.cpp", "th05/op_title.cpp", "th05/op_music.cpp", "th05_op.asm", "th05/hi_view.cpp", "th05/m_char.cpp", }) th05:branch(MODEL_LARGE):link("main", { { "th05_main.asm", extra_inputs = { th02_sprites["pellet"], th02_sprites["sparks"], th04_sprites["pelletbt"], th04_sprites["pointnum"], } }, "th04/slowdown.cpp", "th05/demo.cpp", "th05/ems.cpp", "th05/cfg_lres.cpp", "th04/tile.cpp", "th05/main010.cpp", "th05/f_dialog.cpp", "th05/dialog.cpp", "th05/boss_exp.cpp", "th05/playfld.cpp", "th04/mb_inv.cpp", "th04/boss_bd.cpp", "th05/boss_bg.cpp", "th05/laser_rh.cpp", "th05/p_common.cpp", "th05/p_reimu.cpp", "th05/p_marisa.cpp", "th05/p_mima.cpp", "th05/p_yuuka.cpp", "th05/player.asm", "th05/hud_bar.asm", "th05/scoreupd.asm", "th05/midboss5.cpp", "th05/hud_ovrl.cpp", "th04/player_p.cpp", "th04/vector2n.asm", "th05/spark_a.asm", "th05/bullet_p.cpp", "th04/grcg_3.cpp", "th05/player_a.cpp", "th05/bullet_1.asm", "th05/bullet_c.cpp", "th05/bullet.asm", "th05/bullet_t.cpp", "th03/vector.cpp", "th03/hfliplut.asm", "th04/snd_pmdr.c", "th04/snd_mmdr.c", "th04/snd_mode.cpp", "th04/cdg_p_na.cpp", "th02/snd_se_r.cpp", "th04/snd_se.cpp", "th05/cdg_put.asm", "th04/exit.cpp", "th05/vector.cpp", "th05/snd_load.cpp", "th05/snd_kaja.cpp", "th05/initmain.cpp", "th05/input_s.asm", "th05/inp_h_w.cpp", "th05/frmdelay.cpp", "th04/cdg_load.asm", "th04/scrolly3.cpp", "th04/motion_3.asm", "th05/gather.cpp", "th05/main032.cpp", "th05/midboss.cpp", "th04/hud_hp.cpp", "th05/mb_dft.cpp", "th05/laser.cpp", "th05/cheeto_u.cpp", "th04/it_spl_u.cpp", "th05/bullet_u.cpp", "th05/midboss1.cpp", "th05/boss_1.cpp", "th05/boss_4.cpp", "th05/boss_6.cpp", "th05/boss_x.cpp", "th05/boss.cpp", "th05/main014.cpp", }) th05:branch(MODEL_LARGE):link("maine", { "th05/maine_e.cpp", { "th05_maine_master.asm", o = "mainem.obj" }, "th03/hfliplut.asm", "th04/snd_pmdr.c", "th04/snd_mmdr.c", "th04/snd_mode.cpp", "th04/grppsafx.asm", "th05_maine.asm", "th04/cdg_p_na.cpp", "th02/snd_se_r.cpp", "th04/snd_se.cpp", "th04/bgimage.cpp", "th04/exit.cpp", "th05/vector.cpp", "th05/bgimager.asm", "th05/snd_load.cpp", "th05/snd_kaja.cpp", "th05/pi_cpp_1.cpp", "th05/pi_asm_1.asm", "th05/pi_cpp_2.cpp", "th05/pi_asm_2.asm", "th05/initmain.cpp", "th05/input_s.asm", "th05/inp_h_w.cpp", "th05/snd_dlym.cpp", "th05/frmdelay.cpp", "th04/cdg_load.asm", "th05/egcrect.cpp", "th05/cutscene.cpp", "th05/regist.cpp", "th05/staff.cpp", }) -- ---- -- Research -- -------- local research_cfg = optimized_cfg:branch(Subdir("Research/"), MODEL_SMALL) research_cfg:link("holdkey", { "Research/holdkey.c", "bin/masters.lib", }) local research_sprites = Sprites({ { "Research/blitperf.bmp", "cpp", "sBLITPERF", 16, 16 } }) -- Must be an ordered table to retain the order for `build_dumb.bat`. for _, t in pairs({ { "8086", " -1-" }, { "286", " -2" }, { "386", "" } }) do local cfg = research_cfg:branch({ obj_root = (t[1] .. "/"), cflags = string.format("-DCPU=%s%s", t[1], t[2]), }) cfg:link(("blit" .. t[1]), { -- Bypass `PreviousOutputForSource` by explicitly building each unit. cfg:build_uncached({ "Research/blitperf.cpp", extra_inputs = { research_sprites["blitperf"], th01_sprites["pellet"], } }), cfg:build_uncached("platform/x86real/noexcept.cpp"), cfg:build_uncached("platform/x86real/pc98/blitter.cpp"), cfg:build_uncached("platform/x86real/pc98/font.cpp"), cfg:build_uncached("platform/x86real/pc98/graph.cpp"), cfg:build_uncached("platform/x86real/pc98/grcg.cpp"), cfg:build_uncached("platform/x86real/pc98/palette.cpp"), cfg:build_uncached("platform/x86real/pc98/vsync.cpp"), }) end -- -------- Rules:print()