diff --git a/src/Makefile b/src/Makefile index b53e763..7dcac75 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,128 +1,126 @@ -# $Id: release_makefile_base,v 1.15 2003/11/21 20:00:42 kentd Exp kentd $ - -OBJECTS1 = adb.o clock.o config.o dis.o engine_c.o scc.o iwm.o \ - joystick_driver.o moremem.o paddles.o sim65816.o smartport.o \ - sound.o sound_driver.o video.o scc_socket_driver.o scc_windriver.o \ - scc_macdriver.o - -include vars - -.SUFFIXES: .dep .proto - -AS = $(CC) - -XLIBS = -L/usr/X11R6/lib -PERL = perl - -all: $(TARGET) - -specials: 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s - -specials_clean: - rm -f 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s - - -# Mac builds: -gsportmac: $(OBJECTS) compile_time.o - $(CC) $(CCOPTS) $(LDOPTS) -arch ppc $(OBJECTS) compile_time.o $(LDFLAGS) -o gsport $(EXTRA_LIBS) -prebind -framework Carbon -framework Quicktime - mkdir -p ../GSPORT.app/Contents/Resources/English.lproj/main.nib - mkdir -p ../GSPORT.app/Contents/MacOS - mv gsport ../GSPORT.app/Contents/MacOS/GSPORTMAC - echo "APPL????" > ../GSPORT.app/Contents/PkgInfo - cp -f Info.plist ../GSPORT.app/Contents/ - cp -f info.nib ../GSPORT.app/Contents/Resources/English.lproj/main.nib - cp -f classes.nib ../GSPORT.app/Contents/Resources/English.lproj/main.nib - cp -f objects.xib ../GSPORT.app/Contents/Resources/English.lproj/main.nib - cp -f kegsicon.icns ../GSPORT.app/Contents/Resources/ - cp -f 525.icns ../GSPORT.app/Contents/Resources/ - cp -f 2mg.icns ../GSPORT.app/Contents/Resources/ - touch '../GSPORT.app/Icon?' - cp -f ../config.template ../config.txt - -# Linux for X builds: -gsportx: $(OBJECTS) compile_time.o - $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lX11 - mv gsportx .. - cp -f ../config.template ../config.txt - -# Cygwin for X builds: -gsport.exe: $(OBJECTS) compile_time.o - $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lXext -lX11 -lm - mv gsport.exe .. - cp -f ../config.template ../config.txt - -# Mingw32 (native windows) builds: -gsportwin.exe: $(OBJECTS) compile_time.o - $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) -lwinmm -lgdi32 -ldsound -lcomctl32 -lws2_32 - mv $(NAME)$(SUFFIX) .. - cp -f ../config.template ../config.txt - - -8inst_c.h: instable.h - $(PERL) make_inst c 8 instable.h > 8inst_c.h - -16inst_c.h: instable.h - $(PERL) make_inst c 16 instable.h > 16inst_c.h - -size_c.h: size_tab.h - $(PERL) make_size c size_tab.h > size_c.h - -engine_c.o: 8inst_c.h 16inst_c.h size_c.h - -8inst_s.h: instable.h - $(PERL) make_inst s 8 instable.h > 8inst_s.h - -16inst_s.h: instable.h - $(PERL) make_inst s 16 instable.h > 16inst_s.h - -size_s.h: size_tab.h - $(PERL) make_size s size_tab.h > size_s.h - -8size_s.h: size_tab.h - $(PERL) make_size 8 size_tab.h > 8size_s.h - -16size_s.h: size_tab.h - $(PERL) make_size 16 size_tab.h > 16size_s.h - -engine_s.o: 8inst_s.h 16inst_s.h 8size_s.h 16size_s.h size_s.h - -.s.o: - $(AS) -c $(OPTS) -I. $*.s - -.c.o: - $(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.c - -partls: partls.c - cc $(CCOPTS) $(XOPTS) $(OPTS) -o partls partls.c - -to_pro: prodos.h prodos_protos.h to_pro.c - cc $(CCOPTS) $(XOPTS) $(OPTS) -o to_pro to_pro.c - - -compile_time.o: $(OBJECTS) - - -# dependency stuff -adb.o: adb.c adb.h defc.h defcomm.h iwm.h protos.h -engine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos_engine_c.h size_c.h op_routs.h defs_instr.h 8inst_c.h 16inst_c.h -clock.o: clock.c defc.h defcomm.h iwm.h protos.h -compile_time.o: compile_time.c -config.o: config.c defc.h defcomm.h iwm.h protos.h config.h -dis.o: dis.c defc.h defcomm.h iwm.h protos.h disas.h -scc.o: scc.c defc.h defcomm.h iwm.h protos.h scc.h -scc_socket_driver.o: scc_socket_driver.c defc.h defcomm.h iwm.h protos.h scc.h -scc_windriver.o: scc_windriver.c defc.h defcomm.h iwm.h protos.h scc.h -scc_macdriver.o: scc_macdriver.c defc.h defcomm.h iwm.h protos.h scc.h -iwm.o: iwm.c defc.h defcomm.h iwm.h protos.h iwm_35_525.h -joystick_driver.o: joystick_driver.c defc.h defcomm.h iwm.h protos.h -moremem.o: moremem.c defc.h defcomm.h iwm.h protos.h -paddles.o: paddles.c defc.h defcomm.h iwm.h protos.h -sim65816.o: sim65816.c defc.h defcomm.h iwm.h protos.h -smartport.o: smartport.c defc.h defcomm.h iwm.h protos.h -sound.o: sound.c defc.h defcomm.h iwm.h protos.h sound.h -sound_driver.o: sound_driver.c defc.h defcomm.h iwm.h protos.h sound.h -video.o: video.c defc.h defcomm.h iwm.h protos.h superhires.h kegsfont.h -macdriver.o: macdriver.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h -macsnd_driver.o: macsnd_driver.c defc.h defcomm.h iwm.h protos.h sound.h -windriver.o: windriver.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h -win32snd_driver.o: win32snd_driver.c defc.h defcomm.h iwm.h protos.h sound.h +# $Id: release_makefile_base,v 1.15 2003/11/21 20:00:42 kentd Exp kentd $ + +OBJECTS1 = adb.o clock.o config.o dis.o engine_c.o scc.o iwm.o \ + joystick_driver.o moremem.o paddles.o sim65816.o smartport.o \ + sound.o sound_driver.o video.o scc_socket_driver.o scc_windriver.o \ + scc_macdriver.o + +include vars + +.SUFFIXES: .dep .proto + +AS = $(CC) + +XLIBS = -L/usr/X11R6/lib +PERL = perl + +all: $(TARGET) + +specials: 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s + +specials_clean: + rm -f 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s + + +# Mac builds: +kegsmac: $(OBJECTS) compile_time.o + $(CC) $(CCOPTS) $(LDOPTS) -arch ppc $(OBJECTS) compile_time.o $(LDFLAGS) -o kegsmac $(EXTRA_LIBS) -prebind -framework Carbon -framework Quicktime + mkdir -p ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib + mkdir -p ../KEGSMAC.app/Contents/MacOS + mv kegsmac ../KEGSMAC.app/Contents/MacOS/KEGSMAC + echo "APPL????" > ../KEGSMAC.app/Contents/PkgInfo + cp -f Info.plist ../KEGSMAC.app/Contents/ + cp -f info.nib ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib + cp -f classes.nib ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib + cp -f objects.xib ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib + cp -f kegsicon.icns ../KEGSMAC.app/Contents/Resources/ + cp -f 525.icns ../KEGSMAC.app/Contents/Resources/ + cp -f 2mg.icns ../KEGSMAC.app/Contents/Resources/ + touch '../KEGSMAC.app/Icon?' + +# Linux for X builds: +xkegs: $(OBJECTS) compile_time.o + $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lX11 + mv xkegs .. + +# Cygwin for X builds: +kegs.exe: $(OBJECTS) compile_time.o + $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lXext -lX11 -lm + mv kegs.exe .. + +# Mingw32 (native windows) builds: +kegswin.exe: $(OBJECTS) compile_time.o + $(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) -lwinmm -lgdi32 -ldsound -lcomctl32 -lcomdlg32 -lws2_32 + mv $(NAME)$(SUFFIX) .. + + +8inst_c.h: instable.h + $(PERL) make_inst c 8 instable.h > 8inst_c.h + +16inst_c.h: instable.h + $(PERL) make_inst c 16 instable.h > 16inst_c.h + +size_c.h: size_tab.h + $(PERL) make_size c size_tab.h > size_c.h + +engine_c.o: 8inst_c.h 16inst_c.h size_c.h + +8inst_s.h: instable.h + $(PERL) make_inst s 8 instable.h > 8inst_s.h + +16inst_s.h: instable.h + $(PERL) make_inst s 16 instable.h > 16inst_s.h + +size_s.h: size_tab.h + $(PERL) make_size s size_tab.h > size_s.h + +8size_s.h: size_tab.h + $(PERL) make_size 8 size_tab.h > 8size_s.h + +16size_s.h: size_tab.h + $(PERL) make_size 16 size_tab.h > 16size_s.h + +engine_s.o: 8inst_s.h 16inst_s.h 8size_s.h 16size_s.h size_s.h + +.s.o: + $(AS) -c $(OPTS) -I. $*.s + +.c.o: + $(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.c + +partls: partls.c + cc $(CCOPTS) $(XOPTS) $(OPTS) -o partls partls.c + +to_pro: prodos.h prodos_protos.h to_pro.c + cc $(CCOPTS) $(XOPTS) $(OPTS) -o to_pro to_pro.c + +kegs32.o: win32.rc winresource.h + windres win32.rc -o kegs32.o + +compile_time.o: $(OBJECTS) + + +# dependency stuff +adb.o: adb.c adb.h defc.h defcomm.h iwm.h protos.h +engine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos_engine_c.h size_c.h op_routs.h defs_instr.h 8inst_c.h 16inst_c.h +clock.o: clock.c defc.h defcomm.h iwm.h protos.h +compile_time.o: compile_time.c +config.o: config.c defc.h defcomm.h iwm.h protos.h config.h +dis.o: dis.c defc.h defcomm.h iwm.h protos.h disas.h +scc.o: scc.c defc.h defcomm.h iwm.h protos.h scc.h +scc_socket_driver.o: scc_socket_driver.c defc.h defcomm.h iwm.h protos.h scc.h +scc_windriver.o: scc_windriver.c defc.h defcomm.h iwm.h protos.h scc.h +scc_macdriver.o: scc_macdriver.c defc.h defcomm.h iwm.h protos.h scc.h +iwm.o: iwm.c defc.h defcomm.h iwm.h protos.h iwm_35_525.h +joystick_driver.o: joystick_driver.c defc.h defcomm.h iwm.h protos.h +moremem.o: moremem.c defc.h defcomm.h iwm.h protos.h +paddles.o: paddles.c defc.h defcomm.h iwm.h protos.h +sim65816.o: sim65816.c defc.h defcomm.h iwm.h protos.h +smartport.o: smartport.c defc.h defcomm.h iwm.h protos.h +sound.o: sound.c defc.h defcomm.h iwm.h protos.h sound.h +sound_driver.o: sound_driver.c defc.h defcomm.h iwm.h protos.h sound.h +video.o: video.c defc.h defcomm.h iwm.h protos.h superhires.h kegsfont.h +macdriver.o: macdriver.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h +macsnd_driver.o: macsnd_driver.c defc.h defcomm.h iwm.h protos.h sound.h +windriver.o: windriver.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h kegs32.o +win32snd_driver.o: win32snd_driver.c defc.h defcomm.h iwm.h protos.h sound.h diff --git a/src/README.ethernet.txt b/src/README.ethernet.txt new file mode 100644 index 0000000..372e8a5 --- /dev/null +++ b/src/README.ethernet.txt @@ -0,0 +1,74 @@ +Ethernet support HOW-TO +----------------------- + +Acknowledgment: +--------------- + +Uthernet (TFE) support in KEGS was made possible by implementing the GPL source written by Spiro Trikaliotis for the Vice emulator - http://www.viceteam.org/ This version of KEGS contains the latest code from VICE 2.1. + +Details: + +Right now Uthernet emulation only works under Windows. Future support for PCap under OS X and Linux is planned. +In order to use Uthernet emulation, you must install WinPCap ( http://www.WinPcap.org/install/default.htm ) and +have a wired ethernet connecton on the host computer. + + +KEGS Setup: +----------- + +After KEGS starts, press F4 to enter the text based menu and select the "Ethernet Card Configuration" option. + +By default, Uthernet emulation is turned off, enable it by setting "Uthernet Card in Slot 3"to "On". + +Next, select the host interface you wish to use to communicate with the outside world. A list of available +interfaces is provided on screen. For most the default of interface "0" is correct. + +Return back to the main menu and save you configuration for good measure. Due to limitations, you must exit +and restart KEGS for the changes you made to take effect. Next is configuring the Apple IIgs side of things. + +GS/OS Setup: +------------ + +In order to use TCP/IP connectivity under GS/OS, you have to install the latest version of Marinetti and the +Uthernet Link Layer. + +First download and install the latest version of Marinetti 3.0 available at: +http://www.apple2.org/marinetti/Marinetti3.0b1.SHK + +Then install the latest TCPIP INIT available at +http://www.apple2.org/marinetti/TCPIP30b3.SHK + +Just extract and copy the file to the "System.Setup" folder in your GS/OS system folder, overwriting the existing file + +Last, install the latest Uthernet Link Layer (1.0.1b5) available at: +http://www.wannop.info/speccie/uthernetll.bxy + +Just extract and copy the file to the "TCPIP" folder in your GS/OS system folder. + +After copying over all the files, reboot the emulated IIgs. Once at the desktop, bring up the graphical control +panel available in the Apple menu and double click the "TCP/IP" icon. + +Click on "Setup Connection..." Select the "Uthernet" link layer from the drop down and then click "Configure..." + +Set "Lan Slot:" to "3", check off the DHCP option and then click "Save". Click "OK" to leave the setup dialog. + +You should be able to click "Connect to network" and successfully connect to your TCP/IP netowork. + +From this point on, you are free to run any TCP/IP aware GS/OS applications. + +The following applications have been tested and seem to work fine: +------------------------------------------------------------------ + +Spectrum Automated File Exchange 2.1.9 (FTP client, use passive mode) +Telnet application included with Marinetti + +The following applications have been tested and DO NOT work: +------------------------------------------------------------ + +Casper web server: It will not serve web pages. This is likely a limitation of WinPCap. + +A note about 8-bit applications: +-------------------------------- + +Uthernet enabled versions of Contiki seem to work fine with KEGS. Other 8-bit software should work fine but +are untested at this time. \ No newline at end of file diff --git a/src/SDL.dll b/src/SDL.dll new file mode 100644 index 0000000..628cdfc Binary files /dev/null and b/src/SDL.dll differ diff --git a/src/config.c b/src/config.c index f0cb611..4dead06 100644 --- a/src/config.c +++ b/src/config.c @@ -24,6 +24,11 @@ #include "config.h" #include +#if defined (WIN32) || (WIN64) +#define snprintf _snprintf +typedef unsigned int mode_t; +#endif + extern int Verbose; extern word32 g_vbl_count; extern Iwm iwm; @@ -59,6 +64,21 @@ extern int g_joystick_trim_amount_x; extern int g_joystick_trim_amount_y; extern int g_swap_paddles; extern int g_invert_paddles; +extern int g_ethernet; +extern int g_ethernet_interface; +extern int g_parallel; +extern int g_parallel_out_masking; +extern int g_printer; +extern int g_printer_dpi; +extern char* g_printer_output; +extern int g_printer_multipage; +extern char* g_printer_font_roman; +extern char* g_printer_font_sans; +extern char* g_printer_font_prestige; +extern char* g_printer_font_courier; +extern char* g_printer_font_script; +extern char* g_printer_font_ocra; +extern int g_printer_timeout; extern int g_screen_index[]; extern word32 g_full_refresh_needed; @@ -68,7 +88,6 @@ extern int g_new_a2_stat_cur_line; extern int g_key_down; extern const char g_kegs_version_str[]; - int g_config_control_panel = 0; char g_config_kegs_name[1024]; char g_cfg_cwd_str[CFG_PATH_MAX] = { 0 }; @@ -101,6 +120,7 @@ int g_cfg_curs_mousetext = 0; int g_cfg_opts_vals[CFG_MAX_OPTS]; char g_cfg_opts_strs[CFG_MAX_OPTS][CFG_OPT_MAXSTR]; +char g_cfg_opts_strvals[CFG_MAX_OPTS][CFG_OPT_MAXSTR]; char g_cfg_opt_buf[CFG_OPT_MAXSTR]; char *g_cfg_rom_path = "ROM"; @@ -142,7 +162,8 @@ Cfg_menu g_cfg_disk_menu[] = { Cfg_menu g_cfg_joystick_menu[] = { { "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU }, { "Joystick Emulation,0,Keypad Joystick,1,Mouse Joystick,2,Native Joystick 1," - "3,Native Joystick 2", KNMP(g_joystick_type), CFGTYPE_INT }, + "3,Native Joystick 2,4,Disable Joystick", + KNMP(g_joystick_type), CFGTYPE_INT }, { "Joystick Scale X,0x100,Standard,0x119,+10%,0x133,+20%," "0x150,+30%,0xb0,-30%,0xcd,-20%,0xe7,-10%", KNMP(g_joystick_scale_factor_x), CFGTYPE_INT }, @@ -185,12 +206,64 @@ Cfg_menu g_cfg_serial_menu[] = { { 0, 0, 0, 0, 0 }, }; +Cfg_menu g_cfg_parallel_menu[] = { +{ "Parallel Card Configuration", g_cfg_parallel_menu, 0, 0, CFGTYPE_MENU }, +{ "Parallel Card in Slot 1,0,Off,1,On", + KNMP(g_parallel), CFGTYPE_INT }, +{ "Parallel Output,0,Send full 8-bit data,1,Mask off high bit", + KNMP(g_parallel_out_masking), CFGTYPE_INT }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + +Cfg_menu g_cfg_ethernet_menu[] = { +{ "Ethernet Card Configuration", g_cfg_ethernet_menu, 0, 0, CFGTYPE_MENU }, +{ "Uthernet Card in Slot 3,0,Off,1,On", + KNMP(g_ethernet), CFGTYPE_INT }, +{ "Use Interface Number,0,0,1,1,2,2,3,3,4,4", + KNMP(g_ethernet_interface), CFGTYPE_INT }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + +Cfg_menu g_cfg_printer_menu[] = { +{ "Virtual Printer Configuration", g_cfg_ethernet_menu, 0, 0, CFGTYPE_MENU }, +{ "Virtual Printer Type,0,Epson LQ", + KNMP(g_printer), CFGTYPE_INT }, +{ "Printer DPI,60,60x60 dpi,180,180x180 dpi,360,360x360 dpi", + KNMP(g_printer_dpi), CFGTYPE_INT }, +{ "Printer Output Type,bmp,Windows Bitmap,ps,Postscript (B&W),printer,Direct to host printer", + KNMP(g_printer_output), CFGTYPE_STR }, +{ "Multipage Files? (PS Only),0,No,1,Yes", + KNMP(g_printer_multipage), CFGTYPE_INT }, +{ "Printer Timeout,0,Never,2,2 sec.,15,15 sec.,30,30 sec.,60, 1 min.", + KNMP(g_printer_timeout), CFGTYPE_INT }, +{ "", 0, 0, 0, 0 }, +{ "Epson LQ Fonts", 0, 0, 0, 0 }, +{ "--------------", 0, 0, 0, 0 }, +{ "", 0, 0, 0, 0 }, +{ "Roman", KNMP(g_printer_font_roman), CFGTYPE_FILE }, +{ "Sans Serif", KNMP(g_printer_font_sans), CFGTYPE_FILE }, +{ "Courier", KNMP(g_printer_font_courier), CFGTYPE_FILE }, +{ "Prestige", KNMP(g_printer_font_prestige), CFGTYPE_FILE }, +{ "Script", KNMP(g_printer_font_script), CFGTYPE_FILE }, +{ "OCR A/B", KNMP(g_printer_font_ocra), CFGTYPE_FILE }, +{ "", 0, 0, 0, 0 }, +{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, +{ 0, 0, 0, 0, 0 }, +}; + Cfg_menu g_cfg_main_menu[] = { { "GSport Configuration", g_cfg_main_menu, 0, 0, CFGTYPE_MENU }, { "Disk Configuration", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU }, { "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU }, { "ROM File Selection", g_cfg_rom_menu, 0, 0, CFGTYPE_MENU }, { "Serial Port Configuration", g_cfg_serial_menu, 0, 0, CFGTYPE_MENU }, +{ "Ethernet Card Configuration", g_cfg_ethernet_menu, 0, 0, CFGTYPE_MENU }, +{ "Parallel Card Configuration", g_cfg_parallel_menu, 0, 0, CFGTYPE_MENU }, +{ "Virtual Printer Configuration", g_cfg_printer_menu, 0, 0, CFGTYPE_MENU }, { "Force X-windows display depth", KNMP(g_force_depth), CFGTYPE_INT }, { "Auto-update configuration file,0,Manual,1,Immediately", KNMP(g_config_kegs_auto_update), CFGTYPE_INT }, @@ -241,7 +314,7 @@ int g_cfg_file_pathfield = 0; const char *g_kegs_rom_names[] = { "ROM", "ROM", "ROM.01", "ROM.03", 0 }; /* First entry is special--it will be overwritten by g_cfg_rom_path */ -const char *g_kegs_c1rom_names[] = { 0 }; +const char *g_kegs_c1rom_names[] = { "parallel.rom" }; const char *g_kegs_c2rom_names[] = { 0 }; const char *g_kegs_c3rom_names[] = { 0 }; const char *g_kegs_c4rom_names[] = { 0 }; @@ -331,6 +404,15 @@ config_init_menus(Cfg_menu *menuptr) defptr->intval = val; menuptr->defptr = &(defptr->intval); break; + case CFGTYPE_STR: + str_ptr = (char **)menuptr->ptr; + str = *str_ptr; + // We need to malloc this string since all + // string values must be dynamically alloced + defptr->strval = str; // this can have a copy + *str_ptr = kegs_malloc_str(str); + menuptr->defptr = &(defptr->strval); + break; case CFGTYPE_FILE: str_ptr = (char **)menuptr->ptr; str = *str_ptr; @@ -437,6 +519,37 @@ cfg_text_screen_dump() fclose(ofile); } +void +cfg_get_tfe_name() +{ + int i = 0; + char *ppname = NULL; + char *ppdes = NULL; + cfg_htab_vtab(0,9); + if (tfe_enumadapter_open()) + { + cfg_printf("Interface List:\n---------------"); + while(tfe_enumadapter(&ppname,&ppdes)) + { + cfg_htab_vtab(0, 11+i); + cfg_printf("%2d: %s",i,ppdes); + i++; + lib_free(ppname); + lib_free(ppdes); + } + tfe_enumadapter_close(); + } + else + { + #ifdef WIN32 + cfg_printf("ERROR: Install/Enable WinPcap for Ethernet Support!!"); + #else + cfg_printf("ERROR: Install/Enable LibPcap for Ethernet Support!!"); + #endif + } + return; +} + void config_vbl_update(int doit_3_persec) { @@ -523,6 +636,13 @@ config_parse_option(char *buf, int pos, int len, int line) iptr = (int *)menuptr->ptr; *iptr = val; break; + case CFGTYPE_STR: + strptr = (char **)menuptr->ptr; + if(strptr && *strptr) { + free(*strptr); + } + *strptr = kegs_malloc_str(&buf[pos]); + break; case CFGTYPE_FILE: strptr = (char **)menuptr->ptr; if(strptr && *strptr) { @@ -686,6 +806,7 @@ config_load_roms() continue; } close(fd); + fd = 0; } } @@ -1062,6 +1183,14 @@ config_write_config_kegs_file() curval); } } + if(type == CFGTYPE_STR) { + curstr = *((char **)menuptr->ptr); + defstr = *((char **)menuptr->defptr); + if(strcmp(curstr, defstr) != 0) { + fprintf(fconf, "%s = %s\n", menuptr->name_str, + curstr); + } + } if(type == CFGTYPE_FILE) { curstr = *((char **)menuptr->ptr); defstr = *((char **)menuptr->defptr); @@ -1891,6 +2020,7 @@ cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) char *curstr, *defstr; char *str; char *outstr; + char *strval; int *iptr; int val; int num_opts; @@ -1975,8 +2105,16 @@ cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) my_exit(1); } } else { + if (type == CFGTYPE_INT) + { val = strtoul(valbuf, 0, 0); g_cfg_opts_vals[num_opts] = val; + } + + if (type == CFGTYPE_STR) + { + strncpy(&(g_cfg_opts_strvals[num_opts][0]),&(valbuf[0]),CFG_OPT_MAXSTR); + } outstr = &(g_cfg_opts_strs[num_opts][0]); opt_get_str = 1; } @@ -2005,6 +2143,16 @@ cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) g_cfg_opt_buf[4] = '\t'; } } + if(type == CFGTYPE_STR) { + str_ptr = (char **)menuptr->ptr; + curstr = *str_ptr; + str_ptr = (char **)menuptr->defptr; + defstr = *str_ptr; + if(strcmp(curstr,defstr) == 0) { + g_cfg_opt_buf[3] = 'D'; /* checkmark */ + g_cfg_opt_buf[4] = '\t'; + } + } if(type == CFGTYPE_FILE) { str_ptr = (char **)menuptr->ptr; curstr = *str_ptr; @@ -2039,6 +2187,18 @@ cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) } } } + if(type == CFGTYPE_STR) { + g_cfg_opt_buf[bufpos++] = ' '; + g_cfg_opt_buf[bufpos++] = '='; + g_cfg_opt_buf[bufpos++] = ' '; + g_cfg_opt_buf[bufpos] = 0; + for(i = 0; i < num_opts; i++) { + if(!strcmp(curstr,g_cfg_opts_strvals[i])) { + opt_num = i; + break; + } + } + } if(change != 0) { if(type == CFGTYPE_INT) { @@ -2058,6 +2218,23 @@ cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) iptr = (int *)menuptr->ptr; *iptr = curval; } + if(type == CFGTYPE_STR) { + if(num_opts > 0) { + opt_num += change; + if(opt_num >= num_opts) { + opt_num = 0; + } + if(opt_num < 0) { + opt_num = num_opts - 1; + } + curstr = g_cfg_opts_strvals[opt_num]; + } else { + //curstr += change; + /* HACK: min_val, max_val testing here */ + } + str_ptr = (char **)menuptr->ptr; + *str_ptr = curstr; + } g_config_kegs_update_needed = 1; } @@ -2073,6 +2250,10 @@ cfg_parse_menu(Cfg_menu *menuptr, int menu_pos, int highlight_pos, int change) if(type == CFGTYPE_INT) { str = &(g_cfg_opts_strs[0][0]); snprintf(str, CFG_OPT_MAXSTR, "%d", curval); + } else if (type == CFGTYPE_STR) { + str = &(g_cfg_opts_strs[0][0]); + printf("curstr is: %s str is: %s\n", curstr,str); + snprintf(str, CFG_OPT_MAXSTR, "%s", curstr); } else if (type == CFGTYPE_DISK) { str = &(g_cfg_opts_strs[0][0]), cfg_get_disk_name(str, CFG_OPT_MAXSTR, type_ext, 1); @@ -2297,7 +2478,7 @@ cfg_dirent_sortfn(const void *obj1, const void *obj2) direntptr1 = (const Cfg_dirent *)obj1; direntptr2 = (const Cfg_dirent *)obj2; #if defined(MAC) || defined(_WIN32) - ret = strcasecmp(direntptr1->name, direntptr2->name); + ret = _stricmp(direntptr1->name, direntptr2->name); #else ret = strcmp(direntptr1->name, direntptr2->name); #endif @@ -2966,6 +3147,13 @@ config_control_panel() if(g_cfg_slotdrive >= 0) { cfg_file_draw(); } + /*HACK eh, at least I think it is. Display the available ethernet interfaces + when in the ethernet control panel. This is the only way one can customize a menu pane. + Kent did it with the directory browser, so why not.*/ + if(menuptr == g_cfg_ethernet_menu) + { + cfg_get_tfe_name(); + } key = -1; while(g_config_control_panel) { diff --git a/src/config.h b/src/config.h index fe53b5d..869bf99 100644 --- a/src/config.h +++ b/src/config.h @@ -36,6 +36,7 @@ const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.9 2004-11-12 23:10:28-05 #define CFGTYPE_DISK 3 #define CFGTYPE_FUNC 4 #define CFGTYPE_FILE 5 +#define CFGTYPE_STR 6 /* CFGTYPE limited to just 4 bits: 0-15 */ /* Cfg_menu, Cfg_dirent and Cfg_listhdr are defined in defc.h */ diff --git a/src/engine_c.c b/src/engine_c.c index 18e6d7e..1f40e2c 100644 --- a/src/engine_c.c +++ b/src/engine_c.c @@ -53,6 +53,9 @@ extern byte *g_memory_ptr; extern byte *g_rom_fc_ff_ptr; extern byte *g_rom_cards_ptr; extern byte *g_dummy_memory1_ptr; +extern int g_c068_statereg; +unsigned char ioslotsel = 0; +unsigned char iostrobe = 0; extern int g_num_breakpoints; extern word32 g_breakpts[]; @@ -152,12 +155,12 @@ extern Page_info page_info_rd_wr[]; extern word32 slow_mem_changed[]; #define GET_MEMORY8(addr,dest) \ - addr_latch = (addr); \ - CYCLES_PLUS_1; \ + addr_latch = (addr);\ + CYCLES_PLUS_1; \ stat = GET_PAGE_INFO_RD(((addr) >> 8) & 0xffff); \ wstat = PTR2WORD(stat) & 0xff; \ ptr = stat - wstat + ((addr) & 0xff); \ - if(wstat & (1 << (31 - BANK_IO_BIT))) { \ + if(wstat & (1 << (31 - BANK_IO_BIT)) || iostrobe == 1) { \ fcycles_tmp1 = fcycles; \ dest = get_memory8_io_stub((addr), stat, \ &fcycles_tmp1, fplus_x_m1); \ @@ -374,13 +377,13 @@ get_memory8_io_stub(word32 addr, byte *stat, double *fcycs_ptr, double fcycles; word32 wstat; byte *ptr; - wstat = PTR2WORD(stat) & 0xff; + if(wstat & BANK_BREAK) { check_breakpoints(addr); } fcycles = *fcycs_ptr; - if(wstat & BANK_IO2_TMP) { + if(wstat & BANK_IO2_TMP || iostrobe == 1) { FCYCLES_ROUND; *fcycs_ptr = fcycles; return get_memory_io((addr), fcycs_ptr); @@ -403,7 +406,6 @@ get_memory16_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, word32 addr_latch; word32 ret; word32 tmp1; - fcycles = *fcycs_ptr; fplus_1 = fplus_ptr->plus_1; fplus_x_m1 = fplus_ptr->plus_x_minus_1; @@ -431,7 +433,6 @@ get_memory24_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, word32 ret; word32 tmp1; word32 tmp2; - fcycles = *fcycs_ptr; fplus_1 = fplus_ptr->plus_1; fplus_x_m1 = fplus_ptr->plus_x_minus_1; @@ -506,7 +507,6 @@ set_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, double fcycles, fcycles_tmp1; word32 addrp1; word32 wstat; - fcycles = *fcycs_ptr; SET_MEMORY8(addr, val); addrp1 = addr + 1; @@ -598,7 +598,6 @@ set_memory_c(word32 addr, word32 val, int cycs) double fplus_1; double fplus_x_m1; word32 wstat; - fcycles = g_cur_dcycs - g_last_vbl_dcycs; fplus_1 = 0; fplus_x_m1 = 0; @@ -886,7 +885,7 @@ get_remaining_operands(word32 addr, word32 opcode, word32 psr, Fplus *fplus_ptr) FINISH(RET_C70D, 0); \ } \ } \ - if(wstat & (1 << (31 - BANK_IO2_BIT))) { \ + if(wstat & (1 << (31 - BANK_IO2_BIT)) || iostrobe == 1) { \ FCYCLES_ROUND; \ fcycles_tmp1 = fcycles; \ opcode = get_memory_io((addr), &fcycles_tmp1); \ diff --git a/src/joystick_driver.c b/src/joystick_driver.c index f1fcbbd..52006dc 100644 --- a/src/joystick_driver.c +++ b/src/joystick_driver.c @@ -179,6 +179,11 @@ joystick_init() } } + if (g_joystick_native_type1<0 && g_joystick_native_type2 <0) { + printf ("No joystick is attached\n"); + return; + } + for(i = 0; i < 4; i++) { g_paddle_val[i] = 32767; } diff --git a/src/kegs.sln b/src/kegs.sln new file mode 100644 index 0000000..3d35c04 --- /dev/null +++ b/src/kegs.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kegs", "kegs.vcproj", "{4E045654-5CE8-482F-AE4C-5DD99C943461}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Debug|Win32.Build.0 = Debug|Win32 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Debug|x64.ActiveCfg = Debug|x64 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Debug|x64.Build.0 = Debug|x64 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Release|Win32.ActiveCfg = Release|Win32 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Release|Win32.Build.0 = Release|Win32 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Release|x64.ActiveCfg = Release|x64 + {4E045654-5CE8-482F-AE4C-5DD99C943461}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/kegs.vcproj b/src/kegs.vcproj new file mode 100644 index 0000000..412f146 --- /dev/null +++ b/src/kegs.vcproj @@ -0,0 +1,1238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/kegs32.aps b/src/kegs32.aps new file mode 100644 index 0000000..7e93301 Binary files /dev/null and b/src/kegs32.aps differ diff --git a/src/kegs32.ico b/src/kegs32.ico new file mode 100644 index 0000000..f9f1227 Binary files /dev/null and b/src/kegs32.ico differ diff --git a/src/kegs32.rc b/src/kegs32.rc new file mode 100644 index 0000000..3920f48 --- /dev/null +++ b/src/kegs32.rc @@ -0,0 +1,209 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource." + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_KEGS32 MENU +BEGIN + POPUP "&Emulator" + BEGIN + MENUITEM "&Set Disk Configuration\tALT-F1", ID_FILE_DISK + MENUITEM "Send CTRL Reset\tCTRL-BREAK", ID_FILE_SENDRESET + MENUITEM "Reboot\tCTRL-ALT-BREAK", ID_FILE_SENDREBOOT + MENUITEM SEPARATOR + MENUITEM "Flush Printer", ID_FILE_FLUSHPRINTER + MENUITEM "Toggle &Joystick", ID_FILE_JOYSTICK + MENUITEM "Toggle Debug Statistics", ID_FILE_DEBUGSTAT + MENUITEM SEPARATOR + MENUITEM "E&xit\tALT-F4", ID_FILE_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "Key Commands", ID_HELP_KEY + MENUITEM SEPARATOR + MENUITEM "&About", ID_HELP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDC_KEGS32 BITMAP "wintoolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL ACCELERATORS +BEGIN + VK_F1, ID_FILE_DISK, VIRTKEY, ALT, NOINVERT + VK_F4, ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDC_KEGS32 ICON "kegs32.ico" +KEGS32_ICON ICON "kegs32.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUT_DIALOG DIALOGEX 0, 0, 207, 82 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,78,61,50,14 + LTEXT "KEGS32: GS Emulator.\nBased on KEGS by Kent Dickey\nWindows Port by Chea Chee Keong\n\nThis software is free for non-commercial use.",IDC_STATIC,38,7,162,45,NOT WS_GROUP + ICON "KEGS32_ICON",IDC_STATIC,7,7,20,20 +END + +IDD_DLG_DISKCONF DIALOGEX 0, 0, 268, 182 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Disk Configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,161,50,14 + PUSHBUTTON "Cancel",IDCANCEL,203,161,50,14 + LTEXT "S5D1",IDC_STATIC,19,46,19,8 + EDITTEXT IDC_EDIT_S5D1,43,42,156,14,ES_AUTOHSCROLL,WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S5D1,203,42,50,14 + LTEXT "S5D2",IDC_STATIC,19,62,19,8 + EDITTEXT IDC_EDIT_S5D2,43,60,155,14,ES_AUTOHSCROLL,WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S5D2,203,60,50,14 + LTEXT "S6D1",IDC_STATIC,19,80,19,8 + EDITTEXT IDC_EDIT_S6D1,43,77,156,14,ES_AUTOHSCROLL,WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S6D1,203,77,50,14 + LTEXT "S6D2",IDC_STATIC,19,98,19,8 + EDITTEXT IDC_EDIT_S6D2,43,95,156,14,ES_AUTOHSCROLL,WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S6D2,203,96,50,14 + LTEXT "S7D1",IDC_STATIC,19,118,19,8 + EDITTEXT IDC_EDIT_S7D1,43,115,155,14,ES_AUTOHSCROLL,WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S7D1,203,115,50,14 + LTEXT "S7D2",IDC_STATIC,19,137,19,8 + EDITTEXT IDC_EDIT_S7D2,43,135,155,14,ES_AUTOHSCROLL,WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S7D2,203,135,50,14 + GROUPBOX "Disk settings",IDC_STATIC,7,7,254,148 + LTEXT "Configure your disk images for each drive. Disk image formats supported\nare *.2MG,*.PO and *.DSK. ",IDC_STATIC,19,20,234,16 +END + +IDD_SPEEDDIALOG DIALOG 0, 0, 240, 129 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Speed Control" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "1 MHz",IDC_SLOW,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,45,41,51,13 + CONTROL "2.5 MHz",IDC_NORMAL,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,45,55,43,13 + CONTROL "As fast as possible",IDC_FASTEST,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,45,69,74,13 + CONTROL "Custom (MHz)",IDC_CUSTOM,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,45,83,69,13 + EDITTEXT IDC_EDITCUSTOM,117,83,79,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,133,107,50,15 + PUSHBUTTON "Cancel",IDCANCEL,183,107,50,15 + GROUPBOX "Speed Control",IDC_STATIC,7,7,226,96,WS_GROUP + LTEXT "Adjust the speed of your emulator by selecting the appropriate speed control",IDC_STATIC,46,19,181,19,NOT WS_GROUP + ICON IDC_KEGS32,IDC_STATIC,14,19,21,20 +END + +IDD_KEGS32_KEY DIALOGEX 0, 0, 186, 172 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Help About Key Commands" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,151,50,14 + LTEXT "KEGS32 Key Commands",IDC_STATIC,7,7,82,10 + LTEXT "Alt/F1\t\tOpen-Apple\nF2\t\tClose-Apple\nF7\t\tToggle Fast Disk Emulation\nF8\t\tToggle Mouse Pointer\n\t\tDisplay\n",IDC_STATIC,21,25,151,42 + LTEXT "F11\t\tToggle Fullscreen Display\nF12\t\tReset\nCtrl-Alt-Break\tReboot Emulator\nCtrl-Alt-Esc\tControl-Panel\nCtrl-Break\tReset Emulator",IDC_STATIC,21,66,141,50 + CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | WS_DISABLED | WS_BORDER,7,17,172,1 + LTEXT "For more information, please consult the readme.kegs file",IDC_STATIC,21,124,144,19 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + ID_FILE_DISK "Disk Configuration" +END + +STRINGTABLE +BEGIN + ID_SPEED_1MHZ "Set Speed to 1 Mhz" + ID_SPEED_2MHZ "Set Speed to 2.5 Mhz" + ID_SPEED_FMHZ "Set Speed to as fast as possible" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/moremem.c b/src/moremem.c index 4833490..e18f616 100644 --- a/src/moremem.c +++ b/src/moremem.c @@ -30,6 +30,9 @@ extern byte *g_dummy_memory1_ptr; extern byte *g_slow_memory_ptr; extern byte *g_rom_fc_ff_ptr; extern byte *g_rom_cards_ptr; +extern byte *g_grappler_rom; +extern unsigned char ioslotsel; +extern unsigned char iostrobe; extern word32 slow_mem_changed[]; @@ -41,8 +44,9 @@ extern Page_info page_info_rd_wr[]; extern int Verbose; extern int g_rom_version; extern int g_user_page2_shadow; +extern int g_parallel; - +char c; /* from iwm.c */ int g_num_shadow_all_banks = 0; @@ -275,7 +279,7 @@ fixup_intcx() int start_k; word32 mask; int j, k; - + int test1; rom10000 = &(g_rom_fc_ff_ptr[0x30000]); no_io_shadow = (g_c035_shadow_reg & 0x40); @@ -311,25 +315,27 @@ fixup_intcx() } } for(j = 0xc8; j < 0xd0; j++) { - /* c800 - cfff */ - if(((g_c02d_int_crom & (1 << 3)) == 0) || INTCX) { - rom_inc = rom10000 + (j << 8); - } else { - /* c800 space not necessarily mapped */ - /* just map in ROM */ + + /*c800 - cfff */ + if(((g_c02d_int_crom & (1 << 3)) == 0) || INTCX) + { rom_inc = rom10000 + (j << 8); } + else + { + rom_inc = rom10000 + (j << 8); + + } SET_PAGE_INFO_RD(j + off, rom_inc); } + iostrobe = 0; for(j = 0xc0; j < 0xd0; j++) { SET_PAGE_INFO_WR(j + off, SET_BANK_IO); } } - if(!no_io_shadow) { SET_PAGE_INFO_RD(0xc7, SET_BANK_IO); /* smartport */ } - fixup_brks(); } @@ -1458,8 +1464,16 @@ io_read(word32 loc, double *cyc_ptr) case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - /* UNIMPL_READ; */ - return 0; + if (g_parallel) + { + return parallel_read((word16)loc & 0xf); + } + else + { + UNIMPL_READ; + } + + /* 0xc0a0 - 0xc0af */ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: @@ -1469,19 +1483,41 @@ io_read(word32 loc, double *cyc_ptr) /* UNIMPL_READ; */ /* 0xc0b0 - 0xc0bf */ - case 0xb0: + //case 0xb0: /* c0b0: female voice tool033 look at this */ - return 0; - case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: + // return 0; + //case 0xb1: case 0xb2: case 0xb3: + //case 0xb4: case 0xb5: case 0xb6: case 0xb7: + //case 0xb9: case 0xba: case 0xbb: + //case 0xbc: case 0xbd: case 0xbe: case 0xbf: /* UNIMPL_READ; */ - return 0; + // return 0; /* c0b8: Second Sight card stuff: return 0 */ + //case 0xb8: + // return 0; + // break; + /*Uthernet read access on slot 3*/ + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: case 0xb8: - return 0; - break; + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + if (tfe_enabled){ + return tfe_read((word16)loc & 0xf); + } + else + {return 0;} /* 0xc0c0 - 0xc0cf */ case 0xc0: case 0xc1: case 0xc2: case 0xc3: @@ -1537,12 +1573,13 @@ io_read(word32 loc, double *cyc_ptr) } UNIMPL_READ; case 0xf: + if((loc & 0xfff) == 0xfff) { + return g_rom_fc_ff_ptr[0x3cfff]; + } + if(INTCX || ((g_c02d_int_crom & (1 << 3)) == 0)) { return(g_rom_fc_ff_ptr[0x3c000 + (loc & 0xfff)]); } - if((loc & 0xfff) == 0xfff) { - return g_rom_fc_ff_ptr[0x3cfff]; - } UNIMPL_READ; } @@ -1569,6 +1606,7 @@ io_write(word32 loc, int val, double *cyc_ptr) val = val & 0xff; switch((loc >> 8) & 0xf) { case 0: /* 0xc000 - 0xc0ff */ + //printf ("ioaddress: %x", (loc & 0xf)); switch(loc & 0xff) { /* 0xc000 - 0xc00f */ case 0x00: /* 0xc000 */ @@ -2113,11 +2151,19 @@ io_write(word32 loc, int val, double *cyc_ptr) return; /* 0xc090 - 0xc09f */ - case 0x90: case 0x91: case 0x92: case 0x93: + case 0x90: + case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - UNIMPL_WRITE; + if (g_parallel) + { + return parallel_write((word16)loc & 0xf, (byte)val); + } + else + { + UNIMPL_WRITE; + } /* 0xc0a0 - 0xc0af */ case 0xa0: case 0xa1: case 0xa3: @@ -2128,17 +2174,43 @@ io_write(word32 loc, int val, double *cyc_ptr) case 0xa2: /* Burger Times writes here on error */ case 0xa8: /* Kurzweil SMP writes to 0xc0a8, ignore it */ + UNIMPL_WRITE; return; /* 0xc0b0 - 0xc0bf */ - case 0xb0: + //case 0xb0: /* Second sight stuff--ignore it */ return; - case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: + //case 0xb1: case 0xb2: case 0xb3: + //case 0xb4: case 0xb5: case 0xb6: case 0xb7: + //case 0xb8: case 0xb9: case 0xba: case 0xbb: + //case 0xbc: case 0xbd: case 0xbe: case 0xbf: + // UNIMPL_WRITE; + /*Uthernet write access on slot 3*/ + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + if (tfe_enabled) + { + return tfe_store((word16)loc & 0xf, (byte)val); + } + else + { UNIMPL_WRITE; + } /* 0xc0c0 - 0xc0cf */ case 0xc0: case 0xc1: case 0xc2: case 0xc3: diff --git a/src/objects.xib b/src/objects.xib index aa104c0..616ea10 100644 --- a/src/objects.xib +++ b/src/objects.xib @@ -9,12 +9,12 @@ main - GSPORTMAC + KEGSMAC - GSPORTMAC + KEGSMAC - About GSPORTMAC + About KEGSMAC 0 abou @@ -39,7 +39,7 @@ Configuration F4 0 KCFG - Enter GSport Configuration Panel + Enter KEGS Configuration Panel diff --git a/src/op_routs.h b/src/op_routs.h index ff89cb8..a8d6489 100644 --- a/src/op_routs.h +++ b/src/op_routs.h @@ -1,23 +1,12 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/************************************************************************/ +/* KEGS: Apple //gs Emulator */ +/* Copyright 2002 by Kent Dickey */ +/* */ +/* This code is covered by the GNU GPL */ +/* */ +/* The KEGS web page is kegs.sourceforge.net */ +/* You may contact the author at: kadickey@alumni.princeton.edu */ +/************************************************************************/ #ifdef ASM # ifdef INCLUDE_RCSID_S diff --git a/src/paddles.c b/src/paddles.c index b3db782..0fcfe26 100644 --- a/src/paddles.c +++ b/src/paddles.c @@ -1,23 +1,12 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/************************************************************************/ +/* KEGS: Apple //gs Emulator */ +/* Copyright 2002 by Kent Dickey */ +/* */ +/* This code is covered by the GNU GPL */ +/* */ +/* The KEGS web page is kegs.sourceforge.net */ +/* You may contact the author at: kadickey@alumni.princeton.edu */ +/************************************************************************/ const char rcsid_paddles_c[] = "@(#)$KmKId: paddles.c,v 1.14 2004-10-19 14:52:36-04 kentd Exp $"; diff --git a/src/parallel.c b/src/parallel.c new file mode 100644 index 0000000..08a4fc9 --- /dev/null +++ b/src/parallel.c @@ -0,0 +1,76 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 by GSport contributors + + Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +parallel.c + +This file handles the Apple II Parallel Card emulation in slot 1. Its very +basic, but allows for future support of redirecting the output to a real +parallel port, files, and additional types of emulated printers. +*/ + +#include "defc.h" +#include "printer.h" +extern int g_parallel_out_masking; +extern int g_vbl_count; +extern int g_printer_timeout; +int printer_vbl_count = 0; +int port_block = 0; + +byte parallel_read(word16 io_address) +{ + printf("parallel card status called at %x\n", io_address); + //since we only have a virtual printer, always return state as "Ready" + return 0xff; +} +void parallel_write(word16 io_address, byte val) +{ + //Mask MSB if user has it set. + if(g_parallel_out_masking) { + val = val & 0xfe; + } + printf("parallel card called at %x\n", io_address); + //send a byte to the virtual printer + //By default all output to $C090 gets sent to the printer + if (io_address == 0x00) + { + port_block = 1; + printer_loop(val); + printer_vbl_count = g_vbl_count+(g_printer_timeout*60); + port_block = 0; + } + return; +} + +//This function handles the automatic timeout of the virtual printer if an +//application doesn't send a form feed at the end of the page. It also +//allows multipage mode Postscript and native printer documents to +//print somewhat how a regular application would. +void printer_update() +{ + if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count) + { + printf("Calling printer_update and flushing!\n"); + printer_feed(); + printer_vbl_count = 0; + } + return; +} \ No newline at end of file diff --git a/src/parallel.rom b/src/parallel.rom new file mode 100644 index 0000000..78360af Binary files /dev/null and b/src/parallel.rom differ diff --git a/src/printer.cpp b/src/printer.cpp new file mode 100644 index 0000000..5bba120 --- /dev/null +++ b/src/printer.cpp @@ -0,0 +1,2046 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//Modified for the KEGS emulator by Christopher G. Mason 02/2010 +//Added support for configuring the built in printer fonts + +#include "printer.h" +#include +#include "support.h" +//#include "png.h" +//#pragma comment( lib, “libpng.lib” ) +//#pragma comment (lib, “zdll.lib” ) + +static CPrinter* defaultPrinter = NULL; + +#define PARAM16(I) (params[I+1]*256+params[I]) +#define PIXX ((Bitu)floor(curX*dpi+0.5)) +#define PIXY ((Bitu)floor(curY*dpi+0.5)) + +static Bit16u confdpi, confwidth, confheight; +static Bitu printer_timout; +static bool timeout_dirty; +static const char* document_path; +static char confoutputDevice[50]; +static bool confmultipageOutput; +extern "C" char* g_printer_font_roman; +extern "C" char* g_printer_font_sans; +extern "C" char* g_printer_font_courier; +extern "C" char* g_printer_font_prestige; +extern "C" char* g_printer_font_script; +extern "C" char* g_printer_font_ocra; +Bit8u paramc = '0'; + +#include "printer_charmaps.h" + +void CPrinter::FillPalette(Bit8u redmax, Bit8u greenmax, Bit8u bluemax, Bit8u colorID, SDL_Palette* pal) +{ + float red=redmax/30.9; + float green=greenmax/30.9; + float blue=bluemax/30.9; + + Bit8u colormask=colorID<<=5; + + for(int i = 0; i < 32;i++) { + pal->colors[i+colormask].r=255-(red*(float)i); + pal->colors[i+colormask].g=255-(green*(float)i); + pal->colors[i+colormask].b=255-(blue*(float)i); + } +} + +CPrinter::CPrinter(Bit16u dpi, Bit16u width, Bit16u height, char* output, bool multipageOutput) +{ + if (FT_Init_FreeType(&FTlib)) + { + page = NULL; + } + else + { + this->dpi = dpi; + this->output = output; + this->multipageOutput = multipageOutput; + + defaultPageWidth = (Real64)width/(Real64)10; + defaultPageHeight = (Real64)height/(Real64)10; + + // Create page + page = SDL_CreateRGBSurface( + SDL_SWSURFACE, + (Bitu)(defaultPageWidth*dpi), + (Bitu)(defaultPageHeight*dpi), + 8, + 0, + 0, + 0, + 0); + + // Set a grey palette + SDL_Palette* palette = page->format->palette; + + for (Bitu i=0; i<32; i++) + { + palette->colors[i].r =255; + palette->colors[i].g =255; + palette->colors[i].b =255; + } + // 0 = all white needed for logic 000 + FillPalette( 0, 0, 0, 1, palette); + // 1 = magenta* 001 + FillPalette( 0, 255, 0, 1, palette); + // 2 = cyan* 010 + FillPalette(255, 0, 0, 2, palette); + // 3 = "violet" 011 + FillPalette(255, 255, 0, 3, palette); + // 4 = yellow* 100 + FillPalette( 0, 0, 255, 4, palette); + // 5 = red 101 + FillPalette( 0, 255, 255, 5, palette); + // 6 = green 110 + FillPalette(255, 0, 255, 6, palette); + // 7 = black 111 + FillPalette(255, 255, 255, 7, palette); + + // yyyxxxxx bit pattern: yyy=color xxxxx = intensity: 31=max + // Printing colors on top of each other ORs them and gets the + // correct resulting color. + // i.e. magenta on blank page yyy=001 + // then yellow on magenta 001 | 100 = 101 = red + + color=COLOR_BLACK; + + curFont = NULL; + charRead = false; + autoFeed = false; + outputHandle = NULL; + + resetPrinter(); + + if (strcasecmp(output, "printer") == 0) + { +#if defined (WIN32) + // Show Print dialog to obtain a printer device context + + PRINTDLG pd; + pd.lStructSize = sizeof(PRINTDLG); + pd.hDevMode = (HANDLE) NULL; + pd.hDevNames = (HANDLE) NULL; + pd.Flags = PD_RETURNDC; + pd.hwndOwner = NULL; + pd.hDC = (HDC) NULL; + pd.nFromPage = 1; + pd.nToPage = 1; + pd.nMinPage = 0; + pd.nMaxPage = 0; + pd.nCopies = 1; + pd.hInstance = NULL; + pd.lCustData = 0L; + pd.lpfnPrintHook = (LPPRINTHOOKPROC) NULL; + pd.lpfnSetupHook = (LPSETUPHOOKPROC) NULL; + pd.lpPrintTemplateName = (LPCSTR) NULL; + pd.lpSetupTemplateName = (LPCSTR) NULL; + pd.hPrintTemplate = (HANDLE) NULL; + pd.hSetupTemplate = (HANDLE) NULL; + PrintDlg(&pd); + // TODO: what if user presses cancel? + printerDC = pd.hDC; +#endif + } + } +}; + +void CPrinter::resetPrinterHard() +{ + charRead = false; + resetPrinter(); +} + +void CPrinter::resetPrinter() +{ + color=COLOR_BLACK; + curX = curY = 0.0; + ESCSeen = false; + FSSeen = false; + ESCCmd = 0; + numParam = neededParam = 0; + topMargin = 0.0; + leftMargin = 0.0; + rightMargin = pageWidth = defaultPageWidth; + bottomMargin = pageHeight = defaultPageHeight; + lineSpacing = (Real64)1/6; + cpi = 10.0; + curCharTable = 1; + style = 0; + extraIntraSpace = 0.0; + printUpperContr = true; + bitGraph.remBytes = 0; + densk = 0; + densl = 1; + densy = 2; + densz = 3; + charTables[0] = 0; // Italics + charTables[1] = charTables[2] = charTables[3] = 437; + definedUnit = -1; + multipoint = false; + multiPointSize = 0.0; + multicpi = 0.0; + hmi = -1.0; + msb = 255; + numPrintAsChar = 0; + LQtypeFace = roman; + + selectCodepage(charTables[curCharTable]); + + updateFont(); + + newPage(false,true); + + // Default tabs => Each eight characters + for (Bitu i=0;i<32;i++) + horiztabs[i] = i*8*(1/(Real64)cpi); + numHorizTabs = 32; + + numVertTabs = 255; +} + + +CPrinter::~CPrinter(void) +{ + finishMultipage(); + if (page != NULL) + { + SDL_FreeSurface(page); + page = NULL; + FT_Done_FreeType(FTlib); + } +#if defined (WIN32) + DeleteDC(printerDC); +#endif +}; + +void CPrinter::selectCodepage(Bit16u cp) +{ + Bit16u *mapToUse = NULL; + + switch(cp) + { + case 0: // Italics, use cp437 + case 437: + mapToUse = (Bit16u*)&cp437Map; + break; + case 737: + mapToUse = (Bit16u*)&cp737Map; + break; + case 775: + mapToUse = (Bit16u*)&cp775Map; + break; + case 850: + mapToUse = (Bit16u*)&cp850Map; + break; + case 852: + mapToUse = (Bit16u*)&cp852Map; + break; + case 855: + mapToUse = (Bit16u*)&cp855Map; + break; + case 857: + mapToUse = (Bit16u*)&cp857Map; + break; + case 860: + mapToUse = (Bit16u*)&cp860Map; + break; + case 861: + mapToUse = (Bit16u*)&cp861Map; + break; + case 863: + mapToUse = (Bit16u*)&cp863Map; + break; + case 864: + mapToUse = (Bit16u*)&cp864Map; + break; + case 865: + mapToUse = (Bit16u*)&cp865Map; + break; + case 866: + mapToUse = (Bit16u*)&cp866Map; + break; + default: + //LOG(LOG_MISC,LOG_WARN)("Unsupported codepage %i. Using CP437 instead.", cp); + mapToUse = (Bit16u*)&cp437Map; + } + + for (int i=0; i<256; i++) + curMap[i] = mapToUse[i]; +} + +void CPrinter::updateFont() +{ + // char buffer[1000]; + if (curFont != NULL) + FT_Done_Face(curFont); + + char* fontName; + + switch (LQtypeFace) + { + case roman: + fontName = g_printer_font_roman; + break; + case sansserif: + fontName = g_printer_font_sans; + break; + case courier: + fontName = g_printer_font_courier; + break; + case prestige: + fontName = g_printer_font_prestige; + break; + case script: + fontName = g_printer_font_script; + break; + case ocra: + case ocrb: + fontName = g_printer_font_ocra; + break; + default: + fontName = g_printer_font_roman; + } + + if (FT_New_Face(FTlib, fontName, 0, &curFont)) + { + + printf("Unable to load font %s"); + //LOG_MSG("Unable to load font %s", fontName); + curFont = NULL; + } + + Real64 horizPoints = 10.5; + Real64 vertPoints = 10.5; + + if (!multipoint) { + actcpi = cpi; + /* + switch(style & (STYLE_CONDENSED|STYLE_PROP)) { + case STYLE_CONDENSED: // only condensed + if (cpi == 10.0) { + actcpi = 17.14; + horizPoints *= 10.0/17.14; + } else if(cpi == 12.0) { + actcpi = 20.0; + horizPoints *= 10.0/20.0; + vertPoints *= 10.0/12.0; + } else { + // ignored + } + break; + case STYLE_PROP|STYLE_CONDENSED: + horizPoints /= 2.0; + break; + case 0: // neither + case STYLE_PROP: // only proportional + horizPoints *= 10.0/cpi; + vertPoints *= 10.0/cpi; + break; + } + */ + if (!(style & STYLE_CONDENSED)) { + horizPoints *= 10.0/cpi; + vertPoints *= 10.0/cpi; + } + + if (!(style & STYLE_PROP)) { + if ((cpi == 10.0) && (style & STYLE_CONDENSED)) { + actcpi = 17.14; + horizPoints *= 10.0/17.14; + } + if ((cpi == 12.0) && (style & STYLE_CONDENSED)) { + actcpi = 20.0; + horizPoints *= 10.0/20.0; + vertPoints *= 10.0/12.0; + } + } else if (style & STYLE_CONDENSED) horizPoints /= 2.0; + + + if ((style & STYLE_DOUBLEWIDTH) || (style & STYLE_DOUBLEWIDTHONELINE)) { + actcpi /= 2.0; + horizPoints *= 2.0; + } + + if (style & STYLE_DOUBLEHEIGHT) vertPoints *= 2.0; + } else { // multipoint true + actcpi = multicpi; + horizPoints = vertPoints = multiPointSize; + } + + if ((style & STYLE_SUPERSCRIPT) || (style & STYLE_SUBSCRIPT)) { + horizPoints *= 2.0/3.0; + vertPoints *= 2.0/3.0; + actcpi /= 2.0/3.0; + } + + FT_Set_Char_Size(curFont, (Bit16u)horizPoints*64, (Bit16u)vertPoints*64, dpi, dpi); + + if (style & STYLE_ITALICS || charTables[curCharTable] == 0) + { + FT_Matrix matrix; + matrix.xx = 0x10000L; + matrix.xy = (FT_Fixed)(0.20 * 0x10000L); + matrix.yx = 0; + matrix.yy = 0x10000L; + FT_Set_Transform(curFont, &matrix, 0); + } +} + +bool CPrinter::processCommandChar(Bit8u ch) +{ + if (ESCSeen || FSSeen) + { + ESCCmd = ch; + if(FSSeen) ESCCmd |= 0x800; + ESCSeen = FSSeen = false; + numParam = 0; + + switch (ESCCmd) { + case 0x02: // Undocumented + case 0x0a: // Reverse line feed (ESC LF) + case 0x0c: // Return to top of current page (ESC FF) + case 0x0e: // Select double-width printing (one line) (ESC SO) + case 0x0f: // Select condensed printing (ESC SI) + case 0x23: // Cancel MSB control (ESC #) + case 0x30: // Select 1/8-inch line spacing (ESC 0) + case 0x31: // Select 7/60-inch line spacing (ESC 1) + case 0x32: // Select 1/6-inch line spacing (ESC 2) + case 0x34: // Select italic font (ESC 4) + case 0x35: // Cancel italic font (ESC 5) + case 0x36: // Enable printing of upper control codes (ESC 6) + case 0x37: // Enable upper control codes (ESC 7) + case 0x38: // Disable paper-out detector (ESC 8) + case 0x39: // Enable paper-out detector (ESC 9) + case 0x3c: // Unidirectional mode (one line) (ESC <) + case 0x3d: // Set MSB to 0 (ESC =) + case 0x3e: // Set MSB to 1 (ESC >) + case 0x40: // Initialize printer (ESC @) + case 0x45: // Select bold font (ESC E) + case 0x46: // Cancel bold font (ESC F) + case 0x47: // Select double-strike printing (ESC G) + case 0x48: // Cancel double-strike printing (ESC H) + case 0x4d: // Select 10.5-point, 12-cpi (ESC M) + case 0x4f: // Cancel bottom margin [conflict] (ESC O) + case 0x50: // Select 10.5-point, 10-cpi (ESC P) + case 0x54: // Cancel superscript/subscript printing (ESC T) + case 0x5e: // Enable printing of all character codes on next character (ESC ^) + case 0x67: // Select 10.5-point, 15-cpi (ESC g) + + case 0x834: // Select italic font (FS 4) (= ESC 4) + case 0x835: // Cancel italic font (FS 5) (= ESC 5) + case 0x846: // Select forward feed mode (FS F) + case 0x852: // Select reverse feed mode (FS R) + neededParam = 0; + break; + case 0x19: // Control paper loading/ejecting (ESC EM) + case 0x20: // Set intercharacter space (ESC SP) + case 0x21: // Master select (ESC !) + case 0x2b: // Set n/360-inch line spacing (ESC +) + case 0x2d: // Turn underline on/off (ESC -) + case 0x2f: // Select vertical tab channel (ESC /) + case 0x33: // Set n/180-inch line spacing (ESC 3) + case 0x41: // Set n/60-inch line spacing (ESC A) + case 0x43: // Set page length in lines (ESC C) + case 0x49: // Select character type and print pitch (ESC I) + case 0x4a: // Advance print position vertically (ESC J) + case 0x4e: // Set bottom margin (ESC N) + case 0x51: // Set right margin (ESC Q) + case 0x52: // Select an international character set (ESC R) + case 0x53: // Select superscript/subscript printing (ESC S) + case 0x55: // Turn unidirectional mode on/off (ESC U) + //case 0x56: // Repeat data (ESC V) + case 0x57: // Turn double-width printing on/off (ESC W) + case 0x61: // Select justification (ESC a) + case 0x66: // Absolute horizontal tab in columns [conflict] (ESC f) + case 0x68: // Select double or quadruple size (ESC h) + case 0x69: // Immediate print (ESC i) + case 0x6a: // Reverse paper feed (ESC j) + case 0x6b: // Select typeface (ESC k) + case 0x6c: // Set left margin (ESC 1) + case 0x70: // Turn proportional mode on/off (ESC p) + case 0x72: // Select printing color (ESC r) + case 0x73: // Low-speed mode on/off (ESC s) + case 0x74: // Select character table (ESC t) + case 0x77: // Turn double-height printing on/off (ESC w) + case 0x78: // Select LQ or draft (ESC x) + case 0x7e: // Select/Deselect slash zero (ESC ~) + + case 0x832: // Select 1/6-inch line spacing (FS 2) (= ESC 2) + case 0x833: // Set n/360-inch line spacing (FS 3) (= ESC +) + case 0x841: // Set n/60-inch line spacing (FS A) (= ESC A) + case 0x843: // Select LQ type style (FS C) (= ESC k) + case 0x845: // Select character width (FS E) + case 0x849: // Select character table (FS I) (= ESC t) + case 0x853: // Select High Speed/High Density elite pitch (FS S) + case 0x856: // Turn double-height printing on/off (FS V) (= ESC w) + neededParam = 1; + break; + case 0x24: // Set absolute horizontal print position (ESC $) + case 0x3f: // Reassign bit-image mode (ESC ?) + case 0x4b: // Select 60-dpi graphics (ESC K) + case 0x4c: // Select 120-dpi graphics (ESC L) + case 0x59: // Select 120-dpi, double-speed graphics (ESC Y) + case 0x5a: // Select 240-dpi graphics (ESC Z) + case 0x5c: // Set relative horizontal print position (ESC \) + case 0x63: // Set horizontal motion index (HMI) [conflict] (ESC c) + case 0x65: // Set vertical tab stops every n lines (ESC e) + case 0x85a: // Print 24-bit hex-density graphics (FS Z) + neededParam = 2; + break; + case 0x2a: // Select bit image (ESC *) + case 0x58: // Select font by pitch and point [conflict] (ESC X) + neededParam = 3; + break; + case 0x5b: // Select character height, width, line spacing + neededParam = 7; + break; + case 0x62: // Set vertical tabs in VFU channels (ESC b) + case 0x42: // Set vertical tabs (ESC B) + numVertTabs = 0; + return true; + case 0x44: // Set horizontal tabs (ESC D) + numHorizTabs = 0; + return true; + case 0x25: // Select user-defined set (ESC %) + case 0x26: // Define user-defined characters (ESC &) + case 0x3a: // Copy ROM to RAM (ESC :) + //LOG(LOG_MISC,LOG_ERROR)("User-defined characters not supported!"); + return true; + case 0x28: // Two bytes sequence + return true; + default: + /*LOG_MSG("PRINTER: Unknown command %c (%02Xh) %c , unable to skip parameters.", + (ESCCmd & 0x800)?"FS":"ESC",ESCCmd, ESCCmd);*/ + + neededParam = 0; + ESCCmd = 0; + return true; + } + + if (neededParam > 0) + return true; + } + + // Two bytes sequence + if (ESCCmd == '(') + { + ESCCmd = 0x200 + ch; + + switch (ESCCmd) + { + case 0x242: // Bar code setup and print (ESC (B) + case 0x25e: // Print data as characters (ESC (^) + neededParam = 2; + break; + case 0x255: // Set unit (ESC (U) + neededParam = 3; + break; + case 0x243: // Set page length in defined unit (ESC (C) + case 0x256: // Set absolute vertical print position (ESC (V) + case 0x276: // Set relative vertical print position (ESC (v) + neededParam = 4; + break; + case 0x274: // Assign character table (ESC (t) + case 0x22d: // Select line/score (ESC (-) + neededParam = 5; + break; + case 0x263: // Set page format (ESC (c) + neededParam = 6; + break; + default: + // ESC ( commands are always followed by a "number of parameters" word parameter + //LOG(LOG_MISC,LOG_ERROR) + printf("PRINTER: Skipping unsupported command ESC ( %c (%02X).", ESCCmd, ESCCmd); + neededParam = 2; + ESCCmd = 0x101; + return true; + } + + if (neededParam > 0) + return true; + } + + // Ignore VFU channel setting + if (ESCCmd == 0x62) { + ESCCmd = 0x42; + return true; + } + + // Collect vertical tabs + if (ESCCmd == 0x42) { + if (ch == 0 || (numVertTabs>0 && verttabs[numVertTabs-1] > (Real64)ch*lineSpacing)) // Done + ESCCmd = 0; + else + if (numVertTabs < 16) + verttabs[numVertTabs++] = (Real64)ch*lineSpacing; + } + + // Collect horizontal tabs + if (ESCCmd == 0x44) + { + if (ch == 0 || (numHorizTabs>0 && horiztabs[numHorizTabs-1] > (Real64)ch*(1/(Real64)cpi))) // Done + ESCCmd = 0; + else + if (numHorizTabs < 32) + horiztabs[numHorizTabs++] = (Real64)ch*(1/(Real64)cpi); + } + + if (numParam < neededParam) + { + params[numParam++] = ch; + + if (numParam < neededParam) + return true; + } + + if (ESCCmd != 0) + { + switch (ESCCmd) + { + case 0x02: // Undocumented + // Ignore + break; + case 0x0e: // Select double-width printing (one line) (ESC SO) + if (!multipoint) + { + hmi = -1; + style |= STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + break; + case 0x0f: // Select condensed printing (ESC SI) + if (!multipoint && (cpi!=15.0)) { + hmi = -1; + style |= STYLE_CONDENSED; + updateFont(); + } + break; + case 0x19: // Control paper loading/ejecting (ESC EM) + // We are not really loading paper, so most commands can be ignored + if (params[0] == 'R') + newPage(true,false); // TODO resetx? + break; + case 0x20: // Set intercharacter space (ESC SP) + if (!multipoint) + { + extraIntraSpace = (Real64)params[0] / (printQuality==QUALITY_DRAFT?120:180); + hmi = -1; + updateFont(); + } + break; + case 0x21: // Master select (ESC !) + cpi = params[0] & 0x01 ? 12:10; + + // Reset first seven bits + style &= 0xFF80; + if (params[0] & 0x02) + style |= STYLE_PROP; + if (params[0] & 0x04) + style |= STYLE_CONDENSED; + if (params[0] & 0x08) + style |= STYLE_BOLD; + if (params[0] & 0x10) + style |= STYLE_DOUBLESTRIKE; + if (params[0] & 0x20) + style |= STYLE_DOUBLEWIDTH; + if (params[0] & 0x40) + style |= STYLE_ITALICS; + if (params[0] & 0x80) + { + score = SCORE_SINGLE; + style |= STYLE_UNDERLINE; + } + + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x23: // Cancel MSB control (ESC #) + msb = 255; + break; + case 0x24: // Set absolute horizontal print position (ESC $) + { + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)60.0; + + Real64 newX = leftMargin + ((Real64)PARAM16(0)/unitSize); + if (newX <= rightMargin) + curX = newX; + } + break; + case 0x85a: // Print 24-bit hex-density graphics (FS Z) + setupBitImage(40, PARAM16(0)); + break; + case 0x2a: // Select bit image (ESC *) + setupBitImage(params[0], PARAM16(1)); + break; + case 0x2b: // Set n/360-inch line spacing (ESC +) + case 0x833: // Set n/360-inch line spacing (FS 3) + lineSpacing = (Real64)params[0]/360; + break; + case 0x2d: // Turn underline on/off (ESC -) + if (params[0] == 0 || params[0] == 48) + style &= ~STYLE_UNDERLINE; + if (params[0] == 1 || params[0] == 49) + { + style |= STYLE_UNDERLINE; + score = SCORE_SINGLE; + } + updateFont(); + break; + case 0x2f: // Select vertical tab channel (ESC /) + // Ignore + break; + case 0x30: // Select 1/8-inch line spacing (ESC 0) + lineSpacing = (Real64)1/8; + break; + case 0x32: // Select 1/6-inch line spacing (ESC 2) + lineSpacing = (Real64)1/6; + break; + case 0x33: // Set n/180-inch line spacing (ESC 3) + lineSpacing = (Real64)params[0]/180; + break; + case 0x34: // Select italic font (ESC 4) + style |= STYLE_ITALICS; + updateFont(); + break; + case 0x35: // Cancel italic font (ESC 5) + style &= ~STYLE_ITALICS; + updateFont(); + break; + case 0x36: // Enable printing of upper control codes (ESC 6) + printUpperContr = true; + break; + case 0x37: // Enable upper control codes (ESC 7) + printUpperContr = false; + break; + case 0x3c: // Unidirectional mode (one line) (ESC <) + // We don't have a print head, so just ignore this + break; + case 0x3d: // Set MSB to 0 (ESC =) + msb = 0; + break; + case 0x3e: // Set MSB to 1 (ESC >) + msb = 1; + break; + case 0x3f: // Reassign bit-image mode (ESC ?) + if (params[0] == 75) + densk = params[1]; + if (params[0] == 76) + densl = params[1]; + if (params[0] == 89) + densy = params[1]; + if (params[0] == 90) + densz = params[1]; + break; + case 0x40: // Initialize printer (ESC @) + resetPrinter(); + break; + case 0x41: // Set n/60-inch line spacing + case 0x841: + lineSpacing = (Real64)params[0]/60; + break; + case 0x43: // Set page length in lines (ESC C) + if (params[0] != 0) + pageHeight = bottomMargin = (Real64)params[0] * lineSpacing; + else // == 0 => Set page length in inches + { + neededParam = 1; + numParam = 0; + ESCCmd = 0x100; + return true; + } + break; + case 0x45: // Select bold font (ESC E) + style |= STYLE_BOLD; + updateFont(); + break; + case 0x46: // Cancel bold font (ESC F) + style &= ~STYLE_BOLD; + updateFont(); + break; + case 0x47: // Select dobule-strike printing (ESC G) + style |= STYLE_DOUBLESTRIKE; + break; + case 0x48: // Cancel double-strike printing (ESC H) + style &= ~STYLE_DOUBLESTRIKE; + break; + case 0x4a: // Advance print position vertically (ESC J n) + curY += (Real64)((Real64)params[0] / 180); + if (curY > bottomMargin) + newPage(true,false); + break; + case 0x4b: // Select 60-dpi graphics (ESC K) + setupBitImage(densk, PARAM16(0)); + break; + case 0x4c: // Select 120-dpi graphics (ESC L) + setupBitImage(densl, PARAM16(0)); + break; + case 0x4d: // Select 10.5-point, 12-cpi (ESC M) + cpi = 12; + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x4e: // Set bottom margin (ESC N) + topMargin = 0.0; + bottomMargin = (Real64)params[0] * lineSpacing; + break; + case 0x4f: // Cancel bottom (and top) margin + topMargin = 0.0; + bottomMargin = pageHeight; + break; + case 0x50: // Select 10.5-point, 10-cpi (ESC P) + cpi = 10; + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x51: // Set right margin + rightMargin = (Real64)(params[0]-1.0) / (Real64)cpi; + break; + case 0x52: // Select an international character set (ESC R) + if (params[0] <= 13 || params[0] == 64) + { + if (params[0] == 64) + params[0] = 14; + + curMap[0x23] = intCharSets[params[0]][0]; + curMap[0x24] = intCharSets[params[0]][1]; + curMap[0x40] = intCharSets[params[0]][2]; + curMap[0x5b] = intCharSets[params[0]][3]; + curMap[0x5c] = intCharSets[params[0]][4]; + curMap[0x5d] = intCharSets[params[0]][5]; + curMap[0x5e] = intCharSets[params[0]][6]; + curMap[0x60] = intCharSets[params[0]][7]; + curMap[0x7b] = intCharSets[params[0]][8]; + curMap[0x7c] = intCharSets[params[0]][9]; + curMap[0x7d] = intCharSets[params[0]][10]; + curMap[0x7e] = intCharSets[params[0]][11]; + } + break; + case 0x53: // Select superscript/subscript printing (ESC S) + if (params[0] == 0 || params[0] == 48) + style |= STYLE_SUBSCRIPT; + if (params[0] == 1 || params[1] == 49) + style |= STYLE_SUPERSCRIPT; + updateFont(); + break; + case 0x54: // Cancel superscript/subscript printing (ESC T) + style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT; + updateFont(); + break; + case 0x55: // Turn unidirectional mode on/off (ESC U) + // We don't have a print head, so just ignore this + break; + case 0x57: // Turn double-width printing on/off (ESC W) + if (!multipoint) + { + hmi = -1; + if (params[0] == 0 || params[0] == 48) + style &= ~STYLE_DOUBLEWIDTH; + if (params[0] == 1 || params[0] == 49) + style |= STYLE_DOUBLEWIDTH; + updateFont(); + } + break; + case 0x58: // Select font by pitch and point (ESC X) + multipoint = true; + // Copy currently non-multipoint CPI if no value was set so far + if (multicpi == 0) + multicpi = cpi; + if (params[0] > 0) // Set CPI + { + if (params[0] == 1) // Proportional spacing + style |= STYLE_PROP; + else if (params[0] >= 5) + multicpi = (Real64)360 / (Real64)params[0]; + } + if (multiPointSize == 0) + multiPointSize = (Real64)10.5; + if (PARAM16(1) > 0) // Set points + multiPointSize = ((Real64)PARAM16(1)) / 2; + updateFont(); + break; + case 0x59: // Select 120-dpi, double-speed graphics (ESC Y) + setupBitImage(densy, PARAM16(0)); + break; + case 0x5a: // Select 240-dpi graphics (ESC Z) + setupBitImage(densz, PARAM16(0)); + break; + case 0x5c: // Set relative horizontal print position (ESC \) + { + Bit16s toMove = PARAM16(0); + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)(printQuality==QUALITY_DRAFT?120.0:180.0); + curX += (Real64)((Real64)toMove / unitSize); + } + break; + case 0x61: // Select justification (ESC a) + // Ignore + break; + case 0x63: // Set horizontal motion index (HMI) (ESC c) + hmi = (Real64)PARAM16(0) / (Real64)360.0; + extraIntraSpace = 0.0; + break; + case 0x67: // Select 10.5-point, 15-cpi (ESC g) + cpi = 15; + hmi = -1; + multipoint = false; + updateFont(); + break; + case 0x846: // Select forward feed mode (FS F) - set reverse not implemented yet + if(lineSpacing < 0) lineSpacing *= -1; + break; + case 0x6a: // Reverse paper feed (ESC j) + { + Real64 reverse = (Real64)PARAM16(0) / (Real64)216.0; + reverse = curY - reverse; + if(reverse < leftMargin) curY = leftMargin; + else curY = reverse; + break; + } + case 0x6b: // Select typeface (ESC k) + paramc = params[0]-'0'; + //if (params[0] <= 11 || params[0] == 30 || params[0] == 31) + if (paramc <= 11 || paramc == 30 || paramc == 31) + LQtypeFace = (Typeface)paramc; + updateFont(); + break; + case 0x6c: // Set left margin (ESC l) + leftMargin = (Real64)(params[0]-1.0) / (Real64)cpi; + if (curX < leftMargin) + curX = leftMargin; + break; + case 0x70: // Turn proportional mode on/off (ESC p) + if (params[0] == 0 || params[0] == 48) + style &= (0xffff - STYLE_PROP); + if (params[0] == 1 || params[0] == 49) + { + style |= STYLE_PROP; + printQuality = QUALITY_LQ; + } + multipoint = false; + hmi = -1; + updateFont(); + break; + case 0x72: // Select printing color (ESC r) + + if(params[0]==0 || params[0] > 6) color = COLOR_BLACK; + else color = params[0]<<5; + break; + case 0x73: // Select low-speed mode (ESC s) + // Ignore + break; + case 0x74: // Select character table (ESC t) + case 0x849: // Select character table (FS I) + if (params[0] < 4) + curCharTable = params[0]; + if (params[0] >= 48 && params[0] <= 51) + curCharTable = params[0] - 48; + selectCodepage(charTables[curCharTable]); + updateFont(); + break; + case 0x77: // Turn double-height printing on/off (ESC w) + if (!multipoint) + { + if (params[0] == 0 || params[0] == 48) + style &= ~STYLE_DOUBLEHEIGHT; + if (params[0] == 1 || params[0] == 49) + style |= STYLE_DOUBLEHEIGHT; + updateFont(); + } + break; + case 0x78: // Select LQ or draft (ESC x) + if (params[0] == 0 || params[0] == 48) { + printQuality = QUALITY_DRAFT; + style |= STYLE_CONDENSED; + } + if (params[0] == 1 || params[0] == 49) { + printQuality = QUALITY_LQ; + style &= ~STYLE_CONDENSED; + } + hmi = -1; + updateFont(); + break; + case 0x100: // Set page length in inches (ESC C NUL) + pageHeight = (Real64)params[0]; + bottomMargin = pageHeight; + topMargin = 0.0; + break; + case 0x101: // Skip unsupported ESC ( command + neededParam = PARAM16(0); + numParam = 0; + break; + case 0x274: // Assign character table (ESC (t) + if (params[2] < 4 && params[3] < 16) + { + charTables[params[2]] = codepages[params[3]]; + //LOG_MSG("curr table: %d, p2: %d, p3: %d",curCharTable,params[2],params[3]); + if (params[2] == curCharTable) + selectCodepage(charTables[curCharTable]); + } + break; + case 0x22d: // Select line/score (ESC (-) + style &= ~(STYLE_UNDERLINE | STYLE_STRIKETHROUGH | STYLE_OVERSCORE); + score = params[4]; + if (score) + { + if (params[3] == 1) + style |= STYLE_UNDERLINE; + if (params[3] == 2) + style |= STYLE_STRIKETHROUGH; + if (params[3] == 3) + style |= STYLE_OVERSCORE; + } + updateFont(); + break; + case 0x242: // Bar code setup and print (ESC (B) + //LOG(LOG_MISC,LOG_ERROR)("PRINTER: Bardcode printing not supported"); + // Find out how many bytes to skip + neededParam = PARAM16(0); + numParam = 0; + break; + case 0x243: // Set page length in defined unit (ESC (C) + if (params[0] != 0 && definedUnit > 0) + { + pageHeight = bottomMargin = ((Real64)PARAM16(2)) * definedUnit; + topMargin = 0.0; + } + break; + case 0x255: // Set unit (ESC (U) + definedUnit = (Real64)params[2] / (Real64)3600; + break; + case 0x256: // Set absolute vertical print position (ESC (V) + { + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)360.0; + Real64 newPos = topMargin + (((Real64)PARAM16(2)) * unitSize); + if (newPos > bottomMargin) + newPage(true,false); + else + curY = newPos; + } + break; + case 0x25e: // Print data as characters (ESC (^) + numPrintAsChar = PARAM16(0); + break; + case 0x263: // Set page format (ESC (c) + if (definedUnit > 0) + { + Real64 newTop, newBottom; + newTop = ((Real64)PARAM16(2)) * definedUnit; + newBottom = ((Real64)PARAM16(4)) * definedUnit; + if(newTop >= newBottom) break; + if(newTop < pageHeight) topMargin = newTop; + if(newBottom < pageHeight) bottomMargin = newBottom; + if(topMargin > curY) curY = topMargin; + //LOG_MSG("du %d, p1 %d, p2 %d, newtop %f, newbott %f, nt %f, nb %f, ph %f", + // (Bitu)definedUnit,PARAM16(2),PARAM16(4),topMargin,bottomMargin, + // newTop,newBottom,pageHeight); + } + break; + case 0x276: // Set relative vertical print position (ESC (v) + { + Real64 unitSize = definedUnit; + if (unitSize < 0) + unitSize = (Real64)360.0; + Real64 newPos = curY + ((Real64)((Bit16s)PARAM16(2)) * unitSize); + if (newPos > topMargin) + { + if (newPos > bottomMargin) + newPage(true,false); + else + curY = newPos; + } + } + break; + default: + if (ESCCmd < 0x100); + //LOG(LOG_MISC,LOG_WARN) + //LOG_MSG("PRINTER: Skipped unsupported command ESC %c (%02X)", ESCCmd, ESCCmd); + else; + //LOG(LOG_MISC,LOG_WARN) + //LOG_MSG("PRINTER: Skipped unsupported command ESC ( %c (%02X)", ESCCmd-0x200, ESCCmd-0x200); + } + + ESCCmd = 0; + return true; + } + + switch (ch) + { + case 0x00: // NUL is ignored by the printer + return true; + case 0x07: // Beeper (BEL) + // BEEEP! + return true; + case 0x08: // Backspace (BS) + { + Real64 newX = curX - (1/(Real64)actcpi); + if (hmi > 0) + newX = curX - hmi; + if (newX >= leftMargin) + curX = newX; + } + return true; + case 0x09: // Tab horizontally (HT) + { + // Find tab right to current pos + Real64 moveTo = -1; + for (Bit8u i=0; i curX) + moveTo = horiztabs[i]; + // Nothing found => Ignore + if (moveTo > 0 && moveTo < rightMargin) + curX = moveTo; + } + return true; + case 0x0b: // Tab vertically (VT) + if (numVertTabs == 0) // All tabs cancelled => Act like CR + curX = leftMargin; + else if (numVertTabs == 255) // No tabs set since reset => Act like LF + { + curX = leftMargin; + curY += lineSpacing; + if (curY > bottomMargin) + newPage(true,false); + } + else + { + // Find tab below current pos + Real64 moveTo = -1; + for (Bit8u i=0; i curY) + moveTo = verttabs[i]; + + // Nothing found => Act like FF + if (moveTo > bottomMargin || moveTo < 0) + newPage(true,false); + else + curY = moveTo; + } + if (style & STYLE_DOUBLEWIDTHONELINE) + { + style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + return true; + case 0x0c: // Form feed (FF) + if (style & STYLE_DOUBLEWIDTHONELINE) + { + style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + newPage(true,true); + return true; + case 0x0d: // Carriage Return (CR) + curX = leftMargin; + if (!autoFeed) + return true; + case 0x0a: // Line feed + if (style & STYLE_DOUBLEWIDTHONELINE) + { + style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + curX = leftMargin; + curY += lineSpacing; + if (curY > bottomMargin) + newPage(true,false); + return true; + case 0x0e: //Select Real64-width printing (one line) (SO) + if (!multipoint) + { + hmi = -1; + style |= STYLE_DOUBLEWIDTHONELINE; + updateFont(); + } + return true; + case 0x0f: // Select condensed printing (SI) + if (!multipoint && (cpi!=15.0)) { + hmi = -1; + style |= STYLE_CONDENSED; + updateFont(); + } + return true; + case 0x11: // Select printer (DC1) + // Ignore + return true; + case 0x12: // Cancel condensed printing (DC2) + hmi = -1; + style &= ~STYLE_CONDENSED; + updateFont(); + return true; + case 0x13: // Deselect printer (DC3) + // Ignore + return true; + case 0x14: // Cancel double-width printing (one line) (DC4) + hmi = -1; + style &= ~STYLE_DOUBLEWIDTHONELINE; + updateFont(); + return true; + case 0x18: // Cancel line (CAN) + return true; + case 0x1b: // ESC + ESCSeen = true; + return true; + case 0x1c: // FS (IBM commands) + FSSeen = true; + return true; + default: + return false; + } + + return false; +} + +static void PRINTER_EventHandler(Bitu param); + +void CPrinter::newPage(bool save, bool resetx) +{ + //PIC_RemoveEvents(PRINTER_EventHandler); + if(printer_timout) timeout_dirty=false; + + if (save) + outputPage(); + + if(resetx) curX=leftMargin; + curY = topMargin; + + SDL_Rect rect; + rect.x = 0; + rect.y = 0; + rect.w = page->w; + rect.h = page->h; + SDL_FillRect(page, &rect, SDL_MapRGB(page->format, 255, 255, 255)); + + /*for(int i = 0; i < 256; i++) + { + *((Bit8u*)page->pixels+i)=i; + }*/ +} + +void CPrinter::printChar(Bit8u ch) +{ + charRead = true; + if (page == NULL) return; + // Don't think that DOS programs uses this but well: Apply MSB if desired + if (msb != 255) { + if (msb == 0) ch &= 0x7F; + if (msb == 1) ch |= 0x80; + } + + // Are we currently printing a bit graphic? + if (bitGraph.remBytes > 0) { + printBitGraph(ch); + return; + } + + // Print everything? + if (numPrintAsChar > 0) numPrintAsChar--; + else if (processCommandChar(ch)) return; + + // Do not print if no font is available + if (!curFont) return; + if(ch==0x1) ch=0x20; + + // Find the glyph for the char to render + FT_UInt index = FT_Get_Char_Index(curFont, curMap[ch]); + + // Load the glyph + FT_Load_Glyph(curFont, index, FT_LOAD_DEFAULT); + + // Render a high-quality bitmap + FT_Render_Glyph(curFont->glyph, FT_RENDER_MODE_NORMAL); + + Bit16u penX = PIXX + curFont->glyph->bitmap_left; + Bit16u penY = PIXY - curFont->glyph->bitmap_top + curFont->size->metrics.ascender/64; + + if (style & STYLE_SUBSCRIPT) penY += curFont->glyph->bitmap.rows / 2; + + // Copy bitmap into page + SDL_LockSurface(page); + + blitGlyph(curFont->glyph->bitmap, penX, penY, false); + blitGlyph(curFont->glyph->bitmap, penX+1, penY, true); + + // Doublestrike => Print the glyph a second time one pixel below + if (style & STYLE_DOUBLESTRIKE) { + blitGlyph(curFont->glyph->bitmap, penX, penY+1, true); + blitGlyph(curFont->glyph->bitmap, penX+1, penY+1, true); + } + + // Bold => Print the glyph a second time one pixel to the right + // or be a bit more bold... + if (style & STYLE_BOLD) { + blitGlyph(curFont->glyph->bitmap, penX+1, penY, true); + blitGlyph(curFont->glyph->bitmap, penX+2, penY, true); + blitGlyph(curFont->glyph->bitmap, penX+3, penY, true); + } + SDL_UnlockSurface(page); + + // For line printing + Bit16u lineStart = PIXX; + + // advance the cursor to the right + Real64 x_advance; + if (style & STYLE_PROP) + x_advance = (Real64)((Real64)(curFont->glyph->advance.x)/(Real64)(dpi*64)); + else { + if (hmi < 0) x_advance = 1/(Real64)actcpi; + else x_advance = hmi; + } + x_advance += extraIntraSpace; + curX += x_advance; + + // Draw lines if desired + if ((score != SCORE_NONE) && (style & + (STYLE_UNDERLINE|STYLE_STRIKETHROUGH|STYLE_OVERSCORE))) + { + // Find out where to put the line + Bit16u lineY = PIXY; + double height = (curFont->size->metrics.height>>6); // TODO height is fixed point madness... + + if (style & STYLE_UNDERLINE) lineY = PIXY + (Bit16u)(height*0.9); + else if (style & STYLE_STRIKETHROUGH) lineY = PIXY + (Bit16u)(height*0.45); + else if (style & STYLE_OVERSCORE) + lineY = PIXY - (((score == SCORE_DOUBLE)||(score == SCORE_DOUBLEBROKEN))?5:0); + + drawLine(lineStart, PIXX, lineY, score==SCORE_SINGLEBROKEN || score==SCORE_DOUBLEBROKEN); + + // draw second line if needed + if ((score == SCORE_DOUBLE)||(score == SCORE_DOUBLEBROKEN)) + drawLine(lineStart, PIXX, lineY + 5, score==SCORE_SINGLEBROKEN || score==SCORE_DOUBLEBROKEN); + } + // If the next character would go beyond the right margin, line-wrap. + if((curX + x_advance) > rightMargin) { + curX = leftMargin; + curY += lineSpacing; + if (curY > bottomMargin) newPage(true,false); + } +} + +void CPrinter::blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add) { + for (Bitu y=0; y 0 && (destx+x < page->w) && (desty+y < page->h) ) { + Bit8u* target = (Bit8u*)page->pixels + (x+destx) + (y+desty)*page->pitch; + source>>=3; + + if (add) { + if (((*target)&0x1f )+ source > 31) *target |= (color|0x1f); + else { + *target += source; + *target |= color; + } + } + else *target = source|color; + } + } + } +} + +void CPrinter::drawLine(Bitu fromx, Bitu tox, Bitu y, bool broken) +{ + SDL_LockSurface(page); + + Bitu breakmod = dpi / 15; + Bitu gapstart = (breakmod * 4)/5; + + // Draw anti-aliased line + for (Bitu x=fromx; x<=tox; x++) + { + // Skip parts if broken line or going over the border + if ((!broken || (x%breakmod <= gapstart)) && (x < page->w)) + { + if (y > 0 && (y-1) < page->h) + *((Bit8u*)page->pixels + x + (y-1)*page->pitch) = 240; + if (y < page->h) + *((Bit8u*)page->pixels + x + y*page->pitch) = !broken?255:240; + if (y+1 < page->h) + *((Bit8u*)page->pixels + x + (y+1)*page->pitch) = 240; + } + } + SDL_UnlockSurface(page); +} + +void CPrinter::setAutofeed(bool feed) { + autoFeed = feed; +} + +bool CPrinter::getAutofeed() { + return autoFeed; +} + +bool CPrinter::isBusy() { + // We're never busy + return false; +} + +bool CPrinter::ack() { + // Acknowledge last char read + if(charRead) { + charRead=false; + return true; + } + return false; +} + +void CPrinter::setupBitImage(Bit8u dens, Bit16u numCols) { + switch (dens) + { + case 0: + bitGraph.horizDens = 60; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 1: + bitGraph.horizDens = 120; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 2: + bitGraph.horizDens = 120; + bitGraph.vertDens = 60; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 1; + break; + case 3: + bitGraph.horizDens = 60; + bitGraph.vertDens = 240; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 1; + break; + case 4: + bitGraph.horizDens = 80; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 6: + bitGraph.horizDens = 90; + bitGraph.vertDens = 60; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 1; + break; + case 32: + bitGraph.horizDens = 60; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 33: + bitGraph.horizDens = 120; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 38: + bitGraph.horizDens = 90; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 39: + bitGraph.horizDens = 180; + bitGraph.vertDens = 180; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 3; + break; + case 40: + bitGraph.horizDens = 360; + bitGraph.vertDens = 180; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 3; + break; + case 71: + bitGraph.horizDens = 180; + bitGraph.vertDens = 360; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 6; + break; + case 72: + bitGraph.horizDens = 360; + bitGraph.vertDens = 360; + bitGraph.adjacent = false; + bitGraph.bytesColumn = 6; + break; + case 73: + bitGraph.horizDens = 360; + bitGraph.vertDens = 360; + bitGraph.adjacent = true; + bitGraph.bytesColumn = 6; + break; + default: + //break; + printf("PRINTER: Unsupported bit image density"); + } + + bitGraph.remBytes = numCols * bitGraph.bytesColumn; + bitGraph.readBytesColumn = 0; +} + +void CPrinter::printBitGraph(Bit8u ch) +{ + bitGraph.column[bitGraph.readBytesColumn++] = ch; + bitGraph.remBytes--; + + // Only print after reading a full column + if (bitGraph.readBytesColumn < bitGraph.bytesColumn) + return; + + Real64 oldY = curY; + + SDL_LockSurface(page); + + // When page dpi is greater than graphics dpi, the drawn pixels get "bigger" + Bitu pixsizeX=1; + Bitu pixsizeY=1; + if(bitGraph.adjacent) { + pixsizeX = dpi/bitGraph.horizDens > 0? dpi/bitGraph.horizDens : 1; + pixsizeY = dpi/bitGraph.vertDens > 0? dpi/bitGraph.vertDens : 1; + } + // TODO figure this out for 360dpi mode in windows + +// Bitu pixsizeX = dpi/bitGraph.horizDens > 0? dpi/bitGraph.horizDens : 1; +// Bitu pixsizeY = dpi/bitGraph.vertDens > 0? dpi/bitGraph.vertDens : 1; + + for (Bitu i=0; i>=1) { // for each bit + if (bitGraph.column[i] & j) { + for (Bitu xx=0; xxw) && ((PIXY + yy) < page->h)) + *((Bit8u*)page->pixels + (PIXX+xx) + (PIXY+yy)*page->pitch) |= (color|0x1F); + } + } // else white pixel + + curY += (Real64)1/(Real64)bitGraph.vertDens; // TODO line wrap? + } + } + SDL_UnlockSurface(page); + + curY = oldY; + + bitGraph.readBytesColumn = 0; + + // Advance to the left + curX += (Real64)1/(Real64)bitGraph.horizDens; +} + +void CPrinter::formFeed() +{ + // Don't output blank pages + newPage(!isBlank(),true); + + finishMultipage(); +} + +static void findNextName(char* front, char* ext, char* fname) +{ + document_path = ""; + Bitu i = 1; + Bitu slen = strlen(document_path); + if(slen>(200-15)) { + fname[0]=0; + return; + } + FILE *test = NULL; + do + { + strcpy(fname, document_path); + printf(fname); +#ifdef WIN32 + const char* const pathstring = ".\\%s%d%s"; +#else + const char* const pathstring = "/%s%d%s"; +#endif + sprintf(fname+strlen(fname), pathstring, front,i++,ext); + test = fopen(fname, "rb"); + if (test != NULL) + fclose(test); + } + while (test != NULL ); +} + +void CPrinter::outputPage() +{ +/* SDL_Surface *screen; + +screen = SDL_SetVideoMode(1024, 768, 16, SDL_DOUBLEBUF | SDL_RESIZABLE); +if (screen == NULL) { + printf("Unable to set video mode: %s\n", SDL_GetError()); +} +SDL_Surface *image; +SDL_LockSurface(page); +image = SDL_DisplayFormat(page); +SDL_UnlockSurface(page); +SDL_Rect src, dest; + +src.x = 0; +src.y = 0; +src.w = image->w; +src.h = image->h; + +dest.x = 100; +dest.y = 100; +dest.w = image->w; +dest.h = image->h; + +SDL_BlitSurface(image, &src, screen, &dest); +SDL_Flip(screen); + +SDL_Delay(2000); +SDL_FreeSurface(image);*/ + + char fname[200]; + if (strcasecmp(output, "printer") == 0) + { +#if defined (WIN32) + + Bit16u physW = GetDeviceCaps(printerDC, PHYSICALWIDTH); + Bit16u physH = GetDeviceCaps(printerDC, PHYSICALHEIGHT); + + Real64 scaleW, scaleH; + + if (page->w > physW) + scaleW = (Real64)page->w / (Real64)physW; + else + scaleW = (Real64)physW / (Real64)page->w; + + if (page->h > physH) + scaleH = (Real64)page->h / (Real64)physH; + else + scaleH = (Real64)physH / (Real64)page->h; + + HDC memHDC = CreateCompatibleDC(printerDC); + BITMAPINFO *BitmapInfo; + HBITMAP bitmap; + + // Start new printer job? + if (outputHandle == NULL) + { + DOCINFO docinfo; + docinfo.cbSize = sizeof(docinfo); + docinfo.lpszDocName = "KEGS Virtual Printer"; + docinfo.lpszOutput = NULL; + docinfo.lpszDatatype = NULL; + docinfo.fwType = 0; + + StartDoc(printerDC, &docinfo); + multiPageCounter = 1; + } + SDL_LockSurface(page); + StartPage(printerDC); + DWORD TotalSize; + HGDIOBJ Prev; + void* Pixels; + BitmapInfo = (BITMAPINFO*) + malloc (sizeof (BITMAPINFO)+255*sizeof (RGBQUAD)); + memset (BitmapInfo,0,sizeof (bitmap)); + BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + BitmapInfo->bmiHeader.biWidth = page->w; + BitmapInfo->bmiHeader.biHeight = -page->h; + BitmapInfo->bmiHeader.biPlanes = 1; + BitmapInfo->bmiHeader.biBitCount = page->format->BitsPerPixel; + BitmapInfo->bmiHeader.biCompression = BI_RGB; + BitmapInfo->bmiHeader.biSizeImage = page->h * page->pitch; + BitmapInfo->bmiHeader.biXPelsPerMeter = 0; + BitmapInfo->bmiHeader.biYPelsPerMeter = 0; + BitmapInfo->bmiHeader.biClrUsed = page->format->palette->ncolors; + BitmapInfo->bmiHeader.biClrImportant = 0; + if (page->format->palette) { + for (int I=0; Iformat->palette->ncolors; I++) { + BitmapInfo->bmiColors[I].rgbRed = + (page->format->palette->colors+I)->r; + BitmapInfo->bmiColors[I].rgbGreen = + (page->format->palette->colors+I)->g; + BitmapInfo->bmiColors[I].rgbBlue = + (page->format->palette->colors+I)->b; + } + } + memHDC = CreateCompatibleDC(printerDC); + if (memHDC) { + bitmap = CreateDIBSection(memHDC, BitmapInfo, DIB_RGB_COLORS, + (&Pixels), NULL, 0); + if (bitmap) { + memcpy (Pixels, page->pixels, + BitmapInfo->bmiHeader.biSizeImage); + Prev = SelectObject (memHDC, bitmap); + StretchBlt(printerDC, 0, 0, physW, physH, memHDC, 0, 0, page->w, page->h, SRCCOPY); + SelectObject (memHDC,Prev); + DeleteObject (bitmap); + } + } + free (BitmapInfo); + SDL_UnlockSurface(page); + EndPage(printerDC); + + if (multipageOutput) + { + multiPageCounter++; + outputHandle = printerDC; + } + else + { + EndDoc(printerDC); + outputHandle = NULL; + } + DeleteObject(bitmap); + DeleteDC(memHDC); +#else + //LOG_MSG("PRINTER: Direct printing not supported under this OS"); +#endif + } +#ifdef C_LIBPNG + else if (strcasecmp(output, "png") == 0) + { + // Find a page that does not exists + findNextName("page", ".png", &fname[0]); + + png_structp png_ptr; + png_infop info_ptr; + png_bytep * row_pointers; + png_color palette[256]; + Bitu i; + + /* Open the actual file */ + FILE * fp=fopen(fname,"wb"); + if (!fp) + { + //LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname); + return; + } + + /* First try to alloacte the png structures */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); + if (!png_ptr) return; + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)NULL); + return; + } + + /* Finalize the initing of png library */ + png_init_io(png_ptr, fp); + png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192); + + + png_set_IHDR(png_ptr, info_ptr, page->w, page->h, + 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + for (i=0;i<256;i++) + { + palette[i].red = page->format->palette->colors[i].r; + palette[i].green = page->format->palette->colors[i].g; + palette[i].blue = page->format->palette->colors[i].b; + } + png_set_PLTE(png_ptr, info_ptr, palette,256); + png_set_packing(png_ptr); + SDL_LockSurface(page); + + // Allocate an array of scanline pointers + row_pointers = (png_bytep*)malloc(page->h*sizeof(png_bytep)); + for (i=0; ih; i++) + row_pointers[i] = ((Bit8u*)page->pixels+(i*page->pitch)); + + // tell the png library what to encode. + png_set_rows(png_ptr, info_ptr, row_pointers); + + // Write image to file + png_write_png(png_ptr, info_ptr, 0, NULL); + + + + + SDL_UnlockSurface(page); + + /*close file*/ + fclose(fp); + + /*Destroy PNG structs*/ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /*clean up dynamically allocated RAM.*/ + free(row_pointers); + } +#endif + else if (strcasecmp(output, "ps") == 0) + { + FILE* psfile = NULL; + + // Continue postscript file? + if (outputHandle != NULL) + psfile = (FILE*)outputHandle; + + // Create new file? + if (psfile == NULL) + { + if (!multipageOutput) + findNextName("page", ".ps", &fname[0]); + else + findNextName("doc", ".ps", &fname[0]); + + psfile = fopen(fname, "wb"); + if (!psfile) + { + //LOG(LOG_MISC,LOG_ERROR)("PRINTER: Can't open file %s for printer output", fname); + return; + } + + // Print header + fprintf(psfile, "%%!PS-Adobe-3.0\n"); + fprintf(psfile, "%%%%Pages: (atend)\n"); + fprintf(psfile, "%%%%BoundingBox: 0 0 %i %i\n", (Bit16u)(defaultPageWidth*74), (Bit16u)(defaultPageHeight*74)); + fprintf(psfile, "%%%%Creator: KEGS Virtual Printer\n"); + fprintf(psfile, "%%%%DocumentData: Clean7Bit\n"); + fprintf(psfile, "%%%%LanguageLevel: 2\n"); + fprintf(psfile, "%%%%EndComments\n"); + multiPageCounter = 1; + } + + fprintf(psfile, "%%%%Page: %i %i\n", multiPageCounter, multiPageCounter); + fprintf(psfile, "%i %i scale\n", (Bit16u)(defaultPageWidth*74), (Bit16u)(defaultPageHeight*74)); + fprintf(psfile, "%i %i 8 [%i 0 0 -%i 0 %i]\n", page->w, page->h, page->w, page->h, page->h); + fprintf(psfile, "currentfile\n"); + fprintf(psfile, "/ASCII85Decode filter\n"); + fprintf(psfile, "/RunLengthDecode filter\n"); + fprintf(psfile, "image\n"); + + SDL_LockSurface(page); + + Bit32u pix = 0; + Bit32u numpix = page->h*page->w; + ASCII85BufferPos = ASCII85CurCol = 0; + + while (pix < numpix) + { + // Compress data using RLE + + if ((pix < numpix-2) && (getPixel(pix) == getPixel(pix+1)) && (getPixel(pix) == getPixel(pix+2))) + { + // Found three or more pixels with the same color + Bit8u sameCount = 3; + Bit8u col = getPixel(pix); + while (sameCount < 128 && sameCount+pix < numpix && col == getPixel(pix+sameCount)) + sameCount++; + + fprintASCII85(psfile, 257-sameCount); + fprintASCII85(psfile, 255-col); + + // Skip ahead + pix += sameCount; + } + else + { + // Find end of heterogenous area + Bit8u diffCount = 1; + while (diffCount < 128 && diffCount+pix < numpix && + ( + (diffCount+pix < numpix-2) + || (getPixel(pix+diffCount) != getPixel(pix+diffCount+1)) + || (getPixel(pix+diffCount) != getPixel(pix+diffCount+2)) + )) + diffCount++; + + fprintASCII85(psfile, diffCount-1); + for (Bit8u i=0; i= 79) + { + ASCII85CurCol = 0; + fprintf(f, "\n"); + } + } + else + { + char buffer[5]; + for (Bit8s i=4; i>=0; i--) + { + buffer[i] = (Bit8u)((Bit32u)num % (Bit32u)85); + buffer[i] += 33; + num /= (Bit32u)85; + } + + // Make sure a line never starts with a % (which may be mistaken as start of a comment) + if (ASCII85CurCol == 0 && buffer[0] == '%') + fprintf(f, " "); + + for (int i=0; i<((b != 257)?5:ASCII85BufferPos+1); i++) + { + fprintf(f, "%c", buffer[i]); + if (++ASCII85CurCol >= 79) + { + ASCII85CurCol = 0; + fprintf(f, "\n"); + } + } + } + + ASCII85BufferPos = 0; + } + + } + else // Close string + { + // Partial tupel if there are still bytes in the buffer + if (ASCII85BufferPos > 0) + { + for (Bit8u i = ASCII85BufferPos; i < 4; i++) + ASCII85Buffer[i] = 0; + + fprintASCII85(f, 257); + } + + fprintf(f, "~"); + fprintf(f, ">\n"); + } +} + +void CPrinter::finishMultipage() +{ + if (outputHandle != NULL) + { + if (strcasecmp(output, "ps") == 0) + { + FILE* psfile = (FILE*)outputHandle; + fprintf(psfile, "%%%%Pages: %i\n", multiPageCounter); + fprintf(psfile, "%%%%EOF\n"); + fclose(psfile); + } + else if (strcasecmp(output, "printer") == 0) + { +#if defined (WIN32) + EndDoc(printerDC); +#endif + } + outputHandle = NULL; + } +} + +bool CPrinter::isBlank() { + bool blank = true; + SDL_LockSurface(page); + + for (Bit16u y=0; yh; y++) + for (Bit16u x=0; xw; x++) + if (*((Bit8u*)page->pixels + x + (y*page->pitch)) != 0) + blank = false; + + SDL_UnlockSurface(page); + return blank; +} + +Bit8u CPrinter::getPixel(Bit32u num) { + Bit32u pixel = *((Bit8u*)page->pixels + (num % page->w) + ((num / page->w) * page->pitch)); + return *((Bit8u*)page->pixels + (num % page->w) + ((num / page->w) * page->pitch)); +} + +//Interfaces to C code + + +extern "C" void printer_init(int pdpi, int pwidth, int pheight, char* poutput, bool mpage) +{ + if (defaultPrinter != NULL) return; + defaultPrinter = new CPrinter(pdpi, pwidth,pheight, poutput, mpage); +} +extern "C" void printer_loop(Bit8u pchar) +{ + if (defaultPrinter == NULL) return; + defaultPrinter->printChar(pchar); +} + +extern "C" void printer_close() +{ + delete defaultPrinter; + defaultPrinter = NULL; +} +extern "C" void printer_feed() +{ + if(defaultPrinter == NULL) return; + defaultPrinter->formFeed(); +} \ No newline at end of file diff --git a/src/printer.h b/src/printer.h new file mode 100644 index 0000000..7bf7812 --- /dev/null +++ b/src/printer.h @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//#include +//#include "config.h" + + + +#if !defined __PRINTER_H +#define __PRINTER_H +#ifdef __cplusplus +#ifdef C_LIBPNG +#include +#endif + +#include "SDL.h" + +#include +#include FT_FREETYPE_H + +#if defined (WIN32) +#include +#include +#endif + +#define STYLE_PROP 0x01 +#define STYLE_CONDENSED 0x02 +#define STYLE_BOLD 0x04 +#define STYLE_DOUBLESTRIKE 0x08 +#define STYLE_DOUBLEWIDTH 0x10 +#define STYLE_ITALICS 0x20 +#define STYLE_UNDERLINE 0x40 +#define STYLE_SUPERSCRIPT 0x80 +#define STYLE_SUBSCRIPT 0x100 +#define STYLE_STRIKETHROUGH 0x200 +#define STYLE_OVERSCORE 0x400 +#define STYLE_DOUBLEWIDTHONELINE 0x800 +#define STYLE_DOUBLEHEIGHT 0x1000 + +#define SCORE_NONE 0x00 +#define SCORE_SINGLE 0x01 +#define SCORE_DOUBLE 0x02 +#define SCORE_SINGLEBROKEN 0x05 +#define SCORE_DOUBLEBROKEN 0x06 + +#define QUALITY_DRAFT 0x01 +#define QUALITY_LQ 0x02 + +#define COLOR_BLACK 7<<5 +typedef unsigned Bitu; +typedef signed Bits; +typedef unsigned char Bit8u; +typedef signed char Bit8s; +typedef unsigned short Bit16u; +typedef signed short Bit16s; +typedef unsigned long Bit32u; +typedef signed long Bit32s; +typedef double Real64; +#if defined(_MSC_VER) +typedef unsigned __int64 Bit64u; +typedef signed __int64 Bit64s; +#else +typedef unsigned long long int Bit64u; +typedef signed long long int Bit64s; +#endif +enum Typeface +{ + roman = 0, + sansserif, + courier, + prestige, + script, + ocrb, + ocra, + orator, + orators, + scriptc, + romant, + sansserifh, + svbusaba = 30, + svjittra = 31 +}; + +typedef struct { + Bitu codepage; + const Bit16u* map; +} CHARMAP; + + +class CPrinter { +public: + + CPrinter (Bit16u dpi, Bit16u width, Bit16u height, char* output, bool multipageOutput); + virtual ~CPrinter(); + + // Process one character sent to virtual printer + void printChar(Bit8u ch); + + // Hard Reset (like switching printer off and on) + void resetPrinterHard(); + + // Set Autofeed value + void setAutofeed(bool feed); + + // Get Autofeed value + bool getAutofeed(); + + // True if printer is unable to process more data right now (do not use printChar) + bool isBusy(); + + // True if the last sent character was received + bool ack(); + + // Manual formfeed + void formFeed(); + + // Returns true if the current page is blank + bool isBlank(); + +private: + + // used to fill the color "sub-pallettes" + void FillPalette(Bit8u redmax, Bit8u greenmax, Bit8u bluemax, Bit8u colorID, + SDL_Palette* pal); + + // Checks if given char belongs to a command and process it. If false, the character + // should be printed + bool processCommandChar(Bit8u ch); + + // Resets the printer to the factory settings + void resetPrinter(); + + // Reload font. Must be called after changing dpi, style or cpi + void updateFont(); + + // Clears page. If save is true, saves the current page to a bitmap + void newPage(bool save, bool resetx); + + // Blits the given glyph on the page surface. If add is true, the values of bitmap are + // added to the values of the pixels in the page + void blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add); + + // Draws an anti-aliased line from (fromx, y) to (tox, y). If broken is true, gaps are included + void drawLine(Bitu fromx, Bitu tox, Bitu y, bool broken); + + // Setup the bitGraph structure + void setupBitImage(Bit8u dens, Bit16u numCols); + + // Process a character that is part of bit image. Must be called iff bitGraph.remBytes > 0. + void printBitGraph(Bit8u ch); + + // Copies the codepage mapping from the constant array to CurMap + void selectCodepage(Bit16u cp); + + // Output current page + void outputPage(); + + // Prints out a byte using ASCII85 encoding (only outputs something every four bytes). When b>255, closes the ASCII85 string + void fprintASCII85(FILE* f, Bit16u b); + + // Closes a multipage document + void finishMultipage(); + + // Returns value of the num-th pixel (couting left-right, top-down) in a safe way + Bit8u getPixel(Bit32u num); + + FT_Library FTlib; // FreeType2 library used to render the characters + + SDL_Surface* page; // Surface representing the current page + FT_Face curFont; // The font currently used to render characters + Bit8u color; + + Real64 curX, curY; // Position of the print head (in inch) + + Bit16u dpi; // dpi of the page + Bit16u ESCCmd; // ESC-command that is currently processed + bool ESCSeen; // True if last read character was an ESC (0x1B) + bool FSSeen; // True if last read character was an FS (0x1C) (IBM commands) + + Bit8u numParam, neededParam; // Numbers of parameters already read/needed to process command + + Bit8u params[20]; // Buffer for the read params + Bit16u style; // Style of font (see STYLE_* constants) + Real64 cpi, actcpi; // CPI value set by program and the actual one (taking in account font types) + Bit8u score; // Score for lines (see SCORE_* constants) + + Real64 topMargin, bottomMargin, rightMargin, leftMargin; // Margins of the page (in inch) + Real64 pageWidth, pageHeight; // Size of page (in inch) + Real64 defaultPageWidth, defaultPageHeight; // Default size of page (in inch) + Real64 lineSpacing; // Size of one line (in inch) + + Real64 horiztabs[32]; // Stores the set horizontal tabs (in inch) + Bit8u numHorizTabs; // Number of configured tabs + + Real64 verttabs[16]; // Stores the set vertical tabs (in inch) + Bit8u numVertTabs; // Number of configured tabs + + Bit8u curCharTable; // Currently used char table und charset + Bit8u printQuality; // Print quality (see QUALITY_* constants) + + Typeface LQtypeFace; // Typeface used in LQ printing mode + + Real64 extraIntraSpace; // Extra space between two characters (set by program, in inch) + + bool charRead; // True if a character was read since the printer was last initialized + bool autoFeed; // True if a LF should automatically added after a CR + bool printUpperContr; // True if the upper command characters should be printed + + struct bitGraphicParams // Holds information about printing bit images + { + Bit16u horizDens, vertDens; // Density of image to print (in dpi) + bool adjacent; // Print adjacent pixels? (ignored) + Bit8u bytesColumn; // Bytes per column + Bit16u remBytes; // Bytes left to read before image is done + Bit8u column[6]; // Bytes of the current and last column + Bit8u readBytesColumn; // Bytes read so far for the current column + } bitGraph; + + Bit8u densk, densl, densy, densz; // Image density modes used in ESC K/L/Y/Z commands + + Bit16u curMap[256]; // Currently used ASCII => Unicode mapping + Bit16u charTables[4]; // Charactertables + + Real64 definedUnit; // Unit used by some ESC/P2 commands (negative => use default) + + bool multipoint; // If multipoint mode is enabled + Real64 multiPointSize; // Point size of font in multipoint mode + Real64 multicpi; // CPI used in multipoint mode + + Real64 hmi; // Horizontal motion index (in inch; overrides CPI settings) + + Bit8u msb; // MSB mode + Bit16u numPrintAsChar; // Number of bytes to print as characters (even when normally control codes) + +#if defined (WIN32) + HDC printerDC; // Win32 printer device +#endif + + char* output; // Output method selected by user + void* outputHandle; // If not null, additional pages will be appended to the given handle + bool multipageOutput; // If true, all pages are combined to one file/print job etc. until the "eject page" button is pressed + Bit16u multiPageCounter; // Current page (when printing multipages) + + Bit8u ASCII85Buffer[4]; // Buffer used in ASCII85 encoding + Bit8u ASCII85BufferPos; // Position in ASCII85 encode buffer + Bit8u ASCII85CurCol; // Columns printed so far in the current lines +}; + + +//Interfaces to C code +#ifdef __cplusplus +extern "C" +{ +#endif +void printer_init(int pdpi, int pwidth, int pheight, char* poutput, bool mpage); +void printer_loop(Bit8u pchar); +void printer_close(); +void printer_feed(); +#ifdef __cplusplus +} +#endif + +#endif +#endif diff --git a/src/printer_charmaps.h b/src/printer_charmaps.h new file mode 100644 index 0000000..74d42d0 --- /dev/null +++ b/src/printer_charmaps.h @@ -0,0 +1,327 @@ +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 by GSport contributors + + Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// Various ASCII codepage to unicode maps + +static const Bit16u cp437Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp737Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,0x03a0, +0x03a1,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8, +0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03c0,0x03c1,0x03c3,0x03c2,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03c9,0x03ac,0x03ad,0x03ae,0x03ca,0x03af,0x03cc,0x03cd,0x03cb,0x03ce,0x0386,0x0388,0x0389,0x038a,0x038c,0x038e, +0x038f,0x00b1,0x2265,0x2264,0x03aa,0x03ab,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp775Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0106,0x00fc,0x00e9,0x0101,0x00e4,0x0123,0x00e5,0x0107,0x0142,0x0113,0x0156,0x0157,0x012b,0x0179,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x014d,0x00f6,0x0122,0x00a2,0x015a,0x015b,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x00a4, +0x0100,0x012a,0x00f3,0x017b,0x017c,0x017a,0x201d,0x00a6,0x00a9,0x00ae,0x00ac,0x00bd,0x00bc,0x0141,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x0104,0x010c,0x0118,0x0116,0x2563,0x2551,0x2557,0x255d,0x012e,0x0160,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0172,0x016a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x017d, +0x0105,0x010d,0x0119,0x0117,0x012f,0x0161,0x0173,0x016b,0x017e,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x00d3,0x00df,0x014c,0x0143,0x00f5,0x00d5,0x00b5,0x0144,0x0136,0x0137,0x013b,0x013c,0x0146,0x0112,0x0145,0x2019, +0x00ad,0x00b1,0x201c,0x00be,0x00b6,0x00a7,0x00f7,0x201e,0x00b0,0x2219,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp850Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x00f0,0x00d0,0x00ca,0x00cb,0x00c8,0x0131,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580, +0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x00fe,0x00de,0x00da,0x00db,0x00d9,0x00fd,0x00dd,0x00af,0x00b4, +0x00ad,0x00b1,0x2017,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp852Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x016f,0x0107,0x00e7,0x0142,0x00eb,0x0150,0x0151,0x00ee,0x0179,0x00c4,0x0106, +0x00c9,0x0139,0x013a,0x00f4,0x00f6,0x013d,0x013e,0x015a,0x015b,0x00d6,0x00dc,0x0164,0x0165,0x0141,0x00d7,0x010d, +0x00e1,0x00ed,0x00f3,0x00fa,0x0104,0x0105,0x017d,0x017e,0x0118,0x0119,0x00ac,0x017a,0x010c,0x015f,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x011a,0x015e,0x2563,0x2551,0x2557,0x255d,0x017b,0x017c,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0102,0x0103,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x0111,0x0110,0x010e,0x00cb,0x010f,0x0147,0x00cd,0x00ce,0x011b,0x2518,0x250c,0x2588,0x2584,0x0162,0x016e,0x2580, +0x00d3,0x00df,0x00d4,0x0143,0x0144,0x0148,0x0160,0x0161,0x0154,0x00da,0x0155,0x0170,0x00fd,0x00dd,0x0163,0x00b4, +0x00ad,0x02dd,0x02db,0x02c7,0x02d8,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x02d9,0x0171,0x0158,0x0159,0x25a0,0x00a0 +}; + +static const Bit16u cp855Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0452,0x0402,0x0453,0x0403,0x0451,0x0401,0x0454,0x0404,0x0455,0x0405,0x0456,0x0406,0x0457,0x0407,0x0458,0x0408, +0x0459,0x0409,0x045a,0x040a,0x045b,0x040b,0x045c,0x040c,0x045e,0x040e,0x045f,0x040f,0x044e,0x042e,0x044a,0x042a, +0x0430,0x0410,0x0431,0x0411,0x0446,0x0426,0x0434,0x0414,0x0435,0x0415,0x0444,0x0424,0x0433,0x0413,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x0445,0x0425,0x0438,0x0418,0x2563,0x2551,0x2557,0x255d,0x0439,0x0419,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x043a,0x041a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x043b,0x041b,0x043c,0x041c,0x043d,0x041d,0x043e,0x041e,0x043f,0x2518,0x250c,0x2588,0x2584,0x041f,0x044f,0x2580, +0x042f,0x0440,0x0420,0x0441,0x0421,0x0442,0x0422,0x0443,0x0423,0x0436,0x0416,0x0432,0x0412,0x044c,0x042c,0x2116, +0x00ad,0x044b,0x042b,0x0437,0x0417,0x0448,0x0428,0x044d,0x042d,0x0449,0x0429,0x0447,0x0427,0x00a7,0x25a0,0x00a0 +}; + +static const Bit16u cp857Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x0131,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x0130,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x015e,0x015f, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x011e,0x011f,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4, +0x00ba,0x00aa,0x00ca,0x00cb,0x00c8,0x0000,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580, +0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x0000,0x00d7,0x00da,0x00db,0x00d9,0x00ec,0x00ff,0x00af,0x00b4, +0x00ad,0x00b1,0x0000,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp860Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e3,0x00e0,0x00c1,0x00e7,0x00ea,0x00ca,0x00e8,0x00cd,0x00d4,0x00ec,0x00c3,0x00c2, +0x00c9,0x00c0,0x00c8,0x00f4,0x00f5,0x00f2,0x00da,0x00f9,0x00cc,0x00d5,0x00dc,0x00a2,0x00a3,0x00d9,0x20a7,0x00d3, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00d2,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp861Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00d0,0x00f0,0x00de,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00fe,0x00fb,0x00dd,0x00fd,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00c1,0x00cd,0x00d3,0x00da,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp862Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df, +0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,0x05e8,0x05e9,0x05ea,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp863Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00c2,0x00e0,0x00b6,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x2017,0x00c0,0x00a7, +0x00c9,0x00c8,0x00ca,0x00f4,0x00cb,0x00cf,0x00fb,0x00f9,0x00a4,0x00d4,0x00dc,0x00a2,0x00a3,0x00d9,0x00db,0x0192, +0x00a6,0x00b4,0x00f3,0x00fa,0x00a8,0x00b8,0x00b3,0x00af,0x00ce,0x2310,0x00ac,0x00bd,0x00bc,0x00be,0x00ab,0x00bb, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp864Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x066a,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00b0,0x00b7,0x2219,0x221a,0x2592,0x2500,0x2502,0x253c,0x2524,0x252c,0x251c,0x2534,0x2510,0x250c,0x2514,0x2518, +0x03b2,0x221e,0x03c6,0x00b1,0x00bd,0x00bc,0x2248,0x00ab,0x00bb,0xfef7,0xfef8,0x0000,0x0000,0xfefb,0xfefc,0x0000, +0x00a0,0x00ad,0xfe82,0x00a3,0x00a4,0xfe84,0x0000,0x0000,0xfe8e,0xfe8f,0xfe95,0xfe99,0x060c,0xfe9d,0xfea1,0xfea5, +0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667,0x0668,0x0669,0xfed1,0x061b,0xfeb1,0xfeb5,0xfeb9,0x061f, +0x00a2,0xfe80,0xfe81,0xfe83,0xfe85,0xfeca,0xfe8b,0xfe8d,0xfe91,0xfe93,0xfe97,0xfe9b,0xfe9f,0xfea3,0xfea7,0xfea9, +0xfeab,0xfead,0xfeaf,0xfeb3,0xfeb7,0xfebb,0xfebf,0xfec1,0xfec5,0xfecb,0xfecf,0x00a6,0x00ac,0x00f7,0x00d7,0xfec9, +0x0640,0xfed3,0xfed7,0xfedb,0xfedf,0xfee3,0xfee7,0xfeeb,0xfeed,0xfeef,0xfef3,0xfebd,0xfecc,0xfece,0xfecd,0xfee1, +0xfe7d,0x0651,0xfee5,0xfee9,0xfeec,0xfef0,0xfef2,0xfed0,0xfed5,0xfef5,0xfef6,0xfedd,0xfed9,0xfef1,0x25a0, +}; + +static const Bit16u cp865Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, +0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192, +0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00a4, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, +0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0 +}; + +static const Bit16u cp866Map[256] = { +0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f, +0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f, +0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, +0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, +0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, +0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, +0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, +0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f, +0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f, +0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f, +0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f, +0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, +0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, +0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, +0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f, +0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040e,0x045e,0x00b0,0x2219,0x00b7,0x221a,0x2116,0x00a4,0x25a0,0x00a0 +}; + +CHARMAP charmap[] = { + {437, cp437Map}, + {737, cp737Map}, + {775, cp775Map}, + {850, cp850Map}, + {852, cp852Map}, + {855, cp855Map}, + {857, cp857Map}, + {860, cp860Map}, + {861, cp861Map}, + {863, cp863Map}, + {864, cp864Map}, + {865, cp865Map}, + {866, cp866Map}, + {0, NULL}, +}; + +static const Bit16u codepages[15] = {0, 437, 932, 850, 851, 853, 855, 860, 863, 865, 852, 857, 862, 864, 866}; + +// TODO: Implement all international charsets +static const Bit16u intCharSets[15][12] = +{ + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // USA + {0x0023, 0x0024, 0x00e0, 0x00ba, 0x00e7, 0x00a7, 0x005e, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, // France + {0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x005e, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, // Germany + {0x00a3, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // UK + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, + {0x0023, 0x0024, 0x00a7, 0x00c4, 0x0027, 0x0022, 0x00b6, 0x0060, 0x00a9, 0x00ae, 0x2020, 0x2122} // Legal +}; diff --git a/src/protos.h b/src/protos.h index 9e80e2d..ed6809a 100644 --- a/src/protos.h +++ b/src/protos.h @@ -159,6 +159,7 @@ void config_init(void); void cfg_exit(void); void cfg_toggle_config_panel(void); void cfg_text_screen_dump(void); +void cfg_get_tfe_name(void); void config_vbl_update(int doit_3_persec); void config_parse_option(char *buf, int pos, int len, int line); void config_parse_bram(char *buf, int pos, int len); @@ -539,3 +540,80 @@ void video_update_status_line(int line, const char *string); void video_show_debug_info(void); word32 float_bus(double dcycs); +/*parallel.c*/ +byte parallel_read(word16 paddr); +void parallel_write(word16 paddr, byte pvar); +void printer_update(); + +/*tfc.c*/ +int tfe_enabled; + +void tfe_init(void); +int tfe_resources_init(void); +int tfe_cmdline_options_init(void); +int set_tfe_interface(const char* name); +void get_disabled_state(int * param); + +void tfe_reset(void); +void tfe_shutdown(void); +byte tfe_read(word16 addr); +void tfe_store(word16 addr, byte var); +int tfe_read_snapshot_module(struct snapshot_s *s); +int tfe_write_snapshot_module(struct snapshot_s *s); +int tfe_enumadapter_open(void); +int tfe_enumadapter(char **ppname, char **ppdescription); +int tfe_enumadapter_close(void); + +/*tfearch.c*/ +int tfe_arch_init(void); +void tfe_arch_pre_reset(void); +void tfe_arch_post_reset(void); +int tfe_arch_activate(const char *interface_name); +void tfe_arch_deactivate(void); +void tfe_arch_set_mac(const byte mac[6]); +void tfe_arch_set_hashfilter(const int hash_mask[2]); + +void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ + int bIA, /* individual address (IA) */ + int bMulticast, /* multicast if address passes the hash filter */ + int bCorrect, /* accept correct frames */ + int bPromiscuous, /* promiscuous mode */ + int bIAHash /* accept if IA passes the hash filter */ + ); + +void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver); + +void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ + int onecoll, /* ONECOLL: Terminate after just one collision */ + int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */ + int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */ + int txlength, /* Frame length */ + byte *txframe /* Pointer to the frame to be transmitted */ + ); + +int tfe_arch_receive(byte *pbuffer , /* where to store a frame */ + int *plen, /* IN: maximum length of frame to copy; + OUT: length of received frame + OUT can be bigger than IN if received frame was + longer than supplied buffer */ + int *phashed, /* set if the dest. address is accepted by the hash filter */ + int *phash_index, /* hash table index if hashed == TRUE */ + int *prx_ok, /* set if good CRC and valid length */ + int *pcorrect_mac, /* set if dest. address is exactly our IA */ + int *pbroadcast, /* set if dest. address is a broadcast address */ + int *pcrc_error /* set if received frame had a CRC error */ + ); + +/* + This is a helper for tfe_receive() to determine if the received frame should be accepted + according to the settings. + + This function is even allowed to be called in tfearch.c from tfe_arch_receive() if + necessary, which is the reason why its prototype is included here in tfearch.h. +*/ +int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, + int *pcorrect_mac, int *pbroadcast, int *pmulticast); + +int tfe_arch_enumadapter_open(void); +int tfe_arch_enumadapter(char **ppname, char **ppdescription); +int tfe_arch_enumadapter_close(void); diff --git a/src/resource b/src/resource new file mode 100644 index 0000000..0e1f280 --- /dev/null +++ b/src/resource @@ -0,0 +1,58 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by kegs32.rc +// +#define IDD_ABOUT_DIALOG 101 +#define IDC_KEGS32 102 +#define IDR_TOOLBAR 103 +#define IDD_DLG_DISKCONF 104 +#define IDR_ACCEL 105 +#define IDD_KEGS32_KEY 106 +#define IDD_SPEEDDIALOG 117 +#define IDC_SLOW 1007 +#define IDC_CUSTOM 1008 +#define IDC_EDITCUSTOM 1009 +#define IDC_NORMAL 1010 +#define IDC_FASTEST 1011 +#define ID_TOOLBAR 5000 +#define ID_STATUSBAR 5001 +#define IDC_EDIT_S5D1 10051 +#define IDC_EDIT_S5D2 10052 +#define IDC_EDIT_S6D1 10061 +#define IDC_EDIT_S6D2 10062 +#define IDC_EDIT_S7D1 10071 +#define IDC_EDIT_S7D2 10072 +#define IDC_BTN_S5D1 11051 +#define IDC_BTN_S5D2 11052 +#define IDC_BTN_S6D1 11061 +#define IDC_BTN_S6D2 11062 +#define IDC_BTN_S7D1 11071 +#define IDC_BTN_S7D2 11072 +#define ID_HELP_ABOUT 40001 +#define ID_FILE_EXIT 40002 +#define ID_FILE_DISK 40003 +#define ID_FILE_SENDRESET 40004 +#define ID_FILE_JOYSTICK 40005 +#define ID_FILE_DEBUGSTAT 40006 +#define ID_FILE_SENDREBOOT 40007 +#define ID_FILE_FULLSCREEN 40012 +#define ID_FILE_SPEED 40013 +#define ID_HELP_KEY 40014 +#define ID_FILE_SEND_REBOOT 40014 +#define ID_Menu 40015 +#define ID_EMULATOR_FLUSHPRINTER 40016 +#define ID_FILE_FLUSHPRINTER 40017 +#define ID_SPEED_1MHZ 50001 +#define ID_SPEED_2MHZ 50002 +#define ID_SPEED_FMHZ 50003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 116 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/resource.h b/src/resource.h new file mode 100644 index 0000000..eebe4cd --- /dev/null +++ b/src/resource.h @@ -0,0 +1,57 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by kegs32.rc +// +#define IDD_ABOUT_DIALOG 101 +#define IDC_KEGS32 102 +#define IDR_TOOLBAR 103 +#define IDD_DLG_DISKCONF 104 +#define IDR_ACCEL 105 +#define IDD_KEGS32_KEY 106 +#define ID_TOOLBAR 5000 +#define ID_STATUSBAR 5001 +#define IDC_EDIT_S5D1 10051 +#define IDC_EDIT_S5D2 10052 +#define IDC_EDIT_S6D1 10061 +#define IDC_EDIT_S6D2 10062 +#define IDC_EDIT_S7D1 10071 +#define IDC_EDIT_S7D2 10072 +#define IDC_BTN_S5D1 11051 +#define IDC_BTN_S5D2 11052 +#define IDC_BTN_S6D1 11061 +#define IDC_BTN_S6D2 11062 +#define IDC_BTN_S7D1 11071 +#define IDC_BTN_S7D2 11072 +#define ID_HELP_ABOUT 40001 +#define ID_FILE_EXIT 40002 +#define ID_FILE_DISK 40003 +#define ID_FILE_SENDRESET 40004 +#define ID_FILE_JOYSTICK 40005 +#define ID_FILE_DEBUGSTAT 40006 +#define ID_FILE_SENDREBOOT 40007 +#define ID_FILE_FULLSCREEN 40012 +#define ID_FILE_SPEED 40013 +#define ID_HELP_KEY 40014 +#define ID_SPEED_1MHZ 50001 +#define ID_SPEED_2MHZ 50002 +#define ID_SPEED_FMHZ 50003 + +#define IDD_SPEEDDIALOG 117 +#define IDC_SLOW 1007 +#define IDC_CUSTOM 1008 +#define IDC_EDITCUSTOM 1009 +#define IDC_NORMAL 1010 +#define IDC_FASTEST 1011 + +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40013 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/scc_socket_driver.c b/src/scc_socket_driver.c index e9e5c57..fb7f11b 100644 --- a/src/scc_socket_driver.c +++ b/src/scc_socket_driver.c @@ -30,7 +30,7 @@ const char rcsid_scc_socket_driver_c[] = "@(#)$KmKId: scc_socket_driver.c,v 1.11 extern Scc scc_stat[2]; extern int g_serial_modem[]; -extern int h_errno; +//extern int h_errno; int g_wsastartup_called = 0; /* Usage: scc_socket_init() called to init socket mode */ diff --git a/src/scc_windriver.c b/src/scc_windriver.c index 3f13e46..faddb47 100644 --- a/src/scc_windriver.c +++ b/src/scc_windriver.c @@ -25,6 +25,7 @@ const char rcsid_scc_windriver_c[] = "@(#)$KmKId: scc_windriver.c,v 1.4 2004-11- #include "defc.h" #include "scc.h" +#include "printer.h" extern Scc scc_stat[2]; extern word32 g_c025_val; @@ -32,8 +33,11 @@ extern word32 g_c025_val; #ifdef _WIN32 int scc_serial_win_init(int port) -{ - COMMTIMEOUTS commtimeouts; +{ int state; + Scc *scc_ptr; + scc_ptr = &(scc_stat[port]); + printf("Called port init.\n"); + /*COMMTIMEOUTS commtimeouts; char str_buf[8]; Scc *scc_ptr; HANDLE host_handle; @@ -42,13 +46,12 @@ scc_serial_win_init(int port) scc_ptr = &(scc_stat[port]); - scc_ptr->state = 0; /* mark as failed */ - + scc_ptr->state = 0; */ /* mark as failed */ +/* sprintf(&str_buf[0], "COM%d", port+1); - host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - + printf("scc port is mapped to: %s\n", &str_buf); scc_ptr->host_handle = host_handle; scc_ptr->host_handle2 = malloc(sizeof(DCB)); @@ -72,7 +75,7 @@ scc_serial_win_init(int port) if(ret == 0) { printf("setcommtimeout ret: %d\n", ret); } - +*/ //printer_init(360,85,110,'bmp',0); state = 2; /* raw serial */ scc_ptr->state = state; @@ -163,7 +166,7 @@ scc_serial_win_change_params(int port) void scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) -{ +{/* byte tmp_buf[256]; Scc *scc_ptr; HANDLE host_handle; @@ -177,9 +180,9 @@ scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) if(host_handle == 0) { return; } - +*/ /* Try reading some bytes */ - space_left = MIN(256, space_left); +/* space_left = MIN(256, space_left); ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL); if(ret == 0) { @@ -191,7 +194,7 @@ scc_serial_win_fill_readbuf(int port, int space_left, double dcycs) scc_add_to_readbuf(port, tmp_buf[i], dcycs); } } - + */ } void @@ -210,10 +213,10 @@ scc_serial_win_empty_writebuf(int port) scc_ptr = &(scc_stat[port]); //printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle); - host_handle = scc_ptr->host_handle; + /*host_handle = scc_ptr->host_handle; if(host_handle == 0) { return; - } + }*/ /* Try writing some bytes */ done = 0; @@ -237,18 +240,22 @@ scc_serial_win_empty_writebuf(int port) break; } bytes_written = 1; - ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len, - &bytes_written, NULL); + /*ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len, + &bytes_written, NULL);*/ + printer_loop(scc_ptr->out_buf[rdptr]); + /*ret = printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret, - (int)bytes_written, len); - + (int)bytes_written, len);*/ + /*printf("WriteFile bytes_written:%d, len:%d\n", + (int)bytes_written, len);*/ err_code = (word32)-1; - if(ret == 0) { - err_code = (word32)GetLastError(); +/* if(ret == 0) { + err_code = 0; //(word32)GetLastError(); printf("WriteFile ret:0, err_code: %08x\n", err_code); - } + }*/ - if(ret == 0 || (bytes_written == 0)) { +// if(ret == 0 || (bytes_written == 0)) { + if (bytes_written == 0) { done = 1; break; } else { diff --git a/src/sim65816.c b/src/sim65816.c index 07eccc5..0613f44 100644 --- a/src/sim65816.c +++ b/src/sim65816.c @@ -26,7 +26,7 @@ const char rcsid_sim65816_c[] = "@(#)$KmKId: sim65816.c,v 1.367 2004-11-22 02:39 #define INCLUDE_RCSID_C #include "defc.h" #undef INCLUDE_RCSID_C - +#include "printer.h" #define PC_LOG_LEN (8*1024) @@ -109,6 +109,21 @@ int g_raw_serial = 1; int g_iw2_emul = 0; int g_serial_out_masking = 0; int g_serial_modem[2] = { 0, 1 }; +int g_ethernet = 0; +int g_ethernet_interface = 0; +int g_parallel = 0; +int g_parallel_out_masking = 0; +int g_printer = 0; +int g_printer_dpi = 360; +char* g_printer_output = "bmp"; +int g_printer_multipage = 0; +int g_printer_timeout = 2; +char* g_printer_font_roman = "roman.ttf"; +char* g_printer_font_sans = "sansserif.ttf"; +char* g_printer_font_courier = "courier.ttf"; +char* g_printer_font_prestige = "prestige.ttf"; +char* g_printer_font_script = "script.ttf"; +char* g_printer_font_ocra = "ocra.ttf"; int g_config_iwm_vbl_count = 0; const char g_kegs_version_str[] = "0.1"; @@ -391,7 +406,6 @@ get_memory_io(word32 loc, double *cyc_ptr) halt_printf("get_memory_io:%08x out of range==halt!\n", loc); return 0; } - tmp = loc & 0xfef000; if(tmp == 0xc000 || tmp == 0xe0c000) { return(io_read(loc & 0xfff, cyc_ptr)); @@ -508,7 +522,6 @@ void set_memory_io(word32 loc, int val, double *cyc_ptr) { word32 tmp; - tmp = loc & 0xfef000; if(tmp == 0xc000 || tmp == 0xe0c000) { io_write(loc, val, cyc_ptr); @@ -609,6 +622,7 @@ void my_exit(int ret) { end_screen(); + printer_close(); printf("exiting\n"); exit(ret); } @@ -861,6 +875,15 @@ kegsmain(int argc, char **argv) printf("Forcing black-and-white hires modes\n"); g_cur_a2_stat |= ALL_STAT_COLOR_C021; g_use_bw_hires = 1; + } else if(!strcmp("-enet", argv[i])) { + if((i+1) >= argc) { + printf("Missing argument\n"); + exit(1); + } + tmp1 = strtol(argv[i+1], 0, 0); + printf("Using %d as ethernet enable val\n", tmp1); + g_ethernet = tmp1; + i++; } else { printf("Bad option: %s\n", argv[i]); exit(3); @@ -898,6 +921,33 @@ kegsmain(int argc, char **argv) iwm_init(); config_init(); + printer_init(g_printer_dpi,85,110,g_printer_output,g_printer_multipage); + //If ethernet is enabled in config.kegs, lets initialize it + if (g_ethernet == 1) + { + int i = 0; + char *ppname = NULL; + char *ppdes = NULL; + if (tfe_enumadapter_open()) + { + //Loop through the available adapters until we reach the interface number specified in config.kegs + while(tfe_enumadapter(&ppname,&ppdes)) + { + if (i == g_ethernet_interface) break; + i++; + } + tfe_enumadapter_close(); + printf("Using host ethernet interface: %s\nUthernet support is ON.\n",ppdes); + } + else + { + printf("No ethernet host adapters found. Do you have PCap installed/enabled?\nUthernet support is OFF.\n"); + } + set_tfe_interface(ppname); //Connect the emulated ethernet device with the selected host adapter + lib_free(ppname); + lib_free(ppdes); + tfe_init(); + } load_roms_init_memory(); @@ -912,7 +962,6 @@ kegsmain(int argc, char **argv) //sleep(1); #endif sound_init(); - scc_init(); adb_init(); joystick_init(); diff --git a/src/support.h b/src/support.h new file mode 100644 index 0000000..4a7a6a3 --- /dev/null +++ b/src/support.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2002-2009 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* $Id: support.h,v 1.18 2009/05/27 09:15:41 qbix79 Exp $ */ + +#ifndef DOSBOX_SUPPORT_H +#define DOSBOX_SUPPORT_H + +#include +#include +#include +typedef signed Bits; + +#if defined (_MSC_VER) /* MS Visual C++ */ +#define strcasecmp(a,b) stricmp(a,b) +#define strncasecmp(a,b,n) _strnicmp(a,b,n) +#endif + +#define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0) + +#ifdef HAVE_STRINGS_H +#include +#endif + +void strreplace(char * str,char o,char n); +char *ltrim(char *str); +char *rtrim(char *str); +char *trim(char * str); +char * upcase(char * str); +char * lowcase(char * str); + +bool ScanCMDBool(char * cmd,char const * const check); +char * ScanCMDRemain(char * cmd); +char * StripWord(char *&cmd); +bool IsDecWord(char * word); +bool IsHexWord(char * word); +Bits ConvDecWord(char * word); +Bits ConvHexWord(char * word); + +void upcase(std::string &str); +void lowcase(std::string &str); + +#endif diff --git a/src/tfe/Tfesupp.c b/src/tfe/Tfesupp.c new file mode 100644 index 0000000..9b2124f --- /dev/null +++ b/src/tfe/Tfesupp.c @@ -0,0 +1,188 @@ +/* + * This file is a consolidation of functions required for tfe + * emulation taken from the following files + * + * lib.c - Library functions. + * util.c - Miscellaneous utility functions. + * crc32.c + * + * Written by + * Andreas Boose + * Ettore Perazzoli + * Andreas Matthies + * Tibor Biczo + * Spiro Trikaliotis * + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tfesupp.h" + + +// Lib Stuff +/* #define LIB_DEBUG*/ + + +#ifdef LIB_DEBUG +#define LIB_DEBUG_SIZE 0x10000 +#define LIB_DEBUG_GUARD 0x1000 +#endif + +#define CRC32_POLY 0xedb88320 +static unsigned long crc32_table[256]; +static int crc32_is_initialized = 0; + +void lib_free(void *ptr) +{ +#ifdef LIB_DEBUG + lib_debug_free(ptr, 1, 1); +#endif + +#ifdef LIB_DEBUG + lib_debug_libc_free(ptr); +#else + free(ptr); +#endif +} + +void *lib_malloc(size_t size) +{ +#ifdef LIB_DEBUG + void *ptr = lib_debug_libc_malloc(size); +#else + void *ptr = malloc(size); +#endif + +#ifndef __OS2__ + if (ptr == NULL && size > 0) + exit(-1); +#endif +#ifdef LIB_DEBUG + lib_debug_alloc(ptr, size, 3); +#endif + + return ptr; +} + +/*-----------------------------------------------------------------------*/ + +/* Malloc enough space for `str', copy `str' into it and return its + address. */ +char *lib_stralloc(const char *str) +{ + size_t size; + char *ptr; + + if (str == NULL) + exit(-1); + + size = strlen(str) + 1; + ptr = (char *)lib_malloc(size); + + memcpy(ptr, str, size); + return ptr; +} + + + +/* Like realloc, but abort if not enough memory is available. */ +void *lib_realloc(void *ptr, size_t size) +{ +#ifdef LIB_DEBUG + void *new_ptr = lib_debug_libc_realloc(ptr, size); +#else + void *new_ptr = realloc(ptr, size); +#endif + +#ifndef __OS2__ + if (new_ptr == NULL) + exit(-1); +#endif +#ifdef LIB_DEBUG + lib_debug_free(ptr, 1, 0); + lib_debug_alloc(new_ptr, size, 1); +#endif + + return new_ptr; +} + +// Util Stuff + +/* Set a new value to the dynamically allocated string *str. + Returns `-1' if nothing has to be done. */ +int util_string_set(char **str, const char *new_value) +{ + if (*str == NULL) { + if (new_value != NULL) + *str = lib_stralloc(new_value); + } else { + if (new_value == NULL) { + lib_free(*str); + *str = NULL; + } else { + /* Skip copy if src and dest are already the same. */ + if (strcmp(*str, new_value) == 0) + return -1; + + *str = (char *)lib_realloc(*str, strlen(new_value) + 1); + strcpy(*str, new_value); + } + } + return 0; +} + + +// crc32 Stuff + +unsigned long crc32_buf(const char *buffer, unsigned int len) +{ + int i, j; + unsigned long crc, c; + const char *p; + + if (!crc32_is_initialized) { + for (i = 0; i < 256; i++) { + c = (unsigned long) i; + for (j = 0; j < 8; j++) + c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1; + crc32_table[i] = c; + } + crc32_is_initialized = 1; + } + + crc = 0xffffffff; + for (p = buffer; len > 0; ++p, --len) + crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff]; + + return ~crc; +} + diff --git a/src/tfe/Tfesupp.h b/src/tfe/Tfesupp.h new file mode 100644 index 0000000..ef6928e --- /dev/null +++ b/src/tfe/Tfesupp.h @@ -0,0 +1,53 @@ +/* + * This file is a consolidation of functions required for tfe + * emulation taken from the following files + * + * lib.h - Library functions. + * util.h - Miscellaneous utility functions. + * crc32.h + * + * Written by + * Andreas Boose + * Ettore Perazzoli + * Manfred Spraul + * Andreas Matthies + * Tibor Biczo + * Spiro Trikaliotis * + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + + +#ifndef _TFESUPP_H +#define _TFESUPP_H + +extern FILE* g_fh; // Filehandle for log file + +extern void *lib_malloc(size_t size); +extern void *lib_realloc(void *p, size_t size); +extern void lib_free(void *ptr); +extern char *lib_stralloc(const char *str); + +extern int util_string_set(char **str, const char *new_value); + +extern unsigned long crc32_buf(const char *buffer, unsigned int len); + +#endif diff --git a/src/tfe/Types.h b/src/tfe/Types.h new file mode 100644 index 0000000..e62a772 --- /dev/null +++ b/src/tfe/Types.h @@ -0,0 +1,73 @@ +/* + * types.h - Type definitions for VICE. + * + * Written by + * Ettore Perazzoli + * André Fachat + * Teemu Rantanen + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _TYPES_H +#define _TYPES_H + +/*#ifndef BYTE +#define BYTE unsigned char +#endif + +#ifndef WORD +#define WORD unsigned short +#endif*/ + +#ifndef DWORD + //#ifdef DWORD_IS_LONG + #define DWORD unsigned long + //#else + //#define DWORD unsigned int + //#endif +#endif + +/* RGJ added for AppleWin */ +#ifndef ULONG +typedef unsigned long ULONG; +#endif + +typedef signed char SIGNED_CHAR; +typedef signed short SWORD; +typedef signed int SDWORD; + +typedef DWORD CLOCK; +/* Maximum value of a CLOCK. */ +#define CLOCK_MAX (~((CLOCK)0)) +/* +#if defined(__GNUC__) && defined(__i386__) && !defined(NO_REGPARM) +#define REGPARM1 __attribute__((regparm(1))) +#define REGPARM2 __attribute__((regparm(2))) +#define REGPARM3 __attribute__((regparm(3))) +#else +#define REGPARM1 +#define REGPARM2 +#define REGPARM3 +#endif +*/ +#endif + diff --git a/src/tfe/arch/win32/Bittypes.h b/src/tfe/arch/win32/Bittypes.h new file mode 100644 index 0000000..654f37b --- /dev/null +++ b/src/tfe/arch/win32/Bittypes.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _BITTYPES_H +#define _BITTYPES_H + +#ifndef HAVE_U_INT8_T + +#if SIZEOF_CHAR == 1 +typedef unsigned char u_int8_t; +typedef signed char int8_t; +#elif SIZEOF_INT == 1 +typedef unsigned int u_int8_t; +typedef signed int int8_t; +#else /* XXX */ +#error "there's no appropriate type for u_int8_t" +#endif +#define HAVE_U_INT8_T 1 +#define HAVE_INT8_T 1 + +#endif /* HAVE_U_INT8_T */ + +#ifndef HAVE_U_INT16_T + +#if SIZEOF_SHORT == 2 +typedef unsigned short u_int16_t; +typedef signed short int16_t; +#elif SIZEOF_INT == 2 +typedef unsigned int u_int16_t; +typedef signed int int16_t; +#elif SIZEOF_CHAR == 2 +typedef unsigned char u_int16_t; +typedef signed char int16_t; +#else /* XXX */ +#error "there's no appropriate type for u_int16_t" +#endif +#define HAVE_U_INT16_T 1 +#define HAVE_INT16_T 1 + +#endif /* HAVE_U_INT16_T */ + +#ifndef HAVE_U_INT32_T + +#if SIZEOF_INT == 4 +typedef unsigned int u_int32_t; +typedef signed int int32_t; +#elif SIZEOF_LONG == 4 +typedef unsigned long u_int32_t; +typedef signed long int32_t; +#elif SIZEOF_SHORT == 4 +typedef unsigned short u_int32_t; +typedef signed short int32_t; +#else /* XXX */ +#error "there's no appropriate type for u_int32_t" +#endif +#define HAVE_U_INT32_T 1 +#define HAVE_INT32_T 1 + +#endif /* HAVE_U_INT32_T */ + +#endif /* _BITTYPES_H */ diff --git a/src/tfe/arch/win32/Bpf.h b/src/tfe/arch/win32/Bpf.h new file mode 100644 index 0000000..0acfc7d --- /dev/null +++ b/src/tfe/arch/win32/Bpf.h @@ -0,0 +1,516 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header$ (LBL) + */ + +#ifndef BPF_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int bpf_int32; +typedef u_int bpf_u_int32; + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + * + * The first set is for compatibility with Sun's pcc style + * header files. If your using gcc, we assume that you + * have run fixincludes so the latter set should work. + */ +#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) +#define BIOCGBLEN _IOR(B,102, u_int) +#define BIOCSBLEN _IOWR(B,102, u_int) +#define BIOCSETF _IOW(B,103, struct bpf_program) +#define BIOCFLUSH _IO(B,104) +#define BIOCPROMISC _IO(B,105) +#define BIOCGDLT _IOR(B,106, u_int) +#define BIOCGETIF _IOR(B,107, struct ifreq) +#define BIOCSETIF _IOW(B,108, struct ifreq) +#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) +#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) +#define BIOCGSTATS _IOR(B,111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW(B,112, u_int) +#define BIOCVERSION _IOR(B,113, struct bpf_version) +#define BIOCSTCPF _IOW(B,114, struct bpf_program) +#define BIOCSUDPF _IOW(B,115, struct bpf_program) +#else +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSTCPF _IOW('B',114, struct bpf_program) +#define BIOCSUDPF _IOW('B',115, struct bpf_program) +#endif + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + bpf_u_int32 bh_caplen; /* length of captured portion */ + bpf_u_int32 bh_datalen; /* original length of packet */ + u_short bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; +/* + * Because the structure above is not a multiple of 4 bytes, some compilers + * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. + * Only the kernel needs to know about it; applications use bh_hdrlen. + */ +#if defined(KERNEL) || defined(_KERNEL) +#define SIZEOF_BPF_HDR 18 +#endif + +/* + * Data-link level type codes. + */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#ifdef __NetBSD__ +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ +#endif +#else +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#endif + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides + * with other values. + * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header + * (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 as a DLT_ value. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * This is for RFC 2625 IP-over-Fibre Channel. + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * This is for Full Frontal ATM on Solaris with SunATM, with a + * pseudo-header followed by an AALn PDU. + * + * There may be other forms of Full Frontal ATM on other OSes, + * with different pseudo-headers. + * + * If ATM software returns a pseudo-header with VPI/VCI information + * (and, ideally, packet type information, e.g. signalling, ILMI, + * LANE, LLC-multiplexed traffic, etc.), it should not use + * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump + * and the like don't have to infer the presence or absence of a + * pseudo-header and the form of the pseudo-header. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * Reserved as per request from Kent Dahlgren + * for private use. + */ +#define DLT_RIO 124 /* RapidIO */ +#define DLT_PCI_EXP 125 /* PCI Express */ +#define DLT_AURORA 126 /* Xilinx Aurora link layer */ + +/* + * For future use with 802.11 captures - defined by AbsoluteValue + * Systems to store a number of bits of link-layer information: + * + * http://www.shaftnet.org/~pizza/software/capturefrm.txt + * + * but could and arguably should also be used by non-AVS Linux + * 802.11 drivers and BSD drivers; that may happen in the future. + */ +#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */ + +/* + * Reserved for the TZSP encapsulation, as per request from + * Chris Waters + * TZSP is a generic encapsulation for any other link type, + * which includes a means to include meta-information + * with the packet, e.g. signal strength and channel + * for 802.11 packets. + */ +#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ + +/* + * BSD's ARCNET headers have the source host, destination host, + * and type at the beginning of the packet; that's what's handed + * up to userland via BPF. + * + * Linux's ARCNET headers, however, have a 2-byte offset field + * between the host IDs and the type; that's what's handed up + * to userland via PF_PACKET sockets. + * + * We therefore have to have separate DLT_ values for them. + */ +#define DLT_ARCNET_LINUX 129 /* ARCNET */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) +/* + * Systems based on non-BSD kernels don't have ifnet's (or they don't mean + * anything if it is in ) and won't work like this. + */ +# if __STDC__ +extern void bpf_tap(struct ifnet *, u_char *, u_int); +extern void bpf_mtap(struct ifnet *, struct mbuf *); +extern void bpfattach(struct ifnet *, u_int, u_int); +extern void bpfilterattach(int); +# else +extern void bpf_tap(); +extern void bpf_mtap(); +extern void bpfattach(); +extern void bpfilterattach(); +# endif /* __STDC__ */ +#endif /* BSD && (_KERNEL || KERNEL) */ +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(struct bpf_insn *, int); +extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tfe/arch/win32/Ip6_misc.h b/src/tfe/arch/win32/Ip6_misc.h new file mode 100644 index 0000000..6714f0e --- /dev/null +++ b/src/tfe/arch/win32/Ip6_misc.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1993, 1994, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header$ (LBL) + */ + +/* + * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows + */ + +#include + +#ifndef __MINGW32__ +#include +#endif /* __MINGW32__ */ + +#define IN_MULTICAST(a) IN_CLASSD(a) + +#define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xe0000000) == 0xe0000000) + +#define IN_LOOPBACKNET 127 + +#ifdef __MINGW32__ +/* IPv6 address */ +struct in6_addr + { + union + { + u_int8_t u6_addr8[16]; + u_int16_t u6_addr16[8]; + u_int32_t u6_addr32[4]; + } in6_u; +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#define s6_addr64 in6_u.u6_addr64 + }; + +#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } +#endif /* __MINGW32__ */ + + +#ifdef __MINGW32__ +typedef unsigned short sa_family_t; + +#define __SOCKADDR_COMMON(sa_prefix) \ + sa_family_t sa_prefix##family + +/* Ditto, for IPv6. */ +struct sockaddr_in6 + { + __SOCKADDR_COMMON (sin6_); + u_int16_t sin6_port; /* Transport layer port # */ + u_int32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + }; + +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \ + (((u_int32_t *) (a))[2] == htonl (0xffff))) + +#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000)) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ + ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) +#endif /* __MINGW32__ */ + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +/* + * IPV6 extension headers + */ +#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ +#define IPPROTO_IPV6 41 /* IPv6 header. */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ESP 50 /* encapsulating security payload */ +#define IPPROTO_AH 51 /* authentication header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */ + +#define IPV6_RTHDR_TYPE_0 0 + +/* Option types and related macros */ +#define IP6OPT_PAD1 0x00 /* 00 0 00000 */ +#define IP6OPT_PADN 0x01 /* 00 0 00001 */ +#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ +#define IP6OPT_JUMBO_LEN 6 +#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */ + +#define IP6OPT_RTALERT_LEN 4 +#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ +#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ +#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ +#define IP6OPT_MINLEN 2 + +#define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */ +#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */ +#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */ +#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */ +#define IP6OPT_EID 0x8a /* 10 0 01010 */ + +#define IP6OPT_TYPE(o) ((o) & 0xC0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xC0 + +#define IP6OPT_MUTABLE 0x20 + + +#ifdef __MINGW32__ +#ifndef EAI_ADDRFAMILY +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +#endif /* __MINGW32__ */ diff --git a/src/tfe/arch/win32/pcap-stdinc.h b/src/tfe/arch/win32/pcap-stdinc.h new file mode 100644 index 0000000..221003d --- /dev/null +++ b/src/tfe/arch/win32/pcap-stdinc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header$ (LBL) + */ + +#define SIZEOF_CHAR 1 +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 + +#define _WINSOCKAPI_ +#include + +#include +#include "bittypes.h" +#include +#include + +#ifndef __MINGW32__ +#include "IP6_misc.h" +#endif + +#define caddr_t char* + +#define snprintf _snprintf +//#define vsnprintf _vsnprintf + diff --git a/src/tfe/arch/win32/pcap.h b/src/tfe/arch/win32/pcap.h new file mode 100644 index 0000000..52d958f --- /dev/null +++ b/src/tfe/arch/win32/pcap.h @@ -0,0 +1,273 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ +/* + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header$ (LBL) + */ + +#ifndef lib_pcap_h +#define lib_pcap_h + +#ifdef WIN32 +/* RGJ Changed it to "pcap-stdinc.h" for AppleWin */ +#include "pcap-stdinc.h" +#else /* WIN32 */ +#include +#include +#endif /* WIN32 */ + +/* RGJ Changed it to "bpf.h" for AppleWin */ +#include "bpf.h" + +#include + +#ifdef REMOTE + // We have to define the SOCKET here, although it has been defined in sockutils.h + // This is to avoid the distribution of the 'sockutils.h' file around + // (for example in the WinPcap developer's pack) + #ifndef SOCKET + #ifdef WIN32 + #define SOCKET unsigned int + #else + #define SOCKET int + #endif + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 + +#define PCAP_ERRBUF_SIZE 256 + +/* + * Compatibility for systems that have a bpf.h that + * predates the bpf typedefs for 64-bit support. + */ +#if BPF_RELEASE - 0 < 199406 +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +typedef struct pcap pcap_t; +typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are 32 bit ints so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + * + * Do not change the layout of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * + * Also, do not change the interpretation of any of the members of this + * structure, in any way (this includes using values other than + * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" + * field). + * + * Instead: + * + * introduce a new structure for the new format, if the layout + * of the structure changed; + * + * send mail to "tcpdump-workers@tcpdump.org", requesting a new + * magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed file + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old file header as well as files with the new file header + * (using the magic number to determine the header format). + * + * Then supply the changes to "patches@tcpdump.org", so that future + * versions of libpcap and programs that use it (such as tcpdump) will + * be able to read your new capture file format. + */ +struct pcap_file_header { + bpf_u_int32 magic; + u_short version_major; + u_short version_minor; + bpf_int32 thiszone; /* gmt to local correction */ + bpf_u_int32 sigfigs; /* accuracy of timestamps */ + bpf_u_int32 snaplen; /* max length saved portion of each pkt */ + bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ +}; + +/* + * Each packet in the dump file is prepended with this generic header. + * This gets around the problem of different headers for different + * packet interfaces. + */ +struct pcap_pkthdr { + struct timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + +/* + * As returned by the pcap_stats() + */ +struct pcap_stat { + u_int ps_recv; /* number of packets received */ + u_int ps_drop; /* number of packets dropped */ + u_int ps_ifdrop; /* drops by interface XXX not yet supported */ +#ifdef REMOTE +#ifdef WIN32 +// u_int bs_capt; /* number of packets that reach the application */ +#endif /* WIN32 */ + u_int ps_capt; /* number of packets that reach the application; please get rid off the Win32 ifdef */ + u_int ps_sent; /* number of packets sent by the server on the network */ + u_int ps_netdrop; /* number of packets lost on the network */ +#endif +}; + +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + bpf_u_int32 flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + +typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, + const u_char *); + +char *pcap_lookupdev(char *); +int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); +pcap_t *pcap_open_live(const char *, int, int, int, char *); +pcap_t *pcap_open_dead(int, int); +pcap_t *pcap_open_offline(const char *, char *); +void pcap_close(pcap_t *); +int pcap_loop(pcap_t *, int, pcap_handler, u_char *); +int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); +const u_char* + pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_stats(pcap_t *, struct pcap_stat *); +int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); +void pcap_perror(pcap_t *, char *); +char *pcap_strerror(int); +char *pcap_geterr(pcap_t *); +int pcap_compile(pcap_t *, struct bpf_program *, char *, int, + bpf_u_int32); +int pcap_compile_nopcap(int, int, struct bpf_program *, + char *, int, bpf_u_int32); +void pcap_freecode(struct bpf_program *); +int pcap_datalink(pcap_t *); +int pcap_list_datalinks(pcap_t *, int **); +int pcap_set_datalink(pcap_t *, int); +int pcap_datalink_name_to_val(const char *); +const char *pcap_datalink_val_to_name(int); +int pcap_snapshot(pcap_t *); +int pcap_is_swapped(pcap_t *); +int pcap_major_version(pcap_t *); +int pcap_minor_version(pcap_t *); + +/* XXX */ +FILE *pcap_file(pcap_t *); +int pcap_fileno(pcap_t *); + +pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +int pcap_dump_flush(pcap_dumper_t *); +void pcap_dump_close(pcap_dumper_t *); +void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); + +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + +/* To avoid callback, this returns one packet at a time */ +int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data); + +/* XXX this guy lives in the bpf tree */ +u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +int bpf_validate(struct bpf_insn *f, int len); +char *bpf_image(struct bpf_insn *, int); +void bpf_dump(struct bpf_program *, int); + +#ifdef WIN32 +/* + * Win32 definitions + */ + +int pcap_setbuff(pcap_t *p, int dim); +int pcap_setmode(pcap_t *p, int mode); +int pcap_sendpacket(pcap_t *p, u_char *buf, int size); +int pcap_setmintocopy(pcap_t *p, int size); + +#ifdef WPCAP +/* Include file with the wpcap-specific extensions */ +#include +#endif + +#define MODE_CAPT 0 +#define MODE_STAT 1 +#define MODE_MON 2 + +#endif /* WIN32 */ + +#ifdef REMOTE +/* Includes most of the public stuff that is needed for the remote capture */ +#include "remote-ext.h" +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tfe/arch/win32/tfearch.c b/src/tfe/arch/win32/tfearch.c new file mode 100644 index 0000000..d85527c --- /dev/null +++ b/src/tfe/arch/win32/tfearch.c @@ -0,0 +1,556 @@ +/* + * tfearch.c - TFE ("The final ethernet") emulation, + * architecture-dependant stuff + * + * Written by + * Spiro Trikaliotis + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + +/* #define WPCAP */ + +#include "pcap.h" + +#include +#include +#include +#include + +#include "..\..\defc.h" + + +typedef pcap_t *(*pcap_open_live_t)(const char *, int, int, int, char *); +typedef int (*pcap_dispatch_t)(pcap_t *, int, pcap_handler, u_char *); +typedef int (*pcap_setnonblock_t)(pcap_t *, int, char *); +typedef int (*pcap_datalink_t)(pcap_t *); +typedef int (*pcap_findalldevs_t)(pcap_if_t **, char *); +typedef void (*pcap_freealldevs_t)(pcap_if_t *); +typedef int (*pcap_sendpacket_t)(pcap_t *p, u_char *buf, int size); + +/** #define TFE_DEBUG_ARCH 1 **/ +/** #define TFE_DEBUG_PKTDUMP 1 **/ + +/* #define TFE_DEBUG_FRAMES - might be defined in TFE.H! */ + +#define TFE_DEBUG_WARN 1 /* this should not be deactivated */ + +static pcap_open_live_t p_pcap_open_live; +static pcap_dispatch_t p_pcap_dispatch; +static pcap_setnonblock_t p_pcap_setnonblock; +static pcap_findalldevs_t p_pcap_findalldevs; +static pcap_freealldevs_t p_pcap_freealldevs; +static pcap_sendpacket_t p_pcap_sendpacket; +static pcap_datalink_t p_pcap_datalink; + +static HINSTANCE pcap_library = NULL; + + +/* ------------------------------------------------------------------------- */ +/* variables needed */ + + +//static log_t tfe_arch_log = LOG_ERR; + + +static pcap_if_t *TfePcapNextDev = NULL; +static pcap_if_t *TfePcapAlldevs = NULL; +static pcap_t *TfePcapFP = NULL; + +static char TfePcapErrbuf[PCAP_ERRBUF_SIZE]; + +#ifdef TFE_DEBUG_PKTDUMP + +static +void debug_output( const char *text, BYTE *what, int count ) +{ + char buffer[256]; + char *p = buffer; + char *pbuffer1 = what; + int len1 = count; + int i; + + sprintf(buffer, "\n%s: length = %u\n", text, len1); + OutputDebugString(buffer); + do { + p = buffer; + for (i=0; (i<8) && len1>0; len1--, i++) { + sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++); + p += 3; + } + *(p-1) = '\n'; *p = 0; + OutputDebugString(buffer); + } while (len1>0); +} +#endif // #ifdef TFE_DEBUG_PKTDUMP + + +static +void TfePcapFreeLibrary(void) +{ + if (pcap_library) { + if (!FreeLibrary(pcap_library)) { + //log_message(tfe_arch_log, "FreeLibrary WPCAP.DLL failed!"); + } + pcap_library = NULL; + + p_pcap_open_live = NULL; + p_pcap_dispatch = NULL; + p_pcap_setnonblock = NULL; + p_pcap_findalldevs = NULL; + p_pcap_freealldevs = NULL; + p_pcap_sendpacket = NULL; + p_pcap_datalink = NULL; + } +} + +/* since I don't like typing too much... */ +#define GET_PROC_ADDRESS_AND_TEST( _name_ ) \ + p_##_name_ = (_name_##_t) GetProcAddress(pcap_library, #_name_ ); \ + if (!p_##_name_ ) { \ + /*log_message(tfe_arch_log, "GetProcAddress " #_name_ " failed!");*/ \ + TfePcapFreeLibrary(); \ + return FALSE; \ + } + +static +BOOL TfePcapLoadLibrary(void) +{ + if (!pcap_library) { + pcap_library = LoadLibrary("wpcap.dll"); + + if (!pcap_library) { + //log_message(tfe_arch_log, "LoadLibrary WPCAP.DLL failed!" ); + return FALSE; + } + + GET_PROC_ADDRESS_AND_TEST(pcap_open_live); + GET_PROC_ADDRESS_AND_TEST(pcap_dispatch); + GET_PROC_ADDRESS_AND_TEST(pcap_setnonblock); + GET_PROC_ADDRESS_AND_TEST(pcap_findalldevs); + GET_PROC_ADDRESS_AND_TEST(pcap_freealldevs); + GET_PROC_ADDRESS_AND_TEST(pcap_sendpacket); + GET_PROC_ADDRESS_AND_TEST(pcap_datalink); + } + + return TRUE; +} + +#undef GET_PROC_ADDRESS_AND_TEST + + +/* +static +void TfePcapCloseAdapter(void) +{ + if (TfePcapAlldevs) { + (*p_pcap_freealldevs)(TfePcapAlldevs); + TfePcapAlldevs = NULL; + } +} +*/ + +/* + These functions let the UI enumerate the available interfaces. + + First, TfeEnumAdapterOpen() is used to start enumeration. + + TfeEnumAdapter is then used to gather information for each adapter present + on the system, where: + + ppname points to a pointer which will hold the name of the interface + ppdescription points to a pointer which will hold the description of the interface + + For each of these parameters, new memory is allocated, so it has to be + freed with lib_free(). + + TfeEnumAdapterClose() must be used to stop processing. + + Each function returns 1 on success, and 0 on failure. + TfeEnumAdapter() only fails if there is no more adpater; in this case, + *ppname and *ppdescription are not altered. +*/ +int tfe_arch_enumadapter_open(void) +{ + if (!TfePcapLoadLibrary()) { + return 0; + } + + if ((*p_pcap_findalldevs)(&TfePcapAlldevs, TfePcapErrbuf) == -1) + { + //log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen: pcap_findalldevs: '%s'", TfePcapErrbuf); + return 0; + } + + if (!TfePcapAlldevs) { + /*log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - " + "Do we have the necessary privilege rights?");*/ + return 0; + } + + TfePcapNextDev = TfePcapAlldevs; + + return 1; +} + +int tfe_arch_enumadapter(char **ppname, char **ppdescription) +{ + if (!TfePcapNextDev) + return 0; + + *ppname = lib_stralloc(TfePcapNextDev->name); + *ppdescription = lib_stralloc(TfePcapNextDev->description); + + TfePcapNextDev = TfePcapNextDev->next; + + return 1; +} + +int tfe_arch_enumadapter_close(void) +{ + if (TfePcapAlldevs) { + (*p_pcap_freealldevs)(TfePcapAlldevs); + TfePcapAlldevs = NULL; + } + return 1; +} + +static +BOOL TfePcapOpenAdapter(const char *interface_name) +{ + pcap_if_t *TfePcapDevice = NULL; + + if (!tfe_enumadapter_open()) { + return FALSE; + } + else { + /* look if we can find the specified adapter */ + char *pname; + char *pdescription; + BOOL found = FALSE; + + if (interface_name) { + /* we have an interface name, try it */ + TfePcapDevice = TfePcapAlldevs; + + while (tfe_enumadapter(&pname, &pdescription)) { + if (strcmp(pname, interface_name)==0) { + found = TRUE; + } + lib_free(pname); + lib_free(pdescription); + if (found) break; + TfePcapDevice = TfePcapNextDev; + } + } + + if (!found) { + /* just take the first adapter */ + TfePcapDevice = TfePcapAlldevs; + } + } + + TfePcapFP = (*p_pcap_open_live)(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf); + if ( TfePcapFP == NULL) + { + //log_message(tfe_arch_log, "ERROR opening adapter: '%s'", TfePcapErrbuf); + tfe_enumadapter_close(); + return FALSE; + } + + if ((*p_pcap_setnonblock)(TfePcapFP, 1, TfePcapErrbuf)<0) + { + //log_message(tfe_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", TfePcapErrbuf); + } + + /* Check the link layer. We support only Ethernet for simplicity. */ + if((*p_pcap_datalink)(TfePcapFP) != DLT_EN10MB) + { + //log_message(tfe_arch_log, "ERROR: TFE works only on Ethernet networks."); + tfe_enumadapter_close(); + return FALSE; + } + + tfe_enumadapter_close(); + return TRUE; +} + + +/* ------------------------------------------------------------------------- */ +/* the architecture-dependend functions */ + + +int tfe_arch_init(void) +{ + //tfe_arch_log = log_open("TFEARCH"); + + if (!TfePcapLoadLibrary()) { + return 0; + } + + return 1; +} + +void tfe_arch_pre_reset( void ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_pre_reset()." ); +#endif +} + +void tfe_arch_post_reset( void ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_post_reset()." ); +#endif +} + +int tfe_arch_activate(const char *interface_name) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_activate()." ); +#endif + if (!TfePcapOpenAdapter(interface_name)) { + return 0; + } + return 1; +} + +void tfe_arch_deactivate( void ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_deactivate()." ); +#endif +} + +void tfe_arch_set_mac( const BYTE mac[6] ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); +#endif +} + +void tfe_arch_set_hashfilter(const int hash_mask[2]) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "New hash filter set: %08X:%08X.", + hash_mask[1], hash_mask[0]); +#endif +} + + +/* +void tfe_arch_receive_remove_committed_frame(void) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_receive_remove_committed_frame()." ); +#endif +} +*/ + +void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ + int bIA, /* individual address (IA) */ + int bMulticast, /* multicast if address passes the hash filter */ + int bCorrect, /* accept correct frames */ + int bPromiscuous, /* promiscuous mode */ + int bIAHash /* accept if IA passes the hash filter */ + ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "tfe_arch_recv_ctl() called with the following parameters:" ); + log_message( tfe_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" ); +#endif +} + +void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + log_message( tfe_arch_log, "tfe_arch_line_ctl() called with the following parameters:" ); + log_message( tfe_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" ); + log_message( tfe_arch_log, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" ); +#endif +} + + +typedef struct TFE_PCAP_INTERNAL_tag { + + unsigned int len; + BYTE *buffer; + +} TFE_PCAP_INTERNAL; + +/* Callback function invoked by libpcap for every incoming packet */ +static +void TfePcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) +{ + TFE_PCAP_INTERNAL *pinternal = (void*)param; + + /* determine the count of bytes which has been returned, + * but make sure not to overrun the buffer + */ + if (header->caplen < pinternal->len) + pinternal->len = header->caplen; + + memcpy(pinternal->buffer, pkt_data, pinternal->len); +} + +/* the following function receives a frame. + + If there's none, it returns a -1. + If there is one, it returns the length of the frame in bytes. + + It copies the frame to *buffer and returns the number of copied + bytes as return value. + + At most 'len' bytes are copied. +*/ +static +int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) +{ + int ret = -1; + + /* check if there is something to receive */ + if ((*p_pcap_dispatch)(TfePcapFP, 1, TfePcapPacketHandler, (void*)pinternal)!=0) { + /* Something has been received */ + ret = pinternal->len; + } + +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_receive_frame() called, returns %d.", ret ); +#endif + + return ret; +} + +void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ + int onecoll, /* ONECOLL: Terminate after just one collision */ + int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */ + int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */ + int txlength, /* Frame length */ + BYTE *txframe /* Pointer to the frame to be transmitted */ + ) +{ +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_transmit() called, with: " + "force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u", + force ? "TRUE" : "FALSE", + onecoll ? "TRUE" : "FALSE", + inhibit_crc ? "TRUE" : "FALSE", + tx_pad_dis ? "TRUE" : "FALSE", + txlength + ); +#endif + +#ifdef TFE_DEBUG_PKTDUMP + debug_output( "Transmit frame: ", txframe, txlength); +#endif // #ifdef TFE_DEBUG_PKTDUMP + + if ((*p_pcap_sendpacket)(TfePcapFP, txframe, txlength) == -1) { + //log_message(tfe_arch_log, "WARNING! Could not send packet!"); + } +} + +/* + tfe_arch_receive() + + This function checks if there was a frame received. + If so, it returns 1, else 0. + + If there was no frame, none of the parameters is changed! + + If there was a frame, the following actions are done: + + - at maximum *plen byte are transferred into the buffer given by pbuffer + - *plen gets the length of the received frame, EVEN if this is more + than has been copied to pbuffer! + - if the dest. address was accepted by the hash filter, *phashed is set, else + cleared. + - if the dest. address was accepted by the hash filter, *phash_index is + set to the number of the rule leading to the acceptance + - if the receive was ok (good CRC and valid length), *prx_ok is set, + else cleared. + - if the dest. address was accepted because it's exactly our MAC address + (set by tfe_arch_set_mac()), *pcorrect_mac is set, else cleared. + - if the dest. address was accepted since it was a broadcast address, + *pbroadcast is set, else cleared. + - if the received frame had a crc error, *pcrc_error is set, else cleared +*/ +int tfe_arch_receive(BYTE *pbuffer , /* where to store a frame */ + int *plen, /* IN: maximum length of frame to copy; + OUT: length of received frame + OUT can be bigger than IN if received frame was + longer than supplied buffer */ + int *phashed, /* set if the dest. address is accepted by the hash filter */ + int *phash_index, /* hash table index if hashed == TRUE */ + int *prx_ok, /* set if good CRC and valid length */ + int *pcorrect_mac, /* set if dest. address is exactly our IA */ + int *pbroadcast, /* set if dest. address is a broadcast address */ + int *pcrc_error /* set if received frame had a CRC error */ + ) +{ + int len; + + TFE_PCAP_INTERNAL internal = { *plen, pbuffer }; + + +#ifdef TFE_DEBUG_ARCH + log_message( tfe_arch_log, "tfe_arch_receive() called, with *plen=%u.", *plen ); +#endif + + assert((*plen&1)==0); + + len = tfe_arch_receive_frame(&internal); + + if (len!=-1) { + +#ifdef TFE_DEBUG_PKTDUMP + debug_output( "Received frame: ", internal.buffer, internal.len ); +#endif // #ifdef TFE_DEBUG_PKTDUMP + + if (len&1) + ++len; + + *plen = len; + + /* we don't decide if this frame fits the needs; + * by setting all zero, we let tfe.c do the work + * for us + */ + *phashed = + *phash_index = + *pbroadcast = + *pcorrect_mac = + *pcrc_error = 0; + + /* this frame has been received correctly */ + *prx_ok = 1; + + return 1; + } + + return 0; +} diff --git a/src/tfe/tfe.c b/src/tfe/tfe.c new file mode 100644 index 0000000..63ddc09 --- /dev/null +++ b/src/tfe/tfe.c @@ -0,0 +1,1987 @@ +/* + * tfe.c - TFE ("The final ethernet") emulation. + * + * Written by + * Spiro Trikaliotis + * Christian Vogelgsang + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + + + +#include +#include +#include +#include +#ifdef DOS_TFE +#include +#endif + +#include "..\defc.h" +#include "tfesupp.h" + + +/**/ + +/* warn illegal behaviour */ +/* #define TFE_DEBUG_WARN_REG 1 */ /* warn about invalid register accesses */ +/* #define TFE_DEBUG_WARN_RXTX 1 */ /* warn about invalid rx or tx conditions */ + +/** #define TFE_DEBUG_INIT 1 **/ +/** #define TFE_DEBUG_LOAD 1 **/ /* enable to see tfe port reads */ +/** #define TFE_DEBUG_STORE 1 **/ /* enable to see tfe port writes */ +/** #define TFE_DEBUG_REGISTERS 1 **/ /* enable to see CS8900a register I/O */ +/** #define TFE_DEBUG_IGNORE_RXEVENT 1 **/ /* enable to ignore RXEVENT in DEBUG_REGISTERS */ +/** #define TFE_DEBUG_RXTX_STATE 1 **/ /* enable to see tranceiver state changes */ +/** #define TFE_DEBUG_RXTX_DATA 1 **/ /* enable to see data in/out flow */ +/** #define TFE_DEBUG_FRAMES 1 **/ /* enable to see arch frame send/recv */ + +/* ------------------------------------------------------------------------- */ +/* variables needed */ + +/* + This variable is used when we need to postpone the initialization + because tfe_init() is not yet called +*/ +static int should_activate = 0; +static int init_tfe_flag = 0; +typedef signed int log_t; +#define LOG_ERR ((log_t)-1) +#define LOG_DEFAULT ((log_t)-2) + +static log_t tfe_log = LOG_ERR; + + +/* status which received packages to accept + This is used in tfe_should_accept(). +*/ +static byte tfe_ia_mac[6] = { 0,0,0,0,0,0 }; + +/* remember the value of the hash mask */ +static DWORD tfe_hash_mask[2]; + +/* reveiver setup */ +static word16 tfe_recv_control = 0; /* copy of CC_RXCTL (contains all bits below) */ +static int tfe_recv_broadcast = 0; /* broadcast */ +static int tfe_recv_mac = 0; /* individual address (IA) */ +static int tfe_recv_multicast = 0; /* multicast if address passes the hash filter */ +static int tfe_recv_correct = 0; /* accept correct frames */ +static int tfe_recv_promiscuous = 0; /* promiscuous mode */ +static int tfe_recv_hashfilter = 0; /* accept if IA passes the hash filter */ + +/* Flag: Can we even use TFE, or is the hardware not available? */ +static int tfe_cannot_use = 0; + +/* Flag: Do we have the TFE enabled? */ +int tfe_enabled = 0; + +/* Flag: Do we use the "original" memory map or the memory map of the RR-Net? */ +int tfe_as_rr_net = 0; + +static char *tfe_interface = NULL; + +/* TFE registers */ +/* these are the 8 16-bit-ports for "I/O space configuration" + (see 4.10 on page 75 of cs8900a-4.pdf, the cs8900a data sheet) + + REMARK: The TFE operatoes the cs8900a in IO space configuration, as + it generates I/OW and I/OR signals. +*/ +#define TFE_COUNT_IO_REGISTER 0x10 /* we have 16 I/O register */ + +static byte *tfe = NULL; +/* + RW: RXTXDATA = DE00/DE01 + RW: RXTXDATA2 = DE02/DE03 (for 32-bit-operation) + -W: TXCMD = DE04/DE05 (TxCMD, Transmit Command) mapped to PP + 0144 (Reg. 9, Sec. 4.4, page 46) + -W: TXLENGTH = DE06/DE07 (TxLenght, Transmit Length) mapped to PP + 0146 + R-: INTSTQUEUE = DE08/DE09 (Interrupt Status Queue) mapped to PP + 0120 (ISQ, Sec. 5.1, page 78) + RW: PP_PTR = DE0A/DE0B (PacketPage Pointer) (see. page 75p: Read -011.---- ----.----) + RW: PP_DATA0 = DE0C/DE0D (PacketPage Data (Port 0)) + RW: PP_DATA1 = DE0E/DE0F (PacketPage Data (Port 1)) (for 32 bit only) +*/ + +#define TFE_ADDR_RXTXDATA 0x00 /* RW */ +#define TFE_ADDR_RXTXDATA2 0x02 /* RW 32 bit only! */ +#define TFE_ADDR_TXCMD 0x04 /* -W Maps to PP+0144 */ +#define TFE_ADDR_TXLENGTH 0x06 /* -W Maps to PP+0146 */ +#define TFE_ADDR_INTSTQUEUE 0x08 /* R- Interrupt status queue, maps to PP + 0120 */ +#define TFE_ADDR_PP_PTR 0x0a /* RW PacketPage Pointer */ +#define TFE_ADDR_PP_DATA 0x0c /* RW PacketPage Data, Port 0 */ +#define TFE_ADDR_PP_DATA2 0x0e /* RW PacketPage Data, Port 1 - 32 bit only */ + +/* Makros for reading and writing the visible TFE register: */ +#define GET_TFE_8( _xxx_ ) \ + ( assert(_xxx_> 8) & 0xff; \ + } while (0) + +/* The PacketPage register */ +/* note: The locations 0 to MAX_PACKETPAGE_ARRAY-1 are handled in this array. */ + +#define MAX_PACKETPAGE_ARRAY 0x1000 /* 4 KB */ + +static byte *tfe_packetpage = NULL; + +static word16 tfe_packetpage_ptr = 0; + +/* Makros for reading and writing the PacketPage register: */ + +#define GET_PP_8( _xxx_ ) \ + (assert(_xxx_> 8) & 0xFF; \ + } while (0) + +#define SET_PP_32( _xxx_, _val_ ) \ + do { \ + assert(_xxx_> 8) & 0xFF; \ + tfe_packetpage[_xxx_+2] = (_val_>>16) & 0xFF; \ + tfe_packetpage[_xxx_+3] = (_val_>>24) & 0xFF; \ + } while (0) + + +/* The packetpage register: see p. 39f */ +#define TFE_PP_ADDR_PRODUCTID 0x0000 /* R- - 4.3., p. 41 */ +#define TFE_PP_ADDR_IOBASE 0x0020 /* i RW - 4.3., p. 41 - 4.7., p. 72 */ +#define TFE_PP_ADDR_INTNO 0x0022 /* i RW - 3.2., p. 17 - 4.3., p. 41 */ +#define TFE_PP_ADDR_DMA_CHAN 0x0024 /* i RW - 3.2., p. 17 - 4.3., p. 41 */ +#define TFE_PP_ADDR_DMA_SOF 0x0026 /* ? R- - 4.3., p. 41 - 5.4., p. 89 */ +#define TFE_PP_ADDR_DMA_FC 0x0028 /* ? R- - 4.3., p. 41, "Receive DMA" */ +#define TFE_PP_ADDR_RXDMA_BC 0x002a /* ? R- - 4.3., p. 41 - 5.4., p. 89 */ +#define TFE_PP_ADDR_MEMBASE 0x002c /* i RW - 4.3., p. 41 - 4.9., p. 73 */ +#define TFE_PP_ADDR_BPROM_BASE 0x0030 /* i RW - 3.6., p. 24 - 4.3., p. 41 */ +#define TFE_PP_ADDR_BPROM_MASK 0x0034 /* i RW - 3.6., p. 24 - 4.3., p. 41 */ +/* 0x0038 - 0x003F: reserved */ +#define TFE_PP_ADDR_EEPROM_CMD 0x0040 /* i RW - 3.5., p. 23 - 4.3., p. 41 */ +#define TFE_PP_ADDR_EEPROM_DATA 0x0042 /* i RW - 3.5., p. 23 - 4.3., p. 41 */ +/* 0x0044 - 0x004F: reserved */ +#define TFE_PP_ADDR_REC_FRAME_BC 0x0050 /* RW - 4.3., p. 41 - 5.2.9., p. 86 */ +/* 0x0052 - 0x00FF: reserved */ +#define TFE_PP_ADDR_CONF_CTRL 0x0100 /* - RW - 4.4., p. 46; see below */ +#define TFE_PP_ADDR_STATUS_EVENT 0x0120 /* - R- - 4.4., p. 46; see below */ +/* 0x0140 - 0x0143: reserved */ +#define TFE_PP_ADDR_TXCMD 0x0144 /* # -W - 4.5., p. 70 - 5.7., p. 98 */ +#define TFE_PP_ADDR_TXLENGTH 0x0146 /* # -W - 4.5., p. 70 - 5.7., p. 98 */ +/* 0x0148 - 0x014F: reserved */ +#define TFE_PP_ADDR_LOG_ADDR_FILTER 0x0150 /* RW - 4.6., p. 71 - 5.3., p. 86 */ +#define TFE_PP_ADDR_MAC_ADDR 0x0158 /* # RW - 4.6., p. 71 - 5.3., p. 86 */ +/* 0x015E - 0x03FF: reserved */ +#define TFE_PP_ADDR_RXSTATUS 0x0400 /* R- - 4.7., p. 72 - 5.2., p. 78 */ +#define TFE_PP_ADDR_RXLENGTH 0x0402 /* R- - 4.7., p. 72 - 5.2., p. 78 */ +#define TFE_PP_ADDR_RX_FRAMELOC 0x0404 /* R- - 4.7., p. 72 - 5.2., p. 78 */ +/* here, the received frame is stored */ +#define TFE_PP_ADDR_TX_FRAMELOC 0x0A00 /* -W - 4.7., p. 72 - 5.7., p. 98 */ +/* here, the frame to transmit is stored */ +#define TFE_PP_ADDR_END 0x1000 /* memory to TFE_PP_ADDR_END-1 is used */ + + +/* TFE_PP_ADDR_CONF_CTRL is subdivided: */ +#define TFE_PP_ADDR_CC_RXCFG 0x0102 /* # RW - 4.4.6., p. 52 - 0003 */ +#define TFE_PP_ADDR_CC_RXCTL 0x0104 /* # RW - 4.4.8., p. 54 - 0005 */ +#define TFE_PP_ADDR_CC_TXCFG 0x0106 /* RW - 4.4.9., p. 55 - 0007 */ +#define TFE_PP_ADDR_CC_TXCMD 0x0108 /* R- - 4.4.11., p. 57 - 0009 */ +#define TFE_PP_ADDR_CC_BUFCFG 0x010A /* RW - 4.4.12., p. 58 - 000B */ +#define TFE_PP_ADDR_CC_LINECTL 0x0112 /* # RW - 4.4.16., p. 62 - 0013 */ +#define TFE_PP_ADDR_CC_SELFCTL 0x0114 /* RW - 4.4.18., p. 64 - 0015 */ +#define TFE_PP_ADDR_CC_BUSCTL 0x0116 /* RW - 4.4.20., p. 66 - 0017 */ +#define TFE_PP_ADDR_CC_TESTCTL 0x0118 /* RW - 4.4.22., p. 68 - 0019 */ + +/* TFE_PP_ADDR_STATUS_EVENT is subdivided: */ +#define TFE_PP_ADDR_SE_ISQ 0x0120 /* R- - 4.4.5., p. 51 - 0000 */ +#define TFE_PP_ADDR_SE_RXEVENT 0x0124 /* # R- - 4.4.7., p. 53 - 0004 */ +#define TFE_PP_ADDR_SE_TXEVENT 0x0128 /* R- - 4.4.10., p. 56 - 0008 */ +#define TFE_PP_ADDR_SE_BUFEVENT 0x012C /* R- - 4.4.13., p. 59 - 000C */ +#define TFE_PP_ADDR_SE_RXMISS 0x0130 /* R- - 4.4.14., p. 60 - 0010 */ +#define TFE_PP_ADDR_SE_TXCOL 0x0132 /* R- - 4.4.15., p. 61 - 0012 */ +#define TFE_PP_ADDR_SE_LINEST 0x0134 /* R- - 4.4.17., p. 63 - 0014 */ +#define TFE_PP_ADDR_SE_SELFST 0x0136 /* R- - 4.4.19., p. 65 - 0016 */ +#define TFE_PP_ADDR_SE_BUSST 0x0138 /* # R- - 4.4.21., p. 67 - 0018 */ +#define TFE_PP_ADDR_SE_TDR 0x013C /* R- - 4.4.23., p. 69 - 001C */ + + +/* ------------------------------------------------------------------------- */ +/* more variables needed */ + +static word16 tx_buffer = TFE_PP_ADDR_TX_FRAMELOC; +static word16 rx_buffer = TFE_PP_ADDR_RXSTATUS; + +static word16 tx_count = 0; +static word16 rx_count = 0; +static word16 tx_length = 0; +static word16 rx_length = 0; + +#define TFE_TX_IDLE 0 +#define TFE_TX_GOT_CMD 1 +#define TFE_TX_GOT_LEN 2 +#define TFE_TX_READ_BUSST 3 + +#define TFE_RX_IDLE 0 +#define TFE_RX_GOT_FRAME 1 + +/* tranceiver state */ +static int tx_state = TFE_TX_IDLE; +static int rx_state = TFE_RX_IDLE; +static int tx_enabled = 0; +static int rx_enabled = 0; + +static int rxevent_read_mask = 3; /* set if L and/or H byte was read in RXEVENT? */ + + +/* ------------------------------------------------------------------------- */ +/* some parameter definitions */ + +#define MAX_TXLENGTH 1518 +#define MIN_TXLENGTH 4 + +#define MAX_RXLENGTH 1518 +#define MIN_RXLENGTH 64 + + +/* ------------------------------------------------------------------------- */ +/* debugging functions */ + +#ifdef TFE_DEBUG_FRAMES + +static int TfeDebugMaxFrameLengthToDump = 150; + +static char *debug_outbuffer(const int length, const unsigned char * const buffer) +{ +#define MAXLEN_DEBUG 1600 + + int i; + static char outbuffer[MAXLEN_DEBUG*4+1]; + char *p = outbuffer; + + assert( TfeDebugMaxFrameLengthToDump <= MAXLEN_DEBUG ); + + *p = 0; + + for (i=0; i=length) + break; + + sprintf( p, "%02X%c", buffer[i], ((i+1)%16==0)?'*':(((i+1)%8==0)?'-':' ')); + p+=3; + } + + return outbuffer; +} + +#endif + +/* ------------------------------------------------------------------------- */ +/* initialization and deinitialization functions */ + +static void tfe_set_tx_status(int ready,int error) +{ + word16 old_status = GET_PP_16(TFE_PP_ADDR_SE_BUSST); + + /* mask out TxBidErr and Rdy4TxNOW */ + word16 new_status = old_status & ~0x180; + if(ready) + new_status |= 0x100; /* set Rdy4TxNOW */ + if(error) + new_status |= 0x080; /* set TxBidErr */ + + if(new_status!=old_status) { + SET_PP_16(TFE_PP_ADDR_SE_BUSST,new_status); +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log,"TX: set status Rdy4TxNOW=%d TxBidErr=%d", + ready,error); +#endif + } +} + +static void tfe_set_receiver(int enabled) +{ + rx_enabled = enabled; + rx_state = TFE_RX_IDLE; + + rxevent_read_mask = 3; /* was L or H byte read in RXEVENT? */ +} + +static void tfe_set_transmitter(int enabled) +{ + tx_enabled = enabled; + tx_state = TFE_TX_IDLE; + + tfe_set_tx_status(0,0); +} + +void tfe_reset(void) +{ + if (tfe_enabled && !should_activate) + { + int i; + + assert( tfe ); + assert( tfe_packetpage ); + + tfe_arch_pre_reset(); + + /* initialize visible IO register and PacketPage registers */ + memset( tfe, 0, TFE_COUNT_IO_REGISTER ); + memset( tfe_packetpage, 0, MAX_PACKETPAGE_ARRAY ); + + /* according to page 19 unless stated otherwise */ + SET_PP_32(TFE_PP_ADDR_PRODUCTID, 0x0900630E ); /* p.41: 0E630009 for Rev. D; reversed order! */ + SET_PP_16(TFE_PP_ADDR_IOBASE, 0x0300); + SET_PP_16(TFE_PP_ADDR_INTNO, 0x0004); /* xxxx xxxx xxxx x100b */ + SET_PP_16(TFE_PP_ADDR_DMA_CHAN, 0x0003); /* xxxx xxxx xxxx xx11b */ + +#if 0 /* not needed since all memory is initialized with 0 */ + SET_PP_16(TFE_PP_ADDR_DMA_SOF, 0x0000); + SET_PP_16(TFE_PP_ADDR_DMA_FC, 0x0000); /* x000h */ + SET_PP_16(TFE_PP_ADDR_RXDMA_BC, 0x0000); + SET_PP_32(TFE_PP_ADDR_MEMBASE, 0x0000); /* xxx0 0000h */ + SET_PP_32(TFE_PP_ADDR_BPROM_BASE, 0x00000000); /* xxx0 0000h */ + SET_PP_32(TFE_PP_ADDR_BPROM_MASK, 0x00000000); /* xxx0 0000h */ + + SET_PP_16(TFE_PP_ADDR_SE_ISQ, 0x0000); /* p. 51 */ +#endif + + /* according to descriptions of the registers, see definitions of + TFE_PP_ADDR_CC_... and TFE_PP_ADDR_SE_... above! */ + + SET_PP_16(TFE_PP_ADDR_CC_RXCFG, 0x0003); + SET_PP_16(TFE_PP_ADDR_CC_RXCTL, 0x0005); + SET_PP_16(TFE_PP_ADDR_CC_TXCFG, 0x0007); + SET_PP_16(TFE_PP_ADDR_CC_TXCMD, 0x0009); + SET_PP_16(TFE_PP_ADDR_CC_BUFCFG, 0x000B); + SET_PP_16(TFE_PP_ADDR_CC_LINECTL, 0x0013); + SET_PP_16(TFE_PP_ADDR_CC_SELFCTL, 0x0015); + SET_PP_16(TFE_PP_ADDR_CC_BUSCTL, 0x0017); + SET_PP_16(TFE_PP_ADDR_CC_TESTCTL, 0x0019); + + SET_PP_16(TFE_PP_ADDR_SE_ISQ, 0x0000); + SET_PP_16(TFE_PP_ADDR_SE_RXEVENT, 0x0004); + SET_PP_16(TFE_PP_ADDR_SE_TXEVENT, 0x0008); + SET_PP_16(TFE_PP_ADDR_SE_BUFEVENT, 0x000C); + SET_PP_16(TFE_PP_ADDR_SE_RXMISS, 0x0010); + SET_PP_16(TFE_PP_ADDR_SE_TXCOL, 0x0012); + SET_PP_16(TFE_PP_ADDR_SE_LINEST, 0x0014); + SET_PP_16(TFE_PP_ADDR_SE_SELFST, 0x0016); + SET_PP_16(TFE_PP_ADDR_SE_BUSST, 0x0018); + SET_PP_16(TFE_PP_ADDR_SE_TDR, 0x001C); + + SET_PP_16(TFE_PP_ADDR_TXCMD, 0x0009); + + /* 4.4.19 Self Status Register, p. 65 + Important: set INITD (Bit 7) to signal device is ready */ + SET_PP_16(TFE_PP_ADDR_SE_SELFST, 0x0896); + + tfe_recv_control = GET_PP_16(TFE_PP_ADDR_CC_RXCTL); + + /* spec: mac address is undefined after reset. + real HW: keeps the last set address. */ + for(i=0;i<6;i++) + SET_PP_8(TFE_PP_ADDR_MAC_ADDR+i,tfe_ia_mac[i]); + + /* reset state */ + tfe_set_transmitter(0); + tfe_set_receiver(0); + + tfe_arch_post_reset(); + + printf("CS8900a rev.D reset\n"); + } +} + +#ifdef DOS_TFE +static void set_standard_tfe_interface(void) +{ + char *dev, errbuf[PCAP_ERRBUF_SIZE]; + dev = pcap_lookupdev(errbuf); + util_string_set(&tfe_interface, dev); +} +#endif + +static +int tfe_activate_i(void) +{ + assert( tfe == NULL ); + assert( tfe_packetpage == NULL ); + +#ifdef TFE_DEBUG + log_message( tfe_log, "tfe_activate_i()." ); +#endif + + /* allocate memory for visible IO register */ + tfe = lib_malloc( TFE_COUNT_IO_REGISTER ); + if (tfe==NULL) + { +#ifdef TFE_DEBUG_INIT + log_message(tfe_log, "tfe_activate_i: Allocating tfe failed."); +#endif + tfe_enabled = 0; + return 0; + } + + /* allocate memory for PacketPage register */ + tfe_packetpage = lib_malloc( MAX_PACKETPAGE_ARRAY ); + if (tfe_packetpage==NULL) + { +#ifdef TFE_DEBUG_INIT + log_message(tfe_log, "tfe_activate: Allocating tfe_packetpage failed."); +#endif + lib_free(tfe); + tfe=NULL; + tfe_enabled = 0; + return 0; + } + +#ifdef TFE_DEBUG_INIT + log_message(tfe_log, "tfe_activate: Allocated memory successfully."); + log_message(tfe_log, "\ttfe at $%08X, tfe_packetpage at $%08X", tfe, tfe_packetpage ); +#endif + +#ifdef DOS_TFE + set_standard_tfe_interface(); +#endif + + if (!tfe_arch_activate(tfe_interface)) { + lib_free(tfe_packetpage); + lib_free(tfe); + tfe=NULL; + tfe_packetpage=NULL; + tfe_enabled = 0; + tfe_cannot_use = 1; + return 0; + } + + /* virtually reset the LAN chip */ + tfe_reset(); + + return 0; +} + +static +int tfe_deactivate_i(void) +{ +#ifdef TFE_DEBUG + log_message( tfe_log, "tfe_deactivate_i()." ); +#endif + + assert(tfe && tfe_packetpage); + + tfe_arch_deactivate(); + + lib_free(tfe); + tfe = NULL; + lib_free(tfe_packetpage); + tfe_packetpage = NULL; + return 0; +} + +static +int tfe_activate(void) { +#ifdef TFE_DEBUG + log_message( tfe_log, "tfe_activate()." ); +#endif + + if (init_tfe_flag) { + return tfe_activate_i(); + } + else { + should_activate = 1; + } + return 0; +} + +static +int tfe_deactivate(void) { +#ifdef TFE_DEBUG + log_message( tfe_log, "tfe_deactivate()." ); +#endif + + if (should_activate) + should_activate = 0; + else { + if (tfe_log != LOG_ERR) + return tfe_deactivate_i(); + } + + return 0; +} + +void tfe_init(void) +{ + tfe_enabled = 1; + init_tfe_flag = 1; + should_activate = 1; + if (!tfe_arch_init()) { + tfe_enabled = 0; + tfe_cannot_use = 1; + } + + if (should_activate) { + should_activate = 0; + if (tfe_activate() < 0) { + tfe_enabled = 0; + tfe_cannot_use = 1; + } + } +} + +void tfe_shutdown(void) +{ + assert( (tfe && tfe_packetpage) || (!tfe && !tfe_packetpage)); + + if (tfe) + tfe_deactivate(); + + if (tfe_interface != NULL) + lib_free(tfe_interface); +} + + +/* ------------------------------------------------------------------------- */ +/* reading and writing TFE register functions */ + +/* +These registers are currently fully or partially supported: + +TFE_PP_ADDR_CC_RXCFG 0x0102 * # RW - 4.4.6., p. 52 - 0003 * +TFE_PP_ADDR_CC_RXCTL 0x0104 * # RW - 4.4.8., p. 54 - 0005 * +TFE_PP_ADDR_CC_LINECTL 0x0112 * # RW - 4.4.16., p. 62 - 0013 * +TFE_PP_ADDR_SE_RXEVENT 0x0124 * # R- - 4.4.7., p. 53 - 0004 * +TFE_PP_ADDR_SE_BUSST 0x0138 * # R- - 4.4.21., p. 67 - 0018 * +TFE_PP_ADDR_TXCMD 0x0144 * # -W - 4.5., p. 70 - 5.7., p. 98 * +TFE_PP_ADDR_TXLENGTH 0x0146 * # -W - 4.5., p. 70 - 5.7., p. 98 * +TFE_PP_ADDR_MAC_ADDR 0x0158 * # RW - 4.6., p. 71 - 5.3., p. 86 * + 0x015a + 0x015c +*/ + + +#ifdef TFE_DEBUG_FRAMES + #define return( _x_ ) \ + { \ + int retval = _x_; \ + \ + log_message(tfe_log, "%s correct_mac=%u, broadcast=%u, multicast=%u, hashed=%u, hash_index=%u", (retval? "+++ ACCEPTED":"--- rejected"), *pcorrect_mac, *pbroadcast, *pmulticast, *phashed, *phash_index); \ + \ + return retval; \ + } + +#endif +/* + This is a helper for tfe_receive() to determine if the received frame should be accepted + according to the settings. + + This function is even allowed to be called in tfearch.c from tfe_arch_receive() if + necessary, which is the reason why its prototype is included here in tfearch.h. +*/ +int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, + int *pcorrect_mac, int *pbroadcast, int *pmulticast) +{ + int hashreg; /* Hash Register (for hash computation) */ + + assert(length>=6); /* we need at least 6 octets since the DA has this length */ + + /* first of all, delete any status */ + *phashed = 0; + *phash_index = 0; + *pcorrect_mac = 0; + *pbroadcast = 0; + *pmulticast = 0; + +#ifdef TFE_DEBUG_FRAMES + log_message(tfe_log, "tfe_should_accept called with %02X:%02X:%02X:%02X:%02X:%02X, length=%4u and buffer %s", + tfe_ia_mac[0], tfe_ia_mac[1], tfe_ia_mac[2], + tfe_ia_mac[3], tfe_ia_mac[4], tfe_ia_mac[5], + length, + debug_outbuffer(length, buffer) + ); +#endif + + + if ( buffer[0]==tfe_ia_mac[0] + && buffer[1]==tfe_ia_mac[1] + && buffer[2]==tfe_ia_mac[2] + && buffer[3]==tfe_ia_mac[3] + && buffer[4]==tfe_ia_mac[4] + && buffer[5]==tfe_ia_mac[5] + ) { + /* this is our individual address (IA) */ + + *pcorrect_mac = 1; + + /* if we don't want "correct MAC", we might have the chance + * that this address fits the hash index + */ + if (tfe_recv_mac || tfe_recv_promiscuous) + return(1); + } + + if ( buffer[0]==0xFF + && buffer[1]==0xFF + && buffer[2]==0xFF + && buffer[3]==0xFF + && buffer[4]==0xFF + && buffer[5]==0xFF + ) { + /* this is a broadcast address */ + *pbroadcast = 1; + + /* broadcasts cannot be accepted by the hash filter */ + return((tfe_recv_broadcast || tfe_recv_promiscuous) ? 1 : 0); + } + + /* now check if DA passes the hash filter */ + hashreg = (~crc32_buf((char *)buffer,6) >> 26) & 0x3F; + + *phashed = (tfe_hash_mask[(hashreg>=32)?1:0] & (1 << (hashreg&0x1F))) ? 1 : 0; + if (*phashed) { + *phash_index = hashreg; + + if (buffer[0] & 0x80) { + /* we have a multicast address */ + *pmulticast = 1; + + /* if the multicast address fits into the hash filter, + * the hashed bit has to be clear + */ + *phashed = 0; + + return((tfe_recv_multicast || tfe_recv_promiscuous) ? 1 : 0); + } + return((tfe_recv_hashfilter || tfe_recv_promiscuous) ? 1 : 0); + } + + return(tfe_recv_promiscuous ? 1 : 0); +} + +#ifdef TFE_DEBUG_FRAMES + #undef return +#endif + +static +word16 tfe_receive(void) +{ + word16 ret_val = 0x0004; + + byte buffer[MAX_RXLENGTH]; + + int len; + int hashed; + int hash_index; + int rx_ok; + int correct_mac; + int broadcast; + int multicast; + int crc_error; + + int newframe; + + int ready; + + do { + len = MAX_RXLENGTH; + + ready = 1 ; /* assume we will find a good frame */ + + newframe = tfe_arch_receive( + buffer, /* where to store a frame */ + &len, /* length of received frame */ + &hashed, /* set if the dest. address is accepted by the hash filter */ + &hash_index, /* hash table index if hashed == TRUE */ + &rx_ok, /* set if good CRC and valid length */ + &correct_mac, /* set if dest. address is exactly our IA */ + &broadcast, /* set if dest. address is a broadcast address */ + &crc_error /* set if received frame had a CRC error */ + ); + + assert((len&1) == 0); /* length has to be even! */ + + if (newframe) { + if (hashed || correct_mac || broadcast) { + /* we already know the type of frame: Trust it! */ +#ifdef TFE_DEBUG_FRAMES + log_message( tfe_log, "+++ tfe_receive(): *** hashed=%u, correct_mac=%u, " + "broadcast=%u", hashed, correct_mac, broadcast); +#endif + } + else { + /* determine ourself the type of frame */ + if (!tfe_should_accept(buffer, + len, &hashed, &hash_index, &correct_mac, &broadcast, &multicast)) { + + /* if we should not accept this frame, just do nothing + * now, look for another one */ + ready = 0; /* try another frame */ + continue; + } + } + + + /* we did receive a frame, return that status */ + ret_val |= rx_ok ? 0x0100 : 0; + ret_val |= multicast ? 0x0200 : 0; + + if (!multicast) { + ret_val |= hashed ? 0x0040 : 0; + } + + if (hashed && rx_ok) { + /* we have the 2nd, special format with hash index: */ + assert(hash_index < 64); + ret_val |= hash_index << 9; + } + else { + /* we have the regular format */ + ret_val |= correct_mac ? 0x0400 : 0; + ret_val |= broadcast ? 0x0800 : 0; + ret_val |= crc_error ? 0x1000 : 0; + ret_val |= (lenMAX_RXLENGTH) ? 0x4000 : 0; + } + + /* discard any octets that are beyond the MAX_RXLEN */ + if (len>MAX_RXLENGTH) { + len = MAX_RXLENGTH; + } + + if (rx_ok) { + int i; + + /* set relevant parts of the PP area to correct values */ + SET_PP_16(TFE_PP_ADDR_RXLENGTH, len); + + for (i=0;i=6) && (!odd_address)) + rx_buffer += 2; + + addr += rx_buffer; + value = GET_PP_8(addr); + rx_count++; + } + +#ifdef TFE_DEBUG_RXTX_DATA + log_message(tfe_log,"RX: %04x/%04x: %02x (buffer=%04x,odd=%d)", + rx_count,rx_length+4,value,addr,odd_address); +#endif + + /* check frame end */ + if(rx_count>=rx_length+4) { + /* reset receiver state to idle */ + rx_state = TFE_RX_IDLE; +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log,"RX: read frame (length=%04x)",rx_length); +#endif + } + return value; + } +} + +/* ------------------------------------------------------------------------- */ +/* handle side-effects of read and write operations */ + +/* + This is called *after* the relevant octets are written +*/ +static +void tfe_sideeffects_write_pp(word16 ppaddress, int odd_address) +{ + const char *on_off[2] = { "on","off" }; +#define on_off_str(x) ((x) ? on_off[0] : on_off[1]) + word16 content = GET_PP_16( ppaddress ); + + assert((ppaddress & 1) == 0); + + switch (ppaddress) + { + case TFE_PP_ADDR_CC_RXCFG: + /* Skip_1 Flag: remove current (partial) tx frame and restore state */ + if (content & 0x40) { + +/* tfe_arch_receive_remove_committed_frame(); */ + + /* restore tx state */ + if(tx_state!=TFE_TX_IDLE) { + tx_state = TFE_TX_IDLE; +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log,"TX: skipping current frame"); +#endif + } + + /* reset transmitter */ + tfe_set_transmitter(tx_enabled); + + /* this is an "act once" bit, thus restore it to zero. */ + content &= ~0x40; + SET_PP_16( ppaddress, content ); + } + break; + + case TFE_PP_ADDR_CC_RXCTL: + if(tfe_recv_control!=content) { + tfe_recv_broadcast = content & 0x0800; /* broadcast */ + tfe_recv_mac = content & 0x0400; /* individual address (IA) */ + tfe_recv_multicast = content & 0x0200; /* multicast if address passes the hash filter */ + tfe_recv_correct = content & 0x0100; /* accept correct frames */ + tfe_recv_promiscuous = content & 0x0080; /* promiscuous mode */ + tfe_recv_hashfilter = content & 0x0040; /* accept if IA passes the hash filter */ + tfe_recv_control = content; + + /*log_message(tfe_log,"setup receiver: broadcast=%s mac=%s multicast=%s correct=%s promiscuous=%s hashfilter=%s", + on_off_str(tfe_recv_broadcast), + on_off_str(tfe_recv_mac), + on_off_str(tfe_recv_multicast), + on_off_str(tfe_recv_correct), + on_off_str(tfe_recv_promiscuous), + on_off_str(tfe_recv_hashfilter));*/ + + tfe_arch_recv_ctl( tfe_recv_broadcast, + tfe_recv_mac, + tfe_recv_multicast, + tfe_recv_correct, + tfe_recv_promiscuous, + tfe_recv_hashfilter + ); + } + break; + + case TFE_PP_ADDR_CC_LINECTL: + { + int enable_tx = (content & 0x0080) == 0x0080; + int enable_rx = (content & 0x0040) == 0x0040; + + if((enable_tx!=tx_enabled)||(enable_rx!=rx_enabled)) { + tfe_arch_line_ctl(enable_tx,enable_rx); + tfe_set_transmitter(enable_tx); + tfe_set_receiver(enable_rx); + + /*log_message(tfe_log,"line control: transmitter=%s receiver=%s", + on_off_str(enable_tx), + on_off_str(enable_rx));*/ + } + } + break; + + case TFE_PP_ADDR_CC_SELFCTL: + { + /* reset chip? */ + if((content & 0x40)==0x40) { + tfe_reset(); + } + } + break; + + case TFE_PP_ADDR_TXCMD: + { + if(odd_address) { + word16 txcommand = GET_PP_16(TFE_PP_ADDR_TXCMD); + + /* already transmitting? */ + if(tx_state == TFE_TX_READ_BUSST) { +#ifdef TFE_DEBUG_WARN_RXTX + log_message(tfe_log, "WARNING! Early abort of transmitted frame"); +#endif + } + + /* The transmit status command gets the last transmit command */ + SET_PP_16(TFE_PP_ADDR_CC_TXCMD, txcommand); + + /* set transmit state */ + tx_state = TFE_TX_GOT_CMD; + tfe_set_tx_status(0,0); + +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log, "TX: COMMAND accepted (%04x)",txcommand); +#endif + } + } + break; + + case TFE_PP_ADDR_TXLENGTH: + { + if(odd_address && (tx_state == TFE_TX_GOT_CMD)) { + word16 txlength = GET_PP_16(TFE_PP_ADDR_TXLENGTH); + word16 txcommand = GET_PP_16(TFE_PP_ADDR_CC_TXCMD); + + if(txlength<4) { + /* frame to short */ +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log, "TX: LENGTH rejected - too short! (%04x)",txlength); +#endif + /* mask space available but do not commit */ + tx_state = TFE_TX_IDLE; + tfe_set_tx_status(1,0); + } + else if ( (txlength>MAX_TXLENGTH) + || ((txlength>MAX_TXLENGTH-4) && (!(txcommand&0x1000))) + ) { + tx_state = TFE_TX_IDLE; +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log, "TX: LENGTH rejected - too long! (%04x)",txlength); +#endif + /* txlength too big, mark an error */ + tfe_set_tx_status(0,1); + } + else { + /* make sure we put the octets to transmit at the right place */ + tx_buffer = TFE_PP_ADDR_TX_FRAMELOC; + tx_count = 0; + tx_length = txlength; + tx_state = TFE_TX_GOT_LEN; + +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log, "TX: LENGTH accepted (%04x)",txlength); +#endif + /* all right, signal that we're ready for the next frame */ + tfe_set_tx_status(1,0); + } + } + } + break; + + case TFE_PP_ADDR_LOG_ADDR_FILTER: + case TFE_PP_ADDR_LOG_ADDR_FILTER+2: + case TFE_PP_ADDR_LOG_ADDR_FILTER+4: + case TFE_PP_ADDR_LOG_ADDR_FILTER+6: + { + unsigned int pos = 8 * (ppaddress - TFE_PP_ADDR_LOG_ADDR_FILTER + odd_address); + DWORD *p = (pos < 32) ? &tfe_hash_mask[0] : &tfe_hash_mask[1]; + + *p &= ~(0xFF << pos); /* clear out relevant bits */ + *p |= GET_PP_8(ppaddress+odd_address) << pos; + + tfe_arch_set_hashfilter(tfe_hash_mask); + +#if 0 + if(odd_address && (ppaddress == TFE_PP_ADDR_LOG_ADDR_FILTER+6)) + log_message(tfe_log,"set hash filter: %02x:%02x:%02x:%02x:%02x:%02x", + tfe_hash_mask[0], + tfe_hash_mask[1], + tfe_hash_mask[2], + tfe_hash_mask[3], + tfe_hash_mask[4], + tfe_hash_mask[5]); +#endif + } + break; + + case TFE_PP_ADDR_MAC_ADDR: + case TFE_PP_ADDR_MAC_ADDR+2: + case TFE_PP_ADDR_MAC_ADDR+4: + /* the MAC address has been changed */ + tfe_ia_mac[ppaddress-TFE_PP_ADDR_MAC_ADDR+odd_address] = + GET_PP_8(ppaddress+odd_address); + tfe_arch_set_mac(tfe_ia_mac); + + if(odd_address && (ppaddress == TFE_PP_ADDR_MAC_ADDR+4)) + /*log_message(tfe_log,"set MAC address: %02x:%02x:%02x:%02x:%02x:%02x", + tfe_ia_mac[0],tfe_ia_mac[1],tfe_ia_mac[2], + tfe_ia_mac[3],tfe_ia_mac[4],tfe_ia_mac[5]);*/ + break; + } +#undef on_off_str +} + +/* + This is called *before* the relevant octets are read +*/ +static +void tfe_sideeffects_read_pp(word16 ppaddress,int odd_address) +{ + switch (ppaddress) + { + case TFE_PP_ADDR_SE_RXEVENT: + /* reading this before all octets of the frame are read + performs an "implied skip" */ + { + int access_mask = (odd_address) ? 1 : 2; + + /* update the status register only if the full word of the last + status was read! unfortunately different access patterns are + possible: either the status is read LH, LH, LH... + or HL, HL, HL, or even L, L, L or H, H, H */ + if((access_mask & rxevent_read_mask)!=0) { + /* receiver is not enabled */ + if(!rx_enabled) { +#ifdef TFE_DEBUG_WARN_RXTX + log_message(tfe_log,"WARNING! Can't receive any frame (Receiver is not enabled)!"); +#endif + } else { + /* perform frame reception */ + word16 ret_val = tfe_receive(); + + /* RXSTATUS and RXEVENT are the same, except that RXSTATUS buffers + the old value while RXEVENT sets a new value whenever it is called + */ + SET_PP_16(TFE_PP_ADDR_RXSTATUS, ret_val); + SET_PP_16(TFE_PP_ADDR_SE_RXEVENT, ret_val); + } + + /* reset read mask of (possible) other access */ + rxevent_read_mask = access_mask; + } else { + /* add access bit to mask */ + rxevent_read_mask |= access_mask; + } + } + + break; + + case TFE_PP_ADDR_SE_BUSST: + if(odd_address) { + /* read busst before transmit condition is fullfilled */ + if(tx_state == TFE_TX_GOT_LEN) { + word16 bus_status = GET_PP_16(TFE_PP_ADDR_SE_BUSST); + /* check Rdy4TXNow flag */ + if((bus_status & 0x100) == 0x100) { + tx_state = TFE_TX_READ_BUSST; +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log, "TX: Ready4TXNow set! (%04x)", + bus_status); +#endif + } else { +#ifdef TFE_DEBUG_RXTX_STATE + log_message(tfe_log, "TX: waiting for Ready4TXNow! (%04x)", + bus_status); +#endif + } + } + } + break; + } +} + +/* ------------------------------------------------------------------------- */ +/* read/write from packet page register */ + +/* read a register from packet page */ +static word16 tfe_read_register(word16 ppaddress) +{ + word16 value = GET_PP_16(ppaddress); + + /* --- check the register address --- */ + if(ppaddress<0x100) { + /* reserved range reads 0x0300 on real HW */ + if((ppaddress>=0x0004)&&(ppaddress<0x0020)) { + return 0x0300; + } + } + + /* --- read control register range --- */ + else if(ppaddress<0x120) { + word16 regNum = ppaddress - 0x100; + regNum &= ~1; + regNum ++; +#ifdef TFE_DEBUG_REGISTERS + log_message(tfe_log, + "Read Control Register %04x: %04x (reg=%02x)", + ppaddress,value,regNum); +#endif + + /* reserved register? */ + if((regNum==0x01)||(regNum==0x11)||(regNum>0x19)) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read reserved Control Register %04x (reg=%02x)", + ppaddress,regNum); +#endif + /* real HW returns 0x0300 in reserved register range */ + return 0x0300; + } + + /* make sure interal address is always valid */ + assert((value&0x3f) == regNum); + } + + /* --- read status register range --- */ + else if(ppaddress<0x140) { + word16 regNum = ppaddress - 0x120; + regNum &= ~1; +#ifdef TFE_DEBUG_REGISTERS +#ifdef TFE_DEBUG_IGNORE_RXEVENT + if(regNum!=4) // do not show RXEVENT +#endif + log_message(tfe_log, + "Read Status Register %04x: %04x (reg=%02x)", + ppaddress,value,regNum); +#endif + + /* reserved register? */ + if((regNum==0x02)||(regNum==0x06)||(regNum==0x0a)|| + (regNum==0x0e)||(regNum==0x1a)||(regNum==0x1e)) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read reserved Status Register %04x (reg=%02x)", + ppaddress,regNum); +#endif + /* real HW returns 0x0300 in reserved register range */ + return 0x0300; + } + + /* make sure interal address is always valid */ + assert((value&0x3f) == regNum); + } + + /* --- read transmit register range --- */ + else if(ppaddress<0x150) { + if(ppaddress==0x144) { + /* make sure interal address is always valid */ + assert((value&0x3f) == 0x09); +#ifdef TFE_DEBUG_REGISTERS + log_message(tfe_log, + "Read TX Cmd Register %04x: %04x", + ppaddress,value); +#endif + } + else if(ppaddress==0x146) { +#ifdef TFE_DEBUG_REGISTERS + log_message(tfe_log, + "Read TX Len Register %04x: %04x", + ppaddress,value); +#endif + } + /* reserved range */ + else { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read reserved Initiate Transmit Register %04x", + ppaddress); +#endif + /* real HW returns 0x0300 in reserved register range */ + return 0x0300; + } + } + + /* --- read address filter register range --- */ + else if(ppaddress<0x160) { + /* reserved range */ + if(ppaddress>=0x15e) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read reserved Address Filter Register %04x", + ppaddress); +#endif + /* real HW returns 0x0300 in reserved register range */ + return 0x0300; + } + } + + /* --- reserved range below 0x400 --- + returns 0x300 on real HW + */ + else if(ppaddress<0x400) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read reserved Register %04x", + ppaddress); +#endif + return 0x0300; + } + + /* --- range from 0x400 .. 0x9ff --- RX Frame */ + else if(ppaddress<0xa00) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read from RX Buffer Range %04x", + ppaddress); +#endif + return 0x0000; + } + + /* --- range from 0xa00 .. 0xfff --- TX Frame */ + else { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Read from TX Buffer Range %04x", + ppaddress); +#endif + return 0x0000; + } + + /* actually read from pp memory */ + return value; +} + +void tfe_write_register(word16 ppaddress,word16 value) +{ + /* --- write bus interface register range --- */ + if(ppaddress<0x100) { + int ignore = 0; + if(ppaddress<0x20) { + ignore = 1; + } else if((ppaddress>=0x26)&&(ppaddress<0x2c)) { + ignore = 1; + } else if(ppaddress==0x38) { + ignore = 1; + } else if(ppaddress>=0x44) { + ignore = 1; + } + if(ignore) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ignoring write to read only/reserved Bus Interface Register %04x", + ppaddress); +#endif + return; + } + } + + /* --- write to control register range --- */ + else if(ppaddress<0x120) { + word16 regNum = ppaddress - 0x100; + regNum &= ~1; + regNum += 1; + /* validate internal address */ + if((value&0x3f) != regNum) { + /* fix internal address */ + value &= ~0x3f; + value |= regNum; + } +#ifdef TFE_DEBUG_REGISTERS + log_message(tfe_log, + "Write Control Register %04x: %04x (reg=%02x)", + ppaddress,value,regNum); +#endif + + /* invalid register? -> ignore! */ + if((regNum==0x01)||(regNum==0x11)||(regNum>0x19)) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ignoring write to reserved Control Register %04x (reg=%02x)", + ppaddress,regNum); + #endif + return; + } + } + + /* --- write to status register range --- */ + else if(ppaddress<0x140) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ignoring write to read-only Status Register %04x", + ppaddress); +#endif + return; + } + + /* --- write to initiate transmit register range --- */ + else if(ppaddress<0x150) { + /* check tx_cmd register */ + if(ppaddress==0x144) { + /* validate internal address */ + if((value&0x3f) != 0x09) { + /* fix internal address */ + value &= ~0x3f; + value |= 0x09; + } + /* mask out reserved bits */ + value &= 0x33ff; +#ifdef TFE_DEBUG_REGISTERS + log_message(tfe_log, + "Write TX Cmd Register %04x: %04x", + ppaddress,value); +#endif + } + /* check tx_length register */ + else if(ppaddress==0x146) { + /* HW always masks 0x0fff */ + value &= 0x0fff; +#ifdef TFE_DEBUG_REGISTERS + log_message(tfe_log, + "Write TX Len Register %04x: %04x", + ppaddress,value); +#endif + } + /* reserved range */ + else if((ppaddress<0x144)||(ppaddress>0x147)) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ignoring write to reserved Initiate Transmit Register %04x", + ppaddress); +#endif + return; + } + } + + /* --- write to address filter register range --- */ + else if(ppaddress<0x160) { + /* reserved range */ + if(ppaddress>=0x15e) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ingoring write to reserved Address Filter Register %04x", + ppaddress); +#endif + return; + } + } + + /* --- ignore write outside --- */ + else if(ppaddress<0x400) { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ingoring write to reserved Register %04x", + ppaddress); +#endif + return; + } + else if(ppaddress<0xa00){ +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNING! Ignoring write to RX Buffer Range %04x", + ppaddress); +#endif + return; + } + else { +#ifdef TFE_DEBUG_WARN_REG + log_message(tfe_log, + "WARNIGN! Ignoring write to TX Buffer Range %04x", + ppaddress); +#endif + return; + } + + /* actually set value */ + SET_PP_16(ppaddress, value); +} + +#define PP_PTR_AUTO_INCR_FLAG 0x8000 /* auto increment flag in package pointer */ +#define PP_PTR_FLAG_MASK 0xf000 /* is always : x y 1 1 (with x=auto incr) */ +#define PP_PTR_ADDR_MASK 0x0fff /* address portion of packet page pointer */ + +static void tfe_auto_incr_pp_ptr(void) +{ + /* perform auto increment of packet page pointer */ + if((tfe_packetpage_ptr & PP_PTR_AUTO_INCR_FLAG)==PP_PTR_AUTO_INCR_FLAG) { + /* pointer is always increment by one on real HW */ + word16 ptr = tfe_packetpage_ptr & PP_PTR_ADDR_MASK; + word16 flags = tfe_packetpage_ptr & PP_PTR_FLAG_MASK; + ptr++; + tfe_packetpage_ptr = ptr | flags; + } +} + +/* ------------------------------------------------------------------------- */ +/* read/write TFE registers from VICE */ + +#define LO_BYTE(x) (byte)((x) & 0xff) +#define HI_BYTE(x) (byte)(((x) >> 8) & 0xff) +#define LOHI_WORD(x,y) ( (word16)(x) | ( ((word16)(y)) <<8 ) ) + +/* ----- read byte from I/O range in VICE ----- */ +byte tfe_read(word16 io_address) +{ + byte retval,lo,hi; + word16 word_value; + word16 reg_base; + + assert( tfe ); + assert( tfe_packetpage ); + assert( io_address < 0x10); + + /*if (tfe_as_rr_net) { + /* rr status register is handled by rr cartidge + if (io_address < 0x02) { + return 0; + } + io_address ^= 0x08; + }*/ + /* register base addr */ + reg_base = io_address & ~1; + + /* RX register is special as it reads from RX buffer directly */ + if((reg_base==TFE_ADDR_RXTXDATA)||(reg_base==TFE_ADDR_RXTXDATA2)) { + //io_source=IO_SOURCE_TFE_RR_NET; + return tfe_read_rx_buffer(io_address & 0x01); + } + + /* read packet page pointer */ + if(reg_base==TFE_ADDR_PP_PTR) { + word_value = tfe_packetpage_ptr; + } + /* read a register from packet page */ + else { + word16 ppaddress; + + /* determine read addr in packet page */ + switch (reg_base) { + /* PP_DATA2 behaves like PP_DATA on real HW + both show the contents at the page pointer */ + case TFE_ADDR_PP_DATA: + case TFE_ADDR_PP_DATA2: + /* mask and align address of packet pointer */ + ppaddress = tfe_packetpage_ptr & PP_PTR_ADDR_MASK; + ppaddress &= ~1; + /* if flags match then auto incr pointer */ + tfe_auto_incr_pp_ptr(); + break; + case TFE_ADDR_INTSTQUEUE: + ppaddress = TFE_PP_ADDR_SE_ISQ; + break; + case TFE_ADDR_TXCMD: + ppaddress = TFE_PP_ADDR_TXCMD; + break; + case TFE_ADDR_TXLENGTH: + ppaddress = TFE_PP_ADDR_TXLENGTH; + break; + default: + /* invalid! */ + assert(0); + break; + } + + /* do side effects before access */ + tfe_sideeffects_read_pp(ppaddress,io_address&1); + + /* read register value */ + word_value = tfe_read_register(ppaddress); + +#ifdef TFE_DEBUG_LOAD + log_message(tfe_log, "reading PP Ptr: $%04X => $%04X.",ppaddress,word_value); +#endif + } + + /* extract return value from word_value */ + lo = LO_BYTE(word_value); + hi = HI_BYTE(word_value); + if((io_address & 1) == 0) { + /* low byte on even address */ + retval = lo; + } else { + /* high byte on odd address */ + retval = hi; + } + +#ifdef TFE_DEBUG_LOAD + log_message(tfe_log, "read [$%02X] => $%02X.", io_address, retval); +#endif + + /* update _word_ value in register bank */ + tfe[reg_base] = lo; + tfe[reg_base+1] = hi; + + //io_source=IO_SOURCE_TFE_RR_NET; + return retval; +} + +/* ----- write byte to I/O range of VICE ----- */ +void tfe_store(word16 io_address, byte var) +{ + word16 reg_base; + word16 word_value; + assert( tfe ); + assert( tfe_packetpage ); + assert( io_address < 0x10); + + /*if (tfe_as_rr_net) { + /* rr control register is handled by rr cartidge + if (io_address < 0x02) { + return; + } + io_address ^= 0x08; + }*/ +#ifdef TFE_DEBUG_STORE + log_message(tfe_log, "store [$%02X] <= $%02X.", io_address, (int)byte); +#endif + + /* register base addr */ + reg_base = io_address & ~1; + + /* TX Register is special as it writes to TX buffer directly */ + if((reg_base==TFE_ADDR_RXTXDATA)||(reg_base==TFE_ADDR_RXTXDATA2)) { + tfe_write_tx_buffer(var,io_address & 1); + return; + } + + /* combine stored value with new written byte */ + if((io_address & 1) == 0) { + /* overwrite low byte */ + word_value = LOHI_WORD(var,tfe[reg_base+1]); + } else { + /* overwrite high byte */ + word_value = LOHI_WORD(tfe[reg_base],var); + } + + if(reg_base==TFE_ADDR_PP_PTR) { + /* cv: we store the full package pointer in tfe_packetpage_ptr variable. + this includes the mask area (0xf000) and the addr range (0x0fff). + we ensure that the bits 0x3000 are always set (as in real HW). + odd values of the pointer are valid and supported. + only register read and write have to be mapped to word boundary. */ + word_value |= 0x3000; + tfe_packetpage_ptr = word_value; +#ifdef TFE_DEBUG_STORE + log_message(tfe_log, "set PP Ptr to $%04X.", tfe_packetpage_ptr); +#endif + } else { + /* write a register */ + + /*! \TODO: Find a reasonable default */ + word16 ppaddress = TFE_PP_ADDR_PRODUCTID; + + /* now determine address of write in packet page */ + switch(reg_base) { + case TFE_ADDR_PP_DATA: + case TFE_ADDR_PP_DATA2: + /* mask and align ppaddress from page pointer */ + ppaddress = tfe_packetpage_ptr & (MAX_PACKETPAGE_ARRAY-1); + ppaddress &= ~1; + /* auto increment pp ptr */ + tfe_auto_incr_pp_ptr(); + break; + case TFE_ADDR_TXCMD: + ppaddress = TFE_PP_ADDR_TXCMD; + break; + case TFE_ADDR_TXLENGTH: + ppaddress = TFE_PP_ADDR_TXLENGTH; + break; + case TFE_ADDR_INTSTQUEUE: + ppaddress = TFE_PP_ADDR_SE_ISQ; + break; + case TFE_ADDR_PP_PTR: + break; + default: + /* invalid */ + assert(0); + break; + } + +#ifdef TFE_DEBUG_STORE + log_message(tfe_log, "before writing to PP Ptr: $%04X <= $%04X.", + ppaddress,word_value); +#endif + + /* perform the write */ + tfe_write_register(ppaddress,word_value); + + /* handle sideeffects */ + tfe_sideeffects_write_pp(ppaddress, io_address&1); + + /* update word value if it was changed in write register or by side effect */ + word_value = GET_PP_16(ppaddress); + +#ifdef TFE_DEBUG_STORE + log_message(tfe_log, "after writing to PP Ptr: $%04X <= $%04X.", + ppaddress,word_value); +#endif + } + + /* update tfe registers */ + tfe[reg_base] = LO_BYTE(word_value); + tfe[reg_base+1] = HI_BYTE(word_value); +} + +/* ------------------------------------------------------------------------- */ +/* resources support functions */ +static int set_tfe_disabled(int val, void *param) +{ + /* dummy function since we don't want "disabled" to be stored on disk */ + return 0; +} + +/*static int set_tfe_rr_net(int val, void *param) +{ + if (!tfe_cannot_use) { + if (!val) { + /* TFE should not be used as rr net + if (tfe_as_rr_net) { + tfe_as_rr_net = 0; + + /* if adapter is already enabled then reset the LAN chip + if (tfe) { + tfe_reset(); + } + } + return 0; + } else { + if (!tfe_as_rr_net) { + tfe_as_rr_net = 1; + + /* if adapter is already enabled then reset the LAN chip + if (tfe) { + tfe_reset(); + } + } + return 0; + } + } + + return 0; +}*/ + +static int set_tfe_enabled(int val, void *param) +{ + if (!tfe_cannot_use) { + if (!val) { + /* TFE should be deactived */ + if (tfe_enabled) { + tfe_enabled = 0; + if (tfe_deactivate() < 0) { + return -1; + } + } + return 0; + } else { + if (!tfe_enabled) { + tfe_enabled = 1; + if (tfe_activate() < 0) { + return -1; + } + } + + return 0; + } + + } + return 0; +} + + +int set_tfe_interface(const char *name) +{ + if (tfe_interface != NULL && name != NULL + && strcmp(name, tfe_interface) == 0) + return 0; + + util_string_set(&tfe_interface, name); + + if (tfe_enabled) { + /* ethernet is enabled, make sure that the new name is + taken account of + */ + if (tfe_deactivate() < 0) { + return -1; + } + if (tfe_activate() < 0) { + return -1; + } + + /* virtually reset the LAN chip */ + if (tfe) { + tfe_reset(); + } + } + return 0; +} + + +/*static const resource_string_t resources_string[] = { + { "ETHERNET_INTERFACE", + ARCHDEP_ETHERNET_DEFAULT_DEVICE, RES_EVENT_NO, NULL, + &tfe_interface, set_tfe_interface, NULL }, + { NULL } +}; + +static const resource_int_t resources_int[] = { + { "ETHERNET_DISABLED", 0, RES_EVENT_NO, NULL, + &tfe_cannot_use, set_tfe_disabled, NULL }, + { "ETHERNET_ACTIVE", 0, RES_EVENT_STRICT, (resource_value_t)0, + &tfe_enabled, set_tfe_enabled, NULL }, + { "ETHERNET_AS_RR", 0, RES_EVENT_NO, NULL, + &tfe_as_rr_net, set_tfe_rr_net, NULL }, + { NULL } +};*/ + +/*int tfe_resources_init(void) +{ + if (resources_register_string(resources_string) < 0) + return -1; + + return resources_register_int(resources_int); +}*/ + +/* ------------------------------------------------------------------------- */ +/* commandline support functions */ + +/*static const cmdline_option_t cmdline_options[] = +{ + { "-tfe", SET_RESOURCE, 0, + NULL, NULL, "ETHERNET_ACTIVE", (resource_value_t)1, + USE_PARAM_STRING, USE_DESCRIPTION_ID, + IDCLS_UNUSED, IDCLS_ENABLE_TFE, + NULL, NULL }, + { "+tfe", SET_RESOURCE, 0, + NULL, NULL, "ETHERNET_ACTIVE", (resource_value_t)0, + USE_PARAM_STRING, USE_DESCRIPTION_ID, + IDCLS_UNUSED, IDCLS_DISABLE_TFE, + NULL, NULL }, + { "-tfeif", SET_RESOURCE, 1, + NULL, NULL, "ETHERNET_INTERFACE", NULL, + USE_PARAM_ID, USE_DESCRIPTION_ID, + IDCLS_P_NAME, IDCLS_TFE_INTERFACE, + NULL, NULL }, + { "-tferrnet", SET_RESOURCE, 0, + NULL, NULL, "ETHERNET_AS_RR", (resource_value_t)1, + USE_PARAM_STRING, USE_DESCRIPTION_ID, + IDCLS_UNUSED, IDCLS_ENABLE_TFE_AS_RRNET, + NULL, NULL }, + { "+tferrnet", SET_RESOURCE, 0, + NULL, NULL, "ETHERNET_AS_RR", (resource_value_t)0, + USE_PARAM_STRING, USE_DESCRIPTION_ID, + IDCLS_UNUSED, IDCLS_DISABLE_TFE_AS_RRNET, + NULL, NULL }, + { NULL } +}; + +int tfe_cmdline_options_init(void) +{ + return cmdline_register_options(cmdline_options); +}*/ + + +/* ------------------------------------------------------------------------- */ +/* snapshot support functions */ + +#if 0 + +static char snap_module_name[] = "TFE1764"; +#define SNAP_MAJOR 0 +#define SNAP_MINOR 0 + +int tfe_read_snapshot_module(struct snapshot_s *s) +{ + /* @SRT TODO: not yet implemented */ + return -1; +} + +int tfe_write_snapshot_module(struct snapshot_s *s) +{ + /* @SRT TODO: not yet implemented */ + return -1; +} + +#endif /* #if 0 */ + +/* ------------------------------------------------------------------------- */ +/* functions for selecting and querying available NICs */ + +int tfe_enumadapter_open(void) +{ + if (!tfe_arch_enumadapter_open()) { + tfe_cannot_use = 1; + return 0; + } + return 1; +} + +int tfe_enumadapter(char **ppname, char **ppdescription) +{ + return tfe_arch_enumadapter(ppname, ppdescription); +} + +int tfe_enumadapter_close(void) +{ + return tfe_arch_enumadapter_close(); +} + +//#endif /* #ifdef HAVE_TFE */ diff --git a/src/vars_kegs32 b/src/vars_kegs32 new file mode 100644 index 0000000..f264d63 --- /dev/null +++ b/src/vars_kegs32 @@ -0,0 +1,10 @@ + +TARGET = kegswin.exe +OBJECTS = $(OBJECTS1) win32snd_driver.o windriver.o kegs32.o +CCOPTS = -O2 -DKEGS_LITTLE_ENDIAN +SUFFIX = ".exe" +NAME = kegswin + +XOPTS = -Wall -fomit-frame-pointer -march=pentium +XLIBS = + diff --git a/src/win32.ico b/src/win32.ico new file mode 100644 index 0000000..f9f1227 Binary files /dev/null and b/src/win32.ico differ diff --git a/src/win32.rc b/src/win32.rc index e0cd945..76afa5b 100644 --- a/src/win32.rc +++ b/src/win32.rc @@ -1,24 +1,3 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - #include #include "winresource.h" @@ -28,67 +7,45 @@ #define IDC_STATIC (-1) #endif -IDD_DLG_DISKCONF DIALOGEX 0, 0, 268, 182 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Disk Configuration" -FONT 8, "MS Sans Serif" -BEGIN - DEFPUSHBUTTON "OK",IDOK,150,161,50,14 - PUSHBUTTON "Cancel",IDCANCEL,203,161,50,14 - LTEXT "S5D1",IDC_STATIC,19,46,19,8 - EDITTEXT IDC_EDIT_S5D1,43,42,156,14,ES_AUTOHSCROLL, - WS_EX_ACCEPTFILES - PUSHBUTTON "Browse",IDC_BTN_S5D1,203,42,50,14 - LTEXT "S5D2",IDC_STATIC,19,62,19,8 - EDITTEXT IDC_EDIT_S5D2,43,60,155,14,ES_AUTOHSCROLL - PUSHBUTTON "Browse",IDC_BTN_S5D2,203,60,50,14 - LTEXT "S6D1",IDC_STATIC,19,80,19,8 - EDITTEXT IDC_EDIT_S6D1,43,77,156,14,ES_AUTOHSCROLL - PUSHBUTTON "Browse",IDC_BTN_S6D1,203,77,50,14 - LTEXT "S6D2",IDC_STATIC,19,98,19,8 - EDITTEXT IDC_EDIT_S6D2,43,95,156,14,ES_AUTOHSCROLL - PUSHBUTTON "Browse",IDC_BTN_S6D2,203,96,50,14 - LTEXT "S7D1",IDC_STATIC,19,118,19,8 - EDITTEXT IDC_EDIT_S7D1,43,115,155,14,ES_AUTOHSCROLL - PUSHBUTTON "Browse",IDC_BTN_S7D1,203,115,50,14 - LTEXT "S7D2",IDC_STATIC,19,137,19,8 - EDITTEXT IDC_EDIT_S7D2,43,135,155,14,ES_AUTOHSCROLL - PUSHBUTTON "Browse",IDC_BTN_S7D2,203,135,50,14 - GROUPBOX "Disk settings",IDC_STATIC,7,7,254,148 - LTEXT "Configure your disk images for each drive. Disk image formats supported\nare *.2MG,*.PO and *.DSK. ", - IDC_STATIC,19,20,234,16 -END - ///////////////////////////////////////////////////////////////////////////// // // Menu // -IDC_KEGS32 MENU DISCARDABLE +IDC_KEGS32 MENU DISCARDABLE BEGIN POPUP "&Emulator" BEGIN - MENUITEM "&Set Disk Configuration\tALT-F1", ID_FILE_DISK - MENUITEM "Send CTRL Open-Apple Reset\tCTRL-ALT-BREAK", - ID_FILE_SENDRESET + MENUITEM "&Set Disk Configuration", ID_FILE_DISK + MENUITEM "Send CTRL Reset\tCTRL-BREAK", ID_FILE_SENDRESET + MENUITEM "Reboot\tCTRL-ALT-BREAK", ID_FILE_SENDREBOOT + MENUITEM SEPARATOR MENUITEM "Toggle &Joystick", ID_FILE_JOYSTICK MENUITEM "Toggle Debug Statistics", ID_FILE_DEBUGSTAT MENUITEM SEPARATOR - MENUITEM "E&xit\tALT-F4", ID_FILE_EXIT + MENUITEM "E&xit", ID_FILE_EXIT END POPUP "&Help" BEGIN + MENUITEM "Key Commands", ID_HELP_KEY + MENUITEM SEPARATOR MENUITEM "&About", ID_HELP_ABOUT END END +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +// CREATEPROCESS_MANIFEST RT_MANIFEST "kegs.manifest" ///////////////////////////////////////////////////////////////////////////// // // Bitmap // -IDR_TOOLBAR BITMAP DISCARDABLE "wintoolbar.bmp" +IDC_KEGS32 BITMAP DISCARDABLE "wintoolbar.bmp" ///////////////////////////////////////////////////////////////////////////// // @@ -122,9 +79,102 @@ CAPTION "About" FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK",IDOK,78,61,50,14 - LTEXT "KEGS32: GS Emulator.\nBased on KEGS by Kent Dickey\nWindows Port by Chea Chee Keong\n\nThis software is free for non-commercial use.", + LTEXT "KEGS32: GS Emulator.\nBased on KEGS by Kent Dickey\nWindows Port by Chea Chee Keong\n\nThis software is licensed under GNU GPL.", IDC_STATIC,38,7,162,45,NOT WS_GROUP ICON "KEGS32_ICON",IDC_STATIC,7,7,21,20,0 END +IDD_DLG_DISKCONF DIALOGEX 0, 0, 268, 182 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Disk Configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,150,161,50,14 + PUSHBUTTON "Cancel",IDCANCEL,203,161,50,14 + LTEXT "S5D1",IDC_STATIC,19,46,19,8 + EDITTEXT IDC_EDIT_S5D1,43,42,156,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S5D1,203,42,50,14 + LTEXT "S5D2",IDC_STATIC,19,62,19,8 + EDITTEXT IDC_EDIT_S5D2,43,60,155,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S5D2,203,60,50,14 + LTEXT "S6D1",IDC_STATIC,19,80,19,8 + EDITTEXT IDC_EDIT_S6D1,43,77,156,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S6D1,203,77,50,14 + LTEXT "S6D2",IDC_STATIC,19,98,19,8 + EDITTEXT IDC_EDIT_S6D2,43,95,156,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S6D2,203,96,50,14 + LTEXT "S7D1",IDC_STATIC,19,118,19,8 + EDITTEXT IDC_EDIT_S7D1,43,115,155,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S7D1,203,115,50,14 + LTEXT "S7D2",IDC_STATIC,19,137,19,8 + EDITTEXT IDC_EDIT_S7D2,43,135,155,14,ES_AUTOHSCROLL, + WS_EX_ACCEPTFILES + PUSHBUTTON "Browse",IDC_BTN_S7D2,203,135,50,14 + GROUPBOX "Disk settings",IDC_STATIC,7,7,254,148 + LTEXT "Configure your disk images for each drive. Disk image formats supported\nare *.2MG,*.PO and *.DSK. ", + IDC_STATIC,19,20,234,16 +END + +IDD_SPEEDDIALOG DIALOG 0, 0, 240, 129 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Speed Control" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "1 MHz",IDC_SLOW,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,45,41,51,13 + CONTROL "2.5 MHz",IDC_NORMAL,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,45,55,43,13 + CONTROL "As fast as possible",IDC_FASTEST,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,45,69,74,13 + CONTROL "Custom (MHz)",IDC_CUSTOM,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,45,83,69,13 + EDITTEXT IDC_EDITCUSTOM,117,83,79,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,133,107,50,15 + PUSHBUTTON "Cancel",IDCANCEL,183,107,50,15 + GROUPBOX "Speed Control",IDC_STATIC,7,7,226,96,WS_GROUP + LTEXT "Adjust the speed of your emulator by selecting the appropriate speed control", + IDC_STATIC,46,19,181,19,NOT WS_GROUP + ICON IDC_KEGS32,IDC_STATIC,14,19,21,20 +END + +IDD_KEGS32_KEY DIALOG 0, 0, 186, 172 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Help About Key Commands" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,151,50,14 + LTEXT "KEGS32 Key Commands",IDC_STATIC,7,7,82,10 + LTEXT "Alt/F1\t\tOpen-Apple\nF2\t\tClose-Apple\nF7\t\tToggle Fast Disk Emulation\nF8\t\tToggle Mouse Pointer\n\t\tDisplay\n", + IDC_STATIC,21,25,151,42 + LTEXT "F11\t\tToggle Fullscreen Display\nF12\t\tReset\nCtrl-Alt-Break\tReboot Emulator\nCtrl-Alt-Esc\tControl-Panel\nCtrl-Break\tReset Emulator", + IDC_STATIC,21,66,141,50 + CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | WS_DISABLED | + WS_BORDER,7,17,172,1 + LTEXT "For more information, please consult the readme.kegs file", + IDC_STATIC,21,124,144,19 +END + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + ID_FILE_DISK "Disk Configuration" +END + +STRINGTABLE +BEGIN + ID_SPEED_1MHZ "Set Speed to 1 Mhz" + ID_SPEED_2MHZ "Set Speed to 2.5 Mhz" + ID_SPEED_FMHZ "Set Speed to as fast as possible" +END + + diff --git a/src/win32snd_driver.c b/src/win32snd_driver.c index 869bc17..9be2947 100644 --- a/src/win32snd_driver.c +++ b/src/win32snd_driver.c @@ -1,23 +1,12 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/************************************************************************/ +/* KEGS: Apple //gs Emulator */ +/* Copyright 2002 by Kent Dickey */ +/* */ +/* This code is covered by the GNU GPL */ +/* */ +/* The KEGS web page is kegs.sourceforge.net */ +/* You may contact the author at: kadickey@alumni.princeton.edu */ +/************************************************************************/ const char rcsid_win32snd_driver_c[] = "@(#)$KmKId: win32snd_driver.c,v 1.5 2002-11-19 03:09:59-05 kadickey Exp $"; @@ -28,7 +17,7 @@ const char rcsid_win32snd_driver_c[] = "@(#)$KmKId: win32snd_driver.c,v 1.5 2002 # include # include #endif -#include +//#include extern int Verbose; @@ -69,8 +58,8 @@ win32snd_shutdown() #ifndef __CYGWIN__ void CALLBACK -handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, - DWORD dwParam2) +handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, + DWORD_PTR dwParam2) { LPWAVEHDR lpwavehdr; @@ -131,7 +120,7 @@ child_sound_init_win32() } res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, - (DWORD)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC); + (DWORD_PTR)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC); if(res != MMSYSERR_NOERROR) { printf("Cannot register audio\n"); diff --git a/src/windriver.c b/src/windriver.c index 5a7bc6d..75960fc 100644 --- a/src/windriver.c +++ b/src/windriver.c @@ -1,685 +1,1245 @@ -/* - GSport - an Apple //gs Emulator - Copyright (C) 2010 by GSport contributors - - Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -const char rcsid_windriver_c[] = "@(#)$KmKId: windriver.c,v 1.11 2004-11-24 16:43:46-05 kentd Exp $"; - -/* Based on code from Chea Chee Keong from KEGS32, which is available at */ -/* http://www.geocities.com/akilgard/kegs32 */ - -#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */ -#define STRICT /* Tell Windows we want compile type checks */ - -#include -#include -#include -#include -#include - -#include "defc.h" -#include "protos_windriver.h" - -extern int Verbose; - -extern int g_warp_pointer; -extern int g_screen_depth; -extern int g_force_depth; -int g_screen_mdepth = 0; - -extern int g_quit_sim_now; - -int g_use_shmem = 1; -int g_has_focus = 0; -int g_auto_repeat_on = -1; - -extern Kimage g_mainwin_kimage; - -HDC g_main_dc; -HDC g_main_cdc; -int g_main_height = 0; - -int g_win_capslock_down = 0; - -extern word32 g_palette_8to1624[256]; -extern word32 g_a2palette_8to1624[256]; - -extern word32 g_full_refresh_needed; - -extern int g_border_sides_refresh_needed; -extern int g_border_special_refresh_needed; -extern int g_status_refresh_needed; - -extern int g_lores_colors[]; -extern int g_cur_a2_stat; - -extern int g_a2vid_palette; - -extern int g_installed_full_superhires_colormap; - -extern int g_screen_redraw_skip_amt; - -extern word32 g_a2_screen_buffer_changed; - -HWND g_hwnd_main; -BITMAPINFO *g_bmapinfo_ptr = 0; -volatile BITMAPINFOHEADER *g_bmaphdr_ptr = 0; - -int g_num_a2_keycodes = 0; - -extern char *g_status_ptrs[MAX_STATUS_LINES]; - -int g_win_button_states = 0; - - -/* this table is used to search for the Windows VK_* in col 1 or 2 */ -/* flags bit 8 is or'ed into the VK, so we can distinguish keypad keys */ -/* regardless of numlock */ -int g_a2_key_to_wsym[][3] = { - { 0x35, VK_ESCAPE, 0 }, - { 0x7a, VK_F1, 0 }, - { 0x7b, VK_F2, 0 }, - { 0x63, VK_F3, 0 }, - { 0x76, VK_F4, 0 }, - { 0x60, VK_F5, 0 }, - { 0x61, VK_F6, 0 }, - { 0x62, VK_F7, 0 }, - { 0x64, VK_F8, 0 }, - { 0x65, VK_F9, 0 }, - { 0x6d, VK_F10, 0 }, - { 0x67, VK_F11, 0 }, - { 0x6f, VK_F12, 0 }, - { 0x69, VK_F13, 0 }, - { 0x6b, VK_F14, 0 }, - { 0x71, VK_F15, 0 }, - { 0x7f, VK_PAUSE, VK_CANCEL+0x100 }, - - { 0x32, 0xc0, 0 }, /* '`' */ - { 0x12, '1', 0 }, - { 0x13, '2', 0 }, - { 0x14, '3', 0 }, - { 0x15, '4', 0 }, - { 0x17, '5', 0 }, - { 0x16, '6', 0 }, - { 0x1a, '7', 0 }, - { 0x1c, '8', 0 }, - { 0x19, '9', 0 }, - { 0x1d, '0', 0 }, - { 0x1b, 0xbd, 0 }, /* '-' */ - { 0x18, 0xbb, 0 }, /* '=' */ - { 0x33, VK_BACK, 0 }, /* backspace */ - { 0x72, VK_INSERT+0x100, 0 }, /* Insert key */ -/* { 0x73, XK_Home, 0 }, alias VK_HOME to be KP_Equal! */ - { 0x74, VK_PRIOR+0x100, 0 }, /* pageup */ - { 0x47, VK_NUMLOCK, VK_NUMLOCK+0x100 }, /* clear */ - { 0x51, VK_HOME+0x100, 0 }, /* KP_equal is HOME key */ - { 0x4b, VK_DIVIDE, VK_DIVIDE+0x100 }, - { 0x43, VK_MULTIPLY, VK_MULTIPLY+0x100 }, - - { 0x30, VK_TAB, 0 }, - { 0x0c, 'Q', 0 }, - { 0x0d, 'W', 0 }, - { 0x0e, 'E', 0 }, - { 0x0f, 'R', 0 }, - { 0x11, 'T', 0 }, - { 0x10, 'Y', 0 }, - { 0x20, 'U', 0 }, - { 0x22, 'I', 0 }, - { 0x1f, 'O', 0 }, - { 0x23, 'P', 0 }, - { 0x21, 0xdb, 0 }, /* [ */ - { 0x1e, 0xdd, 0 }, /* ] */ - { 0x2a, 0xdc, 0 }, /* backslash, bar */ - { 0x75, VK_DELETE+0x100, 0 }, - { 0x77, VK_END+0x100, VK_END }, - { 0x79, VK_NEXT+0x100, 0 }, - { 0x59, VK_NUMPAD7, VK_HOME }, - { 0x5b, VK_NUMPAD8, VK_UP }, - { 0x5c, VK_NUMPAD9, VK_PRIOR }, - { 0x4e, VK_SUBTRACT, VK_SUBTRACT+0x100 }, - - // { 0x39, VK_CAPITAL, 0 }, // Handled specially! - { 0x00, 'A', 0 }, - { 0x01, 'S', 0 }, - { 0x02, 'D', 0 }, - { 0x03, 'F', 0 }, - { 0x05, 'G', 0 }, - { 0x04, 'H', 0 }, - { 0x26, 'J', 0 }, - { 0x28, 'K', 0 }, - { 0x25, 'L', 0 }, - { 0x29, 0xba, 0 }, /* ; */ - { 0x27, 0xde, 0 }, /* single quote */ - { 0x24, VK_RETURN, 0 }, - { 0x56, VK_NUMPAD4, VK_LEFT }, - { 0x57, VK_NUMPAD5, VK_CLEAR }, - { 0x58, VK_NUMPAD6, VK_RIGHT }, - { 0x45, VK_ADD, 0 }, - - { 0x38, VK_SHIFT, 0 }, - { 0x06, 'Z', 0 }, - { 0x07, 'X', 0 }, - { 0x08, 'C', 0 }, - { 0x09, 'V', 0 }, - { 0x0b, 'B', 0 }, - { 0x2d, 'N', 0 }, - { 0x2e, 'M', 0 }, - { 0x2b, 0xbc, 0 }, /* , */ - { 0x2f, 0xbe, 0 }, /* . */ - { 0x2c, 0xbf, 0 }, /* / */ - { 0x3e, VK_UP+0x100, 0 }, - { 0x53, VK_NUMPAD1, VK_END }, - { 0x54, VK_NUMPAD2, VK_DOWN }, - { 0x55, VK_NUMPAD3, VK_NEXT }, - - { 0x36, VK_CONTROL, VK_CONTROL+0x100 }, - { 0x3a, VK_SNAPSHOT+0x100, VK_MENU+0x100 },/* Opt=prntscrn or alt-r */ - { 0x37, VK_SCROLL, VK_MENU }, /* Command=scr_lock or alt-l */ - { 0x31, ' ', 0 }, - { 0x3b, VK_LEFT+0x100, 0 }, - { 0x3d, VK_DOWN+0x100, 0 }, - { 0x3c, VK_RIGHT+0x100, 0 }, - { 0x52, VK_NUMPAD0, VK_INSERT }, - { 0x41, VK_DECIMAL, VK_DECIMAL }, - { 0x4c, VK_RETURN+0x100, 0 }, - { -1, -1, -1 } -}; - -int -win_nonblock_read_stdin(int fd, char *bufptr, int len) -{ - HANDLE oshandle; - DWORD dwret; - int ret; - - errno = EAGAIN; - oshandle = (HANDLE)_get_osfhandle(fd); // get stdin handle - dwret = WaitForSingleObject(oshandle, 1); // wait 1msec for data - ret = -1; - if(dwret == WAIT_OBJECT_0) { - ret = read(fd, bufptr, len); - } - return ret; -} - -void -x_dialog_create_kegs_conf(const char *str) -{ -} - -int -x_show_alert(int is_fatal, const char *str) -{ - return 0; -} - -int -win_update_mouse(int x, int y, int button_states, int buttons_valid) -{ - int buttons_changed; - - buttons_changed = ((g_win_button_states & buttons_valid) != - button_states); - g_win_button_states = (g_win_button_states & ~buttons_valid) | - (button_states & buttons_valid); - if(g_warp_pointer && (x == A2_WINDOW_WIDTH/2) && - (y == A2_WINDOW_HEIGHT/2) && (!buttons_changed) ) { - /* tell adb routs to recenter but ignore this motion */ - update_mouse(x, y, 0, -1); - return 0; - } - return update_mouse(x, y, button_states, buttons_valid & 7); -} - -void -win_event_mouse(WPARAM wParam, LPARAM lParam) -{ - POINT pt; - word32 flags; - int buttons; - int x, y; - int motion; - - flags = wParam; - x = LOWORD(lParam) - BASE_MARGIN_LEFT; - y = HIWORD(lParam) - BASE_MARGIN_TOP; - - buttons = (flags & 1) + - (((flags >> 1) & 1) << 2) + - (((flags >> 4) & 1) << 1); -#if 0 - printf("Mouse at %d, %d fl: %08x, but: %d\n", x, y, flags, buttons); -#endif - motion = win_update_mouse(x, y, buttons, 7); - - if(motion && g_warp_pointer) { - /* move mouse to center of screen */ - pt.x = BASE_MARGIN_LEFT + A2_WINDOW_WIDTH/2; - pt.y = BASE_MARGIN_TOP + A2_WINDOW_HEIGHT/2; - ClientToScreen(g_hwnd_main, &pt); - SetCursorPos(pt.x, pt.y); - } -} - -void -win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags) -{ - word32 vk; - int a2code; - int is_up; - int capslock_down; - int i; - - if((flags & 0x4000) && down) { - /* auto-repeating, just ignore it */ - return; - } - - vk = raw_vk + (flags & 0x100); -#if 0 - printf("Key event, vk=%04x, down:%d, repeat: %d, flags: %08x\n", - vk, down, repeat, flags); -#endif - - /* remap a few keys here.. sigh */ - if((vk & 0xff) == VK_APPS) { - /* remap to command */ - vk = VK_MENU; - } - - if((vk & 0xff) == VK_CAPITAL) { - // Windows gives us up-and-down events of the actual key - // Use GetKeyState to get the true toggle state, and pass - // that on to the adb interface - capslock_down = GetKeyState(VK_CAPITAL) & 0x01; - if(capslock_down != g_win_capslock_down) { - g_win_capslock_down = capslock_down; - adb_physical_key_update(0x39, !capslock_down); - } - - return; // Do no more processing! - } - - /* search a2key_to_wsym to find wsym in col 1 or 2 */ - i = 0; - is_up = !down; - for(i = g_num_a2_keycodes-1; i >= 0; i--) { - a2code = g_a2_key_to_wsym[i][0]; - if((vk == g_a2_key_to_wsym[i][1]) || - (vk == g_a2_key_to_wsym[i][2])) { - vid_printf("Found vk:%04x = %02x\n", vk, a2code); - adb_physical_key_update(a2code, is_up); - return; - } - } - printf("VK: %04x unknown\n", vk); -} - -void -win_event_quit(HWND hwnd) -{ - g_quit_sim_now = 1; - my_exit(0); -} - -void -win_event_redraw() -{ - g_full_refresh_needed = -1; - g_a2_screen_buffer_changed = -1; - g_status_refresh_needed = 1; - g_border_sides_refresh_needed = 1; - g_border_special_refresh_needed = 1; -} - -LRESULT CALLBACK -win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) -{ - switch(umsg) { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - win_event_mouse(wParam, lParam); - return 0; - case WM_PAINT: - win_event_redraw(); - break; - } - switch(umsg) { - HANDLE_MSG(hwnd, WM_KEYUP, win_event_key); - HANDLE_MSG(hwnd, WM_KEYDOWN, win_event_key); - HANDLE_MSG(hwnd, WM_SYSKEYUP, win_event_key); - HANDLE_MSG(hwnd, WM_SYSKEYDOWN, win_event_key); - HANDLE_MSG(hwnd, WM_DESTROY, win_event_quit); - } - -#if 0 - switch(umsg) { - case WM_NCACTIVATE: - case WM_NCHITTEST: - case WM_NCMOUSEMOVE: - case WM_SETCURSOR: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_CONTEXTMENU: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_PAINT: - - break; - default: - printf("Got umsg2: %d\n", umsg); - } -#endif - - return DefWindowProc(hwnd, umsg, wParam, lParam); -} - - -int -main(int argc, char **argv) -{ - WNDCLASS wndclass; - RECT rect; - int height; - - InitCommonControls(); - - wndclass.style = 0; - wndclass.lpfnWndProc = (WNDPROC)win_event_handler; - wndclass.cbClsExtra = 0; - wndclass.cbWndExtra = 0; - wndclass.hInstance = GetModuleHandle(NULL); - wndclass.hIcon = LoadIcon((HINSTANCE)NULL, IDI_APPLICATION); - wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); - wndclass.hbrBackground = GetStockObject(WHITE_BRUSH); - wndclass.lpszMenuName = NULL; - wndclass.lpszClassName = "gsportwin"; - - // Register the window - if(!RegisterClass(&wndclass)) { - printf("Registering window failed\n"); - exit(1); - } - - height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES * 16) + 32; - g_main_height = height; - - g_hwnd_main = CreateWindow("gsportwin", "GSportWin - Apple //gs Emulator", - WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, - CW_USEDEFAULT, CW_USEDEFAULT, - X_A2_WINDOW_WIDTH, height, - NULL, NULL, GetModuleHandle(NULL), NULL); - - printf("g_hwnd_main = %p, height = %d\n", g_hwnd_main, height); - GetWindowRect(g_hwnd_main, &rect); - printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top, - rect.right, rect.bottom); - - g_main_dc = GetDC(g_hwnd_main); - - SetTextColor(g_main_dc, 0); - SetBkColor(g_main_dc, 0xffffff); - - g_main_cdc = CreateCompatibleDC(g_main_dc); - - g_screen_depth = 24; - g_screen_mdepth = 32; - - - // Call kegsmain - return kegsmain(argc, argv); -} - - -void -check_input_events() -{ - MSG msg; - - while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) { - if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } else { - printf("GetMessage returned <= 0\n"); - my_exit(2); - } - } - - return; -} - - -void -x_update_color(int col_num, int red, int green, int blue, word32 rgb) -{ -} - -void -x_update_physical_colormap() -{ -} - -void -show_xcolor_array() -{ - int i; - - for(i = 0; i < 256; i++) { - printf("%02x: %08x\n", i, g_palette_8to1624[i]); - } -} - - -void -xdriver_end() -{ - printf("xdriver_end\n"); -} - - -void -x_get_kimage(Kimage *kimage_ptr) -{ - byte *ptr; - int width; - int height; - int depth, mdepth; - int size; - - width = kimage_ptr->width_req; - height = kimage_ptr->height; - depth = kimage_ptr->depth; - mdepth = kimage_ptr->mdepth; - - size = 0; - if(depth == g_screen_depth) { - /* Use g_bmapinfo_ptr, adjusting width, height */ - g_bmaphdr_ptr->biWidth = width; - g_bmaphdr_ptr->biHeight = -height; - kimage_ptr->dev_handle = CreateDIBSection(g_main_dc, - g_bmapinfo_ptr, DIB_RGB_COLORS, - (VOID **)&(kimage_ptr->data_ptr), NULL, 0); - } else { - /* allocate buffers for video.c to draw into */ - - size = (width*height*mdepth) >> 3; - ptr = (byte *)malloc(size); - - if(ptr == 0) { - printf("malloc for data failed, mdepth: %d\n", mdepth); - exit(2); - } - - kimage_ptr->data_ptr = ptr; - - kimage_ptr->dev_handle = (void *)-1; - - } - printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr, - kimage_ptr->dev_handle, kimage_ptr->data_ptr, size); - - return; -} - - -void -dev_video_init() -{ - int extra_size; - int lores_col; - int a2code; - int i; - - printf("Preparing graphics system\n"); - - g_num_a2_keycodes = 0; - for(i = 0; i < 0x7f; i++) { - a2code = g_a2_key_to_wsym[i][0]; - if(a2code < 0) { - g_num_a2_keycodes = i; - } - } - - g_screen_depth = 24; - g_screen_mdepth = 32; - - extra_size = sizeof(RGBQUAD); - if(g_screen_depth == 8) { - extra_size = 256 * sizeof(RGBQUAD); - } - g_bmapinfo_ptr = (BITMAPINFO *)GlobalAlloc(GPTR, - sizeof(BITMAPINFOHEADER) + extra_size); - - g_bmaphdr_ptr = (BITMAPINFOHEADER *)g_bmapinfo_ptr; - g_bmaphdr_ptr->biSize = sizeof(BITMAPINFOHEADER); - g_bmaphdr_ptr->biWidth = A2_WINDOW_WIDTH; - g_bmaphdr_ptr->biHeight = -A2_WINDOW_HEIGHT; - g_bmaphdr_ptr->biPlanes = 1; - g_bmaphdr_ptr->biBitCount = g_screen_mdepth; - g_bmaphdr_ptr->biCompression = BI_RGB; - g_bmaphdr_ptr->biClrUsed = 0; - - video_get_kimages(); - - if(g_screen_depth != 8) { - // Allocate g_mainwin_kimage - video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, - g_screen_mdepth); - } - - for(i = 0; i < 256; i++) { - lores_col = g_lores_colors[i & 0xf]; - video_update_color_raw(i, lores_col); - g_a2palette_8to1624[i] = g_palette_8to1624[i]; - } - - g_installed_full_superhires_colormap = 1; - - ShowWindow(g_hwnd_main, SW_SHOWDEFAULT); - UpdateWindow(g_hwnd_main); - - printf("Done with dev_video_init\n"); - fflush(stdout); - -} - -void -x_redraw_status_lines() -{ - COLORREF oldtextcolor, oldbkcolor; - char *buf; - int line; - int len; - int height; - int margin; - - height = 16; - margin = 0; - - oldtextcolor = SetTextColor(g_main_dc, 0); - oldbkcolor = SetBkColor(g_main_dc, 0xffffff); - for(line = 0; line < MAX_STATUS_LINES; line++) { - buf = g_status_ptrs[line]; - if(buf != 0) { - len = strlen(buf); - TextOut(g_main_dc, 10, X_A2_WINDOW_HEIGHT + - height*line + margin, buf, len); - } - } - SetTextColor(g_main_dc, oldtextcolor); - SetBkColor(g_main_dc, oldbkcolor); -} - - -void -x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, - int width, int height) -{ - void *bitm_old; - POINT point; - - point.x = 0; - point.y = 0; - ClientToScreen(g_hwnd_main, &point); - bitm_old = SelectObject(g_main_cdc, kimage_ptr->dev_handle); - - BitBlt(g_main_dc, destx, desty, width, height, - g_main_cdc, srcx, srcy, SRCCOPY); - - SelectObject(g_main_cdc, bitm_old); -} - -void -x_push_done() -{ -} - -void -x_auto_repeat_on(int must) -{ -} - -void -x_auto_repeat_off(int must) -{ -} - -void -x_hide_pointer(int do_hide) -{ - if(do_hide) { - ShowCursor(0); - } else { - ShowCursor(1); - } -} - -void -x_full_screen(int do_full) -{ - return; -} +/* + GSport - an Apple //gs Emulator + Copyright (C) 2010 by GSport contributors + + Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +const char rcsid_windriver_c[] = "@(#)$KmKId: windriver.c,v 1.11 2004-11-24 16:43:46-05 kentd Exp $"; + +/* Based on code from Chea Chee Keong from KEGS32, which is available at */ +/* http://www.geocities.com/akilgard/kegs32 */ + +#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header junk */ +#define STRICT /* Tell Windows we want compile type checks */ + +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + +#include +#include +#include +#include +#include +#include +#include +#include +#include "winresource.h" +#include "defc.h" +#include "protos_windriver.h" +#include "printer.h" + + +#if defined _MSC_VER && defined _WIN64 +#define gwlproc GWLP_WNDPROC +#endif +#if defined _MSC_VER && defined _WIN32 && !defined _WIN64 +#define gwlproc GWL_WNDPROC +#endif + +extern int Verbose; + +extern int g_warp_pointer; +extern int g_screen_depth; +extern int g_force_depth; + +int g_screen_mdepth = 0; + +extern int g_quit_sim_now; + +int g_use_shmem = 1; +int g_has_focus = 0; +int g_auto_repeat_on = -1; + +extern Kimage g_mainwin_kimage; + +HDC g_main_dc; +HDC g_main_cdc; +int g_main_height = 0; + +int g_win_capslock_down = 0; + +extern word32 g_palette_8to1624[256]; +extern word32 g_a2palette_8to1624[256]; + +extern word32 g_full_refresh_needed; + +extern int g_border_sides_refresh_needed; +extern int g_border_special_refresh_needed; +extern int g_status_refresh_needed; + +extern int g_lores_colors[]; +extern int g_cur_a2_stat; + +extern int g_a2vid_palette; + +extern int g_installed_full_superhires_colormap; + +extern int g_screen_redraw_skip_amt; + +extern word32 g_a2_screen_buffer_changed; + +HWND g_hwnd_main; +BITMAPINFO *g_bmapinfo_ptr = 0; +volatile BITMAPINFOHEADER *g_bmaphdr_ptr = 0; + +// KEGS32 specific customisations +HWND g_win_toolbar=NULL; +HWND g_win_status=NULL; +RECT g_win_status_height={0}; +RECT g_win_toolbar_height={0}; +int g_win_status_debug = 0; +RECT g_main_window_saved_rect; +HMENU g_main_window_menu_saved; +int g_win_fullscreen_state = 0; +WNDPROC oldEditWndProc; +extern int g_joystick_type; +extern int g_config_kegs_update_needed; +extern int g_limit_speed; +extern int g_doc_vol; + +int g_num_a2_keycodes = 0; + +extern char *g_status_ptrs[MAX_STATUS_LINES]; + +int g_win_button_states = 0; + + +/* this table is used to search for the Windows VK_* in col 1 or 2 */ +/* flags bit 8 is or'ed into the VK, so we can distinguish keypad keys */ +/* regardless of numlock */ +int g_a2_key_to_wsym[][3] = { + { 0x35, VK_ESCAPE, 0 }, + { 0x7a, VK_F1, 0 }, + { 0x78, VK_F2, 0 }, + { 0x63, VK_F3, 0 }, + { 0x76, VK_F4, 0 }, + { 0x60, VK_F5, 0 }, + { 0x61, VK_F6, 0 }, + { 0x62, VK_F7, 0 }, + { 0x64, VK_F8, 0 }, + { 0x65, VK_F9, 0 }, + { 0x6d, VK_F10, 0 }, + { 0x67, VK_F11, 0 }, + { 0x6f, VK_F12, 0 }, + { 0x69, VK_F13, 0 }, + { 0x6b, VK_F14, 0 }, + { 0x71, VK_F15, 0 }, + { 0x7f, VK_PAUSE, VK_CANCEL+0x100 }, + + { 0x32, 0xc0, 0 }, /* '`' */ + { 0x12, '1', 0 }, + { 0x13, '2', 0 }, + { 0x14, '3', 0 }, + { 0x15, '4', 0 }, + { 0x17, '5', 0 }, + { 0x16, '6', 0 }, + { 0x1a, '7', 0 }, + { 0x1c, '8', 0 }, + { 0x19, '9', 0 }, + { 0x1d, '0', 0 }, + { 0x1b, 0xbd, 0 }, /* '-' */ + { 0x18, 0xbb, 0 }, /* '=' */ + { 0x33, VK_BACK, 0 }, /* backspace */ + { 0x72, VK_INSERT+0x100, 0 }, /* Insert key */ +/* { 0x73, XK_Home, 0 }, alias VK_HOME to be KP_Equal! */ + { 0x74, VK_PRIOR+0x100, 0 }, /* pageup */ + { 0x47, VK_NUMLOCK, VK_NUMLOCK+0x100 }, /* clear */ + { 0x51, VK_HOME+0x100, 0 }, /* KP_equal is HOME key */ + { 0x4b, VK_DIVIDE, VK_DIVIDE+0x100 }, + { 0x43, VK_MULTIPLY, VK_MULTIPLY+0x100 }, + + { 0x30, VK_TAB, 0 }, + { 0x0c, 'Q', 0 }, + { 0x0d, 'W', 0 }, + { 0x0e, 'E', 0 }, + { 0x0f, 'R', 0 }, + { 0x11, 'T', 0 }, + { 0x10, 'Y', 0 }, + { 0x20, 'U', 0 }, + { 0x22, 'I', 0 }, + { 0x1f, 'O', 0 }, + { 0x23, 'P', 0 }, + { 0x21, 0xdb, 0 }, /* [ */ + { 0x1e, 0xdd, 0 }, /* ] */ + { 0x2a, 0xdc, 0 }, /* backslash, bar */ + { 0x75, VK_DELETE+0x100, 0 }, + { 0x77, VK_END+0x100, VK_END }, + { 0x79, VK_NEXT+0x100, 0 }, + { 0x59, VK_NUMPAD7, VK_HOME }, + { 0x5b, VK_NUMPAD8, VK_UP }, + { 0x5c, VK_NUMPAD9, VK_PRIOR }, + { 0x4e, VK_SUBTRACT, VK_SUBTRACT+0x100 }, + + // { 0x39, VK_CAPITAL, 0 }, // Handled specially! + { 0x00, 'A', 0 }, + { 0x01, 'S', 0 }, + { 0x02, 'D', 0 }, + { 0x03, 'F', 0 }, + { 0x05, 'G', 0 }, + { 0x04, 'H', 0 }, + { 0x26, 'J', 0 }, + { 0x28, 'K', 0 }, + { 0x25, 'L', 0 }, + { 0x29, 0xba, 0 }, /* ; */ + { 0x27, 0xde, 0 }, /* single quote */ + { 0x24, VK_RETURN, 0 }, + { 0x56, VK_NUMPAD4, VK_LEFT }, + { 0x57, VK_NUMPAD5, VK_CLEAR }, + { 0x58, VK_NUMPAD6, VK_RIGHT }, + { 0x45, VK_ADD, 0 }, + + { 0x38, VK_SHIFT, 0 }, + { 0x06, 'Z', 0 }, + { 0x07, 'X', 0 }, + { 0x08, 'C', 0 }, + { 0x09, 'V', 0 }, + { 0x0b, 'B', 0 }, + { 0x2d, 'N', 0 }, + { 0x2e, 'M', 0 }, + { 0x2b, 0xbc, 0 }, /* , */ + { 0x2f, 0xbe, 0 }, /* . */ + { 0x2c, 0xbf, 0 }, /* / */ + { 0x3e, VK_UP+0x100, 0 }, + { 0x53, VK_NUMPAD1, VK_END }, + { 0x54, VK_NUMPAD2, VK_DOWN }, + { 0x55, VK_NUMPAD3, VK_NEXT }, + + { 0x36, VK_CONTROL, VK_CONTROL+0x100 }, + { 0x3a, VK_SNAPSHOT+0x100, VK_MENU+0x100 },/* Opt=prntscrn or alt-r */ + { 0x37, VK_SCROLL, VK_MENU }, /* Command=scr_lock or alt-l */ + { 0x31, ' ', 0 }, + { 0x3b, VK_LEFT+0x100, 0 }, + { 0x3d, VK_DOWN+0x100, 0 }, + { 0x3c, VK_RIGHT+0x100, 0 }, + { 0x52, VK_NUMPAD0, VK_INSERT }, + { 0x41, VK_DECIMAL, VK_DECIMAL }, + { 0x4c, VK_RETURN+0x100, 0 }, + { -1, -1, -1 } +}; + +int +win_nonblock_read_stdin(int fd, char *bufptr, int len) +{ + HANDLE oshandle; + DWORD dwret; + int ret; + + errno = EAGAIN; + oshandle = (HANDLE)_get_osfhandle(fd); // get stdin handle + dwret = WaitForSingleObject(oshandle, 1); // wait 1msec for data + ret = -1; + if(dwret == WAIT_OBJECT_0) { + ret = read(fd, bufptr, len); + } + return ret; +} + +void +init_window(HWND hwnd,BOOL initFlag) { + RECT rect; + RECT wrect; + int adjx,adjy; + int win_height; + GetClientRect(hwnd,&rect); + GetWindowRect(hwnd,&wrect); + adjx=(wrect.right-wrect.left)-(rect.right-rect.left); + adjy=(wrect.bottom-wrect.top)-(rect.bottom-rect.top); + + win_height=X_A2_WINDOW_HEIGHT+(g_win_toolbar_height.bottom-g_win_toolbar_height.top)+(g_win_status_height.bottom-g_win_status_height.top); + + if (g_win_status_debug) { + win_height+=(MAX_STATUS_LINES*16); + } + + if (initFlag) { + SetWindowPos(hwnd,NULL, + g_main_window_saved_rect.left, + g_main_window_saved_rect.top, + X_A2_WINDOW_WIDTH+adjx, + win_height+adjy, + SWP_NOACTIVATE | SWP_NOZORDER); + } else { + SetWindowPos(hwnd,HWND_NOTOPMOST, + g_main_window_saved_rect.left, + g_main_window_saved_rect.top, + X_A2_WINDOW_WIDTH+adjx, + win_height+adjy, + SWP_SHOWWINDOW); + } + SendMessage(g_win_status,WM_SIZE,0,0); + SendMessage(g_win_toolbar,WM_SIZE,0,0); +} + +void win_center_dialog (HWND hDlg) { + RECT rc, rcDlg,rcOwner; + HWND hwndOwner; + + if ((hwndOwner = GetParent(hDlg)) == NULL) { + hwndOwner = GetDesktopWindow(); + } + + GetWindowRect(hwndOwner,&rcOwner); + GetWindowRect(hDlg,&rcDlg); + CopyRect(&rc,&rcOwner); + OffsetRect(&rcDlg,-rcDlg.left,-rcDlg.top); + OffsetRect(&rc,-rc.left,-rc.top); + OffsetRect(&rc,-rcDlg.right,-rcDlg.bottom); + + SetWindowPos(hDlg,g_hwnd_main,rcOwner.left+(rc.right/2), + rcOwner.top+(rc.bottom/2), 0,0, + SWP_SHOWWINDOW | SWP_NOSIZE ); +} + +void +read_disk_entry(HWND hDlg) +{ + char buf[2048]; + int slot,drive; + HWND hwnd; + for (slot=5;slot<=7;slot++) { + for(drive=0;drive<=1;drive++) { + Disk* dsk = cfg_get_dsk_from_slot_drive(slot,drive); + buf[0]=0; + if (dsk->name_ptr && dsk->fd > 0) { + hwnd = GetDlgItem(hDlg,10000+slot*10+(drive+1)); + strcpy(buf,dsk->name_ptr); + SetWindowText(hwnd,buf); + } + } + } +} + +void +write_disk_entry(HWND hDlg) +{ + char buf[2048]; + int slot,drive; + HWND hwnd; + for (slot=5;slot<=7;slot++) { + for(drive=0;drive<=1;drive++) { + hwnd = GetDlgItem(hDlg,10000+slot*10+(drive+1)); + buf[0]=0; + GetWindowText(hwnd,buf,2048); + if (lstrlen(buf)>0) { + insert_disk(slot, drive, buf, 0, 0, 0, -1); + } else { + eject_disk_by_num(slot,drive); + } + } + } +} + +// Message handler for handling edit control +// For dropping files +LRESULT CALLBACK win_dialog_edit(HWND hwnd, UINT message, WPARAM wParam, + LPARAM lParam) { + switch (message) { + case WM_DROPFILES: + { + TCHAR buffer[2048]={0}; + HDROP hdrop = (HDROP) wParam; + memset(buffer,0,2048*sizeof(TCHAR)); + DragQueryFile(hdrop,0,buffer,2048); + SetWindowText(hwnd,buffer); + DragFinish(hdrop); + return 0; + } + default: + return CallWindowProc(oldEditWndProc,hwnd,message,wParam,lParam); + } +} + +// Message handler for disk config. +LRESULT CALLBACK win_dialog_disk(HWND hDlg, UINT message, WPARAM wParam, + LPARAM lParam) +{ + typedef LONG(CALLBACK *SETWL)(HWND,int,LONG); + + SETWL SetWL=NULL; + + switch (message) { + case WM_INITDIALOG: + win_center_dialog(hDlg); + + // Subclass the edit-control + SetWL=SetWindowLong; + oldEditWndProc=(WNDPROC) SetWL(GetDlgItem(hDlg,IDC_EDIT_S5D1), + gwlproc,(LONG)win_dialog_edit); + SetWL(GetDlgItem(hDlg,IDC_EDIT_S5D2),gwlproc, + (LONG)win_dialog_edit); + SetWL(GetDlgItem(hDlg,IDC_EDIT_S6D1),gwlproc, + (LONG)win_dialog_edit); + SetWL(GetDlgItem(hDlg,IDC_EDIT_S6D2),gwlproc, + (LONG)win_dialog_edit); + SetWL(GetDlgItem(hDlg,IDC_EDIT_S7D1),gwlproc, + (LONG)win_dialog_edit); + SetWL(GetDlgItem(hDlg,IDC_EDIT_S7D2),gwlproc, + (LONG)win_dialog_edit); + + // Clean entry field (init) + SetWindowText(GetDlgItem(hDlg,IDC_EDIT_S5D1),_T("")); + SetWindowText(GetDlgItem(hDlg,IDC_EDIT_S5D2),_T("")); + SetWindowText(GetDlgItem(hDlg,IDC_EDIT_S6D1),_T("")); + SetWindowText(GetDlgItem(hDlg,IDC_EDIT_S6D2),_T("")); + SetWindowText(GetDlgItem(hDlg,IDC_EDIT_S7D1),_T("")); + SetWindowText(GetDlgItem(hDlg,IDC_EDIT_S7D2),_T("")); + read_disk_entry(hDlg); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + write_disk_entry(hDlg); + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + case IDCANCEL: + EndDialog(hDlg, LOWORD(wParam)); + return FALSE; + case IDC_BTN_S5D1: + case IDC_BTN_S5D2: + case IDC_BTN_S6D1: + case IDC_BTN_S6D2: + case IDC_BTN_S7D1: + case IDC_BTN_S7D2: + { + + TCHAR filename[2048]={0}; + + OPENFILENAME opfn; + ZeroMemory(&opfn,sizeof(opfn)); + opfn.lStructSize=sizeof(opfn); + opfn.hwndOwner=hDlg; + opfn.lpstrFilter=_T("2mg format (*.2mg)\0*.2mg\0" + "Prodos order format (*.po)\0*.po\0" + "Dos order format (*.dsk)\0*.dsk\0" + "All Files (*.*)\0*.*\0" + "\0\0"); + opfn.lpstrFile=filename; + opfn.nMaxFile=2048; + opfn.Flags=OFN_EXPLORER | OFN_FILEMUSTEXIST | + OFN_HIDEREADONLY | OFN_NOCHANGEDIR ; + if (GetOpenFileName(&opfn)) { + SetWindowText(GetDlgItem(hDlg,LOWORD(wParam-1000)), + filename); + } + } + break; + } + break; + } + return FALSE; +} + + + +// Message handler for about box. +LRESULT CALLBACK win_dialog_about_dialog(HWND hDlg, + UINT message, WPARAM wParam, + LPARAM lParam) +{ + switch (message) { + case WM_INITDIALOG: + win_center_dialog(hDlg); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + case IDCANCEL: + EndDialog(hDlg, LOWORD(wParam)); + return FALSE; + + } + } + return FALSE; +} + +void +x_dialog_create_kegs_conf(const char *str) +{ +} + +int +x_show_alert(int is_fatal, const char *str) +{ + return 0; +} + +int +win_update_mouse(int x, int y, int button_states, int buttons_valid) +{ + int buttons_changed; + + buttons_changed = ((g_win_button_states & buttons_valid) != + button_states); + g_win_button_states = (g_win_button_states & ~buttons_valid) | + (button_states & buttons_valid); + if(g_warp_pointer && (x == A2_WINDOW_WIDTH/2) && + (y == A2_WINDOW_HEIGHT/2) && (!buttons_changed) ) { + /* tell adb routs to recenter but ignore this motion */ + update_mouse(x, y, 0, -1); + return 0; + } + return update_mouse(x, y, button_states, buttons_valid & 7); +} + +void +win_event_mouse(WPARAM wParam, LPARAM lParam) +{ + POINT pt; + word32 flags; + int buttons; + int x, y; + int motion; + + flags = wParam; + x = LOWORD(lParam) - BASE_MARGIN_LEFT; + y = HIWORD(lParam) - BASE_MARGIN_TOP; + + buttons = (flags & 1) + + (((flags >> 1) & 1) << 2) + + (((flags >> 4) & 1) << 1); +#if 0 + printf("Mouse at %d, %d fl: %08x, but: %d\n", x, y, flags, buttons); +#endif + motion = win_update_mouse(x, y, buttons, 7); + + if(motion && g_warp_pointer) { + /* move mouse to center of screen */ + pt.x = BASE_MARGIN_LEFT + A2_WINDOW_WIDTH/2; + pt.y = BASE_MARGIN_TOP + A2_WINDOW_HEIGHT/2; + ClientToScreen(g_hwnd_main, &pt); + SetCursorPos(pt.x, pt.y); + } +} + +void +win_event_command(HWND hwnd, int id, HWND g_wnd_ctl, UINT code_notify) +{ + switch (id) { + case ID_HELP_ABOUT: + DialogBoxParam(GetModuleHandle(NULL), + (LPCTSTR)IDD_ABOUT_DIALOG, + hwnd, + (DLGPROC)win_dialog_about_dialog,0); + break; + case ID_HELP_KEY: + DialogBoxParam(GetModuleHandle(NULL), + (LPCTSTR)IDD_KEGS32_KEY, + hwnd, + (DLGPROC)win_dialog_about_dialog,0); + break; + case ID_FILE_EXIT: + PostQuitMessage(0); + break; + + case ID_FILE_SENDRESET: + // Simulate key pressing to send reset + adb_physical_key_update(0x36, 0); + adb_physical_key_update(0x7f, 0); + adb_physical_key_update(0x7f, 1); + adb_physical_key_update(0x36, 1); + break; + case ID_FILE_SENDREBOOT: + // Simulate key pressing to send reset + adb_physical_key_update(0x36, 0); + adb_physical_key_update(0x37, 0); + adb_physical_key_update(0x7f, 0); + adb_physical_key_update(0x7f, 1); + adb_physical_key_update(0x36, 1); + adb_physical_key_update(0x37, 1); + adb_physical_key_update(0x37, 0); + break; + case ID_FILE_FLUSHPRINTER: + printer_feed(); + break; + case ID_FILE_DEBUGSTAT: + g_win_status_debug = ! g_win_status_debug; + GetWindowRect(g_hwnd_main,&g_main_window_saved_rect); + init_window(g_hwnd_main,FALSE); + if (g_win_status_debug) { + CheckMenuItem(GetMenu(g_hwnd_main), + ID_FILE_DEBUGSTAT,MF_CHECKED); + } else { + CheckMenuItem(GetMenu(g_hwnd_main), + ID_FILE_DEBUGSTAT,MF_UNCHECKED); + } + break; + case ID_FILE_JOYSTICK: + if (g_joystick_type == 4) { + g_joystick_type=2; + + } else { + g_joystick_type=4; + } + if (g_joystick_type==4) { + CheckMenuItem(GetMenu(g_hwnd_main),ID_FILE_JOYSTICK, + MF_UNCHECKED); + } else { + CheckMenuItem(GetMenu(g_hwnd_main),ID_FILE_JOYSTICK, + MF_CHECKED); + } + g_config_kegs_update_needed=1; + break; + case ID_FILE_DISK: + DialogBoxParam(GetModuleHandle(NULL), + (LPCTSTR)IDD_DLG_DISKCONF, + g_hwnd_main, + (DLGPROC)win_dialog_disk,0); + break; + case ID_SPEED_1MHZ: + g_limit_speed = 1; + g_config_kegs_update_needed=1; + break; + case ID_SPEED_2MHZ: + g_limit_speed = 2; + g_config_kegs_update_needed=1; + break; + case ID_SPEED_8MHZ: + g_limit_speed = 3; + g_config_kegs_update_needed=1; + break; + case ID_SPEED_FMHZ: + g_limit_speed = 0; + g_config_kegs_update_needed=1; + break; + default: + break; + } +} + +void +win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags) +{ + word32 vk; + int a2code; + int is_up; + int capslock_down; + int i; + + if((flags & 0x4000) && down) { + /* auto-repeating, just ignore it */ + return; + } + + vk = raw_vk + (flags & 0x100); + +#if 0 + printf("Key event, vk=%04x, down:%d, repeat: %d, flags: %08x\n", + vk, down, repeat, flags); +#endif + + /* remap a few keys here.. sigh */ + if((vk & 0xff) == VK_APPS) { + /* remap to command */ + vk = VK_MENU; + } + + if((vk & 0xff) == VK_CAPITAL) { + // Windows gives us up-and-down events of the actual key + // Use GetKeyState to get the true toggle state, and pass + // that on to the adb interface + capslock_down = GetKeyState(VK_CAPITAL) & 0x01; + if(capslock_down != g_win_capslock_down) { + g_win_capslock_down = capslock_down; + adb_physical_key_update(0x39, !capslock_down); + } + + return; // Do no more processing! + } + + /* search a2key_to_wsym to find wsym in col 1 or 2 */ + i = 0; + is_up = !down; + for(i = g_num_a2_keycodes-1; i >= 0; i--) { + a2code = g_a2_key_to_wsym[i][0]; + if((vk == g_a2_key_to_wsym[i][1]) || + (vk == g_a2_key_to_wsym[i][2])) { + vid_printf("Found vk:%04x = %02x\n", vk, a2code); + adb_physical_key_update(a2code, is_up); + return; + } + } + printf("VK: %04x unknown\n", vk); +} + +void +win_event_quit(HWND hwnd) +{ + g_quit_sim_now = 1; + my_exit(0); +} + +void +win_event_redraw() +{ + g_full_refresh_needed = -1; + g_a2_screen_buffer_changed = -1; + g_status_refresh_needed = 1; + g_border_sides_refresh_needed = 1; + g_border_special_refresh_needed = 1; +} + +LRESULT CALLBACK +win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) +{ + switch(umsg) { + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + win_event_mouse(wParam, lParam); + return 0; + case WM_PAINT: + win_event_redraw(); + break; + } + switch(umsg) { + HANDLE_MSG(hwnd, WM_KEYUP, win_event_key); + HANDLE_MSG(hwnd, WM_KEYDOWN, win_event_key); + HANDLE_MSG(hwnd, WM_SYSKEYUP, win_event_key); + HANDLE_MSG(hwnd, WM_SYSKEYDOWN, win_event_key); + HANDLE_MSG(hwnd, WM_DESTROY, win_event_quit); + HANDLE_MSG(hwnd, WM_COMMAND, win_event_command); + } + +#if 0 + switch(umsg) { + case WM_NCACTIVATE: + case WM_NCHITTEST: + case WM_NCMOUSEMOVE: + case WM_SETCURSOR: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_CONTEXTMENU: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_PAINT: + + break; + default: + printf("Got umsg2: %d\n", umsg); + } +#endif + + return DefWindowProc(hwnd, umsg, wParam, lParam); +} + + +int +_tmain(int argc, char **argv) +{ + WNDCLASS wndclass; + RECT rect; + int height; + int iStatusWidths[] = {60, 100,200,300, -1}; + + InitCommonControls(); + + wndclass.style = 0; + wndclass.lpfnWndProc = (WNDPROC)win_event_handler; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = GetModuleHandle(NULL); + wndclass.hIcon = LoadIcon((HINSTANCE) GetModuleHandle(NULL), + MAKEINTRESOURCE(IDC_KEGS32)); + wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wndclass.hbrBackground = GetStockObject(BLACK_BRUSH); + wndclass.lpszMenuName = MAKEINTRESOURCE(IDC_KEGS32); + wndclass.lpszClassName = _T("Kegs32"); + + // Register the window + if(!RegisterClass(&wndclass)) { + printf("Registering window failed\n"); + exit(1); + } + + height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES * 16) + 32; + g_main_height = height; + + g_hwnd_main = CreateWindow(_T("KEGS32"), + _T("KEGS32 - Apple //gs Emulator"), + WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, + X_A2_WINDOW_WIDTH, height, + NULL, NULL, GetModuleHandle(NULL), NULL); + + if (!g_hwnd_main) { + printf("Window create failed\n"); + exit(1); + } + + // Create Toolbar + g_win_toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, + WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | TBSTYLE_TOOLTIPS, + 0, 0, 0, 0, + g_hwnd_main,(HMENU)IDC_KEGS32, GetModuleHandle(NULL), NULL); + SendMessage(g_win_toolbar,TB_BUTTONSTRUCTSIZE,(WPARAM)sizeof(TBBUTTON),0); + { + TBADDBITMAP tbab; + TBBUTTON tbb[6]; + int i,j; + int idCmd[]={ID_FILE_DISK,-1, + ID_SPEED_1MHZ,ID_SPEED_2MHZ,ID_SPEED_8MHZ,ID_SPEED_FMHZ}; + + ZeroMemory(tbb, sizeof(tbb)); + + for (i=0,j=0;i 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + printf("GetMessage returned <= 0\n"); + my_exit(2); + } + } + + return; +} + + +void +x_update_color(int col_num, int red, int green, int blue, word32 rgb) +{ +} + +void +x_update_physical_colormap() +{ +} + +void +show_xcolor_array() +{ + int i; + + for(i = 0; i < 256; i++) { + printf("%02x: %08x\n", i, g_palette_8to1624[i]); + } +} + + +void +xdriver_end() +{ + printf("xdriver_end\n"); +} + + +void +x_get_kimage(Kimage *kimage_ptr) +{ + byte *ptr; + int width; + int height; + int depth, mdepth; + int size; + + width = kimage_ptr->width_req; + height = kimage_ptr->height; + depth = kimage_ptr->depth; + mdepth = kimage_ptr->mdepth; + + size = 0; + if(depth == g_screen_depth) { + /* Use g_bmapinfo_ptr, adjusting width, height */ + g_bmaphdr_ptr->biWidth = width; + g_bmaphdr_ptr->biHeight = -height; + kimage_ptr->dev_handle = CreateDIBSection(g_main_dc, + g_bmapinfo_ptr, DIB_RGB_COLORS, + (VOID **)&(kimage_ptr->data_ptr), NULL, 0); + } else { + /* allocate buffers for video.c to draw into */ + + size = (width*height*mdepth) >> 3; + ptr = (byte *)malloc(size); + + if(ptr == 0) { + printf("malloc for data failed, mdepth: %d\n", mdepth); + exit(2); + } + + kimage_ptr->data_ptr = ptr; + + kimage_ptr->dev_handle = (void *)-1; + + } + printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr, + kimage_ptr->dev_handle, kimage_ptr->data_ptr, size); + + return; +} + +void +dev_video_init() +{ + int extra_size; + int lores_col; + int a2code; + int i; + + printf("Preparing graphics system\n"); + + g_num_a2_keycodes = 0; + for(i = 0; i < 0x7f; i++) { + a2code = g_a2_key_to_wsym[i][0]; + if(a2code < 0) { + g_num_a2_keycodes = i; + } + } + + g_screen_depth = 24; + g_screen_mdepth = 32; + + extra_size = sizeof(RGBQUAD); + if(g_screen_depth == 8) { + extra_size = 256 * sizeof(RGBQUAD); + } + g_bmapinfo_ptr = (BITMAPINFO *)GlobalAlloc(GPTR, + sizeof(BITMAPINFOHEADER) + extra_size); + + g_bmaphdr_ptr = (BITMAPINFOHEADER *)g_bmapinfo_ptr; + g_bmaphdr_ptr->biSize = sizeof(BITMAPINFOHEADER); + g_bmaphdr_ptr->biWidth = A2_WINDOW_WIDTH; + g_bmaphdr_ptr->biHeight = -A2_WINDOW_HEIGHT; + g_bmaphdr_ptr->biPlanes = 1; + g_bmaphdr_ptr->biBitCount = g_screen_mdepth; + g_bmaphdr_ptr->biCompression = BI_RGB; + g_bmaphdr_ptr->biClrUsed = 0; + + video_get_kimages(); + + if(g_screen_depth != 8) { + // Allocate g_mainwin_kimage + video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, + g_screen_mdepth); + } + + for(i = 0; i < 256; i++) { + lores_col = g_lores_colors[i & 0xf]; + video_update_color_raw(i, lores_col); + g_a2palette_8to1624[i] = g_palette_8to1624[i]; + } + + g_installed_full_superhires_colormap = 1; + + GetWindowRect(g_hwnd_main,&g_main_window_saved_rect); + init_window(g_hwnd_main,TRUE); + ShowWindow(g_hwnd_main, SW_SHOWDEFAULT); + UpdateWindow(g_hwnd_main); + + printf("Done with dev_video_init\n"); + fflush(stdout); + +} + +void +x_redraw_status_lines() +{ + COLORREF oldtextcolor, oldbkcolor; + char *buf; + int line; + int len; + int height; + int margin; + int center_x=0; + int center_y=0; + int toolbar_height; + RECT wrect; + TCHAR buffer[255]; + + height = 16; + margin = 0; + + toolbar_height = + (g_win_toolbar_height.bottom-g_win_toolbar_height.top); + + if (g_win_fullscreen_state) { + GetWindowRect(g_hwnd_main,&wrect); + center_x=(wrect.right-wrect.left)-X_A2_WINDOW_WIDTH; + center_x=center_x/2; + center_y=(wrect.bottom-wrect.top)-X_A2_WINDOW_HEIGHT; + if (g_win_status_debug) { + center_y-=(MAX_STATUS_LINES*16); + } + center_y=center_y/2; + toolbar_height=0; + } + + if (g_win_status_debug) { + oldtextcolor = SetTextColor(g_main_dc, 0xffffff); + oldbkcolor = SetBkColor(g_main_dc, 0x0); + for(line = 0; line < MAX_STATUS_LINES; line++) { + buf = g_status_ptrs[line]; + if(buf != 0) { + len = strlen(buf); + TextOut(g_main_dc, 2+center_x, + X_A2_WINDOW_HEIGHT + + height*line + margin + + toolbar_height+center_y, + buf, len); + } + } + SetTextColor(g_main_dc, oldtextcolor); + SetBkColor(g_main_dc, oldbkcolor); + } + + if (g_win_status !=NULL) { + SendMessage(g_win_status, SB_SETTEXT,0,(LPARAM)_T("GSport ")); + _stprintf(buffer,_T("Vol:%d"),g_doc_vol); + SendMessage(g_win_status, SB_SETTEXT,1,(LPARAM)buffer); + buf=g_status_ptrs[0]; + if (buf != NULL) { + buf=strstr(g_status_ptrs[0],"sim MHz:"); + len=strchr(buf+9,' ')-buf; + buffer[len]=0; + if (sizeof(TCHAR) <2) { + strncpy((char *)buffer,buf,len); + } else { + mbstowcs((wchar_t *)buffer,buf,len); + } + SendMessageA(g_win_status, SB_SETTEXT,2,(LPARAM) buffer); + } else { + SendMessageA(g_win_status,SB_SETTEXT,2,(LPARAM)_T( + "sim MHz:???")); + } + buf=g_status_ptrs[0]; + if (buf != NULL) { + buf=strstr(g_status_ptrs[0],"Eff MHz:"); + len=strchr(buf+9,',')-buf; + buffer[len]=0; + if (sizeof(TCHAR) <2) { + strncpy((char *)buffer,buf,len); + } else { + mbstowcs((wchar_t *)buffer,buf,len); + } + SendMessageA(g_win_status, SB_SETTEXT,3,(LPARAM) buffer); + } else { + SendMessageA(g_win_status,SB_SETTEXT,3,(LPARAM)_T( + "Eff MHz:???")); + } + buf=g_status_ptrs[5]; + if (buf != NULL) { + buf=strstr(g_status_ptrs[5],"fast"); + len=buf-&(g_status_ptrs[5][0]); + buffer[len]=0; + if (sizeof(TCHAR) <2) { + strncpy((char *)buffer,g_status_ptrs[5],len); + } else { + mbstowcs((wchar_t *)buffer,g_status_ptrs[5],len); + } + SendMessageA(g_win_status, SB_SETTEXT,4,(LPARAM) buffer); + } else { + + } + } +} + + +void +x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, + int width, int height) +{ + + void *bitm_old; + POINT point; + RECT wrect; + int toolbar_height= 0; + int center_x=0; + int center_y=0; + + point.x = 0; + point.y = 0; + ClientToScreen(g_hwnd_main, &point); + bitm_old = SelectObject(g_main_cdc, kimage_ptr->dev_handle); + + + + if (!g_win_fullscreen_state) { + toolbar_height= + (g_win_toolbar_height.bottom-g_win_toolbar_height.top); + } else { + GetWindowRect(g_hwnd_main,&wrect); + center_x=(wrect.right-wrect.left)-X_A2_WINDOW_WIDTH; + center_x=center_x/2; + center_y=(wrect.bottom-wrect.top)-X_A2_WINDOW_HEIGHT; + if (g_win_status_debug) { + center_y-=(MAX_STATUS_LINES*16); + } + center_y=center_y/2; + } + + BitBlt( g_main_dc, + destx+center_x, + desty+toolbar_height+center_y, + width, height, + g_main_cdc, srcx, srcy, SRCCOPY); + + SelectObject(g_main_cdc, bitm_old); + +} + +void +x_push_done() +{ +} + +void +x_auto_repeat_on(int must) +{ +} + +void +x_auto_repeat_off(int must) +{ +} + +void +x_hide_pointer(int do_hide) +{ + if(do_hide) { + ShowCursor(0); + } else { + ShowCursor(1); + } +} + +void +x_full_screen(int do_full) +{ + DEVMODE dmScreenSettings; + int style; + + if (do_full && !g_win_fullscreen_state) { + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = 800; + dmScreenSettings.dmPelsHeight = 600; + dmScreenSettings.dmBitsPerPel = 24; + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH| + DM_PELSHEIGHT; + + if (ChangeDisplaySettings(&dmScreenSettings, 2) + !=DISP_CHANGE_SUCCESSFUL) { + // If 24-bit palette does not work, try 32-bit + dmScreenSettings.dmBitsPerPel = 32; + if (ChangeDisplaySettings(&dmScreenSettings, 2)) { + printf ( + "-- Unable to switch to fullscreen mode\n"); + printf ( + "-- No 24-bit or 32-bit mode for fullscreen\n"); + dmScreenSettings.dmBitsPerPel=-1; + } + } + + if (dmScreenSettings.dmBitsPerPel >0) { + g_win_fullscreen_state=!g_win_fullscreen_state; + GetWindowRect(g_hwnd_main,&g_main_window_saved_rect); + ChangeDisplaySettings(&dmScreenSettings, 4); + style=GetWindowLong(g_hwnd_main,GWL_STYLE); + style &= ~WS_CAPTION; + SetWindowLong(g_hwnd_main,GWL_STYLE,style); + g_main_window_menu_saved=GetMenu(g_hwnd_main); + SetMenu(g_hwnd_main,NULL); + ShowWindow(g_win_status,FALSE); + ShowWindow(g_win_toolbar,FALSE); + SetWindowPos(g_hwnd_main,HWND_TOPMOST,0,0, + GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN), + SWP_SHOWWINDOW); + + } + } else { + if (g_win_fullscreen_state) { + ChangeDisplaySettings(NULL,0); + style=GetWindowLong(g_hwnd_main,GWL_STYLE); + style |= WS_CAPTION; + SetWindowLong(g_hwnd_main,GWL_STYLE,style); + SetMenu(g_hwnd_main,g_main_window_menu_saved); + ShowWindow(g_win_status,TRUE); + ShowWindow(g_win_toolbar,TRUE); + init_window(g_hwnd_main,FALSE); + g_win_fullscreen_state=!g_win_fullscreen_state; + } + } + return; +} diff --git a/src/winresource.h b/src/winresource.h index 64e56e3..7d5d615 100644 --- a/src/winresource.h +++ b/src/winresource.h @@ -3,11 +3,13 @@ // Microsoft Developer Studio generated include file. // Used by win32.rc // +#define CREATEPROCESS_MANIFEST 1 #define IDD_ABOUT_DIALOG 101 #define IDC_KEGS32 102 #define IDR_TOOLBAR 103 #define IDD_DLG_DISKCONF 104 #define IDR_ACCEL 105 +#define IDD_KEGS32_KEY 106 #define ID_TOOLBAR 5000 #define ID_STATUSBAR 5001 #define IDC_EDIT_S5D1 10051 @@ -29,6 +31,20 @@ #define ID_FILE_JOYSTICK 40005 #define ID_FILE_DEBUGSTAT 40006 #define ID_FILE_FULLSCREEN 40012 +#define ID_FILE_SPEED 40013 +#define ID_HELP_KEY 40014 +#define ID_FILE_SENDREBOOT 40007 +#define ID_FILE_FLUSHPRINTER 40017 +#define ID_SPEED_1MHZ 50001 +#define ID_SPEED_2MHZ 50002 +#define ID_SPEED_8MHZ 50003 +#define ID_SPEED_FMHZ 50004 +#define IDD_SPEEDDIALOG 117 +#define IDC_SLOW 1007 +#define IDC_CUSTOM 1008 +#define IDC_EDITCUSTOM 1009 +#define IDC_NORMAL 1010 +#define IDC_FASTEST 1011 // Next default values for new objects // diff --git a/src/wintoolbar.bmp b/src/wintoolbar.bmp new file mode 100644 index 0000000..291ba38 Binary files /dev/null and b/src/wintoolbar.bmp differ