Okay, here's an updated test with source! Please check that it still works, in case I've done something stupid like post the odd ROM instead of the even one.
The ROM should be run with a standard NES controller in both ports. The expected output is that the screen should remain black until right is pressed on either controller. If it fails, it should do so almost instantly, producing a white screen. PAL NES does not have DPCM conflicts so this test is not meaningful on PAL.
For quick reference, here's the important code:
Code: Select all
lda #OAM
sta $4014 ; ------ DMA ------
ldx #1 ; even odd <- strobe code must take an odd number of cycles total
stx controller1 ; even odd even
stx $4016 ; odd even odd even
dex ; odd even
stx $4016 ; odd even odd even
read_loop:
lda $4017 ; odd even odd EVEN <- loop code must take an even number of cycles total
and #3 ; odd even
cmp #1 ; odd even
rol controller2, x ; odd even odd even odd even (X = 0; waste 1 cycle and 0 bytes for alignment)
lda $4016 ; odd even odd EVEN
and #3 ; odd even
cmp #1 ; odd even
rol controller1 ; odd even odd even odd
bcc read_loop ; even odd [even]
Yes, it really is that simple. (Do note that I read the controller bits in big-endian order; most other implementations I've seen use little-endian. Conversion between the two should be a simple exercise.)