// "Hello, World!" Demo v3.1
// Copyright (c) Amos Bieler 2002-2003

/*////////////////////////////
// To Do /////////////////////
//////////////////////////////

Add warning/alignment screens (and, maybe, a "Press Start!")

Add DogP's random functions and make the spinning less "spirally."

Make it interactive, somehow?

*/////////////////////////////

#include <libgccvb.h>

/*////////////////////////////
// Data //////////////////////
////////////////////////////*/

// This HWORD array is the "font," (such as it is ;^)
// As you can see, it is, appropriately, called chFont.
const HWORD chFont[] = {
	0x3C0F, 0x3C0F, 0x3C0F, 0x3FFF, 0x3C0F, 0x3C0F, 0x3C0F, 0x0000, // H
	0x3FFF, 0x000F, 0x000F, 0x00FF, 0x000F, 0x000F, 0x3FFF, 0x0000, // E
	0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x3FFF, 0x0000, // L
	0x0FFC, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x0FFC, 0x0000, // O
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000D, 0x0003, // ,
	0x380B, 0x380B, 0x3C0F, 0x2E2E, 0x2EEE, 0x0FFC, 0x0F3C, 0x0000, // W
	0x0FFF, 0x3C0F, 0x3C0F, 0x3C0F, 0x0FFF, 0x0F0F, 0x3C0F, 0x0000, // R
	0x0FFF, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x0FFF, 0x0000, // D
	0x2800, 0x3F00, 0x2F80, 0x0BC0, 0x00F0, 0x0020, 0x000F, 0x000F	// !
};


// This is a set of objects that spells out the message using chars from chFont.
const HWORD objMessage[] = {
//	X	L/RON & P	Y	Pal/HFlp/VFlp/Char
	144,	0xC000,		108,	0,	// "H"
	152,	0xC000,		108,	1,	// "E"
	160,	0xC000,		108,	2,	// "L"
	168,	0xC000,		108,	2,	// "L"
	176,	0xC000,		108,	3,	// "O"
	184,	0xC000,		108,	4,	// ","
	192,	0xC000,		108,	5,	// "W"
	200,	0xC000,		108,	3,	// "O"
	208,	0xC000,		108,	6,	// "R"
	216,	0xC000,		108,	2,	// "L"
	224,	0xC000,		108,	7,	// "D"
	232,	0xC000,		108,	8,	// "!"
};
// As you can see, each Obj has a parallax of 0, (I set it in the game loop...)
// uses palette JPLT0, and is neither horizontally nor vertically flipped.
//
// It would be more intuitive to use a bunch of calls to vbSetObject, but it's faster and
// more efficient (both in size and speed) to do it this way...


// This one is an array of P and Y coordinates for the circle animation.
// Someday, I may calculate this at startup, allowing a different radius by changing one line!
const int Circle[] = {
  0, 187, -1, 185, -2, 181, -2, 174, -3, 164, -3, 151, -4, 138, -4, 123,
 -4, 107, -4,  91, -4,  76, -3,  63, -3,  50, -2,  40, -2,  33, -1,  29,
  0,  27,  1,  29,  2,  33,  2,  40,  3,  50,  3,  63,  4,  76,  4,  91,
  4, 107,  4, 123,  4, 138,  3, 151,  3, 164,  2, 174,  2, 181,  1, 185};

/*////////////////////////////
// Functions /////////////////
////////////////////////////*/

int main ()
{
	HWORD i, points[12];	// The current coordinates for each Object (for animation.)

	// Set up some required video parameters.
	vbDisplayOn ();
//	vbSetColTable ();

	// Copy the font characters into CAM (Character Attribute Memory.)
	// This routine from the default library is very useful!
	//                                          ~~~~

	// copymem(destination address, source address, number of bytes)
	copymem ((void*)CharSeg0, (void*)chFont, 144);

	// Copy the message Objects into OAM (Object Attribute Memory.)
	copymem ((void*)OAMBase, (void*)objMessage, (12 * 8));

	// Set up the first World (31) to hold our Objects.
	// Set up the second World (30) to be the End World.  It and all others are not drawn.
	// (Using a handy set of macros from the default library...)

	// See vbaddr.h for the constants from which to build a world header (WRLD_*)
	// Just OR them together like I did with LON and RON below.

	WORLD_SET_HEAD(31, (WRLD_LON | WRLD_RON | WRLD_OBJ));
	WORLD_SET_G(31, 0, 0, 0);
	WORLD_SET_M(31, 0, 0, 0);
	WORLD_SET_SIZE(31, 0, 0);

	WORLD_SET_HEAD(30, WRLD_END);

	// Set the first SPT pointer (SPT3) to point to the 12 Objects (numbered 0 through 11)
	VIP_REGS[SPT3] = 11;
	VIP_REGS[SPT2] = -1;
	VIP_REGS[SPT1] = -1;
	VIP_REGS[SPT0] = -1;

	// Setup the 12 Object coordinates for the animation
	for(i = 0; i < 12; i++) points[i] = i;

	// Fading in has been used to death, so I just set the brightness directly... ;)
	VIP_REGS[BRTA]  = 32;
	VIP_REGS[BRTB]  = 64;
	VIP_REGS[BRTC]  = 32;

	while (1) {
	// Everything inside this infinite while loop is the animation
	// and is pretty simple when you understand what is happening
	// in the rest of the program.

		for (i=0; i < 12; i++) {
			if (points[i]-- < 1) points[i] += 32;

			while (VIP_REGS[XPSTTS] & XPBSYR);
			OBJ_YSET(i, Circle[points[i]*2+1]);
			OBJ_PSET(i, Circle[points[i]*2]);
		}

		vbWaitFrame (10);
	}
}
