We just released a Feb. 5 '89 prototype of DuckTales for the NES!
If you'd like to support our preservation efforts (and this wasn't cheap), please consider donating or supporting us on Patreon. Thank you!

Aqua Teen Hunger Force: Zombie Ninja Pro-Am

From The Cutting Room Floor
Jump to navigation Jump to search

Title Screen

Aqua Teen Hunger Force: Zombie Ninja Pro-Am

Developer: Creat Studios
Publisher: Midway Games
Platform: PlayStation 2
Released in US: November 5, 2007
Released in EU: November 15, 2007
Released in AU: November 16, 2007


SourceIcon.png This game has uncompiled source code.
DevTextIcon.png This game has hidden development-related text.


Zombie Ninja Pro-Am is a mix of golf, beat 'em up and racing. No zombies or ninjas included.

Build Date

A build date is present in the SLES file.

CREAT Game started
Build date: Sep  8 2007; 01:10:12

Source Code

Large chunks of code are scattered around the SLES file, some of which seem to relate to a debugger.

getCallCount
_import_cached_cache = {}
setmetatable(_import_cached_cache, {__mode='v'})
function create_import_cached(get_environment, require)
    local function _import_cached(name)
        if not _import_cached_cache[name]  then
            local function _import()
                require(name)
            end
            local package = {}
            setmetatable(package, {__index=get_environment()})
            setfenv(_import, package)        
            _import()
            
            _import_cached_cache[name] = package
        end
        
        getfenv(2)[name] = _import_cached_cache[name]
    end
    return _import_cached
end
function __class_metatable_call(cls, ...)
    local obj = {}
    setmetatable(obj, cls)
    if obj.construct then
        obj:construct(...)
    end            
    return obj
end
function __class_createMetatable(base)
    if base  then
        return {__index=base}
    else
        return {}
    end        
end
function class(base)
    local cls = {}
    cls.__index = cls
    local metatable = __class_createMetatable(base)
    metatable.__call = __class_metatable_call
    setmetatable(cls, metatable)
    return cls
end
WeakSet = class()
function WeakSet:construct()
    self.values = {}
    setmetatable(self.values, {__mode='k'})
end
function WeakSet:Add(value)
    self.values[value] = true
end
function WeakSet:Remove(value)
    self.values[value] = nil
end
function WeakSet:Values()
    return pairs(self.values)
end
Pool = class()
function Pool:construct(fabricator)
    self.fabricator = fabricator
    self.free_objects = {}
end
function Pool:getObject()
    if 0==table.getn(self.free_objects) then
        realobj = self.fabricator()
    else
        realobj = table.remove(self.free_objects)
    end
    return self:createProxy(realobj)
end
function Pool:createProxy(realobj)
    local pool = self
    
    local p = newproxy(true)
    local meta = getmetatable(p)
    function meta:__gc()
        table.insert(pool.free_objects, realobj)
    end
    
    meta.__index = realobj
    meta.__newindex = realobj
    
    return p
end
function string.split(s, sep)
    local result = {}
    local pos;
    repeat
        pos = string.find(s, sep)
        if pos then
            table.insert(result, string.sub(s, 1, pos-1))
            s = string.sub(s, pos+1)
        else            
            table.insert(result, s)
        end
    until not pos
    return result
end
StringStream = class()
function StringStream:construct()
    self.result = ''
end
function StringStream:write(data)
    self.result = self.result..data
end
StringInputStream = class()
function StringInputStream:construct(dumped)
    self.dumped = dumped
end
function StringInputStream:read(size)
    local result = string.sub(self.dumped, 1, size)
    self.dumped = string.sub(self.dumped, size+1)
    return result
end
DataWriter = class()
function DataWriter:construct(writer)
    self.writer = writer
end
function DataWriter:writeLabel(_type)
    self.writer:write(_type)
    self.writer:write(':')
end
function DataWriter:writeValue(value)
    local value_as_string = tostring(value)
    self.writer:write(tostring(string.len(value_as_string)))
    self.writer:write('>')
    self.writer:write(value_as_string)
end
DataReader = class()
function DataReader:construct(stream)
    self.stream = stream
end
function DataReader:getNext(separator)
    local s = ''
    while true do
        local cur = self.stream:read(1)
        if cur == separator then break end
        s = s .. cur
    end
    return s
end
function DataReader:readLabel()
    return self:getNext(':')
end
function DataReader:readValue(label)
    local size = self:getNext('>')
    local value = self.stream:read(size)
    if label == 'number' then
        return tonumber(value)
    elseif label == 'boolean' then
        return value == 'true'
    else
        return value
    end
end
BinaryDataWriter = class()
function BinaryDataWriter:construct(p)
    self.writer = pickle.DataWriter:new_local(p)
    self._writer_writeBoolean = self.writer.writeBoolean
    self._writer_writeNullTerminatedString = self.writer.writeNullTerminatedString
    self._writer_writeNumber = self.writer.writeNumber
end
function BinaryDataWriter:getSizeWritten()
    return self.writer.current
end
function BinaryDataWriter:writeLabel(_type)
    self._writer_writeNullTerminatedString(self.writer, _type)
end
function BinaryDataWriter:writeValue(value)
    if 'boolean'==type(value) then
        self._writer_writeBoolean(self.writer, value)
    elseif 'string'==type(value) then
        self._writer_writeNullTerminatedString(self.writer, value)
    else
        self._writer_writeNumber(self.writer, value)
    end        
end
function BinaryDataWriter:start()
end
CompactBinaryDataWriter = class(BinaryDataWriter)
CompactBinaryDataWriter.type_assoc = {
    ['nil'] = 'nil',
    ['boolean'] = 'b',
    ['number'] = 'n',
    ['string'] = 's',
    ['table'] = 't',
function CompactBinaryDataWriter:writeLabel(_type)
    self._writer_writeNullTerminatedString(self.writer, self.type_assoc[_type])
end
function CompactBinaryDataWriter:start()
    self.writer:writeVersion()
end
BinaryDataReader = class()
function BinaryDataReader:construct(p)
    self.reader = pickle.DataReader:new_local(p)
    self.reader_methods = {}
    local names = {'readNullTerminatedString', 'readBoolean', 'readNumber'}
    for i, name in ipairs(names) do
        self.reader_methods[name] = self.reader[name]
    end
    
end
function BinaryDataReader:readLabel()
    return self.reader_methods.readNullTerminatedString(self.reader)
end
function BinaryDataReader:readValue(_type)
    if 'boolean'==_type then
        return self.reader_methods.readBoolean(self.reader)
    elseif 'string'==_type then
        return self.reader_methods.readNullTerminatedString(self.reader)
    else    
        return self.reader_methods.readNumber(self.reader)
    end        
end
Saver = class()
function Saver:construct(what_to_dump)
    self.what_to_dump = what_to_dump
end
function Saver:dump(writer)
    self.writer = writer
    self.writer:start()
    self:dumpValue(self.what_to_dump)
end
function Saver:dumpValue(value)
    local _type = type(value)
    if _type == 'table' then
        self.writer:writeLabel(_type)
        self:dumpTable(value)
    else
        self.writer:writeLabel(_type)
        self.writer:writeValue(value)
    end        
end
function Saver:dumpTable(what_to_dump)
    
    local table_size = 0
    for key, value in pairs(what_to_dump) do
        table_size = table_size+1
    end
    
    self.writer:writeValue(table_size)
    
    for key, value in pairs(what_to_dump) do
        self:dumpValue(key)
        self:dumpValue(value)
    end
end
Loader = class()
function Loader:construct(reader)
    self.reader = reader
end
function Loader:getNextValue()
    local label = self.reader:readLabel()
    
    if label=='table' then
        return self:loadTable()
    else 
        return self.reader:readValue(label)
    end            
end
function Loader:loadTable()
    local table_size = self.reader:readValue('number')
    local result = {}
    for i=1, table_size do
        local key = self:getNextValue()
        local value = self:getNextValue()
        result[key] = value
    end            
    return result
end
function Loader:load()
    return self:getNextValue()
end
threading = {}
threading.Thread = class()
function threading.Thread:construct()
    self.co = coroutine.create(
        function () self:run() end)
end
function threading.Thread:isDead()
    return coroutine.status(self.co)=='dead'
end
function threading.Thread:resume()
    return coroutine.resume(self.co)
end
function threading.Thread:yield()
    coroutine.yield()
end
threading.Event = class()
function threading.Event:clear()
    self.is_set = false
end
function threading.Event:set()
    self.is_set = true
end
function threading.Event:wait()
    while self.is_set do
        coroutine.yield()
    end
end
threading.Manager = class()
function threading.Manager:construct(error_handler)
    self.error_handler = error_handler
    self.threads = {}
end
function threading.Manager:start(thread)
    table.insert(self.threads, thread)
end
function threading.Manager:update(thread)
    alive_threads = {}
    for i, thread in ipairs(self.threads) do
        self:resume(thread)
        if not thread:isDead() then
            table.insert(alive_threads, thread)
        end
    end        
    self.threads = alive_threads
end
function threading.Manager:resume(thread)
    local status, err = thread:resume()
    if not status then
        if self.error_handler then
            self.error_handler(err)
        end                
    end            
end
function prettyFormat(value)
    local xxx = {}
    for key, value in pairs(value) do
        if type(value) == 'table' then
            table.insert(xxx, string.format('%s=%q', tostring(key), 'table'))
        else
            table.insert(xxx, string.format('%s=%q', tostring(key), tostring(value)))
        end
    end
    return '{'..table.concat(xxx, ', ')..'}'
end
function assertStringContains(what, where)
    if not string.find(what, where) then
        local message = string.format('%q doesn\'t contain %q', what, where)
        error(message)
    end
end
function assertEquals(expected, actual)
    if (not (expected==actual)) then
        error(tostring(expected)..' != '..tostring(actual))
    end        
end
function isTableContainedInOther(what, where)
    for key, value in pairs(what) do
        if where[key]~=value then
            return false
        end
    end
    return true
end    
    
function assertTablesEqual(expected, actual)
    if not (isTableContainedInOther(actual, expected) 
            and isTableContainedInOther(expected, actual) ) then
        error(prettyFormat(expected)..' != '..prettyFormat(actual))
    end
end
function isTableValuesContainedInOther(what, where)
    for key, value in pairs(what) do
        if type(what[key]) == 'table' then
            if type(where[key]) ~= 'table' then
                return false
            end
            if not isTableValuesContainedInOther(what[key], where[key]) then
                return false
            end
        else
            if where[key]~=value then
                return false
            end
        end
    end
    return true
end    
    
function assertTablesValuesEqual(expected, actual)
    if not (isTableValuesContainedInOther(actual, expected) 
            and isTableValuesContainedInOther(expected, actual) ) then
        error(prettyFormat(expected)..' != '..prettyFormat(actual))
    end
end
function assertTablesValuesNotEqual(expected, actual)
    if (isTableValuesContainedInOther(actual, expected) 
            and isTableValuesContainedInOther(expected, actual) ) then
        error(prettyFormat(expected)..' == '..prettyFormat(actual))
    end
end
function assertLess(expected, actual)
    if(not(expected>actual) ) then
        error(actual..' not less than '..expected)        
    end
end
function assertTrue(actual)
    if(actual ~= true) then
        error(tostring(actual)..' not true')        
    end
end
function assertFalse(actual)
    if(actual ~= false) then
        error(tostring(actual)..' not false')
    end
end
function assertNil(actual)
    if(actual ~= nil) then
        error(tostring(actual)..' not nil')
    end
end
function assertNotEquals(expected, actual)
    if (not (expected~=actual)) then
        error(tostring(expected)..' == '..tostring(actual))
    end        
end
function assertAlmostEquals(expected, actual, deviation)
    if not (((expected - deviation) <= actual) and ((expected + deviation) >= actual)) then
        error(
            tostring(math.abs(expected - actual))..' > '..tostring(deviation)..
            '(expected='..tostring(expected)..', actual='..tostring(actual)..')')
    end
end
function assertR3dVAlmostEquals(expected, actual, deviation)
    local x_deviation = expected.x - actual.x
    local y_deviation = expected.y - actual.y
    local z_deviation = expected.z - actual.z
    local actual_deviation = math.sqrt(x_deviation*x_deviation + y_deviation*y_deviation + 

z_deviation*z_deviation)
    if(not(deviation>=actual_deviation) ) then
        error(actual_deviation..' not less than '..deviation)        
    end
end
function assertNotAlmostEquals(expected, actual, deviation)
    if (((expected - deviation) <= actual) and ((expected + deviation) >= actual)) then
        error(tostring(math.abs(expected - actual))..' <= '..tostring(deviation))
    end
end
function assertR3dVNotAlmostEquals(expected, actual, deviation)
    local x_deviation = expected.x - actual.x
    local y_deviation = expected.y - actual.y
    local z_deviation = expected.z - actual.z
    local actual_deviation = math.sqrt(x_deviation*x_deviation + y_deviation*y_deviation + 

z_deviation*z_deviation)
    assertLess(actual_deviation, deviation)
end
function assertNotNil(actual)
    if(actual == nil) then
        error(tostring(actual)..' is nil')
    end
end
EventsHandler = class()
function createWeak()
    local weak = {}
    setmetatable(weak, {__mode='v'})
    return weak
end
EventsHandler.weak_pool = Pool(createWeak)
function EventsHandler:createCallHandler(obj, func)
    local weak = self.weak_pool:getObject()
    weak.handler_object = obj
    weak.handler = func
    
    local function callHandler(
        arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 

arg14, arg15, arg16, arg17, arg18, arg19, arg20) 
        return handler(handler_object, 
        arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 

arg14, arg15, arg16, arg17, arg18, arg19, arg20) 
    end
    
    local env = {}
    setmetatable(env, {__index=weak})
    
    setfenv(callHandler, env)
    return callHandler
end
function EventsHandler:createMessenger(handler)
    if not handler then return nil end
    
    local messenger = lua.wrap.Messenger:new_local(lua.system.lua_instance)
    table.insert(self.messengers, messenger)
    lua_wrap_setMessengerHandler(messenger, self:createCallHandler(self, handler))
    return messenger
end            
function EventsHandler:construct(message_source, messages)
    self.messengers = {}
    
    for i, message_name in pairs(messages) do
        local handler = self[message_name]
        local messenger_name = '_luawrap_'..message_name..'Messenger'
        message_source[messenger_name] = self:createMessenger(handler)
    end
end
if not crs then
    crs = {}
end    
function crs.print(...)
    args_str = {}
    for i, value in ipairs(arg) do
        table.insert(args_str, tostring(value))
    end
    logMessage(crs.print_msg_log_level(), table.concat(args_str, ' '))
end
function crs.print_msg_log_level()
    return crs.MSG_REPORT
end

platform = 'ps2'
configuration = 'master'
function Flag(...)
    local result=0
    for i, argument in ipairs(arg) do
        result = bitops.OR(result, argument)
    end
    return result
end
function Rect(x1, y1, x2, y2)
    local rect = r3dRECT:new_local()
    rect.x1 = x1
    rect.y1 = y1
    rect.x2 = x2
    rect.y2 = y2
    return rect
end
Ticker = class()
Ticker.Timer = class(gmp.HDL_TIMER)
function Ticker.Timer:construct()
    gmp.HDL_TIMER.construct(self,  999)
    self.tickers = {}
    setmetatable(self.tickers, {__mode='k'})
end
function Ticker.Timer:OnTimer(elapsed)
    for ticker, working in pairs(self.tickers) do
        if working then
            ticker:OnTimer(elapsed)
        end
    end
end
function Ticker:construct()
    if not self.timer then
        Ticker.timer = self.Timer()
    end
end
function Ticker:Start()
    self.timer.tickers[self] = true
end
function Ticker:Stop()
    self.timer.tickers[self] = false
end
ThreadTicker = class(Ticker)
function ThreadTicker:construct(manager)
    Ticker.construct(self)
    self.manager = manager
end
function ThreadTicker:OnTimer(elapsed)
    self.manager:update()
end
SimpleThread = class(threading.Thread)
function SimpleThread:construct(func)
    threading.Thread.construct(self)
    self.func = func
end    
function SimpleThread:run()
    self.func()
end
WaitTicker = class(Ticker)
function WaitTicker:construct(condition)
    Ticker.construct(self)
    self.conditions = {}
end
function WaitTicker:OnTimer(elapsed)
    local unmet_conditions = {}
    for i, c in ipairs(self.conditions) do
        if c.condition() then
            c.event:clear()
        else
            table.insert(unmet_conditions, c)
        end
    end        
    self.conditions = unmet_conditions
end
function Wait(condition)
    local event = threading.Event()
    event:set()
    table.insert(
        wait_ticker.conditions,
        {condition=condition, event=event}
        )
    event:wait()
end
function initThreadManager()
    thread_manager = threading.Manager(
        function (error)
            print(error)
        end
    )
    thread_ticker = ThreadTicker(thread_manager)
    thread_ticker:Start()
    
    wait_ticker = WaitTicker()
    wait_ticker:Start()
end
function startThread(func)
    thread_manager:start(SimpleThread(func))
end
function initServer()
    con.game.HdlServerEvent = class(EventsHandler)
    function con.game.HdlServerEvent:construct()
        self.impl = con.game.luawrap.HdlServerEvent:new_local()
        EventsHandler.construct(
            self, 
            self.impl,
            {'onReceiveConnection', 'onRecive', 'onDisconnect'})
    end
    HdlServerEvent = class(con.game.HdlServerEvent)
    function HdlServerEvent:construct(handler)
        con.game.HdlServerEvent.construct(self)
        self.handler = handler    
    end
    function HdlServerEvent:onReceiveConnection(connect_info, hDl)
    end
    function HdlServerEvent:onDisconnect(hDl)
    end
    function HdlServerEvent:onRecive(pData, len, hDl)
        local received = asLengthString(pData, len)
        self.handler:handle(received)
    end
    TCPServer = class()
    function TCPServer:construct(server_address, handler)
        self._hdl_server_event = HdlServerEvent(handler)
        self._server = con.game.System:createGameServer(
            self._hdl_server_event.impl, server_address[2])
        self._server:EnableListen(true, 666)
    end
    function TCPServer:broadcast(reply)
        reply_len = string.len(reply)
        buf = StringBuffer:new_local(reply_len)
        buf:initStr(reply)
        self._server:BroadcastData(buf.data, reply_len)
    end    
end
function initDebugger()
    lua.debug.Client = class(EventsHandler)
    function lua.debug.Client:construct()
        EventsHandler.construct(
            self, 
            lua.debug.luawrap.Client:new_local(lua.system.lua_instance),
            {'handleMessage'})
    end
    function lua.debug.createDebugger(client)
        local debugger = {}
        debugger.impl = lua.debug.Debugger:new_local(
            lua.system.lua_instance, client.message_source)
            
        function debugger:handleMessage(message)
            debugger.impl:handleMessage(message)
        end        
        
        return debugger
    end
    Debugger = class()
    Debugger.Client = class(lua.debug.Client)
    
    function Debugger.Client:handleMessage(message)
        print('(ldb) '..message)
        if string.find(message, 'breakpoint hit at ') then
            self.debugger:handleMessage('info locals')
        end
    end
        
    Debugger.CommandManager = class(CommandManager)
    function Debugger.CommandManager:construct(debugger)
        CommandManager.construct(self)
        self.debugger = debugger
    end
    function Debugger.CommandManager:OnTranslateCommand(command, args)
        print(command)
        nargs = args:GetNArg()
        if (nargs>=1) and (args:GetArg(0) == 'ldb') then
            _args = {}
            for i=2, args:GetNArg() do
                table.insert(_args, args:GetArg(i-1))
            end
            
            debugger_command = table.concat(_args, ' ')
                
            print('(ldb) '..debugger_command)
            
            self.debugger:handleMessage(debugger_command)
            return gmp.CMD_RESULT_OK
        end
        return gmp.CMD_RESULT_UNKNOWN    
    end
    function Debugger:construct()
        self.client = self.Client()
        self.debugger = lua.debug.createDebugger(self.client)
        self.client.debugger = self.debugger
        self.cmd_manager = self.CommandManager(self.debugger)
        print('(ldb) '..'ready!')
    end
end    
function initConsole()
    LuaConsole = class() 
    function LuaConsole:construct()
        self.cmd_manager = self.CommandManager()
    end
    LuaConsole.CommandManager = class(CommandManager)
    function LuaConsole.CommandManager:OnTranslateCommand(command, args)
        local nargs = args:GetNArg()
        if (nargs>=1) and (args:GetArg(0) == 'lua') then
            local _args = {}
            for i=2, args:GetNArg() do
                table.insert(_args, args:GetArg(i-1))
            end
            
            local chunk = table.concat(_args, ' ')
            
            print('(lua)', chunk)
            
            local compiled, error = loadstring(chunk, chunk)
            if compiled then
                compiled()
            else
                print(error)
            end
                
            return gmp.CMD_RESULT_OK
        end
        return gmp.CMD_RESULT_UNKNOWN    
    end
    lua_console = LuaConsole()
end
function main()
    print = crs.print
    function sendDebugMessage(message)
        if configuration~='master' then
            con.game.GameProjectServer:sendText(message)
        end            
    end
    
    function crsLog(level, message)
        crsLogFileLine('', -1, level, 'lua', message)
    end
    function logMessage(level, text)
        sendDebugMessage(text)
        for i, value in ipairs(string.split(text, '\n')) do
            crsLog(level, value)
        end
    end
    
    function fatalError(text)
        error(text)
    end
    function fs.FILE_STREAM_readString(self, maxLen)
        local buf = StringBuffer:new(maxLen)
        fs.readString(self, buf, maxLen, 0)    
        local result = buf:asString()
        buf:delete()
        return result
    end
    if configuration~='master' then
        CommandManager = gmp.HDL_CMD_MANAGER
        initServer()
        initConsole()
        initDebugger()
    end        
    Importer = class(sbf2.HDL_IMPORT)
    function Importer:construct(name)
        sbf2.HDL_IMPORT.construct(self, name)
    end
    
    Reader = class()
    
    function Reader:construct(pReader, startOffset)
        self.pReader = pReader
        self.startOffset = startOffset
    end
    
    function Reader:getPtr(pReader)
        return fs.FILE_STREAM_getCurrentPointer(self.pReader, self.startOffset)
    end
    
    function Reader:skipBytes(bytes)
        self.pReader:Seek(bytes, fs.FS_SEEK_CUR)
    end
    
    function Reader:read(text_length)
        local buf = StringBuffer:new_local(text_length)
        self.pReader:Read(buf.data, text_length)
        return asLengthString(buf.data, text_length)
    end        
    function Reader:readByte()
        local size_read, value = self.pReader:ReadByte(0)
        return value        
    end        
    
    function Reader:readDWord()
        local _, value = self.pReader:ReadDWord(0)
        return value        
    end        
    
    function Reader:readString(length)
        return fs.FILE_STREAM_readString(self.pReader, length)
    end
    
        
    function readTextFromStream(script_file, text_length)
        return script_file:read(text_length)
    end        
    
    function readTextFromFile(script_fpath)
        local file_system = fs.System
        local script_file = file_system:OpenFile(
            script_fpath,
            fs.OPEN_FILE_READ, fs.OPEN_FILE_SHARE_READ, fs.OPEN_FILE_OPENEXIST)
            
        local text_length = script_file:GetFileSize()
        local text = readTextFromStream(Reader(script_file, 0), text_length)
        
        script_file:Close()
        
        return text
    end
        function isFile(fpath)
        local file_system = fs.System
        return fs.FS_ERROR_NONE==file_system:IsFileExist(fpath)
    end
        
    function readScriptFromRemoteFile(fpath)
        if platform=='win32' then
            return CompiledScript(assert(loadfile(fpath)), fpath)
        else
            return TextScript(readTextFromFile(fpath), fpath)
        end            
    end
    
    
    TextPtrScript = class()
    
    function TextPtrScript:construct(ptr, size, fpath)
        self.ptr = ptr
        self.size = size
        self.fpath = fpath
    end
    function TextPtrScript:getCompiled()
        return self:compile()
    end
    
    function TextPtrScript:compile()
        local text_length= self.size
        
        local text = asLengthString(self.ptr, text_length)
        
        local compiled, message = loadstring(text, self.fpath)
        if not compiled then
            fatalError(message)
        end
        return compiled
    end        
    
    
    TextScript = class()
    
    function TextScript:construct(text, fpath)
        self.text = text
        self.fpath = fpath
    end
    function TextScript:getCompiled()
        return self:compile()
    end
    
    function TextScript:compile()
        local compiled, message = loadstring(self.text, self.fpath)
        if not compiled then
            fatalError(message)
        end
        return compiled
    end        
    
    CompiledScript = class()
    
    function CompiledScript:construct(compiled, fpath)
        self.compiled = compiled
        self.fpath = fpath
    end
    function CompiledScript:getCompiled()
        return self.compiled
    end
    
    function readScript(reader)
        local has_debug_info = 1==reader:readByte()
        
        local script_size = reader:readDWord()
        local script_ptr = reader:getPtr()
        reader:skipBytes(script_size)
        
        if not has_debug_info then
            return TextPtrScript(script_ptr, script_size, '<unknown sbf script>')
        else
            local script_fpath = reader:readString(MAX_PATH)
            if isFile(script_fpath) then
                return readScriptFromRemoteFile(script_fpath)
            else
                crsLog(crs.MSG_WARNING, 'file '..script_fpath..' not found. Retrieving script 

data from SBF.')
                return TextPtrScript(script_ptr, script_size, script_fpath)
            end
        end
    end        
    
    function createScriptEnv()
        local env = {}
        setmetatable(env, {__index=_G})
        return env
    end
    
    function executeScript(script, env)
        local compiled = script:getCompiled()
        
        setfenv(compiled, env)
        
        compiled()
        
        script.env = env
    end    
    
    MemoryTracer = class()
    
    function MemoryTracer:construct()
        self.stack = {}
    end
    
    function MemoryTracer:Push()
        table.insert(self.stack, true)
    end
    function MemoryTracer:Pop()
        table.remove(self.stack)
    end
    function MemoryTracer:Report()
        local gc_mem, gc_thresh = gcinfo()
        collectgarbage()
        local gc_mem_new, gc_thresh_new = gcinfo()
        self:Log(
            'mem usage:', gc_mem, gc_thresh, 
            ';',
            'after collectgarbage', gc_mem_new, gc_thresh_new)
    end
    
    function MemoryTracer:Log(...)
        local indent_size = table.getn(self.stack)-1
        local indent = string.rep('----', indent_size)
        print(indent, unpack(arg))
    end
    
    memory_tracer = MemoryTracer()
    LuaExecutable = class(Importer)
    function LuaExecutable:construct()
        Importer.construct(self, "LuaExecutable")
        self.scripts = {}    
    end
    function LuaExecutable:OnLoadContent(
        pLoader, version, startOffset, pReader, sbfHandle, pDebugInfo)
        
        memory_tracer:Push()
        memory_tracer:Log('LuaExecutable load', sbfHandle)
        memory_tracer:Report()
        
        local script = readScript(Reader(pReader, startOffset))
        
        memory_tracer:Log('fpath:', script.fpath)
        memory_tracer:Report()
        memory_tracer:Pop()
        
        self.scripts[sbfHandle] = script
                
        return true;
    end
    function LuaExecutable:OnAfterSBFLoaded(
        pLoader, version, startOffset, pReader, sbfHandle, pDebugInfo)
        memory_tracer:Push()
        memory_tracer:Log('LuaExecutable execute', sbfHandle)
        memory_tracer:Report()
        executeScript(self.scripts[sbfHandle], createScriptEnv())
        memory_tracer:Report()
        memory_tracer:Pop()
    end
    function LuaExecutable:OnUnLoadContent(
        pLoader, version, startOffset, pReader, sbfHandle, pDebugInfo)
        memory_tracer:Push()
        memory_tracer:Log('LuaExecutable', sbfHandle, 'unload.')
        self.scripts[sbfHandle] = nil
        memory_tracer:Report()
        memory_tracer:Pop()
    end
    lua_executable = LuaExecutable()
    LuaPackage = class(Importer)
    function LuaPackage:construct()
        Importer.construct(self, "LuaPackage")
        self.scripts = {}
        self.names = {}
    end
        
    function LuaPackage:OnLoadContent(
        pLoader, version, startOffset, pReader, sbfHandle, pDebugInfo)
        
        memory_tracer:Push()
        memory_tracer:Log('LuaPackage load:', sbfHandle)
        memory_tracer:Report()
        
        local reader = Reader(pReader, startOffset)
        
        local name = reader:readString(MAX_PATH)
        local script = readScript(reader)
            
        memory_tracer:Log('fpath:', script.fpath)
        
        self.scripts[sbfHandle] = script
        self.names[sbfHandle] = name
        
        memory_tracer:Pop()
        return true
    end
    function LuaPackage:OnUnLoadContent(
        pLoader, version, startOffset, pReader, sbfHandle, pDebugInfo)
        
        memory_tracer:Push()
        memory_tracer:Log('LuaPackage', sbfHandle, 'unload.')
        memory_tracer:Report()
        
        self.scripts[sbfHandle] = nil
        self.names[sbfHandle] = nil
        memory_tracer:Report()
        memory_tracer:Pop()
    end
        
    lua_package = LuaPackage()
    function require(package_name)
        
        for key, name in pairs(lua_package.names) do
            if name==package_name then
                memory_tracer:Push()
                memory_tracer:Log('LuaPackage execute:', key)
                executeScript(lua_package.scripts[key], getfenv(2))
                memory_tracer:Report()
                memory_tracer:Pop()
                return
            end
        end
        
        error("require: Can't find package "..package_name)
    end
    
    GCTicker = class(Ticker)
    function GCTicker:construct()    
        Ticker.construct(self)
        self.frames_passed = 1
    end
    
    function GCTicker:OnTimer(e)    
        self.frames_passed = self.frames_passed+1
        if self.frames_passed>1 then
            collectgarbage('step', 10)
            self.frames_passed = 1
        end        
    end
    gcticker = GCTicker()
    gcticker:Start()
    print("SystemLib main.lua executed!")
    print("memory usage:", gcinfo())
    collectgarbage()
    print("memory usage after collectgarbage:", gcinfo())
end

LoadEventHandlerManager = class(gm.GameEventsHandler)
function LoadEventHandlerManager:construct()
    gm.GameEventsHandler.construct(self)
    gmLoader_setReceiver(self.this)
    self.handlers = WeakSet()
    self.new_handlers = WeakSet()
end
function LoadEventHandlerManager:OnFinished()
    for handler in self.handlers:Values() do
        handler:OnFinished()
    end    
    for handler in self.new_handlers:Values() do
        handler:OnLoadFinished()
    end    
end
function LoadEventHandlerManager:OnUnloadBefore()
    for handler in self.new_handlers:Values() do
        handler:OnBeforeUnload()
    end    
end
LoadEventHandlerManager.instance = LoadEventHandlerManager()
LoadFinishedEventHandler = class()
function LoadFinishedEventHandler:construct()
    LoadEventHandlerManager.instance.handlers:Add(self)
end
function LoadFinishedEventHandler:OnFinished()
end
LoadEventHandler = class()
print('LoadEventHandler')
print(LoadEventHandler)
function LoadEventHandler:construct()
    if not LoadEventHandlerManager.instance then
        LoadEventHandlerManager.instance = LoadEventHandlerManager()
    end
    
    LoadEventHandlerManager.instance.new_handlers:Add(self)
end
function LoadEventHandler:OnLoadFinished()
end
function LoadEventHandler:OnBeforeUnload()
end
platform = 'ps2'
configuration = 'master'
function game_code_init() 
    _G.import = create_import_cached(
    function() return _G end,
    require
    )
    print('game system lua executed')
end