Skip to content

Commit 9a791c5

Browse files
committed
Add compat with 82 Advanced Edition Python roms.
The device_type enum doesn't directly map to a cert field anymore and since it is stored in the asic state, we increment IMAGE_VERSION. Note that 82AEP pre-A ≈ CE M+, but with working SPI reads. Also display more info parsed from the cert.
1 parent 283611e commit 9a791c5

File tree

21 files changed

+150
-101
lines changed

21 files changed

+150
-101
lines changed

core/asic.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static void plug_devices(void) {
8888
gui_console_printf("[CEmu] Initialized Advanced Peripheral Bus...\n");
8989
}
9090

91-
static asic_rev_t report_reset(asic_rev_t loaded_rev, bool* python) {
91+
static asic_rev_t report_reset(asic_rev_t loaded_rev, emu_device_t device, bool* python) {
9292
/* Parse boot code routines to determine version. */
9393
asic_rev_t default_rev = ASIC_REV_A;
9494
boot_ver_t boot_ver;
@@ -99,7 +99,7 @@ static asic_rev_t report_reset(asic_rev_t loaded_rev, bool* python) {
9999

100100
/* Determine the newest ASIC revision that is compatible */
101101
for (int rev = ASIC_REV_A; rev <= ASIC_REV_M; rev++) {
102-
if (bootver_check_rev(&boot_ver, (asic_rev_t)rev)) {
102+
if (bootver_check_rev(&boot_ver, (asic_rev_t)rev, device)) {
103103
default_rev = rev;
104104
}
105105
}
@@ -114,13 +114,14 @@ static asic_rev_t report_reset(asic_rev_t loaded_rev, bool* python) {
114114
}
115115
gui_console_printf("[CEmu] Default ASIC revision is Rev %c.\n", "AIM"[(int)default_rev - 1]);
116116

117-
loaded_rev = gui_handle_reset((gotVer ? &boot_ver : NULL), loaded_rev, default_rev, python);
117+
loaded_rev = gui_handle_reset((gotVer ? &boot_ver : NULL), loaded_rev, default_rev, device, python);
118118
return (loaded_rev != ASIC_REV_AUTO) ? loaded_rev : default_rev;
119119
}
120120

121121
static void set_features() {
122122
asic.im2 = (asic.revision < ASIC_REV_I);
123123
asic.serFlash = (asic.revision >= ASIC_REV_M);
124+
asic.hasWorkingSPIReads = (asic.device == TI82AEP);
124125
}
125126

126127
void asic_init(void) {
@@ -148,19 +149,19 @@ void asic_reset(void) {
148149
/* Update the Python state first, so it can be read by the reset handler if needed */
149150
static const uint16_t path[] = { 0x0330, 0x0430 };
150151
asic.python = !cert_field_find_path(mem.flash.block + 0x3B0001, SIZE_FLASH_SECTOR_64K, path, 2, NULL, NULL);
151-
asic.revision = report_reset(ASIC_REV_AUTO, &asic.python);
152+
asic.revision = report_reset(ASIC_REV_AUTO, asic.device, &asic.python);
152153
set_features();
153154

154155
for (unsigned int i = 0; i < reset_proc_count; i++) {
155156
reset_procs[i]();
156157
}
157158
}
158159

159-
void set_device_type(ti_device_t device) {
160+
void set_device_type(emu_device_t device) {
160161
asic.device = device;
161162
}
162163

163-
ti_device_t EMSCRIPTEN_KEEPALIVE get_device_type(void) {
164+
emu_device_t EMSCRIPTEN_KEEPALIVE get_device_type(void) {
164165
return asic.device;
165166
}
166167

@@ -203,7 +204,7 @@ bool asic_restore(FILE *image) {
203204
&& fgetc(image) == EOF)
204205
{
205206
bool python = asic.python;
206-
(void)report_reset(asic.revision, &python);
207+
(void)report_reset(asic.revision, asic.device, &python);
207208
return true;
208209
}
209210
return false;

core/asic.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ extern "C" {
99
#include <stdint.h>
1010
#include <stdio.h>
1111

12+
/* Note that this does not map a cert field */
1213
typedef enum {
1314
TI84PCE = 0,
14-
TI83PCE = 1
15-
} ti_device_t;
15+
TI83PCE = 1,
16+
TI82AEP = 2
17+
} emu_device_t;
1618

1719
typedef enum {
1820
ASIC_REV_AUTO = 0, /* Used only with set_asic_revision() */
@@ -22,13 +24,14 @@ typedef enum {
2224
} asic_rev_t;
2325

2426
typedef struct asic_state {
25-
ti_device_t device;
27+
emu_device_t device;
2628
/* Only updated on reset */
2729
asic_rev_t revision;
2830
bool python;
2931
/* Populated based on revision */
3032
bool im2;
3133
bool serFlash;
34+
bool hasWorkingSPIReads;
3235
} asic_state_t;
3336

3437
extern asic_state_t asic;
@@ -39,8 +42,8 @@ void asic_reset(void);
3942
bool asic_restore(FILE *image);
4043
bool asic_save(FILE *image);
4144
void set_cpu_clock(uint32_t new_rate);
42-
void set_device_type(ti_device_t device);
43-
ti_device_t get_device_type(void);
45+
void set_device_type(emu_device_t device);
46+
emu_device_t get_device_type(void);
4447
asic_rev_t get_asic_revision(void);
4548
bool get_asic_python(void);
4649

core/bootver.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
#include "bootver.h"
22

3-
static const boot_ver_t asic_min_ver[] = {
4-
{ 5, 0, 0, 0 }, /* Rev A */
5-
{ 5, 0, 0, 0 }, /* Rev I */
6-
{ 5, 3, 6, 0 }, /* Rev M */
7-
};
8-
9-
static const boot_ver_t asic_max_ver[] = {
10-
{ 5, 3, 5, 65535 }, /* Rev A */
11-
{ 5, 3, 5, 65535 }, /* Rev I */
12-
{ 255, 255, 255, 65535 }, /* Rev M */
13-
};
3+
static const boot_ver_t minRevA_CE = { 5, 0, 0, 0 }; /* Rev A */
4+
static const boot_ver_t minRevI_CE = { 5, 0, 0, 0 }; /* Rev I */
5+
static const boot_ver_t minRevM_CE = { 5, 3, 6, 0 }; /* Rev M */
6+
static const boot_ver_t minRevM_82 = { 5, 6, 3, 0 }; /* Rev pre-A of 82AEP, but otherwise the same JB-007 ASIC as M on CE */
7+
static const boot_ver_t maxRevA_CE = { 5, 3, 5, 65535 }; /* Rev A */
8+
static const boot_ver_t maxRevI_CE = { 5, 3, 5, 65535 }; /* Rev I */
9+
static const boot_ver_t maxRev = { 255, 255, 255, 65535 }; /* Rev M */
10+
11+
/* NULL means unsupported */
12+
static const boot_ver_t* asic_min_ver_8384CE[] = { &minRevA_CE, &minRevI_CE, &minRevM_CE };
13+
static const boot_ver_t* asic_max_ver_8384CE[] = { &maxRevA_CE, &maxRevI_CE, &maxRev };
14+
static const boot_ver_t* asic_min_ver_82AEP[] = { NULL, NULL, &minRevM_82 };
15+
static const boot_ver_t* asic_max_ver_82AEP[] = { NULL, NULL, &maxRev };
1416

1517
static bool parse_entry(const uint8_t* data, uint32_t entry, uint32_t* addr) {
1618
if (entry + 4 >= SIZE_BOOTCODE) {
@@ -98,6 +100,9 @@ bool bootver_parse(const uint8_t* data, boot_ver_t* boot_ver) {
98100
}
99101

100102
bool bootver_check_ver(const boot_ver_t* ver, const boot_ver_t* check) {
103+
if (!ver || !check) {
104+
return false;
105+
}
101106
if (ver->major != check->major) {
102107
return ver->major > check->major;
103108
}
@@ -110,16 +115,19 @@ bool bootver_check_ver(const boot_ver_t* ver, const boot_ver_t* check) {
110115
return ver->build >= check->build;
111116
}
112117

113-
bool bootver_check_rev(const boot_ver_t* ver, asic_rev_t rev) {
118+
bool bootver_check_rev(const boot_ver_t* ver, asic_rev_t rev, emu_device_t device) {
114119
unsigned int index = (unsigned int)rev - 1;
115-
if (index >= sizeof(asic_min_ver) / sizeof(boot_ver_t)) {
120+
if (((device == TI83PCE || device == TI84PCE) && index >= sizeof(asic_min_ver_8384CE) / sizeof(boot_ver_t*)) ||
121+
((device == TI82AEP) && index >= sizeof(asic_min_ver_82AEP) / sizeof(boot_ver_t*))) {
116122
return false;
117123
}
118124

119125
if (!ver) {
120126
return true;
121127
}
122128

123-
return bootver_check_ver(ver, asic_min_ver + index)
124-
&& bootver_check_ver(asic_max_ver + index, ver);
129+
const boot_ver_t** asic_min_ver = (device == TI83PCE || device == TI84PCE) ? asic_min_ver_8384CE : asic_min_ver_82AEP;
130+
const boot_ver_t** asic_max_ver = (device == TI83PCE || device == TI84PCE) ? asic_max_ver_8384CE : asic_max_ver_82AEP;
131+
return bootver_check_ver(ver, asic_min_ver[index])
132+
&& bootver_check_ver(asic_max_ver[index], ver);
125133
}

core/bootver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extern "C" {
2424

2525
bool bootver_check_ver(const boot_ver_t* ver, const boot_ver_t* check);
2626

27-
bool bootver_check_rev(const boot_ver_t* ver, asic_rev_t rev);
27+
bool bootver_check_rev(const boot_ver_t* ver, asic_rev_t rev, emu_device_t device);
2828

2929
#ifdef __cplusplus
3030
}

core/control.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static uint8_t control_read(const uint16_t pio, bool peek) {
2929
value = control.readBatteryStatus;
3030
break;
3131
case 0x03:
32-
value = get_device_type() | asic.serFlash << 4;
32+
value = (get_device_type() == TI84PCE ? 0 : 1) | asic.serFlash << 4;
3333
break;
3434
case 0x06:
3535
value = control.protectedPortsUnlocked;

core/emu.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <emscripten.h>
1919
#endif
2020

21-
#define IMAGE_VERSION 0xCECE001A
21+
#define IMAGE_VERSION 0xCECE001B
2222

2323
void EMSCRIPTEN_KEEPALIVE emu_exit(void) {
2424
cpu_set_signal(CPU_SIGNAL_EXIT);
@@ -100,7 +100,7 @@ emu_state_t emu_load(emu_data_t type, const char *path) {
100100
const uint8_t *data;
101101
uint32_t outer_field_size;
102102
uint32_t data_field_size;
103-
ti_device_t device_type = TI84PCE;
103+
emu_device_t device_type = TI84PCE;
104104
uint32_t offset;
105105
size_t size;
106106

@@ -139,7 +139,8 @@ emu_state_t emu_load(emu_data_t type, const char *path) {
139139

140140
/* Inner 0x801(0) field: calculator model */
141141
if (cert_field_get(outer, outer_field_size, &field_type, &data, &data_field_size)) break;
142-
if (field_type != 0x8012 || data[0] != 0x13) break;
142+
if (field_type != 0x8012 || (data[0] != 0x13 && data[0] != 0x15)) break;
143+
const enum { MODEL_8384CE=0x13, MODEL_82AEP=0x15 } model_id = data[0];
143144

144145
/* Inner 0x802(0) field: skip. */
145146
data_field_size = outer_field_size - (data + data_field_size - outer);
@@ -174,10 +175,24 @@ emu_state_t emu_load(emu_data_t type, const char *path) {
174175
if (field_type != 0x80C2) break;
175176

176177
if (data[1] != 0 && data[1] != 1) break;
177-
device_type = (ti_device_t)(data[1]);
178-
179-
/* If we come here, we've found something. */
180-
gotType = true;
178+
const enum { DEVICE_84PCE=0, DEVICE_83PCE=1 } device_id = data[1];
179+
180+
gui_console_printf("[CEmu] Info from cert: Device type = 0x%02X (%s). Model = 0x%02X (%s).\n",
181+
device_id, (device_id == DEVICE_84PCE) ? "84+CE-like" : "83PCE-like",
182+
model_id, (model_id == MODEL_8384CE) ? "CE" : "82AEP");
183+
184+
if (model_id == MODEL_82AEP && device_id == DEVICE_83PCE) {
185+
device_type = TI82AEP;
186+
gotType = true;
187+
} else if (model_id == MODEL_8384CE && device_id == DEVICE_84PCE) {
188+
device_type = TI84PCE;
189+
gotType = true;
190+
} else if (model_id == MODEL_8384CE && device_id == DEVICE_83PCE) {
191+
device_type = TI83PCE;
192+
gotType = true;
193+
} else {
194+
gui_console_err_printf("[CEmu] Got model<->device discrepency!?\n");
195+
}
181196

182197
gui_console_printf("[CEmu] Loaded ROM Image.\n");
183198
break;

core/emu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ void gui_console_err_printf(const char *format, ...); /* printf from the cor
4545
* boot_ver: boot code version if found, else NULL
4646
* loaded_rev: ASIC_REV_AUTO on reset, or loaded revision on state load
4747
* default_rev: default revision to use when returning ASIC_REV_AUTO
48+
* device: which device we're actually emulating
4849
* python: determined edition based on certificate, can be overridden by updating its value
4950
* returns:
5051
* hardware revision to use; ignored when loading state */
51-
asic_rev_t gui_handle_reset(const boot_ver_t* boot_ver, asic_rev_t loaded_rev, asic_rev_t default_rev, bool* python);
52+
asic_rev_t gui_handle_reset(const boot_ver_t* boot_ver, asic_rev_t loaded_rev, asic_rev_t default_rev, emu_device_t device, bool* python);
5253

5354
#ifdef DEBUG_SUPPORT
5455
void gui_debug_open(int reason, uint32_t data); /* open the gui debugger */

core/spi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ static void spi_update(void) {
160160
}
161161

162162
/* Read from the SPI range of ports */
163+
/* TODO: something with asic.hasWorkingSPIReads probably */
163164
static uint8_t spi_read(uint16_t addr, bool peek) {
164165
static const uint16_t cr0_masks[16] = {
165166
0xF18C, 0xF8EF, 0xF0AC, 0xF3FC, 0xF18C, 0xF4C0, 0xF3AC, 0xF3AC,

gui/qt/emuthread.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ void gui_debug_close(void) {
4848
emu->debugDisable();
4949
}
5050

51-
asic_rev_t gui_handle_reset(const boot_ver_t* boot_ver, asic_rev_t loaded_rev, asic_rev_t default_rev, bool* python) {
52-
return emu->handleReset(boot_ver, loaded_rev, default_rev, python);
51+
asic_rev_t gui_handle_reset(const boot_ver_t* boot_ver, asic_rev_t loaded_rev, asic_rev_t default_rev, emu_device_t device, bool* python) {
52+
return emu->handleReset(boot_ver, loaded_rev, default_rev, device, python);
5353
}
5454

5555
namespace {
@@ -279,12 +279,12 @@ void EmuThread::unblock() {
279279
m_mutex.unlock();
280280
}
281281

282-
asic_rev_t EmuThread::handleReset(const boot_ver_t* bootVer, asic_rev_t loadedRev, asic_rev_t defaultRev, bool* python) {
282+
asic_rev_t EmuThread::handleReset(const boot_ver_t* bootVer, asic_rev_t loadedRev, asic_rev_t defaultRev, emu_device_t device, bool* python) {
283283
// Build a list of supported revisions
284284
QList<int> supportedRevs;
285285
supportedRevs.reserve(ASIC_REV_M - ASIC_REV_A + 1);
286286
for (int rev = ASIC_REV_A; rev <= ASIC_REV_M; rev++) {
287-
if (bootver_check_rev(bootVer, (asic_rev_t)rev)) {
287+
if (bootver_check_rev(bootVer, (asic_rev_t)rev, device)) {
288288
supportedRevs.push_back(rev);
289289
}
290290
}

gui/qt/emuthread.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class EmuThread : public QThread {
3838
void setAsicRev(int rev);
3939
void setAllowAnyRev(bool allow);
4040
void setForcePython(Qt::CheckState state);
41-
asic_rev_t handleReset(const boot_ver_t* bootVer, asic_rev_t loadedRev, asic_rev_t defaultRev, bool* python);
41+
asic_rev_t handleReset(const boot_ver_t* bootVer, asic_rev_t loadedRev, asic_rev_t defaultRev, emu_device_t device, bool* python);
4242
void writeConsole(int console, const char *format, va_list args);
4343
void debugOpen(int reason, uint32_t addr);
4444
void save(emu_data_t fileType, const QString &filePath);

0 commit comments

Comments
 (0)