Problem with DMA_doVramFill

SGDK only sub forum

Moderator: Stef

Post Reply
tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Problem with DMA_doVramFill

Post by tryphon » Tue Apr 21, 2020 1:33 pm

I have a problem with DMA_doVRamFill. My plane A starts at VRAM adress 0xC000 with :

Code: Select all

0xC000 : 2108 2108 2108 2108 2108 2108 2108 2108 2108 2108
(2108 means : tile 0x108 with palette 1, no priority, no flips) (If I'm not mistaken, VRAM is little-endian so it should be 08 21 inside).

I want to change those 2108 to 2142, so I do :

Code: Select all

DMA_doVRamFill(0xC000, 10, 0x42, 2);
But I get :

Code: Select all

0xC000 : 4242 2142 2142 2142 2142 2142 2142 2142 2142 2142


I know there's some problem with DMA operations that can miss the first operation. But I thought SGDK did take care of that. I'm using version 1.4 (maybe 1.34, not sure). Is it related ?

Also, do we agree that, if I want to change the 21 to 00, I'll have to do :

Code: Select all

DMA_doVRamFill(0xC001, 10, 0x42, 2);
?

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

Re: Problem with DMA_doVramFill

Post by Stef » Tue Apr 21, 2020 7:39 pm

In fact SGDK just take care about adjusting len but not the way data are written (and it should probably indeed) so currently you have to take care of that yourself. And unfortunately it's not really straightforward to handle that..

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Problem with DMA_doVramFill

Post by tryphon » Tue Apr 21, 2020 11:02 pm

OK, I think I understood the problem.

I looked in source code of DMA_doVRamFill. In fact, the "value" parameter needs to be u8.

Then, when sending the value to data port, you write :

Code: Select all

    *pw = value | (value << 8);
because the 1st word write sends the lower byte to adress, the upper byte to adjacent adress, then the upper byte to subsequent adresses.

But, unless I'm mistaken, it's impossible to fill, say, 4 adjacent cells with, for example, 0x1234 :

DMA_doVRamFill(0xC000, 4, 0x12, 2) will do :

Code: Select all

0xC000 : 1212 12.. 12.. 12..
then DMA_doVRamFill(0xC001, 4, 0x34, 2) will do :

Code: Select all

0xC000 : 3434 1234 1234 1234
The first cell will always be wrong and I'll have to fix it by hand.

So I modified the DMA_doVRamFill function by making value a u16, and sending value to *pw.
Now I can write :

Code: Select all

my_DMA_doVRamFill(0xC000, 4, 0x1234, 2);
my_DMA_doVRamFill(0xC000, 4, 0x3412, 2); // swap is needed
to fill my 4 cells.

Is it the right way to do it or am I missing something ?

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

Re: Problem with DMA_doVramFill

Post by Stef » Wed Apr 22, 2020 7:41 am

tryphon wrote:
Tue Apr 21, 2020 11:02 pm
OK, I think I understood the problem.

I looked in source code of DMA_doVRamFill. In fact, the "value" parameter needs to be u8.

Then, when sending the value to data port, you write :

Code: Select all

    *pw = value | (value << 8);
...
So I modified the DMA_doVRamFill function by making value a u16, and sending value to *pw.
Now I can write :

Code: Select all

my_DMA_doVRamFill(0xC000, 4, 0x1234, 2);
my_DMA_doVRamFill(0xC000, 4, 0x3412, 2); // swap is needed
to fill my 4 cells.

Is it the right way to do it or am I missing something ?
To fill word you indeed need to use step = 2 and do 2 DMA fill operations.
Why i'm using

Code: Select all

value | (value << 8)
is because you need to write a word and depending the destination address it will take the lower or upper byte.
Indeed what we do usually is just a final word write to fix the first wrong write done by DMA fill operation.

So in your case why not just writing a word filling method to make it even more clear:

Code: Select all

DMA_doVRamWordFill(0xC000, 4, 0x3412);
Which internally does 2 DMA fill operations and take care of fixing the first word ?

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Problem with DMA_doVramFill

Post by tryphon » Wed Apr 22, 2020 8:38 am

Because I sometimes do not need to write the upper byte :)

But I wrote a macro doing both write ;)

(I'm never sure when a function is inlined, so I guess macros are faster)

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

Re: Problem with DMA_doVramFill

Post by Stef » Wed Apr 22, 2020 9:00 am

If you use not too old SGDK with recent GCC (6.3) you can be confident about inlining. The LTO optimization does wonder, it even sometime push it a bit too much (making code size a bit large) but so you can safely use fonction for almost everything (as you can see i don't care too much with them in SGDK, sometime i can have up to 4 or 5 depth levels function).

Post Reply