If someone cared to test (and had a flash cart to do it with), it should be simple enough to set up a test that would have an interrupt trigger just after the CB prefix is read, and then watch the address bus to see if the next memory access is to the stack (to push PC) or to fetch the next instruction, and have your program look at the pushed F register to check for unused bits being set.

Quote:

If I had to make a wild guess, I'd guess that it would finish executing the CB instruction instead of handling the interrupt. This is just a wild guess.

I did a quick test with something like this:

Code:

ld a, $F0 ei swap a

The result is: it runs swap a normally, then handles the interrupt. The PC pushed to the stack points to the instruction following swap a.On a Z80, this technique can be used to reveal prefix opcodes, but here it just handles swap a as usual.

I'll add this test ROM to the mooneye test suite once I tidy up things a bit and verify it on all devices.

Quote:

If CB flag is in the status flags (and POP itself doesn't clear it), the NOP should be interpreted as RLC B, so B will be 3 now.

Mooneye GB test acceptance/bits/reg_f confirms that the low bits of F are not usable. Also, the test I mentioned above would show something special in F if CB would be a status flag

Just some comments about the questions on your "emulation accuracy" page.

Quote:

What happens if the CPU accesses memory during OAM DMA?

I believe someone tested this and found that on the DMG, reads (presumably including opcode fetches) return the byte currently being DMAed. On the GBC, external WRAM (i.e. $C000-$DFFF) is on a separate physical bus from the cartridge slot, probably because of the WRAM bankswitching. If you read WRAM during DMA it has the same effect as on the DMG, but you can apparently run code from ROM normally while DMAing from WRAM (the Wizardry Famicom remakes do this--they don't bother copying their OAM DMA routine to $FF80) There are probably some limitations to executing code in parallel with DMA; the Wizardry games still do a 160-cycle delay loop after triggering DMA.

I've never seen any test results for writes during OAM DMA, or whether OAM DMA automatically suppresses interrupts.

Quote:

What is the exact behaviour of EI?

On a real Z80 (and I believe an 8080 as well), "EI's effect is delayed one cycle" is not true so much as "EI actually disables interrupts until after the next instruction" The reason is to ensure that the sequence "EI; RET" is atomic. If you put a hundred EIs in a row, no interrupts can occur between any of them. You should test whether this is true on the GB as well.

On a real Z80, prefix instructions are the same: no interrupt can occur between the prefix and the instruction it's modifying (the 8080 doesn't have any prefix instructions). This is almost certainly true on the GB as well, otherwise chaos would ensue (you could never safely use a CB instruction any time an interrupt could possibly happen)

Quote:

What is the exact timing of PUSH rr?

It's not surprising that PUSH has an extra internal delay that POP doesn't. Remember that the GB, like other 8080-family CPUs, has a "full" stack: SP points to the last item pushed. So PUSH has to decrement SP first to generate the address for the write, whereas POP can immediately read memory while incrementing SP in parallel. The 6502 family has an "empty" stack, and pops take one more cycle than pushes do--exactly the opposite of the 8080 family.

Quote:

What does MBC1 do if you request a ROM bank number higher than what the cartridge supports?

MBC1 only has five data pins; it can't see the top three bits of the data bus at all. That's why ROMs bigger than 4 MBit need a second register to select the upper bank bits. So a data value of 32 will mirror to 0 in the MBC and trigger the "0 actually selects 1" behaviour, but a data value of 16 on a 2 Mbit ROM, or 8 on a 1 Mbit ROM will mirror to 0 in the ROM and won't be converted to 1. The MBC doesn't "know" how big the ROM is; smaller ROMs just leave the upper address lines of the MBC unconnected.

Likewise MBC2 only has four data pins; that's why its internal battery RAM is arranged in nybbles, and why it only supports up to 2 Mbit ROMs.

Also, MBC1 is only connected to A15, A14 and A13 of the cartridge bus, and MBC2 is only connected to A15, A14 and A8-A0. So MBC1 registers are mirrored over spans of $2000 bytes, and MBC2 registers are mirrored over spans of $100 bytes (you can select a ROM bank by writing to $0100-01FF, $0300-03FF, $0500-05FF, etc.) The reason most monochrome GB games write to $2100 to switch ROM banks is to be compatible with either MBC1 or MBC2.

re those bus timing diagrams: in case it isn't obvious, the reason why accesses to $8000-9FFF don't show any bus activity is that VRAM is on a separate bus on the GB (on the 'Pocket and everything afterwards it's built right into the CPU)

DMG:13-bit address bus and 8-bit data bus to VRAM16-bit address bus and 8-bit data bus to WRAM and the cartridge slot$FF80-FFFE internal to the CPU

GBP:Unconnected external VRAM address and data bus (maybe it can be enabled and the internal VRAM disabled somehow?)16-bit address bus and 8-bit data bus to WRAM and the cartridge slotVRAM and $FF80-FFFE internal to the CPU

GBC:15-bit address bus and 8-bit data bus to WRAM (the upper 3 bits come from the bank select register)16-bit address bus and 8-bit data bus to the cartridge slot onlyVRAM and $FF80-FFFE internal to the CPU

GBA:WRAM moved inside the CPU as well. The only external RAM on the GBA is the big slow work RAM (which isn't usable in GBC mode)

One thing I've never been sure of is what actually is at FEA0-FEFF. It's only marked as "unusable" in documents, but what happens if you try to use it? Some have suggested it partially mirrors OAM.

Also, is FFFF actually within HRAM or is it separate? Can it be accessed during DMA?

No idea about FEA0-FEFF, I doubt it's an OAM mirror though.

FFFF is a memory-mapped register, like everything from FF00 to FF7F. I don't see why it wouldn't be accessible during OAM DMA (it's been discovered that accessing FF46 during DMA restarts the DMA) though some of the registers might have weird side effects.

You know about the OAM corruption hardware bug with 16-bit inc/dec instructions, right? Instructions that don't even perform memory accesses can corrupt OAM, suggesting that the CPU and PPU parts of the die aren't as well segregated as one might expect.

Just some comments about the questions on your "emulation accuracy" page.

Thanks! The page is very out of date so I already have answers to many of the questions, but I don't mind discussing these things and sharing knowledge

Quote:

I believe someone tested this and found that on the DMG, reads (presumably including opcode fetches) return the byte currently being DMAed. On the GBC, external WRAM (i.e. $C000-$DFFF) is on a separate physical bus from the cartridge slot, probably because of the WRAM bankswitching. If you read WRAM during DMA it has the same effect as on the DMG, but you can apparently run code from ROM normally while DMAing from WRAM (the Wizardry Famicom remakes do this--they don't bother copying their OAM DMA routine to $FF80) There are probably some limitations to executing code in parallel with DMA; the Wizardry games still do a 160-cycle delay loop after triggering DMA.

Yes, I've confirmed this as well. Basically, if you DMA stuff from the cartridge bus and the CPU wants to read stuff at the same time, the DMA wins and both the DMA and CPU see a byte from the current DMA source address. This applies regardless of whether it's an opcode fetch or a load.

Quote:

I've never seen any test results for writes during OAM DMA, or whether OAM DMA automatically suppresses interrupts.

I'm pretty sure I've checked that interrupts are not suppressed in any way. But I don't think I've tried writes...And I need to publish test ROMs for all these things. I've got sooo many unpublished test ROMs named oam_hell1, oam_hell2, oam_hell3, etc.

Quote:

On a real Z80 (and I believe an 8080 as well), "EI's effect is delayed one cycle" is not true so much as "EI actually disables interrupts until after the next instruction" The reason is to ensure that the sequence "EI; RET" is atomic. If you put a hundred EIs in a row, no interrupts can occur between any of them. You should test whether this is true on the GB as well.

Unfortunately, this seems to be untrue on the GB based on a test ROM I wrote. EI doesn't disable interrupts, so given an EI sequence, the interrupt happens between the second and third EIs.

Quote:

It's not surprising that PUSH has an extra internal delay that POP doesn't. Remember that the GB, like other 8080-family CPUs, has a "full" stack: SP points to the last item pushed. So PUSH has to decrement SP first to generate the address for the write, whereas POP can immediately read memory while incrementing SP in parallel. The 6502 family has an "empty" stack, and pops take one more cycle than pushes do--exactly the opposite of the 8080 family.

Aha! I never thought about this, but it makes perfect sense.

Quote:

FFFF is a memory-mapped register, like everything from FF00 to FF7F. I don't see why it wouldn't be accessible during OAM DMA (it's been discovered that accessing FF46 during DMA restarts the DMA) though some of the registers might have weird side effects.

I've confirmed that it's accessible as usual. What do you mean exactly mean with "accessing FF46 during DMA restarts the DMA"? Do you mean writing or also reading? Writing indeed restarts the DMA, although the behaviour during the first DMA cycle is slightly different.

I've also thought about $FFFF, and I don't see any reason why it would have to be a separate register. It doesn't really make a difference in emulation, but I find it completely plausible that it's just the last byte of high RAM. After all, all the bits are accessible unlike in the IF register.

Did you notice the logic analysis directory under tests in the mooneye-gb repository? I've done some logic analysis on the Game Boy hardware, and you might be interested in things like the write and read timings in the external bus.

Is there any possibility you can do something like this with the SNES? Or has someone already done it (maybe nocash?)

The SNES CPU is a lot closer to a standard 65816 than the GB is to a standard Z80, but it has a rather different bus from a 65816 (two address buses, separate /RD and /WR strobes instead of RD/WR) and I'm curious what the timings are, especially for DMA (which uses both address buses and the single data bus)

We have some SNES logic analyzer traces from the repair effort with Poot36. It's not all 58-ish signals, but it is 32 of them.

Those are very interesting, thanks for pointing them out. It looks like "FastROM"/3.58MHz cycles have a 50% duty cycle (/RD or /WR is asserted 3 master clocks after the address is put on the bus), and "SlowROM"/2.68MHz cycles stretch the phase in which /RD or /WR is asserted by 2 master clocks (and, for read cycles, presumably the CPU delays latching the data by the same amount).

Unfortunately those traces are missing /PARD and /PAWR (the signals for the "B-bus" or $21xx address range), and as far as I can tell none of them shows any DMA operations (not that you could tell what was going on in DMA without both sets of signals...)

Also there's the little fact that they're traces from a defective CPU...

There's 25 different traces; Numbers 8 and up do have PARD and PAWR. Listings 12, 13, and 15 seem to show DMA.

The defect only appeared to be that the PLB and PLD instructions corrupted the stack pointer; I don't think there's any reason to believe that would affect timing.

Yeah, I see the DMA in listing 15 now. Looks like DMA cycles aren't quite the same as SlowROM cycles. In a SlowROM cycle /RD or /WR is asserted for 5 cycles out of 8, but in a DMA cycle /RD and /PAWR are asserted for only 4 cycles out of 8 (and it looks like they're asserted simultaneously, which was the main thing I was curious about. I wonder how byuu came up with that 'two stage pipeline' nonsense...)

Here's the relevant section of listing 15 annotated with what's going on during an 8-byte general-purpose DMA transfer:

Who is online

Users browsing this forum: No registered users and 1 guest

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum