If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

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.
GraphicsIcon.png This game has unused graphics.
MusicIcon.png This game has unused music.


Hmmm...
To do:
Add a prerelease section

Check if the debug stuff work

Compare US,EU,and AU versions

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

Unused Graphics

5664d7b054696e2b-54ef2f9a5d2de224-00005dd3.png Early hud graphic.

Frylock eyes.png in Frylock eyes graphic there is a random graphic of his braces, this could have mean that Frylock was gonna smile at some point in the main menu randomly.

A1bc0940ae58d8b-c53e4d9046696433-00005e13.png Early hud graphic.

D742137725708a47-00006200.png Unused font that could probably be used for debug.

Unused Music

TRACK1

  • Unknown music track.

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