twh/f2 Posted November 5, 2005 Share Posted November 5, 2005 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? Quote Link to comment Share on other sites More sharing options...
Rybags Posted November 6, 2005 Share Posted November 6, 2005 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. Quote Link to comment Share on other sites More sharing options...
fox Posted November 6, 2005 Share Posted November 6, 2005 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 Quote Link to comment Share on other sites More sharing options...
fox Posted November 6, 2005 Share Posted November 6, 2005 It's even better when you replace "cmp #-48" with "cpx #$80". Quote Link to comment Share on other sites More sharing options...
twh/f2 Posted November 6, 2005 Author Share Posted November 6, 2005 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 Quote Link to comment Share on other sites More sharing options...
Rybags Posted November 6, 2005 Share Posted November 6, 2005 (edited) 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 November 6, 2005 by Rybags Quote Link to comment Share on other sites More sharing options...
twh/f2 Posted November 6, 2005 Author Share Posted November 6, 2005 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 Quote Link to comment Share on other sites More sharing options...
Chrodegang Posted November 6, 2005 Share Posted November 6, 2005 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. Quote Link to comment Share on other sites More sharing options...
twh/f2 Posted November 6, 2005 Author Share Posted November 6, 2005 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 ;------------------------------ Quote Link to comment Share on other sites More sharing options...
fox Posted November 7, 2005 Share Posted November 7, 2005 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). Quote Link to comment Share on other sites More sharing options...
fox Posted November 7, 2005 Share Posted November 7, 2005 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.