mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 15:15:43 +00:00
Add basic CPU LCD controller support
This commit is contained in:
80
src/dbvz.c
80
src/dbvz.c
@@ -10,6 +10,7 @@
|
||||
#include "ads7846.h"
|
||||
#include "sdCard.h"
|
||||
#include "audio/blip_buf.h"
|
||||
#include "m68k/m68k.h"
|
||||
#include "debug/sandbox.h"
|
||||
|
||||
|
||||
@@ -18,6 +19,9 @@
|
||||
|
||||
dbvz_chip_t dbvzChipSelects[DBVZ_CHIP_END];
|
||||
uint8_t dbvzReg[DBVZ_REG_SIZE];
|
||||
uint16_t* dbvzFramebuffer;
|
||||
uint16_t dbvzFramebufferWidth;
|
||||
uint16_t dbvzFramebufferHeight;
|
||||
|
||||
static bool dbvzInterruptChanged;//reduces time wasted on checking interrupts that where updated to a new value identical to the old one, does not need to be in states
|
||||
static double dbvzSysclksPerClk32;//how many SYSCLK cycles before toggling the 32.768 kHz crystal
|
||||
@@ -54,6 +58,81 @@ static int32_t audioGetFramePercentage(void);
|
||||
#include "dbvzRegisterAccessors.c.h"
|
||||
#include "dbvzTiming.c.h"
|
||||
|
||||
void dbvzLcdRender(void){
|
||||
static const uint16_t masterColorLut[16] = {0xFFFF, 0xEEEE, 0xDDDD, 0xCCCC, 0xBBBB, 0xAAAA, 0x9999, 0x8888, 0x7777, 0x6666, 0x5555, 0x4444, 0x3333, 0x2222, 0x1111, 0x0000};//TODO: get a real LUT
|
||||
static const uint8_t bppLut[4] = {1, 4, 16, 4/*invaild, assume most common value*/};
|
||||
uint16_t colorLut2Bpp[4];//stores indexes to masterColorLut
|
||||
uint32_t startAddress = registerArrayRead32(LSSA);
|
||||
uint8_t bitsPerPixel = bppLut[registerArrayRead8(LPICF) & 0x03];
|
||||
uint16_t pageWidth = registerArrayRead8(LVPW) * 2;//in bytes
|
||||
bool invertColors = registerArrayRead8(LPOLCF) & 0x01;
|
||||
uint8_t pixelShift = registerArrayRead8(LPOSR);
|
||||
uint16_t width = FAST_MIN(registerArrayRead16(LXMAX), dbvzFramebufferWidth);
|
||||
uint16_t height = FAST_MIN(registerArrayRead16(LYMAX), dbvzFramebufferHeight);
|
||||
uint16_t y;
|
||||
uint16_t x;
|
||||
|
||||
//TODO: cursor not implemented, not that anything will use a hardware terminal cursor on Palm OS
|
||||
|
||||
switch(bitsPerPixel){
|
||||
case 1:
|
||||
for(y = 0; y < height; y++){
|
||||
for(x = 0; x < width / 16; x++){
|
||||
uint16_t dataUnit = m68k_read_memory_16(startAddress + y * pageWidth + x * 2);
|
||||
uint8_t index;
|
||||
|
||||
for(index = 0; index < 16; index++)
|
||||
if(x * 16 + index >= pixelShift)
|
||||
dbvzFramebuffer[y * dbvzFramebufferWidth + x * 16 + index - pixelShift] = !!(dataUnit & 1 << 16 - index) == invertColors ? masterColorLut[0] : masterColorLut[15];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
colorLut2Bpp[0] = 0;
|
||||
colorLut2Bpp[1] = registerArrayRead8(LGPMR) & 0x0F;
|
||||
colorLut2Bpp[2] = registerArrayRead8(LGPMR) >> 4;
|
||||
colorLut2Bpp[3] = 15;
|
||||
|
||||
for(y = 0; y < height; y++){
|
||||
for(x = 0; x < width / 8; x++){
|
||||
uint16_t dataUnit = m68k_read_memory_16(startAddress + y * pageWidth + x * 2);
|
||||
uint8_t index;
|
||||
|
||||
for(index = 0; index < 8; index++)
|
||||
if(x * 8 + index >= pixelShift)
|
||||
dbvzFramebuffer[y * dbvzFramebufferWidth + x * 8 + index - pixelShift] = invertColors ? masterColorLut[15 - colorLut2Bpp[dataUnit >> 14 - index * 2 & 0x03]] : masterColorLut[colorLut2Bpp[dataUnit >> 14 - index * 2 & 0x03]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
for(y = 0; y < height; y++){
|
||||
for(x = 0; x < width / 4; x++){
|
||||
uint16_t dataUnit = m68k_read_memory_16(startAddress + y * pageWidth + x * 2);
|
||||
uint8_t index;
|
||||
|
||||
for(index = 0; index < 4; index++)
|
||||
if(x * 4 + index >= pixelShift)
|
||||
dbvzFramebuffer[y * dbvzFramebufferWidth + x * 4 + index - pixelShift] = invertColors ? masterColorLut[15 - (dataUnit >> 12 - index * 4 & 0x0F)] : masterColorLut[dataUnit >> 12 - index * 4 & 0x0F];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
debugLog("Invalid DBVZ LCD controller pixel depth!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool dbvzLcdEnabled(void){
|
||||
//if LSSA is set to something other than the Palm OS constant render from it instead of the SED1376
|
||||
//the enable bit is perpously ignored because it is managed by the OS and apps may not set it
|
||||
//return palmAllowInvalidBehavior && registerArrayRead32(LSSA) != 0xBADC0DE0;
|
||||
//return palmAllowInvalidBehavior && registerArrayRead8(LCKCON) & 0x80;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dbvzIsPllOn(void){
|
||||
return !(dbvzSysclksPerClk32 < 1.0);
|
||||
}
|
||||
@@ -540,6 +619,7 @@ uint32_t dbvzGetRegister32(uint32_t address){
|
||||
case IMR:
|
||||
case RTCTIME:
|
||||
case IDR:
|
||||
case LSSA:
|
||||
//simple read, no actions needed
|
||||
return registerArrayRead32(address);
|
||||
|
||||
|
||||
@@ -66,8 +66,13 @@ typedef struct{
|
||||
//variables
|
||||
extern dbvz_chip_t dbvzChipSelects[];
|
||||
extern uint8_t dbvzReg[];//needed for direct execution of the DBVZ regs without a RAM access function
|
||||
extern uint16_t* dbvzFramebuffer;
|
||||
extern uint16_t dbvzFramebufferWidth;
|
||||
extern uint16_t dbvzFramebufferHeight;
|
||||
|
||||
//CPU
|
||||
void dbvzLcdRender(void);
|
||||
bool dbvzLcdEnabled(void);
|
||||
bool dbvzIsPllOn(void);
|
||||
bool m515BacklightAmplifierState(void);
|
||||
bool dbvzAreRegistersXXFFMapped(void);
|
||||
|
||||
@@ -150,10 +150,12 @@
|
||||
#define LCWCH 0xA1C/*Cursor Width & Height Register*/
|
||||
#define LBLKC 0xA1F/*Blink Control Register*/
|
||||
#define LPICF 0xA20/*Panel Interface Config Register*/
|
||||
#define LPOLCF 0xA21/*LCD Polarity Configuration Register*/
|
||||
#define LPXCD 0xA25/*Pixel Clock Divider Register*/
|
||||
#define LCKCON 0xA27/*Clocking Control Register*/
|
||||
#define LRRA 0xA28/*LCD Refresh Rate Adjustment Register*/
|
||||
/*Reserved 0xA2B Octet Terminal Count Register On Original Dragonball*/
|
||||
#define LPOSR 0xA2D/*LCD Panning Offset Register*/
|
||||
#define LFRCM 0xA31/*Frame Rate Control Modulation Register*/
|
||||
#define LGPMR 0xA33/*Gray Palette Mapping Register*/
|
||||
#define DMACR 0xA39/*DMA Control Register*/
|
||||
|
||||
@@ -182,6 +182,11 @@ uint32_t emulatorInit(uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmB
|
||||
palmCycleCounter = 0.0;
|
||||
palmClockMultiplier = 1.00 - DBVZ_CPU_PERCENT_WAITING;
|
||||
sed1376Framebuffer = palmFramebuffer;
|
||||
sed1376FramebufferWidth = 160;
|
||||
sed1376FramebufferHeight = 160;
|
||||
dbvzFramebuffer = palmFramebuffer;
|
||||
dbvzFramebufferWidth = 160;
|
||||
dbvzFramebufferHeight = 160;
|
||||
|
||||
//initialize components
|
||||
blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
|
||||
@@ -745,7 +750,10 @@ void emulatorRunFrame(void){
|
||||
dbvzExecute();
|
||||
|
||||
//LCD controller
|
||||
sed1376Render();
|
||||
if(dbvzLcdEnabled())
|
||||
dbvzLcdRender();
|
||||
else
|
||||
sed1376Render();
|
||||
|
||||
//backlight level, 0% = 1/4 color intensity, 50% = 1/2 color intensity, 100% = full color intensity
|
||||
switch(palmMisc.backlightLevel){
|
||||
@@ -792,7 +800,12 @@ void emulatorSkipFrame(void){
|
||||
dbvzExecute();
|
||||
|
||||
//LCD controller, skip this
|
||||
//sed1376Render();
|
||||
/*
|
||||
if(dbvzLcdEnabled())
|
||||
dbvzLcdRender();
|
||||
else
|
||||
sed1376Render();
|
||||
*/
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
|
||||
uint16_t* sed1376Framebuffer;
|
||||
uint16_t sed1376FramebufferWidth;
|
||||
uint16_t sed1376FramebufferHeight;
|
||||
uint8_t sed1376Ram[0x20000];
|
||||
|
||||
static uint8_t sed1376Registers[0xB4];
|
||||
@@ -366,9 +368,9 @@ void sed1376Render(void){
|
||||
uint16_t pixelX;
|
||||
uint16_t pixelY;
|
||||
|
||||
MULTITHREAD_DOUBLE_LOOP(pixelX, pixelY) for(pixelY = 0; pixelY < 160; pixelY++)
|
||||
for(pixelX = 0; pixelX < 160; pixelX++)
|
||||
sed1376Framebuffer[pixelY * 160 + pixelX] = sed1376RenderPixel(pixelX, pixelY);
|
||||
MULTITHREAD_DOUBLE_LOOP(pixelX, pixelY) for(pixelY = 0; pixelY < sed1376FramebufferHeight; pixelY++)
|
||||
for(pixelX = 0; pixelX < sed1376FramebufferWidth; pixelX++)
|
||||
sed1376Framebuffer[pixelY * sed1376FramebufferWidth + pixelX] = sed1376RenderPixel(pixelX, pixelY);
|
||||
|
||||
//debugLog("Screen start address:0x%08X, buffer width:%d, swivel view:%d degrees\n", sed1376ScreenStartAddress, lineSize, rotation);
|
||||
//debugLog("Screen format, color:%s, BPP:%d\n", boolString(color), bitDepth);
|
||||
@@ -389,14 +391,14 @@ void sed1376Render(void){
|
||||
}
|
||||
//debugLog("PIP state, start x:%d, end x:%d, start y:%d, end y:%d\n", pipStartX, pipEndX, pipStartY, pipEndY);
|
||||
//render PIP only if PIP window is onscreen
|
||||
if(pipStartX < 160 && pipStartY < 160){
|
||||
pipEndX = FAST_MIN(pipEndX, 160);
|
||||
pipEndY = FAST_MIN(pipEndY, 160);
|
||||
if(pipStartX < sed1376FramebufferWidth && pipStartY < sed1376FramebufferHeight){
|
||||
pipEndX = FAST_MIN(pipEndX, sed1376FramebufferWidth);
|
||||
pipEndY = FAST_MIN(pipEndY, sed1376FramebufferHeight);
|
||||
sed1376ScreenStartAddress = sed1376GetPipStartAddress();
|
||||
sed1376LineSize = (sed1376Registers[PIP_LINE_SZ_1] << 8 | sed1376Registers[PIP_LINE_SZ_0]) * 4;
|
||||
MULTITHREAD_DOUBLE_LOOP(pixelX, pixelY) for(pixelY = pipStartY; pixelY < pipEndY; pixelY++)
|
||||
for(pixelX = pipStartX; pixelX < pipEndX; pixelX++)
|
||||
sed1376Framebuffer[pixelY * 160 + pixelX] = sed1376RenderPixel(pixelX, pixelY);
|
||||
sed1376Framebuffer[pixelY * sed1376FramebufferWidth + pixelX] = sed1376RenderPixel(pixelX, pixelY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +407,7 @@ void sed1376Render(void){
|
||||
|
||||
//display inversion
|
||||
if((sed1376Registers[DISP_MODE] & 0x30) == 0x10)
|
||||
MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++)
|
||||
MULTITHREAD_LOOP(index) for(index = 0; index < sed1376FramebufferWidth * sed1376FramebufferHeight; index++)
|
||||
sed1376Framebuffer[index] = ~sed1376Framebuffer[index];
|
||||
}
|
||||
else{
|
||||
@@ -414,7 +416,7 @@ void sed1376Render(void){
|
||||
}
|
||||
else{
|
||||
//black screen
|
||||
memset(sed1376Framebuffer, 0x00, 160 * 160 * sizeof(uint16_t));
|
||||
memset(sed1376Framebuffer, 0x00, sed1376FramebufferWidth * sed1376FramebufferHeight * sizeof(uint16_t));
|
||||
debugLog("Cant draw screen, LCD on:%s, PLL on:%s, power save on:%s, forced blank on:%s\n", palmMisc.lcdOn ? "true" : "false", dbvzIsPllOn() ? "true" : "false", sed1376PowerSaveEnabled() ? "true" : "false", !!(sed1376Registers[DISP_MODE] & 0x80) ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
extern uint16_t* sed1376Framebuffer;
|
||||
extern uint16_t sed1376FramebufferWidth;
|
||||
extern uint16_t sed1376FramebufferHeight;
|
||||
extern uint8_t sed1376Ram[];
|
||||
|
||||
void sed1376Reset(void);
|
||||
|
||||
Reference in New Issue
Block a user