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.
Dependents: YATTT sd_map_test cPong SnowDemo ... more
PokittoLib
Library for programming Pokitto hardware
How to Use
- Import this library to online compiler (see button "import" on the right hand side
- DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
- Change My_settings.h according to your project
- Start coding!
Revision 23:f88837b8f914, committed 2017-12-29
- Comitter:
- Pokitto
- Date:
- Fri Dec 29 05:17:10 2017 +0000
- Parent:
- 22:e826f80d8582
- Child:
- 24:9561281d0378
- Commit message:
- PokittoLib mbed and Github are back in sync with all contributions from Hanski and Spinal included
Changed in this revision
--- a/POKITTO_CORE/PokittoButtons.cpp Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/**************************************************************************/
-/*!
- @file PokittoButtons.cpp
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-#include "PokittoCore.h"
-
-using namespace Pokitto;
-
-uint8_t Buttons::pins[NUM_BTN];
-uint8_t Buttons::states[NUM_BTN];
-uint8_t Buttons::buttons_state;
-uint8_t Buttons::buttons_held;
-uint8_t Buttons::buttons_released; // from LSB up,down,left,right,a,b,c
-uint16_t Buttons::cHWLongPress = CHWLONGPRESSTIMEOUT;
-
-
-void Buttons::begin() {
- #ifndef POK_SIM
- Pokitto::initButtons();
- #endif // POK_SIM
-}
-
-void Buttons::update() {
- #if POK_USE_CONSOLE > 0
- if (console.conscounter) return;
- #endif // POK_USE_CONSOLE
- #ifndef POK_SIM
- /** HARDWARE CODE **/
- for (uint8_t thisButton = 0; thisButton < NUM_BTN; thisButton++) {
- if (Pokitto::heldStates[thisButton]) { //if button pressed
- states[thisButton]++; //increase button hold time
- } else {
- if (states[thisButton] == 0)//button idle
- continue;
- if (states[thisButton] == 0xFF)//if previously released
- states[thisButton] = 0; //set to idle
- else
- states[thisButton] = 0xFF; //button just released
- }
- }
- #else
- /** POK_SIM code **/
- simulator.pollButtons();
- for (uint8_t thisButton = 0; thisButton < NUM_BTN; thisButton++) {
- uint8_t temp=0;
- switch (thisButton) {
- case 0:
- temp = simulator.leftHeld(); break;
- case 1:
- temp = simulator.upHeld(); break;
- case 2:
- temp = simulator.rightHeld(); break;
- case 3:
- temp = simulator.downHeld(); break;
- case 4:
- temp = simulator.aHeld(); break;
- case 5:
- temp = simulator.bHeld(); break;
- case 6:
- temp = simulator.cHeld(); break;
- default:
- break;
- }
-
- if (temp == HIGH) { //if button pressed
- states[thisButton]++; //increase button hold time
- } else {
- if (states[thisButton] == 0)//button idle
- continue;
- if (states[thisButton] == 0xFF)//if previously released
- states[thisButton] = 0; //set to idle
- else
- states[thisButton] = 0xFF; //button just released
- }
- }
-
- #endif // POK_SIM
-}
-
-/*
- * Returns true when 'button' is pressed.
- * The button has to be released for it to be triggered again.
- */
-bool Buttons::pressed(uint8_t button) {
- if (states[button] == 1)
- return true;
- else
- return false;
-}
-
-/*
- * return true if 'button' is released
- */
-bool Buttons::released(uint8_t button) {
- if (states[button] == 0xFF)
- return true;
- else
- return false;
-}
-
-/**
- * returns true ONCE when 'button' is held for 'time' frames
- * @param button The button's ID
- * @param time How much frames button must be held, between 1 and 254.
- * @return true when 'button' is held for 'time' frames
- */
-bool Buttons::held(uint8_t button, uint8_t time){
- if(states[button] == (time+1))
- return true;
- else
- return false;
-}
-
-/**
- * returns true every 'period' frames when 'button' is held
- * @param button The button's ID
- * @param period How much frames button must be held, between 1 and 254.
- * @return true if the button is held for the given time
- */
-bool Buttons::repeat(uint8_t button, uint8_t period) {
- if (period <= 1) {
- if ((states[button] != 0xFF) && (states[button]))
- return true;
- } else {
- if ((states[button] != 0xFF) && ((states[button] % period) == 1))
- return true;
- }
- return false;
-}
-
-/**
- *
- * @param button The button's ID
- * @return The number of frames during which the button has been held.
- */
-uint8_t Buttons::timeHeld(uint8_t button){
- if(states[button] != 0xFF)
- return states[button];
- else
- return 0;
-
-}
-
-void Buttons::pollButtons() {
- #ifdef POK_SIM
- simulator.pollButtons();
- #else
- uint8_t buttons_state_old = buttons_state;
- buttons_state = 0; // clear all
- if (upBtn()) buttons_state |= (1<<UPBIT);
- if (downBtn()) buttons_state |= (1<<DOWNBIT);
- if (leftBtn()) buttons_state |= (1<<LEFTBIT);
- if (rightBtn()) buttons_state |= (1<<RIGHTBIT);
- if (aBtn()) buttons_state |= (1<<ABIT);
- if (bBtn()) buttons_state |= (1<<BBIT);
- if (cBtn()) buttons_state |= (1<<CBIT);
- buttons_held = buttons_state & buttons_state_old; // only if both 1, end result is 1
- buttons_released = ~buttons_state & buttons_state_old; // if now zero, then 1 AND previous 1 = 1
- #endif // POK_SIM
-}
-
-uint8_t Buttons::aBtn() {
- #ifdef POK_SIM
- return simulator.aBtn();
- #else
- return Pokitto::heldStates[BTN_A];
- #endif // POK_SIM
-}
-
-
-uint8_t Buttons::bBtn() {
- #ifdef POK_SIM
- return simulator.bBtn();
- #else
- return Pokitto::heldStates[BTN_B];
- #endif // POK_SIM
-}
-
-uint8_t Buttons::cBtn() {
- uint8_t c;
- #ifdef POK_SIM
- c = simulator.cBtn();
- #else
- c = Pokitto::heldStates[BTN_C];
- #endif // POK_SIM
- return c;
-}
-
-uint8_t Buttons::leftBtn() {
- #ifdef POK_SIM
- return simulator.leftBtn();
- #else
- return Pokitto::heldStates[BTN_LEFT];
- #endif // POK_SIM
-}
-
-uint8_t Buttons::rightBtn() {
- #ifdef POK_SIM
- return simulator.rightBtn();
- #else
- return Pokitto::heldStates[BTN_RIGHT];
- #endif // POK_SIM
-}
-
-uint8_t Buttons::upBtn() {
- #ifdef POK_SIM
- return simulator.upBtn();
- #else
- return Pokitto::heldStates[BTN_UP];
- #endif // POK_SIM
-}
-
-uint8_t Buttons::downBtn() {
- #ifdef POK_SIM
- return simulator.downBtn();
- #else
- return Pokitto::heldStates[BTN_DOWN];
- #endif // POK_SIM
-}
-
-
-
-
-
-
-
-
-//** EOF **//
-
--- a/POKITTO_CORE/PokittoConsole.cpp Fri Dec 29 02:55:34 2017 +0000 +++ b/POKITTO_CORE/PokittoConsole.cpp Fri Dec 29 05:17:10 2017 +0000 @@ -311,3 +311,4 @@ +
--- a/POKITTO_CORE/PokittoCore.cpp Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1252 +0,0 @@
-/**************************************************************************/
-/*!
- @file PokittoCore.cpp
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-#include "PokittoCore.h"
-#include "Pokitto_settings.h"
-#include "PokittoConsole.h"
-#include "PokittoFonts.h"
-#include "PokittoTimer.h"
-#include "PokittoLogos.h"
-#include <stdlib.h>
-#ifndef DISABLEAVRMIN
-#define max(a,b) ((a)>(b)?(a):(b))
-#endif // DISABLEAVRMIN
-
-char selectedfile[25];
-
-//#define F
-#ifdef __ARMCC_VERSION
-typedef void (*func_t)(void);
-#endif
-
-#ifndef POK_SIM
-#include "iap.h"
-/** start the user application
-* https://community.nxp.com/thread/417695
-*
-*/
-void start_application(unsigned long app_link_location){
- //asm(" ldr sp, [r0,#0]");
- //asm(" ldr pc, [r0,#4]");
- //This code is not valid for the Cortex-m0+ instruction set.
- // The equivalent for this (as used by the KL26) is
-__disable_irq();// Start by disabling interrupts, before changing interrupt vectors
-
-// delete buttons
-//pokDeleteButtons();
-
-// completely kill button interrupts in preparation for reset
-LPC_PINT->IENR = 0;
-LPC_PINT->IENF = 0;
-
-SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk & ~(SysTick_CTRL_ENABLE_Msk); //disable systick
-LPC_SYSCON->PDRUNCFG |= (1 << 10); /* Power-down USB PHY */
-LPC_SYSCON->PDRUNCFG |= (1 << 8); /* Power-down USB PLL */
-
-// reset clock source to IRC
-LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
-LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */
-while (LPC_SYSCON->MAINCLKUEN & 0x01); /* Wait Until Updated */
-// switch clock selection to IRC
-LPC_SYSCON->MAINCLKSEL = 0; /* Select Clock Source */
-LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
-LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */
-while (LPC_SYSCON->MAINCLKUEN & 0x01); /* Wait Until Updated */
-//disable PLL clock output
-LPC_SYSCON->SYSPLLCLKUEN = 0;
-while (LPC_SYSCON->SYSPLLCLKUEN & 0x00);
-LPC_SYSCON->SYSPLLCTRL = 0;
-
-//kill peripherals
-LPC_SYSCON->MAINCLKSEL = 0;
-LPC_SYSCON->PRESETCTRL = 0; //disable all peripherals
-
-//power down PLL
-volatile uint32_t tmp;
-tmp = (LPC_SYSCON->PDRUNCFG & 0x000025FFL);
-tmp |= ((1<<7) & 0x000025FFL);
-LPC_SYSCON->PDRUNCFG = (tmp | 0x0000C800L); /* Power-down SYSPLL */
-
-//Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_IRC); //switch to IRC
-
-// clear all gpio states
-LPC_GPIO_PORT->PIN[0] = 0;
-LPC_GPIO_PORT->PIN[1] = 0;
-LPC_GPIO_PORT->PIN[2] = 0;
-
-SCB->VTOR = app_link_location;//APPL_ADDRESS; /* Change vector table address */
-#ifndef __ARMCC_VERSION
-asm(" mov r0, %[address]"::[address] "r" (app_link_location));
-asm(" ldr r1, [r0,#0]"); // get the stack pointer value from the program's reset vector
-asm(" mov sp, r1"); // copy the value to the stack pointer
-asm(" ldr r0, [r0,#4]"); // get the program counter value from the program's reset vector
-asm(" blx r0"); // jump to the' start address
-#else
-uint32_t *app_loc = (uint32_t*)app_link_location;
-__set_MSP (app_loc[0]);
-((func_t)(app_loc[1]))();
-#endif
-}
-#endif
-
-// returns a random integar between 0 and maxVal
-int random(int maxVal)
-{
- return random( 0, maxVal);
-}
-
-// returns a random integar between minVal and maxVal
-int random(int minVal, int maxVal)
-{
- // int rand(void); included by default from newlib
- return rand() % (maxVal-minVal+1) + minVal;
-}
-
-using namespace Pokitto;
-
-bool Core::run_state; // this definition needed
-
-/** Components */
-Backlight Core::backlight;
-Buttons Core::buttons;
-Battery Core::battery;
-#if POK_ENABLE_SOUND > 0
-Sound Core::sound;
-#endif
-Display Core::display;
-
-//GB Related
-uint8_t Core::startMenuTimer;
-uint8_t Core::timePerFrame;
-uint32_t Core::nextFrameMillis;
-uint32_t Core::frameCount;
-const char* Core::popupText;
-uint8_t Core::popupTimeLeft;
-uint16_t Core::frameDurationMicros;
-uint32_t Core::frameStartMicros, Core::frameEndMicros;
-uint8_t Core::volbar_visible=0;
-
-
-Core::Core() {
-
-}
-
-
-int Core::updateLoader (uint32_t version, uint32_t jumpaddress) {
- uint32_t counter=0;
- uint8_t data[256];
- /** prepare the flash writing **/
- float progress=0;
- int opg=-1;
- uint32_t fsize=0;
- fileEnd(); //
- fsize = fileGetPosition();
- if (fsize>0x40000-jumpaddress) fsize = 0x40000-jumpaddress; // shouldn't happen!!
- fileRewind();
- display.println("PLEASE WAIT");
- while (1) {
- //if (counter >= fsize-0x200) {
- // display.println("gotcha");
- //}
- if (counter >= fsize) {
- break;
- }
- opg=progress;
- if (fileReadBytes(&data[0],0x100)<0x100) {
- if (fsize-counter>0x100) {
- display.println("ERROR READING LOA.DER FILE");
- return 1; // 1 means error
- }
- }
- if (CopyPageToFlash(jumpaddress+counter,data)) {
- display.println("FLASH WRITE ERROR");
- return 1;
- } else {
- counter += 0x100;
- display.print(".");
- }
- }
- return 0; //success
-}
-
-void Core::showWarning() {
- display.enableDirectPrinting(true);
- display.directbgcolor = COLOR_BLACK;
- display.clearLCD();
- display.directcolor = COLOR_RED;
- display.setFont(fntC64UIGfx);
- display.adjustCharStep = 0;
- display.adjustLineStep = 0;
- display.setCursor(10*8,9);
- display.print("WARNING!");
- display.directcolor = COLOR_WHITE;
- display.setCursor(5*8,4*9);
- display.print("LOUD SOUND THROUGH");
- display.setCursor(2*8,5*9);
- display.print("HEADPHONES COULD DAMAGE");
- display.setCursor(7*8,6*9);
- display.print("YOUR HEARING.");
- display.setCursor(5*8,8*9);
- display.print("USE "); display.directcolor = COLOR_GREEN;
- display.print("0-100% VOLUME");
- display.directcolor = COLOR_WHITE;
- display.setCursor(5*8,9*9);
- display.print("FOR LISTENING WITH");
- display.setCursor(8*8,10*9);
- display.print("HEADPHONES");
- display.setCursor(5*8,12*9);
- display.print("USE "); display.directcolor = COLOR_RED;
- display.print("> 100% VOLUME"); display.directcolor = COLOR_GREEN;
- display.directcolor = COLOR_WHITE;
- display.setCursor(1*8,13*9);
- display.print("ONLY FOR LISTENING VIA THE");
- display.setCursor(5*8,14*9);
- display.print("BUILT-IN SPEAKER");
- display.setCursor(5*8,17*9);
- display.print("PRESS ");display.directcolor = COLOR_GREEN;
- display.print("C ");display.directcolor = COLOR_WHITE;
- display.print("TO ACCEPT");
- while (!buttons.cBtn()) {
- wait(100);
- }
- display.clearLCD();
- display.enableDirectPrinting(false);
-}
-
-void Core::jumpToLoader() {
- //display.setFont(font5x7);
- //display.adjustCharStep=1;
- //display.adjustLineStep=2;
- display.fontSize=1;
- display.directbgcolor=COLOR_BLACK;
- display.directcolor=COLOR_GREEN;
- display.clearLCD();
- display.setCursor(0,0);
- display.enableDirectPrinting(true);
- #ifdef POK_SIM
- display.println("LOADER IS NOT AVAILABLE ON THE SIMULATOR. PRESS A TO RETURN.");
- #else
- uint32_t* bootinfo;
- uint32_t bootversion=0, sdversion=0, sdjump=0;
- bool flashloader=false, checkforboot=true;
- //check for loa.der on SD card
- #if POK_ENABLE_LOADER_UPDATES > 0
- pokInitSD();
- if (fileOpen("LOA.DER", FILE_MODE_BINARY)==0) {
- //LOA.DER found on SD
- fileEnd(); // go to end
- fileSeekRelative(-8); //rewind 8 bytes
- uint32_t* tptr = &sdversion;
- fileReadBytes((uint8_t*)tptr,4); //read version number of loader on SD card
- tptr = &sdjump;
- fileReadBytes((uint8_t*)tptr,4); //read jump address of loader on sd card
- fileRewind();
- }
- #endif
- //now start searching for bootkey
- while (checkforboot)
- {
- checkforboot=false; flashloader=false;
- bootinfo = (uint32_t*)0x3FFF4;
- if (*bootinfo != 0xB007AB1E) bootinfo = (uint32_t*)0x3FF04; //allow couple of alternative locations
- if (*bootinfo != 0xB007AB1E) bootinfo = (uint32_t*)0x3FE04; //allow couple of alternative locations
- if (*bootinfo != 0xB007AB1E) bootinfo = (uint32_t*)0x3F004; //for futureproofing
- if (*bootinfo != 0xB007AB1E) {
- // no bootkey found at all
- display.directcolor=COLOR_YELLOW;
- display.println("NO LOADER INSTALLED");
- if (sdversion==0 || sdjump < 0x38000) {
- //file open of loader failed
- display.println("NO VALID LOA.DER ON SD");
- display.println("");
- display.directcolor=COLOR_GREEN;
- display.println("PUT LOA.DER ON SD & REBOOT");
- } else flashloader=true;
- } else {
- //loader was found
- //check if we should update the loader
- display.directcolor=COLOR_CYAN;
- display.print("LOADER V.");
- display.directcolor=COLOR_WHITE;
- display.println(*(bootinfo+1));
- #if POK_ENABLE_LOADER_UPDATES
- if (sdversion>(*(bootinfo+1))) flashloader=true;
- else start_application(*(bootinfo+2)); //never returns
- #else
- start_application(*(bootinfo+2)); //never returns
- #endif
- }
- // update loader if it was requested
- if(flashloader) {
- display.directcolor=COLOR_MAGENTA;
- display.print("NEW LOADER ON SD V.");
- display.directcolor=COLOR_WHITE;
- display.println(sdversion);
- display.directcolor=COLOR_GREEN;
- display.println("UPDATE LOADER?\n(UP=YES, DOWN=CANCEL)");
- while(1) {
- if (buttons.upBtn()) {
- if (updateLoader(sdversion,sdjump)) {
- display.println("PUT LOA.DER ON SD AND RETRY");
- } else {
- display.println("SUCCESS!!");
- checkforboot=true; //recheck
- }
- break;
- }
- if (buttons.downBtn()) return;
- }
- } // if flashloader
- } // while checkforboot
- #endif // POK_SIM
- while (!buttons.aBtn()) {
- buttons.pollButtons();
- if (buttons.aBtn()) {
- while (buttons.aBtn()) {
- buttons.pollButtons();
- }
- return;
- }
- }
-}
-
-void Core::askLoader() {
- display.enableDirectPrinting(true);
- display.directbgcolor = COLOR_BLACK;
- display.clearLCD();
- display.directcolor = COLOR_RED;
- display.setFont(fntC64UIGfx);
- display.fontSize=1;
- display.adjustCharStep = 0;
- display.adjustLineStep = 0;
- display.directcolor=COLOR_GREEN;
- display.set_cursor(12*8,6*8);
- display.print("ijkl");
- display.set_cursor(12*8,7*8);
- display.print("mnop");
- display.set_cursor(12*8,8*8);
- display.print("qrst");
- display.set_cursor(12*8,9*8);
- display.print("uvwx");
- display.set_cursor(5*8,12*8);
- display.print("PRESS");
- display.directcolor=COLOR_WHITE;
- display.print(" C ");
- display.directcolor=COLOR_GREEN;
- display.print("FOR LOADER");
- display.directcolor=COLOR_WHITE;
- display.fontSize=2;
- int countd=POK_LOADER_COUNTDOWN; uint16_t c2 = getTime();
- while (countd) {
- buttons.pollButtons();
- display.set_cursor(13*8,15*8);
- display.print(countd);
- if (getTime()>c2+1000) {
- c2=getTime();
- countd--;
- }
- if (cBtn()) {while (cBtn()) buttons.pollButtons();jumpToLoader();countd=0;}
- if (aBtn()) {while (aBtn()) buttons.pollButtons();countd=0;}
- if (bBtn()) {while (bBtn()) buttons.pollButtons();countd=0;}
- }
- display.fontSize=1;
- display.clearLCD();
- display.enableDirectPrinting(false);
-}
-
-
-void Core::drawvolbar(int x, int y, int level, bool text) {
- uint16_t oldcol = display.directcolor;
- if (text) display.directRectangle(0,0,50,50,COLOR_BLACK);
- display.directcolor = COLOR_GREEN;
- if (text) {
- bool temp = display.isDirectPrintingEnabled();
- display.enableDirectPrinting(true);
- display.print(x-1,y-20,(int)sound.getVolume());
- display.print(" ");
- display.enableDirectPrinting(temp);
- }
- if (level<12) display.directcolor = COLOR_GRAY_80;
- display.directBitmap(x,y,Pokitto_volumebar,1,1);
- if (level<24) display.directcolor = COLOR_GRAY_80;
- display.directBitmap(x+8,y,Pokitto_volumebar,1,1);
- display.directBitmap(x+8,y-4,Pokitto_volumebar,1,1);
- display.directcolor = COLOR_RED;
- if (level<48) display.directcolor = COLOR_GRAY_80;
- display.directBitmap(x+16,y,Pokitto_volumebar,1,1);
- display.directBitmap(x+16,y-4,Pokitto_volumebar,1,1);
- display.directBitmap(x+16,y-8,Pokitto_volumebar,1,1);
-
- if (level<96) {
- display.directcolor = COLOR_GRAY_80;
- }
- display.directBitmap(x+24,y,Pokitto_volumebar,1,1);
- display.directBitmap(x+24,y-4,Pokitto_volumebar,1,1);
- display.directBitmap(x+24,y-8,Pokitto_volumebar,1,1);
- display.directBitmap(x+24,y-12,Pokitto_volumebar,1,1);
- if (level<160) {
- display.directcolor = COLOR_GRAY_80;
- }
- display.directBitmap(x+32,y,Pokitto_volumebar,1,1);
- display.directBitmap(x+32,y-4,Pokitto_volumebar,1,1);
- display.directBitmap(x+32,y-8,Pokitto_volumebar,1,1);
- display.directBitmap(x+32,y-12,Pokitto_volumebar,1,1);
- display.directBitmap(x+32,y-16,Pokitto_volumebar,1,1);
- display.directcolor = oldcol;
-}
-
-
-#ifdef POK_SIM
-#define VINCMULT 1
-#else
-#define VINCMULT 50
-#endif //POK_SIM
-void Core::setVolLimit() {
- display.enableDirectPrinting(true);
- display.adjustCharStep = 0;
- sound.setMaxVol(VOLUME_HEADPHONE_MAX);
- int dstate=1;
- bool wipe = true;
- float vol = sound.getVolume(); float tvol;
- volbar_visible=0;
- while (core.isRunning() && dstate){
- switch (dstate) {
- case 1:
- //redraw
- if (wipe) {
- display.clearLCD();
- display.directcolor = COLOR_WHITE;
- display.setCursor(4*8,2*8);
- display.print("SELECT VOLUME LIMIT");
- display.setCursor(5*8,17*9);
- display.print("PRESS ");
- display.directcolor = COLOR_GREEN;
- display.print("A");
- display.directcolor = COLOR_WHITE;
- display.print(" TO ACCEPT");
- display.directcolor = COLOR_GREEN;
- // draw frame below first
- display.setCursor(0,11*8);
- display.println(" abbbbbbbbbbbbbbbbbbbbbbbc");
- display.println(" | |");
- display.println(" | |");
- display.println(" | |");
- display.println(" | |");
- display.println(" dbbbbbbbbbbbbbbbbbbbbbbbe");
- } // wipe = true
- display.setCursor(6*8,17*9);
- if (sound.getVolume()-5<=VOLUME_HEADPHONE_MAX) display.directcolor = COLOR_WHITE;
- else display.directcolor = COLOR_RED;
- display.directBitmap(21*8-4,6*8,Pokitto_headphones,1,2);
- display.setCursor(3*8,6*8+6);
- display.print("HEADPHONES");
- display.setCursor(3*8,8*8+2);
- if (sound.getVolume()-8>VOLUME_HEADPHONE_MAX) display.print("TOO LOUD!");
- else display.print("OK ");
- display.directcolor = COLOR_GREEN;
- display.directBitmap(21*8-4,12*8,Pokitto_speaker,1,2);
- display.setCursor(3*8,12*8+6);
- display.print("VOLUME MAX");
- display.setCursor(3*8,14*8+2);
- tvol = (vol/float(VOLUME_HEADPHONE_MAX))*100;
- if (tvol > 100 && tvol < 120) tvol=100;
- if (sound.getVolume()-5>VOLUME_HEADPHONE_MAX) { display.directcolor=COLOR_RED;}
- else display.directcolor=COLOR_GREEN;
- display.print(int(sound.getVolume()));
- //display.print(int(tvol));
- display.print(" ");
- display.directcolor=COLOR_GREEN;
- drawvolbar(14*8,14*8+4+2,sound.getVolume(),false);
- //display.setCursor(1,10);
- //display.print(vol);
- dstate=2; break;
- case 2:
- buttons.pollButtons();
- if (aBtn()) {dstate=0;while(aBtn()){buttons.pollButtons();};break;}
- if (rightBtn()) {
- if (vol >= VOLUME_HEADPHONE_MAX && vol < VOLUME_HEADPHONE_MAX+1 ) vol += 0.00025f*VINCMULT;
- else if (vol >= VOLUME_HEADPHONE_MAX) vol += 0.025f*VINCMULT;
- else vol += 0.05f*VINCMULT;
- if (vol > VOLUME_HEADPHONE_MAX + 20) {
- sound.setMaxVol(VOLUME_SPEAKER_MAX);
- }
- if (vol > VOLUME_SPEAKER_MAX) vol=VOLUME_SPEAKER_MAX;
- sound.setVolume(vol);
- dstate=1; wipe=false;
- break;
- }
- if (leftBtn()) {
- vol -= 0.025f*VINCMULT;
- if (vol <= VOLUME_HEADPHONE_MAX) sound.setMaxVol(VOLUME_HEADPHONE_MAX);
- if (vol < 0) vol=0;
- sound.setVolume(vol);
- dstate=1; wipe=false;
- break;
- }
- break;
- }
- }
-}
-
-void Core::begin() {
-
- init(); // original functions
- timePerFrame = POK_FRAMEDURATION;
- //nextFrameMillis = 0;
- //frameCount = 0;
- frameEndMicros = 1;
- startMenuTimer = 255;
- //read default settings from flash memory (set using settings.hex)
- readSettings();
- //init everything
- backlight.begin();
- backlight.set(BACKLIGHT_MAX);
- buttons.begin();
- buttons.update();
- battery.begin();
- display.begin();
- #if POK_DISPLAYLOGO
- showLogo();
- #endif // POK_DISPLAYLOGO
-
- display.enableDirectPrinting(true);
- display.directbgcolor = COLOR_BLACK;
- display.clearLCD();
- display.setFont(fntC64UIGfx);
-
- display.enableDirectPrinting(true);
- display.directbgcolor = COLOR_BLACK;
- display.directcolor = COLOR_GREEN;
- display.clearLCD();
- display.setFont(fntC64UIGfx);
- display.adjustCharStep=0;
- display.adjustLineStep=1;
- #ifdef JUSTLOAD
- jumpToLoader();
- #endif
-
- #ifndef DISABLE_LOADER
- askLoader();
- #endif
-
- #ifndef DISABLE_SOUND_WARNING
- //showWarning();
- setVolLimit();
- //sound.setVolume(sound.getVolume());//make sure we're at set volume before continue
- sound.volumeUp();
- #endif
- display.enableDirectPrinting(false);
- display.adjustCharStep=1;
- display.adjustLineStep=1;
- display.fontSize=1;
- display.textWrap=true;
- #if POK_GAMEBUINO_SUPPORT > 0
- display.setFont(font5x7);
- #else
- display.setFont(fontC64);
- #endif
- #if POK_ENABLE_SOUND > 0
- sound.begin();
-
- //mute when B is held during start up or if battery is low
- battery.update();
- if(buttons.pressed(BTN_B) || (battery.level == 0)){
- sound.setVolume(0);
- }
- else{ //play the startup sound on each channel for it to be louder
- #if POK_GBSOUND > 0
- #if(NUM_CHANNELS > 0)
- sound.playPattern(startupSound, 0);
- #endif
- #if(NUM_CHANNELS > 1)
- sound.playPattern(startupSound, 1);
- #endif
- #if(NUM_CHANNELS > 2)
- sound.playPattern(startupSound, 2);
- #endif
- #if(NUM_CHANNELS > 3)
- sound.playPattern(startupSound, 3);
- #endif
- #endif // POK_GBSOUND
- }
- #endif // POK ENABLE_SOUND
-}
-
-void Core::init() {
- run_state = true;
- display.enableDirectPrinting(false);
- display.setFont(DEFAULT_FONT);
- initClock();
- initGPIO();
- initButtons();
- initRandom();
- //initAudio();
- //initDisplay();
-}
-
-void Core::init(uint8_t switches) {
- run_state = true;
- display.enableDirectPrinting(false);
- display.setFont(DEFAULT_FONT);
- initClock();
- initGPIO();
- initButtons();
- initRandom();
- //initAudio();
- //initDisplay();
-}
-
-void Core::initButtons() {
- #ifndef POK_SIM
- Pokitto::initButtons();
- #endif
-}
-
-bool Core::isRunning() {
- #ifdef POK_SIM
- run_state = simulator.isRunning();
- #endif // POK_SIM
- return run_state;
-}
-
-void Core::initDisplay() {
- #if POK_DISPLAYLOGO > 0
- showLogo();
- #endif
- #if POK_USE_CONSOLE > 0
- console.AddMessage(MSOURCE_LCD,MSG_INIT_OK);
- #endif
-}
-
-void Core::showLogo() {
- uint32_t now;
- uint8_t state=0; //jump directly to logo, bypass teeth
- uint16_t counter=0, i=0;
- uint16_t sc;
- while (state < 255/6) {
- now=getTime();
- if (now>refreshtime) {
- refreshtime=now+30;
- switch (state) {
- case 0:
- /** POKITTO CLEAN **/
- display.directbgcolor = COLOR_BLACK;
- display.fillLCD(display.directbgcolor);
- sc = COLOR_BLACK;
- state++;
- break;
- case 1:
- /** POKITTO FADE IN **/
- display.directcolor = display.interpolateColor(sc, COLOR_GREEN, i);
- display.directBitmap(POK_LCD_W/2 - (*Pokitto_logo/2),POK_LCD_H/2-(*(Pokitto_logo+1)/2),Pokitto_logo,1,1);
- i += 28;
- if (i>=0xFF) { state++; i=0;}
- break;
- case 2:
- /** POKITTO WAIT **/
- display.directcolor = COLOR_GREEN;
- display.directBitmap(POK_LCD_W/2 - (*Pokitto_logo/2),POK_LCD_H/2-(*(Pokitto_logo+1)/2),Pokitto_logo,1,1);
- i+= 0x3F;
- if (i>0x3FF) state = 255;
- break;
- }
- if(buttons.aBtn()) state=255;
- }
- }
-}
-
-void Core::readSettings() {
- // ToDo
- /*display.contrast = SCR_CONTRAST;
- backlight.backlightMin = BACKLIGHT_MIN;
- backlight.backlightMax = BACKLIGHT_MAX;
- backlight.ambientLightMin = AMBIENTLIGHT_MIN;
- backlight.ambientLightMax = AMBIENTLIGHT_MAX;
-*/
- sound.setMaxVol(VOLUME_HEADPHONE_MAX);
- sound.globalVolume = VOLUME_STARTUP;
-
- startMenuTimer = START_MENU_TIMER;
-/*
- battery.thresolds[0] = BAT_LVL_CRITIC;
- battery.thresolds[1] = BAT_LVL_LOW;
- battery.thresolds[2] = BAT_LVL_MED;
- battery.thresolds[3] = BAT_LVL_FULL;*/
-}
-
-void Core::titleScreen(const char* name){
- titleScreen(name, 0);
-}
-
-void Core::titleScreen(const uint8_t* logo){
- titleScreen((""), logo);
-}
-
-void Core::titleScreen(){
- titleScreen((""));
-}
-
-void Core::titleScreen(const char* name, const uint8_t *logo){
- display.setFont(font5x7);
- if(startMenuTimer){
- display.fontSize = 1;
- display.textWrap = false;
- display.persistence = false;
- battery.show = false;
- display.setColor(BLACK);
- while(isRunning()){
- if(update()){
- uint8_t logoOffset = name[0]?display.fontHeight:0; //add an offset the logo when there is a name to display
- //draw graphics
- display.setColorDepth(1);
- display.setColor(3);
- //display.drawBitmap(0,0, gamebuinoLogo);
- display.setColor(1);
- if(logo){
- display.drawBitmap(0, 12+logoOffset, logo);
- }
- display.cursorX = 0;
- display.cursorY = 12;
- display.print(name);
-
- //A button
- display.cursorX = LCDWIDTH - display.fontWidth*3 -1;
- display.cursorY = LCDHEIGHT - display.fontHeight*3 - 3;
- if((frameCount/16)%2)
- display.println(("\25 \20"));
- else
- display.println(("\25\20 "));
- //B button
- display.cursorX = LCDWIDTH - display.fontWidth*3 - 1;
- display.cursorY++;
- if(sound.globalVolume)
- display.println(("\26\23\24"));
- else
- display.println(("\26\23x"));
- //C button
- display.cursorX = LCDWIDTH - display.fontWidth*3 - 1;
- display.cursorY++;
- //display.println(F("\27SD"));
-
- //toggle volume when B is pressed
- if(buttons.pressed(BTN_B)){
- sound.setVolume(sound.getVolume() + 1);
- sound.playTick();
- }
- //leave the menu
- if(buttons.pressed(BTN_A) || ((frameCount>=startMenuTimer)&&(startMenuTimer != 255))){
- startMenuTimer = 255; //don't automatically skip the title screen next time it's displayed
- sound.stopPattern(0);
- sound.playOK();
- break;
- }
- //flash the loader
- //if(buttons.pressed(BTN_C))
- // ToDo changeGame();
- }
- }
- battery.show = true;
- }
-}
-
-bool Core::update(bool useDirectMode) {
-#if POK_STREAMING_MUSIC
- sound.updateStream();
- #endif
-
- if ((((nextFrameMillis - getTime())) > timePerFrame) && frameEndMicros) { //if time to render a new frame is reached and the frame end has ran once
- nextFrameMillis = getTime() + timePerFrame;
- frameCount++;
-
- frameEndMicros = 0;
- backlight.update();
- buttons.update();
- battery.update();
-
- return true;
-
- } else {
- if (!frameEndMicros) { //runs once at the end of the frame
- #if POK_ENABLE_SOUND > 0
- sound.updateTrack();
- sound.updatePattern();
- sound.updateNote();
- #endif
- updatePopup();
- displayBattery();
-
- if(!useDirectMode)
- display.update(); //send the buffer to the screen
-
- frameEndMicros = 1; //jonne
-
- }
- return false;
- }
-}
-
-void Core::displayBattery(){
-#if (ENABLE_BATTERY > 0)
- //display.setColor(BLACK, WHITE);
- uint8_t ox,oy;
- ox=display.cursorX;
- oy=display.cursorY;
- display.cursorX = LCDWIDTH-display.fontWidth+1;
- display.cursorY = 0;
- switch(battery.level){
- case 0://battery critic, power down
- sound.stopPattern();
- backlight.set(0);
- display.clear();
- display.fontSize = 1;
- display.print(("LOW BATTERY\n"));
- display.print(battery.voltage);
- display.print(("mV\n\nPLEASE\nTURN OFF"));
- display.update();
- break;
- case 1: //empty battery
- if((frameCount % 16) < 8) display.print('\7'); //blinking battery
- else display.print('x');
- break;
- case 2://low battery
- case 3://full battery
- case 4://full battery
- if(battery.show){
- display.print(char(5+battery.level));
- }
- break;
- default:
- if(battery.show){
- display.print('/');
- }
- break;
- }
-display.cursorX = ox;
-display.cursorY = oy;
-#endif
-}
-
-char* Core::filemenu(char *ext) {
- display.persistence = false;
- uint16_t oldpal0=display.palette[0];
- uint16_t oldpal1=display.palette[1];
- uint16_t oldpal2=display.palette[2];
- display.palette[2]=COLOR_GREEN;
- display.palette[1]=COLOR_WHITE;
- display.palette[0]=COLOR_BLACK;
- uint8_t oldbg=display.bgcolor;
- uint8_t oldfg=display.color;
- display.color=1;
- display.bgcolor=0;
-
- int8_t activeItem = 0;
- int16_t currentY = 100;
- int16_t targetY = 0, rowh = display.fontHeight + 2;
- boolean exit = false;
-
- char* txt;
-
-
- while (isRunning()) {
- if (update()) {
- getFirstFile(ext);
- if (buttons.pressed(BTN_A) || buttons.pressed(BTN_B) || buttons.pressed(BTN_C)) {
- exit = true; //time to exit menu !
- targetY = - display.fontHeight * 10 - 2; //send the menu out of the screen
- if (buttons.pressed(BTN_A)) {
- //answer = activeItem;
- sound.playOK();
- } else {
- sound.playCancel();
- }
- }
- if (exit == false) {
- if (buttons.repeat(BTN_DOWN,4)) {
- activeItem++;
- sound.playTick();
- }
- if (buttons.repeat(BTN_UP,4)) {
- activeItem--;
- sound.playTick();
- }
- //don't go out of the menu
- //if (activeItem == length) activeItem = 0;
- //if (activeItem < 0) activeItem = length - 1;
- if (currentY>targetY) currentY-=16;
- if (currentY<targetY) currentY=targetY;
- //targetY = -rowh * activeItem + (rowh+4); //center the menu on the active item
- } else { //exit :
- if (currentY>targetY) currentY-=16;
- if (currentY<targetY) currentY=targetY;
- if ((currentY - targetY) <= 1)
- {
- display.bgcolor=oldbg;
- display.color=oldfg;
- display.palette[0] = oldpal0;
- display.palette[1] = oldpal1;
- display.palette[2] = oldpal2;
- return selectedfile;
- }
-
- }
- //draw a fancy menu
- //currentY = 0;//(currentY + targetY) / 2 + 5;
- display.cursorX = 0;
- display.cursorY = currentY;
- display.textWrap = false;
- uint16_t fc,bc;
- fc = display.color;
- bc = display.bgcolor;
- //getFirstFile(ext);
- for (int i = 0; i<20; i++) {
- display.invisiblecolor=255;
- display.cursorY = currentY + rowh * i;
- if (i==3) display.color=1;
- if (i == activeItem){
- display.cursorX = 3;
-
- //display.fillRoundRect(0, currentY + display.fontHeight * activeItem - 2, LCDWIDTH, (display.fontHeight+3), 3);
- display.color=2;
- display.fillRect(0, currentY + rowh * activeItem - 2, LCDWIDTH, (rowh));
- display.setColor(0,2);
- } else display.setColor(1,0);
- //display.println((char*)*(const unsigned int*)(items+i));
- //display.println((int)i);
- txt = getNextFile(ext);
- if (txt) {
- display.println(txt);
- if (i == activeItem) {
- strcpy(selectedfile,txt);
- }
- } else i--;
- display.setColor(1,0);
- } // draw menu loop
- } // update
- }
- return 0;
-}
-
-char* Core::filemenu() {
- return filemenu("");
-}
-
-int8_t Core::menu(const char* const* items, uint8_t length) {
-#if (ENABLE_GUI > 0)
- display.persistence = false;
- int8_t activeItem = 0;
- int16_t currentY = display.height;
- int16_t targetY = 0, rowh = display.fontHeight + 2;
- boolean exit = false;
- int8_t answer = -1;
- while (isRunning()) {
- if (update()) {
- if (buttons.pressed(BTN_A) || buttons.pressed(BTN_B) || buttons.pressed(BTN_C)) {
- exit = true; //time to exit menu !
- targetY = - display.fontHeight * length - 2; //send the menu out of the screen
- if (buttons.pressed(BTN_A)) {
- answer = activeItem;
- sound.playOK();
- } else {
- sound.playCancel();
- }
- }
- if (exit == false) {
- if (buttons.repeat(BTN_DOWN,4)) {
- activeItem++;
- sound.playTick();
- }
- if (buttons.repeat(BTN_UP,4)) {
- activeItem--;
- sound.playTick();
- }
- //don't go out of the menu
- if (activeItem == length) activeItem = 0;
- if (activeItem < 0) activeItem = length - 1;
-
- targetY = -rowh * activeItem + (rowh+4); //center the menu on the active item
- } else { //exit :
- if ((currentY - targetY) <= 1)
- return (answer);
- }
- //draw a fancy menu
- currentY = (currentY + targetY) / 2;
- display.cursorX = 0;
- display.cursorY = currentY;
- display.textWrap = false;
- uint16_t fc,bc;
- fc = display.color;
- bc = display.bgcolor;
- for (byte i = 0; i < length; i++) {
- display.cursorY = currentY + rowh * i;
- if (i == activeItem){
- display.cursorX = 3;
-
- //display.fillRoundRect(0, currentY + display.fontHeight * activeItem - 2, LCDWIDTH, (display.fontHeight+3), 3);
- display.fillRect(0, currentY + rowh * activeItem - 2, LCDWIDTH, (rowh));
- display.setColor(bc,fc);
- } else display.setColor(fc,bc);
-
- display.println((char*)*(const unsigned int*)(items+i));
- display.setColor(fc,bc);
- }
-
- }
- }
-#else
- return 0;
-#endif
- return 0;
-}
-
-void Core::keyboard(char* text, uint8_t length) {
-#if (ENABLE_GUI > 0)
- display.persistence = false;
- //memset(text, 0, length); //clear the text
- text[length-1] = '\0';
- //active character in the typing area
- int8_t activeChar = 0;
- //selected char on the keyboard
- int8_t activeX = 0;
- int8_t activeY = 2;
- //position of the keyboard on the screen
- int8_t currentX = LCDWIDTH;
- int8_t currentY = LCDHEIGHT;
- int8_t targetX = 0;
- int8_t targetY = 0;
-
- while (1) {
- if (update()) {
- //move the character selector
- if (buttons.repeat(BTN_DOWN, 4)) {
- activeY++;
- sound.playTick();
- }
- if (buttons.repeat(BTN_UP, 4)) {
- activeY--;
- sound.playTick();
- }
- if (buttons.repeat(BTN_RIGHT, 4)) {
- activeX++;
- sound.playTick();
- }
- if (buttons.repeat(BTN_LEFT, 4)) {
- activeX--;
- sound.playTick();
- }
- //don't go out of the keyboard
- if (activeX == KEYBOARD_W) activeX = 0;
- if (activeX < 0) activeX = KEYBOARD_W - 1;
- if (activeY == KEYBOARD_H) activeY = 0;
- if (activeY < 0) activeY = KEYBOARD_H - 1;
- //set the keyboard position on screen
- targetX = -(display.fontWidth+1) * activeX + LCDWIDTH / 2 - 3;
- targetY = -(display.fontHeight+1) * activeY + LCDHEIGHT / 2 - 4 - display.fontHeight;
- //smooth the keyboard displacement
- currentX = (targetX + currentX) / 2;
- currentY = (targetY + currentY) / 2;
- //type character
- if (buttons.pressed(BTN_A)) {
- if (activeChar < (length-1)) {
- byte thisChar = activeX + KEYBOARD_W * activeY;
- if((thisChar == 0)||(thisChar == 10)||(thisChar == 13)) //avoid line feed and carriage return
- continue;
- text[activeChar] = thisChar;
- text[activeChar+1] = '\0';
- }
- activeChar++;
- sound.playOK();
- if (activeChar > length)
- activeChar = length;
- }
- //erase character
- if (buttons.pressed(BTN_B)) {
- activeChar--;
- sound.playCancel();
- if (activeChar >= 0)
- text[activeChar] = 0;
- else
- activeChar = 0;
- }
- //leave menu
- if (buttons.pressed(BTN_C)) {
- sound.playOK();
- while (1) {
- if (update()) {
- //display.setCursor(0,0);
- display.println(("You entered\n"));
- display.print(text);
- display.println(("\n\n\n\x15:okay \x16:edit"));
- if(buttons.pressed(BTN_A)){
- sound.playOK();
- return;
- }
- if(buttons.pressed(BTN_B)){
- sound.playCancel();
- break;
- }
- }
- }
- }
- //draw the keyboard
- for (int8_t y = 0; y < KEYBOARD_H; y++) {
- for (int8_t x = 0; x < KEYBOARD_W; x++) {
- display.drawChar(currentX + x * (display.fontWidth+1), currentY + y * (display.fontHeight+1), x + y * KEYBOARD_W, 1);
- }
- }
- //draw instruction
- display.cursorX = currentX-display.fontWidth*6-2;
- display.cursorY = currentY+1*(display.fontHeight+1);
- display.print(("\25type"));
-
- display.cursorX = currentX-display.fontWidth*6-2;
- display.cursorY = currentY+2*(display.fontHeight+1);
- display.print(("\26back"));
-
- display.cursorX = currentX-display.fontWidth*6-2;
- display.cursorY = currentY+3*(display.fontHeight+1);
- display.print(("\27save"));
-
- //erase some pixels around the selected character
- display.setColor(WHITE);
- display.drawFastHLine(currentX + activeX * (display.fontWidth+1) - 1, currentY + activeY * (display.fontHeight+1) - 2, 7);
- //draw the selection rectangle
- display.setColor(BLACK);
- display.drawRoundRect(currentX + activeX * (display.fontWidth+1) - 2, currentY + activeY * (display.fontHeight+1) - 3, (display.fontWidth+2)+(display.fontWidth-1)%2, (display.fontHeight+5), 3);
- //draw keyboard outline
- //display.drawRoundRect(currentX - 6, currentY - 6, KEYBOARD_W * (display.fontWidth+1) + 12, KEYBOARD_H * (display.fontHeight+1) + 12, 8, BLACK);
- //text field
- display.drawFastHLine(0, LCDHEIGHT-display.fontHeight-2, LCDWIDTH);
- display.setColor(WHITE);
- display.fillRect(0, LCDHEIGHT-display.fontHeight-1, LCDWIDTH, display.fontHeight+1);
- //typed text
- display.cursorX = 0;
- display.cursorY = LCDHEIGHT-display.fontHeight;
- display.setColor(BLACK);
- display.print(text);
- //blinking cursor
- if (((frameCount % 8) < 4) && (activeChar < (length-1)))
- display.drawChar(display.fontWidth * activeChar, LCDHEIGHT-display.fontHeight, '_',1);
- }
- }
-#endif
-}
-
-void Core::popup(const char* text, uint8_t duration){
-#if (ENABLE_GUI > 0)
- popupText = text;
- popupTimeLeft = duration+12;
-#endif
-}
-
-void Core::updatePopup(){
-#if (ENABLE_GUI > 0)
- if (popupTimeLeft){
- uint8_t yOffset = 0;
- if(popupTimeLeft<12){
- yOffset = 12-popupTimeLeft;
- }
- display.fontSize = 1;
- display.setColor(WHITE);
- display.fillRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3);
- display.setColor(BLACK);
- display.drawRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3);
- display.cursorX = 4;
- display.cursorY = LCDHEIGHT-display.fontHeight+yOffset-1;
- display.print(popupText);
- popupTimeLeft--;
- }
-#endif
-}
-
-void Core::setFrameRate(uint8_t fps) {
- timePerFrame = 1000 / fps;
- sound.prescaler = fps / 20;
- sound.prescaler = __avrmax(1, sound.prescaler);
-}
-
-void Core::pickRandomSeed(){
- initRandom();
-}
-
-bool Core::collidePointRect(int16_t x1, int16_t y1 ,int16_t x2 ,int16_t y2, int16_t w, int16_t h){
- if((x1>=x2)&&(x1<x2+w))
- if((y1>=y2)&&(y1<y2+h))
- return true;
- return false;
-}
-
-bool Core::collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1 ,int16_t x2 ,int16_t y2, int16_t w2, int16_t h2){
- return !( x2 >= x1+w1 ||
- x2+w2 <= x1 ||
- y2 >= y1+h1 ||
- y2+h2 <= y1 );
-}
-
-bool Core::collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2){
- int16_t w1 = pgm_read_byte(b1);
- int16_t h1 = pgm_read_byte(b1 + 1);
- int16_t w2 = pgm_read_byte(b2);
- int16_t h2 = pgm_read_byte(b2 + 1);
-
- if(collideRectRect(x1, y1, w1, h1, x2, y2, w2, h2) == false){
- return false;
- }
-
- int16_t xmin = (x1>=x2)? 0 : x2-x1;
- int16_t ymin = (y1>=y2)? 0 : y2-y1;
- int16_t xmax = (x1+w1>=x2+w2)? x2+w2-x1 : w1;
- int16_t ymax = (y1+h1>=y2+h2)? y2+h2-y1 : h1;
- for(uint8_t y = ymin; y < ymax; y++){
- for(uint8_t x = xmin; x < xmax; x++){
- if(display.getBitmapPixel(b1, x, y) && display.getBitmapPixel(b2, x1+x-x2, y1+y-y2)){
- return true;
- }
- }
- }
- return false;
-}
-
-
-//** EOF **//
-
-
-
-
-
-
-
-
-
--- a/POKITTO_CORE/PokittoCore.h Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +0,0 @@
-/**************************************************************************/
-/*!
- @file PokittoCore.h
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-#ifndef POKITTOCORE_H
-#define POKITTOCORE_H
-
-#include <stdint.h>
-#include <math.h>
-#ifndef POK_SIM
- #include "pwmout_api.h"
- #include "HWButtons.h"
-#else
- #include "PokittoSimulator.h"
-#endif
-#if POK_USE_CONSOLE > 0
- #include "PokittoConsole.h"
-#endif // POK_USE_CONSOLE
-#if POK_ENABLE_SD > 0
- #include "PokittoDisk.h"
-#endif
-
-#include "PokittoFonts.h"
-#include "PokittoPalettes.h"
-#include "PokittoDisplay.h"
-#include "PokittoButtons.h"
-#include "PokittoBattery.h"
-#include "PokittoBacklight.h"
-#include "PokittoSound.h"
-#include "PokittoFakeavr.h"
-
-#define PALETTE_SIZE 16
-#define PI 3.141592741f
-
-// For GB compatibility
-#if PROJ_GAMEBUINO > 0
-extern void setup();
-extern void loop();
-#endif // PROJ_GAMEBUINO
-
-extern uint32_t* ptimer; // re-directed tick counter
-
-namespace Pokitto {
-
-/** Core class.
- * The Core class is a class consisting of static data and methods.
- * It handles the lowlevel hardware functions of the Pokitto.
- * It is declared as static to prevent several instances running at same time.
- * Example:
- * @code
- * // A simple "Hello World!" program with Pokitto
- *
- * #include "Pokitto.h"
- *
- * Pokitto::Core myApp;
- *
- * int main() {
- * myApp.begin(); // This starts up the console (the display, buttons etc.)
- * while(myApp.isRunning()) {
- * if(myApp.Update()) {
- * myApp.display.print("Hello World!");
- * }
- * }
- * }
- * @endcode
- */
-
-class Core
-{
-public:
- /** Create a Core runtime instance
- */
- Core();
-
- /** Backlight component of the Core runtime */
- static Backlight backlight;
- /** Buttons component of the Core runtime */
- static Buttons buttons;
- /** Battery component of the Core runtime */
- static Battery battery;
- /** Sound component of the Core runtime */
- static Sound sound;
- /** Display component of the Core runtime */
- static Display display;
-
- // EXCECUTION CONTROL
-public:
- /** Initialize runtime (use this one) */
- static void begin();
- /** Initialize runtime (deprecated, avoid) */
- static void init();
- /** Initialize runtime with options (deprecated, avoid) */
- static void init(uint8_t);
- /** Return run state (1 = running, 0 = shutting down) */
- static bool isRunning();
- /** Stop running */
- static void quit();
-private:
- /** run_state is true as long as program is running */
- static bool run_state;
-
-public:
- // INITIALIZATION
- /** Initialize display */
- static void initDisplay();
- /** Initialize random generator */
- static void initRandom();
- /** Initialize GPIO */
- static void initGPIO();
- /** Initialize LCD */
- static void initLCD();
- /** Initialize Audio */
- static void initAudio();
-
-
- // DISPLAY
-public:
- /** Initialize backlight */
- static void initBacklight();
-
-private:
- /** Backlight PWM pointer */
- #ifndef POK_SIM
- static pwmout_t backlightpwm;
- #endif
-
- // TIMEKEEPING
-public:
- /** Initialize runtime clock */
- static void initClock();
- /** Get value of time elapsed during program in milliseconds */
- static uint32_t getTime();
- /** Wait for n milliseconds */
- static void wait(uint16_t);
-private:
- /** Time of next refresh */
- static uint32_t refreshtime;
-
- // DIRECT TO SCREEN
-public:
- /** Display Pokitto logo */
- static void showLogo();
- static void showWarning();
- static void setVolLimit();
-
-// BUTTON INPUT HANDLING
-private:
- static uint8_t heldStates[];
-public:
- static void initButtons();
- static void pollButtons();
- static uint8_t leftBtn();
- static uint8_t rightBtn();
- static uint8_t upBtn();
- static uint8_t downBtn();
- static uint8_t aBtn();
- static uint8_t bBtn();
- static uint8_t cBtn();
- static uint8_t leftHeld();
- static uint8_t rightHeld();
- static uint8_t upHeld();
- static uint8_t downHeld();
- static uint8_t aHeld();
- static uint8_t bHeld();
- static uint8_t cHeld();
-
- static uint8_t leftReleased();
- static uint8_t rightReleased();
- static uint8_t upReleased();
- static uint8_t downReleased();
- static uint8_t aReleased();
- static uint8_t bReleased();
- static uint8_t cReleased();
-
- // AUDIO RELATED
- static uint8_t ampIsOn();
- static void ampEnable(uint8_t);
- static uint8_t soundbyte;
-
- // GB RELATED
-public:
- static void readSettings();
- static void titleScreen(const char* name, const uint8_t *logo);
- static void titleScreen(const char* name);
- static void titleScreen(const uint8_t* logo);
- static void titleScreen();
- static bool update(bool useDirectMode=false);
- static uint32_t frameCount;
- static int8_t menu(const char* const* items, uint8_t length);
- static char* filemenu(char*);
- static char* filemenu();
- static void keyboard(char* text, uint8_t length);
- static void popup(const char* text, uint8_t duration);
- static void setFrameRate(uint8_t fps);
- static void pickRandomSeed();
-
- static uint8_t getCpuLoad();
- static uint16_t getFreeRam();
-
- static bool collidePointRect(int16_t x1, int16_t y1 ,int16_t x2 ,int16_t y2, int16_t w, int16_t h);
- static bool collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1 ,int16_t x2 ,int16_t y2, int16_t w2, int16_t h2);
- static bool collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2);
-
-private:
- static uint8_t timePerFrame;
- static uint32_t nextFrameMillis;
- static void updatePopup();
- static const char* popupText;
- static uint8_t popupTimeLeft;
- static void displayBattery();
- static uint16_t frameDurationMicros;
- static uint32_t frameStartMicros, frameEndMicros;
- static uint8_t startMenuTimer;
- static int updateLoader(uint32_t,uint32_t);
-public:
- static uint8_t volbar_visible;
- static void drawvolbar(int,int,int, bool);
- static void askLoader();
- static void jumpToLoader();
-};
-
-// this is the instance used by the system
-extern Core core;
-
-
-}
-
-#endif // POKITTOCORE_H
-
-
-
--- a/POKITTO_CORE/PokittoDisplay.cpp Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2152 +0,0 @@
-/**************************************************************************/
-/*!
- @file PokittoDisplay.cpp
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-
-/* THE SEGMENT BELOW PERTAINS TO CIRCLE DRAWING FUNCTIONS ONLY
-*
-This is the core graphics library for all our displays, providing a common
-set of graphics primitives (points, lines, circles, etc.). It needs to be
-paired with a hardware-specific library for each display device we carry
-(to handle the lower-level functions).
-Adafruit invests time and resources providing this open source code, please
-support Adafruit & open-source hardware by purchasing products from Adafruit!
-Copyright (c) 2013 Adafruit Industries. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-- Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "PokittoDisplay.h"
-#include "Pokitto_settings.h"
-#include "GBcompatibility.h"
-#include "PokittoCore.h"
-#include "PokittoSound.h"
-#include <stdio.h>
-#include <string.h>
-
-#ifndef POK_SIM
-#include "HWLCD.h"
-#else
-#include "SimLCD.h"
-#endif
-
-Pokitto::Core core;
-Pokitto::Sound sound;
-
-using namespace Pokitto;
-
-
-
-uint8_t* Display::m_scrbuf;
-uint8_t* Display::m_tileset;
-uint8_t* Display::m_tilebuf;
-uint8_t* Display::m_tilecolorbuf;
-uint8_t Display::m_mode, Display::m_colordepth;
-uint8_t Display::fontSize=1;
-int16_t Display::cursorX,Display::cursorY;
-uint16_t Display::m_w,Display::m_h;
-uint8_t Display::fontWidth, Display::fontHeight;
-bool Display::textWrap=true;
-
-uint8_t Display::persistence = 0;
-uint16_t Display::color = 1;
-uint16_t Display::bgcolor = 0;
-uint16_t Display::invisiblecolor = 17;
-uint16_t Display::directcolor=0xFFFF;
-uint16_t Display::directbgcolor=0x0;
-
-uint16_t* Display::paletteptr;
-uint16_t Display::palette[PALETTE_SIZE];
-const unsigned char* Display::font;
-int8_t Display::adjustCharStep = 1;
-int8_t Display::adjustLineStep = 1;
-bool Display::fixedWidthFont = false;
-
-/** drawing canvas **/
-//uint8_t* Display::canvas; // points to the active buffer. if null, draw direct to screen
-
-/** screenbuffer **/
-uint8_t Display::bpp = POK_COLORDEPTH;
-#ifndef POK_TILEDMODE
-#if (POK_SCREENMODE == MODE_HI_MONOCHROME)
- uint8_t Display::width = POK_LCD_W;
- uint8_t Display::height = POK_LCD_H;
- uint8_t Display::screenbuffer[((POK_LCD_H+1)*POK_LCD_W)*POK_COLORDEPTH/8]; // maximum resolution
-#elif (POK_SCREENMODE == MODE_HI_4COLOR)
- uint8_t Display::width = POK_LCD_W;
- uint8_t Display::height = POK_LCD_H;
- uint8_t __attribute__((section (".bss"))) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
-#elif (POK_SCREENMODE == MODE_FAST_16COLOR)
- uint8_t Display::width = POK_LCD_W/2;
- uint8_t Display::height = POK_LCD_H/2;
- uint8_t Display::screenbuffer[(((POK_LCD_H/2)+1)*POK_LCD_W/2)*POK_COLORDEPTH/8]; // half resolution
-#elif (POK_SCREENMODE == MODE_HI_16COLOR)
- uint8_t Display::width = POK_LCD_W;
- uint8_t Display::height = POK_LCD_H;
- uint8_t Display::screenbuffer[POK_LCD_H*POK_LCD_W/2]; // 4 bits per pixel
-#elif (POK_SCREENMODE == MODE_LAMENES)
- uint8_t Display::width = 128;
- uint8_t Display::height = 120;
- uint8_t Display::screenbuffer[((121)*128)*POK_COLORDEPTH/8]; // half resolution
-#elif (POK_SCREENMODE == MODE_GAMEBOY)
- uint8_t Display::width = 160;
- uint8_t Display::height = 144;
- uint8_t Display::screenbuffer[160*144/4];
-#else
- uint8_t Display::width = 84;
- uint8_t Display::height = 48;
- uint8_t Display::screenbuffer[128*64]; // not needed because Gamebuino and Arduboy have their own buffer
-#endif
-#else //Tiledmode
-#if (POK_SCREENMODE == MODE_TILED_1BIT)
- uint8_t Display::width = POK_LCD_W;
- uint8_t Display::height = POK_LCD_H;
- uint8_t Display::screenbuffer[0];
-#else
- uint8_t Display::width = POK_LCD_W;
- uint8_t Display::height = POK_LCD_H;
- uint8_t Display::screenbuffer[0];
-#endif
-#endif //tiledmode
-
-// RLE decoding
-#define RLE_ESC_EOL 0
-#define RLE_ESC_EOB 1
-#define RLE_ESC_OFFSET 2
-
-Display::Display() {
- m_scrbuf = screenbuffer;
- setDefaultPalette();
- m_mode = 1; // direct printing on by default
- m_w = POK_LCD_W;
- m_h = POK_LCD_H;
- setFont(DEFAULT_FONT);
- invisiblecolor=17;
- bgcolor=0;
- if (POK_COLORDEPTH) m_colordepth = POK_COLORDEPTH;
- else m_colordepth = 4;
- #if POK_GAMEBUINO_SUPPORT
- setColorDepth(1);
- #endif // POK_GAMEBUINO_SUPPORT
-}
-
-uint16_t Display::getWidth() {
- return width;
-}
-
-uint8_t Display::getNumberOfColors() {
- return 1<<POK_COLORDEPTH;
-}
-
-uint16_t Display::getHeight() {
- return height;
-}
-
-uint8_t Display::getColorDepth() {
- return m_colordepth;
-}
-
-void Display::setColorDepth(uint8_t v) {
- if (v > POK_COLORDEPTH) v=POK_COLORDEPTH;
- m_colordepth = v;
-}
-
-void Display::clearLCD() {
- lcdFillSurface(0);
- setCursor(0,0); // old basic computer style
-}
-
-void Display::fillLCD(uint16_t c) {
- lcdFillSurface(c);
-}
-
-void Display::directPixel(int16_t x, int16_t y, uint16_t color) {
- lcdPixel(x,y,color);
-}
-
-void Display::directTile(int16_t x, int16_t y, int16_t x2, int16_t y2, uint16_t* gfx) {
- lcdTile(x,y,x2,y2,gfx);
-}
-
-void Display::directRectangle(int16_t x, int16_t y,int16_t x2, int16_t y2, uint16_t color) {
- lcdRectangle(x,y,x2,y2,color);
-}
-
-void Display::begin() {
- lcdInit();
-}
-
-void Display::setCursor(int16_t x,int16_t y) {
- cursorX = x;
- cursorY = y;
-}
-
-void Display::update() {
-
-#if POK_SCREENMODE == MODE_GAMEBOY
- lcdRefreshModeGBC(m_scrbuf, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_HI_4COLOR
- lcdRefreshMode1(m_scrbuf, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_HI_16COLOR
- lcdRefreshMode3(m_scrbuf, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_FAST_16COLOR
- lcdRefreshMode2(m_scrbuf, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR
- lcdRefreshGB(m_scrbuf, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_ARDUBOY_16COLOR
- lcdRefreshAB(m_scrbuf, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_TILED_1BIT
- lcdRefreshT1(m_tilebuf, m_tilecolorbuf, m_tileset, paletteptr);
-#endif
-
-if (!persistence) clear();
-
-/** draw volume bar if visible **/
-#if POK_SHOW_VOLUME > 0
-if (core.volbar_visible) {
- core.drawvolbar(4,20,sound.getVolume(),true);
- core.volbar_visible--;
-}
-#endif // POK_SHOW_VOLUME
-
-}
-
-void Display::directBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t depth, uint8_t scale) {
- uint8_t w = *bitmap;
- uint8_t h = *(bitmap + 1);
- bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
- int16_t i, j;
- int8_t byteNum, bitNum, byteWidth = (w + 7) >> 3;
-
- if (depth == 1) {
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- if (*(bitmap + j * byteWidth + byteNum) & (0x80 >> bitNum)) { //0x80 = B10000000
- if (scale==1) directPixel(x + i, y + j,directcolor);
- else {
- directPixel(x + i + i, y + j + j,directcolor);
- directPixel(x + 1 + i + i, y + j + j,directcolor);
- directPixel(x + i + i, y + j + j + 1,directcolor);
- directPixel(x + i + i + 1 , y + j + j + 1,directcolor);
- }
- }
- }
- }
- } else if (depth == 4) {
- for (j = 0; j < h; j+=1) {
- for (i = 0; i < w; i+=2) {
- uint16_t col = paletteptr[*bitmap>>4]; //higher nibble
- if (scale==2) {
- directPixel(x + (i<<1), y + (j<<1),col);
- directPixel(x + (i<<1) + 1, y + (j<<1),col);
- directPixel(x + (i<<1) + 1, y + (j<<1) + 1,col);
- directPixel(x + (i<<1), y + (j<<1) + 1,col);
- } else directPixel(x + i, y + j,col);
- col = paletteptr[*bitmap&0xF]; // lower nibble
- if (scale==2) {
- directPixel(x + (i<<1) + 2, y + (j<<1),col);
- directPixel(x + (i<<1) + 1 + 2, y + (j<<1),col);
- directPixel(x + (i<<1) + 1 + 2, y + (j<<1) + 1,col);
- directPixel(x + (i<<1) + 2 , y + (j<<1) + 1,col);
- } else directPixel(x + i + 1, y + j,col);
- bitmap++;
- }
- }
- }
-
-}
-
-int Display::directChar(int16_t x, int16_t y, uint16_t index){
- const uint8_t* bitmap = font;
- uint8_t w = *bitmap;
- uint8_t h = *(bitmap + 1);
- uint8_t hbytes=0, xtra=1;
- if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit
- hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes
- //bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
- bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !)
- //int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- int8_t i, j, numBytes;
- numBytes = *bitmap++; //first byte of char is the width in bytes
- // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
- uint16_t bitcolumn; //16 bits for 2x8 bit high characters
-
- for (i = 0; i < numBytes; i++) {
- bitcolumn = *bitmap++;
- if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
- for (j = 0; j < h; j++) {
- if (bitcolumn&0x1) {
- if (fontSize==2) {
- directPixel(x + (i<<1) , y + (j<<1),directcolor);
- directPixel(x + (i<<1)+1, y + (j<<1),directcolor);
- directPixel(x + (i<<1) , y + (j<<1)+1,directcolor);
- directPixel(x + (i<<1)+1, y + (j<<1)+1,directcolor);
- } else directPixel(x + i, y + j,directcolor);
- } else if (directbgcolor != invisiblecolor) {
- if (fontSize==2) {
- directPixel(x + (i<<1) , y + (j<<1),directbgcolor);
- directPixel(x + (i<<1)+1, y + (j<<1),directbgcolor);
- directPixel(x + (i<<1) , y + (j<<1)+1,directbgcolor);
- directPixel(x + (i<<1)+1, y + (j<<1)+1,directbgcolor);
- } else directPixel(x + i, y + j,directbgcolor);
- }
- bitcolumn>>=1;
- }
- }
- return (numBytes+adjustCharStep)*fontSize; // for character stepping
-}
-
-int Display::bufferChar(int16_t x, int16_t y, uint16_t index){
- const uint8_t* bitmap = font;
- uint8_t w = *bitmap;
- uint8_t h = *(bitmap + 1);
- uint8_t hbytes=0, xtra=1;
- if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit
- hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes
- //bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
- bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !)
- //int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- int8_t i, j, numBytes;
- numBytes = *bitmap++; //first byte of char is the width in bytes
- // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
- uint16_t bitcolumn; //16 bits for 2x8 bit high characters
-
- for (i = 0; i < numBytes; i++) {
- bitcolumn = *bitmap++;
- if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
- for (j = 0; j <= h; j++) { // was j<=h
- #if PROJ_ARDUBOY > 0
- if (bitcolumn&0x1) {
- drawPixel(x + i, y + 7 - j,color);
- } else drawPixel(x + i, y + 7 - j,bgcolor);
- bitcolumn>>=1;
- #else
- if (bitcolumn&0x1) {
- drawPixel(x + i, y + j,color);
- } else drawPixel(x + i, y + j,bgcolor);
- bitcolumn>>=1;
- #endif // PROJ_ARDUBOY
-
- }
- }
-
- return numBytes+adjustCharStep; // for character stepping
-}
-
-void Display::clear() {
-
- uint8_t c=0;
- c = bgcolor & (PALETTE_SIZE-1) ; //don't let palette go out of bounds
- if (bpp==1 && bgcolor) c=0xFF; // bgcolor !=0, set all pixels
- else if (bpp==2) {
- c = bgcolor & 0x3;
- c = c | (c << 2);
- c = c | (c << 4);
- } else {
- c = (c & 0x0F) | (c << 4);
- }
- uint16_t j = sizeof(screenbuffer);
- memset((void*)m_scrbuf,c,j);
-
- setCursor(0,0);
-
-}
-
-void Display::scroll(int16_t pixelrows) {
- uint16_t index = 0, index2,oc;
- if (pixelrows==0) return;
- if (pixelrows >= height) pixelrows=height-1;
- if (bpp == 4) index2 = pixelrows*width/2;
- else if (bpp == 2) index2 = pixelrows*width/4;
- else return;
- oc = color;
- color = bgcolor;
- if (pixelrows>0) {
- for (uint16_t y=0;y<height-pixelrows;y++) {
- for (uint16_t x=0;x<(width/8)*bpp;x++) screenbuffer[index++]=screenbuffer[index2++];
- }
- fillRect(0,cursorY,width,height);
- } else {
- for (uint16_t y=pixelrows;y<height;y++) {
- for (uint16_t x=0;x<(width*bpp)/8;x++) screenbuffer[index2++]=screenbuffer[index2];
- }
- fillRect(0,0,width,pixelrows);
- }
- color=oc;
-}
-
-void Display::fillScreen(uint16_t c) {
- c = c & (PALETTE_SIZE-1) ; //don't let palette go out of bounds
- if (bpp==1 && c) c=0xFF; // set all pixels
- else if (bpp==2) {
- c = bgcolor & 0x3;
- c = c | (c << 2);
- c = c | (c << 4);
- } else {
- c = (c & 0x0F) | (c << 4);
- }
- memset((void*)m_scrbuf,c,sizeof(screenbuffer));
-}
-
-void Display::setDefaultPalette() {
- #if PICOPALETTE
- loadRGBPalette(palettePico);
- #else
- loadRGBPalette(POK_DEFAULT_PALETTE);
- #endif //PICOPALETTE
-}
-
-void Display::setColor(uint8_t c) {
- color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
-}
-
-void Display::setColor(uint8_t c,uint8_t bgc){
- color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
- bgcolor = bgc & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
-}
-
-void Display::setInvisibleColor(uint16_t c){
- invisiblecolor = c; // invisible color can have values beyond 255 for identification purposes
-}
-
-uint8_t Display::getColor() {
- return color;
-}
-
-uint8_t Display::getBgColor() {
- return bgcolor;
-}
-
-uint16_t Display::getInvisibleColor() {
- return invisiblecolor;
-}
-
-void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
- if (col==invisiblecolor) return; // do not draw transparent pixels
- if ((uint16_t)x >= width || (uint16_t)y >= height) return;
- col &= (PALETTE_SIZE-1);
- #if POK_GAMEBUINO_SUPPORT >0
-
- uint8_t c = col;
- uint8_t ct = col;
-
- uint16_t bitptr=0;
- for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
- c = ct & 1; // take the lowest bit of the color index number
- if(c == 0){ //white - or actually "Clear bit"
- m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
- } else { //black - or actually "Set bit"
- m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
- }
- ct >>=1; // shift to get next bit
- bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
- } // POK_COLOURDEPTH
-
- #else
- #if POK_COLORDEPTH == 1
- if (col) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
- m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
- #elif POK_COLORDEPTH == 2
- if (col) {
- col &= 3;
- }
- uint16_t i = y*(width>>2) + (x>>2);
- uint8_t pixel = m_scrbuf[i];
- uint8_t column = x&0x03;
- if (column==3) pixel = (pixel&0xFC)|(col); // bits 0-1
- else if (column==2) pixel = (pixel&0xF3)|(col<<2); // bits 2-3
- else if (column==1) pixel = (pixel&0xCF)|(col<<4); // bits 4-5
- else pixel = (pixel&0x3F)|(col<<6); // bits 6-7
- m_scrbuf[i] = pixel;
- #elif POK_COLORDEPTH == 3
- #elif POK_COLORDEPTH == 4
- uint16_t i = y*(width>>1) + (x>>1);
- uint8_t pixel = m_scrbuf[i];
- if (x&1) pixel = (pixel&0xF0)|(col);
- else pixel = (pixel&0x0F) | (col<<4);
- m_scrbuf[i] = pixel;
- #endif // POK_COLORDEPTH
- #endif // POK_GAMEBUINO_SUPPORT
-}
-
-void Display::drawPixel(int16_t x,int16_t y) {
- if ((uint16_t)x >= width || (uint16_t)y >= height) return;
-
- #if POK_GAMEBUINO_SUPPORT > 0
-
- uint8_t c = color;
- uint8_t ct = color;
- if(ct == INVERT){
- ct = !getPixel(x, y); //jonne - was c = !getP...
- }
-
- uint16_t bitptr=0;
- for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
- c = ct & 1; // take the lowest bit of the color index number
- if(c == 0){ //white - or actually "Clear bit"
- #if DISPLAY_ROT == NOROT
- m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
- #elif DISPLAY_ROT == ROTCCW
- m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV(x % 8);
- #elif DISPLAY_ROT == ROT180
- m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV((LCDHEIGHT - y - 1) % 8);
- #elif DISPLAY_ROT == ROTCW
- m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitbtr] &= ~_BV((LCDWIDTH - x - 1) % 8);
- #endif
- //return; //jonne
- } else { //black - or actually "Set bit"
- #if DISPLAY_ROT == NOROT
- m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
- #elif DISPLAY_ROT == ROTCCW
- m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] |= _BV(x % 8);
- #elif DISPLAY_ROT == ROT180
- m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDHEIGHT - y - 1) % 8);
- #elif DISPLAY_ROT == ROTCW
- m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDWIDTH - x -1) % 8);
- #endif
- //return; //jonne
- }
- ct >>=1; // shift to get next bit
- bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
- } // POK_COLOURDEPTH
-
- #else
-
- /** NOT Gamebuino */
- #if POK_COLORDEPTH == 1
- if (color) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
- m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
- #elif POK_COLORDEPTH == 2
- uint16_t i = y*(width>>2) + (x>>2);
- uint8_t pixel = m_scrbuf[i];
- uint8_t column = x&0x03;
- if (column==3) pixel = (pixel&0xFC)|(color); // bits 0-1
- else if (column==2) pixel = (pixel&0xF3)|(color<<2); // bits 2-3
- else if (column==1) pixel = (pixel&0xCF)|(color<<4); // bits 4-5
- else pixel = (pixel&0x3F)|(color<<6); // bits 6-7
- m_scrbuf[i] = pixel;
- #elif POK_COLORDEPTH == 3
- #elif POK_COLORDEPTH == 4
- uint16_t i = y*(width>>1) + (x>>1);
- uint8_t pixel = m_scrbuf[i];
- if (x&1) pixel = (pixel&0xF0)|(color);
- else pixel = (pixel&0x0F) | (color<<4);
- m_scrbuf[i] = pixel;
- #endif // POK_COLORDEPTH
- #endif // POK_GAMEBUINO_SUPPORT
-}
-
-uint8_t Display::getPixel(int16_t x,int16_t y) {
- if ((uint16_t)x >= width || (uint16_t)y >= height) return 0;
- #if POK_GAMEBUINO_SUPPORT
- uint8_t color=0; //jonne
- for (uint8_t cbit=0; cbit<POK_COLORDEPTH;cbit++) {
- color |= (m_scrbuf[x + (y / 8) * LCDWIDTH+POK_BITFRAME*cbit] >> (y % 8)) & 0x1 ; //jonne - added +504*cbit
- }
- return color;
- #else
- /** not gamebuino */
- #if POK_COLORDEPTH == 1
- return (m_scrbuf[(y >> 3) * width + x] & (0x80 >> (y & 7))) ? 1:0;
- #elif POK_COLORDEPTH == 2
- uint16_t i = y*(width>>2) + (x>>2);
- uint8_t pixel = m_scrbuf[i];
- uint8_t column = x&0x03;
- if (column==0) return pixel & 0x03; // bits 0-1
- else if (column==1) return (pixel & 0x0C)>>2; // bits 2-3
- else if (column==2) return (pixel & 0x30)>>4; // bits 4-5
- else return pixel>>6;; // bits 6-7
- #elif POK_COLORDEPTH == 3
- #elif POK_COLORDEPTH == 4
- uint16_t i = y*(width>>1) + (x>>1);
- uint8_t pixel = m_scrbuf[i];
- if (x&1) return pixel & 0x0F;
- else return pixel>>4;
- #endif // POK_COLORDEPTH
- #endif // POK_GAMEBUINO_SUPPORT
-}
-
-void Display::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
- if ((uint16_t)x0 >= width || (uint16_t)y0 >= height || (uint16_t)x1 >= width || (uint16_t)y1 >= height ) {
- if (clipLine (&x0,&y0,&x1,&y1)==0) return; // line out of bounds
- }
- if (x0 == x1)
- drawColumn(x0,y0,y1);
- else if (y0 == y1)
- drawRow(x0,x1,y0);
- else {
- int e;
- signed int dx,dy,j, temp;
- signed char s1,s2, xchange;
- signed int x,y;
-
- x = x0;
- y = y0;
-
- //take absolute value
- if (x1 < x0) {
- dx = x0 - x1;
- s1 = -1;
- }
- else if (x1 == x0) {
- dx = 0;
- s1 = 0;
- }
- else {
- dx = x1 - x0;
- s1 = 1;
- }
-
- if (y1 < y0) {
- dy = y0 - y1;
- s2 = -1;
- }
- else if (y1 == y0) {
- dy = 0;
- s2 = 0;
- }
- else {
- dy = y1 - y0;
- s2 = 1;
- }
-
- xchange = 0;
-
- if (dy>dx) {
- temp = dx;
- dx = dy;
- dy = temp;
- xchange = 1;
- }
-
- e = ((int)dy<<1) - dx;
-
- for (j=0; j<=dx; j++) {
- drawPixel(x,y);
-
- if (e>=0) {
- if (xchange==1) x = x + s1;
- else y = y + s2;
- e = e - ((int)dx<<1);
- }
- if (xchange==1)
- y = y + s2;
- else
- x = x + s1;
- e = e + ((int)dy<<1);
- }
- }
-}
-
-uint8_t Display::clipLine(int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1){
- // Check X bounds
- if (*x1<*x0) {
- //std::swap (*x1,*x0); // swap so that we dont have to check x1 also
- swapWT(int16_t*,x1,x0);
- //std::swap (*y1,*y0); // y needs to be swaaped also
- swapWT(int16_t*,y1,y0);
- }
-
- if (*x0>=width) return 0; // whole line is out of bounds
-
- // Clip against X0 = 0
- if (*x0 < 0) {
- if ( *x1 < 0) return 0; // nothing visible
- int16_t dx = (*x1 - *x0);
- int16_t dy = ((*y1 - *y0) << 8); // 8.8 fixed point calculation trick
- int16_t m = dy/dx;
- *y0 = *y0 + ((m*-*x0)>>8); // get y0 at boundary
- *x0 = 0;
- }
-
- // Clip against x1 = 83
- if (*x1 >= width) {
- int16_t dx = (*x1 - *x0);
- int16_t dy = ((*y1 - *y0) << 8); // 8.8 fixed point calculation trick
- int16_t m = dy/dx;
- //*y1 = *y1 + ((m*(*x1-XMAX))>>8); // get y0 at boundary
- *y1 = *y1 + ((m*(width-1-*x1))>>8); // get y0 at boundary
- *x1 = width-1;
- }
-
- // Check Y bounds
- if (*y1<*y0) {
- //std::swap (*x1,*x0); // swap so that we dont have to check x1 also
- swapWT(int16_t*,x1,x0);
- //std::swap (*y1,*y0); // y needs to be swaaped also
- swapWT(int16_t*,y1,y0);
- }
-
- if (*y0>=height) return 0; // whole line is out of bounds
-
- if (*y0 < 0) {
- if ( *y1 < 0) return 0; // nothing visible
- int16_t dx = (*x1 - *x0) << 8;
- int16_t dy = (*y1 - *y0); // 8.8 fixed point calculation trick
- int16_t m = dx/dy;
- *x0 = *x0 + ((m*-*y0)>>8); // get x0 at boundary
- *y0 = 0;
- }
-
- // Clip against y1 = 47
- if (*y1 >= height) {
- int16_t dx = (*x1 - *x0) << 8;
- int16_t dy = (*y1 - *y0); // 8.8 fixed point calculation trick
- int16_t m = dx/dy;
- *x1 = *x1 + ((m*(height-1-*y1))>>8); // get y0 at boundary
- //*x1 = *x1 + ((m*(*y1-YMAX))>>8); // get y0 at boundary
- *y1 = height-1;
- }
- return 1; // clipped succesfully
-}
-
-void Display::map1BitColumn(int16_t x, int16_t sy, int16_t ey, const uint8_t* bitmap, uint16_t column){
- if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds
- if ((uint16_t)x>=width) return; //completely out of bounds
- if (sy>ey) {
- int y=sy;
- sy=ey;
- ey=y; // swap around so that x0 is less than x1
- }
- uint16_t bmw,bmh;
- float texelstep, texelindex;
- bmw = *(bitmap);
- bmh = *(bitmap+1);
- if (column>bmw-1) column=bmw-1;
- bitmap += 2;
- bitmap += column;
- texelstep = (float)bmh/((float)ey-(float)sy);
- texelindex = 0;
- for (int y=sy; y <= ey; y++, texelindex += texelstep) {
- uint8_t texel;
- uint8_t currbyte, bit;
- currbyte = texelindex / 8;
- bit = 7-((uint16_t) texelindex & 0x7);
- texel=*(bitmap+currbyte*bmw);
- if (texel & (1<<bit)) drawPixel(x,y);
- else if (bgcolor != invisiblecolor) drawPixel(x,y,bgcolor);
- }
-};
-
-void Display::drawColumn(int16_t x, int16_t sy, int16_t ey){
- if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds
- if ((uint16_t)x>=width) return; //completely out of bounds
- if (sy>ey) {
- int y=sy;
- sy=ey;
- ey=y; // swap around so that x0 is less than x1
- }
- for (int y=sy; y <= ey; y++) {
- drawPixel(x,y);
- }
-}
-
-void Display::drawRow(int16_t x0, int16_t x1, int16_t y){
- if ((uint16_t)x0>=width && (uint16_t)x1>=width) return; //completely out of bounds
- if ((uint16_t)y>=height) return; //completely out of bounds
-
- if (x0>x1) {
- int x=x0;
- x0=x1;
- x1=x; // swap around so that x0 is less than x1
- }
- for (int x=x0; x <= x1; x++) {
- drawPixel(x,y);
- }
-}
-
-void Display::drawFastVLine(int16_t x, int16_t y, int16_t h){
- if (h<0) {y += h; h = -h;}
- drawColumn(x,y,y+h);
-}
-
-void Display::drawFastHLine(int16_t x, int16_t y, int16_t w){
- if (w<0) {x += w; w = -w;}
- drawRow(x,x+w-1,y);
-}
-
-void Display::drawRectangle(int16_t x0, int16_t y0, int16_t w, int16_t h) {
- drawColumn(x0,y0,y0+h);
- drawColumn(x0+w,y0,y0+h);
- drawRow(x0,x0+w,y0);
- drawRow(x0,x0+w,y0+h);
-}
-
-void Display::fillRectangle(int16_t x0,int16_t y0, int16_t w, int16_t h){
- int16_t x,y,x1,y1;
- x1=x0+w;y1=y0+h;
- if ((x0<0 && x1<0) || (x0>=width && x1 >=width)) return; //completely out of bounds
- if ((y0<0 && y1<0) || (y0>=height && y1 >=height)) return; //completely out of bounds
- if (x0>x1) {x=x1;x1=x0;}
- else x=x0;
- if (y0>y1) {y=y1;y1=y0;}
- else y=y0;
- if (x<0) x=0;
- if (y<0) y=0;
- for (;x<x1;x++) drawColumn(x,y,y1);
-}
-
-void Display::fillRect(int16_t x, int16_t y, int16_t w, int16_t h) {
- fillRectangle(x,y,w,h);
-}
-
-void Display::drawRect(int16_t x, int16_t y, int16_t w, int16_t h) {
- drawRectangle(x,y,w,h);
-}
-
-void Display::drawCircle(int16_t x0, int16_t y0, int16_t r) {
- int16_t f = 1 - r;
- int16_t ddF_x = 1;
- int16_t ddF_y = -2 * r;
- int16_t x = 0;
- int16_t y = r;
-
- drawPixel(x0, y0 + r);
- drawPixel(x0, y0 - r);
- drawPixel(x0 + r, y0);
- drawPixel(x0 - r, y0);
-
- while (x < y) {
- if (f >= 0) {
-
- y--;
- ddF_y += 2;
- f += ddF_y;
- }
- x++;
- ddF_x += 2;
- f += ddF_x;
-
- drawPixel(x0 + x, y0 + y);
- drawPixel(x0 - x, y0 + y);
- drawPixel(x0 + x, y0 - y);
- drawPixel(x0 - x, y0 - y);
- drawPixel(x0 + y, y0 + x);
- drawPixel(x0 - y, y0 + x);
- drawPixel(x0 + y, y0 - x);
- drawPixel(x0 - y, y0 - x);
-
- }
-}
-
-void Display::drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername) {
- int16_t f = 1 - r;
- int16_t ddF_x = 1;
- int16_t ddF_y = -2 * r;
- int16_t x = 0;
- int16_t y = r;
-
- while (x < y) {
- if (f >= 0) {
- y--;
- ddF_y += 2;
- f += ddF_y;
- }
- x++;
- ddF_x += 2;
- f += ddF_x;
- if (cornername & 0x4) {
- drawPixel(x0 + x, y0 + y);
- drawPixel(x0 + y, y0 + x);
- }
- if (cornername & 0x2) {
- drawPixel(x0 + x, y0 - y);
- drawPixel(x0 + y, y0 - x);
- }
- if (cornername & 0x8) {
- drawPixel(x0 - y, y0 + x);
- drawPixel(x0 - x, y0 + y);
- }
- if (cornername & 0x1) {
-
- drawPixel(x0 - y, y0 - x);
- drawPixel(x0 - x, y0 - y);
- }
- }
-}
-
-void Display::fillCircle(int16_t x0, int16_t y0, int16_t r) {
- drawFastVLine(x0, y0 - r, 2 * r );
- fillCircleHelper(x0, y0, r, 3, 0);
-}
-
-void Display::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername, int16_t delta) {
- int16_t f = 1 - r;
- int16_t ddF_x = 1;
- int16_t ddF_y = -2 * r;
- int16_t x = 0;
- int16_t y = r;
-
- while (x < y) {
- if (f >= 0) {
- y--;
- ddF_y += 2;
- f += ddF_y;
- }
- x++;
- ddF_x += 2;
- f += ddF_x;
-
- if (cornername & 0x1) {
- drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne
- drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne
- }
- if (cornername & 0x2) {
-
- drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne
- drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne
- }
- }
-}
-
-void Display::drawRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) {
- if (r<2) {drawRectangle(x,y,w,h);return;}
- // smarter version
- drawFastHLine(x + r, y, w - 2 * r); // Top
- drawFastHLine(x + r, y + h - 1, w - 2 * r); // Bottom
- drawFastVLine(x, y + r, h - 2 * r); // Left
- drawFastVLine(x + w - 1, y + r, h - 2 * r); // Right
- // draw four corners
- drawCircleHelper(x + r, y + r, r, 1);
- drawCircleHelper(x + w - r - 1, y + r, r, 2);
- drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4);
- drawCircleHelper(x + r, y + h - r - 1, r, 8);
-}
-
-void Display::fillRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) {
- if (r<2) {fillRectangle(x,y,w,h);return;}
- fillRectangle(x + r, y, w - 2 * r, h-1);
- // draw four corners
- fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1);
- fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1);
-}
-
-void Display::drawTriangle(int16_t x0, int16_t y0,
- int16_t x1, int16_t y1,
- int16_t x2, int16_t y2) {
- drawLine(x0, y0, x1, y1);
- drawLine(x1, y1, x2, y2);
- drawLine(x2, y2, x0, y0);
-}
-
-void Display::fillTriangle(int16_t x0, int16_t y0,
- int16_t x1, int16_t y1,
- int16_t x2, int16_t y2) {
- int16_t a, b, y, last;
-
- // Sort coordinates by Y order (y2 >= y1 >= y0)
- if (y0 > y1) {
- swapWT(int16_t,y0, y1);
- swapWT(int16_t,x0, x1);
- }
- if (y1 > y2) {
- swapWT(int16_t,y2, y1);
- swapWT(int16_t,x2, x1);
- }
- if (y0 > y1) {
- swapWT(int16_t,y0, y1);
- swapWT(int16_t,x0, x1);
- }
-
- if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
- a = b = x0;
- if (x1 < a) a = x1;
- else if (x1 > b) b = x1;
- if (x2 < a) a = x2;
- else if (x2 > b) b = x2;
- drawFastHLine(a, y0, b - a + 1);
- return;
- }
-
- int16_t
- dx01 = x1 - x0,
- dy01 = y1 - y0,
- dx02 = x2 - x0,
- dy02 = y2 - y0,
- dx12 = x2 - x1,
- dy12 = y2 - y1,
- sa = 0,
- sb = 0;
-
- // For upper part of triangle, find scanline crossings for segments
- // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
- // is included here (and second loop will be skipped, avoiding a /0
- // error there), otherwise scanline y1 is skipped here and handled
- // in the second loop...which also avoids a /0 error here if y0=y1
- // (flat-topped triangle).
- if (y1 == y2) last = y1; // Include y1 scanline
- else last = y1 - 1; // Skip it
-
- for (y = y0; y <= last; y++) {
- a = x0 + sa / dy01;
- b = x0 + sb / dy02;
- sa += dx01;
- sb += dx02;
- /* longhand:
- a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
- b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
- */
- if (a > b) swapWT(int16_t,a, b);
- drawFastHLine(a, y, b - a + 1);
- }
-
- // For lower part of triangle, find scanline crossings for segments
- // 0-2 and 1-2. This loop is skipped if y1=y2.
- sa = dx12 * (y - y1);
- sb = dx02 * (y - y0);
- for (; y <= y2; y++) {
- a = x1 + sa / dy12;
- b = x0 + sb / dy02;
- sa += dx12;
- sb += dx02;
-
- if (a > b) swapWT(int16_t,a, b);
- drawFastHLine(a, y, b - a + 1);
- }
-}
-
-void Display::setFont(const unsigned char * f) {
- font = f;
- fontWidth = *(font)+1;
- fontHeight = *(font + 1)+1;
-}
-
-void Display::drawMonoBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t index) {
- uint8_t w = *bitmap;
- uint8_t h = *(bitmap + 1);
- uint8_t xtra=0;
- if (w&0x7) xtra=1;
- bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
- #if POK_GAMEBUINO_SUPPORT > 0
- int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- if (source & (0x80 >> bitNum)) {
- drawPixel(x + i, y + j);
- }
- }
- }
- #else
- /** not gamebuino */
- int8_t scrx,scry;
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
- int8_t bitptr;
- for (scry = y; scry < y+h; scry+=1) {
- if ((x&1)==0) { /** EVEN pixel starting line**/
- for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) {
- uint8_t targetpixel = *scrptr;
- if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // upper nibble
- else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // upper nibble
- bitptr--;
- if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble
- else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble
- bitptr--;
- if (bitptr<0) { bitptr = 7; bitmap++; }
- *scrptr = targetpixel;
- scrptr++;
- }
- } else { /** ODD pixel starting line **/
- for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) {
- uint8_t targetpixel = *scrptr;
- // store higher nibble of source pixel in lower nibble of target
- if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble
- else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble
- *scrptr = targetpixel; // store
- bitptr--;scrptr++;targetpixel = *scrptr;
- // store lower nibble of source pixel in higher nibble of target
- if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // higher nibble
- else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // higher nibble
- *scrptr = targetpixel; // store
- bitptr--; // do not increment scrptr here !
- }
- }
- if (bitptr!=7) bitmap++; // force skip to next line
- // increment the y jump in the scrptr
- scrptr = scrptr + ((width - w)>>1);
- }
- #endif // POK_GAMEBUINO_SUPPORT
-}
-
-
-void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame)
-{
- int16_t w = *bitmap;
- int16_t h = *(bitmap + 1);
- uint8_t framew = *(bitmap+2);
- bitmap = bitmap + 3; //add an offset to the pointer to start after the width and height
- /** visibility check */
- if (y<-h || y>height) return; //invisible
- if (x<-framew || x>width) return; //invisible
- /** 1 bpp mode */
- if (m_colordepth<2) {
- int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- if (source & (0x80 >> bitNum)) {
- drawPixel(x + i, y + j);
- }
- }
- }
-
- return;
- }
- /** 2 bpp mode */
- if (m_colordepth<4) {
- int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
- for (i = 0; i < w; i++) {
- byteNum = i / 4;
- bitNum = (i % 4)<<1;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- uint8_t output = (source & (0xC0 >> bitNum));
- output >>= (6-bitNum);
- if (output != invisiblecolor) {
- setColor(output);
- drawPixel(x + i, y + j);
- }
- }
- }
-
- return;
- }
- /** 4bpp fast version */
- int16_t scrx,scry,xclip,xjump,scrxjump;
- xclip=xjump=scrxjump=0;
- bitmap += (framew*frame)>>1;
- /** y clipping */
- if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
- else if (y+h>height) { h -=(y-height);}
- /** x clipping */
- xjump = (w-framew)>>1;
- if (x<0) { xclip=(x&1)<<1; framew+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;}
- else if (x+framew>width) {
- xclip = (x&1)<<1;
- scrxjump = x&1;
- xjump=((x+framew-width)>>1)+scrxjump;
- framew = width-x;}
-
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
- /** ONLY 4-bit mode for time being **/
- for (scry = y; scry < y+h; scry+=1) {
- if (scry>=height) return;
- if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
- for (scrx = x; scrx < framew+x-xclip; scrx+=2) {
- uint8_t sourcepixel = *bitmap;
- if (xclip) {
- sourcepixel <<=4;
- sourcepixel |= ((*(bitmap+1))>>4);
- }
- uint8_t targetpixel = *scrptr;
- if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0);
- if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F);
- *scrptr = targetpixel;
- bitmap++;
- scrptr++;
- }
- if (xclip){
- if (framew&1) {
- /**last pixel is odd pixel due to clipping & odd width*/
- uint8_t sourcepixel = *bitmap;
- if ((sourcepixel&0x0F) != invisiblecolor) {
- sourcepixel <<=4;
- uint8_t targetpixel = *scrptr;// & 0x0F;
- targetpixel |= sourcepixel;
- *scrptr = targetpixel;
- }
- //scrptr++;
- }
- bitmap++;
- scrptr++;
- }
- bitmap += xjump; // needed if x<0 clipping occurs
- } else { /** ODD pixel starting line **/
- for (scrx = x; scrx < framew+x-xclip; scrx+=2) {
- uint8_t sourcepixel = *bitmap;
- uint8_t targetpixel = *scrptr;
- // store higher nibble of source pixel in lower nibble of target
- if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
- *scrptr = targetpixel;
- scrptr++;
- targetpixel = *scrptr;
- // store lower nibble of source pixel in higher nibble of target
- if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4);
- *scrptr = targetpixel;
- bitmap++;
- }
- bitmap+=xjump;
- }
- // increment the y jump in the scrptr
- scrptr = scrptr + ((width - framew)>>1)+scrxjump;
- }
-}
-
-
-void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap)
-{
- int16_t w = *bitmap;
- int16_t h = *(bitmap + 1);
- bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
- /** visibility check */
- if (y<-h || y>height) return; //invisible
- if (x<-w || x>width) return; //invisible
- /** 1 bpp mode */
- if (m_colordepth<2) {
- int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- if (source & (0x80 >> bitNum)) {
- drawPixel(x + i, y + j);
- }
- }
- }
-
- return;
- }
- /** 2 bpp mode */
- if (m_colordepth<4) {
- int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
- for (i = 0; i < w; i++) {
- byteNum = i / 4;
- bitNum = (i % 4)<<1;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- uint8_t output = (source & (0xC0 >> bitNum));
- output >>= (6-bitNum);
- if (output != invisiblecolor) {
- setColor(output);
- drawPixel(x + i, y + j);
- }
- }
- }
-
- return;
- }
- /** 4bpp fast version */
- int16_t scrx,scry,xclip,xjump,scrxjump;
- xclip=xjump=scrxjump=0;
- /** y clipping */
- if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
- else if (y+h>height) { h -=(y-height);}
- /** x clipping */
- if (x<0) { xclip=(x&1)<<1; w+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;}
- else if (x+w>width) {
- xclip = (x&1)<<1;
- scrxjump = x&1;
- xjump=((x+w-width)>>1)+scrxjump;
- w = width-x;}
-
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
- /** ONLY 4-bit mode for time being **/
- for (scry = y; scry < y+h; scry+=1) {
- if (scry>=height) return;
- if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
- for (scrx = x; scrx < w+x-xclip; scrx+=2) {
- uint8_t sourcepixel = *bitmap;
- if (xclip) {
- sourcepixel <<=4;
- sourcepixel |= ((*(bitmap+1))>>4);
- }
- uint8_t targetpixel = *scrptr;
- if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0);
- if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F);
- *scrptr = targetpixel;
- bitmap++;
- scrptr++;
- }
- if (xclip){
- if (w&1) {
- /**last pixel is odd pixel due to clipping & odd width*/
- uint8_t sourcepixel = *bitmap;
- if ((sourcepixel&0x0F) != invisiblecolor) {
- sourcepixel <<=4;
- uint8_t targetpixel = *scrptr;// & 0x0F;
- targetpixel |= sourcepixel;
- *scrptr = targetpixel;
- }
- //scrptr++;
- }
- bitmap++;
- scrptr++;
- }
- bitmap += xjump; // needed if x<0 clipping occurs
- } else { /** ODD pixel starting line **/
- for (scrx = x; scrx < w+x-xclip; scrx+=2) {
- uint8_t sourcepixel = *bitmap;
- uint8_t targetpixel = *scrptr;
- // store higher nibble of source pixel in lower nibble of target
- if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
- *scrptr = targetpixel;
- scrptr++;
- targetpixel = *scrptr;
- // store lower nibble of source pixel in higher nibble of target
- if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4);
- *scrptr = targetpixel;
- bitmap++;
- }
- bitmap+=xjump;
- }
- // increment the y jump in the scrptr
- scrptr = scrptr + ((width - w)>>1)+scrxjump;
- }
-}
-
-void Display::drawRleBitmap(int16_t x, int16_t y, const uint8_t* rlebitmap)
-{
- // ONLY can copy 4-bit bitmap to 4-bit screen mode for time being
- #if (POK_SCREENMODE != MODE_FAST_16COLOR)
- return;
- #endif
-
- int16_t w = *rlebitmap;
- int16_t h = *(rlebitmap + 1);
- rlebitmap = rlebitmap + 2; //add an offset to the pointer to start after the width and height
-
- // visibility check
- if (y<-h || y>height) return; //invisible
- if (x<-w || x>width) return; //invisible
-
- // Clipping is not supported
- if ((x < 0) || (x+w > width) || (y < 0) || (y+h > height)) return;
-
- // Currently only support RLE bitmaps in 16 color mode.
- if (m_colordepth != 4) //
- return;
-
- // Go through each line.
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
- bool is_endofbitmap = false;
- for (int16_t scry = y; scry < y+h && !is_endofbitmap;) {
-
- // Process one line. Go through each pixel run and escape command in RLE data.
- for (int16_t scrx = x;;) {
- uint8_t rle_count = *rlebitmap++;
-
- if (rle_count == 0) {
-
- /** Escape or absolute mode */
-
- uint8_t rle_escape_or_runsize = *rlebitmap++;
- if ( rle_escape_or_runsize == RLE_ESC_EOL) {
- // End of line.
- break;
- }
- else if ( rle_escape_or_runsize == RLE_ESC_EOB) {
- // End of bitmap.
- is_endofbitmap = true;
- break;
- }
- else if ( rle_escape_or_runsize == RLE_ESC_OFFSET) {
- // Move position in target.
- // TODO: not tested yet.
- uint8_t xoffset = *rlebitmap++;
- uint8_t yoffset = *rlebitmap++;
- scrptr += (xoffset>1);
- scrx += xoffset;
- scrptr += yoffset*width;
- scry += yoffset;
- }
- else {
-
- /** Absolute mode. Copy pixels from the source bitmap to the target screen. */
-
- int16_t runsize = rle_escape_or_runsize;
- uint8_t targetpixel = *scrptr; // initial value
- uint8_t sourcepixel = *rlebitmap; // initial value
- for( int16_t runx = 0; runx < runsize; ) {
- if (scrx&0x1) { // screen pixel is in the low nibble
- if (runx&0x1) { // bitmap pixel is in the low nibble
- if ((sourcepixel&0x0F) != invisiblecolor)
- targetpixel = (targetpixel&0xF0) | (sourcepixel&0x0F); // Copy low to low nibble.
- rlebitmap++;
- }
- else // bitmap pixel is in the high nibble
- if ((sourcepixel>>4) != invisiblecolor)
- targetpixel = (targetpixel&0xF0) | (sourcepixel>>4); // Copy high to low nibble.
-
- // Copy the byte to the target.
- *scrptr = targetpixel;
- scrptr++;
- }
- else { // screen pixel is in the high nibble
- targetpixel = *scrptr;
- sourcepixel = *rlebitmap;
- if (runx&0x1) { // bitmap pixel is sourcepixel = *rlebitmapin the low nibble
- if ((sourcepixel&0x0F) != invisiblecolor )
- targetpixel = (targetpixel&0x0F) | ((sourcepixel<<4)&0xF0); // Copy low to high nibble.
- rlebitmap++; // read the new source byte
- }
- else // bitmap pixel is in the high nibble
- if ((sourcepixel>>4) != invisiblecolor )
- targetpixel = (targetpixel&0x0F) | (sourcepixel&0xF0); // Copy high to high nibble.
- }
- runx++;
- scrx++;
- } // end for
-
- // If this is odd target index, copy the byte to the target.
- if (scrx&0x1) {
- *scrptr = targetpixel;
- scrptr++;
- }
-
- // In absolute mode the source size is always padded to the word boundary.
- if (runsize%4) {
- int16_t padpixcount = 4 - (runsize%4);
- rlebitmap += padpixcount>>1; // skip n padding bytes
- }
- }
- }
- else {
-
- /** Encoded mode. Duplicate one pixel pair to the all required pixels on the target screen */
-
- int16_t runsize = rle_count;
- uint8_t clonepixelpair = *rlebitmap++;
- uint8_t targetpixel = *scrptr; // initial value
- for( int16_t runx = 0; runx < runsize; ) {
- if (scrx&0x1) { // screen pixel is in the low nibble
- if (runx&0x1) { // bitmap pixel is in the low nibble
- if ((clonepixelpair&0x0F) != invisiblecolor)
- targetpixel = (targetpixel&0xF0) | (clonepixelpair&0x0F); // Copy low to low nibble.
- }
- else // bitmap pixel is in the high nibble
- if ((clonepixelpair>>4) != invisiblecolor)
- targetpixel = (targetpixel&0xF0) | (clonepixelpair>>4); // Copy high to low nibble.
-
- // Copy the byte to the target.
- *scrptr = targetpixel;
- scrptr++;
- }
- else { // screen pixel is in the high nibble
- targetpixel = *scrptr;
- if (runx&0x1) {// bitmap pixel is in the low nibble
- if ((clonepixelpair&0x0F) != invisiblecolor )
- targetpixel = (targetpixel&0x0F) | ((clonepixelpair<<4)&0xF0); // Copy low to high nibble.
- }
- else // bitmap pixel is in the high nibble
- if ((clonepixelpair>>4) != invisiblecolor )
- targetpixel = (targetpixel&0x0F) | (clonepixelpair&0xF0); // Copy high to high nibble.
- }
- runx++;
- scrx++;
-
- } // end for
-
- // If this is odd target index, copy the byte to the target.
- if (scrx&0x1) {
- *scrptr = targetpixel;
- scrptr++;
- }
- } // end if
- } // end while
-
- // Increment the target screen pointer and index.
- scrptr = scrptr + ((width - w)>>1);
- scry++;
- } // end for scry
-}
-
-void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
-{
- int16_t w = *bitmap;
- int16_t h = *(bitmap + 1);
- bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
- /** visibility check */
- if (y<-h || y>height) return; //invisible
- if (x<-w || x>width) return; //invisible
- /** 1 bpp mode */
- if (m_colordepth<2) {
- int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- if (source & (0x80 >> bitNum)) {
- drawPixel(x + w - i, y + j);
- }
- }
- }
-
- return;
- }
- /** 2 bpp mode */
- if (m_colordepth<4) {
- int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
- for (i = 0; i < w; i++) {
- byteNum = i / 4;
- bitNum = (i % 4)<<1;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- uint8_t output = (source & (0xC0 >> bitNum));
- output >>= (6-bitNum);
- if (output != invisiblecolor) {
- setColor(output);
- drawPixel(x + i, y + j);
- }
- }
- }
-
- return;
- }
- /** 4bpp fast version */
- int16_t scrx,scry,xclip,xjump,scrxjump;
- xclip=xjump=scrxjump=0;
- /** y clipping */
- if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
- else if (y+h>height) { h -=(y-height);}
- /** x clipping */
- bitmap += ((w>>1)-1); //inverted!
- if (x<0) {
- xclip=(x&1)<<1;
- w+=x;
- xjump = ((-x)>>1);
- //bitmap += xjump; // do not clip left edge of source, as bitmap is inverted !
- x=0;
- }
- else if (x+w>width) {
- xclip = (x&1)<<1;
- scrxjump = x&1;
- xjump=((x+w-width)>>1)+scrxjump;
- w = width-x;}
-
- //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
- /** ONLY 4-bit mode for time being **/
- for (scry = y; scry < y+h; scry+=1) {
- // for (scry = y; scry < y+2; scry+=1) {
- if (scry>=height) return;
- if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
- //for (scrx = w+x-xclip-1; scrx >= x; scrx-=2) {
- for (scrx = x; scrx < w+x-xclip; scrx+=2) {
- uint8_t sourcepixel = *(bitmap);
- if (xclip) {
- sourcepixel <<=4;
- sourcepixel |= ((*(bitmap-1))>>4);//inverted!
- }
- uint8_t targetpixel = *scrptr;
- // NIBBLES ARE INVERTED BECAUSE PICTURE IS FLIPPED !!!
- if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0xF0) | (sourcepixel>>4);
- if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel<<4);
- *scrptr = targetpixel;
- bitmap--;
- scrptr++;
- }
- bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
- if (xclip){
- if (w&1) {
- /**last pixel is odd pixel due to clipping & odd width*/
- uint8_t sourcepixel = *bitmap;
- if ((sourcepixel&0x0F) != invisiblecolor) {
- sourcepixel <<=4;
- uint8_t targetpixel = *scrptr;// & 0x0F;
- targetpixel |= sourcepixel;
- *scrptr = targetpixel;
- }
- //scrptr++;
- }
- bitmap++;
- scrptr++;
- }
- bitmap += xjump; // needed if x<0 clipping occurs
- } else { /** ODD pixel starting line **/
- for (scrx = x; scrx < w+x-xclip; scrx+=2 ) {
- uint8_t sourcepixel = *bitmap;
- uint8_t targetpixel = *scrptr;
- // inverted !!! store lower nibble of source pixel in lower nibble of target
- if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F );
- *scrptr = targetpixel;
- scrptr++;
- targetpixel = *scrptr;
- // inverted ! store higher nibble of source pixel in higher nibble of target
- if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel & 0xF0);
- *scrptr = targetpixel;
- bitmap--;
- }
- bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
- bitmap+=xjump;
- }
- // increment the y jump in the scrptr
- scrptr = scrptr + ((width - w)>>1)+scrxjump;
- }
-}
-
-void Display::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip) {
-#if PROJ_GAMEBUINO == 0
- if (!flip) drawBitmap(x,y,bitmap);
- else drawBitmapXFlipped(x,y,bitmap);
-#else
- if((rotation == NOROT) && (flip == NOFLIP)){
- drawBitmap(x,y,bitmap); //use the faster algorithm
- return;
- }
- uint8_t w = bitmap[0];
- uint8_t h = bitmap[1];
- bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
- int8_t i, j, //coordinates in the raw bitmap
- k, l, //coordinates in the rotated/flipped bitmap
- byteNum, bitNum, byteWidth = (w + 7) >> 3;
-
- rotation %= 4;
-
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- if (bitmap[j * byteWidth + byteNum] & (B10000000 >> bitNum)) {
- switch (rotation) {
- case NOROT: //no rotation
- k = i;
- l = j;
- break;
- case ROTCCW: //90� counter-clockwise
- k = j;
- l = w - i - 1;
- break;
- case ROT180: //180�
- k = w - i - 1;
- l = h - j - 1;
- break;
- case ROTCW: //90� clockwise
- k = h - j - 1;
- l = i;
- break;
- }
- if (flip) {
- flip %= 4;
- if (flip & B00000001) { //horizontal flip
- k = w - k;
- }
- if (flip & B00000010) { //vertical flip
- l = h - l;
- }
- }
- k += x; //place the bitmap on the screen
- l += y;
- drawPixel(k, l);
- }
- }
- }
-#endif //PROJ_GAMEBUINO
-
-}
-
-uint8_t* Display::getBuffer() {
- return m_scrbuf;
-}
-
-uint8_t Display::getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y) {
- uint16_t w = *bitmap;
- uint8_t sourcebyte = bitmap[2+(y * ((w+7)>>3))+ (x>>3)];
- return sourcebyte & (0x80>>(x&7));
-}
-
-int Display::print_char(uint8_t x, uint8_t y, unsigned char c) {
- c -= font[2];
- if (m_mode) return directChar(x,y,c);
- return bufferChar(x,y,c);
-}
-
-void Display::drawChar(int8_t x, int8_t y, unsigned char c, uint8_t size) {
- print_char(x,y,c);
- return;
-}
-
-
-bool Display::isDirectPrintingEnabled() {
- return m_mode;
-}
-
-void Display::enableDirectPrinting(uint8_t m) {
- if (m) {
- m_mode=true;
- m_w = POK_LCD_W;
- m_h = POK_LCD_H;
- } else {
- m_mode=false;
- m_w = getWidth();
- m_h = getHeight();
- }
-}
-
-void Display::write(uint8_t c) {
- int charstep=0;
- if(font[3]) {
- // only caps in this font
- if (c>=97) c-=32;
- }
- switch(c) {
- case '\0': //null
- break;
- case '\n': //line feed
- cursorX = 0;
- inc_txtline();
- break;
- case 8: //backspace
- cursorX -= font[0];
- charstep=print_char(cursorX,cursorY,' ');
- break;
- case 13: //carriage return
- cursorX = 0;
- break;
- case 14: //form feed new page(clear screen)
- //clear_screen();
- break;
- default:
- if (cursorX >= (m_w - font[0])) {
- cursorX = 0;
- if (textWrap) inc_txtline();
- else return; // stop outputting text
- charstep=print_char(cursorX,cursorY,c);
- }
- else
- charstep=print_char(cursorX,cursorY,c);
- if (c==' ' && adjustCharStep) charstep=(charstep>>1)+1;
- cursorX += charstep;
- }
-}
-
-void Display::inc_txtline() {
- if (cursorY > m_h - 2*font[1]) //= (height - (font[1]+1)))
- #if SCROLL_TEXT > 0
- scroll(font[1] + adjustLineStep);
- #else
- cursorY = 0;
- #endif
- else
- cursorY += font[1] + adjustLineStep;
-}
-
-/* default implementation: may be overridden */
-void Display::write(const char *str)
-{
- while (*str)
- write(*str++);
-}
-
-/* default implementation: may be overridden */
-void Display::write(const uint8_t *buffer, uint8_t size)
-{
- while (size--)
- write(*buffer++);
-}
-
-void Display::print(const char str[])
-{
- write(str);
-}
-
-void Display::print(char c, int base)
-{
- print((long) c, base);
-}
-
-void Display::print(unsigned char b, int base)
-{
- print((unsigned long) b, base);
-}
-
-void Display::print(int n, int base)
-{
- print((long) n, base);
-}
-
-void Display::print(unsigned int n, int base)
-{
- print((unsigned long) n, base);
-}
-
-void Display::print(long n, int base)
-{
- if (base == 0) {
- write(n);
- } else if (base == 10) {
- if (n < 0) {
- print('-');
- n = -n;
- }
- printNumber(n, 10);
- } else {
- printNumber(n, base);
- }
-}
-
-void Display::print(unsigned long n, int base)
-{
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-void Display::print(double n, int digits)
-{
- printFloat(n, digits);
-}
-
-void Display::println(void)
-{
- print('\r');
- print('\n');
-}
-
-void Display::println(const char c[])
-{
- print(c);
- println();
-}
-
-void Display::println(char c, int base)
-{
- print(c, base);
- println();
-}
-
-void Display::println(unsigned char b, int base)
-{
- print(b, base);
- println();
-}
-
-void Display::println(int n, int base)
-{
- print(n, base);
- println();
-}
-
-void Display::println(unsigned int n, int base)
-{
- print(n, base);
- println();
-}
-
-void Display::println(long n, int base)
-{
- print(n, base);
- println();
-}
-
-void Display::println(unsigned long n, int base)
-{
- print(n, base);
- println();
-}
-
-void Display::println(double n, int digits)
-{
- print(n, digits);
- println();
-}
-
-void Display::set_cursor(uint8_t x, uint8_t y) {
- cursorX = x;
- cursorY = y;
-}
-
-void Display::print(uint8_t x, uint8_t y, const char str[]) {
- cursorX = x;
- cursorY = y;
- write(str);
-
-}
-void Display::print(uint8_t x, uint8_t y, char c, int base) {
- cursorX = x;
- cursorY = y;
- print((long) c, base);
-}
-void Display::print(uint8_t x, uint8_t y, unsigned char b, int base) {
- cursorX = x;
- cursorY = y;
- print((unsigned long) b, base);
-}
-void Display::print(uint8_t x, uint8_t y, int n, int base) {
- cursorX = x;
- cursorY = y;
- print((long) n, base);
-}
-void Display::print(uint8_t x, uint8_t y, unsigned int n, int base) {
- cursorX = x;
- cursorY = y;
- print((unsigned long) n, base);
-}
-void Display::print(uint8_t x, uint8_t y, long n, int base) {
- cursorX = x;
- cursorY = y;
- print(n,base);
-}
-void Display::print(uint8_t x, uint8_t y, unsigned long n, int base) {
- cursorX = x;
- cursorY = y;
- print(n,base);
-}
-void Display::print(uint8_t x, uint8_t y, double n, int digits) {
- cursorX = x;
- cursorY = y;
- print(n,digits);
-}
-
-void Display::println(uint8_t x, uint8_t y, const char c[])
-{
- cursorX = x;
- cursorY = y;
- print(c);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, char c, int base)
-{
- cursorX = x;
- cursorY = y;
- print(c, base);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, unsigned char b, int base)
-{
- cursorX = x;
- cursorY = y;
- print(b, base);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, int n, int base)
-{
- cursorX = x;
- cursorY = y;
- print(n, base);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, unsigned int n, int base)
-{
- cursorX = x;
- cursorY = y;
- print(n, base);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, long n, int base)
-{
- cursorX = x;
- cursorY = y;
- print(n, base);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, unsigned long n, int base)
-{
- cursorX = x;
- cursorY = y;
- print(n, base);
- println();
-}
-
-void Display::println(uint8_t x, uint8_t y, double n, int digits)
-{
- cursorX = x;
- cursorY = y;
- print(n, digits);
- println();
-}
-
-void Display::printNumber(unsigned long n, uint8_t base)
-{
- unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
- unsigned long i = 0;
-
- if (n == 0) {
- print('0');
- return;
- }
-
- while (n > 0) {
- buf[i++] = n % base;
- n /= base;
- }
-
- for (; i > 0; i--)
- print((char) (buf[i - 1] < 10 ?
- '0' + buf[i - 1] :
- 'A' + buf[i - 1] - 10));
-}
-
-void Display::printFloat(double number, uint8_t digits)
-{
- // Handle negative numbers
- if (number < 0.0)
- {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- for (uint8_t i=0; i<digits; ++i)
- rounding /= 10.0;
-
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits > 0)
- print(".");
-
- // Extract digits from the remainder one at a time
- while (digits-- > 0)
- {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
-}
-
-void Display::draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap)
-{
- int8_t scry;
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
-
- /** ONLY 4-bit mode for time being **/
-
- if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
- for (scry = y; scry < h+y; scry++) {
- uint8_t sourcepixel = *bitmap;
- uint8_t targetpixel = *scrptr;
- targetpixel = (targetpixel&0x0F) | (sourcepixel << 4);
- *scrptr = targetpixel;
- bitmap++;
- scrptr+=55;
- }
- } else { /** ODD pixel starting line **/
- for (scry = y; scry < h+y; scry++) {
- uint8_t sourcepixel = *bitmap;
- uint8_t targetpixel = *scrptr;
- // store source pixel in lower nibble of target
- targetpixel = (targetpixel & 0xF0) | (sourcepixel);
- *scrptr = targetpixel;
- scrptr+=55;
- bitmap++;
- }
- }
-}
-
-void Display::lcdRefresh(unsigned char* scr) {
-
-#if POK_SCREENMODE == MODE_GAMEBOY
- lcdRefreshModeGBC(scr, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_HI_4COLOR
- lcdRefreshMode1(scr, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_FAST_16COLOR
- lcdRefreshMode2(scr, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR
- lcdRefreshGB(scr, paletteptr);
-#endif
-
-#if POK_SCREENMODE == MODE_ARDUBOY_16COLOR
- lcdRefreshAB(scr, paletteptr);
-#endif
-
-}
-
-void Display::setFrameBufferTo(uint8_t* sb) {
- m_scrbuf = sb;
-};
-
-void Display::setTileBufferTo(uint8_t* tb) {
- m_tilebuf = tb;
-};
-
-void Display::loadTileset(const uint8_t* ts) {
- m_tileset = (uint8_t*) ts;
-};
-
-void Display::setTile(uint16_t i, uint8_t t) {
- if (!m_tilebuf) return;
- m_tilebuf[i]=t;
-};
-
-
-/** Eof */
-
-
-
-
--- a/POKITTO_CORE/PokittoDisplay.h Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,410 +0,0 @@
-/**************************************************************************/
-/*!
- @file PokittoDisplay.h
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-
-
-/* THE SEGMENT BELOW PERTAINS TO CIRCLE DRAWING FUNCTIONS ONLY
-*
-This is the core graphics library for all our displays, providing a common
-set of graphics primitives (points, lines, circles, etc.). It needs to be
-paired with a hardware-specific library for each display device we carry
-(to handle the lower-level functions).
-Adafruit invests time and resources providing this open source code, please
-support Adafruit & open-source hardware by purchasing products from Adafruit!
-Copyright (c) 2013 Adafruit Industries. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-- Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef POKITTODISPLAY_H
-#define POKITTODISPLAY_H
-
-#include <stdint.h>
-#include "Pokitto_settings.h"
-#include "PokittoGlobs.h"
-#include "PokittoFonts.h"
-#include "PokittoPalettes.h"
-
-// Basic Color definitions
-#define COLOR_BLACK (uint16_t)(0x0000)
-#define COLOR_BLUE (uint16_t)(0x001F)
-#define COLOR_RED (uint16_t)(0xF800)
-#define COLOR_GREEN (uint16_t)(0x07E0)
-#define COLOR_CYAN (uint16_t)(0x07FF)
-#define COLOR_MAGENTA (uint16_t)(0xF81F)
-#define COLOR_YELLOW (uint16_t)(0xFFE0)
-#define COLOR_WHITE (uint16_t)(0xFFFF)
-
-// Grayscale Values
-#define COLOR_GRAY_15 (uint16_t)(0x0861) // 15 15 15
-#define COLOR_GRAY_30 (uint16_t)(0x18E3) // 30 30 30
-#define COLOR_GRAY_50 (uint16_t)(0x3186) // 50 50 50
-#define COLOR_GRAY_80 (uint16_t)(0x528A) // 80 80 80
-#define COLOR_GRAY_128 (uint16_t)(0x8410) // 128 128 128
-#define COLOR_GRAY_200 (uint16_t)(0xCE59) // 200 200 200
-#define COLOR_GRAY_225 (uint16_t)(0xE71C) // 225 225 225
-
-/** The tables below are palettes, that resemble the Pico 8 palette*/
-
-enum defcolors {
- C_BLACK,
- C_DARKBLUE,
- C_PURPLE,
- C_DARKGREEN,
-
- C_BROWN,
- C_DARKBROWN,
- C_LIGHTGRAY,
- C_WHITE,
-
- C_RED,
- C_ORANGE,
- C_YELLOW,
- C_GREEN,
-
- C_BLUE,
- C_DARKGRAY,
- C_PINK,
- C_PEACH
-};
-
-const uint16_t def565palette[16] = {
- //kind of like pico8 palette
- 0,0x194a,0x792a,0x42a,
- 0xaa86,0x5aa9,0xc618,0xff9d,
- 0xf809,0xfd00,0xff84,0x72a,
- 0x2d7f,0x83b3,0xfbb5,0xfe75
-};
-
-#define PALETTE_SIZE 16
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-namespace Pokitto {
-
-class Display {
-public:
- Display();
-
- // PROPERTIES
-private:
- static uint8_t* canvas;
- static uint8_t bpp;
- static uint8_t m_colordepth;
-public:
- static uint8_t width;
- static uint8_t height;
- static uint8_t screenbuffer[];
-
- // PROPERTIES
- static void setColorDepth(uint8_t);
- static uint8_t getColorDepth();
- static uint8_t getBitsPerPixel();
- static uint16_t getWidth();
- static uint16_t getHeight();
- static uint8_t getNumberOfColors();
-
- // IMPORTANT PUBLIC STATE MEMBERS
- /** Selected font */
- static const unsigned char * font;
- /** Set if screen is cleared between updates or not*/
- static uint8_t persistence;
- /** Selected drawing color */
- static uint16_t color;
- /** Selected background color */
- static uint16_t bgcolor;
- /** Selected invisible color */
- static uint16_t invisiblecolor;
- /** Direct unbuffered color */
- static uint16_t directcolor;
- /** Direct unbuffered background color */
- static uint16_t directbgcolor;
- /** set color with a command */
- static void setColor(uint8_t);
- /** set color and bgcolor with a command */
- static void setColor(uint8_t,uint8_t);
- /** set invisiblecolor with a command */
- static void setInvisibleColor(uint16_t);
- /** get color */
- static uint8_t getColor();
- /** get background color */
- static uint8_t getBgColor();
- /** get invisible color */
- static uint16_t getInvisibleColor();
-
-
- /** Initialize display */
- static void begin();
- /** Clear display buffer */
- static void clear();
- /** Scroll by x lines */
- static void scroll(int16_t);
- /** Fill display buffer */
- static void fillScreen(uint16_t);
- /** Send display buffer to display hardware */
- static void update();
- /** Forced update of LCD display memory with a given pixel buffer */
- static void lcdRefresh(unsigned char*);
- /** Clear LCD hardware memory */
- static void clearLCD();
- /** Fill LCD hardware memory */
- static void fillLCD(uint16_t);
- /** Show Pokitto logo at startup*/
- static void showLogo();
- /** Point to another screenbuffer instead of the default one */
- static void setFrameBufferTo(uint8_t*);
-
- // COLORS AND PALETTE
-public:
- /** set default palette */
- static void setDefaultPalette();
- /** master palette */
- static uint16_t palette[PALETTE_SIZE];
- /** runtime palette pointer */
- static uint16_t *paletteptr;
- /** convert RGB to 565 color value */
- static uint16_t RGBto565(uint8_t,uint8_t,uint8_t);
- /** linear interpolation between colors */
- static uint16_t interpolateColor(uint16_t, uint16_t, uint8_t);
- /** load an R,G,B triplet palette */
- static void loadRGBPalette(const unsigned char*);
- /** load a ready-made 565 palette */
- static void load565Palette(const uint16_t*);
- /** rotate palette by step */
- static void rotatePalette(int8_t);
- /** tween between two palettes **/
- static void tweenPalette(uint16_t*, const uint16_t*, const uint16_t*, uint8_t);
-
- // DIRECT DRAWING (NO BUFFERING)
- /** Direct pixel (not through display buffer) */
- static void directPixel(int16_t,int16_t,uint16_t);
- /** Direct tile 16bit (not through display buffer) */
- static void directTile(int16_t x, int16_t y, int16_t x2, int16_t y2, uint16_t* gfx);
- /** Direct rectangle (not through display buffer) */
- static void directRectangle(int16_t, int16_t,int16_t, int16_t, uint16_t);
- /** Set the cursor for printing to a certain screen position */
- static void setCursor(int16_t,int16_t);
- /** direct bitmap to screen (no buffering) */
- static void directBitmap(int16_t,int16_t,const uint8_t*, uint8_t,uint8_t);
-
-
- // DRAWING METHODS
- /** Draw pixel at various bit depths */
- static void drawPixel(int16_t,int16_t);
- /** Draw pixel with specific color index at various bit depths */
- static void drawPixel(int16_t x,int16_t y, uint8_t col);
- /** Get pixel at various bit depths */
- static uint8_t getPixel(int16_t,int16_t);
- /** Draw line **/
- static void drawLine(int16_t,int16_t,int16_t,int16_t);
- /** Clip line with screen boundaries, returns 0 if whole line is out of bounds */
- static uint8_t clipLine(int16_t*, int16_t*, int16_t*, int16_t*);
- /** Draw a column real fast */
- static void drawColumn(int16_t, int16_t, int16_t);
- /** Map a 1-bit column real fast */
- static void map1BitColumn(int16_t, int16_t, int16_t, const uint8_t*, uint16_t);
- /** Draw a row real fast */
- static void drawRow(int16_t, int16_t, int16_t);
- /** Legacy drawColumn name, for compatibility - macros are not OK because of scope problems */
- static void drawFastVLine(int16_t, int16_t, int16_t);
- /** Legacy drawRow name, for compatibility - macros are not OK because of scope problems */
- static void drawFastHLine(int16_t, int16_t, int16_t);
- /** Draw rectangle (edges only) */
- static void drawRectangle(int16_t,int16_t,int16_t,int16_t);
- /** Fill rectangle */
- static void fillRectangle(int16_t,int16_t,int16_t,int16_t);
- /** GB compatibility fillRect */
- static void fillRect(int16_t x, int16_t y, int16_t w, int16_t h);
- /** GB compatibility drawRect */
- static void drawRect(int16_t x, int16_t y, int16_t w, int16_t h);
-
- // Functions lifted from Adafruit GFX library (see PokittoDisplay.h for license //
- /** Draw circle */
- static void drawCircle(int16_t x0, int16_t y0, int16_t r);
- /** Draw circle helper */
- static void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername);
- /** Fill circle */
- static void fillCircle(int16_t x0, int16_t y0, int16_t r);
- /** Fill circle helper*/
- static void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername, int16_t delta);
- /** draw triangle */
- static void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
- /** Fill triangle*/
- static void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
- /** Draw rounded rectangle */
- static void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius);
- /** Fill rounded rectangle */
- static void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius);
-
- // BITMAPS !
- /** Draw monochromatic bitmap. Used in font rendering */
- static void drawMonoBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t index);
- /** Draw bitmap */
- static void drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap);
- /** Draw RLE bitmap */
- static void drawRleBitmap(int16_t x, int16_t y, const uint8_t* bitmap);
- /** Draw animated bitmap frame */
- static void drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame);
- /** Draw bitmap flipped on x-axis*/
- static void drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap);
- /** Draw bitmap with options */
- static void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip);
- /** Get pointer to the screen buffer - GB compatibility */
- static uint8_t* getBuffer();
- /** Get pixel in a monochromatic bitmap - GB compatibility */
- static uint8_t getBitmapPixel(const uint8_t*, uint16_t, uint16_t);
- /** Optimized functions for drawing bit columns - used in raytracing */
- static void draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap);
-
- // PRINTING
- /** direct character to screen (no buffering) */
- static int directChar(int16_t, int16_t, uint16_t);
- /** character to screenbuffer */
- static int bufferChar(int16_t, int16_t, uint16_t);
- /** set the active font */
- static void setFont(const unsigned char * f);
- /** font dimensions */
- static uint8_t fontWidth, fontHeight;
- /** text wrapping */
- static bool textWrap;
- /** GB compatibility drawChar */
- static void drawChar(int8_t x, int8_t y, unsigned char c, uint8_t size);
-
- static void enableDirectPrinting(uint8_t m);
- static bool isDirectPrintingEnabled();
- static int print_char(uint8_t x, uint8_t y, unsigned char c);
- static void set_cursor(uint8_t, uint8_t);
- static void write(uint8_t);
- static void write(const char *str);
- static void write(const uint8_t *buffer, uint8_t size);
- static void print(const char[]);
- static void print(char, int base = 0);
- static void print(unsigned char, int base = 0);
- static void print(int, int base = 10);
- static void print(unsigned int, int base = 10);
- static void print(long, int base = 10);
- static void print(unsigned long, int base = 10);
- static void print(double, int base = 2);
- static void print(uint8_t, uint8_t, const char[]);
- static void print(uint8_t, uint8_t, char, int = 0);
- static void print(uint8_t, uint8_t, unsigned char, int = 0);
- static void print(uint8_t, uint8_t, int, int = 10);
- static void print(uint8_t, uint8_t, unsigned int, int = 10);
- static void print(uint8_t, uint8_t, long, int = 10);
- static void print(uint8_t, uint8_t, unsigned long, int = 10);
- static void print(uint8_t, uint8_t, double, int = 2);
- static void println(uint8_t, uint8_t, const char[]);
- static void println(uint8_t, uint8_t, char, int = 0);
- static void println(uint8_t, uint8_t, unsigned char, int = 0);
- static void println(uint8_t, uint8_t, int, int = 10);
- static void println(uint8_t, uint8_t, unsigned int, int = 10);
- static void println(uint8_t, uint8_t, long, int = 10);
- static void println(uint8_t, uint8_t, unsigned long, int = 10);
- static void println(uint8_t, uint8_t, double, int = 2);
- static void println(uint8_t, uint8_t);
- static void println(const char[]);
- static void println(char, int = 0);
- static void println(unsigned char, int = 0);
- static void println(int, int = 10);
- static void println(unsigned int, int = 10);
- static void println(long, int = 10 );
- static void println(unsigned long, int = 10);
- static void println(double, int = 2);
- static void println(void);
-
- static int16_t cursorX,cursorY;
- static uint8_t fontSize;
- static int8_t adjustCharStep, adjustLineStep;
- static bool fixedWidthFont;
-
- static void inc_txtline();
- static void printNumber(unsigned long, uint8_t);
- static void printFloat(double, uint8_t);
-
- /** Tiled mode functions **/
-
- static void loadTileset(const uint8_t*);
-
- static void setTileBufferTo(uint8_t*);
- static void clearTileBuffer();
- static void shiftTileBuffer(int8_t,int8_t);
-
- static void setTile(uint16_t,uint8_t);
- static uint8_t getTile(uint16_t);
- static uint8_t getTile(uint8_t,uint8_t);
-
-
-
-private:
- static uint8_t m_mode;
- static uint16_t m_w,m_h; // store these for faster access when switching printing modes
- /** Pointer to screen buffer */
- static uint8_t* m_scrbuf;
- /** Pointer to tileset */
- static uint8_t* m_tileset;
- /** Pointer to tilebuffer */
- static uint8_t* m_tilebuf;
- /** Pointer to tilecolorbuffer */
- static uint8_t* m_tilecolorbuf;
-
-};
-
-}
-
-#endif // POKITTODISPLAY_H
-
-
-
-
-
--- a/POKITTO_CORE/PokittoSound.cpp Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,914 +0,0 @@
-/**************************************************************************/
-/*!
- @file PokittoSound.cpp
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-/*
- * NOTE:
- * API of the Pokitto Sound library is partially identical to the Gamebuino Sound API.
- * Due to the difference in architecture (ARM Cortex-M0+ in mbed environment vs. 8-bit AVR)
- * large parts are not identical. Most functions were rewritten, with only API remaining.
- * We want to give attribution to the original author's project:
- *
- * License for Gamebuino-identical code:
- *
- * (C) Copyright 2014 Aur�lien Rodot. All rights reserved.
- *
- * This file is part of the Gamebuino Library (http://gamebuino.com)
- *
- * The Gamebuino Library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- */
-
-#include "PokittoSound.h"
-#include "Pokitto_settings.h"
-#include "PokittoCore.h"
-#include "Synth.h"
-
-#ifndef POK_SIM
-#include "HWSound.h"
-#else
-#include "SimSound.h"
-#include "PokittoSimulator.h"
-#endif
-
-typedef uint8_t byte;
-
-using namespace Pokitto;
-
-Pokitto::Core c;
-
-uint8_t Sound::prescaler;
-uint16_t Sound::globalVolume;
-uint16_t Sound::volumeMax = VOLUME_HEADPHONE_MAX;
-
-bool Sound::trackIsPlaying[NUM_CHANNELS];
-bool Sound::patternIsPlaying[NUM_CHANNELS];
-uint8_t Sound::outputPitch[NUM_CHANNELS];
-int8_t Sound::outputVolume[NUM_CHANNELS];
-
-uint16_t *Sound::trackData[NUM_CHANNELS];
-uint8_t Sound::trackCursor[NUM_CHANNELS];
-uint16_t **Sound::patternSet[NUM_CHANNELS];
-int8_t Sound::patternPitch[NUM_CHANNELS];
-
-// pattern data
-uint16_t *Sound::patternData[NUM_CHANNELS];
-uint16_t **Sound::instrumentSet[NUM_CHANNELS];
-bool Sound::patternLooping[NUM_CHANNELS];
-uint16_t Sound::patternCursor[NUM_CHANNELS];
-
-// note data
-uint8_t Sound::notePitch[NUM_CHANNELS];
-uint8_t Sound::noteDuration[NUM_CHANNELS];
-int8_t Sound::noteVolume[NUM_CHANNELS];
-bool Sound::notePlaying[NUM_CHANNELS];
-
-// commands data
-int8_t Sound::commandsCounter[NUM_CHANNELS];
-int8_t Sound::volumeSlideStepDuration[NUM_CHANNELS];
-int8_t Sound::volumeSlideStepSize[NUM_CHANNELS];
-uint8_t Sound::arpeggioStepDuration[NUM_CHANNELS];
-int8_t Sound::arpeggioStepSize[NUM_CHANNELS];
-uint8_t Sound::tremoloStepDuration[NUM_CHANNELS];
-int8_t Sound::tremoloStepSize[NUM_CHANNELS];
-
-// instrument data
-uint16_t *Sound::instrumentData[NUM_CHANNELS];
-uint8_t Sound::instrumentLength[NUM_CHANNELS]; //number of steps in the instrument
-uint8_t Sound::instrumentLooping[NUM_CHANNELS]; //how many steps to loop on when the last step of the instrument is reached
-uint16_t Sound::instrumentCursor[NUM_CHANNELS]; //which step is being played
-uint8_t Sound::instrumentNextChange[NUM_CHANNELS]; //how many frames before the next step
-
-//current step data
-int8_t Sound::stepVolume[NUM_CHANNELS];
-uint8_t Sound::stepPitch[NUM_CHANNELS];
-uint8_t Sound::chanVolumes[NUM_CHANNELS];
-
-#if (POK_ENABLE_SOUND < 1)
- #define NUM_CHANNELS 0
-#endif
-
-#if(NUM_CHANNELS > 0)
- #ifndef POK_SIM
- uint8_t sbyte;
- #else
- uint8_t sbyte;
- float pwm1;
- #endif // POK_SIM
-
-//declare these variables globally for faster access
-uint8_t _rand = 1;
-uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform
-bool _chanState[NUM_CHANNELS]; //if the waveform is currently high or low
-uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform
-uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform
-uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform
-bool _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise
-
-#if POK_GBSOUND > 0
-const uint16_t squareWaveInstrument[] = {0x0101, 0x03F7};
-const uint16_t noiseInstrument[] = {0x0101, 0x03FF};
-const uint16_t* const defaultInstruments[] = {squareWaveInstrument,noiseInstrument};
-
-const uint16_t playOKPattern[] = {0x0005,0x138,0x168,0x0000};
-const uint16_t playCancelPattern[] = {0x0005,0x168,0x138,0x0000};
-const uint16_t playTickP[] = {0x0045,0x168,0x0000};
-#endif
-#if(EXTENDED_NOTE_RANGE > 0)
-//extended note range
-#define NUM_PITCH 59
-const uint8_t _halfPeriods[NUM_PITCH] = {246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,104,98,92,87,82,78,73,69,65,62,58,55,52,49,46,44,41,39,37,35,33,31,29,28,26,25,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6};
-#else
-//regular note range
-#define NUM_PITCH 36
-const uint8_t _halfPeriods[NUM_PITCH] = {246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,104,98,92,87,82,78,73,69,65,62,58,55,52,49,46,44,41,39,37,35,33};
-#endif
-
-#endif
-
-void Pokitto::audio_IRQ() {
- #if POK_STREAMING_MUSIC > 0
- #if POK_STREAMFREQ_HALVE > 0
- streamstep = 1-streamstep;
- #else
- streamstep=1;
- #endif
-
- streamstep &= streamon; //check if stream is on
-
- if(streamvol && streamstep) {
- uint8_t output = (*currentPtr++);
- sbyte = output;
- } else {
- sbyte = 0; // duty cycle
- }
-
- if (currentPtr >= endPtr)
- {
- currentBuffer++;
- if (currentBuffer==4) currentBuffer=0;
- currentPtr = buffers[currentBuffer];
- endPtr = currentPtr + BUFFER_SIZE;
- }
-
- #endif // POK_STREAMING_MUSIC
- #if (NUM_CHANNELS > 0)
- Sound::generateOutput();
- #endif
-}
-
-void Sound::volumeUp() {
- if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()+VOLUME_STEP*2);
- else setVolume(getVolume()+VOLUME_STEP);
-}
-
-void Sound::volumeDown() {
- if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()-VOLUME_STEP*4);
- else setVolume(getVolume()-VOLUME_STEP);
-}
-
-
-void Sound::setMaxVol(int16_t v) {
- if (v < 0) v = 0; //prevent nasty wraparound
- if (v > VOLUME_SPEAKER_MAX) {
- v = VOLUME_SPEAKER_MAX;
- }
- volumeMax = v;
- setVolume(globalVolume);
-}
-
-uint16_t Sound::getMaxVol() {
- return volumeMax;
-}
-
-void Sound::updateStream() {
- #if POK_STREAMING_MUSIC
- if (oldBuffer != currentBuffer) {
- if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE);
- else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE);
- else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE);
- else fileReadBytes(&buffers[2][0],BUFFER_SIZE);
- oldBuffer = currentBuffer;
- streamcounter += BUFFER_SIZE;
- }
-
- #ifndef POK_SIM
- if ( streamcounter > fs.fsize - (BUFFER_SIZE)) {
- #else
- if ( streamcounter > getFileLength() - (BUFFER_SIZE)) {
- #endif
- streamcounter=0;
- #if POK_STREAM_LOOP > 0
- fileRewind();
- #endif
- #ifndef POK_SIM
- streamon=0;
- #endif // POK_SIM
- }
- #endif
-}
-
-void Sound::begin() {
-#if POK_ENABLE_SOUND > 0
-soundInit();
-ampEnable(true);
-#endif
-#if (NUM_CHANNELS > 0)
-#if POK_ENABLE_SOUND > 0
-#if POK_GBSOUND > 0
- prescaler = 1;
- for(byte i=0; i<NUM_CHANNELS; i++){
- chanVolumes[i] = VOLUME_CHANNEL_MAX;
- changeInstrumentSet(defaultInstruments, i); //load default instruments. #0:square wave, #1: noise
- command(CMD_INSTRUMENT, 0, 0, i); //set the default instrument to square wave
- }
-#endif // POK_GBSOUND
-#endif //POK_ENABLE_SOUND
-#endif
-}
-
-void Sound::playTrack(const uint16_t* track, uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- stopTrack(channel);
- trackCursor[channel] = 0;
- trackData[channel] = (uint16_t*)track;
- trackIsPlaying[channel] = true;
-#endif
-}
-
-void Sound::stopTrack(uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- trackIsPlaying[channel] = false;
- stopPattern(channel);
-#endif
-}
-
-void Sound::stopTrack(){
-#if(NUM_CHANNELS > 0)
- for(uint8_t i=0; i<NUM_CHANNELS; i++){
- stopTrack(i);
- }
-#endif
-}
-
-void Sound::updateTrack(uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- if(trackIsPlaying[channel] && !patternIsPlaying[channel]){
- uint16_t data = pgm_read_word(trackData[channel] + trackCursor[channel]);
- if(data == 0xFFFF){ //en of the track
- trackIsPlaying[channel] = false;
- return;
- }
- uint8_t patternID = data & 0xFF;
- data >>= 8;
- patternPitch[channel] = data;
- playPattern((const uint16_t*)pgm_read_word(&(patternSet[channel][patternID])), channel);
- trackCursor[channel] ++;
- }
-#endif
-}
-
-void Sound::updateTrack(){
-#if(NUM_CHANNELS > 0)
- for (uint8_t i=0; i<NUM_CHANNELS; i++){
- updateTrack(i);
- }
-#endif
-}
-
-void Sound::changePatternSet(const uint16_t* const* patterns, uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- patternSet[channel] = (uint16_t**)patterns;
-#endif
-}
-
-void Sound::playPattern(const uint16_t* pattern, uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- stopPattern(channel);
- patternData[channel] = (uint16_t*)pattern;
- patternCursor[channel] = 0;
- patternIsPlaying[channel] = true;
- noteVolume[channel] = 9;
- //reinit commands
- volumeSlideStepDuration[channel] = 0;
- arpeggioStepDuration[channel] = 0;
- tremoloStepDuration[channel] = 0;
-#endif
-}
-
-void Sound::updatePattern(){
-#if(NUM_CHANNELS > 0)
- for (uint8_t i=0; i<NUM_CHANNELS; i++){
- updatePattern(i);
- }
-#endif
-}
-
-void Sound::changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- instrumentSet[channel] = (uint16_t**)instruments;
-#endif
-}
-
-void Sound::updatePattern(uint8_t i){
-#if(NUM_CHANNELS > 0)
- if(i>=NUM_CHANNELS)
- return;
- if(patternIsPlaying[i]){
- if(noteDuration[i]==0){//if the end of the previous note is reached
-
- uint16_t data = pgm_read_word(patternCursor[i] + patternData[i]);
-
- if(data == 0){ //end of the pattern reached
- if(patternLooping[i] == true){
- patternCursor[i] = 0;
- data = pgm_read_word(patternCursor[i] + patternData[i]);
- }
- else{
- patternIsPlaying[i] = false;
- if(trackIsPlaying[i]){ //if this pattern is part of a track, get the next pattern
- updateTrack(i);
- data = pgm_read_word(patternCursor[i] + patternData[i]);
- } else {
- stopNote(i);
- //Serial.print("pattern end\n");
- return;
- }
- }
- }
-
- while (data & 0x0001){ //read all commands and instrument changes
- data >>= 2;
- //Serial.print("\ncmd\t");
- uint8_t cmd = data & 0x0F;
- data >>= 4;
- uint8_t X = data & 0x1F;
- data >>= 5;
- int8_t Y = data - 16;
- command(cmd,X,Y,i);
- patternCursor[i]++;
- data = pgm_read_word(patternCursor[i] + patternData[i]);
- }
- data >>= 2;
-
- uint8_t pitch = data & 0x003F;
- data >>= 6;
-
- uint8_t duration = data;
- if(pitch != 63){
- }
-
- playNote(pitch, duration, i);
-
- patternCursor[i]++;
- }
- }
-#endif
-}
-
-void Sound::stopPattern(uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- stopNote(channel);
- patternIsPlaying[channel] = false;
-#endif
-}
-
-void Sound::stopPattern(){
-#if(NUM_CHANNELS > 0)
- for(uint8_t i=0; i<NUM_CHANNELS; i++){
- stopPattern(i);
- }
-#endif
-}
-
-void Sound::command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t i){
-#if(NUM_CHANNELS > 0)
- if(i>=NUM_CHANNELS)
- return;
- switch(cmd){
- case CMD_VOLUME: //volume
- X = constrain((int8_t)X, 0, 10);
- noteVolume[i] = X;
- break;
- case CMD_INSTRUMENT: //instrument
- instrumentData[i] = (uint16_t*)pgm_read_word(&(instrumentSet[i][X]));
- instrumentLength[i] = pgm_read_word(&(instrumentData[i][0])) & 0x00FF; //8 LSB
- instrumentLength[i] *= prescaler;
- instrumentLooping[i] = min2((pgm_read_word(&(instrumentData[i][0])) >> 8), instrumentLength[i]); //8 MSB - check that the loop is shorter than the instrument length
- instrumentLooping[i] *= prescaler;
- break;
- case CMD_SLIDE: //volume slide
- volumeSlideStepDuration[i] = X * prescaler;
- volumeSlideStepSize[i] = Y;
- break;
- case CMD_ARPEGGIO:
- arpeggioStepDuration[i] = X * prescaler;
- arpeggioStepSize[i] = Y;
- break;
- case CMD_TREMOLO:
- tremoloStepDuration[i] = X * prescaler;
- tremoloStepSize[i] = Y;
- break;
- default:
- break;
- }
-#endif
-}
-
-void Sound::playNote(uint8_t pitch, uint8_t duration, uint8_t channel){
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- //set note
- notePitch[channel] = pitch;
- noteDuration[channel] = duration * prescaler;
- //reinit vars
- instrumentNextChange[channel] = 0;
- instrumentCursor[channel] = 0;
- notePlaying[channel] = true;
- _chanState[channel] = true;
- commandsCounter[channel] = 0;
-#endif
-}
-
-void Sound::stopNote(uint8_t channel) {
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- notePlaying[channel] = false;
- //counters
- noteDuration[channel] = 0;
- instrumentCursor[channel] = 0;
- commandsCounter[channel] = 0;
- //output
- _chanOutput[channel] = 0;
- _chanOutputVolume[channel] = 0;
- _chanState[channel] = false;
- updateOutput();
-#endif
-}
-
-void Sound::stopNote() {
-#if(NUM_CHANNELS > 0)
- for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- stopNote(channel);
- }
-#endif
-}
-
-void Sound::updateNote() {
-#if(NUM_CHANNELS > 0)
- for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
- updateNote(i);
- }
-#endif
-}
-
-void Sound::updateNote(uint8_t i) {
-#if(NUM_CHANNELS > 0)
- if(i>=NUM_CHANNELS)
- return;
- if (notePlaying[i]) {
-
- if(noteDuration[i] == 0){
- stopNote(i);
- //Serial.println("note end");
- return;
- } else {
- noteDuration[i]--;
- }
-
- if (instrumentNextChange[i] == 0) {
-
- //read the step data from the progmem and decode it
- uint16_t thisStep = pgm_read_word(&(instrumentData[i][1 + instrumentCursor[i]]));
-
- stepVolume[i] = thisStep & 0x0007;
- thisStep >>= 3;
-
- uint8_t stepNoise = thisStep & 0x0001;
- thisStep >>= 1;
-
- uint8_t stepDuration = thisStep & 0x003F;
- thisStep >>= 6;
-
- stepPitch[i] = thisStep;
-
- //apply the step settings
- instrumentNextChange[i] = stepDuration * prescaler;
-
- _chanNoise[i] = stepNoise;
-
-
- instrumentCursor[i]++;
-
- if (instrumentCursor[i] >= instrumentLength[i]) {
- if (instrumentLooping[i]) {
- instrumentCursor[i] = instrumentLength[i] - instrumentLooping[i];
- } else {
- stopNote(i);
- }
- }
- }
- instrumentNextChange[i]--;
-
- commandsCounter[i]++;
-
- //UPDATE VALUES
- //pitch
- outputPitch[i] = notePitch[i] + stepPitch[i] + patternPitch[i];
- if(arpeggioStepDuration[i]){
- outputPitch[i] += commandsCounter[i] / arpeggioStepDuration[i] * arpeggioStepSize[i];
- }
- outputPitch[i] = (outputPitch[i] + NUM_PITCH) % NUM_PITCH; //wrap
- //volume
- outputVolume[i] = noteVolume[i];
- if(volumeSlideStepDuration[i]){
- outputVolume[i] += commandsCounter[i] / volumeSlideStepDuration[i] * volumeSlideStepSize[i];
- }
- if(tremoloStepDuration[i]){
- outputVolume[i] += ((commandsCounter[i]/tremoloStepDuration[i]) % 2) * tremoloStepSize[i];
- }
- outputVolume[i] = constrain(outputVolume[i], 0, 9);
- if(notePitch[i] == 63){
- outputVolume[i] = 0;
- }
- // jonnehw noInterrupts();
- _chanHalfPeriod[i] = pgm_read_byte(_halfPeriods + outputPitch[i]);
- _chanOutput[i] = _chanOutputVolume[i] = outputVolume[i] * (globalVolume>>GLOBVOL_SHIFT) * chanVolumes[i] * stepVolume[i];
- //Serial.println(outputVolume[i]);
- // jonnehw interrupts();
- }
-#endif
-}
-
-void Sound::setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod) {
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- _chanHalfPeriod[channel] = halfPeriod;
- _chanState[channel] = false;
- _chanCount[channel] = 0;
- updateOutput();
-#endif
-}
-
-
-void Sound::generateOutput() {
-#if(NUM_CHANNELS > 0)
- bool outputChanged = false;
- //no for loop here, for the performance sake (this function runs 15 000 times per second...)
- //CHANNEL 0
- if (_chanOutputVolume[0]) {
- _chanCount[0]++;
- if (_chanCount[0] >= _chanHalfPeriod[0]) {
- outputChanged = true;
- _chanState[0] = !_chanState[0];
- _chanCount[0] = 0;
- if (_chanNoise[0]) {
- _rand = 67 * _rand + 71;
- _chanOutput[0] = _rand % _chanOutputVolume[0];
- }
- }
- }
-
-
- //CHANNEL 1
- #if (NUM_CHANNELS > 1)
- if (_chanOutputVolume[1]) {
- _chanCount[1]++;
- if (_chanCount[1] >= _chanHalfPeriod[1]) {
- outputChanged = true;
- _chanState[1] = !_chanState[1];
- _chanCount[1] = 0;
- if (_chanNoise[1]) {
- _rand = 67 * _rand + 71;
- _chanOutput[1] = _rand % _chanOutputVolume[1];
- }
- }
- }
- #endif
-
- //CHANNEL 2
- #if (NUM_CHANNELS > 2)
- if (_chanOutputVolume[2]) {
- _chanCount[2]++;
- if (_chanCount[2] >= _chanHalfPeriod[2]) {
- outputChanged = true;
- _chanState[2] = !_chanState[2];
- _chanCount[2] = 0;
- if (_chanNoise[2]) {
- _rand = 67 * _rand + 71;
- _chanOutput[2] = _rand % _chanOutputVolume[2];
- }
- }
- }
- #endif
-
- //CHANNEL 3
- #if (NUM_CHANNELS > 3)
- if (_chanOutputVolume[3]) {
- _chanCount[3]++;
- if (_chanCount[3] >= _chanHalfPeriod[3]) {
- outputChanged = true;
- _chanState[3] = !_chanState[3];
- _chanCount[3] = 0;
- if (_chanNoise[3]) {
- _rand = 67 * _rand + 71;
- _chanOutput[3] = _rand % _chanOutputVolume[3];
- }
- }
- }
- #endif
-
- #if POK_STREAMING_MUSIC
- if (streamstep) {
- outputChanged=true;
- }
- #endif
-
- if (outputChanged) {
- updateOutput();
- }
-#endif
-}
-
-void Sound::updateOutput() {
-#if(NUM_CHANNELS > 0)
- uint8_t output = 0;
-
- //CHANNEL 0
- if (_chanState[0]) {
- output += _chanOutput[0];
- }
-
- //CHANNEL 1
- #if (NUM_CHANNELS > 1)
- if (_chanState[1]) {
- output += _chanOutput[1];
- }
- #endif
-
- //CHANNEL 2
- #if (NUM_CHANNELS > 2)
- if (_chanState[2]) {
- output += _chanOutput[2];
- }
- #endif
-
- //CHANNEL 3
- #if (NUM_CHANNELS > 3)
- if (_chanState[3]) {
- output += _chanOutput[3];
- }
- #endif
-
- #ifndef POK_SIM
- #if POK_ENABLE_SOUND
- /** HARDWARE **/
-
- #if POK_STREAMING_MUSIC
- if (streamstep) {
- pwmout_write(&audiopwm,(float)sbyte/(float)255);
- }
- #endif
- dac_write((uint8_t)output); //direct hardware mixing baby !
- soundbyte = output;
- #endif //POK_ENABLE_SOUND
- #else
- /** SIMULATOR **/
- #if POK_STREAMING_MUSIC
- if (streamstep) {
- uint16_t o = output + sbyte;
- output = o/2;
- }
- #endif
- soundbyte = output;
- #endif // POK_SIM
-#endif
-}
-
-void Sound::setPatternLooping(bool loop, uint8_t channel) {
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- patternLooping[channel] = loop;
-#endif
-}
-
-void Sound::playOK(){
- #if POK_GBSOUND
-#if(NUM_CHANNELS > 0)
- playPattern(playOKPattern,0);
-#endif
-#endif // POK_GBSOUND
-}
-
-void Sound::playCancel(){
-#if POK_GBSOUND
-#if(NUM_CHANNELS > 0)
- playPattern(playCancelPattern,0);
-#endif
-#endif
-}
-
-void Sound::playTick(){
-#if POK_GBSOUND
-#if(NUM_CHANNELS > 0)
- playPattern(playTickP,0);
-#endif
-#endif // POK_GBSOUND
-}
-
-void Sound::setVolume(int16_t volume) {
-//#if NUM_CHANNELS > 0
- if (volume<0) volume = 0;
- if (volume>volumeMax) volume = volumeMax;
- globalVolume = volume; // % (volumeMax+1);
- #ifndef POK_SIM
- volume = (volume / 2)-10;
- if (volume<0) volume = 0;
- #if POK_ENABLE_SOUND > 0
- setHWvolume(volume);
- #endif
- #endif
- #if POK_SHOW_VOLUME > 0
- c.volbar_visible = VOLUMEBAR_TIMEOUT;
- #endif
-//#endif
-}
-
-uint16_t Sound::getVolume() {
-//#if NUM_CHANNELS > 0
- return globalVolume;
-//#else
-// return 0;
-//#endif
-}
-
-void Sound::setVolume(int8_t volume, uint8_t channel) {
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return;
- volume = (volume > VOLUME_CHANNEL_MAX) ? VOLUME_CHANNEL_MAX : volume;
- volume = (volume < 0) ? 0 : volume;
- chanVolumes[channel] = volume;
-#endif
-}
-
-uint8_t Sound::getVolume(uint8_t channel) {
-#if(NUM_CHANNELS > 0)
- if(channel>=NUM_CHANNELS)
- return 255;
- return (chanVolumes[channel]);
-#else
- return 0;
-#endif
-}
-
-void Sound::playTone(uint8_t os, int frq, uint8_t amp, uint8_t wav,uint8_t arpmode)
-{
- if (wav>5) wav=0;
- if (arpmode>MAX_ARPMODE) arpmode=MAX_ARPMODE;
- if (os==1) setOSC(&osc1,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
- else if (os==2) setOSC(&osc2,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
- else if (os==3) setOSC(&osc3,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
-}
-
-void Sound::playTone(uint8_t os, uint16_t frq, uint8_t volume, uint32_t duration)
-{
- if (os==1) setOSC(&osc1,1,WSAW,frq,volume,duration);
- else if (os==2) setOSC(&osc2,1,WTRI,frq,volume,duration);
- else if (os==3) setOSC(&osc3,1,WTRI,frq,volume,duration);
-}
-
-uint8_t Sound::ampIsOn()
-{
- #ifdef POK_SIM
- return core.ampIsOn();
- #else
- #if POK_ENABLE_SOUND > 0
- return Pokitto::ampIsOn();
- #endif
- #endif // POK_SIM
- return 0;
-}
-
-void Sound::ampEnable(uint8_t v) {
- #ifdef POK_SIM
- core.ampEnable(v);
- #else
- #if POK_ENABLE_SOUND > 0
- Pokitto::ampEnable(v);
- #endif
- #endif // POK_SIM
-
-}
-
-int Sound::playMusicStream(char* filename)
-{
- return playMusicStream(filename,0);
-}
-
-int Sound::playMusicStream()
-{
- #if POK_STREAMING_MUSIC >0
- if (currentPtr) {
- pokPlayStream();
- return 1;
- } else return 0; //no stream
- #endif // POK_STREAMING_MUSIC
-}
-
-void Sound::pauseMusicStream() {
- #if POK_ENABLE_SOUND > 0
- pokPauseStream();
- #endif
-}
-
-int Sound::playMusicStream(char* filename, uint8_t options)
-{
- #if POK_STREAMING_MUSIC
- uint8_t result;
- result = pokInitSD();
- if (!isThisFileOpen(filename)) {
- fileClose(); // close any open files
- result = fileOpen(filename,FILE_MODE_OVERWRITE | FILE_MODE_BINARY);
- }
-
- if (result) {
- currentPtr = 0; // mark that no stream is available
- return 0; // opening music file failed
- }
-
- fileReadBytes(&buffers[0][0],BUFFER_SIZE);
- fileReadBytes(&buffers[1][0],BUFFER_SIZE);
- fileReadBytes(&buffers[2][0],BUFFER_SIZE);
- fileReadBytes(&buffers[3][0],BUFFER_SIZE);
- currentBuffer = 0;
- currentPtr = buffers[currentBuffer];
- endPtr = currentPtr + BUFFER_SIZE;
-
- //streaming = STR_PLAYING|options;
-
- if (!options) pokPlayStream(); // activate stream
- #endif //POK_STREAMING_MUSIC
- return 1; // opening music file succeeded
-}
-
--- a/POKITTO_HW/HWButtons.cpp Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/**************************************************************************/
-/*!
- @file HWButtons.cpp
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-#include "HWButtons.h"
-#include "PokittoCore.h"
-#include "PokittoSound.h"
-#include "PokittoDisplay.h"
-
-Pokitto::Sound _s;
-Pokitto::Display _bd;
-
-using namespace mbed;
-
-InterruptIn ABtn(POK_BTN_A_PIN);
-InterruptIn BBtn(POK_BTN_B_PIN);
-InterruptIn CBtn(POK_BTN_C_PIN);
-InterruptIn UBtn(POK_BTN_UP_PIN);
-InterruptIn DBtn(POK_BTN_DOWN_PIN);
-InterruptIn LBtn(POK_BTN_LEFT_PIN);
-InterruptIn RBtn(POK_BTN_RIGHT_PIN);
-
-#define BS_IDLE 0
-#define BS_DOWN 1
-#define BS_UP 2
-
-uint8_t Pokitto::heldStates[NUM_BTN];
-
-void APressed() { Pokitto::heldStates[BTN_A] = 1; }
-void AReleased() { Pokitto::heldStates[BTN_A] = 0; }
-void BPressed() { Pokitto::heldStates[BTN_B] = 1; }
-void BReleased() { Pokitto::heldStates[BTN_B] = 0; }
-void CPressed() { Pokitto::heldStates[BTN_C] = 1;}
-void CReleased() { Pokitto::heldStates[BTN_C] = 0; }
-void UPressed() { Pokitto::heldStates[BTN_UP] = 1; }
-void UReleased() { Pokitto::heldStates[BTN_UP] = 0; }
-void DPressed() { Pokitto::heldStates[BTN_DOWN] = 1; }
-void DReleased() { Pokitto::heldStates[BTN_DOWN] = 0; }
-void RPressed() {
- /* Hardware volume control */
- if (Pokitto::heldStates[BTN_C]) _s.volumeUp();
- else Pokitto::heldStates[BTN_RIGHT] = 1;
- }
-void RReleased() { Pokitto::heldStates[BTN_RIGHT] = 0; }
-void LPressed() {
- /* Hardware volume control */
- if (Pokitto::heldStates[BTN_C]) _s.volumeDown();
- else Pokitto::heldStates[BTN_LEFT] = 1;
- }
-void LReleased() { Pokitto::heldStates[BTN_LEFT] = 0; }
-
-void Pokitto::initButtons() {
- ABtn.fall(&AReleased);
- ABtn.rise(&APressed);
- BBtn.fall(&BReleased);
- BBtn.rise(&BPressed);
- CBtn.fall(&CReleased);
- CBtn.rise(&CPressed);
- UBtn.fall(&UReleased);
- UBtn.rise(&UPressed);
- DBtn.fall(&DReleased);
- DBtn.rise(&DPressed);
- LBtn.fall(&LReleased);
- LBtn.rise(&LPressed);
- RBtn.fall(&RReleased);
- RBtn.rise(&RPressed);
-}
-
-uint8_t Pokitto::Core::aBtn() {
- return Pokitto::heldStates[BTN_A];
-}
-
-uint8_t Pokitto::Core::bBtn() {
- return Pokitto::heldStates[BTN_B];
-}
-
-uint8_t Pokitto::Core::cBtn() {
- return Pokitto::heldStates[BTN_C];
-}
-
-uint8_t Pokitto::Core::upBtn() {
- return Pokitto::heldStates[BTN_UP];
-}
-uint8_t Pokitto::Core::downBtn() {
- return Pokitto::heldStates[BTN_DOWN];
-}
-
-uint8_t Pokitto::Core::leftBtn() {
- return Pokitto::heldStates[BTN_LEFT];
-}
-uint8_t Pokitto::Core::rightBtn() {
- return Pokitto::heldStates[BTN_RIGHT];
-}
-
--- a/POKITTO_HW/HWLCD.cpp Fri Dec 29 02:55:34 2017 +0000
+++ b/POKITTO_HW/HWLCD.cpp Fri Dec 29 05:17:10 2017 +0000
@@ -37,6 +37,11 @@
#include "HWLCD.h" //HWLCD.h" #include "HWLCD.h"
#include "Pokitto_settings.h"
+#ifndef DISABLEAVRMIN
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif // DISABLEAVRMIN
+
#define AB_JUMP 1024 // jump one 1-bit Arduboy screen forward to get next color bit
#define GB_JUMP 504 // jump one 1-bit Gamebuino screen forward to get next color bit
@@ -327,6 +332,7 @@
}
}
+
void Pokitto::setWindow(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
write_command(0x37); write_data(x1);
write_command(0x36); write_data(x2);
@@ -449,7 +455,11 @@
uint16_t scanline[4][176]; // read 4 half-nibbles = 4 pixels at a time
uint8_t *d, yoffset=0;
+#ifdef PROJ_USE_FPS_COUNTER
+xptr = 8;
+#else
xptr = 0;
+#endif
setDRAMptr(xptr,yoffset);
@@ -474,51 +484,367 @@
d+=220/4; // jump to read byte directly below in screenbuffer
}
- s=0;
- /** draw scanlines **/
- for (s=0;s<176;) {
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
- }
- for (s=0;s<176;) {
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
- }
- for (s=0;s<176;) {
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
- }
- for (s=0;s<176;) {
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
- setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+
+#ifdef PROJ_USE_FPS_COUNTER
+ if (x>=8 ) {
+#else
+ {
+
+#endif
+
+ /** draw scanlines **/
+ for (s=0;s<176;) {
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ }
+ for (s=0;s<176;) {
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ }
+ for (s=0;s<176;) {
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ }
+ for (s=0;s<176;) {
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ }
}
}
}
+// Copy sprite pixels to the scanline
+#define SPRITE_2BPP_INNER_LOOP(n)\
+\
+ /* If the sprite is enabled and contained in this vertical scanline, copy 4 pixels. */\
+ if (sprScanlineAddr[(n)] &&\
+ y >= sprites[(n)].y && y < sprites[(n)].y + sprites[(n)].h ) {\
+\
+ int16_t sprx = sprites[(n)].x;\
+ uint16_t s_data16b = 0; /* sprite data, 2 bytes */\
+\
+ /* Get pixel block, 4 or 8 pixels horizontally. Use the predefined bitshift mode. */\
+ /* Note:it is cheapest to compare to 0 first. */\
+ if (sprScanlineBitshiftMode[(n)] == BITSHIFT_MODE_MIDDLE_BYTE) {\
+ s_data16b = *(sprScanlineAddr[(n)]);\
+ uint16_t leftByte = *(sprScanlineAddr[(n)]-1);\
+ s_data16b = (leftByte << 8) | s_data16b;\
+ }\
+ else if (sprScanlineBitshiftMode[(n)] == BITSHIFT_MODE_FIRST_BYTE) {\
+ s_data16b = *(sprScanlineAddr[(n)]);\
+ }\
+ else { /* BITSHIFT_MODE_LAST_BYTE */\
+ uint16_t leftByte = *(sprScanlineAddr[(n)]-1);\
+ s_data16b = (leftByte << 8) | s_data16b;\
+ }\
+\
+ /* Shift sprite pixels according to sprite x. After shifting we have only 4 pixels. */\
+ uint8_t shiftRight = (sprx&0x3) << 1;\
+ s_data16b = (s_data16b >> shiftRight);\
+\
+ /* Get individual pixels */\
+ uint8_t s_t4 = s_data16b & 0x03; s_data16b >>= 2; /* lowest half-nibble */\
+ uint8_t s_t3 = s_data16b & 0x03; s_data16b >>= 2; /* second lowest half-nibble */\
+ uint8_t s_t2 = s_data16b & 0x03; s_data16b >>= 2; /* second highest half-nibble */\
+ uint8_t s_t1 = s_data16b & 0x03; /* highest half-nibble */\
+\
+ /* Store pixels as 16-bit colors from the palette */\
+ if (s_t4 != transparentColor) p4 = sprites[(n)].palette[s_t4];\
+ if (s_t3 != transparentColor) p3 = sprites[(n)].palette[s_t3];\
+ if (s_t2 != transparentColor) p2 = sprites[(n)].palette[s_t2];\
+ if (s_t1 != transparentColor) p = sprites[(n)].palette[s_t1];\
+\
+ /* Advance scanline address */\
+ sprScanlineAddr[(n)] += (sprites[(n)].w >> 2);\
+ }
+
+// Loop unrolling macros
+#define UNROLLED_LOOP_1() SPRITE_2BPP_INNER_LOOP(0)
+#define UNROLLED_LOOP_2() UNROLLED_LOOP_1() SPRITE_2BPP_INNER_LOOP(1)
+#define UNROLLED_LOOP_3() UNROLLED_LOOP_2() SPRITE_2BPP_INNER_LOOP(2)
+#define UNROLLED_LOOP_4() UNROLLED_LOOP_3() SPRITE_2BPP_INNER_LOOP(3)
+#define UNROLLED_LOOP_5() UNROLLED_LOOP_4() SPRITE_2BPP_INNER_LOOP(4)
+#define UNROLLED_LOOP_6() UNROLLED_LOOP_5() SPRITE_2BPP_INNER_LOOP(5)
+#define UNROLLED_LOOP_7() UNROLLED_LOOP_6() SPRITE_2BPP_INNER_LOOP(6)
+#define UNROLLED_LOOP_8() UNROLLED_LOOP_7() SPRITE_2BPP_INNER_LOOP(7)
+#define UNROLLED_LOOP_9() UNROLLED_LOOP_8() SPRITE_2BPP_INNER_LOOP(8)
+#define UNROLLED_LOOP_10() UNROLLED_LOOP_9() SPRITE_2BPP_INNER_LOOP(9)
+#define UNROLLED_LOOP_11() UNROLLED_LOOP_10() SPRITE_2BPP_INNER_LOOP(10)
+#define UNROLLED_LOOP_12() UNROLLED_LOOP_11() SPRITE_2BPP_INNER_LOOP(11)
+#define UNROLLED_LOOP_13() UNROLLED_LOOP_12() SPRITE_2BPP_INNER_LOOP(12)
+#define UNROLLED_LOOP_14() UNROLLED_LOOP_13() SPRITE_2BPP_INNER_LOOP(13)
+#define UNROLLED_LOOP_15() UNROLLED_LOOP_14() SPRITE_2BPP_INNER_LOOP(14)
+#define UNROLLED_LOOP_16() UNROLLED_LOOP_15() SPRITE_2BPP_INNER_LOOP(15)
+#define UNROLLED_LOOP_N_(n) UNROLLED_LOOP_##n()
+#define UNROLLED_LOOP_N(n) UNROLLED_LOOP_N_(n)
+
+/**
+Update the screen buffer of 220x176 pixels and sprites to LCD.
+
+If useDirectMode=true only sprites are updated TO LCD and the dirty rect is drawn behind the sprite current and previous
+location.
+If useDirectMode=false both the full screen buffer and sprites are updated to LCD.
+
+Limitations of sprites:
+- Sprite is enabled if sprites.bitmapData is not NULL
+- All enabled sprites must be at the beginning of the sprites array.
+*/
+void Pokitto::lcdRefreshMode1Spr(uint8_t * scrbuf, uint16_t* paletteptr, SpriteInfo* sprites, bool useDirectMode) {
+
+ // In direct mode, return now if there are no sprites
+ if (useDirectMode && (sprites == NULL || sprites[0].bitmapData == NULL))
+ return;
+
+ uint16_t x,y;
+ uint16_t scanline[4][176]; // read 4 half-nibbles (= 4 pixels) at a time
+ const uint8_t transparentColor = 0; // fixed palette index 0 for transparency
+
+ // Calculate the current amount of sprites
+ // Note: Sprites must be taken into use from index 0 upwards, because the first sprite with bitmapData==NULL is considered as the last sprite
+ uint8_t spriteCount = 0;
+ if (sprites != NULL)
+ for (;sprites[spriteCount].bitmapData != NULL && spriteCount < SPRITE_COUNT; spriteCount++);
+
+ // If drawing the screen buffer, set the start pos to LCD commands only here.
+ #ifdef PROJ_USE_FPS_COUNTER
+ if (!useDirectMode) setDRAMptr(8, 0);
+ #else
+ if (!useDirectMode) setDRAMptr(0, 0);
+ #endif
+
+ // TODO OPTIMIZE: if a sprite is totally out-of-screen, it could be marked here already. Even in this case we might
+ // need to clear the previous sprite location with screen buffer pixels.
+
+ // Go through each vertical group of 4 scanlines.
+ for (x=0; x<220; x+=4) {
+
+ uint8_t *screenBufScanlineAddr = scrbuf + (x>>2);// point to beginning of line in data
+
+ /*Prepare scanline start address for sprites that are visible in this vertical scanline. Sprite width cannot exceed the screen width*/
+ uint8_t *sprScanlineAddr[SPRITE_COUNT]; // Sprite start address for the scanline
+ uint8_t sprScanlineBitshiftMode[SPRITE_COUNT]; // Sprite bitshift mode for the scanline
+ const uint8_t BITSHIFT_MODE_MIDDLE_BYTE = 0;
+ const uint8_t BITSHIFT_MODE_FIRST_BYTE = 1;
+ const uint8_t BITSHIFT_MODE_LAST_BYTE = 2;
+ uint8_t scanlineMinY = 0; // Min y to draw for the scanline
+ uint8_t scanlineMaxY = 175; // Max y to draw for the scanline
+
+ // If not drawing the screen buffer, reset min and max to uninitialized values
+ if (useDirectMode ) {
+ scanlineMinY = 255;
+ scanlineMaxY = 0;
+ }
+ if (sprites != NULL) {
+
+ // Check all the sprites for this scanline.
+ for (int sprindex = 0; sprindex < spriteCount; sprindex++) {
+
+ int16_t sprx = sprites[sprindex].x;
+ int16_t spry = sprites[sprindex].y;
+ uint8_t sprw = sprites[sprindex].w;
+ uint8_t sprh = sprites[sprindex].h;
+ int16_t sprOldX = sprites[sprindex].oldx;
+ int16_t sprOldY = sprites[sprindex].oldy;
+
+ // Detect the dirty rect x-span by combining the previous and current sprite position.
+ int16_t sprDirtyXMin = min(sprx, sprOldX);
+ int16_t sprDirtyXMax = max(sprx, sprOldX);
+
+ // Is current x inside the sprite combined dirty rect ?
+ int16_t sprDirtyXMaxEnd = sprDirtyXMax + sprw - 1 + 4; // Add 4 pixels to dirty rect width (needed?)
+ if (sprDirtyXMin <= x+3 && x <= sprDirtyXMaxEnd) {
+
+ // If not drawing the whole screen buffer, detect the dirty rect y-span by combining the old and
+ // current sprite position, and combine all the sprites.
+ if (useDirectMode) {
+
+ // Dirty rect
+ int16_t sprDirtyYMin = min(spry, sprOldY);
+ sprDirtyYMin = max(sprDirtyYMin, 0);
+ int16_t sprDirtyYMax = max(spry, sprOldY);
+ int16_t sprDirtyYMaxEnd = sprDirtyYMax + sprh - 1;
+ sprDirtyYMaxEnd = min(sprDirtyYMaxEnd, 175);
+
+ // Get the scanline min and max y values for drawing
+ if (sprDirtyYMin < scanlineMinY)
+ scanlineMinY = sprDirtyYMin;
+ if (sprDirtyYMaxEnd > scanlineMaxY)
+ scanlineMaxY = sprDirtyYMaxEnd;
+ }
+
+ // Check if the sprite should be active for this vertical scanline group.
+ if (sprx <= x+3 && x < sprx + sprw) { // note: cover group of 4 pixels of the scanline (x+3)
+
+ // Find the byte number in the sprite data
+ int16_t byteNum = ((x+3) - sprx)>>2;
+
+ // Get the start addres of the spite data in this scanline.
+ sprScanlineAddr[sprindex] = const_cast<uint8_t*>(sprites[sprindex].bitmapData + byteNum);
+
+ // If the sprite goes over the top, it must be clipped from the top.
+ if(spry < 0)
+ sprScanlineAddr[sprindex] += (-spry) * (sprw >> 2);
+
+ // Select the bitshift mode for the blit algorithm
+ if (byteNum == 0)
+ sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_FIRST_BYTE;
+ else if (byteNum >= (sprw >> 2))
+ sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_LAST_BYTE;
+ else
+ sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_MIDDLE_BYTE;
+ }
+ else
+ sprScanlineAddr[sprindex] = NULL; // Deactive sprite for this scanline
+ }
+ else
+ sprScanlineAddr[sprindex] = NULL; // Deactive sprite for this scanline
+ }
+ }
+
+ // The height must dividable by 8. That is needed because later we copy 8 pixels at a time to the LCD.
+ if (useDirectMode && scanlineMaxY - scanlineMinY + 1 > 0) {
+ uint8_t scanlineH = scanlineMaxY - scanlineMinY + 1;
+ uint8_t addW = 8 - (scanlineH & 0x7);
+
+ // if height is not dividable by 8, make it be.
+ if (addW != 0) {
+ if (scanlineMinY > addW )
+ scanlineMinY -= addW;
+ else if( scanlineMaxY + addW < 176)
+ scanlineMaxY += addW;
+ else {
+ scanlineMinY = 0;
+ scanlineMaxY = 175;
+ }
+ }
+ }
+
+ // Find colours in this group of 4 scanlines
+ screenBufScanlineAddr += (scanlineMinY * 220/4);
+ for (y=scanlineMinY; y<=scanlineMaxY; y++)
+ {
+ // get the screen buffer data first
+ uint8_t tdata = *screenBufScanlineAddr;
+ uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble
+ uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble
+ uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble
+ uint8_t t = tdata & 0x03;// highest half-nibble
+
+ // Convert to 16-bit colors in palette
+ uint16_t p = paletteptr[t];
+ uint16_t p2 = paletteptr[t2];
+ uint16_t p3 = paletteptr[t3];
+ uint16_t p4 = paletteptr[t4];
+
+ // Add active sprite pixels
+ if (sprites != NULL) {
+
+ // Use loop unrolling for speed optimization
+ UNROLLED_LOOP_N(SPRITE_COUNT)
+ }
+
+ // put the result nibble values in the scanline
+ scanline[0][y] = p;
+ scanline[1][y] = p2;
+ scanline[2][y] = p3;
+ scanline[3][y] = p4;
+
+ screenBufScanlineAddr += 220>>2; // jump to read byte directly below in screenbuffer
+ }
+
+ // Draw scanline to LCD
+#ifdef PROJ_USE_FPS_COUNTER
+ if (x>=8 && scanlineMaxY - scanlineMinY +1 > 0) {
+#else
+ if (scanlineMaxY - scanlineMinY +1 > 0) {
+#endif
+ if (useDirectMode) setDRAMptr(x, scanlineMinY);
+ for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+ }
+
+ if (useDirectMode) setDRAMptr(x+1, scanlineMinY);
+ for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+ }
+
+ if (useDirectMode) setDRAMptr(x+2, scanlineMinY);
+ for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+ }
+
+ if (useDirectMode) setDRAMptr(x+3, scanlineMinY);
+ for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+ }
+ }
+ }
+
+ // Update old x and y for the sprites
+ if (sprites != NULL) {
+ for (int sprindex = 0; sprindex < spriteCount; sprindex++) {
+ sprites[sprindex].oldx = sprites[sprindex].x;
+ sprites[sprindex].oldy = sprites[sprindex].y;
+ }
+ }
+
+ #ifdef POK_SIM
+ simulator.refreshDisplay();
+ #endif
+}
+
void Pokitto::lcdRefreshMode2(uint8_t * scrbuf, uint16_t* paletteptr) {
uint16_t x,y;
uint16_t scanline[2][88]; // read two nibbles = pixels at a time
@@ -1206,8 +1532,80 @@
#endif
}
+
+void Pokitto::lcdRefreshMode13(uint8_t * scrbuf, uint16_t* paletteptr, uint8_t offset){
+uint16_t x,y;
+uint16_t scanline[2][110]; // read two nibbles = pixels at a time
+uint8_t *d;
+
+write_command(0x20); write_data(0);
+write_command(0x21); write_data(0);
+write_command(0x22);
+CLR_CS_SET_CD_RD_WR;
+
+for(x=0;x<110;x+=2)
+ {
+ d = scrbuf+x;// point to beginning of line in data
+ uint8_t s=0;
+ for(y=0;y<88;y++)
+ {
+ uint8_t t = *d;
+ uint8_t t1 = *(d+1);
+ scanline[0][s] = paletteptr[(t+offset)&255];
+ scanline[1][s++] = paletteptr[(t1+offset)&255];
+ d+=110; // jump to read byte directly below in screenbuffer
+ }
+ s=0;
+ for (s=0;s<88;) {
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ }
+ for (s=0;s<88;) {
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ }
+ for (s=0;s<88;) {
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ }
+ for (s=0;s<88;) {
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+ }
+ }
+
+}
+
+
+
+
void Pokitto::blitWord(uint16_t c) {
setup_data_16(c);CLR_WR;SET_WR;
}
+
--- a/POKITTO_HW/HWLCD.h Fri Dec 29 02:55:34 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/**************************************************************************/
-/*!
- @file HWLCD.h
- @author Jonne Valola
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2016, Jonne Valola
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/**************************************************************************/
-
-#ifndef __HWLCD_H__
-#define __HWLCD_H__
-
-#include "mbed.h"
-#include "gpio_api.h"
-#include "pinmap.h"
-
-#define write_command write_command_16
-#define write_data write_data_16
-
-namespace Pokitto {
-
-
-extern void initBacklight();
-extern void setBacklight(float);
-extern void lcdFillSurface(uint16_t);
-extern void lcdPixel(int16_t x, int16_t y, uint16_t c);
-extern void setWindow(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
-extern void lcdTile(int16_t x0, int16_t y0, int16_t width, int16_t height, uint16_t* gfx);
-extern void lcdRectangle(int16_t x, int16_t y,int16_t x2, int16_t y2, uint16_t color);
-extern void lcdInit();
-extern void lcdSleep();
-extern void lcdWakeUp();
-extern void lcdRefresh(uint8_t *, uint16_t*);
-extern void lcdRefreshAB(uint8_t *, uint16_t*);
-extern void lcdRefreshGB(uint8_t *, uint16_t*);
-extern void lcdRefreshRegionMode1(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t * scrbuf, uint16_t * paletteptr);
-extern void lcdRefreshMode1(uint8_t *, uint16_t*);
-extern void lcdRefreshMode2(uint8_t *, uint16_t*);
-extern void lcdRefreshMode3(uint8_t *, uint16_t*);
-extern void lcdRefreshModeGBC(uint8_t *, uint16_t*);
-/** Update LCD from 1-bit tile mode */
-extern void lcdRefreshT1(uint8_t*, uint8_t*, uint8_t*, uint16_t*);
-extern void lcdClear();
-extern void lcdFill(uint16_t);
-/** Blit one word of data*/
-extern void blitWord(uint16_t);
-
-/**************************************************************************/
-/** PINS AND PORTS **/
-/**************************************************************************/
-
-#if POK_BOARDREV == 1
-/** 2-layer board version 1.3 **/
- #define LCD_CD_PORT 0
- #define LCD_CD_PIN 2
- #define LCD_WR_PORT 1
- #define LCD_WR_PIN 23
- #define LCD_RD_PORT 1
- #define LCD_RD_PIN 24
- #define LCD_RES_PORT 1
- #define LCD_RES_PIN 28
-#else
-/** 4-layer board version 2.1 **/
- #define LCD_CD_PORT 0
- #define LCD_CD_PIN 2
- #define LCD_WR_PORT 1
- #define LCD_WR_PIN 12
- #define LCD_RD_PORT 1
- #define LCD_RD_PIN 24
- #define LCD_RES_PORT 1
- #define LCD_RES_PIN 0
-#endif
-
-/**************************************************************************/
-/** LCD CONTROL MACROS **/
-/**************************************************************************/
-
-#define CLR_RESET LPC_GPIO_PORT->CLR[LCD_RES_PORT] = 1 << LCD_RES_PIN; //RST = (0); // Clear pin
-#define SET_RESET LPC_GPIO_PORT->SET[LCD_RES_PORT] = 1 << LCD_RES_PIN; // RST = (1); // Set pin
-
-#define CLR_CD { LPC_GPIO_PORT->CLR[LCD_CD_PORT] = 1 << LCD_CD_PIN; } // RS = (0); // Clear pin
-#define SET_CD { LPC_GPIO_PORT->SET[LCD_CD_PORT] = 1 << LCD_CD_PIN; }// RS = (1); // Set pin
-
-#define CLR_WR { LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN; __asm("nop");__asm("nop");}//WR = (0); // Clear pin
-#define SET_WR LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN; //WR = (1); // Set pin
-
-#define CLR_RD LPC_GPIO_PORT->CLR[LCD_RD_PORT] = 1 << LCD_RD_PIN; //RD = (0); // Clear pin
-#define SET_RD LPC_GPIO_PORT->SET[LCD_RD_PORT] = 1 << LCD_RD_PIN; //RD = (1); // Set pin
-
-#define SET_CS //CS tied to ground
-#define CLR_CS
-
-#define CLR_CS_CD_SET_RD_WR {CLR_CD; SET_RD; SET_WR;}
-#define CLR_CS_SET_CD_RD_WR {SET_CD; SET_RD; SET_WR;}
-#define SET_CD_RD_WR {SET_CD; SET_RD; SET_WR;}
-#define SET_WR_CS SET_WR;
-
-#define SET_MASK_P2 LPC_GPIO_PORT->MASK[2] = ~(0x7FFF8); //mask P2_3 ...P2_18
-#define CLR_MASK_P2 LPC_GPIO_PORT->MASK[2] = 0; // all on
-
-
-
-/**************************************************************************/
-/** SETUP GPIO & DATA **/
-/**************************************************************************/
-
-static void setup_gpio()
-{
- /** control lines **/
- LPC_GPIO_PORT->DIR[LCD_CD_PORT] |= (1 << LCD_CD_PIN );
- LPC_GPIO_PORT->DIR[LCD_WR_PORT] |= (1 << LCD_WR_PIN );
- LPC_GPIO_PORT->DIR[LCD_RD_PORT] |= (1 << LCD_RD_PIN );
- LPC_GPIO_PORT->DIR[LCD_RES_PORT] |= (1 << LCD_RES_PIN );
- /** data lines **/
- LPC_GPIO_PORT->DIR[2] |= (0xFFFF << 3); // P2_3...P2_18 as output
-
- pin_mode(P2_3,PullNone); // turn off pull-up
- pin_mode(P2_4,PullNone); // turn off pull-up
- pin_mode(P2_5,PullNone); // turn off pull-up
- pin_mode(P2_6,PullNone); // turn off pull-up
-
- pin_mode(P2_7,PullNone); // turn off pull-up
- pin_mode(P2_8,PullNone); // turn off pull-up
- pin_mode(P2_9,PullNone); // turn off pull-up
- pin_mode(P2_10,PullNone); // turn off pull-up
-
- pin_mode(P2_11,PullNone); // turn off pull-up
- pin_mode(P2_12,PullNone); // turn off pull-up
- pin_mode(P2_13,PullNone); // turn off pull-up
- pin_mode(P2_14,PullNone); // turn off pull-up
-
- pin_mode(P2_15,PullNone); // turn off pull-up
- pin_mode(P2_16,PullNone); // turn off pull-up
- pin_mode(P2_17,PullNone); // turn off pull-up
- pin_mode(P2_18,PullNone); // turn off pull-up
-}
-
-
-
-
-#define HI_BYTE(d) (LPC_GPIO->MPIN[1]= (d<<13)) //((d>>8)<<21))
-#define LO_BYTE(d) (LPC_GPIO->MPIN[1]= (d<<21)) //because of mask makes no difference
-
-// Macros to set data bus direction to input/output
-#define LCD_GPIO2DATA_SETINPUT GPIO_GPIO2DIR &= ~LCD_DATA_MASK
-#define LCD_GPIO2DATA_SETOUTPUT GPIO_GPIO2DIR |= LCD_DATA_MASK
-
-
-// Basic Color definitions
-#define COLOR_BLACK (uint16_t)(0x0000)
-#define COLOR_BLUE (uint16_t)(0x001F)
-#define COLOR_RED (uint16_t)(0xF800)
-#define COLOR_GREEN (uint16_t)(0x07E0)
-#define COLOR_CYAN (uint16_t)(0x07FF)
-#define COLOR_MAGENTA (uint16_t)(0xF81F)
-#define COLOR_YELLOW (uint16_t)(0xFFE0)
-#define COLOR_WHITE (uint16_t)(0xFFFF)
-
-// Grayscale Values
-#define COLOR_GRAY_15 (uint16_t)(0x0861) // 15 15 15
-#define COLOR_GRAY_30 (uint16_t)(0x18E3) // 30 30 30
-#define COLOR_GRAY_50 (uint16_t)(0x3186) // 50 50 50
-#define COLOR_GRAY_80 (uint16_t)(0x528A) // 80 80 80
-#define COLOR_GRAY_128 (uint16_t)(0x8410) // 128 128 128
-#define COLOR_GRAY_200 (uint16_t)(0xCE59) // 200 200 200
-#define COLOR_GRAY_225 (uint16_t)(0xE71C) // 225 225 225
-
-
-} // namespace pokitto
-#endif // __HWLCD_H_
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/ImageFormat/BmpImage.cpp Fri Dec 29 05:17:10 2017 +0000
@@ -0,0 +1,482 @@
+/**************************************************************************/
+/*!
+ @file BmpImage.cpp
+ @author Hannu Viitala. Original BMP decoder code by Jonne Valola.
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2016, Jonne Valola
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#if POKITTO_USE_WIN_SIMULATOR
+#include "defines_win_SIM.h"
+#endif
+
+#define PROJ_MBED 1
+
+#if PROJ_LINUX || PROJ_MBED
+#include "defines_linux_SIM.h"
+#endif
+
+#include "Pokitto.h"
+#include "PokittoDisk.h"
+#ifdef POK_SIM
+#include "FileIO.h"
+#endif
+
+#if POK_ENABLE_SD > 0
+
+
+#include "PokittoDisplay.h"
+#include "ImageFormat.h"
+
+Pokitto::Core _game;
+Pokitto::Display pokdisp;
+
+int openImageFileFromSD(char* filepath, uint16_t **palette_out, uint8_t **bitmap_out) {
+
+ // Reset the out pointers.
+ *palette_out = 0;
+ *bitmap_out = 0;
+
+ BITMAPFILEHEADER bf;
+ BITMAPINFO bmi;
+
+ uint32_t bytes_read=0, bmpsize=0;
+
+ /** numcol is the number of colors for output */
+ unsigned int numcol = 0;
+
+ if (POK_COLORDEPTH == 8) numcol=256;
+ else if (POK_COLORDEPTH == 4) numcol=16;
+ else if (POK_COLORDEPTH == 2) numcol=4;
+ else if (POK_COLORDEPTH == 1) numcol=1;
+
+ if (!isThisFileOpen(filepath)) {
+ fileClose(); // close any open files
+ fileOpen(filepath, FILE_MODE_READONLY | FILE_MODE_BINARY);
+ }
+ else
+ return -1; // Already open, not good.
+
+ if (fileOK() && fileReadBytes((uint8_t*)&bf, sizeof(bf)) == sizeof(bf) ) {
+ bytes_read += sizeof(bf);
+ }
+ else
+ {
+ POK_TRACE("Error reading BMP header\n");
+ fileClose();
+ return(-1);
+ }
+
+ if (fileReadBytes((uint8_t*)&bmi,sizeof(bmi.bmiHeader)) != sizeof(bmi.bmiHeader)) {
+ POK_TRACE("Error reading BMP info\n");
+ fileClose();
+ return(-1);
+ }
+ bytes_read += sizeof(bmi.bmiHeader);
+
+ /** Check image validity */
+
+ if (bf.bfType != 0x4D42) {
+ POK_TRACE("Bitmap file has an unrecognized format (4D42 id missing from beginning).\n");
+ POK_TRACE("BMP2POK accepts .BMP files that have an indexed (1,-bit, 4-bit or 8-bit) color palette.\n");
+ fileClose();
+ return(-1);
+ }
+ if (bmi.bmiHeader.biBitCount != POK_COLORDEPTH ) {
+ POK_TRACE("ERROR!\nThe image color depth should be the same as screen color depth!\n");
+ }
+ if (bmi.bmiHeader.biWidth%32 && bmi.bmiHeader.biBitCount == 1) {
+ POK_TRACE("ERROR!\nPadding of 1-bit (monochrome) images is not yet supported\n");
+ POK_TRACE("1-bit images need to have width that is divisible by 32!\n");
+ POK_TRACE("Adjust size of source image.\n");
+ fileClose();
+ return(-1);
+ }
+ if (bmi.bmiHeader.biWidth%4) {
+ POK_TRACE("Width is not divisible by 4\n");
+ fileClose();
+ return(-1);
+ }
+ if (bmi.bmiHeader.biWidth%8 && bmi.bmiHeader.biBitCount==4) {
+ if (bmi.bmiHeader.biWidth%4) {
+ POK_TRACE("ERROR!\n4-bit source images have to have a width that is divisible by 4\n");
+ fileClose();
+ return(-1);
+ }
+ }
+ if (bmi.bmiHeader.biBitCount != 8 && bmi.bmiHeader.biBitCount != 4 && bmi.bmiHeader.biBitCount != 1)
+ {
+ POK_TRACE("Only 8bpp, 4bpp & 1bpp BMP files are supported\n");
+ fileClose();
+ return(-1);
+ }
+ if (bmi.bmiHeader.biCompression != 0 &&
+ !(bmi.bmiHeader.biCompression == BI_RLE4 && bmi.bmiHeader.biBitCount == 4))
+ {
+ POK_TRACE("Only RLE compression for bitmaps with 4 bpp is supported\n");
+ fileClose();
+ return(-1);
+ }
+
+ /* If the height is negative the bmp image is in the correct way.
+ If the heigh is positive the bmp image is vertically mirrored
+ */
+ int biAbsHeight = bmi.bmiHeader.biHeight;
+ if (bmi.bmiHeader.biHeight < 0 )
+ biAbsHeight = - bmi.bmiHeader.biHeight;
+
+ /** Read and copy palette **/
+
+ int c = bmi.bmiHeader.biClrUsed;
+ if (c==0) c = 1 << bmi.bmiHeader.biBitCount; // from MS BMP specs. 0 means 2^n colors
+ bmi.bmiHeader.biClrUsed = c;
+
+ /* Allocate memory for the output parameter */
+ if (numcol>bmi.bmiHeader.biClrUsed) numcol = bmi.bmiHeader.biClrUsed;
+ *palette_out = (uint16_t*) malloc(numcol*2);
+ if (*palette_out == NULL)
+ {
+ POK_TRACE("Error allocating temporary palette buffer.\n");
+ free(*palette_out);
+ return(-1);
+ }
+
+ /* seek to the beginning of the color table - because of gimp */
+ fileSeekAbsolute(bf.bfOffBits-c*4); //gfx data star minus color table
+
+ for (unsigned int c=0;c<numcol;c++) {
+
+ RGBQUAD rgbValue;
+ fileReadBytes((uint8_t*)&rgbValue, sizeof(RGBQUAD));
+ bytes_read += sizeof(RGBQUAD);
+
+ unsigned int r,g,b,o;
+ r = rgbValue.rgbRed >> 3; // 5 bit
+ g = rgbValue.rgbGreen >> 2; // 6 bits
+ b = rgbValue.rgbBlue >> 3; // 5 bits
+ o = (r<<11)|(g<<5)|b;
+
+ (*palette_out)[c] = o;
+ }
+
+ /** Read and copy image data **/
+
+ /* Get image data size. If the biSizeImage is given (>0) for RLE image, use that to reduce memory usage. */
+ bmpsize = bmi.bmiHeader.biWidth * biAbsHeight*bmi.bmiHeader.biBitCount/8;
+ if (bmi.bmiHeader.biCompression == BI_RLE4)
+ bmpsize = (bmi.bmiHeader.biSizeImage > 0) ? bmi.bmiHeader.biSizeImage : bmpsize;
+
+ // SEEK to the beginning of the data
+ fileSeekAbsolute(bf.bfOffBits);
+
+ /* Allocate output data buffer */
+ *bitmap_out = (uint8_t *) malloc(bmpsize + 2); // header takes 2 bytes
+ if (*bitmap_out == NULL)
+ {
+ POK_TRACE("Error allocating temporary data buffer, is image too big?\n");
+ free(*palette_out);
+ return(-1);
+ }
+
+ /* Store image size to the pokitto bitmap header */
+ uint32_t outindex = 0;
+ (*bitmap_out)[outindex++] = bmi.bmiHeader.biWidth;
+ (*bitmap_out)[outindex++] = biAbsHeight;
+
+ if (bmi.bmiHeader.biCompression == BI_RLE4) {
+ bool eofReached = false;
+ while (outindex < bmpsize && !eofReached ) {
+ /* Read byte from the file. */
+ unsigned char rleByte;
+ if (fileReadBytes(&rleByte, sizeof(rleByte)) != sizeof(rleByte))
+ {
+ /* End of file reached. Allocate a new bitmap which is of the exact size of the data */
+ eofReached = true;
+
+ /* Allocate output data buffer */
+ uint8_t* old_bitmap = *bitmap_out;
+ *bitmap_out = NULL;
+ *bitmap_out = (uint8_t *) malloc(outindex); // header takes 2 bytes
+ if (*bitmap_out == NULL)
+ {
+ POK_TRACE("Error allocating temporary data buffer, is image too big?\n");
+ free(old_bitmap);
+ free(*palette_out);
+ return(-1);
+ }
+
+ /* Copy data */
+ for (int i=0; i<outindex;i++)
+ (*bitmap_out)[i] = old_bitmap[i];
+
+ /* Free original bitmap */
+ free(old_bitmap);
+ }
+ else {
+ /* Store byte */
+ (*bitmap_out)[outindex++] = rleByte;
+ }
+ } // end while
+ }
+ else {
+ /* Do vertical mirroring only for uncompressed data.
+ Note the compressed RLE data above could not be mirrored.
+ */
+ int widthInBytes = bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount/8;
+ int widthInBytesInc, incY, startY, endY;
+ if (bmi.bmiHeader.biHeight > 0 ) {
+ /* Mirror vertically */
+ widthInBytesInc = - widthInBytes;
+ incY = -1;
+ startY = biAbsHeight - 1;
+ endY = -1;
+ }
+ else {
+ /* Do not mirror */
+ widthInBytesInc = widthInBytes;
+ incY = 1;
+ startY = 0;
+ endY = biAbsHeight;
+ }
+
+ /* Copy all bytes to the output bitmap */
+ for ( int y = startY, beginLine=startY*widthInBytes; y != endY; y += incY, beginLine += widthInBytesInc) {
+
+ /* Go to the beginning of the previous or next line */
+ outindex = beginLine;
+
+ for ( int xbyte = 0; xbyte < widthInBytes; xbyte++) {
+
+ /* Read byte from the file. */
+ unsigned char byteOfPixels;
+ if (fileReadBytes(&byteOfPixels, sizeof(byteOfPixels)) != sizeof(byteOfPixels))
+ {
+ POK_TRACE("Error reading BMP data\n");
+ fileClose();
+ free(*bitmap_out);
+ free(*palette_out);
+ return(-1);
+ }
+
+ /* Copy a byte from the file to the bitmap */
+ (*bitmap_out)[2 + outindex] = byteOfPixels;
+ outindex++;
+ } // end for
+ } // end for
+ } // end if
+
+ // Done with the file reading.
+ fileClose();
+
+ return 0;
+}
+
+int directDrawImageFileFromSD(int16_t sx, int16_t sy, char* filepath) {
+
+ return(directDrawImageFileFromSD(0, 0, 0/* full width */, 0/* full height */, sx, sy, filepath));
+}
+
+int directDrawImageFileFromSD(uint16_t ix, uint16_t iy, uint16_t iw, uint16_t ih, int16_t sx, int16_t sy, char* filepath) {
+
+ BITMAPFILEHEADER bf;
+ BITMAPINFO bmi;
+
+ uint32_t bytes_read=0;
+
+ if (!isThisFileOpen(filepath)) {
+ fileClose(); // close any open files
+ fileOpen(filepath, FILE_MODE_READONLY | FILE_MODE_BINARY);
+ }
+ else {
+ POK_TRACE("Error! Already open\n");
+ return -1; // Already open, not good.
+ }
+
+ if (fileOK() && fileReadBytes((uint8_t*)&bf, sizeof(bf)) == sizeof(bf) ) { //!HV why we have to check fileOK()?
+ bytes_read += sizeof(bf);
+ }
+ else
+ {
+ POK_TRACE("Error reading BMP header\n");
+ fileClose();
+ return(-1);
+ }
+
+ if (fileReadBytes((uint8_t*)&bmi,sizeof(bmi.bmiHeader)) != sizeof(bmi.bmiHeader)) {
+ POK_TRACE("Error reading BMP info\n");
+ fileClose();
+ return(-1);
+ }
+ bytes_read += sizeof(bmi.bmiHeader);
+
+ /** Check image validity */
+
+ if (bf.bfType != 0x4D42) {
+ POK_TRACE("Bitmap file has an unrecognized format (4D42 id missing from beginning).\n");
+ POK_TRACE("BMP2POK accepts .BMP files that have an indexed (1,-bit, 4-bit or 8-bit) color palette.\n");
+ fileClose();
+ return(-1);
+ }
+ if (bmi.bmiHeader.biBitCount != 24 ) {
+ POK_TRACE("ERROR!\nThe image color depth should be the same as screen color depth (%d)!\n");
+ fileClose();
+ return(-1);
+ }
+ if (bmi.bmiHeader.biCompression != 0 )
+ {
+ POK_TRACE("Compression is not supported.\n");
+ fileClose();
+ return(-1);
+ }
+
+ /* If the height is negative the bmp image is in the correct way.
+ If the heigh is positive the bmp image is vertically mirrored
+ */
+ int biAbsHeight = bmi.bmiHeader.biHeight;
+ if (bmi.bmiHeader.biHeight < 0 )
+ biAbsHeight = - bmi.bmiHeader.biHeight;
+
+ /** Zero size parameter means full image size */
+ if(iw==0) iw = bmi.bmiHeader.biWidth; // 0 means full image width
+ if(ih==0) ih = biAbsHeight; // 0 means full image width
+
+ /** Check parameters */
+ if( ix + iw > bmi.bmiHeader.biWidth ) {
+ POK_TRACE("Error! Invalid parameter\n");
+ fileClose();
+ return(-1);
+ }
+ if( iy + ih > biAbsHeight ) {
+ POK_TRACE("Error! Invalid parameter\n");
+ fileClose();
+ return(-1);
+ }
+ if( sx > pokdisp.getWidth()-1 || sx<-iw) {
+ POK_TRACE("Error! Invalid parameter\n");
+ fileClose();
+ return(-1);
+ }
+ if( sy > pokdisp.getHeight()-1 || sy<-ih) {
+ POK_TRACE("Error! Invalid parameter\n");
+ fileClose();
+ return(-1);
+ }
+
+ /** Zero size parameter means full image size */
+ if(iw==0) iw = bmi.bmiHeader.biWidth; // 0 means full image width
+ if(ih==0) ih = biAbsHeight; // 0 means full image width
+
+ /** Clip image to screen dimensions */
+
+ int16_t clipX1OnScreen = max( 0, sx);
+ int16_t clipX2OnScreen = min( pokdisp.getWidth()-1, sx+iw-1);
+ int16_t clipWidthOnScreen = clipX2OnScreen-clipX1OnScreen+1;
+ int16_t clipY1OnScreen = max( 0, sy);
+ int16_t clipY2OnScreen = min( pokdisp.getHeight()-1, sy+ih-1);
+ int16_t clipHeightOnScreen = clipY2OnScreen-clipY1OnScreen+1;
+
+ uint16_t skipImagePixelsAtLineStart = ix+(clipX1OnScreen-sx);
+ uint16_t skipImagePixelsAtLineStartAsBytes = skipImagePixelsAtLineStart*3; // 3 bytes per pixel
+ uint16_t skipImagePixelsAtLineEndAsBytes = (bmi.bmiHeader.biWidth-(skipImagePixelsAtLineStart+clipWidthOnScreen))*3; // 3 bytes per pixel
+
+ uint16_t skipImageRowsAtImageStart = iy+(clipY1OnScreen-sy);
+ uint16_t skipImageRowsAtImageEnd = biAbsHeight-(skipImageRowsAtImageStart+clipHeightOnScreen);
+
+ /* Vertical loop parameters */
+ int incY, startY, pastEndY;
+ uint32_t skipImageRowsAsBytes = 0;
+ if (bmi.bmiHeader.biHeight > 0 ) {
+ /* Mirror vertically */
+ incY = -1;
+ startY = clipY2OnScreen;
+ pastEndY = clipY1OnScreen-1;
+ skipImageRowsAsBytes = skipImageRowsAtImageEnd*bmi.bmiHeader.biWidth*3; // 3 bytes per pixel
+ }
+ else {
+ /* Do not mirror */
+ incY = 1;
+ startY = clipY1OnScreen ;
+ pastEndY = clipY2OnScreen+1;
+ skipImageRowsAsBytes = skipImageRowsAtImageStart*bmi.bmiHeader.biWidth*3; // 3 bytes per pixel
+ }
+
+ /** Read and copy image data directly to the screen **/
+
+ /* Seek to the beginning of the data */
+ fileSeekAbsolute(bf.bfOffBits);
+
+ /* Seek until the image rect starts */
+ if (skipImageRowsAsBytes>0) fileSeekRelative( skipImageRowsAsBytes );
+
+ /* Copy all bytes to the output bitmap */
+ for ( int y = startY; y != pastEndY; y += incY) {
+
+ /* Seek until the image rect starts */
+ if (skipImagePixelsAtLineStartAsBytes>0) fileSeekRelative( skipImagePixelsAtLineStartAsBytes );
+
+ for ( int x = clipX1OnScreen; x <= clipX2OnScreen; x++) {
+
+ /* Read RGB pixel from the file. For 24 bpp the pixel is stored to 3 bytes*/
+ uint32_t rgb24;
+ if (fileReadBytes((uint8_t*)&rgb24, 3) != 3)
+ {
+ POK_TRACE("Error reading BMP data\n");
+ fileClose();
+ return(-1);
+ }
+
+ /* Copy a pixel from the file directly to the screen */
+// uint8_t r,g,b;
+// r = (xrgb >> (3 + 16)) & 0x1f; // 5 bit
+// g = (xrgb >> (2 + 8)) & 0x3f; // 6 bits
+// b = (xrgb >> 3) & 0x1f; // 5 bits
+// uint16_t targetpixel = (r<<11) | (g<<5) | b;
+
+ uint16_t targetpixel =
+ ((rgb24 >> 8) & 0x0000F800) | // red (bits 15-11)
+ ((rgb24 >> 5) & 0x000007E0) | // green (bits 10-5)
+ ((rgb24 >> 3) & 0x0000001F); // blue (bits 4-0)
+ _game.display.directPixel(x, y, targetpixel);
+ } // end for
+
+ /* Skip pixels at line end */
+ if (skipImagePixelsAtLineEndAsBytes>0) fileSeekRelative( skipImagePixelsAtLineEndAsBytes );
+
+ } // end for
+
+ // Done with the file reading.
+ fileClose();
+
+ return 0;
+}
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/ImageFormat/ImageFormat.h Fri Dec 29 05:17:10 2017 +0000
@@ -0,0 +1,37 @@
+/**************************************************************************/
+/*!
+ @file ImageFormat.h
+ @author Hannu Viitala
+
+ @section LICENSE
+
+ Pokitto development stage library
+ Software License Agreement
+
+ Copyright (c) 2015, Jonne Valola ("Author")
+ All rights reserved.
+
+ This library is intended solely for the purpose of Pokitto development.
+
+ Redistribution and use in source and binary forms, with or without
+ modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#ifndef IMAGE_FORMAT_H
+
+#define POK_TRACE(str) printf("%s (%d): %s", __FILE__, __LINE__,str)
+
+extern int openImageFileFromSD(char*, uint16_t **, uint8_t **);
+extern int directDrawImageFileFromSD(int16_t /*sx*/, int16_t /*sy*/, char* /*filepath*/);
+extern int directDrawImageFileFromSD(uint16_t /*ix*/, uint16_t /*iy*/, uint16_t /*iw*/, uint16_t /*ih*/, int16_t /*sx*/, int16_t /*sy*/, char* /*filepath*/);
+
+#define IMAGE_FORMAT_H
+
+
+#ifndef boolean
+//typedef bool boolean;
+#endif
+
+#endif // IMAGE_FORMAT_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/ImageFormat/defines_linux_SIM.h Fri Dec 29 05:17:10 2017 +0000
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "helpers.h"
+
+#define _MAX_DRIVE 3
+#define _MAX_DIR 256
+#define _MAX_FNAME 256
+#define _MAX_EXT 256
+
+#include <ctype.h>
+
+char* _strupr( char* s )
+ {
+ char* p = s;
+ while (*p = toupper( *p )) p++;
+ return s;
+ }
+
+typedef struct tagRGBQUAD {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ uint8_t rgbReserved;
+} RGBQUAD;
+
+typedef struct tagBITMAPFILEHEADER {
+ int16_t bfType;
+ int32_t bfSize;
+ int16_t bfReserved1;
+ int16_t bfReserved2;
+ int32_t bfOffBits;
+} __attribute__((packed)) BITMAPFILEHEADER, *PBITMAPFILEHEADER;
+
+#define BI_RLE4 2
+typedef struct tagBITMAPINFOHEADER {
+ int32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ int16_t biPlanes;
+ int16_t biBitCount;
+ int32_t biCompression;
+ int32_t biSizeImage;
+ int32_t biXPelsPerMeter;
+ int32_t biYPelsPerMeter;
+ int32_t biClrUsed;
+ int32_t biClrImportant;
+} __attribute__((packed)) BITMAPINFOHEADER, *PBITMAPINFOHEADER;
+
+typedef struct tagBITMAPINFO {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[1];
+} __attribute__((packed)) BITMAPINFO, *PBITMAPINFO;
+
+RGBQUAD myColors[257];
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/POKITTO_LIBS/ImageFormat/defines_win_SIM.h Fri Dec 29 05:17:10 2017 +0000 @@ -0,0 +1,7 @@ +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "windows.h" +#include <stdint.h> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/POKITTO_LIBS/ImageFormat/helpers.h Fri Dec 29 05:17:10 2017 +0000 @@ -0,0 +1,10 @@ +#ifndef HELPERS_H +#define HELPERS_H + +extern void add_underscores(char *); +extern void print_usage(char *); + + +#endif // HELPERS_H + +
--- a/Pokitto_settings.h Fri Dec 29 02:55:34 2017 +0000 +++ b/Pokitto_settings.h Fri Dec 29 05:17:10 2017 +0000 @@ -382,5 +382,9 @@ /** LOADER UPDATE MECHANISM **/ #define POK_ENABLE_LOADER_UPDATES 1 //1=check for new loader versions on SD and update if new found +#ifndef SPRITE_COUNT +#define SPRITE_COUNT 4 // The default max sprite count +#endif + #endif // POKITTO_SETTINGS_H