mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-09 05:49:19 +00:00
refactoring
This commit is contained in:
parent
0f4e4be73c
commit
0a2fb1aeee
4
Makefile
4
Makefile
@ -8,9 +8,9 @@ CXXFLAGS=-Wall -I/usr/include/SDL2 -I .. -I . -I apple -I nix -I sdl -I/usr/loca
|
||||
|
||||
TSRC=cpu.cpp util/testharness.cpp
|
||||
|
||||
COMMONSRCS=cpu.cpp apple/appledisplay.cpp apple/applekeyboard.cpp apple/applemmu.cpp apple/applevm.cpp apple/diskii.cpp apple/nibutil.cpp LRingBuffer.cpp globals.cpp apple/parallelcard.cpp apple/fx80.cpp lcg.cpp apple/hd32.cpp images.cpp apple/appleui.cpp vmram.cpp bios.cpp apple/noslotclock.cpp apple/woz.cpp apple/crc32.c apple/woz-serializer.cpp apple/mouse.c
|
||||
COMMONSRCS=cpu.cpp apple/appledisplay.cpp apple/applekeyboard.cpp apple/applemmu.cpp apple/applevm.cpp apple/diskii.cpp apple/nibutil.cpp LRingBuffer.cpp globals.cpp apple/parallelcard.cpp apple/fx80.cpp lcg.cpp apple/hd32.cpp images.cpp apple/appleui.cpp vmram.cpp bios.cpp apple/noslotclock.cpp apple/woz.cpp apple/crc32.c apple/woz-serializer.cpp apple/mouse.c physicaldisplay.cpp
|
||||
|
||||
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o LRingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o images.o apple/appleui.o vmram.o bios.o apple/noslotclock.o apple/woz.o apple/crc32.o apple/woz-serializer.o apple/mouse.o
|
||||
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o LRingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o images.o apple/appleui.o vmram.o bios.o apple/noslotclock.o apple/woz.o apple/crc32.o apple/woz-serializer.o apple/mouse.o physicaldisplay.o
|
||||
|
||||
FBSRCS=linuxfb/linux-speaker.cpp linuxfb/fb-display.cpp linuxfb/linux-keyboard.cpp linuxfb/fb-paddles.cpp nix/nix-filemanager.cpp linuxfb/aiie.cpp linuxfb/linux-printer.cpp nix/nix-clock.cpp nix/nix-prefs.cpp
|
||||
|
||||
|
@ -42,8 +42,6 @@
|
||||
|
||||
#define drawApplePixel(c,x,y) { g_display->cacheDoubleWidePixel(x,y,c); }
|
||||
|
||||
#define draw2Pixels(cA, cB, x, y) { g_display->cache2DoubleWidePixels(x,y,cA, cB); }
|
||||
|
||||
#define DrawLoresPixelAt(c, x, y) { \
|
||||
uint8_t pixel = c & 0x0F; \
|
||||
for (uint8_t y2 = 0; y2<4; y2++) { \
|
||||
|
@ -101,7 +101,7 @@ void AppleUI::drawBatteryStatus(uint8_t percent)
|
||||
b = (float)b * alpha + (bgb * (1.0 - alpha));
|
||||
|
||||
uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
|
||||
g_display->drawUIPixel(x+xoff, y+yoff, color16);
|
||||
g_display->drawPixel(x+xoff, y+yoff, color16);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,9 +126,9 @@ void AppleUI::blit()
|
||||
// FIXME make these bitmaps so the size/location are abstracted
|
||||
for (int y=0; y<LED_HEIGHT; y++) {
|
||||
for (int x=0; x<LED_WIDTH; x++) {
|
||||
g_display->drawUIPixel(x + LED_X, y + LED1_Y, driveActivity[0] ? 0xFA00 : 0x0000);
|
||||
g_display->drawPixel(x + LED_X, y + LED1_Y, driveActivity[0] ? 0xFA00 : 0x0000);
|
||||
|
||||
g_display->drawUIPixel(x + LED_X, y + LED2_Y, driveActivity[1] ? 0xFA00 : 0x0000);
|
||||
g_display->drawPixel(x + LED_X, y + LED2_Y, driveActivity[1] ? 0xFA00 : 0x0000);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
34
bios.cpp
34
bios.cpp
@ -137,12 +137,12 @@ void BIOS::DrawMenuBar()
|
||||
|
||||
for (int i=0; i<NUM_TITLES; i++) {
|
||||
for (int x=0; x<titleWidths[i] + 2*XPADDING; x++) {
|
||||
g_display->drawUIPixel(xpos+x, 0, 0xFFFF);
|
||||
g_display->drawUIPixel(xpos+x, LINEHEIGHT, 0xFFFF);
|
||||
g_display->drawPixel(xpos+x, 0, 0xFFFF);
|
||||
g_display->drawPixel(xpos+x, LINEHEIGHT, 0xFFFF);
|
||||
}
|
||||
for (int y=0; y<=LINEHEIGHT; y++) {
|
||||
g_display->drawUIPixel(xpos, y, 0xFFFF);
|
||||
g_display->drawUIPixel(xpos + titleWidths[i] + 2*XPADDING, y, 0xFFFF);
|
||||
g_display->drawPixel(xpos, y, 0xFFFF);
|
||||
g_display->drawPixel(xpos + titleWidths[i] + 2*XPADDING, y, 0xFFFF);
|
||||
}
|
||||
|
||||
xpos += XPADDING;
|
||||
@ -551,7 +551,7 @@ uint16_t BIOS::AboutScreenHandler(bool needsRedraw, bool performAction)
|
||||
// Draw a black area where we're going to "boot" a fake //e for the about screen. Don't put the whole graphic around it so it's obvious it's not a //e.
|
||||
for (uint8_t y=12; y<12+192; y++) {
|
||||
for (uint16_t x=20; x<280+20; x++) {
|
||||
g_display->drawUIPixel( x, y, 0x0000 );
|
||||
g_display->drawPixel( x, y, 0x0000 );
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -682,26 +682,26 @@ uint16_t BIOS::PaddlesScreenHandler(bool needsRedraw, bool performAction)
|
||||
// Draw the target for the paddle position
|
||||
for (uint16_t y=10; y<=110; y++) {
|
||||
for (uint16_t x=160; x<=260; x++) {
|
||||
g_display->drawUIPixel(x, y, 0x0000);
|
||||
g_display->drawUIPixel(x, 10, 0xFFFF);
|
||||
g_display->drawUIPixel(x, 110, 0xFFFF);
|
||||
g_display->drawPixel(x, y, 0x0000);
|
||||
g_display->drawPixel(x, 10, 0xFFFF);
|
||||
g_display->drawPixel(x, 110, 0xFFFF);
|
||||
}
|
||||
g_display->drawUIPixel(160, y, 0xFFFF);
|
||||
g_display->drawUIPixel(260, y, 0xFFFF);
|
||||
g_display->drawPixel(160, y, 0xFFFF);
|
||||
g_display->drawPixel(260, y, 0xFFFF);
|
||||
}
|
||||
|
||||
for (uint16_t y=57; y<=63; y++) {
|
||||
g_display->drawUIPixel(207,y,0xFFFF);
|
||||
g_display->drawUIPixel(213,y,0xFFFF);
|
||||
g_display->drawPixel(207,y,0xFFFF);
|
||||
g_display->drawPixel(213,y,0xFFFF);
|
||||
}
|
||||
for (uint16_t x=207; x<=213; x++) {
|
||||
g_display->drawUIPixel(x,57,0xFFFF);
|
||||
g_display->drawUIPixel(x,63,0xFFFF);
|
||||
g_display->drawPixel(x,57,0xFFFF);
|
||||
g_display->drawPixel(x,63,0xFFFF);
|
||||
}
|
||||
|
||||
float drawX = ((float)lastPaddleX/255.0)*100.0;
|
||||
float drawY = ((float)lastPaddleY/255.0)*100.0;
|
||||
g_display->drawUIPixel(160+drawX, 10+drawY, 0xFFFF);
|
||||
g_display->drawPixel(160+drawX, 10+drawY, 0xFFFF);
|
||||
|
||||
g_display->flush();
|
||||
|
||||
@ -1050,7 +1050,7 @@ void BIOS::DrawHardwareMenu()
|
||||
uint16_t volCutoff = 300.0 * (float)((float) g_volume / 15.0);
|
||||
for (uint8_t y=234; y<=235; y++) {
|
||||
for (uint16_t x = 0; x< 300; x++) {
|
||||
g_display->drawUIPixel( x, y, x <= volCutoff ? 0xFFFF : 0x0010 );
|
||||
g_display->drawPixel( x, y, x <= volCutoff ? 0xFFFF : 0x0010 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1159,7 +1159,7 @@ uint16_t BIOS::DrawDiskNames(uint8_t page, int8_t selection, const char *filter)
|
||||
g_display->drawString(M_NORMAL, 0, 0, title);
|
||||
|
||||
for (int x=0; x<strlen(title)*8; x++) {
|
||||
g_display->drawUIPixel(x, LINEHEIGHT-1, 0xFFFF);
|
||||
g_display->drawPixel(x, LINEHEIGHT-1, 0xFFFF);
|
||||
}
|
||||
|
||||
uint8_t vpos = FILEMENUSTARTAT;
|
||||
|
96
physicaldisplay.cpp
Normal file
96
physicaldisplay.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "physicaldisplay.h"
|
||||
#include "globals.h"
|
||||
#include "applevm.h"
|
||||
#include "appleui.h"
|
||||
|
||||
#include "font.h"
|
||||
|
||||
const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
|
||||
0xC006, // 1 magenta
|
||||
0x0010, // 2 dark blue
|
||||
0xA1B5, // 3 purple
|
||||
0x0480, // 4 dark green
|
||||
0x6B4D, // 5 dark grey
|
||||
0x1B9F, // 6 med blue
|
||||
0x0DFD, // 7 light blue
|
||||
0x92A5, // 8 brown
|
||||
0xF8C5, // 9 orange
|
||||
0x9555, // 10 light gray
|
||||
0xFCF2, // 11 pink
|
||||
0x07E0, // 12 green
|
||||
0xFFE0, // 13 yellow
|
||||
0x87F0, // 14 aqua
|
||||
0xFFFF // 15 white
|
||||
};
|
||||
|
||||
void PhysicalDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
|
||||
{
|
||||
int8_t xsize = 8,
|
||||
ysize = 0x07;
|
||||
|
||||
uint16_t offPixel, onPixel;
|
||||
switch (mode) {
|
||||
case M_NORMAL:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0010;
|
||||
break;
|
||||
case M_SELECTED:
|
||||
onPixel = 0x0000;
|
||||
offPixel = 0xFFFF;
|
||||
break;
|
||||
case M_DISABLED:
|
||||
default:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
case M_SELECTDISABLED:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0xFFE0;
|
||||
break;
|
||||
case M_PLAIN:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
}
|
||||
|
||||
const unsigned char *ch = asciiToAppleGlyph(c);
|
||||
for (int8_t y_off = 0; y_off <= ysize; y_off++) {
|
||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||
if (*ch & (1 << (x_off))) {
|
||||
drawPixel(x+x_off, y+y_off, onPixel);
|
||||
} else {
|
||||
drawPixel(x+x_off, y+y_off, onPixel);
|
||||
}
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str)
|
||||
{
|
||||
int8_t xsize = 8; // width of a char in this font
|
||||
|
||||
for (int8_t i=0; i<strlen(str); i++) {
|
||||
drawCharacter(mode, x, y, str[i]);
|
||||
x += xsize;
|
||||
if (x >= (320-xsize)/2) break; // FIXME this is a
|
||||
// pre-scaled number, b/c
|
||||
// drawCharacter is
|
||||
// scaling. Klutzy. It's
|
||||
// also using the ILI
|
||||
// constant; what about
|
||||
// the RA8875?
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalDisplay::redraw()
|
||||
{
|
||||
if (g_ui) {
|
||||
g_ui->drawStaticUIElement(UIeOverlay);
|
||||
|
||||
if (g_vm) {
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
}
|
||||
}
|
||||
}
|
@ -10,31 +10,27 @@ class PhysicalDisplay {
|
||||
PhysicalDisplay() { overlayMessage[0] = '\0'; }
|
||||
virtual ~PhysicalDisplay() {};
|
||||
|
||||
virtual void flush() = 0; // flush any pending drawings
|
||||
virtual void redraw() = 0; // total redraw, assuming nothing
|
||||
virtual void redraw(); // total redraw, assuming nothing
|
||||
virtual void blit() = 0; // blit everything to the display (including UI area)
|
||||
virtual void blit(AiieRect r) = 0; // blit a piece of the VM area to the display
|
||||
virtual void flush() = 0;
|
||||
|
||||
virtual void drawUIImage(uint8_t imageIdx) = 0;
|
||||
// FIXME: drawImageOfSizeAt should probably be private now
|
||||
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint16_t sizey, uint16_t wherex, uint16_t wherey) = 0;
|
||||
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c) = 0;
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str) = 0;
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c);
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str);
|
||||
virtual void debugMsg(const char *msg) { strncpy(overlayMessage, msg, sizeof(overlayMessage));overlayMessage[strlen(overlayMessage)] = 0; }
|
||||
|
||||
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color) = 0;
|
||||
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b) = 0;
|
||||
|
||||
virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color) = 0;
|
||||
|
||||
virtual void clrScr(uint8_t coloridx) = 0;
|
||||
|
||||
// methods to draw in to the buffer - not directly to the screen.
|
||||
|
||||
// First, methods that expect *us* to pixel-double the width...
|
||||
virtual void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color) = 0;
|
||||
virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB) = 0;
|
||||
|
||||
// Then the direct-pixel methods
|
||||
virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color) = 0;
|
||||
|
@ -227,9 +227,8 @@ struct timespec runDisplay(struct timespec now)
|
||||
g_ui->blit();
|
||||
g_vm->vmdisplay->lockDisplay();
|
||||
if (g_vm->vmdisplay->needsRedraw()) {
|
||||
AiieRect what = g_vm->vmdisplay->getDirtyRect();
|
||||
g_vm->vmdisplay->didRedraw();
|
||||
g_display->blit(what);
|
||||
g_display->blit();
|
||||
}
|
||||
g_vm->vmdisplay->unlockDisplay();
|
||||
|
||||
|
@ -7,13 +7,6 @@
|
||||
#include "applevm.h"
|
||||
|
||||
#include "apple/appleui.h"
|
||||
// FIXME should be able to omit this include and rely on the xterns, which
|
||||
// would prove it's linking properly
|
||||
#include "apple/font.h"
|
||||
extern const unsigned char ucase_glyphs[512];
|
||||
extern const unsigned char lcase_glyphs[256];
|
||||
extern const unsigned char mousetext_glyphs[256];
|
||||
extern const unsigned char interface_glyphs[256];
|
||||
|
||||
#include "images.h"
|
||||
|
||||
@ -94,19 +87,6 @@ void SDLDisplay::flush()
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
void SDLDisplay::redraw()
|
||||
{
|
||||
// primarily for the device, where it's in and out of the
|
||||
// bios. Draws the background image.
|
||||
g_ui->drawStaticUIElement(UIeOverlay);
|
||||
|
||||
if (g_vm && g_ui) {
|
||||
// determine whether or not a disk is inserted & redraw each drive
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::drawUIImage(uint8_t imageIdx)
|
||||
{
|
||||
switch (imageIdx) {
|
||||
@ -163,34 +143,16 @@ void SDLDisplay::blit()
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
// Blit the videoBuffer to the display device, in the rect given
|
||||
void SDLDisplay::blit(AiieRect r)
|
||||
{
|
||||
blit();
|
||||
/*
|
||||
if (overlayMessage[0]) {
|
||||
drawString(M_SELECTDISABLED, 1, 240 - 16 - 12, overlayMessage);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
*/
|
||||
}
|
||||
|
||||
inline void putpixel(SDL_Renderer *renderer, int x, int y, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, 255);
|
||||
SDL_RenderDrawPoint(renderer, x, y);
|
||||
}
|
||||
|
||||
void SDLDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
if (x >= SDL_WIDTH || y >= SDL_HEIGHT) return; // make sure it's onscreen
|
||||
|
||||
videoBuffer[y][x] = color16To32(color);
|
||||
}
|
||||
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
uint8_t
|
||||
r = (color & 0xF800) >> 8,
|
||||
g = (color & 0x7E0) >> 3,
|
||||
@ -204,69 +166,9 @@ void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
putpixel(renderer, x, (y*2)+yoff, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
|
||||
{
|
||||
int8_t xsize = 8,
|
||||
ysize = 0x07;
|
||||
|
||||
uint16_t offPixel, onPixel;
|
||||
switch (mode) {
|
||||
case M_NORMAL:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0010;
|
||||
break;
|
||||
case M_SELECTED:
|
||||
onPixel = 0x0000;
|
||||
offPixel = 0xFFFF;
|
||||
break;
|
||||
case M_DISABLED:
|
||||
default:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
case M_SELECTDISABLED:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0xFFE0;
|
||||
break;
|
||||
case M_PLAIN:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
}
|
||||
|
||||
// scale up the font
|
||||
const unsigned char *ch = asciiToAppleGlyph(c);
|
||||
for (int8_t y_off = 0; y_off <= ysize; y_off++) {
|
||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||
if (*ch & (1 << (x_off))) {
|
||||
for (int8_t ys=0; ys<2; ys++) {
|
||||
for (int8_t xs=0; xs<2; xs++) {
|
||||
drawUIPixel((x + x_off)*2+xs, (y+y_off)*2 + ys, onPixel);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int8_t ys=0; ys<2; ys++) {
|
||||
for (int8_t xs=0; xs<2; xs++) {
|
||||
drawUIPixel((x + x_off)*2+xs, (y+y_off)*2 + ys, offPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x < SDL_WIDTH && y < SDL_HEIGHT) {
|
||||
putpixel(renderer, x, (y*2)+yoff, r, g, b);
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str)
|
||||
{
|
||||
int8_t xsize = 8; // width of a char in this font
|
||||
|
||||
for (int8_t i=0; i<strlen(str); i++) {
|
||||
drawCharacter(mode, x, y, str[i]);
|
||||
x += xsize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,16 +213,6 @@ void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedCol
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorB, uint8_t colorA)
|
||||
{
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x*2)+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[colorA]);
|
||||
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x+1)*2+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[colorB]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::windowResized(uint32_t w, uint32_t h)
|
||||
{
|
||||
// Preserve the aspect ratio
|
||||
|
@ -17,8 +17,6 @@ class SDLDisplay : public PhysicalDisplay {
|
||||
virtual ~SDLDisplay();
|
||||
|
||||
virtual void blit();
|
||||
virtual void blit(AiieRect r);
|
||||
virtual void redraw();
|
||||
|
||||
virtual void flush();
|
||||
|
||||
@ -28,16 +26,11 @@ class SDLDisplay : public PhysicalDisplay {
|
||||
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c);
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str);
|
||||
virtual void clrScr(uint8_t coloridx);
|
||||
|
||||
virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color);
|
||||
virtual void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color);
|
||||
void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedColor);
|
||||
virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB);
|
||||
|
||||
void windowResized(uint32_t w, uint32_t h);
|
||||
|
||||
|
@ -1,8 +1,15 @@
|
||||
#include "ILI9341_wrap.h"
|
||||
|
||||
#include "images.h"
|
||||
#include "globals.h"
|
||||
#include "appledisplay.h"
|
||||
|
||||
#define _332To565(c) ((((c) & 0xe0) << 8) | (((c) & 0x1c) << 6) | ((c) & 0x03))
|
||||
|
||||
ILI9341_Wrap::ILI9341_Wrap(const uint8_t cs_pin, const uint8_t rst_pin, const uint8_t mosi_pin, const uint8_t sck_pin, const uint8_t miso_pin, const uint8_t dc_pin) : BaseDisplay(cs_pin, rst_pin, mosi_pin, sck_pin, miso_pin, dc_pin)
|
||||
{
|
||||
tft = NULL;
|
||||
frame_buffer = NULL;
|
||||
|
||||
_cs = cs_pin;
|
||||
_dc = dc_pin;
|
||||
@ -33,27 +40,68 @@ void ILI9341_Wrap::fillWindow(uint16_t color = 0x0000)
|
||||
|
||||
void ILI9341_Wrap::setFrameBuffer(uint8_t *frame_buffer)
|
||||
{
|
||||
tft->setFrameBuffer((uint16_t *)frame_buffer);
|
||||
tft->useFrameBuffer(true);
|
||||
tft->fillScreen(ILI9341_BLACK);
|
||||
if (tft) {
|
||||
tft->fillScreen(ILI9341_BLACK);
|
||||
this->frame_buffer = (uint16_t *)frame_buffer;
|
||||
tft->setFrameBuffer((uint16_t *)frame_buffer);
|
||||
tft->useFrameBuffer(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool ILI9341_Wrap::asyncUpdateActive()
|
||||
{
|
||||
return tft->asyncUpdateActive();
|
||||
return tft ? tft->asyncUpdateActive() : false;
|
||||
}
|
||||
|
||||
bool ILI9341_Wrap::updateScreenAsync(bool update_cont)
|
||||
{
|
||||
return tft->updateScreenAsync(update_cont);
|
||||
return tft ? tft->updateScreenAsync(update_cont) : false;
|
||||
}
|
||||
|
||||
void ILI9341_Wrap::drawPixel(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
tft->drawPixel(x, y, color);
|
||||
frame_buffer[y*ILI9341_WIDTH+x] = color;
|
||||
}
|
||||
|
||||
void ILI9341_Wrap::drawPixel(int16_t x, int16_t y, uint8_t color)
|
||||
{
|
||||
frame_buffer[y*ILI9341_WIDTH+x] = _332To565(color);
|
||||
}
|
||||
|
||||
// The 9341 is half the width we need, so this jumps through hoops to
|
||||
// reduce the resolution in a way that's reasonable by blending pixels
|
||||
void ILI9341_Wrap::cacheApplePixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
if (x&1) {
|
||||
uint16_t origColor =frame_buffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH+(x>>1)+SCREENINSET_9341_X];
|
||||
if (g_displayType == m_blackAndWhite) {
|
||||
// There are four reasonable decisions here: if either pixel
|
||||
// *was* on, then it's on; if both pixels *were* on, then it's
|
||||
// on; and if the blended value of the two pixels were on,
|
||||
// then it's on; or if the blended value of the two is above
|
||||
// some certain overall brightness, then it's on. This is the
|
||||
// last of those - where the brightness cutoff is defined in
|
||||
// the bios as g_luminanceCutoff.
|
||||
uint16_t blendedColor = blendColors(origColor, color);
|
||||
uint16_t luminance = luminanceFromRGB(_565toR(blendedColor),
|
||||
_565toG(blendedColor),
|
||||
_565toB(blendedColor));
|
||||
cacheDoubleWideApplePixel(x>>1,y,(uint16_t)((luminance >= g_luminanceCutoff) ? 0xFFFF : 0x0000));
|
||||
} else {
|
||||
cacheDoubleWideApplePixel(x>>1, y, color);
|
||||
}
|
||||
} else {
|
||||
// All of the even pixels get drawn...
|
||||
cacheDoubleWideApplePixel(x>>1, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341_Wrap::cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16)
|
||||
{
|
||||
frame_buffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = color16;
|
||||
}
|
||||
|
||||
uint32_t ILI9341_Wrap::frameCount()
|
||||
{
|
||||
return tft->frameCount();
|
||||
return tft ? tft->frameCount() : 0;
|
||||
}
|
||||
|
@ -27,11 +27,17 @@ class ILI9341_Wrap : public BaseDisplay {
|
||||
virtual bool updateScreenAsync(bool update_cont = false);
|
||||
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint8_t color);
|
||||
|
||||
virtual void cacheApplePixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
virtual void ILI9341_Wrap::cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16);
|
||||
|
||||
virtual uint32_t frameCount();
|
||||
|
||||
private:
|
||||
ILI9341_t3n *tft;
|
||||
uint8_t _cs, _dc, _rst, _mosi, _sck, _miso;
|
||||
uint16_t *frame_buffer;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "RA8875_t4.h"
|
||||
#include "RA8875_registers.h"
|
||||
|
||||
#include "images.h"
|
||||
|
||||
// Discussion about DMA channels: http://forum.pjrc.com/threads/25778-Could-there-be-something-like-an-ISR-template-function/page3
|
||||
// Thread discussing the way to get started: https://forum.pjrc.com/threads/63353-Teensy-4-1-How-to-start-using-DMA
|
||||
// Thread of someone writing an LCD interface: https://forum.pjrc.com/threads/67247-Teensy-4-0-DMA-SPI
|
||||
@ -401,6 +403,31 @@ void RA8875_t4::drawPixel(int16_t x, int16_t y, uint16_t color)
|
||||
_pfbtft[y*RA8875_WIDTH+x] = _color16To8bpp(color);
|
||||
}
|
||||
|
||||
void RA8875_t4::drawPixel(int16_t x, int16_t y, uint8_t color)
|
||||
{
|
||||
// FIXME: bounds checking
|
||||
_pfbtft[y*RA8875_WIDTH+x] = color;
|
||||
}
|
||||
|
||||
void RA8875_t4::cacheApplePixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
// The 8875 display doubles vertically
|
||||
uint c8 = _565To332(color);
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
_pfbtft[((y*2)+SCREENINSET_8875_Y+yoff) * RA8875_WIDTH +x+SCREENINSET_8875_X] = c8;
|
||||
}
|
||||
}
|
||||
|
||||
void RA8875_t4::cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16)
|
||||
{
|
||||
// The RA8875 doubles Apple's pixels.
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
_pfbtft[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(color16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RA8875_t4::frameCount()
|
||||
{
|
||||
return _dma_frame_count;
|
||||
|
@ -37,6 +37,11 @@ class RA8875_t4 : public BaseDisplay {
|
||||
virtual bool updateScreenAsync(bool update_cont = false);
|
||||
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint8_t color);
|
||||
|
||||
virtual void cacheApplePixel(uint16_t x, uint16_t y, uint16_t color16);
|
||||
virtual void cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16);
|
||||
|
||||
virtual uint32_t frameCount();
|
||||
|
||||
uint8_t color16To8bpp(uint16_t color) __attribute__((always_inline)) {
|
||||
|
42
teensy/basedisplay.h
Normal file
42
teensy/basedisplay.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef __BASE_DISPLAY_H
|
||||
#define __BASE_DISPLAY_H
|
||||
|
||||
const uint16_t loresPixelColors[16];
|
||||
|
||||
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
||||
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
|
||||
#define _565toG(c) ( ((c) & 0x07E0) >> 3 )
|
||||
#define _565toB(c) ( ((c) & 0x001F) << 3 )
|
||||
#define RGBto332(r,g,b) ((((r) & 0xE0)) | (((g) & 0xE0) >> 3) | ((b) >> 6))
|
||||
#define luminanceFromRGB(r,g,b) ( ((r)*0.2126) + ((g)*0.7152) + ((b)*0.0722) )
|
||||
#define _565To332(c) ((((c) & 0xe000) >> 8) | (((c) & 0x700) >> 6) | (((c) & 0x18) >> 3))
|
||||
#define _332To565(c) ((((c) & 0xe0) << 8) | (((c) & 0x1c) << 6) | ((c) & 0x03))
|
||||
|
||||
#define blendColors(a,b) RGBto565( (_565toR(a) + _565toR(b))/2, (_565toG(a) + _565toG(b))/2, (_565toB(a) + _565toB(b))/2 )
|
||||
|
||||
class BaseDisplay {
|
||||
public:
|
||||
BaseDisplay(uint8_t cs_pin, uint8_t rst_pin, uint8_t mosi_pin, uint8_t sck_pin, uint8_t miso_pin, uint8_t dc_pin=255) {};
|
||||
|
||||
~BaseDisplay() {};
|
||||
|
||||
virtual void begin(uint32_t spi_clock=30000000u, uint32_t spi_clock_read=2000000) = 0;
|
||||
|
||||
virtual void fillWindow(uint16_t color = 0x0000) = 0;
|
||||
|
||||
virtual void setFrameBuffer(uint8_t *frame_buffer) = 0;
|
||||
|
||||
virtual bool asyncUpdateActive();
|
||||
virtual bool updateScreenAsync(bool update_cont = false) = 0;
|
||||
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint8_t color) = 0;
|
||||
|
||||
// Apple interface methods
|
||||
virtual void cacheApplePixel(uint16_t x, uint16_t y, uint16_t color) = 0;
|
||||
virtual void cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16) = 0;
|
||||
|
||||
virtual uint32_t frameCount() = 0;
|
||||
};
|
||||
|
||||
#endif
|
1
teensy/physicaldisplay.cpp
Symbolic link
1
teensy/physicaldisplay.cpp
Symbolic link
@ -0,0 +1 @@
|
||||
../physicaldisplay.cpp
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* https://forum.pjrc.com/threads/186-Teensy-3-fault-handler-demonstration?highlight=crash+handler
|
||||
*
|
||||
* call this from setup():
|
||||
* enableFaultHandler();
|
||||
*
|
||||
* On crash you see something like:
|
||||
* !!!! Crashed at pc=0x490, lr=0x55B.
|
||||
*
|
||||
* which you can interpret thusly:
|
||||
* $ arm-none-eabi-addr2line -s -f -C -e main.elf 0x490 0x55B
|
||||
* Print:: println(char const*)
|
||||
* Print.h:47
|
||||
* main
|
||||
* main_crash.cpp:86
|
||||
*/
|
||||
|
||||
#define SCB_SHCSR_USGFAULTENA (uint32_t)1<<18
|
||||
#define SCB_SHCSR_BUSFAULTENA (uint32_t)1<<17
|
||||
#define SCB_SHCSR_MEMFAULTENA (uint32_t)1<<16
|
||||
|
||||
#define SCB_SHPR1_USGFAULTPRI *(volatile uint8_t *)0xE000ED20
|
||||
#define SCB_SHPR1_BUSFAULTPRI *(volatile uint8_t *)0xE000ED19
|
||||
#define SCB_SHPR1_MEMFAULTPRI *(volatile uint8_t *)0xE000ED18
|
||||
|
||||
// enable bus, usage, and mem fault handlers.
|
||||
void enableFaultHandler()
|
||||
{
|
||||
SCB_SHCSR |= SCB_SHCSR_BUSFAULTENA | SCB_SHCSR_USGFAULTENA | SCB_SHCSR_MEMFAULTENA;
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
void __attribute__((naked)) _fault_isr () {
|
||||
uint32_t* sp=0;
|
||||
// this is from "Definitive Guide to the Cortex M3" pg 423
|
||||
asm volatile ( "TST LR, #0x4\n\t" // Test EXC_RETURN number in LR bit 2
|
||||
"ITE EQ\n\t" // if zero (equal) then
|
||||
"MRSEQ %0, MSP\n\t" // Main Stack was used, put MSP in sp
|
||||
"MRSNE %0, PSP\n\t" // else Process stack was used, put PSP in sp
|
||||
: "=r" (sp) : : "cc");
|
||||
|
||||
Serial.print("!!!! Crashed at pc=0x");
|
||||
Serial.print(sp[6], 16);
|
||||
Serial.print(", lr=0x");
|
||||
Serial.print(sp[5], 16);
|
||||
Serial.println(".");
|
||||
|
||||
Serial.flush();
|
||||
|
||||
// allow USB interrupts to preempt us:
|
||||
SCB_SHPR1_BUSFAULTPRI = (uint8_t)255;
|
||||
SCB_SHPR1_USGFAULTPRI = (uint8_t)255;
|
||||
SCB_SHPR1_MEMFAULTPRI = (uint8_t)255;
|
||||
|
||||
while (1) {
|
||||
digitalWrite(13, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(13, LOW);
|
||||
delay(100);
|
||||
|
||||
asm volatile (
|
||||
"WFI" // Wait For Interrupt.
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hard_fault_isr(void) __attribute__ ((alias("_fault_isr")));
|
||||
void memmanage_fault_isr(void) __attribute__ ((alias("_fault_isr")));
|
||||
void bus_fault_isr(void) __attribute__ ((alias("_fault_isr")));
|
||||
void usage_fault_isr(void) __attribute__ ((alias("_fault_isr")));
|
@ -4,13 +4,6 @@
|
||||
#include "iocompat.h"
|
||||
|
||||
#include "appleui.h"
|
||||
// FIXME should be able to omit this include and rely on the xterns, which
|
||||
// would prove it's linking properly
|
||||
#include "font.h"
|
||||
extern const unsigned char ucase_glyphs[512];
|
||||
extern const unsigned char lcase_glyphs[256];
|
||||
extern const unsigned char mousetext_glyphs[256];
|
||||
extern const unsigned char interface_glyphs[256];
|
||||
|
||||
#include "globals.h"
|
||||
#include "applevm.h"
|
||||
@ -20,14 +13,8 @@ extern const unsigned char interface_glyphs[256];
|
||||
|
||||
#include "images.h"
|
||||
|
||||
// We have two handles to the DMA buffer - the actual data
|
||||
// (dmaBuffer), which is the larger of the two sizes at 800*480 bytes
|
||||
// (=38400); or dmaBuffer16, which is the same pointer for (320*240 =
|
||||
// 76800) 16-bit words (using 153600 bytes of RAM). Since the 800*480
|
||||
// is larger we'll construct a buffer using that value and then use it
|
||||
// either as dmaBuffer or dmaBuffer16.
|
||||
DMAMEM uint8_t dmaBuffer[RA8875_HEIGHT * RA8875_WIDTH] __attribute__((aligned(32)));
|
||||
uint16_t *dmaBuffer16 = NULL; // At runtime, this points to dmaBuffer.
|
||||
uint8_t *dmaBuffer = NULL;
|
||||
uint16_t *dmaBuffer16 = NULL;
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
@ -38,42 +25,8 @@ uint16_t *dmaBuffer16 = NULL; // At runtime, this points to dmaBuffer.
|
||||
#define PIN_MISO 1
|
||||
#define PIN_SCK 27
|
||||
|
||||
// RGB map of each of the lowres colors
|
||||
const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
|
||||
0xC006, // 1 magenta
|
||||
0x0010, // 2 dark blue
|
||||
0xA1B5, // 3 purple
|
||||
0x0480, // 4 dark green
|
||||
0x6B4D, // 5 dark grey
|
||||
0x1B9F, // 6 med blue
|
||||
0x0DFD, // 7 light blue
|
||||
0x92A5, // 8 brown
|
||||
0xF8C5, // 9 orange
|
||||
0x9555, // 10 light gray
|
||||
0xFCF2, // 11 pink
|
||||
0x07E0, // 12 green
|
||||
0xFFE0, // 13 yellow
|
||||
0x87F0, // 14 aqua
|
||||
0xFFFF // 15 white
|
||||
};
|
||||
|
||||
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
||||
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
|
||||
#define _565toG(c) ( ((c) & 0x07E0) >> 3 )
|
||||
#define _565toB(c) ( ((c) & 0x001F) << 3 )
|
||||
#define RGBto332(r,g,b) ((((r) & 0xE0)) | (((g) & 0xE0) >> 3) | ((b) >> 6))
|
||||
#define luminanceFromRGB(r,g,b) ( ((r)*0.2126) + ((g)*0.7152) + ((b)*0.0722) )
|
||||
#define _565To332(c) ((((c) & 0xe000) >> 8) | (((c) & 0x700) >> 6) | (((c) & 0x18) >> 3))
|
||||
|
||||
#define blendColors(a,b) RGBto565( (_565toR(a) + _565toR(b))/2, (_565toG(a) + _565toG(b))/2, (_565toB(a) + _565toB(b))/2 )
|
||||
|
||||
|
||||
BaseDisplay *tft = NULL;
|
||||
|
||||
TeensyDisplay::TeensyDisplay()
|
||||
{
|
||||
dmaBuffer16 = (uint16_t *)dmaBuffer;
|
||||
|
||||
driveIndicator[0] = driveIndicator[1] = false;
|
||||
driveIndicatorDirty = true;
|
||||
|
||||
@ -86,10 +39,12 @@ TeensyDisplay::TeensyDisplay()
|
||||
digitalWrite(11, HIGH); // turn on pull-up
|
||||
|
||||
if (digitalRead(11)) {
|
||||
// Default: use older, small ILI display if pin 11 is not connected to ground
|
||||
// Default: use older, smaller but faster, ILI display if pin 11 is not connected to ground
|
||||
Serial.println(" using ILI9341 display");
|
||||
|
||||
dmaBuffer16 = (uint16_t *)malloc((320*240)*2+32); // malloc() happens in the DMAMEM area (RAM2) FIXME *** CONSTANTS -- and does the +32 align properly?
|
||||
|
||||
tft = new ILI9341_Wrap(PIN_CS, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO, PIN_DC);
|
||||
use8875 = false;
|
||||
|
||||
// Load the 9341 images
|
||||
getImageInfoAndData(IMG_9341_SHELL, &shellWidth, &shellHeight, &shellImage);
|
||||
@ -100,11 +55,14 @@ TeensyDisplay::TeensyDisplay()
|
||||
getImageInfoAndData(IMG_9341_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
|
||||
|
||||
tft->begin(50000000u);
|
||||
tft->setFrameBuffer((uint8_t *)dmaBuffer16);
|
||||
} else {
|
||||
// If someone grounded pin 11, then use the new RA8875 display
|
||||
Serial.println(" using RA8875 display");
|
||||
|
||||
dmaBuffer = (uint8_t *)malloc(800*480+32); // malloc() happens in the DMAMEM area (RAM2) FIXME *** CONSTANTS -- and does the +32 align properly?
|
||||
|
||||
tft = new RA8875_t4(PIN_CS, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
||||
use8875 = true;
|
||||
|
||||
// Load the 8875 images
|
||||
getImageInfoAndData(IMG_8875_SHELL, &shellWidth, &shellHeight, &shellImage);
|
||||
@ -118,32 +76,21 @@ TeensyDisplay::TeensyDisplay()
|
||||
// 60MHz: unexpected palatte shifts & (may be audio overruns, needs checking since bumping up buffer sizes) 17 FPS
|
||||
// And I can't get the SPI bus working at 80MHz or higher. Not sure why yet...
|
||||
tft->begin(57500000);
|
||||
tft->setFrameBuffer((uint8_t *)dmaBuffer);
|
||||
}
|
||||
|
||||
tft->setFrameBuffer((uint8_t *)dmaBuffer);
|
||||
Serial.print("before ");
|
||||
Serial.println((uint32_t)tft);
|
||||
Serial.print("after ");
|
||||
Serial.println((uint32_t)tft);
|
||||
tft->fillWindow();
|
||||
Serial.println("finished filling");
|
||||
}
|
||||
|
||||
TeensyDisplay::~TeensyDisplay()
|
||||
{
|
||||
}
|
||||
|
||||
void TeensyDisplay::flush()
|
||||
{
|
||||
}
|
||||
|
||||
void TeensyDisplay::redraw()
|
||||
{
|
||||
if (g_ui) {
|
||||
g_ui->drawStaticUIElement(UIeOverlay);
|
||||
|
||||
if (g_vm) {
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Take one of the abstracted image constants, figure out which one it
|
||||
// is based on the current display, and display it via
|
||||
// drawImageOfSizeAt.
|
||||
@ -185,17 +132,16 @@ void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
|
||||
uint16_t v = pgm_read_byte(p++);
|
||||
v <<= 8;
|
||||
v |= pgm_read_byte(p++);
|
||||
if (use8875) {
|
||||
dmaBuffer[(y+wherey)*RA8875_WIDTH + x+wherex] = _565To332(v);
|
||||
} else {
|
||||
dmaBuffer16[(y+wherey)*ILI9341_WIDTH + x+wherex] = v;
|
||||
}
|
||||
tft->drawPixel(x+wherex, y+wherey, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::blit()
|
||||
{
|
||||
if (!tft)
|
||||
return;
|
||||
|
||||
// Start updates, if they're not running already
|
||||
if (!tft->asyncUpdateActive())
|
||||
tft->updateScreenAsync(true);
|
||||
@ -214,186 +160,32 @@ void TeensyDisplay::blit()
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::blit(AiieRect r)
|
||||
{
|
||||
}
|
||||
|
||||
// FIXME do we still need 2 different methods for drawing pixels
|
||||
void TeensyDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
if (use8875) {
|
||||
if (x < RA8875_WIDTH && y < RA8875_HEIGHT)
|
||||
dmaBuffer[y*RA8875_WIDTH+x] = _565To332(color);
|
||||
} else {
|
||||
if (x < ILI9341_WIDTH && y < ILI9341_HEIGHT)
|
||||
dmaBuffer16[y*ILI9341_WIDTH+x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
if (use8875) {
|
||||
if (x < RA8875_WIDTH && y < RA8875_HEIGHT)
|
||||
dmaBuffer[y*RA8875_WIDTH+x] = _565To332(color);
|
||||
} else {
|
||||
if (x < ILI9341_WIDTH && y < ILI9341_HEIGHT)
|
||||
dmaBuffer16[y*ILI9341_WIDTH+x] = color;
|
||||
}
|
||||
tft->drawPixel(x,y,color);
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
|
||||
|
||||
drawPixel(x,y,color16);
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
|
||||
{
|
||||
int8_t xsize = 8,
|
||||
ysize = 0x07;
|
||||
|
||||
uint16_t offPixel, onPixel;
|
||||
switch (mode) {
|
||||
case M_NORMAL:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0010;
|
||||
break;
|
||||
case M_SELECTED:
|
||||
onPixel = 0x0000;
|
||||
offPixel = 0xFFFF;
|
||||
break;
|
||||
case M_DISABLED:
|
||||
default:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
case M_SELECTDISABLED:
|
||||
onPixel = 0x7BEF;
|
||||
offPixel = 0xFFE0;
|
||||
break;
|
||||
case M_PLAIN:
|
||||
onPixel = 0xFFFF;
|
||||
offPixel = 0x0000;
|
||||
break;
|
||||
}
|
||||
|
||||
const unsigned char *ch = asciiToAppleGlyph(c);
|
||||
for (int8_t y_off = 0; y_off <= ysize; y_off++) {
|
||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||
if (use8875) {
|
||||
for (int8_t ys=0; ys<2; ys++) {
|
||||
for (int8_t xs=0; xs<2; xs++) {
|
||||
if (*ch & (1 << (x_off))) {
|
||||
drawUIPixel((x + x_off)*2+xs, (y + y_off)*2+ys, onPixel);
|
||||
} else {
|
||||
drawUIPixel((x + x_off)*2+xs, (y + y_off)*2+ys, offPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (*ch & (1 << (x_off))) {
|
||||
drawUIPixel((x + x_off), (y + y_off), onPixel);
|
||||
} else {
|
||||
drawUIPixel((x + x_off), (y + y_off), offPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str)
|
||||
{
|
||||
int8_t xsize = 8; // width of a char in this font
|
||||
|
||||
for (int8_t i=0; i<strlen(str); i++) {
|
||||
drawCharacter(mode, x, y, str[i]);
|
||||
x += xsize;
|
||||
if (x >= (RA8875_WIDTH-xsize)/2) break; // FIXME this is a pre-scaled number, b/c drawCharacter is scaling. Klutzy.
|
||||
}
|
||||
tft->drawPixel(x,y,color16);
|
||||
}
|
||||
|
||||
void TeensyDisplay::clrScr(uint8_t coloridx)
|
||||
{
|
||||
uint16_t color16 = loresPixelColors[c_black];
|
||||
if (use8875) {
|
||||
uint8_t c = _565To332(color16);
|
||||
for (uint16_t y=0; y<RA8875_HEIGHT; y++) {
|
||||
for (uint16_t x=0; x<RA8875_WIDTH; x++) {
|
||||
// This could be faster - make one line, then memcpy the line to
|
||||
// the other lines? Or just use memset since it's 8bpp
|
||||
dmaBuffer[y*RA8875_WIDTH+x] = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (coloridx == c_black) {
|
||||
memset(dmaBuffer16, 0x00, ILI9341_HEIGHT * ILI9341_WIDTH * 2);
|
||||
} else if (coloridx == c_white) {
|
||||
memset(dmaBuffer16, 0xFF, ILI9341_HEIGHT * ILI9341_WIDTH * 2);
|
||||
} else {
|
||||
if (coloridx < 16)
|
||||
color16 = loresPixelColors[coloridx];
|
||||
// This could be faster - make one line, then memcpy the line to
|
||||
// the other lines?
|
||||
for (uint16_t y=0; y<ILI9341_HEIGHT; y++) {
|
||||
for (uint16_t x=0; x<ILI9341_WIDTH; x++) {
|
||||
dmaBuffer16[y*ILI9341_WIDTH+x] = color16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint16_t color16 = loresPixelColors[coloridx];
|
||||
tft->fillWindow(color16);
|
||||
}
|
||||
|
||||
void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
{
|
||||
if (use8875) {
|
||||
// The 8875 display doubles vertically
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff) * RA8875_WIDTH +x+SCREENINSET_8875_X] = _565To332(loresPixelColors[color]);
|
||||
}
|
||||
} else {
|
||||
// The 9341 is half the width we need, so this jumps through hoops
|
||||
// to reduce the resolution in a way that's reasonable by blending
|
||||
// pixels
|
||||
if (x&1) {
|
||||
uint16_t origColor = dmaBuffer16[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH+(x>>1)+SCREENINSET_9341_X];
|
||||
uint16_t newColor = (uint16_t) loresPixelColors[color];
|
||||
if (g_displayType == m_blackAndWhite) {
|
||||
// There are four reasonable decisions here: if either pixel
|
||||
// *was* on, then it's on; if both pixels *were* on, then it's
|
||||
// on; and if the blended value of the two pixels were on, then
|
||||
// it's on; or if the blended value of the two is above some
|
||||
// certain overall brightness, then it's on. This is the last of
|
||||
// those - where the brightness cutoff is defined in the bios as
|
||||
// g_luminanceCutoff.
|
||||
uint16_t blendedColor = blendColors(origColor, newColor);
|
||||
uint16_t luminance = luminanceFromRGB(_565toR(blendedColor),
|
||||
_565toG(blendedColor),
|
||||
_565toB(blendedColor));
|
||||
cacheDoubleWidePixel(x>>1,y,(uint16_t)((luminance >= g_luminanceCutoff) ? 0xFFFF : 0x0000));
|
||||
} else {
|
||||
cacheDoubleWidePixel(x>>1,y,color);
|
||||
// Else if it's black, we leave whatever was in the other pixel.
|
||||
}
|
||||
} else {
|
||||
// All of the even pixels get drawn...
|
||||
cacheDoubleWidePixel(x>>1,y,color);
|
||||
}
|
||||
}
|
||||
tft->cacheApplePixel(x,y,loresPixelColors[color]);
|
||||
}
|
||||
|
||||
void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint16_t color16)
|
||||
{
|
||||
if (use8875) {
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(color16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dmaBuffer16[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = color16;
|
||||
}
|
||||
tft->cacheDoubleWideApplePixel(x, y, color16);
|
||||
}
|
||||
|
||||
// "DoubleWide" means "please double the X because I'm in low-res
|
||||
@ -402,38 +194,14 @@ void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
{
|
||||
uint16_t color16;
|
||||
color16 = loresPixelColors[(( color & 0x0F ) )];
|
||||
|
||||
if (use8875) {
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(color16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dmaBuffer16[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = color16;
|
||||
}
|
||||
}
|
||||
|
||||
// This exists for 4bpp optimization. We could totally call
|
||||
// cacheDoubleWidePixel twice, but the (x&1) pfutzing is messy if
|
||||
// we're just storing both halves anyway...
|
||||
void TeensyDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y,
|
||||
uint8_t colorA, uint8_t colorB)
|
||||
{
|
||||
if (use8875) {
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
for (int xoff=0; xoff<2; xoff++) {
|
||||
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(colorA);
|
||||
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x+1)*2+SCREENINSET_8875_X+xoff] = _565To332(colorB);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dmaBuffer16[(y+SCREENINSET_8875_Y)*ILI9341_WIDTH + (x)+SCREENINSET_9341_X] = colorA;
|
||||
dmaBuffer16[(y+SCREENINSET_8875_Y)*ILI9341_WIDTH + ((x+1))+SCREENINSET_9341_X] = colorB;
|
||||
}
|
||||
tft->cacheDoubleWideApplePixel(x, y, color16);
|
||||
}
|
||||
|
||||
uint32_t TeensyDisplay::frameCount()
|
||||
{
|
||||
if (!tft)
|
||||
return 0;
|
||||
|
||||
return tft->frameCount();
|
||||
}
|
||||
|
@ -17,36 +17,27 @@ class TeensyDisplay : public PhysicalDisplay {
|
||||
virtual ~TeensyDisplay();
|
||||
|
||||
virtual void blit();
|
||||
virtual void blit(AiieRect r);
|
||||
virtual void redraw();
|
||||
virtual void flush() { };
|
||||
|
||||
virtual void clrScr(uint8_t coloridx);
|
||||
virtual void flush();
|
||||
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c);
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str);
|
||||
|
||||
virtual void drawUIImage(uint8_t imageIdx);
|
||||
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint16_t sizey, uint16_t wherex, uint16_t wherey);
|
||||
|
||||
void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint16_t color16);
|
||||
virtual void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color);
|
||||
virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB);
|
||||
virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color);
|
||||
|
||||
uint32_t frameCount();
|
||||
private:
|
||||
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||
virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
|
||||
bool needsRedraw;
|
||||
bool driveIndicator[2];
|
||||
bool driveIndicatorDirty;
|
||||
|
||||
private:
|
||||
bool use8875;
|
||||
|
||||
const uint8_t *shellImage;
|
||||
const uint16_t shellWidth, shellHeight;
|
||||
const uint8_t *d1OpenImage;
|
||||
@ -56,6 +47,8 @@ private:
|
||||
const uint8_t *d2ClosedImage;
|
||||
const uint8_t *appleImage;
|
||||
const uint16_t appleImageWidth, appleImageHeight;
|
||||
|
||||
BaseDisplay *tft;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -32,7 +32,6 @@
|
||||
#define BATTERYSELECT 21 // digital select that turns on the power reading ckt
|
||||
|
||||
#include "globals.h"
|
||||
#include "teensy-crash.h"
|
||||
|
||||
BIOS bios;
|
||||
|
||||
@ -166,6 +165,10 @@ void setup()
|
||||
delay(2000);
|
||||
#endif
|
||||
delay(200); // let the power settle & serial to get its bearings
|
||||
if (CrashReport) {
|
||||
Serial.print(CrashReport);
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
pinMode(DEBUGPIN, OUTPUT); // for debugging
|
||||
pinMode(BATTERYSELECT, OUTPUT);
|
||||
|
Loading…
Reference in New Issue
Block a user