## Recommended Posts

the // division seems to freeze the compiler. I've added div_mul and div_mul16 to the includes file and it's simply refusing to compile if I don't rem out

`b = brickx // 2`

I forgot until now that I had implemented // to save the remainder, so it's likely that later changes broke it!

However, // uses a slow sort of binary long division that takes quite a few cycles. For some values, this is the best way, but for dividing by two, it's much slower than it needs to be.

A much better and faster way to get the remainder would be this:

``` b=brickx/2
temp1=brickx & 1
```

##### Share on other sites

I'm trying to divide by 3, actually, if that's possible within a reasonable number of cycles.

##### Share on other sites
I'm trying to divide by 3, actually, if that's possible within a reasonable number of cycles.

It's around 200 cycles regardless of the divisor. It's reasonable as long as there aren't too many divisions in your program.

I see the problem - it's the preprocessor. Since I forgot about //, the preprocessor thinks you've put in two divides in a row and screws up the compiler. For now, you can use some inline asm. For example, b=brickx//3 would turn into:

``` asm
LDA brickx
LDY #3
jsr div16
STA b
end
```

##### Share on other sites
I'm trying to divide by 3, actually, if that's possible within a reasonable number of cycles.

If you're handy with the inline assembler or calling assembler routines you could also use this routine which will be 40 odd cycles, and so much faster.

Unsigned divide by 3 routine (6502)

change the usage of temp to temp1 in the code like so, and then perhaps put it at the end of your batari basic file.

If you're just going to just use it one time then you can inline it as well. put LDA brickx at top and replace rts with STA b.

```asm
; unsigned divide by 3
div3unsigned:
sta	temp1
lsr
lsr
clc
ror
lsr
clc
ror
lsr
clc
ror
lsr
clc
ror
lsr
rts
end
```

and call it in your code

```asm
LDA brickx
jsr div3unsigned
STA b
end
```

Also, depending on the range of your numbers you can get away with a small table to do a divide by 3.

```asm
LDY brickx
LDA div3table,Y
STA b
end
```

and then somewhere at the end of your file

```asm
; table good from 0-9
div3table: .byte 0,0,0,1,1,1,2,2,2,3
end
```

One other reasonable approach is to avoid doing the divide altogether. It's often possible to optimize it out of your loop

##### Share on other sites

Times like these I wish I knew 6502 assembly.

One more question so I know if I even need to divide by 3. How big in Atari pixels is one pfpixel?

Edited by Luigi301

##### Share on other sites

four if I recall correctly.

##### Share on other sites

Okay, found another bug, this one's score-related.

I'm trying to use the score to check some game variables, but setting the score is acting very oddly. I can do score = 6 and the score comes up as 6. But if I do

```value = 6
score = value```

then the score comes up as 70.

##### Share on other sites

I just found a minor bug in version 0.99c. It displays 264 lines instead of 262 lines. I checked, and versions 0.99a and 0.99b both displayed 262 lines, so something changed in 0.99c to cause this. I'll compare the files to see what it was, and post my findings.

Also, the "const" keyword doesn't work anymore, but I haven't backtracked yet to see which version it stopped working in.

MR

##### Share on other sites

Here's a bit operation bug I found

in the getPosition routine of my code, the line

temp1 = rand: position{1} = temp1(7)

is generating the following code

.skipL058

.L059 ; temp1 = rand : position{1} = temp1 ( 7 )

jsr randomize

STA temp1

LDA temp1

AND #65536

PHP

LDA position

PLP

.byte \$D0, \$03

AND #253

.byte \$0C

ORA #2

STA position

I'm guessing it really wants to do an AND #128

for now I'm doing a work around

Silhouette.bas

##### Share on other sites

Here's a bit operation bug I found

in the getPosition routine of my code, the line

temp1 = rand: position{1} = temp1(7)

is generating the following code

Did you actually mean to type temp1{7}? I changed the () to {} and it compiled correctly with 128 instead of 65536.

By the way, I don't know which editor you're using, or what font you're using, but in Crimson Editor with Courier New 10 it was really hard to see the difference between () and {}, whereas it shows up easily in your AtariAge post. I was just checking my Crimson Editor screen font settings, and I think I've decided to go with Terminal 10.

Michael

"AAARRRGGGHHH!!! This computer program is driving me CRAZY!!! It keeps doing what I TELL it to do instead of what I WANT it to do!!!" Been there, done that, wore the straitjacket!

##### Share on other sites

Did you actually mean to type temp1{7}? I changed the () to {} and it compiled correctly with 128 instead of 65536.

Doh! Thanks, I thought I hade checked this multiple times. I'm actually using 2600IDE. I probably need to switch to a real editor though. I should just set up PSPad to work with bAtari Basic.

##### Share on other sites

Did you actually mean to type temp1{7}? I changed the () to {} and it compiled correctly with 128 instead of 65536.

Doh! Thanks, I thought I hade checked this multiple times. I'm actually using 2600IDE. I probably need to switch to a real editor though. I should just set up PSPad to work with bAtari Basic.

2600IDE lets you change the font, too. True, it isn't a full-featured editor, but it's very easy to use, and it's what I used when I started programming in batari Basic. I'm currently using Crimson Editor, but I've actually *purchased* Multi-Edit (a commercial IDE for professional programmers, which I happen to like), and every so often I pay to update it to the next version, so I really *ought* to be using that instead. Really, the only reason I'm using Crimson Editor at all is because I wanted a free IDE that I could tell people about in my posts, so I could help them with it if they have trouble.

Michael

##### Share on other sites

This seems like a bug to me. Is the language supposed to support use of bitwise operators in the conditional expressions of if-then statements? When I use the & operator I get incorrect code:

```.L0226 ;  rem ** The upper nybble of playerStatus forms an invulnerability counter,

.L0227 ;  rem ** and bit 0 is set when the player is using the shield.

.L0228 ;  if playerStatus  &  %11110001 then SkipPlayerIsNotHurt

LDA playerStatus
CMP #%11110001
.L0229 ;  playerHealth  =  playerHealth  /  2  :  rem Decrease the health bar by 1.

LDA playerHealth
lsr
STA playerHealth
.L0230 ;  playerStatus  =  playerStatus  |  \$F0  :  rem Set invulnerability counter to max.

LDA playerStatus
ORA #\$F0
STA playerStatus
.SkipPlayerIsNotHurt
; SkipPlayerIsNotHurt```

Is this a bug or a feature

Cheers!

##### Share on other sites
This seems like a bug to me. Is the language supposed to support use of bitwise operators in the conditional expressions of if-then statements? When I use the & operator I get incorrect code:

```.L0226 ;  rem ** The upper nybble of playerStatus forms an invulnerability counter,

.L0227 ;  rem ** and bit 0 is set when the player is using the shield.

.L0228 ;  if playerStatus  &  %11110001 then SkipPlayerIsNotHurt

LDA playerStatus
CMP #%11110001
.L0229 ;  playerHealth  =  playerHealth  /  2  :  rem Decrease the health bar by 1.

LDA playerHealth
lsr
STA playerHealth
.L0230 ;  playerStatus  =  playerStatus  |  \$F0  :  rem Set invulnerability counter to max.

LDA playerStatus
ORA #\$F0
STA playerStatus
.SkipPlayerIsNotHurt
; SkipPlayerIsNotHurt```

Is this a bug or a feature

Cheers!

bB typically does a load and compare as shown, and determines from the operator what kind of branch to use, but if it's not found, it apparently it just does nothing if the operator isn't recognized as valid. I think it doesn't report an error because lack of a valid operator doesn't necessarily mean the statement is malformed (though that check could be done.)

I've been meaning to allow any sort of operation in if/thens other than just a simple compare, but haven't got around to it. Maybe there's a case for adding & until I get around to it, as I've had a use for that kind of operation myself.

##### Share on other sites

bB typically does a load and compare as shown, and determines from the operator what kind of branch to use, but if it's not found, it apparently it just does nothing if the operator isn't recognized as valid. I think it doesn't report an error because lack of a valid operator doesn't necessarily mean the statement is malformed (though that check could be done.)

I've been meaning to allow any sort of operation in if/thens other than just a simple compare, but haven't got around to it. Maybe there's a case for adding & until I get around to it, as I've had a use for that kind of operation myself.

My bad! I misread the online manual. I mistook the && operator for the & operator.

##### Share on other sites

Here is an interesting compiler bug or wierdness. I should learn not to start variable names with "joy", but it is strange what causes this one to happen.

If you setup a variable that starts with joy and then later try to do an equals comparison to a variable it will fail with the error:

---------- Capture Output ----------

> "C:\Atari2600\bB\2600bas.bat" C:\Atari2600\projects\bug.bas

(13): invalid console switch/controller reference

(13): Error: Unknown keyword: (whatever your variable name was that you were trying to compare the joy... variable to)

Compilation failed.

> Terminated with exit code 0.

Code to reproduce compile bug attached. If you change all references to joybits to gamebits, it compiles. If you use greater than instead of equals, it compiles. Fun!

bug.bas

Edited by Fort Apocalypse

##### Share on other sites

On a somewhat related topic it would be nice to be able to do this:

set kernel_options no_blank_lines

set smartbranching on

dim gamebits = temp4

mainloop

gamebits = 0

gamebits{0} = joy0down

gamebits{1} = joy0right

gamebits{2} = joy0up

gamebits{3} = joy0left

temp3 = 4

if gamebits > temp3 then COLUBK = 15 else COLUBK = 0

goto mainloop

but currently this produces the following compiler error because I guess switches aren't allowed to be assigned to a variable or bit.

---------- Capture Output ----------

> "C:\Atari2600\bB\2600bas.bat" C:\Atari2600\projects\bug.bas

2600 Basic compilation complete.

C:\Atari2600\projects\bug.bas.asm (1529): error: Value in 'and #65536' must be <\$100.

C:\Atari2600\projects\bug.bas.asm (1541): error: Value in 'and #65536' must be <\$100.

C:\Atari2600\projects\bug.bas.asm (1553): error: Value in 'and #65536' must be <\$100.

C:\Atari2600\projects\bug.bas.asm (1565): error: Value in 'and #65536' must be <\$100.

bytes of ROM space left

Unrecoverable error(s) in pass, aborting assembly!

Complete.

> Terminated with exit code 0.

bug.bas

##### Share on other sites
On a somewhat related topic it would be nice to be able to do this:

set kernel_options no_blank_lines

set smartbranching on

dim gamebits = temp4

mainloop

gamebits = 0

gamebits{0} = joy0down

gamebits{1} = joy0right

gamebits{2} = joy0up

gamebits{3} = joy0left

temp3 = 4

if gamebits > temp3 then COLUBK = 15 else COLUBK = 0

goto mainloop

but currently this produces the following compiler error because I guess switches aren't allowed to be assigned to a variable or bit.

---------- Capture Output ----------

> "C:\Atari2600\bB\2600bas.bat" C:\Atari2600\projects\bug.bas

2600 Basic compilation complete.

C:\Atari2600\projects\bug.bas.asm (1529): error: Value in 'and #65536' must be <\$100.

C:\Atari2600\projects\bug.bas.asm (1541): error: Value in 'and #65536' must be <\$100.

C:\Atari2600\projects\bug.bas.asm (1553): error: Value in 'and #65536' must be <\$100.

C:\Atari2600\projects\bug.bas.asm (1565): error: Value in 'and #65536' must be <\$100.

bytes of ROM space left

Unrecoverable error(s) in pass, aborting assembly!

Complete.

> Terminated with exit code 0.

Yes, you can't currently start any variable with "joy."

However, you can assign bits to joystick moves, though not in the way you noted.

gamebits=((gamebits&\$F0)|(SWCHA/16))^15

Bits 3 to 0 of gamebits will be set to right, left, down, and up respectively, without affecting other bits.

##### Share on other sites
However, you can assign bits to joystick moves, though not in the way you noted.

gamebits=((gamebits&\$F0)|(SWCHA/16))^15

Bits 3 to 0 of gamebits will be set to right, left, down, and up respectively, without affecting other bits.

Cool! Thanks!!!

##### Share on other sites

gamebits=((gamebits&\$F0)|(SWCHA/16))^15

Bits 3 to 0 of gamebits will be set to right, left, down, and up respectively, without affecting other bits."

Can either of you give some examples of when that would be useful/possible applications?

##### Share on other sites

gamebits=((gamebits&\$F0)|(SWCHA/16))^15

Bits 3 to 0 of gamebits will be set to right, left, down, and up respectively, without affecting other bits."

Can either of you give some examples of when that would be useful/possible applications?

Try this:

```  temp1=(SWCHA/16)^15:if temp1 then gamebits=(gamebits&\$F0)|temp1
if gamebits{3} then player0x=player0x+1
if gamebits{2} then player0x=player0x-1
if gamebits{1} then player0y=player0y+1
if gamebits{0} then player0y=player0y-1```

##### Share on other sites
Can either of you give some examples of when that would be useful/possible applications?

Here is an example I'm working on. If I could figure out how to make joystick1 return the exact same variable with bits in the same place, then I could save a few more lines of code.

(Will start a thread on it, too so you can post there if interested in it.)

atar0.1.bas

atar0.1.bas.bin

##### Share on other sites

I found a slight timing bug in the standard kernel, when the last line of the playfield is being drawn:

```   ifnconst no_blank_lines
lastkernelline
ifnconst PFcolors
sleep 10
else
ldy #124
lda (pfcolortable),y
sta COLUPF
endif

ifconst PFheights
ldx #1
sleep 4
else
ldx playfieldpos
sleep 3
endif

jmp enterlastkernel

else
lastkernelline

ifconst PFheights
ldx #1
sleep 5
else
ldx playfieldpos
sleep 4
endif

cpx #1
bne .enterfromNBL  ; <----- This crosses a page boundary!
jmp no_blank_lines_bailout
endif

if ((<*)>\$d5)
align 256
endif
; this is a kludge to prevent page wrapping - fix!!!

.skipDrawlastP1
sleep 2
lda #0
jmp .continuelastP1

.endkerloop  ; enter at cycle 59??
nop

.enterfromNBL
ifconst pfres
ldy.w playfield+pfres*4-4
sty PF1  ; 3
ldy.w playfield+pfres*4-3
sty PF2  ; 3
ldy.w playfield+pfres*4-1
sty PF1  ; possibly too early?
ldy.w playfield+pfres*4-2
sty PF2  ; 3
else
ldy.w playfield+44
sty PF1  ; 3
ldy.w playfield+45
sty PF2  ; 3
ldy.w playfield+47
sty PF1  ; possibly too early?
ldy.w playfield+46
sty PF2  ; 3
endif```

(I reformatted the line indentations for increased legibility, and included more lines than necessary in the quoted code to better show the location of the line in question-- the branch which crosses a page boundary.)

When the kernel is drawing the last row of the playfield, the instructions to load/store the playfield data (in .enterfromNBL) are starting 1 cycle later than the corresponding load/store instructions for the other rows of the playfield, which causes the first pixel of PF1 to be drawn incorrectly, as shown below:

I corrected the timing bug by changing the sleeps in the following two lines:

```   ifnconst no_blank_lines
lastkernelline
ifnconst PFcolors
sleep 10
else
ldy #124
lda (pfcolortable),y
sta COLUPF
endif

ifconst PFheights
ldx #1
sleep 4
else
ldx playfieldpos
sleep 3
endif

jmp enterlastkernel

else
lastkernelline

ifconst PFheights
ldx #1
;		 sleep 5  ; <----- I reduced this by 1 cycle to fix the timing
sleep 4
else
ldx playfieldpos
;		 sleep 4  ; <----- I reduced this by 1 cycle to fix the timing
sleep 3
endif

cpx #1
bne .enterfromNBL
jmp no_blank_lines_bailout
endif

if ((<*)>\$d5)
align 256
endif
; this is a kludge to prevent page wrapping - fix!!!

.skipDrawlastP1
sleep 2
lda #0
jmp .continuelastP1

.endkerloop  ; enter at cycle 59??
nop

.enterfromNBL
ifconst pfres
ldy.w playfield+pfres*4-4
sty PF1  ; 3
ldy.w playfield+pfres*4-3
sty PF2  ; 3
ldy.w playfield+pfres*4-1
sty PF1  ; possibly too early?
ldy.w playfield+pfres*4-2
sty PF2  ; 3
else
ldy.w playfield+44
sty PF1  ; 3
ldy.w playfield+45
sty PF2  ; 3
ldy.w playfield+47
sty PF1  ; possibly too early?
ldy.w playfield+46
sty PF2  ; 3
endif```

After recompiling with the updated std_kernel.asm file, the last playfield row is drawn correctly:

Michael

##### Share on other sites
I found a slight timing bug in the standard kernel, when the last line of the playfield is being drawn:

I've attached a .zip file containing the updated std_kernel.asm and std_kernel_SC.asm files.

Michael

std_kernel.zip

##### Share on other sites
I found a slight timing bug in the standard kernel, when the last line of the playfield is being drawn:

I've attached a .zip file containing the updated std_kernel.asm and std_kernel_SC.asm files.

Michael

That's awesome. Thanks, Michael!

It would be great if there could either be an official pinned patch thread where people could link to topics that included patches to the kernels (so patch and discussion would be contained in other threads) and it would be great if the best of the patches could be hosted on the batari basic site with links to the atariage forum threads that discuss the patches. Same with minikernels, etc.

I'm having trouble at the moment finding the fix for pfcolors that Maus said was here in the forum somewhere so I thought it might be good to mention this here.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.