mirror of https://github.com/AbePralle/FGB.git
536 lines
17 KiB
Plaintext
536 lines
17 KiB
Plaintext
# To run this build file, install Rogue from github.com/AbePralle/Rogue and type "rogo" at the command line.
|
|
|
|
#$ LIBRARIES(macOS) = rgbds( which:rgbasm )
|
|
|
|
# description()s are optional - Rogo uses introspection to determine which commands are available.
|
|
# 'rogo help default' displays the description for "default", etc.
|
|
description( "default", "The default action is performed when no other actions are specified. Use 'rogo default' to explicitly perform the default option." )
|
|
description( "help", "Displays a list of all actions that can be performed by Rogo." )
|
|
|
|
augment Build
|
|
PROPERTIES
|
|
# These properties can be overridden with a Local.mk setting ROM_NAME=OtherName etc.
|
|
ROM_NAME = "FGB.gb"
|
|
endAugment
|
|
|
|
routine rogo_fix
|
|
#{
|
|
forEach (filepath in File.listing("Assets/Cinema/**"))
|
|
if (not File.is_folder(filepath))
|
|
if (filepath.ends_with(".dat"))
|
|
local to_filepath = "Data/Cinema/" + filepath.after_first("Assets/Cinema/")
|
|
println "$ -> $" (filepath,to_filepath)
|
|
File.rename( filepath, to_filepath )
|
|
endIf
|
|
endIf
|
|
endForEach
|
|
}#
|
|
local existing = Set<<String>>()
|
|
existing.add( "L0001_Contents" )
|
|
existing.add( "L0005_Contents" )
|
|
existing.add( "L0006_Contents" )
|
|
existing.add( "L0007_Contents" )
|
|
existing.add( "L0009_Contents" )
|
|
existing.add( "L0011_Contents" )
|
|
existing.add( "L0013_Contents" )
|
|
existing.add( "L0104_Contents" )
|
|
existing.add( "L0107_Contents" )
|
|
existing.add( "L0109_Contents" )
|
|
existing.add( "L0110_Contents" )
|
|
existing.add( "L0111_Contents" )
|
|
existing.add( "L0112_Contents" )
|
|
existing.add( "L0113_Contents" )
|
|
existing.add( "L0114_Contents" )
|
|
existing.add( "L0200_Contents" )
|
|
existing.add( "L0201_Contents" )
|
|
existing.add( "L0203_Contents" )
|
|
existing.add( "L0204_Contents" )
|
|
existing.add( "L0211_Contents" )
|
|
existing.add( "L0212_Contents" )
|
|
existing.add( "L0213_Contents" )
|
|
existing.add( "L0300_Contents" )
|
|
existing.add( "L0301_Contents" )
|
|
existing.add( "L0302_Contents" )
|
|
existing.add( "L0303_Contents" )
|
|
existing.add( "L0305_Contents" )
|
|
existing.add( "L0306_Contents" )
|
|
existing.add( "L0307_Contents" )
|
|
existing.add( "L0308_Contents" )
|
|
existing.add( "L0309_Contents" )
|
|
existing.add( "L0310_Contents" )
|
|
existing.add( "L0311_Contents" )
|
|
existing.add( "L0312_Contents" )
|
|
existing.add( "L0313_Contents" )
|
|
existing.add( "L0315_Contents" )
|
|
existing.add( "L0400_Contents" )
|
|
existing.add( "L0401_Contents" )
|
|
existing.add( "L0402_Contents" )
|
|
existing.add( "L0403_Contents" )
|
|
existing.add( "L0404_Contents" )
|
|
existing.add( "L0406_Contents" )
|
|
existing.add( "L0407_Contents" )
|
|
existing.add( "L0408_Contents" )
|
|
existing.add( "L0409_Contents" )
|
|
existing.add( "L0410_Contents" )
|
|
existing.add( "L0411_Contents" )
|
|
existing.add( "L0413_Contents" )
|
|
existing.add( "L0500_Contents" )
|
|
existing.add( "L0501_Contents" )
|
|
existing.add( "L0502_Contents" )
|
|
existing.add( "L0503_Contents" )
|
|
existing.add( "L0504_Contents" )
|
|
existing.add( "L0505_Contents" )
|
|
existing.add( "L0506_Contents" )
|
|
existing.add( "L0507_Contents" )
|
|
existing.add( "L0508_Contents" )
|
|
existing.add( "L0509_Contents" )
|
|
existing.add( "L0510_Contents" )
|
|
existing.add( "L0512_Contents" )
|
|
existing.add( "L0600_Contents" )
|
|
existing.add( "L0601_Contents" )
|
|
existing.add( "L0602_Contents" )
|
|
existing.add( "L0603_Contents" )
|
|
existing.add( "L0604_Contents" )
|
|
existing.add( "L0605_Contents" )
|
|
existing.add( "L0606_Contents" )
|
|
existing.add( "L0607_Contents" )
|
|
existing.add( "L0608_Contents" )
|
|
existing.add( "L0609_Contents" )
|
|
existing.add( "L0610_Contents" )
|
|
existing.add( "L0700_Contents" )
|
|
existing.add( "L0701_Contents" )
|
|
existing.add( "L0702_Contents" )
|
|
existing.add( "L0703_Contents" )
|
|
existing.add( "L0704_Contents" )
|
|
existing.add( "L0705_Contents" )
|
|
existing.add( "L0706_Contents" )
|
|
existing.add( "L0707_Contents" )
|
|
existing.add( "L0708_Contents" )
|
|
existing.add( "L0709_Contents" )
|
|
existing.add( "L0710_Contents" )
|
|
existing.add( "L0711_Contents" )
|
|
existing.add( "L0712_Contents" )
|
|
existing.add( "L0800_Contents" )
|
|
existing.add( "L0801_Contents" )
|
|
existing.add( "L0802_Contents" )
|
|
existing.add( "L0803_Contents" )
|
|
existing.add( "L0804_Contents" )
|
|
existing.add( "L0805_Contents" )
|
|
existing.add( "L0806_Contents" )
|
|
existing.add( "L0807_Contents" )
|
|
existing.add( "L0808_Contents" )
|
|
existing.add( "L0809_Contents" )
|
|
existing.add( "L0810_Contents" )
|
|
existing.add( "L0811_Contents" )
|
|
existing.add( "L0812_Contents" )
|
|
existing.add( "L0900_Contents" )
|
|
existing.add( "L0901_Contents" )
|
|
existing.add( "L0902_Contents" )
|
|
existing.add( "L0903_Contents" )
|
|
existing.add( "L0904_Contents" )
|
|
existing.add( "L0905_Contents" )
|
|
existing.add( "L0906_Contents" )
|
|
existing.add( "L0907_Contents" )
|
|
existing.add( "L0908_Contents" )
|
|
existing.add( "L0909_Contents" )
|
|
existing.add( "L0910_Contents" )
|
|
existing.add( "L0911_Contents" )
|
|
existing.add( "L1001_Contents" )
|
|
existing.add( "L1002_Contents" )
|
|
existing.add( "L1003_Contents" )
|
|
existing.add( "L1004_Contents" )
|
|
existing.add( "L1005_Contents" )
|
|
existing.add( "L1006_Contents" )
|
|
existing.add( "L1007_Contents" )
|
|
existing.add( "L1008_Contents" )
|
|
existing.add( "L1009_Contents" )
|
|
existing.add( "L1011_Contents" )
|
|
existing.add( "L1100_Contents" )
|
|
existing.add( "L1101_Contents" )
|
|
existing.add( "L1111_Contents" )
|
|
existing.add( "L1201_Contents" )
|
|
existing.add( "L1300_Contents" )
|
|
existing.add( "L1304_Contents" )
|
|
existing.add( "L1312_Contents" )
|
|
existing.add( "L1403_Contents" )
|
|
existing.add( "L1412_Contents" )
|
|
existing.add( "L1500_Contents" )
|
|
existing.add( "L1512_Contents" )
|
|
existing.add( "L0000_Contents" )
|
|
existing.add( "L0002_Contents" )
|
|
existing.add( "L0003_Contents" )
|
|
existing.add( "L0004_Contents" )
|
|
existing.add( "L0008_Contents" )
|
|
existing.add( "L0010_Contents" )
|
|
existing.add( "L0012_Contents" )
|
|
existing.add( "L0014_Contents" )
|
|
existing.add( "L0015_Contents" )
|
|
existing.add( "L0103_Contents" )
|
|
existing.add( "L0105_Contents" )
|
|
existing.add( "L0106_Contents" )
|
|
existing.add( "L0108_Contents" )
|
|
existing.add( "L0115_Contents" )
|
|
existing.add( "L0205_Contents" )
|
|
existing.add( "L0214_Contents" )
|
|
existing.add( "L0215_Contents" )
|
|
existing.add( "L0304_Contents" )
|
|
existing.add( "L0314_Contents" )
|
|
existing.add( "L0405_Contents" )
|
|
existing.add( "L0412_Contents" )
|
|
existing.add( "L0612_Contents" )
|
|
existing.add( "L0912_Contents" )
|
|
existing.add( "L1000_Contents" )
|
|
existing.add( "L1010_Contents" )
|
|
existing.add( "L1012_Contents" )
|
|
existing.add( "L1102_Contents" )
|
|
existing.add( "L1103_Contents" )
|
|
existing.add( "L1104_Contents" )
|
|
existing.add( "L1105_Contents" )
|
|
existing.add( "L1112_Contents" )
|
|
existing.add( "L1200_Contents" )
|
|
existing.add( "L1202_Contents" )
|
|
existing.add( "L1203_Contents" )
|
|
existing.add( "L1204_Contents" )
|
|
existing.add( "L1212_Contents" )
|
|
existing.add( "L1301_Contents" )
|
|
existing.add( "L1302_Contents" )
|
|
existing.add( "L1400_Contents" )
|
|
existing.add( "L1401_Contents" )
|
|
existing.add( "L1402_Contents" )
|
|
existing.add( "L1502_Contents" )
|
|
existing.add( "L1503_Contents" )
|
|
existing.add( "L1504_Contents" )
|
|
forEach (line at index in LineReader(File("temp.txt")))
|
|
local level = line.extract_string( "*($)*" )
|
|
if (not level) nextIteration
|
|
if (existing.contains(level))
|
|
println line
|
|
else
|
|
println "DW 0,0 ;$" (index)
|
|
endIf
|
|
endForEach
|
|
endRoutine
|
|
|
|
routine rogo_reid( old:String, new:String )
|
|
do_reid( old, new )
|
|
endRoutine
|
|
|
|
routine do_reid( old:String, new:String, &yes )
|
|
if (new == "")
|
|
local temp = "_Temp" + Random.int32(1_000_000)
|
|
do_reid( old, temp )
|
|
do_reid( temp, old.capitalized, &yes )
|
|
return
|
|
elseIf (0 == old.compare_to(new,&ignore_case))
|
|
local temp = "_Temp" + Random.int32(1_000_000)
|
|
do_reid( old, temp )
|
|
do_reid( temp, new, &yes )
|
|
return
|
|
endIf
|
|
execute ''reid --exact "$" "$" "Assets/**" "Data/**" "Source/**"$'' (old,new,which{yes:" --yes"||""})
|
|
execute @|ls Source
|
|
endRoutine
|
|
|
|
routine rogo_default
|
|
rogo_build
|
|
endRoutine
|
|
|
|
routine rogo_build
|
|
local rgbasm = System.find_program( "rgbasm" )
|
|
if (not rgbasm)
|
|
throw Error( "Please install the RGBDS Game Boy assembler from https://github.com/rednex/rgbds" )
|
|
endIf
|
|
|
|
File.create_folder( "Build" )
|
|
File.create_folder( "ROM" )
|
|
|
|
local build_output = "Build/" + Build.ROM_NAME
|
|
local rom_output = "ROM/" + Build.ROM_NAME
|
|
|
|
local obj_files = String[]
|
|
local any_new_obj_files = false
|
|
forEach (asm_file in File.listing("Source/**/*.asm"))
|
|
local obj_file = "Build/$.obj" (File.filename(asm_file).leftmost(-4))
|
|
if (File.is_newer_than(asm_file,obj_file))
|
|
execute "rgbasm -p 0xff $ -o $" (asm_file,obj_file)
|
|
any_new_obj_files = true
|
|
elseIf (File.is_newer_than(obj_file,rom_output))
|
|
any_new_obj_files = true
|
|
endIf
|
|
obj_files.add( obj_file )
|
|
endForEach
|
|
|
|
if (any_new_obj_files)
|
|
execute "rgblink --map Build/FGB.map --sym Build/FGB.sym $ -o $" (obj_files.join(" "),build_output)
|
|
execute "rgbfix -p 0xff -v $" (build_output)
|
|
|
|
local file_size = File.size( build_output )
|
|
println "> Copy $ -> $ ($ bytes)" (build_output,rom_output,file_size.format(","))
|
|
File.copy( build_output, rom_output )
|
|
else
|
|
println "No changes detected. Output: $ ($ bytes)" (rom_output,File.size(rom_output).format(","))
|
|
endIf
|
|
endRoutine
|
|
|
|
routine rogo_clean
|
|
verbose_delete( "Build" )
|
|
endRoutine
|
|
|
|
routine verbose_delete( filepath:String )
|
|
if (File.exists(filepath))
|
|
println "> Delete " + filepath
|
|
File.delete( filepath )
|
|
endIf
|
|
endRoutine
|
|
|
|
routine execute( commands:String, &suppress_error )->Logical
|
|
forEach (cmd in LineReader(commands))
|
|
print( "> " ).println( cmd )
|
|
if (System.run(cmd) != 0)
|
|
if (suppress_error) return false
|
|
else throw Error( "Build failed." )
|
|
endIf
|
|
endForEach
|
|
return true
|
|
endRoutine
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Introspection-based Launcher Framework
|
|
#------------------------------------------------------------------------------
|
|
# Rogo is a "build your own build system" facilitator. At its core Rogo just recompiles build files if
|
|
# needed and then runs the build executable while forwarding any command line arguments. This file contains
|
|
# a default framework which uses introspection to turn command line arguments into parameterized routine calls.
|
|
|
|
# Example: to handle the command "rogo abc xyz 5", define "routine rogo_abc_xyz( n:Int32 )".
|
|
|
|
# "rogo_default" will run in the absence of any other command line argument.
|
|
|
|
# The following "comment directives" can be used in this file to control how RogueC compiles it and to
|
|
# manage automatic dependency installation and linking.
|
|
|
|
# Each of the following should be on a line beginning with the characters #$ (preceding whitespace is fine).
|
|
# Sample args are given.
|
|
|
|
# ROGUEC = roguec # Path to roguec compiler to compile this file with
|
|
# ROGUEC_ARGS = --whatever # Additional options to pass to RogueC
|
|
# CPP = g++ -Wall -std=gnu++11 -fno-strict-aliasing -Wno-invalid-offsetof # C++ compiler path and/or invocation
|
|
# CPP_ARGS = -a -b -c # Additional C++ args
|
|
# LINK = true # Links following LIBRARIES with this Build file
|
|
# LINK = -lalpha -lbeta # Links following LIBRARIES and includes these additional flags
|
|
# LINK = false # Linking turned off for following LIBRARIES - info can still be obtained from #$LIBRARY_FLAGS()
|
|
# LINK(macOS) = ... # Options applying only to System.os=="macOS" (use with any OS and any comment directive)
|
|
# LIBRARIES = libalpha
|
|
# LIBRARIES = libbeta(library-name)
|
|
# LIBRARIES = libfreetype6-dev(freetype2)
|
|
# DEPENDENCIES = Library/Rogue/**/*.rogue
|
|
#
|
|
# LIBRARIES = name(package)
|
|
# LIBRARIES = name(package:<package> install:<install-cmd> link:<link-flags> which:<which-name>)
|
|
#
|
|
# The following macro is replaced within this file (Build.rogue) - the libraries should also be declared in #$ LIBRARIES:
|
|
#
|
|
# $LIBRARY_FLAGS(lib1,lib2) # sample macro
|
|
# ->
|
|
# -Ipath/to/lib1/include -Lpath/to/lib1/library -I ... # sample replacement
|
|
|
|
routine syntax( command:String, text:String )
|
|
Build.rogo_syntax[ command ] = text
|
|
endRoutine
|
|
|
|
routine description( command:String, text:String )
|
|
Build.rogo_descriptions[ command ] = text
|
|
endRoutine
|
|
|
|
routine help( command:String, description=null:String, syntax=null:String )
|
|
if (description) Global.description( command, description )
|
|
if (syntax) Global.syntax( command, syntax )
|
|
endRoutine
|
|
|
|
try
|
|
Build.launch
|
|
catch (err:Error)
|
|
Build.rogo_error = err
|
|
Build.on_error
|
|
endTry
|
|
|
|
class Build [singleton]
|
|
PROPERTIES
|
|
rogo_syntax = StringTable<<String>>()
|
|
rogo_descriptions = StringTable<<String>>()
|
|
rogo_prefix = ?:{ $moduleName.count:$moduleName "::" || "" } + "rogo_" : String
|
|
rogo_command = "default"
|
|
rogo_args = @[]
|
|
rogo_error : Error
|
|
|
|
LOCAL_DEFS_FILE = "Local.mk"
|
|
|
|
METHODS
|
|
method launch
|
|
rogo_args.add( forEach in System.command_line_arguments )
|
|
read_defs
|
|
on_launch
|
|
parse_args
|
|
dispatch_command
|
|
|
|
method dispatch_command
|
|
local m = find_command( rogo_command )
|
|
require m
|
|
|
|
local args = @[]
|
|
forEach (arg in rogo_args)
|
|
which (arg)
|
|
case "true": args.add( true )
|
|
case "false": args.add( false )
|
|
case "null": args.add( NullValue )
|
|
others: args.add( arg )
|
|
endWhich
|
|
endForEach
|
|
if (m.parameter_count == 1 and args.count > 1) args = @[ args ] # Wrap args in a ValueList.
|
|
m.call( Global, args )
|
|
|
|
method find_command( name:String )->MethodInfo
|
|
return <<Global>>.find_method( rogo_prefix + name )
|
|
|
|
method on_error
|
|
Console.error.println "=" * 79
|
|
Console.error.println rogo_error
|
|
Console.error.println "=" * 79
|
|
on_exit
|
|
System.exit 1
|
|
|
|
method on_command_found
|
|
noAction
|
|
|
|
method on_command_not_found
|
|
println "=" * 79
|
|
println "ERROR: No such command '$'." (rogo_args.first)
|
|
println "=" * 79
|
|
println
|
|
rogo_command = "help"
|
|
rogo_args.clear
|
|
on_command_found
|
|
|
|
method on_launch
|
|
noAction
|
|
|
|
method on_exit
|
|
noAction
|
|
|
|
method parse_args
|
|
block
|
|
if (rogo_args.count)
|
|
local parts = String[]
|
|
parts.add( forEach in rogo_args )
|
|
rogo_args.clear
|
|
|
|
while (parts.count)
|
|
local cmd = _join( parts )
|
|
if (find_command(cmd))
|
|
rogo_command = cmd
|
|
on_command_found
|
|
escapeBlock
|
|
endIf
|
|
rogo_args.insert( parts.remove_last )
|
|
endWhile
|
|
|
|
on_command_not_found
|
|
endIf
|
|
|
|
# Use default command
|
|
on_command_found
|
|
endBlock
|
|
|
|
method read_defs
|
|
read_defs( LOCAL_DEFS_FILE )
|
|
|
|
method read_defs( defs_filepath:String )
|
|
# Attempt to read defs from Local.mk
|
|
local overrides = String[]
|
|
if (File.exists(defs_filepath))
|
|
forEach (line in LineReader(File(defs_filepath)))
|
|
if (line.contains("="))
|
|
local name = line.before_first('=').trimmed
|
|
local value = line.after_first('=').trimmed
|
|
if (value.begins_with('"') or value.begins_with('\''))
|
|
value = value.leftmost(-1).rightmost(-1)
|
|
endIf
|
|
local p = <<Build>>.find_property( name )
|
|
if (p)
|
|
overrides.add( "$ = $" (name,value) )
|
|
<<Build>>.set_property( this, p, Value(value) )
|
|
endIf
|
|
endIf
|
|
endForEach
|
|
endIf
|
|
|
|
method _join( value:Value )->String
|
|
local args = String[]
|
|
args.add( forEach in value )
|
|
return args.join( "_" )
|
|
endClass
|
|
|
|
|
|
routine rogo_help( command="":String )
|
|
command = Build._join( Build.rogo_args )
|
|
if (command.count)
|
|
local syntax = get_syntax( command )
|
|
local success = false
|
|
if (syntax)
|
|
println "SYNTAX"
|
|
println " " + syntax
|
|
println
|
|
success = true
|
|
endIf
|
|
local description = get_description( command )
|
|
if (description)
|
|
println "DESCRIPTION"
|
|
forEach (line in LineReader(description.word_wrapped(76)))
|
|
print( " " ).println( line )
|
|
endForEach
|
|
println
|
|
success = true
|
|
endIf
|
|
if (success)
|
|
return
|
|
else
|
|
println "=" * 79
|
|
println "ERROR: No such command '$'." (command)
|
|
println "=" * 79
|
|
println
|
|
endIf
|
|
endIf
|
|
|
|
println "USAGE"
|
|
local lines = String[]
|
|
forEach (m in <<Global>>.methods)
|
|
if (m.name.begins_with(Build.rogo_prefix))
|
|
lines.add( " " + get_syntax(m.name.after_first(Build.rogo_prefix)) )
|
|
endIf
|
|
endForEach
|
|
lines.sort( (a,b)=>(a<b) )
|
|
println (forEach in lines)
|
|
println
|
|
endRoutine
|
|
|
|
|
|
routine get_syntax( m_name:String )->String
|
|
if (Build.rogo_syntax.contains(m_name))
|
|
return "rogo " + Build.rogo_syntax[ m_name ]
|
|
else
|
|
local m = <<Global>>.find_method( Build.rogo_prefix + m_name )
|
|
if (not m) return null
|
|
local line = "rogo $" (m_name.replacing('_',' '))
|
|
line += " <$>" (m.parameter_name(forEach in 0..<m.parameter_count))
|
|
return line
|
|
endIf
|
|
endRoutine
|
|
|
|
|
|
routine get_description( m_name:String )->String
|
|
if (Build.rogo_descriptions.contains(m_name))
|
|
return Build.rogo_descriptions[ m_name ]
|
|
else
|
|
return null
|
|
endIf
|
|
endRoutine
|