Skip to content

Instantly share code, notes, and snippets.

@SelvinPL
Created November 25, 2021 21:16
Show Gist options
  • Select an option

  • Save SelvinPL/388a712d47c2379b734cd03176c8a2c1 to your computer and use it in GitHub Desktop.

Select an option

Save SelvinPL/388a712d47c2379b734cd03176c8a2c1 to your computer and use it in GitHub Desktop.

Final(?) magnet implementation for GB Robbo

C using 0xCyyx  8072	11	412/  1204/ 733.8
C using map[]	5772	11	300/  944/  524.7
ASM		5060	11	276/  872/  460.0
.title "magnets_s"
.module magnets_s
.area _CODE
newRobboY = 15
newRobboX = 14
robboMagnetDrag = 13
DIR_RIGHT = 0x0
DIR_LEFT = 0x2
DIR_NONE = 0x8
TILE_MAGNET_RIGHT = 0x0c
TILE_MAGNET_LEFT = 0x1c
.globl _playSound
.globl _currentState
_checkMagnet::
ld a, (#(_currentState + newRobboY))
;================ b => currentState.newRobboY .... temporally
ld b, a
swap a
and a, #0x0f
or a, #0xc0
;================ h => hiAddress = 0xc0 | (currentState.newRobboY >> 4) hiAddress will not change
ld h, a
ld a, b
swap a
and a, #0xf0
;================ d => lowY = currentState.newRobboY << 4
ld d, a
ld a, (#(_currentState + newRobboX))
;================ b => currentState.newRobboX loop counter
ld b, a
;================ e => currentState.newRobboX for left loop counter ld a,(a16) is costly
ld e, a
or a, d
inc a
;================ l => currentState.newRobboX | lowY + 1
ld l, a
loopStartRight$:
;================ while ++b != 16 x is [0..15]
inc b
ld a, b
sub a, #0x10
jr Z, checkLeft$
;================ we already have tile address in hl so we load and increment hl
ld a, (hl+)
;================ is tile a magnet?
cp a, #TILE_MAGNET_LEFT
jr NZ, checkIfRightTileNotEmpty$
;================ yes? robbo slowly dying ... set dragging state to drag to right
ld hl, #(_currentState + robboMagnetDrag)
ld (hl), #DIR_RIGHT
;================ play magnet sound
ld de, #_magnetSound
push de
call _playSound
pop hl
ret
checkIfRightTileNotEmpty$:
;=============== any non empty(0) tile blocks magnet
or a, a
jr Z, loopStartRight$
checkLeft$:
ld a, e
or a, d
dec a
;================ l => currentState.newRobboX | lowY - 1
ld l, a
loopStartLeft$:
;================ while --e != 255
dec e
ld a, e
sub a, #0xff
jr Z, magnetNotFound$
;================ we already have tile address in hl so we load and decrement hl
ld a, (hl-)
;================ is tile a magnet?
cp a, #TILE_MAGNET_RIGHT
jr NZ, checkIfLeftTileNotEmpty$
;================ yes? roboo is slowly dying ... set dragging state to drag to left
ld hl, #(_currentState + robboMagnetDrag)
ld (hl), #DIR_LEFT
;================ play magnet sound
ld de, #_magnetSound
push de
call _playSound
pop hl
ret
checkIfLeftTileNotEmpty$:
;=============== any non empty(0) tile blocks magnet
or a, a
jr Z, loopStartLeft$
magnetNotFound$:
;================ no magnets found set dragging state to drag to none ... robbo is safe
ld hl, #(_currentState + robboMagnetDrag)
ld (hl),#DIR_NONE
ret
#define MAKE_ADDRESS(hiAddress, loAddress) ((uint8_t*)(((hiAddress) << 8) | (loAddress)))
void checkMagneta()
{
uint8_t hiAddress = 0xc0 | (currentState.newRobboY >> 4);
uint8_t lowY = currentState.newRobboY << 4;
uint8_t nextX = currentState.newRobboX;
while (++nextX != 16)
{
uint8_t tile = *(MAKE_ADDRESS(hiAddress, nextX | lowY));
if (tile == TILE_MAGNET_LEFT)
{
currentState.robboMagnetDrag = DIR_RIGHT;
playSound(magnetSound);
return;
}
else if (tile != TILE_EMPTY)
break;
};
uint8_t prevX = currentState.newRobboX;
while (--prevX != 255)
{
uint8_t tile1 = *(MAKE_ADDRESS(hiAddress, prevX | lowY));
if (tile1 == TILE_MAGNET_RIGHT)
{
currentState.robboMagnetDrag = DIR_LEFT;
playSound(magnetSound);
return;
}
else if (tile1 != TILE_EMPTY)
break;
};
currentState.robboMagnetDrag = DIR_NONE;
}
void checkMagnetb()
{
uint8_t* mapY = currentLevel.map + 16 * currentState.newRobboY;
uint8_t nextX = currentState.newRobboX;
while (++nextX != 16)
{
uint8_t tile = *(mapY + nextX);
if (tile == TILE_MAGNET_LEFT)
{
currentState.robboMagnetDrag = DIR_RIGHT;
playSound(magnetSound);
return;
}
else if (tile != TILE_EMPTY)
break;
};
uint8_t prevX = currentState.newRobboX;
while (--prevX != 255)
{
uint8_t tile1 = *(mapY + prevX);
if (tile1 == TILE_MAGNET_RIGHT)
{
currentState.robboMagnetDrag = DIR_LEFT;
playSound(magnetSound);
return;
}
else if (tile1 != TILE_EMPTY)
break;
};
currentState.robboMagnetDrag = DIR_NONE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment