Skip to content

Instantly share code, notes, and snippets.

@SelvinPL
Last active November 25, 2021 13:22
Show Gist options
  • Select an option

  • Save SelvinPL/42f5e807174f9d6f8a7d7aa5e9649813 to your computer and use it in GitHub Desktop.

Select an option

Save SelvinPL/42f5e807174f9d6f8a7d7aa5e9649813 to your computer and use it in GitHub Desktop.

Funny thing ... because SDCC do not generate good code for this uint8_t* address = (uint8_t *)((hiAddress << 8) | loAddress); new version is even worst than old ... but finally asm version is 11% faster

old image

new image

asm image

.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::
;uint8_t hiAddress = 0xc0 | (currentState.newRobboY >> 4);
ld a, (#(_currentState + newRobboY))
ld b, a
swap a
and a, #0x0f
or a, #0xc0
;!!!!!!!!!!!!! c = hiAddress
ld c, a
;uint8_t lowY = currentState.newRobboY << 4;
ld a, b
swap a
and a, #0xf0
;!!!!!!!!!!!! d = lowY
ld d, a
;checked.all = 0;
;!!!!!!!!!!!! e = checked
ld e, #0x00
;uint8_t x = 1
;!!!!!!!!!!!!! b = x
ld b, #0x01
;do
loopStart$:
;if (!checked.right)
ld a, e
and a, #0x02
jr NZ, checkLeft$
;uint8_t nextX = currentState.newRobboX + x;
ld a, (#(_currentState + newRobboX))
add a, b
;if (nextX < 16)
bit 4, a
jr NZ, checkedRight$
;uint16_t address = (nextX | lowY) | (hiAddress << 8);
or a, d
ld l, a
ld h, c
;uint8_t tile = *((uint8_t*)address);
ld a, (hl)
;if (tile == TILE_MAGNET_LEFT)
cp a, #TILE_MAGNET_LEFT
jr NZ, checkIfRightTileNotEmpty$
;currentState.robboMagnetDrag = DIR_RIGHT;
ld hl, #(_currentState + robboMagnetDrag)
ld (hl),#DIR_RIGHT
;playSound(magnetSound);
ld de, #_magnetSound
push de
call _playSound
pop hl
;return;
jr return$
checkIfRightTileNotEmpty$:
;else if (tile != TILE_EMPTY)
or a, a
jr Z, checkLeft$
checkedRight$:
;checked.right = TRUE;
set 1, e
checkLeft$:
;if (!checked.left)
ld a, e
and a, #0x01
jr NZ, loopCheck$
;uint8_t prevX = currentState.newRobboX - x;
ld a, (#(_currentState + newRobboX))
sub a, b
;if (prevX > 0)
jr Z, checkedLeft$
;uint16_t address = (prevX | lowY) | (hiAddress << 8);
or a, d
ld l, a
ld h, c
;uint8_t tile = *((uint8_t*)address);
ld a, (hl)
;if (tile == TILE_MAGNET_RIGHT)
cp a, #TILE_MAGNET_RIGHT
jr NZ, checkIfLeftTileNotEmpty$
;currentState.robboMagnetDrag = DIR_LEFT;
ld hl, #(_currentState + robboMagnetDrag)
ld (hl),#DIR_LEFT
;playSound(magnetSound);
ld de, #_magnetSound
push de
call _playSound
pop hl
;return;
jr return$
checkIfLeftTileNotEmpty$:
;else if (tile != TILE_EMPTY)
or a, a
jr Z, loopCheck$
checkedLeft$:
;checked.left = TRUE;
set 0, e
loopCheck$:
;while (++x < 16 && checked.all != 0b11)
inc b
ld a, b
sub a, #0x10
jr NC, magnetNotFound$
ld a, e
sub a, #0x03
jr NZ, loopStart$
magnetNotFound$:
;currentState.robboMagnetDrag = DIR_NONE;
ld hl, #(_currentState + robboMagnetDrag)
ld (hl),#DIR_NONE
return$:
ret
#define LEFT 1
#define RIGHT 2
void checkMagnet()
{
uint8_t checked = 0;
uint8_t hiAddress = 0xc0 | (currentState.newRobboY >> 4);
uint8_t lowY = currentState.newRobboY << 4;
uint8_t x = 1;
do
{
if (!(checked & RIGHT))
{
uint8_t nextX = currentState.newRobboX + x;
if ((nextX & 0x10) == 0)
{
uint8_t loAddress = nextX | lowY;
uint8_t* address = (uint8_t *)((hiAddress << 8) | loAddress);
uint8_t tile = *(address);
if (tile == TILE_MAGNET_LEFT)
{
currentState.robboMagnetDrag = DIR_RIGHT;
playSound(magnetSound);
return;
}
else if (tile != TILE_EMPTY)
goto checkedRight;
}
else
{
checkedRight:
checked |= RIGHT;
}
}
if (!(checked & LEFT))
{
uint8_t prevX = currentState.newRobboX - x;
if ((prevX & 0x10) == 0)
{
uint8_t loAddress = prevX | lowY;
uint8_t* address = (uint8_t*)((hiAddress << 8) | loAddress);
uint8_t tile = *(address);
if (tile == TILE_MAGNET_RIGHT)
{
currentState.robboMagnetDrag = DIR_LEFT;
playSound(magnetSound);
return;
}
else if (tile != TILE_EMPTY)
goto checkedLeft;
}
else
{
checkedLeft:
checked |= LEFT;
}
}
} while (++x < 16 && checked != (LEFT | RIGHT));
currentState.robboMagnetDrag = DIR_NONE;
}
#define LEFT 1
#define RIGHT 2
void checkMagnet()
{
uint8_t checked = 0;
uint8_t* mapY = currentLevel.map + 16 * currentState.newRobboY;
uint8_t x = 1;
do
{
if (!(checked & RIGHT))
{
uint8_t nextX = currentState.newRobboX + x;
if ((nextX & 0x10) == 0)
{
uint8_t tile = *(mapY + nextX);
if (tile == TILE_MAGNET_LEFT)
{
currentState.robboMagnetDrag = DIR_RIGHT;
playSound(magnetSound);
return;
}
else if (tile != TILE_EMPTY)
goto checkedRight;
}
else
{
checkedRight:
checked |= RIGHT;
}
}
if (!(checked & LEFT))
{
uint8_t prevX = currentState.newRobboX - x;
if ((prevX & 0x10) == 0)
{
uint8_t tile = *(mapY + prevX);
if (tile == TILE_MAGNET_RIGHT)
{
currentState.robboMagnetDrag = DIR_LEFT;
playSound(magnetSound);
return;
}
else if (tile != TILE_EMPTY)
goto checkedLeft;
}
else
{
checkedLeft:
checked |= LEFT;
}
}
} while (++x < 16 && checked != (LEFT | RIGHT));
currentState.robboMagnetDrag = DIR_NONE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment