lgblgblgb / xemu

Emulations (running on Linux/Unix/Windows/macOS, utilizing SDL2) of some - mainly - 8 bit machines, including the Commodore LCD, Commodore 65, and the MEGA65 as well.
https://github.com/lgblgblgb/xemu/wiki
GNU General Public License v2.0
201 stars 31 forks source link

MEGA65/DMA: If I/O flag for destination is set, I/O registers will be written only #366

Closed ghost closed 1 year ago

ghost commented 1 year ago

Using DMA copying, it's quick and easy to fill the VIC2 I/O registers for sprites. So I decided to place the sprite pointers at $cff0 right before and include them in the copying process. So I set the I/O flag in the DMA job so that the I/O area is visible to the controller and copy data to $cff0 - $d02e.

As it turns out, when the I/O flag is set, only the I/O area is written and the rest is ignored. On hardware all bytes will be written.

using version: Xemu/MEGA65 20220613133247 master

lgblgblgb commented 1 year ago

Thanks for the report UPDATE: next post

~As far as I am aware, that is the desired behaviour. Ie, if I/O bit is set, I/O is accessed. There is no "mixed mode" ie the DMA cannot see the memory map as your CPU does, DMA only sees physical addresses. By selecting I/O you limit DMA to deal with the I/O only (regardless the rest of the address), otherwise the physical addresses counts (regardless what CPU sees at a given addresses). I mean, I/O means the I/O registers, what usually you can access "with legacy access" at $DXXX.~

~Why do you think is it a bug? Have you got any experience that a real MEGA65 behaves differently? If so, please give me some example code which demonstrates the problem, since it does not make any sense for me at this point at least. Honestly, at this point, I cannot even imagine how should work otherwise, this is the only sane behaviour. Thanks!~

lgblgblgb commented 1 year ago

BREAKING NEWS

Hmm, very interesting, it seems MEGA65-core VHDL does not agree with me, but with you:

-- redirect memory write to IO block if required
-- address is in 256ths of a byte, so must be shifted up 8 bits
-- hence 23 downto 20 instead of 15 downto 12 
if dmagic_dest_addr(23 downto 20) = x"d" and dmagic_dest_io='1' then
    memory_access_address(27 downto 16) := x"FFD";
    memory_access_address(15 downto 14) := "00";
    if hypervisor_mode='0' then
        memory_access_address(13 downto 12) := unsigned(viciii_iomode);
    else
        memory_access_address(13 downto 12) := "11";
    end if;
end if;

I will discuss it with Paul, since it's probably not what C65 would do, and MEGA65 "should be" C65 compatible. But anyway, if it turns out the way MEGA65 wants to do, surely I will modify emulation too, just this is not how it should work (but surely my opinion does not count too much, but only how it's implemented).

https://discord.com/channels/719326990221574164/782759365064917065/1072812266199728158

ghost commented 1 year ago

@lgblgblgb First of all, thank you for taking care of this matter.

I wrote a short .prg for this, see the attachment below.

It starts with a sprite with only position registers set, and sprite ptr points to address $0000. By pressing space, the I/O registers and the sprite pointer, located at $CFF0 are updated in one go (single dma job). In Xemu the sprite ptr doesn't change.

Hope that helped.

DMATEST.zip

lgblgblgb commented 1 year ago

@xhl77 Thanks! To be honest, I asked for the test program when I hadn't yet even realized what your problem here was, since "but this is how it should work, and it's not a bug" ;) Then I realized something very strange was going on, and maybe it's a MEGA65-core problem that it implemented this thing incorrectly back to then, as it should be all-I/O or all-memory and not some strange mixed mode. Now I am not even sure on this, that this is how C65 should work (and surely I have no real C65 to check).

Now at least I understand exactly what the problem is. Still, I am not sure what to do, but probably it's better to follow MEGA65 of course, even if it's a core bug there and shouldn't be used that way there either (???). Hmmm.

If MEGA65-core developers decides to handle this problem as bug in the core (so adopt the full memory or full I/O behaviour as a bug fix), then I can revert my changes back to, how Xemu works ... basically right now ;) But till that - if that ever happens! - it's better if I follow MEGA65 let it be a bug or feature ;)

lgblgblgb commented 1 year ago

@xhl77 But one thing is clear, if I were you, I would avoid using this feature to expect memory access too in I/O mode, since though it is how MEGA65-core works now, it's maybe fixed to the all-I/O or all-memory mode later and then your program will break the same way as now with Xemu. Surely, I'll fix Xemu to follow MEGA65-core for now, but my point here, that maybe MEGA65 will fix this problem at one point as well.

ghost commented 1 year ago

Thank you for the clarification. I'll leave it like this for now. If something changes, I can adjust it. I'm working on a long term project so it won't be released anytime soon ;)

lgblgblgb commented 1 year ago

Some DMA related changes have just been pushed into next, including this issue. Note, that I needed more modifications here and there inside the DMA code, so I am not 100% sure, if I introduced some regression as well ... The usual development model applies here, it will be in next for now, and after some weeks/month or so, the accumulated changes in next will be merged into master as a new "stable" release then, if no problem is found in next meanwhile.

@xhl77 Please report back if you find any problems with a new next build (including the fix for this issue, but also potentially anything going wrong which worked before - ie the "regression"). I close this issue now, but if you have anything to report back, don't feel bad to re-open this issue.

Thanks again!