TINSEL: Correctly handle the pDispList OBJECT linked lists, i.e. use OBJECT** for a pointer to the head.

Signed-off-by: Max Horn <max@quendi.de>
This commit is contained in:
Christoph Mallon 2011-05-18 14:40:49 +02:00 committed by Max Horn
parent 9c01c38512
commit f143668db4
10 changed files with 32 additions and 48 deletions

View file

@ -149,7 +149,7 @@ int PlayfieldGetCenterX(int which) {
* @param which Which playfield * @param which Which playfield
*/ */
OBJECT *GetPlayfieldList(int which) { OBJECT **GetPlayfieldList(int which) {
PLAYFIELD *pPlayfield; // pointer to relavent playfield PLAYFIELD *pPlayfield; // pointer to relavent playfield
// make sure there is a background // make sure there is a background
@ -162,22 +162,7 @@ OBJECT *GetPlayfieldList(int which) {
pPlayfield = pCurBgnd->fieldArray + which; pPlayfield = pCurBgnd->fieldArray + which;
// return the display list pointer for this playfield // return the display list pointer for this playfield
// return &pPlayfield->pDispList;
// HACK: We pretend that pPlayfield is an OBJECT here, by explicitly
// casting a pointer to it (resp. to its first member) to an OBJECT
// pointer.
// Of course it isn't, but its first member is pDispList, an OBJECT
// pointer, just like the first member of an OBJECT is pNext, also
// an OBJECT pointer. This (classic) trick allows us to use
// pPlayfield as a fake anchor element for the linked list of
// objects pDispList points to, which in turn simplifies some list
// manipulation code. Alas, this is prone to confuse aliasing
// analysis in compilers, and also silly developers like myself ;).
// So at the very least, I figured we should document this trick
// here explicitly.
// Personally, I would prefer if we got rid of this trick, e.g. by
// introducing an explicit anchor element.
return (OBJECT *)&pPlayfield->pDispList;
} }
/** /**
@ -217,10 +202,10 @@ void DrawBackgnd() {
pPlay->bMoved = true; pPlay->bMoved = true;
// sort the display list for this background - just in case somebody has changed object Z positions // sort the display list for this background - just in case somebody has changed object Z positions
SortObjectList((OBJECT *)&pPlay->pDispList); SortObjectList(&pPlay->pDispList);
// generate clipping rects for all objects that have moved etc. // generate clipping rects for all objects that have moved etc.
FindMovingObjects((OBJECT *)&pPlay->pDispList, &ptWin, FindMovingObjects(&pPlay->pDispList, &ptWin,
&pPlay->rcClip, false, pPlay->bMoved); &pPlay->rcClip, false, pPlay->bMoved);
// clear playfield moved flag // clear playfield moved flag
@ -247,8 +232,7 @@ void DrawBackgnd() {
if (IntersectRectangle(rcPlayClip, pPlay->rcClip, *r)) if (IntersectRectangle(rcPlayClip, pPlay->rcClip, *r))
// redraw all objects within this clipping rect // redraw all objects within this clipping rect
UpdateClipRect((OBJECT *)&pPlay->pDispList, UpdateClipRect(&pPlay->pDispList, &ptWin, &rcPlayClip);
&ptWin, &rcPlayClip);
} }
} }

View file

@ -93,7 +93,7 @@ void PlayfieldGetPos( // Returns the xy position of the specified playfield in
int PlayfieldGetCenterX( // Returns the xy position of the specified playfield in the current background int PlayfieldGetCenterX( // Returns the xy position of the specified playfield in the current background
int which); // which playfield int which); // which playfield
OBJECT *GetPlayfieldList( // Returns the display list for the specified playfield OBJECT **GetPlayfieldList( // Returns the display list for the specified playfield
int which); // which playfield int which); // which playfield
void KillPlayfieldList( // Kills all the objects on the display list for the specified playfield void KillPlayfieldList( // Kills all the objects on the display list for the specified playfield

View file

@ -105,10 +105,10 @@ static bool LooseIntersectRectangle(const Common::Rect &pSrc1, const Common::Rec
* @param bNoVelocity When reset, objects pos is updated with velocity * @param bNoVelocity When reset, objects pos is updated with velocity
* @param bScrolled) When set, playfield has scrolled * @param bScrolled) When set, playfield has scrolled
*/ */
void FindMovingObjects(OBJECT *pObjList, Common::Point *pWin, Common::Rect *pClip, bool bNoVelocity, bool bScrolled) { void FindMovingObjects(OBJECT **pObjList, Common::Point *pWin, Common::Rect *pClip, bool bNoVelocity, bool bScrolled) {
OBJECT *pObj; // object list traversal pointer OBJECT *pObj; // object list traversal pointer
for (pObj = pObjList->pNext; pObj != NULL; pObj = pObj->pNext) { for (pObj = *pObjList; pObj != NULL; pObj = pObj->pNext) {
if (!bNoVelocity) { if (!bNoVelocity) {
// we want to add velocities to objects position // we want to add velocities to objects position
@ -203,7 +203,7 @@ void MergeClipRect() {
* @param pWin Window top left position * @param pWin Window top left position
* @param pClip Pointer to clip rectangle * @param pClip Pointer to clip rectangle
*/ */
void UpdateClipRect(OBJECT *pObjList, Common::Point *pWin, Common::Rect *pClip) { void UpdateClipRect(OBJECT **pObjList, Common::Point *pWin, Common::Rect *pClip) {
int x, y, right, bottom; // object corners int x, y, right, bottom; // object corners
int hclip, vclip; // total size of object clipping int hclip, vclip; // total size of object clipping
DRAWOBJECT currentObj; // filled in to draw the current object in list DRAWOBJECT currentObj; // filled in to draw the current object in list
@ -212,7 +212,7 @@ void UpdateClipRect(OBJECT *pObjList, Common::Point *pWin, Common::Rect *pClip)
// Initialise the fields of the drawing object to empty // Initialise the fields of the drawing object to empty
memset(&currentObj, 0, sizeof(DRAWOBJECT)); memset(&currentObj, 0, sizeof(DRAWOBJECT));
for (pObj = pObjList->pNext; pObj != NULL; pObj = pObj->pNext) { for (pObj = *pObjList; pObj != NULL; pObj = pObj->pNext) {
if (pObj->flags & DMA_ABS) { if (pObj->flags & DMA_ABS) {
// object position is absolute // object position is absolute
x = fracToInt(pObj->xPos); x = fracToInt(pObj->xPos);

View file

@ -55,7 +55,7 @@ bool UnionRectangle( // Creates the union of two rectangles
const Common::Rect &pSrc2); // a source rectangle const Common::Rect &pSrc2); // a source rectangle
void FindMovingObjects( // Creates clipping rectangles for all the objects that have moved on the specified object list void FindMovingObjects( // Creates clipping rectangles for all the objects that have moved on the specified object list
OBJECT *pObjList, // playfield display list to draw OBJECT **pObjList, // playfield display list to draw
Common::Point *pWin, // playfield window top left position Common::Point *pWin, // playfield window top left position
Common::Rect *pClip, // playfield clipping rectangle Common::Rect *pClip, // playfield clipping rectangle
bool bVelocity, // when set, objects pos is updated with velocity bool bVelocity, // when set, objects pos is updated with velocity
@ -64,7 +64,7 @@ void FindMovingObjects( // Creates clipping rectangles for all the objects that
void MergeClipRect(); // Merges any clipping rectangles that overlap void MergeClipRect(); // Merges any clipping rectangles that overlap
void UpdateClipRect( // Redraws all objects within this clipping rectangle void UpdateClipRect( // Redraws all objects within this clipping rectangle
OBJECT *pObjList, // object list to draw OBJECT **pObjList, // object list to draw
Common::Point *pWin, // window top left position Common::Point *pWin, // window top left position
Common::Rect *pClip); // pointer to clip rectangle Common::Rect *pClip); // pointer to clip rectangle

View file

@ -90,7 +90,7 @@ OBJECT *MultiInitObject(const MULTI_INIT *pInitTbl) {
*/ */
void MultiInsertObject(OBJECT *pObjList, OBJECT *pInsObj) { void MultiInsertObject(OBJECT **pObjList, OBJECT *pInsObj) {
// validate object pointer // validate object pointer
assert(isValidObject(pInsObj)); assert(isValidObject(pInsObj));
@ -111,7 +111,7 @@ void MultiInsertObject(OBJECT *pObjList, OBJECT *pInsObj) {
* @param pMultiObj Multi-part object to be deleted * @param pMultiObj Multi-part object to be deleted
*/ */
void MultiDeleteObject(OBJECT *pObjList, OBJECT *pMultiObj) { void MultiDeleteObject(OBJECT **pObjList, OBJECT *pMultiObj) {
// validate object pointer // validate object pointer
assert(isValidObject(pMultiObj)); assert(isValidObject(pMultiObj));

View file

@ -57,11 +57,11 @@ OBJECT *MultiInitObject( // Initialise a multi-part object
const MULTI_INIT *pInitTbl); // pointer to multi-object initialisation table const MULTI_INIT *pInitTbl); // pointer to multi-object initialisation table
void MultiInsertObject( // Insert a multi-part object onto a object list void MultiInsertObject( // Insert a multi-part object onto a object list
OBJECT *pObjList, // list to insert multi-part object onto OBJECT **pObjList, // list to insert multi-part object onto
OBJECT *pInsObj); // head of multi-part object to insert OBJECT *pInsObj); // head of multi-part object to insert
void MultiDeleteObject( // Delete all the pieces of a multi-part object void MultiDeleteObject( // Delete all the pieces of a multi-part object
OBJECT *pObjList, // list to delete multi-part object from OBJECT **pObjList, // list to delete multi-part object from
OBJECT *pMultiObj); // multi-part object to be deleted OBJECT *pMultiObj); // multi-part object to be deleted
void MultiHideObject( // Hide a multi-part object void MultiHideObject( // Hide a multi-part object

View file

@ -162,13 +162,13 @@ void CopyObject(OBJECT *pDest, OBJECT *pSrc) {
* @param pInsObj Object to insert * @param pInsObj Object to insert
*/ */
void InsertObject(OBJECT *pObjList, OBJECT *pInsObj) { void InsertObject(OBJECT **pObjList, OBJECT *pInsObj) {
OBJECT *pPrev, *pObj; // object list traversal pointers OBJECT **pAnchor, *pObj; // object list traversal pointers
// validate object pointer // validate object pointer
assert(isValidObject(pInsObj)); assert(isValidObject(pInsObj));
for (pPrev = pObjList, pObj = pObjList->pNext; pObj != NULL; pPrev = pObj, pObj = pObj->pNext) { for (pAnchor = pObjList, pObj = *pAnchor; pObj != NULL; pAnchor = &pObj->pNext, pObj = *pAnchor) {
// check Z order // check Z order
if (pInsObj->zPos < pObj->zPos) { if (pInsObj->zPos < pObj->zPos) {
// object Z is lower than list Z - insert here // object Z is lower than list Z - insert here
@ -182,9 +182,9 @@ void InsertObject(OBJECT *pObjList, OBJECT *pInsObj) {
} }
} }
// insert obj between pPrev and pObj // insert obj between pAnchor and pObj
pInsObj->pNext = pObj; pInsObj->pNext = pObj;
pPrev->pNext = pInsObj; *pAnchor = pInsObj;
} }
@ -194,8 +194,8 @@ void InsertObject(OBJECT *pObjList, OBJECT *pInsObj) {
* @param pObjList List to delete object from * @param pObjList List to delete object from
* @param pDelObj Object to delete * @param pDelObj Object to delete
*/ */
void DelObject(OBJECT *pObjList, OBJECT *pDelObj) { void DelObject(OBJECT **pObjList, OBJECT *pDelObj) {
OBJECT *pPrev, *pObj; // object list traversal pointers OBJECT **pAnchor, *pObj; // object list traversal pointers
const Common::Rect rcScreen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); const Common::Rect rcScreen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
// validate object pointer // validate object pointer
@ -207,7 +207,7 @@ void DelObject(OBJECT *pObjList, OBJECT *pDelObj) {
assert(numObj >= 0); assert(numObj >= 0);
#endif #endif
for (pPrev = pObjList, pObj = pObjList->pNext; pObj != NULL; pPrev = pObj, pObj = pObj->pNext) { for (pAnchor = pObjList, pObj = *pAnchor; pObj != NULL; pAnchor = &pObj->pNext, pObj = *pAnchor) {
if (pObj == pDelObj) { if (pObj == pDelObj) {
// found object to delete // found object to delete
@ -217,7 +217,7 @@ void DelObject(OBJECT *pObjList, OBJECT *pDelObj) {
} }
// make PREV next = OBJ next - removes OBJ from list // make PREV next = OBJ next - removes OBJ from list
pPrev->pNext = pObj->pNext; *pAnchor = pObj->pNext;
// place free list in OBJ next // place free list in OBJ next
pObj->pNext = pFreeObjects; pObj->pNext = pFreeObjects;
@ -245,12 +245,12 @@ void DelObject(OBJECT *pObjList, OBJECT *pDelObj) {
* Sort the specified object list in Z Y order. * Sort the specified object list in Z Y order.
* @param pObjList List to sort * @param pObjList List to sort
*/ */
void SortObjectList(OBJECT *pObjList) { void SortObjectList(OBJECT **pObjList) {
OBJECT *pPrev, *pObj; // object list traversal pointers OBJECT *pPrev, *pObj; // object list traversal pointers
OBJECT head; // temporary head of list - because pObjList is not usually a OBJECT OBJECT head; // temporary head of list - because pObjList is not usually a OBJECT
// put at head of list // put at head of list
head.pNext = pObjList->pNext; head.pNext = *pObjList;
// set head of list dummy OBJ Z Y values to lowest possible // set head of list dummy OBJ Z Y values to lowest possible
head.yPos = intToFrac(MIN_INT16); head.yPos = intToFrac(MIN_INT16);

View file

@ -134,15 +134,15 @@ void CopyObject( // copy one object to another
OBJECT *pSrc); // source object OBJECT *pSrc); // source object
void InsertObject( // insert a object onto a sorted object list void InsertObject( // insert a object onto a sorted object list
OBJECT *pObjList, // list to insert object onto OBJECT **pObjList, // list to insert object onto
OBJECT *pInsObj); // object to insert OBJECT *pInsObj); // object to insert
void DelObject( // delete a object from a object list and add to free list void DelObject( // delete a object from a object list and add to free list
OBJECT *pObjList, // list to delete object from OBJECT **pObjList, // list to delete object from
OBJECT *pDelObj); // object to delete OBJECT *pDelObj); // object to delete
void SortObjectList( // re-sort an object list void SortObjectList( // re-sort an object list
OBJECT *pObjList); // list to sort OBJECT **pObjList); // list to sort
OBJECT *GetNextObject( // object list iterator - returns next obj in list OBJECT *GetNextObject( // object list iterator - returns next obj in list
OBJECT *pObjList, // which object list OBJECT *pObjList, // which object list

View file

@ -104,7 +104,7 @@ int JustifyText(char *szStr, int xPos, const FONT *pFont, int mode) {
* @param mode Mode flags for the string * @param mode Mode flags for the string
* @param sleepTime Sleep time between each character (if non-zero) * @param sleepTime Sleep time between each character (if non-zero)
*/ */
OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int color, OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime) { int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime) {
int xJustify; // x position of text after justification int xJustify; // x position of text after justification
int yOffset; // offset to next line of text int yOffset; // offset to next line of text

View file

@ -95,7 +95,7 @@ struct TEXTOUT {
* @param mode mode flags for the string * @param mode mode flags for the string
* @param sleepTime Sleep time between each character (if non-zero) * @param sleepTime Sleep time between each character (if non-zero)
*/ */
OBJECT *ObjectTextOut(OBJECT *pList, char *szStr, int color, OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime = 0); int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime = 0);
OBJECT *ObjectTextOutIndirect( // output a string of text OBJECT *ObjectTextOutIndirect( // output a string of text