gbdev / gb-asm-tutorial

Learn to create games for the Game Boy using Assembly
http://gbdev.io/gb-asm-tutorial/
MIT License
100 stars 31 forks source link

Part 2 chapter 7 - code only #93

Open hollannikas opened 1 week ago

hollannikas commented 1 week ago

Hi there! I thought I'd have a go at #81.

Before adding any text and explanation to the docs, I thought I'd see first if this is what you were looking for. I did add some explanation in code comments and would be happy to update the teaching materials accordingly, once we agree on the code.

I've used packed BCD in just one byte. The actual code is in 40692b2d201dda928ea79ac954494ea36a6ca039 at labels IncreaseScorePackedBCD and UpdateScoreBoard

Looking forward to your questions and comments.

Rangi42 commented 1 week ago

I wonder if a 8/8 division algorithm would be more or less complicated to teach than BCD and daa?

; Increase score by 1
IncreaseScore:
    ld a, [wScore]
    inc a
    ld [wScore], a
    ret

; Read the score from wScore and update the score display
UpdateScoreBoard:
    ; Divide score by 10
    ; The quotient is the tens digit, the remainder is the ones digit
    ld a, [wScore]
    ld h, a  ; h = dividend
    ld l, 10 ; l = divisor
    ; Divide h by l, putting the quotient in h and the remainder in l
    ; Dividing by 10 means that the quotient is the tens digit
    ; and the remainder is the ones digit
    call DivideHByL
    ; Show the tens digits on screen
    ld a, h ; quotient
    add a, DIGIT_OFFSET
    ld [SCORE_TENS], a
    ; Show the ones digit on screen
    ld a, l ; remainder
    add a, DIGIT_OFFSET
    ld [SCORE_ONES], a
    ret

; Divide h by l, returning the quotient in h and the remainder in l
DivideHByL:
    ld a, 0 ; Initialize the remainder to 0
    ld b, 8 ; Loop over each bit in the dividend
    DivideLoop:
    ; Multiply h by 2, overflowing into a
    sla h
    rl a
    ; If the remainder so far is not less than the divisor...
    cp a, l
    jp c, ContinueDivideLoop
    ; ...then subtract the divisor from the remainder
    sub a, l
    ; and increment the quotient
    inc h
ContinueDivideLoop:
    dec b
    jp nz, DivideLoop
    ld a, l ; Return the remainder in l
    ret
hollannikas commented 1 week ago

I wonder if a 8/8 division algorithm would be more or less complicated to teach than BCD and daa?

This would also be an easy entry into BCD manipulation, if that's what the tutorial is supposed to explain.

For teaching purposes, especially if someone is new to assembly, the BCD approach might be easier to grasp. One could ask the reader to accept that daa "fixes" the accumulator after an add or sub, with an optional (graphical) explanation of how daa works in depth if needed.

A bit off-topic maybe, but my personal opinion would be that if you need a large score range and want the digit extraction to be clear, the division approach would be better, especially while increasing the score. If the range is small (1 byte,) BCD might be a bit faster for displaying.