Problem with negative health/ ASM6502 question

So I have tracked down an issue, but I am not sure quite how to solve it.

I have 2 different player attacks.
Standard attacks do 1 dmg
Kicks do 3 dmg

This is my slightly modified code for doing damage/checking if the monster is dead:
Code:
LDA Object_health,x
    SEC
    SBC #PLR_KICKDMG
    CMP #$01
    BCC killMonster_SR
    STA Object_health,x
    RTS

The problem arises here:
Monster has 2 health remaining,
Player kicks monster - subtract 3 health
Monster now has -1 health.
Compare accumulator to 01
BCC checks if health is less than 01 and branch to death
When it compares 1 to -1 I am getting FALSE.
Same goes for any more negative numbers.

Basically, if the damage I do to a monster puts their health below zero, they become invincible. So I guess BCC doesn't account for negative numbers.
Is there a way I can rewrite the check to account for if the number is negative?
 

Kasumi

New member
Subtraction and cmp run mostly the same logic. If the subtraction would cause the value to be less than 0, the carry is clear, otherwise it is set.

In other words, there's no need for any cmp after a subtract if you're trying to determine if the subtract made something less than (or equal to) 0. The carry will tell you. This is actually how cmp works too. If you have a value, and subtract a larger value, the result will be less than 0, clearing the carry. If you have a value and subtract the same or a lesser value, the result will be greater than or equal to zero, setting the carry. This is why cmp is commonly explained as "carry clear = A was less than the value", but it's helpful to understand the whole thing. (That is, cmp just subtracts the value from A without storing the result in A.)
Code:
lda Object_health,x
sec
sbc #PLR_KICKDMG
bcc killMonster_SR;If object_health-PLR_KICKDMG is less than zero, branch
beq killMonster_SR;If object_health-PLR_KICKDMG was equal to zero, branch
STA Object_health,x
    RTS

Alternatively:
Code:
lda Object_health,x
cmp #PLR_KICKDMG
bcc killMonster_SR;If ;If object_health-PLR_KICKDMG is less than zero actually subtracting the health would kill it
beq killMonster_SR;;If Object_health-PLR_KICKDMG = 0, actually subtracting the health would also kill it
;If here, subtracting PLR_KICKDMG would result
;In a value greater than or equal to 1
;sec;It's already set
sbc #PLR_KICKDMG
STA Object_health,x
RTS
Alternatively, alternatively:
Code:
LDA Object_health,x
    SEC
    SBC #PLR_KICKDMG
    BMI killMonster_SR;If negative, kill the monster
    BEQ killMonster_SR;If equal to zero, kill the monster
    STA Object_health,x
    RTS
The last one doesn't allow as high health, though. (If the monster's health is 132, 132-3 = 129, which has the negative bit set, to the monster gets killed despite having lots of health.) I just give all three examples to show how the carry flag and cmp actually work.

Edit: Further, you usually don't want to use cmp #1, bcc. The only value that would clear the carry when subtracting 1 is 0, and there's a free zero check for most instructions.
Code:
LDA Object_health,x
    SEC
    SBC #PLR_KICKDMG
    CMP #$01
    BCC killMonster_SR
would branch in all the same cases as
Code:
LDA Object_health,x
    SEC
    SBC #PLR_KICKDMG
    BEQ killMonster_SR
because SBC affects the zero flag. You usually don't want to use cmp #0 for similar reasons. Checks for zero are usually free.

Edit2: To explain even further, the 6502 treats negative numbers as negative and not negative simultaneously. $FF is simultaneously 255 and -1. $FE is simultaneously 254 and -2. CMP/SBC/ADC all don't care whether you as the programmer consider the number negative or not. 0 minus 1 is negative 1, but it's also 255. 0 + -1 = -1, but 0 + 255 also equals 255. So the CPU gets the same result whether you consider $FF to be -1 or whether you consider $FF to be 255.

The carry is more for unsigned comparisons ($FF = 255), the negative flag is more for signed comparisons ($FF = -1). So when you subtracted 3 from 2 and got -1, that's the same as 255. And 255 is > 1 which is why your bcc failed. But that doesn't necessarily mean using bpl or bmi would have worked better, comparisons (especially signed comparisons) are a deep topic.
 
Top Bottom