diff --git a/.gitignore b/.gitignore index 6ce57ed..94faf56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,10 @@ -sim/CVS* -*.svn/* *.DS_Store/* .DS_Store .depend *.o *.d -config -flash-49g+ -flash-50g -flash-noboot sdcard -sram x49gp -s3c2410-sram qemu/qemu-git/arm-softmmu qemu/qemu-git/libhw32 qemu/qemu-git/libhw64 diff --git a/Makefile b/Makefile index 850b29f..a0fc466 100644 --- a/Makefile +++ b/Makefile @@ -29,24 +29,16 @@ X49GP_DEBUG = \ -DDEBUG_X49GP_TIMER_IDLE \ -DDEBUG_X49GP_ARM_IDLE \ -DDEBUG_X49GP_ENABLE_IRQ \ + -DDEBUG_X49GP_BLOCK \ + -DDEBUG_X49GP_MAIN \ -DDEBUG_X49GP_UI DEBUG = -g # -pg -#2.09 -#FIRMWARE = 4950_92.bin -#HPGCC3 (copy HPGCC3 ROM first) -#FIRMWARE = 49_hpgcc.bin -#2.15 -#FIRMWARE = 4950_215.bin -#2.15full -FIRMWARE = 2MB_215f.bin - BOOT49GP = boot-49g+.bin BOOT50G = boot-50g.bin -SERIAL49GP = DE00000001 -SERIAL50G = DEA0000001 -COPYRIGHT = Kinposhcopyright +IMAGE49GP = hp49g+.png +IMAGE50G = hp50g.png QEMU_DEFINES = -DTARGET_ARM -DX49GP \ -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ @@ -90,6 +82,13 @@ X49GP_INCLUDES = -Iinclude -Ibitmaps $(QEMU_INC) INCLUDES = $(GDB_INCLUDES) $(X49GP_INCLUDES) +INSTALL_PREFIX = /usr/local +INSTALL_BINARY_DIR = "$(INSTALL_PREFIX)"/bin +INSTALL_DATA_DIR = "$(INSTALL_PREFIX)"/share/$(TARGET) +INSTALL_MENU_DIR = "$(INSTALL_PREFIX)"/share/applications +INSTALL_MAN_DIR = "$(INSTALL_PREFIX)/share/man/man1" +DEFINES += -DX49GP_DATADIR=\"$(INSTALL_DATA_DIR)\" + ifdef QEMU_OLD CC = $(shell if [ "`uname -s`" = "Darwin" ]; then echo "gcc"; else echo "gcc-3.4"; fi) else @@ -103,7 +102,7 @@ CC += $(shell if [ "`uname -m`" = "sparc64" -o "`uname -m`" = "sun4u" ]; then ec COCOA_LIBS=$(shell if [ "`uname -s`" = "Darwin" ]; then echo "-F/System/Library/Frameworks -framework Cocoa -framework IOKit"; fi) -CFLAGS = -O2 -Wall -Werror $(DEBUG) $(INCLUDES) $(DEFINES) -Wno-error=deprecated-declarations +CFLAGS = -O2 -Wall -Werror $(DEBUG) $(INCLUDES) $(DEFINES) LDFLAGS = $(DEBUG) $(X49GP_LDFLAGS) $(GDB_LDFLAGS) LDLIBS = $(X49GP_LIBS) $(GDB_LIBS) $(COCOA_LIBS) @@ -158,12 +157,13 @@ VVFATOBJS += $(QEMU_DIR)/cutils.o endif TARGET = x49gp +TARGET_ALLCAPS = X49GP all: do-it-all ifeq (.depend,$(wildcard .depend)) include .depend -do-it-all: $(QEMU) $(TARGET) flash-49g+ flash-50g sram s3c2410-sram +do-it-all: $(QEMU) $(TARGET) else do-it-all: depend-and-build endif @@ -176,59 +176,20 @@ $(TARGET): $(OBJS) $(VVFATOBJS) $(QEMU_OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(VVFATOBJS) $(LDLIBS) endif -flash-49g+: $(BOOT49GP) flash-noboot - @cp flash-noboot $@ - @/bin/echo -n "$@: Copy boot loader \"$(BOOT49GP)\" to "; echo "0" - @dd if=$(BOOT49GP) of=$@ bs=16 seek=0 conv=notrunc 2>/dev/null - @/bin/echo -n "$@: Set serial number \"$(SERIAL49GP)\" at "; expr 16 \* 1023 - @/bin/echo -n "$(SERIAL49GP)" >serialno - @dd if=serialno of=$@ bs=16 seek=1023 conv=notrunc 2>/dev/null - @rm -f serialno +install: all $(TARGET).desktop $(TARGET).man + install -D -m 755 $(TARGET) "$(INSTALL_BINARY_DIR)/$(TARGET)" + install -D -m 644 $(BOOT49GP) "$(INSTALL_DATA_DIR)/$(BOOT49GP)" + install -D -m 644 $(BOOT50G) "$(INSTALL_DATA_DIR)/$(BOOT50G)" + install -D -m 644 $(IMAGE49GP) "$(INSTALL_DATA_DIR)/$(IMAGE49GP)" + install -D -m 644 $(IMAGE50G) "$(INSTALL_DATA_DIR)/$(IMAGE50G)" + install -D -m 644 $(TARGET).desktop "$(INSTALL_MENU_DIR)/$(TARGET).desktop" + install -D -m 644 $(TARGET).man "$(INSTALL_MAN_DIR)/$(TARGET).1" -flash-50g: $(BOOT50G) flash-noboot - @cp flash-noboot $@ - @/bin/echo -n "$@: Copy boot loader \"$(BOOT50G)\" to "; echo "0" - @dd if=$(BOOT50G) of=$@ bs=16 seek=0 conv=notrunc 2>/dev/null - @/bin/echo -n "$@: Set serial number \"$(SERIAL50G)\" at "; expr 16 \* 1023 - @/bin/echo -n "$(SERIAL50G)" >serialno - @dd if=serialno of=$@ bs=16 seek=1023 conv=notrunc 2>/dev/null - @rm -f serialno +$(TARGET).desktop: x49gp.desktop.in + perl -p -e "s!TARGET!$(TARGET)!" $@ -flash-noboot: $(FIRMWARE) - @/bin/echo -n "$@: Fill ff: 0 " - @/bin/echo -ne "\377" >one - @COUNT=0; \ - SIZE=1; \ - while [ $${COUNT} -le 20 ]; do \ - cat one one >one2; \ - mv one2 one; \ - COUNT=`expr $${COUNT} + 1`; \ - SIZE=`expr $${SIZE} + $${SIZE}`; \ - /bin/echo -n "."; \ - done; \ - echo " $${SIZE}" - @mv one $@ - @/bin/echo -n "$@: Mark blocks:" - @OFFSET=524544; \ - for block in 02 03 04 05 06 07 10 11 12 13 14 15; do \ - /bin/echo -ne "\360\0$${block}\000\000\000" >header; \ - dd if=header of=$@ bs=1 seek=$${OFFSET} conv=notrunc 2>/dev/null; \ - /bin/echo -n " $${OFFSET}"; \ - OFFSET=`expr $${OFFSET} + 131072`; \ - done; \ - echo "" - @/bin/echo -n "$@: Copy firmware \"$(FIRMWARE)\" to "; expr 16 \* 1024 - @dd if=$(FIRMWARE) of=$@ bs=16 seek=1024 conv=notrunc 2>/dev/null - @/bin/echo -n "$@: Set copyright \"$(COPYRIGHT)\" at "; expr 16 \* 1024 - @/bin/echo -n "$(COPYRIGHT)" >copyright - @dd if=copyright of=$@ bs=16 seek=1024 conv=notrunc 2>/dev/null - @rm -f one one2 header copyright - -sram: - dd if=/dev/zero of=$@ bs=1024 count=512 - -s3c2410-sram: - dd if=/dev/zero of=$@ bs=1024 count=4 +$(TARGET).man: x49gp.man.in + perl -p -e "s!TARGET_ALLCAPS!$(TARGET_ALLCAPS)!;" -e "s!TARGET!$(TARGET)!" $@ sdcard: ifeq ($(shell uname),Darwin) @@ -238,9 +199,6 @@ else /sbin/mkdosfs -v -C -S 512 -f 2 -F 16 -r 512 -R 2 -n "x49gp" $@ 65536 endif -config: - ./newconfig - sim: dummy $(MAKE) -C $@ @@ -285,8 +243,7 @@ clean: clean-libs distclean: clean rm -rf $(QEMU) - rm -f $(TARGET) flash-49g+ flash-50g flash-noboot sram s3c2410-sram - rm -f config + rm -f $(TARGET) $(TARGET).desktop $(TARGET).man $(TARGET).man depend-and-build: depend $(MAKE) -C . all @@ -311,8 +268,7 @@ clean: clean-qemu distclean: clean $(MAKE) -C $(QEMU) -f Makefile-small distclean - rm -f $(TARGET) flash-49g+ flash-50g flash-noboot sram s3c2410-sram - rm -f config + rm -f $(TARGET) $(TARGET).desktop $(TARGET).man $(TARGET).man depend-libs: $(QEMU)/config-host.h diff --git a/README b/README deleted file mode 100644 index 1b0456e..0000000 --- a/README +++ /dev/null @@ -1,63 +0,0 @@ -Next steps: - - - Verify Locks needed - - Audit Keyboard <-> IO Port Interaction - - Add remote gdb interface - - -Registers to check access to: - - IO PORT MISCCR - MMU FSR - MMU FAR - MMU Alignment Checks in general - MMU r7: Wait for Interrupt - - -File Manager: - - Read from 0x08080000: Probe memory size??? - -> Add mirrored mapping of SRAM? - - -Annunciators: - - Bits set in Column 132 of the LCD screen memory: - - Row 0: Transmit - Row 1: Left Shift - Row 2: Right Shift - Row 3: Alpha - Row 4: Battery - Row 5: Busy - -IRQ Branch Table: - - 08000020: IRQ reads 08000020 + (IRQOFFSET << 2), branches there - - IRQ returns with "subs pc, lr, #4" - - - -The speed of the emulator is an issue... - -It is running about 20 times SLOWER than the original calculator at the moment -on my 400 MHz UltraSparc. There will be quite some speedup running on a modern -PC or workstation with faster processor. Also, at the moment I have a lot of debugging -enabled, which slows down the emulator. - -Getting the full 75 MHz out of the emulated ARM core will be hard work, I have not -looked into the potential optimizations that can be done in the core emulator, but -there are some things done during every instruction that we don't need for this -machine. - -There are generally two options to speed up or use the emulator: - -1. Emulate the hardware as closely as possible to help debug programms digging - into the s3c2410. -2. Emulate the saturn part to make it a usable calculator. Here one could implement - some of the most often used KOS syscalls directly in the emulator without doing - these on the emulated ARM core. This would speed up the calculator significantly. - -Optimally there will be a runtime option to switch between these two modes. - diff --git a/README.QEMU b/README.QEMU deleted file mode 100644 index 40777dc..0000000 --- a/README.QEMU +++ /dev/null @@ -1 +0,0 @@ -Fix ldX_le/stX_le on sparc: use ASI_LE diff --git a/README.config b/README.config deleted file mode 100644 index 1719a90..0000000 --- a/README.config +++ /dev/null @@ -1,11 +0,0 @@ -[x49gp] -basename=.x49gp -[x49gp] -name=hp49g+ -image=hp49g+.png -[flash] -filename=flash -[sram] -filename=sram -[s3c2410-sram] -filename=s3c2410-sram diff --git a/README.md b/README.md index d778396..b47d48e 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@ Prereqs: sudo yum install git gtk2-devel ``` +* Arch: + +``` + sudo pacman -S git gtk2 +``` + ------------------------------------------------------------------------ Start up X11 and use xterm @@ -43,71 +49,19 @@ git clone https://github.com/chwdt/x49gp.git ------------------------------------------------------------------------ -Edit FIRMWARE (optional): - -The default firmware will be 4950_92.bin, for HPGCC3 development copy -49_hpgcc.bin in to x49gp and change FIRMWARE in the Makefile. - ------------------------------------------------------------------------- - Build: ``` cd x49gp make -make sdcard -make config ``` ------------------------------------------------------------------------ -Mount SD card: - -OS/X: +Install (optional): ``` -open sdcard.dmg -``` - -Linux: - -``` -sudo mkdir -p /Volumes/X49GP/ -sudo mount -o loop sdcard /Volumes/X49GP -``` - ------------------------------------------------------------------------- - -Put stuff in SD, e.g.: - -OS/X: - -``` -cp BACKUP /Volumes/X49GP/ -``` - -Linux: - -``` -sudo cp BACKUP /Volumes/X49GP/ -``` - -NOTE: If using HPGCC2 don't forget the ARMToolbox. - ------------------------------------------------------------------------- - -Eject SD: - -OS/X: - -``` -hdiutil detach $(df | grep -i x49gp | head -1 | awk '{print $1}') -``` - -Linux: - -``` -sudo umount /Volumes/X49GP +make install ``` ------------------------------------------------------------------------ @@ -115,9 +69,46 @@ sudo umount /Volumes/X49GP Run: ``` -./x49gp config +./x49gp ``` +When installed, there should be an applications menu entry to run x49gp. +Installing also enables running it from the terminal in any directory: + +``` +x49gp +``` + +------------------------------------------------------------------------ + +First launch setup + +On the first launch, the calculator will be missing a firmware, forcing +the bootloader to complain and demand a fresh one. +HP's official firmwares can be found at e.g.: +https://www.hpcalc.org/hp49/pc/rom/ +Some of the most popular of these are also included in x49gp's source +directory. +Alternatively, the most up-to-date version of NewRPL can be found at: +https://hpgcc3.org/downloads/newrplfw.bin + +Pick a firmware to use and store it in any directory along with its +update.scp file. The update.scp file only contains the filename of the +firmware (when renaming the firmware, make sure the new name fits into +a DOS-style 8.3 naming scheme) followed by a DOS-style linebreak, so a +missing update.scp can be rectified easily. + +Right click on the screen, or press the menu key on a physical keyboard, +to open the menu, and click on "Mount SD folder". +Select the directory containing the firmware. Then, select the SD option +from the bootloader's update source menu by clicking on the virtual key +labeled "2" or by pressing the "2" key on a physical keyboard. + +Now the bootloader is installing the firmware; wait until it finishes +printing hex numbers to the virtual display, then follow its prompt to +press Reset ( = F12 or the Reset entry in the menu) or Enter. +The calculator should be fully usable after this procedure. + ------------------------------------------------------------------------ Do stuff, e.g.: @@ -147,7 +138,14 @@ EVAL To Exit Emulator -* ctrl-c to exit (from launch window) +Use any of: + +* Press Alt-F4 or your system's equivalent key combination + +* Open the menu using a right click on the screen or the menu key, then +choose "Quit" + +* Press Ctrl-C in the launch terminal ------------------------------------------------------------------------ @@ -156,15 +154,26 @@ Start Over: * clean slate? ``` -rm -f flash-49g+ flash-50g flash-noboot sram s3c2410-sram -make flash-49g+ flash-50g flash-noboot sram s3c2410-sram -./newconfig +rm -r ~/.x49gp ``` * soft reset only? +With x49gp running, press F12, or right click on the screen and select +"Reset" from the menu. + +------------------------------------------------------------------------ + +Debugging with x49gp + +There is a GDB interface for debugging ARM programs, e.g. HPGCC2/3 +applications or replacement firmwares. To use it, start x49gp from a +terminal with the -d option, and start arm-none-eabi-gdb with an +appropriate ELF file in another terminal. To connect to x49gp, type in +the GDB console: + ``` -./newconfig +target remote :1234 ``` ------------------------------------------------------------------------ @@ -177,12 +186,3 @@ Known Limitations: - `f*` calls stable (HPGCC3) ------------------------------------------------------------------------ - -Change Log: - -Additional note: August 22, 2013 - -Updated this so that it'll compile on Ubuntu 12.04. - ---Nicholas Kirchner - diff --git a/bitmaps/CVS/Entries b/bitmaps/CVS/Entries deleted file mode 100644 index e32251f..0000000 --- a/bitmaps/CVS/Entries +++ /dev/null @@ -1,91 +0,0 @@ -/ann_alpha.xbm/1.4/Thu Dec 11 12:14:08 2008// -/ann_battery.xbm/1.4/Thu Dec 11 12:14:08 2008// -/ann_busy.xbm/1.4/Thu Dec 11 12:14:08 2008// -/ann_io.xbm/1.4/Thu Dec 11 12:14:08 2008// -/ann_left.xbm/1.4/Thu Dec 11 12:14:08 2008// -/ann_right.xbm/1.4/Thu Dec 11 12:14:08 2008// -/button_large.xbm/1.4/Thu Dec 11 12:14:08 2008// -/button_normal.xbm/1.4/Thu Dec 11 12:14:08 2008// -/button_round.pix/1.1/Wed Jul 12 11:30:39 2006// -/button_round.xbm/1.4/Thu Dec 11 12:14:08 2008// -/button_small.xbm/1.4/Thu Dec 11 12:14:08 2008// -/button_tiny.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_A.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_B.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_C.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_D.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_E.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_F.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_G.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_H.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_I.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_J.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_K.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_L.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_M.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_N.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_O.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_P.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_Q.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_R.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_S.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_T.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_U.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_V.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_W.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_X.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_Y.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_Z.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny__i.xbm/1.1/Thu Dec 11 12:19:15 2008// -/tiny_ampersand.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_arrowleft.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_arrowright.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_braceleft.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_braceright.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_bracketleft.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_bracketright.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_colon.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_comma.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_equal.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_greater.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_guillemotleft.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_guillemotright.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_hyphen.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_large_comma.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_less.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_arrowleft.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_arrowright.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_downarrowleft.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_downarrowright.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_e.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_equal.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_greater.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_greaterequal.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_infinity.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_integral.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_less.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_lessequal.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_notequal.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_numbersign.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_partialdiff.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_pi.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_radical.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_summation.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_x.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_math_y.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_notdef.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_numbersign.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_one.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_overscore.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_parenleft.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_parenright.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_period.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_quotedbl.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_slash.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_three.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_two.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_twosuperior.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_underscore.xbm/1.5/Thu Dec 11 12:14:08 2008// -/tiny_xsuperior.xbm/1.4/Thu Dec 11 12:14:08 2008// -/tiny_zero.xbm/1.4/Thu Dec 11 12:14:08 2008// -D diff --git a/bitmaps/CVS/Repository b/bitmaps/CVS/Repository deleted file mode 100644 index a01358d..0000000 --- a/bitmaps/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -x49gp/bitmaps diff --git a/bitmaps/CVS/Root b/bitmaps/CVS/Root deleted file mode 100644 index 6f29e94..0000000 --- a/bitmaps/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:pserver:anonymous@x49gp.cvs.sourceforge.net:/cvsroot/x49gp diff --git a/block-vvfat.c b/block-vvfat.c index 33a610b..3864a67 100644 --- a/block-vvfat.c +++ b/block-vvfat.c @@ -47,7 +47,7 @@ file system (test if the boot sector still relies on that fact)! */ /* MAYBE TODO: write block-visofs.c */ -#define DEBUG +//#define DEBUG #undef DEBUG_SECTORS #ifdef DEBUG diff --git a/block.c b/block.c index 4d5a7cf..3148d7a 100644 --- a/block.c +++ b/block.c @@ -156,14 +156,24 @@ find_protocol(const char *filename) memcpy(protocol, filename, len); protocol[len] = '\0'; for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { -fprintf(stderr, "%s:%u: protocol '%s', drv->protocol_name '%s'\n", __FUNCTION__, __LINE__, protocol, drv1->protocol_name); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, + "%s:%u: protocol '%s', drv->protocol_name '%s'\n", + __FUNCTION__, __LINE__, protocol, drv1->protocol_name); +#endif if (drv1->protocol_name && !strcmp(drv1->protocol_name, protocol)) { -fprintf(stderr, "%s:%u: protocol '%s', drv %p\n", __FUNCTION__, __LINE__, protocol, drv1); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: protocol '%s', drv %p\n", + __FUNCTION__, __LINE__, protocol, drv1); +#endif return drv1; } } -fprintf(stderr, "%s:%u: protocol '%s', NULL\n", __FUNCTION__, __LINE__, protocol); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: protocol '%s', NULL\n", + __FUNCTION__, __LINE__, protocol); +#endif return NULL; } @@ -276,8 +286,10 @@ bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) { BlockDriverState *bs; int ret; - -fprintf(stderr, "%s:%u: filename '%s'\n", __FUNCTION__, __LINE__, filename); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: filename '%s'\n", + __FUNCTION__, __LINE__, filename); +#endif bs = bdrv_new(""); if (!bs) @@ -285,11 +297,16 @@ fprintf(stderr, "%s:%u: filename '%s'\n", __FUNCTION__, __LINE__, filename); ret = bdrv_open(bs, filename, flags | BDRV_O_FILE); if (ret < 0) { bdrv_delete(bs); -fprintf(stderr, "%s:%u: '%s': %d\n", __FUNCTION__, __LINE__, filename, ret); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: '%s': %d\n", + __FUNCTION__, __LINE__, filename, ret); +#endif return ret; } *pbs = bs; -fprintf(stderr, "%s:%u: return 0\n", __FUNCTION__, __LINE__); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: return 0\n", __FUNCTION__, __LINE__); +#endif return 0; } @@ -300,7 +317,10 @@ bdrv_open(BlockDriverState *bs, const char *filename, int flags) char backing_filename[1024]; BlockDriver *drv = NULL; -fprintf(stderr, "%s:%u: filename '%s'\n", __FUNCTION__, __LINE__, filename); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: filename '%s'\n", + __FUNCTION__, __LINE__, filename); +#endif bs->read_only = 0; bs->is_temporary = 0; @@ -310,24 +330,34 @@ fprintf(stderr, "%s:%u: filename '%s'\n", __FUNCTION__, __LINE__, filename); if (flags & BDRV_O_FILE) { drv = find_protocol(filename); if (!drv) { -fprintf(stderr, "%s:%u: drv: %p\n", __FUNCTION__, __LINE__, drv); +#ifdef DEBUG_X49GP_BLOCK +f printf(stderr, "%s:%u: drv: %p\n", + __FUNCTION__, __LINE__, drv); +#endif return -ENOENT; } } else { if (!drv) { drv = find_image_format(filename); if (!drv) { -fprintf(stderr, "%s:%u: drv: %p\n", __FUNCTION__, __LINE__, drv); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: drv: %p\n", + __FUNCTION__, __LINE__, drv); +#endif return -1; } } } -fprintf(stderr, "%s:%u: drv: %p\n", __FUNCTION__, __LINE__, drv); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: drv: %p\n", __FUNCTION__, __LINE__, drv); +#endif bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); if (bs->opaque == NULL && drv->instance_size > 0) { -fprintf(stderr, "%s:%u: no opaque\n", __FUNCTION__, __LINE__); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: no opaque\n", __FUNCTION__, __LINE__); +#endif return -1; } /* Note: for compatibility, we open disk image files as RDWR, and @@ -337,7 +367,10 @@ fprintf(stderr, "%s:%u: no opaque\n", __FUNCTION__, __LINE__); else open_flags = flags & ~(BDRV_O_FILE); ret = drv->bdrv_open(bs, filename, open_flags); -fprintf(stderr, "%s:%u: drv->bdrv_open: %d\n", __FUNCTION__, __LINE__, ret); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: drv->bdrv_open: %d\n", + __FUNCTION__, __LINE__, ret); +#endif if (ret == -EACCES && !(flags & BDRV_O_FILE)) { ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY); bs->read_only = 1; @@ -346,7 +379,10 @@ fprintf(stderr, "%s:%u: drv->bdrv_open: %d\n", __FUNCTION__, __LINE__, ret); qemu_free(bs->opaque); bs->opaque = NULL; bs->drv = NULL; -fprintf(stderr, "%s:%u: return %d\n", __FUNCTION__, __LINE__, ret); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: return %d\n", + __FUNCTION__, __LINE__, ret); +#endif return ret; } if (drv->bdrv_getlength) { @@ -363,15 +399,27 @@ fprintf(stderr, "%s:%u: return %d\n", __FUNCTION__, __LINE__, ret); if (!bs->backing_hd) { fail: bdrv_close(bs); -fprintf(stderr, "%s:%u: return -ENOMEM\n", __FUNCTION__, __LINE__); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: return -ENOMEM\n", + __FUNCTION__, __LINE__); +#endif return -ENOMEM; } -fprintf(stderr, "%s:%u: combine '%s' '%s'\n", __FUNCTION__, __LINE__, filename, bs->backing_file); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: combine '%s' '%s'\n", + __FUNCTION__, __LINE__, filename, bs->backing_file); +#endif path_combine(backing_filename, sizeof(backing_filename), filename, bs->backing_file); -fprintf(stderr, "%s:%u: combine: '%s'\n", __FUNCTION__, __LINE__, backing_filename); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: combine: '%s'\n", + __FUNCTION__, __LINE__, backing_filename); +#endif if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0) { -fprintf(stderr, "%s:%u: backing fail\n", __FUNCTION__, __LINE__); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: backing fail\n", + __FUNCTION__, __LINE__); +#endif goto fail; } } @@ -381,7 +429,9 @@ fprintf(stderr, "%s:%u: backing fail\n", __FUNCTION__, __LINE__); if (bs->change_cb) bs->change_cb(bs->change_opaque); -fprintf(stderr, "%s:%u: return 0\n", __FUNCTION__, __LINE__); +#ifdef DEBUG_X49GP_BLOCK + fprintf(stderr, "%s:%u: return 0\n", __FUNCTION__, __LINE__); +#endif return 0; } diff --git a/config.tmpl b/config.tmpl deleted file mode 100644 index d7ac773..0000000 --- a/config.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -[x49gp] -basename= -[gui] -name=hp50g -image=hp50g.png -[flash] -filename=flash-50g -[sram] -filename=sram -[s3c2410-sram] -filename=s3c2410-sram -[s3c2410-sdi] -filename=sdcard.dmg diff --git a/flash.c b/flash.c index 3aab061..8ca4dac 100644 --- a/flash.c +++ b/flash.c @@ -9,7 +9,12 @@ #include #include +#include +#include +#include + #include +#include #include #include @@ -40,6 +45,7 @@ typedef struct { uint32_t cfi_size; uint32_t sector_size; uint32_t block_size; + char *filename; int fd; size_t size; @@ -54,6 +60,8 @@ typedef struct { #define SST29VF160_BLOCK_SIZE 0x00010000 #define SST29VF160_SIZE 0x00200000 +#define BOOT_SIZE 0x00004000 + static const unsigned short sst29vf160_cfi_data[] = { [0x10] = 0x0051, @@ -460,48 +468,113 @@ static int flash_load(x49gp_module_t *module, GKeyFile *key) { x49gp_flash_t *flash = module->user_data; + x49gp_t *x49gp = module->x49gp; + x49gp_ui_t *ui = x49gp->ui; + int calc = ui->calculator; char *filename; + struct stat st; + char *bootfile; + int bootfd; + int error; #ifdef DEBUG_X49GP_MODULES printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif - filename = x49gp_module_get_filename(module, key, "filename"); - if (NULL == filename) { - fprintf(stderr, "%s: %s:%u: key \"filename\" not found\n", - module->name, __FUNCTION__, __LINE__); - return -1; - } + error = x49gp_module_get_filename(module, key, "filename", "flash", + &(flash->filename), &filename); - flash->fd = open(filename, O_RDWR); + flash->fd = open(filename, O_RDWR | O_CREAT, 0644); if (flash->fd < 0) { + error = -errno; fprintf(stderr, "%s: %s:%u: open %s: %s\n", module->name, __FUNCTION__, __LINE__, filename, strerror(errno)); g_free(filename); - return -1; + return error; } - flash->data = mmap(phys_ram_base + flash->offset, SST29VF160_SIZE, + flash->size = SST29VF160_SIZE; + if (fstat(flash->fd, &st) < 0) { + error = -errno; + fprintf(stderr, "%s: %s:%u: fstat %s: %s\n", + module->name, __FUNCTION__, __LINE__, + filename, strerror(errno)); + g_free(filename); + close(flash->fd); + flash->fd = -1; + return error; + } + + if (ftruncate(flash->fd, flash->size) < 0) { + error = -errno; + fprintf(stderr, "%s: %s:%u: ftruncate %s: %s\n", + module->name, __FUNCTION__, __LINE__, + filename, strerror(errno)); + g_free(filename); + close(flash->fd); + flash->fd = -1; + return error; + } + + flash->data = mmap(phys_ram_base + flash->offset, flash->size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, flash->fd, 0); if (flash->data == (void *) -1) { + error = -errno; fprintf(stderr, "%s: %s:%u: mmap %s: %s\n", module->name, __FUNCTION__, __LINE__, filename, strerror(errno)); g_free(filename); close(flash->fd); flash->fd = -1; - return -1; + return error; } - flash->size = SST29VF160_SIZE; g_free(filename); - return 0; + + + if (flash->size > st.st_size) { + fprintf(stderr, "Flash too small, rebuilding\n"); + + memset(phys_ram_base + flash->offset + st.st_size, + 0xFF, flash->size - st.st_size); + + bootfd = x49gp_module_open_rodata(module, + calc == UI_CALCULATOR_HP49GP ? + "boot-49g+.bin" : + "boot-50g.bin", + &bootfile); + + if (bootfd < 0) { + g_free(filename); + close(flash->fd); + flash->fd = -1; + return bootfd; + } + + if (read(bootfd, phys_ram_base + flash->offset, + BOOT_SIZE) < 0) { + error = -errno; + fprintf(stderr, "%s: %s:%u: read %s: %s\n", + module->name, __FUNCTION__, __LINE__, + filename, strerror(errno)); + g_free(bootfile); + close(bootfd); + close(flash->fd); + flash->fd = -1; + return error; + } + + close(bootfd); + g_free(bootfile); + } + + return error; } static int -flash_save(x49gp_module_t *module, GKeyFile *config) +flash_save(x49gp_module_t *module, GKeyFile *key) { x49gp_flash_t *flash = module->user_data; int error; @@ -510,6 +583,8 @@ flash_save(x49gp_module_t *module, GKeyFile *config) printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif + x49gp_module_set_filename(module, key, "filename", flash->filename); + error = msync(flash->data, flash->size, MS_ASYNC); if (error) { fprintf(stderr, "%s:%u: msync: %s\n", diff --git a/gdbstub.c b/gdbstub.c index 78ec755..4158bc4 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -455,8 +455,10 @@ static void gdb_read_byte(GDBState *s, int ch) int i, csum; char reply[1]; -//printf("%s: state %u, byte %02x (%c)\n", __FUNCTION__, s->state, ch, ch); +#ifdef DEBUG_GDB +printf("%s: state %u, byte %02x (%c)\n", __FUNCTION__, s->state, ch, ch); fflush(stdout); +#endif switch(s->state) { case RS_IDLE: @@ -515,8 +517,10 @@ gdb_handlesig (CPUState *env, int sig) s = &gdbserver_state; -//printf("%s: sig: %u\n", __FUNCTION__, sig); +#ifdef DEBUG_GDB +printf("%s: sig: %u\n", __FUNCTION__, sig); fflush(stdout); +#endif /* disable single step if it was enabled */ cpu_single_step(env, 0); @@ -537,8 +541,10 @@ fflush(stdout); { int i; -//printf("%s: read: %d\n", __FUNCTION__, n); +#ifdef DEBUG_GDB +printf("%s: read: %d\n", __FUNCTION__, n); fflush(stdout); +#endif for (i = 0; i < n; i++) gdb_read_byte (s, buf[i]); @@ -547,6 +553,7 @@ fflush(stdout); { /* XXX: Connection closed. Should probably wait for annother connection before continuing. */ + gdbserver_fd = -1; return sig; } } @@ -573,8 +580,10 @@ gdb_poll (CPUState *env) return 0; } -//printf("%s: revents: %08x\n", __FUNCTION__, pfd.revents); +#ifdef DEBUG_GDB +printf("%s: revents: %08x\n", __FUNCTION__, pfd.revents); fflush(stdout); +#endif if (pfd.revents & (POLLIN | POLLHUP)) return 1; @@ -628,6 +637,10 @@ static void gdb_accept(void *opaque) gdb_syscall_state = s; fcntl(fd, F_SETFL, O_NONBLOCK); + + /* When the debugger is connected, stop accepting connections */ + /* to free the port up for other concurrent instances. */ + close(gdbserver_fd); } static int gdbserver_open(int port) @@ -663,6 +676,9 @@ static int gdbserver_open(int port) int gdbserver_start(int port) { + if (gdbserver_fd >= 0) + return -1; + gdbserver_fd = gdbserver_open(port); if (gdbserver_fd < 0) return -1; @@ -670,3 +686,8 @@ int gdbserver_start(int port) gdb_accept (NULL); return 0; } + +int gdbserver_isactive() +{ + return (gdbserver_fd >= 0); +} diff --git a/gdbstub.h b/gdbstub.h index b3330e5..9ca7af1 100644 --- a/gdbstub.h +++ b/gdbstub.h @@ -15,4 +15,6 @@ int gdb_handlesig (CPUState *, int); void gdb_exit(CPUState *, int); int gdbserver_start(int); +int gdbserver_isactive(); + #endif diff --git a/include/CVS/Entries b/include/CVS/Entries deleted file mode 100644 index 9e08e9f..0000000 --- a/include/CVS/Entries +++ /dev/null @@ -1,18 +0,0 @@ -/bitmap_font.h/1.5/Thu Dec 11 12:18:17 2008// -/bitmaps.h/1.9/Thu Dec 11 12:18:17 2008// -/block.h/1.1/Thu Dec 11 12:18:17 2008// -/byteorder.h/1.5/Thu Dec 11 12:18:17 2008// -/glyphname.h/1.3/Thu Dec 11 12:18:17 2008// -/list.h/1.5/Thu Dec 11 12:18:17 2008// -/s3c2410.h/1.18/Thu Dec 11 12:18:17 2008// -/s3c2410_intc.h/1.3/Thu Dec 11 12:18:17 2008// -/s3c2410_mmu.h/1.3/Thu Dec 11 12:18:17 2008// -/s3c2410_power.h/1.3/Thu Dec 11 12:18:17 2008// -/s3c2410_timer.h/1.3/Thu Dec 11 12:18:17 2008// -/saturn.h/1.1/Thu Dec 11 12:18:17 2008// -/symbol.h/1.4/Thu Dec 11 12:18:17 2008// -/x49gp.h/1.15/Thu Dec 11 12:18:17 2008// -/x49gp_timer.h/1.3/Thu Dec 11 12:18:17 2008// -/x49gp_types.h/1.5/Thu Dec 11 12:18:17 2008// -/x49gp_ui.h/1.14/Thu Dec 11 12:18:17 2008// -D diff --git a/include/CVS/Repository b/include/CVS/Repository deleted file mode 100644 index 9500df1..0000000 --- a/include/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -x49gp/include diff --git a/include/CVS/Root b/include/CVS/Root deleted file mode 100644 index 6f29e94..0000000 --- a/include/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:pserver:anonymous@x49gp.cvs.sourceforge.net:/cvsroot/x49gp diff --git a/include/s3c2410.h b/include/s3c2410.h index 4be61ab..e06ab49 100644 --- a/include/s3c2410.h +++ b/include/s3c2410.h @@ -336,7 +336,7 @@ extern int x49gp_s3c2410_adc_init(x49gp_t *x49gp); extern int x49gp_s3c2410_spi_init(x49gp_t *x49gp); extern int x49gp_s3c2410_sdi_init(x49gp_t *x49gp); -extern void s3c2410_io_port_g_update(x49gp_t *x49gp); +extern void s3c2410_io_port_g_update(x49gp_t *x49gp, int column, int row, unsigned char columnbit, unsigned char rowbit, uint32_t new_state); extern void s3c2410_io_port_f_set_bit(x49gp_t *x49gp, int n, uint32_t set); extern void x49gp_schedule_lcd_update(x49gp_t *x49gp); diff --git a/include/x49gp.h b/include/x49gp.h index 6739281..e2e09d4 100644 --- a/include/x49gp.h +++ b/include/x49gp.h @@ -67,6 +67,7 @@ struct __x49gp_s__ { void *s3c2410_watchdog; void *s3c2410_intc; void *s3c2410_io_port; + void *s3c2410_sdi; void *timer; uint8_t *sram; @@ -95,6 +96,9 @@ struct __x49gp_s__ { GKeyFile *config; const char *progname; + const char *progpath; + const char *basename; + int debug_port; }; extern void x49gp_set_idle(x49gp_t *, x49gp_arm_idle_t idle); @@ -110,8 +114,11 @@ extern int x49gp_module_init(x49gp_t *x49gp, const char *name, extern int x49gp_module_register(x49gp_module_t *module); extern int x49gp_module_unregister(x49gp_module_t *module); -extern char *x49gp_module_get_filename(x49gp_module_t *module, GKeyFile *, - const char *key); +extern int x49gp_module_get_filename(x49gp_module_t *module, GKeyFile *, + const char *, char *, char **, + char **); +extern int x49gp_module_set_filename(x49gp_module_t *module, GKeyFile *, + const char *, const char *); extern int x49gp_module_get_int(x49gp_module_t *module, GKeyFile *, const char *, int, int *); extern int x49gp_module_set_int(x49gp_module_t *module, GKeyFile *, @@ -131,6 +138,15 @@ extern int x49gp_module_set_u64(x49gp_module_t *module, GKeyFile *, const char *, uint64_t); extern int x49gp_module_get_string(x49gp_module_t *module, GKeyFile *, const char *, char *, char **); +extern int x49gp_module_set_string(x49gp_module_t *module, GKeyFile *, + const char *, const char *); +extern int x49gp_module_open_rodata(x49gp_module_t *module, + const char *name, + char **path); + +extern void s3c2410_sdi_unmount(x49gp_t *x49gp); +extern int s3c2410_sdi_mount(x49gp_t *x49gp, char *filename); +extern int s3c2410_sdi_is_mounted(x49gp_t *x49gp); extern int x49gp_modules_init(x49gp_t *); extern int x49gp_modules_exit(x49gp_t *); diff --git a/include/x49gp_ui.h b/include/x49gp_ui.h index b242531..dcaf777 100644 --- a/include/x49gp_ui.h +++ b/include/x49gp_ui.h @@ -93,6 +93,9 @@ typedef struct { struct __x49gp_ui_s__ { GtkWidget *window; GtkWidget *fixed; + GtkWidget *menu; + GtkWidget *menu_unmount; + GtkWidget *menu_debug; GdkPixbuf *bg_pixbuf; GdkPixmap *bg_pixmap; @@ -105,6 +108,9 @@ struct __x49gp_ui_s__ { x49gp_ui_button_t *buttons; unsigned int nr_buttons; + unsigned int buttons_down; + + char *name; GtkWidget *lcd_canvas; GdkPixmap *lcd_pixmap; diff --git a/main.c b/main.c index 1bd6a2f..0c106b8 100644 --- a/main.c +++ b/main.c @@ -25,14 +25,6 @@ #include "gdbstub.h" -static void *oom_check(void *ptr) -{ - if (ptr == NULL) { - abort(); - } - return ptr; -} - static x49gp_t *x49gp; #ifdef QEMU_OLD // LD TEMPO HACK @@ -51,6 +43,16 @@ ram_addr_t ram_size = 0x80000; // LD ??? /* vl.c */ int singlestep; +#if !(defined(__APPLE__) || defined(_POSIX_C_SOURCE) && !defined(__sun__)) +static void *oom_check(void *ptr) +{ + if (ptr == NULL) { + abort(); + } + return ptr; +} +#endif + void *qemu_memalign(size_t alignment, size_t size) { #if defined(__APPLE__) || defined(_POSIX_C_SOURCE) && !defined(__sun__) @@ -293,12 +295,252 @@ x49gp_lcd_timer(void *data) x49gp_mod_timer(x49gp->lcd_timer, expires); } +struct options { + char *config; + int debug_port; + int start_debugger; + + int more_options; +}; + +struct option_def; + +typedef int (*option_action)(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname); + +struct option_def { + option_action action; + char *longname; + char shortname; +}; + +static int action_help(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname); +static int action_debuglater(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname); +static int action_debug(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname); + +static int action_unknown_with_param(struct options *opt, + struct option_def *match, char *this_opt, + char *param, char *progname); +static int action_longopt(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname); +static int action_endopt(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname); + +struct option_def option_defs[] = { + { action_help, "help", 'h' }, + { action_debuglater, "enable-debug", 'D' }, + { action_debug, "debug", 'd' }, + + { action_longopt, NULL, '-' }, + { action_unknown_with_param, NULL, '=' }, + { action_endopt, "", '\0' } +}; + static void -usage(const char *progname) +warn_unneeded_param(struct option_def *match, char *this_opt) { - fprintf(stderr, "usage: %s \n", - progname); - exit(1); + if (this_opt[1] == '-') { + fprintf(stderr, "The option \"--%s\" does not support" + " parameters\n", match->longname); + } else + fprintf(stderr, "The option '-%c' does not support parameters\n", + match->shortname); +} + +static int +action_help(struct options *opt, struct option_def *match, char *this_opt, + char *param, char *progname) +{ + if (param != NULL) + warn_unneeded_param(match, this_opt); + + fprintf(stderr, "Emulator for HP 49G+ / 50G calculators\n" + "Usage: %s [] []\n" + "Valid options:\n" + " -D, --enable-debug[=] like -D, but also start the" + " debugger immediately\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, ~/.%s/config is used.\n" + "Please consult the manual for more details on config file" + " settings.\n", progname, DEFAULT_GDBSTUB_PORT, progname); + exit(0); +} + +static int +action_debuglater(struct options *opt, struct option_def *match, char *this_opt, + char *param, char *progname) +{ + char *end; + int port; + + if (param == NULL) { + if (opt->debug_port == 0) + opt->debug_port = DEFAULT_GDBSTUB_PORT; + return FALSE; + } + + port = strtoul(param, &end, 0); + if ((end == param) || (*end != '\0')) { + fprintf(stderr, "Invalid port \"%s\", using default\n", param); + if (opt->debug_port == 0) + opt->debug_port = DEFAULT_GDBSTUB_PORT; + return TRUE; + } + + if (opt->debug_port != 0 && opt->debug_port != DEFAULT_GDBSTUB_PORT) + fprintf(stderr, "Additional debug port \"%s\" specified," + " overriding\n", param); + opt->debug_port = port; + return TRUE; +} + +static int +action_debug(struct options *opt, struct option_def *match, char *this_opt, + char *param, char *progname) +{ + opt->start_debugger = TRUE; + return action_debuglater(opt, match, this_opt, param, progname); +} + +static int +action_longopt(struct options *opt, struct option_def *match, char *this_opt, + char *param, char *progname) +{ + int i; + char *test_str, *option_str; + + if (this_opt[1] != '-' || param != NULL) { + fprintf(stderr, "Unrecognized option '-', ignoring\n"); + return FALSE; + } + + for (i = 0; i < sizeof(option_defs) / sizeof(option_defs[0]); i++) { + if (option_defs[i].longname == NULL) + continue; + + test_str = option_defs[i].longname; + option_str = this_opt + 2; + + while (*test_str != '\0' && *test_str == *option_str) { + test_str++; + option_str++; + } + + if (*test_str != '\0') continue; + + switch (*option_str) { + case '\0': + (option_defs[i].action)(opt, option_defs + i, this_opt, + NULL, progname); + return TRUE; + case '=': + (option_defs[i].action)(opt, option_defs + i, this_opt, + option_str+2, progname); + return TRUE; + } + } + + fprintf(stderr, "Unrecognized option \"%s\", ignoring\n", this_opt + 2); + return TRUE; +} + +static int +action_unknown_with_param(struct options *opt, struct option_def *match, + char *this_opt, char *param, char *progname) +{ + return TRUE; +} + +static int +action_endopt(struct options *opt, struct option_def *match, char *this_opt, + char *param, char *progname) +{ + opt->more_options = FALSE; + return TRUE; +} + +static void +parse_shortopt(struct options *opt, char *this_opt, char *progname) +{ + char *option = this_opt + 1; + char *param; + int i; + + if (*option == '\0') { + fprintf(stderr, + "Empty option present, ignoring\n"); + return; + } + + do { + for (i = 0; i < sizeof(option_defs) / sizeof(option_defs[0]); + i++) { + + if (*option == option_defs[i].shortname) { + if (*(option + 1) == '=') { + param = option + 2; + } else { + param = NULL; + } + + if ((option_defs[i].action)(opt, option_defs + i, + this_opt, param, + progname)) + return; + break; + } + } + + + if (i == sizeof(option_defs) / sizeof(option_defs[0])) + fprintf(stderr, + "Unrecognized option '%c', ignoring\n", + *option); + option++; + } while (*option != '\0'); +} + +static void +parse_options(struct options *opt, int argc, char **argv, char *progname) +{ + opt->more_options = TRUE; + + while (argc > 1) { + switch (argv[1][0]) { + case '\0': + break; + break; + + case '-': + if (opt->more_options) { + parse_shortopt(opt, argv[1], progname); + break; + } + /* FALL THROUGH */ + + default: + if (opt->config != NULL) { + fprintf(stderr, + "Additional config file \"%s\"" + " specified, overriding\n", + argv[1]); + } + opt->config = argv[1]; + } + + argc--; + argv++; + } + } void @@ -321,22 +563,23 @@ ui_sighnd(int sig) int main(int argc, char **argv) { - char *progname; + char *progname, *progpath; int error; + struct options opt; + const char *home; - progname = strrchr(argv[0], '/'); - if (progname) - progname++; - else - progname = argv[0]; + progname = g_path_get_basename(argv[0]); + progpath = g_path_get_dirname(argv[0]); gtk_init(&argc, &argv); - if (argc < 2) - usage(progname); + opt.config = NULL; + opt.debug_port = 0; + opt.start_debugger = FALSE; + parse_options(&opt, argc, argv, progname); x49gp = malloc(sizeof(x49gp_t)); if (NULL == x49gp) { @@ -346,14 +589,17 @@ main(int argc, char **argv) } memset(x49gp, 0, sizeof(x49gp_t)); -fprintf(stderr, "_SC_PAGE_SIZE: %08lx\n", sysconf(_SC_PAGE_SIZE)); +#ifdef DEBUG_X49GP_MAIN + fprintf(stderr, "_SC_PAGE_SIZE: %08lx\n", sysconf(_SC_PAGE_SIZE)); -printf("%s:%u: x49gp: %p\n", __FUNCTION__, __LINE__, x49gp); + printf("%s:%u: x49gp: %p\n", __FUNCTION__, __LINE__, x49gp); +#endif INIT_LIST_HEAD(&x49gp->modules); x49gp->progname = progname; + x49gp->progpath = progpath; x49gp->clk_tck = sysconf(_SC_CLK_TCK); x49gp->emulator_fclk = 75000000; @@ -391,7 +637,19 @@ printf("%s:%u: x49gp: %p\n", __FUNCTION__, __LINE__, x49gp); exit(1); } - error = x49gp_modules_load(x49gp, argv[argc-1]); + if (opt.config == NULL) { + char config_dir[strlen(progname) + 2]; + + home = g_get_home_dir(); + sprintf(config_dir, ".%s", progname); + opt.config = g_build_filename(home, config_dir, + "config", NULL); + } + + x49gp->basename = g_path_get_dirname(opt.config); + x49gp->debug_port = opt.debug_port; + + error = x49gp_modules_load(x49gp, opt.config); if (error) { if (error != -EAGAIN) { exit(1); @@ -416,17 +674,15 @@ printf("%s:%u: x49gp: %p\n", __FUNCTION__, __LINE__, x49gp); x49gp_mod_timer(x49gp->lcd_timer, x49gp_get_clock()); - if(argc>=3) { - if((argv[1][0]=='-')&&(argv[1][1]=='d')&&(argv[1][2]==0)) { - gdbserver_start(1234); - gdb_handlesig(x49gp->env, 0); - } - } + if(opt.debug_port != 0 && opt.start_debugger) { + gdbserver_start(opt.debug_port); + gdb_handlesig(x49gp->env, 0); + } x49gp_main_loop(x49gp); - x49gp_modules_save(x49gp, argv[argc-1]); + x49gp_modules_save(x49gp, opt.config); x49gp_modules_exit(x49gp); diff --git a/module.c b/module.c index 80be789..4e1a3b1 100644 --- a/module.c +++ b/module.c @@ -37,7 +37,9 @@ x49gp_modules_init(x49gp_t *x49gp) exit(1); } -printf("%s: phys_ram_base: %p\n", __FUNCTION__, phys_ram_base); +#ifdef DEBUG_X49GP_MODULES + printf("%s: phys_ram_base: %p\n", __FUNCTION__, phys_ram_base); +#endif phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS); memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS); @@ -103,6 +105,13 @@ x49gp_modules_load(x49gp_t *x49gp, const char *filename) printf("%s:%u:\n", __FUNCTION__, __LINE__); #endif + if (g_mkdir_with_parents(x49gp->basename, 0755)) { + error = -errno; + fprintf(stderr, "%s:%u: g_mkdir_with_parents: %s\n", + __FUNCTION__, __LINE__, strerror(errno)); + return error; + } + x49gp->config = g_key_file_new(); if (NULL == x49gp->config) { fprintf(stderr, "%s:%u: g_key_file_new: Out of memory\n", @@ -110,7 +119,9 @@ x49gp_modules_load(x49gp_t *x49gp, const char *filename) return -ENOMEM; } - if (! g_key_file_load_from_file(x49gp->config, filename, 0, &gerror)) { + if (! g_key_file_load_from_file(x49gp->config, filename, + G_KEY_FILE_KEEP_COMMENTS, &gerror) + && ! g_error_matches(gerror, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { fprintf(stderr, "%s:%u: g_key_file_load_from_file: %s\n", __FUNCTION__, __LINE__, gerror->message); g_key_file_free(x49gp->config); @@ -133,16 +144,18 @@ x49gp_modules_load(x49gp_t *x49gp, const char *filename) { extern unsigned char *phys_ram_base; -printf("%s: phys_ram_base: %p\n", __FUNCTION__, phys_ram_base); -printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", - phys_ram_base[0], - phys_ram_base[1], - phys_ram_base[2], - phys_ram_base[3], - phys_ram_base[4], - phys_ram_base[5], - phys_ram_base[6], - phys_ram_base[7]); +#ifdef DEBUG_X49GP_MODULES + printf("%s: phys_ram_base: %p\n", __FUNCTION__, phys_ram_base); + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + phys_ram_base[0], + phys_ram_base[1], + phys_ram_base[2], + phys_ram_base[3], + phys_ram_base[4], + phys_ram_base[5], + phys_ram_base[6], + phys_ram_base[7]); +#endif } return result; @@ -176,7 +189,7 @@ x49gp_modules_save(x49gp_t *x49gp, const char *filename) return -ENOMEM; } - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { error = -errno; fprintf(stderr, "%s:%u: open %s: %s\n", @@ -227,60 +240,45 @@ x49gp_module_unregister(x49gp_module_t *module) return 0; } -char * +int x49gp_module_get_filename(x49gp_module_t *module, GKeyFile *key, - const char *name) + const char *name, char *reset, char **valuep, + char **path) { - char *filename; - char *basename; - const char *home; - char *path; + x49gp_t *x49gp = module->x49gp; + int error; - filename = g_key_file_get_string(key, module->name, name, NULL); - if (NULL == filename) { - fprintf(stderr, "%s: %s:%u: key \"%s\" not found\n", - module->name, __FUNCTION__, __LINE__, name); - return NULL; + error = x49gp_module_get_string(module, key, name, reset, valuep); + + if (g_path_is_absolute(*valuep)) { + *path = g_strdup(*valuep); + return error; } - if (g_path_is_absolute(filename)) { - return filename; - } - - home = g_get_home_dir(); - - basename = g_key_file_get_string(key, "x49gp", "basename", NULL); - if (NULL == basename) { - fprintf(stderr, "%s: %s:%u: key \"basename\" not found\n", - "x49gp", __FUNCTION__, __LINE__); - g_free(filename); - return NULL; - } - - path = g_build_filename(home, basename, filename, NULL); + *path = g_build_filename(x49gp->basename, *valuep, NULL); if (NULL == path) { fprintf(stderr, "%s: %s:%u: Out of memory\n", module->name, __FUNCTION__, __LINE__); + g_free(*valuep); + *valuep = NULL; } - g_free(filename); - g_free(basename); + return error; +} - return path; +int +x49gp_module_set_filename(x49gp_module_t *module, GKeyFile *key, + const char *name, const char *value) +{ + return x49gp_module_set_string(module, key, name, value); } int x49gp_module_get_int(x49gp_module_t *module, GKeyFile *key, const char *name, int reset, int *valuep) { - uint32_t value; - int error; - - error = x49gp_module_get_u32(module, key, name, reset, &value); - if (0 == error) { - *valuep = value; - } - return error; + return x49gp_module_get_u32(module, key, name, reset, + (uint32_t *) valuep); } int @@ -411,7 +409,7 @@ x49gp_module_get_string(x49gp_module_t *module, GKeyFile *key, if (NULL == data) { fprintf(stderr, "%s: %s:%u: key \"%s\" not found\n", module->name, __FUNCTION__, __LINE__, name); - *valuep = strdup(reset); + *valuep = g_strdup(reset); return -EAGAIN; } @@ -419,6 +417,59 @@ x49gp_module_get_string(x49gp_module_t *module, GKeyFile *key, return 0; } +int x49gp_module_set_string(x49gp_module_t *module, GKeyFile *key, + const char *name, const char *value) +{ + g_key_file_set_value(key, module->name, name, value); + + return 0; +} + +int +x49gp_module_open_rodata(x49gp_module_t *module, const char *name, + char **path) +{ + x49gp_t *x49gp = module->x49gp; + int fd; + int error; + + *path = g_build_filename(x49gp->progpath, name, NULL); + if (NULL == *path) { + fprintf(stderr, "%s: %s:%u: Out of memory\n", + module->name, __FUNCTION__, __LINE__); + return -ENOMEM; + } + + fd = open(*path, O_RDONLY); + +#ifdef X49GP_DATADIR + if (fd < 0 && (errno == EACCES || errno == ENOENT)) { + g_free(*path); + + *path = g_build_filename(X49GP_DATADIR, name, NULL); + if (NULL == *path) { + fprintf(stderr, "%s: %s:%u: Out of memory\n", + module->name, __FUNCTION__, __LINE__); + return -ENOMEM; + } + + fd = open(*path, O_RDONLY); + } +#endif + + if (fd < 0) { + error = -errno; + fprintf(stderr, "%s: %s:%u: open %s: %s\n", + module->name, __FUNCTION__, __LINE__, + *path, strerror(errno)); + g_free(*path); + *path = NULL; + return error; + } + + return fd; +} + int x49gp_module_init(x49gp_t *x49gp, const char *name, int (*init)(x49gp_module_t *), diff --git a/newconfig b/newconfig deleted file mode 100755 index 50a0e01..0000000 --- a/newconfig +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -if [ ! -r "config.tmpl" ] -then - echo "Cannot read config.tmpl" >&2 - exit 1 -fi - -B=${PWD##$HOME/} -perl -p -e "s!^(basename=).*!\1$B!" config - -if [ "$(uname -s)" = "Linux" ] -then - perl -p -e "s!^(filename=sdcard).dmg!\1!" config -fi - -echo "New config created" -exit 0 diff --git a/qemu/.cvsignore b/qemu/.cvsignore deleted file mode 100644 index 1750fe8..0000000 --- a/qemu/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -qemu diff --git a/qemu/CVS/Entries b/qemu/CVS/Entries deleted file mode 100644 index bab072d..0000000 --- a/qemu/CVS/Entries +++ /dev/null @@ -1,4 +0,0 @@ -/.cvsignore/1.1/Thu Dec 11 12:22:06 2008// -/prepare.sh/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.9.0.tar.gz/1.1/Thu Dec 11 12:14:08 2008// -D/patches//// diff --git a/qemu/CVS/Repository b/qemu/CVS/Repository deleted file mode 100644 index 1275b0c..0000000 --- a/qemu/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -x49gp/qemu diff --git a/qemu/CVS/Root b/qemu/CVS/Root deleted file mode 100644 index 6f29e94..0000000 --- a/qemu/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:pserver:anonymous@x49gp.cvs.sourceforge.net:/cvsroot/x49gp diff --git a/qemu/patches/CVS/Entries b/qemu/patches/CVS/Entries deleted file mode 100644 index 3a2dc7e..0000000 --- a/qemu/patches/CVS/Entries +++ /dev/null @@ -1,27 +0,0 @@ -/q_block.c_hdled_1.diff/1.1/Thu Dec 11 12:14:08 2008// -/q_block_int.h_hdled_1.diff/1.1/Thu Dec 11 12:14:08 2008// -/q_host-cocoa_02.diff/1.1/Thu Dec 11 12:14:08 2008// -/q_vga.c_02.diff/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.7.2-dyngen-check-stack-clobbers.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.7.2-gcc4-opts.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.8.0-gcc4-hacks.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.8.0-osx-bugfix.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.9.0-arm-shift.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.9.0-enforce-16byte-stack-boundary.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.9.0-gcc4.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.9.0-i386-FORCE_RET.patch/1.1/Thu Dec 11 12:14:08 2008// -/qemu-0.9.0-osx-intel-port.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-qcow2.diff/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-sparc-clobber.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-sparc-compile-flags.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-sparc-load-store-le.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-sparc-register.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-arm-dump-state.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-arm-mmu.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-arm-semihosting.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-block.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-build-libqemu.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-debug-unassigned.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-0.9.0-x49gp-phys_ram_dirty.patch/1.1/Thu Dec 11 12:14:09 2008// -/qemu-2ndbootdevice_04.diff/1.1/Thu Dec 11 12:14:09 2008// -D diff --git a/qemu/patches/CVS/Repository b/qemu/patches/CVS/Repository deleted file mode 100644 index 2413c0a..0000000 --- a/qemu/patches/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -x49gp/qemu/patches diff --git a/qemu/patches/CVS/Root b/qemu/patches/CVS/Root deleted file mode 100644 index 6f29e94..0000000 --- a/qemu/patches/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:pserver:anonymous@x49gp.cvs.sourceforge.net:/cvsroot/x49gp diff --git a/s3c2410_adc.c b/s3c2410_adc.c index 30c2815..c8ccd9d 100644 --- a/s3c2410_adc.c +++ b/s3c2410_adc.c @@ -223,7 +223,9 @@ s3c2410_adc_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_adc_readfn, s3c2410_adc_writefn, adc); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_ADC + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_ADC_BASE, S3C2410_MAP_SIZE, iotype); return 0; diff --git a/s3c2410_intc.c b/s3c2410_intc.c index 29d6d8e..209a475 100644 --- a/s3c2410_intc.c +++ b/s3c2410_intc.c @@ -707,7 +707,9 @@ s3c2410_intc_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_intc_readfn, s3c2410_intc_writefn, intc); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_INTC + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_INTC_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_io_port.c b/s3c2410_io_port.c index c857c99..8ef29ab 100644 --- a/s3c2410_io_port.c +++ b/s3c2410_io_port.c @@ -248,8 +248,7 @@ s3c2410_io_port_read(void *opaque, target_phys_addr_t offset) break; case S3C2410_IO_PORT_GPGDAT: - *(reg->datap) = s3c2410_scan_keys(io->x49gp, io->gpgcon, *(reg->datap)); - break; + return s3c2410_scan_keys(io->x49gp, io->gpgcon, io->gpgdat); case S3C2410_IO_PORT_GPHDAT: if (0 == ((io->gphcon >> 14) & 3)) { @@ -356,16 +355,25 @@ static uint32_t lcd_data = 0; } void -s3c2410_io_port_g_update(x49gp_t *x49gp) +s3c2410_io_port_g_update(x49gp_t *x49gp, int column, int row, unsigned char columnbit, unsigned char rowbit, uint32_t new_state) { s3c2410_io_port_t *io = x49gp->s3c2410_io_port; - uint32_t oldvalue, change; + uint32_t oldvalue, newvalue, change; int n; - oldvalue=io->gpgdat; - io->gpgdat = s3c2410_scan_keys(x49gp, io->gpgcon, io->gpgdat); + oldvalue = s3c2410_scan_keys(x49gp, io->gpgcon, io->gpgdat); - change=io->gpgdat^oldvalue; + if (new_state) { + x49gp->keybycol[column] |= rowbit; + x49gp->keybyrow[row] |= columnbit; + + } else { + x49gp->keybycol[column] &= ~rowbit; + x49gp->keybyrow[row] &= ~columnbit; + } + + newvalue = s3c2410_scan_keys(x49gp, io->gpgcon, io->gpgdat); + change=newvalue^oldvalue; for(n=0;n<15;++n) { @@ -374,11 +382,12 @@ s3c2410_io_port_g_update(x49gp_t *x49gp) case 2: /* Interrupt */ { - if(n+8<=15) { - // EINT 8-15 - switch ((io->extint1 >> (4 * n)) & 7) { + switch (n+8<=15 ? + (io->extint1 >> (4 * n)) & 7 : // EINT 8-15 + (io->extint2 >> (4 * (n-8))) & 7 // EINT 16-23 + ) { case 0: /* Low Level */ - if (!(io->gpgdat & (1 << n))) + if (!(newvalue & (1 << n))) { io->eintpend |= 1 << (n + 8); if (io->eintpend & ~(io->eintmask)) @@ -386,7 +395,7 @@ s3c2410_io_port_g_update(x49gp_t *x49gp) } break; case 1: /* High Level */ - if (io->gpgdat & (1 << n)) { + if (newvalue & (1 << n)) { io->eintpend |= 1 << (n + 8); if (io->eintpend & ~(io->eintmask)) s3c2410_intc_assert(x49gp, EINT8_23, 1); @@ -394,7 +403,7 @@ s3c2410_io_port_g_update(x49gp_t *x49gp) break; case 2: /* Falling Edge */ case 3: - if ((change & (1 << n)) && !(io->gpgdat & (1 << n))) { + if ((change & (1 << n)) && !(newvalue & (1 << n))) { io->eintpend |= 1 << (n + 8); if (io->eintpend & ~(io->eintmask)) s3c2410_intc_assert(x49gp, EINT8_23, 1); @@ -402,7 +411,7 @@ s3c2410_io_port_g_update(x49gp_t *x49gp) break; case 4: /* Rising Edge */ case 5: - if ((change & (1 << n)) && (io->gpgdat & (1 << n))) { + if ((change & (1 << n)) && (newvalue & (1 << n))) { io->eintpend |= 1 << (n + 8); if (io->eintpend & ~(io->eintmask)) s3c2410_intc_assert(x49gp, EINT8_23, 1); @@ -416,53 +425,6 @@ s3c2410_io_port_g_update(x49gp_t *x49gp) s3c2410_intc_assert(x49gp, EINT8_23, 1); } break; - } - } - else { - // EINT 16-23 - switch ((io->extint2 >> (4 * (n-8))) & 7) { - case 0: /* Low Level */ - if (!(io->gpgdat & (1 << n))) - { - io->eintpend |= 1 << (n + 8); - if (io->eintpend & ~(io->eintmask)) - s3c2410_intc_assert(x49gp, EINT8_23, 1); - } - break; - case 1: /* High Level */ - if (io->gpgdat & (1 << n)) { - io->eintpend |= 1 << (n + 8); - if (io->eintpend & ~(io->eintmask)) - s3c2410_intc_assert(x49gp, EINT8_23, 1); - } - break; - case 2: /* Falling Edge */ - case 3: - if ((change & (1 << n)) && !(io->gpgdat & (1 << n))) { - io->eintpend |= 1 << (n + 8); - if (io->eintpend & ~(io->eintmask)) - s3c2410_intc_assert(x49gp, EINT8_23, 1); - } - break; - case 4: /* Rising Edge */ - case 5: - if ((change & (1 << n)) && (io->gpgdat & (1 << n))) { - io->eintpend |= 1 << (n + 8); - if (io->eintpend & ~(io->eintmask)) - s3c2410_intc_assert(x49gp, EINT8_23, 1); - } - break; - case 6: /* Any Edge */ - case 7: - if (change & (1 << n)) { - io->eintpend |= 1 << (n + 8); - if (io->eintpend & ~(io->eintmask)) - s3c2410_intc_assert(x49gp, EINT8_23, 1); - } - break; - } - - } } @@ -701,7 +663,9 @@ s3c2410_io_port_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_io_port_readfn, s3c2410_io_port_writefn, io); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_IO_PORT + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_IO_PORT_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_lcd.c b/s3c2410_lcd.c index bdc7e1a..ac8c6c9 100644 --- a/s3c2410_lcd.c +++ b/s3c2410_lcd.c @@ -110,7 +110,7 @@ x49gp_get_pixel_color(s3c2410_lcd_t *lcd, int x, int y) case 1: return 15 * data; case 2: - return 15 & (lcd->bluelut >> (2 * data)); + return 15 & (lcd->bluelut >> (4 * data)); default: return data; } @@ -375,7 +375,9 @@ s3c2410_lcd_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_lcd_readfn, s3c2410_lcd_writefn, lcd); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_LCD + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_LCD_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_memc.c b/s3c2410_memc.c index 149dd3f..1e6de60 100644 --- a/s3c2410_memc.c +++ b/s3c2410_memc.c @@ -237,7 +237,9 @@ s3c2410_memc_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_memc_readfn, s3c2410_memc_writefn, memc); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_MEMC + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_MEMC_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_nand.c b/s3c2410_nand.c index 42c4c3f..36363be 100644 --- a/s3c2410_nand.c +++ b/s3c2410_nand.c @@ -218,7 +218,9 @@ s3c2410_nand_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_nand_readfn, s3c2410_nand_writefn, nand); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_NAND + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_NAND_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_power.c b/s3c2410_power.c index 228dd83..3f1d6e0 100644 --- a/s3c2410_power.c +++ b/s3c2410_power.c @@ -329,7 +329,9 @@ s3c2410_power_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_power_readfn, s3c2410_power_writefn, power); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_POWER + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_POWER_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_rtc.c b/s3c2410_rtc.c index 7360761..a02ff87 100644 --- a/s3c2410_rtc.c +++ b/s3c2410_rtc.c @@ -465,7 +465,9 @@ s3c2410_rtc_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_rtc_readfn, s3c2410_rtc_writefn, rtc); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_RTC + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_RTC_BASE, S3C2410_MAP_SIZE, iotype); return 0; diff --git a/s3c2410_sdi.c b/s3c2410_sdi.c index c5fd667..da3bb93 100644 --- a/s3c2410_sdi.c +++ b/s3c2410_sdi.c @@ -39,6 +39,7 @@ typedef struct { x49gp_t *x49gp; + char *filename; BlockDriverState *bs; int fd; @@ -525,15 +526,89 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data) } } +void +s3c2410_sdi_unmount(x49gp_t *x49gp) +{ + s3c2410_sdi_t *sdi = x49gp->s3c2410_sdi; + + if (sdi->bs) { + bdrv_delete(sdi->bs); + sdi->bs = NULL; + } + + if (sdi->fd >= 0) { + close(sdi->fd); + sdi->fd = -1; + } + + g_free(sdi->filename); + sdi->filename = g_strdup(""); + + s3c2410_io_port_f_set_bit(x49gp, 3, 0); +} + +int +s3c2410_sdi_mount(x49gp_t *x49gp, char *filename) +{ + s3c2410_sdi_t *sdi = x49gp->s3c2410_sdi; + struct stat st; + char vvfat_name[1024]; + int error = 0; + + s3c2410_sdi_unmount(x49gp); + g_free(sdi->filename); + sdi->filename = filename; + + if (strcmp(filename, "") && (stat(filename, &st) == 0)) { + if (S_ISDIR(st.st_mode)) { + sprintf(vvfat_name, "fat:rw:16:%s", filename); + sdi->bs = bdrv_new(""); + if (sdi->bs) { + error = bdrv_open(sdi->bs, vvfat_name, 0); + if (error != 0) { + fprintf(stderr, + "%s:%u: bdrv_open %s: %d\n", + __FUNCTION__, __LINE__, + vvfat_name, error); + bdrv_delete(sdi->bs); + sdi->bs = NULL; + } + } + } else { + sdi->fd = open(filename, O_RDWR); + if (sdi->fd < 0) { + fprintf(stderr, "%s:%u: open %s: %s\n", + __FUNCTION__, __LINE__, filename, + strerror(errno)); + } + } + } + + if ((sdi->bs != NULL) || (sdi->fd >= 0)) { + s3c2410_io_port_f_set_bit(x49gp, 3, 1); + } else { + s3c2410_io_port_f_set_bit(x49gp, 3, 0); + } + + return error; +} + +int +s3c2410_sdi_is_mounted(x49gp_t *x49gp) +{ + s3c2410_sdi_t *sdi = x49gp->s3c2410_sdi; + + return (sdi->bs != NULL) || (sdi->fd >= 0); +} + static int s3c2410_sdi_load(x49gp_module_t *module, GKeyFile *key) { + x49gp_t *x49gp = module->x49gp; s3c2410_sdi_t *sdi = module->user_data; s3c2410_offset_t *reg; - char *filename; - char vvfat_name[1024]; - struct stat st; - int error = 0; + char *filename, *filepath; + int error, error2; int i; #ifdef DEBUG_X49GP_MODULES @@ -542,32 +617,18 @@ s3c2410_sdi_load(x49gp_module_t *module, GKeyFile *key) sdi->fd = -1; sdi->bs = NULL; + sdi->filename = NULL; - filename = x49gp_module_get_filename(module, key, "filename"); - if (filename && (stat(filename, &st) == 0)) { - if (S_ISDIR(st.st_mode)) { - sprintf(vvfat_name, "fat:rw:16:%s", filename); - sdi->bs = bdrv_new(""); - if (sdi->bs) { - error = bdrv_open(sdi->bs, vvfat_name, 0); - fprintf(stderr, "%s:%u: bdrv_open(%s): %d\n", - __FUNCTION__, __LINE__, vvfat_name, error); - if (error != 0) { - bdrv_delete(sdi->bs); - sdi->bs = NULL; - } - } - } else { - sdi->fd = open(filename, O_RDWR); - } - g_free(filename); - } - - if ((sdi->bs != NULL) || (sdi->fd >= 0)) { - s3c2410_io_port_f_set_bit(sdi->x49gp, 3, 1); + error = x49gp_module_get_filename(module, key, "filename", "", + &filename, &filepath); + if (strcmp(filename, "")) { + error2 = s3c2410_sdi_mount(x49gp, filepath); + if (0 == error) error = error2; } else { - s3c2410_io_port_f_set_bit(sdi->x49gp, 3, 0); + s3c2410_sdi_unmount(x49gp); } + g_free(sdi->filename); + sdi->filename = filename; for (i = 0; i < sdi->nr_regs; i++) { reg = &sdi->regs[i]; @@ -594,6 +655,8 @@ s3c2410_sdi_save(x49gp_module_t *module, GKeyFile *key) printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif + x49gp_module_set_filename(module, key, "filename", sdi->filename); + for (i = 0; i < sdi->nr_regs; i++) { reg = &sdi->regs[i]; @@ -665,6 +728,7 @@ s3c2410_sdi_init(x49gp_module_t *module) } module->user_data = sdi; + module->x49gp->s3c2410_sdi = sdi; sdi->x49gp = module->x49gp; #ifdef QEMU_OLD @@ -674,7 +738,9 @@ s3c2410_sdi_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_sdi_readfn, s3c2410_sdi_writefn, sdi); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_SDI + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_SDI_BASE, S3C2410_MAP_SIZE, iotype); bdrv_init(); diff --git a/s3c2410_spi.c b/s3c2410_spi.c index f4626ee..b18a71a 100644 --- a/s3c2410_spi.c +++ b/s3c2410_spi.c @@ -256,7 +256,9 @@ s3c2410_spi_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_spi_readfn, s3c2410_spi_writefn, spi); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_SPI + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_SPI_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_sram.c b/s3c2410_sram.c index 5fc2c01..376bda3 100644 --- a/s3c2410_sram.c +++ b/s3c2410_sram.c @@ -15,6 +15,7 @@ typedef struct { void *data; + char *filename; int fd; uint32_t offset; size_t size; @@ -31,14 +32,11 @@ s3c2410_sram_load(x49gp_module_t *module, GKeyFile *key) printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif - filename = x49gp_module_get_filename(module, key, "filename"); - if (NULL == filename) { - fprintf(stderr, "%s: %s:%u: key \"filename\" not found\n", - module->name, __FUNCTION__, __LINE__); - return -ENOENT; - } + error = x49gp_module_get_filename(module, key, "filename", + "s3c2410-sram", &(filemap->filename), + &filename); - filemap->fd = open(filename, O_RDWR); + filemap->fd = open(filename, O_RDWR | O_CREAT, 0644); if (filemap->fd < 0) { error = -errno; fprintf(stderr, "%s: %s:%u: open %s: %s\n", @@ -48,7 +46,19 @@ s3c2410_sram_load(x49gp_module_t *module, GKeyFile *key) return error; } - filemap->data = mmap(phys_ram_base + filemap->offset, S3C2410_SRAM_SIZE, + filemap->size = S3C2410_SRAM_SIZE; + if (ftruncate(filemap->fd, filemap->size) < 0) { + error = -errno; + fprintf(stderr, "%s: %s:%u: ftruncate %s: %s\n", + module->name, __FUNCTION__, __LINE__, + filename, strerror(errno)); + g_free(filename); + close(filemap->fd); + filemap->fd = -1; + return error; + } + + filemap->data = mmap(phys_ram_base + filemap->offset, filemap->size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, filemap->fd, 0); if (filemap->data == (void *) -1) { @@ -61,12 +71,11 @@ s3c2410_sram_load(x49gp_module_t *module, GKeyFile *key) filemap->fd = -1; return error; } - filemap->size = S3C2410_SRAM_SIZE; g_free(filename); x49gp_schedule_lcd_update(module->x49gp); - return 0; + return error; } static int @@ -79,6 +88,8 @@ s3c2410_sram_save(x49gp_module_t *module, GKeyFile *key) printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif + x49gp_module_set_filename(module, key, "filename", filemap->filename); + error = msync(filemap->data, filemap->size, MS_ASYNC); if (error) { fprintf(stderr, "%s:%u: msync: %s\n", diff --git a/s3c2410_timer.c b/s3c2410_timer.c index 8c19352..69e90b0 100644 --- a/s3c2410_timer.c +++ b/s3c2410_timer.c @@ -522,7 +522,9 @@ s3c2410_timer_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_timer_readfn, s3c2410_timer_writefn, timer); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_TIMER + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_TIMER_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_uart.c b/s3c2410_uart.c index 4e34582..ff4cf2e 100644 --- a/s3c2410_uart.c +++ b/s3c2410_uart.c @@ -388,7 +388,9 @@ s3c2410_uart_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_uart_readfn, s3c2410_uart_writefn, uart_regs); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_UART + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_UART0_BASE, S3C2410_MAP_SIZE, iotype); return 0; diff --git a/s3c2410_usbdev.c b/s3c2410_usbdev.c index 62368b6..97a060c 100644 --- a/s3c2410_usbdev.c +++ b/s3c2410_usbdev.c @@ -296,7 +296,9 @@ s3c2410_usbdev_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_usbdev_readfn, s3c2410_usbdev_writefn, usbdev); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_USBDEV + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_USBDEV_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/s3c2410_watchdog.c b/s3c2410_watchdog.c index f8e48fc..93eb1be 100644 --- a/s3c2410_watchdog.c +++ b/s3c2410_watchdog.c @@ -342,7 +342,9 @@ s3c2410_watchdog_init(x49gp_module_t *module) iotype = cpu_register_io_memory(s3c2410_watchdog_readfn, s3c2410_watchdog_writefn, watchdog); #endif -printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#ifdef DEBUG_S3C2410_WATCHDOG + printf("%s: iotype %08x\n", __FUNCTION__, iotype); +#endif cpu_register_physical_memory(S3C2410_WATCHDOG_BASE, S3C2410_MAP_SIZE, iotype); return 0; } diff --git a/sim/.cvsignore b/sim/.cvsignore deleted file mode 100644 index 4671378..0000000 --- a/sim/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -.depend diff --git a/sim/CVS/Entries b/sim/CVS/Entries deleted file mode 100644 index abd9e8e..0000000 --- a/sim/CVS/Entries +++ /dev/null @@ -1,2 +0,0 @@ -/.cvsignore/1.1/Thu Jun 8 05:41:42 2006// -D diff --git a/sim/CVS/Repository b/sim/CVS/Repository deleted file mode 100644 index 0374a59..0000000 --- a/sim/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -x49gp/sim diff --git a/sim/CVS/Root b/sim/CVS/Root deleted file mode 100644 index 6f29e94..0000000 --- a/sim/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:pserver:anonymous@x49gp.cvs.sourceforge.net:/cvsroot/x49gp diff --git a/sram.c b/sram.c index 842425f..91243d7 100644 --- a/sram.c +++ b/sram.c @@ -18,6 +18,7 @@ typedef struct { void *data; void *shadow; + char *filename; int fd; size_t size; uint32_t offset; @@ -611,14 +612,10 @@ sram_load(x49gp_module_t *module, GKeyFile *key) printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif - filename = x49gp_module_get_filename(module, key, "filename"); - if (NULL == filename) { - fprintf(stderr, "%s: %s:%u: key \"filename\" not found\n", - module->name, __FUNCTION__, __LINE__); - return -ENOENT; - } + error = x49gp_module_get_filename(module, key, "filename", "sram", + &(sram->filename), &filename); - sram->fd = open(filename, O_RDWR); + sram->fd = open(filename, O_RDWR | O_CREAT, 0644); if (sram->fd < 0) { error = -errno; fprintf(stderr, "%s: %s:%u: open %s: %s\n", @@ -629,6 +626,16 @@ sram_load(x49gp_module_t *module, GKeyFile *key) } sram->size = 0x00080000; + if (ftruncate(sram->fd, sram->size) < 0) { + error = -errno; + fprintf(stderr, "%s: %s:%u: ftruncate %s: %s\n", + module->name, __FUNCTION__, __LINE__, + filename, strerror(errno)); + g_free(filename); + close(sram->fd); + sram->fd = -1; + return error; + } sram->data = mmap(phys_ram_base + sram->offset, sram->size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, @@ -662,7 +669,7 @@ sram_load(x49gp_module_t *module, GKeyFile *key) sram->x49gp->sram = phys_ram_base + sram->offset; g_free(filename); - return 0; + return error; } static int @@ -675,6 +682,8 @@ sram_save(x49gp_module_t *module, GKeyFile *key) printf("%s: %s:%u\n", module->name, __FUNCTION__, __LINE__); #endif + x49gp_module_set_filename(module, key, "filename", sram->filename); + error = msync(sram->data, sram->size, MS_ASYNC); if (error) { fprintf(stderr, "%s:%u: msync: %s\n", diff --git a/timer.c b/timer.c index 4221700..aa3c7d4 100644 --- a/timer.c +++ b/timer.c @@ -20,6 +20,8 @@ #include +#include "gdbstub.h" + typedef struct { long type; } x49gp_clock_t; @@ -278,6 +280,7 @@ printf("PC %08x: SRAM %08x: %08x %08x %08x <%08x>\n", x49gp->env->regs[15], 0x08 if (ret == EXCP_DEBUG) { gdb_handlesig(x49gp->env, SIGTRAP); + continue; } if (x49gp->arm_idle != prev_idle) { diff --git a/ui.c b/ui.c index 36296e5..2694432 100644 --- a/ui.c +++ b/ui.c @@ -11,6 +11,7 @@ #include #include #include +#include /* For ntohl() */ #include #include @@ -24,6 +25,8 @@ #include #include +#include "gdbstub.h" + #include #if defined(__linux__) @@ -729,6 +732,47 @@ x49gp_ui_style_init(GtkStyle *style, GtkWidget *widget, style->ythickness = 0; } +static const uint32_t PIXBUF_MAGIC = 0x47646b50; + +typedef struct { + uint32_t magic; + uint32_t length; + uint32_t pixdata_type; + uint32_t rowstride; + uint32_t width; + uint32_t height; +} pixbuf_inline_data_t; + +static GdkPixbuf * +x49gp_pixbuf_new_from_inline(gint data_length, const guint8 *data) +{ + const pixbuf_inline_data_t *pbd = (const pixbuf_inline_data_t *) data; + uint32_t magic, rowstride, width, height, length; + const guint8 *pixdata; + + magic = ntohl(pbd->magic); + if (magic != PIXBUF_MAGIC) { + return NULL; + } + + length = ntohl(pbd->length); + /* The data comes from a C string, which contains a trailing \0. */ + /* This will be counted by sizeof(), but the embedded header */ + /* specifies the true size. Compensate by adding 1 to it. */ + if (length + 1 != data_length) { + return NULL; + } + + width = ntohl(pbd->width); + height = ntohl(pbd->height); + rowstride = ntohl(pbd->rowstride); + + pixdata = (void *) (pbd + 1); + + return gdk_pixbuf_new_from_data(pixdata, GDK_COLORSPACE_RGB, TRUE, 8, + width, height, rowstride, NULL, NULL); +} + static int x49gp_ui_button_pixmaps_init(x49gp_t *x49gp, x49gp_ui_button_t *button, x49gp_ui_color_t color) @@ -750,7 +794,6 @@ x49gp_ui_button_pixmaps_init(x49gp_t *x49gp, x49gp_ui_button_t *button, if (i == GTK_STATE_ACTIVE) { if (color == UI_COLOR_SILVER) { - GError *gerror = NULL; src = gdk_pixbuf_new_subpixbuf(ui->bg_pixbuf, ui->kb_x_offset + button->key->x, @@ -760,8 +803,8 @@ x49gp_ui_button_pixmaps_init(x49gp_t *x49gp, x49gp_ui_button_t *button, dst = gdk_pixbuf_copy(src); g_object_unref(src); - src = gdk_pixbuf_new_from_inline(sizeof(button_round), - button_round, FALSE, &gerror); + src = x49gp_pixbuf_new_from_inline(sizeof(button_round), + button_round); gdk_pixbuf_composite(src, dst, 0, 0, @@ -1462,6 +1505,33 @@ bitmap_font_draw_text(GdkDrawable *drawable, GdkColor *color, } } +static void +x49gp_ui_choose_file(x49gp_t *x49gp, const char *prompt, + GtkFileChooserAction action, char **filename) +{ + GtkWidget *dialog; + x49gp_ui_t *ui = x49gp->ui; + + dialog = gtk_file_chooser_dialog_new(prompt, GTK_WINDOW(ui->window), + action, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, + GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + } else { + *filename = NULL; + } + + gtk_widget_destroy(dialog); +} + static gboolean x49gp_ui_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) @@ -1469,6 +1539,7 @@ x49gp_ui_button_press(GtkWidget *widget, GdkEventButton *event, x49gp_ui_button_t *button = user_data; const x49gp_ui_key_t *key = button->key; x49gp_t *x49gp = button->x49gp; + x49gp_ui_t *ui = x49gp->ui; #ifdef DEBUG_X49GP_UI fprintf(stderr, "%s:%u: type %u, button %u\n", __FUNCTION__, __LINE__, event->type, event->button); @@ -1479,14 +1550,15 @@ x49gp_ui_button_press(GtkWidget *widget, GdkEventButton *event, switch (event->button) { case 1: + ui->buttons_down++; + if (button->down) return FALSE; button->down = TRUE; break; case 3: - if (!button->down) { - gtk_button_pressed(GTK_BUTTON(button->button)); - } - button->down = TRUE; button->hold = TRUE; + if (button->down) return FALSE; + gtk_button_pressed(GTK_BUTTON(button->button)); + button->down = TRUE; break; default: return TRUE; @@ -1499,9 +1571,7 @@ x49gp_ui_button_press(GtkWidget *widget, GdkEventButton *event, #endif if (key->rowbit) { - x49gp->keybycol[key->column] |= key->rowbit; - x49gp->keybyrow[key->row] |= key->columnbit; - s3c2410_io_port_g_update(x49gp); + s3c2410_io_port_g_update(x49gp, key->column, key->row, key->columnbit, key->rowbit, 1); } else { s3c2410_io_port_f_set_bit(x49gp, key->eint, 1); @@ -1510,6 +1580,55 @@ x49gp_ui_button_press(GtkWidget *widget, GdkEventButton *event, return FALSE; } +static void +x49gp_release_single_button(x49gp_ui_button_t *button, x49gp_ui_button_t *cause) +{ + x49gp_t *x49gp = button->x49gp; + const x49gp_ui_key_t *key; + GtkButton *gtkbutton; + +#ifdef DEBUG_X49GP_UI + printf("%s: button %u: col %u, row %u, eint %u\n", __FUNCTION__, + event->button, + button->key->column, button->key->row, button->key->eint); +#endif + + button->down = FALSE; + button->hold = FALSE; + + gtkbutton = GTK_BUTTON(button->button); + + if (button != cause) + gtkbutton->in_button = FALSE; + gtk_button_released(gtkbutton); + + key = button->key; + + if (key->rowbit) { + s3c2410_io_port_g_update(x49gp, key->column, key->row, key->columnbit, key->rowbit, 0); + + } else { + s3c2410_io_port_f_set_bit(x49gp, key->eint, 0); + } +} + +static void +x49gp_release_all_buttons(x49gp_t *x49gp, x49gp_ui_button_t *cause) +{ + x49gp_ui_button_t *button; + x49gp_ui_t *ui = x49gp->ui; + int i; + + for (i = 0; i < ui->nr_buttons; i++) { + button = &ui->buttons[i]; + + if (! button->down) + continue; + + x49gp_release_single_button(button, cause); + } +} + static gboolean x49gp_ui_button_release(GtkWidget *widget, GdkEventButton *event, gpointer user_data) @@ -1517,9 +1636,6 @@ x49gp_ui_button_release(GtkWidget *widget, GdkEventButton *event, x49gp_ui_button_t *button = user_data; x49gp_t *x49gp = button->x49gp; x49gp_ui_t *ui = x49gp->ui; - const x49gp_ui_key_t *key; - GtkButton *gtkbutton; - int i; if (event->type != GDK_BUTTON_RELEASE) return FALSE; @@ -1531,37 +1647,34 @@ x49gp_ui_button_release(GtkWidget *widget, GdkEventButton *event, return TRUE; } - for (i = 0; i < ui->nr_buttons; i++) { - button = &ui->buttons[i]; + if (ui->buttons_down > 0) + ui->buttons_down--; - if (! button->down) - continue; + if (ui->buttons_down == 0) { + x49gp_release_all_buttons(x49gp, button); + } else { + x49gp_release_single_button(button, button); + } -#ifdef DEBUG_X49GP_UI - printf("%s: button %u: col %u, row %u, eint %u\n", __FUNCTION__, - event->button, - button->key->column, button->key->row, button->key->eint); -#endif + return FALSE; +} - button->down = FALSE; - button->hold = FALSE; +static gboolean +x49gp_ui_show_menu(GtkWidget *widget, GdkEventButton *event, gpointer user_data) +{ + x49gp_t *x49gp = user_data; + x49gp_ui_t *ui = x49gp->ui; - gtkbutton = GTK_BUTTON(button->button); + gtk_widget_set_sensitive(ui->menu_unmount, + s3c2410_sdi_is_mounted(x49gp)); + if (ui->menu_debug) + gtk_widget_set_sensitive(ui->menu_debug, + ! gdbserver_isactive()); - if (button != user_data) - gtkbutton->in_button = FALSE; - gtk_button_released(gtkbutton); - - key = button->key; - - if (key->rowbit) { - x49gp->keybycol[key->column] &= ~(key->rowbit); - x49gp->keybyrow[key->row] &= ~(key->columnbit); - s3c2410_io_port_g_update(x49gp); - - } else { - s3c2410_io_port_f_set_bit(x49gp, key->eint, 0); - } + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + gtk_menu_popup(GTK_MENU(ui->menu), NULL, NULL, NULL, NULL, + event->button, event->time); + return TRUE; } return FALSE; @@ -1582,6 +1695,76 @@ x49gp_ui_button_leave(GtkWidget *widget, GdkEventCrossing *event, return TRUE; } +static gboolean +x49gp_ui_focus_lost(GtkWidget *widget, GdkEventFocus *event, + gpointer user_data) +{ + x49gp_t *x49gp = user_data; + x49gp_ui_t *ui = x49gp->ui; + + if (event->type != GDK_FOCUS_CHANGE) + return FALSE; + + ui->buttons_down = 0; + x49gp_release_all_buttons(x49gp, NULL); + + return FALSE; +} + +static void +x49gp_ui_popup_at_widget(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, + gpointer user_data) +{ + GtkWidget *widget = GTK_WIDGET(user_data); + + gdk_window_get_origin(widget->window, x, y); + *x += widget->allocation.x; + *y += widget->allocation.y; +} + +static void +x49gp_ui_mount_sd_folder(GtkMenuItem *menuitem, gpointer user_data) +{ + x49gp_t *x49gp = user_data; + char *filename; + + x49gp_ui_choose_file(x49gp, "Choose SD folder ...", + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, &filename); + if (filename != NULL) s3c2410_sdi_mount(x49gp, filename); +} + +static void +x49gp_ui_mount_sd_image(GtkMenuItem *menuitem, gpointer user_data) +{ + x49gp_t *x49gp = user_data; + char *filename; + + x49gp_ui_choose_file(x49gp, "Choose SD image ...", + GTK_FILE_CHOOSER_ACTION_OPEN, &filename); + if (filename != NULL) s3c2410_sdi_mount(x49gp, filename); +} + +static void +x49gp_ui_debug(GtkMenuItem *menuitem, gpointer user_data) +{ + x49gp_t *x49gp = user_data; + + if(x49gp->debug_port != 0 && ! gdbserver_isactive()) { + gdbserver_start(x49gp->debug_port); + gdb_handlesig(x49gp->env, 0); + } +} + +static void +x49gp_ui_calculator_reset(GtkMenuItem *menuitem, gpointer user_data) +{ + x49gp_t *x49gp = user_data; + + x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON); + cpu_reset(x49gp->env); + x49gp_set_idle(x49gp, 0); +} + static gboolean x49gp_ui_key_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { @@ -1591,76 +1774,95 @@ x49gp_ui_key_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) GdkEventButton bev; gboolean save_in; int index; + guint keyval; #ifdef DEBUG_X49GP_UI fprintf(stderr, "%s:%u: type %u, keyval %04x\n", __FUNCTION__, __LINE__, event->type, event->keyval); #endif - - switch (event->keyval) { - case GDK_A: case GDK_a: case GDK_F1: index = 0; break; - case GDK_B: case GDK_b: case GDK_F2: index = 1; break; - case GDK_C: case GDK_c: case GDK_F3: index = 2; break; - case GDK_D: case GDK_d: case GDK_F4: index = 3; break; - case GDK_E: case GDK_e: case GDK_F5: index = 4; break; - case GDK_F: case GDK_f: case GDK_F6: index = 5; break; - case GDK_G: case GDK_g: index = 6; break; - case GDK_H: case GDK_h: index = 7; break; - case GDK_I: case GDK_i: index = 8; break; - case GDK_J: case GDK_j: index = 9; break; - case GDK_K: case GDK_k: index = 10; break; - case GDK_L: case GDK_l: index = 11; break; - case GDK_Up: case GDK_KP_Up: index = 12; break; - case GDK_Left: case GDK_KP_Left: index = 13; break; - case GDK_Down: case GDK_KP_Down: index = 14; break; - case GDK_Right: case GDK_KP_Right: index = 15; break; - case GDK_M: case GDK_m: index = 16; break; - case GDK_N: case GDK_n: index = 17; break; - case GDK_O: case GDK_o: - case GDK_apostrophe: index = 18; break; - case GDK_P: case GDK_p: index = 19; break; - case GDK_BackSpace: case GDK_Delete: - case GDK_KP_Delete: index = 20; break; - case GDK_Q: case GDK_q: index = 21; break; - case GDK_R: case GDK_r: index = 22; break; - case GDK_S: case GDK_s: index = 23; break; - case GDK_T: case GDK_t: index = 24; break; - case GDK_U: case GDK_u: index = 25; break; - case GDK_V: case GDK_v: index = 26; break; - case GDK_W: case GDK_w: index = 27; break; - case GDK_X: case GDK_x: index = 28; break; - case GDK_Y: case GDK_y: index = 29; break; - case GDK_Z: case GDK_z: - case GDK_slash: case GDK_KP_Divide: index = 30; break; - case GDK_Tab: index = 31; break; -#ifndef __APPLE__ - case GDK_Alt_L: case GDK_Alt_R: - case GDK_Meta_L: case GDK_Meta_R: - case GDK_Mode_switch: index = 31; break; + /* We want to know the keyval as interpreted without modifiers. */ + /* However, there is one modifier we do care about: NumLock, */ + /* which normally is represented by MOD2. */ + if (! gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), + event->hardware_keycode, + event->state & GDK_MOD2_MASK, + event->group, + &keyval, NULL, NULL, NULL)) + return FALSE; +#ifdef DEBUG_X49GP_UI + fprintf(stderr, "%s:%u: state %u, base keyval %04x\n", __FUNCTION__, __LINE__, event->state, keyval); #endif - case GDK_7: case GDK_KP_7: index = 32; break; - case GDK_8: case GDK_KP_8: index = 33; break; - case GDK_9: case GDK_KP_9: index = 34; break; - case GDK_multiply: case GDK_backslash: - case GDK_KP_Multiply: index = 35; break; - case GDK_Shift_L: index = 36; break; - case GDK_4: case GDK_KP_4: index = 37; break; - case GDK_5: case GDK_KP_5: index = 38; break; - case GDK_6: case GDK_KP_6: index = 39; break; - case GDK_minus: case GDK_KP_Subtract: index = 40; break; - case GDK_Shift_R: case GDK_Control_L: index = 41; break; - case GDK_1: case GDK_KP_1: index = 42; break; - case GDK_2: case GDK_KP_2: index = 43; break; - case GDK_3: case GDK_KP_3: index = 44; break; - case GDK_plus: case GDK_equal: - case GDK_KP_Add: index = 45; break; - case GDK_Escape: index = 46; break; - case GDK_0: case GDK_KP_0: index = 47; break; - case GDK_period: case GDK_comma: - case GDK_KP_Decimal: index = 48; break; - case GDK_space: case GDK_KP_Space: index = 49; break; - case GDK_Return: case GDK_KP_Enter: index = 50; break; - case GDK_F12: + switch (keyval) { + case GDK_KEY_a: case GDK_KEY_F1: index = 0; break; + case GDK_KEY_b: case GDK_KEY_F2: index = 1; break; + case GDK_KEY_c: case GDK_KEY_F3: index = 2; break; + case GDK_KEY_d: case GDK_KEY_F4: index = 3; break; + case GDK_KEY_e: case GDK_KEY_F5: index = 4; break; + case GDK_KEY_f: case GDK_KEY_F6: index = 5; break; + case GDK_KEY_g: index = 6; break; + case GDK_KEY_h: index = 7; break; + case GDK_KEY_i: index = 8; break; + case GDK_KEY_j: index = 9; break; + case GDK_KEY_k: index = 10; break; + case GDK_KEY_l: index = 11; break; + case GDK_KEY_Up: case GDK_KEY_KP_Up: index = 12; break; + case GDK_KEY_Left: case GDK_KEY_KP_Left: index = 13; break; + case GDK_KEY_Down: case GDK_KEY_KP_Down: index = 14; break; + case GDK_KEY_Right: case GDK_KEY_KP_Right: index = 15; break; + case GDK_KEY_m: index = 16; break; + case GDK_KEY_n: index = 17; break; + case GDK_KEY_o: case GDK_KEY_apostrophe: index = 18; break; + case GDK_KEY_p: index = 19; break; + case GDK_KEY_BackSpace: case GDK_KEY_Delete: + case GDK_KEY_KP_Delete: index = 20; break; + case GDK_KEY_dead_circumflex: case GDK_KEY_asciicircum: + case GDK_KEY_q: case GDK_KEY_caret: index = 21; break; + case GDK_KEY_r: index = 22; break; + case GDK_KEY_s: index = 23; break; + case GDK_KEY_t: index = 24; break; + case GDK_KEY_u: index = 25; break; + case GDK_KEY_v: index = 26; break; + case GDK_KEY_w: index = 27; break; + case GDK_KEY_x: index = 28; break; + case GDK_KEY_y: index = 29; break; + case GDK_KEY_z: + case GDK_KEY_slash: case GDK_KEY_KP_Divide: index = 30; break; + case GDK_KEY_Tab: index = 31; break; +#ifndef __APPLE__ + //case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: + //case GDK_KEY_Meta_L: case GDK_KEY_Meta_R: + case GDK_KEY_Mode_switch: index = 31; break; +#endif + case GDK_KEY_7: case GDK_KEY_KP_7: index = 32; break; + case GDK_KEY_8: case GDK_KEY_KP_8: index = 33; break; + case GDK_KEY_9: case GDK_KEY_KP_9: index = 34; break; + case GDK_KEY_multiply: case GDK_KEY_KP_Multiply: index = 35; break; + case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: index = 36; break; + case GDK_KEY_4: case GDK_KEY_KP_4: index = 37; break; + case GDK_KEY_5: case GDK_KEY_KP_5: index = 38; break; + case GDK_KEY_6: case GDK_KEY_KP_6: index = 39; break; + case GDK_KEY_minus: case GDK_KEY_KP_Subtract: index = 40; break; + case GDK_KEY_Control_L: case GDK_KEY_Control_R: index = 41; break; + case GDK_KEY_1: case GDK_KEY_KP_1: index = 42; break; + case GDK_KEY_2: case GDK_KEY_KP_2: index = 43; break; + case GDK_KEY_3: case GDK_KEY_KP_3: index = 44; break; + case GDK_KEY_plus: case GDK_KEY_KP_Add: index = 45; break; + case GDK_KEY_Escape: index = 46; break; + case GDK_KEY_0: case GDK_KEY_KP_0: index = 47; break; + case GDK_KEY_period: case GDK_KEY_comma: + case GDK_KEY_KP_Decimal: case GDK_KP_Separator: index = 48; break; + case GDK_KEY_space: case GDK_KEY_KP_Space: index = 49; break; + case GDK_KEY_Return: case GDK_KEY_KP_Enter: index = 50; break; + + /* QUERTY compat: US English, UK English, International English */ + case GDK_KEY_backslash: index = 35; break; + case GDK_KEY_equal: index = 45; break; + + /* QUERTZ compat: German */ + case GDK_KEY_ssharp: index = 30; break; + case GDK_KEY_numbersign: index = 35; break; + + case GDK_KEY_F12: switch (event->type) { case GDK_KEY_PRESS: x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON); @@ -1674,6 +1876,19 @@ x49gp_ui_key_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) break; } return FALSE; + + case GDK_KEY_Menu: + gtk_widget_set_sensitive(ui->menu_unmount, + s3c2410_sdi_is_mounted(x49gp)); + if (ui->menu_debug) + gtk_widget_set_sensitive(ui->menu_debug, + ! gdbserver_isactive()); + + gtk_menu_popup(GTK_MENU(ui->menu), NULL, NULL, + x49gp_ui_popup_at_widget, ui->lcd_canvas, + 0, event->time); + return FALSE; + default: return FALSE; } @@ -2147,7 +2362,7 @@ x49gp_window_button_press(GtkWidget *widget, GdkEventButton *event, } static void -x49gp_ui_quit(GtkWidget *widget, GdkEvent *event, gpointer user_data) +x49gp_ui_quit(gpointer user_data, GtkWidget *widget, GdkEvent *event) { x49gp_t *x49gp = user_data; @@ -2211,23 +2426,37 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) x49gp_ui_t *ui = module->user_data; x49gp_ui_button_t *button; const x49gp_ui_key_t *key; + GtkWidget *screen_box; + GtkWidget *menu_mount_folder, *menu_mount_image, *menu_unmount; + GtkWidget *menu_debug, *menu_reset, *menu_quit; GError *gerror = NULL; GdkBitmap *shape; + char *typestr; char *imagefile; - char *name; + int fd; int i; - imagefile = x49gp_module_get_filename(module, keyfile, "image"); - x49gp_module_get_string(module, keyfile, "name", "hp49g+", &name); - - if (!strcmp(name, "hp49g+")) { + x49gp_module_get_string(module, keyfile, "type", "hp50g", &typestr); + if (!strcmp(typestr, "hp49g+")) { ui->calculator = UI_CALCULATOR_HP49GP; - } else if (!strcmp(name, "hp50g")) { + } else if (!strcmp(typestr, "hp50g")) { ui->calculator = UI_CALCULATOR_HP50G; } else { - ui->calculator = 0; + fprintf(stderr, "Invalid calculator type, reverting to default\n"); + ui->calculator = UI_CALCULATOR_HP50G; } + x49gp_module_get_string(module, keyfile, "name", + ui->calculator == UI_CALCULATOR_HP49GP ? + "HP 49g+" : "HP 50g", + &(ui->name)); + + fd = x49gp_module_open_rodata(module, + ui->calculator == UI_CALCULATOR_HP49GP ? + "hp49g+.png" : "hp50g.png", + &imagefile); + if (fd < 0) return fd; + gdk_pixbuf_get_file_info(imagefile, &ui->width, &ui->height); ui->lcd_width = 131 * 2; @@ -2241,6 +2470,7 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) ui->kb_y_offset = 301; ui->bg_pixbuf = gdk_pixbuf_new_from_file(imagefile, &gerror); + close(fd); ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); @@ -2250,8 +2480,8 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) gtk_widget_set(ui->window, "resizable", FALSE, NULL); gtk_window_set_decorated(GTK_WINDOW(ui->window), FALSE); - gtk_widget_set_name(ui->window, name); - gtk_window_set_title(GTK_WINDOW(ui->window), name); + gtk_widget_set_name(ui->window, ui->name); + gtk_window_set_title(GTK_WINDOW(ui->window), ui->name); // gtk_window_set_icon(GTK_WINDOW(ui->window), ui->bg_pixbuf); @@ -2325,7 +2555,13 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) ui->lcd_canvas = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(ui->lcd_canvas), ui->lcd_width, ui->lcd_height); - x49gp_ui_place_at(x49gp, GTK_FIXED(ui->fixed), ui->lcd_canvas, + screen_box = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(screen_box), + TRUE); + gtk_event_box_set_above_child(GTK_EVENT_BOX(screen_box), + FALSE); + gtk_container_add(GTK_CONTAINER(screen_box), ui->lcd_canvas); + x49gp_ui_place_at(x49gp, GTK_FIXED(ui->fixed), screen_box, ui->lcd_x_offset, ui->lcd_y_offset, ui->lcd_width, ui->lcd_height); @@ -2396,6 +2632,49 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) GDK_LEAVE_NOTIFY_MASK); } + ui->menu = gtk_menu_new(); + + menu_mount_folder = gtk_menu_item_new_with_label("Mount SD folder ..."); + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_mount_folder); + g_signal_connect(G_OBJECT(menu_mount_folder), "activate", + G_CALLBACK(x49gp_ui_mount_sd_folder), x49gp); + menu_mount_image = gtk_menu_item_new_with_label("Mount SD image ..."); + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_mount_image); + g_signal_connect(G_OBJECT(menu_mount_image), "activate", + G_CALLBACK(x49gp_ui_mount_sd_image), x49gp); + menu_unmount = gtk_menu_item_new_with_label("Unmount SD"); + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_unmount); + g_signal_connect_swapped(G_OBJECT(menu_unmount), "activate", + G_CALLBACK(s3c2410_sdi_unmount), x49gp); + ui->menu_unmount = menu_unmount; + + if (x49gp->debug_port != 0) { + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), + gtk_separator_menu_item_new()); + menu_debug = gtk_menu_item_new_with_label("Start debugger"); + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_debug); + g_signal_connect(G_OBJECT(menu_debug), "activate", + G_CALLBACK(x49gp_ui_debug), x49gp); + ui->menu_debug = menu_debug; + } else + ui->menu_debug = NULL; + + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), + gtk_separator_menu_item_new()); + menu_reset = gtk_menu_item_new_with_label("Reset"); + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_reset); + g_signal_connect(G_OBJECT(menu_reset), "activate", + G_CALLBACK(x49gp_ui_calculator_reset), x49gp); + menu_quit = gtk_menu_item_new_with_label("Quit"); + gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_quit); + g_signal_connect_swapped(G_OBJECT(menu_quit), "activate", + G_CALLBACK(x49gp_ui_quit), x49gp); + + gtk_widget_show_all(ui->menu); + + g_signal_connect(G_OBJECT(screen_box), "button-press-event", + G_CALLBACK(x49gp_ui_show_menu), x49gp); + g_signal_connect(G_OBJECT(ui->background), "configure-event", G_CALLBACK(x49gp_window_configure_event), x49gp); @@ -2404,10 +2683,13 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) g_signal_connect(G_OBJECT(ui->lcd_canvas), "configure-event", G_CALLBACK(x49gp_lcd_configure_event), x49gp); - g_signal_connect(G_OBJECT(ui->window), "delete-event", - G_CALLBACK(x49gp_ui_quit), x49gp); - g_signal_connect(G_OBJECT(ui->window), "destroy", - G_CALLBACK(x49gp_ui_quit), x49gp); + g_signal_connect_swapped(G_OBJECT(ui->window), "delete-event", + G_CALLBACK(x49gp_ui_quit), x49gp); + g_signal_connect_swapped(G_OBJECT(ui->window), "destroy", + G_CALLBACK(x49gp_ui_quit), x49gp); + + g_signal_connect(G_OBJECT(ui->window), "focus-out-event", + G_CALLBACK(x49gp_ui_focus_lost), x49gp); g_signal_connect(G_OBJECT(ui->window), "key-press-event", G_CALLBACK(x49gp_ui_key_event), x49gp); @@ -2418,6 +2700,7 @@ gui_load(x49gp_module_t *module, GKeyFile *keyfile) G_CALLBACK(x49gp_window_button_press), x49gp); gtk_widget_add_events(ui->window, + GDK_FOCUS_CHANGE_MASK | GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); @@ -2429,6 +2712,13 @@ gui_load(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+" : "hp50g"); + x49gp_module_set_string(module, keyfile, "name", ui->name); + return 0; } diff --git a/update.scp b/update.scp index d9872e9..3a6e469 100644 --- a/update.scp +++ b/update.scp @@ -1 +1 @@ -4950_215.bin +2MB_215f.bin diff --git a/updatefw b/updatefw deleted file mode 100755 index 125d72b..0000000 --- a/updatefw +++ /dev/null @@ -1,3 +0,0 @@ -rm flash-50g flash-noboot -make flash-50g -