Skip to content

Commit 040ce28

Browse files
committed
core: Add support for ROM files up to 32 MB
1 parent 516d420 commit 040ce28

8 files changed

Lines changed: 89 additions & 59 deletions

File tree

core/emu.c

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

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

2323
void EMSCRIPTEN_KEEPALIVE emu_exit(void) {
2424
cpu_set_signal(CPU_SIGNAL_EXIT);
@@ -43,7 +43,7 @@ bool emu_save(emu_data_t type, const char *path) {
4343
success = fwrite(&version, sizeof version, 1, file) == 1 && asic_save(file);
4444
break;
4545
case EMU_DATA_ROM:
46-
success = fwrite(mem.flash.block, 1, SIZE_FLASH, file) == SIZE_FLASH;
46+
success = fwrite(mem.flash.block, 1, mem.flash.size, file) == mem.flash.size;
4747
break;
4848
case EMU_DATA_RAM:
4949
success = fwrite(mem.ram.block, 1, SIZE_RAM, file) == SIZE_RAM;
@@ -115,15 +115,35 @@ emu_state_t emu_load(emu_data_t type, const char *path) {
115115

116116
if (fseek(file, 0L, SEEK_END) < 0) goto rerr;
117117
size = (size_t)ftell(file);
118-
if (size > SIZE_FLASH) {
119-
gui_console_err_printf("[CEmu] Invalid ROM size (%u bytes | max %u bytes)\n", (unsigned int)size, SIZE_FLASH);
118+
if (size > SIZE_FLASH_MAX) {
119+
gui_console_err_printf("[CEmu] Invalid ROM size (%u bytes | max %u bytes)\n", (unsigned int)size, SIZE_FLASH_MAX);
120120
goto rerr;
121121
}
122122
rewind(file);
123123

124124
asic_free();
125125
asic_init();
126126

127+
/* Allocate FLASH memory */
128+
if (size < SIZE_FLASH_MIN) {
129+
mem.flash.size = SIZE_FLASH_MIN;
130+
} else {
131+
/* Round up to next power of 2 */
132+
uint32_t rounded = size - 1;
133+
rounded |= rounded >> 1;
134+
rounded |= rounded >> 2;
135+
rounded |= rounded >> 4;
136+
rounded |= rounded >> 8;
137+
rounded |= rounded >> 16;
138+
mem.flash.size = rounded + 1;
139+
}
140+
mem.flash.block = malloc(mem.flash.size);
141+
if (mem.flash.block == NULL) {
142+
gui_console_err_printf("[CEmu] Error allocating memory for ROM\n");
143+
goto rerr;
144+
}
145+
memset(mem.flash.block, 0xFF, mem.flash.size);
146+
127147
if (fread(mem.flash.block, size, 1, file) != 1) {
128148
gui_console_err_printf("[CEmu] Error reading ROM image\n");
129149
goto rerr;
@@ -134,7 +154,7 @@ emu_state_t emu_load(emu_data_t type, const char *path) {
134154
outer = mem.flash.block;
135155

136156
/* Outer 0x800(0) field. */
137-
if (cert_field_get(outer + offset, SIZE_FLASH - offset, &field_type, &outer, &outer_field_size)) break;
157+
if (cert_field_get(outer + offset, mem.flash.size - offset, &field_type, &outer, &outer_field_size)) break;
138158
if (field_type != 0x800F) continue;
139159

140160
/* Inner 0x801(0) field: calculator model */

core/flash.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static void flash_set_mask(void) {
3939
| flash.maskReg[1] << 8
4040
| flash.maskReg[2] << 16
4141
| flash.maskReg[3] << 24;
42-
flash.mask = ~value & (SIZE_FLASH - 1);
42+
flash.mask = ~value & (mem.flash.size - 1);
4343
}
4444

4545
void flash_flush_cache(void) {
@@ -108,9 +108,9 @@ static void flash_finish_command(void) {
108108
}
109109

110110
static void flash_erase(uint32_t size) {
111-
assert(!(size & (size - 1)));
111+
assert(!(size & (size - 1)) && size <= mem.flash.size);
112112
if (flash.commandStatus[1] & 1 << 1) {
113-
memset(&mem.flash.block[flash.commandAddress & (SIZE_FLASH - 1) & -size], 0xFF, size);
113+
memset(&mem.flash.block[flash.commandAddress & (mem.flash.size - size)], 0xFF, size);
114114
}
115115
flash_finish_command();
116116
}
@@ -150,7 +150,7 @@ static void flash_execute_command(void) {
150150
flash_erase(64 << 10);
151151
break;
152152
case 0xC7: case 0x60: // Chip Erase
153-
flash_erase(SIZE_FLASH);
153+
flash_erase(mem.flash.size);
154154
break;
155155
}
156156
if (!flash.commandLength && flash.commandStatus[0] & 3 << 1) {
@@ -201,8 +201,14 @@ static uint8_t flash_read_command(bool peek) {
201201
flash.commandAddress = 0;
202202
}
203203
addr = 0;
204+
} else if (addr == 2) {
205+
value = 0x16;
206+
while ((1 << value) < mem.flash.size) {
207+
value++;
208+
}
209+
} else {
210+
value = 0xEF40 >> (1 - addr) * 8;
204211
}
205-
value = 0xEF4016 >> (2 - addr) * 8;
206212
if (!peek) {
207213
flash.commandAddress++;
208214
}
@@ -213,7 +219,7 @@ static uint8_t flash_read_command(bool peek) {
213219
static void flash_write_command(uint8_t byte) {
214220
switch (flash.command[0xF]) {
215221
case 0x32: // Quad Input Page Program
216-
mem.flash.block[flash.commandAddress & (SIZE_FLASH - 1)] &= byte;
222+
mem.flash.block[flash.commandAddress & (mem.flash.size - 1)] &= byte;
217223
flash.commandAddress = (flash.commandAddress & ~0xFF) | ((flash.commandAddress + 1) & 0xFF);
218224
break;
219225
}

core/interrupt.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,19 +123,19 @@ eZ80portrange_t init_intrpt(void) {
123123
}
124124

125125
bool intrpt_save(FILE *image) {
126-
bool ret = false;
126+
bool ret = true;
127127
size_t request;
128128
for (request = 0; request < sizeof(intrpt) / sizeof(*intrpt); request++) {
129-
ret |= fwrite(&intrpt[request], sizeof(intrpt[request]), 1, image) == 1;
129+
ret &= fwrite(&intrpt[request], sizeof(intrpt[request]), 1, image) == 1;
130130
}
131131
return ret;
132132
}
133133

134134
bool intrpt_restore(FILE *image) {
135-
bool ret = false;
135+
bool ret = true;
136136
size_t request;
137137
for (request = 0; request < sizeof(intrpt) / sizeof(*intrpt); request++) {
138-
ret |= fread(&intrpt[request], sizeof(intrpt[request]), 1, image) == 1;
138+
ret &= fread(&intrpt[request], sizeof(intrpt[request]), 1, image) == 1;
139139
}
140140
return ret;
141141
}

core/lcd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ void emu_set_lcd_ptrs(uint32_t **dat, uint32_t **dat_end, int width, int height,
592592
}
593593

594594
if (addr < 0xD00000) {
595-
mem_end = mem.flash.block + SIZE_FLASH;
595+
mem_end = mem.flash.block + mem.flash.size;
596596
data_start = mem.flash.block + addr;
597597
} else if (addr < 0xE00000) {
598598
mem_end = mem.ram.block + SIZE_RAM;

core/mem.c

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,12 @@ static uint8_t mem_read_flash_serial(uint32_t);
2626
void mem_init(void) {
2727
unsigned int i;
2828

29-
/* Allocate FLASH memory */
30-
mem.flash.block = (uint8_t*)malloc(SIZE_FLASH);
31-
memset(mem.flash.block, 0xFF, SIZE_FLASH);
32-
3329
for (i = 0; i < NUM_8K_SECTORS; i++) {
34-
mem.flash.sector8k[i].ptr = mem.flash.block + i * SIZE_FLASH_SECTOR_8K;
3530
mem.flash.sector8k[i].ipb = 0;
3631
mem.flash.sector8k[i].dpb = 1;
3732
}
3833

39-
for (i = 0; i < NUM_SECTORS; i++) {
40-
mem.flash.sector[i].ptr = mem.flash.block + i * SIZE_FLASH_SECTOR_64K;
34+
for (i = 0; i < NUM_SECTORS_MAX; i++) {
4135
mem.flash.sector[i].ipb = 1;
4236
mem.flash.sector[i].dpb = 1;
4337
}
@@ -77,7 +71,7 @@ static uint32_t addr_block(uint32_t *addr, int32_t size, void **block, uint32_t
7771
if (*addr < 0xD00000) {
7872
*addr &= asic.serFlash ? flash.mask : flash.mappedBytes - 1;
7973
*block = mem.flash.block;
80-
*block_size = SIZE_FLASH;
74+
*block_size = mem.flash.size;
8175
} else if (*addr < 0xE00000) {
8276
*addr &= 0x07FFFF;
8377
*block = mem.ram.block;
@@ -184,6 +178,11 @@ void mem_dma_write(const void *buf, uint32_t addr, int32_t size) {
184178
}
185179
}
186180

181+
static uint32_t flash_num_sectors(void) {
182+
uint32_t num_sectors = mem.flash.size / SIZE_FLASH_SECTOR_64K;
183+
return num_sectors >= NUM_SECTORS_MAX ? NUM_SECTORS_MAX : num_sectors;
184+
}
185+
187186
static void flash_reset_write_index(uint32_t addr, uint8_t byte) {
188187
(void)addr;
189188
(void)byte;
@@ -208,21 +207,21 @@ static void flash_write(uint32_t addr, uint8_t byte) {
208207
}
209208

210209
static void flash_erase(uint32_t addr, uint8_t byte) {
211-
unsigned int i;
212210
(void)addr;
213211
(void)byte;
214212

215213
mem.flash.command = FLASH_CHIP_ERASE;
216214

217-
for (i = 0; i < NUM_8K_SECTORS; i++) {
215+
for (uint32_t i = 0; i < NUM_8K_SECTORS; i++) {
218216
if ((mem.flash.sector8k[i].ipb & mem.flash.sector8k[i].dpb) == 1) {
219-
memset(mem.flash.sector8k[i].ptr, 0xFF, SIZE_FLASH_SECTOR_8K);
217+
memset(&mem.flash.block[i * SIZE_FLASH_SECTOR_8K], 0xFF, SIZE_FLASH_SECTOR_8K);
220218
}
221219
}
222220

223-
for (i = 0; i < NUM_SECTORS; i++) {
221+
uint32_t num_sectors = flash_num_sectors();
222+
for (uint32_t i = 0; i < num_sectors; i++) {
224223
if ((mem.flash.sector[i].ipb & mem.flash.sector[i].dpb) == 1) {
225-
memset(mem.flash.sector[i].ptr, 0xFF, SIZE_FLASH_SECTOR_64K);
224+
memset(&mem.flash.block[i * SIZE_FLASH_SECTOR_64K], 0xFF, SIZE_FLASH_SECTOR_64K);
226225
}
227226
}
228227

@@ -235,15 +234,15 @@ static void flash_erase_sector(uint32_t addr, uint8_t byte) {
235234

236235
mem.flash.command = FLASH_SECTOR_ERASE;
237236

238-
if (addr < 0x10000) {
237+
if (addr < SIZE_FLASH_SECTOR_8K * NUM_8K_SECTORS) {
239238
selected = addr / SIZE_FLASH_SECTOR_8K;
240239
if ((mem.flash.sector8k[selected].ipb & mem.flash.sector8k[selected].dpb) == 1) {
241-
memset(mem.flash.sector8k[selected].ptr, 0xff, SIZE_FLASH_SECTOR_8K);
240+
memset(&mem.flash.block[selected * SIZE_FLASH_SECTOR_8K], 0xFF, SIZE_FLASH_SECTOR_8K);
242241
}
243242
} else {
244243
selected = addr / SIZE_FLASH_SECTOR_64K;
245244
if ((mem.flash.sector[selected].ipb & mem.flash.sector[selected].dpb) == 1) {
246-
memset(mem.flash.sector[selected].ptr, 0xff, SIZE_FLASH_SECTOR_64K);
245+
memset(&mem.flash.block[selected * SIZE_FLASH_SECTOR_64K], 0xFF, SIZE_FLASH_SECTOR_64K);
247246
}
248247
}
249248
}
@@ -284,17 +283,17 @@ static void flash_enter_dpb(uint32_t addr, uint8_t byte) {
284283
}
285284

286285
static void flash_erase_ipb(uint32_t addr, uint8_t byte) {
287-
int i;
288286
(void)addr;
289287
(void)byte;
290288

291289
if( mem.flash.command == FLASH_IPB_MODE )
292290
{
293-
for (i = 0; i < NUM_8K_SECTORS; i++) {
291+
for (uint32_t i = 0; i < NUM_8K_SECTORS; i++) {
294292
mem.flash.sector8k[i].ipb = 1;
295293
}
296294

297-
for (i = 0; i < NUM_SECTORS; i++) {
295+
uint32_t num_sectors = flash_num_sectors();
296+
for (uint32_t i = 0; i < num_sectors; i++) {
298297
mem.flash.sector[i].ipb = 1;
299298
}
300299

@@ -485,9 +484,10 @@ static uint8_t mem_read_flash_parallel(uint32_t addr) {
485484
}
486485
cpu.cycles += flash.waitStates;
487486

487+
addr &= mem.flash.size - 1;
488488
switch(mem.flash.command) {
489489
case FLASH_NO_COMMAND:
490-
value = mem.flash.block[addr & (SIZE_FLASH - 1)];
490+
value = mem.flash.block[addr];
491491
break;
492492
case FLASH_SECTOR_ERASE:
493493
value = 0x80;
@@ -502,7 +502,7 @@ static uint8_t mem_read_flash_parallel(uint32_t addr) {
502502
mem.flash.command = FLASH_NO_COMMAND;
503503
break;
504504
case FLASH_READ_SECTOR_PROTECTION:
505-
if (addr < 0x10000) {
505+
if (addr < SIZE_FLASH_SECTOR_8K * NUM_8K_SECTORS) {
506506
selected = addr / SIZE_FLASH_SECTOR_8K;
507507
value = !(mem.flash.sector8k[selected].ipb & mem.flash.sector8k[selected].dpb);
508508
} else {
@@ -597,6 +597,7 @@ static void mem_write_flash(uint32_t addr, uint8_t byte) {
597597
flash_write_t *w;
598598
flash_write_pattern_t *pattern;
599599

600+
addr &= mem.flash.size - 1;
600601
if (mem.flash.command != FLASH_NO_COMMAND) {
601602
if ((mem.flash.command != FLASH_DEEP_POWER_DOWN && byte == 0xF0) ||
602603
(mem.flash.command == FLASH_DEEP_POWER_DOWN && byte == 0xAB)) {
@@ -918,37 +919,38 @@ bool mem_save(FILE *image) {
918919
assert(mem.ram.block);
919920

920921
return fwrite(&mem, sizeof(mem), 1, image) == 1 &&
921-
fwrite(mem.flash.block, SIZE_FLASH, 1, image) == 1 &&
922+
fwrite(mem.flash.block, mem.flash.size, 1, image) == 1 &&
922923
fwrite(mem.ram.block, SIZE_RAM, 1, image) == 1;
923924
}
924925

925926
bool mem_restore(FILE *image) {
926-
bool ret = false;
927+
bool ret = true;
927928
unsigned int i;
928929
uint8_t *tmp_flash_ptr;
929930
uint8_t *tmp_ram_ptr;
930931

931-
assert(mem.flash.block);
932932
assert(mem.ram.block);
933-
934-
tmp_flash_ptr = mem.flash.block;
935933
tmp_ram_ptr = mem.ram.block;
936934

937-
ret |= fread(&mem, sizeof(mem), 1, image) == 1;
935+
free(mem.flash.block);
936+
937+
ret &= fread(&mem, sizeof(mem), 1, image) == 1;
938938

939-
mem.flash.block = tmp_flash_ptr;
940939
mem.ram.block = tmp_ram_ptr;
940+
mem.flash.block = NULL;
941941

942-
ret |= fread(mem.flash.block, SIZE_FLASH, 1, image) == 1 &&
943-
fread(mem.ram.block, SIZE_RAM, 1, image) == 1;
944-
945-
for (i = 0; i < 8; i++) {
946-
mem.flash.sector[i].ptr = &mem.flash.block[i*SIZE_FLASH_SECTOR_8K];
942+
if (mem.flash.size < SIZE_FLASH_MIN || mem.flash.size > SIZE_FLASH_MAX ||
943+
(mem.flash.size & (mem.flash.size - 1))) {
944+
return false;
947945
}
948-
for (i = 0; i < 64; i++) {
949-
mem.flash.sector[i].ptr = &mem.flash.block[i*SIZE_FLASH_SECTOR_64K];
946+
mem.flash.block = malloc(mem.flash.size);
947+
if (mem.flash.block == NULL) {
948+
return false;
950949
}
951950

951+
ret &= fread(mem.flash.block, mem.flash.size, 1, image) == 1;
952+
ret &= fread(mem.ram.block, SIZE_RAM, 1, image) == 1;
953+
952954
mem_read_flash = asic.serFlash ? mem_read_flash_serial : mem_read_flash_parallel;
953955

954956
return ret;

core/mem.h

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

1212
#define SIZE_RAM 0x65800
13-
#define SIZE_FLASH 0x400000
13+
#define SIZE_FLASH_MIN 0x400000
14+
#define SIZE_FLASH_MAX_PAR 0x800000
15+
#define SIZE_FLASH_MAX 0x2000000
1416
#define SIZE_FLASH_SECTOR_8K 0x2000
1517
#define SIZE_FLASH_SECTOR_64K 0x10000
16-
#define NUM_SECTORS 64
18+
#define NUM_SECTORS_MAX (SIZE_FLASH_MAX_PAR / SIZE_FLASH_SECTOR_64K)
1719
#define NUM_8K_SECTORS 8
1820

1921
enum flash_commands {
@@ -38,15 +40,15 @@ typedef struct {
3840
typedef struct {
3941
uint8_t dpb : 1;
4042
uint8_t ipb : 1;
41-
uint8_t *ptr;
4243
} flash_sector_state_t;
4344

4445
typedef struct {
4546
uint8_t write;
4647
uint8_t read;
47-
flash_sector_state_t sector8k[8];
48-
flash_sector_state_t sector[64];
48+
flash_sector_state_t sector8k[NUM_8K_SECTORS];
49+
flash_sector_state_t sector[NUM_SECTORS_MAX];
4950
uint8_t *block;
51+
uint32_t size;
5052

5153
/* internal */
5254
uint8_t command;

core/vat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ bool vat_search_next(calc_var_t *var) {
318318
} else {
319319
var->namelen = 3;
320320
}
321-
var->archived = var->address > 0xC0000 && var->address < 0x400000;
321+
var->archived = var->address > 0xC0000 && var->address < 0xC00000;
322322
if (var->archived) {
323323
var->address += 9 + var->named + var->namelen;
324324
} else if (var->address < 0xD1A881 || var->address >= 0xD40000) {

0 commit comments

Comments
 (0)