tonioni / WinUAE

WinUAE Amiga emulator
http://www.winuae.net/
549 stars 90 forks source link

Graphics glitch (ECS Agnus, DMA off in the middle of a raster line) #179

Open dirkwhoffmann opened 4 years ago

dirkwhoffmann commented 4 years ago

While playing around with DMACON, I found something weird. I’ve written two test programs that disable DMA in the middle of a raster line:

https://github.com/dirkwhoffmann/vAmigaTS/tree/master/Agnus/DMACON/bplen0

A500 8A:

bplen0_A500_8A

Relevant part of the Copper list:

    dc.w    BPLCON0,(4<<12)|$200

    dc.w    $3001,$FFFE  ; WAIT 
    dc.w    COLOR00, $F00
    dc.w    $3101,$FFFE  ; WAIT 
    dc.w    DMACON,$0100
    dc.w    COLOR00, $000

    dc.w    $3801,$FFFE  ; WAIT 
    dc.w    COLOR00, $F00
    dc.w    $3901,$FFFE  ; WAIT 
    dc.w    DMACON,$8100
    dc.w    COLOR00, $000

    dc.w    $4001,$FFFE  ; WAIT 
    dc.w    COLOR00, $F00
    dc.w    $4181,$FFFE  ; WAIT 
    dc.w    $4181,$FFFE  ; WAIT 
    dc.w    DMACON,$0100
    dc.w    COLOR00, $000

https://github.com/dirkwhoffmann/vAmigaTS/tree/master/Agnus/DMACON/bplen0b

A500 8A:

bplen0b_A500_8A

Relevant part of the Copper list:

    dc.w    $3001,$FFFE  ; WAIT 
    dc.w    COLOR00, $F00
    dc.w    $3101,$FFFE  ; WAIT 
    dc.w    DMACON,$0100
    dc.w    COLOR00, $000

    dc.w    $3801,$FFFE  ; WAIT 
    dc.w    COLOR00, $F00
    dc.w    $3901,$FFFE  ; WAIT 
    dc.w    DMACON,$8100
    dc.w    COLOR00, $000

    dc.w    $4001,$FFFE  ; WAIT 
    dc.w    COLOR00, $F00
    dc.w    $4185,$FFFE  ; WAIT 
    dc.w    DMACON,$0100
    dc.w    COLOR00, $000

In UAE (ECS Agnus, OCS Denise), both test programs looks like this:

Bildschirmfoto 2020-08-02 um 11 49 31

I already did some hackery in my own emulator and managed to reproduce the first image by doing the following:

The second test case is even worse. The picture is shifted by an additional word which means the bitplane pointers have been incremented by 2 in addition to adding the modulos (all bitplane pointers are reset in the VBLANK interrupt handler).

Right now, I have no idea what’s happening here, but I am pretty confident that it is related to when and how the bitplane pointers get modified by an ECS Agnus.

tonioni commented 4 years ago

OCS should work like that, if DMA gets switched on and it was previously switched off during same scanline, state machine jumps directly to "DDFSTOP passed" state. I never did any test programs when I implemented this so there is chance I missed something that isn't visible in any "real" demos.

tonioni commented 4 years ago

Bleh. I reset this flag if display emulation was in line-based mode, I guess just to be sure it does not get stuck in impossible state but it was also accidentally reset when it should not have been... Flag reset removed (and included same extra "jump to ddfstop passed" state to OCS mode) and first test case is correct.

All my statefile test cases still seems to work. (I think one of the tricky ones is Crash landing / Scoopex crack intro)

Not sure about second one. Going to do logic analyzer checks later.

tonioni commented 4 years ago

I didn't bother with logic analyzer (at least not yet) because reason looks quite obvious if you manually adjust position when DMA gets switched off and modify bitplane pattern.

There seems to be two possible results when DMA is switched back on: one "bitplane block" gets DMA'd or two "blocks" gets DMA'd. It seems to depend on distance between DMA off vs BPLDAT1 DMA slot.

tonioni commented 4 years ago

Right, above assumption seems to be correct. Emulation matches real A500 if 2*"blocks" is chosen when DMA ends so that 4 cycle DMA off "cooldown" ends just before next BPL1DAT slot, otherwise choose 1 block.

It seems like whole display state machine gets "stuck" in this situation but DDFSTOP comparator is still active and if DDFSTOP has been detected at least once after DMA gets back on, DMA continues where it was left but active DDFSTOP condition causes it to stop after 1 or 2 blocks.

Display DMA is a total mess to emulate..

dirkwhoffmann commented 4 years ago

Display DMA is a total mess to emulate..

You are so right. It's a nightmare 😣.

tonioni commented 3 years ago

These are now fully emulated and nightmare has finally ended :)

Last few months I have been examining Agnus (pre-production version) and Alice schematics that "leaked" last year and rewrote UAE emulation based on chip logic behavior (blitter, bitplanes and copper is now updated. mostly). Lots and lots of ugly hacks got removed and emulation was greatly simplified. Which is nice :)

Anyway, the reason for this behavior is that if DMA gets switched on while bitplane DMA is active, "ddfstop passed" state gets set. Also if DMA was switched off exactly when "bitplane block" was finished ((sequencer counter & 7) == 7), "ddfstop passed" state gets advanced twice, to state where modulos are added. When DMA gets re-enabled, bpl sequencer counter restarts from zero. Result is scanline that has either 1 or 2 bitplane blocks at the beginning. The rest is blank. This is ECS only because OCS has strange way of deciding ddfstrt/stop limits.

I'll write detailed description of bitplane sequencer features later..

btw, one important chipset feature is that bitplane engine (and everything) is pipelined, in case of bitplane, decision to create DMA request was done 2-4 cycles (ddf/diw decision, bitplane sequencer enable/disable, selected plane to internal RGA bus, internal RGA bus to external RGA bus) before it appears on screen. All this 4 cycle delay and other weird stuff are simply side-effects of internal pipelining.

dirkwhoffmann commented 3 years ago

Awesome news!!!

I'll write detailed description of bitplane sequencer features later..

I'm looking forward to that. That's so valuable for all emulator developers.