mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-12 11:31:16 +00:00
viacuda: Add 1 Sec Timer, fix Get/Set Real Time.
GET_REAL_TIME was using the wrong offset and wasn't setting out_count. May need to add time zone offset which could be different between host and guest. get-time and set-time can be tested in Open Firmware. SET_REAL_TIME is used by the Date/Time Control Panel when you change the date. It is unknown what method Mac OS uses to get the time at boot. Mac OS 8.6 does not use GET_REAL_TIME during boot, so the time is left as 12:00 AM Jan 1, 1904.
This commit is contained in:
parent
9a70c3bdb0
commit
d06d80619e
@ -87,6 +87,17 @@ ViaCuda::ViaCuda() {
|
||||
this->cuda_init();
|
||||
|
||||
this->int_ctrl = nullptr;
|
||||
|
||||
std::tm tm = {
|
||||
.tm_sec = 0,
|
||||
.tm_min = 0,
|
||||
.tm_hour = 0,
|
||||
.tm_mday = 1,
|
||||
.tm_mon = 1 - 1,
|
||||
.tm_year = 1904 - 1900,
|
||||
.tm_isdst = -1 // Use DST value from local time zone
|
||||
};
|
||||
mac_epoch = std::chrono::system_clock::from_time_t(std::mktime(&tm));
|
||||
}
|
||||
|
||||
ViaCuda::~ViaCuda()
|
||||
@ -495,10 +506,7 @@ void ViaCuda::process_adb_command() {
|
||||
}
|
||||
|
||||
void ViaCuda::autopoll_handler() {
|
||||
if (!this->autopoll_enabled)
|
||||
return;
|
||||
|
||||
uint8_t poll_command = this->adb_bus_obj->poll();
|
||||
uint8_t poll_command = this->autopoll_enabled ? this->adb_bus_obj->poll() : 0;
|
||||
|
||||
if (poll_command) {
|
||||
if (!this->old_tip || !this->treq) {
|
||||
@ -520,6 +528,36 @@ void ViaCuda::autopoll_handler() {
|
||||
|
||||
// draw guest system's attention
|
||||
schedule_sr_int(USECS_TO_NSECS(30));
|
||||
} else if (this->one_sec_mode == 3) {
|
||||
uint32_t this_time = calc_real_time();
|
||||
if (this_time != this->last_time) {
|
||||
|
||||
if ((this->last_time & 15) == 0) {
|
||||
/*
|
||||
FIXME: This doesn't do anything in Mac OS 8.6.
|
||||
A real Mac probably doesn't do this. So why do I?
|
||||
supermario checks for packets that are not PKT_TICK
|
||||
to set the time but I don't know which Mac OS versions
|
||||
have that code and if that code is triggered by this.
|
||||
*/
|
||||
response_header(9, 0);
|
||||
this->out_buf[3] = CUDA_GET_REAL_TIME;
|
||||
uint32_t real_time = this_time + time_offset;
|
||||
WRITE_DWORD_BE_U(&this->out_buf[3], real_time);
|
||||
this->out_count = 7;
|
||||
} else {
|
||||
response_header(CUDA_PKT_TICK, 0);
|
||||
this->out_count = 1;
|
||||
}
|
||||
this->last_time = this_time;
|
||||
|
||||
// assert TREQ
|
||||
this->via_regs[VIA_B] &= ~CUDA_TREQ;
|
||||
this->treq = 0;
|
||||
|
||||
// draw guest system's attention
|
||||
schedule_sr_int(USECS_TO_NSECS(30));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,13 +594,14 @@ void ViaCuda::pseudo_command(int cmd, int data_count) {
|
||||
}
|
||||
this->is_open_ended = true;
|
||||
break;
|
||||
case CUDA_GET_REAL_TIME:
|
||||
case CUDA_GET_REAL_TIME: {
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
this->out_buf[2] = (uint8_t)((this->real_time >> 24) & 0xFF);
|
||||
this->out_buf[3] = (uint8_t)((this->real_time >> 16) & 0xFF);
|
||||
this->out_buf[4] = (uint8_t)((this->real_time >> 8) & 0xFF);
|
||||
this->out_buf[5] = (uint8_t)((this->real_time) & 0xFF);
|
||||
uint32_t this_time = this->calc_real_time();
|
||||
uint32_t real_time = this_time + time_offset;
|
||||
WRITE_DWORD_BE_U(&this->out_buf[3], real_time);
|
||||
this->out_count = 7;
|
||||
break;
|
||||
}
|
||||
case CUDA_WRITE_MCU_MEM:
|
||||
addr = READ_WORD_BE_A(&this->in_buf[2]);
|
||||
// if addr is inside PRAM, update PRAM with data from in_buf
|
||||
@ -587,13 +626,13 @@ void ViaCuda::pseudo_command(int cmd, int data_count) {
|
||||
error_response(CUDA_ERR_BAD_PAR);
|
||||
}
|
||||
break;
|
||||
case CUDA_SET_REAL_TIME:
|
||||
case CUDA_SET_REAL_TIME: {
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
this->real_time = ((uint32_t)in_buf[2]) >> 24;
|
||||
this->real_time += ((uint32_t)in_buf[3]) >> 16;
|
||||
this->real_time += ((uint32_t)in_buf[4]) >> 8;
|
||||
this->real_time += ((uint32_t)in_buf[5]);
|
||||
uint32_t real_time = this->calc_real_time();
|
||||
uint32_t new_time = READ_DWORD_BE_U(&in_buf[2]);
|
||||
this->time_offset = new_time - real_time;
|
||||
break;
|
||||
}
|
||||
case CUDA_WRITE_PRAM:
|
||||
addr = READ_WORD_BE_A(&this->in_buf[2]);
|
||||
if (addr <= 0xFF) {
|
||||
@ -637,7 +676,8 @@ void ViaCuda::pseudo_command(int cmd, int data_count) {
|
||||
this->out_buf[3] = (uint8_t)((this->device_mask) & 0xFF);
|
||||
break;
|
||||
case CUDA_ONE_SECOND_MODE:
|
||||
LOG_F(INFO, "Cuda: One Second Interrupt - Byte Sent: %d", this->in_buf[2]);
|
||||
LOG_F(INFO, "Cuda: One Second Interrupt Mode: %d", this->in_buf[2]);
|
||||
this->one_sec_mode = this->in_buf[2];
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
case CUDA_READ_WRITE_I2C:
|
||||
@ -673,6 +713,13 @@ void ViaCuda::pseudo_command(int cmd, int data_count) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ViaCuda::calc_real_time() {
|
||||
auto end = std::chrono::system_clock::now();
|
||||
auto elapsed_systemclock = end - this->mac_epoch;
|
||||
auto elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>(elapsed_systemclock);
|
||||
return uint32_t(elapsed_seconds.count());
|
||||
}
|
||||
|
||||
/* sends data from the current I2C to host ad infinitum */
|
||||
void ViaCuda::i2c_handler() {
|
||||
this->receive_byte(this->curr_i2c_addr, &this->via_regs[VIA_SR]);
|
||||
|
@ -48,6 +48,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <devices/common/nvram.h>
|
||||
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
||||
class AdbBus;
|
||||
class InterruptCtrl;
|
||||
@ -213,7 +214,10 @@ private:
|
||||
int32_t out_count;
|
||||
int32_t out_pos;
|
||||
uint8_t poll_rate;
|
||||
int32_t real_time = 0;
|
||||
uint32_t last_time = 0;
|
||||
uint32_t time_offset = 0;
|
||||
std::chrono::time_point<std::chrono::system_clock> mac_epoch;
|
||||
uint8_t one_sec_mode = 0;
|
||||
bool file_server;
|
||||
uint16_t device_mask = 0;
|
||||
|
||||
@ -247,6 +251,7 @@ private:
|
||||
void process_packet();
|
||||
void process_adb_command();
|
||||
void pseudo_command(int cmd, int data_count);
|
||||
uint32_t calc_real_time();
|
||||
|
||||
void null_out_handler(void);
|
||||
void pram_out_handler(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user