Chris Dick
/
Gameduino_Invaders_game
Invaders game for the Gameduino
utils.h
- Committer:
- TheChrisyd
- Date:
- 2013-10-26
- Revision:
- 4:e82f4a87df9e
- Parent:
- 2:20a89dc286d5
File content as of revision 4:e82f4a87df9e:
#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