spinal cord / PokittoLib

Dependents:   Sensitive

Fork of PokittoLib by Jonne Valola

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PokittoDisplay.cpp Source File

PokittoDisplay.cpp

Go to the documentation of this file.
00001 /**************************************************************************/
00002 /*!
00003     @file     PokittoDisplay.cpp
00004     @author   Jonne Valola
00005 
00006     @section LICENSE
00007 
00008     Software License Agreement (BSD License)
00009 
00010     Copyright (c) 2016, Jonne Valola
00011     All rights reserved.
00012 
00013     Redistribution and use in source and binary forms, with or without
00014     modification, are permitted provided that the following conditions are met:
00015     1. Redistributions of source code must retain the above copyright
00016     notice, this list of conditions and the following disclaimer.
00017     2. Redistributions in binary form must reproduce the above copyright
00018     notice, this list of conditions and the following disclaimer in the
00019     documentation and/or other materials provided with the distribution.
00020     3. Neither the name of the copyright holders nor the
00021     names of its contributors may be used to endorse or promote products
00022     derived from this software without specific prior written permission.
00023 
00024     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
00025     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00028     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 */
00035 /**************************************************************************/
00036 
00037 
00038 /* THE SEGMENT BELOW PERTAINS TO CIRCLE DRAWING FUNCTIONS ONLY
00039 *
00040 This is the core graphics library for all our displays, providing a common
00041 set of graphics primitives (points, lines, circles, etc.).  It needs to be
00042 paired with a hardware-specific library for each display device we carry
00043 (to handle the lower-level functions).
00044 Adafruit invests time and resources providing this open source code, please
00045 support Adafruit & open-source hardware by purchasing products from Adafruit!
00046 Copyright (c) 2013 Adafruit Industries.  All rights reserved.
00047 Redistribution and use in source and binary forms, with or without
00048 modification, are permitted provided that the following conditions are met:
00049 - Redistributions of source code must retain the above copyright notice,
00050   this list of conditions and the following disclaimer.
00051 - Redistributions in binary form must reproduce the above copyright notice,
00052   this list of conditions and the following disclaimer in the documentation
00053   and/or other materials provided with the distribution.
00054 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00055 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00056 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00057 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00058 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00059 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00060 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00061 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00062 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00063 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00064 POSSIBILITY OF SUCH DAMAGE.
00065 */
00066 
00067 #include "PokittoDisplay.h "
00068 #include "Pokitto_settings.h "
00069 #include "GBcompatibility.h"
00070 #include "PokittoCore.h "
00071 #include "PokittoSound.h "
00072 #include <stdio.h>
00073 #include <string.h>
00074 
00075 #ifndef POK_SIM
00076 #include "HWLCD.h "
00077 #else
00078 #include "SimLCD.h"
00079 #endif
00080 
00081 Pokitto::Core core;
00082 Pokitto::Sound sound;
00083 
00084 using namespace Pokitto;
00085 
00086 
00087 
00088 uint8_t* Display::m_scrbuf;
00089 uint8_t* Display::m_tileset;
00090 uint8_t* Display::m_tilebuf;
00091 uint8_t* Display::m_tilecolorbuf;
00092 uint8_t Display::m_mode, Display::m_colordepth;
00093 uint8_t Display::fontSize=1;
00094 int16_t Display::cursorX,Display::cursorY;
00095 uint16_t Display::m_w,Display::m_h;
00096 uint8_t Display::fontWidth, Display::fontHeight;
00097 bool Display::textWrap=true;
00098 
00099 uint8_t Display::persistence = 0;
00100 uint16_t Display::color = 1;
00101 uint16_t Display::bgcolor = 0;
00102 uint16_t Display::invisiblecolor = 17;
00103 uint16_t Display::directcolor=0xFFFF;
00104 uint16_t Display::directbgcolor=0x0;
00105 
00106 uint16_t* Display::paletteptr;
00107 uint16_t Display::palette[PALETTE_SIZE];
00108 const unsigned char* Display::font;
00109 int8_t Display::adjustCharStep = 1;
00110 int8_t Display::adjustLineStep = 1;
00111 bool Display::fixedWidthFont = false;
00112 
00113 /** drawing canvas **/
00114 //uint8_t* Display::canvas; // points to the active buffer. if null, draw direct to screen
00115 
00116 /** screenbuffer **/
00117 uint8_t Display::bpp = POK_COLORDEPTH;
00118 #ifndef POK_TILEDMODE
00119 #if (POK_SCREENMODE == MODE_HI_MONOCHROME)
00120     uint8_t Display::width = POK_LCD_W;
00121     uint8_t Display::height = POK_LCD_H;
00122     uint8_t Display::screenbuffer[((POK_LCD_H+1)*POK_LCD_W)*POK_COLORDEPTH/8]; // maximum resolution
00123 #elif (POK_SCREENMODE == MODE_HI_4COLOR)
00124     uint8_t Display::width = POK_LCD_W;
00125     uint8_t Display::height = POK_LCD_H;
00126     uint8_t __attribute__((section (".bss"))) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
00127 #elif (POK_SCREENMODE == MODE_FAST_16COLOR)
00128     uint8_t Display::width = POK_LCD_W/2;
00129     uint8_t Display::height = POK_LCD_H/2;
00130     uint8_t Display::screenbuffer[(((POK_LCD_H/2)+1)*POK_LCD_W/2)*POK_COLORDEPTH/8]; // half resolution
00131 #elif (POK_SCREENMODE == MODE_HI_16COLOR)
00132     uint8_t Display::width = POK_LCD_W;
00133     uint8_t Display::height = POK_LCD_H;
00134     uint8_t Display::screenbuffer[POK_LCD_H*POK_LCD_W/2]; // 4 bits per pixel
00135 #elif (POK_SCREENMODE == MODE_LAMENES)
00136     uint8_t Display::width = 128;
00137     uint8_t Display::height = 120;
00138     uint8_t Display::screenbuffer[((121)*128)*POK_COLORDEPTH/8]; // half resolution
00139 #elif (POK_SCREENMODE == MODE_GAMEBOY)
00140     uint8_t Display::width = 160;
00141     uint8_t Display::height = 144;
00142     uint8_t Display::screenbuffer[160*144/4];
00143 #else
00144     uint8_t Display::width = 84;
00145     uint8_t Display::height = 48;
00146     uint8_t Display::screenbuffer[128*64]; // not needed because Gamebuino and Arduboy have their own buffer
00147 #endif
00148 #else //Tiledmode
00149 #if (POK_SCREENMODE == MODE_TILED_1BIT)
00150     uint8_t Display::width = POK_LCD_W;
00151     uint8_t Display::height = POK_LCD_H;
00152     uint8_t Display::screenbuffer[0];
00153 #else
00154     uint8_t Display::width = POK_LCD_W;
00155     uint8_t Display::height = POK_LCD_H;
00156     uint8_t Display::screenbuffer[0];
00157 #endif
00158 #endif //tiledmode
00159 
00160 // RLE decoding
00161 #define RLE_ESC_EOL 0
00162 #define RLE_ESC_EOB 1
00163 #define RLE_ESC_OFFSET 2
00164 
00165 Display::Display() {
00166     m_scrbuf = screenbuffer;
00167     setDefaultPalette();
00168     m_mode = 1; // direct printing on by default
00169     m_w = POK_LCD_W;
00170     m_h = POK_LCD_H;
00171     setFont(DEFAULT_FONT);
00172     invisiblecolor=17;
00173     bgcolor=0;
00174     if (POK_COLORDEPTH) m_colordepth = POK_COLORDEPTH;
00175     else m_colordepth = 4;
00176     #if POK_GAMEBUINO_SUPPORT
00177     setColorDepth(1);
00178     #endif // POK_GAMEBUINO_SUPPORT
00179 }
00180 
00181 uint16_t Display::getWidth() {
00182     return width;
00183 }
00184 
00185 uint8_t Display::getNumberOfColors() {
00186     return 1<<POK_COLORDEPTH;
00187 }
00188 
00189 uint16_t Display::getHeight() {
00190     return height;
00191 }
00192 
00193 uint8_t Display::getColorDepth() {
00194     return m_colordepth;
00195 }
00196 
00197 void Display::setColorDepth(uint8_t v) {
00198     if (v > POK_COLORDEPTH) v=POK_COLORDEPTH;
00199     m_colordepth = v;
00200 }
00201 
00202 void Display::clearLCD() {
00203     lcdFillSurface(0);
00204     setCursor(0,0); // old basic computer style
00205 }
00206 
00207 void Display::fillLCD(uint16_t c) {
00208     lcdFillSurface(c);
00209 }
00210 
00211 void Display::directPixel(int16_t x, int16_t y, uint16_t color) {
00212     lcdPixel(x,y,color);
00213 }
00214 
00215 void Display::directTile(int16_t x, int16_t y, int16_t x2, int16_t y2, uint16_t* gfx) {
00216     lcdTile(x,y,x2,y2,gfx);
00217 }
00218 
00219 void Display::directRectangle(int16_t x, int16_t y,int16_t x2, int16_t y2, uint16_t color) {
00220     lcdRectangle(x,y,x2,y2,color);
00221 }
00222 
00223 void Display::begin() {
00224     lcdInit();
00225 }
00226 
00227 void Display::setCursor(int16_t x,int16_t y) {
00228     cursorX = x;
00229     cursorY = y;
00230 }
00231 
00232 void Display::update() {
00233 
00234 #if POK_SCREENMODE == MODE_GAMEBOY
00235     lcdRefreshModeGBC(m_scrbuf, paletteptr);
00236 #endif
00237 
00238 #if POK_SCREENMODE == MODE_HI_4COLOR
00239     lcdRefreshMode1(m_scrbuf, paletteptr);
00240 #endif
00241 
00242 #if POK_SCREENMODE == MODE_HI_16COLOR
00243     lcdRefreshMode3(m_scrbuf, paletteptr);
00244 #endif
00245 
00246 #if POK_SCREENMODE == MODE_FAST_16COLOR
00247     lcdRefreshMode2(m_scrbuf, paletteptr);
00248 #endif
00249 
00250 #if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR
00251     lcdRefreshGB(m_scrbuf, paletteptr);
00252 #endif
00253 
00254 #if POK_SCREENMODE == MODE_ARDUBOY_16COLOR
00255     lcdRefreshAB(m_scrbuf, paletteptr);
00256 #endif
00257 
00258 #if POK_SCREENMODE == MODE_TILED_1BIT
00259     lcdRefreshT1(m_tilebuf, m_tilecolorbuf, m_tileset, paletteptr);
00260 #endif
00261 
00262 if (!persistence) clear();
00263 
00264 /** draw volume bar if visible **/
00265 #if POK_SHOW_VOLUME > 0
00266 if (core.volbar_visible) {
00267         core.drawvolbar(4,20,sound.getVolume(),true);
00268         core.volbar_visible--;
00269 }
00270 #endif // POK_SHOW_VOLUME
00271 
00272 }
00273 
00274 void Display::directBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t depth, uint8_t scale) {
00275     uint8_t w = *bitmap;
00276     uint8_t h = *(bitmap + 1);
00277     bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
00278     int16_t i, j;
00279     int8_t byteNum, bitNum, byteWidth = (w + 7) >> 3;
00280 
00281     if (depth == 1) {
00282         for (i = 0; i < w; i++) {
00283             byteNum = i / 8;
00284             bitNum = i % 8;
00285             for (j = 0; j < h; j++) {
00286                 if (*(bitmap + j * byteWidth + byteNum) & (0x80 >> bitNum)) { //0x80 = B10000000
00287                     if (scale==1) directPixel(x + i, y + j,directcolor);
00288                     else {
00289                         directPixel(x + i + i, y + j + j,directcolor);
00290                         directPixel(x + 1 + i + i, y + j + j,directcolor);
00291                         directPixel(x + i + i, y + j + j + 1,directcolor);
00292                         directPixel(x + i + i + 1 , y + j + j + 1,directcolor);
00293                     }
00294                 }
00295             }
00296         }
00297     } else if (depth == 4) {
00298         for (j = 0; j < h; j+=1) {
00299             for (i = 0; i < w; i+=2) {
00300                 uint16_t col = paletteptr[*bitmap>>4]; //higher nibble
00301                 if (scale==2) {
00302                         directPixel(x + (i<<1), y + (j<<1),col);
00303                         directPixel(x + (i<<1) + 1, y + (j<<1),col);
00304                         directPixel(x + (i<<1) + 1, y + (j<<1) + 1,col);
00305                         directPixel(x + (i<<1), y + (j<<1) + 1,col);
00306                 } else directPixel(x + i, y + j,col);
00307                 col = paletteptr[*bitmap&0xF]; // lower nibble
00308                 if (scale==2) {
00309                         directPixel(x + (i<<1) + 2, y + (j<<1),col);
00310                         directPixel(x + (i<<1) + 1 + 2, y + (j<<1),col);
00311                         directPixel(x + (i<<1) + 1 + 2, y + (j<<1) + 1,col);
00312                         directPixel(x + (i<<1) + 2 , y + (j<<1) + 1,col);
00313                 } else directPixel(x + i + 1, y + j,col);
00314                 bitmap++;
00315             }
00316         }
00317     }
00318 
00319 }
00320 
00321 int Display::directChar(int16_t x, int16_t y, uint16_t index){
00322     const uint8_t* bitmap = font;
00323     uint8_t w = *bitmap;
00324     uint8_t h = *(bitmap + 1);
00325     uint8_t hbytes=0, xtra=1;
00326     if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit
00327     hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes
00328     //bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
00329     bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !)
00330     //int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
00331     int8_t i, j, numBytes;
00332     numBytes = *bitmap++; //first byte of char is the width in bytes
00333     // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
00334     uint16_t bitcolumn; //16 bits for 2x8 bit high characters
00335 
00336     for (i = 0; i < numBytes; i++) {
00337             bitcolumn = *bitmap++;
00338             if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
00339             for (j = 0; j < h; j++) {
00340                 if (bitcolumn&0x1) {
00341                     if (fontSize==2) {
00342                         directPixel(x + (i<<1)  , y + (j<<1),directcolor);
00343                         directPixel(x + (i<<1)+1, y + (j<<1),directcolor);
00344                         directPixel(x + (i<<1)  , y + (j<<1)+1,directcolor);
00345                         directPixel(x + (i<<1)+1, y + (j<<1)+1,directcolor);
00346                     } else directPixel(x + i, y + j,directcolor);
00347                 } else if (directbgcolor != invisiblecolor) {
00348                     if (fontSize==2) {
00349                         directPixel(x + (i<<1)  , y + (j<<1),directbgcolor);
00350                         directPixel(x + (i<<1)+1, y + (j<<1),directbgcolor);
00351                         directPixel(x + (i<<1)  , y + (j<<1)+1,directbgcolor);
00352                         directPixel(x + (i<<1)+1, y + (j<<1)+1,directbgcolor);
00353                     } else directPixel(x + i, y + j,directbgcolor);
00354                 }
00355                 bitcolumn>>=1;
00356             }
00357     }
00358     return (numBytes+adjustCharStep)*fontSize; // for character stepping
00359 }
00360 
00361 int Display::bufferChar(int16_t x, int16_t y, uint16_t index){
00362     const uint8_t* bitmap = font;
00363     uint8_t w = *bitmap;
00364     uint8_t h = *(bitmap + 1);
00365     uint8_t hbytes=0, xtra=1;
00366     if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit
00367     hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes
00368     //bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
00369     bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !)
00370     //int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
00371     int8_t i, j, numBytes;
00372     numBytes = *bitmap++; //first byte of char is the width in bytes
00373     // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
00374     uint16_t bitcolumn; //16 bits for 2x8 bit high characters
00375 
00376     for (i = 0; i < numBytes; i++) {
00377             bitcolumn = *bitmap++;
00378             if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
00379             for (j = 0; j <= h; j++) { // was j<=h
00380                 #if PROJ_ARDUBOY > 0
00381                 if (bitcolumn&0x1) {
00382                     drawPixel(x + i, y + 7 - j,color);
00383                 } else drawPixel(x + i, y + 7 - j,bgcolor);
00384                 bitcolumn>>=1;
00385                 #else
00386                 if (bitcolumn&0x1) {
00387                     drawPixel(x + i, y + j,color);
00388                 } else drawPixel(x + i, y + j,bgcolor);
00389                 bitcolumn>>=1;
00390                 #endif // PROJ_ARDUBOY
00391 
00392             }
00393     }
00394 
00395     return numBytes+adjustCharStep; // for character stepping
00396 }
00397 
00398 void Display::clear() {
00399 
00400     uint8_t c=0;
00401     c = bgcolor & (PALETTE_SIZE-1) ; //don't let palette go out of bounds
00402     if (bpp==1 && bgcolor) c=0xFF; // bgcolor !=0, set all pixels
00403     else if (bpp==2) {
00404         c = bgcolor & 0x3;
00405         c = c | (c << 2);
00406         c = c | (c << 4);
00407     } else {
00408         c = (c & 0x0F) | (c << 4);
00409     }
00410     uint16_t j = sizeof(screenbuffer);
00411     memset((void*)m_scrbuf,c,j);
00412 
00413     setCursor(0,0);
00414 
00415 }
00416 
00417 void Display::scroll(int16_t pixelrows) {
00418     uint16_t index = 0, index2,oc;
00419     if (pixelrows==0) return;
00420     if (pixelrows >= height) pixelrows=height-1;
00421     if (bpp == 4) index2 = pixelrows*width/2;
00422     else if (bpp == 2) index2 = pixelrows*width/4;
00423     else return;
00424     oc = color;
00425     color = bgcolor;
00426     if (pixelrows>0) {
00427     for (uint16_t y=0;y<height-pixelrows;y++) {
00428             for (uint16_t x=0;x<(width/8)*bpp;x++) screenbuffer[index++]=screenbuffer[index2++];
00429     }
00430     fillRect(0,cursorY,width,height);
00431     } else {
00432     for (uint16_t y=pixelrows;y<height;y++) {
00433             for (uint16_t x=0;x<(width*bpp)/8;x++) screenbuffer[index2++]=screenbuffer[index2];
00434     }
00435     fillRect(0,0,width,pixelrows);
00436     }
00437     color=oc;
00438 }
00439 
00440 void Display::fillScreen(uint16_t c) {
00441     c = c & (PALETTE_SIZE-1) ; //don't let palette go out of bounds
00442     if (bpp==1 && c) c=0xFF; // set all pixels
00443     else if (bpp==2) {
00444         c = bgcolor & 0x3;
00445         c = c | (c << 2);
00446         c = c | (c << 4);
00447     } else {
00448         c = (c & 0x0F) | (c << 4);
00449     }
00450     memset((void*)m_scrbuf,c,sizeof(screenbuffer));
00451 }
00452 
00453 void Display::setDefaultPalette() {
00454     #if PICOPALETTE
00455         loadRGBPalette(palettePico);
00456     #else
00457         loadRGBPalette(POK_DEFAULT_PALETTE);
00458     #endif //PICOPALETTE
00459 }
00460 
00461 void Display::setColor(uint8_t c) {
00462     color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
00463 }
00464 
00465 void Display::setColor(uint8_t c,uint8_t bgc){
00466     color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
00467     bgcolor = bgc & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
00468 }
00469 
00470 void Display::setInvisibleColor(uint16_t c){
00471     invisiblecolor = c; // invisible color can have values beyond 255 for identification purposes
00472 }
00473 
00474 uint8_t Display::getColor() {
00475     return color;
00476 }
00477 
00478 uint8_t Display::getBgColor() {
00479     return bgcolor;
00480 }
00481 
00482 uint16_t Display::getInvisibleColor() {
00483     return invisiblecolor;
00484 }
00485 
00486 void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
00487     if (col==invisiblecolor) return; // do not draw transparent pixels
00488     if ((uint16_t)x >= width || (uint16_t)y >= height) return;
00489     col &= (PALETTE_SIZE-1);
00490     #if POK_GAMEBUINO_SUPPORT >0
00491 
00492     uint8_t c = col;
00493     uint8_t ct = col;
00494 
00495     uint16_t bitptr=0;
00496     for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
00497     c = ct & 1; // take the lowest bit of the color index number
00498     if(c == 0){ //white - or actually "Clear bit"
00499         m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
00500     } else { //black - or actually "Set bit"
00501         m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
00502     }
00503     ct >>=1; // shift to get next bit
00504     bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
00505     } // POK_COLOURDEPTH
00506 
00507     #else
00508     #if POK_COLORDEPTH == 1
00509         if (col) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
00510         m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
00511     #elif POK_COLORDEPTH == 2
00512         if (col) {
00513                 col &= 3;
00514         }
00515         uint16_t i = y*(width>>2) + (x>>2);
00516         uint8_t pixel = m_scrbuf[i];
00517         uint8_t column = x&0x03;
00518         if (column==3) pixel = (pixel&0xFC)|(col); // bits 0-1
00519         else if (column==2) pixel = (pixel&0xF3)|(col<<2); // bits 2-3
00520         else if (column==1) pixel = (pixel&0xCF)|(col<<4); // bits 4-5
00521         else pixel = (pixel&0x3F)|(col<<6); // bits 6-7
00522         m_scrbuf[i] = pixel;
00523     #elif POK_COLORDEPTH == 3
00524     #elif POK_COLORDEPTH == 4
00525     uint16_t i = y*(width>>1) + (x>>1);
00526     uint8_t pixel = m_scrbuf[i];
00527     if (x&1) pixel = (pixel&0xF0)|(col);
00528     else pixel = (pixel&0x0F) | (col<<4);
00529     m_scrbuf[i] = pixel;
00530     #endif // POK_COLORDEPTH
00531     #endif // POK_GAMEBUINO_SUPPORT
00532 }
00533 
00534 void Display::drawPixel(int16_t x,int16_t y) {
00535     if ((uint16_t)x >= width || (uint16_t)y >= height) return;
00536 
00537     #if POK_GAMEBUINO_SUPPORT > 0
00538 
00539     uint8_t c = color;
00540     uint8_t ct = color;
00541     if(ct == INVERT){
00542      ct = !getPixel(x, y); //jonne - was c = !getP...
00543     }
00544 
00545     uint16_t bitptr=0;
00546     for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
00547     c = ct & 1; // take the lowest bit of the color index number
00548     if(c == 0){ //white - or actually "Clear bit"
00549     #if DISPLAY_ROT == NOROT
00550         m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
00551     #elif DISPLAY_ROT == ROTCCW
00552         m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV(x % 8);
00553     #elif DISPLAY_ROT == ROT180
00554         m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV((LCDHEIGHT - y - 1) % 8);
00555     #elif DISPLAY_ROT == ROTCW
00556         m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitbtr] &= ~_BV((LCDWIDTH - x - 1) % 8);
00557     #endif
00558         //return; //jonne
00559     } else { //black - or actually "Set bit"
00560     #if DISPLAY_ROT == NOROT
00561         m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
00562     #elif DISPLAY_ROT == ROTCCW
00563         m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] |= _BV(x % 8);
00564     #elif DISPLAY_ROT == ROT180
00565         m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDHEIGHT - y - 1) % 8);
00566     #elif DISPLAY_ROT == ROTCW
00567         m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDWIDTH - x -1) % 8);
00568     #endif
00569         //return; //jonne
00570     }
00571     ct >>=1; // shift to get next bit
00572     bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
00573     } // POK_COLOURDEPTH
00574 
00575     #else
00576 
00577     /** NOT Gamebuino */
00578     #if POK_COLORDEPTH == 1
00579         if (color) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
00580         m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
00581     #elif POK_COLORDEPTH == 2
00582         uint16_t i = y*(width>>2) + (x>>2);
00583         uint8_t pixel = m_scrbuf[i];
00584         uint8_t column = x&0x03;
00585         if (column==3) pixel = (pixel&0xFC)|(color); // bits 0-1
00586         else if (column==2) pixel = (pixel&0xF3)|(color<<2); // bits 2-3
00587         else if (column==1) pixel = (pixel&0xCF)|(color<<4); // bits 4-5
00588         else pixel = (pixel&0x3F)|(color<<6); // bits 6-7
00589         m_scrbuf[i] = pixel;
00590     #elif POK_COLORDEPTH == 3
00591     #elif POK_COLORDEPTH == 4
00592             uint16_t i = y*(width>>1) + (x>>1);
00593             uint8_t pixel = m_scrbuf[i];
00594             if (x&1) pixel = (pixel&0xF0)|(color);
00595             else pixel = (pixel&0x0F) | (color<<4);
00596             m_scrbuf[i] = pixel;
00597     #endif // POK_COLORDEPTH
00598     #endif // POK_GAMEBUINO_SUPPORT
00599 }
00600 
00601 uint8_t Display::getPixel(int16_t x,int16_t y) {
00602     if ((uint16_t)x >= width || (uint16_t)y >= height) return 0;
00603     #if POK_GAMEBUINO_SUPPORT
00604     uint8_t color=0; //jonne
00605     for (uint8_t cbit=0; cbit<POK_COLORDEPTH;cbit++) {
00606         color |= (m_scrbuf[x + (y / 8) * LCDWIDTH+POK_BITFRAME*cbit] >> (y % 8)) & 0x1 ; //jonne - added +504*cbit
00607     }
00608     return color;
00609     #else
00610     /** not gamebuino */
00611     #if POK_COLORDEPTH == 1
00612         return (m_scrbuf[(y >> 3) * width + x] & (0x80 >> (y & 7))) ? 1:0;
00613     #elif POK_COLORDEPTH == 2
00614         uint16_t i = y*(width>>2) + (x>>2);
00615         uint8_t pixel = m_scrbuf[i];
00616         uint8_t column = x&0x03;
00617         if (column==0) return pixel & 0x03; // bits 0-1
00618         else if (column==1) return (pixel & 0x0C)>>2; // bits 2-3
00619         else if (column==2) return (pixel & 0x30)>>4; // bits 4-5
00620         else return pixel>>6;; // bits 6-7
00621     #elif POK_COLORDEPTH == 3
00622     #elif POK_COLORDEPTH == 4
00623     uint16_t i = y*(width>>1) + (x>>1);
00624     uint8_t pixel = m_scrbuf[i];
00625     if (x&1) return pixel & 0x0F;
00626     else return pixel>>4;
00627     #endif // POK_COLORDEPTH
00628     #endif // POK_GAMEBUINO_SUPPORT
00629 }
00630 
00631 void Display::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
00632     if ((uint16_t)x0 >= width || (uint16_t)y0 >= height || (uint16_t)x1 >= width || (uint16_t)y1 >= height ) {
00633         if (clipLine (&x0,&y0,&x1,&y1)==0) return; // line out of bounds
00634     }
00635     if (x0 == x1)
00636         drawColumn(x0,y0,y1);
00637     else if (y0 == y1)
00638         drawRow(x0,x1,y0);
00639     else {
00640         int e;
00641         signed int dx,dy,j, temp;
00642         signed char s1,s2, xchange;
00643         signed int x,y;
00644 
00645         x = x0;
00646         y = y0;
00647 
00648         //take absolute value
00649         if (x1 < x0) {
00650             dx = x0 - x1;
00651             s1 = -1;
00652         }
00653         else if (x1 == x0) {
00654             dx = 0;
00655             s1 = 0;
00656         }
00657         else {
00658             dx = x1 - x0;
00659             s1 = 1;
00660         }
00661 
00662         if (y1 < y0) {
00663             dy = y0 - y1;
00664             s2 = -1;
00665         }
00666         else if (y1 == y0) {
00667             dy = 0;
00668             s2 = 0;
00669         }
00670         else {
00671             dy = y1 - y0;
00672             s2 = 1;
00673         }
00674 
00675         xchange = 0;
00676 
00677         if (dy>dx) {
00678             temp = dx;
00679             dx = dy;
00680             dy = temp;
00681             xchange = 1;
00682         }
00683 
00684         e = ((int)dy<<1) - dx;
00685 
00686         for (j=0; j<=dx; j++) {
00687             drawPixel(x,y);
00688 
00689             if (e>=0) {
00690                 if (xchange==1) x = x + s1;
00691                 else y = y + s2;
00692                 e = e - ((int)dx<<1);
00693             }
00694             if (xchange==1)
00695                 y = y + s2;
00696             else
00697                 x = x + s1;
00698             e = e + ((int)dy<<1);
00699         }
00700     }
00701 }
00702 
00703 uint8_t Display::clipLine(int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1){
00704     // Check X bounds
00705     if (*x1<*x0) {
00706         //std::swap (*x1,*x0); // swap so that we dont have to check x1 also
00707         swapWT(int16_t*,x1,x0);
00708         //std::swap (*y1,*y0); // y needs to be swaaped also
00709         swapWT(int16_t*,y1,y0);
00710     }
00711 
00712     if (*x0>=width) return 0; // whole line is out of bounds
00713 
00714     // Clip against X0 = 0
00715     if (*x0 < 0) {
00716         if ( *x1 < 0) return 0; // nothing visible
00717         int16_t dx = (*x1 - *x0);
00718         int16_t dy = ((*y1 - *y0) << 8); // 8.8 fixed point calculation trick
00719         int16_t m = dy/dx;
00720         *y0 = *y0 + ((m*-*x0)>>8); // get y0 at boundary
00721         *x0 = 0;
00722     }
00723 
00724     // Clip against x1 = 83
00725     if (*x1 >= width) {
00726         int16_t dx = (*x1 - *x0);
00727         int16_t dy = ((*y1 - *y0) << 8); // 8.8 fixed point calculation trick
00728         int16_t m = dy/dx;
00729         //*y1 = *y1 + ((m*(*x1-XMAX))>>8); // get y0 at boundary
00730         *y1 = *y1 + ((m*(width-1-*x1))>>8); // get y0 at boundary
00731         *x1 = width-1;
00732     }
00733 
00734     // Check Y bounds
00735     if (*y1<*y0) {
00736         //std::swap (*x1,*x0); // swap so that we dont have to check x1 also
00737         swapWT(int16_t*,x1,x0);
00738         //std::swap (*y1,*y0); // y needs to be swaaped also
00739         swapWT(int16_t*,y1,y0);
00740     }
00741 
00742     if (*y0>=height) return 0; // whole line is out of bounds
00743 
00744     if (*y0 < 0) {
00745         if ( *y1 < 0) return 0; // nothing visible
00746         int16_t dx = (*x1 - *x0) << 8;
00747         int16_t dy = (*y1 - *y0); // 8.8 fixed point calculation trick
00748         int16_t m = dx/dy;
00749         *x0 = *x0 + ((m*-*y0)>>8); // get x0 at boundary
00750         *y0 = 0;
00751     }
00752 
00753     // Clip against y1 = 47
00754     if (*y1 >= height) {
00755         int16_t dx = (*x1 - *x0) << 8;
00756         int16_t dy = (*y1 - *y0); // 8.8 fixed point calculation trick
00757         int16_t m = dx/dy;
00758         *x1 = *x1 + ((m*(height-1-*y1))>>8); // get y0 at boundary
00759         //*x1 = *x1 + ((m*(*y1-YMAX))>>8); // get y0 at boundary
00760         *y1 = height-1;
00761     }
00762     return 1; // clipped succesfully
00763 }
00764 
00765 void Display::map1BitColumn(int16_t x, int16_t sy, int16_t ey, const uint8_t* bitmap, uint16_t column){
00766     if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds
00767     if ((uint16_t)x>=width) return; //completely out of bounds
00768     if (sy>ey) {
00769             int y=sy;
00770             sy=ey;
00771             ey=y; // swap around so that x0 is less than x1
00772     }
00773     uint16_t bmw,bmh;
00774     float texelstep, texelindex;
00775     bmw = *(bitmap);
00776     bmh = *(bitmap+1);
00777     if (column>bmw-1) column=bmw-1;
00778     bitmap += 2;
00779     bitmap += column;
00780     texelstep = (float)bmh/((float)ey-(float)sy);
00781     texelindex = 0;
00782     for (int y=sy; y <= ey; y++, texelindex += texelstep) {
00783         uint8_t texel;
00784         uint8_t currbyte, bit;
00785         currbyte = texelindex / 8;
00786         bit = 7-((uint16_t) texelindex & 0x7);
00787         texel=*(bitmap+currbyte*bmw);
00788         if (texel & (1<<bit)) drawPixel(x,y);
00789         else if (bgcolor != invisiblecolor) drawPixel(x,y,bgcolor);
00790     }
00791 };
00792 
00793 void Display::drawColumn(int16_t x, int16_t sy, int16_t ey){
00794     if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds
00795     if ((uint16_t)x>=width) return; //completely out of bounds
00796     if (sy>ey) {
00797             int y=sy;
00798             sy=ey;
00799             ey=y; // swap around so that x0 is less than x1
00800     }
00801     for (int y=sy; y <= ey; y++) {
00802         drawPixel(x,y);
00803     }
00804 }
00805 
00806 void Display::drawRow(int16_t x0, int16_t x1, int16_t y){
00807     if ((uint16_t)x0>=width && (uint16_t)x1>=width) return; //completely out of bounds
00808     if ((uint16_t)y>=height) return; //completely out of bounds
00809 
00810     if (x0>x1) {
00811             int x=x0;
00812             x0=x1;
00813             x1=x; // swap around so that x0 is less than x1
00814     }
00815     for (int x=x0; x <= x1; x++) {
00816         drawPixel(x,y);
00817     }
00818 }
00819 
00820 void Display::drawFastVLine(int16_t x, int16_t y, int16_t h){
00821     if (h<0) {y += h; h = -h;}
00822     drawColumn(x,y,y+h);
00823 }
00824 
00825 void Display::drawFastHLine(int16_t x, int16_t y, int16_t w){
00826     if (w<0) {x += w; w = -w;}
00827     drawRow(x,x+w-1,y);
00828 }
00829 
00830 void Display::drawRectangle(int16_t x0, int16_t y0, int16_t w, int16_t h) {
00831     drawColumn(x0,y0,y0+h);
00832     drawColumn(x0+w,y0,y0+h);
00833     drawRow(x0,x0+w,y0);
00834     drawRow(x0,x0+w,y0+h);
00835 }
00836 
00837 void Display::fillRectangle(int16_t x0,int16_t y0, int16_t w, int16_t h){
00838     int16_t x,y,x1,y1;
00839     x1=x0+w;y1=y0+h;
00840     if ((x0<0 && x1<0) || (x0>=width && x1 >=width)) return; //completely out of bounds
00841     if ((y0<0 && y1<0) || (y0>=height && y1 >=height)) return; //completely out of bounds
00842     if (x0>x1) {x=x1;x1=x0;}
00843     else x=x0;
00844     if (y0>y1) {y=y1;y1=y0;}
00845     else y=y0;
00846     if (x<0) x=0;
00847     if (y<0) y=0;
00848     for (;x<x1;x++) drawColumn(x,y,y1);
00849 }
00850 
00851 void Display::fillRect(int16_t x, int16_t y, int16_t w, int16_t h) {
00852     fillRectangle(x,y,w,h);
00853 }
00854 
00855 void Display::drawRect(int16_t x, int16_t y, int16_t w, int16_t h) {
00856     drawRectangle(x,y,w,h);
00857 }
00858 
00859 void Display::drawCircle(int16_t x0, int16_t y0, int16_t r) {
00860     int16_t f = 1 - r;
00861     int16_t ddF_x = 1;
00862     int16_t ddF_y = -2 * r;
00863     int16_t x = 0;
00864     int16_t y = r;
00865 
00866     drawPixel(x0, y0 + r);
00867     drawPixel(x0, y0 - r);
00868     drawPixel(x0 + r, y0);
00869     drawPixel(x0 - r, y0);
00870 
00871     while (x < y) {
00872         if (f >= 0) {
00873 
00874             y--;
00875             ddF_y += 2;
00876             f += ddF_y;
00877         }
00878         x++;
00879         ddF_x += 2;
00880         f += ddF_x;
00881 
00882         drawPixel(x0 + x, y0 + y);
00883         drawPixel(x0 - x, y0 + y);
00884         drawPixel(x0 + x, y0 - y);
00885         drawPixel(x0 - x, y0 - y);
00886         drawPixel(x0 + y, y0 + x);
00887         drawPixel(x0 - y, y0 + x);
00888         drawPixel(x0 + y, y0 - x);
00889         drawPixel(x0 - y, y0 - x);
00890 
00891     }
00892 }
00893 
00894 void Display::drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername) {
00895     int16_t f = 1 - r;
00896     int16_t ddF_x = 1;
00897     int16_t ddF_y = -2 * r;
00898     int16_t x = 0;
00899     int16_t y = r;
00900 
00901     while (x < y) {
00902         if (f >= 0) {
00903             y--;
00904             ddF_y += 2;
00905             f += ddF_y;
00906         }
00907         x++;
00908         ddF_x += 2;
00909         f += ddF_x;
00910         if (cornername & 0x4) {
00911             drawPixel(x0 + x, y0 + y);
00912             drawPixel(x0 + y, y0 + x);
00913         }
00914         if (cornername & 0x2) {
00915             drawPixel(x0 + x, y0 - y);
00916             drawPixel(x0 + y, y0 - x);
00917         }
00918         if (cornername & 0x8) {
00919             drawPixel(x0 - y, y0 + x);
00920             drawPixel(x0 - x, y0 + y);
00921         }
00922         if (cornername & 0x1) {
00923 
00924             drawPixel(x0 - y, y0 - x);
00925             drawPixel(x0 - x, y0 - y);
00926         }
00927     }
00928 }
00929 
00930 void Display::fillCircle(int16_t x0, int16_t y0, int16_t r) {
00931     drawFastVLine(x0, y0 - r, 2 * r );
00932     fillCircleHelper(x0, y0, r, 3, 0);
00933 }
00934 
00935 void Display::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername, int16_t delta) {
00936     int16_t f = 1 - r;
00937     int16_t ddF_x = 1;
00938     int16_t ddF_y = -2 * r;
00939     int16_t x = 0;
00940     int16_t y = r;
00941 
00942     while (x < y) {
00943         if (f >= 0) {
00944             y--;
00945             ddF_y += 2;
00946             f += ddF_y;
00947         }
00948         x++;
00949         ddF_x += 2;
00950         f += ddF_x;
00951 
00952         if (cornername & 0x1) {
00953             drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne
00954             drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne
00955         }
00956         if (cornername & 0x2) {
00957 
00958             drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne
00959             drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne
00960         }
00961     }
00962 }
00963 
00964 void Display::drawRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) {
00965     if (r<2) {drawRectangle(x,y,w,h);return;}
00966     // smarter version
00967     drawFastHLine(x + r, y, w - 2 * r); // Top
00968     drawFastHLine(x + r, y + h - 1, w - 2 * r); // Bottom
00969     drawFastVLine(x, y + r, h - 2 * r); // Left
00970     drawFastVLine(x + w - 1, y + r, h - 2 * r); // Right
00971     // draw four corners
00972     drawCircleHelper(x + r, y + r, r, 1);
00973     drawCircleHelper(x + w - r - 1, y + r, r, 2);
00974     drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4);
00975     drawCircleHelper(x + r, y + h - r - 1, r, 8);
00976 }
00977 
00978 void Display::fillRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) {
00979     if (r<2) {fillRectangle(x,y,w,h);return;}
00980     fillRectangle(x + r, y, w - 2 * r, h-1);
00981     // draw four corners
00982     fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1);
00983     fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1);
00984 }
00985 
00986 void Display::drawTriangle(int16_t x0, int16_t y0,
00987         int16_t x1, int16_t y1,
00988         int16_t x2, int16_t y2) {
00989     drawLine(x0, y0, x1, y1);
00990     drawLine(x1, y1, x2, y2);
00991     drawLine(x2, y2, x0, y0);
00992 }
00993 
00994 void Display::fillTriangle(int16_t x0, int16_t y0,
00995         int16_t x1, int16_t y1,
00996         int16_t x2, int16_t y2) {
00997     int16_t a, b, y, last;
00998 
00999     // Sort coordinates by Y order (y2 >= y1 >= y0)
01000     if (y0 > y1) {
01001         swapWT(int16_t,y0, y1);
01002         swapWT(int16_t,x0, x1);
01003     }
01004     if (y1 > y2) {
01005         swapWT(int16_t,y2, y1);
01006         swapWT(int16_t,x2, x1);
01007     }
01008     if (y0 > y1) {
01009         swapWT(int16_t,y0, y1);
01010         swapWT(int16_t,x0, x1);
01011     }
01012 
01013     if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
01014         a = b = x0;
01015         if (x1 < a) a = x1;
01016         else if (x1 > b) b = x1;
01017         if (x2 < a) a = x2;
01018         else if (x2 > b) b = x2;
01019         drawFastHLine(a, y0, b - a + 1);
01020         return;
01021     }
01022 
01023     int16_t
01024     dx01 = x1 - x0,
01025             dy01 = y1 - y0,
01026             dx02 = x2 - x0,
01027             dy02 = y2 - y0,
01028             dx12 = x2 - x1,
01029             dy12 = y2 - y1,
01030             sa = 0,
01031             sb = 0;
01032 
01033     // For upper part of triangle, find scanline crossings for segments
01034     // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
01035     // is included here (and second loop will be skipped, avoiding a /0
01036     // error there), otherwise scanline y1 is skipped here and handled
01037     // in the second loop...which also avoids a /0 error here if y0=y1
01038     // (flat-topped triangle).
01039     if (y1 == y2) last = y1; // Include y1 scanline
01040     else last = y1 - 1; // Skip it
01041 
01042     for (y = y0; y <= last; y++) {
01043         a = x0 + sa / dy01;
01044         b = x0 + sb / dy02;
01045         sa += dx01;
01046         sb += dx02;
01047         /* longhand:
01048         a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
01049         b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
01050          */
01051         if (a > b) swapWT(int16_t,a, b);
01052         drawFastHLine(a, y, b - a + 1);
01053     }
01054 
01055     // For lower part of triangle, find scanline crossings for segments
01056     // 0-2 and 1-2.  This loop is skipped if y1=y2.
01057     sa = dx12 * (y - y1);
01058     sb = dx02 * (y - y0);
01059     for (; y <= y2; y++) {
01060         a = x1 + sa / dy12;
01061         b = x0 + sb / dy02;
01062         sa += dx12;
01063         sb += dx02;
01064 
01065         if (a > b) swapWT(int16_t,a, b);
01066         drawFastHLine(a, y, b - a + 1);
01067     }
01068 }
01069 
01070 void Display::setFont(const unsigned char * f) {
01071     font = f;
01072     fontWidth = *(font)+1;
01073     fontHeight = *(font + 1)+1;
01074 }
01075 
01076 void Display::drawMonoBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t index) {
01077     uint8_t w = *bitmap;
01078     uint8_t h = *(bitmap + 1);
01079     uint8_t xtra=0;
01080     if (w&0x7) xtra=1;
01081     bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
01082     #if POK_GAMEBUINO_SUPPORT > 0
01083     int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
01084     for (i = 0; i < w; i++) {
01085         byteNum = i / 8;
01086         bitNum = i % 8;
01087         for (j = 0; j < h; j++) {
01088             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01089             if (source & (0x80 >> bitNum)) {
01090                 drawPixel(x + i, y + j);
01091             }
01092         }
01093     }
01094     #else
01095     /** not gamebuino */
01096     int8_t scrx,scry;
01097     uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
01098     int8_t bitptr;
01099     for (scry = y; scry < y+h; scry+=1) {
01100             if ((x&1)==0) { /** EVEN pixel starting line**/
01101                 for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) {
01102                     uint8_t targetpixel = *scrptr;
01103                     if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // upper nibble
01104                     else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // upper nibble
01105                     bitptr--;
01106                     if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble
01107                     else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble
01108                     bitptr--;
01109                     if (bitptr<0) { bitptr = 7; bitmap++; }
01110                     *scrptr = targetpixel;
01111                     scrptr++;
01112                 }
01113             } else { /** ODD pixel starting line **/
01114                 for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) {
01115                     uint8_t targetpixel = *scrptr;
01116                     // store higher nibble of source pixel in lower nibble of target
01117                     if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble
01118                     else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble
01119                     *scrptr = targetpixel; // store
01120                     bitptr--;scrptr++;targetpixel = *scrptr;
01121                     // store lower nibble of source pixel in higher nibble of target
01122                     if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // higher nibble
01123                     else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // higher nibble
01124                     *scrptr = targetpixel; // store
01125                     bitptr--; // do not increment scrptr here !
01126                 }
01127             }
01128             if (bitptr!=7) bitmap++; // force skip to next line
01129             // increment the y jump in the scrptr
01130             scrptr = scrptr + ((width - w)>>1);
01131     }
01132     #endif // POK_GAMEBUINO_SUPPORT
01133 }
01134 
01135 
01136 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame)
01137 {
01138     int16_t w = *bitmap;
01139     int16_t h = *(bitmap + 1);
01140     uint8_t framew = *(bitmap+2);
01141     bitmap = bitmap + 3; //add an offset to the pointer to start after the width and height
01142     /** visibility check */
01143     if (y<-h || y>height) return; //invisible
01144     if (x<-framew || x>width) return;  //invisible
01145     /** 1 bpp mode */
01146     if (m_colordepth<2) {
01147     int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
01148     for (i = 0; i < w; i++) {
01149         byteNum = i / 8;
01150         bitNum = i % 8;
01151         for (j = 0; j < h; j++) {
01152             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01153             if (source & (0x80 >> bitNum)) {
01154                 drawPixel(x + i, y + j);
01155             }
01156         }
01157     }
01158 
01159     return;
01160     }
01161     /** 2 bpp mode */
01162     if (m_colordepth<4) {
01163     int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
01164     for (i = 0; i < w; i++) {
01165         byteNum = i / 4;
01166         bitNum = (i % 4)<<1;
01167         for (j = 0; j < h; j++) {
01168             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01169             uint8_t output = (source & (0xC0 >> bitNum));
01170             output >>= (6-bitNum);
01171             if (output != invisiblecolor) {
01172                 setColor(output);
01173                 drawPixel(x + i, y + j);
01174             }
01175         }
01176     }
01177 
01178     return;
01179     }
01180     /** 4bpp fast version */
01181     int16_t scrx,scry,xclip,xjump,scrxjump;
01182     xclip=xjump=scrxjump=0;
01183     bitmap += (framew*frame)>>1;
01184     /** y clipping */
01185     if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
01186     else if (y+h>height) { h -=(y-height);}
01187     /** x clipping */
01188     xjump = (w-framew)>>1;
01189     if (x<0) { xclip=(x&1)<<1; framew+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;}
01190     else if (x+framew>width) {
01191             xclip = (x&1)<<1;
01192             scrxjump = x&1;
01193             xjump=((x+framew-width)>>1)+scrxjump;
01194             framew = width-x;}
01195 
01196     uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
01197     /** ONLY 4-bit mode for time being **/
01198     for (scry = y; scry < y+h; scry+=1) {
01199             if (scry>=height) return;
01200             if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
01201                 for (scrx = x; scrx < framew+x-xclip; scrx+=2) {
01202                     uint8_t sourcepixel = *bitmap;
01203                     if (xclip) {
01204                             sourcepixel <<=4;
01205                             sourcepixel |= ((*(bitmap+1))>>4);
01206                     }
01207                     uint8_t targetpixel = *scrptr;
01208                     if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0);
01209                     if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F);
01210                     *scrptr = targetpixel;
01211                     bitmap++;
01212                     scrptr++;
01213                 }
01214                 if (xclip){
01215                     if (framew&1) {
01216                         /**last pixel is odd pixel due to clipping & odd width*/
01217                         uint8_t sourcepixel = *bitmap;
01218                         if ((sourcepixel&0x0F) != invisiblecolor) {
01219                             sourcepixel <<=4;
01220                             uint8_t targetpixel = *scrptr;// & 0x0F;
01221                             targetpixel |= sourcepixel;
01222                             *scrptr = targetpixel;
01223                         }
01224                         //scrptr++;
01225                     }
01226                     bitmap++;
01227                     scrptr++;
01228                 }
01229                 bitmap += xjump; // needed if x<0 clipping occurs
01230             } else { /** ODD pixel starting line **/
01231                 for (scrx = x; scrx < framew+x-xclip; scrx+=2) {
01232                     uint8_t sourcepixel = *bitmap;
01233                     uint8_t targetpixel = *scrptr;
01234                     // store higher nibble of source pixel in lower nibble of target
01235                     if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
01236                     *scrptr = targetpixel;
01237                     scrptr++;
01238                     targetpixel = *scrptr;
01239                     // store lower nibble of source pixel in higher nibble of target
01240                     if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4);
01241                     *scrptr = targetpixel;
01242                     bitmap++;
01243                 }
01244                 bitmap+=xjump;
01245             }
01246             // increment the y jump in the scrptr
01247             scrptr = scrptr + ((width - framew)>>1)+scrxjump;
01248     }
01249 }
01250 
01251 
01252 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap)
01253 {
01254     int16_t w = *bitmap;
01255     int16_t h = *(bitmap + 1);
01256     bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
01257     /** visibility check */
01258     if (y<-h || y>height) return; //invisible
01259     if (x<-w || x>width) return;  //invisible
01260     /** 1 bpp mode */
01261     if (m_colordepth<2) {
01262     int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
01263     for (i = 0; i < w; i++) {
01264         byteNum = i / 8;
01265         bitNum = i % 8;
01266         for (j = 0; j < h; j++) {
01267             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01268             if (source & (0x80 >> bitNum)) {
01269                 drawPixel(x + i, y + j);
01270             }
01271         }
01272     }
01273 
01274     return;
01275     }
01276     /** 2 bpp mode */
01277     if (m_colordepth<4) {
01278     int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
01279     for (i = 0; i < w; i++) {
01280         byteNum = i / 4;
01281         bitNum = (i % 4)<<1;
01282         for (j = 0; j < h; j++) {
01283             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01284             uint8_t output = (source & (0xC0 >> bitNum));
01285             output >>= (6-bitNum);
01286             if (output != invisiblecolor) {
01287                 setColor(output);
01288                 drawPixel(x + i, y + j);
01289             }
01290         }
01291     }
01292 
01293     return;
01294     }
01295     /** 4bpp fast version */
01296     int16_t scrx,scry,xclip,xjump,scrxjump;
01297     xclip=xjump=scrxjump=0;
01298     /** y clipping */
01299     if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
01300     else if (y+h>height) { h -=(y-height);}
01301     /** x clipping */
01302     if (x<0) { xclip=(x&1)<<1; w+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;}
01303     else if (x+w>width) {
01304             xclip = (x&1)<<1;
01305             scrxjump = x&1;
01306             xjump=((x+w-width)>>1)+scrxjump;
01307             w = width-x;}
01308 
01309     uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
01310     /** ONLY 4-bit mode for time being **/
01311     for (scry = y; scry < y+h; scry+=1) {
01312             if (scry>=height) return;
01313             if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
01314                 for (scrx = x; scrx < w+x-xclip; scrx+=2) {
01315                     uint8_t sourcepixel = *bitmap;
01316                     if (xclip) {
01317                             sourcepixel <<=4;
01318                             sourcepixel |= ((*(bitmap+1))>>4);
01319                     }
01320                     uint8_t targetpixel = *scrptr;
01321                     if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0);
01322                     if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F);
01323                     *scrptr = targetpixel;
01324                     bitmap++;
01325                     scrptr++;
01326                 }
01327                 if (xclip){
01328                     if (w&1) {
01329                         /**last pixel is odd pixel due to clipping & odd width*/
01330                         uint8_t sourcepixel = *bitmap;
01331                         if ((sourcepixel&0x0F) != invisiblecolor) {
01332                             sourcepixel <<=4;
01333                             uint8_t targetpixel = *scrptr;// & 0x0F;
01334                             targetpixel |= sourcepixel;
01335                             *scrptr = targetpixel;
01336                         }
01337                         //scrptr++;
01338                     }
01339                     bitmap++;
01340                     scrptr++;
01341                 }
01342                 bitmap += xjump; // needed if x<0 clipping occurs
01343             } else { /** ODD pixel starting line **/
01344                 for (scrx = x; scrx < w+x-xclip; scrx+=2) {
01345                     uint8_t sourcepixel = *bitmap;
01346                     uint8_t targetpixel = *scrptr;
01347                     // store higher nibble of source pixel in lower nibble of target
01348                     if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
01349                     *scrptr = targetpixel;
01350                     scrptr++;
01351                     targetpixel = *scrptr;
01352                     // store lower nibble of source pixel in higher nibble of target
01353                     if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4);
01354                     *scrptr = targetpixel;
01355                     bitmap++;
01356                 }
01357                 bitmap+=xjump;
01358             }
01359             // increment the y jump in the scrptr
01360             scrptr = scrptr + ((width - w)>>1)+scrxjump;
01361     }
01362 }
01363 
01364 void Display::drawRleBitmap(int16_t x, int16_t y, const uint8_t* rlebitmap)
01365 {
01366     // ONLY can copy 4-bit bitmap to 4-bit screen mode for time being
01367     #if (POK_SCREENMODE != MODE_FAST_16COLOR)
01368     return;
01369     #endif
01370 
01371     int16_t w = *rlebitmap;
01372     int16_t h = *(rlebitmap + 1);
01373     rlebitmap = rlebitmap + 2; //add an offset to the pointer to start after the width and height
01374 
01375     // visibility check
01376     if (y<-h || y>height) return; //invisible
01377     if (x<-w || x>width) return;  //invisible
01378 
01379     // Clipping is not supported
01380     if ((x < 0) || (x+w > width) || (y < 0) || (y+h > height)) return;
01381 
01382     // Currently only support RLE bitmaps in 16 color mode.
01383     if (m_colordepth != 4)  //
01384         return;
01385 
01386     // Go through each line.
01387     uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
01388     bool is_endofbitmap = false;
01389     for (int16_t scry = y; scry < y+h && !is_endofbitmap;) {
01390 
01391         // Process one line. Go through each pixel run and escape command in RLE data.
01392         for (int16_t scrx = x;;) {
01393             uint8_t rle_count = *rlebitmap++;
01394 
01395             if (rle_count == 0) {
01396 
01397                /** Escape or absolute mode */
01398 
01399                 uint8_t rle_escape_or_runsize = *rlebitmap++;
01400                 if ( rle_escape_or_runsize == RLE_ESC_EOL) {
01401                     // End of line.
01402                     break;
01403                 }
01404                 else if ( rle_escape_or_runsize == RLE_ESC_EOB) {
01405                     // End of bitmap.
01406                     is_endofbitmap = true;
01407                     break;
01408                 }
01409                 else if ( rle_escape_or_runsize == RLE_ESC_OFFSET) {
01410                     // Move position in target.
01411                     // TODO: not tested yet.
01412                     uint8_t xoffset = *rlebitmap++;
01413                     uint8_t yoffset = *rlebitmap++;
01414                     scrptr += (xoffset>1);
01415                     scrx += xoffset;
01416                     scrptr += yoffset*width;
01417                     scry += yoffset;
01418                  }
01419                 else {
01420 
01421                     /** Absolute mode. Copy pixels from the source bitmap to the target screen. */
01422 
01423                     int16_t runsize = rle_escape_or_runsize;
01424                     uint8_t targetpixel = *scrptr;  // initial value
01425                     uint8_t sourcepixel = *rlebitmap;  // initial value
01426                     for( int16_t runx = 0; runx < runsize; ) {
01427                         if (scrx&0x1)  { // screen pixel is in the low nibble
01428                             if (runx&0x1) { // bitmap pixel is in the low nibble
01429                                 if ((sourcepixel&0x0F) != invisiblecolor)
01430                                     targetpixel = (targetpixel&0xF0) | (sourcepixel&0x0F); // Copy low to low nibble.
01431                                 rlebitmap++;
01432                             }
01433                             else // bitmap pixel is in the high nibble
01434                                 if ((sourcepixel>>4) != invisiblecolor)
01435                                     targetpixel = (targetpixel&0xF0) | (sourcepixel>>4); // Copy high to low nibble.
01436 
01437                             // Copy the byte to the target.
01438                             *scrptr = targetpixel;
01439                             scrptr++;
01440                         }
01441                         else  { // screen pixel is in the high nibble
01442                             targetpixel = *scrptr;
01443                             sourcepixel = *rlebitmap;
01444                             if (runx&0x1) { // bitmap pixel is sourcepixel = *rlebitmapin the low nibble
01445                                 if ((sourcepixel&0x0F) != invisiblecolor )
01446                                     targetpixel = (targetpixel&0x0F) | ((sourcepixel<<4)&0xF0); // Copy low to high nibble.
01447                                 rlebitmap++;  // read the new source byte
01448                             }
01449                             else // bitmap pixel is in the high nibble
01450                                 if ((sourcepixel>>4) != invisiblecolor )
01451                                     targetpixel = (targetpixel&0x0F) | (sourcepixel&0xF0); // Copy high to high nibble.
01452                         }
01453                         runx++;
01454                         scrx++;
01455                     }  // end for
01456 
01457                      // If this is odd target index, copy the byte to the target.
01458                     if (scrx&0x1) {
01459                         *scrptr = targetpixel;
01460                         scrptr++;
01461                     }
01462 
01463                     // In absolute mode the source size is always padded to the word boundary.
01464                     if (runsize%4) {
01465                         int16_t padpixcount = 4 - (runsize%4);
01466                         rlebitmap += padpixcount>>1;  // skip n padding bytes
01467                     }
01468                 }
01469             }
01470             else {
01471 
01472                 /** Encoded mode. Duplicate one pixel pair to the all required pixels on the target screen */
01473 
01474                 int16_t runsize = rle_count;
01475                 uint8_t clonepixelpair = *rlebitmap++;
01476                 uint8_t targetpixel = *scrptr;  // initial value
01477                 for( int16_t runx = 0;  runx < runsize; ) {
01478                     if (scrx&0x1)  { // screen pixel is in the low nibble
01479                         if (runx&0x1) { // bitmap pixel is in the low nibble
01480                             if ((clonepixelpair&0x0F) != invisiblecolor)
01481                                 targetpixel = (targetpixel&0xF0) | (clonepixelpair&0x0F); // Copy low to low nibble.
01482                         }
01483                         else // bitmap pixel is in the high nibble
01484                             if ((clonepixelpair>>4) != invisiblecolor)
01485                                 targetpixel = (targetpixel&0xF0) | (clonepixelpair>>4); // Copy high to low nibble.
01486 
01487                         // Copy the byte to the target.
01488                         *scrptr = targetpixel;
01489                         scrptr++;
01490                     }
01491                     else  { // screen pixel is in the high nibble
01492                         targetpixel = *scrptr;
01493                         if (runx&0x1) {// bitmap pixel is in the low nibble
01494                             if ((clonepixelpair&0x0F) != invisiblecolor )
01495                                 targetpixel = (targetpixel&0x0F) | ((clonepixelpair<<4)&0xF0); // Copy low to high nibble.
01496                         }
01497                         else // bitmap pixel is in the high nibble
01498                             if ((clonepixelpair>>4) != invisiblecolor )
01499                                 targetpixel = (targetpixel&0x0F) | (clonepixelpair&0xF0); // Copy high to high nibble.
01500                     }
01501                     runx++;
01502                     scrx++;
01503 
01504                 }  // end for
01505 
01506                 // If this is odd target index, copy the byte to the target.
01507                 if (scrx&0x1) {
01508                     *scrptr = targetpixel;
01509                     scrptr++;
01510                  }
01511             } // end if
01512         }  // end while
01513 
01514         // Increment the target screen pointer and index.
01515         scrptr = scrptr + ((width - w)>>1);
01516         scry++;
01517     } // end for scry
01518 }
01519 
01520 void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
01521 {
01522     int16_t w = *bitmap;
01523     int16_t h = *(bitmap + 1);
01524     bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
01525     /** visibility check */
01526     if (y<-h || y>height) return; //invisible
01527     if (x<-w || x>width) return;  //invisible
01528     /** 1 bpp mode */
01529     if (m_colordepth<2) {
01530     int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
01531     for (i = 0; i < w; i++) {
01532         byteNum = i / 8;
01533         bitNum = i % 8;
01534         for (j = 0; j < h; j++) {
01535             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01536             if (source & (0x80 >> bitNum)) {
01537                 drawPixel(x + w - i, y + j);
01538             }
01539         }
01540     }
01541 
01542     return;
01543     }
01544     /** 2 bpp mode */
01545     if (m_colordepth<4) {
01546     int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
01547     for (i = 0; i < w; i++) {
01548         byteNum = i / 4;
01549         bitNum = (i % 4)<<1;
01550         for (j = 0; j < h; j++) {
01551             uint8_t source = *(bitmap + j * byteWidth + byteNum);
01552             uint8_t output = (source & (0xC0 >> bitNum));
01553             output >>= (6-bitNum);
01554             if (output != invisiblecolor) {
01555                 setColor(output);
01556                 drawPixel(x + i, y + j);
01557             }
01558         }
01559     }
01560 
01561     return;
01562     }
01563     /** 4bpp fast version */
01564     int16_t scrx,scry,xclip,xjump,scrxjump;
01565     xclip=xjump=scrxjump=0;
01566     /** y clipping */
01567     if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
01568     else if (y+h>height) { h -=(y-height);}
01569     /** x clipping */
01570     bitmap += ((w>>1)-1); //inverted!
01571     if (x<0) {
01572             xclip=(x&1)<<1;
01573             w+=x;
01574             xjump = ((-x)>>1);
01575             //bitmap += xjump; // do not clip left edge of source, as bitmap is inverted !
01576             x=0;
01577             }
01578     else if (x+w>width) {
01579             xclip = (x&1)<<1;
01580             scrxjump = x&1;
01581             xjump=((x+w-width)>>1)+scrxjump;
01582             w = width-x;}
01583 
01584     //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
01585     uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
01586     /** ONLY 4-bit mode for time being **/
01587     for (scry = y; scry < y+h; scry+=1) {
01588     //    for (scry = y; scry < y+2; scry+=1) {
01589             if (scry>=height) return;
01590             if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
01591                 //for (scrx = w+x-xclip-1; scrx >= x; scrx-=2) {
01592                 for (scrx = x; scrx < w+x-xclip; scrx+=2) {
01593                     uint8_t sourcepixel = *(bitmap);
01594                     if (xclip) {
01595                             sourcepixel <<=4;
01596                             sourcepixel |= ((*(bitmap-1))>>4);//inverted!
01597                     }
01598                     uint8_t targetpixel = *scrptr;
01599                     // NIBBLES ARE INVERTED BECAUSE PICTURE IS FLIPPED !!!
01600                     if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0xF0) | (sourcepixel>>4);
01601                     if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel<<4);
01602                     *scrptr = targetpixel;
01603                     bitmap--;
01604                     scrptr++;
01605                 }
01606                 bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
01607                 if (xclip){
01608                     if (w&1) {
01609                         /**last pixel is odd pixel due to clipping & odd width*/
01610                         uint8_t sourcepixel = *bitmap;
01611                         if ((sourcepixel&0x0F) != invisiblecolor) {
01612                             sourcepixel <<=4;
01613                             uint8_t targetpixel = *scrptr;// & 0x0F;
01614                             targetpixel |= sourcepixel;
01615                             *scrptr = targetpixel;
01616                         }
01617                         //scrptr++;
01618                     }
01619                     bitmap++;
01620                     scrptr++;
01621                 }
01622                 bitmap += xjump; // needed if x<0 clipping occurs
01623             } else { /** ODD pixel starting line **/
01624                 for (scrx = x; scrx < w+x-xclip; scrx+=2 ) {
01625                     uint8_t sourcepixel = *bitmap;
01626                     uint8_t targetpixel = *scrptr;
01627                     // inverted !!! store lower nibble of source pixel in lower nibble of target
01628                     if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F );
01629                     *scrptr = targetpixel;
01630                     scrptr++;
01631                     targetpixel = *scrptr;
01632                     // inverted ! store higher nibble of source pixel in higher nibble of target
01633                     if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel & 0xF0);
01634                     *scrptr = targetpixel;
01635                     bitmap--;
01636                 }
01637                 bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
01638                 bitmap+=xjump;
01639             }
01640             // increment the y jump in the scrptr
01641             scrptr = scrptr + ((width - w)>>1)+scrxjump;
01642     }
01643 }
01644 
01645 void Display::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip) {
01646 #if PROJ_GAMEBUINO == 0
01647     if (!flip) drawBitmap(x,y,bitmap);
01648     else drawBitmapXFlipped(x,y,bitmap);
01649 #else
01650     if((rotation == NOROT) && (flip == NOFLIP)){
01651         drawBitmap(x,y,bitmap); //use the faster algorithm
01652         return;
01653     }
01654     uint8_t w = bitmap[0];
01655     uint8_t h = bitmap[1];
01656     bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
01657     int8_t i, j, //coordinates in the raw bitmap
01658             k, l, //coordinates in the rotated/flipped bitmap
01659             byteNum, bitNum, byteWidth = (w + 7) >> 3;
01660 
01661     rotation %= 4;
01662 
01663     for (i = 0; i < w; i++) {
01664         byteNum = i / 8;
01665         bitNum = i % 8;
01666         for (j = 0; j < h; j++) {
01667             if (bitmap[j * byteWidth + byteNum] & (B10000000 >> bitNum)) {
01668                 switch (rotation) {
01669                     case NOROT: //no rotation
01670                         k = i;
01671                         l = j;
01672                         break;
01673                     case ROTCCW: //90� counter-clockwise
01674                         k = j;
01675                         l = w - i - 1;
01676                         break;
01677                     case ROT180: //180�
01678                         k = w - i - 1;
01679                         l = h - j - 1;
01680                         break;
01681                     case ROTCW: //90� clockwise
01682                         k = h - j - 1;
01683                         l = i;
01684                         break;
01685                 }
01686                 if (flip) {
01687                     flip %= 4;
01688                     if (flip & B00000001) { //horizontal flip
01689                         k = w - k;
01690                     }
01691                     if (flip & B00000010) { //vertical flip
01692                         l = h - l;
01693                     }
01694                 }
01695                 k += x; //place the bitmap on the screen
01696                 l += y;
01697                 drawPixel(k, l);
01698             }
01699         }
01700     }
01701 #endif //PROJ_GAMEBUINO
01702 
01703 }
01704 
01705 uint8_t* Display::getBuffer() {
01706     return m_scrbuf;
01707 }
01708 
01709 uint8_t Display::getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y) {
01710     uint16_t w = *bitmap;
01711     uint8_t sourcebyte = bitmap[2+(y * ((w+7)>>3))+ (x>>3)];
01712     return sourcebyte & (0x80>>(x&7));
01713 }
01714 
01715 int Display::print_char(uint8_t x, uint8_t y, unsigned char c) {
01716     c -= font[2];
01717     if (m_mode) return directChar(x,y,c);
01718     return bufferChar(x,y,c);
01719 }
01720 
01721 void Display::drawChar(int8_t x, int8_t y, unsigned char c, uint8_t size) {
01722     print_char(x,y,c);
01723     return;
01724 }
01725 
01726 
01727 bool Display::isDirectPrintingEnabled() {
01728     return m_mode;
01729 }
01730 
01731 void Display::enableDirectPrinting(uint8_t m) {
01732     if (m) {
01733             m_mode=true;
01734             m_w = POK_LCD_W;
01735             m_h = POK_LCD_H;
01736     } else {
01737             m_mode=false;
01738             m_w = getWidth();
01739             m_h = getHeight();
01740     }
01741 }
01742 
01743 void Display::write(uint8_t c) {
01744     int charstep=0;
01745     if(font[3]) {
01746         // only caps in this font
01747         if (c>=97) c-=32;
01748     }
01749     switch(c) {
01750         case '\0':          //null
01751             break;
01752         case '\n':          //line feed
01753             cursorX = 0;
01754             inc_txtline();
01755             break;
01756         case 8:             //backspace
01757             cursorX -= font[0];
01758             charstep=print_char(cursorX,cursorY,' ');
01759             break;
01760         case 13:            //carriage return
01761             cursorX = 0;
01762             break;
01763         case 14:            //form feed new page(clear screen)
01764             //clear_screen();
01765             break;
01766         default:
01767             if (cursorX >= (m_w - font[0])) {
01768                 cursorX = 0;
01769                 if (textWrap) inc_txtline();
01770                 else return; // stop outputting text
01771                 charstep=print_char(cursorX,cursorY,c);
01772             }
01773             else
01774                 charstep=print_char(cursorX,cursorY,c);
01775             if (c==' ' && adjustCharStep) charstep=(charstep>>1)+1;
01776             cursorX += charstep;
01777     }
01778 }
01779 
01780 void Display::inc_txtline() {
01781     if (cursorY > m_h - 2*font[1]) //= (height - (font[1]+1)))
01782         #if SCROLL_TEXT > 0
01783         scroll(font[1] + adjustLineStep);
01784         #else
01785         cursorY = 0;
01786         #endif
01787     else
01788         cursorY += font[1] + adjustLineStep;
01789 }
01790 
01791 /* default implementation: may be overridden */
01792 void Display::write(const char *str)
01793 {
01794   while (*str)
01795     write(*str++);
01796 }
01797 
01798 /* default implementation: may be overridden */
01799 void Display::write(const uint8_t *buffer, uint8_t size)
01800 {
01801   while (size--)
01802     write(*buffer++);
01803 }
01804 
01805 void Display::print(const char str[])
01806 {
01807   write(str);
01808 }
01809 
01810 void Display::print(char c, int base)
01811 {
01812   print((long) c, base);
01813 }
01814 
01815 void Display::print(unsigned char b, int base)
01816 {
01817   print((unsigned long) b, base);
01818 }
01819 
01820 void Display::print(int n, int base)
01821 {
01822   print((long) n, base);
01823 }
01824 
01825 void Display::print(unsigned int n, int base)
01826 {
01827   print((unsigned long) n, base);
01828 }
01829 
01830 void Display::print(long n, int base)
01831 {
01832   if (base == 0) {
01833     write(n);
01834   } else if (base == 10) {
01835     if (n < 0) {
01836       print('-');
01837       n = -n;
01838     }
01839     printNumber(n, 10);
01840   } else {
01841     printNumber(n, base);
01842   }
01843 }
01844 
01845 void Display::print(unsigned long n, int base)
01846 {
01847   if (base == 0) write(n);
01848   else printNumber(n, base);
01849 }
01850 
01851 void Display::print(double n, int digits)
01852 {
01853   printFloat(n, digits);
01854 }
01855 
01856 void Display::println(void)
01857 {
01858   print('\r');
01859   print('\n');
01860 }
01861 
01862 void Display::println(const char c[])
01863 {
01864   print(c);
01865   println();
01866 }
01867 
01868 void Display::println(char c, int base)
01869 {
01870   print(c, base);
01871   println();
01872 }
01873 
01874 void Display::println(unsigned char b, int base)
01875 {
01876   print(b, base);
01877   println();
01878 }
01879 
01880 void Display::println(int n, int base)
01881 {
01882   print(n, base);
01883   println();
01884 }
01885 
01886 void Display::println(unsigned int n, int base)
01887 {
01888   print(n, base);
01889   println();
01890 }
01891 
01892 void Display::println(long n, int base)
01893 {
01894   print(n, base);
01895   println();
01896 }
01897 
01898 void Display::println(unsigned long n, int base)
01899 {
01900   print(n, base);
01901   println();
01902 }
01903 
01904 void Display::println(double n, int digits)
01905 {
01906   print(n, digits);
01907   println();
01908 }
01909 
01910 void Display::set_cursor(uint8_t x, uint8_t y) {
01911     cursorX = x;
01912     cursorY = y;
01913 }
01914 
01915 void Display::print(uint8_t x, uint8_t y, const char str[]) {
01916     cursorX = x;
01917     cursorY = y;
01918     write(str);
01919 
01920 }
01921 void Display::print(uint8_t x, uint8_t y, char c, int base) {
01922     cursorX = x;
01923     cursorY = y;
01924     print((long) c, base);
01925 }
01926 void Display::print(uint8_t x, uint8_t y, unsigned char b, int base) {
01927     cursorX = x;
01928     cursorY = y;
01929     print((unsigned long) b, base);
01930 }
01931 void Display::print(uint8_t x, uint8_t y, int n, int base) {
01932     cursorX = x;
01933     cursorY = y;
01934     print((long) n, base);
01935 }
01936 void Display::print(uint8_t x, uint8_t y, unsigned int n, int base) {
01937     cursorX = x;
01938     cursorY = y;
01939     print((unsigned long) n, base);
01940 }
01941 void Display::print(uint8_t x, uint8_t y, long n, int base) {
01942     cursorX = x;
01943     cursorY = y;
01944     print(n,base);
01945 }
01946 void Display::print(uint8_t x, uint8_t y, unsigned long n, int base) {
01947     cursorX = x;
01948     cursorY = y;
01949     print(n,base);
01950 }
01951 void Display::print(uint8_t x, uint8_t y, double n, int digits) {
01952     cursorX = x;
01953     cursorY = y;
01954     print(n,digits);
01955 }
01956 
01957 void Display::println(uint8_t x, uint8_t y, const char c[])
01958 {
01959     cursorX = x;
01960     cursorY = y;
01961     print(c);
01962     println();
01963 }
01964 
01965 void Display::println(uint8_t x, uint8_t y, char c, int base)
01966 {
01967     cursorX = x;
01968     cursorY = y;
01969     print(c, base);
01970     println();
01971 }
01972 
01973 void Display::println(uint8_t x, uint8_t y, unsigned char b, int base)
01974 {
01975     cursorX = x;
01976     cursorY = y;
01977     print(b, base);
01978     println();
01979 }
01980 
01981 void Display::println(uint8_t x, uint8_t y, int n, int base)
01982 {
01983     cursorX = x;
01984     cursorY = y;
01985     print(n, base);
01986     println();
01987 }
01988 
01989 void Display::println(uint8_t x, uint8_t y, unsigned int n, int base)
01990 {
01991     cursorX = x;
01992     cursorY = y;
01993     print(n, base);
01994     println();
01995 }
01996 
01997 void Display::println(uint8_t x, uint8_t y, long n, int base)
01998 {
01999     cursorX = x;
02000     cursorY = y;
02001     print(n, base);
02002     println();
02003 }
02004 
02005 void Display::println(uint8_t x, uint8_t y, unsigned long n, int base)
02006 {
02007     cursorX = x;
02008     cursorY = y;
02009     print(n, base);
02010     println();
02011 }
02012 
02013 void Display::println(uint8_t x, uint8_t y, double n, int digits)
02014 {
02015     cursorX = x;
02016     cursorY = y;
02017     print(n, digits);
02018     println();
02019 }
02020 
02021 void Display::printNumber(unsigned long n, uint8_t base)
02022 {
02023   unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
02024   unsigned long i = 0;
02025 
02026   if (n == 0) {
02027     print('0');
02028     return;
02029   }
02030 
02031   while (n > 0) {
02032     buf[i++] = n % base;
02033     n /= base;
02034   }
02035 
02036   for (; i > 0; i--)
02037     print((char) (buf[i - 1] < 10 ?
02038       '0' + buf[i - 1] :
02039       'A' + buf[i - 1] - 10));
02040 }
02041 
02042 void Display::printFloat(double number, uint8_t digits)
02043 {
02044   // Handle negative numbers
02045   if (number < 0.0)
02046   {
02047      print('-');
02048      number = -number;
02049   }
02050 
02051   // Round correctly so that print(1.999, 2) prints as "2.00"
02052   double rounding = 0.5;
02053   for (uint8_t i=0; i<digits; ++i)
02054     rounding /= 10.0;
02055 
02056   number += rounding;
02057 
02058   // Extract the integer part of the number and print it
02059   unsigned long int_part = (unsigned long)number;
02060   double remainder = number - (double)int_part;
02061   print(int_part);
02062 
02063   // Print the decimal point, but only if there are digits beyond
02064   if (digits > 0)
02065     print(".");
02066 
02067   // Extract digits from the remainder one at a time
02068   while (digits-- > 0)
02069   {
02070     remainder *= 10.0;
02071     int toPrint = int(remainder);
02072     print(toPrint);
02073     remainder -= toPrint;
02074   }
02075 }
02076 
02077 void Display::draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap)
02078 {
02079     int8_t scry;
02080     uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
02081 
02082     /** ONLY 4-bit mode for time being **/
02083 
02084             if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
02085                 for (scry = y; scry < h+y; scry++) {
02086                     uint8_t sourcepixel = *bitmap;
02087                     uint8_t targetpixel = *scrptr;
02088                     targetpixel = (targetpixel&0x0F) | (sourcepixel << 4);
02089                     *scrptr = targetpixel;
02090                     bitmap++;
02091                     scrptr+=55;
02092                 }
02093             } else { /** ODD pixel starting line **/
02094                 for (scry = y; scry < h+y; scry++) {
02095                     uint8_t sourcepixel = *bitmap;
02096                     uint8_t targetpixel = *scrptr;
02097                     // store source pixel in lower nibble of target
02098                     targetpixel = (targetpixel & 0xF0) | (sourcepixel);
02099                     *scrptr = targetpixel;
02100                     scrptr+=55;
02101                     bitmap++;
02102                 }
02103             }
02104 }
02105 
02106 void Display::lcdRefresh(unsigned char* scr) {
02107 
02108 #if POK_SCREENMODE == MODE_GAMEBOY
02109     lcdRefreshModeGBC(scr, paletteptr);
02110 #endif
02111 
02112 #if POK_SCREENMODE == MODE_HI_4COLOR
02113     lcdRefreshMode1(scr, paletteptr);
02114 #endif
02115 
02116 #if POK_SCREENMODE == MODE_FAST_16COLOR
02117     lcdRefreshMode2(scr, paletteptr);
02118 #endif
02119 
02120 #if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR
02121     lcdRefreshGB(scr, paletteptr);
02122 #endif
02123 
02124 #if POK_SCREENMODE == MODE_ARDUBOY_16COLOR
02125     lcdRefreshAB(scr, paletteptr);
02126 #endif
02127 
02128 }
02129 
02130 void Display::setFrameBufferTo(uint8_t* sb) {
02131     m_scrbuf = sb;
02132 };
02133 
02134 void Display::setTileBufferTo(uint8_t* tb) {
02135     m_tilebuf = tb;
02136 };
02137 
02138 void Display::loadTileset(const uint8_t* ts) {
02139     m_tileset = (uint8_t*) ts;
02140 };
02141 
02142 void Display::setTile(uint16_t i, uint8_t t) {
02143     if (!m_tilebuf) return;
02144     m_tilebuf[i]=t;
02145 };
02146 
02147 
02148 /** Eof */
02149 
02150 
02151