the cutting room mirror

Source Code

This is a sub-page of Mojibribon.

1/03F6A7E1/list.lua#

DYNAMIC_TEXTURES = nil

MANUAL_TEXTURES = nil

AUTO_TEXTURES = {"alart.tm2", "base_kado640.tm2", "base_naka640.tm2", "batsu.tm2", "batsu2.tm2", "button_hi.tm2", "chara_mj.tm2", "chara_mk.tm2", "chara_os.tm2", "ed_A.tm2", "ed_B.tm2", "ed_C.tm2", "ed_moji.tm2", "henkan.tm2", "henkan_naka.tm2", "in_A.tm2", "in_B.tm2", "in_C.tm2", "in_D.tm2", "in_E.tm2", "in_F_left.tm2", "in_F_right.tm2", "in_H.tm2", "maru_eg.tm2", "maru_hira.tm2", "maru_hira2.tm2", "mb.tm2", "mk.tm2", "os.tm2", "sankaku.tm2", "seal_mb.tm2", "seal_mk.tm2", "seal_oz.tm2", "select.tm2", "select_moji.tm2", "select_moji2.tm2", "sikaku.tm2", "start.tm2", "start_moji.tm2", "transp.tm2", "txted_waku1_1.tm2", "txted_waku1_2.tm2", "txted_waku2_1.tm2", "txted_waku2_2.tm2", "txted_waku2_3.tm2", "waku.tm2", "waku_a.tm2", "waku_b.tm2", "waku_c.tm2", "yk_a.tm2", "wakka.tm2", "yk_b.tm2", "yomi.tm2", "circle.tm2", "square.tm2", "triangle.tm2", "x.tm2", "cursor.tm2", "fan_help.tm2", "fan_retry.tm2", "fan_syosai.tm2", "fan_goroku.tm2", "fan_kettei.tm2", "fan_yameru.tm2", "fan_yes.tm2", "fan_no.tm2", "alert.tm2", "alert_edge.tm2", "moji_l.tm2", "moji_2.tm2", "stick_mk.tm2", "stick_mk2.tm2", "yg.tm2", "yg_naka.tm2", "lip_0.tm2", "moji_hida.tm2", "moji_migi.tm2", "txted_waku4.tm2", "c_decide.tm2", "in_E2.tm2"}
maru_eg.tm2

2/10AE9F72/list.lua#

DYNAMIC_TEXTURES = nil

MANUAL_TEXTURES = nil

AUTO_TEXTURES = {"eruption.tm2", "fude8e.tm2", "light_mask.tm2", "mb_e.tm2", "mb_ha.tm2", "mb_i.tm2", "mb_ka.tm2", "mb_ke.tm2", "mb_mi.tm2", "mb_mo.tm2", "mb_n.tm2", "mb_ni.tm2", "mb_no.tm2", "mb_nu.tm2", "mb_ri.tm2", "mb_si.tm2", "mb_tu.tm2", "mb_wa.tm2", "mb_ya.tm2", "mk_a.tm2", "mk_ba.tm2", "mk_e.tm2", "mk_ha.tm2", "mk_he.tm2", "mk_hi.tm2", "mk_ho.tm2", "mk_hu.tm2", "mk_i.tm2", "mk_ka.tm2", "mk_ke.tm2", "mk_ki.tm2", "mk_ko.tm2", "mk_ku.tm2", "mk_ma.tm2", "mk_me.tm2", "mk_mi.tm2", "mk_mo.tm2", "mk_mu.tm2", "mk_n.tm2", "mk_na.tm2", "mk_ne.tm2", "mk_ni.tm2", "mk_no.tm2", "mk_nu.tm2", "mk_o.tm2", "mk_ra.tm2", "mk_re.tm2", "mk_ri.tm2", "mk_ro.tm2", "mk_ru.tm2", "mk_sa.tm2", "mk_se.tm2", "mk_si.tm2", "mk_so.tm2", "mk_su.tm2", "mk_ta.tm2", "mk_te.tm2", "mk_ti.tm2", "mk_to.tm2", "mk_tu.tm2", "mk_u.tm2", "mk_wa.tm2", "mk_wo.tm2", "mk_ya.tm2", "mk_yo.tm2", "mk_yu.tm2", "mk_zo.tm2", "oz_a.tm2", "oz_e.tm2", "oz_ha.tm2", "oz_he.tm2", "oz_hi.tm2", "oz_ho.tm2", "oz_hu.tm2", "oz_i.tm2", "oz_ka.tm2", "oz_ke.tm2", "oz_ki.tm2", "oz_ko.tm2", "oz_ku.tm2", "oz_ma.tm2", "oz_me.tm2", "oz_mi.tm2", "oz_mo.tm2", "oz_mu.tm2", "oz_n.tm2", "oz_na.tm2", "oz_ne.tm2", "oz_ni.tm2", "oz_no.tm2", "oz_nu.tm2", "oz_o.tm2", "oz_ra.tm2", "oz_re.tm2", "oz_ri.tm2", "oz_ro.tm2", "oz_ru.tm2", "oz_sa.tm2", "oz_se.tm2", "oz_si.tm2", "oz_so.tm2", "oz_su.tm2", "oz_ta.tm2", "oz_te.tm2", "oz_ti.tm2", "oz_to.tm2", "oz_tu.tm2", "oz_u.tm2", "oz_wa.tm2", "oz_wo.tm2", "oz_ya.tm2", "oz_yo.tm2", "oz_yu.tm2", "oz_zi.tm2", "rb.tm2", "ring_mask.tm2", "sel_hai.tm2", "sel_waku.tm2"}mb_e.tm2

3/EBFF0D63/config.lua#

--
-- config file for mojiburibon
--

----
-- SCRIPTING INSTRUCTIONS
--
--  syntax
--      Colors - syntax for specifying colors is
--          Color { r, g, b, a } with range [0.0 .. 1.0] or
--          IntColor { r, g, b, a } with range [1 .. 255],
--          "a" defaults to opaque.
--
--
--  program
--
--      A "program" is a set of parameters for the game.  Some parameters are
--      global while others may be set differently for each stage.  Here is
--      the meaning of each parameter:
--
--          Name - name displayed for program.
--          Info - extra info string
--          IsExtra - 1 for extra stage, else 0
--          IsTest - 1 for test stage, else 0
--
--      Character:
--          GameCharacter - one of MOJIBRI, MOJIKO, OSOREZAN.  Now the
--              character is set by the rap text, so this should be set to
--              match the first speaker.
--          ForceCharacter - set to 1 to ignore rap speaker info and always
--              use GameCharacter graphics.  (for debug-- faster loading!)
--          ForceSubCharacter - If set, force the starting form.  Use 'A',
--              'B', etc.  (for debug)
--          CharaInfo - a list of tables (one per character) containing:
--              BaseDir - root of data files (with trailing slash)
--              ModelBaseDir - root of model data files (with trailing slash)
--              DangoInfo - (see below)
--              ParticleInfo - (see below)
--              Offset - 3D offset of character during game time, in character
--                  model space
--
--      Background:
--          BackgroundSceneDir - location of background graphics data, including
--              trailing slash
--
--      Time signature:
--          Tempo - tempo of the backtrack in beats per minute (bpm).
--          BeatsPerBar - number of beats per bar.
--          PulsesPerBeat - number of pulses per beat.
--          IntroBarCount - number of bars in the intro.
--          ThresholdLeadIntroPulse -- min starting pulse to lead in one
--            bar early.
--          RingBarCount - number of bars on a ring.
--          SlowMinJumpPulseCount - min ring to ring pulses for slow tempo
--          FastMinJumpPulseCount - min ring to ring pulses for fast tempo
--          ThresholdJumpTempo - min tempo to use FastMinJumpPulseCount
--          SlowPaddingPulseCount - ring to ring padding unit for slow tempo
--          FastPaddingPulseCount - ring to ring padding unit for fast tempo
--          ThresholdPaddingTempo - min tempo to use FastPaddingPulseCount
--
--      NOTE ABOUT AUDIO FILES
--
--      Audio file formats:
--        .raw: 16bit, 48khz mono.
--        .pcm: 16bit, 48khz mono.
--        .adpcm: adpcm, 48khz mono.
--        .vag: adpcm with vag header, 48khz mono.
--
--      Audio file parameters marked with (*) are stereo, so left and right
--      channels are required.  You can set just one file name, for example
--      'abc.raw', which will expand to { 'abc_L.raw', 'abc_R.raw' } or
--      specify both names explicitly like { 'left.raw', 'right.raw' }.
--
--      Sound Mix:
--          BackTrackLevel - amplitude of the back track.
--          RapTrackLevel - amplitude of the rap track.
--          MuteRate - mute/unmute rate in dB/sec
--          ForceMono - set to 1 to use left track only of stereo
--              files (for faster loading)
--
--      Sound Effects
--          SoundEffectMain - base name for main effect files (.hd .bd)
--          SoundEffectLevel - amplitude of the sound effects.
--          SoundEffectAuxLevel - amplitude of "minor" sound effects.
--
--      Rap:
--          RapSheetFile - path of rap sheet
--          RapTextFile - path of rap text.  This is used in place of rap
--              sheet (for development only).
--          DumpRap - set to 1 for debug output
--
--      Backtrack:
--          BackTrackIntro (*)
--          BackTrackLoop (*)
--
--      Graphics Parameters:
--          RingWidth - ring width in radians.
--              NOTE: This parameter does not affect glyph and piece sizes,
--                  only tile/paper graphics and character height.  Glyph width
--                  is always 1/pulses_per_ring, with 1:1 aspect.
--          RingSeparation - distance between rings in ring radians
--          RingPattern - sequence of ring counts having syntax:
--                  { advance, curve, climb, curve, ... }
--              Zero values are not allowed, except as a special case the
--              first two values may be zero, resulting in climbing mode start.
--          CharaScale - conversion scale from character space to ring space
--          GlyphScale - 1 is end-to-end
--          PieceScale - 1 is end-to-end
--          DrawRingPaper - 1 to draw ring paper, else 0
--          PaperColor - The ring background color.
--          InkColorBefore/After - glyph colors before and after drawing
--          BumpPattern - This pattern spans one beat and is the scale applied
--              to a piece.  The first value corresponds to the correct tap
--              point.
--          TailBumpPattern - pattern for tail piece
--          StoneIndex - indicates stone to use on this stage (count from 1)
--
--          EnableRingTiles - set to 1 for display of ring tiles
--          TilesPerMora - number of tile objects in one mora space
--          RingTileInfo - list of tile parameter keys for first, second,
--            and last rings.  Parameters not interpolated are taken from
--            the first key.  See example below for parameter details.
--          TilesPerMora2/RingTileInfo2 - same as TilesPerMora/RingTileInfo,
--            but for extra tiles displayed on difficult rings.
--
--      Tap Timing:
--          WriteOffset - positon of drawn glyph relative to glyph under
--            character.  Units of pulse, with positive towards the future.
--          MaxTapLead/Lag - allowed error from correct tap
--            point in pulses (MaxTapLead + MaxTapLag must be less than 1).
--            These are arrays with one value for each form, { A, B, C, D }.
--          MaxReleaseLead/Lag - allowed error from correct release
--            point in pulses
--          MaxTailLead/Lag - allowed error for tail jump tap in pulses
--            (MaxTailLag must be less than 1)
--          Miss/WriteMissLockout - duration of command lockout after miss,
--            in pulses
--          JoyWriteTriggerLevel - joystick Y coordinate distance that defines
--            top and bottom hot areas
--          JoyWriteDecayRate - Controls the write command dampening
--            characteristic.  Units are joystick coordinates per second.
--          JoyWriteTimeout - Timeout of write command in seconds.
--          JoyWriteStrongMin - minimum time to hold top position for strong
--            write in pulses
--
--          NOTES
--            Lead/Lag times are currently referenced from left side of
--              glyph. [Center would be better.]
--            Positive lead times are towards the past, positive lag times
--              are toward the future.  [Positve towards future for both would
--              be better.]
--
--      Scoring:
--          ExpertMinStageRings - min stage rings needed for expert rating
--          ExpertMinGoodRatio  - min ratio of perfect rings for expert rating
--
--      ParticleInfo - a table containing:
--          SourceNodeName      - node index of splash source
--          SourceNodeName2     - secondary source (for mojiko)
--          Texture             - texture name for particle
--          Lifetime            - normal particle lifetime
--          Num                 - maximum partcle number at same time
--          NearSettlePlane     - dist to near settle plane from camera
--          FarSettlePlane      - dist to far settle plane from camera
--          SourceSegment       - source segment in local space
--          SourceSegment2      - secondary source
--          Gravity             - gravity vector
--          Collector           - conv. point for scattered particles
--          ScatteringConvergency - convergency of scattered particles
--          Density             - global particle density
--          SizeVariationRatio  - size randomize level
--          SettledSize         - magnification when settled
--          ScatteringSize      - basic size of scattering particle
--          VelocityToSizeCoefficient - velocity to size relation
--          MaxSize             - maximum initial size
--          DropThresholdSpeed  - threshold speed for drop effect
--          DropSpreadRatio     - divergence for drop particle
--          DropBackwardSpeed   - backward vector for drop particle
--          SpreadRatio         - divergence for all particle
--          ScatteringMinSpeed  - minimum speed for scattering
--          ScatteringMaxSpeed  - maximum speed for scattering
--          SettledAlpha        - mult. for alpha of settled particle
--          ScatteringAlpha     - mult. for alpha of scattering particle
--          ScatteringGeneration - particle gen speed for scattering
--          FrontGrowthSpeed    - mult. for front settled particle
--          ScatteringGrowthSpeed - mult. for scattering particle
--          EnableSplashHole    - make a hole of ink splash and gilding
--          SplashHoleCenter    - center of splash hole (x,y value)
--          SplashHoleRadius    - radius of splash hole
--          SplashHoleOblateness - oblateness of splash hole
--
--          << following is stuff for gilding (confetti) >>
--          GildingNum               - table size for gilding array
--          GildingTexture           - texture filename
--          GildingColor             - diffuse color
--          GildingSpecularColor     - specular color
--          GildingAmbientIntensity  - ambient intensity
--          GildingShininess         - shininess coefficient (nop fixed to 16)
--          GildingLightDirection    - light direction (in global corrdinate)
--          GildingSize              - half size of each piece
--          GildingDensity           - gilding piece num for each piece
--          GildingRotationPeriod    - rotation period (unit is 1/second)
--          GildingClipColor         - satulated color for gilding
--          GildingDivergency        - how fast gilding will be fly away
--          GildingExtent            - initial distance from ink particle
--          SparkleTexture           - texture filename for sparkle
--          SparkleSize              - half size of sparkle
--          SparkleRatio             - gilding is replaced by sparkle
--          SparkleColor             - color of sparkle
--          SparkleExtent            - generation distance from ink particle
--          SparkleLifetime          - lifetime for sparkle
--
--      EnableParticle               - display splash particle
--      EnableGilding               - display gilding effect
--
--      DangoInfo - a table containing:
--          Type                   - STACKED_DANGO or FLUTTERING_DANGO
--          NodeName               - node name to link dango objects
--          TopNodeName            - node at top position for dangos
--          BaseHeight             - distance to base plane of dango from
--                                   origin (+Y direction)
--          FieldDiameter          - horizontal diameter of the location
--                                   field of dangos
--          Scale                  - scale factor for each dango model
--          Rigidity               - rigidity of dango structure against
--                                   inertial force
--          GlobalAccelerationFilter   - smooth filter constant for global
--                                   inertial
--          LocalInertialSensitivity   - sensitivity to local inertial
--          GlobalInertialSensitivity  - sensitivity to global inertial
--          FlutteringLength;      - flying distance for fluttering dangos
--          FlutteringFrequency    - frequency of fluttering (per second)
--          FlutteringStartLength  - minimum distance for fluttering dango
--          FlutteringSpreadAngle  - spread angle (degree) for fluttering dango
--          BaseStickiness         - stickiness at lowest dango position
--          StackRandomizeRatio    - randomized offset to stacked dango
--          MaxAcceleration        - maximum affect from acceleration
--
--      Misc debug:
--          DisplayHeapAllocationMap - display heap allocation map
--                                   NOTE: noneffective without DebugMalloc
--          ShowBenchmark       - 1 to display benchmark info, else 0
--          DebugButtons        - 1 to enable special debugging buttons, else 0
--
--      Misc:
--          InkAllowance        - starting ink for each ring is set by:
--                                  num_moras * tappitsu_usage * ink_allowance
--          MaxInkAllowance     - global, effectively sets the scale of the
--                                  ink meter
--

----
-- LOCAL ENVIRONMENT CONFIG
--
-- For data not in Perforce (huge files and their dependent data), let's
-- make defaults work for the majority of users (that is, kyle accounts).
-- To override such variables, make a file "local-config.lua" and set them
-- there.  (NOTE: Don't check the local config file into Perforce.)
--
-- In addition to this, we'll make the default location more cross-system
-- friendly.  Instead of pointing to the vr2 home account, we'll point to
-- a fixed path that can be easily symlinked or nfs mounted as needed.

-- Load the local config if it exists.
-- ISSUE: It's a little confusing specifying paths from the program exe.
--      For a solution that allows script-relative paths, see ebtest-vg.
--dofile('data/local-config.lua')

-- Here are defaults for overridable variables:

----
-- UTIL FUNCTIONS

CHARA_NAMES =
{
    [MOJIKO] = 'mojiko',
    [MOJIBRI] = 'mojibri',
    [OSOREZAN] = 'osorezan',
}

-- make_globals
--
-- This function does some operations on the user's global table before sending
-- it out:
--
--      merges defaults into CharaInfo list (defined in char_info_defaults)
--
function make_globals(t)
    local temp = util.RecursiveCopyTable(t)
    for i = 1, getn(temp.CharaInfo) do
        local item = util.RecursiveCopyTable(char_info_defaults)
        util.RecursiveMergeTable(item, temp.CharaInfo[i])
        temp.CharaInfo[i] = item
    end
    Globals(temp)
end

-- make_program
--
-- This function merges any number of input tables with certain global tables
-- to make a program (stage).
--
-- The merge happens as follows, with values in later tables having precedence.
--
--      stage defaults (defined in stage_default table)
--      user tables (input to make_program function)
--
function make_program(...)
    local temp = { }
    util.RecursiveMergeTable(temp, stage_default)
    for table in arg do
        util.RecursiveMergeTable(temp, table)
    end

    -- append info to program name
    temp.Info = temp.Info .. ' (' .. CHARA_NAMES[temp.GameCharacter] .. ')'
    temp.Info = temp.Info .. " (" .. temp.Tempo .. "bpm)"
    if temp.RapSheetFile and temp.RapSheetFile ~= '' then
        temp.Info = temp.Info .. " (SHEET)"
    end

    Stage(temp)
end

----

BACKGROUND_DATA = 'data/game/stages/'

-- the ring data is huge so we keep it in a separate file
dofile('data/game/rings.lua')

-- Defaults for per-character global data
--
char_info_defaults =
{
    GlyphScale = .8,
    ParticleInfo =
    {
        SourceNodeName = '',
        SourceNodeName2 = '',
        Texture = 'splash01.tm2',
        Lifetime = 4.0,
        Num = 500,
        Density = 1.0,
        SourceSegment = { { 0, 0, 0, 1 }, { 0, 1, 0, 1 } },
        SourceSegment2 = { { 0, 0, 0, 1 }, { 0, 1, 0, 1 } },
        ScatteringSourceSegment = { { 0, 0, 0, 1 }, { 0, 1, 0, 1 } },
        ScatteringSourceSegment2 = { { 0, 0, 0, 1 }, { 0, 1, 0, 1 } },
        ScatteringConvergency = 0.6,
        SizeVariationRatio = 0.3,
        SettledSize = 4.0,
        ScatteringSize = 1.2,
        VelocityToSizeCoefficient = 0.03125,
        MaxSize = 3.0,
        DropThresholdSpeed = 1.3,
        DropSpreadRatio = 0.0,
        DropBackwardSpeed = 3.0,
        SpreadRatio = 0.2,
        ScatteringMinSpeed = 7.0,
        ScatteringMaxSpeed = 9.0,
        SettledAlpha = 0.333,
        ScatteringAlpha = 0.7,
        FrontGrowthSpeed = 5.0,
        ScatteringGrowthSpeed = 6.0,
        -- these 4 parameters should be set by program ??
        NearSettlePlane = 1.0,
        FarSettlePlane = 10.0,
        Gravity = { 0, -5, 0, 0 },
        Collector = { 0, 0, 0, 0 },
        EnableSplashHole = 1,
        SplashHoleCenter = { -0.05, -0.105, 0, 0 },
        SplashHoleRadius = 0.08,
        SplashHoleOblateness = 1.3,
        GildingTexture = 'goldtex.tm2',
        GildingColor = { 0.6, 0.5, 0.1, 1.0 },
        GildingSpecularColor = { 8.0, 4.0, 2.0, 1.0 },
        GildingAmbientIntensity  = 0.7,
        GildingShininess = 16,
        GildingLightDirection = { 1.0, 1.0, 1.0, 1 },
        GildingSize = 0.007,
        GildingDensity = 8.5,
        GildingRotationPeriod = 0.346,
        GildingClipColor = { 1.0, 0.95, 0.8, 1.0 },
        GildingDivergency = 0.06,
        GildingExtent = 1.5,
        SparkleTexture = 'sparkle.tm2',
        SparkleSize = 0.03,
        SparkleRatio = 0.0222,
        SparkleColor = { 1.0, 1.0, 0.8, 1 },
        SparkleExtent = 5.0,
        SparkleLifetime = 0.15,
        -- temporary parameter to debug gildings
    },
    DangoInfo =
    {
        Scale = 1.2,
        FieldDiameter = 3.0,
        Rigidity = 1.0,
        GlobalAccelerationFilter = 0.95,
        LocalInertialSensitivity = 0.7,
        GlobalInertialSensitivity = 0.15,
        FlutteringStartLength = 0.5,
        FlutteringLength = 6.0,
        FlutteringFrequency = 3.0,
        FlutteringSpreadAngle = 48.0,
        BaseStickiness = 0.2,
        StackRandomizeRatio = 0.3,
        MaxAcceleration = 350.0,
        CoreModel = 'data/common/chara/dango.xvm',
        PlaneModel = 'data/common/chara/dango_plane.xvm',
    },
}

-- These are global values, which stay the same for all stages.
--
make_globals
{
    CharaInfo =
    {
        -- NOTE: the +1 is because podvectors start from 1 on Lua side
        [MOJIBRI+1] = {
            BaseDir = 'data/game/chara/mojibri/',
            ModelBaseDir = 'data/common/chara/mojibri/',
            Offset = { -8, 0, 0 },
            GlyphScale = .85,
            ParticleInfo =
            {
                Num = 500,
                Density = 1.0,
                NearSettlePlane = 1.3,
                FarSettlePlane = 3.6,
                SourceNodeName = 'null_hosaki',
                SourceSegment = { { 0, -3.7, 0, 1 }, { 0, -7.4, 0, 1 } },
                ScatteringSourceSegment = { { 0, -6.5, 0, 1 }, { 0, -13.2, 0, 1 } },
                ScatteringGeneration = 300.0,
                GildingNum = 2000,
            },
            DangoInfo =
            {
                Type = STACKED_DANGO,
                NodeName = 'dango_null',
                TopNodeName = 'dango1',
                BaseHeight = 8.0,
            },
        },
        [MOJIKO+1] = {
            BaseDir = 'data/game/chara/mojiko/',
            ModelBaseDir = 'data/common/chara/mojiko/',
            Offset = { -8, 0, 0 },
            ParticleInfo =
            {
                Num = 250,
                Density = 0.5,
                NearSettlePlane = 1.3,
                FarSettlePlane = 3.2,
                SourceNodeName = 'null_hosaki_dw',
                SourceNodeName2 = 'null_hosaki_up',
                SourceSegment  = { { 0, -3.0, 0, 1 }, { 0, -5.9, 0, 1 } },
                SourceSegment2 = { { 0,  3.0, 0, 1 }, { 0,  5.9, 0, 1 } },
                ScatteringSourceSegment  = { { 0, -3.0, 0, 1 }, { 0, -5.9, 0, 1 } },
                ScatteringSourceSegment2 = { { 0,  3.0, 0, 1 }, { 0,  5.9, 0, 1 } },
                ScatteringGeneration = 600.0,
                GildingNum = 1000,
            },
            DangoInfo =
            {
                Type = STACKED_DANGO,
                NodeName = 'dango_null',
                TopNodeName = 'dango1',
                BaseHeight = 3.6,
            },
        },
        [OSOREZAN+1] = {
            BaseDir = 'data/game/chara/osorezan/',
            ModelBaseDir = 'data/common/chara/osorezan/',
            Offset = { -8, 0, 0 },
            ParticleInfo =
            {
                Num = 500,
                Density = 1.0,
                NearSettlePlane = 1.1,
                FarSettlePlane = 2.8,
                SourceNodeName = 'null_hosaki',
                SourceSegment = { { 0, -3.7, 0, 1 }, { 0, -7.4, 0, 1 } },
                ScatteringSourceSegment = { { 0, -3.7, 0, 1 }, { 0, -7.4, 0, 1 } },
                ScatteringGeneration = 300.0,
                DropBackwardSpeed = 2.5,
                GildingNum = 2000,
            },
            DangoInfo =
            {
                Type = FLUTTERING_DANGO,
                NodeName = 'dango_null',
                BaseHeight = 7.5,
                LocalInertialSensitivity = 0.5,
                GlobalInertialSensitivity = 0.02,
            },
        },
    },

    -- Graphics Parameters
    BumpPattern =
    {
        --.5, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1,
        --.5, .6, .7, .8,   .9, 1, 1, 1,   1, 1, 1, 1,   1.2, 1.3, 1.1, .8,
        .4, .6, .7, .8,   .9, 1, 1, 1,   1, 1, 1, 1.2,   1.5, 1.5, 1.2, .8,
    },
    TailBumpPattern =
    {
        1.5, 1.5, 1.5, 1.4,   1.3, 1.2, 1.1, 1,   1, 1, 1, 1,   1, 1, 1, 1.3,
    },
    PieceScale = 1,
    TilesPerMora2 = 2,
    RingTileInfo2 =
    {
        {
            Size = .01,
            PositionExtent = .06,
            PositionRate = 0.6,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 1, 1, .1, .2 },
            Color2 = Color { 1, 1, .0, .4 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = APPEND,
        },
        {
            Size = .01,
            PositionExtent = .06,
            PositionRate = 0.6,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 1, 1, .1, .1 },
            Color2 = Color { 1, 1, .0, .2 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = .01,
            PositionExtent = .06,
            PositionRate = 0.6,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 1, 1, .1, 0 },
            Color2 = Color { 1, 1, .0, 0 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },

    -- Sound Effects
    SoundEffectMain = 'data/game/sound/main',
    SoundEffectLevel = 1.0,
    SoundEffectAuxLevel = 1.0,

    -- Tap Timing
    WriteOffset = 0,
    MaxTapLead = { 0.14, 0.14, 0.18, 0.22 },
    MaxTapLag  = { 0.54, 0.54, 0.58, 0.62 },
    MaxReleaseLead = 0.2,
    MaxReleaseLag = 0.6,
    MaxTailLead = 0.2,
    MaxTailLag = 0.8,
    MissLockout = 0.8,
    WriteMissLockout = 1.5,
    JoyWriteTriggerLevel = .9,
    JoyWriteDecayRate = 9.6,
    JoyWriteTimeout = .25,
    JoyWriteStrongMin = 1.1,

    MaxInkAllowance = 1.8,

    -- Scoring
    ExpertMinStageRings = 10,
    ExpertMinGoodRatio = .90,

    -- Speech Synthesizer
    VrsDirectory = 'data/common/vrs/',
    SpeechSampleRate = 22050,

    -- Debugging
    AutoMode = 0,
    DemoMode = 0,
    DemoModeDuration = 30,
    SkipStartAnim = 0,
    ForceCharacter = 0,
    --ForceSubCharacter = 'D',
    DebugButtons = 0,
    ShowBenchmark = 0,
    ShowGameMarkers = 0,
    EnableRingTiles = 1,
    EnableParticle = 1,
    EnableGilding = 1,
    DumpRapSpd = 0,
    DumpRapSheet = 0,
    DumpRap = 0,
    DisplayHeapAllocationMap = 1,
}

----
-- Here are defaults for per-stage data.
--
stage_default =
{
    Info = '',
    IsExtra = 0,
    IsTest = 0,

    -- Character
    GameCharacter = MOJIBRI,

    -- Background
    BackgroundSceneDir = BACKGROUND_DATA .. '01/',

    -- Time Signature
    Tempo = 100,
    IntroBarCount = 2,
    BeatsPerBar = 4,
    PulsesPerBeat = 4,
    ThresholdLeadIntroPulse = 12,
    RingBarCount = 2,
    SlowMinJumpPulseCount = 8,
    FastMinJumpPulseCount = 16,
    ThresholdJumpTempo = 90,
    SlowPaddingPulseCount = 8,
    FastPaddingPulseCount = 16,
    ThresholdPaddingTempo = 90,

    -- Graphics Layout
    RingWidth = .15,
    RingSeparation = 1.2,
    RingPattern = { 3, 3, 3, 3, 5, 5, 5, 5, 5, 5 },
    CharaScale = .025,
    DrawRingPaper = 0,
    PaperColor = Color { .75, 0.75, 0.70 },
    -- Alpha of 0 is used to make before text invisible
    InkColorBefore = Color { 0, 0, 0, 0 },
    InkColorAfter = Color { 0, 0, 0 },
    StoneIndex = 1,
    InkAllowance = 2,

    TilesPerMora = 10,
    -- Ring tile parameter keys
    -- TextureName, ColorSync, and AlphaMode of 2nd and last key not used.
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 0.77, 0.67, 0.55, 0.45 },
            Color2 = Color { 184/256, 148/256, 112/256, 0.9 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 0.95, 0.9, 0.73, 0.45 },
            Color2 = Color { 0.77, 0.67, 0.55, 0.45 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 0.95, 0.9, 0.73, 0 },
            Color2 = Color { 0.77, 0.67, 0.55, 0 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },

    -- Sound Mix
    BackTrackLevel = 0.5,
    RapTrackLevel = 0.95,
    MuteRate = 360.0,
    --ForceMono = 1,
}

----

-- helper for making internal programs
function internal(name, character, tempo, introBars, inkAllowance, extra)
    local dir = 'data/game/stages/'..name..'/'
    -- NOTE: if name can't be converted to a stage number, stage 1 is used.
    --      For final version it is assumed internal stages are named
    --      like '01', '02', etc.
    local stage_index = tonumber(name) or 1
    local background = format("%s%02d/", BACKGROUND_DATA, stage_index)
    make_program({
        Name = name,

        GameCharacter = character,
        BackgroundSceneDir = background,
        StoneIndex = stage_index,
        InkAllowance = inkAllowance,

        Tempo = tempo,
        IntroBarCount = introBars,
        RapSheetFile = 'data/common/rap/'..name..'.sht',
        BackTrackIntro = dir..'intro.vag',
        BackTrackLoop  = dir..'loop.vag',
    }, ring_param_list[stage_index], extra)
end

-- wrapper that saves arguments to internal(), for later use
-- by internal_ref()
_internal = internal
_internal_calls = { }
function internal(...)
    -- call table is indexed by program name
    _internal_calls[arg[1]] = arg
    call(_internal, arg)
end

-- helper for making alternate internal programs
--
-- Currently these programs just have a different rap and start character,
-- but the same backtrack and graphics as an existing internal stage.
function internal_ref(rapDir, titlePrefix, name, internalName, character,
        hasSheet, isExtra, isTest)
    local call_args = _internal_calls[internalName]
    util.Assert(call_args, 'referencing unknown internal stage')
    -- add extra argument to call
    -- NOTE: assuming this argument not specified in original call
    local mod_call_args = util.CopyTable(call_args)
    local rap_name = rapDir..name
    local rap_sheet = hasSheet and rap_name..'.sht' or ''
    local rap_text = hasSheet and '' or rap_name..'.txt'
    tinsert(mod_call_args, {
        Name = titlePrefix..name,
        GameCharacter = character,
        RapSheetFile = rap_sheet,
        RapTextFile = rap_text,
        IsExtra = isExtra,
        IsTest = isTest,
    })
    call(_internal, mod_call_args)
end

function extra_text(name, internalName, character, hasSheet)
    internal_ref('data/common/rap/extra/', 'extra ', name,
        internalName, character, hasSheet, 1, 0)
end

function test_text(name, internalName, character, hasSheet)
    internal_ref('data/common/rap/test/', '', name,
        internalName, character, hasSheet, 0, 1)
end

----

--  The character info written here is no longer used except for these cases:
--      * when ForceCharacter set to 1
--      * when no start character in rap text
--
--  It's also used in the program name.  In the future the program may need to
--  know the start character before the rap text is loaded, so we should keep
--  the info up to date.

internal('01' , MOJIBRI ,    70,    2, 3.0)
internal('02' , MOJIBRI ,    80,    2, 3.0)
internal('03' , MOJIBRI ,    74,    2, 1.7)
internal('04' , MOJIBRI ,    76,    2, 1.7)
internal('05' , MOJIBRI ,    73,    2, 1.6)
internal('06' , MOJIBRI ,    77,    2, 1.6)
internal('07' , MOJIKO  ,    80,    2, 1.6)
internal('08' , MOJIBRI ,    70,    2, 1.4)
internal('09' , MOJIKO  ,    80,    2, 1.4)
internal('10' , MOJIKO  ,    91,    4, 1.5)
internal('11' , MOJIBRI ,    86,    4, 1.4)
internal('12' , MOJIBRI ,    80,    2, 1.4)
internal('13' , OSOREZAN,    68,    2, 1.3)
internal('14' , MOJIKO  ,    90,    2, 1.4)
internal('15' , OSOREZAN,    78,    2, 1.3)
internal('16' , MOJIKO  ,    82,    2, 1.3)
internal('17' , OSOREZAN,    84,    2, 1.2)
internal('18' , MOJIBRI ,    70,    1, 1.1)

-- NOTE: these must come after the internal stage they reference
extra_text('01', '01', MOJIBRI  , nil)
extra_text('02', '02', MOJIBRI  , nil)
extra_text('03', '03', MOJIKO   , nil)
extra_text('04', '04', MOJIBRI  , nil)
extra_text('05', '05', OSOREZAN , nil)
extra_text('06', '06', MOJIKO   , nil)
extra_text('07', '07', MOJIKO   , nil)
extra_text('08', '08', MOJIBRI  , nil)
extra_text('09', '09', MOJIBRI  , nil)
extra_text('10', '10', MOJIBRI  ,   1)
extra_text('11', '11', MOJIBRI  ,   1)
extra_text('12', '12', OSOREZAN , nil)
extra_text('13', '13', OSOREZAN ,   1)
extra_text('14', '14', MOJIBRI  ,   1)
extra_text('15', '15', MOJIKO   ,   1)
extra_text('16', '16', OSOREZAN ,   1)
extra_text('17', '17', MOJIKO   ,   1)
extra_text('18', '18', MOJIBRI  ,   1)

-- short stages for clear test
test_text('short1', '01', MOJIBRI )
test_text('short1', '01', MOJIKO  )
test_text('short1', '01', OSOREZAN)

-- short stage with character change
test_text('short2', '01', MOJIBRI)

-- rap with rests inside chunks
test_text('rests', '01', MOJIBRI, 1)

-- special stage to see write animations
test_text('writetest', '01', MOJIBRI, 1)

test_text('long', '01', MOJIBRI)
test_text('xxx', '01', MOJIBRI)

3/EBFF0D63/rings.lua#

-- IMPORTANT NOTE: TextureName cannot be changed yet.  See John.

ring_param_list =
{

[1] = {
    RingPattern = { 30 },
    TilesPerMora = 10,
    -- Ring tile parameter keys
    -- TextureName, ColorSync, and AlphaMode of 2nd and last key not used.
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 238/256, 235/256, 255/256, 0.75 },
            Color2 = Color { 154/256, 136/256, 209/256, 0.45 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 238/256, 235/256, 255/256, 0.22 },
            Color2 = Color { 154/256, 136/256, 209/256, 0.22 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 238/256, 235/256, 255/256, 0.00 },
            Color2 = Color { 154/256, 136/256, 209/256, 0.00 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[2] = {
    RingPattern = { 30 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 242/256, 225/256, 116/256, 0.45 },
            Color2 = Color { 242/256, 242/256, 217/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 242/256, 225/256, 116/256, 0.20 },
            Color2 = Color { 242/256, 242/256, 217/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 242/256, 225/256, 116/256, 0.05 },
            Color2 = Color { 242/256, 242/256, 217/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[3] = {
    RingPattern = { 30 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 250/256, 237/256, 230/256, 0.60 },
            Color2 = Color { 245/256, 205/256, 157/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 250/256, 237/256, 230/256, 0.20 },
            Color2 = Color { 245/256, 205/256, 157/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 250/256, 237/256, 230/256, 0.05 },
            Color2 = Color { 245/256, 205/256, 157/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[4] = {
    RingPattern = { 30 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 238/256, 239/256, 243/256, 0.45 },
            Color2 = Color { 167/256, 194/256, 218/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 238/256, 239/256, 243/256, 0.20 },
            Color2 = Color { 167/256, 194/256, 218/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 238/256, 239/256, 243/256, 0.02 },
            Color2 = Color { 167/256, 194/256, 218/256, 0.02 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[5] = {
    RingPattern = { 20,5,5 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 233/256, 236/256, 243/256, 0.45 },
            Color2 = Color { 141/256, 150/256, 188/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 244/256, 245/256, 248/256, 0.20 },
            Color2 = Color { 158/256, 166/256, 193/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 244/256, 245/256, 248/256, 0.05 },
            Color2 = Color { 158/256, 166/256, 193/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[6] = {
    RingPattern = { 1,2,27 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 171/256, 199/256, 127/256, 0.75 },
            Color2 = Color { 230/256, 222/256, 167/256, 0.45 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 171/256, 199/256, 127/256, 0.15 },
            Color2 = Color { 230/256, 222/256, 167/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 171/256, 199/256, 127/256, 0.02 },
            Color2 = Color { 230/256, 222/256, 167/256, 0.02 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[7] = {
    RingPattern = { 0,0,15,5,5,10 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 250/256, 153/256, 238/256, 0.75 },
            Color2 = Color { 249/256, 217/256, 250/256, 0.60 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 250/256, 153/256, 238/256,  0.15 },
            Color2 = Color { 250/256, 250/256, 250/256, 0.15 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 250/256, 153/256, 238/256, 0.02 },
            Color2 = Color { 250/256, 250/256, 250/256, 0.02 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[8] = {
    RingPattern = { 4,1,1,3,1,1,1,3,3,2,2,3,5},
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 255/256, 255/256, 223/256, 0.45 },
            Color2 = Color { 235/256, 220/256, 161/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 243/256, 243/256, 212/256, 0.25 },
            Color2 = Color { 233/256, 220/256, 173/256, 0.25 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 243/256, 243/256, 212/256, 0.02 },
            Color2 = Color { 233/256, 220/256, 173/256, 0.02 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[9] = {
    RingPattern = { 0,0,2,2,2,1,1,2,1,2,7,3,2,2,3 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 207/256, 156/256, 243/256, 0.60 },
            Color2 = Color { 255/256, 255/256, 255/256, 0.45 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 207/256, 156/256, 243/256, 0.20 },
            Color2 = Color { 255/256, 255/256, 255/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 207/256, 156/256, 243/256, 0.05 },
            Color2 = Color { 255/256, 255/256, 255/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[10] = {
    RingPattern = { 8,1,11,1,2,1,6 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 255/256, 242/256, 229/256, 0.60 },
            Color2 = Color { 229/256, 195/256, 161/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 246/256, 235/256, 224/256, 0.20 },
            Color2 = Color { 238/256, 216/256, 194/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 246/256, 235/256, 224/256, 0.05 },
            Color2 = Color { 238/256, 216/256, 194/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[11] = {
    RingPattern = { 1,13,1,5,10 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 224/256, 152/256, 187/256, 0.70 },
            Color2 = Color { 245/256, 233/256, 239/256, 0.40 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 242/256, 170/256, 206/256, 0.18 },
            Color2 = Color { 250/256, 250/256, 250/256, 0.18 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 242/256, 170/256, 206/256, 0.06 },
            Color2 = Color { 250/256, 250/256, 250/256, 0.06 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[12] = {
    RingPattern = { 1,4,1,1,1,4,1,1,1,4,1,1,1,4,1,1,1,1 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 199/256, 187/256, 182/256, 0.60 },
            Color2 = Color { 134/256, 98/256, 93/256, 0.60 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 213/256, 213/256, 212/256, 0.20 },
            Color2 = Color { 134/256, 98/256, 93/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 213/256, 213/256, 212/256, 0.02 },
            Color2 = Color { 134/256, 98/256, 93/256, 0.02 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[13] = {
    RingPattern = { 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 236/256, 243/256, 246/256, 0.45 },
            Color2 = Color { 185/256, 209/256, 223/256, 0.60 },

            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 236/256, 243/256, 246/256, 0.15 },
            Color2 = Color { 185/256, 209/256, 223/256, 0.15 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 236/256, 243/256, 246/256, 0.02 },
            Color2 = Color { 185/256, 209/256, 223/256, 0.02 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[14] = {
    RingPattern = { 1,2,1,1,1,1,3,1,2,1,3,1,4,8, },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 238/256, 219/256, 229/256, 0.45 },
            Color2 = Color { 185/256, 166/256, 209/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 238/256, 219/256, 229/256, 0.20 },
            Color2 = Color { 185/256, 166/256, 209/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 238/256, 219/256, 229/256, 0.05 },
            Color2 = Color { 185/256, 166/256, 209/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[15] = {
    RingPattern = { 3,1,2,2,3,1,1,1,16 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 224/256, 166/256, 195/256, 0.60 },
            Color2 = Color { 250/256, 250/256, 250/256, 0.60 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 224/256, 166/256, 195/256, 0.20 },
            Color2 = Color { 248/256, 231/256, 240/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 224/256, 166/256, 195/256, 0.00 },
            Color2 = Color { 248/256, 231/256, 240/256, 0.00 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[16] = {
    RingPattern = { 1,2,1,1,1,5,1,4,2,1,1,3,7 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 166/256, 205/256, 224/256, 0.45 },
            Color2 = Color { 250/256, 250/256, 250/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 166/256, 205/256, 224/256, 0.15 },
            Color2 = Color { 237/256, 245/256, 252/256, 0.15 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 166/256, 205/256, 224/256, 0.05 },
            Color2 = Color { 237/256, 245/256, 252/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[17] = {
    RingPattern = { 2,4,4,4,4,4,4,3,1 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 214/256, 138/256, 190/256, 0.45 },
            Color2 = Color { 255/256, 235/256, 249/256, 0.75 },
            ColorRate = 0.4,
            ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 214/256, 138/256, 190/256, 0.20 },
            Color2 = Color { 255/256, 235/256, 249/256, 0.20 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 214/256, 138/256, 190/256, 0.05 },
            Color2 = Color { 255/256, 235/256, 249/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

[18] = {
    RingPattern = { 13,2,1,1,1,1,1,1,2,1,6 },
    TilesPerMora = 10,
    RingTileInfo =
    {
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            TextureName = 'ring05.tm2',
            Color1 = Color { 241/256, 243/256, 250/256, 0.60 },
            Color2 = Color { 188/256, 144/256, 145/256, 0.90 },
            ColorRate = 2,
            ColorSync = 0,
    --        ColorRate = 0.4,
    --        ColorSync = 1,
            AlphaRate = 0.5,
            AlphaMode = TRANSPARENT,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 241/256, 243/256, 250/256, 0.25 },
            Color2 = Color { 188/256, 144/256, 145/256, 0.25 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
        {
            Size = 9/100,
            PositionExtent = 4/100,
            PositionRate = 0.3,
            SizeRatio = 0.4,
            SizeRate = 0.25,
            Color1 = Color { 241/256, 243/256, 250/256, 0.05 },
            Color2 = Color { 188/256, 144/256, 145/256, 0.05 },
            ColorRate = 0.4,
            AlphaRate = 0.5,
        },
    },
},

}

3/EBFF0D63/sound/se_main.h#

enum
{
    LOADING = 0,
    BRUSH_UP,
    BRUSH_DOWN,
    JUMP,
    MISS_MOJIBRI,
    MISS_MOJIKO,
    MISS_OSOREZAN,
    RETURN,
    WRITE_MISS,
    WRITE,          // loop
    START_MOJIBRI,
    START_MOJIKO,
    START_OSOREZAN,
    GAME_CLEAR,
    GAME_OVER,
    EVOLVE,
    DEVOLVE,
    SWITCH,
    INK_METER_RETURN,
    JUMP_SPECIAL1,
    JUMP_SPECIAL2,
    INK_WIPE,
    CHUNK_ERASE,
};

5/0CD50325/list.lua#

DYNAMIC_TEXTURES = nil

MANUAL_TEXTURES = nil

AUTO_TEXTURES = {"bird01.tm2", "carsor_a.tm2", "jump_ok.tm2", "jump_piece.tm2", "moji_tyuto.tm2", "piece_map.tm2", "ps2_fude.tm2", "ring_map.tm2", "sumi_a01.tm2", "sumi_c01.tm2", "titl.tm2", "tyu_titl.tm2"}

6/C7FF0336/list.lua#

DYNAMIC_TEXTURES = nil

MANUAL_TEXTURES = nil

AUTO_TEXTURES = {"h_heart.tm2", "sel_hai.tm2", "sel_waku.tm2"}

B/2A751A0B/list.lua#

DYNAMIC_TEXTURES = nil

MANUAL_TEXTURES = nil

AUTO_TEXTURES = {"00.tm2", "01.tm2", "02.tm2", "03.tm2", "10.tm2", "11.tm2", "20.tm2", "21.tm2", "22.tm2", "23.tm2", "24.tm2", "30.tm2", "31.tm2", "32.tm2", "33.tm2", "40.tm2", "41.tm2", "42.tm2", "43.tm2", "44.tm2", "50.tm2", "51.tm2", "52.tm2", "53.tm2", "60.tm2", "61.tm2", "62.tm2", "brush2.tm2", "copylight_scei.tm2", "fude2_01.tm2", "fude8b2.tm2", "gold2.tm2", "logo_a01.tm2", "logo_a02.tm2", "logo_a03.tm2", "logo_a04.tm2", "logo_a05.tm2", "logo_a06.tm2", "logo_b01.tm2", "logo_b02.tm2", "logo_b03.tm2", "logo_b04.tm2", "logo_b05.tm2", "logo_b06.tm2", "logo_b07.tm2", "logo_b08.tm2", "logo_b09.tm2", "logo_b10.tm2", "logo_c01.tm2", "mb2_eye00.tm2", "mb2_eye01.tm2", "mb2_eye02.tm2", "mb2_eye05.tm2", "mb2_eye07.tm2", "mb2_eye09.tm2", "mb2_eye10.tm2", "mb2_eye11.tm2", "mb2_mole.tm2", "mb2_mouth00.tm2", "mb2_mouth01.tm2", "mb2_mouth02.tm2", "mb2_mouth03.tm2", "mb2_mouth04.tm2", "mb2_mouth05.tm2", "mb2_mouth07.tm2", "mb2_mouth08.tm2", "mb2_mouth11.tm2", "mb2_mouth12.tm2", "mb2_mouth13.tm2", "mb2_nose.tm2", "op_waku.tm2", "op_waku2.tm2", "opening_font02.tm2", "rock.tm2", "sizuku.tm2", "sumi_tobi.tm2", "sumidare01.tm2", "sumidare02.tm2", "sumidare03.tm2", "take01.tm2", "take04.tm2", "take05.tm2", "titl.tm2", "tm.tm2", "water1.tm2", "water2.tm2", "water3.tm2", "water4.tm2"}

C/08D4483C/list.lua#

DYNAMIC_TEXTURES = nil

MANUAL_TEXTURES = nil

AUTO_TEXTURES = {"fude8c.tm2", "paper01.tm2", "waku2.tm2", "ring05.tm2", "sumi_a01.tm2", "sumi_c01.tm2", "bird01.tm2", "num0.tm2", "num1.tm2", "num2.tm2", "num3.tm2", "num4.tm2", "num5.tm2", "num6.tm2", "num7.tm2", "num8.tm2", "num9.tm2", "auto2.tm2", "jyozu.tm2", "itiryu.tm2", "tyoitiryu.tm2", "start_mb_ha.tm2", "start_mb_ji.tm2", "start_mb_me.tm2", "start_mjk_da.tm2", "start_mjk_ka.tm2", "start_mjk_ku.tm2", "start_mjk_mo.tm2", "start_mjk_n.tm2", "start_mjk_oo.tm2", "start_robo_go.tm2", "start_robo_oo.tm2", "start_robo_u.tm2", "evo_fade.tm2", "evo_win.tm2", "evo_light.tm2", "evo_rb.tm2", "drip.tm2", "retry_prompt.tm2", "retry_edit_prompt.tm2", "pause_prompt.tm2", "piece.tm2", "jump_piece.tm2", "jump_piece_pre.tm2", "drip01.tm2", "meijin_stamp.tm2", "gokaku_stamp.tm2", "shikkaku_stamp.tm2", "sumi2.tm2", "bablu.tm2", "awa1.tm2"}

C/48F3299C/pods/MblCharacterEnum#

/ NOTE: This header is used by both C and Lua.

#ifndef MblCharacterEnum_h
#define MblCharacterEnum_h

namespace Mbl {

enum ECharacter { MOJIBRI, MOJIKO, OSOREZAN, GAME_CHARACTER_NUM };

}

#endif // MblCharacterEnum_h

C/48F3299C/pods/MblDangoPod#

#ifndef MblDangoPod_h
#define MblDangoPod_h

// NOTE: This header is used by both C and Lua.

#include <string>

namespace Mbl {

// procedural control type of dango movement
enum EDangoType { STACKED_DANGO, FLUTTERING_DANGO } ;

struct SDangoInfo
{
    EDangoType Type;
    std::string NodeName;
    std::string TopNodeName;
    float BaseHeight;
    float FieldDiameter;
    float Scale;
    float Rigidity;
    float GlobalAccelerationFilter;
    float LocalInertialSensitivity;
    float GlobalInertialSensitivity;
    float FlutteringLength;
    float FlutteringFrequency;
    float FlutteringStartLength;
    float FlutteringSpreadAngle;
    float BaseStickiness;
    float StackRandomizeRatio;
    float MaxAcceleration;
    std::string CoreModel;
    std::string PlaneModel;
};

} // namespace Mbl

#endif // MblDangoPod_h

C/48F3299C/pods/MblParticlePod#

#ifndef MblParticlePod_h
#define MblParticlePod_h

// NOTE: This header is used by both C and Lua.

#include <string>
#include "MblNavectorPod.h"

namespace Mbl {

// ISSUE: should share this general struct
struct VectorPair
{
    NaVECTOR4 first;
    NaVECTOR4 second;
};

struct SParticleInfo
{
    std::string SourceNodeName;
    std::string SourceNodeName2;
    std::string Texture;
    float Lifetime;
    int Num;
    float NearSettlePlane;
    float FarSettlePlane;
    VectorPair SourceSegment;
    VectorPair SourceSegment2;
    VectorPair ScatteringSourceSegment;
    VectorPair ScatteringSourceSegment2;
    NaVECTOR4 Gravity;
    NaVECTOR4 Collector;
    float ScatteringConvergency;
    float Density;
    float SizeVariationRatio;
    float SettledSize;
    float ScatteringSize;
    float VelocityToSizeCoefficient;
    float MaxSize;
    float DropThresholdSpeed;
    float DropSpreadRatio;
    float DropBackwardSpeed;
    float SpreadRatio;
    float ScatteringMinSpeed;
    float ScatteringMaxSpeed;
    float SettledAlpha;
    float ScatteringAlpha;
    float ScatteringGeneration;
    float FrontGrowthSpeed;
    float ScatteringGrowthSpeed;

    // stuff for gold gilding
    int GildingNum;
    std::string GildingTexture;
    NaCOLOR4 GildingColor;
    NaCOLOR4 GildingSpecularColor;
    NaCOLOR4 GildingClipColor;
    NaVECTOR4 GildingLightDirection;
    float GildingAmbientIntensity;
    float GildingShininess;
    float GildingSize;
    float GildingDensity;
    float GildingRotationPeriod;
    float GildingDivergency;
    float GildingExtent;
    std::string SparkleTexture;
    float SparkleSize;
    float SparkleRatio;
    NaCOLOR4 SparkleColor;
    float SparkleExtent;
    float SparkleLifetime;
    bool EnableSplashHole;
    NaVECTOR4 SplashHoleCenter;
    float SplashHoleRadius;
    float SplashHoleOblateness;
};

} // namespace Mbl

#endif // MblParticlePod_h

C/48F3299C/pods/MblNavectorPod#

#ifndef navectorPod_h
#define navectorPod_h

#include "navector.h"

#ifdef LUAPOD_ONLY
  // About "float_a16":
  //
  // LuaPod does not have alignment control.  For the purpose of EE vector
  // alignment a special float primitive has been defined to line up the head
  // of the structure.
  //
  struct NaCOLOR4 { float_a16 r; float g; float b; float a; };
  struct NaVECTOR4 { float_a16 x; float y; float z; float w; };
#endif

#endif

C/48F3299C/pods/MgConfigPod#

// MgConfigPod.h - structures for runtime configuration
//
// NOTE: This header is used by both C and Lua.

#ifndef MgConfigPod_h
#define MgConfigPod_h

// Any includes here need to be supported by LuaPod.  Support for string,
// and PodVector is built-in:
#include <string>
#include "PodVector.h"
// Other headers (and this one itself) need to be passed to LuaPod in the
// correct order because LuaPod does not process C directives like include.
#include "MblNavectorPod.h"
#include "MblDangoPod.h"
#include "MblParticlePod.h"
#include "MblCharacterEnum.h"

namespace Config {

using std::string;
using LuaUtil::podvector;

enum EAlphaMode { OFF, TRANSPARENT, APPEND, TRANSPARENT_Z };

struct ModulatedTileInfo
{
    float Size;
    float PositionExtent;
    float PositionRate;
    float SizeRatio;
    float SizeRate;
    string TextureName;
    NaCOLOR4 Color1;
    NaCOLOR4 Color2;
    float ColorRate;
    bool ColorSync;
    float AlphaRate;
    EAlphaMode AlphaMode;
};

struct FloatPair
{
    float first;
    float second;
};

struct StereoFileSet
{
    string left;
    string right;
};

struct SynthStyleSet
{
    int Speaker;
    int Speed;
    int Volume;
    int Pitch;
    int Intonation;
    int VarioUp;
    int VarioDown;
    int NumberRead;
    int SymbolRead;
    int PowerPointCount;
    int PitchPointCount;
};

struct RapperStyleSet
{
    float SwingRatio;
    float StrongLastNoteStretch;
    float WeakLastNoteStretch;
    float ConstantFlying;
    podvector <float> Pitches;
    float Modulation;
    float Sweep;
    int StrongVowelAmp;
    int WeakVowelAmp;
};

// put global character data here
struct SCharaInfo
{
    string BaseDir;
    string ModelBaseDir;
    Mbl::SDangoInfo DangoInfo;
    Mbl::SParticleInfo ParticleInfo;
    NaVECTOR4 Offset;
    float GlyphScale;
};

struct Globals
{
    // this can be indexed by the ECharacter enumeration
    podvector<SCharaInfo> CharaInfo;

    float WriteOffset;
    podvector<float> MaxTapLead;
    podvector<float> MaxTapLag;
    float MaxReleaseLead;
    float MaxReleaseLag;
    float MaxTailLead;
    float MaxTailLag;
    float MissLockout;
    float WriteMissLockout;
    float JoyWriteTriggerLevel;
    float JoyWriteDecayRate;      // per frame
    float JoyWriteTimeout;        // frames
    float JoyWriteStrongMin;
    bool ShowGameMarkers;
    bool AutoMode;
    bool DemoMode;
    float DemoModeDuration;
    podvector<float> BumpPattern;
    podvector<float> TailBumpPattern;
    float PieceScale;
    float MaxInkAllowance;
    float ExpertMinGoodRatio;
    int ExpertMinStageRings;
    int TilesPerMora2;
    podvector<ModulatedTileInfo> RingTileInfo2;

    string SoundEffectMain;
    float SoundEffectLevel;
    float SoundEffectAuxLevel;

    string VrsDirectory;
    int SpeechSampleRate;

    bool DumpRap;
    bool DumpRapSpd;
    bool DumpRapSheet;
    bool SkipStartAnim;
    bool ForceCharacter;
    char ForceSubCharacter;
    bool DisplayHeapAllocationMap;
    bool EnableRingTiles;
    bool EnableParticle;
    bool EnableGilding;
    bool ShowBenchmark;
    bool DebugButtons;
};

struct Stage
{
    string Name;
    string Info;
    bool IsExtra;
    bool IsTest;

    Mbl::ECharacter GameCharacter;
    string BackgroundSceneDir;
    int StoneIndex;
    float InkAllowance;

    string RapTextFile;
    string RapSheetFile;

    StereoFileSet BackTrackIntro;
    StereoFileSet BackTrackLoop;

    float BackTrackLevel;
    float RapTrackLevel;
    float MuteRate;

    float RingWidth;
    float RingSeparation;
    podvector<int> RingPattern;
    float CharaScale;
    bool DrawRingPaper;
    NaCOLOR4 PaperColor;
    int TilesPerMora;
    podvector<ModulatedTileInfo> RingTileInfo;

    NaCOLOR4 InkColorBefore;
    NaCOLOR4 InkColorAfter;

    // MgTimeSig initializers:
    float Tempo;
    int BeatsPerBar;
    int PulsesPerBeat;
    int IntroBarCount;
    int ThresholdLeadIntroPulse;
    int RingBarCount;
    int SlowMinJumpPulseCount;
    int FastMinJumpPulseCount;
    int ThresholdJumpTempo;
    int SlowPaddingPulseCount;
    int FastPaddingPulseCount;
    int ThresholdPaddingTempo;
};

} // namespace Config

#endif // MgConfigPod_h

C/48F3299C/luamods/ConfigFilter.lua#

-- ConfigFilter.lua -- filter user config file
--
-- DEPENDENCIES
--
--      libraries:  modlib, podlib
--      modules:    util
--
--
-- Inputs to this script from caller:
--
--      set_stage()
--      set_globals()
--      FrameRate       - game frame rate

module.Import('util.lua')

-- local data
cfilt =
{
    FramePeriod = 1 / FrameRate,
}

----
-- user functions
--

-- IntColor - specify color using 8 bit rgba
--
function IntColor(t)
    return { t[1]/255, t[2]/255, t[3]/255, (t[4] or 255)/255 }
end

-- IntColor - specify color using floating point rgba
--
function Color(t)
    t[4] = t[4] or 1
    return t
end

-- ISSUE: with the splitting of globals and per-stage data, any hacks
--      will have to be aware of which table their data exists in.

function Globals(table)
    ----------------------------------------------------------------------------
    -- conversions between user script values and program

    -- convert time quantities into frame units
    table.JoyWriteDecayRate = table.JoyWriteDecayRate * FrameRate;
    table.JoyWriteTimeout = table.JoyWriteTimeout * FrameRate;

    -- convert 'chars' to byte code
    -- ISSUE: it would be nice if podlib handled this automatically
    table.ForceSubCharacter =
        (table.ForceSubCharacter) and strbyte(table.ForceSubCharacter) or 0

    ----------------------------------------------------------------------------
    -- create the C data and initialize it using table
    -- NOTE: all fields in table must be present in the C structure
    local c_data = pod.New('Globals', table)

    -- now hand it to the C program
    set_globals(pod.GetPointer(c_data))
end

function Stage( table )
    -- A copy of the table is made because we later fiddle with values in
    -- place, and if a stage was called twice on the same table it would
    -- cause problems.
    -- NOTE: this needs to be RecursiveCopyTable if we alter any nested fields
    local table = util.CopyTable(table)

    ----------------------------------------------------------------------------
    -- conversions between user script values and program

    -- handle stereo file sets
    -- If only base name provided, automatically append channel suffixes.
    local stereo_vars = { 'BackTrackIntro', 'BackTrackLoop' };
    for var in stereo_vars do
        local name = table[var]
        if type(name) == 'string' then
            local base = util.RemoveSuffixPart(name)
            local suffix = util.SuffixPart(name)
            if suffix ~= "" then suffix = '.'..suffix end
            table[var] = { base..'_L'..suffix, base..'_R'..suffix }
        end
    end

    ----------------------------------------------------------------------------
    -- create the C data and initialize it using table
    -- NOTE: all fields in table must be present in the C structure
    local c_data = pod.New('Stage', table)

    -- now hand it to the C program
    set_stage(pod.GetPointer(c_data))
end


----
-- export enums to global space
--
pod.ExportEnums(globals())

C/48F3299C/luamods/class.lua#

----
--
-- class implementation
--
-- Modeled after Python, for better or worse...
--
--
-- USEAGE
--
--      Make a new class like this:
--          MyClass = Class()
--
--      Instantiate a class like this:
--          instance = MyClass( args )
--
--      Subclass like this:
--          MySubclass = Class( MyClass )
--
--      Invoke parent class method like this:
--          ParentClass.method( self )
--
--
-- ISSUES
--
--      Can't implement __del__ without table gc events.
--

module.Import("util.lua")

local _Class = {}

-- make an instance
function _Class:___callhandler( ... )
    self = util.CopyTable( self )
    -- Insert new self into arg list.
    -- Note that original self wasn't included in arg list.
    tinsert( arg, 1, self )
    call( self.__init__, arg )
    self.___callhandler = self.__call__
    return self
end

function _Class:__call__( ... )
end

function _Class:__init__( ... )
end

local CallHandler = function( ... )
    return call( arg[1].___callhandler, arg )
end

-- for now, all class types share a tag
local class_tag = newtag()
settag( _Class, class_tag )
settagmethod( class_tag, "function", CallHandler )

-- make a class
function Class( parent )
    -- parent arg is optional
    return util.CopyTable( parent or %_Class )
end

C/48F3299C/luamods/cmdline.lua#

-- cmdline.lua - command line processing module
--
--
-- DEPENDENCIES
--
--      libraries:  stdlib, strlib, mathlib
--

cmdline = { }

--
-- The optionTable argument of these function should be a list of options.
-- Here is an example of an option:
--
--     {
--         switch = "-o",
--         argtype = "string", -- or "scalar", "bool"
--         default = "a.out",
--         varname = "outfile"
--         description = "output file (default:%s)"
--     }
--
-- There may be a printf-style tag in the description string.  It will
-- be mapped to the default value.
--

--
-- GetOptions - parse command line args
--
-- Returns table of option variables.  The table will also contain a field
-- "args" which is a list of remaining unprocessed arguments.
--
-- On error, returns nil and a message.
--
function cmdline.GetOptions(args, optionTable)
    -- initialize option var table with defaults
    local option_vars = { }
    for i = 1, getn(optionTable) do
        local option = optionTable[i]
        option_vars[option.varname] = option.default
    end
    local i = 1
    while i <= getn(args) do
        local item = args[i]
        -- stop processing options when item isn't a switch
        if not strfind(item, "^%-") then break end
        -- look for match in option table
        local option
        for j = 1, getn(optionTable) do
            local e = optionTable[j]
            if item == e.switch then
                option = e
                break
            end
        end
        -- error if option not matched
        if not option then return nil, "unknown option "..item end
        local argtype = option.argtype
        local option_val
        if (argtype == "bool") then
            option_val = 1
        elseif (argtype == "integer") then
            option_val = tonumber(args[i+1])
            if not option_val or option_val ~= floor(option_val) then
                return nil, "expected integer for option "..option.switch
            end
        elseif (argtype == "scalar") then
            option_val = tonumber(args[i+1])
            if not option_val then
                return nil, "expected scalar for option "..option.switch
            end
        else
            option_val = args[i+1]
        end
        option_vars[option.varname] = option_val
        i = i + 1 + ((argtype == "bool") and 0 or 1)
    end
    -- copy remaining args to new table and place in field of output table
    local new_args = { }
    for j = i, getn(args) do
        tinsert(new_args, args[j])
    end
    option_vars.args = new_args
    return option_vars
end

--
-- GetOptionSummary
--
-- Returns a list containing one string for each option, such as:
--
--      "-o string   output file"
--
function cmdline.GetOptionSummary(optionTable)
    local symbol_map = { bool="", scalar="x", string="string", integer="n" }

    -- first find max width of option name field
    local names = { }
    local names_width = 0
    for i = 1, getn(optionTable) do
        local option = optionTable[i]
        local symbol = symbol_map[option.argtype]
        names[i] = option.switch.." "..symbol
        names_width = max(names_width, strlen(names[i]))
    end

    local t = { }
    for i = 1, getn(optionTable) do
        local option = optionTable[i]
        local description = format(option.description, option.default)
        local msg = format("%-"..names_width.."s  %s", names[i], description)
        tinsert(t, msg)
    end
    return t
end

C/48F3299C/luamods/modlib.lua#

-- modlib.lua - Simple module library.
--
--
-- DEPENDENCIES
--
--      libraries:  baselib, strlib

module =
{
    filenames = {},
    paths = {},
}

-- chunk return value is returned, error called on failed import
function module.Import(filename)
    local imports = module.filenames
    if not imports[filename] then
        for path,x in module.paths do
            local fullpath = path.."/"..filename
            imports[filename] = dofile(fullpath)
            if imports[filename] then break end
        end
        assert(imports[filename], 'Module "'..filename..'" not found.')
    end
    return imports[filename]
end

-- path may contain several items separated by a colon
-- NOTE: path search order is not specified
function module.AddPath(path)
    -- tack on an extra : to make the regex easier
    path = path .. ":"
    local index = 1
    while 1 do
        local from, to, path_item = strfind(path, "(.-)%:+", index)
        if not from then break end
        module.paths[path_item] = 1
        index = to+1
    end
end

C/48F3299C/luamods/podlib.lua#

-- podlib.lua - interface to C plain old data
--
-- See README.
--
--
-- DEPENDENCIES
--
--      libraries:  stdlib, strlib, iolib, mathlib, modlib, podlib
--      modules: util
--
--
-- TODO
--
--  options for "user fields"
--  struct to struct copy, CreateTable?
--  check enum range on assignment
--  allow enum as string?  true/false?
--  use numbers instead of userdata for pointers to lower resource usage
--  there should be a way to get array size from Lua

module.Import('util.lua')

pod = { }

----
-- ABI defs
--

pod.abi_table = { }

pod.abi_table['linux_x86'] =
{
    ['char'         ] = { size = 1, alignment = 1 },
    ['short'        ] = { size = 2, alignment = 2 },
    ['int'          ] = { size = 4, alignment = 4 },
    --['long'         ] = { size = 4, alignment = 4 },

    ['bool'         ] = { size = 1, alignment = 1 },
    ['enum'         ] = { size = 4, alignment = 4 },

    ['float'        ] = { size = 4, alignment = 4 },
    --['double'       ] = { size = 8, alignment = 8 },

    ['string'       ] = { size = 4, alignment = 4 },
    ['podvector'    ] = { size = 8, alignment = 4 },
    ['$ptr'         ] = { size = 4, alignment = 4 },
}

----
-- private functions
--
-- GLOSSARY
--
--  def              - pod definition
--  instance         - pod instance
--  proxy            - user interface to pod instance
--  root instance    - an instance not contained by another instance
--
--
-- NOTES
--
-- Here is a synopsis of the internal pod structures:
--
--  abi = {
--      ['char'         ] = { size = 1, alignment = 1 },
--      ['short'        ] = { size = 2, alignment = 2 },
--  }
--
--  def = {
--      defType = 'struct',
--      typeName = 'abc',
--      fieldList = { 'a', 'b', 'c' },
--      size = 9,
--      alignment = 4,
--      fields =
--      {
--          -- static member indicated by nil offset
--          ['a'        ] = { type= 'int'     , offset=  0,  },
--          ['b'        ] = { type= 'float'   , offset=  4,  },
--          ['c'        ] = { type= 'char'    , offset=  8,  },
--      },
--  }
--
--  def = {
--      defType = 'enum',
--      typeName = 'EState',
--      fieldList = { 'IDLE', 'RUN', 'WAIT' },
--      size = 0,
--      alignment = 0,
--      fields =
--      {
--          ['IDLE'     ] = { type= 'enum'    , const=   0,  },
--          ['RUN'      ] = { type= 'enum'    , const=   1,  },
--          ['WAIT'     ] = { type= 'enum'    , const=   2,  },
--      },
--  }
--
--  def = {                 -- these "array defs" are not stored in defs table
--      defType = 'struct',
--      typeName = '$array',
--      arrayResize = function(proxy, n) ... end
--      fieldList = { 1, 2, 3 },
--      size = 12,
--      alignment = 4,
--      fields =
--      {
--          [ 1         ] = { type= 'int'     , offset=  0,  },
--          [ 2         ] = { type= 'int'     , offset=  4,  },
--          [ 3         ] = { type= 'int'     , offset=  8,  },
--      },
--  }
--
--  instance = { def = def, ptr = ptr, parentPtr = parent }
--
--  proxy = { _inst = instance, somefield = nested_proxy }
--

-- this function accounts for typedef'd aliases or enums
-- input may be a type name or a pod member (deprecated)
function pod._getPrimitiveType(x)
    local typename = (type(x) == 'table') and x.type or x
    -- NOTE: assuming a "prim" listed in defs is enum
    return pod.defs[typename] and 'enum' or typename
end

function pod._isPodType(typename)
    local def = pod.defs[typename]
    return def and (def ~= 'enum')
end

function pod._gettable_handler(proxy, index)
    do
        local proxy_val = rawget(proxy, index)
        if proxy_val then return proxy_val end
    end
    local instance = rawget(proxy, '_inst')
    local ptr = instance.ptr
    local def = instance.def
    local member = def.fields[index]
    util.Assert(member,
        'No member "%s" in %s "%s".', index, def.defType, def.typeName)
    local val
    if not member.offset then
        -- static const member
        val = member.const
        assert(val)
    else
        local prim_type = pod._getPrimitiveType(member)
        local f_name = 'pod_get_'..prim_type
        local f = globals()[f_name]
        util.Assert(f, 'Function "%s" not defined.', f_name)
        val = call(f, { ptr, member.offset })
    end
    return val
end

function pod._settable_handler(proxy, index, value)
    -- if member is a pod itself hand off to Assign
    do
        local proxy_val = rawget(proxy, index)
        if proxy_val then
            pod.Assign(proxy_val, value)
            return
        end
    end
    local instance = rawget(proxy, '_inst')
    local ptr = instance.ptr
    local def = instance.def
    local member = def.fields[index]
    util.Assert(member,
        'No member "%s" in %s "%s".', index, def.defType, def.typeName)
    util.Assert(not member.const,
        'Cannot assign to constant member "%s" of %s "%s".',
        index, def.defType, def.typeName)
    local prim_type = pod._getPrimitiveType(member)
    local f_name = 'pod_set_'..prim_type
    local f = globals()[f_name]
    util.Assert(f, 'Function "%s" not defined.', f_name)
    call(f, { ptr, member.offset, value })
end

-- create def on the fly that acts like array
-- TODO: use efficient proxies for fieldList and fields
function pod._makePodvectorDef(elementType, elementSize, elementAlignment, n)
    local make_fieldlist = function()
        local t = { }
        for i = 1, %n do t[i] = i end
        return t
    end
    local make_fields = function()
        local t = { }
        local typeName
        for i = 1, %n do
            t[i] = { type=%elementType, offset=(i-1)*%elementSize }
        end
        return t
    end
    local array_resize = function(proxy, newN)
        if %n == newN then return end
        pod._destroyProxy(proxy)
        local def = pod._makePodvectorDef(%elementType, %elementSize,
            %elementAlignment, newN)
        local podvector_ptr = proxy._inst.parentPtr
        local new_proxy = pod._makeProxy(def, nil, nil, podvector_ptr)
        pod_set_vector(podvector_ptr, newN, pod.GetPointer(new_proxy))
        -- unfortunately must reuse existing proxy table, and can't use
        -- plain copy because it will trigger tag methods
        for i, v in proxy do rawset(proxy, i, nil) end
        for i, v in new_proxy do rawset(proxy, i, v) end
    end
    return
    {
        defType = 'struct',
        typeName = '$array',
        arrayResize = array_resize,
        fieldList = make_fieldlist(),
        size = n * elementSize,
        alignment = elementAlignment,
        fields = make_fields(),
    }
end

function pod._makePodvectorProxy(memberPtr, elementInfo, isBind)
    local n, array
    if isBind then
        n, array = pod_get_podvector(memberPtr)
    else
        n, array = 0, pod_ptr_new(0)
        pod_set_vector(memberPtr, n, array)
    end
    local member_def = pod._makePodvectorDef(elementInfo.type,
        elementInfo.size, elementInfo.alignment, n)
    return pod._makeProxy(member_def, array, isBind, memberPtr)
end

-- if ptr is nil a new structure will be allocated
-- the isBind flag controls initialization of complex members
-- parentPtr is used for special linking such as from array proxy to
--      concrete type
function pod._makeProxy(def, ptr, isBind, parentPtr)
    ptr = ptr or pod_ptr_new(def.size)
    -- ISSUE: would like to keep proxy clean by linking to instance externally,
    --      but will wait for 4.1's weak tables
    local instance = { def = def, ptr = ptr, parentPtr = parentPtr }
    local proxy = { _inst = instance }
    for name, info in def.fields do
        local member_ptr = info.offset and pod_ptr_add(ptr, info.offset)
        if info.type == 'string' then
            if not isBind then
                pod_ptr_init_string(member_ptr)
            end
        elseif info.type == 'podvector' then
            proxy[name] = pod._makePodvectorProxy(member_ptr, info.templateInfo,
                isBind)
        else
            local member_def = pod.defs[info.type]
            -- call recursively on pod members (except enums)
            if member_def and member_def.defType ~= 'enum' then
                proxy[name] = pod._makeProxy(member_def, member_ptr, isBind)
            end
        end
    end
    settag(proxy, pod.tagval)
    return proxy
end

function pod._destroyProxy(proxy)
    -- do special destructions
    -- NOTE: complex member destruction order is not reverse of _makeProxy
    do
        local instance = proxy._inst
        local ptr, def = instance.ptr, instance.def
        for name, info in def.fields do
            if info.type == 'string' then
                pod_ptr_destroy_string(pod_ptr_add(ptr, info.offset))
            end
        end
        if def.typeName == '$array' then
            pod_ptr_del(pod.GetPointer(proxy))
        end
    end
    -- call recursively on nested proxies, skipping instance field
    for name, child in proxy do
        if name ~= '_inst' then pod._destroyProxy(child) end
    end
end

function pod._parse_type(p)
    -- padding with spaces makes matching more simple
    p = ' '..p..' '
    local template_type
    local x, x, basic_type = strfind(p, '%s*([%w_]+)[%s*&]*$')
    if not basic_type then
        -- try again assuming template
        -- NOTE: only supporting one template parameter
        x, x, basic_type, template_type =
            strfind(p, '%s*([%w_]+)%s*<%s*([%w_]+)%s*>[%s*&]*$')
    end
    util.Assert(basic_type, 'Cannot locate type in "%s"', p)
    return
    {
        basicType = basic_type,
        templateType = template_type,
        isPtr = strfind(p, '^.-%*%s*$'),
        isRef = strfind(p, '^.-%&%s*$'),
        isConst = strfind(p, '[%s]const[%s]'),
        isStatic = strfind(p, '[%s]static[%s]'),
    }
end

function pod._parse_construct(abi, s)
    local x, x, def_type, name, members =
        strfind(s, '(%w+)%s+([%w_:]+)%s+(%b{})')
    util.Assert((def_type=='struct' or def_type=='enum') and name and members,
        'Unsupported construct:\n%s', s)
    if def_type=='struct' then
        pod._parse_struct(abi, name, members)
    else
        pod._parse_enum(abi, name, members)
    end
end

-- returns size, alignment
-- ISSUE: abi primitives and defs really need to be unified
function pod._getAbiInfo(abi, typeName)
    -- Both pod and abi structures have size/alignment fields in common.
    -- In the case of enum pod type we use primitive enum.
    local pod_info = pod.defs[typeName] or abi[typeName]
    if (pod_info and pod_info.defType == 'enum') then
        pod_info = abi['enum']
    end
    util.Assert(pod_info, 'Unknown type "%s"', typeName)
    return pod_info.size, pod_info.alignment
end

function pod._parse_struct(abi, name, members)
    --
    -- create table representing members and list of member names
    --
    local members_table = { }
    local members_list = { }
    local closure = { size = 0, alignment = 1 }

    local do_member = function(m)
        local x, x, def_type, name = strfind(m, '^(.+)%s+([%w_]+)$')
        util.Assert(def_type and name, 'Cannot understand "%s"', m)
        local type_info = pod._parse_type(def_type)
        assert(not type_info.isRef, "Reference types not supported.")

        local basic_type = type_info.isPtr and '$ptr' or type_info.basicType
        local member_size, alignment = pod._getAbiInfo(%abi, basic_type)

        -- previous size becomes current offset
        -- first increment size to necessary alignment
        local miss_by = mod(%closure.size, alignment)
        if miss_by > 0 then
            %closure.size = %closure.size + (alignment - miss_by)
        end

        local template_type = type_info.templateType
        local template_info
        if template_type then
            -- TODO: handle nested templates
            local size, alignment = pod._getAbiInfo(%abi, template_type)
            template_info =
            {
                type = template_type,
                size = size,
                alignment = alignment,
            }
        end

        -- create member entry
        %members_table[name] =
        {
            type = basic_type,
            offset = %closure.size,
            templateInfo = template_info
        }
        tinsert(%members_list, name)
        -- update structure size
        %closure.size = %closure.size + member_size
        -- structure alignment is set to largest member alignment
        %closure.alignment = max(%closure.alignment, alignment)
    end

    -- remove outer brackets
    members = gsub(members, '{(.-)}', '%1')
    gsub(members, '(.-);', do_member)

    --
    -- create pod def
    --

    -- final size must be rounded up to structure alignment
    do
        local alignment = closure.alignment
        local size = closure.size
        local miss_by = mod(size, alignment)
        if miss_by > 0 then
            size = size + (alignment - miss_by)
        end
        closure.size = size
    end

    local def =
    {
        defType = 'struct',
        typeName = name,
        fieldList = members_list,
        size = closure.size,
        alignment = closure.alignment,
        fields = members_table,
    }
    --util.PrintVal(def)
    pod.defs[name] = def
end

function pod._parse_enum(abi, name, members)
    --
    -- create table representing members and list of member names
    --
    local members_table = { }
    local members_list = { }
    local closure = { count = 0 }

    local do_member = function(m)
        -- create member entry
        -- ISSUE: should type be set to int here to reduce special cases?
        %members_table[m] = { type = 'enum', const = %closure.count }
        tinsert(%members_list, m)
        %closure.count = %closure.count + 1
    end

    -- remove outer brackets and add ',' to help match
    members = gsub(members, '{(.-)}', '%1,')
    gsub(members, '([%w_]+)%s*,', do_member)

    --
    -- create pod def
    --

    local def =
    {
        defType = 'enum',
        typeName = name,
        fieldList = members_list,
        size = 0,
        alignment = 0, -- this shouldn't be used
        fields = members_table,
    }
    --util.PrintVal(def)
    pod.defs[name] = def
end

-- This is called by podlibopen.
-- TODO: support include path
--
function pod._init(defaultAbiName)
    --pod.includePath = includePath
    pod.defaultAbiName = defaultAbiName
    pod.defs = { }
    pod.tagval = newtag()
    settagmethod(pod.tagval, 'gettable', pod._gettable_handler)
    settagmethod(pod.tagval, 'settable', pod._settable_handler)
end

----
-- public functions
--

-- AddHeader - add definitions from given header file
--
function pod.AddHeader(filename, abiName)
    -- load header into string
    local f = openfile(filename, 'r')
    local f_text = read(f, '*a')
    closefile(f)
    pod.AddHeaderString(f_text)
end

-- AddHeaderString - add definitions from given header string
--
function pod.AddHeaderString(f_text, abiName)
    abiName = abiName or pod.defaultAbiName
    local abi = pod.abi_table[abiName]
    util.Assert(abi, 'Unknown ABI "%s"', abiName)

    -- NOTE: trying to preserve line numbers during these transforms, may
    --      be useful for error reporting someday
    -- NOTE: regex %s matches linefeeds
    -- remove C++ comments
    f_text = gsub(f_text, '(.-)//.-\n', '%1\n')
    -- remove C comments
    f_text = gsub(f_text, '/%*.-%*/', '')
    -- remove C directives
    f_text = gsub(f_text, '#.-\n', '\n')
    -- remove using statements
    f_text = gsub(f_text, '%s*using%s*.-%;', '\n')
    -- remove namespace qualilfier on names
    f_text = gsub(f_text, '[%w_:]*%:%:([%w_]+)', '%1')
    -- remove namespace constructs
    local strip_namespace = function (s)
        return gsub(s, '^.-%{(.*)%}.-$', '%1\n')
    end
    local num_subs
    repeat
        f_text, num_subs = gsub(f_text, '(%s?namespace%s.-%b{}.-;?)',
            strip_namespace)
    until num_subs == 0
    --print(f_text)
    -- now parse the structures, assuming no nesting
    gsub(f_text, '%s*(.-%b{}).-;', util.Bind(pod._parse_construct, abi))
end

-- New - get proxy to new structure instance
--
-- The instance is created using the global C++ new operator.  Destruction from
-- C++ via delete operator is allowed.
--
function pod.New(structName, initializer)
    local def = pod.defs[structName]
    util.Assert(def, 'Unknown type "%s".', structName)
    local proxy = pod._makeProxy(def)
    if initializer then pod.Assign(proxy, initializer) end
    return proxy
end

-- Delete - delete instance
--
function pod.Delete(proxy)
    pod._destroyProxy(proxy)
    pod_ptr_del(proxy._inst.ptr)
end

-- Bind - get proxy to existing structure instance
--
-- The ptr argument must be a userdata pointing to an initialized instance
-- of the named structure.  There is no type checking!
--
function pod.Bind(ptr, structName)
    local def = pod.defs[structName]
    assert(def)
    local proxy = pod._makeProxy(def, ptr, 1)
    return proxy
end

-- GetPointer - get instance pointer as userdata
--
function pod.GetPointer(proxy)
    return proxy._inst.ptr
end

-- GetFields - get a list of fields for given structure
--
function pod.GetFields(proxy)
    return proxy._inst.def.fieldList
end

-- SizeOf - get size in bytes of a given structure
--
function pod.SizeOf(proxy)
    return proxy._inst.def.size
end

-- Assign - initialize/set a structure from a table
--
-- For nested structure members the assignment operator can be used
-- normally.  However for root pods this function must be used.
--
-- The table may be a list, in which case elements of the list are assigned
-- to fields of the structure in order.
--
-- The table may be a map (with no numerical keys), in which case the map
-- elements are assigned to the structure fields of the same name.  All keys
-- in the map must be valid structure fields.
--
function pod.Assign(proxy, table)
    assert(type(table) == 'table', 'Initializer is not a table.')
    local n = getn(table)
    local def = proxy._inst.def
    if def.typeName == '$array' then
        def.arrayResize(proxy, n)
    end
    if n > 0 then
        local fields = pod.GetFields(proxy)
        assert(n <= getn(fields), 'Initializer list too long.')
        for i = 1, n do
            proxy[fields[i]] = table[i]
        end
    else
        for i, v in table do
            proxy[i] = v
        end
    end
end

-- GetAbi - get internal ABI table
--
-- The returned table is a reference not a copy, so modifying it will change
-- library behavior.
--
-- ISSUE: It would be better to return a copy but deep table copy not provided
--      by util module.
--
function pod.GetAbi(name)
    return pod.abi_table[name]
end

-- SetAbi - set internal ABI table
--
function pod.SetAbi(abi, name)
    assert(type(abi) == 'table' and type(name) == 'string')
    pod.abi_table[name] = abi
end

-- SetEeAbi - util for setting ps2 ee ABI
--
--     * bool size may change with switch to gcc-3.0
--     * string size is dependent on STL version
--
function pod.SetEeAbi(boolSize, stringSize, podvectorSize)
    pod.SetAbi(
    {
        ['char'         ] = { size = 1, alignment = 1 },
        ['short'        ] = { size = 2, alignment = 2 },
        ['int'          ] = { size = 4, alignment = 4 },
        --['long'         ] = { size = 8, alignment = 8 },

        ['bool'         ] = { size = boolSize, alignment = boolSize },
        ['enum'         ] = { size = 4, alignment = 4 },

        ['float'        ] = { size = 4, alignment = 4 },
        -- Until some alignment control is supported, this is a hack that when
        -- used as the first member of a struct will give vector alignment.
        ['float_a16'    ] = { size = 4, alignment = 4*4 },
        --['double'       ] = { size = 8, alignment = 8 },

        ['string'       ] = { size = stringSize, alignment = 4 },
        ['podvector'    ] = { size = podvectorSize, alignment = 4 },
        ['$ptr'         ] = { size = 4, alignment = 4 },
    },
    'ps2_ee')
end

-- ExportEnums - copy all defined enums to given table
--
function pod.ExportEnums(table)
    for x, def in pod.defs do
        if def.defType == 'enum' then
            for name, params in def.fields do
                table[name] = params.const
            end
        end
    end
end

C/48F3299C/luamods/util.lua#

-- util.lua - util module
--
--
-- DEPENDENCIES
--
--      libraries:  stdlib, strlib, iolib, xlib
--

util =
{
    FLT_MAX = 3.40282347e+38,
    FLT_EPSILON = 1.192092896e-7,
    identfunc = function(x) return x end,

    -- internal
    _MaxDefaultTag = 5,
}

----
-- TABLE OPERATIONS
----

-- CopyTable
--
function util.CopyTable( t, ... ) -- option: bCopyTag=1
    local bCopyTag = (arg.n < 1) or arg[1]
    local copy = {}
    for i, v in t do
        copy[i] = v
    end
    -- settag does not allow val to be a default tag
    local ttag = tag(t)
    if bCopyTag and (ttag > util._MaxDefaultTag) then
        settag( copy, ttag )
    end
    return copy
end

-- RecursiveCopyTable - like CopyTable but recursively copies nested tables
--
function util.RecursiveCopyTable(t)
    local copy = { }
    for i, v in t do
        if type(v) == 'table' then
            copy[i] = util.RecursiveCopyTable(v)
        else
            copy[i] = v
        end
    end
    return copy
end

-- MergeTable - copy items of table b into table a
--
function util.MergeTable( ta, tb )
    for i, v in tb do
        ta[i] = v
    end
end

-- RecursiveMergeTable - like MergeTable but recursively merges nested tables
--
-- Table b may be nil, in which case table a is not modified.
-- Arrays (tables that return getn > 1) are not merged.
--
function util.RecursiveMergeTable( ta, tb )
    if not tb then return end
    for i, v in tb do
        if type(ta[i]) == 'table' and getn(ta[i]) == 0 then
            util.RecursiveMergeTable(ta[i], v)
        elseif type(v) == 'table' then
            ta[i] = util.RecursiveCopyTable(v)
        else
            ta[i] = v
        end
    end
end

-- WeakMergeTable - copy items of table b into table a if they don't exist
--
function util.WeakMergeTable( ta, tb )
    for i, v in tb do
        ta[i] = ta[i] or v
    end
end

----
-- LIST OPERATIONS
----

-- AppendList - add items in list b to end of list a
--
-- Optional closed range [from, to] may be provided for list b.  Negative
-- index counts from end of table.
--
function util.AppendList(ta, tb, from, to)
    local b_size = getn(tb)
    from = from or 1
    to = to or b_size
    if from < 0 then from = from + (b_size + 1) end
    if to < 0 then to = to + (b_size + 1) end
    local add_count = to - from + 1
    if add_count > 0 then
        local a_size = getn(ta)
        for i = 1, add_count do
            ta[a_size+i] = tb[from+i-1]
        end
        if ta.n then ta.n = ta.n + add_count end
    end
end

-- SearchList - returns index of first element matching value else nil
--
function util.SearchList(t, value)
    for i = 1, getn(t) do
        if t[i] == value then
            return i
        end
    end
    return nil
end

-- RemoveFromList - removes first element matching value if it exists
--
function util.RemoveFromList(t, value)
    local index = util.SearchList(t, value)
    if index then
        tremove(t, index)
    end
end

-- Enum - make an enum table from a list
--
-- Returns table t in which t[list[i]] = i for elements 1..n of list
--
function util.Enum(list)
    local t = { }
    for i = 1, getn(list) do
        t[list[i]] = i
    end
    return t
end

-- ListToTable - transform a list (in place) into a table using given keys
--
-- List and keys must be same length.  Result is undefined if any values
-- in keys are numbers or "n".
--
function util.ListToTable(list, keys)
    local n = getn(list)
    assert(n == getn(keys))
    for i = 1, n do
        list[keys[i]] = list[i]
        list[i] = nil
    end
    list.n = nil
end

----
-- I/O OPERATIONS
----

-- printf - acts like C printf
--
function util.printf( ... )
    -- unfortunately have to use write() to avoid linefeed, which is in iolib
    write( call(format, arg) )
end

-- ToString - includes table contents, optional tag value display
--
function util.ToString( val, showTag, indentLevel )
    showTag = showTag or 1
    indentLevel = indentLevel or 1

    local string = tostring(val)
    if (showTag == 1) and (tag(val) > util._MaxDefaultTag) then
        string = string.." (tag="..tag(val)..")"
    end

    if type(val) == "table" then
        local indent_string = strrep("   ", indentLevel)
        string = string .. " {\n"
        for i,v in val do
            string = string..indent_string.."["..tostring(i).."] = "..
                util.ToString(v, showTag, indentLevel+1).."\n"
        end
        string = string..strrep("   ", indentLevel-1).."}"
    end
    return string
end

-- PrintVal - uses ToString above and has tag display option
--
function util.PrintVal( val, showTag )
    print( util.ToString(val, showTag) )
end

----
-- ERROR CHECKING
----

-- Assert - fast assert with printf style message
--
-- Using printf style for the message is convenient, and often faster since
-- formatting is delayed.  Trailing linefeed is not required.
--
function util.Assert( condition, ... )
    if not condition then
        if getn(arg) > 0 then
            assert(condition, call(format, arg))
        else
            assert( condition )
        end
    end
end

-- GetGlobalNames - returns hash table of current global names
--
function util.GetGlobalNames()
    local names = {}
    for i,x in globals() do
        names[i] = 1
    end
    return names
end

-- DiffGlobalNames - shows diff of current global names vs previously recorded
--
function util.DiffGlobalNames(t)
    local gtable = globals()
    local deleted = {}
    local added = {}
    for i,x in t do
        if not gtable[i] then
            tinsert(deleted, i)
        end
    end
    for i,x in gtable do
        if not t[i] then
            tinsert(added, i)
        end
    end
    sort(deleted)
    sort(added)
    print("Changes to global names:")
    print("    Deleted")
    for i = 1, getn(deleted) do
        print("        "..deleted[i])
    end
    print("    Added")
    for i = 1, getn(added) do
        print("        "..added[i])
    end
end

----
-- ARGUMENT MANIPULATION
----

-- compress - returns its input args as a table
--
function util.compress(...)
    return arg
end

-- expand - return elements of table with indexes 1..getn(), in order,
--      as individual values
--
function util.expand_r(table, from, to)
    if from < to then
        return table[from], util.expand_r(table, from+1, to)
    else
        return table[from]
    end
end

function util.expand(table)
    return util.expand_r(table, 1, getn(table))
end

-- MakeCurry - Generates function that supports currying.
--
-- "realfunc" is the function that finally receives the curried arguments
-- "packcurry" is a function that packs the curried arguments and signals
--      when to stop currying by returning nil.
--

-- internal function
function util._curry(curry_info, arglist)
    if curry_info.packcurry(arglist, curry_info.curried_arg) then
        return function(...)
            return util._curry(%curry_info, arg)
        end
    else
        return call(curry_info.realfunc, curry_info.curried_arg)
    end
end

function util.MakeCurry(realfunc, packcurry)
    return function (...)
        local curry_info =
        {
            realfunc = %realfunc,
            packcurry = %packcurry,
            curried_arg = {},
        }
        return util._curry(curry_info, arg)
    end
end

----
-- FUNCTOR OPERATIONS
----

-- Bind - given functor and set of arguments, generate binding as new functor
--
function util.Bind(functor, ...)
    local bound_args = arg
    return function(...)
        local all_args = { }
        util.AppendList(all_args, %bound_args)
        util.AppendList(all_args, arg)
        return call(%functor, all_args)
    end
end

-- BindFromSecond
--
-- This version skips the first argument when binding.
-- It's useful for object method functors when you want to leave the object
-- argument unbound.
--
function util.BindFromSecond(functor, ...)
    local bound_args = arg
    return function(...)
        local all_args = { arg[1] }
        util.AppendList(all_args, %bound_args)
        util.AppendList(all_args, arg, 2, -1)
        return call(%functor, all_args)
    end
end

-- Chain - generate functor that is chain of input functors
--
-- Return value of output functor is result of last input functor in chain.
--
function util.Chain(...)
    local funs = arg
    local num_funs = getn(funs)
    return function(...)
        local result
        for i=1, %num_funs do
            result = call(%funs[i], arg)
        end
        return result
    end
end

-- functor tests
if nil then
    function a(n, s) print("a("..n..", "..s..")") end
    function b(n, s) print("b("..n..", "..s..")") end

    MyClass = { }
    function MyClass.test(self, n, s) print("MyClass.test("..n..", "..s..")") end

    c = util.Bind(a, 5)
    d = util.Bind(a, 10, "ten")
    e = util.BindFromSecond(MyClass.test, 123)
    f = util.Chain(a, b, a)

    c("five")
    d()
    obj = MyClass   -- (that is, obj is an instance of MyClass)
    e(obj, "abc")
    f(66, "chain")
end

----
-- FILE PATH OPERATIONS
----

-- DirectoryPart - return directory part (without trailing /) of a path
--
function util.DirectoryPart(path)
    local x, x, result = strfind(path, "^(.*)%/.-$")
    return result or "."
end

-- BasePart - return base name of a path
--
function util.BasePart(path)
    local x, x, result = strfind(path, "^.-([^/]*)$")
    return result or ""
end

-- SuffixPart - return final suffix of a path
--
function util.SuffixPart(path)
    local x, x, result = strfind(path, "^.*%.([^/]-)$")
    return result or ""
end

-- RemoveSuffixPart - remove final suffix from path
--
function util.RemoveSuffixPart(path)
    local x, x, result = strfind(path, "^(.*)%.[^/]-$")
    return result or ""
end

-- ReplaceSuffixPart - return path with suffix replaced by given string
--
function util.ReplaceSuffixPart(path, suffix)
    local x, x, result = strfind(path, "^(.*%.)[^/]-$")
    return result .. suffix
end

-- FileExists - return true if file exists and is readable
function util.FileExists(path)
    local file = openfile(path, "rb")
    if file then closefile(file) end
    return file ~= nil
end

----
-- BINARY OPERATIONS
----

--
-- pack/unpack binary strings
--
-- Trying to implement a subset of Perl's pack/unpack.  Refer to Perl's
-- documentation.
--
--      types supported: simple types (l, f, b, x, etc.).  For bit types,
--          string format values are not supported.
--
--      rules supported: repeat
--
-- Support functions for each type must be implemented in C:
--
--      pack_TYPE(value, current_byte, bit_index)
--          where value is of type TYPE.  current_byte and bit_index
--              are only used for bit packing ("b" type, etc)
--          returns triple binary Lua string representing value, argument step,
--              bit step (optional)
--
--      unpack_TYPE(string, byte_index, bit_index)
--          where the data is at byte_index of string.  bit_index is
--              only used for bit packing
--          returns triple value of type TYPE (nil if none), byte step,
--              bit step (optional)
--
--
--  NOTES
--      pack_x/unpack_x are implemented in Lua
--      types A, a, and Z do not support an explicit count
--

function pack_x()
    return "\000", 0
end

function unpack_x()
    return nil, 1
end

util.pack_bittype_match = "[bBhH]"

function util.pack(template, ...)
    local data = ""
    local arg_index = 1
    local template_index = 1
    local bit_index = 0
    while 1 do
        local head, tail, typeid, count_str = strfind(template, "(%a)(%d*)",
            template_index)
        if not head then break end
        local bBitMode = strfind(typeid, util.pack_bittype_match)
        if bit_index > 0 and not bBitMode then
            bit_index = 0
        end
        local func = getglobal("pack_"..typeid)
        util.Assert(func, "function pack_%s not defined", typeid)
        local count = tonumber(count_str) or 1
        for i = 1, count do
            local current_byte = (bit_index > 0) and strbyte(data, -1) or 0
            local data_item, arg_step, bit_step = func(arg[arg_index],
                current_byte, bit_index)
            bit_step = bit_step or 0
            local adjusted_data = (bit_index == 0) and data or
                strsub(data, 1, -2)
            arg_index = arg_index + arg_step
            bit_index = mod(bit_index + bit_step, 8)
            data = adjusted_data .. data_item
            --dump_pack(data, bit_index)
        end
        template_index = tail+1
    end
    return data
end

-- offset defaults to 0
function util.unpack(template, binstring, offset)
    local data = {}
    local data_index = 1 + (offset or 0)
    local template_index = 1
    local bit_index = 0
    while 1 do
        local head, tail, typeid, count_str = strfind(template, "(%a)(%d*)",
            template_index)
        if not head then break end
        local bBitMode = strfind(typeid, util.pack_bittype_match)
        if bit_index > 0 and not bBitMode then
            bit_index = 0
            data_index = data_index + 1
        end
        local func = getglobal("unpack_"..typeid)
        util.Assert(func, "function unpack_%s not defined", typeid)
        local count = tonumber(count_str) or 1
        for i = 1, count do
            local data_item, byte_step, bit_step = func(binstring, data_index,
                bit_index)
            bit_step = bit_step or 0
            data_index = data_index + byte_step
            bit_index = mod(bit_index + bit_step, 8)
            if data_item then
                tinsert(data, data_item)
            end
        end
        template_index = tail+1
    end
    return data
end

if nil then
    function dump_pack(data, bit_index)
        for i = 1, strlen(data) do
            util.printf("%02X ", strbyte(data, i))
        end
        util.printf(", bit:%d\n", bit_index)
    end

    local test = util.pack("b4x3l", 0,1,0,1, 5)
    util.PrintVal(util.unpack("b4x3l", test))
end