Implemented gc tag methods to get rid of some more memory leaks.

This commit is contained in:
Marcus Comstedt 2006-02-26 20:04:25 +00:00
parent f532857b06
commit 7edab1abfb
2 changed files with 122 additions and 47 deletions

168
lua.cpp
View file

@ -32,6 +32,7 @@
#include "font.h"
#include "primitives.h"
#include "savegame.h"
#include "lipsynch.h"
#include "imuse/imuse.h"
@ -41,6 +42,8 @@
extern Imuse *g_imuse;
static int tagSTAT, tagACTR, tagCOLR, tagFONT, tagVBUF, tagPRIM, tagTEXT;
#define strmatch(src, dst) (strlen(src) == strlen(dst) && strcmp(src, dst) == 0)
#define DEBUG_FUNCTION() debugFunction("Function", __FUNCTION__)
@ -49,35 +52,35 @@ static void stubWarning(char *funcName);
static inline bool isObject(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('STAT'))
if (lua_isuserdata(param) && lua_tag(param) == tagSTAT)
return true;
return false;
}
static inline bool isActor(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('ACTR'))
if (lua_isuserdata(param) && lua_tag(param) == tagACTR)
return true;
return false;
}
static inline bool isColor(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('COLR'))
if (lua_isuserdata(param) && lua_tag(param) == tagCOLR)
return true;
return false;
}
static inline bool isFont(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('FONT'))
if (lua_isuserdata(param) && lua_tag(param) == tagFONT)
return true;
return false;
}
static inline bool isBitmapObject(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('VBUF'))
if (lua_isuserdata(param) && lua_tag(param) == tagVBUF)
return true;
return false;
}
@ -85,7 +88,7 @@ static inline bool isBitmapObject(int num) {
// Helper functions to ensure the arguments we get are what we expect
static inline ObjectState *check_object(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('STAT'))
if (lua_isuserdata(param) && lua_tag(param) == tagSTAT)
return static_cast<ObjectState *>(lua_getuserdata(param));
luaL_argerror(num, "objectstate expected");
return NULL;
@ -93,7 +96,7 @@ static inline ObjectState *check_object(int num) {
static inline Actor *check_actor(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('ACTR'))
if (lua_isuserdata(param) && lua_tag(param) == tagACTR)
return static_cast<Actor *>(lua_getuserdata(param));
luaL_argerror(num, "actor expected");
return NULL;
@ -101,7 +104,7 @@ static inline Actor *check_actor(int num) {
static inline Color *check_color(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('COLR'))
if (lua_isuserdata(param) && lua_tag(param) == tagCOLR)
return static_cast<Color *>(lua_getuserdata(param));
luaL_argerror(num, "color expected");
return NULL;
@ -109,7 +112,7 @@ static inline Color *check_color(int num) {
static inline Font *check_font(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('FONT'))
if (lua_isuserdata(param) && lua_tag(param) == tagFONT)
return static_cast<Font *>(lua_getuserdata(param));
luaL_argerror(num, "font expected");
return NULL;
@ -117,7 +120,7 @@ static inline Font *check_font(int num) {
static inline PrimitiveObject *check_primobject(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('PRIM'))
if (lua_isuserdata(param) && lua_tag(param) == tagPRIM)
return static_cast<PrimitiveObject *>(lua_getuserdata(param));
luaL_argerror(num, "primitive (rectangle) expected");
return NULL;
@ -125,7 +128,7 @@ static inline PrimitiveObject *check_primobject(int num) {
static inline TextObject *check_textobject(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('TEXT'))
if (lua_isuserdata(param) && lua_tag(param) == tagTEXT)
return static_cast<TextObject *>(lua_getuserdata(param));
luaL_argerror(num, "textobject expected");
return NULL;
@ -133,7 +136,7 @@ static inline TextObject *check_textobject(int num) {
static inline Bitmap *check_bitmapobject(int num) {
lua_Object param = lua_getparam(num);
if (lua_isuserdata(param) && lua_tag(param) == MKID('VBUF'))
if (lua_isuserdata(param) && lua_tag(param) == tagVBUF)
return static_cast<Bitmap *>(lua_getuserdata(param));
luaL_argerror(num, "image object expected");
return NULL;
@ -292,6 +295,10 @@ static void CheckForFile() {
// Color functions
static void gc_color() {
delete check_color(1);
}
static unsigned char clamp_color(int c) {
if (c < 0)
return 0;
@ -306,7 +313,7 @@ static void MakeColor() {
DEBUG_FUNCTION();
c = new Color (clamp_color(check_int(1)), clamp_color(check_int(2)), clamp_color(check_int(3)));
lua_pushusertag(c, MKID('COLR'));
lua_pushusertag(c, tagCOLR);
}
static void GetColorComponents() {
@ -343,6 +350,12 @@ static void WriteRegistryValue() {
// Actor functions
static void gc_actor() {
Actor *actor = check_actor(1);
g_engine->killActor(actor);
delete actor;
}
static void LoadActor() {
const char *name;
@ -351,7 +364,7 @@ static void LoadActor() {
name = "<unnamed>";
else
name = luaL_check_string(1);
lua_pushusertag(new Actor(name), MKID('ACTR'));
lua_pushusertag(new Actor(name), tagACTR);
}
static void GetActorTimeScale() {
@ -379,7 +392,7 @@ static void GetCameraActor() {
DEBUG_FUNCTION();
stubWarning("VERIFY: GetCameraActor");
act = g_engine->selectedActor();
lua_pushusertag(act, MKID('ACTR'));
lua_pushusertag(act, tagACTR);
}
static void SetSayLineDefaults() {
@ -430,7 +443,7 @@ static void GetActorTalkColor() {
DEBUG_FUNCTION();
act = check_actor(1);
c = new Color(act->talkColor());
lua_pushusertag(c, MKID('COLR'));
lua_pushusertag(c, tagCOLR);
}
static void SetActorRestChore() {
@ -1379,7 +1392,7 @@ static void GetVisibleThings() {
// Consider the active actor visible
if (sel == (*i) || sel->angleTo(*(*i)) < 90) {
lua_pushobject(result);
lua_pushusertag(*i, MKID('ACTR'));
lua_pushusertag(*i, tagACTR);
lua_pushnumber(1);
lua_settable();
}
@ -2167,20 +2180,8 @@ void GetControlState() {
pushbool(g_driver->getControlState(num));
}
static void GetImage() {
char *bitmapName;
DEBUG_FUNCTION();
bitmapName = luaL_check_string(1);
Bitmap *image = g_resourceloader->loadBitmap(bitmapName);
lua_pushusertag(image, MKID('VBUF'));
}
static void FreeImage() {
Bitmap *bitmap;
DEBUG_FUNCTION();
bitmap = check_bitmapobject(1);
static void killBitmapPrimitives(Bitmap *bitmap)
{
for (Engine::PrimitiveListType::const_iterator i = g_engine->primitivesBegin(); i != g_engine->primitivesEnd(); i++) {
PrimitiveObject *p = *i;
if (p->isBitmap() && p->getBitmapHandle() == bitmap) {
@ -2188,8 +2189,33 @@ static void FreeImage() {
break;
}
}
}
g_resourceloader->uncache(bitmap->getFilename());
static void gc_bitmap() {
Bitmap *bitmap;
DEBUG_FUNCTION();
bitmap = check_bitmapobject(1);
killBitmapPrimitives(bitmap);
bitmap->luaGc();
}
static void GetImage() {
char *bitmapName;
DEBUG_FUNCTION();
bitmapName = luaL_check_string(1);
Bitmap *image = g_resourceloader->loadBitmap(bitmapName);
image->luaRef();
lua_pushusertag(image, tagVBUF);
}
static void FreeImage() {
Bitmap *bitmap;
DEBUG_FUNCTION();
bitmap = check_bitmapobject(1);
killBitmapPrimitives(bitmap);
}
static void BlastImage() {
@ -2270,6 +2296,12 @@ static void Exit() {
g_driver->quit();
}
static void gc_textobject() {
TextObject *textObject = check_textobject(1);
g_engine->killTextObject(textObject);
delete textObject;
}
/* Check for an existing object by a certain name
* this function is used by several functions that look
* for text objects to see if they need to be created/modified/destroyed.
@ -2385,7 +2417,7 @@ static void MakeTextObject() {
textObject->createBitmap();
g_engine->registerTextObject(textObject);
lua_pushusertag(textObject, MKID('TEXT'));
lua_pushusertag(textObject, tagTEXT);
lua_pushnumber(textObject->getBitmapWidth());
lua_pushnumber(textObject->getBitmapHeight());
}
@ -2516,6 +2548,12 @@ static void PauseMovie() {
g_smush->pause(lua_isnil(lua_getparam(1)) != 0);
}
static void gc_primitive() {
PrimitiveObject *primitive = check_primobject(1);
g_engine->killPrimitiveObject(primitive);
delete primitive;
}
static void PurgePrimitiveQueue() {
DEBUG_FUNCTION();
g_engine->killPrimitiveObjects();
@ -2544,7 +2582,7 @@ static void DrawLine() {
lua_pushobject(tableObj);
lua_pushstring("color");
lua_Object colorObj = lua_gettable();
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKID('COLR')) {
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == tagCOLR) {
color = static_cast<Color *>(lua_getuserdata(colorObj));
}
}
@ -2552,7 +2590,7 @@ static void DrawLine() {
PrimitiveObject *p = new PrimitiveObject();
p->createLine(x1, x2, y1, y2, color);
g_engine->registerPrimitiveObject(p);
lua_pushusertag(p, MKID('PRIM'));
lua_pushusertag(p, tagPRIM);
}
static void ChangePrimitive() {
@ -2588,7 +2626,7 @@ static void ChangePrimitive() {
lua_pushobject(tableObj);
lua_pushstring("color");
lua_Object colorObj = lua_gettable();
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKID('COLR')) {
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == tagCOLR) {
color = static_cast<Color *>(lua_getuserdata(colorObj));
pmodify->setColor(color);
}
@ -2621,7 +2659,7 @@ static void DrawRectangle() {
lua_pushobject(tableObj);
lua_pushstring("color");
lua_Object colorObj = lua_gettable();
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKID('COLR')) {
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == tagCOLR) {
color = static_cast<Color *>(lua_getuserdata(colorObj));
}
@ -2635,7 +2673,7 @@ static void DrawRectangle() {
PrimitiveObject *p = new PrimitiveObject();
p->createRectangle(x1, x2, y1, y2, color, filled);
g_engine->registerPrimitiveObject(p);
lua_pushusertag(p, MKID('PRIM'));
lua_pushusertag(p, tagPRIM);
}
static void BlastRect() {
@ -2659,7 +2697,7 @@ static void BlastRect() {
lua_pushobject(tableObj);
lua_pushstring("color");
lua_Object colorObj = lua_gettable();
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == MKID('COLR')) {
if (lua_isuserdata(colorObj) && lua_tag(colorObj) == tagCOLR) {
color = static_cast<Color *>(lua_getuserdata(colorObj));
}
@ -2700,6 +2738,12 @@ static void GetDiskFreeSpace() {
}
// Objectstate functions
static void gc_object() {
ObjectState *state = check_object(1);
g_engine->currScene()->deleteObjectState(state);
delete state;
}
static void NewObjectState() {
ObjectState *state = NULL;
ObjectState::Position pos;
@ -2719,7 +2763,7 @@ static void NewObjectState() {
state = new ObjectState(setupID, pos, bitmap, zbitmap, visible);
g_engine->currScene()->addObjectState(state);
lua_pushusertag(state, MKID('STAT'));
lua_pushusertag(state, tagSTAT);
}
static void FreeObjectState() {
@ -2735,7 +2779,7 @@ static void SendObjectToBack() {
DEBUG_FUNCTION();
param = lua_getparam(1);
if (lua_isuserdata(param) && lua_tag(param) == MKID('STAT')) {
if (lua_isuserdata(param) && lua_tag(param) == tagSTAT) {
ObjectState *state = static_cast<ObjectState *>(lua_getuserdata(param));
// moving object to top in list ?
g_engine->currScene()->moveObjectStateToFirst(state);
@ -2747,7 +2791,7 @@ static void SendObjectToFront() {
DEBUG_FUNCTION();
param = lua_getparam(1);
if (lua_isuserdata(param) && lua_tag(param) == MKID('STAT')) {
if (lua_isuserdata(param) && lua_tag(param) == tagSTAT) {
ObjectState *state = static_cast<ObjectState *>(lua_getuserdata(param));
// moving object to last in list ?
g_engine->currScene()->moveObjectStateToLast(state);
@ -2782,7 +2826,8 @@ static void ScreenShot() {
Bitmap *screenshot = g_driver->getScreenshot(width, height);
g_engine->setMode(mode);
if (screenshot) {
lua_pushusertag(screenshot, MKID('VBUF'));
screenshot->luaRef();
lua_pushusertag(screenshot, tagVBUF);
} else {
lua_pushnil();
}
@ -2838,7 +2883,8 @@ static void GetSaveGameImage() {
savedState->readBlock(data, dataSize);
screenshot = new Bitmap(data, width, height, "screenshot");
if (screenshot) {
lua_pushusertag(screenshot, MKID('VBUF'));
screenshot->luaRef();
lua_pushusertag(screenshot, tagVBUF);
} else {
lua_pushnil();
error("Could not restore screenshot from file!");
@ -2960,6 +3006,10 @@ static int RestoreCallback(int /*tag*/, int value, SaveGame * /*savedState*/) {
return value;
}
static void gc_font() {
check_font(1)->luaGc();
}
static void LockFont() {
lua_Object param1;
@ -2969,7 +3019,8 @@ static void LockFont() {
char *fontName = lua_getstring(param1);
Font *result = g_resourceloader->loadFont(fontName);
if (result) {
lua_pushusertag(result, MKID('FONT'));
result->luaRef();
lua_pushusertag(result, tagFONT);
}
}
}
@ -3105,10 +3156,10 @@ static void debugFunction(char *debugMessage, const char *funcName) {
else if (lua_istable(lua_getparam(i)))
fprintf(output, "{...}");
else if (lua_isuserdata(lua_getparam(i))) {
if (lua_tag(lua_getparam(i)) == MKID('ACTR')) {
if (lua_tag(lua_getparam(i)) == tagACTR) {
Actor *a = check_actor(i);
fprintf(output, "<actor \"%s\">", a->name());
} else if (lua_tag(lua_getparam(i)) == MKID('COLR')) {
} else if (lua_tag(lua_getparam(i)) == tagCOLR) {
Color *c = check_color(i);
fprintf(output, "<color #%02x%02x%02x>", c->red(), c->green(), c->blue());
} else
@ -3723,6 +3774,29 @@ void register_lua() {
lua_pushnumber(0x8000);
lua_setglobal("HOT");
// Create userdata tags, and set gc tagmethods
tagSTAT = lua_newtag();
tagACTR = lua_newtag();
tagCOLR = lua_newtag();
tagFONT = lua_newtag();
tagVBUF = lua_newtag();
tagPRIM = lua_newtag();
tagTEXT = lua_newtag();
lua_pushcfunction(gc_object);
lua_settagmethod(tagSTAT, "gc");
lua_pushcfunction(gc_actor);
lua_settagmethod(tagACTR, "gc");
lua_pushcfunction(gc_color);
lua_settagmethod(tagCOLR, "gc");
lua_pushcfunction(gc_font);
lua_settagmethod(tagFONT, "gc");
lua_pushcfunction(gc_bitmap);
lua_settagmethod(tagVBUF, "gc");
lua_pushcfunction(gc_primitive);
lua_settagmethod(tagPRIM, "gc");
lua_pushcfunction(gc_textobject);
lua_settagmethod(tagTEXT, "gc");
saveCallback = SaveCallback;
restoreCallback = RestoreCallback;
}