Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

Ads

#1 2019-12-11 17:20:46

jdsoft
Member
Registered: 2019-12-04
Posts: 10

Alternatives to module (%) operation

Hello!
Is there a better way to apply module operation to a number?

x = number % 10

I have read that "%" is not efficient enough in gbdk
Thanks!

Offline

 

#2 2019-12-12 04:48:36

Zalo
Member
From: Spain
Registered: 2016-07-26
Posts: 103
Website

Re: Alternatives to module (%) operation

When using power of 2 you can simply use bit masks:
eg: (n % 8) can be achieved doing (n & 0x7)

Offline

 

#3 2019-12-13 02:00:44

jdsoft
Member
Registered: 2019-12-04
Posts: 10

Re: Alternatives to module (%) operation

Wow, great idea!
Thanks a lot

Offline

 

#4 2019-12-14 19:44:34

h0tp3ngu1n
Member
Registered: 2019-08-18
Posts: 25

Re: Alternatives to module (%) operation

If you don't mind wasting some space, you could use a lookup table.
(Note: I'm new, so hopefully what I just said isn't a bad idea)

Last edited by h0tp3ngu1n (2019-12-14 19:45:20)

Offline

 

#5 2019-12-15 02:02:59

jdsoft
Member
Registered: 2019-12-04
Posts: 10

Re: Alternatives to module (%) operation

It's interesting too, thanks h0tp3ngu1n.

Offline

 

#6 2020-02-26 15:04:22

toxa
Member
Registered: 2020-02-13
Posts: 309

Re: Alternatives to module (%) operation

if you need decimal numbers to count score, for example, you may use BCD numbers. i wrote some routines to deal with 8-digit (4-byte) BCD numbers. something like this:

Code:

#include "bcd.h"

BCD bcd_timer_value = {{0, 0, 0, 0}}; // decimal 12345678 will be {{0x78, 0x56, 0x34, 0x12}}
BCD bcd_addend = {{1, 0, 0, 0}}; 
unsigned char text[9];  // at least 8+1 symbols

// ...
    while (1) {
        // ...
        bcd_add(&bcd_timer_value, &bcd_addend);
        set_bkg_tiles(6, 1, bcd2text(&bcd_timer_value, 0x2D, text), 1, text); // 0x2d - offset for zero digit tile
    }

so, the % 10 for this bcd value will be: bcd_timer_value.bytes[0] & 0x0f (the lower nibble of the lower byte of the 4-byte BCD number)

the bcd.h file:

Code:

typedef struct { unsigned char bytes[4]; } BCD;

void bcd_add(BCD * sour, BCD * value) __naked
{
    sour; value; // suppress warninig: unreferenced function argument
__asm
            lda     HL, 5(SP)
            ld      D, (HL)         
            dec     HL
            ld      E, (HL)         ; DE: value
            dec     HL
            ld      A, (HL-)
            ld      L, (HL)
            ld      H, A            ; HL: sour

            or      A               ; clear C, HC

            ld      A,(DE)
            add     (HL)
            daa
            ld      (HL+), A
            inc     DE
            
            ld      A,(DE)
            adc     (HL)
            daa
            ld      (HL+), A
            inc     DE
            
            ld      A,(DE)
            adc     (HL)
            daa
            ld      (HL+), A
            inc     DE
            
            ld      A,(DE)
            adc     (HL)
            daa
            ld      (HL+), A
            
            ret
__endasm;
}

void bcd_sub(BCD * sour, BCD * value) __naked
{
    sour; value; // suppress warninig: unreferenced function argument 
__asm
            lda     HL, 2(SP)
            ld      E, (HL)         
            inc     HL
            ld      D, (HL)         ; DE: sour
            inc     HL
            ld      A, (HL+)
            ld      H, (HL)
            ld      L, A            ; HL: value

            or      A               ; clear C, HC

            ld      A,(DE)
            sub     (HL)
            daa
            ld      (DE), A
            inc     DE
            inc     HL
            
            ld      A,(DE)
            sbc     (HL)
            daa
            ld      (DE), A
            inc     DE
            inc     HL
            
            ld      A,(DE)
            sbc     (HL)
            daa
            ld      (DE), A
            inc     DE
            inc     HL
            
            ld      A,(DE)
            sbc     (HL)
            daa
            ld      (DE), A
            
            ret
__endasm;
}

UBYTE bcd2text(BCD * bcd, UBYTE tile_offset, unsigned char * buffer) __naked
{
    bcd; tile_offset; buffer;
__asm
            push    BC
            
            lda     HL, 4(SP)
            ld      E, (HL)         
            inc     HL
            ld      D, (HL)         ; DE: bcd
            inc     HL
            ld      B, #0
            ld      C, (HL)         ; C: digit offset
            inc     HL
            ld      A, (HL+)
            ld      H, (HL)
            ld      L, A            ; HL: buffer

            inc     DE
            inc     DE
            inc     DE

            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            jr      Z, $bcdtxt01
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt01:  ld      A, (DE)
            and     #0x0f
            or      B
            jr      Z, $bcdtxt02
            ld      A, (DE)
            and     #0x0f            
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt02:  ld      A, (DE)
            dec     DE         

            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            or      B
            jr      Z, $bcdtxt03
            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt03:  ld      A, (DE)
            and     #0x0f
            or      B
            jr      Z, $bcdtxt04
            ld      A, (DE)
            and     #0x0f            
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt04:  ld      A, (DE)
            dec     DE         

            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            or      B
            jr      Z, $bcdtxt05
            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt05:  ld      A, (DE)
            and     #0x0f
            or      B
            jr      Z, $bcdtxt06
            ld      A, (DE)
            and     #0x0f            
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt06:  ld      A, (DE)
            dec     DE         

            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            or      B
            jr      Z, $bcdtxt07
            ld      A, (DE)
            srl     A
            srl     A
            srl     A
            srl     A
            add     C
            ld      (HL+), A
            inc     B
$bcdtxt07:  ld      A, (DE)
            and     #0x0f
            add     C
            ld      (HL+), A
            inc     B

            xor     A, A
            ld      (HL+), A

            ld      D, A
            ld      E, B
            pop     BC
            
            ret
__endasm;
}

Last edited by toxa (2020-02-28 06:28:05)

Offline

 

#7 2020-02-28 07:42:10

toxa
Member
Registered: 2020-02-13
Posts: 309

Re: Alternatives to module (%) operation

ps: and a compare function, returns -1 when A<B; 1 when A>B and 0 when equal

Code:

BYTE bcd_compare(BCD * A, BCD * B) __naked
{
    A; B; 
__asm
            lda     HL, 2(SP)
            ld      E, (HL)         
            inc     HL
            ld      D, (HL)         ; DE: sour
            inc     HL
            ld      A, (HL+)
            ld      H, (HL)
            ld      L, A            ; HL: value

            inc     DE
            inc     DE
            inc     DE
            
            inc     HL
            inc     HL
            inc     HL
            
            ld      A, (DE)
            cp      (HL)
            jr      Z, $bcdcmp01
            jr      C, $bcdcmp_aB
$bcdcmp_Ab:
            ld      DE, #0x0001
            ret
$bcdcmp_aB:            
            ld      DE, #0xffff
            ret
$bcdcmp01:  
            dec     DE
            dec     HL
            ld      A, (DE)
            cp      (HL)
            jr      Z, $bcdcmp02
            jr      C, $bcdcmp_aB
            jr      $bcdcmp_Ab
$bcdcmp02:            
            dec     DE
            dec     HL
            ld      A, (DE)
            cp      (HL)
            jr      Z, $bcdcmp03
            jr      C, $bcdcmp_aB
            jr      $bcdcmp_Ab
$bcdcmp03:            
            dec     DE
            dec     HL
            ld      A, (DE)
            cp      (HL)
            jr      C, $bcdcmp_aB
            jr      NZ, $bcdcmp_Ab

            ld      DE, #0x0000
            ret
__endasm;
}

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson