From 6b0f6176f6a86c96efb3bc452405e1ba9b7439f9 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 8 Jul 2012 21:47:06 +0000 Subject: [PATCH] Add LuaJIT-based BUILD map loader and batch processing script + example. git-svn-id: https://svn.eduke32.com/eduke32@2813 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/lunatic/build.lua | 175 ++++++++++++++++++ polymer/eduke32/source/lunatic/foreachmap.lua | 34 ++++ polymer/eduke32/source/lunatic/mapstats.lua | 26 +++ 3 files changed, 235 insertions(+) create mode 100644 polymer/eduke32/source/lunatic/build.lua create mode 100755 polymer/eduke32/source/lunatic/foreachmap.lua create mode 100644 polymer/eduke32/source/lunatic/mapstats.lua diff --git a/polymer/eduke32/source/lunatic/build.lua b/polymer/eduke32/source/lunatic/build.lua new file mode 100644 index 000000000..383e9b228 --- /dev/null +++ b/polymer/eduke32/source/lunatic/build.lua @@ -0,0 +1,175 @@ + +-- Loaders for various BUILD structures for LuaJIT + +-- TODO: bound-checking, load ART + + +local ffi = require "ffi" +local io = require "io" + +local assert = assert +local print = print + +module(...) + +ffi.cdef[[ +#pragma pack(push,1) +typedef struct +{ + int16_t wallptr, wallnum; + int32_t ceilingz, floorz; + int16_t ceilingstat, floorstat; + int16_t ceilingpicnum, ceilingheinum; + int8_t ceilingshade; + uint8_t ceilingpal, ceilingxpanning, ceilingypanning; + int16_t floorpicnum, floorheinum; + int8_t floorshade; + uint8_t floorpal, floorxpanning, floorypanning; + uint8_t visibility, filler; + int16_t lotag, hitag, extra; +} sectortype; + +typedef struct +{ + int32_t x, y; + int16_t point2, nextwall, nextsector; + int16_t cstat; + int16_t picnum, overpicnum; + int8_t shade; + uint8_t pal, xrepeat, yrepeat, xpanning, ypanning; + int16_t lotag, hitag, extra; +} walltype; + +typedef struct +{ + int32_t x, y, z; + int16_t cstat, picnum; + int8_t shade; + uint8_t pal, clipdist, filler; + uint8_t xrepeat, yrepeat; + int8_t xoffset, yoffset; + int16_t sectnum, statnum; + int16_t ang, owner, xvel, yvel, zvel; + int16_t lotag, hitag, extra; +} spritetype; +]] + +local C = ffi.C + + +local MAX = +{ + SECTORS = { [7]=1024, [8]=4096, [9]=4096 }, + WALLS = { [7]=8192, [8]=16384, [9]=16384 }, + SPRITES = { [7]=4096, [8]=16384, [9]=16384 }, +} + +local function doread(fh, basectype, numelts) + local cd = ffi.new(basectype.."[?]", numelts) + local size = ffi.sizeof(cd) + + if (numelts==0) then + return nil + end + + assert(size % numelts == 0) + local datstr = fh:read(size) + + if (datstr == nil or #datstr < size) then + fh:close() + return nil + end + + ffi.copy(cd, datstr, size) + + return cd +end + +--== LOADBOARD ==-- +-- returns: +-- on failure, nil, errmsg +-- on success, a table +-- { +-- version = , +-- numsectors=, numwalls=, numsprites=, +-- sector=, +-- wall=, +-- sprite=nil or (array of spritetype), +-- start = +-- { x=, y=, z=, ang=, sectnum= } +-- } +function loadboard(filename) + local fh, errmsg = io.open(filename) + + if (fh==nil) then + return nil, errmsg + end + + -- The table we'll return on success + local map = { start={} } + + local cd = doread(fh, "int32_t", 4) + if (cd==nil) then + return nil, "Couldn't read header" + end + + map.version = cd[0] + map.start.x = cd[1] + map.start.y = cd[2] + map.start.z = cd[3] + + if (map.version < 7 or map.version > 9) then + fh:close() + return nil, "Invalid map version" + end + + cd = doread(fh, "int16_t", 3) + if (cd==nil) then + return nil, "Couldn't read header (2)" + end + + map.start.ang = cd[0] + map.start.sectnum = cd[1] + + -- sectors + map.numsectors = cd[2] + if (map.numsectors <= 0 or map.numsectors > MAX.SECTORS[map.version]) then + fh:close() + return nil, "Invalid number of sectors" + end + + map.sector = doread(fh, "sectortype", map.numsectors) + if (map.sector == nil) then + return nil, "Couldn't read sectors" + end + + -- walls + cd = doread(fh, "int16_t", 1) + map.numwalls = cd[0] + if (map.numwalls <= 0 or map.numwalls > MAX.WALLS[map.version]) then + fh:close() + return nil, "Invalid number of walls" + end + + map.wall = doread(fh, "walltype", map.numwalls) + if (map.wall == nil) then + return nil, "Couldn't read walls" + end + + -- sprites + cd = doread(fh, "int16_t", 1) + map.numsprites = cd[0] + if (map.numsprites < 0 or map.numsprites > MAX.SPRITES[map.version]) then + fh:close() + return nil, "Invalid number of sprites" + end + + map.sprite = doread(fh, "spritetype", map.numsprites) + if (map.numsprites~=0 and map.sprite == nil) then + return nil, "Couldn't read sprites" + end + + -- done + fh:close() + return map +end diff --git a/polymer/eduke32/source/lunatic/foreachmap.lua b/polymer/eduke32/source/lunatic/foreachmap.lua new file mode 100755 index 000000000..52bb16f1c --- /dev/null +++ b/polymer/eduke32/source/lunatic/foreachmap.lua @@ -0,0 +1,34 @@ +#!/usr/local/bin/luajit + +-- Generic map iterator. + +-- The first cmdline arg is a name of a lua file (may be sans .lua) which must +-- be a module and is `require'd into this script, e.g. "stats" or "stats.lua". +-- Then, for each 2nd and following argument, if map loading succeeds, +-- .success(map, filename) is run, otherwise .failure(filename, errmsg) -- +-- these must be functions in the loaded module. + +-- TODO: aggregate batch mode + + +if (#arg < 1) then + error("Usage: luajit ./foreachmap ...") +end + +local B = require "build" +local string = require "string" + +local modname = string.gsub(arg[1], "%.lua$", "") +local mod = require(modname) + + +for i=2,#arg do + local fn = arg[i] + local map, errmsg = B.loadboard(fn) + + if (map ~= nil) then + mod.success(map, fn) + else + mod.failure(fn, errmsg) + end +end diff --git a/polymer/eduke32/source/lunatic/mapstats.lua b/polymer/eduke32/source/lunatic/mapstats.lua new file mode 100644 index 000000000..d68076fea --- /dev/null +++ b/polymer/eduke32/source/lunatic/mapstats.lua @@ -0,0 +1,26 @@ + +-- Print out some statistics for a BUILD map, +-- foreachmap module. + +local string = require "string" +local print = print + +module(...) + + +local function printf(fmt, ...) + print(string.format(fmt, ...)) +end + + +function success(map, fn) + printf("--- %s:", fn) + + printf(" version: %d", map.version) + printf(" numsectors: %d\n numwalls: %d\n numsprites: %d", + map.numsectors, map.numwalls, map.numsprites) +end + +function failure(fn, errmsg) + printf("--- %s: %s", fn, errmsg) +end