Well, here’s some of the stuff currently running through my head about DS programming:
Coding in assembly has a lot of geek cred, certainly, but it’s tedious compared to low-level programming languages like C. This is especially so on RISC processors like the ARM, which are supposedly designed with low-level languages in mind.
For example, say I want to store a 16-bit value to memory somewhere. Call it writing a pixel to video memory. The ARM instruction set allows a programmer to load an immediate value into a register, though it only allows 8 bits at a time. The 8 bit value is packed into a bitfield in the MOV instruction, though, which looks very clever from what I know of CPU design. Furthermore, you can shift the value up to 30 bits in the same instruction. So, for your most significant 8 bits, you can load them directly into a register and then shift them into position in the same instruction. For the least significant bits, you can then ORR them in to the register, again using a direct value. Then you can STRH (store halfword) them from the register into memory. 3 steps.
In C you can do this in one line, and it will automatically and deterministically (I think) handle the proper order of machine code steps to do this in, which is in some ways handier. Unless the compiler is dumb and chooses to do this in the most consistent (but least efficient) manner. This I do not know because I haven’t been disassembling a lot of compiler output (but I probably should be).
What it boils down to is that I should consider doing more programming in C. The build process is similar to building from assembly code and might be easier on me. On the other hand it comes at the expense of learning the hardware, because I’d be tempted to set up compiler directives to translate the hardware addresses into handy variables. That and I’d have to get past C’s confusing pointer syntax.
Realistically, since programming efficient code means making sure subroutines and such can fit into the ARM9′s tiny tiny TCM, I’d want to be sure hand-code as much as possible and even do THUMB interworking.
(Oh what? The DS has 32KB of instruction TCM, that’s pretty big. I thought it was 96B or something. Still, efficiency matters.)
Well, as I’m writing this, hand-coded assembly seems more fun, so I’ll stick with that. What it means is a lot of studying ARM opcodes to see how the bitfields are laid out, which means I’ll probably also be writing some ARM code in binary. Wheeee.
Oh, the “Hello, world” thing, that’s important, too.
I have a bit of experience with graphics programming from playing with SDL. It’s wacky stuff. The “easy” way to write a hello world program for the DS would be to include stdio.h, turn on the text console, and do a printf() command. Great, but it encourages lazy programming and doesn’t teach you anything about graphics. A slightly harder way would be to make a bitmap of your text, convert it into one of the DS’s graphics formats, link it to your program, and display it as a background or sprite. That’s a little better, but it still involves a lot of magical conversions and you don’t have to think much about how the DS’s graphics system works.
The method I’ve chosen is the least efficient but the most educational. Cut out the middleman entirely, as is my style. Use the framebuffer mode on the main screen, because it is conveniently simple. What that gives you is a blob of video memory wherein each 16-bit segment is a pixel on the screen.
This poses an interesting challenge because we’re dealing with raster graphics, which you don’t use quite like cartesian coordinates. The pixels are stored in a flat memory space, so you don’t have a simple X,Y mapping of the screen. It’s halfway there. You need a third piece of information, the span, to find your pixel in memory. At least, that’s what it’s called in SDL, I think it also might be called pitch, but it’s the same idea. This is the number of pixels wide your framebuffer is. So, to get the scanline, you multiply the Y coordinate by the span. Then you add the X coordinate. Oh, and you have to multiply everything by 2 because we’re dealing with halfwords and not bytes.
With this knowledge, you can very tediously draw an image to the screen just using ARM instructions, not worrying about storing bitmaps in memory or anything. I just tried this and it is really really tedious, but hey, I did it on my first try because I understand the maths!
Okay, well I’m almost to my hello world thing. Right now it’s just a matter of putting “hello world” on a grid and plotting the points. Also, incidentally, the GNU assembler provides fairly helpful error messages when you use an instruction wrong.