GC Error: Bad Refs

BlitzMax Forums/BlitzMax Programming/GC Error: Bad Refs

Strict

Import Brl.Blitz
Import Brl.Math
Import Brl.System
Import Brl.StandardIO
Import Brl.Pixmap
Import Brl.TGALoader
Import Brl.Max2D
Import Brl.GLMax2D
?Win32
Import Brl.D3D7Max2D

Import Pub.DirectX
?
Import Pub.OpenGL
Import Pub.Glew
Import Pub.StdC

Global State:State2D = New State2D

Function Push2D( )
    State = State.Push( )
End Function

Function Pop2D( )
    State = State.Pop( )
End Function

Type State2D
    Const CF_TRANSFORM = 0
    Const CF_BLEND = 1
    Const CF_VIEWPORT = 2
    Const CF_HANDLE = 3
    Const CF_ORIGIN = 4
    Const CF_ALPHA = 5
    Const CF_COLOR = 6
    Const CF_CLSCOLOR = 7
    
    Field _pred:State2D
    Field sx#=1, sy#=1
    Field rot#
    Field r%,g%,b%,a#
    Field ox#, oy#
    Field hx#, hy#
    Field vx%, vy%, vw%, vh%
    Field blend_% = SOLIDBLEND
    Field cr%, cg%, cb%
    Field cf[]=[1,1,1,1,1,1,1,1]
    
    ' Does not copy its predecessor
    Method Clone:State2D( )
        Local s:State2D = New State2D
        MemCopy( Varptr s.sx, Varptr sx, 80 )
        Return s
    End Method
    
    ' Creates a copy of the top state (Self prior to Push()ing) and sets self as its predecessor
    Method Push:State2D( )
        Local s:State2D = Clone( )
        s._pred = Self
        Return s
    End Method
    
    Method Pop:State2D( )
        Assert _pred,"State2D error: stack underflow"
        Local p:State2D = _pred
        _pred = Null
        p.Bind( )
        Return p
    End Method
    
    Method Scale( x#, y# )
        sx :* x
        sy :* y
        cf[CF_TRANSFORM]=True
    End Method
    
    Method Rotate( r# )
        rot :+ r
        cf[CF_TRANSFORM]=True
    End Method
    
    Method ScaleAbsolute( x#, y# )
        sx = x
        sy = y
        cf[CF_TRANSFORM]=True
    End Method
    
    Method Rotation( r# )
        rot = r
        cf[CF_TRANSFORM]=True
    End Method
    
    Method Color( r%, g%, b% )
        Self.r = r
        Self.g = g
        Self.b = b
        cf[CF_COLOR]=True
    End Method
    
    Method Alpha( a# )
        Self.a = a
        cf[CF_ALPHA]=True
    End Method
    
    Method ClearColor( r%, g%, b% )
        cr = r
        cg = g
        cb = b
        cf[CF_CLSCOLOR]=True
    End Method
    
    Method Handle( hx#, hy# )
        Self.hx = hx
        Self.hy = hy
        cf[CF_HANDLE]=True
    End Method
    
    Method Viewport( x%, y%, w%, h% )
        vx = x
        vy = y
        vw = w
        vh = h
        cf[CF_VIEWPORT]=True
    End Method
    
    Method Blend( b% )
        blend_ = b
        cf[CF_BLEND]=True
    End Method
    
    Method Origin( ox#, oy# )
        Self.ox = ox
        Self.oy = oy
        cf[CF_ORIGIN]=True
    End Method
    
    Method MoveOrigin( ox_#, oy_# )
        Self.ox :+ ox_
        Self.oy :+ oy_
        cf[CF_ORIGIN]=True
    End Method
    
    Method Identity( )
        sx = 1
        sy = 1
        rot = 0
        
        r = 255
        g = 255
        b = 255
        
        a = 1
        
        ox = 0
        oy = 0
        
        hx = 0
        hy = 0
        
        vx = 0
        vy = 0
        vw = GraphicsWidth( )
        vh = GraphicsHeight( )
        
        blend_ = SOLIDBLEND
        
        cr = 0
        cg = 0
        cb = 0
        
        cf = [1,1,1,1,1,1,1,1]
    End Method
    
    Method Bind( )
        Update( True )
    End Method
    
    Method Update( Force=0 )
        If cf[CF_ORIGIN] Or Force Then SetOrigin( ox, oy )
        If cf[CF_HANDLE] Or Force Then SetHandle( hx, hy )
        If cf[CF_TRANSFORM] Or Force Then SetTransform( rot, sx, sy )
        If cf[CF_VIEWPORT] Or Force Then SetViewport( vx, vy, vw, vh )
        If cf[CF_COLOR] Or Force Then SetColor( r, g, b )
        If cf[CF_ALPHA] Or Force Then SetAlpha( a )
        If cf[CF_BLEND] Or Force Then SetBlend( blend_ )
        If cf[CF_CLSCOLOR] Or Force Then SetClsColor( cr, cg, cb )
        cf = [0,0,0,0,0,0,0,0]
    End Method
End Type

Type Sprite
    Field img:TImage
    Field x#, y#
    Field w#=1, h#=1
    Field r%=255, g%=255, b%=255, a#=1
    Field blend%=SOLIDBLEND
    Field sx#=1, sy#=1
    Field rot#
    Field hidden%=0
    Field children:TList = New TList
    Field link:TLink
    Field parent:Sprite
    Field frame%
    
    Method New( )
    End Method
    
    Method Hide( )
        hidden = True
    End Method
    
    Method Show( )
        hidden = False
    End Method
    
    Method IsHidden( )
        Return hidden
    End Method
    
    Method Draw( )
        If hidden Then Return
        
        Push2D( )
        
        State.Scale( sx, sy )
        State.Rotate( rot )
        
        Local tx#=x, ty#=y
        
        If parent Then TForm(tx, ty, State.sx, State.sy, State.rot)
        State.MoveOrigin( tx, ty )
        
        If img Then
            State.Color( r, g, b )
            State.Alpha( a )
            State.Blend( blend )
            
            State.Update( False )
            
            DrawImageRect( img, 0, 0, w*img.width, h*img.height, frame )
        EndIf
        
        For Local i:Sprite = EachIn children
            i.Draw( )
        Next
        
        Pop2D( )
    End Method
    
    Method Dispose( )
        link.Remove( )
        For Local i:Sprite = EachIn children
            i.Dispose( )
        Next
    End Method
    
    Method Delete( )
        Dispose( )
    End Method
    
    Method SetParent( p:Sprite )
        If p = parent Then Return
        If link Then
            link.Remove( )
            link = Null
        EndIf
        parent = p
        If parent Then link = parent.children.AddLast( Self )
    End Method
End Type

Function TForm( x# Var, y# Var, sx#, sy#, a# )
    Local c#=Cos( a )
    Local s#=Sin( a )
    Local cx# = x
    Local cy# = y
    x = (c*sx)*cx+((-s)*sy)*cy
    y = (s*sx)*cx+(c*sy)*cy
End Function

'SetGraphicsDriver( GLMax2DDriver( ) )
Graphics( 800, 600, 0 )

'Local i:TImage = LoadImage( "./media/test.tga" )

Local s:Sprite = New Sprite
's.img = i

s.x = 256
s.y = 256
s.sx = .5
s.sy = .5

Local s2:Sprite = New Sprite
's2.img = i
s2.x = 0
s2.y = 0
s2.sx = .5
s2.sy = .5
s2.SetParent( s )

Repeat
    Cls( )
    s.Draw( )
    s.rot :+ 1
    
 '   DrawImage i, 384, 384
    Flip( )
Until KeyHit( KEY_ESCAPE ) Or AppTerminate( )


Having trouble figuring out what's causing this even after going over the GC code. So, I present to you the code that produces the 'error.' No, it doesn't draw anything right now (and doesn't even if you add an image -- I borked it somehow, but that's irrelevant).

So, anyone have any ideas? Would be a good idea for BRL to step in and comment on this.

Near as I can tell, it's the memcopy doing it.

Yepp definitely the memcopy.
It does not update the refcounter which is used by the GC to decide "whats unneeded" as it is no BM internal functionality but a C functionality to operate on external / C data.
You need to fully writeout your clone functionality to solve the ref count problem.

Oh yeah, copying four too many bytes. Thanks, guys.