mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 15:15:43 +00:00
Allow any custom fb size part 2
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
#define JOYSTICK_DEADZONE 4000
|
||||
#define JOYSTICK_MULTIPLIER 0.0001
|
||||
#define SCREEN_HIRES (!(palmFramebufferWidth == 160 && palmFramebufferHeight == 220))
|
||||
|
||||
|
||||
static retro_log_printf_t log_cb;
|
||||
@@ -28,10 +29,6 @@ static retro_environment_t environ_cb;
|
||||
static retro_input_poll_t input_poll_cb;
|
||||
static retro_input_state_t input_state_cb;
|
||||
|
||||
static bool screenHires;
|
||||
static uint16_t screenWidth;
|
||||
static uint16_t screenHeight;
|
||||
static uint16_t screenData[480 * 480];
|
||||
static uint32_t emuFeatures;
|
||||
static bool useJoystickAsMouse;
|
||||
static float touchCursorX;
|
||||
@@ -39,7 +36,7 @@ static float touchCursorY;
|
||||
|
||||
|
||||
static void renderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
if(screenHires){
|
||||
if(SCREEN_HIRES){
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
|
||||
@@ -48,9 +45,9 @@ static void renderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
|
||||
for(y = 0; y < 32; y++)
|
||||
for(x = 6; x < 26; x++)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < screenWidth && screenY + y < screenHeight)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
|
||||
if(cursor32x32[y * 32 + x] != 0xFFFF)
|
||||
screenData[(screenY + y) * screenWidth + screenX + x] = cursor32x32[y * 32 + x];
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor32x32[y * 32 + x];
|
||||
}
|
||||
else{
|
||||
int8_t x;
|
||||
@@ -61,9 +58,9 @@ static void renderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
|
||||
for(y = 0; y < 16; y++)
|
||||
for(x = 3; x < 13; x++)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < screenWidth && screenY + y < screenHeight)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
|
||||
if(cursor16x16[y * 16 + x] != 0xFFFF)
|
||||
screenData[(screenY + y) * screenWidth + screenX + x] = cursor16x16[y * 16 + x];
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor16x16[y * 16 + x];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,23 +251,23 @@ void retro_run(void){
|
||||
int16_t y = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y);
|
||||
|
||||
if(x < -JOYSTICK_DEADZONE || x > JOYSTICK_DEADZONE)
|
||||
touchCursorX += x * JOYSTICK_MULTIPLIER * (screenHires ? 2.0 : 1.0);
|
||||
touchCursorX += x * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0);
|
||||
|
||||
if(y < -JOYSTICK_DEADZONE || y > JOYSTICK_DEADZONE)
|
||||
touchCursorY += y * JOYSTICK_MULTIPLIER * (screenHires ? 2.0 : 1.0);
|
||||
touchCursorY += y * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0);
|
||||
|
||||
if(touchCursorX < 0)
|
||||
touchCursorX = 0;
|
||||
else if(touchCursorX > screenWidth - 1)
|
||||
touchCursorX = screenWidth - 1;
|
||||
else if(touchCursorX > palmFramebufferWidth - 1)
|
||||
touchCursorX = palmFramebufferWidth - 1;
|
||||
|
||||
if(touchCursorY < 0)
|
||||
touchCursorY = 0;
|
||||
else if(touchCursorY > screenHeight - 1)
|
||||
touchCursorY = screenHeight - 1;
|
||||
else if(touchCursorY > palmFramebufferHeight - 1)
|
||||
touchCursorY = palmFramebufferHeight - 1;
|
||||
|
||||
palmInput.touchscreenX = touchCursorX / (screenWidth - 1);
|
||||
palmInput.touchscreenY = touchCursorY / (screenHeight - 1);
|
||||
palmInput.touchscreenX = touchCursorX / (palmFramebufferWidth - 1);
|
||||
palmInput.touchscreenY = touchCursorY / (palmFramebufferHeight - 1);
|
||||
palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
|
||||
}
|
||||
else{
|
||||
@@ -298,13 +295,12 @@ void retro_run(void){
|
||||
|
||||
//run emulator
|
||||
emulatorRunFrame();
|
||||
memcpy(screenData, screenHires ? palmExtendedFramebuffer : palmFramebuffer, screenWidth * screenHeight * sizeof(uint16_t));
|
||||
|
||||
//draw mouse
|
||||
if(useJoystickAsMouse)
|
||||
renderMouseCursor(touchCursorX, touchCursorY);
|
||||
|
||||
video_cb(screenData, screenWidth, screenHeight, screenWidth * sizeof(uint16_t));
|
||||
video_cb(palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t));
|
||||
audio_cb(palmAudio, AUDIO_SAMPLES_PER_FRAME);
|
||||
}
|
||||
|
||||
@@ -378,11 +374,9 @@ bool retro_load_game(const struct retro_game_info *info){
|
||||
timeInfo = localtime(&rawTime);
|
||||
emulatorSetRtc(timeInfo->tm_yday, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
|
||||
|
||||
screenHires = emuFeatures & FEATURE_CUSTOM_FB;
|
||||
screenWidth = screenHires ? 320 : 160;
|
||||
screenHeight = screenHires ? 440 : 220;
|
||||
touchCursorX = screenWidth / 2;
|
||||
touchCursorY = screenHeight / 2;
|
||||
//set mouse position
|
||||
touchCursorX = palmFramebufferWidth / 2;
|
||||
touchCursorY = palmFramebufferHeight / 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,8 +67,6 @@ EmuWrapper::EmuWrapper(){
|
||||
emuThreadJoin = false;
|
||||
emuRunning = false;
|
||||
emuPaused = false;
|
||||
emuVideoWidth = 0;
|
||||
emuVideoHeight = 0;
|
||||
emuNewFrameReady = false;
|
||||
|
||||
frontendDebugString = new char[200];
|
||||
@@ -189,15 +187,6 @@ uint32_t EmuWrapper::init(const QString& romPath, const QString& bootloaderPath,
|
||||
}
|
||||
}
|
||||
|
||||
if(features & FEATURE_CUSTOM_FB){
|
||||
emuVideoWidth = 320;
|
||||
emuVideoHeight = 320 + 120;
|
||||
}
|
||||
else{
|
||||
emuVideoWidth = 160;
|
||||
emuVideoHeight = 160 + 60;
|
||||
}
|
||||
|
||||
emuInput = palmInput;
|
||||
emuRamFilePath = ramPath;
|
||||
emuSdCardFilePath = sdCardPath;
|
||||
|
||||
@@ -21,8 +21,6 @@ private:
|
||||
std::atomic<bool> emuThreadJoin;
|
||||
std::atomic<bool> emuRunning;
|
||||
std::atomic<bool> emuPaused;
|
||||
uint16_t emuVideoWidth;
|
||||
uint16_t emuVideoHeight;
|
||||
std::atomic<bool> emuNewFrameReady;
|
||||
QString emuRamFilePath;
|
||||
QString emuSdCardFilePath;
|
||||
@@ -51,13 +49,13 @@ public:
|
||||
std::vector<uint64_t>& getDuplicateCallCount();
|
||||
std::vector<uint32_t> getCpuRegisters();
|
||||
|
||||
uint16_t screenWidth() const{return emuVideoWidth;}
|
||||
uint16_t screenHeight() const{return emuVideoHeight;}
|
||||
uint16_t screenWidth() const{return palmFramebufferWidth;}
|
||||
uint16_t screenHeight() const{return palmFramebufferHeight;}
|
||||
bool newFrameReady() const{return emuNewFrameReady;}
|
||||
void frameHandled(){emuNewFrameReady = false;}
|
||||
|
||||
//calling these while newFrameReady() == false is undefined behavior, the other thread may be writing to them
|
||||
const QPixmap getFramebuffer(){return QPixmap::fromImage(QImage((uchar*)(emuVideoWidth == 320 ? palmExtendedFramebuffer : palmFramebuffer), emuVideoWidth, emuVideoHeight, emuVideoWidth * sizeof(uint16_t), QImage::Format_RGB16));}
|
||||
const QPixmap getFramebuffer(){return QPixmap::fromImage(QImage((uchar*)palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t), QImage::Format_RGB16));}
|
||||
const int16_t* getAudioSamples() const{return palmAudio;}
|
||||
bool getPowerButtonLed() const{return palmMisc.powerButtonLed;}
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ input_t palmInput;
|
||||
sd_card_t palmSdCard;
|
||||
misc_hw_t palmMisc;
|
||||
uint16_t* palmFramebuffer;
|
||||
uint16_t* palmExtendedFramebuffer;
|
||||
uint16_t palmFramebufferWidth;
|
||||
uint16_t palmFramebufferHeight;
|
||||
int16_t* palmAudio;
|
||||
blip_t* palmAudioResampler;
|
||||
uint32_t palmSpecialFeatures;
|
||||
@@ -61,21 +62,16 @@ uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t spec
|
||||
palmRam = malloc(((specialFeatures & FEATURE_RAM_HUGE) ? SUPERMASSIVE_RAM_SIZE : RAM_SIZE) + 4);
|
||||
palmRom = malloc(ROM_SIZE + 4);
|
||||
palmReg = malloc(REG_SIZE + 4);
|
||||
palmFramebuffer = malloc(160 * (160 + 60) * sizeof(uint16_t));//really 160*160, the extra pixels are the silkscreened digitizer area
|
||||
palmFramebuffer = malloc(480 * 480 * sizeof(uint16_t));
|
||||
palmAudio = malloc(AUDIO_SAMPLES_PER_FRAME * 2 * sizeof(int16_t));
|
||||
palmAudioResampler = blip_new(AUDIO_SAMPLE_RATE);//have 1 second of samples
|
||||
if(specialFeatures & FEATURE_CUSTOM_FB)
|
||||
palmExtendedFramebuffer = malloc(480 * 480 * sizeof(uint16_t));
|
||||
else
|
||||
palmExtendedFramebuffer = NULL;
|
||||
if(!palmRam || !palmRom || !palmReg || !palmFramebuffer || !palmAudio || !palmAudioResampler || (!palmExtendedFramebuffer && (specialFeatures & FEATURE_CUSTOM_FB))){
|
||||
if(!palmRam || !palmRom || !palmReg || !palmFramebuffer || !palmAudio || !palmAudioResampler){
|
||||
free(palmRam);
|
||||
free(palmRom);
|
||||
free(palmReg);
|
||||
free(palmFramebuffer);
|
||||
free(palmAudio);
|
||||
blip_delete(palmAudioResampler);
|
||||
free(palmExtendedFramebuffer);
|
||||
return EMU_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -94,15 +90,11 @@ uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t spec
|
||||
else{
|
||||
memset(palmReg + REG_SIZE - 1 - BOOTLOADER_SIZE, 0x00, BOOTLOADER_SIZE);
|
||||
}
|
||||
memset(palmFramebuffer, 0x00, 160 * 160 * sizeof(uint16_t));
|
||||
memcpy(palmFramebuffer + 160 * 160, silkscreen160x60, 160 * 60 * sizeof(uint16_t));
|
||||
if(palmExtendedFramebuffer){
|
||||
memset(palmExtendedFramebuffer, 0x00, 320 * 320 * sizeof(uint16_t));
|
||||
memcpy(palmExtendedFramebuffer + 320 * 320, silkscreen320x120, 320 * 120 * sizeof(uint16_t));
|
||||
}
|
||||
memset(palmAudio, 0x00, AUDIO_SAMPLES_PER_FRAME * 2/*channels*/ * sizeof(int16_t));
|
||||
memset(&palmInput, 0x00, sizeof(palmInput));
|
||||
memset(&palmMisc, 0x00, sizeof(palmMisc));
|
||||
palmFramebufferWidth = 160;
|
||||
palmFramebufferHeight = 220;
|
||||
palmMisc.batteryLevel = 100;
|
||||
palmCycleCounter = 0.0;
|
||||
palmClockMultiplier = (specialFeatures & FEATURE_FAST_CPU) ? 2.00 : 1.00;//overclock
|
||||
@@ -137,7 +129,6 @@ void emulatorExit(void){
|
||||
free(palmFramebuffer);
|
||||
free(palmAudio);
|
||||
blip_delete(palmAudioResampler);
|
||||
free(palmExtendedFramebuffer);
|
||||
free(palmSdCard.flashChip.data);
|
||||
emulatorInitialized = false;
|
||||
}
|
||||
@@ -146,9 +137,8 @@ void emulatorExit(void){
|
||||
void emulatorHardReset(void){
|
||||
//equivalent to taking the battery out and putting it back in
|
||||
memset(palmRam, 0x00, palmSpecialFeatures & FEATURE_RAM_HUGE ? SUPERMASSIVE_RAM_SIZE : RAM_SIZE);
|
||||
memset(palmFramebuffer, 0x00, 160 * 160 * sizeof(uint16_t));
|
||||
if(palmExtendedFramebuffer)
|
||||
memset(palmExtendedFramebuffer, 0x00, 320 * 320 * sizeof(uint16_t));
|
||||
palmFramebufferWidth = 160;
|
||||
palmFramebufferHeight = 220;
|
||||
flx68000Reset();
|
||||
sed1376Reset();
|
||||
ads7846Reset();
|
||||
@@ -159,6 +149,8 @@ void emulatorHardReset(void){
|
||||
|
||||
void emulatorSoftReset(void){
|
||||
//equivalent to pushing the reset button on the back of the device
|
||||
palmFramebufferWidth = 160;
|
||||
palmFramebufferHeight = 220;
|
||||
flx68000Reset();
|
||||
sed1376Reset();
|
||||
ads7846Reset();
|
||||
@@ -176,6 +168,7 @@ uint64_t emulatorGetStateSize(void){
|
||||
size += sizeof(uint32_t);//save state version
|
||||
size += sizeof(uint32_t);//palmSpecialFeatures
|
||||
size += sizeof(uint64_t);//palmSdCard.flashChip.size, needs to be done first to verify the malloc worked
|
||||
size += sizeof(uint16_t) * 2;//palmFramebuffer(Width/Height)
|
||||
size += flx68000StateSize();
|
||||
size += sed1376StateSize();
|
||||
size += ads7846StateSize();
|
||||
@@ -228,6 +221,12 @@ bool emulatorSaveState(buffer_t buffer){
|
||||
writeStateValue64(buffer.data + offset, palmSdCard.flashChip.size);
|
||||
offset += sizeof(uint64_t);
|
||||
|
||||
//screen state
|
||||
writeStateValue16(buffer.data + offset, palmFramebufferWidth);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValue16(buffer.data + offset, palmFramebufferHeight);
|
||||
offset += sizeof(uint16_t);
|
||||
|
||||
//chips
|
||||
flx68000SaveState(buffer.data + offset);
|
||||
offset += flx68000StateSize();
|
||||
@@ -385,6 +384,12 @@ bool emulatorLoadState(buffer_t buffer){
|
||||
return false;
|
||||
offset += sizeof(uint64_t);
|
||||
|
||||
//screen state
|
||||
palmFramebufferWidth = readStateValue16(buffer.data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
palmFramebufferHeight = readStateValue16(buffer.data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
|
||||
//chips
|
||||
flx68000LoadState(buffer.data + offset);
|
||||
offset += flx68000StateSize();
|
||||
@@ -609,27 +614,13 @@ void emulatorRunFrame(void){
|
||||
|
||||
//video
|
||||
sed1376Render();
|
||||
|
||||
//render in 320x320 mode
|
||||
if(palmExtendedFramebuffer){
|
||||
uint16_t pixCopyX;
|
||||
uint16_t pixCopyY;
|
||||
|
||||
//scale original framebuffer to large one if enabled, this alone doesnt increase resolution, that requires a driver
|
||||
//scale horizontal
|
||||
MULTITHREAD_DOUBLE_LOOP(pixCopyX, pixCopyY) for(pixCopyY = 0; pixCopyY < 160; pixCopyY++){
|
||||
for(pixCopyX = 0; pixCopyX < 160; pixCopyX++){
|
||||
palmExtendedFramebuffer[pixCopyY * 320 * 2 + pixCopyX * 2] = palmFramebuffer[pixCopyY * 160 + pixCopyX];
|
||||
palmExtendedFramebuffer[pixCopyY * 320 * 2 + pixCopyX * 2 + 1] = palmFramebuffer[pixCopyY * 160 + pixCopyX];
|
||||
}
|
||||
}
|
||||
//scale vertical
|
||||
MULTITHREAD_LOOP(pixCopyY) for(pixCopyY = 0; pixCopyY < 160; pixCopyY++)
|
||||
memcpy(palmExtendedFramebuffer + pixCopyY * 320 * 2 + 320, palmExtendedFramebuffer + pixCopyY * 320 * 2, 320 * sizeof(uint16_t));
|
||||
|
||||
|
||||
//replace all black pixels in 160x160 with those from 320x320 framebuffer memory, only if black in both buffers will the display color be black, this allows all the 160x160 APIs to work on the larger framebuffer seamlessly
|
||||
if(palmFramebufferWidth == 160 && palmFramebufferHeight == 220){
|
||||
//simple render
|
||||
memcpy(palmFramebuffer, sed1376Framebuffer, 160 * 160 * sizeof(uint16_t));
|
||||
memcpy(palmFramebuffer + 160 * 160, silkscreen160x60, 160 * 60 * sizeof(uint16_t));
|
||||
}
|
||||
else{
|
||||
//advanced render
|
||||
//DRIVER NEEDS TO BE WRITTEN STILL
|
||||
//the above was enabled early so using the hires silkscreen and mouse cursor was possible in RetroArch
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +124,9 @@ extern uint8_t* palmReg;//dont touch
|
||||
extern input_t palmInput;//write allowed
|
||||
extern sd_card_t palmSdCard;//dont touch
|
||||
extern misc_hw_t palmMisc;//read/write allowed
|
||||
extern uint16_t* palmFramebuffer;//read allowed if FEATURE_320x320 is off, or else invalid data will be displayed
|
||||
extern uint16_t* palmExtendedFramebuffer;//read allowed if FEATURE_320x320 is on, or else SIGSEGV
|
||||
extern uint16_t* palmFramebuffer;//read allowed
|
||||
extern uint16_t palmFramebufferWidth;//read allowed
|
||||
extern uint16_t palmFramebufferHeight;//read allowed
|
||||
extern int16_t* palmAudio;//read allowed, 2 channel signed 16 bit audio
|
||||
extern blip_t* palmAudioResampler;//dont touch
|
||||
extern uint32_t palmSpecialFeatures;//read allowed
|
||||
|
||||
@@ -33,7 +33,7 @@ static uint8_t sed1376Read8(uint32_t address){
|
||||
return 0x00;
|
||||
#endif
|
||||
if(address & SED1376_MR_BIT)
|
||||
return BUFFER_READ_8_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask);
|
||||
return BUFFER_READ_8_BIG_ENDIAN(sed1376Ram, address, chips[CHIP_B0_SED].mask);
|
||||
else
|
||||
return sed1376GetRegister(address & chips[CHIP_B0_SED].mask);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ static uint16_t sed1376Read16(uint32_t address){
|
||||
return 0x0000;
|
||||
#endif
|
||||
if(address & SED1376_MR_BIT)
|
||||
return BUFFER_READ_16_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask);
|
||||
return BUFFER_READ_16_BIG_ENDIAN(sed1376Ram, address, chips[CHIP_B0_SED].mask);
|
||||
else
|
||||
return sed1376GetRegister(address & chips[CHIP_B0_SED].mask);
|
||||
}
|
||||
@@ -53,25 +53,25 @@ static uint32_t sed1376Read32(uint32_t address){
|
||||
return 0x00000000;
|
||||
#endif
|
||||
if(address & SED1376_MR_BIT)
|
||||
return BUFFER_READ_32_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask);
|
||||
return BUFFER_READ_32_BIG_ENDIAN(sed1376Ram, address, chips[CHIP_B0_SED].mask);
|
||||
else
|
||||
return sed1376GetRegister(address & chips[CHIP_B0_SED].mask);
|
||||
}
|
||||
static void sed1376Write8(uint32_t address, uint8_t value){
|
||||
if(address & SED1376_MR_BIT)
|
||||
BUFFER_WRITE_8_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask, value);
|
||||
BUFFER_WRITE_8_BIG_ENDIAN(sed1376Ram, address, chips[CHIP_B0_SED].mask, value);
|
||||
else
|
||||
sed1376SetRegister(address & chips[CHIP_B0_SED].mask, value);
|
||||
}
|
||||
static void sed1376Write16(uint32_t address, uint16_t value){
|
||||
if(address & SED1376_MR_BIT)
|
||||
BUFFER_WRITE_16_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask, value);
|
||||
BUFFER_WRITE_16_BIG_ENDIAN(sed1376Ram, address, chips[CHIP_B0_SED].mask, value);
|
||||
else
|
||||
sed1376SetRegister(address & chips[CHIP_B0_SED].mask, value);
|
||||
}
|
||||
static void sed1376Write32(uint32_t address, uint32_t value){
|
||||
if(address & SED1376_MR_BIT)
|
||||
BUFFER_WRITE_32_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask, value);
|
||||
BUFFER_WRITE_32_BIG_ENDIAN(sed1376Ram, address, chips[CHIP_B0_SED].mask, value);
|
||||
else
|
||||
sed1376SetRegister(address & chips[CHIP_B0_SED].mask, value);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
|
||||
#define SED1376_REG_SIZE 0xB4
|
||||
#define SED1376_LUT_SIZE 0x100
|
||||
#define SED1376_FB_SIZE 0x20000//actual size is 0x14000, but that cant be masked off by address lines so size is increased to prevent buffer overflow
|
||||
#define SED1376_RAM_SIZE 0x20000//actual size is 0x14000, but that cant be masked off by address lines so size is increased to prevent buffer overflow
|
||||
|
||||
|
||||
uint8_t sed1376Framebuffer[SED1376_FB_SIZE];
|
||||
uint16_t sed1376Framebuffer[160 * 160];
|
||||
uint8_t sed1376Ram[SED1376_RAM_SIZE];
|
||||
|
||||
static uint8_t sed1376Registers[SED1376_REG_SIZE];
|
||||
static uint8_t sed1376RLut[SED1376_LUT_SIZE];
|
||||
@@ -112,7 +113,7 @@ void sed1376Reset(void){
|
||||
memset(sed1376RLut, 0x00, SED1376_LUT_SIZE);
|
||||
memset(sed1376GLut, 0x00, SED1376_LUT_SIZE);
|
||||
memset(sed1376BLut, 0x00, SED1376_LUT_SIZE);
|
||||
memset(sed1376Framebuffer, 0x00, SED1376_FB_SIZE);
|
||||
memset(sed1376Ram, 0x00, SED1376_RAM_SIZE);
|
||||
|
||||
palmMisc.backlightLevel = 0;
|
||||
palmMisc.lcdOn = false;
|
||||
@@ -131,7 +132,7 @@ uint64_t sed1376StateSize(void){
|
||||
|
||||
size += SED1376_REG_SIZE;
|
||||
size += SED1376_LUT_SIZE * 3;
|
||||
size += SED1376_FB_SIZE;
|
||||
size += SED1376_RAM_SIZE;
|
||||
|
||||
return size;
|
||||
}
|
||||
@@ -147,8 +148,8 @@ void sed1376SaveState(uint8_t* data){
|
||||
offset += SED1376_LUT_SIZE;
|
||||
memcpy(data + offset, sed1376BLut, SED1376_LUT_SIZE);
|
||||
offset += SED1376_LUT_SIZE;
|
||||
memcpy(data + offset, sed1376Framebuffer, SED1376_FB_SIZE);
|
||||
offset += SED1376_FB_SIZE;
|
||||
memcpy(data + offset, sed1376Ram, SED1376_RAM_SIZE);
|
||||
offset += SED1376_RAM_SIZE;
|
||||
}
|
||||
|
||||
void sed1376LoadState(uint8_t* data){
|
||||
@@ -163,8 +164,8 @@ void sed1376LoadState(uint8_t* data){
|
||||
offset += SED1376_LUT_SIZE;
|
||||
memcpy(sed1376BLut, data + offset, SED1376_LUT_SIZE);
|
||||
offset += SED1376_LUT_SIZE;
|
||||
memcpy(sed1376Framebuffer, data + offset, SED1376_FB_SIZE);
|
||||
offset += SED1376_FB_SIZE;
|
||||
memcpy(sed1376Ram, data + offset, SED1376_RAM_SIZE);
|
||||
offset += SED1376_RAM_SIZE;
|
||||
|
||||
//refresh LUT
|
||||
MULTITHREAD_LOOP(index) for(index = 0; index < SED1376_LUT_SIZE; index++)
|
||||
@@ -338,7 +339,7 @@ void sed1376Render(void){
|
||||
|
||||
MULTITHREAD_DOUBLE_LOOP(pixelX, pixelY) for(pixelY = 0; pixelY < 160; pixelY++)
|
||||
for(pixelX = 0; pixelX < 160; pixelX++)
|
||||
palmFramebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
|
||||
sed1376Framebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
|
||||
|
||||
//debugLog("Screen start address:0x%08X, buffer width:%d, swivel view:%d degrees\n", screenStartAddress, lineSize, rotation);
|
||||
//debugLog("Screen format, color:%s, BPP:%d\n", boolString(color), bitDepth);
|
||||
@@ -366,7 +367,7 @@ void sed1376Render(void){
|
||||
lineSize = (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++)
|
||||
palmFramebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
|
||||
sed1376Framebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,21 +377,21 @@ void sed1376Render(void){
|
||||
//display inversion
|
||||
if((sed1376Registers[DISP_MODE] & 0x30) == 0x10)
|
||||
MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++)
|
||||
palmFramebuffer[index] = ~palmFramebuffer[index];
|
||||
sed1376Framebuffer[index] = ~sed1376Framebuffer[index];
|
||||
|
||||
|
||||
//backlight level, 0 = 1/4 color intensity, 1 = 1/2 color intensity, 2 = full color intensity
|
||||
switch(palmMisc.backlightLevel){
|
||||
case 0:
|
||||
MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++){
|
||||
palmFramebuffer[index] >>= 2;
|
||||
palmFramebuffer[index] &= 0x39E7;
|
||||
sed1376Framebuffer[index] >>= 2;
|
||||
sed1376Framebuffer[index] &= 0x39E7;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++){
|
||||
palmFramebuffer[index] >>= 1;
|
||||
palmFramebuffer[index] &= 0x7BEF;
|
||||
sed1376Framebuffer[index] >>= 1;
|
||||
sed1376Framebuffer[index] &= 0x7BEF;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -404,7 +405,7 @@ void sed1376Render(void){
|
||||
}
|
||||
else{
|
||||
//black screen
|
||||
memset(palmFramebuffer, 0x00, 160 * 160 * sizeof(uint16_t));
|
||||
memset(sed1376Framebuffer, 0x00, 160 * 160 * 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", pllIsOn() ? "true" : "false", sed1376PowerSaveEnabled() ? "true" : "false", !!(sed1376Registers[DISP_MODE] & 0x80) ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern uint8_t sed1376Framebuffer[];
|
||||
extern uint16_t sed1376Framebuffer[];
|
||||
extern uint8_t sed1376Ram[];
|
||||
|
||||
void sed1376Reset(void);
|
||||
uint64_t sed1376StateSize(void);
|
||||
|
||||
@@ -31,38 +31,38 @@ static uint16_t lutMonochromeValue(uint8_t lutIndex){
|
||||
|
||||
//monochrome
|
||||
static uint16_t get1BppMonochrome(uint16_t x, uint16_t y){
|
||||
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01);
|
||||
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01);
|
||||
}
|
||||
static uint16_t get2BppMonochrome(uint16_t x, uint16_t y){
|
||||
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03);
|
||||
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03);
|
||||
}
|
||||
static uint16_t get4BppMonochrome(uint16_t x, uint16_t y){
|
||||
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F);
|
||||
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F);
|
||||
}
|
||||
static uint16_t get8BppMonochrome(uint16_t x, uint16_t y){
|
||||
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]);
|
||||
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]);
|
||||
}
|
||||
static uint16_t get16BppMonochrome(uint16_t x, uint16_t y){
|
||||
uint16_t pixelValue = sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2)] << 8 | sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2 + 1)];
|
||||
uint16_t pixelValue = sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2)] << 8 | sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2 + 1)];
|
||||
return makeRgb16FromGreenComponent(pixelValue);
|
||||
}
|
||||
|
||||
//color
|
||||
static uint16_t get1BppColor(uint16_t x, uint16_t y){
|
||||
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01];
|
||||
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01];
|
||||
}
|
||||
static uint16_t get2BppColor(uint16_t x, uint16_t y){
|
||||
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03];
|
||||
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03];
|
||||
}
|
||||
static uint16_t get4BppColor(uint16_t x, uint16_t y){
|
||||
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F];
|
||||
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F];
|
||||
}
|
||||
static uint16_t get8BppColor(uint16_t x, uint16_t y){
|
||||
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]];
|
||||
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]];
|
||||
}
|
||||
static uint16_t get16BppColor(uint16_t x, uint16_t y){
|
||||
//this format is little endian, to use big endian data sed1376Registers[SPECIAL_EFFECT] & 0x40 must be set
|
||||
return sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2) + 1)] << 8 | sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2))];
|
||||
return sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2) + 1)] << 8 | sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2))];
|
||||
}
|
||||
|
||||
static void selectRenderer(bool color, uint8_t bpp){
|
||||
|
||||
@@ -15,7 +15,7 @@ These registers will do nothing if their corresponding feature bit is not set on
|
||||
#define FEATURE_RAM_HUGE 0x00000001/*128mb RAM*/
|
||||
#define FEATURE_FAST_CPU 0x00000002/*doubles CPU speed*/
|
||||
#define FEATURE_HYBRID_CPU 0x00000004/*allows running ARM opcodes in an OS 4 enviroment*/
|
||||
#define FEATURE_320x320 0x00000008/*creates a 320x320 framebuffer for hires mode, the 160x160 framebuffer is a transparent overlay over the 320x320 framebuffer*/
|
||||
#define FEATURE_CUSTOM_FB 0x00000008/*creates a dynamicly sized framebuffer for hires mode, the 160x160 framebuffer is a transparent overlay over the extended framebuffer*/
|
||||
#define FEATURE_SYNCED_RTC 0x00000010/*RTC always equals host system time*/
|
||||
#define FEATURE_HLE_APIS 0x00000020/*memcpy, memcmp, wait on timer will be replaced with the hosts function*/
|
||||
#define FEATURE_EMU_HONEST 0x00000040/*tell the OS that its running in an emu, does nothing else*/
|
||||
@@ -27,7 +27,7 @@ These registers will do nothing if their corresponding feature bit is not set on
|
||||
|
||||
/*registers*/
|
||||
#define EMU_INFO 0x000/*gets the feature bits, read only*/
|
||||
#define EMU_HIRESFB 0x004/*sets the address of the 320x320 framebuffer, read/write*/
|
||||
#define EMU_HIRESFB 0x004/*sets the address of the dynamic framebuffer, read/write, EMU_SIZE must have x width in the top 16 bits and y width in the bottom 16 bits*/
|
||||
#define EMU_SRC 0x008/*write only*/
|
||||
#define EMU_DST 0x00C/*write only*/
|
||||
#define EMU_SIZE 0x010/*write only*/
|
||||
|
||||
Reference in New Issue
Block a user