Repetitious handle assigning

Discussion in 'Mac Programming' started by Mu0n, Jan 23, 2005.

  1. macrumors newbie

    Joined:
    Jan 23, 2005
    Location:
    Montreal
    #1
    Platform I'm programming on: System 7.5.5, THINK C 6.
    Target platforms: System 1 to MacOS 9.2 (I don't care about anything from 7.0 and up, they just happen to work, without multitasking awareness though, but I couldn't care less. The main target is System 6. Possibly between 6.0.3 and 6.0.8 to take advantage of the extended Time Manager).

    I'm trying to use and re-use a handle (a "sprite graphic" handle in my
    example) to a struct which contains an offscreen bitmap (handle), among
    other things. My functions already allocates memory for the handle
    itself and for its internal BitMapHandle.

    In my dummy debug program, I'm declaring a global SpriteHandle (called
    theBkg, because it'll handle a background graphic to be displayed),
    which will be loaded up during runtime, Disposed of, possibly reloaded
    again, and so on. I thought the DisposBitMap used on the element of the
    struct and DisposHandle used on the handle itself would effectively cut
    ties to their corresponding memory blocks, and reset these Handle's
    content (the address to these memory areas) to NULL, but checking their
    values in debug mode clearly shows that these addresses do not change.

    I've tried to do 2 cycles of "Allocate handles, load graphics, delete
    handles" and it crashes during the 2nd load graphics step.

    Here is a short sample code in C which responds to keyDown events by
    allocating/assigning/loading the graphics. The second and subsequent
    keyDown events it detects, it first Disposes the Handle, then tries to
    reassign/reload it. KeyDown events have to be separated by a keyUp
    event in order for my program to react (so that you don't get a bunch
    of keyDown events all at once - not sure if it was needed, but here it
    is). Following the main function is a couple of functions I'm using
    that I provide for reference.

    The graphic used is whatever is contained into PICT resource ID=128.

    The purpose of being able to do this is that I'll need to add/destroy
    sprite elements to an evolving linked list during runtime of a game.

    Code:
    #include "Sprites.h"
    
    SpriteHandle theBkg = NULL;
    
    void main(void)
    {
    EventRecord wutup;
    Boolean released = true;
    int count=0;
    Str63 theString;
    
    InitMacStuff(); //toolbox init calls, the standard ones
    MacPlusArea(black, white); //just sets a window the size of a whole
    screen
    
    SetEventMask(everyEvent);
    do
      {
      GetNextEvent(everyEvent, &wutup);
      if(wutup.what == keyDown && released == true)
        {
        released = false;
        if(theBkg == NULL)
          {
          theBkg = CreateSprite(1,false,false);
          LoadPictIntoSpriteFrame(theBkg,1,128);
          DrawSprite(theBkg,1,srcCopy); //Crash doesn't occur here, so I won't provide the function
         }
        else
          {
          DeleteSprite(theBkg);
          theBkg = CreateSprite(1,false,false);
          LoadPictIntoSpriteFrame(theBkg,1,128);
          DrawSprite(theBkg,1,srcCopy);
          }
        count++;
        NumToString(count,theString);
        MoveTo(250,250);
        DrawString(theString);
      }
      else if(wutup.what == keyUp) released = true;
    } 
    while(wutup.what != mouseDown);
    }
    
    
    ****KEY FUNCTIONS/DEFINITIONS USED****
    
    typedef struct Sprite{
    Rect theRect, bufferRect;
    int numberFrames, speed;
    BitMapHandle buffer;
    BitMapHandle frames;
    BitMapHandle masks;
    } Sprite;
    
    typedef Sprite *SpritePtr, **SpriteHandle;
    
    void DeleteSprite(SpriteHandle theSprite)
    {
    short loop;
    BitMapHandle bh,mh,buffh;
    Boolean isMasked,isBuffered;
    
    bh = (**theSprite).frames;
    isMasked = IsSpriteMasked(theSprite);
    if(isMasked)
      {
      mh = (**theSprite).masks;
      }
    
    for(loop = 0; loop < (**theSprite).numberFrames; loop++)
      {
      MyDisposePtr( (*bh)[loop].baseAddr);
      if(isMasked)
        {
        MyDisposePtr((*mh)[loop].baseAddr);
        }
      }
    MyDisposeHandle((Handle) (**theSprite).frames);
    if(isMasked)
      {
      MyDisposeHandle((Handle) (**theSprite).masks);
      }
    isBuffered=IsSpriteCleaning(theSprite);
    if(isBuffered)
      {
      buffh= (**theSprite).buffer;
      MyDisposePtr( (**buffh).baseAddr);
      MyDisposeHandle((Handle)buffh);
      }
    MyDisposeHandle((Handle) theSprite);
    }
    
    
    SpriteHandle CreateSprite(int frameAmount, Boolean wantMasks, Boolean
    wantBuffer)
    {
    SpriteHandle theSprite = NULL;
    BitMapHandle bh = NULL, mh = NULL, buffh = NULL;
    Rect emptyRect = {0,0,0,0};
    
    if(NULL != (theSprite = (SpriteHandle)
    NewHandleClear(sizeof(Sprite))) && NULL != (bh = (BitMapHandle)NewHandleClear(sizeof(BitMap)*frameAmount)) && NULL != (mh = (BitMapHandle)NewHandleClear(sizeof(BitMap)*frameAmount)) && NULL != (buffh = (BitMapHandle)NewHandleClear(sizeof(BitMap)))  )
      {
    // all the allocations succeeded
      (**theSprite).frames = bh;
      (**theSprite).numberFrames = frameAmount;
      (**theSprite).theRect = emptyRect;
      (**theSprite).bufferRect = emptyRect;
      if(wantMasks==false) MyDisposeHandle((Handle)mh);
      else (**theSprite).masks = mh;
      if(wantBuffer==false) MyDisposeHandle((Handle)buffh);
      else (**theSprite).buffer = buffh;
      return theSprite;
      }
    
    // something failed. clean up
    MyDisposeHandle((Handle) bh);
    MyDisposeHandle((Handle) mh);
    MyDisposeHandle((Handle) buffh);
    MyDisposeHandle((Handle) theSprite);
    
    return NULL;
    }
    
    
    void MyDisposeHandle(Handle h)
    {
    if(NULL != h)
      {
      DisposeHandle(h);
      }
    }
    
    void MyDisposePtr(Ptr p)
    {
    if(NULL != p)
      {
      DisposePtr(p);
      }
    }
    
    void MyDisposeBitMap(BitMap *bmp)
    {
    if(NULL != bmp)
      {
      MyDisposePtr(bmp->baseAddr);
      }
    }
    
    void LoadPictIntoSpriteFrame(SpriteHandle theSprite,short theFrame, int
    resID)
    {
    BitMap loadBM, maskBM;
    BitMapHandle bh = NULL, mh = NULL;
    Boolean isRectEmpty;
    
    loadBM.baseAddr = NULL;
    maskBM.baseAddr = NULL;
    
    HLock((Handle)theSprite);
    isRectEmpty = EmptyRect(&((**theSprite).theRect));
    HUnlock((Handle)theSprite);
    
    if(LoadPicResIntoBitMap(&loadBM, resID))
      {
      if(isRectEmpty) (**theSprite).theRect = loadBM.bounds;
    
    /* only sets it once--the first time a frame is loaded.
    I'll have to assume all other frames will have the exact same
    bounds.*/
    
      bh = (**theSprite).frames;
      (*bh)[theFrame] = loadBM;
      if(IsSpriteMasked(theSprite))
        {
        mh = (**theSprite).masks;
        maskBM.bounds = loadBM.bounds;
        if(maskBM.baseAddr == NULL) InitBitMap(&maskBM);
        MyCalcMask(&(*bh)[theFrame],&maskBM);
        (*mh)[theFrame] = maskBM;
        }
      } 
    }
    
     
  2. macrumors member

    Joined:
    Oct 7, 2004
    #2
    um...excuse the un-helpful response, but when you say system 7; do you mean Mac System 7 right? um...why?
     
  3. thread starter macrumors newbie

    Joined:
    Jan 23, 2005
    Location:
    Montreal
    #3
    Indeed. And why? Why not. I just want to make a small game that can run on a Mac Plus.
     
  4. macrumors member

    Joined:
    Oct 7, 2004
    #4
    i completely respect that. i was just curious.
     

Share This Page