Program fails with debug off, works with it on?

BlitzMax Forums/BlitzMax Programming/Program fails with debug off, works with it on?

ImaginaryHuman(Posted 2005) [#1]
The following code is a Method within a custom `bitmap` type, which draws a line of pixels at any angle, pixel by pixel. The code has been cropped t show only one of the drawing modes (replace mode). Clipping is optionally performed. In the program I am testing with, I call the method as follows:

Test1.PixelLine(-50,-50,x*4,y*4,$FFFFFFFF,0,False)

I can apparently set clipping to True or False and I get the same problem.

The problem is, when I compile my test program with Debug On, the program works correctly and the lines are drawn. When I compile with Debug Off, the program only draws the first pixel of the line. (Normally you'd think it'd be the other way around, or that the debugging wouldn't change behavior?!)

So far I can only tell that, with Debug Off, the program flow doesn't seem to get into the `While` loops, failing the test right away.

Does anyone see what might be causing this strange problem? How can I get this to run with debug off?

	Method PixelLine(MXpos1:Int,MYpos1:Int,MXpos2:Int,MYPos2:Int,MColor:Int=$FFFFFFFF,MMode:Int=0,MClip:Int=False)
		'To draw a diagonal/straight line of pixels on this `Bitmap` from MXpos,MYpos to MXpos2,MYpos2
                 'in the given `color` MColor (RGBA) or with XXYY value for each pixel
		'Uses the Bresenham's line drawing algorithm with integer math only
		'Requires that at least one pixel must be drawable and is within the this `Bitmap` object's memory space if clipping is off
		'Performs clipping if MClip is True
		'Copies differently based on the MMode. 0=Replace
		Local MRowBytes:Int=Width		'RowBytes/4 because it's an Int Pointer
		Local MBasePointer:Int Ptr=DataBankIntPtr		'Base address of bitmap memory
		Local MColorFast:Int=MColor		'Make sure it's in a register for speed
	 	Local MSteep:Int=Abs(MYpos2-MYpos1) > Abs(MXpos2-MXpos1)			'Boolean
		If MSteep		'=True?
			Local MTemp:Int=MXpos1; MXpos1=MYpos1; MYpos1=MTemp		'Swap X1,Y1
			MTemp=MXpos2; MXpos2=MYpos2; MYpos2=MTemp		'Swap X2,Y2
		EndIf
		Local MDeltaX:Int=Abs(MXpos2-MXpos1)		'X Difference
		Local MDeltaY:Int=Abs(MYpos2-MYpos1)		'Y Difference
		Local MError:Int=0		'Overflow counter
		Local MDeltaError:Int=MDeltaY		'Counter adder
		Local MX:Int=MXpos1		'Start at X1,Y1
		Local MY:Int=MYpos1			
		Local MXStep:Int
		Local MYStep:Int
		If MXpos1<MXpos2 Then MXStep=1 Else MXStep=-1			'Direction
		If MYpos1<MYpos2 Then MYStep=1 Else MYStep=-1		'Direction
		Select MMode		'Redirect flow
			Case 1	If (MColorFast & $000000FF) Then MMode=0
			Case 2	If (MaskValue<>MColorFast) Then MMode=0
			Case 5	If (MaskValue=MColorFast) Then MMode=0
			Case 9	If (MColorFast & $000000FF) Then MMode=0
		End Select
		Local MClipFast:Int=MClip		'For speed
		Local MWidthFast:Int=Width		'For speed
		Local MHeightFast:Int=Height		'For speed
		Local MClipping:Int=False		'For signalling that a line started outside of the bitmap
		Select MMode
			Case 0		'Replace mode - Copies RGBA/XXYY solidly overwriting all data
				If MSteep
					If MClipFast
						If MY>-1 And MY<MWidthFast And MX>-1 And MX<MHeightFast
							(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast		'Replace at Y,X
							MClipping=False		'Does the line start outside the bitmap?
						Else
							MClipping=True		'The line starts outside the bitmap
						EndIf
					Else
						(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast		'Replace at Y,X
					EndIf
				Else
					If MClipFast
						If MX>-1 And MX<MWidthFast And MY>-1 And MY<MHeightFast
							(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast		'Replace at X,Y				
							MClipping=False		'Does the line start outside the bitmap?
						Else
							MClipping=True		'The line starts outside the bitmap
						EndIf
					Else
						(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast		'Replace at X,Y
					EndIf
				EndIf
				If MClipFast
					While MX<>MXpos2
						MX:+MXStep		'Move in X
						MError:+MDeltaError		'Add to counter
						If (MError Shl 1)>MDeltaX		'Would it overflow?
							MY:+MYStep		'Move in Y
							MError=MError-MDeltaX		'Overflow/wrap the counter
						EndIf
						If MClipping=False
							'Inside the bitmap, draw the pixel
							If MSteep
								If (MY<0) Or (MY>=MWidthFast) Or (MX<0) Or (MX>=MHeightFast) Then Return
								(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast		'Replace at Y,X
							Else
								If (MX<0) Or (MX>=MWidthFast) Or (MY<0) Or (MY>=MHeightFast) Then Return
								(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast		'Replace at X,Y
							EndIf
						Else
							'Outside the bitmap, check if it came inside
							If MSteep
								If (MY>-1) And (MY<MWidthFast) And (MX>-1) And (MX<MHeightFast) Then MClipping=False
							Else
								If (MX>-1) And (MX<MWidthFast) And (MY>-1) And (MY<MHeightFast) Then MClipping=False
							EndIf 
						EndIf
					Wend
				Else
					While MX<>MXpos2
						MX:+MXStep		'Move in X
						MError:+MDeltaError		'Add to counter
						If (MError Shl 1)>MDeltaX		'Would it overflow?
							MY:+MYStep		'Move in Y
							MError=MError-MDeltaX		'Overflow/wrap the counter
						EndIf
						If MSteep
							(MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast		'Replace at Y,X
						Else
							(MBasePointer+MX+(MY*MRowBytes))[0]=MColorFast		'Replace at X,Y
						EndIf
					Wend
				EndIf
                 End Select
End Method

(P.S. use the code for whatever you like, it's not the best but it works - usually.)

The Type fields are as follows if you need to know:
	Field DataBankPtr:Byte Ptr		'Byte-Pointer to the actual memory reserved in the bank
	Field DataBankIntPtr:Int Ptr		'Int-Pointer to the memory in the bank
	Field DataBank:TBank		'Pointer to a TBank object to store data
	Field Width:Int		'Total width of the bitmap in terms of pixels or units of representation
	Field Height:Int		'Total height of the bitmap in terms of pixels or units of representation
	Field RowBytes:Int		'How many total bytes of data are allocated in each row of pixels or units (Width*4)
	Field TotalBytes:Int		'How many bytes in total does the bitmap data take up
	Field FromPixmap:TPixmap		'Pointer to a Pixmap object which may have been used for loading data from an image, used as a static bank
	Field MaskValue:Int		'RGBA color or 4-byte value, where all pixels in the Bitmap of that color/value are transparent/non-copied when copying in Mode 2 (ValueMask mode)



ImaginaryHuman(Posted 2005) [#2]
Okay. I am still hunting down the bug. What I've found now is even more bizarre. If I insert a couple of Print statements into the code, as below:

              Select MMode
                        Case 0          'Replace mode - Copies RGBA/XXYY solidly overwriting all data
                                If MSteep

Print MClipFast    'Prints a 0 (false) which is correct

                                        If MClipFast

Print "Shouldn't be here!: "+MClipFast    'Prints a 0 (which it is, but the IF shouldn't have been taken!)

                                                If MY>-1 And MY<MWidthFast And MX>-1 And MX<MHeightFast
                                                        (MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast          'Replace at Y,X
                                                        MClipping=False         'Does the line start outside the bitmap?
                                                Else
                                                        MClipping=True          'The line starts outside the bitmap
                                                EndIf
                                        Else
                                                (MBasePointer+MY+(MX*MRowBytes))[0]=MColorFast          'Replace at Y,X
                                        EndIf
                                Else
 


What happens now is that the MClipFast variable is False or 0 .... which it should be, as passed to the function. However, the IF statement which is ONLY supposed to be performed if MClipFast is NONZERO, is actually taken.

If I change the code to: If MClipFast=False the If section is NOT taken, even though the MClipFast variable is clearly still a 0. It's supposed to be the other way around.

Again, this problem is fixed with Debug on, but persists without the debug version.

What's going on here? Is this a compiler bug? I can't really set the If to be the inverse of logic, because it wont work while I'm debugging, and similarly I can't set it to what it should be because it fails in the `release` version. So I'm stuck.

Any ideaS?


salric(Posted 2005) [#3]
I've had the same problem & submitted it as a bug report - it is a compiler bug which you won't find happening in the previous blitzmax version. Mark has said he'll fix it (the bug is now in the bugbin)...

The post is here for your reference:
http://www.blitzmax.com/Community/posts.php?topic=49476#550809

So either revert to the previous Blitzmax version, be satisfied with debug mode only in the current version.

It's a wierd bug to be sure ;-)


ImaginaryHuman(Posted 2005) [#4]
Oh ok. Good to know. Thanks.

Btw, when I click that link it fails.


salric(Posted 2005) [#5]
That's wierd that you can't click on the link... if you click on my nickname, then click on forum posts, you'll see a post something along the lines of expressions not properly evaluated in larger progs.

I thought it was something to do with the size of the program, although seeing your code reproduce the error makes me think again.

Whatever it is, it's a perplexing bug - I remember being incredibly frustrated when I first encountered the problem. I've been waiting months for it to be fixed ;-(


Hotcakes(Posted 2005) [#6]
AngelDaniel, your cookies are probably set to a different domain and the bug bin is hidden from people who don't have a registered product (ie no cookie - no login - guest). Change the www.blitzmax.com section to www.blitzbasic.com or blitzbasic.co.nz or whatever it is you use and the link should work fine.


ozak(Posted 2005) [#7]
Try using DebugLog. When developing for the Playstation 1 back in the day, my team and I could only log text to a console. no debugging :)


Rimmsy(Posted 2005) [#8]
Suprisingly enough that's what I do now with bmx. I only use debuglog and don't rely on the debugger.

The debugger works but when I go to click on anything like a variable or type I get two clicks maximum then the debugger + game crash and I have to end task them both. Seems that bug is unique to me because nobody else I know has it.


ImaginaryHuman(Posted 2005) [#9]
I guess I could use the ?Debug compiler directive and have two different pieces of code for each situation.

My code is actually a lot bigger, but this piece that is not working right I cut out and made it look like it's stand-alone. I have no idea what could cause the problem. It does seem like the expression is not evaluated right, or, that the assembler code generated is using the wrong kind of jump instruction or jumps to the wrong label, causing it to enter the wrong area.


Koriolis(Posted 2005) [#10]
Glad to know it's already reported and taken care of. My program simply does next to *nothing* in release mode, and yet works perfectly in debug mode. I hope that's the same issue here and not yet another different problem.


ImaginaryHuman(Posted 2005) [#11]
So long as the bugs get fixed fairly soon it's probably work-aroundable.