Giter Site home page Giter Site logo

Comments (21)

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024 2

Very cool. Thanks for reporting! I've set up a new test case exploiting the undocumented ECS feature (more precisely: the ECS Denise feature. The Agnus type doesn't matter, because Agnus only handles the vertical DIW).

A500 (OCS Denise):

minmax3_A500_ECS

A500+ (ECS Denise):

minmax3_A500+

The difference in both images results from this code fragment which will trigger the DIW stop logic on machines with a SuperDenise or Lisa chip:

        dc.w	$5681,$FFFE  ; WAIT 
	dc.w    DIWSTOP,$2c02
	dc.w    DIWHIGH,$0000
	dc.w	$5701,$FFFE  ; WAIT 
	dc.w    DIWHIGH,$2100
	dc.w    DIWSTOP,_DIWSTOP

	dc.w	$5881,$FFFE  ; WAIT 
	dc.w    DIWSTOP,$2c03
	dc.w    DIWHIGH,$0000
	dc.w	$5901,$FFFE  ; WAIT 
	dc.w    DIWHIGH,$2100
	dc.w    DIWSTOP,_DIWSTOP 

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024 2

Simple test case running in vAmiga 2.4:

Bildschirmfoto 2024-01-04 um 15 56 24

Sprite DMA is blocked by expanding the DDF window temporarily. As vAmiga works right now, the sprite data registers keep their old value during the blocking period.

Tomorrow, I'll run the test case on a real machine. I expect it to behave differently based on a hardware-design point of view. Keeping the old value would likely require some extra logic.

from vamiga.

emoon avatar emoon commented on May 25, 2024 1

Without knowing anything about what is going on in the demo (but knowing Amiga in general) my guess would be that it's a "stray" sprite showing up for whatever reason.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024 1

More findings:

The demo starts DDF very early at $18, thus blocking DMA for all sprites except for sprite 0 (which cannot be blocked). 2 bitplanes are enabled which blocks the red cycle for sprite 7:

Bildschirmfoto 2024-01-04 um 13 24 07

For sprites 1 to 6, the corresponding cycles are also blocked. However, this does not cause any harm because their SPRxPTR is correctly set. For Sprite 7, initialization is missing.

In case a sprite's DMA cycle is blocked, the current code does nothing, i.e., the old sprite register value is kept.

        if (busOwner[pos.h] == BUS_NONE) {

            if (sprdma()) {
                
                // Read in the next data word (part B)
                auto value = doSpriteDmaRead<nr>();
                denise.pokeSPRxDATB<nr>(value);
                
            } else {

                busOwner[pos.h] = BUS_BLOCKED;
            }
        }

TODO: Write a test case to check if bitplane data is copied into the register rather than keeping the old value.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

Just did a little code review. Before this bug can be properly fixed, the following function needs to be made timing-sensitive (like setDIWSTRT and setDIWSTOP already are):

void
Denise::setDIWHIGH(u16 value)
{
    trace(DIW_DEBUG, "setDIWHIGH(%x)\n", value);

    if (!isECS()) return;

    // 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
    // -- -- H8 -- -- -- -- -- -- -- H8 -- -- -- -- --
    //     (stop)                  (strt)

    diwhigh = value;

    hstrt = LO_BYTE(diwstrt) | (GET_BIT(diwhigh,  5) ? 0x100 : 0x000);
    hstop = LO_BYTE(diwstop) | (GET_BIT(diwhigh, 13) ? 0x100 : 0x000);

    if (hstrt > 0x1C7) hstrt = INT16_MAX;
    if (hstop > 0x1C7) hstop = INT16_MAX;

    // Inform the debugger about the changed display window
    debugger.updateDiwH(hstrt, hstop);
}

TODO:

  1. Write some timing tests for register DIWHIGH.
  2. Factor out the timing-related functionality from setDIWSTRT and setDIWSTOP to separate functions.
  3. Call the new function from setDIWHIGH.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

One issue of setDIWHIGH was that it didn't check for the invalid trigger positions 0 and 1. In fact, this shielded an OCS bug, namely this one, mentioned in the EAB thread earlier.

After fixing this, things got worse from the outside because the demos's splash screens are now gone. To get the DIW logic 100% correct, it should probably be handled event-driven (via the event scheduler). I need to consider whether it's worth doing, as it would slow down emulation a bit.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

Summing up:

  1. DIW emulation is more accurate now. vAmiga now passes minmax3 in ECS mode:
Bildschirmfoto 2024-01-03 um 13 30 45
  1. The graphics bug reported by @mras0 (flickering black stripes) has a different cause. It has nothing to do with DIW logic. Interestingly, there is nothing special going on during the faulty demo scene. Just bitplane DMA inside the main display area and some Blitter DMA in the lower part:
Bildschirmfoto 2024-01-03 um 13 24 59

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

my guess would be that it's a "stray" sprite showing up for whatever reason.

Yes, indeed! After disabling sprite drawing with the following hack, it looks perfect.

template <Resolution R> void
Denise::drawSprites()
{
    // REMOVE ASAP
    wasArmed = false;

from vamiga.

emoon avatar emoon commented on May 25, 2024

Cool. Thanks for confirming :)

So it might be that the sprite DMA has been left on by accident then and when horizontal scrolling a screen on Amiga (at least on OCS) the last sprite (and half of the second last) can't be used because the extra DMA needing for the offscreen fetching. So it might be that sprite data that shows up for some reason.

If that isn't the case it might be that the sprite that shows up ends up pointing on stale data somewhere and depending on how the memory is initialized it may end up showing some data or not showing it.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

More findings: Culprit is indeed sprite 7. With an additional trace statement in here...

template <isize nr> void
Agnus::executeFirstSpriteCycle()
{
    if (pos.v == sprVStop[nr]) {

        sprDmaState[nr] = SPR_DMA_IDLE;

        if (busOwner[pos.h] == BUS_NONE) {

            // Read in the next control word (POS part)
            if (sprdma()) {
                
                auto value = doSpriteDmaRead<nr>();
                trace(true, "executeFirstSpriteCycle %ld %u\n", nr, value);
                agnus.pokeSPRxPOS<nr>(value);
                denise.pokeSPRxPOS<nr>(value);
                
            } else {

                busOwner[pos.h] = BUS_BLOCKED;
            }
        }

... the following output is produced:

[2564] ( 25, 21) 05209A  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 0 0
[2564] ( 25, 25) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 1 0
[2564] ( 25, 29) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 2 0
[2564] ( 25, 33) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 3 0
[2564] ( 25, 37) 05209A  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 4 0
[2564] ( 25, 41) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 5 0
[2564] ( 25, 45) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 6 0
[2564] ( 25, 49) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 7 3587
[2565] ( 25, 21) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 0 0
[2565] ( 25, 25) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 1 0
[2565] ( 25, 29) 05209A  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 2 0
[2565] ( 25, 33) 05209A  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 3 0
[2565] ( 25, 37) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 4 0
[2565] ( 25, 41) 052092  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 5 0
[2565] ( 25, 45) 05209A  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 6 0
[2565] ( 25, 49) 05209A  0 BCBSDA 4020 37C0 Agnus:508 executeFirstSpriteCycle 7 54280

Bogus values are written into SPR7POS. Interestingly, the DMA slots for sprite 7 are not blocked by bitplane DMA. Needs further investigation...

from vamiga.

emoon avatar emoon commented on May 25, 2024

Interestingly, the DMA slots for sprite 7 are not blocked by bitplane DMA.

I can't remember what actually happens on the original hardware in this case. It might be that fetched bitplane graphics ends up as a sprite.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

Just run the test on both an A500 and an A500+. Unexpectedly, vAmiga does the right thing:

blocked1_A500

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

At least I have gotten a better understanding of what's going on. The faulty scene has a Copper list that resets SPRxPTR for all sprites, but sprite 7:

Bildschirmfoto 2024-01-05 um 10 38 38

SPR7PTR still contains the value used in the previous scene. From now on, SPR7PTR is freely running, thus using everything as position and data that is found in memory.

Bildschirmfoto 2024-01-05 um 10 39 10

It doesn't crawl through uninitialized memory, though. Thus, it is still unclear why the stray sprite does not show up on a real machine.

from vamiga.

emoon avatar emoon commented on May 25, 2024

You don't happen to have a Action replay for you Amiga? That way you could investigate the value of the data on the original hw.

from vamiga.

mras0 avatar mras0 commented on May 25, 2024

If DMA isn't enabled for sprite 7 then the pointer value won't increase. In WinUAE I can see SPR7PT stays $33004.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

I've modified my test case above to only enable two bitplanes. This steals the second sprite cycle and leaves the first one enabled. Because only SPR7DATA is written now (and SPR7DATB is skipped), the sprite data for data register B should end up in SPT7DATA in every other line. This should visually stretch the sprite vertically, which is precisely what happens in vAmiga:

Bildschirmfoto 2024-01-05 um 16 37 38

On a real machine, however, the result is identical to what we see for four bitplanes enabled (which steals all sprite cycles).

Therefore, I think I know what's going wrong in vAmiga:

  • In vAmiga, a sprite DMA cycle is skipped if and only if this cycle is actually used by bitplane DMA.
  • On a real machine, I suppose, sprite DMA is skipped after bitplane DMA has started, regardless of whether the bus is free at at a specific sprite cycle or not.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

Part of the sprite logic:

Bildschirmfoto 2024-01-05 um 17 29 18

Not 100% sure, but the BPRUN signal could be the one that decides whether a sprite DMA cycle is skipped or not.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

Blocking sprite DMA slots w.r.t. BPRUN fixes the issue. Stray sprites are gone.

from vamiga.

mras0 avatar mras0 commented on May 25, 2024

Yeah, I'm not sure how the logic works, but yes Agnus blocks sprite fetches if bitplanes need them (or is supposed to). Apparently there's an OCS bug related to that though:

"- sprite DMA vs bitplane DMA off-by-one fix. Second sprite control was stolen by bitplane DMA even if slot was free but next slot was used by bitplane. (ECS Agnus)" (example: https://eab.abime.net/showthread.php?t=75094)

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

The eab article talks about an undocumented OCS hardware bug, but the bug is not explained? At least I didn't find any infos.

In the meantime, I've also improved my test case: blocking4. It enables all 7 sprites and shifts the DDF window in small steps across the sprite DMA area:

A500 ECS:

blocked4_A500_ECS

A500 OCS:

blocked4_A500_OCS

Latest vAmiga (dev branch) passes the ECS test:

Bildschirmfoto 2024-01-06 um 10 44 39

It fails the OCS test though:

Bildschirmfoto 2024-01-06 um 10 44 22

Interestingly, vAmiga shows a DDF window error, independent of the sprite mismatches The first three bars in the extended areas to the left are too short.

from vamiga.

dirkwhoffmann avatar dirkwhoffmann commented on May 25, 2024

Update:

  • vAmiga has no DDF window error. The too-short bars are due to my new DIW code, which is still buggy (border is displayed in red in the photo below).

  • I think I know what the "OCS bug" is:

Bildschirmfoto 2024-01-06 um 11 37 19

Summing up:

  • My test cases back up my assumption that the BPRUN signal takes away sprite DMA slots (as seen in the Agnus schematics).
  • OCS has a timing issue on the BPRUN line. The sprite logic sees BPRUN going up one cycle too early. E.g., if bitplane DMA starts at $18, sprite DMA is already blocked at $17 which takes away the second sprite DMA cycle for sprite 0. This can be seen on the OCS photo at the marked position:

blocked4_A500_OCS_Kopie

Sprite 0 exhibits "zebra stripes", indicating that the second sprite DMA cycle is stolen. In theory, this should not happen because sprite 0 was meant to be unblockable by the hardware designers. In ECS Agnus, they have fixed the timing of the BPRUN line, which fixes the bug.

As always in science (OK, this is not really science, but anyway...), these are only hypotheses waiting to be refuted.

from vamiga.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.