// testd.d: A GBA program written in D // by Nick Sabalausky (nick [:at:] twistedpairgaming.com) // August 2004 // I'm using a lot of messy "*((ushort *)(0x4000000))" style stuff // because D doesn't support #define and I'm not yet sure the // best equivilent to "#define REG_DISPCNT *(u32*)0x4000000". // NOTE: A lot of this code is horribly inefficient, but it works. // "extern (C)" is required for AgbMain() so that crt0 can find it. extern (C) void AgbMain() { // REG_DISPCNT: Mode 4, 1D Object Mode, BG2 and Objects on. *((ushort *)(0x4000000)) = 0x1444; // Set up background palette *((ushort *)(0x5000000) + 1) = (10 << 10) + (0 << 5) + 5; // Dark Blue *((ushort *)(0x5000000) + 2) = (26 << 10) + (25 << 5) + 25; // Light Grey // Fill screen with dark blue // (NOTE: This is a very slow way to fill the screen) ubyte* screenPtr; for(screenPtr=(ubyte*)0x6000000; screenPtr < (ubyte*)0x6000000 + (240*160); screenPtr += 2) { // This will fill two consecutive pixels (due to GBA's video mem architecture) *screenPtr = 0x01; } // Draw a big "D" // Left Line DrawVLineFromTo(45, 40, 110, 0x02); DrawVLineFromTo(46, 40, 110, 0x02); DrawVLineFromTo(47, 40, 110, 0x02); // Right Line DrawVLineFromTo(75, 60, 90, 0x02); DrawVLineFromTo(74, 60, 90, 0x02); DrawVLineFromTo(73, 60, 90, 0x02); // Top Line DrawHLineFromTo(40, 45, 65, 0x02); DrawHLineFromTo(41, 45, 65, 0x02); DrawHLineFromTo(42, 45, 65, 0x02); DrawHLineFromTo(43, 45, 65, 0x02); // Bottom Line DrawHLineFromTo(110, 45, 65, 0x02); DrawHLineFromTo(109, 45, 65, 0x02); DrawHLineFromTo(108, 45, 65, 0x02); DrawHLineFromTo(107, 45, 65, 0x02); // Top Diagonal Line DrawDDownLineLength(65, 40, 20, 0x02); DrawDDownLineLength(65, 41, 20, 0x02); DrawDDownLineLength(66, 40, 20, 0x02); DrawDDownLineLength(66, 41, 20, 0x02); DrawDDownLineLength(65, 42, 20, 0x02); DrawDDownLineLength(65, 43, 20, 0x02); // Bottom Diagonal Line DrawDUpLineLength(65, 110, 20, 0x02); DrawDUpLineLength(65, 109, 20, 0x02); DrawDUpLineLength(64, 110, 20, 0x02); DrawDUpLineLength(64, 109, 20, 0x02); DrawDUpLineLength(64, 108, 20, 0x02); DrawDUpLineLength(64, 107, 20, 0x02); // A nice smily face :) DrawEye(52, 80, 0x02); DrawEye(63, 80, 0x02); DrawHLineFromTo(94, 55, 62, 0x02); DrawHLineFromTo(95, 55, 62, 0x02); DrawPixel(54, 93, 0x02); DrawPixel(54, 92, 0x02); DrawPixel(53, 91, 0x02); DrawPixel(53, 90, 0x02); DrawPixel(62, 93, 0x02); DrawPixel(62, 92, 0x02); DrawPixel(63, 91, 0x02); DrawPixel(63, 90, 0x02); // Cool color cycling effect // (If you wonder how it works, note that I'm ignoring VBlank) ushort* FGColorPtr = ((ushort *)(0x5000000) + 2); ushort color = *FGColorPtr; while(1) { color += 3; *FGColorPtr = color; int delay; for(delay=0; delay<10; delay++) {} } } void DrawEye(int x, int y, ubyte color) { DrawPixel(x+0, y+0, 0x02); DrawPixel(x+0, y+1, 0x02); DrawPixel(x+1, y+0, 0x02); DrawPixel(x+1, y+1, 0x02); DrawPixel(x+0, y+2, 0x02); DrawPixel(x+0, y+3, 0x02); DrawPixel(x+0, y+3, 0x02); DrawPixel(x+1, y+2, 0x02); } // NOTE: These drawing functions treat the Mode 4 screen as 120x160 // NOTE: These drawing function do NOT perform clipping // NOTE: These are kinda messy, too ;) void DrawPixel(int x, int y, ubyte color) { // This will fill two consecutive pixels (due to GBA's video mem architecture) *((ubyte *)(0x6000000) + (x*2) + (y*240)) = color; } void DrawVLineFromTo(int x, int y1, int y2, ubyte color) { ubyte* screenPtr; for(screenPtr=(ubyte*)0x6000000 + (240*y1) + (x*2); screenPtr < (ubyte*)0x6000000 + (240*y2); screenPtr += 240) { // This will fill two consecutive pixels (due to GBA's video mem architecture) *screenPtr = color; } } void DrawHLineFromTo(int y, int x1, int x2, ubyte color) { ubyte* screenPtr; for(screenPtr=(ubyte*)0x6000000 + (240*y) + (x1*2); screenPtr < (ubyte*)0x6000000 + (240*y) + (x2*2); screenPtr += 2) { // This will fill two consecutive pixels (due to GBA's video mem architecture) *screenPtr = color; } } // 45 Degree Diagonal, top-left to bottom-right void DrawDDownLineLength(int x, int y, int length, ubyte color) { ubyte* screenPtr; length /= 2; for(screenPtr=(ubyte*)0x6000000 + (240*y) + (x*2); screenPtr < (ubyte*)0x6000000 + (240*(y+(length*2))) + ((x*2)+length); screenPtr += (240*2)+2) { // This will fill two consecutive pixels (due to GBA's video mem architecture) *screenPtr = color; } } // 45 Degree Diagonal, bottom-left to top-right void DrawDUpLineLength(int x, int y, int length, ubyte color) { ubyte* screenPtr; length /= 2; for(screenPtr=(ubyte*)0x6000000 + (240*y) + (x*2); screenPtr > (ubyte*)0x6000000 + (240*(y-(length*2))) + ((x*2)-length); screenPtr -= (240*2)-2) { // This will fill two consecutive pixels (due to GBA's video mem architecture) *screenPtr = color; } } // END OF FILE /////////////////////////////////////