Chris Dick / Gameduino

Dependencies:   Arduino

Dependents:   Gameduino_Asteroids_game Gameduino_Ball_demo Gameduino_Bitmap_demo Gameduino_chessboard_demo ... more

Committer:
TheChrisyd
Date:
Thu Dec 20 23:02:36 2012 +0000
Revision:
4:84c1ca3e1be0
Parent:
0:c9523256df08
Updated Arduino library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TheChrisyd 0:c9523256df08 1 /**
TheChrisyd 0:c9523256df08 2 * @section LICENSE
TheChrisyd 0:c9523256df08 3 * Copyright (c) 2012 James Bowman, Chris Dick
TheChrisyd 0:c9523256df08 4 *
TheChrisyd 0:c9523256df08 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
TheChrisyd 0:c9523256df08 6 * of this software and associated documentation files (the "Software"), to deal
TheChrisyd 0:c9523256df08 7 * in the Software without restriction, including without limitation the rights
TheChrisyd 0:c9523256df08 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
TheChrisyd 0:c9523256df08 9 * copies of the Software, and to permit persons to whom the Software is
TheChrisyd 0:c9523256df08 10 * furnished to do so, subject to the following conditions:
TheChrisyd 0:c9523256df08 11 *
TheChrisyd 0:c9523256df08 12 * The above copyright notice and this permission notice shall be included in
TheChrisyd 0:c9523256df08 13 * all copies or substantial portions of the Software.
TheChrisyd 0:c9523256df08 14 *
TheChrisyd 0:c9523256df08 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
TheChrisyd 0:c9523256df08 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
TheChrisyd 0:c9523256df08 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
TheChrisyd 0:c9523256df08 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
TheChrisyd 0:c9523256df08 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
TheChrisyd 0:c9523256df08 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
TheChrisyd 0:c9523256df08 21 * THE SOFTWARE.
TheChrisyd 0:c9523256df08 22 *
TheChrisyd 0:c9523256df08 23 * @section DESCRIPTION
TheChrisyd 0:c9523256df08 24 * Copyright (c) 2011 by James Bowman <jamesb@excamera.com>
TheChrisyd 0:c9523256df08 25 * Gameduino library for mbed. Ported from Arduino by Chris Dick
TheChrisyd 0:c9523256df08 26 *
TheChrisyd 0:c9523256df08 27 *
TheChrisyd 0:c9523256df08 28 *
TheChrisyd 0:c9523256df08 29 *
TheChrisyd 0:c9523256df08 30 */
TheChrisyd 0:c9523256df08 31
TheChrisyd 0:c9523256df08 32 #include "GD.h"
TheChrisyd 0:c9523256df08 33
TheChrisyd 0:c9523256df08 34 GDClass::GDClass(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName utx, PinName urx)
TheChrisyd 0:c9523256df08 35 : gameduino_spi(mosi, miso, sclk)
TheChrisyd 0:c9523256df08 36 , gameduino_cs(cs)
TheChrisyd 0:c9523256df08 37 , pc(utx, urx) {
TheChrisyd 0:c9523256df08 38
TheChrisyd 0:c9523256df08 39 }
TheChrisyd 0:c9523256df08 40
TheChrisyd 0:c9523256df08 41 void GDClass::begin()
TheChrisyd 0:c9523256df08 42 {
TheChrisyd 0:c9523256df08 43 delay(250); // give Gameduino time to boot
TheChrisyd 0:c9523256df08 44 gameduino_spi.format(8,0);
TheChrisyd 0:c9523256df08 45 gameduino_spi.frequency(8000000);
TheChrisyd 0:c9523256df08 46
TheChrisyd 0:c9523256df08 47
TheChrisyd 0:c9523256df08 48 gameduino_cs = 1;
TheChrisyd 0:c9523256df08 49
TheChrisyd 0:c9523256df08 50 wr(J1_RESET, 1); // HALT coprocessor
TheChrisyd 0:c9523256df08 51 __wstart(RAM_SPR); // Hide all sprites
TheChrisyd 0:c9523256df08 52 for (int i = 0; i < 512; i++)
TheChrisyd 0:c9523256df08 53 {
TheChrisyd 0:c9523256df08 54 xhide();
TheChrisyd 0:c9523256df08 55 }
TheChrisyd 0:c9523256df08 56 __end();
TheChrisyd 0:c9523256df08 57 fill(RAM_PIC, 0, 1024 * 10); // Zero all character RAM
TheChrisyd 0:c9523256df08 58 fill(RAM_SPRPAL, 0, 2048); // Sprite palletes black
TheChrisyd 0:c9523256df08 59 fill(RAM_SPRIMG, 0, 64 * 256); // Clear all sprite data
TheChrisyd 0:c9523256df08 60 fill(VOICES, 0, 256); // Silence
TheChrisyd 0:c9523256df08 61 fill(PALETTE16A, 0, 128); // Black 16-, 4-palletes and COMM
TheChrisyd 0:c9523256df08 62
TheChrisyd 0:c9523256df08 63 wr16(SCROLL_X, 0);
TheChrisyd 0:c9523256df08 64 wr16(SCROLL_Y, 0);
TheChrisyd 0:c9523256df08 65 wr(JK_MODE, 0);
TheChrisyd 0:c9523256df08 66 wr(SPR_DISABLE, 0);
TheChrisyd 0:c9523256df08 67 wr(SPR_PAGE, 0);
TheChrisyd 0:c9523256df08 68 wr(IOMODE, 0);
TheChrisyd 0:c9523256df08 69 wr16(BG_COLOR, 0);
TheChrisyd 0:c9523256df08 70 wr16(SAMPLE_L, 0);
TheChrisyd 0:c9523256df08 71 wr16(SAMPLE_R, 0);
TheChrisyd 0:c9523256df08 72 wr16(SCREENSHOT_Y, 0);
TheChrisyd 0:c9523256df08 73 wr(MODULATOR, 64);
TheChrisyd 0:c9523256df08 74 }
TheChrisyd 0:c9523256df08 75
TheChrisyd 0:c9523256df08 76 void GDClass::end() {
TheChrisyd 0:c9523256df08 77 }
TheChrisyd 0:c9523256df08 78
TheChrisyd 0:c9523256df08 79 void GDClass::__start(unsigned int addr) // start an spi transaction to addr
TheChrisyd 0:c9523256df08 80 {
TheChrisyd 0:c9523256df08 81 gameduino_cs = 0;
TheChrisyd 0:c9523256df08 82 gameduino_spi.write(highByte(addr));
TheChrisyd 0:c9523256df08 83 gameduino_spi.write(lowByte(addr));
TheChrisyd 0:c9523256df08 84 }
TheChrisyd 0:c9523256df08 85
TheChrisyd 0:c9523256df08 86 void GDClass::__wstart(unsigned int addr) // start an spi write transaction to addr
TheChrisyd 0:c9523256df08 87 {
TheChrisyd 0:c9523256df08 88 __start(0x8000|addr);
TheChrisyd 0:c9523256df08 89 }
TheChrisyd 0:c9523256df08 90
TheChrisyd 0:c9523256df08 91 void GDClass::__wstartspr(unsigned int sprnum)
TheChrisyd 0:c9523256df08 92 {
TheChrisyd 0:c9523256df08 93 __start((0x8000 | RAM_SPR) + (sprnum << 2));
TheChrisyd 0:c9523256df08 94 spr = 0;
TheChrisyd 0:c9523256df08 95 }
TheChrisyd 0:c9523256df08 96
TheChrisyd 0:c9523256df08 97 void GDClass::__end() // end the spi transaction
TheChrisyd 0:c9523256df08 98 {
TheChrisyd 0:c9523256df08 99 gameduino_cs = 1;
TheChrisyd 0:c9523256df08 100 }
TheChrisyd 0:c9523256df08 101
TheChrisyd 0:c9523256df08 102 byte GDClass::rd(unsigned int addr)
TheChrisyd 0:c9523256df08 103 {
TheChrisyd 0:c9523256df08 104 __start(addr);
TheChrisyd 0:c9523256df08 105 byte r = gameduino_spi.write(0);
TheChrisyd 0:c9523256df08 106 __end();
TheChrisyd 0:c9523256df08 107 return r;
TheChrisyd 0:c9523256df08 108 }
TheChrisyd 0:c9523256df08 109
TheChrisyd 0:c9523256df08 110 void GDClass::wr(unsigned int addr, byte v)
TheChrisyd 0:c9523256df08 111 {
TheChrisyd 0:c9523256df08 112 __wstart(addr);
TheChrisyd 0:c9523256df08 113 gameduino_spi.write(v);
TheChrisyd 0:c9523256df08 114 __end();
TheChrisyd 0:c9523256df08 115 }
TheChrisyd 0:c9523256df08 116
TheChrisyd 0:c9523256df08 117 unsigned int GDClass::rd16(unsigned int addr)
TheChrisyd 0:c9523256df08 118 {
TheChrisyd 0:c9523256df08 119 unsigned int r;
TheChrisyd 0:c9523256df08 120
TheChrisyd 0:c9523256df08 121 __start(addr);
TheChrisyd 0:c9523256df08 122 r = gameduino_spi.write(0);
TheChrisyd 0:c9523256df08 123 r |= (gameduino_spi.write(0) << 8);
TheChrisyd 0:c9523256df08 124 __end();
TheChrisyd 0:c9523256df08 125 return r;
TheChrisyd 0:c9523256df08 126 }
TheChrisyd 0:c9523256df08 127
TheChrisyd 0:c9523256df08 128 void GDClass::wr16(unsigned int addr, unsigned int v)
TheChrisyd 0:c9523256df08 129 {
TheChrisyd 0:c9523256df08 130 __wstart(addr);
TheChrisyd 0:c9523256df08 131 gameduino_spi.write(lowByte(v));
TheChrisyd 0:c9523256df08 132 gameduino_spi.write(highByte(v));
TheChrisyd 0:c9523256df08 133 __end();
TheChrisyd 0:c9523256df08 134 }
TheChrisyd 0:c9523256df08 135
TheChrisyd 0:c9523256df08 136 void GDClass::fill(int addr, byte v, unsigned int count)
TheChrisyd 0:c9523256df08 137 {
TheChrisyd 0:c9523256df08 138 __wstart(addr);
TheChrisyd 0:c9523256df08 139 while (count--)
TheChrisyd 0:c9523256df08 140 gameduino_spi.write(v);
TheChrisyd 0:c9523256df08 141 __end();
TheChrisyd 0:c9523256df08 142 }
TheChrisyd 0:c9523256df08 143
TheChrisyd 0:c9523256df08 144 void GDClass::copy(unsigned int addr, PROGMEM prog_uchar *src, int count)
TheChrisyd 0:c9523256df08 145 {
TheChrisyd 0:c9523256df08 146 __wstart(addr);
TheChrisyd 0:c9523256df08 147 while (count--) {
TheChrisyd 0:c9523256df08 148 gameduino_spi.write(pgm_read_byte_near(src));
TheChrisyd 0:c9523256df08 149 src++;
TheChrisyd 0:c9523256df08 150 }
TheChrisyd 0:c9523256df08 151 __end();
TheChrisyd 0:c9523256df08 152 }
TheChrisyd 0:c9523256df08 153
TheChrisyd 0:c9523256df08 154
TheChrisyd 0:c9523256df08 155
TheChrisyd 0:c9523256df08 156 void GDClass::microcode(PROGMEM prog_uchar *src, int count)
TheChrisyd 0:c9523256df08 157 {
TheChrisyd 0:c9523256df08 158 wr(J1_RESET, 1);
TheChrisyd 0:c9523256df08 159 copy(J1_CODE, src, count);
TheChrisyd 0:c9523256df08 160 wr(J1_RESET, 0);
TheChrisyd 0:c9523256df08 161 }
TheChrisyd 0:c9523256df08 162
TheChrisyd 0:c9523256df08 163
TheChrisyd 0:c9523256df08 164
TheChrisyd 0:c9523256df08 165 void GDClass::setpal(int pal, unsigned int rgb)
TheChrisyd 0:c9523256df08 166 {
TheChrisyd 0:c9523256df08 167 wr16(RAM_PAL + (pal << 1), rgb);
TheChrisyd 0:c9523256df08 168 }
TheChrisyd 0:c9523256df08 169
TheChrisyd 0:c9523256df08 170 void GDClass::sprite(int spr, int x, int y, byte image, byte palette, byte rot, byte jk)
TheChrisyd 0:c9523256df08 171 {
TheChrisyd 0:c9523256df08 172 __wstart(RAM_SPR + (spr << 2));
TheChrisyd 0:c9523256df08 173 gameduino_spi.write(lowByte(x));
TheChrisyd 0:c9523256df08 174 gameduino_spi.write((palette << 4) | (rot << 1) | (highByte(x) & 1));
TheChrisyd 0:c9523256df08 175 gameduino_spi.write(lowByte(y));
TheChrisyd 0:c9523256df08 176 gameduino_spi.write((jk << 7) | (image << 1) | (highByte(y) & 1));
TheChrisyd 0:c9523256df08 177 __end();
TheChrisyd 0:c9523256df08 178 }
TheChrisyd 0:c9523256df08 179
TheChrisyd 0:c9523256df08 180 void GDClass::xsprite(int ox, int oy, signed char x, signed char y, byte image, byte palette, byte rot, byte jk)
TheChrisyd 0:c9523256df08 181 {
TheChrisyd 0:c9523256df08 182 if (rot & 2)
TheChrisyd 0:c9523256df08 183 x = -16-x;
TheChrisyd 0:c9523256df08 184 if (rot & 4)
TheChrisyd 0:c9523256df08 185 y = -16-y;
TheChrisyd 0:c9523256df08 186 if (rot & 1) {
TheChrisyd 0:c9523256df08 187 int s;
TheChrisyd 0:c9523256df08 188 s = x; x = y; y = s;
TheChrisyd 0:c9523256df08 189 }
TheChrisyd 0:c9523256df08 190 ox += x;
TheChrisyd 0:c9523256df08 191 oy += y;
TheChrisyd 0:c9523256df08 192 gameduino_spi.write(lowByte(ox));
TheChrisyd 0:c9523256df08 193 gameduino_spi.write((palette << 4) | (rot << 1) | (highByte(ox) & 1));
TheChrisyd 0:c9523256df08 194 gameduino_spi.write(lowByte(oy));
TheChrisyd 0:c9523256df08 195 gameduino_spi.write((jk << 7) | (image << 1) | (highByte(oy) & 1));
TheChrisyd 0:c9523256df08 196 spr++;
TheChrisyd 0:c9523256df08 197 }
TheChrisyd 0:c9523256df08 198
TheChrisyd 0:c9523256df08 199 void GDClass::xhide()
TheChrisyd 0:c9523256df08 200 {
TheChrisyd 0:c9523256df08 201 gameduino_spi.write(lowByte(400));
TheChrisyd 0:c9523256df08 202 gameduino_spi.write(highByte(400));
TheChrisyd 0:c9523256df08 203 gameduino_spi.write(lowByte(400));
TheChrisyd 0:c9523256df08 204 gameduino_spi.write(highByte(400));
TheChrisyd 0:c9523256df08 205 spr++;
TheChrisyd 0:c9523256df08 206 }
TheChrisyd 0:c9523256df08 207
TheChrisyd 0:c9523256df08 208 void GDClass::plots(int ox, int oy, PROGMEM sprplot *psp, byte count, byte rot, byte jk)
TheChrisyd 0:c9523256df08 209 {
TheChrisyd 0:c9523256df08 210 while (count--) {
TheChrisyd 0:c9523256df08 211 struct sprplot sp;
TheChrisyd 0:c9523256df08 212 sp = *psp++;
TheChrisyd 0:c9523256df08 213 xsprite(ox, oy, sp.x, sp.y, sp.image, sp.palette, rot, jk);
TheChrisyd 0:c9523256df08 214 }
TheChrisyd 0:c9523256df08 215 }
TheChrisyd 0:c9523256df08 216
TheChrisyd 0:c9523256df08 217 void GDClass::sprite2x2(int spr, int x, int y, byte image, byte palette, byte rot, byte jk)
TheChrisyd 0:c9523256df08 218 {
TheChrisyd 0:c9523256df08 219 __wstart(0x3000 + (spr << 2));
TheChrisyd 0:c9523256df08 220 xsprite(x, y, -16, -16, image + 0, palette, rot, jk);
TheChrisyd 0:c9523256df08 221 xsprite(x, y, 0, -16, image + 1, palette, rot, jk);
TheChrisyd 0:c9523256df08 222 xsprite(x, y, -16, 0, image + 2, palette, rot, jk);
TheChrisyd 0:c9523256df08 223 xsprite(x, y, 0, 0, image + 3, palette, rot, jk);
TheChrisyd 0:c9523256df08 224 __end();
TheChrisyd 0:c9523256df08 225 }
TheChrisyd 0:c9523256df08 226
TheChrisyd 0:c9523256df08 227 void GDClass::waitvblank()
TheChrisyd 0:c9523256df08 228 {
TheChrisyd 0:c9523256df08 229 // Wait for the VLANK to go from 0 to 1: this is the start
TheChrisyd 0:c9523256df08 230 // of the vertical blanking interval.
TheChrisyd 0:c9523256df08 231
TheChrisyd 0:c9523256df08 232 while (rd(VBLANK) == 1)
TheChrisyd 0:c9523256df08 233 ;
TheChrisyd 0:c9523256df08 234 while (rd(VBLANK) == 0)
TheChrisyd 0:c9523256df08 235 ;
TheChrisyd 0:c9523256df08 236 }
TheChrisyd 0:c9523256df08 237
TheChrisyd 0:c9523256df08 238 /* Fixed ascii font, useful for debug */
TheChrisyd 0:c9523256df08 239
TheChrisyd 0:c9523256df08 240 #include "font8x8.h"
TheChrisyd 0:c9523256df08 241 static byte stretch[16] = {
TheChrisyd 0:c9523256df08 242 0x00, 0x03, 0x0c, 0x0f,
TheChrisyd 0:c9523256df08 243 0x30, 0x33, 0x3c, 0x3f,
TheChrisyd 0:c9523256df08 244 0xc0, 0xc3, 0xcc, 0xcf,
TheChrisyd 0:c9523256df08 245 0xf0, 0xf3, 0xfc, 0xff
TheChrisyd 0:c9523256df08 246 };
TheChrisyd 0:c9523256df08 247
TheChrisyd 0:c9523256df08 248
TheChrisyd 0:c9523256df08 249 void GDClass::ascii()
TheChrisyd 0:c9523256df08 250 {
TheChrisyd 0:c9523256df08 251 long i;
TheChrisyd 0:c9523256df08 252 for (i = 0; i < 768; i++) {
TheChrisyd 0:c9523256df08 253 byte b = font8x8[i];
TheChrisyd 0:c9523256df08 254 byte h = stretch[b >> 4];
TheChrisyd 0:c9523256df08 255 byte l = stretch[b & 0xf];
TheChrisyd 0:c9523256df08 256 wr(0x1000 + (16 * ' ') + (2 * i), h);
TheChrisyd 0:c9523256df08 257 wr(0x1000 + (16 * ' ') + (2 * i) + 1, l);
TheChrisyd 0:c9523256df08 258 }
TheChrisyd 0:c9523256df08 259 for (i = 0x20; i < 0x80; i++) {
TheChrisyd 0:c9523256df08 260 setpal(4 * i + 0, TRANSPARENT);
TheChrisyd 0:c9523256df08 261 setpal(4 * i + 3, RGB(255,255,255));
TheChrisyd 0:c9523256df08 262 }
TheChrisyd 0:c9523256df08 263 fill(RAM_PIC, ' ', 4096);
TheChrisyd 0:c9523256df08 264 }
TheChrisyd 0:c9523256df08 265
TheChrisyd 0:c9523256df08 266 void GDClass::putstr(int x, int y, const char *s)
TheChrisyd 0:c9523256df08 267 {
TheChrisyd 0:c9523256df08 268 __wstart((y << 6) + x);
TheChrisyd 0:c9523256df08 269 while (*s)
TheChrisyd 0:c9523256df08 270 gameduino_spi.write(*s++);
TheChrisyd 0:c9523256df08 271 __end();
TheChrisyd 0:c9523256df08 272 }
TheChrisyd 0:c9523256df08 273
TheChrisyd 0:c9523256df08 274 void GDClass::voice(int v, byte wave, unsigned int freq, byte lamp, byte ramp)
TheChrisyd 0:c9523256df08 275 {
TheChrisyd 0:c9523256df08 276 __wstart(VOICES + (v << 2));
TheChrisyd 0:c9523256df08 277 gameduino_spi.write(lowByte(freq));
TheChrisyd 0:c9523256df08 278 gameduino_spi.write(highByte(freq) | (wave << 7));
TheChrisyd 0:c9523256df08 279 gameduino_spi.write(lamp);
TheChrisyd 0:c9523256df08 280 gameduino_spi.write(ramp);
TheChrisyd 0:c9523256df08 281 __end();
TheChrisyd 0:c9523256df08 282 }
TheChrisyd 0:c9523256df08 283
TheChrisyd 0:c9523256df08 284 void GDClass::screenshot(unsigned int frame)
TheChrisyd 0:c9523256df08 285 {
TheChrisyd 0:c9523256df08 286 int yy, xx;
TheChrisyd 0:c9523256df08 287 byte undone[38]; // 300-long bitmap of lines pending
TheChrisyd 0:c9523256df08 288
TheChrisyd 0:c9523256df08 289 // initialize to 300 ones
TheChrisyd 0:c9523256df08 290 memset(undone, 0xff, 37);
TheChrisyd 0:c9523256df08 291 undone[37] = 0xf;
TheChrisyd 0:c9523256df08 292 int nundone = 300;
TheChrisyd 0:c9523256df08 293
TheChrisyd 0:c9523256df08 294 pc.putc(0xa5); // sync byte
TheChrisyd 0:c9523256df08 295 pc.putc(lowByte(frame));
TheChrisyd 0:c9523256df08 296 pc.putc(highByte(frame));
TheChrisyd 0:c9523256df08 297
TheChrisyd 0:c9523256df08 298 while (nundone) {
TheChrisyd 0:c9523256df08 299 // find a pending line a short distance ahead of the raster
TheChrisyd 0:c9523256df08 300 int hwline = rd16(SCREENSHOT_Y) & 0x1ff;
TheChrisyd 0:c9523256df08 301 for (yy = (hwline + 7) % 300; ((undone[yy>>3] >> (yy&7)) & 1) == 0; yy = (yy + 1) % 300)
TheChrisyd 0:c9523256df08 302 ;
TheChrisyd 0:c9523256df08 303 wr16(SCREENSHOT_Y, 0x8000 | yy); // ask for it
TheChrisyd 0:c9523256df08 304
TheChrisyd 0:c9523256df08 305 // housekeeping while waiting: mark line done and send yy
TheChrisyd 0:c9523256df08 306 undone[yy>>3] ^= (1 << (yy&7));
TheChrisyd 0:c9523256df08 307 nundone--;
TheChrisyd 0:c9523256df08 308 pc.putc(lowByte(yy));
TheChrisyd 0:c9523256df08 309 pc.putc(highByte(yy));
TheChrisyd 0:c9523256df08 310 while ((rd(SCREENSHOT_Y + 1) & 0x80) == 0)
TheChrisyd 0:c9523256df08 311 ;
TheChrisyd 0:c9523256df08 312
TheChrisyd 0:c9523256df08 313 // Now send the line, compressing zero pixels
TheChrisyd 0:c9523256df08 314 uint16_t zeroes = 0;
TheChrisyd 0:c9523256df08 315 for (xx = 0; xx < 800; xx += 2) {
TheChrisyd 0:c9523256df08 316 uint16_t v = rd16(SCREENSHOT + xx);
TheChrisyd 0:c9523256df08 317 if (v == 0) {
TheChrisyd 0:c9523256df08 318 zeroes++;
TheChrisyd 0:c9523256df08 319 } else {
TheChrisyd 0:c9523256df08 320 if (zeroes) {
TheChrisyd 0:c9523256df08 321 pc.putc(lowByte(zeroes));
TheChrisyd 0:c9523256df08 322 pc.putc(0x80 | highByte(zeroes));
TheChrisyd 0:c9523256df08 323 zeroes = 0;
TheChrisyd 0:c9523256df08 324 }
TheChrisyd 0:c9523256df08 325 pc.putc(lowByte(v));
TheChrisyd 0:c9523256df08 326 pc.putc(highByte(v));
TheChrisyd 0:c9523256df08 327 }
TheChrisyd 0:c9523256df08 328 }
TheChrisyd 0:c9523256df08 329 if (zeroes) {
TheChrisyd 0:c9523256df08 330 pc.putc(lowByte(zeroes));
TheChrisyd 0:c9523256df08 331 pc.putc(0x80 | highByte(zeroes));
TheChrisyd 0:c9523256df08 332 }
TheChrisyd 0:c9523256df08 333 }
TheChrisyd 0:c9523256df08 334 wr16(SCREENSHOT_Y, 0); // restore screen to normal
TheChrisyd 0:c9523256df08 335 }
TheChrisyd 0:c9523256df08 336
TheChrisyd 0:c9523256df08 337 class GDflashbits {
TheChrisyd 0:c9523256df08 338 public:
TheChrisyd 0:c9523256df08 339 void begin(PROGMEM prog_uchar *s) {
TheChrisyd 0:c9523256df08 340 src = s;
TheChrisyd 0:c9523256df08 341 mask = 0x01;
TheChrisyd 0:c9523256df08 342 }
TheChrisyd 0:c9523256df08 343 byte get1(void) {
TheChrisyd 0:c9523256df08 344 byte r = (pgm_read_byte_near(src) & mask) != 0;
TheChrisyd 0:c9523256df08 345 mask <<= 1;
TheChrisyd 0:c9523256df08 346 if (!mask) {
TheChrisyd 0:c9523256df08 347 mask = 1;
TheChrisyd 0:c9523256df08 348 src++;
TheChrisyd 0:c9523256df08 349 }
TheChrisyd 0:c9523256df08 350 return r;
TheChrisyd 0:c9523256df08 351 }
TheChrisyd 0:c9523256df08 352 unsigned short getn(byte n) {
TheChrisyd 0:c9523256df08 353 unsigned short r = 0;
TheChrisyd 0:c9523256df08 354 while (n--) {
TheChrisyd 0:c9523256df08 355 r <<= 1;
TheChrisyd 0:c9523256df08 356 r |= get1();
TheChrisyd 0:c9523256df08 357 }
TheChrisyd 0:c9523256df08 358 return r;
TheChrisyd 0:c9523256df08 359 }
TheChrisyd 0:c9523256df08 360 private:
TheChrisyd 0:c9523256df08 361 PROGMEM prog_uchar *src;
TheChrisyd 0:c9523256df08 362 byte mask;
TheChrisyd 0:c9523256df08 363 };
TheChrisyd 0:c9523256df08 364
TheChrisyd 0:c9523256df08 365 static GDflashbits GDFB;
TheChrisyd 0:c9523256df08 366
TheChrisyd 0:c9523256df08 367 void GDClass::uncompress(unsigned int addr, PROGMEM prog_uchar *src)
TheChrisyd 0:c9523256df08 368 {
TheChrisyd 0:c9523256df08 369 GDFB.begin(src);
TheChrisyd 0:c9523256df08 370 byte b_off = GDFB.getn(4);
TheChrisyd 0:c9523256df08 371 byte b_len = GDFB.getn(4);
TheChrisyd 0:c9523256df08 372 byte minlen = GDFB.getn(2);
TheChrisyd 0:c9523256df08 373 unsigned short items = GDFB.getn(16);
TheChrisyd 0:c9523256df08 374 while (items--) {
TheChrisyd 0:c9523256df08 375 if (GDFB.get1() == 0) {
TheChrisyd 0:c9523256df08 376 wr(addr++, GDFB.getn(8));
TheChrisyd 0:c9523256df08 377 } else {
TheChrisyd 0:c9523256df08 378 int offset = -GDFB.getn(b_off) - 1;
TheChrisyd 0:c9523256df08 379 int l = GDFB.getn(b_len) + minlen;
TheChrisyd 0:c9523256df08 380 while (l--) {
TheChrisyd 0:c9523256df08 381 wr(addr, rd(addr + offset));
TheChrisyd 0:c9523256df08 382 addr++;
TheChrisyd 0:c9523256df08 383 }
TheChrisyd 0:c9523256df08 384 }
TheChrisyd 0:c9523256df08 385 }
TheChrisyd 0:c9523256df08 386 }