From 5ce2c5c5f98286425d621b7af50b7a1b40d6e1ce Mon Sep 17 00:00:00 2001 From: falco Date: Fri, 10 Mar 2023 04:55:37 -0500 Subject: [PATCH] EvmuRom refactor, EvmuBuzzer bugfix, gimbal dates 1) Syncing libGimbal submodule 2) evmu_address_space.h - added entry for BIOS BCD encoded seconds (seems to be right) - added entry for BIOS mode 3) evmu_battery.h, evmu_buzzer.h - added file header + todo list for documentation/organization 4) EvmuRom - totally and completely refactored - biosLoaded() removed, now use biosType() != EVMU_BIOS_TYPE_EMULATED - Subroutine enum values are now entry points - virtual methods are now actually used + implemented - call() takes a PC and returns a PC - added biosType() which uses newfound system variable - refactored EVERYTHING to use GblDateTime internally + externally - removed every reference to old REEST device other than writing flash, which will have to go once the flash write signal is redone - implemented properties - moved random miscellaneous notes and shit to implementation file 5) EvmuBuzzer - fixed bug with startup beep and other sounds not working correctly - had to remove mute check for inactive PCM from gain accessor, since gain is retrieved before a sample is even played 6) EvmuLcd - added/embedded logo for evil usage later --- .../cpp/include/evmu-core-cpp/evmu_device.hpp | 2 +- lib/api/evmu/hw/evmu_address_space.h | 4 +- lib/api/evmu/hw/evmu_battery.h | 8 + lib/api/evmu/hw/evmu_buzzer.h | 10 +- lib/api/evmu/hw/evmu_gamepad.h | 7 +- lib/api/evmu/hw/evmu_lcd.h | 7 + lib/api/evmu/hw/evmu_rom.h | 180 +++----- lib/lib/libgimbal | 2 +- lib/source/hw/evmu_buzzer.c | 8 +- lib/source/hw/evmu_cpu.c | 4 +- lib/source/hw/evmu_lcd.c | 18 + lib/source/hw/evmu_memory.c | 28 +- lib/source/hw/evmu_rom.c | 388 ++++++++++++------ 13 files changed, 374 insertions(+), 292 deletions(-) diff --git a/legacy/wrappers/cpp/include/evmu-core-cpp/evmu_device.hpp b/legacy/wrappers/cpp/include/evmu-core-cpp/evmu_device.hpp index e70f048..58ad451 100644 --- a/legacy/wrappers/cpp/include/evmu-core-cpp/evmu_device.hpp +++ b/legacy/wrappers/cpp/include/evmu-core-cpp/evmu_device.hpp @@ -263,7 +263,7 @@ inline bool VmuDevice::writeMemoryByte(uint16_t address, uint8_t value) const { } inline bool VmuDevice::isBiosLoaded(void) const { - return EvmuRom_biosLoaded(EVMU_DEVICE_PRISTINE_PUBLIC(_dev)->pRom); + return EvmuRom_biosType(EVMU_DEVICE_PRISTINE_PUBLIC(_dev)->pRom) != EVMU_BIOS_TYPE_EMULATED; } inline void VmuDevice::skipBiosSetup(bool enable) { diff --git a/lib/api/evmu/hw/evmu_address_space.h b/lib/api/evmu/hw/evmu_address_space.h index 1d26300..8d1ff84 100644 --- a/lib/api/evmu/hw/evmu_address_space.h +++ b/lib/api/evmu/hw/evmu_address_space.h @@ -44,7 +44,7 @@ extern "C" { #define EVMU_ADDRESS_SYSTEM_DAY_BCD 0x13 // BCD Day #define EVMU_ADDRESS_SYSTEM_HOUR_BCD 0x14 // BCD Hour #define EVMU_ADDRESS_SYSTEM_MINUTE_BCD 0x15 // BCD Minute -// UNKNOWN [1 byte] 0x16 // BCD Second? +#define EVMU_ADDRESS_SYSTEM_SEC_BCD 0x16 // BCD Seconds(?) #define EVMU_ADDRESS_SYSTEM_YEAR_MSB 0x17 // Non-BCD Year High Byte #define EVMU_ADDRESS_SYSTEM_YEAR_LSB 0x18 // Non-BCD Year Low Byte #define EVMU_ADDRESS_SYSTEM_MONTH 0x19 // Non-BCD Month @@ -55,7 +55,7 @@ extern "C" { #define EVMU_ADDRESS_SYSTEM_HALF_SEC 0x1e // 0 or 1, driven by base-timer interrupt every 0.5s, WORK AREA, DON'T WRITE #define EVMU_ADDRESS_SYSTEM_LEAP_YEAR 0x1f // 0 for no, 1 for yes, WORK AREA, DON'T WRITE //-------------------- General Bios Variables -------------------- -// UNKNOWN [17 bytes] 0x20-0x30 // probably BIOS logic... LOOKS LIKE ITS THE MODE INDEX!!! +#define EVMU_ADDRESS_SYSTEM_MODE 0x30 // probably BIOS logic... LOOKS LIKE ITS THE MODE INDEX!!! #define EVMU_ADDRESS_SYSTEM_DATE_SET 0x31 // 0xff - date set, 00 - date not set //0x33 - 0x34 seem to be INACTIVITY COUNTERS for putting the bitch to sleep!!!! // UNKKNOWN [32 bytes] 0x32-0x49 // other BIOS settings? diff --git a/lib/api/evmu/hw/evmu_battery.h b/lib/api/evmu/hw/evmu_battery.h index f431956..b0fc68c 100755 --- a/lib/api/evmu/hw/evmu_battery.h +++ b/lib/api/evmu/hw/evmu_battery.h @@ -1,3 +1,11 @@ +/*! \file + * \brief BIOS battery monitor + low battery detection circuit + * \ingroup Peripherals + * + * \todo + * - properties + */ + #ifndef EVMU_BATTERY_H #define EVMU_BATTERY_H diff --git a/lib/api/evmu/hw/evmu_buzzer.h b/lib/api/evmu/hw/evmu_buzzer.h index 772f8d4..19499f9 100755 --- a/lib/api/evmu/hw/evmu_buzzer.h +++ b/lib/api/evmu/hw/evmu_buzzer.h @@ -1,7 +1,9 @@ -/*! - * \todo - * implement properties - * stop playback when emulation halts +/*! \file + * \brief Piezoelectric buzzer, PWM tone generation + * \ingroup Peripherals + * + * \todo + * - Stop playback when emulation halts */ #ifndef EVMU_BUZZER_H diff --git a/lib/api/evmu/hw/evmu_gamepad.h b/lib/api/evmu/hw/evmu_gamepad.h index e5b25a4..275d15e 100755 --- a/lib/api/evmu/hw/evmu_gamepad.h +++ b/lib/api/evmu/hw/evmu_gamepad.h @@ -1,7 +1,6 @@ -/*! - * \todo - * Supposed to only poll for input when latch is set/reset - * reading from pin should not return latch value +/*! \file + * \brief Port 3 button states + back-end polling hooks + * \ingroup Peripherals */ #ifndef EVMU_GAMEPAD_H diff --git a/lib/api/evmu/hw/evmu_lcd.h b/lib/api/evmu/hw/evmu_lcd.h index 5dfed16..9ff95b0 100755 --- a/lib/api/evmu/hw/evmu_lcd.h +++ b/lib/api/evmu/hw/evmu_lcd.h @@ -1,3 +1,10 @@ +/*! \file + * \brief LCD display circuit with emulated effects + back-end rendering signals + * \ingroup Peripherals + * \todo + * - Pixel ghosting still needs some work + */ + #ifndef EVMU_LCD_H #define EVMU_LCD_H diff --git a/lib/api/evmu/hw/evmu_rom.h b/lib/api/evmu/hw/evmu_rom.h index 7752c6b..2351c59 100644 --- a/lib/api/evmu/hw/evmu_rom.h +++ b/lib/api/evmu/hw/evmu_rom.h @@ -1,3 +1,18 @@ +/*! \file + * \brief External ROM chip, BIOS, Firmware routines + * \ingroup Peripherals + * + * \todo + * - CLEAN UP IMPLEMENTATION IN GENERAL + * - remove "reestDevice" references (pending Flash updates get moved) + * - EvmuRom_setBiosMode() + * - EvmuRom["biosMode"]: R/W + * - EvmuRom["dateTime"]: R/W (pending on ISO8601 in Gimbal) + * - Maybe signal when entering/exiting BIOS + * - overridable virtuals for whole custom BIOS + * - return elapsed ticks/cycles for subroutine call + * - return BIOS version information and shit + */ #ifndef EVMU_ROM_H #define EVMU_ROM_H @@ -10,23 +25,13 @@ #define EVMU_ROM_CLASS(klass) (GBL_CLASS_CAST(klass, EvmuRom)) #define EVMU_ROM_GET_CLASS(instance) (GBL_INSTANCE_GET_CLASS(instance, EvmuRom)) -#define EVMU_ROM_SIZE 65536 - -#define EVMU_BIOS_SYS_PROG_ADDRESS_BASE 0x0000 -#define EVMU_BIOS_SYS_PROG_SIZE 16384 -#define EVMU_BIOS_OS_PROG_ADDRESS_BASE 0xed00 -#define EVMU_BIOS_OS_PROG_SIZE 4096 - -// Firmware calls: utility functions that return execution back to app -#define EVMU_BIOS_ADDRESS_FM_WRT_EX 0x100 -#define EVMU_BIOS_ADDRESS_FM_WRTA_EX 0x108 -#define EVMU_BIOS_ADDRESS_FM_VRF_EX 0x110 -#define EVMU_BIOS_ADDRESS_FM_PRD_EX 0x120 +#define EVMU_ROM_SIZE 65536 ///< Total size of external ROM chip -// BIOS routines: control yields to BIOS? -#define EVMU_BIOS_ADDRESS_TIMER_EX 0x130 // Timer update function used as ISR to populate date/time in system variables -#define EVMU_BIOS_ADDRESS_SLEEP_EX 0x140 -#define EVMU_BIOS_ADDRESS_EXIT_EX 0x1f0 // MODE button? +#define EVMU_BIOS_SYS_PROG_ADDRESS_BASE 0x0000 ///< Start of Firmware/Subroutines in bytes +#define EVMU_BIOS_SYS_PROG_SIZE 16384 ///< Size of Firmware/Subroutines in bytes +#define EVMU_BIOS_OS_PROG_ADDRESS_BASE 0xed00 ///< Start address of OS/BIOS program +#define EVMU_BIOS_OS_PROG_SIZE 4096 ///< Size of OS/BIOS program in bytes +#define EVMU_BIOS_SKIP_DATE_TIME_PC 0x2e1 ///< BIOS PC address just after setting date/time #define GBL_SELF_TYPE EvmuRom @@ -36,138 +41,67 @@ GBL_FORWARD_DECLARE_STRUCT(GblDateTime); GBL_FORWARD_DECLARE_STRUCT(EvmuRom); GBL_DECLARE_ENUM(EVMU_BIOS_SUBROUTINE) { - EVMU_BIOS_SUBROUTINE_FM_WRT_EX, - EVMU_BIOS_SUBROUTINE_FM_WRTA_EX, - EVMU_BIOS_SUBROUTINE_FM_VRF_EX, - EVMU_BIOS_SUBROUTINE_FM_PRD_EX, - EVMU_BIOS_SUBROUTINE_TIMER_EX, - EVMU_BIOS_SUBROUTINE_SLEEP_EX, - EVMU_BIOS_SUBROUTINE_EXIT_EX, - EVMU_BIOS_SUBROUTINE_COUNT + EVMU_BIOS_SUBROUTINE_RESET = 0x000, ///< Regular starting point + // Firmware calls: utility functions that return execution back to app + EVMU_BIOS_SUBROUTINE_FM_WRT_EX = 0x100, ///< Flash memory write, return address variant 1 + EVMU_BIOS_SUBROUTINE_FM_WRTA_EX = 0x108, ///< Flash memory write, return address variant 2 + EVMU_BIOS_SUBROUTINE_FM_VRF_EX = 0x110, ///< Flash memory page data verify + EVMU_BIOS_SUBROUTINE_FM_PRD_EX = 0x120, ///< Flash memory paged read data + // BIOS routines: control yields to BIOS? + EVMU_BIOS_SUBROUTINE_TIMER_EX = 0x130, ///< System time update, used as Base Timer ISR + EVMU_BIOS_SUBROUTINE_SLEEP_EX = 0x140, ///< Enable sleep mode + EVMU_BIOS_SUBROUTINE_EXIT_EX = 0x1f0 ///< MODE button logic }; GBL_DECLARE_ENUM(EVMU_BIOS_TYPE) { - EVMU_BIOS_TYPE_EMULATED, - EVMU_BIOS_TYPE_AMERICAN_IMAGE_V1_05 = 0xC825003A, - EVMU_BIOS_TYPE_JAPANESE_IMAGE_V1_04 = 0x8E0F867A, - EVMU_BIOS_TYPE_UNKNOWN_IMAGE + EVMU_BIOS_TYPE_EMULATED, ///< Default, no BIOS, software emulation + EVMU_BIOS_TYPE_AMERICAN_IMAGE_V1_05 = 0xC825003A, ///< CRC for American BIOS + EVMU_BIOS_TYPE_JAPANESE_IMAGE_V1_04 = 0x8E0F867A, ///< CRC for Japanese BIOS + EVMU_BIOS_TYPE_UNKNOWN_IMAGE ///< Any other unknown image }; GBL_DECLARE_ENUM(EVMU_BIOS_MODE) { - EVMU_BIOS_MODE_UNKNOWN, - EVMU_BIOS_MODE_MAPLE, //connected to DC, maple mode - EVMU_BIOS_MODE_GAME, - EVMU_BIOS_MODE_FILE, - EVMU_BIOS_MODE_TIME, - EVMU_BIOS_MODE_COUNT + EVMU_BIOS_MODE_FILE, ///< File Manager mode + EVMU_BIOS_MODE_GAME, ///< Game/Application mode + EVMU_BIOS_MODE_TIME, ///< Clock/time mode + EVMU_BIOS_MODE_MAPLE, ///< Connected to DC, Maple slave mode + EVMU_BIOS_MODE_UNKNOWN, ///< Unnknown mode (unknown BIOS) + EVMU_BIOS_MODE_COUNT ///< Number of BIOS modes }; GBL_CLASS_DERIVE(EvmuRom, EvmuPeripheral) EVMU_RESULT (*pFnLoadBios)(GBL_SELF, const char* pPath); - EVMU_RESULT (*pFnCallBios)(GBL_SELF, EvmuAddress psw); + EVMU_RESULT (*pFnCallBios)(GBL_SELF, EvmuAddress entryPc, EvmuAddress* pRetPc); GBL_CLASS_END GBL_INSTANCE_DERIVE_EMPTY(EvmuRom, EvmuPeripheral) GBL_PROPERTIES(EvmuRom, - (biosActive, GBL_GENERIC, (READ), GBL_BOOL_TYPE), - (biosType, GBL_GENERIC, (READ), GBL_ENUM_TYPE), - (biosMode, GBL_GENERIC, (READ, WRITE), GBL_ENUM_TYPE) + (biosActive, GBL_GENERIC, (READ), GBL_BOOL_TYPE), + (biosType, GBL_GENERIC, (READ), GBL_ENUM_TYPE), + (biosMode, GBL_GENERIC, (READ), GBL_ENUM_TYPE), + (dateTime, GBL_GENERIC, (READ), GBL_STRING_TYPE) ) -EVMU_EXPORT GblType EvmuRom_type (void) GBL_NOEXCEPT; +EVMU_EXPORT GblType EvmuRom_type (void) GBL_NOEXCEPT; -EVMU_EXPORT GblBool EvmuRom_biosLoaded (GBL_CSELF) GBL_NOEXCEPT; -EVMU_EXPORT GblBool EvmuRom_biosActive (GBL_CSELF) GBL_NOEXCEPT; +EVMU_EXPORT GblBool EvmuRom_biosActive (GBL_CSELF) GBL_NOEXCEPT; +EVMU_EXPORT EVMU_BIOS_TYPE EvmuRom_biosType (GBL_CSELF) GBL_NOEXCEPT; +EVMU_EXPORT EVMU_BIOS_MODE EvmuRom_biosMode (GBL_CSELF) GBL_NOEXCEPT; -EVMU_EXPORT EVMU_RESULT EvmuRom_loadBios (GBL_SELF, const char* pPath) GBL_NOEXCEPT; -EVMU_EXPORT EvmuAddress EvmuRom_callBios (GBL_SELF) GBL_NOEXCEPT; +EVMU_EXPORT EVMU_RESULT EvmuRom_loadBios (GBL_SELF, const char* pPath) GBL_NOEXCEPT; +EVMU_EXPORT EvmuAddress EvmuRom_callBios (GBL_SELF, EvmuAddress entry) GBL_NOEXCEPT; -EVMU_EXPORT EVMU_RESULT EvmuRom_skipBiosSetup (GBL_SELF, GblBool enableSkip) GBL_NOEXCEPT; +EVMU_EXPORT EVMU_RESULT EvmuRom_skipBiosSetup (GBL_SELF, GblBool enableSkip) GBL_NOEXCEPT; -EVMU_EXPORT EVMU_RESULT EvmuRom_dateTime (GBL_CSELF, - GblDateTime* pDateTime) GBL_NOEXCEPT; - -EVMU_EXPORT EVMU_RESULT EvmuRom_setDateTime (GBL_SELF, - const GblDateTime* pDTime) GBL_NOEXCEPT; +EVMU_EXPORT GblDateTime* EvmuRom_dateTime (GBL_CSELF, + GblDateTime* pDateTime) GBL_NOEXCEPT; +EVMU_EXPORT EVMU_RESULT EvmuRom_setDateTime (GBL_SELF, + const GblDateTime* pDateTime) GBL_NOEXCEPT; GBL_DECLS_END #undef GBL_SELF_TYPE #endif // EVMU_ROM_H - - -/* - * WHOLE ADDRESS SPACE: BIOS - * Standalone Utility Functions: Firmware/OS routines - * Random routines mid-BIOS: system routines - * All of this shit: subroutines - * - */ - -/* FLASH MEMORY VARIABLES USED WITH BIOS FW CALL - * THIS IS IN RAM BANK 1, IN APP-SPACE!!! - * 0x7d Fmbank - Specify flash bank to use (guess bit 0 or 1) - * 0x7e Fmadd_h - Flash memory address (upper 8 bits) - * 0x7f Fmadd_l - Flash memory address (lower 8 bits) - */ - -/* -Document all known static metadata regions in the BIOS -1) BIOS version -2) Maple information -3) Font characters - -4) Known harness-able utility functions that can be used via stack return attacks - -add a public API that allows you to query and extract this info. - -Present at 0x14BE in the BIOS, alongside some build info. -0x14BE JAP BIOS version info -0xAA7 US BIOS version info - -Visual Memory Produced By or Under License From SEGA ENTERPRISES,LTD. -Version 1.004,1998/09/30,315-6208-01,SEGA Visual Memory System BIOS Produced by Sue -*/ - -/* Need a list of BIOS initialization registers with default values! - * - */ - -#if 0 -EVMU_EXPORT EvmuAddress EvmuRom_subroutineAddress (EVMU_BIOS_SUBROUTINE sub) GBL_NOEXCEPT; -EVMU_EXPORT EvmuAddress EvmuRom_subroutineRetAddress (EVMU_BIOS_SUBROUTINE sub) GBL_NOEXCEPT; - -EVMU_EXPORT EVMU_RESULT EvmuRom_callSubroutine (GBL_CSELF, - EVMU_BIOS_SUBROUTINE subroutine) GBL_NOEXCEPT; - -EVMU_EXPORT EVMU_RESULT EvmuRom_biosVersionString (GBL_CSELF, GblStringBuffer* pStr) GBL_NOEXCEPT; - -EVMU_EXPORT EvmuWord EvmuRom_readByte (GBL_CSELF, EvmuAddress address) GBL_NOEXCEPT; - -EVMU_EXPORT EVMU_RESULT EvmuRom_readBytes (GBL_CSELF, - EvmuAddress base, - void* pData, - GblSize* pBytes) GBL_NOEXCEPT; - -EVMU_EXPORT EvmuWord EvmuRom_writeByte (GBL_CSELF, - EvmuAddress address, - EvmuWord value) GBL_NOEXCEPT; - -EVMU_EXPORT EVMU_RESULT EvmuRom_writeBytes (GBL_CSELF, - EvmuAddress base, - void* pData, - GblSize* pBytes) GBL_NOEXCEPT; - -EVMU_EXPORT EVMU_BIOS_TYPE EvmuRom_biosType (GBL_CSELF) GBL_NOEXCEPT; -EVMU_EXPORT EVMU_BIOS_MODE EvmuRom_biosMode (GBL_CSELF) GBL_NOEXCEPT; -EVMU_EXPORT EVMU_RESULT EvmuRom_setBiosMode (GBL_CSELF, EVMU_BIOS_MODE mode) GBL_NOEXCEPT; - -#endif -// Call this whole fucker "Bios" -// Call the thing that MUXes Flash + Bios "Rom" - - -// use system clock? diff --git a/lib/lib/libgimbal b/lib/lib/libgimbal index 3b105a7..9ec6c66 160000 --- a/lib/lib/libgimbal +++ b/lib/lib/libgimbal @@ -1 +1 @@ -Subproject commit 3b105a71fc777f3ef779ea107f7a1245536ccac3 +Subproject commit 9ec6c66dc12388b6447ff0ea0b800a4589d55aea diff --git a/lib/source/hw/evmu_buzzer.c b/lib/source/hw/evmu_buzzer.c index 3a79d70..ce95019 100755 --- a/lib/source/hw/evmu_buzzer.c +++ b/lib/source/hw/evmu_buzzer.c @@ -9,7 +9,7 @@ #include "../types/evmu_marshal_.h" #define EVMU_BUZZER_FREQ_RESP_BASE_OFFSET_ 0xe0 -#define EVMU_BUZZER_FREQ_RESP_DEFAULT_VALUE_ 40 +#define EVMU_BUZZER_FREQ_RESP_DEFAULT_VALUE_ 30 #define EVMU_BUZZER_FREQ_RESP_MAX_VALUE_ 72 static uint8_t freqResponse_[0x1f] = { @@ -224,10 +224,12 @@ EVMU_EXPORT GblSize EvmuBuzzer_pcmFrequency(const EvmuBuzzer* pSelf) { EVMU_EXPORT float EvmuBuzzer_pcmGain(const EvmuBuzzer* pSelf) { EvmuBuzzer_* pSelf_ = EVMU_BUZZER_(pSelf); - +/* Cannot work when update is called before play! Mutes next tone! if(!pSelf_->active) { return 0.0f; - } else if(pSelf->enableFreqResp) { + } else +*/ + if(pSelf->enableFreqResp) { if(pSelf_->tonePeriod < EVMU_BUZZER_FREQ_RESP_BASE_OFFSET_ || pSelf_->tonePeriod > EVMU_BUZZER_FREQ_RESP_BASE_OFFSET_ + GBL_COUNT_OF(freqResponse_)) diff --git a/lib/source/hw/evmu_cpu.c b/lib/source/hw/evmu_cpu.c index 126a489..4f48896 100755 --- a/lib/source/hw/evmu_cpu.c +++ b/lib/source/hw/evmu_cpu.c @@ -67,9 +67,9 @@ EVMU_EXPORT EVMU_RESULT EvmuCpu_executeNext(EvmuCpu* pSelf) { //Check if we entered the firmware if(!(pMemory_->sfr[EVMU_SFR_OFFSET(EVMU_ADDRESS_SFR_EXT)] & 0x1)) { - if(!EvmuRom_biosLoaded(pRom)) { + if(EvmuRom_biosType(pRom) == EVMU_BIOS_TYPE_EMULATED) { //handle the BIOS call in software if no firwmare has been loaded - if((pSelf_->pc = EvmuRom_callBios(pRom))) + if((pSelf_->pc = EvmuRom_callBios(pRom, pSelf_->pc))) //jump back to USER mode before resuming execution. EvmuMemory_writeInt(pMemory, EVMU_ADDRESS_SFR_EXT, diff --git a/lib/source/hw/evmu_lcd.c b/lib/source/hw/evmu_lcd.c index 5082ef7..de31af2 100755 --- a/lib/source/hw/evmu_lcd.c +++ b/lib/source/hw/evmu_lcd.c @@ -313,6 +313,24 @@ EVMU_EXPORT EvmuTicks EvmuLcd_refreshRateTicks(const EvmuLcd* pSelf) { EVMU_LCD_REFRESH_TICKS_83HZ_ : EVMU_LCD_REFRESH_TICKS_166HZ_; } +EVMU_EXPORT void EvmuLcd_drawLogo(const EvmuLcd* pSelf) { + const static uint8_t byteArray[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x70, 0xff, 0xff, 0xff, 0xfe, 0x07, 0x3e, 0x7f, 0xff, 0xff, 0xfc, 0x0f, 0x3f, 0x3f, 0xff, + 0xff, 0xf8, 0x3e, 0x3f, 0x9f, 0xff, 0xff, 0xf8, 0x7e, 0xbf, 0xdf, 0xff, 0xff, 0xf0, 0x7e, 0x9f, + 0xef, 0xff, 0xff, 0xf0, 0xfa, 0x9f, 0xff, 0xff, 0xff, 0xe0, 0xfa, 0x9f, 0xff, 0xff, 0xff, 0xe1, + 0xfa, 0x9f, 0xff, 0xff, 0xff, 0xe1, 0xf8, 0x9f, 0xff, 0xff, 0xff, 0xe1, 0xf8, 0x9b, 0xff, 0xff, + 0xff, 0xe1, 0xea, 0x09, 0xf7, 0xff, 0xff, 0xe0, 0xea, 0x09, 0xf7, 0xff, 0xff, 0xf0, 0xe2, 0x81, + 0xef, 0xff, 0xff, 0xf0, 0x6a, 0x81, 0xef, 0xff, 0xff, 0xf8, 0x40, 0x80, 0xcf, 0xff, 0xff, 0xf8, + 0x20, 0x00, 0x9f, 0xff, 0xff, 0xfc, 0x18, 0x02, 0x1f, 0xff, 0xff, 0xfe, 0x03, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0x02, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x82, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x83, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x9f, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff + }; + +} + static GBL_RESULT EvmuLcd_refreshScreen_(EvmuLcd* pSelf) { GBL_CTX_BEGIN(NULL); diff --git a/lib/source/hw/evmu_memory.c b/lib/source/hw/evmu_memory.c index 9d6baaf..288e505 100755 --- a/lib/source/hw/evmu_memory.c +++ b/lib/source/hw/evmu_memory.c @@ -6,6 +6,7 @@ #include "evmu_timers_.h" #include "evmu_gamepad_.h" #include "evmu_rom_.h" +#include EVMU_EXPORT EvmuAddress EvmuMemory_indirectAddress(const EvmuMemory* pSelf, uint8_t mode) { EvmuAddress value = 0; @@ -510,8 +511,6 @@ static GBL_RESULT EvmuMemory_reset_(EvmuIBehavior* pSelf) { EvmuDevice_* pDevice_ = EVMU_DEVICE_(pDevice); GBL_INSTANCE_VCALL_DEFAULT(EvmuIBehavior, pFnReset, pSelf); - time_t t = time(NULL); - struct tm *tm = localtime(&t); GblBool skipSetup = pDevice_->pRom->bSetupSkipEnabled; @@ -553,12 +552,12 @@ static GBL_RESULT EvmuMemory_reset_(EvmuIBehavior* pSelf) { pDevice_->pTimers->timer0.tscale = 256; GBL_CTX_INFO("Resetting PC."); if(skipSetup) { - EvmuCpu_setPc(pDevice->pCpu, 0x02E1); + EvmuCpu_setPc(pDevice->pCpu, EVMU_BIOS_SKIP_DATE_TIME_PC); } else { EvmuCpu_setPc(pDevice->pCpu, 0x0); } - if(EvmuRom_biosLoaded(pDevice->pRom)) { + if(EvmuRom_biosType(pDevice->pRom) != EVMU_BIOS_TYPE_EMULATED) { // pDevice_->pMemory->sfr[EVMU_SFR_OFFSET(EVMU_ADDRESS_SFR_P7)] |= SFR_P7_P71_MASK; pDevice_->pMemory->pIntMap[VMU_MEM_SEG_GP1] = pDevice_->pMemory->ram[VMU_RAM_BANK0]; pDevice_->pMemory->pIntMap[VMU_MEM_SEG_GP2] = &pDevice_->pMemory->ram[VMU_RAM_BANK0][VMU_MEM_SEG_SIZE]; @@ -568,23 +567,10 @@ static GBL_RESULT EvmuMemory_reset_(EvmuIBehavior* pSelf) { } //else { //Initialize System Variables -#if 1 - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_MSB_BCD] = GBL_BCD_BYTE_PACK(tm->tm_year/100+19); - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_LSB_BCD] = GBL_BCD_BYTE_PACK(tm->tm_year%100); - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MONTH_BCD] = GBL_BCD_BYTE_PACK(tm->tm_mon+1); - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DAY_BCD] = GBL_BCD_BYTE_PACK(tm->tm_mday); - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HOUR_BCD] = GBL_BCD_BYTE_PACK(tm->tm_hour); - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MINUTE_BCD] = GBL_BCD_BYTE_PACK(tm->tm_min); - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_MSB] = (tm->tm_year+1900)>>8; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_LSB] = (tm->tm_year+1900)&0xff; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MONTH] = tm->tm_mon+1; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DAY] = tm->tm_mday; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HOUR] = tm->tm_hour; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MINUTE] = tm->tm_min; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_SEC] = tm->tm_sec; - pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DATE_SET] = 0xff; -#endif - if(!EvmuRom_biosLoaded(pDevice->pRom)) { + GblDateTime dateTime; + EvmuRom_setDateTime(pDevice->pRom, GblDateTime_nowLocal(&dateTime)); + + if(EvmuRom_biosType(pDevice->pRom) == EVMU_BIOS_TYPE_EMULATED) { pDevice_->pMemory->pIntMap[VMU_MEM_SEG_GP1] = pDevice_->pMemory->ram[VMU_RAM_BANK1]; pDevice_->pMemory->pIntMap[VMU_MEM_SEG_GP2] = &pDevice_->pMemory->ram[VMU_RAM_BANK1][VMU_MEM_SEG_SIZE]; //EvmuMemory_setExtSource(pMemory, EVMU_MEMORY_EXT_SRC_FLASH_BANK_0); diff --git a/lib/source/hw/evmu_rom.c b/lib/source/hw/evmu_rom.c index c2b7d2c..4a57868 100644 --- a/lib/source/hw/evmu_rom.c +++ b/lib/source/hw/evmu_rom.c @@ -1,93 +1,87 @@ #include "evmu_rom_.h" #include "evmu_memory_.h" #include "evmu_device_.h" - -EVMU_EXPORT GblBool EvmuRom_biosLoaded(const EvmuRom* pSelf) { - EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); - // VMU Reset Vector is at 0x0 so must be non-zero if loaded - return pSelf_->pMemory->rom[0]? GBL_TRUE : GBL_FALSE; -} +#include EVMU_EXPORT GblBool EvmuRom_biosActive(const EvmuRom* pSelf) { EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); return pSelf_->pMemory->pExt == pSelf_->pMemory->rom; } -static inline int monthDays_(const EvmuRom_* pSelf_) { - int m = pSelf_->pMemory->ram[0][0x19]; - if(m==2) { - int y = pSelf_->pMemory->ram[0][0x18] | (pSelf_->pMemory->ram[0][0x17] << 8); - if(y&3) - return 28; - if(!(y%4000)) - return 29; - if(!(y%1000)) - return 28; - if(!(y%400)) - return 29; - if(!(y%100)) - return 28; - return 29; - } else return (m>7? ((m&1)? 30:31) : ((m&1)? 31:30)); +EVMU_EXPORT EVMU_BIOS_TYPE EvmuRom_biosType(const EvmuRom* pSelf) { + EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); + return pSelf_->eBiosType; } -EVMU_EXPORT EVMU_RESULT EvmuRom_loadBios(EvmuRom* pSelf, const char* path) { +EVMU_EXPORT EVMU_BIOS_MODE EvmuRom_biosMode(const EvmuRom* pSelf) { + if(EvmuRom_biosType(pSelf) == EVMU_BIOS_TYPE_EMULATED) + return EVMU_BIOS_MODE_UNKNOWN; + EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); + return (EVMU_BIOS_MODE)pSelf_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MODE]; - FILE* file = NULL; +} - EVMU_LOG_VERBOSE("Loading BIOS image from file [%s].", path); - EVMU_LOG_PUSH(); +EVMU_EXPORT EVMU_RESULT EvmuRom_setDateTime(EvmuRom* pSelf, const GblDateTime* pDateTime) { + GBL_CTX_BEGIN(NULL); - if (!(file = fopen(path, "rb"))) { - EVMU_LOG_ERROR("Could not open file!"); - EVMU_LOG_POP(0); - return 0; - } + EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); + EvmuMemory_* pMemory = pSelf_->pMemory; + + GBL_CTX_VERIFY_ARG(pDateTime); + GBL_CTX_VERIFY(GblDateTime_isValid(pDateTime), + GBL_RESULT_ERROR_INVALID_DATE_TIME); + + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_MSB_BCD] = GBL_BCD_BYTE_PACK(pDateTime->date.year / 100); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_LSB_BCD] = GBL_BCD_BYTE_PACK(pDateTime->date.year % 100); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MONTH_BCD] = GBL_BCD_BYTE_PACK(pDateTime->date.month + 1); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DAY_BCD] = GBL_BCD_BYTE_PACK(pDateTime->date.day); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HOUR_BCD] = GBL_BCD_BYTE_PACK(pDateTime->time.hours); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MINUTE_BCD] = GBL_BCD_BYTE_PACK(pDateTime->time.minutes); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_SEC_BCD] = GBL_BCD_BYTE_PACK(pDateTime->time.seconds); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_MSB] = pDateTime->date.year >> 8; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_LSB] = pDateTime->date.year & 0xff; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MONTH] = pDateTime->date.month; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DAY] = pDateTime->date.day; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HOUR] = pDateTime->time.hours; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MINUTE] = pDateTime->time.minutes; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_SEC] = pDateTime->time.seconds; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HALF_SEC] = 0; + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_LEAP_YEAR] = GblDate_isLeapYear(pDateTime->date.year); + pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DATE_SET] = 0xff; - //Clear ROM - memset(pSelf_->pMemory->rom, 0, sizeof(pSelf_->pMemory->rom)); + GBL_CTX_END(); +} - size_t bytesRead = 0; - size_t bytesTotal = 0; +EVMU_EXPORT GblDateTime* EvmuRom_dateTime(const EvmuRom* pSelf, GblDateTime* pDateTime) { + GBL_CTX_BEGIN(NULL); - while(bytesTotal < sizeof(pSelf_->pMemory->rom)) { - if(bytesRead = fread(pSelf_->pMemory->rom+bytesTotal, 1, sizeof(pSelf_->pMemory->rom)-bytesTotal, file)) { - bytesTotal += bytesRead; - } else break; - } + EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); + EvmuMemory_* pMemory = pSelf_->pMemory; - fclose(file); + GBL_CTX_VERIFY_ARG(pDateTime); - EVMU_LOG_VERBOSE("Read %d bytes.", bytesTotal); + pDateTime->date.year = (pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_MSB] << 8) + | (pMemory->ram[0][EVMU_ADDRESS_SYSTEM_YEAR_LSB] & 0xff); + pDateTime->date.month = pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MONTH] + 1; + pDateTime->date.day = pMemory->ram[0][EVMU_ADDRESS_SYSTEM_DAY]; + pDateTime->time.hours = pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HOUR]; + pDateTime->time.minutes = pMemory->ram[0][EVMU_ADDRESS_SYSTEM_MINUTE]; + pDateTime->time.seconds = pMemory->ram[0][EVMU_ADDRESS_SYSTEM_SEC]; - //assert(bytesRead <= 0); //Didn't read shit - assert(bytesTotal >= 0); + GBL_CTX_VERIFY(GblDateTime_normalize(pDateTime) != NULL, + GBL_RESULT_ERROR_INVALID_DATE_TIME); - GblHash biosHash = gblHashCrc(pSelf_->pMemory->rom, EVMU_ROM_SIZE); - switch (biosHash) { - case EVMU_BIOS_TYPE_AMERICAN_IMAGE_V1_05: - EVMU_LOG_VERBOSE("Detected American V1.05 BIOS"); - pSelf_->eBiosType = EVMU_BIOS_TYPE_AMERICAN_IMAGE_V1_05; - break; - case EVMU_BIOS_TYPE_JAPANESE_IMAGE_V1_04: - EVMU_LOG_VERBOSE("Detected Japanese V1.04 BIOS"); - pSelf_->eBiosType = EVMU_BIOS_TYPE_JAPANESE_IMAGE_V1_04; - break; - default: - EVMU_LOG_WARNING("Unknown BIOS CRC: 0x%X", biosHash); - pSelf_->eBiosType = EVMU_BIOS_TYPE_UNKNOWN_IMAGE; - break; - } - - EVMU_LOG_POP(0); - return 1; + GBL_CTX_END_BLOCK(); + return GBL_RESULT_SUCCESS(GBL_CTX_RESULT())? + pDateTime : NULL; } + EVMU_EXPORT EVMU_RESULT EvmuRom_skipBiosSetup(EvmuRom* pSelf, GblBool enabled) { - EVMU_LOG_PUSH(); EVMU_LOG_VERBOSE("%s BIOS Setup Skip", enabled ? "Enabling" : "Disabling"); + EVMU_LOG_PUSH(); EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); @@ -102,11 +96,27 @@ EVMU_EXPORT EVMU_RESULT EvmuRom_skipBiosSetup(EvmuRom* pSelf, GblBool enabled) { break; } - EVMU_LOG_POP(0); - return 1; + EVMU_LOG_POP(1); + return GBL_RESULT_SUCCESS; +} + +EVMU_EXPORT EVMU_RESULT EvmuRom_loadBios(EvmuRom* pSelf, const char* pPath) { + GBL_CTX_BEGIN(NULL); + GBL_INSTANCE_VCALL(EvmuRom, pFnLoadBios, pSelf, pPath); + GBL_CTX_END(); } +EVMU_EXPORT EvmuAddress EvmuRom_callBios(EvmuRom* pSelf, EvmuAddress entry) { + EvmuAddress returnPc = 0; + GBL_CTX_BEGIN(NULL); + GBL_INSTANCE_VCALL(EvmuRom, pFnCallBios, pSelf, entry, &returnPc); + GBL_CTX_END_BLOCK(); + + return returnPc; +} + +///\todo DEREEST ME!!!! static void biosWriteFlashRom_(EvmuRom_* pSelf_) { EvmuDevice* pDevice = EvmuPeripheral_device(EVMU_PERIPHERAL(EVMU_ROM_PUBLIC_(pSelf_))); EvmuDevice_* pDevice_ = EVMU_DEVICE_(pDevice); @@ -127,102 +137,170 @@ static void biosWriteFlashRom_(EvmuRom_* pSelf_) { } } -/* - * TimeShooter.VMS is entering FM at unknown address!!!!! Marcus's emulator can't handle it either. - */ -EVMU_EXPORT EvmuAddress EvmuRom_callBios(EvmuRom* pSelf) { +EVMU_EXPORT EVMU_RESULT EvmuRom_loadBios_(EvmuRom* pSelf, const char* path) { + EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); + + FILE* file = NULL; + + EVMU_LOG_VERBOSE("Loading BIOS image from file [%s].", path); + EVMU_LOG_PUSH(); + + if (!(file = fopen(path, "rb"))) { + EVMU_LOG_ERROR("Could not open file!"); + EVMU_LOG_POP(1); + return 0; + } + + //Clear ROM + memset(pSelf_->pMemory->rom, 0, sizeof(pSelf_->pMemory->rom)); + + size_t bytesRead = 0; + size_t bytesTotal = 0; + + while(bytesTotal < sizeof(pSelf_->pMemory->rom)) { + if((bytesRead = fread(pSelf_->pMemory->rom+bytesTotal, 1, sizeof(pSelf_->pMemory->rom)-bytesTotal, file))) { + bytesTotal += bytesRead; + } else break; + } + + fclose(file); + + EVMU_LOG_VERBOSE("Read %d bytes.", bytesTotal); + + GBL_ASSERT(bytesTotal >= 0); + + const GblHash biosHash = gblHashCrc(pSelf_->pMemory->rom, EVMU_ROM_SIZE); + switch (biosHash) { + case EVMU_BIOS_TYPE_AMERICAN_IMAGE_V1_05: + EVMU_LOG_VERBOSE("Detected American V1.05 BIOS"); + pSelf_->eBiosType = EVMU_BIOS_TYPE_AMERICAN_IMAGE_V1_05; + break; + case EVMU_BIOS_TYPE_JAPANESE_IMAGE_V1_04: + EVMU_LOG_VERBOSE("Detected Japanese V1.04 BIOS"); + pSelf_->eBiosType = EVMU_BIOS_TYPE_JAPANESE_IMAGE_V1_04; + break; + default: + EVMU_LOG_WARNING("Unknown BIOS CRC: 0x%X", biosHash); + pSelf_->eBiosType = EVMU_BIOS_TYPE_UNKNOWN_IMAGE; + break; + } + + EVMU_LOG_POP(1); + return GBL_RESULT_SUCCESS; +} + +static EVMU_RESULT EvmuRom_callBios_(EvmuRom* pSelf, EvmuAddress pc, EvmuAddress* pRetPc) { + GBL_CTX_BEGIN(NULL); + EvmuRom_* pSelf_ = EVMU_ROM_(pSelf); EvmuDevice* pDevice = EvmuPeripheral_device(EVMU_PERIPHERAL(pSelf)); EvmuDevice_* pDevice_ = EVMU_DEVICE_(pDevice); - VMUDevice* dev = EVMU_DEVICE_REEST(pDevice); - switch(EvmuCpu_pc(pDevice->pCpu)) { - case EVMU_BIOS_ADDRESS_FM_WRT_EX: //fm_wrt_ex(ORG 0100H) + switch(pc) { + case EVMU_BIOS_SUBROUTINE_RESET: + *pRetPc = 0x0; + break; + case EVMU_BIOS_SUBROUTINE_FM_WRT_EX: //fm_wrt_ex(ORG 0100H) biosWriteFlashRom_(pSelf_); - return 0x105; - case EVMU_BIOS_ADDRESS_FM_WRTA_EX: //fm_vrf_ex(ORG 0108H) + *pRetPc = 0x105; + break; + case EVMU_BIOS_SUBROUTINE_FM_WRTA_EX: //fm_vrf_ex(ORG 0108H) biosWriteFlashRom_(pSelf_); - return 0x10b; - case EVMU_BIOS_ADDRESS_FM_VRF_EX: { //fm_vrf_ex(ORG 0110H) + *pRetPc = 0x10b; + break; + case EVMU_BIOS_SUBROUTINE_FM_VRF_EX: { //fm_vrf_ex(ORG 0110H) int i, a = ((pDevice_->pMemory->ram[1][0x7d]<<16)|(pDevice_->pMemory->ram[1][0x7e]<<8)|pDevice_->pMemory->ram[1][0x7f])&0x1ffff; int r = 0; for(i=0; i<0x80; i++) - if((r = (pDevice_->pMemory->flash[(a&~0xff)|((a+i)&0xff)] ^ pDevice_->pMemory->ram[1][i+0x80])) != 0) + if((r = (pDevice_->pMemory->flash[(a&~0xff)|((a+i)&0xff)] ^ pDevice_->pMemory->ram[1][i+0x80])) != 0) + break; + EvmuMemory_writeInt(pDevice->pMemory, 0x100, r); + *pRetPc = 0x115;\ break; - //writemem(0x100, r); - //printf("READ FLASH[%x] = %d\n", 0, r); - EvmuMemory_writeInt(EVMU_DEVICE_PRISTINE_PUBLIC(dev)->pMemory, 0x100, r); - return 0x115; } - case EVMU_BIOS_ADDRESS_FM_PRD_EX: { //fm_prd_ex(ORG 0120H) + case EVMU_BIOS_SUBROUTINE_FM_PRD_EX: { //fm_prd_ex(ORG 0120H) int i, a = ((pDevice_->pMemory->ram[1][0x7d]<<16)|(pDevice_->pMemory->ram[1][0x7e]<<8)|pDevice_->pMemory->ram[1][0x7f])&0x1ffff; for(i=0; i<0x80; i++) { - pDevice_->pMemory->ram[1][i+0x80] = pDevice_->pMemory->flash[(a&~0xff)|((a+i)&0xff)]; - //printf("READ FLASH[%x] = %d\n", (a&~0xff)|((a+i)&0xff), pDevice_->pMemory->ram[1][i+0x80]); + pDevice_->pMemory->ram[1][i+0x80] = pDevice_->pMemory->flash[(a&~0xff)|((a+i)&0xff)]; + } + *pRetPc = 0x125; + break; + } + case EVMU_BIOS_SUBROUTINE_TIMER_EX: //timer_ex fm_prd_ex(ORG 0130H) + if(!((pDevice_->pMemory->ram[0][EVMU_ADDRESS_SYSTEM_HALF_SEC]^=1)&1)) { + GblDateTime curTime; + EvmuRom_setDateTime(pSelf, GblDateTime_addSeconds(EvmuRom_dateTime(pSelf, &curTime), 1)); } + *pRetPc = 0x139; + break; + case EVMU_BIOS_SUBROUTINE_SLEEP_EX: + EVMU_LOG_WARNING("Entered firmware at SLEEP mode address! Unimplemented!"); + *pRetPc = 0; + break; + default: + EVMU_LOG_ERROR("Entering firmware at unknown address! [%x]", pc); + *pRetPc = 0; + } + GBL_CTX_END(); +} - /* - fprintf(stderr, "ROM read @ %05x\n", a); - */ - return 0x125; - } - case EVMU_BIOS_ADDRESS_TIMER_EX: //timer_ex fm_prd_ex(ORG 0130H) - if(!((pDevice_->pMemory->ram[0][0x1e]^=1)&1)) - if(++pDevice_->pMemory->ram[0][0x1d]>=60) { - pDevice_->pMemory->ram[0][0x1d] = 0; - if(++pDevice_->pMemory->ram[0][0x1c]>=60) { - pDevice_->pMemory->ram[0][0x1c] = 0; - if(++pDevice_->pMemory->ram[0][0x1b]>=24) { - pDevice_->pMemory->ram[0][0x1b] = 0; - if(++pDevice_->pMemory->ram[0][0x1a] > monthDays_(pSelf_)) { - pDevice_->pMemory->ram[0][0x1a] = 1; - if(++pDevice_->pMemory->ram[0][0x19]>=13) { - pDevice_->pMemory->ram[0][0x19] = 1; - if(pDevice_->pMemory->ram[0][0x18]==0xff) { - pDevice_->pMemory->ram[0][0x18]=0; - pDevice_->pMemory->ram[0][0x17]++; - } else - pDevice_->pMemory->ram[0][0x18]++; - } - } - } - } - } - return 0x139; - case EVMU_BIOS_ADDRESS_SLEEP_EX: //fm_prd_ex(ORG 0140H) - EVMU_LOG_WARNING("Entered firmare at SLEEP mode address! Unimplemented!"); - return 0; +static GBL_RESULT EvmuRom_GblObject_setProperty_(GblObject* pObject, const GblProperty* pProp, GblVariant* pValue) { + GBL_UNUSED(pObject, pProp, pValue); + GBL_CTX_BEGIN(NULL); + + switch(pProp->id) { default: - //assert(0); - EVMU_LOG_ERROR("Entering firmware at unknown address! [%x]", - EvmuCpu_pc(pDevice->pCpu)); - return 0; + GBL_CTX_RECORD_SET(GBL_RESULT_ERROR_INVALID_PROPERTY, + "Attempt to read unknown EvmuRom property: [%s]", + GblProperty_nameString(pProp)); + break; } + GBL_CTX_END(); } -static GBL_RESULT EvmuRom_GblObject_constructed_(GblObject* pSelf) { + +static GBL_RESULT EvmuRom_GblObject_property_(const GblObject* pObject, const GblProperty* pProp, GblVariant* pValue) { GBL_CTX_BEGIN(NULL); - GBL_INSTANCE_VCALL_DEFAULT(EvmuPeripheral, base.pFnConstructed, pSelf); - GblObject_setName(pSelf, EVMU_ROM_NAME); + EvmuRom* pSelf = EVMU_ROM(pObject); - EvmuRom* pRom = EVMU_ROM(pSelf); - EvmuRom_* pRom_ = EVMU_ROM_(pRom); - pRom_->eBiosType = EVMU_BIOS_TYPE_EMULATED; - pRom_->bSetupSkipEnabled = GBL_FALSE; + switch(pProp->id) { + case EvmuRom_Property_Id_biosActive: + GblVariant_setBool(pValue, EvmuRom_biosActive(pSelf)); + break; + case EvmuRom_Property_Id_biosType: + GblVariant_setBool(pValue, EvmuRom_biosType(pSelf)); + break; + case EvmuRom_Property_Id_biosMode: + GblVariant_setBool(pValue, EvmuRom_biosMode(pSelf)); + break; + case EvmuRom_Property_Id_dateTime: { + GblDateTime dt; + GblStringBuffer* pBuffer = GBL_STRING_BUFFER_ALLOCA(GBL_DATE_TIME_ISO8601_STRING_SIZE); + GblVariant_setString(pValue, GblDateTime_toIso8601(EvmuRom_dateTime(pSelf, &dt), pBuffer)); + break; + } + default: + GBL_CTX_RECORD_SET(GBL_RESULT_ERROR_INVALID_PROPERTY, + "Attempt to read unknown EvmuRom property: [%s]", + GblProperty_nameString(pProp)); + break; + } GBL_CTX_END(); } -static GBL_RESULT EvmuRom_IBehavior_reset_(EvmuIBehavior* pSelf) { +static GBL_RESULT EvmuRom_GblObject_constructed_(GblObject* pSelf) { GBL_CTX_BEGIN(NULL); - GBL_INSTANCE_VCALL_DEFAULT(EvmuIBehavior, pFnReset, pSelf); + GBL_INSTANCE_VCALL_DEFAULT(EvmuPeripheral, base.pFnConstructed, pSelf); + GblObject_setName(pSelf, EVMU_ROM_NAME); EvmuRom* pRom = EVMU_ROM(pSelf); EvmuRom_* pRom_ = EVMU_ROM_(pRom); - GBL_UNUSED(pRom_); + pRom_->eBiosType = EVMU_BIOS_TYPE_EMULATED; + pRom_->bSetupSkipEnabled = GBL_FALSE; GBL_CTX_END(); } @@ -231,8 +309,11 @@ static GBL_RESULT EvmuRomClass_init_(GblClass* pClass, const void* pUd, GblConte GBL_UNUSED(pUd); GBL_CTX_BEGIN(pCtx); - GBL_OBJECT_CLASS(pClass) ->pFnConstructed = EvmuRom_GblObject_constructed_; - EVMU_IBEHAVIOR_CLASS(pClass)->pFnReset = EvmuRom_IBehavior_reset_; + GBL_OBJECT_CLASS(pClass)->pFnConstructed = EvmuRom_GblObject_constructed_; + GBL_OBJECT_CLASS(pClass)->pFnProperty = EvmuRom_GblObject_property_; + GBL_OBJECT_CLASS(pClass)->pFnSetProperty = EvmuRom_GblObject_setProperty_; + EVMU_ROM_CLASS(pClass) ->pFnCallBios = EvmuRom_callBios_; + EVMU_ROM_CLASS(pClass) ->pFnLoadBios = EvmuRom_loadBios_; GBL_CTX_END(); } @@ -262,4 +343,49 @@ EVMU_EXPORT GblType EvmuRom_type(void) { +/*// Call this whole fucker "Bios" +// Call the thing that MUXes Flash + Bios "Rom" + + +// use system clock? + * + * + * TimeShooter.VMS is entering FM at unknown address!!!!! Marcus's emulator can't handle it either. + * + * WHOLE ADDRESS SPACE: BIOS + * Standalone Utility Functions: Firmware/OS routines + * Random routines mid-BIOS: system routines + * All of this shit: subroutines + * + */ + +/* FLASH MEMORY VARIABLES USED WITH BIOS FW CALL + * THIS IS IN RAM BANK 1, IN APP-SPACE!!! + * 0x7d Fmbank - Specify flash bank to use (guess bit 0 or 1) + * 0x7e Fmadd_h - Flash memory address (upper 8 bits) + * 0x7f Fmadd_l - Flash memory address (lower 8 bits) + */ + +/* +Document all known static metadata regions in the BIOS +1) BIOS version +2) Maple information +3) Font characters + +4) Known harness-able utility functions that can be used via stack return attacks + +add a public API that allows you to query and extract this info. + +Present at 0x14BE in the BIOS, alongside some build info. +0x14BE JAP BIOS version info +0xAA7 US BIOS version info + +Visual Memory Produced By or Under License From SEGA ENTERPRISES,LTD. +Version 1.004,1998/09/30,315-6208-01,SEGA Visual Memory System BIOS Produced by Sue +*/ + +/* Need a list of BIOS initialization registers with default values! + * + */ +