Chris Dick
/
Gameduino_Invaders_game
Invaders game for the Gameduino
Diff: utils.h
- Revision:
- 0:8a7c58553b44
- Child:
- 1:f44175dd69fd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utils.h Thu Jun 21 19:13:34 2012 +0000 @@ -0,0 +1,232 @@ +#ifndef COM_ARTLUM_GDUTILS_INCLUDED +#define COM_ARTLUM_GDUTILS_INCLUDED +#include "arduino.h" +#include "GD.h" +//#include "WProgram.h" + +/*--------------------------------------------------- + Coprocessor controller - makes it easy to do + raster effects (eg. split screens) without + writing any FORTH. + + The way this works is that you build a list of + instructions in memory (a "copperlist") and + the coprocessor will execute the list on every + video frame. + + Code samples: + + void setup() { + ... + // Make a copperlist to change a palette color on line 100 + // The copperlist is stored on the Gameduino at address 0x3f80 + Coprocessor::reset(); + CopperlistBuilder cp; + cp.begin(0x3f80); + cp.wait(100); + cp.write16(PALETTE4A, 0x7fff); + cp.end(); // And start using the new copperlist + } + + Modifying an existing copperlist: + + // Make a copperlist to set the horizontal scroll register + // on line 220 and modify the copperlist. + // a) Build the list + unsigned int XscrollInst; + void setup() { + ... + CopperlistBuilder cp; + cp.begin(0x3f80); + cp.wait(220); + XscrollInst = cp.position(); // Get current output location + cp.write16(SCROLL_X, 0); + cp.end(); + } + // b) Modify the list with current 'xscroll' + void loop() { + CopperlistBuilder cp; + cp.begin(XscrollInst) // Where the 'write16()' instruction is + cp.write16(SCROLL_X, xscroll); // Overwrite the previous instruction + } + + Notes: + The Coprocessor object uses the "COMM" block + of memory at 0x2980 so don't mess with it. + + The coprocessor also provides support for the + sound functions below. +---------------------------------------------------*/ +class Coprocessor { +public: + // This initializes everything and load the coprocessor code. + // You should call this in your setup() function after "GD.begin();" + // + // The sample page is the page of Gameduino memory to + // use as a buffer for sample playback. It *must* be + // on a page boundry (ie. bottom 8 bits are 0) and + // the whole page will be used so you can't use it + // for anything else. + static void reset(unsigned int samplePage=0x3f00); // Default: Use memory from 0x3f00 to 0x3fff + + // Select a copperlist. The list will start running on the next video frame. + // nb. The "CopperlistBuilder::end()" function normally calls this automatically + // (unless you tell it not to...) + static void setCopperlist(unsigned int addr); + + // Where the sample playback page is located + static unsigned int samplePage(); + + // Where the coprocessor is currently reading samples + // from in the sample page. Use this info to keep the + // page full of fresh sample data for playback + static byte sampleReadPos(); + + // A copy of the coprocessor YLINE register + static int yline(); +}; + +// This object helps you make a copperlist in memory +class CopperlistBuilder { + unsigned int out,start; + void put(byte); + void put16(unsigned int); +public: + // Available commands are: + // * Wait for a raster line + // * Write a byte to a memory location + // * Write a 16-bit word to a memory location + // * Copy a block of memory from one place to another + void begin(unsigned int dest); + void wait(int line); + void write(unsigned int addr, byte val); + void write16(unsigned int addr, unsigned int val); + void copy(unsigned int src, unsigned int dst, unsigned int numBytes); + void end(bool executeNow=true); + + // Where I'm currently outputting + unsigned int position(); +}; + + +/*------------------------------------------------------------------ + Sound functions - play synthesized sounds and sound samples + + These functions require support from the Coprocessor object + above. If you load different microcode they'll stop working... +------------------------------------------------------------------*/ + +/*------------------------------------------------------------------ + Synthesized sounds +------------------------------------------------------------------*/ +#define SYNTHSOUNDS 0 +#if SYNTHSOUNDS +// ADSR volume envelope +struct ADSR { + byte attack; // Attack time (in clock ticks) + byte decay; // Decay time (in clock ticks) + byte sustain; // Sustain level [0..255] + byte release; // Release time (in clock ticks) + ADSR(byte a=4, byte d=4, byte s=90, byte r=30); + byte evaluate(unsigned int elapsedTime, unsigned int releaseTime); +}; + +// Change pitch of a sound as it plays +struct PitchModulator { + // Vibrato + byte vibratoDelay; // Delay before vibrato starts (in clock ticks) + byte vibrato; // Amount of vibrato (percentage of note pitch) + char vibratoDelta; // Added to 'vibrato' every clock tick + // Pitch Sweep + byte sweepDelay; // Delay before sweep starts (in clock ticks) + byte sweep; + char sweepDelta; + PitchModulator() { + vibratoDelay = 0; + vibrato = 0; + vibratoDelta = 0; + } + int evaluate(int startpitch, unsigned int time); +}; + +// All the parameters for a sound +struct Sound { + ADSR adsr; + PitchModulator pm; +}; + +class SoundPlayer { + // Playback parameters + Sound sound; + byte volume; + unsigned int pitch; + unsigned int duration; + // Internal vars + unsigned int ticks; + bool active, releasing; + // Sound players form a linked list + bool isLinked; + SoundPlayer *link; + // The SoundPlayer is updated from SoundController + void update(); + friend class SoundController; + // You can't copy me... + SoundPlayer(const SoundPlayer&); + void operator=(const SoundPlayer&); +public: + SoundPlayer(); + + // Set the sound parameters + SoundPlayer& setSound(const Sound&); + + // Set playback volume in range [0..255], default = 255 + SoundPlayer& setVolume(byte); + + // Play a sound, pitch in Hz, duration in clock ticks. + // If duration is 'infinite' then the sound plays until you call 'release()' + // One "clock tick" is equivalent to one call to "SoundController::update()" + enum { infinite=0x7fff }; + void play(unsigned int pitchHz, unsigned int duration=infinite); + + // Make the current sound enter the 'release' phase + void release(); + + // Stop sound playback immediately + void stop(); +}; +#endif + +/*------------------------------------------------------------------ + Main sound controller object +------------------------------------------------------------------*/ +struct SoundController { + // Reset all sounds, return to silence + static void reset(); + + // Update all sound - call this at least once every video frame. + // The frequency at which you call this function is one "clock tick" for synthesised sounds + static void update(); + + // Play a sound sample from program memory + // Samples are eight bits and will be played at + // the system sample rate (see "Coprocessor"). + // if "numBytes" is negative, the sample will repeat until you play + // another sample on the channel (eg. pass a null pointer to "playSample()"...) + static void playSample(prog_char*, int numBytes, byte channel); +}; + + + +/*------------------------------------------------------------ + Useful little functions +------------------------------------------------------------*/ +// Show a number on screen +void showNumber(int n, byte x, byte y); +void showHexNumber(unsigned int n, byte x, byte y); + +// Send screenshot to serial port + +void sendScreenshot(); + +// COM_ARTLUM_GDUTILS_INCLUDED +#endif