Is DMA Fill buggy?

For anything related to VDP (plane, color, sprite, tiles)

Moderators: BigEvilCorporation, Mask of Destiny

Post Reply
Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Is DMA Fill buggy?

Post by Miquel » Tue Jul 11, 2017 11:08 am

I have tried a lot of permutations but always in certain conditions there are some random writes to other VRAM locations. I remember that this bug have been occurring since the beginning of development. Even using a past version of SGDK code. Tested on accurate emulators and real hardware, just the same. Code is executed in vertical exception, so no overwrite to dma registers can happen. I also check DMA busy bit before using any DMA function or writing to VRAM.
I followed recommendations inside manual:
- word destination address write
- final write must use ram (tested several writes for what is worth)

For example when I do next DMA Fill:
addrs: 0xE800
size: 0x800
data: any
increment: 1

It writes an unexepted byte to @ 0xF001 of VRAM.

Is DMA Fill faulty or I'm doing some thing wrong?
Last edited by Miquel on Tue Jul 11, 2017 7:02 pm, edited 5 times in total.
HELP. Spanish TVs are brain washing people to be hostile to me.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Is DMA Fill buggy?

Post by Stef » Tue Jul 11, 2017 11:35 am

Older version of SGDK probably had it wrong because of the weird internal implementation of DMA fill, but in laters ones i tried to improve that so DMA fill usage is more user friendly... Still probably i didn't got it perfectly right :-/ Looking at the dma fill method, i think i didn't handled all cases...

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Is DMA Fill buggy?

Post by Miquel » Tue Jul 11, 2017 12:14 pm

Yes, I remember when you/SGDK tried to do 2byte fill and then move it to 1byte fill only. Just then is when I tried both versions of SGDK code. Random writes happened anyway (in my ROM at least).
HELP. Spanish TVs are brain washing people to be hostile to me.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Is DMA Fill buggy?

Post by Stef » Tue Jul 11, 2017 1:57 pm

Does it happen on emulators as well or only on real hardware ?

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Is DMA Fill buggy?

Post by Miquel » Tue Jul 11, 2017 2:23 pm

It occurs on real hardware (an asian MD1) and on Regen v0.97D. Exactly the same.

But currently I'm not using SGDK code for DMA fill.
HELP. Spanish TVs are brain washing people to be hostile to me.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: Is DMA Fill buggy?

Post by Chilly Willy » Tue Jul 11, 2017 5:17 pm

Doesn't the "must write to ram" mean the CPU must write WORK RAM? That's why nearly every DMA routine you see finishes with the code pushing a value on the stack, then popping that to the VDP - pushing the value on the stack does that write to ram.

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

Re: Is DMA Fill buggy?

Post by Mask of Destiny » Tue Jul 11, 2017 6:31 pm

DMA fill has a really hacky implementation in the VDP. The word you write is written normally and then after that, the DMA engine fills with one byte of that word. If you write another word before the fill is complete, that write will take place as normal and then the fill will continue with a byte from the new word.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Is DMA Fill buggy?

Post by Miquel » Tue Jul 11, 2017 6:41 pm

Chilly Willy wrote:
Tue Jul 11, 2017 5:17 pm
Doesn't the "must write to ram" mean the CPU must write WORK RAM? That's why nearly every DMA routine you see finishes with the code pushing a value on the stack, then popping that to the VDP - pushing the value on the stack does that write to ram.
Done, I force the compiler to do it from memory thought an asm instruction:

Code: Select all

void VideoDMAFill( u16 destination, u16 size, u8 value )
{
	USING_CTRLPORT;
	USING_CTRLPORT32;
	// Wait for last dma end
	while( g_vpdCtrlPort & VDP_DMABUSY_FLAG ) ;
	// Setup DMA operation (VRAM FILL)
	SET2REGISTERS( 15, 1, 23, 0x80 );
	// Setup DMA length
	SETREGISTER( 19, ((u16u8)size).byte0 );
	SETREGISTER( 20, ((u16u8)size).byte1 );
	// Setup destination
	*vpdCtrlPort = 0x4000 | (destination & 0x3FFF);
	//*vpdCtrlPort = 0x0080 | (destination >> 14);
	asm volatile ( "move.w %1, %0" : "=m" (*vpdCtrlPort) : "m" (0x0080 | (destination >> 14)) );
	//g_vpdDataPort = ((u16)value) | (((u16)value) << 8);
	asm volatile ( "move.w %1, %0" : "=m" (g_vpdDataPort) : "m" (((u16)value) | (((u16)value) << 8)) );
}
Not sure wich one is the one, so I do it on both cases (address and data). But same resuts.
Mask of Destiny wrote:
Tue Jul 11, 2017 6:31 pm
DMA fill has a really hacky implementation in the VDP. The word you write is written normally and then after that, the DMA engine fills with one byte of that word. If you write another word before the fill is complete, that write will take place as normal and then the fill will continue with a byte from the new word.
The DMA Fill works as expected but also does 1 (even addrss) o 2 (odd addrss) more byte writes to another location, with the same data you provided for the DMA Fill.
HELP. Spanish TVs are brain washing people to be hostile to me.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: Is DMA Fill buggy?

Post by Miquel » Tue Jul 11, 2017 7:37 pm

I think I got it:
- In DMAFill function you should decrement size by one.
- DMAFill has "endianness problems", so in a word (16bits) it writes first the upper byte.
HELP. Spanish TVs are brain washing people to be hostile to me.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Is DMA Fill buggy?

Post by Stef » Tue Jul 11, 2017 9:03 pm

Something like that indeed, exactly what i try to address with SGDK implementation.

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

Re: Is DMA Fill buggy?

Post by Mask of Destiny » Tue Jul 11, 2017 9:30 pm

Miquel wrote:
Tue Jul 11, 2017 6:41 pm
The DMA Fill works as expected but also does 1 (even addrss) o 2 (odd addrss) more byte writes to another location, with the same data you provided for the DMA Fill.
It's not the fill that's doing the extra writes. The write that triggers the fill works as normal and then the fill continues afterwards. 2 extra bytes are always written from that initial word, but depending on the initial address and the auto-increment settings one of those bytes will just get overwritten by the fill.
Miquel wrote:
Tue Jul 11, 2017 7:37 pm
- In DMAFill function you should decrement size by one.
In most cases this is true. You should also avoid doing a DMA fill to an odd address as it will generally behave strangely.
Miquel wrote:
Tue Jul 11, 2017 7:37 pm
- DMAFill has "endianness problems", so in a word (16bits) it writes first the upper byte.
It's not so much that DMA fill has endianness problems as it is that the FIFO is word oriented, but VRAM is only byte wide and DMA fill is byte oriented. When you perform the data write that triggers the fill, the following happens:
  1. Value written along with current value of VDP address and cd regs are written to the FIFO
  2. Address register is incremented by the value in the autoinc field
  3. MSB of the word in the FIFO is written to the saved address
  4. LSB of the word in the FIFO is written to the saved address ^ 1
  5. Actual fill starts, MSB of the word in the FIFO is written DMA length times to address ^ 1, with address incremented by the autoinc value after every write
It's possible I have steps 3 and 4 reversed, but I'm pretty sure I have the rest correct. IIRC, that FIFO test ROM Nemesis put together tests DMA fill pretty extensively and the above list is based on my implementation in BlastEm which passes all those tests.

The above explains why it appears that there's an additional write when you try to do a fill to an odd address. For instance, if you try to do a fill to address 1
  1. Address of 1 is saved in FIFO
  2. Address register is incremented by 1, and is now 2
  3. MSB of the word in the FIFO is written to 1
  4. LSB of the word in the FIFO is written to 0
  5. DMA fill starts with an address of 2, so neither of the bytes written by the initial word are overwritten
Hoppefully that's clear

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

Re: Is DMA Fill buggy?

Post by Eke » Tue Jul 11, 2017 10:10 pm

The 'issue' is that VRAM byte writes (used by VRAM fill and copy DMA) actually occur to VRAM address ^ 1 so you can get unexpected results depending on start address, DMA length and increment alignments.

In your case, when VRAM address reaches F000H, last write occurs at F001H instead of F000H. I think some games read last VRAM address value before DMA then modify/write it back manually after DMA for this reason.

Post Reply