18 Commits

Author SHA1 Message Date
meepingsnesroms
1fb14b6675 Merge pull request #50 from meepingsnesroms/devel
Fix link.T for classics
2018-12-24 21:00:25 +00:00
meepingsnesroms
91995814dd Merge pull request #49 from meepingsnesroms/devel
Fix returning port k for port f
2018-12-22 19:57:10 +00:00
meepingsnesroms
ba9e6f2a6e Merge pull request #48 from meepingsnesroms/devel
Fix naming convention in hwrTestSuite
2018-12-21 04:25:17 +00:00
meepingsnesroms
c49889b030 Merge pull request #47 from meepingsnesroms/devel
Get tests and emu in sync, fix typo
2018-12-21 04:21:02 +00:00
meepingsnesroms
6cdfec1fd9 Merge pull request #46 from meepingsnesroms/devel
Add issue template
2018-12-14 01:37:46 +00:00
meepingsnesroms
17d0df1bc9 Merge pull request #45 from meepingsnesroms/devel
Try to redo port d interrupts again, they all seem to be right this time
2018-12-13 05:28:33 +00:00
meepingsnesroms
1a2993df55 Merge pull request #43 from meepingsnesroms/devel
Misc fixes
2018-12-10 20:23:22 +00:00
meepingsnesroms
8f5a6d1279 Merge pull request #42 from meepingsnesroms/devel
No cyclone for iOS, it really doesnt want to work
2018-12-09 17:42:59 +00:00
meepingsnesroms
4ba20d67e2 Merge pull request #41 from meepingsnesroms/devel
Test cyclone on iOS again
2018-12-09 17:32:32 +00:00
meepingsnesroms
9f701da401 Merge pull request #40 from meepingsnesroms/devel
Android fix
2018-12-08 20:17:47 +00:00
meepingsnesroms
fcb56ff523 Merge pull request #39 from meepingsnesroms/devel
More makefile changes
2018-12-08 19:28:27 +00:00
meepingsnesroms
274b5f6e6f Merge pull request #38 from meepingsnesroms/devel
Just disable asm on iOS for now
2018-12-08 16:40:42 +00:00
meepingsnesroms
f9fe7b69dc Merge pull request #37 from meepingsnesroms/devel
Please work now
2018-12-08 16:25:39 +00:00
meepingsnesroms
f6d688987c Merge pull request #36 from meepingsnesroms/devel
Split clang and GCC version of Cyclone since they each wont accept so…
2018-12-08 16:07:23 +00:00
meepingsnesroms
406bf692ee Merge pull request #35 from meepingsnesroms/devel
Enable Cyclone68k
2018-12-08 08:35:13 +00:00
meepingsnesroms
a4142a25e1 Merge pull request #34 from meepingsnesroms/devel
Add overlay, make button map match overlay
2018-12-07 18:39:24 +00:00
meepingsnesroms
8059920bfb Merge pull request #33 from meepingsnesroms/devel
Update version info
2018-12-06 18:14:54 +00:00
meepingsnesroms
7081547823 Merge pull request #32 from meepingsnesroms/devel
Fix power button bug
2018-12-05 21:53:59 +00:00
26 changed files with 216 additions and 247 deletions

View File

@@ -1,9 +1,9 @@
Lakka(needs makefile)
classics/new haxchi(should work)
xbox(don't know)
xbox360(don't know)
Fixed:
classics/new haxchi
PSP
msvc2010
msvc2003

View File

@@ -3,9 +3,9 @@ This is like unimplementedHardware.txt but only lists things that have functiona
State manager goes bezerk and crashes when saving on android, also can't close the window or it won't open again(also only on Android)
If there is no userdata-en-m515.ram on Android the emu won't create it(this is likely because theres no graceful exit being done on Android only goto home menu and kill process)
app install hack needs to be removed when SD card works
cyclone68k is broken on iOS
Fixed:
cyclone68k is broken on iOS(not gonna happen, iOS supposedly has its own ASM syntax)
double pressing power button issue(better without PDKBEN but still not correct)
Holding the buttons emulates pressing them like a turbo button(may be caused by the lack of sound emulation(wrong, sound works now))(may be because the minimum length of a button press is a whole frame(wrong, increasing the framerate doesn't change this behavior))(port d doesn't seem to be documented properly)
16 bpp mode is broken

View File

@@ -1,5 +1,3 @@
cyclone68k is crasing again when you turn the Palm off then turn it back on
Fixed:
Endian compatibility is broken(the CPU state needs to be standardized)(fixed again with musashi and the other 68k core isn't used right now)
RetroArch port crashes on exit(needed to check if environ_cb returned true, switched to libretro-common filestreams too)

View File

@@ -2,6 +2,7 @@ CPU:
sysTrapPceNativeCall, ARM Emulator
Trace T1 bit, should be unused by the OS and applications anyway
Test what bits of IMR are writable
On hardware PDIRQEG seems not to actually work at all(CPUID:0x57000000)
SCR privilege violation doesnt trigger the same as on hardware(likely has to do with not emulating the unused chip selects)
TCN2 is unimplemented and seems to be used by the same routines that turn the CPU off for sleep mode
@@ -13,20 +14,23 @@ Port M Infrared shutdown (PMDATA 0x20)
some undocumented I/O might be on port e and port j
SPI1, probably the SD card since SD cards use SPI for data transfer
SPITEST SSTATUS is undocumented and therefore unemulated
may need to trigger an interrupt if a IMR masked interrupt becomes unmasked and its bit is still set in IPR
When SPICLK2, SPITXD or SPIRXD on port e is disabled ADS7846 functions should respond appropriately(not transmitting or receiving or blocking both for the clock)
REFREQ clock frequency in RTCCTL should slow down the RTC when enabled
Dont know if it possible to have the backlight on and the display off at the same time(theres no reason for it but it may be possible)
SPI1 slave mode, should never be used
port d data register INT* bits seem to have there data bits cleared when an edge triggered interrupt is cleared(according to MC68VZ328UM.pdf Page 10-15)
RxOverflow on SPI1, don't know if back or front of FIFO is overwritten on overflow(currently losing oldest entry)
ICR POL(1,2,3,6) may flip the pin value as well as the interrupt, POL5 does not flip the INT5 pin though, this was confirmed with a hardware test(it doesnt seem to but there is instability on the pin when the SD card is plugged in, this may have to do with card detect also being a data line on the SD pinout)
edge triggered INT* don't clear on write to ISR when masked in IMR(at least that seems to be the reason)
Cyclone will cause SIGSEGVs, don't know why yet
PWM2 is not implemented
don't know if flushing the PWM1 FIFO sets all the bytes to 0x00, or just sets the read pointer to the write pointer preserving the newest sample and making the size 0(readPtr = writePtr has significantly cleaner audio then 0ing it out though)
while it is stated that the PLL is turned off "30 clocks" after the DISPLL bit is set, it doesnt state where the clocks come from, CLK32 or SYSCLK
SPI1 SPISPC register
UART1 USTCNT1
PLLFSR has a hack that makes busy wait loops finish faster by toggling the CLK32 bit on read, for power button issue
should also not transfer data to SD card when MOSI, MISO or SPICLK1 are disabled
port d data register INT* bits seem to have there data bits cleared when an edge triggered interrupt is cleared(according to MC68VZ328UM.pdf Page 10-15)
PDKBEN also has a hack for power on
Memory:
SD card can't be read or written to by Palm OS
@@ -53,11 +57,6 @@ MakePalmBitmap:
Fixed:
edge triggered INT* don't clear on write to ISR when masked in IMR(I needed to use (ints & ~IMR) not (ints & IMR) which only triggers disable interrupts while blocking active ones)
PDKBEN also has a hack for power on(its been removed)
On hardware PDIRQEG seems not to actually work at all(CPUID:0x57000000)(it does)
may need to trigger an interrupt if a IMR masked interrupt becomes unmasked and its bit is still set in IPR(already doing that)
Cyclone will cause SIGSEGVs, don't know why yet(seems to have been caused by compressed jumptable)
power button must be pushed twice to turn the CPU back on(when debugging it works the first time, then must be pushed twice to turn off instead of on)(this also occurs in the RetroArch build)
the power button double press issue may be because the button map I am using was taken from POSE source, the power button may be mapped to other locations on the button matrix than expected
if a sound interrupt is triggered while the button interrupt is disabled the button interrupt will still trigger(in galax game)(seems to be an issue with FIFOAV always = true hack and how INT_PWM1 needed to be cleared on read or write)

View File

@@ -28,15 +28,15 @@ else ifeq ($(platform), osx)
endif
endif
# ifneq (,$(filter qnx vita ctr rpi2 classic_armv7_a7,$(platform)))
# EMU_OPTIMIZE_FOR_ARM32 = 1
# else ifneq (,$(findstring armv7,$(platform)))
# EMU_OPTIMIZE_FOR_ARM32 = 1
# else ifneq (,$(findstring armv6,$(platform)))
# EMU_OPTIMIZE_FOR_ARM32 = 1
# else ifneq (,$(findstring armhf,$(platform)))
# EMU_OPTIMIZE_FOR_ARM32 = 1
# endif
ifneq (,$(filter qnx vita ctr rpi2 classic_armv7_a7,$(platform)))
EMU_OPTIMIZE_FOR_ARM32 = 1
else ifneq (,$(findstring armv7,$(platform)))
EMU_OPTIMIZE_FOR_ARM32 = 1
else ifneq (,$(findstring armv6,$(platform)))
EMU_OPTIMIZE_FOR_ARM32 = 1
else ifneq (,$(findstring armhf,$(platform)))
EMU_OPTIMIZE_FOR_ARM32 = 1
endif
include $(EMU_PATH)/makefile.all

View File

@@ -8,11 +8,11 @@ GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
EMU_OPTIMIZE_FOR_ARM32 := 0
# set ASM CPU core, only use with ARMv4<->7, ARMv8 is its own architecture
# ifeq ($(TARGET_ARCH), arm)
# ifneq ($(TARGET_ARCH_ABI), arm64-v8a)
# EMU_OPTIMIZE_FOR_ARM32 := 1
# endif
# endif
ifeq ($(TARGET_ARCH), arm)
ifneq ($(TARGET_ARCH_ABI), arm64-v8a)
EMU_OPTIMIZE_FOR_ARM32 := 1
endif
endif
include $(CORE_DIR)/build/Makefile.common

View File

@@ -19,7 +19,6 @@
#define JOYSTICK_DEADZONE 4000
#define JOYSTICK_MULTIPLIER 0.0001
#define SCREEN_HIRES (!(palmFramebufferWidth == 160 && palmFramebufferHeight == 220))
static retro_log_printf_t log_cb;
@@ -29,6 +28,10 @@ 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[320 * 440];
static uint32_t emuFeatures;
static bool useJoystickAsMouse;
static float touchCursorX;
@@ -36,7 +39,7 @@ static float touchCursorY;
static void renderMouseCursor(int16_t screenX, int16_t screenY){
if(SCREEN_HIRES){
if(screenHires){
int8_t x;
int8_t y;
@@ -45,9 +48,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 < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < 320 && screenY + y < 440)
if(cursor32x32[y * 32 + x] != 0xFFFF)
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor32x32[y * 32 + x];
screenData[(screenY + y) * 320 + screenX + x] = cursor32x32[y * 32 + x];
}
else{
int8_t x;
@@ -58,9 +61,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 < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < 160 && screenY + y < 220)
if(cursor16x16[y * 16 + x] != 0xFFFF)
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor16x16[y * 16 + x];
screenData[(screenY + y) * 160 + screenX + x] = cursor16x16[y * 16 + x];
}
}
@@ -95,10 +98,10 @@ static void check_variables(bool booting){
if (!strcmp(var.value, "enabled"))
emuFeatures |= FEATURE_HYBRID_CPU;
var.key = "palm_emu_feature_custom_fb";
var.key = "palm_emu_feature_320x320";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
if (!strcmp(var.value, "enabled"))
emuFeatures |= FEATURE_CUSTOM_FB;
emuFeatures |= FEATURE_320x320;
var.key = "palm_emu_feature_synced_rtc";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
@@ -167,8 +170,8 @@ void retro_get_system_av_info(struct retro_system_av_info *info){
info->geometry.base_width = 160;
info->geometry.base_height = 220;
info->geometry.max_width = 480;
info->geometry.max_height = 480;
info->geometry.max_width = 320;
info->geometry.max_height = 440;
info->geometry.aspect_ratio = 160.0 / 220.0;
}
@@ -179,7 +182,7 @@ void retro_set_environment(retro_environment_t cb){
{ "palm_emu_feature_ram_huge", "Extra RAM Hack; disabled|enabled" },
{ "palm_emu_feature_fast_cpu", "Overclock 2x; disabled|enabled" },
{ "palm_emu_feature_hybrid_cpu", "Extra RAM Hack; disabled|enabled" },
{ "palm_emu_feature_custom_fb", "Custom Resolution; disabled|enabled" },
{ "palm_emu_feature_320x320", "Double Resolution; disabled|enabled" },
{ "palm_emu_feature_synced_rtc", "Force Match System Clock; disabled|enabled" },
{ "palm_emu_feature_hle_apis", "HLE API Implementations; disabled|enabled" },
{ "palm_emu_feature_emu_honest", "Tell Programs They're In An Emulator(for test programs); disabled|enabled" },
@@ -251,23 +254,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 * (SCREEN_HIRES ? 2.0 : 1.0);
touchCursorX += x * JOYSTICK_MULTIPLIER * (screenHires ? 2.0 : 1.0);
if(y < -JOYSTICK_DEADZONE || y > JOYSTICK_DEADZONE)
touchCursorY += y * JOYSTICK_MULTIPLIER * (SCREEN_HIRES ? 2.0 : 1.0);
touchCursorY += y * JOYSTICK_MULTIPLIER * (screenHires ? 2.0 : 1.0);
if(touchCursorX < 0)
touchCursorX = 0;
else if(touchCursorX > palmFramebufferWidth - 1)
touchCursorX = palmFramebufferWidth - 1;
else if(touchCursorX > screenWidth - 1)
touchCursorX = screenWidth - 1;
if(touchCursorY < 0)
touchCursorY = 0;
else if(touchCursorY > palmFramebufferHeight - 1)
touchCursorY = palmFramebufferHeight - 1;
else if(touchCursorY > screenHeight - 1)
touchCursorY = screenHeight - 1;
palmInput.touchscreenX = touchCursorX / (palmFramebufferWidth - 1);
palmInput.touchscreenY = touchCursorY / (palmFramebufferHeight - 1);
palmInput.touchscreenX = touchCursorX / (screenWidth - 1);
palmInput.touchscreenY = touchCursorY / (screenHeight - 1);
palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
}
else{
@@ -295,12 +298,13 @@ 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(palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t));
video_cb(screenData, screenWidth, screenHeight, screenWidth * sizeof(uint16_t));
audio_cb(palmAudio, AUDIO_SAMPLES_PER_FRAME);
}
@@ -374,9 +378,11 @@ 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);
//set mouse position
touchCursorX = palmFramebufferWidth / 2;
touchCursorY = palmFramebufferHeight / 2;
screenHires = emuFeatures & FEATURE_320x320;
screenWidth = screenHires ? 320 : 160;
screenHeight = screenHires ? 440 : 220;
touchCursorX = screenWidth / 2;
touchCursorY = screenHeight / 2;
return true;
}

View File

@@ -50,7 +50,7 @@ android{
QMAKE_CXXFLAGS += -fopenmp
QMAKE_LFLAGS += -fopenmp
DEFINES += EMU_MULTITHREADED
# CONFIG += optimize_for_arm32 # for now, later this will check if building for ARMv4<->7
CONFIG += optimize_for_arm32 # for now, later this will check if building for ARMv4<->7
}
ios{

View File

@@ -67,6 +67,8 @@ EmuWrapper::EmuWrapper(){
emuThreadJoin = false;
emuRunning = false;
emuPaused = false;
emuVideoWidth = 0;
emuVideoHeight = 0;
emuNewFrameReady = false;
frontendDebugString = new char[200];
@@ -187,6 +189,15 @@ uint32_t EmuWrapper::init(const QString& romPath, const QString& bootloaderPath,
}
}
if(features & FEATURE_320x320){
emuVideoWidth = 320;
emuVideoHeight = 320 + 120;
}
else{
emuVideoWidth = 160;
emuVideoHeight = 160 + 60;
}
emuInput = palmInput;
emuRamFilePath = ramPath;
emuSdCardFilePath = sdCardPath;
@@ -316,7 +327,7 @@ uint32_t EmuWrapper::loadState(const QString& path){
return error;
}
uint32_t EmuWrapper::installApplication(const QString& path){
uint32_t EmuWrapper::installApplication(QString path){
bool wasPaused = isPaused();
uint32_t error = EMU_ERROR_INVALID_PARAMETER;
QFile appFile(path);

View File

@@ -21,6 +21,8 @@ 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;
@@ -43,19 +45,19 @@ public:
bool isRunning() const{return emuRunning;}
bool isPaused() const{return emuPaused;}
uint32_t installApplication(const QString& path);
uint32_t installApplication(QString path);
std::vector<QString>& getDebugStrings();
std::vector<uint64_t>& getDuplicateCallCount();
std::vector<uint32_t> getCpuRegisters();
uint16_t screenWidth() const{return palmFramebufferWidth;}
uint16_t screenHeight() const{return palmFramebufferHeight;}
uint16_t screenWidth() const{return emuVideoWidth;}
uint16_t screenHeight() const{return emuVideoHeight;}
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*)palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t), QImage::Format_RGB16));}
const QPixmap getFramebuffer(){return QPixmap::fromImage(QImage((uchar*)(emuVideoWidth == 320 ? palmExtendedFramebuffer : palmFramebuffer), emuVideoWidth, emuVideoHeight, emuVideoWidth * sizeof(uint16_t), QImage::Format_RGB16));}
const int16_t* getAudioSamples() const{return palmAudio;}
bool getPowerButtonLed() const{return palmMisc.powerButtonLed;}

View File

@@ -53,10 +53,9 @@ void printLastRun(){
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::MainWindow){
QAudioFormat format;
QString resourceDirPath;
ui->setupUi(this);
//audio output
QAudioFormat format;
format.setSampleRate(AUDIO_SAMPLE_RATE);
format.setChannelCount(2);
format.setSampleSize(16);
@@ -68,7 +67,6 @@ MainWindow::MainWindow(QWidget* parent) :
#endif
format.setSampleType(QAudioFormat::SignedInt);
//submodules
settings = new QSettings(QDir::homePath() + "/MuCfg.txt", QSettings::IniFormat);//settings is public, create it first
stateManager = new StateManager(this);
emuDebugger = new DebugViewer(this);
@@ -76,27 +74,6 @@ MainWindow::MainWindow(QWidget* parent) :
audioDevice = new QAudioOutput(format, this);
audioOut = audioDevice->start();
//resource directory
resourceDirPath = settings->value("resourceDirectory", "").toString();
//get default path if path not set
if(resourceDirPath == ""){
#if defined(Q_OS_ANDROID)
resourceDirPath = "/sdcard/Mu";
#elif defined(Q_OS_IOS)
resourceDirPath = "/var/mobile/Media/Mu";
#else
resourceDirPath = QDir::homePath() + "/Mu";
#endif
settings->setValue("resourceDirectory", resourceDirPath);
}
//create directory tree, in case someone deleted it since the emu was last run or it was never created
createHomeDirectoryTree(resourceDirPath);
//GUI
ui->setupUi(this);
//this makes the display window and button icons resize properly
ui->centralWidget->installEventFilter(this);
ui->centralWidget->setObjectName("centralWidget");
@@ -120,9 +97,29 @@ MainWindow::MainWindow(QWidget* parent) :
ui->screenshot->installEventFilter(this);
ui->stateManager->installEventFilter(this);
QString resourceDirPath = settings->value("resourceDirectory", "").toString();
//use default path if path not set
if(resourceDirPath == ""){
#if defined(Q_OS_ANDROID)
resourceDirPath = "/sdcard/Mu";
#elif defined(Q_OS_IOS)
resourceDirPath = "/var/mobile/Media/Mu";
#else
resourceDirPath = QDir::homePath() + "/Mu";
#endif
settings->setValue("resourceDirectory", resourceDirPath);
}
//create directory tree, in case someone deleted it since the emu was last run
createHomeDirectoryTree(resourceDirPath);
#if !defined(EMU_DEBUG) || defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
ui->debugger->hide();
#endif
connect(refreshDisplay, SIGNAL(timeout()), this, SLOT(updateDisplay()));
refreshDisplay->start(1000 / EMU_FPS);//update display every X milliseconds
}
@@ -293,7 +290,7 @@ void MainWindow::on_right_released(){
void MainWindow::on_ctrlBtn_clicked(){
if(!emu.isInited()){
QString sysDir = settings->value("resourceDirectory", "").toString();
uint32_t error = emu.init(sysDir + "/palmos41-en-m515.rom", QFile(sysDir + "/bootloader-en-m515.rom").exists() ? sysDir + "/bootloader-en-m515.rom" : "", sysDir + "/userdata-en-m515.ram", sysDir + "/sd-en-m515.img", FEATURE_CUSTOM_FB | FEATURE_DEBUG);
uint32_t error = emu.init(sysDir + "/palmos41-en-m515.rom", QFile(sysDir + "/bootloader-en-m515.rom").exists() ? sysDir + "/bootloader-en-m515.rom" : "", sysDir + "/userdata-en-m515.ram", sysDir + "/sd-en-m515.img", FEATURE_320x320 | FEATURE_DEBUG);
if(error == EMU_ERROR_NONE){
ui->calendar->setEnabled(true);
ui->addressBook->setEnabled(true);
@@ -375,6 +372,7 @@ void MainWindow::on_stateManager_clicked(){
if(!wasPaused)
emu.pause();
stateManager->updateStateList();
stateManager->exec();
if(!wasPaused)

View File

@@ -20,21 +20,12 @@ StateManager::StateManager(QWidget* parent) :
//this allows resizing the screenshot of the savestate
ui->statePreview->installEventFilter(this);
ui->statePreview->setObjectName("statePreview");
updateStateList();
}
StateManager::~StateManager(){
delete ui;
}
bool StateManager::eventFilter(QObject* object, QEvent* event){
if(object->objectName() == "statePreview" && event->type() == QEvent::Resize)
updateStatePreview();
return QDialog::eventFilter(object, event);
}
void StateManager::updateStateList(){
MainWindow* parent = (MainWindow*)parentWidget();
QString saveDirPath = parent->settings->value("resourceDirectory", "").toString() + "/saveStates";
@@ -56,27 +47,21 @@ void StateManager::updateStateList(){
}
}
bool StateManager::eventFilter(QObject* object, QEvent* event){
if(object->objectName() == "statePreview" && event->type() == QEvent::Resize)
updateStatePreview();
return QDialog::eventFilter(object, event);
}
void StateManager::updateStatePreview(){
if(ui->states->currentItem()){
MainWindow* parent = (MainWindow*)parentWidget();
QString statePath = parent->settings->value("resourceDirectory", "").toString() + "/saveStates/" + ui->states->currentItem()->text();
ui->statePreview->setPixmap(QPixmap(statePath + ".png").scaled(ui->statePreview->width() * 0.98, ui->statePreview->height() * 0.98, Qt::KeepAspectRatio, Qt::SmoothTransformation));
ui->statePreview->update();
}
else{
//remove outdated image
ui->statePreview->clear();
}
ui->statePreview->update();
}
int StateManager::getStateIndexRowByName(const QString& name){
for(int index = 0; index < ui->states->count(); index++)
if(ui->states->item(index)->text() == name)
return index;
return -1;//nothing by that name exists
}
void StateManager::on_saveState_clicked(){
@@ -87,8 +72,6 @@ void StateManager::on_saveState_clicked(){
parent->emu.saveState(statePath + ".state");
parent->emu.getFramebuffer().save(statePath + ".png");
updateStateList();
ui->states->setCurrentRow(getStateIndexRowByName(ui->newStateName->text()));//this also updates the preview image
}
}
@@ -109,7 +92,6 @@ void StateManager::on_deleteState_clicked(){
QFile(statePath + ".state").remove();
QFile(statePath + ".png").remove();
updateStateList();
ui->states->setCurrentRow(0);//pick first valid entry since the old one is no longer valid
}
}

View File

@@ -16,12 +16,12 @@ public:
explicit StateManager(QWidget* parent = nullptr);
~StateManager();
void updateStateList();
private slots:
bool eventFilter(QObject* object, QEvent* event);
void updateStateList();
void updateStatePreview();
int getStateIndexRowByName(const QString& name);
void on_saveState_clicked();
void on_loadState_clicked();

View File

@@ -39,8 +39,7 @@ input_t palmInput;
sd_card_t palmSdCard;
misc_hw_t palmMisc;
uint16_t* palmFramebuffer;
uint16_t palmFramebufferWidth;
uint16_t palmFramebufferHeight;
uint16_t* palmExtendedFramebuffer;
int16_t* palmAudio;
blip_t* palmAudioResampler;
uint32_t palmSpecialFeatures;
@@ -62,16 +61,21 @@ 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(480 * 480 * sizeof(uint16_t));
palmFramebuffer = malloc(160 * (160 + 60) * sizeof(uint16_t));//really 160*160, the extra pixels are the silkscreened digitizer area
palmAudio = malloc(AUDIO_SAMPLES_PER_FRAME * 2 * sizeof(int16_t));
palmAudioResampler = blip_new(AUDIO_SAMPLE_RATE);//have 1 second of samples
if(!palmRam || !palmRom || !palmReg || !palmFramebuffer || !palmAudio || !palmAudioResampler){
if(specialFeatures & FEATURE_320x320)
palmExtendedFramebuffer = malloc(320 * (320 + 120) * sizeof(uint16_t));//really 320*320, the extra pixels are the silkscreened digitizer area
else
palmExtendedFramebuffer = NULL;
if(!palmRam || !palmRom || !palmReg || !palmFramebuffer || !palmAudio || !palmAudioResampler || (!palmExtendedFramebuffer && (specialFeatures & FEATURE_320x320))){
free(palmRam);
free(palmRom);
free(palmReg);
free(palmFramebuffer);
free(palmAudio);
blip_delete(palmAudioResampler);
free(palmExtendedFramebuffer);
return EMU_ERROR_OUT_OF_MEMORY;
}
@@ -90,11 +94,15 @@ 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
@@ -106,11 +114,11 @@ uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t spec
sandboxInit();
//reset everything
flx68000Reset();
sed1376Reset();
ads7846Reset();
pdiUsbD12Reset();
sdCardReset();
flx68000Reset();
setRtc(0, 0, 0, 0);//RTCTIME and DAYR are not cleared by reset, clear them manually in case the frontend doesnt set the RTC
emulatorInitialized = true;
@@ -129,6 +137,7 @@ void emulatorExit(void){
free(palmFramebuffer);
free(palmAudio);
blip_delete(palmAudioResampler);
free(palmExtendedFramebuffer);
free(palmSdCard.flashChip.data);
emulatorInitialized = false;
}
@@ -137,25 +146,24 @@ 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);
palmFramebufferWidth = 160;
palmFramebufferHeight = 220;
memset(palmFramebuffer, 0x00, 160 * 160 * sizeof(uint16_t));
if(palmExtendedFramebuffer)
memset(palmExtendedFramebuffer, 0x00, 320 * 320 * sizeof(uint16_t));
flx68000Reset();
sed1376Reset();
ads7846Reset();
pdiUsbD12Reset();
sdCardReset();
flx68000Reset();
setRtc(0, 0, 0, 0);
}
void emulatorSoftReset(void){
//equivalent to pushing the reset button on the back of the device
palmFramebufferWidth = 160;
palmFramebufferHeight = 220;
flx68000Reset();
sed1376Reset();
ads7846Reset();
pdiUsbD12Reset();
sdCardReset();
flx68000Reset();
}
void emulatorSetRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t seconds){
@@ -168,7 +176,6 @@ 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();
@@ -196,7 +203,7 @@ uint64_t emulatorGetStateSize(void){
size += sizeof(uint8_t) * 2;//pwm1(Read/Write)
size += sizeof(uint8_t) * 7;//palmMisc
size += sizeof(uint64_t) * 2;//palmSdCard.command / palmSdCard.responseState
size += sizeof(uint8_t) * 4;//palmSdCard.commandBitsRemaining / palmSdCard.response / palmSdCard.allowInvalidCrc / palmSdCard.chipSelect
size += sizeof(uint8_t) * 2;//palmSdCard.commandBitsRemaining / palmSdCard.response
size += palmSdCard.flashChip.size;//palmSdCard.flashChip.data
return size;
@@ -221,12 +228,6 @@ 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();
@@ -355,10 +356,6 @@ bool emulatorSaveState(buffer_t buffer){
offset += sizeof(uint8_t);
writeStateValue64(buffer.data + offset, palmSdCard.responseState);
offset += sizeof(uint64_t);
writeStateValue8(buffer.data + offset, palmSdCard.allowInvalidCrc);
offset += sizeof(uint8_t);
writeStateValue8(buffer.data + offset, palmSdCard.chipSelect);
offset += sizeof(uint8_t);
memcpy(buffer.data + offset, palmSdCard.flashChip.data, palmSdCard.flashChip.size);
offset += palmSdCard.flashChip.size;
@@ -388,12 +385,6 @@ 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();
@@ -522,10 +513,6 @@ bool emulatorLoadState(buffer_t buffer){
offset += sizeof(uint8_t);
palmSdCard.responseState = readStateValue64(buffer.data + offset);
offset += sizeof(uint64_t);
palmSdCard.allowInvalidCrc = readStateValue8(buffer.data + offset);
offset += sizeof(uint8_t);
palmSdCard.chipSelect = readStateValue8(buffer.data + offset);
offset += sizeof(uint8_t);
if(palmSdCard.flashChip.data)
free(palmSdCard.flashChip.data);
palmSdCard.flashChip.data = stateSdCardBuffer;
@@ -622,13 +609,27 @@ void emulatorRunFrame(void){
//video
sed1376Render();
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
//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
//DRIVER NEEDS TO BE WRITTEN STILL
//the above was enabled early so using the hires silkscreen and mouse cursor was possible in RetroArch
}
}

View File

@@ -91,8 +91,6 @@ typedef struct{
uint8_t commandBitsRemaining;
uint8_t response;
uint64_t responseState;//this can contain many different types of data depending on the response type
bool allowInvalidCrc;
bool chipSelect;
buffer_t flashChip;
}sd_card_t;
@@ -126,9 +124,8 @@ 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
extern uint16_t palmFramebufferWidth;//read allowed
extern uint16_t palmFramebufferHeight;//read 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 int16_t* palmAudio;//read allowed, 2 channel signed 16 bit audio
extern blip_t* palmAudioResampler;//dont touch
extern uint32_t palmSpecialFeatures;//read allowed

View File

@@ -187,7 +187,7 @@ static void checkPortDInterrupts(void){
uint8_t portDInterruptEdgeTriggered = icrEdgeTriggered | registerArrayRead8(PDIRQEG);
uint8_t portDInterruptEnabled = (~registerArrayRead8(PDSEL) & 0xF0) | registerArrayRead8(PDIRQEN);
uint8_t portDIsInput = ~registerArrayRead8(PDDIR);
uint8_t portDInterruptTriggered = portDInterruptValue & portDInterruptEnabled & portDIsInput & (~portDInterruptEdgeTriggered | ~portDInterruptLastValue & (pllIsOn() ? 0xFF : 0xF0));
uint8_t portDInterruptTriggered = portDInterruptValue & portDInterruptEnabled & portDIsInput & (~portDInterruptEdgeTriggered | ~portDInterruptLastValue/* & (pllIsOn() ? 0xFF : 0xF0)*/);
if(portDInterruptTriggered & 0x01)
setIprIsrBit(INT_INT0);
@@ -229,13 +229,18 @@ static void checkPortDInterrupts(void){
else if(!(portDInterruptEdgeTriggered & 0x80))
clearIprIsrBit(INT_IRQ6);
//active low/off level triggered interrupt(triggers on 0, not a pull down resistor)
//active low/off level triggered interrupt
//The SELx, POLx, IQENx, and IQEGx bits have no effect on the functionality of KBENx, 10.4.5.8 Port D Keyboard Enable Register MC68VZ328UM.pdf
//the above has finally been verified to be correct!
if(registerArrayRead8(PDKBEN) & ~(getPortDValue() ^ registerArrayRead8(PDPOL)) & portDIsInput)
//the above seems like a lie, 10.4.4 Port D Operation MC68VZ328UM.pdf
//completely removing PDKBEN is not accurate but makes the buttons function properly
//I am fairly sure that port d is not documented properly by the data sheet so Im going with what works properly right now
//the "!pllIsOn() &&" is a hack, it prevents rapid button presses, but allows INT_KB to turn the device back on
/*
if(!pllIsOn() && registerArrayRead8(PDKBEN) & getPortDValue() ^ registerArrayRead8(PDPOL))
setIprIsrBit(INT_KB);
else
clearIprIsrBit(INT_KB);
*/
//save to check against next time this function is called
portDInterruptLastValue = portDInterruptTriggered;
@@ -429,7 +434,6 @@ uint16_t getHwRegister16(uint32_t address){
uint16_t fifoVal = spi1RxFifoRead();
//check if SPI1 interrupts changed
setSpiIntCs(registerArrayRead16(SPIINTCS));
debugLog("SPIRXD read, FIFO value:0x%04X, SPIINTCS:0x%04X\n", fifoVal, registerArrayRead16(SPIINTCS));
return fifoVal;
}
@@ -596,13 +600,6 @@ void setHwRegister8(uint32_t address, uint8_t value){
updateAds7846ChipSelectStatus();
break;
case PJSEL:
case PJDIR:
case PJDATA:
registerArrayWrite8(address, value);
updateSdCardChipSelectStatus();
break;
case PKSEL:
case PKDIR:
case PKDATA:
@@ -629,6 +626,7 @@ void setHwRegister8(uint32_t address, uint8_t value){
//select between GPIO or special function
case PCSEL:
case PESEL:
case PJSEL:
//direction select
case PADIR:
@@ -636,6 +634,7 @@ void setHwRegister8(uint32_t address, uint8_t value){
case PDDIR:
case PEDIR:
case PFDIR:
case PJDIR:
//pull up/down enable
case PAPUEN:
@@ -651,6 +650,7 @@ void setHwRegister8(uint32_t address, uint8_t value){
case PCDATA:
case PEDATA:
case PFDATA:
case PJDATA:
//dragonball LCD controller, not attached to anything in Palm m515
case LCKCON:
@@ -690,13 +690,13 @@ void setHwRegister16(uint32_t address, uint16_t value){
case IMR:
//this is a 32 bit register but Palm OS writes to it as 16 bit chunks
registerArrayWrite16(IMR, value & 0x00FF);
registerArrayWrite16(ISR, registerArrayRead16(IPR) & ~registerArrayRead16(IMR));
registerArrayWrite16(ISR, registerArrayRead16(IPR) & registerArrayRead16(IMR));
checkInterrupts();
break;
case IMR + 2:
//this is a 32 bit register but Palm OS writes to it as 16 bit chunks
registerArrayWrite16(IMR + 2, value & 0xFFFF);//Palm OS writes to reserved bits 14 and 15
registerArrayWrite16(ISR + 2, registerArrayRead16(IPR + 2) & ~registerArrayRead16(IMR + 2));
registerArrayWrite16(ISR + 2, registerArrayRead16(IPR + 2) & registerArrayRead16(IMR + 2));
checkInterrupts();
break;
@@ -982,7 +982,7 @@ void setHwRegister32(uint32_t address, uint32_t value){
case IMR:
registerArrayWrite32(IMR, value & 0x00FFFFFF);//Palm OS writes to reserved bits 14 and 15
registerArrayWrite32(ISR, registerArrayRead32(IPR) & ~registerArrayRead32(IMR));
registerArrayWrite32(ISR, registerArrayRead32(IPR) & registerArrayRead32(IMR));
checkInterrupts();
break;
@@ -1020,7 +1020,6 @@ void resetHwRegisters(void){
memset(spi1TxFifo, 0x00, sizeof(spi1TxFifo));
spi1RxReadPosition = 0;
spi1RxWritePosition = 0;
spi1RxOverflowed = false;
spi1TxReadPosition = 0;
spi1TxWritePosition = 0;
pwm1ClocksToNextSample = 0;
@@ -1147,7 +1146,6 @@ void resetHwRegisters(void){
updatePowerButtonLedStatus();
updateVibratorStatus();
updateAds7846ChipSelectStatus();
updateSdCardChipSelectStatus();
updateBacklightAmplifierStatus();
palmSysclksPerClk32 = sysclksPerClk32();

View File

@@ -40,22 +40,21 @@ static uint8_t spi1RxFifoEntrys(void){
}
static uint16_t spi1RxFifoRead(void){
uint16_t value = spi1RxFifo[spi1RxReadPosition];
if(spi1RxFifoEntrys() > 0)
spi1RxReadPosition = (spi1RxReadPosition + 1) % 9;
spi1RxOverflowed = false;
return spi1RxFifo[spi1RxReadPosition];
return value;
}
static void spi1RxFifoWrite(uint16_t value){
if(spi1RxFifoEntrys() < 8){
spi1RxWritePosition = (spi1RxWritePosition + 1) % 9;
spi1RxFifo[spi1RxWritePosition] = value;
}
else{
spi1RxOverflowed = true;
debugLog("SPI1 RX FIFO overflowed\n");
}
spi1RxFifo[spi1RxWritePosition] = value;
}
static void spi1RxFifoFlush(void){
@@ -70,9 +69,10 @@ static uint8_t spi1TxFifoEntrys(void){
}
static uint16_t spi1TxFifoRead(void){
uint16_t value = spi1TxFifo[spi1TxReadPosition];
//dont need a safety check here, the emulator will always check that data is present before trying to access it
spi1TxReadPosition = (spi1TxReadPosition + 1) % 9;
return spi1TxFifo[spi1TxReadPosition];
return value;
}
static void spi1TxFifoWrite(uint16_t value){
@@ -95,6 +95,7 @@ static uint8_t pwm1FifoEntrys(void){
}
int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){
uint8_t sample = pwm1Fifo[pwm1ReadPosition];
uint16_t period = registerArrayRead8(PWMP1) + 2;
uint16_t pwmc1 = registerArrayRead16(PWMC1);
uint8_t prescaler = (pwmc1 >> 8 & 0x7F) + 1;
@@ -102,14 +103,9 @@ int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){
uint8_t repeat = 1 << (pwmc1 >> 2 & 0x03);
int32_t audioNow = now + clockOffset;
int32_t audioSampleDuration = (pwmc1 & 0x8000)/*CLKSRC*/ ? audioGetFramePercentIncrementFromClk32s(period * prescaler * clockDivider) : audioGetFramePercentIncrementFromSysclks(period * prescaler * clockDivider);
float dutyCycle;
float dutyCycle = fMin((float)sample / period, 1.00);
uint8_t index;
//try to get next sample, if none are available play old sample
if(pwm1FifoEntrys() > 0)
pwm1ReadPosition = (pwm1ReadPosition + 1) % 6;
dutyCycle = fMin((float)pwm1Fifo[pwm1ReadPosition] / period, 1.00);
for(index = 0; index < repeat; index++){
#if !defined(EMU_NO_SAFETY)
if(audioNow + audioSampleDuration >= AUDIO_CLOCK_RATE)
@@ -121,6 +117,10 @@ int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){
audioNow += audioSampleDuration;
}
//remove used entry
if(pwm1FifoEntrys() > 0)
pwm1ReadPosition = (pwm1ReadPosition + 1) % 6;
//check for interrupt
if(pwm1FifoEntrys() < 2){
//trigger interrupt if enabled
@@ -336,7 +336,7 @@ static void setSpiIntCs(uint16_t value){
newSpiIntCs |= (rxEntrys >= 4) << 4;//RH
newSpiIntCs |= (rxEntrys > 0) << 3;//RR
newSpiIntCs |= (txEntrys == 8) << 2;//TF
newSpiIntCs |= (txEntrys >= 4) << 1;//TH, the datasheet contradicts itself on whether its more than or equal to 4 empty or full slots
newSpiIntCs |= (txEntrys >= 4) << 1;//TH
newSpiIntCs |= txEntrys == 0;//TE
//if interrupt state changed update interrupts too, top 8 bits are just the enable bits for the bottom 8
@@ -358,7 +358,7 @@ static void setSpiCont1(uint16_t value){
//debugLog("SPICONT1 write, old value:0x%04X, value:0x%04X\n", oldSpiCont1, value);
//SPI1 disabled
if(oldSpiCont1 & 0x0200 && !(value & 0x0200)){
if(oldSpiCont1 & 0x0200 && !(value & 0x2000)){
spi1RxFifoFlush();
spi1TxFifoFlush();
}
@@ -380,8 +380,8 @@ static void setSpiCont1(uint16_t value){
//The most significant bit is output when the CPU loads the transmitted data, 13.2.3 SPI 1 Phase and Polarity Configurations MC68VZ328UM.pdf
for(bits = 0; bits < bitCount; bits++){
newRxFifoEntry <<= 1;
newRxFifoEntry |= sdCardExchangeBit(!!(currentTxFifoEntry & startBit));
newRxFifoEntry <<= 1;
currentTxFifoEntry <<= 1;
}
@@ -398,8 +398,6 @@ static void setSpiCont1(uint16_t value){
//update SPIINTCS interrupt bits
setSpiIntCs(registerArrayRead16(SPIINTCS));
//debugLog("Transfer complete, SPIINTCS:0x%04X\n", registerArrayRead16(SPIINTCS));
registerArrayWrite16(SPICONT1, value);
}
@@ -727,10 +725,6 @@ static void updateAds7846ChipSelectStatus(void){
ads7846SetChipSelect(!!(getPortGValue() & 0x04));
}
static void updateSdCardChipSelectStatus(void){
sdCardSetChipSelect(!!(getPortJValue() & 0x08));
}
static void updateBacklightAmplifierStatus(void){
palmMisc.backlightLevel = (palmMisc.backlightLevel > 0) ? (1 + backlightAmplifierState()) : 0;
}

View File

@@ -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(sed1376Ram, address, chips[CHIP_B0_SED].mask);
return BUFFER_READ_8_BIG_ENDIAN(sed1376Framebuffer, 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(sed1376Ram, address, chips[CHIP_B0_SED].mask);
return BUFFER_READ_16_BIG_ENDIAN(sed1376Framebuffer, 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(sed1376Ram, address, chips[CHIP_B0_SED].mask);
return BUFFER_READ_32_BIG_ENDIAN(sed1376Framebuffer, 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(sed1376Ram, address, chips[CHIP_B0_SED].mask, value);
BUFFER_WRITE_8_BIG_ENDIAN(sed1376Framebuffer, 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(sed1376Ram, address, chips[CHIP_B0_SED].mask, value);
BUFFER_WRITE_16_BIG_ENDIAN(sed1376Framebuffer, 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(sed1376Ram, address, chips[CHIP_B0_SED].mask, value);
BUFFER_WRITE_32_BIG_ENDIAN(sed1376Framebuffer, address, chips[CHIP_B0_SED].mask, value);
else
sed1376SetRegister(address & chips[CHIP_B0_SED].mask, value);
}

View File

@@ -81,17 +81,6 @@ void sdCardReset(void){
palmSdCard.commandBitsRemaining = 48;
palmSdCard.responseState = 0;
palmSdCard.response = SD_CARD_RESPONSE_NOTHING;
palmSdCard.allowInvalidCrc = false;
palmSdCard.chipSelect = false;
}
void sdCardSetChipSelect(bool value){
if(value != palmSdCard.chipSelect){
//may need to perform other actions on chip select toggle too
debugLog("SD card chip select set to:%s\n", value ? "true" : "false");
palmSdCard.chipSelect = value;
}
}
bool sdCardExchangeBit(bool bit){
@@ -166,13 +155,11 @@ bool sdCardExchangeBit(bool bit){
#endif
debugLog("SD command:cmd:0x%02X, arg:0x%08X, CRC:0x%02X\n", command, argument, crc);
if(palmSdCard.allowInvalidCrc || sdCardCmdIsCrcValid(command, argument, crc)){
//respond with command value
if(sdCardCmdIsCrcValid(command, argument, crc)){
debugLog("SD valid CRC\n");
switch(command){
case GO_IDLE_STATE:
palmSdCard.allowInvalidCrc = true;
sdCardDoResponseR1(0x01);//"idle state" bit set should be set
break;
@@ -183,7 +170,6 @@ bool sdCardExchangeBit(bool bit){
}
else{
//send back R1 response with CRC error set
debugLog("SD invalid CRC\n");
sdCardDoResponseR1(0x08);//"command CRC error" bit set
}

View File

@@ -5,7 +5,6 @@
void sdCardReset(void);
void sdCardSetChipSelect(bool value);
bool sdCardExchangeBit(bool bit);
#endif

View File

@@ -25,11 +25,10 @@
#define SED1376_REG_SIZE 0xB4
#define SED1376_LUT_SIZE 0x100
#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
#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
uint16_t sed1376Framebuffer[160 * 160];
uint8_t sed1376Ram[SED1376_RAM_SIZE];
uint8_t sed1376Framebuffer[SED1376_FB_SIZE];
static uint8_t sed1376Registers[SED1376_REG_SIZE];
static uint8_t sed1376RLut[SED1376_LUT_SIZE];
@@ -113,7 +112,7 @@ void sed1376Reset(void){
memset(sed1376RLut, 0x00, SED1376_LUT_SIZE);
memset(sed1376GLut, 0x00, SED1376_LUT_SIZE);
memset(sed1376BLut, 0x00, SED1376_LUT_SIZE);
memset(sed1376Ram, 0x00, SED1376_RAM_SIZE);
memset(sed1376Framebuffer, 0x00, SED1376_FB_SIZE);
palmMisc.backlightLevel = 0;
palmMisc.lcdOn = false;
@@ -132,7 +131,7 @@ uint64_t sed1376StateSize(void){
size += SED1376_REG_SIZE;
size += SED1376_LUT_SIZE * 3;
size += SED1376_RAM_SIZE;
size += SED1376_FB_SIZE;
return size;
}
@@ -148,8 +147,8 @@ void sed1376SaveState(uint8_t* data){
offset += SED1376_LUT_SIZE;
memcpy(data + offset, sed1376BLut, SED1376_LUT_SIZE);
offset += SED1376_LUT_SIZE;
memcpy(data + offset, sed1376Ram, SED1376_RAM_SIZE);
offset += SED1376_RAM_SIZE;
memcpy(data + offset, sed1376Framebuffer, SED1376_FB_SIZE);
offset += SED1376_FB_SIZE;
}
void sed1376LoadState(uint8_t* data){
@@ -164,8 +163,8 @@ void sed1376LoadState(uint8_t* data){
offset += SED1376_LUT_SIZE;
memcpy(sed1376BLut, data + offset, SED1376_LUT_SIZE);
offset += SED1376_LUT_SIZE;
memcpy(sed1376Ram, data + offset, SED1376_RAM_SIZE);
offset += SED1376_RAM_SIZE;
memcpy(sed1376Framebuffer, data + offset, SED1376_FB_SIZE);
offset += SED1376_FB_SIZE;
//refresh LUT
MULTITHREAD_LOOP(index) for(index = 0; index < SED1376_LUT_SIZE; index++)
@@ -339,7 +338,7 @@ void sed1376Render(void){
MULTITHREAD_DOUBLE_LOOP(pixelX, pixelY) for(pixelY = 0; pixelY < 160; pixelY++)
for(pixelX = 0; pixelX < 160; pixelX++)
sed1376Framebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
palmFramebuffer[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);
@@ -367,7 +366,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++)
sed1376Framebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
palmFramebuffer[pixelY * 160 + pixelX] = renderPixel(pixelX, pixelY);
}
}
@@ -377,21 +376,21 @@ void sed1376Render(void){
//display inversion
if((sed1376Registers[DISP_MODE] & 0x30) == 0x10)
MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++)
sed1376Framebuffer[index] = ~sed1376Framebuffer[index];
palmFramebuffer[index] = ~palmFramebuffer[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++){
sed1376Framebuffer[index] >>= 2;
sed1376Framebuffer[index] &= 0x39E7;
palmFramebuffer[index] >>= 2;
palmFramebuffer[index] &= 0x39E7;
}
break;
case 1:
MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++){
sed1376Framebuffer[index] >>= 1;
sed1376Framebuffer[index] &= 0x7BEF;
palmFramebuffer[index] >>= 1;
palmFramebuffer[index] &= 0x7BEF;
}
break;
case 2:
@@ -405,7 +404,7 @@ void sed1376Render(void){
}
else{
//black screen
memset(sed1376Framebuffer, 0x00, 160 * 160 * sizeof(uint16_t));
memset(palmFramebuffer, 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");
}
}

View File

@@ -4,8 +4,7 @@
#include <stdint.h>
#include <stdbool.h>
extern uint16_t sed1376Framebuffer[];
extern uint8_t sed1376Ram[];
extern uint8_t sed1376Framebuffer[];
void sed1376Reset(void);
uint64_t sed1376StateSize(void);

View File

@@ -31,38 +31,38 @@ static uint16_t lutMonochromeValue(uint8_t lutIndex){
//monochrome
static uint16_t get1BppMonochrome(uint16_t x, uint16_t y){
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01);
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01);
}
static uint16_t get2BppMonochrome(uint16_t x, uint16_t y){
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03);
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03);
}
static uint16_t get4BppMonochrome(uint16_t x, uint16_t y){
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F);
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F);
}
static uint16_t get8BppMonochrome(uint16_t x, uint16_t y){
return lutMonochromeValue(sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]);
return lutMonochromeValue(sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]);
}
static uint16_t get16BppMonochrome(uint16_t x, uint16_t y){
uint16_t pixelValue = sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2)] << 8 | sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2 + 1)];
uint16_t pixelValue = sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2)] << 8 | sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x) * 2 + 1)];
return makeRgb16FromGreenComponent(pixelValue);
}
//color
static uint16_t get1BppColor(uint16_t x, uint16_t y){
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01];
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 8)] >> (7 - x % 8) & 0x01];
}
static uint16_t get2BppColor(uint16_t x, uint16_t y){
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03];
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 4)] >> (6 - x % 4 * 2) & 0x03];
}
static uint16_t get4BppColor(uint16_t x, uint16_t y){
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F];
return sed1376OutputLut[sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + y * lineSize + x / 2)] >> (4 - x % 2 * 4) & 0x0F];
}
static uint16_t get8BppColor(uint16_t x, uint16_t y){
return sed1376OutputLut[sed1376Ram[handlePanelDataSwaps(screenStartAddress + y * lineSize + x)]];
return sed1376OutputLut[sed1376Framebuffer[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 sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2) + 1)] << 8 | sed1376Ram[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2))];
return sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2) + 1)] << 8 | sed1376Framebuffer[handlePanelDataSwaps(screenStartAddress + (y * lineSize + x * 2))];
}
static void selectRenderer(bool color, uint8_t bpp){

View File

@@ -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_CUSTOM_FB 0x00000008/*creates a dynamicly sized framebuffer for hires mode, the 160x160 framebuffer is a transparent overlay over the extended framebuffer*/
#define FEATURE_320x320 0x00000008/*creates a 320x320 framebuffer for hires mode, the 160x160 framebuffer is a transparent overlay over the 320x320 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 dynamic framebuffer, read/write, EMU_SIZE must have width in the top 16 bits and height in the bottom 16 bits*/
#define EMU_HIRESFB 0x004/*sets the address of the 320x320 framebuffer, read/write*/
#define EMU_SRC 0x008/*write only*/
#define EMU_DST 0x00C/*write only*/
#define EMU_SIZE 0x010/*write only*/

View File

@@ -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_CUSTOM_FB 0x00000008/*creates a dynamicly sized framebuffer for hires mode, the 160x160 framebuffer is a transparent overlay over the extended framebuffer*/
#define FEATURE_320x320 0x00000008/*creates a 320x320 framebuffer for hires mode, the 160x160 framebuffer is a transparent overlay over the 320x320 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 dynamic framebuffer, read/write, EMU_SIZE must have width in the top 16 bits and height in the bottom 16 bits*/
#define EMU_HIRESFB 0x004/*sets the address of the 320x320 framebuffer, read/write*/
#define EMU_SRC 0x008/*write only*/
#define EMU_DST 0x00C/*write only*/
#define EMU_SIZE 0x010/*write only*/