mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-10 12:50:11 +00:00
refactor of UI layer
This commit is contained in:
parent
7f6e7dd73a
commit
7da0ed9a2b
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ CXXFLAGS=-Wall -I .. -I . -I apple -I sdl -I/usr/local/include/SDL2 -O3 -g
|
||||
|
||||
TSRC=cpu.cpp util/testharness.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
|
||||
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
|
||||
|
||||
SDLOBJS=sdl/sdl-speaker.o sdl/sdl-display.o sdl/sdl-keyboard.o sdl/sdl-paddles.o sdl/sdl-filemanager.o sdl/aiie.o sdl/sdl-printer.o sdl/sdl-clock.o
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#if DISPLAYRUN == 512
|
||||
|
||||
#define drawPixel(c, x, y) { \
|
||||
#define drawApplePixel(c, x, y) { \
|
||||
uint16_t idx = (((y) << 9) + (x)) >> 1; \
|
||||
if ((x) & 1) { \
|
||||
videoBuffer[idx] = (videoBuffer[idx] & 0xF0) | (c); \
|
||||
@ -56,7 +56,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#define drawPixel(c, x, y) { \
|
||||
#define drawApplePixel(c, x, y) { \
|
||||
uint16_t idx = ((y) * DISPLAYRUN + (x)) / 2; \
|
||||
if ((x) & 1) { \
|
||||
videoBuffer[idx] = (videoBuffer[idx] & 0xF0) | (c); \
|
||||
@ -76,13 +76,13 @@
|
||||
uint8_t pixel = c & 0x0F; \
|
||||
for (uint8_t y2 = 0; y2<4; y2++) { \
|
||||
for (int8_t x2 = 6; x2>=0; x2--) { \
|
||||
drawPixel(pixel, x*7+x2, y*8+y2); \
|
||||
drawApplePixel(pixel, x*7+x2, y*8+y2); \
|
||||
} \
|
||||
} \
|
||||
pixel = (c >> 4); \
|
||||
for (uint8_t y2 = 4; y2<8; y2++) { \
|
||||
for (int8_t x2 = 6; x2>=0; x2--) { \
|
||||
drawPixel(pixel, x*7+x2, y*8+y2); \
|
||||
drawApplePixel(pixel, x*7+x2, y*8+y2); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
@ -243,8 +243,8 @@ inline void AppleDisplay::Draw14DoubleHiresPixelsAt(uint16_t addr)
|
||||
// pixels for every color.
|
||||
|
||||
for (int8_t xoff = 0; xoff < 14; xoff += 2) {
|
||||
drawPixel(bitTrain & 0x0F, col+xoff, row);
|
||||
drawPixel(bitTrain & 0x0F, col+xoff+1, row);
|
||||
drawApplePixel(bitTrain & 0x0F, col+xoff, row);
|
||||
drawApplePixel(bitTrain & 0x0F, col+xoff+1, row);
|
||||
|
||||
bitTrain >>= 4;
|
||||
}
|
||||
@ -425,10 +425,10 @@ void AppleDisplay::redraw80ColumnText(uint8_t startingY)
|
||||
bool pixelOn = ( (d & (1<<x2)) | (d & (1<<(x2+1))) );
|
||||
if (pixelOn) {
|
||||
uint8_t val = (invert ? c_black : textColor);
|
||||
drawPixel(val, (basex+x2)/2, row*8+y2);
|
||||
drawApplePixel(val, (basex+x2)/2, row*8+y2);
|
||||
} else {
|
||||
uint8_t val = (invert ? textColor : c_black);
|
||||
drawPixel(val, (basex+x2)/2, row*8+y2);
|
||||
drawApplePixel(val, (basex+x2)/2, row*8+y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -442,10 +442,10 @@ void AppleDisplay::redraw80ColumnText(uint8_t startingY)
|
||||
bool pixelOn = ( (d & (1<<x2)) | (d & (1<<(x2+1))) );
|
||||
if (pixelOn) {
|
||||
uint8_t val = (invert ? c_black : textColor);
|
||||
drawPixel(val, (basex+x2)/2, row*8+y2);
|
||||
drawApplePixel(val, (basex+x2)/2, row*8+y2);
|
||||
} else {
|
||||
uint8_t val = (invert ? textColor : c_black);
|
||||
drawPixel(val, (basex+x2)/2, row*8+y2);
|
||||
drawApplePixel(val, (basex+x2)/2, row*8+y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -480,10 +480,10 @@ void AppleDisplay::redraw40ColumnText(uint8_t startingY)
|
||||
for (uint8_t x2 = 0; x2 < 7; x2++) {
|
||||
if (d & 1) {
|
||||
uint8_t val = (invert ? c_black : textColor);
|
||||
drawPixel(val, col*7+x2, row*8+y2);
|
||||
drawApplePixel(val, col*7+x2, row*8+y2);
|
||||
} else {
|
||||
uint8_t val = (invert ? textColor : c_black);
|
||||
drawPixel(val, col*7+x2, row*8+y2);
|
||||
drawApplePixel(val, col*7+x2, row*8+y2);
|
||||
}
|
||||
d >>= 1;
|
||||
}
|
||||
@ -562,14 +562,14 @@ void AppleDisplay::Draw80LoresPixelAt(uint8_t c, uint8_t x, uint8_t y, uint8_t o
|
||||
uint8_t pixel = c & 0x0F;
|
||||
for (uint8_t y2 = 0; y2<4; y2++) {
|
||||
for (int8_t x2 = 3; x2>=offset; x2--) {
|
||||
drawPixel(pixel, x*7+x2+offset*3, y*8+y2);
|
||||
drawApplePixel(pixel, x*7+x2+offset*3, y*8+y2);
|
||||
}
|
||||
}
|
||||
|
||||
pixel = (c >> 4);
|
||||
for (uint8_t y2 = 4; y2<8; y2++) {
|
||||
for (int8_t x2 = 3; x2>=offset; x2--) {
|
||||
drawPixel(pixel, x*7+x2+offset*3, y*8+y2);
|
||||
drawApplePixel(pixel, x*7+x2+offset*3, y*8+y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
127
apple/appleui.cpp
Normal file
127
apple/appleui.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "appleui.h"
|
||||
|
||||
#include "vm.h" // for DISPLAYHEIGHT. Probably not the most sensible.
|
||||
#include "images.h"
|
||||
#include "globals.h"
|
||||
|
||||
// FIXME: abstract and standardize the sizes, onscreen locations, and
|
||||
// underlying bitmap types
|
||||
|
||||
AppleUI::AppleUI()
|
||||
{
|
||||
}
|
||||
|
||||
AppleUI::~AppleUI()
|
||||
{
|
||||
}
|
||||
|
||||
void AppleUI::drawStaticUIElement(uint8_t element)
|
||||
{
|
||||
// Only one static UI element right now...
|
||||
if (element != UIeOverlay)
|
||||
return;
|
||||
|
||||
g_display->drawImageOfSizeAt(displayBitmap, DBITMAP_WIDTH, DBITMAP_HEIGHT, 0, 0);
|
||||
}
|
||||
|
||||
void AppleUI::drawOnOffUIElement(uint8_t element, bool state)
|
||||
{
|
||||
uint16_t xoff = 55;
|
||||
uint8_t yoff = 216;
|
||||
uint16_t xsize;
|
||||
uint8_t ysize;
|
||||
const uint8_t *img;
|
||||
|
||||
switch (element) {
|
||||
case UIeDisk1_state:
|
||||
xoff = 55;
|
||||
yoff = 216;
|
||||
xsize = 43;
|
||||
ysize = 20;
|
||||
img = state ? driveLatchOpen : driveLatch;
|
||||
break;
|
||||
case UIeDisk2_state:
|
||||
xoff = 55+134;
|
||||
yoff = 216;
|
||||
xsize = 43;
|
||||
ysize = 20;
|
||||
img = state ? driveLatchOpen : driveLatch;
|
||||
break;
|
||||
case UIeDisk1_activity:
|
||||
case UIeDisk2_activity:
|
||||
{
|
||||
uint16_t xoff = 125;
|
||||
uint16_t yoff = 213;
|
||||
if (element == UIeDisk2_activity)
|
||||
xoff += 135;
|
||||
for (int x=0; x<6; x++) {
|
||||
g_display->drawPixel(x + xoff, yoff, state ? 0xF800 : 0x8AA9);
|
||||
g_display->drawPixel(x + xoff, yoff + 1, state ? 0xF800 : 0x8AA9);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
g_display->drawImageOfSizeAt(img, xsize, ysize, xoff, yoff);
|
||||
}
|
||||
|
||||
void AppleUI::drawPercentageUIElement(uint8_t element, uint8_t percent)
|
||||
{
|
||||
// only 1 element of this type
|
||||
if (element != UIePowerPercentage) {
|
||||
return;
|
||||
}
|
||||
drawBatteryStatus(percent);
|
||||
}
|
||||
|
||||
void AppleUI::drawBatteryStatus(uint8_t percent)
|
||||
{
|
||||
uint16_t xoff = 301;
|
||||
uint16_t yoff = 222;
|
||||
|
||||
// the area around the apple is 12 wide; it's exactly 11 high the
|
||||
// color is 210/202/159
|
||||
|
||||
float watermark = ((float)percent / 100.0) * 11;
|
||||
|
||||
for (int y=0; y<11; y++) {
|
||||
uint8_t bgr = 210;
|
||||
uint8_t bgg = 202;
|
||||
uint8_t bgb = 159;
|
||||
|
||||
if (11-y > watermark) {
|
||||
// black...
|
||||
bgr = bgg = bgb = 0;
|
||||
}
|
||||
|
||||
for (int x=0; x<10; x++) {
|
||||
#ifdef TEENSYDUINO
|
||||
uint8_t r = pgm_read_byte(&appleBitmap[(y * 10 + x)*4 + 0]);
|
||||
uint8_t g = pgm_read_byte(&appleBitmap[(y * 10 + x)*4 + 1]);
|
||||
uint8_t b = pgm_read_byte(&appleBitmap[(y * 10 + x)*4 + 2]);
|
||||
uint8_t a = pgm_read_byte(&appleBitmap[(y * 10 + x)*4 + 3]);
|
||||
#else
|
||||
const uint8_t *p = &appleBitmap[(y * 10 + (x-1))*4];
|
||||
uint8_t r, g, b, a;
|
||||
r = p[0];
|
||||
g = p[1];
|
||||
b = p[2];
|
||||
a = p[3];
|
||||
#endif
|
||||
|
||||
// It's RGBA; blend w/ background color
|
||||
float alpha = (float)a / 255.0;
|
||||
r = (float)r * alpha + (bgr * (1.0 - alpha));
|
||||
g = (float)g * alpha + (bgg * (1.0 - alpha));
|
||||
b = (float)b * alpha + (bgb * (1.0 - alpha));
|
||||
|
||||
g_display->drawPixel(x+xoff, y+yoff, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
29
apple/appleui.h
Normal file
29
apple/appleui.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef __APPLEUI_H
|
||||
#define __APPLEUI_H
|
||||
|
||||
#include "vmui.h"
|
||||
|
||||
// Element IDs
|
||||
enum {
|
||||
UIeOverlay = 0,
|
||||
UIeDisk1_state = 1,
|
||||
UIeDisk2_state = 2,
|
||||
UIeDisk1_activity = 3,
|
||||
UIeDisk2_activity = 4,
|
||||
UIePowerPercentage = 5,
|
||||
};
|
||||
|
||||
class AppleUI : public VMui {
|
||||
public:
|
||||
AppleUI();
|
||||
~AppleUI();
|
||||
|
||||
virtual void drawStaticUIElement(uint8_t element);
|
||||
virtual void drawOnOffUIElement(uint8_t element, bool state);
|
||||
virtual void drawPercentageUIElement(uint8_t element, uint8_t percent);
|
||||
|
||||
void drawBatteryStatus(uint8_t percent);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -13,6 +13,7 @@
|
||||
#include "applemmu.h" // for FLOATING
|
||||
|
||||
#include "globals.h"
|
||||
#include "appleui.h"
|
||||
|
||||
#include "diskii-rom.h"
|
||||
|
||||
@ -195,12 +196,12 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
||||
|
||||
case 0x08: // drive off
|
||||
indicatorIsOn[selectedDisk] = 99;
|
||||
g_display->setDriveIndicator(selectedDisk, false); // FIXME: after a spell...
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: delay a bit? Queue for later drawing?
|
||||
checkFlush(curHalfTrack[selectedDisk]>>1);
|
||||
break;
|
||||
case 0x09: // drive on
|
||||
indicatorIsOn[selectedDisk] = 100;
|
||||
g_display->setDriveIndicator(selectedDisk, true);
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: delay a bit? Queue for later drawing?
|
||||
break;
|
||||
|
||||
case 0x0A: // select drive 1
|
||||
@ -238,12 +239,12 @@ uint8_t DiskII::readSwitches(uint8_t s)
|
||||
if (!indicatorIsOn[selectedDisk]) {
|
||||
// printf("Unexpected read while disk isn't on?\n");
|
||||
indicatorIsOn[selectedDisk] = 100;
|
||||
g_display->setDriveIndicator(selectedDisk, true);
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, true); // FIXME: queue for later drawing?
|
||||
}
|
||||
if (indicatorIsOn[selectedDisk] > 0 && indicatorIsOn[selectedDisk] < 100) {
|
||||
// slowly spin it down...
|
||||
if (--indicatorIsOn[selectedDisk] == 0) {
|
||||
g_display->setDriveIndicator(selectedDisk, false);
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: queue for later drawing?
|
||||
}
|
||||
|
||||
}
|
||||
@ -426,7 +427,7 @@ void DiskII::insertDisk(int8_t driveNum, const char *filename, bool drawIt)
|
||||
ejectDisk(driveNum);
|
||||
disk[driveNum] = g_filemanager->openFile(filename);
|
||||
if (drawIt)
|
||||
g_display->drawDriveDoor(driveNum, false);
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state + driveNum, false);
|
||||
|
||||
if (_endsWithI(filename, ".nib")) {
|
||||
diskType[driveNum] = nibDisk;
|
||||
@ -446,7 +447,7 @@ void DiskII::ejectDisk(int8_t driveNum)
|
||||
if (disk[driveNum] != -1) {
|
||||
g_filemanager->closeFile(disk[driveNum]);
|
||||
disk[driveNum] = -1;
|
||||
g_display->drawDriveDoor(driveNum, true);
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state + driveNum, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,7 +458,7 @@ void DiskII::select(int8_t which)
|
||||
|
||||
if (which != selectedDisk) {
|
||||
indicatorIsOn[selectedDisk] = 0;
|
||||
g_display->setDriveIndicator(selectedDisk, false);
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_activity + selectedDisk, false); // FIXME: queue for later drawing?
|
||||
|
||||
checkFlush(curHalfTrack[selectedDisk]>>1);
|
||||
|
||||
|
@ -8,5 +8,6 @@ PhysicalKeyboard *g_keyboard = NULL;
|
||||
PhysicalSpeaker *g_speaker = NULL;
|
||||
PhysicalPaddles *g_paddles = NULL;
|
||||
PhysicalPrinter *g_printer = NULL;
|
||||
VMui *g_ui;
|
||||
int16_t g_volume = 15;
|
||||
uint8_t g_displayType = 3; // FIXME m_perfectcolor
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "physicalspeaker.h"
|
||||
#include "physicalpaddles.h"
|
||||
#include "physicalprinter.h"
|
||||
#include "vmui.h"
|
||||
|
||||
extern FileManager *g_filemanager;
|
||||
extern Cpu *g_cpu;
|
||||
@ -17,5 +18,6 @@ extern PhysicalKeyboard *g_keyboard;
|
||||
extern PhysicalSpeaker *g_speaker;
|
||||
extern PhysicalPaddles *g_paddles;
|
||||
extern PhysicalPrinter *g_printer;
|
||||
extern VMui *g_ui;
|
||||
extern int16_t g_volume;
|
||||
extern uint8_t g_displayType;
|
||||
|
29523
images.cpp
Normal file
29523
images.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,14 +13,15 @@ class PhysicalDisplay {
|
||||
virtual void redraw() = 0; // total redraw, assuming nothing
|
||||
virtual void blit(AiieRect r) = 0; // redraw just the VM display area
|
||||
|
||||
virtual void drawDriveDoor(uint8_t which, bool isOpen) = 0;
|
||||
virtual void setDriveIndicator(uint8_t which, bool isRunning) = 0;
|
||||
virtual void drawBatteryStatus(uint8_t percent) = 0;
|
||||
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint8_t sizey, uint16_t wherex, uint8_t wherey) = 0;
|
||||
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c) = 0;
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str) = 0;
|
||||
virtual void debugMsg(const char *msg) { strncpy(overlayMessage, msg, sizeof(overlayMessage)); }
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
char overlayMessage[40];
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "sdl-paddles.h"
|
||||
#include "sdl-filemanager.h"
|
||||
#include "sdl-printer.h"
|
||||
#include "appleui.h"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
@ -286,6 +287,8 @@ int main(int argc, char *argv[])
|
||||
g_display = new SDLDisplay();
|
||||
// g_displayType = m_blackAndWhite;
|
||||
|
||||
g_ui = new AppleUI();
|
||||
|
||||
// paddles have to be created after g_display created the window
|
||||
g_paddles = new SDLPaddles();
|
||||
|
||||
@ -356,7 +359,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
g_printer->update();
|
||||
g_keyboard->maintainKeyboard();
|
||||
g_display->drawBatteryStatus(100);
|
||||
g_ui->drawPercentageUIElement(UIePowerPercentage, 100);
|
||||
|
||||
// calculate FPS & dynamically step up/down as necessary
|
||||
static time_t startAt = time(NULL);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "globals.h"
|
||||
#include "applevm.h"
|
||||
|
||||
#include "apple/appleui.h"
|
||||
|
||||
// RGB map of each of the lowres colors
|
||||
const uint8_t loresPixelColors[16][3] = { { 0, 0, 0 }, // black
|
||||
{ 195, 0, 48 }, // magenta
|
||||
@ -53,85 +55,28 @@ void SDLDisplay::redraw()
|
||||
// primarily for the device, where it's in and out of the
|
||||
// bios. Draws the background image.
|
||||
printf("redraw background\n");
|
||||
g_ui->drawStaticUIElement(UIeOverlay);
|
||||
|
||||
for (int y=0; y<DISPLAYHEIGHT; y++) {
|
||||
for (int x=0; x<DISPLAYWIDTH; x++) {
|
||||
uint8_t *p = &displayBitmap[(y * DBITMAP_WIDTH + x)*3];
|
||||
drawPixel(x, y, p[0], p[1], p[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_vm) {
|
||||
drawDriveDoor(0, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
drawDriveDoor(1, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
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::setDriveIndicator(uint8_t which, bool isRunning)
|
||||
void SDLDisplay::drawImageOfSizeAt(const uint8_t *img,
|
||||
uint16_t sizex, uint8_t sizey,
|
||||
uint16_t wherex, uint8_t wherey)
|
||||
{
|
||||
driveIndicator[which] = isRunning;
|
||||
driveIndicatorDirty = true;
|
||||
}
|
||||
|
||||
void SDLDisplay::drawDriveDoor(uint8_t which, bool isOpen)
|
||||
{
|
||||
// location of drive door for left drive
|
||||
uint16_t xoff = 55;
|
||||
uint16_t yoff = 216;
|
||||
|
||||
// location for right drive
|
||||
if (which == 1) {
|
||||
xoff += 134;
|
||||
}
|
||||
|
||||
for (int y=0; y<20; y++) {
|
||||
for (int x=0; x<43; x++) {
|
||||
uint8_t *p = &driveLatch[(y * 43 + x)*3];
|
||||
if (isOpen) {
|
||||
p = &driveLatchOpen[(y * 43 + x)*3];
|
||||
}
|
||||
drawPixel(x+xoff, y+yoff, p[0], p[1], p[2]);
|
||||
for (uint8_t y=0; y<sizey; y++) {
|
||||
for (uint16_t x=0; x<sizex; x++) {
|
||||
const uint8_t *p = &img[(y * sizex + x)*3];
|
||||
p = &img[(y * sizex + x)*3];
|
||||
drawPixel(x+wherex, y+wherey, p[0], p[1], p[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::drawBatteryStatus(uint8_t percent)
|
||||
{
|
||||
uint16_t xoff = 300;
|
||||
uint16_t yoff = 222;
|
||||
|
||||
// the area around the apple is 12 wide
|
||||
// it's exactly 11 high
|
||||
// the color is 210/202/159
|
||||
|
||||
float watermark = ((float)percent / 100.0) * 11;
|
||||
|
||||
for (int y=0; y<11; y++) {
|
||||
uint8_t bgr = 210;
|
||||
uint8_t bgg = 202;
|
||||
uint8_t bgb = 159;
|
||||
|
||||
if (11-y > watermark) {
|
||||
// black...
|
||||
bgr = bgg = bgb = 0;
|
||||
}
|
||||
|
||||
for (int x=0; x<11; x++) {
|
||||
uint8_t *p = &appleBitmap[(y * 10 + (x-1))*4];
|
||||
// It's RGBA; blend w/ background color
|
||||
|
||||
uint8_t r,g,b;
|
||||
float alpha = (float)p[3] / 255.0;
|
||||
r = (float)p[0] * alpha + (bgr * (1.0 - alpha));
|
||||
g = (float)p[1] * alpha + (bgg * (1.0 - alpha));
|
||||
b = (float)p[2] * alpha + (bgb * (1.0 - alpha));
|
||||
|
||||
drawPixel(x+xoff, y+yoff, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define BASEX 36
|
||||
#define BASEY 26
|
||||
|
||||
@ -162,20 +107,6 @@ void SDLDisplay::blit(AiieRect r)
|
||||
drawString(M_SELECTDISABLED, 1, 240 - 16 - 12, overlayMessage);
|
||||
}
|
||||
|
||||
if (driveIndicatorDirty) {
|
||||
// location of status indicator for left drive
|
||||
uint16_t xoff = 125;
|
||||
uint16_t yoff = 213;
|
||||
for (int which=0; which<2; which++,xoff+=135) { // +135 for right drive
|
||||
for (int y=0; y<1; y++) {
|
||||
for (int x=0; x<6; x++) {
|
||||
drawPixel(x + xoff, y + yoff, driveIndicator[which] ? 0xF800 : 0x8AA9);
|
||||
}
|
||||
}
|
||||
}
|
||||
driveIndicatorDirty = false;
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
@ -185,7 +116,7 @@ inline void putpixel(SDL_Renderer *renderer, int x, int y, uint8_t r, uint8_t g,
|
||||
SDL_RenderDrawPoint(renderer, x, y);
|
||||
}
|
||||
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint8_t y, uint16_t color)
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
uint8_t
|
||||
r = (color & 0xF800) >> 8,
|
||||
@ -201,7 +132,7 @@ void SDLDisplay::drawPixel(uint16_t x, uint8_t y, uint16_t color)
|
||||
}
|
||||
}
|
||||
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// Pixel-doubling
|
||||
for (int yoff=0; yoff<2; yoff++) {
|
||||
|
@ -28,12 +28,11 @@ class SDLDisplay : public PhysicalDisplay {
|
||||
virtual void blit(AiieRect r);
|
||||
virtual void redraw();
|
||||
|
||||
virtual void drawDriveDoor(uint8_t which, bool isOpen);
|
||||
virtual void setDriveIndicator(uint8_t which, bool isRunning);
|
||||
virtual void drawBatteryStatus(uint8_t percent);
|
||||
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint8_t sizey, uint16_t wherex, uint8_t wherey);
|
||||
|
||||
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);
|
||||
|
||||
void drawPixel(uint16_t x, uint8_t y, uint16_t color);
|
||||
void drawPixel(uint16_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c);
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str);
|
||||
virtual void debugMsg(const char *msg);
|
||||
@ -41,9 +40,6 @@ class SDLDisplay : public PhysicalDisplay {
|
||||
private:
|
||||
SDL_Window *screen;
|
||||
SDL_Renderer *renderer;
|
||||
|
||||
bool driveIndicator[2];
|
||||
bool driveIndicatorDirty;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
1
teensy/appleui.cpp
Symbolic link
1
teensy/appleui.cpp
Symbolic link
@ -0,0 +1 @@
|
||||
../apple/appleui.cpp
|
1
teensy/appleui.h
Symbolic link
1
teensy/appleui.h
Symbolic link
@ -0,0 +1 @@
|
||||
../apple/appleui.h
|
1
teensy/images.cpp
Symbolic link
1
teensy/images.cpp
Symbolic link
@ -0,0 +1 @@
|
||||
../images.cpp
|
@ -2,7 +2,7 @@
|
||||
#include "teensy-display.h"
|
||||
|
||||
#include "bios-font.h"
|
||||
#include "images.h"
|
||||
#include "appleui.h"
|
||||
|
||||
#define RS 16
|
||||
#define WR 17
|
||||
@ -212,19 +212,11 @@ void TeensyDisplay::redraw()
|
||||
|
||||
moveTo(0, 0);
|
||||
|
||||
for (int y=0; y<TEENSY_DHEIGHT; y++) {
|
||||
for (int x=0; x<TEENSY_DWIDTH; x++) {
|
||||
uint8_t r = pgm_read_byte(&displayBitmap[(y * DBITMAP_WIDTH + x)*3 + 0]);
|
||||
uint8_t g = pgm_read_byte(&displayBitmap[(y * DBITMAP_WIDTH + x)*3 + 1]);
|
||||
uint8_t b = pgm_read_byte(&displayBitmap[(y * DBITMAP_WIDTH + x)*3 + 2]);
|
||||
uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
|
||||
setPixel(color16);
|
||||
}
|
||||
}
|
||||
g_ui->drawStaticUIElement(UIeOverlay);
|
||||
|
||||
if (g_vm) {
|
||||
drawDriveDoor(0, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
drawDriveDoor(1, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
}
|
||||
|
||||
cbi(P_CS, B_CS);
|
||||
@ -411,8 +403,6 @@ void TeensyDisplay::blit(AiieRect r)
|
||||
|
||||
drawString(M_SELECTDISABLED, 1, 240 - 16 - 12, overlayMessage);
|
||||
}
|
||||
|
||||
redrawDriveIndicators();
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
||||
@ -470,98 +460,25 @@ void TeensyDisplay::drawString(uint8_t mode, uint16_t x, uint8_t y, const char *
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawDriveDoor(uint8_t which, bool isOpen)
|
||||
void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
|
||||
uint16_t sizex, uint8_t sizey,
|
||||
uint16_t wherex, uint8_t wherey)
|
||||
{
|
||||
// location of drive door for left drive
|
||||
uint8_t r, g, b;
|
||||
|
||||
uint16_t xoff = 55;
|
||||
uint16_t yoff = 216;
|
||||
|
||||
// location for right drive
|
||||
|
||||
if (which == 1) {
|
||||
xoff += 134;
|
||||
if (sizex == DISPLAYWIDTH) {
|
||||
moveTo(0,0);
|
||||
}
|
||||
|
||||
for (int y=0; y<20; y++) {
|
||||
for (int x=0; x<43; x++) {
|
||||
uint8_t r, g, b;
|
||||
if (isOpen) {
|
||||
r = pgm_read_byte(&driveLatchOpen[(y * 43 + x)*3 + 0]);
|
||||
g = pgm_read_byte(&driveLatchOpen[(y * 43 + x)*3 + 1]);
|
||||
b = pgm_read_byte(&driveLatchOpen[(y * 43 + x)*3 + 2]);
|
||||
} else {
|
||||
r = pgm_read_byte(&driveLatch[(y * 43 + x)*3 + 0]);
|
||||
g = pgm_read_byte(&driveLatch[(y * 43 + x)*3 + 1]);
|
||||
b = pgm_read_byte(&driveLatch[(y * 43 + x)*3 + 2]);
|
||||
}
|
||||
drawPixel(x+xoff, y+yoff, r, g, b);
|
||||
for (uint8_t y=0; y<sizey; y++) {
|
||||
if (sizex != DISPLAYWIDTH) {
|
||||
moveTo(wherex, wherey + y);
|
||||
}
|
||||
for (uint16_t x=0; x<sizex; x++) {
|
||||
r = pgm_read_byte(&img[(y*sizex + x)*3 + 0]);
|
||||
g = pgm_read_byte(&img[(y*sizex + x)*3 + 1]);
|
||||
b = pgm_read_byte(&img[(y*sizex + x)*3 + 2]);
|
||||
setPixel((((r&248)|g>>5) << 8) | ((g&28)<<3|b>>3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::setDriveIndicator(uint8_t which, bool isRunning)
|
||||
{
|
||||
driveIndicator[which] = isRunning;
|
||||
driveIndicatorDirty = true;
|
||||
}
|
||||
|
||||
void TeensyDisplay::redrawDriveIndicators()
|
||||
{
|
||||
if (driveIndicatorDirty) {
|
||||
// location of status indicator for left drive
|
||||
uint16_t xoff = 125;
|
||||
uint16_t yoff = 213;
|
||||
|
||||
for (int which = 0; which <= 1; which++,xoff += 135) {
|
||||
|
||||
for (int y=0; y<2; y++) {
|
||||
for (int x=0; x<6; x++) {
|
||||
drawPixel(x + xoff, y + yoff, driveIndicator[which] ? 0xF800 : 0x8AA9);
|
||||
}
|
||||
}
|
||||
}
|
||||
driveIndicatorDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawBatteryStatus(uint8_t percent)
|
||||
{
|
||||
uint16_t xoff = 300;
|
||||
uint16_t yoff = 222;
|
||||
|
||||
// the area around the apple is 12 wide
|
||||
// it's exactly 11 high
|
||||
// the color is 210/202/159
|
||||
|
||||
float watermark = ((float)percent / 100.0) * 11;
|
||||
|
||||
for (int y=0; y<11; y++) {
|
||||
uint8_t bgr = 210;
|
||||
uint8_t bgg = 202;
|
||||
uint8_t bgb = 159;
|
||||
if (11-y > watermark) {
|
||||
// black...
|
||||
bgr = bgg = bgb = 0;
|
||||
}
|
||||
|
||||
for (int x=0; x<11; x++) {
|
||||
uint8_t *p = &appleBitmap[(y * 10 + (x-1))*4];
|
||||
// It's RGBA; blend w/ background color
|
||||
|
||||
uint8_t r,g,b;
|
||||
float alpha = (float)pgm_read_byte(&appleBitmap[(y * 10 + (x-1))*4 + 3]) / 255.0;
|
||||
|
||||
r = (float)pgm_read_byte(&appleBitmap[(y * 10 + (x-1))*4 + 0])
|
||||
* alpha + (bgr * (1.0 - alpha));
|
||||
g = (float)pgm_read_byte(&appleBitmap[(y * 10 + (x-1))*4 + 1])
|
||||
* alpha + (bgr * (1.0 - alpha));
|
||||
b = (float)pgm_read_byte(&appleBitmap[(y * 10 + (x-1))*4 + 2])
|
||||
* alpha + (bgr * (1.0 - alpha));
|
||||
|
||||
|
||||
drawPixel(x+xoff, y+yoff, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,14 +45,11 @@ class TeensyDisplay : public PhysicalDisplay {
|
||||
virtual void drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c);
|
||||
virtual void drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str);
|
||||
|
||||
virtual void drawDriveDoor(uint8_t which, bool isOpen);
|
||||
virtual void setDriveIndicator(uint8_t which, bool isRunning);
|
||||
virtual void drawBatteryStatus(uint8_t percent);
|
||||
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint8_t sizey, uint16_t wherex, uint8_t wherey);
|
||||
|
||||
protected:
|
||||
void moveTo(uint16_t col, uint16_t row);
|
||||
void drawNextPixel(uint16_t color);
|
||||
void redrawDriveIndicators();
|
||||
|
||||
private:
|
||||
regtype *P_RS, *P_WR, *P_CS, *P_RST, *P_SDA, *P_SCL, *P_ALE;
|
||||
@ -68,9 +65,9 @@ class TeensyDisplay : public PhysicalDisplay {
|
||||
void setColor(byte r, byte g, byte b);
|
||||
void setColor(uint16_t color);
|
||||
void fillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
|
||||
void drawPixel(uint16_t x, uint16_t y);
|
||||
void drawPixel(uint16_t x, uint16_t y, uint16_t color);
|
||||
void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||
virtual void drawPixel(uint16_t x, uint16_t y);
|
||||
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);
|
||||
|
||||
inline void LCD_Writ_Bus(uint8_t VH,uint8_t VL) __attribute__((always_inline));
|
||||
inline void LCD_Write_COM(uint8_t VL) __attribute__((always_inline));
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "teensy-speaker.h"
|
||||
#include "teensy-paddles.h"
|
||||
#include "teensy-filemanager.h"
|
||||
#include "appleui.h"
|
||||
|
||||
#define RESETPIN 39
|
||||
#define BATTERYPIN A19
|
||||
@ -94,6 +95,9 @@ void setup()
|
||||
Serial.println(" display");
|
||||
g_display = new TeensyDisplay();
|
||||
|
||||
Serial.println(" UI");
|
||||
g_ui = new AppleUI();
|
||||
|
||||
// Next create the virtual CPU. This needs the VM's MMU in order to
|
||||
// run, but we don't have that yet.
|
||||
Serial.println(" cpu");
|
||||
@ -128,8 +132,6 @@ void setup()
|
||||
Serial.println("Reading prefs");
|
||||
readPrefs(); // read from eeprom and set anything we need setting
|
||||
|
||||
Serial.println("free-running");
|
||||
|
||||
startMicros = nextInstructionMicros = micros();
|
||||
|
||||
// Debugging: insert a disk on startup...
|
||||
@ -143,6 +145,8 @@ void setup()
|
||||
Serial.print("Free RAM: ");
|
||||
Serial.println(FreeRamEstimate());
|
||||
|
||||
Serial.println("free-running");
|
||||
|
||||
Timer1.initialize(3);
|
||||
Timer1.attachInterrupt(runCPU);
|
||||
Timer1.start();
|
||||
@ -323,7 +327,7 @@ void loop()
|
||||
batteryLevel = 168;
|
||||
|
||||
batteryLevel = map(batteryLevel, 146, 168, 0, 100);
|
||||
g_display->drawBatteryStatus(batteryLevel);
|
||||
g_ui->drawPercentageUIElement(UIePowerPercentage, batteryLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
1
teensy/vmui.h
Symbolic link
1
teensy/vmui.h
Symbolic link
@ -0,0 +1 @@
|
||||
../vmui.h
|
37
vmui.h
Normal file
37
vmui.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef __VMUI_H
|
||||
#define __VMUI_H
|
||||
|
||||
//#ifndef TEENSYDUINO
|
||||
#include <stdint.h>
|
||||
//#endif
|
||||
|
||||
/* Abstraction of VM-specific UI element drawing.
|
||||
*
|
||||
* UI elements are things like
|
||||
* - disk drive 1/inserted, disk drive 1/ejected;
|
||||
* - power icon percentage;
|
||||
* - disk drive 1/activity indicator, on/off;
|
||||
* - parallel port activity;
|
||||
* - network activity;
|
||||
* etc. (No, not all of those things exist yet.)
|
||||
*
|
||||
* This encapsulates the VM positioning and icon data. The actual
|
||||
* drawing routines are in the physical implementation (TeensyDisplay
|
||||
* or SDLDisplay).
|
||||
*
|
||||
* Most of those are on/off indicators. Some are percentage indicators.
|
||||
* The element IDs are in the VM's UI class (cf. AppleUI).
|
||||
*/
|
||||
|
||||
class VMui
|
||||
{
|
||||
public:
|
||||
VMui() {};
|
||||
~VMui() {};
|
||||
|
||||
virtual void drawStaticUIElement(uint8_t element) = 0;
|
||||
virtual void drawOnOffUIElement(uint8_t element, bool state) = 0; // on or off
|
||||
virtual void drawPercentageUIElement(uint8_t element, uint8_t percent) = 0; // 0-100
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user