Peanut-GB icon indicating copy to clipboard operation
Peanut-GB copied to clipboard

gb: add delay and memcpy detection

Open deltabeard opened this issue 1 year ago • 3 comments

Add detection of busy loops, or loops that wait for a status. Such loops may include:

  • Waiting for OAM DMA.
  • Waiting for an interrupt.
  • Copying from one block of memory to another (eg. Copying data from ROM to RAM).

A use case is where the emulation speed can be increased because all ROMs perform at least one of the tasks written above in some cases. Instead of executing each task instruction by instruction, a look-ahead should be used to determine whether the task can be performed with high-level emulation instead (eg. calling memcpy() in peanut-gb).

deltabeard avatar Oct 05 '23 11:10 deltabeard

Busy loops

.wait
	dec a
	jr nz, .wait

from https://github.com/pret/pokered/blob/30c244ae4f1acc6f018499ceaa9b138367d7bedf/engine/gfx/oam_dma.asm#L23C1-L25C14

memcpy routines

CopyData::
; Copy bc bytes from hl to de.
	ld a, [hli]
	ld [de], a
	inc de
	dec bc
	ld a, c
	or b
	jr nz, CopyData
	ret

from https://github.com/pret/pokered/blob/30c244ae4f1acc6f018499ceaa9b138367d7bedf/home/copy.asm#L15

Also:

; Copy bytes from one area to another.
; @param de: Source
; @param hl: Destination
; @param bc: Length
Memcopy:
    ld a, [de]
    ld [hli], a
    inc de
    dec bc
    ld a, b
    or a, c
    jp nz, Memcopy
    ret

from https://gbdev.io/gb-asm-tutorial/part2/functions.html

Another example that can only copy up to 255 bytes.

.loop
	ld a, [hli]
	ld [de], a
	inc de
	dec c
	jr nz, .loop
	ret

from https://github.com/pret/pokered/blob/30c244ae4f1acc6f018499ceaa9b138367d7bedf/home/vcopy.asm#L439

Also:

.loop_17:
	ld a, [de]
	ld [hl], a
	inc l
	inc e
	dec b
	jr nz, .loop_17

from https://github.com/alexsteb/tetris_disassembly/blob/b4bbceb3cc086121ab4fe9bf4dad6752fe956ec0/main.asm#L6260C1-L6266C17

Also:

COPY_TILES::
	ldi a, [hl]
	ld [de], a
	inc de
	dec bc
	ld a, b
	or c
	jr nz, COPY_TILES

from https://github.com/alexsteb/tetris_disassembly/blob/b4bbceb3cc086121ab4fe9bf4dad6752fe956ec0/main.asm#L6713C1-L6720C19

memset routines

.loop
	ld [hli], a
	dec c
	jr nz, .loop
	dec b
	jr nz, .loop
	jp Delay3

from https://github.com/pret/pokered/blob/30c244ae4f1acc6f018499ceaa9b138367d7bedf/home/copy2.asm#L180

Also:

.x
	ld [hli], a
	dec c
	jr nz, .x

from https://github.com/pret/pokered/blob/b302e93674f376f2881cbd931a698345ad27bec3/home/copy2.asm#L169C1-L172C11

.x
	ld [hli], a
	dec b
	jr nz, .x

strcpy routines

; copies a string from de to hl
CopyString::
	ld a, [de]
	inc de
	ld [hli], a
	cp "@"
	jr nz, CopyString
	ret

from https://github.com/pret/pokered/blob/30c244ae4f1acc6f018499ceaa9b138367d7bedf/home/copy_string.asm#L7

deltabeard avatar Oct 11 '23 13:10 deltabeard

Possible elimination of register checks in loops?

.x:
	ld a, [$FF00+$41]
	and $03
	jr nz, .x

deltabeard avatar Oct 13 '23 18:10 deltabeard

If the routine is in WRAM or HRAM, than the first instruction in the routine could be changed to an invalid instruction that could then be hijacked into a memcpy or memset instruction. The first bank of the ROM could be internally cached to allow Peanut-GB to replace such instructions, since that is likely where such common routines would be placed in a ROM. It might be best to only perform this check in the first bank of the ROM and only check for memcpy in HRAM (OAM copy) to reduce the impact of failed routing detection on each JR instruction.

deltabeard avatar Oct 16 '23 17:10 deltabeard