Skip to content

Commit

Permalink
Added support for Code ROM persistence.
Browse files Browse the repository at this point in the history
This isn't something exceptionally useful as normally the emulator is started
with "flashing" a game into it, but it is notably required for the currently
existing bootloader versions to operate correctly (they don't try to reflash
the game if they remeber it being loaded in the EEPROM by checksum).
  • Loading branch information
Jubatian committed Sep 19, 2017
1 parent 5568c80 commit ee8df43
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 37 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -16,6 +16,7 @@
/gamefile.c
# If the program created various files, ignore those too
/eeprom.bin
/coderom.bin
/capture.mp4
# If for a Windows build an SDL2 development library is supplied locally, skip that
/SDL2*
2 changes: 1 addition & 1 deletion Make_config.mk
Expand Up @@ -62,7 +62,7 @@ CC_LIB=
#
# Version number to use. It should be a BCD date of YYYYMMDD format.
#
VER_DATE=0x20170918
VER_DATE=0x20170919
#
#
# In case a test build (debug) is necessary, give 'test' here. It enables
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Expand Up @@ -54,6 +54,7 @@ OBJECTS += $(OBD)/cu_spisd.o
OBJECTS += $(OBD)/filesys.o
endif
OBJECTS += $(OBD)/eepdump.o
OBJECTS += $(OBD)/romdump.o
OBJECTS += $(OBD)/guicore.o
OBJECTS += $(OBD)/audio.o
OBJECTS += $(OBD)/ginput.o
Expand Down Expand Up @@ -176,6 +177,9 @@ $(OBD)/frame.o: frame.c $(DEPS)
$(OBD)/eepdump.o: eepdump.c $(DEPS)
$(CC) -c $< -o $@ $(CFSIZ)

$(OBD)/romdump.o: romdump.c $(DEPS)
$(CC) -c $< -o $@ $(CFSIZ)

$(OBD)/avconv.o: avconv.c $(DEPS)
$(CC) -c $< -o $@ $(CFSIZ)

Expand Down
46 changes: 37 additions & 9 deletions cu_avr.c
Expand Up @@ -104,9 +104,12 @@ boole event_it_enter;
/* Vector to call when entering interrupt */
auint event_it_vect;

/* EEPROM change indicator */
/* EEPROM change indicator for saves to persistent storage */
boole eeprom_changed;

/* Code ROM change indicator for saves to persistent storage */
boole crom_changed;

/* Watchdog-based debug counter: Time of last WDR execution */
auint wd_last;

Expand Down Expand Up @@ -916,11 +919,15 @@ static auint cu_avr_read_io(auint port)
/*
** Resets the CPU as if it was power-cycled. It properly initializes
** everything from the state as if cu_avr_crom_update() and cu_avr_io_update()
** was called.
** was called. The bootpri flag requests prioritizing the bootloader when set
** TRUE, otherwise game is prioritized (used when both a game and a bootloader
** appears to be present in the ROM).
*/
void cu_avr_reset(void)
void cu_avr_reset(boole bootpri)
{
auint i;
boole hasgame;
boole hasboot;

for (i = 0U; i < 4096U; i++){
access_mem[i] = 0U;
Expand All @@ -947,12 +954,16 @@ void cu_avr_reset(void)

cpu_state.latch = 0U;

/* Check whether something is loaded. Normally the AVR is fused to use the
** boot loader, so if anything is present there, use that. If there is no
** boot loader (only an application is loaded), boot that instead. */
/* Determine boot fuses according to the contents of the ROM and the boot
** prioritization parameter. The boot loader is used when it exists and it
** is prioritized or when it looks like there is no game in the Code ROM. */

if ( (cpu_state.crom[(VBASE_BOOT * 2U) + 0U] != 0U) ||
(cpu_state.crom[(VBASE_BOOT * 2U) + 1U] != 0U) ){ cpu_state.iors[CU_IO_MCUCR] |= 2U; }
hasgame = (cpu_state.crom[ 0U] != 0U) ||
(cpu_state.crom[ 1U] != 0U);
hasboot = (cpu_state.crom[(VBASE_BOOT * 2U) + 0U] != 0U) ||
(cpu_state.crom[(VBASE_BOOT * 2U) + 1U] != 0U);
if ( (hasboot && bootpri) ||
(!hasgame) ){ cpu_state.iors[CU_IO_MCUCR] |= 2U; }

cpu_state.pc = (((cpu_state.iors[CU_IO_MCUCR] >> 1) & 1U) * VBASE_BOOT) + VECT_RESET;

Expand Down Expand Up @@ -1116,7 +1127,8 @@ uint8* cu_avr_get_ioinfo(void)
/*
** Returns whether the EEPROM changed since the last clear of this indicator.
** Calling cu_avr_io_update() clears this indicator (as well as resetting by
** cu_avr_reset()). Passing TRUE also clears it.
** cu_avr_reset()). Passing TRUE also clears it. This can be used to save
** EEPROM state to persistent storage when it changes.
*/
boole cu_avr_eeprom_ischanged(boole clear)
{
Expand All @@ -1126,6 +1138,20 @@ boole cu_avr_eeprom_ischanged(boole clear)
}


/*
** Returns whether the Code ROM changed since the last clear of this
** indicator. Calling cu_avr_io_update() clears this indicator (as well as
** resetting by cu_avr_reset()). Passing TRUE also clears it. This can be used
** to save Code ROM state to persistent storage when it changes.
*/
boole cu_avr_crom_ischanged(boole clear)
{
boole ret = crom_changed;
if (clear){ crom_changed = FALSE; }
return ret;
}



/*
** Returns whether the Code ROM was modified since reset. This can be used to
Expand Down Expand Up @@ -1179,6 +1205,7 @@ void cu_avr_crom_update(auint base, auint len)
}

cpu_state.crom_mod = TRUE;
crom_changed = TRUE;
}


Expand All @@ -1194,6 +1221,7 @@ void cu_avr_io_update(void)
auint t0;

eeprom_changed = FALSE;
crom_changed = FALSE;

t0 = (cpu_state.iors[CU_IO_TCNT1H] << 8) |
(cpu_state.iors[CU_IO_TCNT1L] );
Expand Down
18 changes: 15 additions & 3 deletions cu_avr.h
Expand Up @@ -38,9 +38,11 @@
/*
** Resets the CPU as if it was power-cycled. It properly initializes
** everything from the state as if cu_avr_crom_update() and cu_avr_io_update()
** was called.
** was called. The bootpri flag requests prioritizing the bootloader when set
** TRUE, otherwise game is prioritized (used when both a game and a bootloader
** appears to be present in the ROM).
*/
void cu_avr_reset(void);
void cu_avr_reset(boole bootpri);


/*
Expand Down Expand Up @@ -92,11 +94,21 @@ uint8* cu_avr_get_ioinfo(void);
/*
** Returns whether the EEPROM changed since the last clear of this indicator.
** Calling cu_avr_io_update() clears this indicator (as well as resetting by
** cu_avr_reset()). Passing TRUE also clears it.
** cu_avr_reset()). Passing TRUE also clears it. This can be used to save
** EEPROM state to persistent storage when it changes.
*/
boole cu_avr_eeprom_ischanged(boole clear);


/*
** Returns whether the Code ROM changed since the last clear of this
** indicator. Calling cu_avr_io_update() clears this indicator (as well as
** resetting by cu_avr_reset()). Passing TRUE also clears it. This can be used
** to save Code ROM state to persistent storage when it changes.
*/
boole cu_avr_crom_ischanged(boole clear);


/*
** Returns whether the Code ROM was modified since reset. This can be used to
** determine if it is necessary to include the Code ROM in a save state.
Expand Down
1 change: 0 additions & 1 deletion cu_avr_e.h
Expand Up @@ -450,7 +450,6 @@ static void op_17(auint arg1, auint arg2) /* SPM */
(WRAP32(cpu_state.spm_end - cpu_state.cycle)) ){
cycle_next_event = cpu_state.spm_end; /* Set SPM HW processing target */
}
cpu_state.crom_mod = TRUE; /* Code ROM modified */
}else if (cpu_state.spm_mode == 0x08U){ /* Boot lock bit set (unimplemented) */
cpu_state.iors[CU_IO_SPMCSR] &= 0xE0U;
}else if (cpu_state.spm_mode == 0x10U){ /* RWW section read enable */
Expand Down
1 change: 0 additions & 1 deletion cu_avr_n.h
Expand Up @@ -222,7 +222,6 @@ static void cu_avr_exec(void)
(WRAP32(cpu_state.spm_end - cpu_state.cycle)) ){
cycle_next_event = cpu_state.spm_end; /* Set SPM HW processing target */
}
cpu_state.crom_mod = TRUE; /* Code ROM modified */
}else if (cpu_state.spm_mode == 0x08U){ /* Boot lock bit set (unimplemented) */
cpu_state.iors[CU_IO_SPMCSR] &= 0xE0U;
}else if (cpu_state.spm_mode == 0x10U){ /* RWW section read enable */
Expand Down
5 changes: 3 additions & 2 deletions cu_hfile.c
@@ -1,7 +1,7 @@
/*
* Hex file parser
*
* Copyright (C) 2016
* Copyright (C) 2016 - 2017
* Sandor Zsuga (Jubatian)
* Uzem (the base of CUzeBox) is copyright (C)
* David Etherton,
Expand Down Expand Up @@ -41,7 +41,8 @@ static const char cu_war[] = "Warning: ";

/*
** Attempts to load the passed file into code memory. The code memory is not
** cleared, so bootloader image may be added before this if there is any.
** cleared, so bootloader image or other contents may be added before this if
** there are any.
**
** The code memory must be 64 KBytes.
**
Expand Down
5 changes: 3 additions & 2 deletions cu_hfile.h
@@ -1,7 +1,7 @@
/*
* Hex file parser
*
* Copyright (C) 2016
* Copyright (C) 2016 - 2017
* Sandor Zsuga (Jubatian)
* Uzem (the base of CUzeBox) is copyright (C)
* David Etherton,
Expand Down Expand Up @@ -38,7 +38,8 @@

/*
** Attempts to load the passed file into code memory. The code memory is not
** cleared, so bootloader image may be added before this if there is any.
** cleared, so bootloader image or other contents may be added before this if
** there are any.
**
** The code memory must be 64 KBytes.
**
Expand Down
5 changes: 3 additions & 2 deletions cu_ufile.c
@@ -1,7 +1,7 @@
/*
* UzeRom file parser
*
* Copyright (C) 2016
* Copyright (C) 2016 - 2017
* Sandor Zsuga (Jubatian)
* Uzem (the base of CUzeBox) is copyright (C)
* David Etherton,
Expand Down Expand Up @@ -46,7 +46,8 @@ static const char cu_war[] = "Warning: ";

/*
** Attempts to load the passed file into code memory. The code memory is not
** cleared, so bootloader image may be added before this if there is any.
** cleared, so bootloader image or other contents may be added before this if
** there are any.
**
** The code memory must be 64 KBytes.
**
Expand Down
5 changes: 3 additions & 2 deletions cu_ufile.h
@@ -1,7 +1,7 @@
/*
* UzeRom file parser
*
* Copyright (C) 2016
* Copyright (C) 2016 - 2017
* Sandor Zsuga (Jubatian)
* Uzem (the base of CUzeBox) is copyright (C)
* David Etherton,
Expand Down Expand Up @@ -55,7 +55,8 @@ typedef struct{

/*
** Attempts to load the passed file into code memory. The code memory is not
** cleared, so bootloader image may be added before this if there is any.
** cleared, so bootloader image or other contents may be added before this if
** there are any.
**
** The code memory must be 64 KBytes.
**
Expand Down
14 changes: 7 additions & 7 deletions eepdump.c
Expand Up @@ -45,16 +45,16 @@ void eepdump_load(uint8* eeprom)
{
auint rv;

if (!filesys_open(FILESYS_CH_EEP, eepdump_file)){ goto ex_fail; }
if (!filesys_open(FILESYS_CH_ROM, eepdump_file)){ goto ex_fail; }

rv = filesys_read(FILESYS_CH_EEP, eeprom, 2048U);
rv = filesys_read(FILESYS_CH_ROM, eeprom, 2048U);
if (rv != 2048){ goto ex_fail; }

filesys_flush(FILESYS_CH_EEP);
filesys_flush(FILESYS_CH_ROM);
return;

ex_fail:
filesys_flush(FILESYS_CH_EEP);
filesys_flush(FILESYS_CH_ROM);
memset(eeprom, 0xFFU, 2048U);
return;
}
Expand All @@ -67,10 +67,10 @@ void eepdump_load(uint8* eeprom)
*/
void eepdump_save(uint8 const* eeprom)
{
(void)(filesys_open(FILESYS_CH_EEP, eepdump_file)); /* Might fail since tries to open for reading */
(void)(filesys_open(FILESYS_CH_ROM, eepdump_file)); /* Might fail since tries to open for reading */

(void)(filesys_write(FILESYS_CH_EEP, eeprom, 2048U)); /* Don't care for faults (can't do anything about them) */
(void)(filesys_write(FILESYS_CH_ROM, eeprom, 2048U)); /* Don't care for faults (can't do anything about them) */

filesys_flush(FILESYS_CH_EEP);
filesys_flush(FILESYS_CH_ROM);
return;
}
6 changes: 3 additions & 3 deletions filesys.h
@@ -1,7 +1,7 @@
/*
* Filesystem interface layer
*
* Copyright (C) 2016
* Copyright (C) 2016 - 2017
* Sandor Zsuga (Jubatian)
* Uzem (the base of CUzeBox) is copyright (C)
* David Etherton,
Expand Down Expand Up @@ -52,8 +52,8 @@
#define FILESYS_CH_SD 0U
/* Various emulator one-shot tasks (such as game loading) */
#define FILESYS_CH_EMU 1U
/* EEPROM dumps */
#define FILESYS_CH_EEP 2U
/* EEPROM & Code ROM dumps */
#define FILESYS_CH_ROM 2U

/* Number of filesystem channels (must be one larger than the largest entry
** of the list above) */
Expand Down

0 comments on commit ee8df43

Please sign in to comment.