forked from Miroirs/x49gp
Compare commits
3 commits
69ce49c003
...
347d61ced9
Author | SHA1 | Date | |
---|---|---|---|
|
347d61ced9 | ||
|
f30edab58c | ||
|
b5f6fbe716 |
8 changed files with 276 additions and 219 deletions
3
Makefile
3
Makefile
|
@ -143,7 +143,8 @@ SRCS = ./src/main.c \
|
||||||
./src/tiny_font.c \
|
./src/tiny_font.c \
|
||||||
./src/symbol.c \
|
./src/symbol.c \
|
||||||
./src/gdbstub.c \
|
./src/gdbstub.c \
|
||||||
./src/block.c
|
./src/block.c \
|
||||||
|
./src/options.c
|
||||||
|
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
||||||
|
|
41
dist/x49gpng.man.in
vendored
41
dist/x49gpng.man.in
vendored
|
@ -142,10 +142,7 @@ to rebuild the flash and ask for a firmware again.
|
||||||
Please consult HP's manual (for their official firmware) or the documentation of the custom firmware (if using one) for an explanation of using the calculator.
|
Please consult HP's manual (for their official firmware) or the documentation of the custom firmware (if using one) for an explanation of using the calculator.
|
||||||
.Sh OPTIONS
|
.Sh OPTIONS
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl d Ns Oo Ns = Ns Ar port Oc , Fl Fl debug Ns Oo Ns = Ns Ar port Oc
|
|
||||||
Enable the GDB remote debugging interface on the specified port (default 1234) and start the interface immediately. When used multiple times, the last explicitly specified port wins. If the connection is closed before
|
|
||||||
.Nm
|
|
||||||
is shut down, then the interface can be restarted from the popup menu.
|
|
||||||
.It Fl D Ns Oo Ns = Ns Ar port Oc , Fl Fl enable-debug Ns Oo Ns = Ns Ar port Oc
|
.It Fl D Ns Oo Ns = Ns Ar port Oc , Fl Fl enable-debug Ns Oo Ns = Ns Ar port Oc
|
||||||
Same as
|
Same as
|
||||||
.Fl d ,
|
.Fl d ,
|
||||||
|
@ -155,6 +152,12 @@ the last explicitly specified port will still win, and the GDB interface will be
|
||||||
.Do Nm
|
.Do Nm
|
||||||
.Fl D Dc
|
.Fl D Dc
|
||||||
when the possibility for spontaneous debug sessions exists.
|
when the possibility for spontaneous debug sessions exists.
|
||||||
|
|
||||||
|
.It Fl d , Fl Fl debug
|
||||||
|
Enable the GDB remote debugging interface on the specified port (default 1234) and start the interface immediately. When used multiple times, the last explicitly specified port wins. If the connection is closed before
|
||||||
|
.Nm
|
||||||
|
is shut down, then the interface can be restarted from the popup menu.
|
||||||
|
|
||||||
.It Fl f Ns Oo Ns = Ns Ar firmware Oc , Fl Fl reflash Ns Oo Ns = Ns Ar firmware Oc
|
.It Fl f Ns Oo Ns = Ns Ar firmware Oc , Fl Fl reflash Ns Oo Ns = Ns Ar firmware Oc
|
||||||
Rebuild the flash. If the firmware is not specified,
|
Rebuild the flash. If the firmware is not specified,
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -163,15 +166,30 @@ will ask for one through a file selection dialog window like on the first launch
|
||||||
for safety reasons: the firmware may have changed, so the code at the location where
|
for safety reasons: the firmware may have changed, so the code at the location where
|
||||||
.Nm
|
.Nm
|
||||||
was stopped previously could be entirely different from the code at that location afterwards; a reboot ensures an orderly reinitialization of the operating system.
|
was stopped previously could be entirely different from the code at that location afterwards; a reboot ensures an orderly reinitialization of the operating system.
|
||||||
.It Fl F Ns Oo Ns = Ns Ar firmware Oc , Fl Fl reflash-full Ns Oo Ns = Ns Ar firmware Oc
|
.It Fl F , Fl Fl reflash-full
|
||||||
Same as
|
Same as
|
||||||
.Fl f ,
|
.Fl f ,
|
||||||
but erase the area beyond the firmware too. This has the same effect as deleting the flash, but with the added benefit of being able to specify the firmware on the command-line for automation in scripts.
|
but erase the area beyond the firmware too. This has the same effect as deleting the flash, but with the added benefit of being able to specify the firmware on the command-line for automation in scripts.
|
||||||
|
|
||||||
.It Fl r , Fl Fl reboot
|
.It Fl r , Fl Fl reboot
|
||||||
Reboot the calculator instead of starting from the state saved in the configuration file.
|
Reboot the calculator instead of starting from the state saved in the configuration file.
|
||||||
|
|
||||||
.It Fl h , Fl Fl help
|
.It Fl h , Fl Fl help
|
||||||
Print a compact help message and exit.
|
Print a compact help message and exit.
|
||||||
.It Ar config
|
|
||||||
|
.It Fl Fl 50g
|
||||||
|
show HP 50g faceplate (default)
|
||||||
|
|
||||||
|
.It Fl Fl 50g-newrpl
|
||||||
|
show HP 50g faceplate with newRPL labels
|
||||||
|
|
||||||
|
.It Fl Fl 49gp
|
||||||
|
show HP 49g+ faceplate
|
||||||
|
|
||||||
|
.It Fl Fl 49gp-newrpl
|
||||||
|
show HP 49g+ faceplate with newRPL labels
|
||||||
|
|
||||||
|
.It Fl c Ns Oo Ns = Ns Ar config Oc , Fl Fl config Ns Oo Ns = Ns Ar config Oc
|
||||||
Use
|
Use
|
||||||
.Ar config
|
.Ar config
|
||||||
as the configuration file instead of the default one. See below for details on the format; if the file does not exist, it will be created with default values.
|
as the configuration file instead of the default one. See below for details on the format; if the file does not exist, it will be created with default values.
|
||||||
|
@ -195,17 +213,6 @@ in the sections
|
||||||
which allow changing the filename of the files where the state of the respective memory is held. These can be absolute paths, or paths relative to the location of the configuration file (in the simplest case, only a filename). Any files that do not exist will be created with appropriate size and placeholder content. For
|
which allow changing the filename of the files where the state of the respective memory is held. These can be absolute paths, or paths relative to the location of the configuration file (in the simplest case, only a filename). Any files that do not exist will be created with appropriate size and placeholder content. For
|
||||||
.Em s3c2410-sdi ,
|
.Em s3c2410-sdi ,
|
||||||
the empty string is accepted as a special value for no inserted SD card.
|
the empty string is accepted as a special value for no inserted SD card.
|
||||||
.Pp
|
|
||||||
Finally, the
|
|
||||||
.Em gui
|
|
||||||
section contains the keys
|
|
||||||
.Em name ,
|
|
||||||
which specifies the window title (possibly useful when multiple different instances are present), and
|
|
||||||
.Em type ,
|
|
||||||
which specifies the type of the calculator (accepted values are
|
|
||||||
.Sy hp49g+
|
|
||||||
and
|
|
||||||
.Sy hp50g ) .
|
|
||||||
.It Sy flash
|
.It Sy flash
|
||||||
The default name of the file backing the flash memory; required size: 2 MiB. If this file does not exist or is too small, the calculator type's appropriate bootloader will be copied into the first 16 KiB. Do NOT simply put a firmware file here, it will not work. Just use the builtin firmware installation mechanism instead.
|
The default name of the file backing the flash memory; required size: 2 MiB. If this file does not exist or is too small, the calculator type's appropriate bootloader will be copied into the first 16 KiB. Do NOT simply put a firmware file here, it will not work. Just use the builtin firmware installation mechanism instead.
|
||||||
.It Sy sram
|
.It Sy sram
|
||||||
|
|
18
src/list.h
18
src/list.h
|
@ -47,33 +47,33 @@ struct list_head {
|
||||||
* This is only for internal list manipulation where we know
|
* This is only for internal list manipulation where we know
|
||||||
* the prev/next entries already!
|
* the prev/next entries already!
|
||||||
*/
|
*/
|
||||||
static inline void __list_add( struct list_head* new, struct list_head* prev, struct list_head* next )
|
static inline void __list_add( struct list_head* new_entry, struct list_head* prev, struct list_head* next )
|
||||||
{
|
{
|
||||||
next->prev = new;
|
next->prev = new_entry;
|
||||||
new->next = next;
|
new_entry->next = next;
|
||||||
new->prev = prev;
|
new_entry->prev = prev;
|
||||||
prev->next = new;
|
prev->next = new_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_add - add a new entry
|
* list_add - add a new entry
|
||||||
* @new: new entry to be added
|
* @new_entry: new entry to be added
|
||||||
* @head: list head to add it after
|
* @head: list head to add it after
|
||||||
*
|
*
|
||||||
* Insert a new entry after the specified head.
|
* Insert a new entry after the specified head.
|
||||||
* This is good for implementing stacks.
|
* This is good for implementing stacks.
|
||||||
*/
|
*/
|
||||||
static inline void list_add( struct list_head* new, struct list_head* head ) { __list_add( new, head, head->next ); }
|
static inline void list_add( struct list_head* new_entry, struct list_head* head ) { __list_add( new_entry, head, head->next ); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_add_tail - add a new entry
|
* list_add_tail - add a new entry
|
||||||
* @new: new entry to be added
|
* @new_entry: new entry to be added
|
||||||
* @head: list head to add it before
|
* @head: list head to add it before
|
||||||
*
|
*
|
||||||
* Insert a new entry before the specified head.
|
* Insert a new entry before the specified head.
|
||||||
* This is useful for implementing queues.
|
* This is useful for implementing queues.
|
||||||
*/
|
*/
|
||||||
static inline void list_add_tail( struct list_head* new, struct list_head* head ) { __list_add( new, head->prev, head ); }
|
static inline void list_add_tail( struct list_head* new_entry, struct list_head* head ) { __list_add( new_entry, head->prev, head ); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete a list entry by making the prev/next entries
|
* Delete a list entry by making the prev/next entries
|
||||||
|
|
179
src/main.c
179
src/main.c
|
@ -24,18 +24,10 @@
|
||||||
#include "x49gp_ui.h"
|
#include "x49gp_ui.h"
|
||||||
#include "s3c2410.h"
|
#include "s3c2410.h"
|
||||||
#include "x49gp_timer.h"
|
#include "x49gp_timer.h"
|
||||||
|
|
||||||
#include "gdbstub.h"
|
#include "gdbstub.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
#ifndef VERSION_MAJOR
|
extern struct options opt;
|
||||||
# define VERSION_MAJOR 0
|
|
||||||
#endif
|
|
||||||
#ifndef VERSION_MINOR
|
|
||||||
# define VERSION_MINOR 0
|
|
||||||
#endif
|
|
||||||
#ifndef PATCHLEVEL
|
|
||||||
# define PATCHLEVEL 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static x49gp_t* x49gp;
|
static x49gp_t* x49gp;
|
||||||
|
|
||||||
|
@ -48,7 +40,7 @@ uint8_t* phys_ram_base;
|
||||||
int phys_ram_size;
|
int phys_ram_size;
|
||||||
ram_addr_t ram_size = 0x80000; // LD ???
|
ram_addr_t ram_size = 0x80000; // LD ???
|
||||||
|
|
||||||
/* vl.c */
|
/* for qemu-git */
|
||||||
int singlestep;
|
int singlestep;
|
||||||
|
|
||||||
#if !( defined( __APPLE__ ) || defined( _POSIX_C_SOURCE ) && !defined( __sun__ ) )
|
#if !( defined( __APPLE__ ) || defined( _POSIX_C_SOURCE ) && !defined( __sun__ ) )
|
||||||
|
@ -125,11 +117,11 @@ void* qemu_vmalloc( size_t size )
|
||||||
uint32_t do_arm_semihosting( CPUState* env )
|
uint32_t do_arm_semihosting( CPUState* env )
|
||||||
{
|
{
|
||||||
uint32_t number;
|
uint32_t number;
|
||||||
if ( env->thumb ) {
|
if ( env->thumb )
|
||||||
number = lduw_code( env->regs[ 15 ] - 2 ) & 0xff;
|
number = lduw_code( env->regs[ 15 ] - 2 ) & 0xff;
|
||||||
} else {
|
else
|
||||||
number = ldl_code( env->regs[ 15 ] - 4 ) & 0xffffff;
|
number = ldl_code( env->regs[ 15 ] - 4 ) & 0xffffff;
|
||||||
}
|
|
||||||
switch ( number ) {
|
switch ( number ) {
|
||||||
case SWI_Breakpoint:
|
case SWI_Breakpoint:
|
||||||
break;
|
break;
|
||||||
|
@ -181,9 +173,9 @@ void x49gp_set_idle( x49gp_t* x49gp, x49gp_arm_idle_t idle )
|
||||||
|
|
||||||
x49gp->arm_idle = idle;
|
x49gp->arm_idle = idle;
|
||||||
|
|
||||||
if ( x49gp->arm_idle == X49GP_ARM_RUN ) {
|
if ( x49gp->arm_idle == X49GP_ARM_RUN )
|
||||||
x49gp->env->halted = 0;
|
x49gp->env->halted = 0;
|
||||||
} else {
|
else {
|
||||||
x49gp->env->halted = 1;
|
x49gp->env->halted = 1;
|
||||||
cpu_exit( x49gp->env );
|
cpu_exit( x49gp->env );
|
||||||
}
|
}
|
||||||
|
@ -228,131 +220,6 @@ void x49gp_lcd_timer( void* data )
|
||||||
x49gp_mod_timer( x49gp->lcd_timer, expires );
|
x49gp_mod_timer( x49gp->lcd_timer, expires );
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********/
|
|
||||||
/* OPTIONS */
|
|
||||||
/***********/
|
|
||||||
|
|
||||||
struct options {
|
|
||||||
char* config;
|
|
||||||
int debug_port;
|
|
||||||
int start_debugger;
|
|
||||||
char* firmware;
|
|
||||||
x49gp_reinit_t reinit;
|
|
||||||
|
|
||||||
int more_options;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct options opt;
|
|
||||||
|
|
||||||
static void config_init( char* progname, int argc, char* argv[] )
|
|
||||||
{
|
|
||||||
int option_index;
|
|
||||||
int c = '?';
|
|
||||||
|
|
||||||
opt.config = NULL;
|
|
||||||
opt.debug_port = 0;
|
|
||||||
opt.start_debugger = false;
|
|
||||||
opt.reinit = X49GP_REINIT_NONE;
|
|
||||||
opt.firmware = NULL;
|
|
||||||
|
|
||||||
const char* optstring = "hrc:D:df:F";
|
|
||||||
struct option long_options[] = {
|
|
||||||
{"help", no_argument, NULL, 'h'},
|
|
||||||
|
|
||||||
{"config", required_argument, NULL, 'c'},
|
|
||||||
|
|
||||||
{"enable-debug", required_argument, NULL, 'D'},
|
|
||||||
{"debug", no_argument, NULL, 'd'},
|
|
||||||
{"reflash", required_argument, NULL, 'f'},
|
|
||||||
{"reflash-full", no_argument, NULL, 'F'},
|
|
||||||
{"reboot", no_argument, NULL, 'r'},
|
|
||||||
|
|
||||||
{0, 0, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
while ( c != EOF ) {
|
|
||||||
c = getopt_long( argc, argv, optstring, long_options, &option_index );
|
|
||||||
|
|
||||||
switch ( c ) {
|
|
||||||
case 'h':
|
|
||||||
fprintf( stderr,
|
|
||||||
"%s %i.%i.%i Emulator for HP 49G+ / 50G calculators\n"
|
|
||||||
"Usage: %s [<options>]\n"
|
|
||||||
"Valid options:\n"
|
|
||||||
" -c --config[=<filename>] alternate config file\n"
|
|
||||||
" -D --enable-debug[=<port>] enable the debugger interface\n"
|
|
||||||
" (default port: %u)\n"
|
|
||||||
" -d --debug use along -D to also start the debugger immediately\n"
|
|
||||||
" -f --reflash[=firmware] rebuild the flash using the supplied firmware\n"
|
|
||||||
" (default: select one interactively)\n"
|
|
||||||
" (implies -r for safety reasons)\n"
|
|
||||||
" -F --reflash-full use along -f to drop the flash contents\n"
|
|
||||||
" in the area beyond the firmware\n"
|
|
||||||
" -r --reboot reboot on startup instead of continuing from the\n"
|
|
||||||
" saved state in the config file\n"
|
|
||||||
" -h --help print this message and exit\n"
|
|
||||||
"The config file is formatted as INI file and contains the settings for which\n"
|
|
||||||
" persistence makes sense, like calculator model, CPU registers, etc.\n"
|
|
||||||
"If the config file is omitted, ~/.config/%s/config is used.\n"
|
|
||||||
"Please consult the manual for more details on config file settings.\n",
|
|
||||||
progname, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, progname, DEFAULT_GDBSTUB_PORT, progname );
|
|
||||||
exit( EXIT_SUCCESS );
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
if ( opt.reinit < X49GP_REINIT_REBOOT_ONLY )
|
|
||||||
opt.reinit = X49GP_REINIT_REBOOT_ONLY;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
opt.config = strdup( optarg );
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
{
|
|
||||||
char* end;
|
|
||||||
int port;
|
|
||||||
|
|
||||||
if ( optarg == NULL && opt.debug_port == 0 )
|
|
||||||
opt.debug_port = DEFAULT_GDBSTUB_PORT;
|
|
||||||
|
|
||||||
port = strtoul( optarg, &end, 0 );
|
|
||||||
if ( ( end == optarg ) || ( *end != '\0' ) ) {
|
|
||||||
fprintf( stderr, "Invalid port \"%s\", using default\n", optarg );
|
|
||||||
if ( opt.debug_port == 0 )
|
|
||||||
opt.debug_port = DEFAULT_GDBSTUB_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( opt.debug_port != 0 && opt.debug_port != DEFAULT_GDBSTUB_PORT )
|
|
||||||
fprintf( stderr,
|
|
||||||
"Additional debug port \"%s\" specified, overriding\n",
|
|
||||||
optarg );
|
|
||||||
opt.debug_port = port;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
opt.start_debugger = true;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
opt.reinit = X49GP_REINIT_FLASH_FULL;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if ( opt.reinit < X49GP_REINIT_FLASH )
|
|
||||||
opt.reinit = X49GP_REINIT_FLASH;
|
|
||||||
|
|
||||||
if ( opt.firmware != NULL )
|
|
||||||
fprintf( stderr,
|
|
||||||
"Additional firmware file \"%s\" specified,"
|
|
||||||
" overriding\n",
|
|
||||||
optarg );
|
|
||||||
opt.firmware = optarg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/************/
|
|
||||||
/* \OPTIONS */
|
|
||||||
/************/
|
|
||||||
|
|
||||||
void ui_sighnd( int sig )
|
void ui_sighnd( int sig )
|
||||||
{
|
{
|
||||||
switch ( sig ) {
|
switch ( sig ) {
|
||||||
|
@ -367,12 +234,8 @@ void ui_sighnd( int sig )
|
||||||
|
|
||||||
int main( int argc, char** argv )
|
int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
char *progname, *progpath;
|
char* progname = g_path_get_basename( argv[ 0 ] );
|
||||||
int error;
|
char* progpath = g_path_get_dirname( argv[ 0 ] );
|
||||||
const char* home;
|
|
||||||
|
|
||||||
progname = g_path_get_basename( argv[ 0 ] );
|
|
||||||
progpath = g_path_get_dirname( argv[ 0 ] );
|
|
||||||
|
|
||||||
gtk_init( &argc, &argv );
|
gtk_init( &argc, &argv );
|
||||||
|
|
||||||
|
@ -396,7 +259,6 @@ int main( int argc, char** argv )
|
||||||
x49gp->progname = progname;
|
x49gp->progname = progname;
|
||||||
x49gp->progpath = progpath;
|
x49gp->progpath = progpath;
|
||||||
x49gp->clk_tck = sysconf( _SC_CLK_TCK );
|
x49gp->clk_tck = sysconf( _SC_CLK_TCK );
|
||||||
|
|
||||||
x49gp->emulator_fclk = 75000000;
|
x49gp->emulator_fclk = 75000000;
|
||||||
x49gp->PCLK_ratio = 4;
|
x49gp->PCLK_ratio = 4;
|
||||||
x49gp->PCLK = 75000000 / 4;
|
x49gp->PCLK = 75000000 / 4;
|
||||||
|
@ -416,34 +278,23 @@ int main( int argc, char** argv )
|
||||||
x49gp_ui_init( x49gp );
|
x49gp_ui_init( x49gp );
|
||||||
|
|
||||||
x49gp_s3c2410_arm_init( x49gp );
|
x49gp_s3c2410_arm_init( x49gp );
|
||||||
|
|
||||||
x49gp_flash_init( x49gp );
|
x49gp_flash_init( x49gp );
|
||||||
x49gp_sram_init( x49gp );
|
x49gp_sram_init( x49gp );
|
||||||
|
|
||||||
x49gp_s3c2410_init( x49gp );
|
x49gp_s3c2410_init( x49gp );
|
||||||
|
|
||||||
if ( x49gp_modules_init( x49gp ) ) {
|
if ( x49gp_modules_init( x49gp ) )
|
||||||
exit( EXIT_FAILURE );
|
exit( EXIT_FAILURE );
|
||||||
}
|
|
||||||
|
|
||||||
if ( opt.config == NULL ) {
|
|
||||||
char config_dir[ strlen( progname ) + 9 ];
|
|
||||||
|
|
||||||
home = g_get_home_dir();
|
|
||||||
sprintf( config_dir, ".config/%s", progname );
|
|
||||||
opt.config = g_build_filename( home, config_dir, "config", NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
x49gp->basename = g_path_get_dirname( opt.config );
|
x49gp->basename = g_path_get_dirname( opt.config );
|
||||||
x49gp->debug_port = opt.debug_port;
|
x49gp->debug_port = opt.debug_port;
|
||||||
x49gp->startup_reinit = opt.reinit;
|
x49gp->startup_reinit = opt.reinit;
|
||||||
x49gp->firmware = opt.firmware;
|
x49gp->firmware = opt.firmware;
|
||||||
|
|
||||||
error = x49gp_modules_load( x49gp, opt.config );
|
int error = x49gp_modules_load( x49gp, opt.config );
|
||||||
if ( error || opt.reinit >= X49GP_REINIT_REBOOT_ONLY ) {
|
if ( error || opt.reinit >= X49GP_REINIT_REBOOT_ONLY ) {
|
||||||
if ( error && error != -EAGAIN ) {
|
if ( error && error != -EAGAIN )
|
||||||
exit( EXIT_FAILURE );
|
exit( EXIT_FAILURE );
|
||||||
}
|
|
||||||
x49gp_modules_reset( x49gp, X49GP_RESET_POWER_ON );
|
x49gp_modules_reset( x49gp, X49GP_RESET_POWER_ON );
|
||||||
}
|
}
|
||||||
// x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
|
// x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
|
||||||
|
@ -471,7 +322,7 @@ int main( int argc, char** argv )
|
||||||
x49gp_modules_save( x49gp, opt.config );
|
x49gp_modules_save( x49gp, opt.config );
|
||||||
x49gp_modules_exit( x49gp );
|
x49gp_modules_exit( x49gp );
|
||||||
|
|
||||||
#if 0
|
#if false
|
||||||
printf("ClkTicks: %lu\n", ARMul_Time(x49gp->arm));
|
printf("ClkTicks: %lu\n", ARMul_Time(x49gp->arm));
|
||||||
printf("D TLB: hit0 %lu, hit1 %lu, search %lu (%lu), walk %lu\n",
|
printf("D TLB: hit0 %lu, hit1 %lu, search %lu (%lu), walk %lu\n",
|
||||||
x49gp->mmu->dTLB.hit0, x49gp->mmu->dTLB.hit1,
|
x49gp->mmu->dTLB.hit0, x49gp->mmu->dTLB.hit1,
|
||||||
|
|
170
src/options.c
Normal file
170
src/options.c
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
|
#include "gdbstub.h"
|
||||||
|
|
||||||
|
struct options opt;
|
||||||
|
|
||||||
|
void config_init( char* progname, int argc, char* argv[] )
|
||||||
|
{
|
||||||
|
int option_index;
|
||||||
|
int c = '?';
|
||||||
|
|
||||||
|
bool do_enable_debugger = false;
|
||||||
|
bool do_start_debugger = false;
|
||||||
|
bool do_reflash = false;
|
||||||
|
bool do_reflash_full = false;
|
||||||
|
|
||||||
|
opt.config = NULL;
|
||||||
|
opt.debug_port = 0;
|
||||||
|
opt.start_debugger = false;
|
||||||
|
opt.reinit = X49GP_REINIT_NONE;
|
||||||
|
opt.firmware = NULL;
|
||||||
|
opt.model = MODEL_50G;
|
||||||
|
opt.name = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
const char* optstring = "hrc:D:df:Fn:";
|
||||||
|
struct option long_options[] = {
|
||||||
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
|
||||||
|
{"config", required_argument, NULL, 'c'},
|
||||||
|
|
||||||
|
{"enable-debug", required_argument, NULL, 'D'},
|
||||||
|
{"debug", no_argument, NULL, 'd'},
|
||||||
|
{"reflash", required_argument, NULL, 'f'},
|
||||||
|
{"reflash-full", no_argument, NULL, 'F'},
|
||||||
|
{"reboot", no_argument, NULL, 'r'},
|
||||||
|
|
||||||
|
{"50g", no_argument, NULL, 506},
|
||||||
|
{"50g-newrpl", no_argument, NULL, 507},
|
||||||
|
{"49gp", no_argument, NULL, 496},
|
||||||
|
{"49gp-newrpl", no_argument, NULL, 497},
|
||||||
|
{"name", required_argument, NULL, 'n'},
|
||||||
|
|
||||||
|
{0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
while ( c != EOF ) {
|
||||||
|
c = getopt_long( argc, argv, optstring, long_options, &option_index );
|
||||||
|
|
||||||
|
switch ( c ) {
|
||||||
|
case 'h':
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s %i.%i.%i Emulator for HP 49G+ / 50G calculators\n"
|
||||||
|
"Usage: %s [<options>]\n"
|
||||||
|
"Valid options:\n"
|
||||||
|
" -h --help print this message and exit\n"
|
||||||
|
" -c --config[=<filename>] alternate config file\n"
|
||||||
|
" --50g show HP 50g faceplate (default)\n"
|
||||||
|
" --50g-newrpl show HP 50g faceplate with newRPL labels\n"
|
||||||
|
" --49gp show HP 49g+ faceplate\n"
|
||||||
|
" --49gp-newrpl show HP 49g+ faceplate with newRPL labels\n"
|
||||||
|
" -n --name[=<name>] set alternate UI name\n"
|
||||||
|
" -D --enable-debug[=<port>] enable the debugger interface\n"
|
||||||
|
" (default port: %u)\n"
|
||||||
|
" -d --debug use along -D to also start the debugger immediately\n"
|
||||||
|
" -f --reflash[=firmware] rebuild the flash using the supplied firmware\n"
|
||||||
|
" (default: select one interactively)\n"
|
||||||
|
" (implies -r for safety reasons)\n"
|
||||||
|
" -F --reflash-full use along -f to drop the flash contents\n"
|
||||||
|
" in the area beyond the firmware\n"
|
||||||
|
" -r --reboot reboot on startup instead of continuing from the\n"
|
||||||
|
" saved state in the config file\n"
|
||||||
|
"The config file is formatted as INI file and contains the settings for which\n"
|
||||||
|
" persistence makes sense, like calculator model, CPU registers, etc.\n"
|
||||||
|
"If the config file is omitted, ~/.config/%s/config is used.\n"
|
||||||
|
"Please consult the manual for more details on config file settings.\n",
|
||||||
|
progname, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, progname, DEFAULT_GDBSTUB_PORT, progname );
|
||||||
|
exit( EXIT_SUCCESS );
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if ( opt.reinit < X49GP_REINIT_REBOOT_ONLY )
|
||||||
|
opt.reinit = X49GP_REINIT_REBOOT_ONLY;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
opt.config = strdup( optarg );
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
do_enable_debugger = true;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
do_start_debugger = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
do_reflash = true;
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
do_reflash_full = true;
|
||||||
|
break;
|
||||||
|
case 496:
|
||||||
|
opt.model = MODEL_49GP;
|
||||||
|
break;
|
||||||
|
case 497:
|
||||||
|
opt.model = MODEL_49GP_NEWRPL;
|
||||||
|
break;
|
||||||
|
case 506:
|
||||||
|
opt.model = MODEL_50G;
|
||||||
|
break;
|
||||||
|
case 507:
|
||||||
|
opt.model = MODEL_50G_NEWRPL;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
opt.name = strdup( optarg );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( do_enable_debugger ) {
|
||||||
|
char* end;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
if ( optarg == NULL && opt.debug_port == 0 )
|
||||||
|
opt.debug_port = DEFAULT_GDBSTUB_PORT;
|
||||||
|
|
||||||
|
port = strtoul( optarg, &end, 0 );
|
||||||
|
if ( ( end == optarg ) || ( *end != '\0' ) ) {
|
||||||
|
fprintf( stderr, "Invalid port \"%s\", using default\n", optarg );
|
||||||
|
if ( opt.debug_port == 0 )
|
||||||
|
opt.debug_port = DEFAULT_GDBSTUB_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( opt.debug_port != 0 && opt.debug_port != DEFAULT_GDBSTUB_PORT )
|
||||||
|
fprintf( stderr,
|
||||||
|
"Additional debug port \"%s\" specified, overriding\n",
|
||||||
|
optarg );
|
||||||
|
opt.debug_port = port;
|
||||||
|
|
||||||
|
opt.start_debugger = do_start_debugger;
|
||||||
|
}
|
||||||
|
if ( do_reflash ) {
|
||||||
|
if ( opt.reinit < X49GP_REINIT_FLASH )
|
||||||
|
opt.reinit = X49GP_REINIT_FLASH;
|
||||||
|
|
||||||
|
if ( opt.firmware != NULL )
|
||||||
|
fprintf( stderr,
|
||||||
|
"Additional firmware file \"%s\" specified,"
|
||||||
|
" overriding\n",
|
||||||
|
optarg );
|
||||||
|
opt.firmware = optarg;
|
||||||
|
|
||||||
|
if ( do_reflash_full )
|
||||||
|
opt.reinit = X49GP_REINIT_FLASH_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( opt.config == NULL ) {
|
||||||
|
char config_dir[ strlen( progname ) + 9 ];
|
||||||
|
|
||||||
|
const char* home = g_get_home_dir();
|
||||||
|
sprintf( config_dir, ".config/%s", progname );
|
||||||
|
opt.config = g_build_filename( home, config_dir, "config", NULL );
|
||||||
|
}
|
||||||
|
}
|
36
src/options.h
Normal file
36
src/options.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef _CONFIG_H
|
||||||
|
#define _CONFIG_H 1
|
||||||
|
|
||||||
|
#include "x49gp.h"
|
||||||
|
|
||||||
|
#ifndef VERSION_MAJOR
|
||||||
|
# define VERSION_MAJOR 0
|
||||||
|
#endif
|
||||||
|
#ifndef VERSION_MINOR
|
||||||
|
# define VERSION_MINOR 0
|
||||||
|
#endif
|
||||||
|
#ifndef PATCHLEVEL
|
||||||
|
# define PATCHLEVEL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum { MODEL_49GP = 0, MODEL_49GP_NEWRPL, MODEL_50G, MODEL_50G_NEWRPL } x49gpng_model_t;
|
||||||
|
|
||||||
|
struct options {
|
||||||
|
char* config;
|
||||||
|
int debug_port;
|
||||||
|
int start_debugger;
|
||||||
|
char* firmware;
|
||||||
|
x49gp_reinit_t reinit;
|
||||||
|
|
||||||
|
x49gpng_model_t model;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct options opt;
|
||||||
|
|
||||||
|
/*************/
|
||||||
|
/* functions */
|
||||||
|
/*************/
|
||||||
|
extern void config_init( char* progname, int argc, char* argv[] );
|
||||||
|
|
||||||
|
#endif /* !_CONFIG_H */
|
44
src/ui.c
44
src/ui.c
|
@ -19,6 +19,7 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <gdk/gdkkeysyms.h>
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
|
||||||
|
#include "options.h"
|
||||||
#include "x49gp.h"
|
#include "x49gp.h"
|
||||||
#include "x49gp_ui.h"
|
#include "x49gp_ui.h"
|
||||||
#include "s3c2410.h"
|
#include "s3c2410.h"
|
||||||
|
@ -3273,31 +3274,29 @@ static int gui_load( x49gp_module_t* module, GKeyFile* keyfile )
|
||||||
GtkWidget *menu_debug, *menu_reset, *menu_quit;
|
GtkWidget *menu_debug, *menu_reset, *menu_quit;
|
||||||
GError* gerror = NULL;
|
GError* gerror = NULL;
|
||||||
GdkBitmap* shape;
|
GdkBitmap* shape;
|
||||||
char* typestr;
|
|
||||||
char* imagefile;
|
char* imagefile;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
x49gp_module_get_string( module, keyfile, "type", "hp50g", &typestr );
|
switch ( opt.model ) {
|
||||||
if ( !strcmp( typestr, "hp49g+" ) )
|
case MODEL_50G_NEWRPL:
|
||||||
ui->calculator = UI_CALCULATOR_HP49GP;
|
|
||||||
else if ( !strcmp( typestr, "hp49g+/newrpl" ) )
|
|
||||||
ui->calculator = UI_CALCULATOR_HP49GP_NEWRPL;
|
|
||||||
else if ( !strcmp( typestr, "hp50g" ) )
|
|
||||||
ui->calculator = UI_CALCULATOR_HP50G;
|
|
||||||
else if ( !strcmp( typestr, "hp50g/newrpl" ) )
|
|
||||||
ui->calculator = UI_CALCULATOR_HP50G_NEWRPL;
|
ui->calculator = UI_CALCULATOR_HP50G_NEWRPL;
|
||||||
else {
|
ui->name = opt.name != NULL ? opt.name : "HP 50g / newRPL";
|
||||||
fprintf( stderr, "Invalid calculator type, reverting to default\n" );
|
break;
|
||||||
|
case MODEL_49GP:
|
||||||
|
ui->calculator = UI_CALCULATOR_HP49GP;
|
||||||
|
ui->name = opt.name != NULL ? opt.name : "HP 49g+";
|
||||||
|
break;
|
||||||
|
case MODEL_49GP_NEWRPL:
|
||||||
|
ui->calculator = UI_CALCULATOR_HP49GP_NEWRPL;
|
||||||
|
ui->name = "opt.name != NULL ? opt.name : HP 49g+ / newRPL";
|
||||||
|
break;
|
||||||
|
case MODEL_50G:
|
||||||
|
default:
|
||||||
ui->calculator = UI_CALCULATOR_HP50G;
|
ui->calculator = UI_CALCULATOR_HP50G;
|
||||||
|
ui->name = opt.name != NULL ? opt.name : "HP 50g";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
x49gp_module_get_string( module, keyfile, "name",
|
|
||||||
ui->calculator == UI_CALCULATOR_HP49GP ? "HP 49g+"
|
|
||||||
: ui->calculator == UI_CALCULATOR_HP49GP_NEWRPL ? "HP 49g+ / newRPL"
|
|
||||||
: ui->calculator == UI_CALCULATOR_HP50G ? "HP 50g"
|
|
||||||
: "HP 50g / newRPL",
|
|
||||||
&( ui->name ) );
|
|
||||||
|
|
||||||
fd = x49gp_module_open_rodata( module,
|
fd = x49gp_module_open_rodata( module,
|
||||||
ui->calculator == UI_CALCULATOR_HP49GP || ui->calculator == UI_CALCULATOR_HP49GP_NEWRPL
|
ui->calculator == UI_CALCULATOR_HP49GP || ui->calculator == UI_CALCULATOR_HP49GP_NEWRPL
|
||||||
? "hp49g+-cropped.png"
|
? "hp49g+-cropped.png"
|
||||||
|
@ -3508,15 +3507,6 @@ static int gui_load( x49gp_module_t* module, GKeyFile* keyfile )
|
||||||
|
|
||||||
static int gui_save( x49gp_module_t* module, GKeyFile* keyfile )
|
static int gui_save( x49gp_module_t* module, GKeyFile* keyfile )
|
||||||
{
|
{
|
||||||
x49gp_ui_t* ui = module->user_data;
|
|
||||||
|
|
||||||
x49gp_module_set_string( module, keyfile, "type",
|
|
||||||
ui->calculator == UI_CALCULATOR_HP49GP ? "hp49g+"
|
|
||||||
: ui->calculator == UI_CALCULATOR_HP49GP_NEWRPL ? "hp49g+/newrpl"
|
|
||||||
: ui->calculator == UI_CALCULATOR_HP50G ? "hp50g"
|
|
||||||
: "hp50g/newrpl" );
|
|
||||||
x49gp_module_set_string( module, keyfile, "name", ui->name );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#ifndef _X49GP_TIMER_H
|
#ifndef _X49GP_TIMER_H
|
||||||
#define _X49GP_TIMER_H 1
|
#define _X49GP_TIMER_H 1
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "list.h"
|
# include "list.h"
|
||||||
|
#include "x49gp_types.h"
|
||||||
|
|
||||||
#define X49GP_TIMER_VIRTUAL 0
|
#define X49GP_TIMER_VIRTUAL 0
|
||||||
#define X49GP_TIMER_REALTIME 1
|
#define X49GP_TIMER_REALTIME 1
|
||||||
|
|
Loading…
Reference in a new issue