Lesson A3 - Simulating Z80 functionality for the GBZ80

preview_player
Показать описание
The Gameboy processor isn't a true Z80, and has many commands missing, however we can use macros to simulate the missing commands, so we can port Z80 code to the GBZ80 easily!

As always, this Video lesson matches the text lesson on my website, and you can get the source code as well...

If would like to support my channel and ongoing 8-bit game development, please consider backing me on patreon:
Рекомендации по теме
Комментарии
Автор

Here are some comments and suggestions for optimizations if you ARE interested. Other instructions can be extrapolated from these.

z_ex_sphl: I don't think there's a nuch more optimized way of doing it, but keep in mind that this version is not interrupt safe because it leaves some values open to being overwritten by the return address if an interrupt happens at that exact time.

z_ex_dehl: Kind of obvious, but the inner push/pop is a time waster.
push hl
ld l, e
ld h, d
pop de

z_ldi: You can use the load and increment operation instead of load and then increment. (The exact syntax used for this instruction in your assembler may vary.)
push af
ld a, [hl+]
ld [de], a
inc de
dec bc
pop af

z_halt: It doesn't skip the byte, but repeats that byte. So an instruction may be executed twice, or become an argument to itself. For example, the value 3E would be read as 3E 3E if the bug was active, and would create ld a, $3E

z_ld_iy_plusn_a: This instruction could be done something like this, again using the load and increment instruction.
push hl
push af
ld hl, r_iyl
ld a, [hl+]
add \aoffset
ld l, a
ld h, [hl]
jr nc, .nocarry\@
inc h
.nocarry\@
pop af
ld [hl], a
pop hl

z_inc_iy: could be done by incrementing the value in place
push hl
ld hl, r_iy
inc [hl]
jr .nocarry\@
inc hl
inc [hl]
.nocarry\@
pop hl


z_ld_hl_from: There's a pattern for this kind of load once again using the load and increment instruction. This is 2 bytes shorter and 2 instruction cycles/8 machine cycles faster than your current code. (Since GB instructions always take multiples of 4 machine cycles, cycle times are often calculated as "instruction cycles" or "nop cycles".)

ld hl, \addr
ldi a, [hl+]
ld h, [hl]
ld l, a

z_ld_ix: Using binary logic would probably work and be safer than remainder division. try something like this. Again, subject to exact assembler syntax. Your assembler most likely will NOT use square brackets for indirection, for example.

push af
push hl
ld hl, r_ixl
ld a, (\value)&$FF
ld [hl+], a
ld [hl], (\value>>8)&$FF
pop hl
pop af

This one might be faster. Can't be bothered to do the cycle calculations now. Doesn't use and consequently doesn't save AF. Only increments L, which is safe as long as the low and high byte are on the same 256 block. (Which you can always decide them to be.)
push hl
ld hl, r_ixl
ld [hl], (\value)&$FF
inc l
ld [hl], (\value>>8)&$FF
pop hl

z_exx: That is a monster! Maybe you can do something like: push all; do a (perhaps partially or whollly unrolled) xor swap with the shadow register map; pop all.

Another big optimization would be to put all the emulated registers in the HRAM region. That way they can be accessed using the ldh opcode which is 1 byte shorter and 1 instruction cycle faster.

Gameboygenius
Автор

So i cannot understand what each hex value does to a ram or register. I cannot understand how the machine interprets this as english, other than that 'i know what the opcodes do.'

tylercolburn
join shbcf.ru