• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

Archived

This topic is now archived and is closed to further replies.

Arek the Absolute

GBA- Waiting for DMA

12 posts in this topic

I am officially stumped. What''s the best way to wait for a DMA transfer to finish? I know you can adjust when it starts, but let''s say I''m telling it to start immediately. Now, what seems to be happening is it''s going further into the program without waiting for DMA to finish. I figure I could probably fix this with a simple while loop or something, but for the life of me I can''t find any way to tell when DMA is finished. Is there any way to track how much it''s copied, or when it''s finished...? -Arek the Absolute
0

Share this post


Link to post
Share on other sites
Can anyone at least tell me if my theory is reasonable? If I use DMA to fill the screen buffer, for instance, the fill color overlaps some of the lines I draw afterward. If I don''t fill the screen, there''s no problem. Is this DMA taking time after I set its registers? And is there anything I can do about it?

-Arek the Absolute
0

Share this post


Link to post
Share on other sites
To be honest I am not sure what exactly you are trying to do. If you are trying to do this in 3D be careful and test it on Boycott Advance since it is the only legal emulator because you could crash just unlikly

Anyway try this link and see if it help but I am still unsure what you are trying to accomplish.

http://www.doc.ic.ac.uk/~mac/manuals/hpux-manual-pages/hpux/usr/man/man7/framebuf.7.html

Good Luck and I will keep an eye on the thread because I would like to know if I am wrong or not.
0

Share this post


Link to post
Share on other sites
My code specifically:


  

#include "smlib.h" /* include basic libraries, functions, etc. All taken from StaringMonkey''s examples, with DMA.h taken from Dovoto''s tutorials*/

#define BUTTON(key) (!(*KEYS & key)) // macro for key input
u16* videoBuffer = (u16*)0x6000000; // for writing to screen
void DMA_FillScreen(void* color); /* prototype for clear screen function*/
int x = 0; int y = 0; // upper left corner of square

int main(void){

SetMode(MODE_3 | BG2_ENABLE); /* set to mode 3, enable BG2*/

// main game loop
while(1){

/* fill the screen in white, the function is defined below */
u16 color[] = {0xFFFF};
DMA_FillScreen((void*)color);

// adjust position according to key input
if (BUTTON(KEY_UP)){y--;}
if (BUTTON(KEY_DOWN)){y++;}
if (BUTTON(KEY_LEFT)){x--;}
if (BUTTON(KEY_RIGHT)){x++;}

/* draw the edges of the square using a simple Brasenham line algorithm */

Line(x,y,x,y+30,0x0FFF);
Line(x,y,x+30,y,0x0FFF);
Line(x+30,y,x+30,y+30,0x0FFF);
Line(x,y+30,x+30,y+30,0x0FFF);

// wait for the screen to finish drawing

while(REG_VCOUNT < 160){}
}
}

void DMA_FillScreen(void* color){
REG_DMA3SAD = (u32)color;
REG_DMA3DAD = (u32)VideoBuffer;
REG_DMA3CNT = 240*160 | DMA_ENABLE | DMA_TIMEING_IMMEDIATE | DMA_16 | DMA_SOURCE_FIXED | DMA_DEST_RELOAD;
}



Now, if you compile it and run it, you don''t see anything other than a white screen. You can move the square down, however, and it begins to appear. It''s pretty obvious that either something is overlapping the square, or that the line functions aren''t working. However, if you comment out the DMA_FillScreen, the problem doesn''t happen! That means clearly something is overlapping the square. The only thing that accesses the screen other than the calls to Line is DMA_FillScreen. The only way I can see this is happening is if DMA still finishes filling the screen AFTER the lines are drawn. How can that be prevented?

All those functions, constants, etc can all be found on http://www.thepernproject.com either in StaringMonkey''s demos, or in Dovoto''s. (And I''m pretty sure I only used DMA.h from him)

-Arek the Absolute
0

Share this post


Link to post
Share on other sites
I always thought DMA halted the CPU, so your program stalls until it is completed... But in your situation that doesn''t appear to be the case. Are you testing on real hardware or emulator?
Is the VCOUNT register declared as volatile? Else GCC might optimize out the while loop that waits for vblank, causing your screen to tear...
Maybe it''s got something to do with the line drawing algorithm you use. Maybe you could try plotting some pixels yourself, see if the same is happening there.
As a final soluting (but only if nothing else helps, because it''s more of a hack) you could use an interrupt. They signal when a DMA transfer finishes. But that''s not the optimal solution.
Well, if all else fails you can always try the gbadev.org mailing list. That''s where the pros are. Good luck,

Jasper
0

Share this post


Link to post
Share on other sites
I''m not sure if this is right, but your using the flag DMA_DEST_RELOAD in the DMA register. Wouldn''t this cause the destination (in this case the video buffer) to revert to its original value after the DMA transfew is finished? So, shouldn''t you be using the flag DMA_DEST_INCREMENT instead?
0

Share this post


Link to post
Share on other sites
Aprosenf:
Thanks for pointing that out, and it is a good point. Unfortunately, I''ve tried it on all the possible settings, and that just happened to be the last one that I had it on when I posted the code. Thanks tho, I''d forgotten about that.
JasperW:
Man, I wish DMA did halt the CPU, but it seems I have no such luck. I''ve now tested it personally on VisualBoy Advance, BoyCott Advance, and on a real-life GBA, with the same results all around.
REG_VCOUNT is declared as volatile, but thanks anyway. And same with plotting pixels myself. They don''t show up in certain regions (top third or more of the screen) And even if that were the case, I have no idea what I''d be able to change. As I said earlier, the problem doesn''t happen if I don''t fill the screen using DMA. I''ll think about that interrupt, but as you say, that''s a last resort. I think I''ll take your advice on that mailing list.

Thanks a lot anyway, all around! Speak up if you think of anything! (At least I don''t feel stupid for not being able to figure it out anymore. )

-Arek the Absolute
0

Share this post


Link to post
Share on other sites
Hey,
I don''t know a solution to your problem, but from everything I''ve heard/read, DMA does halt the CPU and doesn''t release it until the copy is finished. Perhaps your code error is somewhere else?

--Nairb
0

Share this post


Link to post
Share on other sites
I was thinking about it some more when I realized that DMA transfer is taking up one hell of a lot of CPU cycles. You''re transferring 240 x 160 = 38400 16 bits values. I don''t know how long the transfer takes, but since you are using DMA16 at least 2 cycles per 16 bits and possibly more because of the wait states of the VRAM (I don''t know if the source address is in IWRAM or EWRAM, but if it''s in EWRAM it also adds 2 cycles per 16 bits).
This means you''re doing at least 38400 * 2 cycles = 76800 cycles (and probably more) per vblank while you''ve only 83776 cycles. So the internal clock might get messed up.
Try filling only one third of the screen or switch to 32 bits DMA (twice as fast). Let me know what your findings are. Good luck,

Jasper
0

Share this post


Link to post
Share on other sites
I think you may be on to something, JasperW. If I only fill one third of the screen, there''s no overlapping problem. Just a lot of old data in the bottom two thirds of the screen. If I switch to 32 bits, it draws every other pixel as black... Which means if I tell it to copy (240*160/3) pixels, it fills two thirds of the screen, but every other pixel is black instead of white. If I try to fill 240*160 pixels in 32 bit pieces, the overlapping problem still occurs. It would seem then, that the problem doesn''t occur in smaller DMA transfers. Unfortunately, I don''t really know how to solve that. If I use for loops, it takes way too long. And DMA''s doing this... Anyone have any ideas on ways around this mess?

-Arek the Absolute
0

Share this post


Link to post
Share on other sites
The black/white pixel problem can probably be solved by making color an u32 instead of an u16 and assigning it the value 0xFFFFFFFF (two pixels at a time). Or did you already do that? I thought 32 bits DMA to VRAM is possible but I''m no expert

Then on to the problem of the duration of the DMA. It seems nearly impossible to solve. One 32 bits transfer takes at a standard of 2 cycles plus the wait states of the memory you''re reading from and writing to.

You should make sure the color variable is in IWRAM (zero wait states) rather than EWRAM (2 cycles) but GCC might already do that (if not I don''t know how to do it). Make sure it isn''t defined as a constant and residing in ROM (lots of wait states). The wait states to video memory are variable so I don''t really know how much time they take but I''ll assume it''s about 2 cycles (same as EWRAM).

So the optimal 32 bit transfer takes standard + read + write = 2 + 0 + 2 = 4 cycles. You''ll need 240 * 160 / 2 = 19200 transfers, which mean 76800 cycles to fill the whole screen. Seeing that you have 83776 you should be able to make it in theory (!= practice). It does how leave you with very little time to do anything else...

You might want to consider switching to mode 4 or 5 where you have a backbuffer so you don''t have to worry too much about filling the screen in time. Or create a backbuffer for mode 3 in EWRAM, but that''s a lot of pain and effort. Other than that I really don''t know what to do. Well, that''s about it from me. Good luck,

Jasper
0

Share this post


Link to post
Share on other sites
Thanks for your help! I don''t know if I''ll ever be able to deal with Mode 3, but thanks for helping me with that. At least I know what''s going wrong, if not any way to solve it. I guess, however, if I ever figure things out I''m honor bound to write a tutorial, right? Don''t get your hopes up. I''ll probably be going to Mode 4 soon enough. Heh. Thanks, and BTW, I did get the u32 color[] = {0xFFFFFFFF}; thing, and copying does now work properly. Thanks!

-Arek the Absolute
0

Share this post


Link to post
Share on other sites
There was some stuff about this on the GBADev mailing list (www.gbadev.org) a while ago. If I remember correctly it was eventually decided it wasn''t possible to DMA an entire 15bpp screen in the vblank period. You could however transfer the new in image line by line in the hblank period (at the end of each line) much in the same way as the GBC worked with the camera.
0

Share this post


Link to post
Share on other sites