VDP DMA fill in Ballz 3D; not writing fill byte

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Post Reply
Near
Very interested
Posts: 109
Joined: Thu Feb 28, 2008 4:45 pm

VDP DMA fill in Ballz 3D; not writing fill byte

Post by Near » Sat Aug 26, 2017 6:49 pm

So Ballz 3D after the Sega logo sets up a VDP DMA fill operation by writing to the control port, $c00004.

In my emulator, when you start a DMA fill operation, it sets a "wait" flag, which prevents the DMA from running until you later write to the VDP data port, $c00000, which signals the byte to be used for the fill operation in the top eight bits.

However, Ballz 3D never writes to the data port. It instead enters a loop polling ($c00005).d1, or the VDP busy flag, which for higan maps to command.bit(5) or CD5. CD5 stays set because the DMA isn't running.

But I did notice at the very end, that last move.w (a0),(a1) ends up writing to the control port and hitting the commandPending block of code, where I clear the wait flag for VDP DMA copy operations, since there is no need to obtain a fill byte first. If I modify that code to clear the wait flag here, then the game ... gets past this point in code, but the graphics are still garbled all throughout the game.

So my first attempt:

Code: Select all

auto VDP::writeDataPort(uint16 data) -> void {
  io.commandPending = false;

  //DMA VRAM fill
  if(dma.io.wait) {
    dma.io.wait = false;
    dma.io.fill = data >> 8;
    //falls through to memory write
    //causes extra transfer to occur on VRAM fill operations
  }

Code: Select all

auto VDP::writeControlPort(uint16 data) -> void {
  //command write (lo)
  if(io.commandPending) {
    io.commandPending = false;

    io.command.bits(2,5) = data.bits(4,7);
    io.address.bits(14,15) = data.bits(0,1);
    if(!dma.io.enable) io.command.bit(5) = 0;
    if(dma.io.mode == 3) dma.io.wait = false;  //*** change this to if(dma.io.mode >= 2) ***
    return;
  }
  
  //command write (hi)
  if(data.bits(14,15) != 2) {
    io.commandPending = true;

    io.command.bits(0,1) = data.bits(14,15);
    io.address.bits(0,13) = data.bits(0,13);
    return;
  }

  //register write (d13 is ignored)
  if(data.bits(14,15) == 2)
  switch(data.bits(8,12)) {
    ...
  //DMA source
  case 0x17: {
    dma.io.source.bits(16,21) = data.bits(0,5);
    dma.io.mode = data.bits(6,7);
    dma.io.wait = dma.io.mode.bit(1);
    return;
  }

  }
}
My second attempt yields slightly better results ... if I avoid setting $c00004.d1 when DMA WAIT is active, I can now see the "Accolade" logo, but there's still a ton of graphical corruption in-game. Which may well be a separate bug.

Code: Select all

auto VDP::readControlPort() -> uint16 {
  io.commandPending = false;

  uint16 result = 0b0011'0100'0000'0000;
  result |= Region::PAL() << 0;
  result |= (io.command.bit(5) && !dma.io.wait) << 1;  //DMA active
  result |= (state.hcounter >= 1280) << 2;  //horizontal blank
  result |= (state.vcounter >= screenHeight()) << 3;  //vertical blank
  result |= io.interlaceMode.bit(0) ? state.field << 4 : 0;
  result |= vip << 7;
  result |= 1 << 9;  //FIFO empty
  return result;
}
So ... my question is, is this correct behavior? If a game starts a VDP DMA fill operation, it's supposed to block until the fill byte is written to the data port.

A) will a write to the control port possibly clear the wait flag like it does for VDP DMA copy operations? or
B) will $c00004 reads return 0 for d1 (DMA active) when the wait flag is set? or
C) am I totally wrong and is there a third option here?

Ballz 3D trace log: you can't see the values because of reading from (a0), but suffice to say it's setting up and executing a DMA fill operation.

Code: Select all

00267a  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvZnx 00ff125a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00267c  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff125e 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00267e  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff1262 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002680  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff1266 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002682  4e75  rts                         00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
0025ea  3290  move.w  (a0),(a1)           00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff6 00000000
0025ec  6100  bsr     $002684             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff6 00000000
002684  08b9  bclr.b  #$04,($ff125b)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00268c  0829  btst.b  #$01,($c00005)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002692  66f8  bne     $00268c             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00268c  0829  btst.b  #$01,($c00005)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002692  66f8  bne     $00268c             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00268c  0829  btst.b  #$01,($c00005)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002692  66f8  bne     $00268c             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000

Mask of Destiny
Very interested
Posts: 615
Joined: Thu Nov 30, 2006 6:30 am

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Mask of Destiny » Sat Aug 26, 2017 7:32 pm

I think your main problem here is not the subtleties of DMA fill, but instead that this DMA is not a DMA fill at all. It's a 68K->VDP transfer. VDP register $17 gets set to $7F which means that bit 7 is not set, thus indicating a 68K->VDP transfer.

Anyway, I implement DMA fill and the DMA flag as follows:
1) DMA flag reflects CD bit 5, regardless of whether the actual fill has started
2) Rather than a DMA wait flag, I have a DMA run flag. This is set immediately for 68K->VDP and copy (another flag handles whether a read or write is needed on the next external slot), but not for DMA fill.
3) When the last word leaves the FIFO, I check if CD bit 5 is set and if register $17 indicates a DMA fill. If both are true, I enable the DMA run flag so that the fill will start on the next external slot

I can't guarantee this is 100% faithful to hardware, but it does pass all of Nemesis' VDP FIFO testing ROM which does test at least some DMA fill edge cases (though I don't think it looks too hard at the DMA flag returned by the control port).

Near
Very interested
Posts: 109
Joined: Thu Feb 28, 2008 4:45 pm

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Near » Sat Aug 26, 2017 10:53 pm

That block of code is executed multiple times to differing effects.

Code: Select all

  //DMA source
  case 0x17: {
    dma.io.source.bits(16,21) = data.bits(0,5);
    dma.io.mode = data.bits(6,7);
    dma.io.wait = dma.io.mode.bit(1);
    print(hex(cpu.r.pc, 8), "  ", dma.io.mode, " ", dma.io.wait, "\n");
    return;
  }
Prints:

Code: Select all

0000023c  2 1
00002682  1 0
00002682  1 0
00002682  1 0
...
00002682  1 0
00002682  2 1
So the last one is definitely a DMA fill.
3) When the last word leaves the FIFO, I check if CD bit 5 is set and if register $17 indicates a DMA fill. If both are true, I enable the DMA run flag so that the fill will start on the next external slot
Shit. I don't implement the FIFO ;_;

Maybe the fill byte was supposed to be sitting in the FIFO waiting to be pulled in, but since there's no FIFO, it didn't take effect when it was supposed to. Sigh, I'd really like to have FIFO support. Anyone up for a bounty offer on that? ^-^

Mask of Destiny
Very interested
Posts: 615
Joined: Thu Nov 30, 2006 6:30 am

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Mask of Destiny » Sat Aug 26, 2017 11:16 pm

Woops. I did check multiple runs through there, but it initially looked like they were all normal transfers. I guess I didn't look hard enough.
byuu wrote:
Sat Aug 26, 2017 10:53 pm
Maybe the fill byte was supposed to be sitting in the FIFO waiting to be pulled in, but since there's no FIFO, it didn't take effect when it was supposed to.
At least in BlastEm, the FIFO appears to always be empty when Ballz sets register $17 for a DMA fill.

Mask of Destiny
Very interested
Posts: 615
Joined: Thu Nov 30, 2006 6:30 am

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Mask of Destiny » Sat Aug 26, 2017 11:33 pm

Looking into this a bit more, it looks like the instances in which the subroutine at $2610 is called for a DMA fill, it should be called by the subroutine at $25F4. This subroutine ($25F4), pops a word off the stack into the VDP data register before calling the subroutine that checks the DMA flag ($2684). It would appear that either your trace is from one of the non-fill cases or something is causing the wrong subroutine to be called.

Here's the $25F$ subroutine (well really a fragment of a subroutine reached from a bra) for reference:

Code: Select all

ADR_25F4:
	move SR, -(a7)	;25F4
	ori #$700, SR	;25F6
	move.w d2, -(a7)	;25FA
	bsr ADR_2610	;25FC
	move.w (a0), (a1)	;2600
	move.w (a7)+, ADR_C00000.l	;2602
	bsr ADR_2684	;2608
	move (a7)+, SR	;260C
	rts	;260E

Near
Very interested
Posts: 109
Joined: Thu Feb 28, 2008 4:45 pm

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Near » Sun Aug 27, 2017 1:04 am

Looking into this a bit more, it looks like the instances in which the subroutine at $2610 is called for a DMA fill, it should be called by the subroutine at $25F4.
This is not the case, sorry ... here is a trace log from Mednafen hitting this exact case, performing the VDP DMA fill operation. It's the thirteenth time $2680 performs a DMA after reset, and the first to be a DMA fill operation.

https://hastebin.com/raw/huqowupeda

You can see her emulator breaks the loop on the first try.

A full trace log in Mednafen from power-on to past the Accolade logo display never reaches $25f4 once.

Same code from higan:

Code: Select all

137e38  4e75  rts                         00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvZnx 00ff125a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00ffffee 00000000
00267a  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvZnx 00ff125a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00267c  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff125e 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00267e  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff1262 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002680  2298  move.l  (a0)+,(a1)          00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff1266 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002682  4e75  rts                         00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
0025ea  3290  move.w  (a0),(a1)           00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvzNx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff6 00000000
0025ec  6100  bsr     $002684             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff6 00000000
002684  08b9  bclr.b  #$04,($ff125b)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00268c  0829  btst.b  #$01,($c00005)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002692  66f8  bne     $00268c             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
00268c  0829  btst.b  #$01,($c00005)      00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
002692  66f8  bne     $00268c             00000000 00ff4000 471c0083 00000000 00000000 000094ff 0000ffff 00000018 tS7cvznx 00ff126a 00c00004 00ff9630 00c00000 00c00004 00000722 00ff2868 00fffff2 00000000
<infinite loop>

Mask of Destiny
Very interested
Posts: 615
Joined: Thu Nov 30, 2006 6:30 am

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Mask of Destiny » Sun Aug 27, 2017 1:17 am

That's not how this game runs in BlastEm. I don't have the equivalent of trace logs, but for this specific question my debugger will suffice:

Code: Select all

ADDFE: bne #-396 <ADC74>
>b 2680
68K Breakpoint 0 set at 2680
>com 0
Enter commands for breakpoing 0, type end when done
>>p/x (a0).w
>>c
>>end
>b 2600
68K Breakpoint 1 set at 2600
>c
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 977f
Continuing
(a0).w: 9780
Continuing
68K Breakpoint 1 hit
2600: move.w (a0), (a1)
Essentially, I set a breakpoint on 2680 with a command to print out the first word of what (a0) is pointing at and then I set a second breakpoint at 2600 (immediately after the call to 2610). You can see that the very first instance in which (a0) points to a register write indicating a DMA fill, the second breakpoint is hit immediately after. I continued this procedure until I got in game and the results were the same. Every time a fill was indicated, that breakpoint was hit immediately after.

Are you sure Mednafen is actually doing a fill here? I don't see how you can determine that from the trace log you linked.

Near
Very interested
Posts: 109
Joined: Thu Feb 28, 2008 4:45 pm

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Near » Sun Aug 27, 2017 3:06 am

Well then we are at an impasse ;_;

If I had the ability to produce a 68K trace log of instructions like in Mednafen and higan through BlastEm, then I could go line by line to find out where higan diverges and work to fix that. But I don't see an option to produce trace logs in your emulator :(

> Are you sure Mednafen is actually doing a fill here? I don't see how you can determine that from the trace log you linked.

I am not 100% certain, but I perfectly match the trace log once interrupts are omitted (timing's a real bitch. I still have almost no understanding of 68K timing, and it seems Mednafen runs about 30-40% higher IPC than higan does.)

It would be quite the bug if somehow the thirteenth transfer somehow flipped a bit in RAM to turn a regular DMA into a fill DMA. But, stranger things have happened, so I won't rule it out.

Anyway, once again let me just say thank you very much for taking the time to investigate this, provide feedback, and help me out. It's extremely appreciated, and I hope one day I can return the favor. The same goes for all of you here ^-^

Sik
Very interested
Posts: 939
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Sik » Sun Aug 27, 2017 1:32 pm

Wild guess: some 68000 instruction is being emulated wrong (or possibly an edge case e.g. with the flags).

Also don't trust too much mednafen regarding timings, it's not exactly an accurate emulator =P
Sik is pronounced as "seek", not as "sick".

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by r57shell » Mon Aug 28, 2017 12:53 am

byuu wrote:
Sat Aug 26, 2017 6:49 pm
So ... my question is, is this correct behavior? If a game starts a VDP DMA fill operation, it's supposed to block until the fill byte is written to the data port.
In case if I get question right: it will not block M68k, and it will not block M68k during fill.
There is no reason for blocking.
M68k blocked with M68k->VDP transfer just because DMA holding BUS for read access cycles.
And it never release it until end of operation.
But fill doesn't require any M68k reads, so it doesn't need to hold BUS.
Sik wrote:
Sun Aug 27, 2017 1:32 pm
Also don't trust too much mednafen regarding timings, it's not exactly an accurate emulator =P
At least found by me bug in Mednafen timings is wrong PAL HV Counters.
It's somewhere in bugs section in his forum.
It was reported more than half of year, and still not fixed.
Image

Near
Very interested
Posts: 109
Joined: Thu Feb 28, 2008 4:45 pm

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Near » Tue Aug 29, 2017 3:33 am

That's not it, no. Let's ignore Ballz 3D and presume a test ROM:

We set up for a VDP DMA fill operation and set CD5, but then we don't write the fill byte. And there's no FIFO slots available to pull it from, the FIFO is totally empty.

Instead, we poll the VDP status bit 1 (DMA) waiting for it to be zero, in a tight loop.

What happens on a real system in this case? Will the system hang because the status bit 1 (DMA) is always set? Will the status bit not get set until we write the fill byte to the data register? Something else?

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Re: VDP DMA fill in Ballz 3D; not writing fill byte

Post by Eke » Tue Aug 29, 2017 8:40 am

byuu wrote:
Tue Aug 29, 2017 3:33 am
That's not it, no. Let's ignore Ballz 3D and presume a test ROM:

We set up for a VDP DMA fill operation and set CD5, but then we don't write the fill byte. And there's no FIFO slots available to pull it from, the FIFO is totally empty.

Instead, we poll the VDP status bit 1 (DMA) waiting for it to be zero, in a tight loop.

What happens on a real system in this case? Will the system hang because the status bit 1 (DMA) is always set? Will the status bit not get set until we write the fill byte to the data register? Something else?
The former. DMA busy flag get set as soon as CD5 (command bit 5) & DMA enable flag are set. It's cleared when DMA is finished (i.e after fill data has been written to DATA port and all internal write cycles have been processed by VDP) or (presumably, I personally did not verified it) when DMA is cancelled (by clearing CD5 or disabling DMA before any data got written to DATA port).

When DMA source (register 0x17 bits 6-7) is set to internal Write FIFO (i.e "DMA Fill"), an additional DMA pending flag is set on CTRL port write if FIFO is empty and is cleared on the next data write. More likely, what really happens in hardware is that, when the source of DMA is the internal FIFO, DMA process is made pending until FIFO empty flag changes from 0 to 1. It is not sure if any write that disable DMA or clear CD5 would also clear DMA pending but that's apparently not the case (see this post from Nemesis)
Nemesis wrote:Now on to CD5. CD5 has a similar function to CD4, but it relates specifically to DMA operations. One thing you need to understand about CD5 is that it can only ever be modified externally by a control port write if the DMA enable bit is set (reg 1, bit 4). If DMA enable is cleared, the state of CD5 will be retained whenever the command code register is modified. Note that I said retained, not cleared. If you have a pending DMA fill just waiting on a data port write to kick it off, and you then clear the DMA enable bit and attempt to rewrite the same command data you wrote to setup the DMA fill, but this time leave CD5 unset, CD5 will still be set afterwards, and a DMA fill operation will still be triggered when you perform a data port write. The absolute only effect the DMA enable bit ever has is to enable or disable control port writes being able to modify the current state of CD5.
I therefore see a potential issue with the code snippets you posted

Code: Select all

if(io.commandPending) {
    io.commandPending = false;

    io.command.bits(2,5) = data.bits(4,7);
    io.address.bits(14,15) = data.bits(0,1);
    if(!dma.io.enable) io.command.bit(5) = 0;
    if(dma.io.mode == 3) dma.io.wait = false;  //*** change this to if(dma.io.mode >= 2) ***
    return;
  }

Code: Select all

//DMA source
  case 0x17: {
    dma.io.source.bits(16,21) = data.bits(0,5);
    dma.io.mode = data.bits(6,7);
    dma.io.wait = dma.io.mode.bit(1);
    return;
  }
Writing DMA source register does not cause DMA Fill pending flag to be set, CTRL port write that sets CD5 to trigger DMA does. Also, in the above code, setting up the source for DMA Copy actually set that pending flag as well (which conveniently get cleared here when DMA Copy is triggered through CTRL port write but that's still incorrect).

I would change that code to :

Code: Select all

if(io.commandPending) {
    io.commandPending = false;

    io.command.bits(2,4) = data.bits(4,6);
    io.address.bits(14,15) = data.bits(0,1);
    if (dma.io.enable) io.command.bit(5) = data.bit(7);
    if((io.command.bit(5)) && (dma.io.mode == 2)) dma.io.wait = true; // probably not 100% correct and should be replaced by a test on FIFO empty flag 0->1 transition in DMA fill loop
    return;
  }
and

Code: Select all

//DMA source
  case 0x17: {
    dma.io.source.bits(16,21) = data.bits(0,5);
    dma.io.mode = data.bits(6,7);
    return;
  }

Post Reply