Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of PokittoLib by
PokittoDisplay.cpp
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
Generated on Tue Jul 12 2022 18:08:13 by
1.7.2
