Tilemap/VX: Ensure proxy objects don't outlive their parents
Either of these would previously crash (same for VX): tm = Tilemap.new at = tm.autotiles tm = nil GC.start at[0] = Bitmap.new(1, 1) tm = Tilemap.new at = tm.autotiles tm.dispose at[0] = Bitmap.new(1, 1) Funnily, this makes RMXP itself crash too, but crashing is never acceptable except for possibly resource exhaustion.
This commit is contained in:
		
							parent
							
								
									e9d0d0566b
								
							
						
					
					
						commit
						9758e660c4
					
				
					 9 changed files with 41 additions and 12 deletions
				
			
		| 
						 | 
					@ -94,6 +94,10 @@ RB_METHOD(tilemapInitialize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rb_iv_set(autotilesObj, "array", ary);
 | 
						rb_iv_set(autotilesObj, "array", ary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Circular reference so both objects are always
 | 
				
			||||||
 | 
						 * alive at the same time */
 | 
				
			||||||
 | 
						rb_iv_set(autotilesObj, "tilemap", self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return self;
 | 
						return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,10 @@ RB_METHOD(tilemapVXInitialize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rb_iv_set(autotilesObj, "array", ary);
 | 
						rb_iv_set(autotilesObj, "array", ary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Circular reference so both objects are always
 | 
				
			||||||
 | 
						 * alive at the same time */
 | 
				
			||||||
 | 
						rb_iv_set(autotilesObj, "tilemap", self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return self;
 | 
						return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@ struct
 | 
				
			||||||
	SYMD(tone),
 | 
						SYMD(tone),
 | 
				
			||||||
	SYMD(rect),
 | 
						SYMD(rect),
 | 
				
			||||||
	SYMD(src_rect),
 | 
						SYMD(src_rect),
 | 
				
			||||||
 | 
						SYMD(tilemap),
 | 
				
			||||||
	SYMD(tileset),
 | 
						SYMD(tileset),
 | 
				
			||||||
	SYMD(autotiles),
 | 
						SYMD(autotiles),
 | 
				
			||||||
	SYMD(map_data),
 | 
						SYMD(map_data),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,6 +42,7 @@ enum CommonSymbol
 | 
				
			||||||
	CStone,
 | 
						CStone,
 | 
				
			||||||
	CSrect,
 | 
						CSrect,
 | 
				
			||||||
	CSsrc_rect,
 | 
						CSsrc_rect,
 | 
				
			||||||
 | 
						CStilemap,
 | 
				
			||||||
	CStileset,
 | 
						CStileset,
 | 
				
			||||||
	CSautotiles,
 | 
						CSautotiles,
 | 
				
			||||||
	CSmap_data,
 | 
						CSmap_data,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,13 +93,18 @@ MRB_METHOD(tilemapInitialize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wrapProperty(mrb, self, &t->getAutotiles(), CSautotiles, TilemapAutotilesType);
 | 
						wrapProperty(mrb, self, &t->getAutotiles(), CSautotiles, TilemapAutotilesType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mrb_value autotilesObj = mrb_iv_get(mrb, self, getMrbData(mrb)->symbols[CSautotiles]);
 | 
						MrbData &mrbData = *getMrbData(mrb);
 | 
				
			||||||
 | 
						mrb_value autotilesObj = mrb_iv_get(mrb, self, mrbData.symbols[CSautotiles]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mrb_value ary = mrb_ary_new_capa(mrb, 7);
 | 
						mrb_value ary = mrb_ary_new_capa(mrb, 7);
 | 
				
			||||||
	for (int i = 0; i < 7; ++i)
 | 
						for (int i = 0; i < 7; ++i)
 | 
				
			||||||
		mrb_ary_push(mrb, ary, mrb_nil_value());
 | 
							mrb_ary_push(mrb, ary, mrb_nil_value());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mrb_iv_set(mrb, autotilesObj, getMrbData(mrb)->symbols[CSarray], ary);
 | 
						mrb_iv_set(mrb, autotilesObj, mrbData.symbols[CSarray], ary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Circular reference so both objects are always
 | 
				
			||||||
 | 
						 * alive at the same time */
 | 
				
			||||||
 | 
						mrb_iv_set(mrb, autotilesObj, mrbData.symbols[CStilemap], self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return self;
 | 
						return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,7 +241,6 @@ struct TilemapPrivate
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Viewport *viewport;
 | 
						Viewport *viewport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Tilemap::Autotiles autotilesProxy;
 | 
					 | 
				
			||||||
	Bitmap *autotiles[autotileCount];
 | 
						Bitmap *autotiles[autotileCount];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Bitmap *tileset;
 | 
						Bitmap *tileset;
 | 
				
			||||||
| 
						 | 
					@ -1183,6 +1182,9 @@ void ZLayer::finiUpdateZ(ZLayer *prev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
 | 
					void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!p)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < 0 || i > autotileCount-1)
 | 
						if (i < 0 || i > autotileCount-1)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1206,6 +1208,9 @@ void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Bitmap *Tilemap::Autotiles::get(int i) const
 | 
					Bitmap *Tilemap::Autotiles::get(int i) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!p)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < 0 || i > autotileCount-1)
 | 
						if (i < 0 || i > autotileCount-1)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1215,7 +1220,7 @@ Bitmap *Tilemap::Autotiles::get(int i) const
 | 
				
			||||||
Tilemap::Tilemap(Viewport *viewport)
 | 
					Tilemap::Tilemap(Viewport *viewport)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	p = new TilemapPrivate(viewport);
 | 
						p = new TilemapPrivate(viewport);
 | 
				
			||||||
	p->autotilesProxy.p = p;
 | 
						atProxy.p = p;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Tilemap::~Tilemap()
 | 
					Tilemap::~Tilemap()
 | 
				
			||||||
| 
						 | 
					@ -1244,11 +1249,11 @@ void Tilemap::update()
 | 
				
			||||||
		p->tiles.aniIdx = 0;
 | 
							p->tiles.aniIdx = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Tilemap::Autotiles &Tilemap::getAutotiles() const
 | 
					Tilemap::Autotiles &Tilemap::getAutotiles()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	guardDisposed();
 | 
						guardDisposed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return p->autotilesProxy;
 | 
						return atProxy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(Tilemap, Viewport, Viewport*, p->viewport)
 | 
					DEF_ATTR_RD_SIMPLE(Tilemap, Viewport, Viewport*, p->viewport)
 | 
				
			||||||
| 
						 | 
					@ -1379,4 +1384,5 @@ void Tilemap::setOY(int value)
 | 
				
			||||||
void Tilemap::releaseResources()
 | 
					void Tilemap::releaseResources()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	delete p;
 | 
						delete p;
 | 
				
			||||||
 | 
						atProxy.p = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void update();
 | 
						void update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Autotiles &getAutotiles() const;
 | 
						Autotiles &getAutotiles();
 | 
				
			||||||
	Viewport *getViewport() const;
 | 
						Viewport *getViewport() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DECL_ATTR( Tileset,    Bitmap*   )
 | 
						DECL_ATTR( Tileset,    Bitmap*   )
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	TilemapPrivate *p;
 | 
						TilemapPrivate *p;
 | 
				
			||||||
 | 
						Autotiles atProxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void releaseResources();
 | 
						void releaseResources();
 | 
				
			||||||
	const char *klassName() const { return "tilemap"; }
 | 
						const char *klassName() const { return "tilemap"; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
 | 
					struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TilemapVX::BitmapArray bitmapsProxy;
 | 
					 | 
				
			||||||
	Bitmap *bitmaps[BM_COUNT];
 | 
						Bitmap *bitmaps[BM_COUNT];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Table *mapData;
 | 
						Table *mapData;
 | 
				
			||||||
| 
						 | 
					@ -358,6 +357,9 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
 | 
					void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!p)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < 0 || i >= BM_COUNT)
 | 
						if (i < 0 || i >= BM_COUNT)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -378,6 +380,9 @@ void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Bitmap *TilemapVX::BitmapArray::get(int i) const
 | 
					Bitmap *TilemapVX::BitmapArray::get(int i) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (!p)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (i < 0 || i >= BM_COUNT)
 | 
						if (i < 0 || i >= BM_COUNT)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -387,7 +392,7 @@ Bitmap *TilemapVX::BitmapArray::get(int i) const
 | 
				
			||||||
TilemapVX::TilemapVX(Viewport *viewport)
 | 
					TilemapVX::TilemapVX(Viewport *viewport)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	p = new TilemapVXPrivate(viewport);
 | 
						p = new TilemapVXPrivate(viewport);
 | 
				
			||||||
	p->bitmapsProxy.p = p;
 | 
						bmProxy.p = p;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TilemapVX::~TilemapVX()
 | 
					TilemapVX::~TilemapVX()
 | 
				
			||||||
| 
						 | 
					@ -413,11 +418,11 @@ void TilemapVX::update()
 | 
				
			||||||
	p->aniOffset = Vec2(aniIdxA * 2 * 32, aniIdxC * 32);
 | 
						p->aniOffset = Vec2(aniIdxA * 2 * 32, aniIdxC * 32);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TilemapVX::BitmapArray &TilemapVX::getBitmapArray() const
 | 
					TilemapVX::BitmapArray &TilemapVX::getBitmapArray()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	guardDisposed();
 | 
						guardDisposed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return p->bitmapsProxy;
 | 
						return bmProxy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData)
 | 
					DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData)
 | 
				
			||||||
| 
						 | 
					@ -521,4 +526,5 @@ void TilemapVX::setOY(int value)
 | 
				
			||||||
void TilemapVX::releaseResources()
 | 
					void TilemapVX::releaseResources()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	delete p;
 | 
						delete p;
 | 
				
			||||||
 | 
						bmProxy.p = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void update();
 | 
						void update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BitmapArray &getBitmapArray() const;
 | 
						BitmapArray &getBitmapArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DECL_ATTR( Viewport,   Viewport* )
 | 
						DECL_ATTR( Viewport,   Viewport* )
 | 
				
			||||||
	DECL_ATTR( MapData,    Table*    )
 | 
						DECL_ATTR( MapData,    Table*    )
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	TilemapVXPrivate *p;
 | 
						TilemapVXPrivate *p;
 | 
				
			||||||
 | 
						BitmapArray bmProxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void releaseResources();
 | 
						void releaseResources();
 | 
				
			||||||
	const char *klassName() const { return "tilemap"; }
 | 
						const char *klassName() const { return "tilemap"; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue