gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Bad habits in popular tutorials

#20594 - tepples - Thu May 13, 2004 3:47 pm

Several popular GBA programming tutorials, such as the ones at gbajunkie and Pern Project, are commonly held to teach bad habits. Which are those? I'm thinking about writing at least part of a GBA programming tutorial free of such bad habits.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#20595 - poslundc - Thu May 13, 2004 3:53 pm

The one that constantly gets my goat (as everyone on here probably knows by now) is data being put into header files.

I would like to see a tutorial that shows how to append data as an array in a simple C file with a corresponding header file. It could also talk about using assembly files, binary files, and file systems such as GBFS, but this is the simplest, easiest-to-understand way to include data and it should be made available to newbies.

Dan.

#20605 - mr_schmoe - Thu May 13, 2004 6:04 pm

I would like to see a tutorial on the GBFS. I looked into it once, but it was bit too complicated for me. (Maybe at the time I wasn't well versed enough on the subject to understand.)

#20606 - ScottLininger - Thu May 13, 2004 6:06 pm

The "incorrect" tutorials I learned from (like so many on this forum) were the excellent Pern tutorials.

A new set of up-to-date tutorials would be wonderful. Just keep it SIMPLE. The thing that I loved about the Pern tutorials is that I was able install the devkit and compile the first little game in under an hour. From there, it only took me another couple of hours to build my own crappy game.

Granted, it was all Mode4 without sprites, but it was EASY.

After that, I was hooked, and I've slowly learned the "proper" way to do stuff.

So... if you want to write a "beginner's" tutorial, make sure that it's simple enough for a bonehead like me to figure out. Assume your audience knows VIRTUALLY NOTHING about hardware registers, endian-issues, and the like. And provide some demos that include complete make files that are as idiot proof as possible.

Or, perhaps a better approach would be to write some "intermediate" tutorials that assume you've already gone through the PERN stuff, and now will enlighten us to a little better way.

Either way, it's a good idea. If it's half as good as the FAQ, the community would benefit greatly.

#20607 - sajiimori - Thu May 13, 2004 6:07 pm

One word: OAMData.

Ok, another word cuz I can't resist: DMA_TIMEING_...

Edit for elaboration: More than just a misspelling, the choice of "OAMData" as a name for sprite character RAM has caused more than a few confused readers to post here.


Last edited by sajiimori on Thu May 13, 2004 6:28 pm; edited 1 time in total

#20608 - ScottLininger - Thu May 13, 2004 6:11 pm

This one drives me nuts:

TRANSPERENT

#20609 - wintermute - Thu May 13, 2004 6:23 pm

objcopy can also be used to attach binary data which saves having to convert to a c file at all. You can actually link the raw data directly using the -b binary option when linking i.e. :-
Code:

 arm-elf-gcc -Wl,-b,binary,binfile.dat <rest of objects>


my pet peeves with the average 'tutorial'

1. #including binary files as converted arrays.
2. using batch files full of dos commands to build projects.
3. using Nmake for gcc based projects.
4. using ld directly to link projects then specifying several paths to libraries in order to compensate.
5. gba defines that need to be cast in order to use them.
6. inline asm without clobber lists.
7. having conditional elements in the crt0.
8. Spelling mistakes.
9. poor grammar.

#20610 - CyberSlag5k - Thu May 13, 2004 6:24 pm

Quote:
Ok, another word cuz I can't resist: DMA_TIMEING_...


Heh, I noticed that one too.
_________________
When you find yourself in the company of a halfling and an ill-tempered Dragon, remember, you do not have to outrun the Dragon...

#20614 - mr_schmoe - Thu May 13, 2004 6:44 pm

Two things.

First:
Quote:
3. using Nmake for gcc based projects.

What would you recommend for that?

Second:
Quote:

8. Spelling mistakes.
9. poor grammar.

That's just lazyness on the programmers part. But I agree wholeheartedly.

#20619 - poslundc - Thu May 13, 2004 8:09 pm

ScottLininger wrote:
This one drives me nuts:

TRANSPERENT


How about the TIMMER registers?

I had a field day going through and correcting all the spelling mistakes in my gba.h...

Dan.

#20624 - tepples - Thu May 13, 2004 10:08 pm

Here's my plan, indexed to correspond to wintermute's list:

0. Publish each chapter of the new tutorial under a free documentation license (probably Creative Commons by-sa) so that others can fix my bugs without having to rewrite the whole hoover-dam thing from scratch.
  1. I'll use a bin2s tool, which outputs assembly language (.s) source code, because those are less likely to tempt users into #include "data.c".
  2. I too will start off with batch files until I introduce GNU Make in an early chapter.
  3. You have no chance to survive; GNU Make your time.
  4. Link only with gcc or g++. Ganon uses ld.
  5. My header file, which names registers differently from the purported official header to avoid even the slightest appearance of infringement, includes the proper casts. It also includes macros done the right way.
  6. I won't teach inline assembly language, as I feel it's just as fast to call a subroutine as to handle GCC's horrid clobber syntax. Besides, the reader is already used to adding .s files to the project from fix-plan[1].
  7. I'll use the standard GBA crt0 and link script that come with the GCC distribution I choose (probably devkitARM).
  8. I have won the school spelling bee three times, and I know to go to Google if a word looks wrong.
  9. I don't have a problem with grammar either.
And yes, I'll introduce macros in the header file that make modes 3 and 5 ridiculously easy to use, as if they were just a 2D array of pixels.

I will assume familiarity with the C programming language, referring users to the alt.comp.lang.learn.c-c++ FAQ list. How much other familiarity should I assume?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#20629 - poslundc - Thu May 13, 2004 11:29 pm

tepples wrote:
I'll use a bin2s tool, which outputs assembly language (.s) source code, because those are less likely to tempt users into #include "data.c".


I think this is the only thing I really take issue with. Not because the advantages of data in assembly over C aren't apparent, just because I believe having to do anything involving assembly will be intimidating to new users. And they have to get their data into a raw format anyway before they can use bin2s.

I like the idea of teaching C arrays because it is very familiar, is compatible with the famous tools everyone seems to use (less work = more appealing to newbies), and means they'll be less likely to just go and do it the way Pern and GBAJunkie show them how.

I guess my point is: make it easy for them to append the data properly, early on. They can worry about what the best method is later, so long as they aren't screwing around with improper header files.

Quote:
My header file, which names registers differently from the purported official header to avoid even the slightest appearance of infringement, includes the proper casts. It also includes macros done the right way.


*sigh* This is probably the most sensible way to go, although since I'm using the standard DKA header file it'll be a pain to answer questions.

Dan.

#20631 - dagamer34 - Fri May 14, 2004 1:03 am

Maybe dividing up the tutorials in to different levels might help a bit. And a dictionary for common terms is a must. I don't know how many people have asked what an ISR is.
_________________
Little kids and Playstation 2's don't mix. :(

#20634 - MumblyJoe - Fri May 14, 2004 2:40 am

If I can make a suggestion, and I know I will get flamed with "meh dont do it that way" replys but whatever...

instead of:

Code:
#define SOMEREGISTER *(u16*)0xF000000


or

Code:
#define SOMERAM (u16*)0xF000000;


try:

Code:
u16& SOMEREGISTER = *(u16*)0xF000000;


and

Code:
u16* const SOMERAM = (u16*)0xF000000;


And yes I know that one of those is C++ specific and thats why I expect to get flamed. But honestly I prefer to have better type information attached to my constants and pointer, using #defines really is a terrible way to do things. Besides, with a good compiler (and I wont say that gcc is a good compiler) it shouldn't matter.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20637 - sajiimori - Fri May 14, 2004 4:19 am

Quote:

using #defines really is a terrible way to do things.

Maybe you could give a situation where your way is better...?
Quote:

Besides, with a good compiler (and I wont say that gcc is a good compiler) it shouldn't matter.

Even your hypothetical "good compiler" would create a memory object for SOMEREGISTER, and accessing it will involve work.

#20638 - poslundc - Fri May 14, 2004 5:19 am

MumblyJoe wrote:
using #defines really is a terrible way to do things.


Why?

I'm genuinely interested in hearing your reasoning. Because I can't think of a single reason to favour your way, which as sajimori already pointed out requires accessing of a memory object, and also purports to make linking a huge mess for large projects.

Dan.

#20644 - NoMis - Fri May 14, 2004 8:24 am

I think the tutorials are good that way they are, except for the spelling mistakes like TIMMER or TIMEING. But its just an easier way to begin with data included as a header file. I learnd C/C++ in school and therefor know that its bad habbit and wont make it in my real game. But for experimenting and trying the system its quick and easy.
I think that someone who want to programm the gba should have a good understanding of C/C++ first and therefor should already know that its messy.

@ MumblyJoe
I don't think you get flamed. This forum is realy great and you can actualy have a nice diskussion about such things (i know terrible forums where you get flamed bye 5 guy for a simple question and have no chance to diskus something because the forum is full of kiddies).
In my oppinion every programmer has his personal style and if its efficient enough i don't see a problem.

#20646 - Sweex - Fri May 14, 2004 8:40 am

poslundc wrote:
MumblyJoe wrote:
using #defines really is a terrible way to do things.


Why?

I'm genuinely interested in hearing your reasoning. Because I can't think of a single reason to favour your way, which as sajimori already pointed out requires accessing of a memory object, and also purports to make linking a huge mess for large projects.

Dan.


Why? Two reasons why: You cannot put #defines in your watch/variables window when debugging, and the second: It is not typesafe so a bigger chance on weird behaviour!

Now, having sais that, the first reason is less important on GBA as I think most of us aren't using any debugger.
_________________
If everything fails, read the manual: If even that fails, post on forum!

#20647 - Sweex - Fri May 14, 2004 8:41 am

Oh, and I just wanted to say that with the gained experience in general here, it is a great idea to make some now tutorials!
_________________
If everything fails, read the manual: If even that fails, post on forum!

#20660 - poslundc - Fri May 14, 2004 2:50 pm

Sweex wrote:
You cannot put #defines in your watch/variables window when debugging


This is true, but it only means you need to manually know/look up the addresses in memory you wish to debug. This is a tradeoff for not bogging down the elf file with tons of extra symbols that aren't necessary programmatically.

Quote:
It is not typesafe so a bigger chance on weird behaviour!


I don't see how. The compiler should perform the same typechecks on statements involving macro-ed pointers that it does on actual variable objects.

Dan.

#20668 - wintermute - Fri May 14, 2004 4:35 pm

Sweex wrote:

Why? Two reasons why: You cannot put #defines in your watch/variables window when debugging, and the second: It is not typesafe so a bigger chance on weird behaviour!

Now, having sais that, the first reason is less important on GBA as I think most of us aren't using any debugger.


#defines are generally used for the GBA hardware registers so putting them in your watch/variables is unlikely to do what you want.

what's not typesafe about this?

Code:


#define   REG_DISPCNT   *(vu16 *)(REG_BASE + 0x00)
#define   REG_DISPSTAT   *(vu16 *)(REG_BASE + 0x04)
#define   REG_VCOUNT   *(vu16 *)(REG_BASE + 0x06)
#define   BGCTRL      ((vu16 *)(REG_BASE + 0x08))



find me a compiler that won't place 4 bytes in the rodata section for every single one of your definitions.

#20674 - Lupin - Fri May 14, 2004 5:43 pm

Using variables for registers sounds like a joke to me... Not only the 4 wasted bytes is the problem but the slowdown when reading/writing to a register... and you really get no more typesafety since ALL pointers in C will be 32 bit (because of 32 bit addressing), no matter what type of pointer.
I really don't get the advantage of using memory... I think you should take a look into asm and try to understand how it works in hardware and then you will understand what your code will compile to.

wintermute, this is like the first time i see you on the gbadev board :)
_________________
Team Pokeme
My blog and PM ASM tutorials

#20679 - sajiimori - Fri May 14, 2004 6:48 pm

Lupin, don't insinuate that people must not know how compilers work, while in the same breath making an error about the nature of pointers.

Type safety is not just about the size of pointers -- it's also about the size of the objects they point to (and how those objects are handled). The point was that casting immediate values results in the same typesafety as using variables.

#20681 - wintermute - Fri May 14, 2004 9:03 pm

tepples wrote:

1. I'll use a bin2s tool, which outputs assembly language (.s) source code, because those are less likely to tempt users into #include "data.c".


Personally I'd rather see tools that output gcc object files and autogenerated headers - I have no idea why people persist in turning binary data in source code 8 times bigger than the original data only to have the compiler turn it back into binary again. If you have a look at some of the code examples (such as they are so far :) ) you'll see the method I generally use for data. For bigger projects this method combined with GBA crusher http://members.cox.net/jsensebe/gba/GBACrusher.zip is pretty much ideal. DevkitARM also provides a version of GAS which includes the .incbin directive for another alternative.

Quote:

5. My header file, which names registers differently from the purported official header to avoid even the slightest appearance of infringement, includes the proper casts. It also includes macros done the right way.


I can't see any reason to avoid the 'official' names since they are publically available on many sites, including the main documents used by homebrew developers - gbatek & cowbite. The headers in libgba are based largely on those documents and I'd be more than happy to receive feedback on how those could be improved. Ideally I'd like to see libgba become a community effort with contributions from everyone who finds it useful.

#20682 - wintermute - Fri May 14, 2004 9:08 pm

Lupin wrote:
Using variables for registers sounds like a joke to me... Not only the 4 wasted bytes is the problem but the slowdown when reading/writing to a register... and you really get no more typesafety since ALL pointers in C will be 32 bit (because of 32 bit addressing), no matter what type of pointer.
I really don't get the advantage of using memory... I think you should take a look into asm and try to understand how it works in hardware and then you will understand what your code will compile to.

wintermute, this is like the first time i see you on the gbadev board :)


Hi :)

I'm afraid you're a bit misinformed about what the compiler does with the variables that Sweex has suggested using. He's right in that gcc will generate identical code for the register access when defining registers as const but unfortunately additional data is placed in the .rodata section. Understanding asm & looking at the compiler output is a good idea though :)

#20694 - sgeos - Sat May 15, 2004 4:08 am

I'd be happy to read any 'up to date' tutorial. For starters, I'd like to know how to include raw data in a file and muck about with from my code.

-Brendan

#20695 - crossraleigh - Sat May 15, 2004 4:13 am

I do like the pin8gba.h header much more than others I have seen; a tutorial that uses it would be very nice.

I don't have any particular bad habits to point out, but I do have an alternative way to access OAM entries:

Code:
union oam_entry {
   struct {
      u16 y;
      u16 x;
      u16 data_index;
      u16 pad;
   };
   long long options;
};

#define OAM ((volatile union oam_entry*) 0x07000000)

// Initialize a 32x32 16-color sprite at (45,10).
OAM[0].options = OAM_32x32 | OAM_PAL(7) | OAM_PRI(1);
OAM[0].data_index |= OAM_DATA_INDEX_MASK & 16;
OAM[0].x |= OAM_X_MASK & 45;
OAM[0].y |= OAM_Y_MASK & 10;


For me, this is better than the 16-bit attribute method, and should be superior to bitfields in any case. At least in my OAM usage, the options can be determined at compile time, so there is no significant overhead using long long. This method is not ideal, however, for anyone who ? for instance ? is often using H-flip or V-flip.

#20697 - Lupin - Sat May 15, 2004 11:09 am

sajiimori, i am aware that in C the pointer type specifies the size of the object they point to, I just tried to point out that there is no difference in defining the pointer type by using a variable or by using a register because you have to specify the pointer type in both cases, but i think everything got said by now :)
_________________
Team Pokeme
My blog and PM ASM tutorials

#20725 - MumblyJoe - Sun May 16, 2004 2:15 am

OK, I started a tiny argument before about defines and references and just thought I would quickly compile and disassemble some code to show the difference.

Here is the code (i know there was a better way to do conditional defines but whatever):

Code:
typedef volatile unsigned short vu16;

#define USEDEFINE

#ifdef USEDEFINE

#define BULLPOINTER (vu16*)0x6000000

int main()
{


   *BULLPOINTER = 0x0500;

   while(1){}

   return 0;
}

#else

vu16& reference = *(vu16*)0x6000000;

int main()
{


   reference = 0x0500;

   while(1){}

   return 0;
}

#endif


I compiled it with the following options:

Code:
g++ -c -O3 -mthumb -mthumb-interwork -fno-rtti -fno-exceptions -o reftest.o reftest.cpp



When a define is used I get:

[Images not permitted - Click here to view it]

When I use a reference I get:

[Images not permitted - Click here to view it]


So basically take a look and see how it works, I think it is worth the effort and it's never made a speed difference for me, even in loops.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20726 - poslundc - Sun May 16, 2004 3:27 am

Two load operations versus two arithmetic operations? I'll take the arithmetic operations, thank you. Especially when loading from ROM, where you'll be wasting a ton of cycles on cache misses (which slows you down on hardware, not emulation).

Dan.

#20729 - MumblyJoe - Sun May 16, 2004 5:01 am

I see your point poslundc, so I did a little test just out of curiosity (not to argue that I am right). According to several tests I have read, gcc is a shitty compiler compared to alot of them. So I did a quick test with borlands compiler with speed optimisations turned on and its fairly interesting to see how it handled it. Of course this is x86 asm and moving data around in arm differs a bit but you can see what I mean in this code.

With defines:
Code:
   .686p
   ifdef ??version
   if ??version GT 500H
   .mmx
   endif
   endif
   model flat
   ifndef   ??version
   ?debug   macro
   endm
   endif
   ?debug   S "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp"
   ?debug   T "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp"
_TEXT   segment dword public use32 'CODE'
_TEXT   ends
_DATA   segment dword public use32 'DATA'
_DATA   ends
_BSS   segment dword public use32 'BSS'
_BSS   ends
DGROUP   group   _BSS,_DATA
_TEXT   segment dword public use32 'CODE'
_main   segment virtual
   align   2
@_main   proc   near
?live16385@0:
 ;   
 ;   int main()
 ;   {
 ;      #ifdef USEDEFINE
 ;      *SOMEPLACE = 0x500;
 ;   
@1:
   mov eax,100663296
   mov dword ptr [eax],1280
 ;   
 ;      #else
 ;      someplace = 0x500;
 ;      #endif
 ;   
 ;      return 0;
 ;   
   xor eax,eax
 ;   
 ;   }
 ;   
@3:
@2:
   ret
@_main   endp
_main   ends
_TEXT   ends
_TEXT   segment dword public use32 'CODE'
_TEXT   ends
   ?debug   D "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp" 12464 28143
   end


With references:
Code:
   .686p
   ifdef ??version
   if ??version GT 500H
   .mmx
   endif
   endif
   model flat
   ifndef   ??version
   ?debug   macro
   endm
   endif
   ?debug   S "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp"
   ?debug   T "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp"
_TEXT   segment dword public use32 'CODE'
_TEXT   ends
_DATA   segment dword public use32 'DATA'
_DATA   ends
_BSS   segment dword public use32 'BSS'
_BSS   ends
DGROUP   group   _BSS,_DATA
_DATA   segment dword public use32 'DATA'
   align   4
_someplace   label   dword
   dd   100663296
_DATA   ends
_TEXT   segment dword public use32 'CODE'
_main   segment virtual
   align   2
@_main   proc   near
?live16385@0:
 ;   
 ;   int main()
 ;   {
 ;      #ifdef USEDEFINE
 ;      *SOMEPLACE = 0x500;
 ;      #else
 ;      someplace = 0x500;
 ;   
@1:
   mov eax,dword ptr [_someplace]
   mov dword ptr [eax],1280
 ;   
 ;      #endif
 ;   
 ;      return 0;
 ;   
   xor eax,eax
 ;   
 ;   }
 ;   
@3:
@2:
   ret
@_main   endp
_main   ends
_TEXT   ends
_TEXT   segment dword public use32 'CODE'
_TEXT   ends
   public   _someplace
   ?debug   D "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp" 12464 28130
   end


And last using a pointer:

Code:
   .686p
   ifdef ??version
   if ??version GT 500H
   .mmx
   endif
   endif
   model flat
   ifndef   ??version
   ?debug   macro
   endm
   endif
   ?debug   S "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp"
   ?debug   T "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp"
_TEXT   segment dword public use32 'CODE'
_TEXT   ends
_DATA   segment dword public use32 'DATA'
_DATA   ends
_BSS   segment dword public use32 'BSS'
_BSS   ends
DGROUP   group   _BSS,_DATA
_DATA   segment dword public use32 'DATA'
   align   4
_someplace   label   dword
   dd   100663296
_DATA   ends
_TEXT   segment dword public use32 'CODE'
_main   segment virtual
   align   2
@_main   proc   near
?live16385@0:
 ;   
 ;   int main()
 ;   {
 ;      #ifdef USEDEFINE
 ;      *SOMEPLACE = 0x500;
 ;      #else
 ;      *someplace = 0x500;
 ;   
@1:
   mov eax,dword ptr [_someplace]
   mov dword ptr [eax],1280
 ;   
 ;      #endif
 ;   
 ;      return 0;
 ;   
   xor eax,eax
 ;   
 ;   }
 ;   
@3:
@2:
   ret
@_main   endp
_main   ends
_TEXT   ends
_TEXT   segment dword public use32 'CODE'
_TEXT   ends
   public   _someplace
   ?debug   D "C:\Documents and Settings\Dirk Ramrod\Desktop\proof\proof.cpp" 12464 28362
   end


The pointer and ref code is identical here but I understand good compilers can optimise better with references because they cant be changed to point elsewhere.

Anyway, not trying to prove a point just showing that there are other options. In my x86 code the whole difference is 4 bytes in memory and a single instruction that does a fetch. I would allow a little sacrifice like that for nicer code :P

Oh and before anyone says it I know that using defines for conditional compiles so I can show why I don't like defines is kinda ironic :P
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20731 - sajiimori - Sun May 16, 2004 5:50 am

Quote:

In my x86 code the whole difference is 4 bytes in memory and a single instruction that does a fetch.

...which is what we said from the beginning. ;)
Quote:

I would allow a little sacrifice like that for nicer code :P

So it's an aesthetic thing? I like consistency, and if C were powerful enough to do away with the preprocessor I'd gladly do so, but I still can't think of any objective way it's nicer...

BTW, you're talking to a guy whose current favorite language is Lisp (to some fans, the only "beautiful language"), so I definitely consider aesthetically pleasing code an end in itself, even at the expense of efficiency.

#20733 - MumblyJoe - Sun May 16, 2004 10:05 am

sajiimori wrote:
So it's an aesthetic thing? I like consistency, and if C were powerful enough to do away with the preprocessor I'd gladly do so, but I still can't think of any objective way it's nicer...


Well, its kind of an aesthetic thing, but also a very functional thing. I'm too young to have been poisoned by C (joking) and learnt C++. Most C++ experts pick on C's way of doing things alot, I'm a little more liberal though and use some C style things. So functionally I prefer getting variable names in my error messages etc. Also I like the readability of code to be high, and I find defines can mess that up.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20736 - poslundc - Sun May 16, 2004 2:22 pm

MumblyJoe wrote:
So functionally I prefer getting variable names in my error messages etc.


That's a valid choice, but keep in mind that when you are doing GBA programming you are doing hardware programming, and you are using memory-mapped registers, not variables. #define simply keeps your code closer to the true hardware representation; using variables instead adds a layer of abstraction that I find pointless.

Quote:
Also I like the readability of code to be high, and I find defines can mess that up.


Again, I don't see how.

Dan.

#20749 - MumblyJoe - Mon May 17, 2004 1:15 am

poslundc wrote:
Quote:
Also I like the readability of code to be high, and I find defines can mess that up.


Again, I don't see how.


Well lets say I want to move to a new layer of abstraction, such as a class which represents a register. An imaginary example is:

Code:
class Reg
{
    public:
    static void Enable(){control|=0x0001;}
    private:
    static vu16& control;
};
vu16& Reg::control = *(vu16*)0x6000000;


I do this alot, especially with registers that have slightly strange uses, to use a define here I would really have to undefine it after the code to keep my code from having names like _VIDEO___CONTROL and shit like that which I see in tutorials. I far prefer my engine.Background2.Colors(256) over remembering the defines every time, and my code runs pretty damn fast,and the files are small.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20750 - col - Mon May 17, 2004 1:45 am

If you are using c++, this should work, depending on packing etc. i've not fully tested it...

Code:

struct Regs{
   u32 DISPCNT;
   u16 DISPSTAT;
   u16 VCOUNT;
    //etc
};

Regs* const reg = (Regs*)0x4000000;

....then somewhere in your code....

reg -> DISPCNT =  MODE0 | BG0_ENABLE | OBJ_ENABLE | OBJ_MAP_1D;



or if you want to use references:
Code:

struct Regs{
   u32 DISPCNT;
   u16 DISPSTAT;
   u16 VCOUNT;
    //etc
};

Regs& const reg = *(Regs*)0x4000000;

....then somewhere in your code....

reg.DISPCNT =  MODE0 | BG0_ENABLE | OBJ_ENABLE | OBJ_MAP_1D;



this way you get your neat code with no macros, the pointer version costs the same as using #defines, if you use the references version, you only pay the extra 8 bytes once instead of per register.
[EDIT: using references costs per access as pointed out in sajiimoris reply - and the const shouldnt be there in the references version]

Col


Last edited by col on Mon May 17, 2004 2:54 am; edited 1 time in total

#20751 - sajiimori - Mon May 17, 2004 2:16 am

You can't do type& const x; because all references are const (in that you can't change what they refer to). Declaring a reference static should give the compiler the option of optimizing it away, but GCC doesn't do this.
Quote:

...you only pay the extra 8 bytes once instead of per register.

...and then of course each time you access it.

#20753 - MumblyJoe - Mon May 17, 2004 2:22 am

Actually the more I test gcc to see how it is optimising my code the more I am starting to agree that #defines could be good sometimes :P

If only borland made an ARM/Thumb compiler, then we could write some awsome fast shit :P
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20754 - sajiimori - Mon May 17, 2004 2:26 am

Meh... if it's really important, hand code it. ;)

#20755 - col - Mon May 17, 2004 2:42 am

sajiimori wrote:
You can't do type& const x; because all references are const (in that you can't change what they refer to). Declaring a reference static should give the compiler the option of optimizing it away, but GCC doesn't do this.

oops, that was a cut'n'paste error - forgot to take out the const :)
Quote:

Quote:

...you only pay the extra 8 bytes once instead of per register.

...and then of course each time you access it.

ouch - i missed that.
well - i did say i hadn't tested it :)

col

#20767 - f(DarkAngel) - Mon May 17, 2004 12:39 pm

Some ARM asm tutorials say that asl/asr can be freely replaced with lsl/lsr. I've manually found that this is not true (took me ~2 days to find the problem in matrix multiplication http://cvs.sourceforge.net/viewcvs.py/demi/stdgba/src/stdgba_math.S?rev=1.4&view=auto ), and logical shifts seems to be for unsigned values while arithmetic shift is for signed values.
_________________
death scream...

#20768 - wintermute - Mon May 17, 2004 1:11 pm

cue something else that really annoys me - why do so many people feel the need to use <my library name>_bios_<function name>? Then there's people using ARM code all over the place despite it being a recommended practice to use thumb code in ROM.

#20769 - wintermute - Mon May 17, 2004 1:25 pm

further to the #define vs reference debate a quick test of the 3 methods available

first the source

Code:

//---------------------------------------------------------------------------------
typedef   unsigned short int      u16;
typedef   volatile u16         vu16;

#define   REG_BASE   0x04000000

#define   REG_DISPCNT      *(vu16 *)(REG_BASE + 0x00)
static vu16* const DISPCNT = (vu16*)(REG_BASE + 0x00);
static vu16& reference = *(vu16*)(REG_BASE + 0x00);

//---------------------------------------------------------------------------------
static void constval()
//---------------------------------------------------------------------------------
{
   *DISPCNT=0;
}

//---------------------------------------------------------------------------------
static void referenceval()
//---------------------------------------------------------------------------------
{
   reference=0;
}


//---------------------------------------------------------------------------------
static void defineval()
//---------------------------------------------------------------------------------
{
   REG_DISPCNT=0;
}

//---------------------------------------------------------------------------------
int main(void)
//---------------------------------------------------------------------------------
{
   defineval();
   constval();
   referenceval();

   return(0);
}


this was compiled with arm-elf-g++ -O3 -mthumb -mthumb-interwork -fomit-frame-pointer -save-temps and resulted in the following assembly

Code:

   .code   16
   .file   "main.c"
   .section   .rodata
   .align   2
   .type   reference, %object
   .size   reference, 4
reference:
   .word   67108864
   .text
   .align   2
   .global   main
   .code 16
   .thumb_func
   .type   main, %function
main:
   ldr   r0, .L5
   mov   r3, #128
   lsl   r1, r3, #19
   ldr   r3, [r0]
   mov   r2, #0
   mov   r0, #0
   strh   r2, [r1]
   strh   r2, [r1]
   @ sp needed for prologue
   strh   r2, [r3]
   bx   lr
.L6:
   .align   2
.L5:
   .word   reference
   .size   main, .-main
   .ident   "GCC: (GNU) 3.4.0 (mingw special)"


as you can see, the pointer variant & the #define result in identical code. The reference generates an unneeded memory reference and an additional 4 bytes in the .rodata section. My personal preference would be for the #define variant given that I'm a lazy swine and typing an extra * is too much effort :P

#20771 - poslundc - Mon May 17, 2004 2:12 pm

f(DarkAngel) wrote:
Some ARM asm tutorials say that asl/asr can be freely replaced with lsl/lsr.


ASL and LSL assemble into the same thing. I suppose theoretically an arithmetic left-shift would produce a carry output whereas a logical left-shift wouldn't, but on the ARM this is handled by the CPSR-update flag.

ASR and LSR are mightily different, as ASR sign-extends whereas LSR only pads with zeros. Most mathematical applications, as you observed, require the use of ASR whereas most bit-juggling applications use LSR.

Dan.

#20773 - f(DarkAngel) - Mon May 17, 2004 4:09 pm

wintermute wrote:
cue something else that really annoys me - why do so many people feel the need to use <my library name>_bios_<function name>?


This is a C convention. There's no namespace in C.
The reason for using this not "feeling the need", this method reduces the chance for name conflicts, especially when using differrent libraries in the same program, probably not considering whether if you're annoyed or not.
_________________
death scream...

#20828 - Cearn - Tue May 18, 2004 2:35 pm

Turning back to peeves for a while, I was pretty annoyed when I found out that the matrix PERN gives for rotation/scaling doesn't do what one would expect it too, and got pretty pissed when I found the bad matrix just about everywhere I looked. If you plan on including something about affine functions, <i>please</i> make sure it gives a proper matrix.

On including binary data: as much as I can see why this would be a good thing, I've always wondered just how to do this since it's not an easy thing to find in manuals. A particular question would be: what'd be the name of the variable/reference/point whatever that one would use to find it? In assembly you can use a label, but somehow I doubt that'd work for pure binary files. Related to this is the question of what you actually got in the binary file, what's the width/height bpp of the data? Would the binary have a header, or should you just remember all that? Also, in the event that the conversion to GBA data went awry, browsing throught C or assembly is a lot easier than through pure binary. But of course, converters never fail, right? :P

Slightly off-topic, what kind of form were you planning on using (html, pdf, doc (only kidding) )? I'm asking because the more I use html for Tonc, the more I wish I had something that would keep all my (numbered) references and equations in check.

#20848 - wintermute - Tue May 18, 2004 6:35 pm

the docs you want for objcopy are here :- http://sources.redhat.com/binutils/docs-2.15/binutils/objcopy.html

admittedly they're not stupendously clear if you haven't used objcopy much. I tend to use a make macro for dealing with raw to object file conversion.

Code:

define bin2o
   cp $(<) $(*).tmp
   $(OBJCOPY) -I binary -O elf32-littlearm -B arm \
   --rename-section .data=.rodata,readonly,data,contents \
   --redefine-sym _binary_$*_tmp_start=$*\
   --redefine-sym _binary_$*_tmp_end=$*_end\
   --redefine-sym _binary_$*_tmp_size=$*_size\
   $(*).tmp $(@)
   echo "extern const u8" $(*)"[];" > $(*).h
   echo "extern const u32" $(*)_size[]";" >> $(*).h
   rm $(*).tmp
endef

#---------------------------------------------------------------------------------
%.o   :   %.pcx
#---------------------------------------------------------------------------------
   @echo $(notdir $<)
   @$(bin2o)


what this does is redefine the standard _binary_<filename>_<extension>_start style labels to <filename>_start, <filename>_end and <filename>_size and generate a header with the appropriate externs. By default objcopy places things in the data section, --rename-section takes care of that & moves things to the .rodata section where they belong.

Ideally you want some sort of header with your binary data to make things a bit easier otherwise you're pretty much stuck with doing things manually. You can of course write tools which will ouput directly to an elf object and allow a little more flexibility.

#20897 - LOst? - Wed May 19, 2004 2:14 pm

I know one thing I hate so much.

Don't spell INTERRUPT:

INTERUPT
INTRUPT
INTERPT

I can't stand the registers having bad spelling.


Also, I must say that I want the game to operate with HBlank and VBlank correctly. Not just some void function with if conditions.

And the flags for setting interrupts that have been used, it should be something that's taken care of automatically. It's just confusing and annoying since I can't seem to understand what it's good for.

No more for-loops for loading sprites and graphics. I know it seems more easy to do it that way, but it's so crappy. Memcpy or DMACOPY it instead. It's the samr thing and everyone understands it.

Be sure to give out tools that work. Not just that worked with this sample, like some crappy PCX2SPR

And also, I hate this thing so much. All tools use different ways of storing data. Some is in header files. Some is in C files with externs. And most of them use u16 types but doesn't include the type. And some of them never add the last line that GCC complain about, making it hard to see if you got errors.

There is really much that I get annoyed at, but we should be happy there is a lot of people that have done this for us!

#20901 - Cearn - Wed May 19, 2004 3:10 pm

wintermute wrote:
The docs you want for objcopy are here :- http://sources.redhat.com/binutils/docs-2.15/binutils/objcopy.html
admittedly they're not stupendously clear if you haven't used objcopy much.

I have a feeling it's safe to say that a good number of Windows users have have little experience with command-line programs, lets alone objcopy.

wintermute wrote:
I tend to use a make macro for dealing with raw to object file conversion.

which I somehow missed when browsing through your makefiles, d'oh! Not sure you want to see something like that in the first makefile you ever see, though.

at Lost?
How about the many variations of palette? :P
On the HBlank, VBlank thing, I'm assuming you're talking (at least partially) about using the VBlank interrupt for vsyncing instead of checking REG_VCOUNT? As much as I agree this is better, the use of interrupts is still often done via a custom crt0.S/lnkscript where you have to uncomment certain things (if you can find it amidst the assembly and comments). This is probably not something you want newbies to confront with right at the start. Having a nice separate interrupt handler (like devkitARM's libgba's single_ints.s) for that would certainly help, but even then you'd have to wait until after discussing interrupts (and possibly assembly).
And isn't it possible to set the interrupt flags in the main interrupt handler so the separate isr's don't have to?

On copies: yeah dma is great, but apparently you should go overboard with it, see http://forum.gbadev.org/viewtopic.php?t=3392 and http://forum.gbadev.org/viewtopic.php?t=1803. Wish I'd known about that stuff sooner. And about using the standard memory routines, remember that these assume bytes, not (half)words. Though memcpy should convert itself to use 32bit copies (at least the Visual C version does, I don't know about the GCC one), using memset can wreak havoc, especially when trying to copy to VRAM.

Spelling edit; how in the world can I spell "great" as "create"?!?


Last edited by Cearn on Thu Dec 22, 2005 7:57 pm; edited 1 time in total

#20902 - LOst? - Wed May 19, 2004 3:20 pm

Cearn wrote:

at Lost?
How about the many variations of palette? :P
On the HBlank, VBlank thing, I'm assuming you're talking (at least partially) about using the VBlank interrupt for vsyncing instead of checking REG_VCOUNT? As much as I agree this is better, the use of interrupts is still often done via a custom crt0.S/lnkscript where you have to uncomment certain things (if you can find it amidst the assembly and comments). This is probably not something you want newbies to confront with right at the start. Having a nice separate interrupt handler (like devkitARM's libgba's single_ints.s) for that would certainly help, but even then you'd have to wait until after discussing interrupts (and possibly assembly).
And isn't it possible to set the interrupt flags in the main interrupt handler so the separate isr's don't have to?

You are right, but still better force people to use Interrupts instead of making them being lazy. Sooner or later they will have to understand them anyway.

Yea, we got pallette, pallet, pallete, palete, palets.... Argh! English please!

#20905 - poslundc - Wed May 19, 2004 4:21 pm

I disagree entirely with the notion that interrupts should be taught as the method to sync to VBlank in tutorials.

Checking REG_VCOUNT is infinitely easier for new programmers to understand, it gets them thinking about and understanding the relation between their code and the hardware's performance and behaviour, and even more to the point, using the interrupt is an optimization and not something that is required for or contributes to basic functionality or even performance of a program.

At best, all that using the interrupts does is spare a little battery drain. At worst, it confuses the heck out of a new programmer.

And it's an optimization, people! Remember Knuth! I still use REG_VCOUNT to sync my programs in the dev stage to VBlank, and I have yet to be told a compelling reason not to!

Dan.

#20907 - Lord Graga - Wed May 19, 2004 6:03 pm

I agree with you poslundc.

while doing the REG_VCOUNT check you don't WASTE any cycles if you aren't doing interrupts. Notice how it wouldn't actually waste any cycles that the coder has used anyway. So, no harm done, and screw batteries.

On the other hand, wouldn't it take extra cycles to have an interrupt running?

#20921 - dagamer34 - Wed May 19, 2004 11:22 pm

Lord Graga wrote:
I agree with you poslundc.

while doing the REG_VCOUNT check you don't WASTE any cycles if you aren't doing interrupts. Notice how it wouldn't actually waste any cycles that the coder has used anyway. So, no harm done, and screw batteries.

On the other hand, wouldn't it take extra cycles to have an interrupt running?


So, the real reason why I see that there are bad habits in tutorials, is that there is no one way to do something on the GBA. Questions like, "Should we teach them how to use DMA first, or have them use a for loop?" and "Are interrupts something a newbie really needs to learn first (for VSync), or will checking REG_VCOUNT be ok?", confuse tutorial writers, and they end up writing about whatever feels comfortable to them.

Without answering questions like these, this topic could go on for several pages without anything actually being done to change it.
_________________
Little kids and Playstation 2's don't mix. :(

#20924 - poslundc - Wed May 19, 2004 11:53 pm

dagamer34 wrote:
So, the real reason why I see that there are bad habits in tutorials, is that there is no one way to do something on the GBA. Questions like, "Should we teach them how to use DMA first, or have them use a for loop?" and "Are interrupts something a newbie really needs to learn first (for VSync), or will checking REG_VCOUNT be ok?", confuse tutorial writers, and they end up writing about whatever feels comfortable to them.


DMA copying and interrupt-based VBlank synching are both optimizations that have simple, C-based equivalents.

#including object data in a header file is erroneous and leads to worlds of problems as a project grows. The fact that the compiler lets you get away with it is no excuse for teaching it that way.

There is a tremendous difference between the two.

In the case of the former, I will always advocate teaching the C-based technique first and introducing the optimization later. Otherwise you end up with people who can't even debug their code properly because it relies on them using the DMA incorrectly or something. (I regularly use the DMA, but one of the first things I'll do when a block of code doesn't work properly is take out the DMA and replace it with a for-loop copy.)

Dan.

#20932 - tepples - Thu May 20, 2004 4:53 am

LOst? wrote:
Also, I must say that I want the game to operate with HBlank and VBlank correctly. Not just some void function with if conditions.

What exactly do you mean by this?

Quote:
And the flags for setting interrupts that have been used, it should be something that's taken care of automatically. It's just confusing and annoying since I can't seem to understand what it's good for.

So do you want macros for IRQ_PROLOG and IRQ_EPILOG?

Quote:
No more for-loops for loading sprites and graphics. I know it seems more easy to do it that way, but it's so crappy. Memcpy or DMACOPY it instead.

When I get to loading tiles, I'll teach using cpu_memcpy() and then dma_memcpy(), modeled after the similarly named function from the C library.

Quote:
Be sure to give out tools that work.

I plan to eat my own dogfood, to teach with the same tools I used to make my own games.

Quote:
All tools use different ways of storing data. Some is in header files. Some is in C files with externs.

C files with externs are strongly preferred to header files, and assembly files with externs are slightly preferred to C files with externs. However, I'll be teaching with GBFS because Windows developers seem to be more familiar with loading files and resources by name.

Quote:
And most of them use u16 types but doesn't include the type.

Already fixed in my tools.

Quote:
And some of them never add the last line that GCC complain about, making it hard to see if you got errors.

Already fixed in my tools.

And I have checked the spellings of interrupt, timer, palette, and other terms against a dictionary published by Merriam-Webster.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#20936 - yanos - Thu May 20, 2004 6:07 am

What is actualy wrong with putting data in header files?

#20937 - MumblyJoe - Thu May 20, 2004 6:16 am

I wish I had waited and read your tutorials as a start tepples, sounds like they will be awsome. It's a crying shame that alot of the people who wrote the original tutorials that are floating around never updated or corrected thier problems.

As a suggestion, how about including a chapter (marked optional because it's not really neccessary to know this) on writing your own tools. Personally I think that would be great because I am only now starting to get a set of reliable tools together because I wrote them myself (and honestly they would probably seem useless to alot of people who do things differently to me).

As for using GBFS in a tutorial... well I have never used it and I think its overkill for resource management... you will have to sell that idea to me :P
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20946 - poslundc - Thu May 20, 2004 1:27 pm

yanos wrote:
What is actualy wrong with putting data in header files?


Header files are meant to contain meta-data: basically shared information on how to access other information. This can include structs, function prototypes, references to external variables, and macro definitions.

They should never, ever contain executable code (exception: static inline functions) and that includes arrays of data.

A data file that is #included into two separate C files will end up defining the same symbol twice, which will cause an error when you get to the linking stage. These errors can be very difficult to track down.

Dan.

#20947 - poslundc - Thu May 20, 2004 1:28 pm

tepples wrote:
Quote:
No more for-loops for loading sprites and graphics. I know it seems more easy to do it that way, but it's so crappy. Memcpy or DMACOPY it instead.

When I get to loading tiles, I'll teach using cpu_memcpy() and then dma_memcpy(), modeled after the similarly named function from the C library.

Quote:
All tools use different ways of storing data. Some is in header files. Some is in C files with externs.

C files with externs are strongly preferred to header files, and assembly files with externs are slightly preferred to C files with externs. However, I'll be teaching with GBFS because Windows developers seem to be more familiar with loading files and resources by name.


*sigh* I'm telling you, when all is said and done people will just wind up using the Pern tutorials instead.

Dan.

#20948 - wintermute - Thu May 20, 2004 1:51 pm

Lord Graga wrote:
I agree with you poslundc.

while doing the REG_VCOUNT check you don't WASTE any cycles if you aren't doing interrupts. Notice how it wouldn't actually waste any cycles that the coder has used anyway. So, no harm done, and screw batteries.

On the other hand, wouldn't it take extra cycles to have an interrupt running?


VblankIntrWait puts the CPU into sleep mode until an interrupt occurs, it is not simply a loop like the REG V_COUNT check. If you don't have any interrupts then it is wasting ALL the cycles from the start of the loop until the vblank period.

If you're working on a commercial game and you don't use the IntrWait functions you *will* fail Nintendo lot check

#20949 - poslundc - Thu May 20, 2004 2:53 pm

wintermute wrote:
VblankIntrWait puts the CPU into sleep mode until an interrupt occurs, it is not simply a loop like the REG V_COUNT check. If you don't have any interrupts then it is wasting ALL the cycles from the start of the loop until the vblank period.


So? You make it sound like it is wasting food or crude oil or something. It simply keeps the CPU alive and doesn't bother to conserve a tiny amount of battery power. "Wasting cycles" only has significance if those cycles could have otherwise been made useful for calculations or something. But they couldn't, and your code doesn't perform the slightest bit poorer as a result.

Quote:
If you're working on a commercial game and you don't use the IntrWait functions you *will* fail Nintendo lot check


This should hardly be a concern of a beginner's tutorial.

Dan.

#20951 - wintermute - Thu May 20, 2004 3:12 pm

poslundc wrote:
wintermute wrote:
VblankIntrWait puts the CPU into sleep mode until an interrupt occurs, it is not simply a loop like the REG V_COUNT check. If you don't have any interrupts then it is wasting ALL the cycles from the start of the loop until the vblank period.


So? You make it sound like it is wasting food or crude oil or something. It simply keeps the CPU alive and doesn't bother to conserve a tiny amount of battery power. "Wasting cycles" only has significance if those cycles could have otherwise been made useful for calculations or something. But they couldn't, and your code doesn't perform the slightest bit poorer as a result.

Quote:
If you're working on a commercial game and you don't use the IntrWait functions you *will* fail Nintendo lot check



This should hardly be a concern of a beginner's tutorial.


The point is that Nintendo feel the impact on battery life is significant enough to fail games that don't use this method.

The beginners of today may well be the game developers of tomorrow - I fail to see why they should be taught bad habits in the early stages.

#20954 - poslundc - Thu May 20, 2004 4:13 pm

It's not a bad habit. Bad habits are things like passing structs instead of pointers, using floats without a coprocessor, and optimizing the crap out of non-time-critical routines. There is nothing programatically even questionable about hanging in a loop in order to catch up with a display frequency. It's simply an easier-to-implement and easier-to-understand way of doing it.

The fact that Nintendo wants you to optimize it into an interrupt before your game is published has absolutely nothing to do with getting people started programming the GBA. Beginners will gravitate towards the tutorial that's easiest to understand and simplest to get successfully coding in. And I guarantee you that anyone new to the hardware will find hanging in a loop a lot more straightforward than fiddling with interrupts.

Dan.

#20957 - wintermute - Thu May 20, 2004 5:38 pm

Disregard for power management in a portable system is an extremely bad habit. I suggest you run some tests with the two methods, you might be quite unpleasantly surprised by the results.

As for the simple to understand - the interrupt dispatcher can be supplied as 'black box' code to be used in a standard project framework with suitable 'accessor' functions for initialising and setting up interrupt routines.

Personally I feel that 'don't worry about this for now, it works' is much better than 'here's a completely unacceptable method which isn't reliable and should never be used if you ever hope to work in a commercial environment'

There are circumstances where the loop approach will never complete - admittedly those are rarely encountered but the potential for complete failure is there. Martin Korth's emulator complains about loops like this for good reason and the warnings should be heeded.

#20960 - sajiimori - Thu May 20, 2004 6:30 pm

Quote:

There are circumstances where the loop approach will never complete - admittedly those are rarely encountered but the potential for complete failure is there.

Can you explain which circumstances those are?

#20963 - poslundc - Thu May 20, 2004 7:18 pm

wintermute wrote:
Disregard for power management in a portable system is an extremely bad habit. I suggest you run some tests with the two methods, you might be quite unpleasantly surprised by the results.


Care to enlighten me? I've used software I've developed for hours on end with no noticeable reduction in battery life.

Quote:
As for the simple to understand - the interrupt dispatcher can be supplied as 'black box' code to be used in a standard project framework with suitable 'accessor' functions for initialising and setting up interrupt routines.


And most people will just go to the Pern tutorials instead so they can easily get started programming without having to muck around with other people's frameworks. (If I wanted to use a framework I'd have learned HAMLib.)

Quote:
Personally I feel that 'don't worry about this for now, it works' is much better than 'here's a completely unacceptable method which isn't reliable and should never be used if you ever hope to work in a commercial environment'


It is reliable. Show that it isn't. I've not once run into a problem using it.

And like I said, if Nintendo has a problem with it you can easily optimize it into an interrupt. But homebrew tutorials aren't there to teach Nintendo publishing standards. Heck, we aren't even supposed to know what they are.

Dan.

#20975 - alek - Thu May 20, 2004 10:22 pm

This thread is starting to get quit large so I might have missed if someone already has suggested this but I think your tutorial should include a chapter on sound and sound mixing. Just my two cents...

#20978 - dagamer34 - Fri May 21, 2004 12:07 am

alek wrote:
This thread is starting to get quit large so I might have missed if someone already has suggested this but I think your tutorial should include a chapter on sound and sound mixing. Just my two cents...

Actually, no one has mentioned it yet. But if he does put it in, I'm thinking a series of tutorials divided up into sections would be easier for him to write and update.
_________________
Little kids and Playstation 2's don't mix. :(

#20988 - MrMr[iCE] - Fri May 21, 2004 1:03 am

Quote:
Care to enlighten me? I've used software I've developed for hours on end with no noticeable reduction in battery life.


I'd love to. I wrote a book reader app for the SP. During testing (aka reading full length books), on a full charge I could get about 5-6 hours with the frontlight on. I already knew about the intrwait functions and used them to halt the sp until next keypress. I also added in code to disabe sound, making sure only the key interupt was active, etc. The result was on a full charge, I could get over 9 hours reading time. I know this is not related to vblank intrwaits, but it is relevant to the issue, and is useful info for those who wish to develop apps that need to conserve battery life.

Frankly, I dont see why this is such a major issue discussing why not to use a *built in feature* intended for the purpose of syncing to hardware events. Beginner or not, this is something that needs to be learned from the start.
_________________
Does the corpse have a familiar face?

#20991 - poslundc - Fri May 21, 2004 2:41 am

MrMr[iCE] wrote:
I know this is not related to vblank intrwaits, but it is relevant to the issue, and is useful info for those who wish to develop apps that need to conserve battery life.


OK, forgive me for being blunt, but I've just moved a whole apartment into a trailer and I'm dead tired. You're right that it's not relevant to VBlank syncing. Your frontlight battery-draining example on the SP has no bearing whatsoever on my question. So what's your point, then? Yes, it's useful info for those who want to develop apps that need to conserve battery life. But for the umpteenth time, it's not necessary for an introductory tutorial and makes things unnecessarily complicated for beginners.

Quote:
Frankly, I dont see why this is such a major issue discussing why not to use a *built in feature* intended for the purpose of syncing to hardware events. Beginner or not, this is something that needs to be learned from the start.


DMA is a built-in feature, but I don't expect beginners to use it to load data into memory. Why? Because it's an optimization. It's nice-to-know, not need-to-know. Beginners need to know the need-to-know stuff. The nice-to-know stuff can come in the later chapters, but if you try to dump it all on them at once they'll just do things the Pern way because it's more familiar to them, and you'll have accomplished nothing.

Dan.

#20994 - MumblyJoe - Fri May 21, 2004 2:50 am

wintermute wrote:
The beginners of today may well be the game developers of tomorrow - I fail to see why they should be taught bad habits in the early stages.


Because even if the beginners of today read all the tutorials around and worked as hard as humanly possible it's unlikely that they would ever find work developing for the GBA, considering the handheld is having a midlife crisis about now.

EDIT: I realised this made me sound jaded, I really do think that you should teach the best way first no matter how technical it is, I know too many people who have read a shitty "Teach yourself C++ in 24 Hours" book and not only dont know anything advanced, they know the wrongway to do simple things.


Also someone mentioned the tests nintendo does to allow publishing of games, could someone send me a comprehensive list of these?
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#20995 - sajiimori - Fri May 21, 2004 4:39 am

Quote:

I know too many people who have read a shitty "Teach yourself C++ in 24 Hours" book and not only dont know anything advanced, they know the wrongway to do simple things.

The alternative, which is more common in the real world, are people who think they know how to do specific "advanced" things, but don't understand the principles enough to extend their knowledge.

Teaching the simple way first is right.

#20996 - tepples - Fri May 21, 2004 6:11 am

In case you just joined us:

What has been agreed upon
  1. Don't do bin2c and then #include "data.c". Use an appended data method instead.
  2. Include PC-side tools that Just Work.
  3. Start with mode 3, arguably the simplest mode, as the frame buffer is just a 2D array.
  4. Don't confuse sprite cel VRAM with OAM.
  5. Correct spelling is a good thing.
  6. Introduce GNU Make early on.
  7. Emphasize -mthumb and -marm as appropriate.
  8. Link with gcc.
  9. Cast to the proper type inside the header file's macros.
  10. Don't encourage inline assembly language.
  11. Use devkitARM rather than DevKit Advance; reasons include devkitARM's cleaner crt0 and linker script.
  12. Use clones of memcpy() to load data into VRAM. Make a CPU version and a DMA version with the same arguments.
  13. Include a dictionary for systems programming techniques.
  14. Make sure to publish the tutorial under a free documentation license.

What's still under debate
  1. Introduce VBlankIntrWait() early on vs. in a later chapter on interrupts.


dagamer34: What terms should I put in the glossary? You mentioned ISR; what others?

And other than putting mode 3 first (direct hi-color, direct pixel addressing, making primitives dead easy), in what order should I explain the various modes, and when should I introduce sprites?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#20997 - abilyk - Fri May 21, 2004 6:20 am

sajiimori wrote:
Teaching the simple way first is right.


I definitely agree. With the majority of my math and computer hardware classes, we'd have to learn the long, drawn-out ways of doing things before we learned the "shortcuts." Granted, these shortcuts represented the right way to solve the problem, and advanced students and professionals, I'm sure, would use them. But beginning students won't appreciate these shortcuts and will likely have a more difficult time understanding the concepts if they don't muck through the simple, less efficient way first.

Also, I agree with pretty much all of what Dan has been saying, especially regarding GBFS. Tepples, I'm sure any tutorial you'd write would be correct and concise and a great learning tool. But if you force people to use GBFS, you'll probably lose a chunk of your audience, if only for that section of the tutorial. Many people will want to code everything by themselves, and others still may not want to learn an additional system to get their demo to work.

Personally, when I started out, I read about things like DMA and interrupts, but I didn't bother implementing them right away because I could achieve the same results doing something I already knew how to do (using memcpy, waiting for Vblank using a loop). Had your upcoming tutorial been around back then, I probably would have skimmed over the GBFS section and used another source to show how to include data the "quick and dirty" way. I think you should keep the GBFS info in there, sure, but I'd suggest doing it in addition to explaining the simpler way first as a more basic technique.

#21004 - niltsair - Fri May 21, 2004 2:38 pm

I agree about not teaching VBlank interupt right off the bat. When first starting a lot fo people will not event know what's the use of VBlank synching so after a couple of basic lessons, teach them to add while(VBLANK<160); and later on have a VBLank revisisted section teaching them to sync with interupt and why. While at it, add in the section how to create a timer with VBlank interupt to time your game (took me some time to figure out why my game was running fine in 1 emulator and too fast/slow in others (was using hardware timers)).

Interupts require more planning that beginer shouldn't worry about (keeping a copy of OAM and update real OAM during VBlank, same with Video Registers, etc...).
_________________
-Inside every large program is a small program struggling to get out. (Hoare's Law of Large Programs)
-The man who can smile when things go wrong has thought of someone he can blame it on. (Nixon's Theorem)

#21032 - wintermute - Fri May 21, 2004 11:48 pm

niltsair wrote:
I agree about not teaching VBlank interupt right off the bat. When first starting a lot fo people will not event know what's the use of VBlank synching so after a couple of basic lessons, teach them to add while(VBLANK<160); and later on have a VBLank revisisted section teaching them to sync with interupt and why.


Vblank syncing is one of the most fundamental tasks when writing a game, especially on a machine like the GBA where access to VRAM is restricted outside the vblank period. If you want to put things on screen you *need* to know about it.

while (REG_VCOUNT<160); is not sufficient for a working wait for vsync, especially with simple programs. The correct way to do this is to wait for the vblank period to finish, then wait for it to start again.

Given that REG_DISPSTAT contains a flag which will tell you if the machine is currently in the vblank period, I fail to see why people feel the need to use the scan line counter for this purpose apart from someone getting it wrong back in the mists of time.

Code:

while (!(REG_DISPSTAT & 1)); // wait for vblank period to start
...
code to be executed during vblank
...
code which isn't vblank critical
...
while (REG_DISPSTAT & 1); // wait for vblank period to end


If the second wait is not present and your code does not consume the entire vblank period then it will quite happily execute several times a frame.

The problem with this is that most of the time your code will be sitting in a loop doing nothing more than consuming the battery. This can translate into 50 - 60% less battery life (yes you did read that right) and so the IntrWait functions have been provided as a simple method to wait for events while conserving energy.

The issues people have with complexity are, I think, related to having only full interrupt dispatchers available as examples. To make use of the IntrWait functions does not require that all the interrupts are serviced, it merely needs some code to indicate that an interrupt has taken place.

here's a spectacularly nasty piece of code - I wanted to put together a completely self contained example for illustration purposes. The IntrMain function is given as inline assembly only to allow the mixing of ARM and thumb code within a single source file. The confusing casting & anding of the function pointer is part of making this work. Normally the definitions would be in a header file and the interrupt handler in a separate file, compiled as ARM code.

This code is not what I would consider clean and is only given as an illustration of using the IntrWait functions.

Code:

typedef   unsigned short int      u16;
typedef   volatile u16         vu16;

#define   REG_BASE   0x04000000

typedef void ( * IntFn)(void);
#define INT_VECTOR      *(IntFn *)(0x03007ffc)      // BIOS Interrupt vector
#define   REG_IME         *(vu16 *)(REG_BASE + 0x208)   // Interrupt Master Enable
#define   REG_IE         *(vu16 *)(REG_BASE + 0x200)   // Interrupt Enable
#define   REG_IF         *(vu16 *)(REG_BASE + 0x202)   // Interrupt Request

#define   REG_DISPCNT      *(vu16 *)(REG_BASE + 0x000)
#define   REG_DISPSTAT   *(vu16 *)(REG_BASE + 0x004)

#define   VRAM      ((u16*)0x06000000)

#define   MODE_3   3      // BG Mode 3
#define   BG2_ON   (1<<10)   // enable background 2

#define IE_VBL      (1<<0)
#define LCDC_VBL   (1<<3)

//---------------------------------------------------------------------------------
#if   defined   ( __thumb__ )
#define   SystemCall(Number)    asm ("SWI     "#Number"\n" :::  "r0", "r1", "r2", "r3")
#else
#define   SystemCall(Number)    asm ("SWI     "#Number"   << 16\n" :::"r0", "r1", "r2", "r3")
#endif

#define   VBlankIntrWait()   SystemCall(5)

//---------------------------------------------------------------------------------
void IntrMain(void)
//---------------------------------------------------------------------------------
{
   asm (   ".code 32\n"                  // Main interrupt handler must be ARM
         "mov      r3,   #0x4000000\n"      // REG_BASE
         "ldr      r2,   [r3,#0x200]\n"      // Read   REG_IE
         "and      r1,   r2,   r2,   lsr   #16\n"   // r1 =   IE & IF

         "ldrh   r2, [r3, #-8]\n"      // mix up with BIOS irq flags at 3007FF8h,
         "orr   r2, r2, r1\n"         // aka mirrored at 3FFFFF8h, this is required
         "strh   r2, [r3, #-8]\n"      // when using the (VBlank)IntrWait functions
         "add   r3,r3,#0x200\n"
         "strh   r2,   [r3, #2]\n"         // Clear the interrupt flag
         "mov   pc,lr\n"            // return - gcc inserts thumb prologue
      );
}

//---------------------------------------------------------------------------------
int main(void)
//---------------------------------------------------------------------------------
{
   INT_VECTOR = (IntFn)((unsigned int)IntrMain & -4);      // set up the ISR
   REG_IE = IE_VBL;         // Enable the vblank Interrupt
   REG_DISPSTAT = LCDC_VBL;   // Enable the lcd controller vblank
   REG_IME =1;               // Interrupts on

   REG_DISPCNT = MODE_3 | BG2_ON;

   int x=120<<8;
   int   y=80<<8;

   int dx = 0.75 * 256;
   int dy = 1.25 * 256;

   int lastx = x;
   int lasty = y;

   while(1)
   {

      lastx= x;
      lasty=y;

      x+=dx;
      y+=dy;
      if ( (x>>8)<0 || (x>>8)>239)
      {
         dx= -dx;
         x+=dx;
      }

      if ( (y>>8)<0 || (y>>8)>159)
      {
         dy= -dy;
         y+=dy;
      }

      VBlankIntrWait();      // wait for next vblank

      VRAM[(lasty>>8) * 240 + (lastx>>8)] = 0;
      VRAM[(y>>8) * 240 + (x>>8)] = -1;
   }
}






Quote:

While at it, add in the section how to create a timer with VBlank interupt to time your game (took me some time to figure out why my game was running fine in 1 emulator and too fast/slow in others (was using hardware timers)).


this is a problem with the emulators, not your code.


Quote:

Interupts require more planning that beginer shouldn't worry about (keeping a copy of OAM and update real OAM during VBlank, same with Video Registers, etc...).


this has absolutely nothing to do with interrupts. You can only update OAM during the vblank period whether you have interrupts enabled or not.

#21039 - tepples - Sat May 22, 2004 2:39 am

wintermute wrote:
Vblank syncing is one of the most fundamental tasks when writing a game, especially on a machine like the GBA where access to VRAM is restricted outside the vblank period. If you want to put things on screen you *need* to know about it.

Unlike GBC VRAM, GBA VRAM is dual-ported. OAM, on the other hand, needs to be updated either in vblank or (if the unlock bit of DISPCNT is set) in hblank.

Quote:
while (REG_VCOUNT<160); is not sufficient for a working wait for vsync, especially with simple programs. The correct way to do this is to wait for the vblank period to finish, then wait for it to start again.

I've already covered this in my draft of chapter 2 (mode 3 and basic animation). You have to wait while(VCOUNT >= 160) and then wait while(VCOUNT < 160).

Quote:
Given that REG_DISPSTAT contains a flag which will tell you if the machine is currently in the vblank period, I fail to see why people feel the need to use the scan line counter for this purpose apart from someone getting it wrong back in the mists of time.

Spinning on DISPSTAT and spinning on VCOUNT take the same amount of CPU effort.

Quote:
To make use of the IntrWait functions does not require that all the interrupts are serviced, it merely needs some code to indicate that an interrupt has taken place.

This is the hard part, and without extremely hairy hacks, it seems to require compiling separate source files, one for main() in Thumb, and one for isr() in ARM. Then I have to teach about object files and all that.

Quote:
here's a spectacularly nasty piece of code - I wanted to put together a completely self contained example for illustration purposes. The IntrMain function is given as inline assembly only to allow the mixing of ARM and thumb code within a single source file.

Which is why I wait to introduce the minimal ISR and IntrWait() until after having introduced multiple source files and GNU Make in chapter 3.

Quote:
This code is not what I would consider clean

Tutorials need clean code.

Quote:
Code:
#define   VRAM      ((u16*)0x06000000)

Want to see a really clever way of accessing mode 3?
Code:
typedef u16 MODE3_LINE[240];
#define MODE3_FB ((MODE3_LINE *)0x06000000)

Then one can access pixels as if they were in a 2D array, making it dead easy to write quick prototypes.

Quote:
Code:
//---------------------------------------------------------------------------------
#if   defined   ( __thumb__ )
#define   SystemCall(Number)    asm ("SWI     "#Number"\n" :::  "r0", "r1", "r2", "r3")
#else
#define   SystemCall(Number)    asm ("SWI     "#Number"   << 16\n" :::"r0", "r1", "r2", "r3")
#endif
#define   VBlankIntrWait()   SystemCall(5)

Clever. Thanks. Do you have a macro for SWIs that take arguments? I seem to recall that a register may not appear both in the input list and in the clobber list.

Quote:
Quote:

While at it, add in the section how to create a timer with VBlank interupt to time your game (took me some time to figure out why my game was running fine in 1 emulator and too fast/slow in others (was using hardware timers)).

this is a problem with the emulators, not your code.

I'm already hinting that counting vblanks is the right way to time animations.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21054 - keldon - Sat May 22, 2004 3:00 pm

that is what's wrong with the tutorials - - you're telling them how to run the 100 metres before they've learned how to jump off the launch pad.

In your tutorials get them to do the basic stuff - but include the complex code as your tutorial include, letting them know it's behind so that they don't have to worry about it. Then let them write their own VBlank routine / handler for another tutorial so they know how to do it themselves later.

#21074 - poslundc - Sun May 23, 2004 2:39 am

wintermute wrote:
while (REG_VCOUNT<160); is not sufficient for a working wait for vsync, especially with simple programs. The correct way to do this is to wait for the vblank period to finish, then wait for it to start again.


This is true, and it's important that tutorials teach it this way. I'm not certain whether or not the Pern tutorials do.

Quote:
Given that REG_DISPSTAT contains a flag which will tell you if the machine is currently in the vblank period, I fail to see why people feel the need to use the scan line counter for this purpose apart from someone getting it wrong back in the mists of time.


Let's be clear on one thing: counting scanlines isn't "getting it wrong". It's not wrong because it works just fine and makes perfect sense from a hardware perspective.

But yes, checking REG_DISPSTAT is just as effective and an equally viable way to teach VBlank synching. One is not inherently more right than the other, though.

I like using the scanline counter because often I am interested in trapping other phases of the CPU in addition to VBlank. Scanline counting is an easy way to do this.

I like scanline counting in tutorials because it gets the programmers thinking about and comprehending the way their software interacts timing-wise with the hardware.

But these are both personal, subjective reasons. I think a tutorial that teaches either method is fine.

Quote:
The problem with this is that most of the time your code will be sitting in a loop doing nothing more than consuming the battery. This can translate into 50 - 60% less battery life (yes you did read that right)


My own experience doesn't support those findings one bit. Perhaps if you had a program that did nothing but call VBlankIntrWait vs. a program that hangs in an infinite loop? But then I would still be surprised at those numbers.

Quote:
here's a spectacularly nasty piece of code

<nasty code snipped>


This is how you want to train beginners?! They will take Pern over your tutorial any day!

Dan.

#21082 - mr_schmoe - Sun May 23, 2004 5:50 pm

So, when are ya'll going to get around to writing these updated tutorials?

#21084 - Lord Graga - Sun May 23, 2004 7:58 pm

One thing that I would enjoy quite a lot was, if all basic things had 2 or 3 documents that explained it, making it easier to go "Uh, I don't get that, lemme check what the other one tells me about this!". :)

#21085 - tepples - Sun May 23, 2004 7:58 pm

I'm writing them a little bit every day. So far here's a draft of the outline and the first section.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21090 - ecurtz - Sun May 23, 2004 8:21 pm

I'd love to see the Mac and Linux information included as well, maybe linked in pages in the sections where you were explaining Windows specific stuff. I'm not volunteering (yet) but I'm sure you could get somebody to write those sections for you if you didn't have time or inclination.

I think the current order looks good. IMO sprites are sipler to understand than the tiled graphics modes and should come first.

It would be VERY cool, although obviously more work, to have the tools such as image conversion written in Java or something so the source could be included. I think it helps a lot to think about how the data is getting used to understand how you're creating the data in the first place.

#21094 - sgeos - Sun May 23, 2004 8:48 pm

I think it would be neat if each lesson was a stand alone module with prerequisite module knowledge listed. That would also make it easier for other authors to help write tutorial modules.

For example:
Mode 7 (needs scale/rotate bgs, ISRs, and fixed point math)

-Brendan

#21098 - tepples - Sun May 23, 2004 9:34 pm

ecurtz wrote:
I'd love to see the Mac and Linux information included as well

If I had a recent enough Macintosh computer (that is, not a 75 MHz POS running Mac OS 8.1 that grandpa uses to do a pub's books) or a PC video card that worked well with X11 (Mandrake 9.2 couldn't put my ATI Radeon 9000 into an accelerated mode), I would be able to develop and test such instructions myself. Under the free documentation licenses that cover the tutorial, any volunteer is free to do that.

Quote:
It would be VERY cool, although obviously more work, to have the tools such as image conversion written in Java or something so the source could be included.

I'm already including the C source code for all tools I provide.

And no, Brendan, "mode 7" (that is, rotation and scaling of individual scanlines of a background) doesn't need interrupts. It needs only HDMA. But I still find your dependency idea interesting.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21100 - sgeos - Sun May 23, 2004 9:47 pm

tepples wrote:
And no, Brendan, "mode 7" (that is, rotation and scaling of individual scanlines of a background) doesn't need interrupts. It needs only HDMA. But I still find your dependency idea interesting.


Thats the neat thing about dependencies is that different authors could write different tutorials:

"mode 7" speed version (needs rot scale bgs, and HDMA)
"mode 7" space version (needs rot scale bgs, and ISRs)

Assuming that more than one version of a topic has been written, it allows for specialization. Somebody might finish learning about HDMA and really like the concept. Great! There is tutorial out there that draws on those skills. If the learner skipped DMA and learned about ISRs first, then s/he can still learn about the "mode 7" effect.

-Brendan

#21103 - wintermute - Sun May 23, 2004 10:13 pm

poslundc wrote:

Quote:
The problem with this is that most of the time your code will be sitting in a loop doing nothing more than consuming the battery. This can translate into 50 - 60% less battery life (yes you did read that right)


My own experience doesn't support those findings one bit. Perhaps if you had a program that did nothing but call VBlankIntrWait vs. a program that hangs in an infinite loop? But then I would still be surprised at those numbers.


then you haven't tested it. As I said in the original post, you'd be unpleasantly surprised by the numbers.


Quote:
here's a spectacularly nasty piece of code

<nasty code snipped>


This is how you want to train beginners?! They will take Pern over your tutorial any day!

Dan.[/quote]

No, as I said, it's a spectacularly nasty piece of code it was just done that way to get a completely self contained example for purposes of illustration..

Secondly, I'm not the one writing tutorials.

Thirdly, it looks to me like you're a bit of a troll.

#21108 - poslundc - Sun May 23, 2004 11:43 pm

wintermute wrote:
poslundc wrote:
My own experience doesn't support those findings one bit. Perhaps if you had a program that did nothing but call VBlankIntrWait vs. a program that hangs in an infinite loop? But then I would still be surprised at those numbers.


then you haven't tested it. As I said in the original post, you'd be unpleasantly surprised by the numbers.


What can I say? I've never observed more than maybe 20% difference in battery drain in the programs I've written.

As for the example... I have little use for a program that does nothing but wait for VBlank to occur, and you've already expressed in an interest in making tutorial information practical.

Quote:
No, as I said, it's a spectacularly nasty piece of code it was just done that way to get a completely self contained example for purposes of illustration..


Of what, exactly? We already know how VBlank syncing with interrupts is done. This is a thread about what ought to be taught in tutorials. I fail to see how a messy example of VBlank syncing furthers that resolution.

Quote:
Thirdly, it looks to me like you're a bit of a troll.


That's such a ridiculously inappropriate thing to say I can barely formulate a response to it. I could point out that I've backed up every single point I've made with logic and relevance to the topic. I could point out that if I am a troll, I must be a very good one since you're the first person to find me out in the 800-odd posts I've made; I've managed to trick just about everyone else in thinking I'm a valued contributor to the forums. I could point out that a troll is someone who baits others into responding with intentionally inflammatory, non-substantial posts, not someone who argues a point well. I could say it looks to me like you're a bit of an idiot who isn't capable of attacking my argument so is trying to attack my character instead.

But instead I will simply say that I don't have the time to waste on mudslingers. Let me know when you have something salient to say in response to my points.

Dan.

#21109 - wintermute - Mon May 24, 2004 12:30 am

tepples wrote:
wintermute wrote:
Vblank syncing is one of the most fundamental tasks when writing a game, especially on a machine like the GBA where access to VRAM is restricted outside the vblank period. If you want to put things on screen you *need* to know about it.

Unlike GBC VRAM, GBA VRAM is dual-ported. OAM, on the other hand, needs to be updated either in vblank or (if the unlock bit of DISPCNT is set) in hblank.


Odd, a lot of documention suggests that this isn't the case. I've also seen it reported that it is not possible to write to VRAM which is currently being accessed by the LCD controller.

I've just done some tests which confirm that this doesn't appear to be the case. I find it difficult to believe that the VRAM is actually dual ported though - it seems more likely that wait states are inserted (Nintendo being renowned for doing things on the cheap - DMA and the 16bit write to VRAM being prime examples). Must try some speed tests later.

Quote:

Spinning on DISPSTAT and spinning on VCOUNT take the same amount of CPU effort.


just checked some gcc thumb output, the DISPSTAT one is 4bytes shorter and has 2 fewer instructions in the loop so actually they don't. That's just picky though :P


Quote:

This is the hard part, and without extremely hairy hacks, it seems to require compiling separate source files, one for main() in Thumb, and one for isr() in ARM. Then I have to teach about object files and all that.


yeah, I was a bit surprised by how hairy that example was :)

Quote:

Tutorials need clean code.


completely, as I said it was just done that way to get a self contained example for illustration.

Quote:

Quote:
Code:
#define   VRAM      ((u16*)0x06000000)

Want to see a really clever way of accessing mode 3?
Code:
typedef u16 MODE3_LINE[240];
#define MODE3_FB ((MODE3_LINE *)0x06000000)

Then one can access pixels as if they were in a 2D array, making it dead easy to write quick prototypes.


That's quite neat, shame you can't do that for mode 4. Consider it nicked :)


Quote:

Quote:
Code:
//---------------------------------------------------------------------------------
#if   defined   ( __thumb__ )
#define   SystemCall(Number)    asm ("SWI     "#Number"\n" :::  "r0", "r1", "r2", "r3")
#else
#define   SystemCall(Number)    asm ("SWI     "#Number"   << 16\n" :::"r0", "r1", "r2", "r3")
#endif
#define   VBlankIntrWait()   SystemCall(5)

Clever. Thanks. Do you have a macro for SWIs that take arguments? I seem to recall that a register may not appear both in the input list and in the clobber list.


The best way to do this is just to put the calls in a library as I've done with llibgba. GCC uses r0 - r3 as parameters to functions with 4 or less arguments with the rest going on the stack for 5 or more. I've played around with inlining these calls but I came to the conclusion that it's just not worth the trouble.

*Warning* do not place this function declaration in the same file as code which calls it. At higher optimisation levels gcc will inline the function and mess it up quite badly. Fixing this makes the compiler generate more code tthan it would for a simple function call so, personally, I'd recommend just not bothering.

Code:

#include "gba_systemcalls.h"

//---------------------------------------------------------------------------------
void CpuSet( const void *source,  void *dest, u32 mode)
//---------------------------------------------------------------------------------
{
   SystemCall(11);
}

//---------------------------------------------------------------------------------
void CpuFastSet( const void *source,  void *dest, u32 mode)
//---------------------------------------------------------------------------------
{
   SystemCall(12);
}


For functions which return parameters it seems to be easiest just to resort to assembly.


Code:

prototype in header file

u16 Sqrt(u32 X);

in assembly file


   .text
   .code 16

   .global   Sqrt
   .thumb_func
Sqrt:
   swi      8
   bx      lr

#21110 - wintermute - Mon May 24, 2004 12:37 am

poslundc wrote:

But instead I will simply say that I don't have the time to waste on mudslingers. Let me know when you have something salient to say in response to my points.


ditto

#21118 - tepples - Mon May 24, 2004 5:04 am

wintermute wrote:
The best way to do this is just to put the calls in a library as I've done with llibgba.

When do you plan on having a draft libgba manual so that I can build the tutorial around it?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21121 - sajiimori - Mon May 24, 2004 7:08 am

Boy wm, you are digging quite a hole for yourself. You have a lot of nerve calling Dan names, especially since several people have already backed him up. Or are we all conspiring to troll just for you?
Quote:

just checked some gcc thumb output, the DISPSTAT one is 4bytes shorter and has 2 fewer instructions in the loop so actually they don't. That's just picky though :P

Utter nonsense. A short loop and a long loop take the same CPU cycles if they run for the same amount of time, which they obviously will if they are waiting for the same event.

#21122 - Dracula-X - Mon May 24, 2004 9:49 am

My .02 - if you don't like it, I couldn't care less. :)

Battery life is of paramount importance, regardless of what a personal 'finding' may be. Nintendo, being the ultimate authority on official protocol and guidelines, has layed out what is termed as proper, and dismissing battery life is just downright juvenile. A fundamental question would be what do you think most beginners would prefer to be taught - the proper way, as outlined by Nintendo themselves, or in a manner that is contrary (particularly because some post on this board says it's ok)? I would wager most would want to be taught what is proper, as defined by Nintendo, especially if they have sights on pursuing a career in the industry. There is a 'right' way, and beginners ought to be taught the right way - or don't teach them at all.

I'm a bit dismayed at how this thread has turned sour, especially over so trivial a matter. I'd also like to point out that no amount of posting to these boards should ever be a measure of some self-imagined authority over what is proper and what is not. This is Nintendo hardware, and we should be following their guidelines - and let's not bring up the fact that we shouldn't even be aware of said guidelines when everyone is being pointed to documentations and manuals that often lift naming conventions and documentation verbatim and everything the homebrew 'scene' has (docs, emulators) is owed to leaked material (*sniff*, *sniff* what's that? oh! that is the smell of hypocrisy!).

Let's agree to disagree and keep it at that, and leave it civil. My vote is for teaching the proper method. I am agreeable to counting scanlines as long as there is sufficient documentation explaining why this hits the batteries hard (yes, it does).

#21126 - poslundc - Mon May 24, 2004 12:22 pm

Quote:
(*sniff*, *sniff* what's that? oh! that is the smell of hypocrisy!).

Let's agree to disagree and keep it at that, and leave it civil.


Speaking of hypocrisy... why not drop the sarcastic attitude if you care at all about civility.

Quote:
Battery life is of paramount importance, regardless of what a personal 'finding' may be.


- It is clearly of paramount importance to you. That does not make it of paramount importance to a beginner's tutorial. What is important to a beginner's tutorial is getting new programmers started on the GBA hardware with minimal difficulty and effort, so they will be able to fill in the gaps and learn the rest on their own. As such, Nintendo considering something to be an industry standard for publication is completely irrelevant to such a tutorial.

- I'll say it again: it is not the job of a beginner's tutorial to teach new programmers the optimizations Nintendo expects them to use if/when their game gets published. Anyone who writes GBA software good enough to merit publication will be perfectly able to optimize their VBlank syncing with interrupts when the time comes. None of them will come crying to the forum that their beginner's tutorial taught them to count scanlines instead.

- My "personal findings" are useless if there is any hard documentation to the contrary around. Currently there is none. We welcome you to perform and document the necessary tests to develop the curve relating battery drain to CPU activity (also taking into account things like areas of memory the instructions are being run from, prefetch state, etc.). We would thank you greatly for it. But until this is done your claim that it "hits the batteries hard (yes, it does)" is just as meaningless a "personal finding" as mine.

Quote:
I'd also like to point out that no amount of posting to these boards should ever be a measure of some self-imagined authority over what is proper and what is not.


Since this is an obvious reference to my mentioning of my post-count, I'll just say you are totally off-base with regards to my meaning. I have no interest in establishing authority of any sort; we have admins here for that. I don't think I am more "special" than anyone else because of it; certainly there are people on this board who post less than me who know a hell of a lot more, in fact, many of them taught me the stuff I know. I was called a troll, and simply rebutting the insult. Read the post again.

Dan.

#21128 - Dracula-X - Mon May 24, 2004 2:08 pm

poslundc wrote:
Speaking of hypocrisy... why not drop the sarcastic attitude if you care at all about civility.

I'll reserve the right to a sarcastic remark in the face of hypocrisy, the fact that you resorted to a schoolyard "I know you are but what am I" retort brings a smile to my face. You can drop it now.

poslundc wrote:
Quote:
Battery life is of paramount importance, regardless of what a personal 'finding' may be.

- It is clearly of paramount importance to you. That does not make it of paramount importance to a beginner's tutorial. What is important to a beginner's tutorial is getting new programmers started on the GBA hardware with minimal difficulty and effort, so they will be able to fill in the gaps and learn the rest on their own. As such, Nintendo considering something to be an industry standard for publication is completely irrelevant to such a tutorial.

Subjective opinion is what that is. You want to start them out on the wrong road in the name hand-holding. I'd rather they learn the right way with documentation on a level they can understand.

poslundc wrote:
- I'll say it again: it is not the job of a beginner's tutorial to teach new programmers the optimizations Nintendo expects them to use if/when their game gets published. Anyone who writes GBA software good enough to merit publication will be perfectly able to optimize their VBlank syncing with interrupts when the time comes. None of them will come crying to the forum that their beginner's tutorial taught them to count scanlines instead.

I see, you've appointed yourself an authority on what beginner tutorials should teach too, because I don't see an "I think" or "I feel" in there anywhere, so you must be right!. I'll say it again, you ask a newcomer if he or she would rather learn the way the professionals do it, the way Nintendo wants it done, or some halfhearted method for the sake of being simple and making things 'easy' because you don't have faith in the tutorial writer's ability to explain it properly (which is bordering absurdity because setting up a vblank irq and syncing with it is trivial), my gut tells me the majority of beginners will want to do it the right way. A well constructed tutorial will guide readers appropriately and explain things thoroughly using the industry accepted methods. End of story.

poslundc wrote:
- My "personal findings" are useless if there is any hard documentation to the contrary around. Currently there is none. We welcome you to perform and document the necessary tests to develop the curve relating battery drain to CPU activity (also taking into account things like areas of memory the instructions are being run from, prefetch state, etc.). We would thank you greatly for it. But until this is done your claim that it "hits the batteries hard (yes, it does)" is just as meaningless a "personal finding" as mine.

Ooh, very clever, and very convenient. For those of us who make a living and must abide by Nintendo's regulations to put a game on the shelf must all be suffering from some mass delusion, and Nintendo must have pulled this stipulation from their arse (I guess they want to be cheeky). All because poslundc 'says so' - that's really what it comes down to.

poslundc wrote:
Quote:
I'd also like to point out that no amount of posting to these boards should ever be a measure of some self-imagined authority over what is proper and what is not.

Since this is an obvious reference to my mentioning of my post-count, I'll just say you are totally off-base with regards to my meaning. I have no interest in establishing authority of any sort; we have admins here for that. I don't think I am more "special" than anyone else because of it; certainly there are people on this board who post less than me who know a hell of a lot more, in fact, many of them taught me the stuff I know. I was called a troll, and simply rebutting the insult. Read the post again.

Really could have fooled me :) An industry veteran of 2 decades (that's right kids, wintermute has been doing this a LONG time) suggests using the proper method in the tutorial (not only because it is the way the pros do it, not only because it's the way Nintendo wants it done, but because there is nothing inherently complex or confusing about it if explained the way it needs to be - or do you not have faith in Tepples' ability to handle it?) and because it doesn't resonate with your 'zen of scanline counting' you get your panties in a bunch. Wonderful.

#21140 - sajiimori - Mon May 24, 2004 7:17 pm

Move it to Offtopic.

#21142 - keldon - Mon May 24, 2004 8:05 pm

:D lolol

#21146 - Miked0801 - Mon May 24, 2004 10:10 pm

ty.

#21150 - dagamer34 - Mon May 24, 2004 10:20 pm

This topic is really turning sour. Is there anyway to save it? Perhaps someone really should do those battery tests.

I don't think the number of posts should affect the quality of an answer. There are no prizes, or rankings as such, so if someone has 800+ posts and hasn't had their account deleted, they must have done something right?

And if people are going to bicker, don't even move it to Off Topic. Just PM each other and go at it there.

It's sad to see our boards turn this way. Just when I had thought I had found a place where there is no fighting, differences come between us.

EDIT: tepples, I think you should add a "Common Pitfalls" section to the tutorials that would include things like "No 8-bit writes to VRAM" and stuff like that.
_________________
Little kids and Playstation 2's don't mix. :(

#21152 - wintermute - Mon May 24, 2004 10:57 pm

tepples wrote:
wintermute wrote:
The best way to do this is just to put the calls in a library as I've done with libgba.

When do you plan on having a draft libgba manual so that I can build the tutorial around it?


dang, I guess I'm going to have to shuffle this one up my todo list a touch :P

It's been something I've been meaning to do for a while but haven't yet decided on a format for. One of the problems I keep coming back to is just how much depth to go into regarding the hw register definitions - it seems like a lot of work to essentially replicate extremely good documentation like gbatek.

Perhaps building your tutorials around libgba would be a good approach towards a good set of documentation. Having the tutorials explain the registers and having a quick reference guide with libgba.

I'm open to suggestions as to the best way to do it

#21156 - keldon - Tue May 25, 2004 12:25 am

I feel it is important to let newbies know there is a lot more to creating games than using these libraries. But not by principle, I do this so that they don't develop games for months wondering why they CANNOT do X and Y - - and saying "if only they didn't put such a mask over me"

I don't mean to shower them with information. But balance good practice with the learning curve. Nothing should take more than 20 minutes to learn, and anything bigger than that should be carefully taught (usually by breaking it down).

One problem people have is that they forget that a complete beginner cannot even program, let alone deal with hardware. And we will never teach beginners unless we remember this.

#21158 - tepples - Tue May 25, 2004 1:51 am

Dracula-X wrote:
A fundamental question would be what do you think most beginners would prefer to be taught - the proper way, as outlined by Nintendo themselves

The "proper way" is to get a developer license before even looking at a tutorial. Don't worry; I plan to introduce VBlankIntrWait() as soon as I've introduced hardware and software interrupts.

Quote:
I would wager most would want to be taught what is proper, as defined by Nintendo

Would evidence of "proper" behavior include Nintendo's legal action against vendors of flash carts?

Quote:
This is Nintendo hardware

I'm typing this on Dell hardware.

Quote:
and we should be following their guidelines

Nintendo's guidelines are "don't."

Quote:
Let's agree to disagree and keep it at that, and leave it civil. My vote is for teaching the proper method.

Do you mean "teaching the proper method" or "teaching the proper method" FIRST? The "proper method" requires either more complicated build scripts or extremely hairy assembly hacks?

keldon wrote:
they forget that a complete beginner cannot even program

I do list C programming as a prerequisite in the first chapter.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21162 - sgeos - Tue May 25, 2004 4:45 am

dagamer34 wrote:
This topic is really turning sour. Is there anyway to save it?

That depends on one's personal definition of save. Once you ignore the noise, this topic *is* saved. People can argue about how a tutorial can be done from now until the end of time, but until they have written a tutorial and received feedback on it, I can not give their side comments much merit.

I'd rather hear the constructive criticism that the tutorial writers have received instead of theories about what would make a better tutorial. I think that talking about how existing tutorial material could be inproved is productive.

Bickering over another persons opinion strikes me as out of place. My question is, "do you feel strongly enough about it to write your own tutorial?" Yes? Excellent. I look forward to reading it. No? Let it go and the thread will become less noisy. (Note that unless one *is* a troll, should not not bickering result in less stress?)

-Brendan

#21166 - tepples - Tue May 25, 2004 5:35 am

"Put up or shut up" eh? OK, I'll put up. Here's my tutorial so far with draft chapters 1 and 2. I'd like to see somebody run through the steps, particularly in chapter 1 about tool setup, and let me know how well they work.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21347 - bats - Fri May 28, 2004 3:00 am

I tested the tool setup on my desktop, and everything went through without a hitch.

General comments on the tutorial:

    I like the code. Very clean, nice comments.

    The header file is so simple! Very nice for a beginner's tutorial.

    The documentation is a little cold -- maybe a little too technical for my taste [emotionally -- the technical aspects of the document have the right amount of technicality :) ]. Maybe that's what you were going for, though. I like when technical documents throw in some jokes, a quote at the beginning of the chapter, that kind of thing.

    The flow through chapter 2 seemed a little awkward, the jump from GBA info into fixed-point arithmetic and Newtonian physics mainly. If I were reading a book I would expect those things to be in appendices.

    The physics section could be fleshed out a bit, also. Next draft, I'd suppose.

Other than that, a very nice start!

Ben

#21355 - tepples - Fri May 28, 2004 3:45 am

bats wrote:
I like when technical documents throw in some jokes

I can see two reasons for that:
  • My personality includes Asperger syndrome, a mild form of autism that preserves high function but deadens my pragmatic language skills such as distinguishing a joke from a serious admonition. I enjoy puns, but some jokes make me think of ways that they could in fact be serious. Remember that the widely hated Digital Millennium Copyright Act and foreign counterparts started out perceived as a joke.
  • In this X-rated world, I tend to have trouble keeping jokes entirely G-rated.
If somebody were to provide a humor patch against my tutorials, I would gladly review it.

bats wrote:
The flow through chapter 2 seemed a little awkward, the jump from GBA info into fixed-point arithmetic and Newtonian physics mainly. The physics section could be fleshed out a bit, also. Next draft, I'd suppose.

Don't those two goals conflict a bit? And does there exist a Free tutorial for game physics that I could include as a prerequisite? I'll work on a transition paragraph.

Otherwise, thanks.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#21359 - sajiimori - Fri May 28, 2004 4:09 am

There's an HTML typo in the section about installing MinGW.
Code:

<li>Install MinGW by running the executable that you downloaded.
    Remember that GCC and other programs from the
    <acronym title="Unified Information and
    Control System">UNIX</acronym">

The UNIX acronym applies to the rest of the document. =)

edit: another one in Ch2
Code:

<acronym title="video RAM">VRAM</acronym">

#21384 - bats - Fri May 28, 2004 2:13 pm

I knew I shoulda kept my big mouth shut. Oh, well. Hope I didn't offend.

I don't think the goals conflict. It's just that when I was reading along, the fixed-point section kinda caught me be surprise. I'm probably making a bigger deal of this than is necessary. As for the physics section, it just seemed a little thin -- some simple formulas and concepts might be nice. Then again, an already finished game physics tutorial might be nicer. :)

I'd give gamedev.net a good search.

Ben

#21396 - sgeos - Fri May 28, 2004 6:52 pm

bats wrote:
I knew I shoulda kept my big mouth shut. Oh, well. Hope I didn't offend.


Any reasonable person likes to get feedback.

-Brendan

#21582 - DigitalChaos - Tue Jun 01, 2004 11:42 am

I just read the first two chapters. They're very good. Keep going and finish it. Gread code. Keep it up, how long do you expect it to be?

#21640 - jeromie - Wed Jun 02, 2004 8:29 am

Hi Guys -

I just wanted to offer myself to the group as a guinnea pig for future tutorial stuff.

A little bit about me:

I'm an experienced PHP developer with a few years of web development under my belt. I'm familiar with basic C structures and constructs -- PHP borrows heavily from C and C++. I understand general OO design concepts (classes, methods, functions, pointers), but I'm *not* used to accessing hardware and memory directly.

Hopefully I can be a good resource for you guys, providing feedback on the tutorial from the perspective of a user competent at the core skill set, but one who's still a neophyte for all intents and purposes.

I'm terribly bored with web development, and am looking to develop a new skill set. I'm very appreciative of your efforts, and am looking forward to really getting my game development chops together.

Please let me know if I can be of any assistance.

Best regards,
Jeromie Clark

#22018 - DigitalChaos - Fri Jun 11, 2004 9:37 am

Any updates on this man?

#22032 - tepples - Fri Jun 11, 2004 5:11 pm

Sorry, I got off track with Tournamix, a choreography competition on another phpBB forum I read. I'll probably have another chance to work on this today.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#22039 - DigitalChaos - Fri Jun 11, 2004 8:13 pm

awesome, i'm really looking forward to this

#22220 - Krakken - Tue Jun 15, 2004 12:18 am

I've had a look through it and i'm impressed. Like someone mentioned just now though, some of the subjects are very, very brief. For example, the physics section, I think that should be made into a whole tutorial topic. It would be a valuable asset to a lot of people to understand concepts like the laws of physics and how they are applied in programming. Unless i'm mistaken also, physics has not been covered in any other GBA tutorials.

#22246 - Fatnickc - Tue Jun 15, 2004 5:19 pm

Sorry to ask this if it has already been asked, or it is not ready to be read by us yet, but what is the address of the tutorial?

#22250 - alek - Tue Jun 15, 2004 9:42 pm

Fatnickc wrote:
Sorry to ask this if it has already been asked, or it is not ready to be read by us yet, but what is the address of the tutorial?

If you look at the previous page and the post second from the bottom I think you might find what you are looking for

#22258 - DigitalChaos - Wed Jun 16, 2004 7:31 am

still waitin on updates...

#22272 - Fatnickc - Wed Jun 16, 2004 5:23 pm

thank you for that. I need to improve my skills and figure it would be better to start again.

#22514 - tepples - Wed Jun 23, 2004 8:54 am

T u t o r i a l . P a r t . 3

covering bitmap images in modes 3 and 5

can be found here

provided my internet connection isn't down

have any bad habits snuck in?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#22566 - skinnybeans - Thu Jun 24, 2004 10:37 am

ive read through the first 2 tutes and really like them. They are much easier to understand than the pern project ones!!

I hope you keep up the good work. Are interrupts like callbacks?

#22574 - tepples - Thu Jun 24, 2004 2:48 pm

Yes, interrupts on the GBA are a bit like callbacks, but I won't get to them until chapter 6.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#22700 - skinnybeans - Sun Jun 27, 2004 11:08 am

cool, i look forward to it.

not sure if i should post this here or in another thread, but seeing as im using the setup from the tutorial, and its kinda related teaching newbies things ill ask here:

How do you debug your gba proggies when they are running?? Ive taken the code from the second tute and tried to add a generic line drawing fucntion that uses bresenhams algorithm but it aint working, and not being able to check the values of variables at run-time means i have pretty much no chance of getting it working proplerly!

Im used to developing in visual studio and setting breakpoints and all that jazz, is there anyway i can do something like this for gba dev? is this going to be covered in one of your tutorials?

Ive got mappy and it seems to allow some of these features if you load an elf file into it. I tried but had no success =(

#22701 - wintermute - Sun Jun 27, 2004 11:40 am

skinnybeans wrote:
cool, i look forward to it.

How do you debug your gba proggies when they are running?? Ive taken the code from the second tute and tried to add a generic line drawing fucntion that uses bresenhams algorithm but it aint working, and not being able to check the values of variables at run-time means i have pretty much no chance of getting it working proplerly!



Go to http://www.devkit.tk

in the downloads section you'll find Insight 5.2.1 and Visualboy Advance 1.7.1 SDL version.

Start that version of VBA from a command shell with the command line 'vba -Gtcp' (you can also do this with a batch file or add the parameters to a windows shortcut)

Start arm-elf-gdb from the Insight package , File->open and select the elf file that you compiled ( I hope you used devkitARM :P) Now click File->Target Settings - here select Remote/TCP, 127.0.0.1 in the hostname box and 55555 in the Port box. Click the run button.

you need to add -g to the parameters for beth link and compile.

Hey presto full source level debugging.

#22710 - tepples - Sun Jun 27, 2004 6:15 pm

I will warn you that GBFS won't work with .elf files, but if you use bin2s on your GBFS file instead of appending it and then using find_first_gbfs_file(), you can still debug a program that uses GBFS.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#22722 - dagamer34 - Sun Jun 27, 2004 10:01 pm

tepples wrote:
I will warn you that GBFS won't work with .elf files, but if you use bin2s on your GBFS file instead of appending it and then using find_first_gbfs_file(), you can still debug a program that uses GBFS.


Do you have an example to the bin2s method?
_________________
Little kids and Playstation 2's don't mix. :(

#22734 - tepples - Mon Jun 28, 2004 7:27 am

The bin2s way, for the builds used within the programming department for source level debugging:
Code:
(in make.bat)
bin2s data.gbfs > data.s
gcc -Wall -O -mthumb -mthumb-interwork main.c data.s -o main.elf

(in main.c)
extern const GBFS_FILE data_gbfs[];

The appended way, for the builds sent to the assets department:
Code:
(in make.bat)
gcc -Wall -O -mthumb -mthumb-interwork main.c -o main.elf
objcopy -O binary main.elf main.bin
padbin 256 tmp.bin
copy /b tmp.bin+data.gbfs main.gba

(in main.c)
const GBFS_FILE *data_gbfs;
int main() {
  find_first_gbfs_file(find_first_gbfs_file);
  /* ... */
}

_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#24117 - dagamer34 - Wed Jul 28, 2004 3:58 am

I guess I should have posted this a while back... but here are the things I think would be good to put in the dictionary:

ISR, VBlank, HBlank, DMA, HDMA, Modes 0-5(brief description), EEPROM, SRAM, Flash ROM, EWRAM, IWRAM, OAM, Tiles, Interrupts.

That's what I have so far. If you want me to, I can also come up with the definitions.
_________________
Little kids and Playstation 2's don't mix. :(

#24123 - dovoto - Wed Jul 28, 2004 7:28 am

A quick response in defense of the pern project.

1) They are being rewritten with proper grammar and spelling (at least more proper)

2) Day 1, and 2 rewrites are complete and up, and include such things as how to get data into your games by every means other then some sort of proprietary rom file system. The new graphics converter (improperly named pcx2sprite) can output raw, c, header, object file, and source code will be provided when I have time to comment it. Day 3, and 9 should be up in this weekend.

3) Defines are fine for registers...if your emulator does not have a register viewer get a new emulator. But the tutorials purpose is not to give you a library but to teach you the hardware. The implementation is completely up to you. Use bitfields for all I care :)

4) Day 3 and nine should be up by the end of the week.

5) make is a waste of time for single file projects such as 90% of my tutorials and I felt (and still feel) that make is a complexity that has no place in my tutorial.

6) In response to 5 and as a compromise I will add an appendix to cover make files, and be sure to enlighten readers on the proper way to manage projects.

7) I have several hundred hours of effort invested in my tutorials and well over a hundred pages of GBA info.. I have no editor and I can?t spell, but I do now write my text in a word processor before posting it for the world to see. My tutorials are always open to feedback of any sort.

8) I have only made it to page two of this thread and felt compelled to post so if i am being redundant please forgive :)

9) My tutorials were at one time very popular and their accuracy and "correctness" both in a technical sense and in an aesthetic sense are important to me. Instead of starting a new series can we instead just give me feedback to incorporate into my rewrite?


-i am going to finish reading this thread and see if there is anything else to add.
_________________
www.drunkencoders.com

#24144 - tepples - Wed Jul 28, 2004 3:18 pm

dovoto wrote:
2) Day 1, and 2 rewrites are complete and up, and include such things as how to get data into your games by every means other then some sort of proprietary rom file system.

Slight correction: GBFS isn't proprietary but rather free software.

Quote:
5) make is a waste of time for single file projects such as 90% of my tutorials

Anything that involves converting bitmaps won't be a single file project, as you need at least one file for code and one for graphics. Anything on or after the day ISRs are introduced won't be a single file project, as you need at least one file for Thumb code in ROM and another for ARM code in IWRAM.

Quote:
9) My tutorials were at one time very popular and their accuracy and "correctness" both in a technical sense and in an aesthetic sense are important to me. Instead of starting a new series can we instead just give me feedback to incorporate into my rewrite?

I wish you good luck on version 2.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#25256 - Deanonious - Thu Aug 19, 2004 4:09 pm

I have significant experience writing software in Windows... mostly Visual Basic and some Visual C++, and because of that I have absolutely no hardware programming experience, so prior windows programming experience a side, I consider myself a complete newbie.

I have looked through many of the tutorials out there, I even read through all of Mr. Harbour's book, and I have some comments on what I have found or not found in them, and I think this insight would be quite useful to the discussion at hand.

1) Coming from a totally "Modern" Windows programming background I do not completely understand Timers or Interrupts. I understand procedural programs and Event driven programs, and although Message Handlers are a direct descendent of Interrupt Handlers I have been so completely sheltered from the hardware aspects of coding them that Interrupt Handlers still remain mysterious to me. I do realize and undestand there importance in GBA programming, but I have not found a concise and adaquate reference on them. I believe that a good introduction to them should be made as early as possible in the Beginner Tutorials, and then as the tutorials progress more in depth coverage of them should be given.

2) Memory management is another GBA programming issue that I somewhat struggle with, "Modern" PC programmers are not taught to maximize memory usage, and since I have started learning GBA programming I have decided that this is a great shame, and I now consider it "bad" programming practices. I believe that the non-technical aspects of memory management should be covered very early, perhaps even in the introduction to the tutorials, and then more in depth coverage should be given as the tutorials progress.

I am a Math/Computer Science major at Texas Tech University, and most modern Computer Science classes (here anyway) don't ever cover
malloc(), realloc(), memmove(), memcpy()... in fact in the last CS class I took I actually got in trouble for using memcpy() in my code and was told that the For Loop method for copying memory was the only "Acceptable" method (besides using the STL Allocator Class) because most modern programmers would not understand my code.

3) File System Support (or the lack thereof) is a huge stumbling block for me, from my non-hardware programming background, I do not understand how to attach binary data to an executable but I very often find myself needing (or atleast wanting to) include binary (or even occassionaly ASCII) data to my programs. I do agree that using a "third party" library like GBFS may not be the best approach to teaching this, but attention needs to be given to this subject early on. Perhaps even an Advanced Tutorial on how to write your own GBFS like library.

4) Lastly I want to see a detailed well commented Header file of ALL the registers that are needed for programming the GBA. Although, I agree that a beginner should be introduced to them slowly and as needed, some of the tutorial writers seem to lump the needed ones togather every project and I find it tedious to re-write #define's all the time, besides from personal experience typing in memory addresses is extremely error prone, it's easy to make a typo in a memory address and until you become familiar with the addresses it isn't always easy to find where you made the typo. I know that DevKitAdvance and HAM both have there own Register Defintions included but I would like to learn GBA programming from scratch, so I would like go through tutorials and eventually write my own complete Register Defination file.

I hope that you find some of my comments helpful.

Dean

#25268 - sajiimori - Thu Aug 19, 2004 6:06 pm

Quote:

...in the last CS class I took I actually got in trouble for using memcpy() in my code and was told that the For Loop method for copying memory was the only "Acceptable" method (besides using the STL Allocator Class) because most modern programmers would not understand my code.

Then that was not a very good class. Part of knowing the language is knowing the standard library, and if a "professional" C programmer doesn't know C then they have no claim to that title.

Anyway, these particular tutorials have the prerequisite of knowing C, so it's appropriate to leave out explanations of standard library functions. There are many C tutorials already out there.
Quote:

a "third party" library like GBFS

Everything in the homebrew community is 3rd party.
Quote:

Lastly I want to see a detailed well commented Header file of ALL the registers that are needed for programming the GBA.

Check the GBATek document -- it's pretty complete.

#25273 - Deanonious - Thu Aug 19, 2004 10:12 pm

Dude Sajiimori you don't have to be a jerk about it.

I was just saying Universities do NOT teach "C" anymore, it's considered outdated and obsolete. From day one when you walk into a CS Class at Texas Tech University you start learning C++, strings are the STL String class, C-Strings are just some stupid thing left over from C so if you need one call string::c_str() and all dynamic memory is either handled by new/delete and for loops or by the STL Allocator class. It's been that way since before I started here in 2000. I personally thinks it's stupid my self, I learned C over 10 years ago that's why I know the C-standard library, but that is the way things are going now. Sorry.

As far as the GBATek goes, yes it is a wonderful reference; however, a beginner isn't going to want to weed through technical references to look for something, when they probably won't even know what they are looking for.

#25277 - poslundc - Thu Aug 19, 2004 10:44 pm

Deanonious wrote:
I was just saying Universities do NOT teach "C" anymore, it's considered outdated and obsolete. From day one when you walk into a CS Class at Texas Tech University you start learning C++, strings are the STL String class, C-Strings are just some stupid thing left over from C so if you need one call string::c_str() and all dynamic memory is either handled by new/delete and for loops or by the STL Allocator class.


A couple of things to be aware of:

1. Universities still teach C. Your university doesn't teach C. You may believe that your university is better for this reason, but you would have an extremely difficult time making an irrefutable case for it. Already working against it:

2. Extensions like STL are a total speed/memory kill on a platform like the GBA. So those "outdated", "obsolete", "stupid things left over from C" are, ironically, of critical importance if you want to do anything on many embedded platforms.

Dan.

#25282 - sajiimori - Thu Aug 19, 2004 11:53 pm

I didn't mean to offend you, but in my honest opinion it's a bad idea to teach students to be willfully ignorant about certain parts of the subject language.

Ask yourself why the standard C library is included in the C++ definition. It's for backward compatability, right? Well if C++ was designed with backward compatability in mind, shouldn't C++ programmers be backward compatable as well by knowing the standard C library?

This may seem like an abstract or overly intuitive argument, but cross-platform compatability is one of the main reasons C++ has become so popular, and firms that use the language take advantage of this feature regularly (e.g. by using 3rd party libraries written in C).

About GBATek, I thought you were looking for a reference. Sorry if I misinterpreted. At this point I'm not sure what you were asking for, because a big list of all the registers and their usage sounds like a reference to me, and I can't imagine how such a list could alleviate the chore of hunting down the information you need. Tutorials have that goal, which is why I tended to rely on them until I was more comfortable with the hardware.

#25284 - dagamer34 - Fri Aug 20, 2004 1:01 am

Take a look at The Pern Project. It's currently being redone so check it every so often.

Universities don't teach you everything you need to know. Now you know that. So, simply move on.
_________________
Little kids and Playstation 2's don't mix. :(

#25289 - Deanonious - Fri Aug 20, 2004 4:02 am

I never said that I agreed with my Universities policy on not teaching C or what they claim is obsolete programming techniques. In fact I have gotten in a LOT of trouble because I challanged and/or refused to buy into there crap. I am like most of you I started with C over 10 years ago, and I totally disagree with my Universities teaching approaches to Computer Science. I never said that I think my university is better than any other university, I was merely pointing out the fact that some "programmers" are coming from a different background than most of you and that they shouldn't be talked down too because they weren't taught techniques that they are assumed to know. Yes I think it's a real shame that a lot of these techniques aren't taught at my university, I have gone too the Chairman of the Department on numerous occassions to voice my opionions on the subject, and have debated with numerous professors over there "policies" and/or teaching style. Hell, I almost failed a C++ class because I used OOP techniques???

I was trying to point out a few things that I believe should be addressed in a beginner tutorial, I never said that you should go out and write the next "Teach yourself systems programming in C in 21 days" book, I was just making a few points on my experiences as a beginner GBA programmer and certain things about Memory/Resource Management were and in some cases still are a mystery to me. At least include a link to Rafael Baptista's great article "Gameboy Advance Resource Management" on Gamasutra.com and maybe in the introduction link to a few really good C tutorials that are pertinent to the subject, and say something like "Hey if you aren't familiar with 'C Standard Library Memory Management' go brush up here... <insert link>"

The URL to the Baptista Article is:
http://www.gamasutra.com/features/20010509/baptista_01.htm

Unfortunately, I think that you have to log-in to Gamasutra.com to read it :(. The Code is no longer available as Nintendo has decreed that it as usual violated there intellectual property rights and has confiscated it, those among us that are "licensced" still have the joy of obtaining it via Nintendo's developer site. He wrote a more general "Memory Manager" tutorial on his website it can be found here.

http://www.oroboro.com/rafael/docserv.php?index=algorithms&article=memmgr

<begin Totally Off-Topic Rant>

It makes me really sad that Nintendo is such a jerk, I can understand some kind of Quality Assurance testing, like maybe Windows, if you want to put a Microsoft Windows Approved sicker on your game you have to pass there QA tests, but making developers pay thousands of dollars to write Software for your system is just crappy.

If I were Nintendo I would want people to develop software for my system it seems to be that the more quality games that are out there the more people are going to want to buy your system and that means more profit. With the PSP coming out soon with all it's raw power, Nintendo may very well die if they don't come to there senses, in my opionion Nintendo hasn't had a home console worth buying since the SNES, the Gameboy is there only saving grace.

Sorry, that just came to be because I was trying to dl the source to Mr. Baptista's article and I got really depressed when I couldn't.

<end Totally Off-Topic Rant>

I didn't want or mean to start another flame war in this thread, I merely wanted to aid the community by stating my take on the current state of GBA programming tutorials. I'm sorry for causing such a stir, I just wanted to help.

#25291 - tepples - Fri Aug 20, 2004 5:09 am

<offtopic>
Deanonious wrote:
If I were Nintendo I would want people to develop software for my system it seems to be that the more quality games that are out there the more people are going to want to buy your system and that means more profit.

Think of Nintendo's position in 1985. The U.S. video game market had just crashed from a glut of poor-quality third-party software for Atari 2600 and a few other early 8-bit console platforms that didn't use signed binaries.

</offtopic>

That said, I'm still working on my tutorial off and on, but given that The Pern Project's tutorial is being rewritten, I might trim down the scope of my project to cover only what New Pern doesn't.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#25328 - expos1994 - Fri Aug 20, 2004 6:06 pm

Nintendo was smart to limit the 3rd party developers in 1985, but that business model doesn't work quite as well today.
Sony proved that when Playstation became the #1 console back in the mid-late nineties. They charged developers something like $5 for a license. Nintendo has been playing catch-up ever since.

It make me wonder about how well the PSP is going to do up against the DS. If I had to put money on it, I'd put it on the PSP.