/* * Copyright (C) 2011-2013 by James Bowman * Gameduino library for arduino. * */ #ifndef _GD_H_INCLUDED #define _GD_H_INCLUDED #ifdef BOARD_maple #include "wirish.h" typedef const unsigned char prog_uchar; #define Serial SerialUSB #define pgm_read_byte_near(x) (*(prog_uchar*)x) #define pgm_read_byte(x) (*(prog_uchar*)x) #define PROGMEM const extern HardwareSPI SPI; #include #include #include #endif #define flash_uint8_t const PROGMEM uint8_t #define flash_int8_t const PROGMEM int8_t struct sprplot { char x, y; byte image, palette; }; class GDClass { public: static void begin(int pin = 9); static void end(); static void __start(unsigned int addr); static void __wstart(unsigned int addr); static void __end(void); static byte rd(unsigned int addr); static void wr(unsigned int addr, byte v); static unsigned int rd16(unsigned int addr); static void wr16(unsigned int addr, unsigned int v); static void fill(int addr, byte v, unsigned int count); static void copy(unsigned int addr, flash_uint8_t *src, int count); #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) static void copy(unsigned int addr, uint_farptr_t src, int count); static void microcode(uint_farptr_t src, int count); static void uncompress(unsigned int addr, uint_farptr_t src); #endif static void setpal(int pal, unsigned int rgb); static void sprite(int spr, int x, int y, byte image, byte palette, byte rot = 0, byte jk = 0); static void sprite2x2(int spr, int x, int y, byte image, byte palette, byte rot = 0, byte jk = 0); static void waitvblank(); static void microcode(flash_uint8_t *src, int count); static void uncompress(unsigned int addr, flash_uint8_t *src); static void voice(int v, byte wave, unsigned int freq, byte lamp, byte ramp); static void ascii(); static void putstr(int x, int y, const char *s); static void screenshot(unsigned int frame); void __wstartspr(unsigned int spr = 0); void xsprite(int ox, int oy, char x, char y, byte image, byte palette, byte rot = 0, byte jk = 0); void xhide(); void plots(int ox, int oy, const PROGMEM sprplot *psp, byte count, byte rot, byte jk); byte spr; // Current sprite, incremented by xsprite/xhide above }; #define GD_HAS_PLOTS 1 // have the 'GD.plots' method extern GDClass GD; #define RGB(r,g,b) ((((r) >> 3) << 10) | (((g) >> 3) << 5) | ((b) >> 3)) #define TRANSPARENT (1 << 15) // transparent for chars and sprites #define RAM_PIC 0x0000 // Screen Picture, 64 x 64 = 4096 bytes #define RAM_CHR 0x1000 // Screen Characters, 256 x 16 = 4096 bytes #define RAM_PAL 0x2000 // Screen Character Palette, 256 x 8 = 2048 bytes #define IDENT 0x2800 #define REV 0x2801 #define FRAME 0x2802 #define VBLANK 0x2803 #define SCROLL_X 0x2804 #define SCROLL_Y 0x2806 #define JK_MODE 0x2808 #define J1_RESET 0x2809 #define SPR_DISABLE 0x280a #define SPR_PAGE 0x280b #define IOMODE 0x280c #define BG_COLOR 0x280e #define SAMPLE_L 0x2810 #define SAMPLE_R 0x2812 #define MODULATOR 0x2814 #define VIDEO_MODE 0x2815 #define MODE_800x600_72 0 #define MODE_800x600_60 1 #define SCREENSHOT_Y 0x281e #define PALETTE16A 0x2840 // 16-color palette RAM A, 32 bytes #define PALETTE16B 0x2860 // 16-color palette RAM B, 32 bytes #define PALETTE4A 0x2880 // 4-color palette RAM A, 8 bytes #define PALETTE4B 0x2888 // 4-color palette RAM A, 8 bytes #define COMM 0x2890 // Communication buffer #define COLLISION 0x2900 // Collision detection RAM, 256 bytes #define VOICES 0x2a00 // Voice controls #define J1_CODE 0x2b00 // J1 coprocessor microcode RAM #define SCREENSHOT 0x2c00 // screenshot line RAM #define RAM_SPR 0x3000 // Sprite Control, 512 x 4 = 2048 bytes #define RAM_SPRPAL 0x3800 // Sprite Palettes, 4 x 256 = 2048 bytes #define RAM_SPRIMG 0x4000 // Sprite Image, 64 x 256 = 16384 bytes #ifndef GET_FAR_ADDRESS // at some point this will become official... https://savannah.nongnu.org/patch/?6352 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define GET_FAR_ADDRESS(var) \ ({ \ uint_farptr_t tmp; \ \ __asm__ __volatile__( \ \ "ldi %A0, lo8(%1)" "\n\t" \ "ldi %B0, hi8(%1)" "\n\t" \ "ldi %C0, hh8(%1)" "\n\t" \ "clr %D0" "\n\t" \ : \ "=d" (tmp) \ : \ "p" (&(var)) \ ); \ tmp; \ }) #else #define GET_FAR_ADDRESS(var) (var) #endif #endif // simple utilities for accessing the asset library in a filesystem-like // way // Details of the flash chip: // http://www.atmel.com/dyn/resources/prod_documents/doc3638.pdf const int FLASHSEL = 2; // flash SPI select pin class Asset { private: uint32_t addr; // pointer into flash memory uint16_t remain; // number of remaing unread bytes byte find_name(const char *name) { // addr points at a directory, scan for name, if found set addr // to the entry and return 1, otherwise return 0. while (true) { static struct { char name[12]; uint16_t length; uint32_t addr; } de; read(&de, sizeof(de)); if (de.name[0] == 0) return 0; // end of dir, no match found if (strcmp(de.name, name) == 0) { remain = de.length; addr = de.addr; return 1; } } } public: int open(const char *d, ...) { va_list ap; va_start(ap, d); addr = 512L * 640; remain = 1024; pinMode(FLASHSEL, OUTPUT); digitalWrite(FLASHSEL, HIGH); do { if (!find_name(d)) return 0; d = va_arg(ap, const char *); } while (d != NULL); return 1; } int read(void *dst, uint16_t n) { GD.wr(IOMODE, 'F'); digitalWrite(FLASHSEL, LOW); SPI.transfer(0x03); SPI.transfer((byte)(addr >> 16)); SPI.transfer((byte)(addr >> 8)); SPI.transfer((byte)(addr >> 0)); uint16_t actual = min(n, remain); // actual bytes read byte *bdst = (byte*)dst; for (uint16_t a = actual; a; a--) { byte b = SPI.transfer(0); *bdst++ = b; addr++; if ((511 & (uint16_t)addr) == 264) addr = addr - 264 + 512; } remain -= actual; digitalWrite(FLASHSEL, HIGH); GD.wr(IOMODE, 0); return actual; } void load(uint16_t dst) { while (remain) { byte buf[16]; uint16_t n = min(remain, sizeof(buf)); read(buf, n); GD.__wstart(dst); for (byte i = 0; i < n; i++) SPI.transfer(buf[i]); GD.__end(); dst += n; } } uint16_t available() { return remain; } }; #endif