Jump to content
IGNORED

[LePix] Assembler Question


twh/f2

Recommended Posts

Howdy Friends,

 

I am a newbie to 6502 assembler. The following code is a routine which basically protects the screen borders after a X-adjustment of my mouse.

 

In C/Java style it's pretty easy:

 

x_new = mx+x 
if (mx==positive) {
   if (x_new>x_max) {
    x=x_max
   } else {
    x=x_new;
    } 
} else {
   if (x_new<0) {
   x=0
   } else {
   x=x_new;
   }
}

 

This is what I wrote in 6502 assembler ( I am using MADS ):

**************************
* Cursor X/Y/W/H manipulation

x_new   dta 0

cursor_add_x .local
;       in:  x= mx (x-pos diff)

       txa
       clc
       adc cursor_x
       sta x_new
       
       txa
       bmi _negativ   ; mx=negativ? yes -> _negativ
       lda x_new
       cmp MOD_max_x
       bcs _bigger_max
       lda x_new
       sta cursor_X
       rts
       
_bigger_max
       lda MOD_max_x
       sta cursor_X
       rts     
       
_negativ
       lda x_new
       cmp #0
       bcs _bigger_equal
       lda #0
       sta cursor_X
       rts

_bigger_equal
       lda x_new
       sta cursor_X    
       rts

 

Unfortunately it's not working. The right border (MOD_max_x) works good, but the left border (0) doesn't seem to work at all.

 

I have difficulties to code something like "X<0" or "x>0" .. :-( ..

 

what is wrong?

Link to comment
Share on other sites

That code looks a bit over-complicated.

 

Why not just add your offset, then use the following code to correct out-of bounds conditions:


start lda cursor_x
bpl notneg; cursor pos is >0, < 128
clc
neg adc #40
sta cursor_x
bmi neg; if x<0 keep adding 40 to get it back in bounds
bpl finish
notneg cmp #40
bcc finish
; no sec needed here
sbc #40
sta cursor_x
jmp notneg
finish rts

 

That code is a bit over-complicated too, but you can't just AND out the high bits of the cursor position, as the wrap-around won't work properly.

Link to comment
Share on other sites

cursor_add_x .local
 txa
 clc
 adc cursor_x
 cmp MOD_max_x
 bcc _set
 cmp #-48
; if it's -48..-1 then set to 0
; I chose -48 because 48+160+48==256
 lda #0
 bcs _set
; else set to MOD_max_x
 lda MOD_max_x
_set
 sta cursor_x
 rts

Link to comment
Share on other sites

It's even better when you replace "cmp #-48" with "cpx #$80". :)

960971[/snapback]

 

wow.. I got code from Fox the Numen :) ... hehe.. The piece of code works well! Now I found another problem. Again I messed around with my basic 6502 knowledge but I couldn't find a good solution.

 

The problem is now: If X-register contains a value higher/lower than 48/-48, then the routine again fails (the mouse cursor breaks the border). So I thought, alright .. let's test first if the value is higher/lower and then set the maximum/minimum. something like this:

 

if (X>48)
  X=48
else if (X<(-48))
  X=-48

 

I think my problem currently is that I am not able to translate structured high language code to assembler syntax. could you guys please give me in a short some best practices?

 

\twh

Link to comment
Share on other sites

Negative numbers aren't natively supported in Assembler.

 

If you are using an 8-bit value only, then having -1 represented by $FF is sort of OK, since adding it to any number results in subtracting 1.

 

But, that won't work for multi-byte binary values.

 

How you implement your add/subtracts should reflect the purpose you are doing it.

 

Bounds checking is another issue. Finding an out of bounds value is easy enough, but you have to take more complex corrective action if it's anything more detailed than a transition from 39 to 40, or 0 to -1.

 

I wrote a multi-PM mover once, which supported 4 players, each split at a number of vertical locations.

 

I used an 8-bit value for velocity as follows:

bit 7: 1=backwards, 0=forwards.

bits 6-4: velocity of object (which will translate to a whole number from 0 to 7)

bits 3-0: fractonal velocity of object - a value from 0 to 15 which is added to an accumulator variable. If this 4 bit overflows, then the object is moved 1 extra pixel backwards or forwards.

 

Such a scheme is useful for moving sprites around, but something similar could be implemented for character movement.

 

The only thing is that I didn't use bounds checking, most games with horizontal motion with PMs work fine with the X-pos just going from 0-255.

 

This is the game I used the routine in. Sorry, but the source code is long gone, but you could easily enough use the disassembler in Atari800Win to see what's going on:

 

lunar_lander.txt

 

Load the game, with BASIC enabled, using ENTER "<dev:filename>"

Edited by Rybags
Link to comment
Share on other sites

Negative numbers aren't natively supported in Assembler.

 

yes. But this is very difficult to understand. After 6 hours of testing I finally found (by random?) a code which corrects a byte

 

 

       cmp #5
       bcc _set
       cmp #133        // #-5, #(-5) , #133
       bcs _set2
       lda #5

_set    sta mhoriz
       jmp _end
_set2   lda #-5
       sta mhoriz

 

I know, very ugly. But hell... this really destroys my understanding of how the 6502 or assembler is using negative numbers.

 

I thought, that "lda #-5" should be the same as "lda #133" (where 128+5=133) .. but when i replace "lda #-5" by "lda #133" .. I get a different result.

 

The same with "Cmp #133" . I always get different results when I use

   cmp #-5
   cmp #(-5)
   cmp #133

 

:-(

 

\twh

Link to comment
Share on other sites

I thought, that "lda #-5" should be the same as "lda #133" (where 128+5=133)

 

1000 0000 = -128

1000 0001 = -127

...

1111 1011 = -5

 

Hope this helps.

961051[/snapback]

 

yes this helps a lot. But I already found it out myself. I was wrong on how the 6502 handles negative values.

 

this is the final version of my subroutine:

 

;-----------------------------

max_step = 30

maxsize	.local
;  in:  a=value (e.g -36 or 39)
;  out: a=reduced value (e.g. -30 or 30)

cmp #max_step
bcc _set
cmp #128
bcs _negativ
lda #max_step
rts
_negativ cmp #256-max_step
bcs _set
lda #-max_step
_set	rts
.endl maxsize

;------------------------------

Link to comment
Share on other sites

Acually if you use my code with "cpx #$80" and not "cmp #-48",

wrapping problems arise only if the absolute difference exceeds 96,

which is close to the range of signed 8-bit number: -128..127.

So there's not much you can do without widening the input to 16 bits

(problematic).

Link to comment
Share on other sites

Negative numbers aren't natively supported in Assembler.

Actually they are, maybe just some crappy assemblers don't support negative constants directly. The same problems with signed numbers that you can encounter with assembly language can be seen in C/Java: e.g. you add two positive integers and get a negative result. So understanding the representation of signed integers is good no matter which language you are programming in (except when it's only Atari BASIC).

 

But, that won't work for multi-byte binary values.

Of course it will. Moreover, it's much easier than your "sign & absolute value" method. You add multi-byte signed integers as normal:

lda val1
clc
adc val2
sta result
lda val1+1
adc val2+1
sta result+1

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

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

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...