support -8 or -9 flag to choose display type emulated in the SDL build

This commit is contained in:
Jorj Bauer 2022-02-08 21:48:54 -05:00
parent 1c09349746
commit 0473196d40
3 changed files with 140 additions and 51 deletions

View File

@ -371,10 +371,25 @@ void loop()
} }
} }
bool use8875 = true;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
_init_darwin_shim(); _init_darwin_shim();
/* Look for flags first and strip them out of argv/argc if present, leaving
* just filenames for disks to have been inserted */
if (argc > 1 && !strcmp(argv[1], "-9")) {
argc--;
argv++;
use8875 = false;
}
else if (argc > 1 && !strcmp(argv[1], "-8")) {
argc--;
argv++;
use8875 = true;
}
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_EVERYTHING);
g_speaker = new SDLSpeaker(); g_speaker = new SDLSpeaker();

View File

@ -10,6 +10,16 @@
#include "images.h" #include "images.h"
#define RA8875_WIDTH 800
#define RA8875_HEIGHT 480
#define ILI9341_WIDTH 320
#define ILI9341_HEIGHT 240
// *** FIXME need a better blend
#define blendColors(a,b) (a | b)
extern bool use8875;
// RGB map of each of the lowres colors // RGB map of each of the lowres colors
const uint8_t loresPixelColors[16][3] = { { 0, 0, 0 }, // black const uint8_t loresPixelColors[16][3] = { { 0, 0, 0 }, // black
{ 0xAC, 0x12, 0x4C }, // magenta { 0xAC, 0x12, 0x4C }, // magenta
@ -42,26 +52,37 @@ const uint8_t loresPixelColors[16][3] = { { 0, 0, 0 }, // black
SDLDisplay::SDLDisplay() SDLDisplay::SDLDisplay()
{ {
memset(videoBuffer, 0, sizeof(videoBuffer));
driveIndicator[0] = driveIndicator[1] = true; // assume on so they will redraw the first time driveIndicator[0] = driveIndicator[1] = true; // assume on so they will redraw the first time
shellImage = NULL; shellImage = NULL;
d1OpenImage = d1ClosedImage = d2OpenImage = d2ClosedImage = NULL; d1OpenImage = d1ClosedImage = d2OpenImage = d2ClosedImage = NULL;
appleImage = NULL; appleImage = NULL;
getImageInfoAndData(IMG_8875_SHELL, &shellWidth, &shellHeight, &shellImage); if (use8875) {
getImageInfoAndData(IMG_8875_D1OPEN, &driveWidth, &driveHeight, &d1OpenImage); videoBuffer = (uint32_t *)calloc(RA8875_HEIGHT * RA8875_WIDTH, sizeof(uint32_t));
getImageInfoAndData(IMG_8875_D1CLOSED, &driveWidth, &driveHeight, &d1ClosedImage); getImageInfoAndData(IMG_8875_SHELL, &shellWidth, &shellHeight, &shellImage);
getImageInfoAndData(IMG_8875_D2OPEN, &driveWidth, &driveHeight, &d2OpenImage); getImageInfoAndData(IMG_8875_D1OPEN, &driveWidth, &driveHeight, &d1OpenImage);
getImageInfoAndData(IMG_8875_D2CLOSED, &driveWidth, &driveHeight, &d2ClosedImage); getImageInfoAndData(IMG_8875_D1CLOSED, &driveWidth, &driveHeight, &d1ClosedImage);
getImageInfoAndData(IMG_8875_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage); getImageInfoAndData(IMG_8875_D2OPEN, &driveWidth, &driveHeight, &d2OpenImage);
getImageInfoAndData(IMG_8875_D2CLOSED, &driveWidth, &driveHeight, &d2ClosedImage);
getImageInfoAndData(IMG_8875_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
} else {
videoBuffer = (uint32_t *)calloc(ILI9341_HEIGHT * ILI9341_WIDTH, sizeof(uint32_t));
getImageInfoAndData(IMG_9341_SHELL, &shellWidth, &shellHeight, &shellImage);
getImageInfoAndData(IMG_9341_D1OPEN, &driveWidth, &driveHeight, &d1OpenImage);
getImageInfoAndData(IMG_9341_D1CLOSED, &driveWidth, &driveHeight, &d1ClosedImage);
getImageInfoAndData(IMG_9341_D2OPEN, &driveWidth, &driveHeight, &d2OpenImage);
getImageInfoAndData(IMG_9341_D2CLOSED, &driveWidth, &driveHeight, &d2ClosedImage);
getImageInfoAndData(IMG_9341_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
}
// FIXME: abstract constants // FIXME: abstract constants
screen = SDL_CreateWindow("Aiie!", screen = SDL_CreateWindow("Aiie!",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SDL_WIDTH, SDL_HEIGHT, use8875 ? RA8875_WIDTH : ILI9341_WIDTH,
use8875 ? RA8875_HEIGHT : ILI9341_HEIGHT,
SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE); SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
// SDL_RENDERER_SOFTWARE because, at least on my Mac, this has some // SDL_RENDERER_SOFTWARE because, at least on my Mac, this has some
@ -72,10 +93,10 @@ SDLDisplay::SDLDisplay()
SDL_RenderPresent(renderer); // perform the render SDL_RenderPresent(renderer); // perform the render
buffer = SDL_CreateTexture(renderer, buffer = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGB888, SDL_PIXELFORMAT_RGB888,
SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_STREAMING,
SDL_WIDTH, use8875 ? RA8875_WIDTH : ILI9341_WIDTH,
SDL_HEIGHT); use8875 ? RA8875_HEIGHT : ILI9341_HEIGHT);
} }
SDLDisplay::~SDLDisplay() SDLDisplay::~SDLDisplay()
@ -96,16 +117,24 @@ void SDLDisplay::drawUIImage(uint8_t imageIdx)
drawImageOfSizeAt(shellImage, shellWidth, shellHeight, 0, 0); drawImageOfSizeAt(shellImage, shellWidth, shellHeight, 0, 0);
break; break;
case IMG_D1OPEN: case IMG_D1OPEN:
drawImageOfSizeAt(d1OpenImage, driveWidth, driveHeight, 4, 67); drawImageOfSizeAt(d1OpenImage, driveWidth, driveHeight,
use8875 ? 4 : 55,
use8875 ? 67 : 216);
break; break;
case IMG_D1CLOSED: case IMG_D1CLOSED:
drawImageOfSizeAt(d1ClosedImage, driveWidth, driveHeight, 4, 67); drawImageOfSizeAt(d1ClosedImage, driveWidth, driveHeight,
use8875 ? 4 : 189,
use8875 ? 116 : 216);
break; break;
case IMG_D2OPEN: case IMG_D2OPEN:
drawImageOfSizeAt(d2OpenImage, driveWidth, driveHeight, 4, 116); drawImageOfSizeAt(d2OpenImage, driveWidth, driveHeight,
use8875 ? 4 : 189,
use8875 ? 116 : 216);
break; break;
case IMG_D2CLOSED: case IMG_D2CLOSED:
drawImageOfSizeAt(d2ClosedImage, driveWidth, driveHeight, 4, 116); drawImageOfSizeAt(d2ClosedImage, driveWidth, driveHeight,
use8875 ? 4 : 189,
use8875 ? 116 : 216);
break; break;
case IMG_APPLEBATTERY: case IMG_APPLEBATTERY:
// FIXME *** // FIXME ***
@ -117,19 +146,19 @@ void SDLDisplay::drawDriveActivity(bool drive0, bool drive1)
{ {
if (drive0 != driveIndicator[0]) { if (drive0 != driveIndicator[0]) {
printf("change d0\n"); printf("change d0\n");
for (int y=0; y<LED_HEIGHT_8875; y++) { for (int y=0; y<(use8875 ? LED_HEIGHT_8875 : LED_HEIGHT_9341); y++) {
for (int x=0; x<LED_WIDTH_8875; x++) { for (int x=0; x<(use8875 ? LED_WIDTH_8875 : LED_WIDTH_9341); x++) {
// FIXME this isn't working, not sure why // FIXME this isn't working, not sure why
drawPixel(x+LED1_X_8875, y+LED1_Y_8875, 0xFF, 0, 0); ///*drive0 ?*/ 0xFA00/* : 0x0000*/); drawPixel(x+(use8875 ? LED1_X_8875 : LED1_X_9341), y+(use8875 ? LED1_Y_8875 : LED1_Y_9341), drive0 ? 0xFA00 : 0x0000);
} }
} }
driveIndicator[0] = drive0; driveIndicator[0] = drive0;
} }
if (drive1 != driveIndicator[1]) { if (drive1 != driveIndicator[1]) {
for (int y=0; y<LED_HEIGHT_8875; y++) { for (int y=0; y<(use8875 ? LED_HEIGHT_8875 : LED_HEIGHT_9341); y++) {
for (int x=0; x<LED_WIDTH_8875; x++) { for (int x=0; x<(use8875 ? LED_WIDTH_8875 : LED_WIDTH_9341); x++) {
drawPixel(x+LED2_X_8875, y+LED2_Y_8875, drive0 ? 0xFA00 : 0x0000); drawPixel(x+(use8875 ? LED2_X_8875 : LED2_X_9341), y+(use8875 ? LED2_Y_8875 : LED2_Y_9341), drive0 ? 0xFA00 : 0x0000);
} }
} }
@ -147,7 +176,8 @@ void SDLDisplay::drawImageOfSizeAt(const uint8_t *img,
uint16_t v = *p++; uint16_t v = *p++;
v<<=8; v<<=8;
v |= *p++; v |= *p++;
videoBuffer[(y+wherey)][(x+wherex)] = color16To32(v); videoBuffer[(y+wherey) * (use8875 ? RA8875_WIDTH : ILI9341_WIDTH) +
(x+wherex)] = color16To32(v);
} }
} }
} }
@ -162,7 +192,11 @@ void SDLDisplay::blit()
&pitch); &pitch);
// FIXME what if pitch isn't as expected? Should be width*4 // FIXME what if pitch isn't as expected? Should be width*4
memcpy(pixels, videoBuffer, sizeof(videoBuffer)); static uint32_t bufsize = 0;
if (!bufsize) {
bufsize = use8875 ? (RA8875_WIDTH*RA8875_HEIGHT*sizeof(uint32_t)) : (ILI9341_HEIGHT*ILI9341_WIDTH*sizeof(uint32_t));
}
memcpy(pixels, videoBuffer, bufsize);
SDL_UnlockTexture(buffer); SDL_UnlockTexture(buffer);
SDL_RenderCopy(renderer, buffer, NULL, NULL); SDL_RenderCopy(renderer, buffer, NULL, NULL);
@ -177,7 +211,10 @@ inline void putpixel(SDL_Renderer *renderer, int x, int y, uint8_t r, uint8_t g,
void SDLDisplay::drawPixel(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 if (use8875 && (x >= RA8875_WIDTH || y >= RA8875_HEIGHT))
return;
if ((!use8875) && (x >= ILI9341_WIDTH || y >= ILI9341_HEIGHT))
return;
uint8_t uint8_t
r = (color & 0xF800) >> 8, r = (color & 0xF800) >> 8,
@ -189,9 +226,12 @@ 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) void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
{ {
if (x < SDL_WIDTH && y < SDL_HEIGHT) { if (use8875 && (x >= RA8875_WIDTH || y >= RA8875_HEIGHT))
putpixel(renderer, x, y, r, g, b); return;
} if ((!use8875) && (x >= ILI9341_WIDTH || y >= ILI9341_HEIGHT))
return;
putpixel(renderer, x, y, r, g, b);
} }
void SDLDisplay::clrScr(uint8_t coloridx) void SDLDisplay::clrScr(uint8_t coloridx)
@ -202,36 +242,66 @@ void SDLDisplay::clrScr(uint8_t coloridx)
uint32_t packedColor = packColor32(loresPixelColors[coloridx]); uint32_t packedColor = packColor32(loresPixelColors[coloridx]);
for (uint16_t y=0; y<SDL_HEIGHT; y++) { for (uint16_t y=0; y<(use8875 ? RA8875_HEIGHT : ILI9341_HEIGHT); y++) {
for (uint16_t x=0; x<SDL_WIDTH; x++) { for (uint16_t x=0; x<(use8875 ? RA8875_WIDTH : ILI9341_WIDTH); x++) {
videoBuffer[y][x] = packedColor; videoBuffer[y*(use8875 ? RA8875_WIDTH : ILI9341_WIDTH) + x] = packedColor;
} }
} }
} }
void SDLDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color) void SDLDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
{ {
for (int yoff=0; yoff<2; yoff++) { if (use8875) {
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][x+SCREENINSET_8875_X] = packColor32(loresPixelColors[color]); for (int yoff=0; yoff<2; yoff++) {
videoBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH +
x+SCREENINSET_8875_X] = packColor32(loresPixelColors[color]);
}
} else {
if (x&1) {
uint32_t origColor =videoBuffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH+(x>>1)+SCREENINSET_9341_X];
if (g_displayType == m_blackAndWhite) {
uint32_t blendedColor = blendColors(origColor, color);
uint32_t luminance = luminanceFromRGB((blendedColor & 0xFF0000)>>16,
(blendedColor & 0x00FF00)>> 8,
(blendedColor & 0x0000FF));
cacheDoubleWidePixel(x>>1,y,(uint32_t)((luminance >= g_luminanceCutoff) ? 0xFFFFFF : 0x000000));
} else {
cacheDoubleWidePixel(x>>1, y, color);
}
} else {
// All of the even pixels get drawn...
cacheDoubleWidePixel(x>>1, y, color);
}
} }
} }
// "DoubleWide" means "please double the X because I'm in low-res width mode" // "DoubleWide" means "please double the X because I'm in low-res width mode"
void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color) void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
{ {
for (int yoff=0; yoff<2; yoff++) { if (use8875) {
for (int xoff=0; xoff<2; xoff++) { for (int yoff=0; yoff<2; yoff++) {
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x*2)+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[color]); for (int xoff=0; xoff<2; xoff++) {
videoBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH +
(x*2)+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[color]);
}
} }
} else {
videoBuffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = packColor32(loresPixelColors[color]);
} }
} }
void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedColor) void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedColor)
{ {
for (int yoff=0; yoff<2; yoff++) { if (use8875) {
for (int xoff=0; xoff<2; xoff++) { for (int yoff=0; yoff<2; yoff++) {
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x*2)+SCREENINSET_8875_X+xoff] = packedColor; for (int xoff=0; xoff<2; xoff++) {
videoBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH +
(x*2)+SCREENINSET_8875_X+xoff] = packedColor;
}
} }
} else {
videoBuffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = packedColor;
} }
} }
@ -239,11 +309,15 @@ void SDLDisplay::windowResized(uint32_t w, uint32_t h)
{ {
// Preserve the aspect ratio // Preserve the aspect ratio
float aspectRatio = (float)w/(float)h; float aspectRatio = (float)w/(float)h;
if (aspectRatio != ((float)SDL_WIDTH)/((float)SDL_HEIGHT)) {
if (aspectRatio > ((float)SDL_WIDTH)/((float)SDL_HEIGHT)) { float expectedWidth = use8875 ? RA8875_WIDTH : ILI9341_WIDTH;
h = ((1.f * ((float)SDL_HEIGHT)) / ((float)SDL_WIDTH)) * w; float expectedHeight = use8875 ? RA8875_HEIGHT : ILI9341_HEIGHT;
if (aspectRatio != ((float)expectedWidth)/((float)expectedHeight)) {
if (aspectRatio > ((float)expectedWidth)/((float)expectedHeight)) {
h = ((1.f * ((float)expectedHeight)) / ((float)expectedWidth)) * w;
} else { } else {
w = (((float)SDL_WIDTH)/((float)SDL_HEIGHT)) * h; w = (((float)expectedWidth)/((float)expectedHeight)) * h;
} }
} }

View File

@ -8,8 +8,8 @@
#include "physicaldisplay.h" #include "physicaldisplay.h"
#define SDL_WIDTH 800 //#define SDL_WIDTH 800
#define SDL_HEIGHT 480 //#define SDL_HEIGHT 480
class SDLDisplay : public PhysicalDisplay { class SDLDisplay : public PhysicalDisplay {
public: public:
@ -37,7 +37,7 @@ class SDLDisplay : public PhysicalDisplay {
void windowResized(uint32_t w, uint32_t h); void windowResized(uint32_t w, uint32_t h);
private: private:
uint32_t videoBuffer[SDL_HEIGHT][SDL_WIDTH]; uint32_t *videoBuffer;
SDL_Window *screen; SDL_Window *screen;
SDL_Renderer *renderer; SDL_Renderer *renderer;