commit f73a49cab3767ad8cad84d19096e163d17b0eaae Author: David Kuder Date: Wed Apr 12 10:43:16 2023 -0400 Initial Import diff --git a/adtpro/adtpro b/adtpro/adtpro new file mode 100644 index 0000000..6c675e4 Binary files /dev/null and b/adtpro/adtpro differ diff --git a/adtpro/adtpro.bin b/adtpro/adtpro.bin new file mode 100644 index 0000000..fafc3a0 Binary files /dev/null and b/adtpro/adtpro.bin differ diff --git a/adtpro/adtproaud b/adtpro/adtproaud new file mode 100644 index 0000000..6c675e4 Binary files /dev/null and b/adtpro/adtproaud differ diff --git a/adtpro/adtproaud.bin b/adtpro/adtproaud.bin new file mode 100644 index 0000000..71a2014 Binary files /dev/null and b/adtpro/adtproaud.bin differ diff --git a/adtpro/adtproeth b/adtpro/adtproeth new file mode 100644 index 0000000..6c675e4 Binary files /dev/null and b/adtpro/adtproeth differ diff --git a/adtpro/adtproeth.bin b/adtpro/adtproeth.bin new file mode 100644 index 0000000..ab40640 Binary files /dev/null and b/adtpro/adtproeth.bin differ diff --git a/adtpro/vedrive b/adtpro/vedrive new file mode 100644 index 0000000..ff5cbe3 Binary files /dev/null and b/adtpro/vedrive differ diff --git a/adtpro/vedrive.low b/adtpro/vedrive.low new file mode 100644 index 0000000..d676ec0 Binary files /dev/null and b/adtpro/vedrive.low differ diff --git a/adtpro/vedrive.setup b/adtpro/vedrive.setup new file mode 100644 index 0000000..13a1c6c Binary files /dev/null and b/adtpro/vedrive.setup differ diff --git a/adtpro/vedrive.system b/adtpro/vedrive.system new file mode 100644 index 0000000..37cd24e Binary files /dev/null and b/adtpro/vedrive.system differ diff --git a/adtpro/vsdrive b/adtpro/vsdrive new file mode 100644 index 0000000..84c6cc1 Binary files /dev/null and b/adtpro/vsdrive differ diff --git a/adtpro/vsdrive.low b/adtpro/vsdrive.low new file mode 100644 index 0000000..3123b77 Binary files /dev/null and b/adtpro/vsdrive.low differ diff --git a/basic/amber.bas b/basic/amber.bas new file mode 100644 index 0000000..55d33d6 --- /dev/null +++ b/basic/amber.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,192 diff --git a/basic/amber.inverse.bas b/basic/amber.inverse.bas new file mode 100644 index 0000000..508c29d --- /dev/null +++ b/basic/amber.inverse.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,208 diff --git a/basic/c64.bas b/basic/c64.bas new file mode 100644 index 0000000..6db4bb9 --- /dev/null +++ b/basic/c64.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,224 diff --git a/basic/color.bas b/basic/color.bas new file mode 100644 index 0000000..d2e767e --- /dev/null +++ b/basic/color.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,0 diff --git a/basic/green.bas b/basic/green.bas new file mode 100644 index 0000000..69bb7e6 --- /dev/null +++ b/basic/green.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,160 diff --git a/basic/green.inverse.bas b/basic/green.inverse.bas new file mode 100644 index 0000000..fc4d1b0 --- /dev/null +++ b/basic/green.inverse.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,176 diff --git a/basic/iigs.bas b/basic/iigs.bas new file mode 100644 index 0000000..2f71417 --- /dev/null +++ b/basic/iigs.bas @@ -0,0 +1,6 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,240 + 50 POKE S + 2,246 + 60 POKE S + 4,6 diff --git a/basic/mono.bas b/basic/mono.bas new file mode 100644 index 0000000..46f95b7 --- /dev/null +++ b/basic/mono.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,128 diff --git a/basic/mono.inverse.bas b/basic/mono.inverse.bas new file mode 100644 index 0000000..61452b6 --- /dev/null +++ b/basic/mono.inverse.bas @@ -0,0 +1,4 @@ + 10 PRINT "CARD IS INSTALLED IN SLOT"; + 20 INPUT S + 30 S = (S * 16) + 49280 + 40 POKE S + 1,144 diff --git a/basic/themes.bas b/basic/themes.bas new file mode 100644 index 0000000..387a6b1 --- /dev/null +++ b/basic/themes.bas @@ -0,0 +1,36 @@ + 10 TEXT : HOME + 20 PRINT "CARD IS INSTALLED IN SLOT"; + 30 INPUT S + 40 IF S > 7 GOTO 80 + 50 IF S < 0 GOTO 80 + 60 GOTO 100 + 80 PRINT "INVALID SLOT" + 90 GOTO 20 +100 S = (S * 16) + 49280 +110 PRINT "COLOR SCHEMES:" +120 PRINT "0: FULL COLOR" +130 PRINT "1: MONOCHROME" +140 PRINT "2: INVERSE" +150 PRINT "3: AMBER" +160 PRINT "4: AMBER INV" +170 PRINT "5: GREEN" +180 PRINT "6: GREEN INV" +190 PRINT "7: COMMODORE" +200 PRINT "8: APPLE IIGS" +210 PRINT "CHOICE"; +220 INPUT T +230 IF T = 0 GOTO 300 +240 IF T = 8 GOTO 400 +250 IF T > 8 GOTO 280 +260 IF T < 0 GOTO 280 +270 GOTO 420 +280 PRINT "INVALID ENTRY" +290 GOTO 210 +300 POKE S + 2,240 +310 POKE S + 3,0 +320 POKE S + 1,0 +330 END +400 POKE S + 2,246 +410 POKE S + 3,6 +420 POKE S + 1,128 + ((T-1)*16) +430 END diff --git a/fonts/00.us.enh.pf b/fonts/00.us.enh.pf new file mode 100644 index 0000000..259bbf2 Binary files /dev/null and b/fonts/00.us.enh.pf differ diff --git a/fonts/01.us.une.pf b/fonts/01.us.une.pf new file mode 100644 index 0000000..c23e9b4 Binary files /dev/null and b/fonts/01.us.une.pf differ diff --git a/fonts/02.clintonv1.pf b/fonts/02.clintonv1.pf new file mode 100644 index 0000000..9cdc4a0 Binary files /dev/null and b/fonts/02.clintonv1.pf differ diff --git a/fonts/03.reactive.pf b/fonts/03.reactive.pf new file mode 100644 index 0000000..ef9ad14 Binary files /dev/null and b/fonts/03.reactive.pf differ diff --git a/fonts/04.danpaymar.pf b/fonts/04.danpaymar.pf new file mode 100644 index 0000000..ae208b6 Binary files /dev/null and b/fonts/04.danpaymar.pf differ diff --git a/fonts/05.blippo.pf b/fonts/05.blippo.pf new file mode 100644 index 0000000..b08aa64 Binary files /dev/null and b/fonts/05.blippo.pf differ diff --git a/fonts/06.byte.pf b/fonts/06.byte.pf new file mode 100644 index 0000000..6dd0434 Binary files /dev/null and b/fonts/06.byte.pf differ diff --git a/fonts/07.colossal.pf b/fonts/07.colossal.pf new file mode 100644 index 0000000..b5976bf Binary files /dev/null and b/fonts/07.colossal.pf differ diff --git a/fonts/08.count.pf b/fonts/08.count.pf new file mode 100644 index 0000000..970a4d0 Binary files /dev/null and b/fonts/08.count.pf differ diff --git a/fonts/09.flow.pf b/fonts/09.flow.pf new file mode 100644 index 0000000..cc225ee Binary files /dev/null and b/fonts/09.flow.pf differ diff --git a/fonts/0a.gothic.pf b/fonts/0a.gothic.pf new file mode 100644 index 0000000..c4b3d85 Binary files /dev/null and b/fonts/0a.gothic.pf differ diff --git a/fonts/0b.outline.pf b/fonts/0b.outline.pf new file mode 100644 index 0000000..a7a1a84 Binary files /dev/null and b/fonts/0b.outline.pf differ diff --git a/fonts/0c.pigfont.pf b/fonts/0c.pigfont.pf new file mode 100644 index 0000000..9d2d719 Binary files /dev/null and b/fonts/0c.pigfont.pf differ diff --git a/fonts/0d.pinocchio.pf b/fonts/0d.pinocchio.pf new file mode 100644 index 0000000..ce4bc7a Binary files /dev/null and b/fonts/0d.pinocchio.pf differ diff --git a/fonts/0e.slant.pf b/fonts/0e.slant.pf new file mode 100644 index 0000000..59ed45f Binary files /dev/null and b/fonts/0e.slant.pf differ diff --git a/fonts/0f.stop.pf b/fonts/0f.stop.pf new file mode 100644 index 0000000..fc6d4c7 Binary files /dev/null and b/fonts/0f.stop.pf differ diff --git a/fonts/10.euro.une.pf b/fonts/10.euro.une.pf new file mode 100644 index 0000000..f4bbd9b Binary files /dev/null and b/fonts/10.euro.une.pf differ diff --git a/fonts/11.euro.enh.pf b/fonts/11.euro.enh.pf new file mode 100644 index 0000000..840318a Binary files /dev/null and b/fonts/11.euro.enh.pf differ diff --git a/fonts/12.clintonv2.pf b/fonts/12.clintonv2.pf new file mode 100644 index 0000000..ab59282 Binary files /dev/null and b/fonts/12.clintonv2.pf differ diff --git a/fonts/13.germanenh.pf b/fonts/13.germanenh.pf new file mode 100644 index 0000000..ba6a175 Binary files /dev/null and b/fonts/13.germanenh.pf differ diff --git a/fonts/14.germanune.pf b/fonts/14.germanune.pf new file mode 100644 index 0000000..893d175 Binary files /dev/null and b/fonts/14.germanune.pf differ diff --git a/fonts/15.frenchenh.pf b/fonts/15.frenchenh.pf new file mode 100644 index 0000000..7d862b3 Binary files /dev/null and b/fonts/15.frenchenh.pf differ diff --git a/fonts/16.frenchune.pf b/fonts/16.frenchune.pf new file mode 100644 index 0000000..6276561 Binary files /dev/null and b/fonts/16.frenchune.pf differ diff --git a/fonts/17.hebrewenh.pf b/fonts/17.hebrewenh.pf new file mode 100644 index 0000000..1143897 Binary files /dev/null and b/fonts/17.hebrewenh.pf differ diff --git a/fonts/18.hebrewune.pf b/fonts/18.hebrewune.pf new file mode 100644 index 0000000..9ff7b39 Binary files /dev/null and b/fonts/18.hebrewune.pf differ diff --git a/fonts/19.plus.enh.pf b/fonts/19.plus.enh.pf new file mode 100644 index 0000000..f20a136 Binary files /dev/null and b/fonts/19.plus.enh.pf differ diff --git a/fonts/1a.plus.une.pf b/fonts/1a.plus.une.pf new file mode 100644 index 0000000..d8a483e Binary files /dev/null and b/fonts/1a.plus.une.pf differ diff --git a/fonts/1b.katakana.pf b/fonts/1b.katakana.pf new file mode 100644 index 0000000..d9b15ba Binary files /dev/null and b/fonts/1b.katakana.pf differ diff --git a/fonts/1c.cyrillic.pf b/fonts/1c.cyrillic.pf new file mode 100644 index 0000000..6fe7bee Binary files /dev/null and b/fonts/1c.cyrillic.pf differ diff --git a/fonts/1d.greek.pf b/fonts/1d.greek.pf new file mode 100644 index 0000000..6c851b7 Binary files /dev/null and b/fonts/1d.greek.pf differ diff --git a/fonts/1e.esperanto.pf b/fonts/1e.esperanto.pf new file mode 100644 index 0000000..93ec0d8 Binary files /dev/null and b/fonts/1e.esperanto.pf differ diff --git a/fonts/1f.videx.pf b/fonts/1f.videx.pf new file mode 100644 index 0000000..6276df1 Binary files /dev/null and b/fonts/1f.videx.pf differ diff --git a/fonts/20.plus.une.pf b/fonts/20.plus.une.pf new file mode 100644 index 0000000..d8a483e Binary files /dev/null and b/fonts/20.plus.une.pf differ diff --git a/fonts/21.us.enh.pf b/fonts/21.us.enh.pf new file mode 100644 index 0000000..259bbf2 Binary files /dev/null and b/fonts/21.us.enh.pf differ diff --git a/fonts/22.us.enh.pf b/fonts/22.us.enh.pf new file mode 100644 index 0000000..259bbf2 Binary files /dev/null and b/fonts/22.us.enh.pf differ diff --git a/fonts/23.cyrillic.pf b/fonts/23.cyrillic.pf new file mode 100644 index 0000000..6fe7bee Binary files /dev/null and b/fonts/23.cyrillic.pf differ diff --git a/fonts/24.pcbold.pf b/fonts/24.pcbold.pf new file mode 100644 index 0000000..b215aa0 Binary files /dev/null and b/fonts/24.pcbold.pf differ diff --git a/fonts/blank.pf b/fonts/blank.pf new file mode 100644 index 0000000..e9784eb Binary files /dev/null and b/fonts/blank.pf differ diff --git a/prodos/basic.system b/prodos/basic.system new file mode 100644 index 0000000..c68b372 Binary files /dev/null and b/prodos/basic.system differ diff --git a/prodos/bitsy.boot b/prodos/bitsy.boot new file mode 100644 index 0000000..706c933 Binary files /dev/null and b/prodos/bitsy.boot differ diff --git a/prodos/pd35.po b/prodos/pd35.po new file mode 100644 index 0000000..dbae8dd Binary files /dev/null and b/prodos/pd35.po differ diff --git a/prodos/pd525.po b/prodos/pd525.po new file mode 100644 index 0000000..d853fc6 Binary files /dev/null and b/prodos/pd525.po differ diff --git a/prodos/prodos.bin b/prodos/prodos.bin new file mode 100644 index 0000000..a701ba0 Binary files /dev/null and b/prodos/prodos.bin differ diff --git a/prodos/quit.system b/prodos/quit.system new file mode 100644 index 0000000..201230d Binary files /dev/null and b/prodos/quit.system differ diff --git a/src/loader.c b/src/loader.c new file mode 100644 index 0000000..7b7c1b6 --- /dev/null +++ b/src/loader.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include "v2types.h" +#include "menu.h" + +void main (void) { + char filename[32]; + + strcpy(filename, NEXTNAME); + + if(get_ostype() >= 0x30) { + strcat(filename, ".ENH"); + } else { + strcat(filename, ".BASE"); + } + + exec(filename, ""); + + backdrop("Loader"); + window(" Error ", longmin(longmax(26, strlen(filename)+4), 38), 6, 1); + gotoy(11); gotox(13); + cputs("Unable to load file"); + gotoy(12); gotox(longmin(3, (20-strlen(filename)))); + printlimited(filename, 34); +} diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 0000000..348c417 --- /dev/null +++ b/src/menu.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include +#include "v2types.h" +#include "v2loader.h" + +#define PROGNAME "Startup Menu" +volatile uint16_t cardslot = 3; + +#include "v2analog.h" +#include "menu.h" + +int confirm_exit(void) { + backdrop(PROGNAME); + if(confirm(" Are you sure? ", "Quit?")) { + clrscr(); + return -1; + } + return 2; +} + +typedef enum { + MENU_TERMINATOR = 0, + MENU_MISSING, + MENU_SEPARATOR, + MENU_LAUNCH_CHECKARGS, + MENU_LAUNCH_NOCHECKARGS, + MENU_EXIT +} menu_type_t; + +typedef struct menu_s { + menu_type_t type; + char *entry; + char *filename_enhanced; + char *filename_base; + char *arguments; +} menu_t; + +menu_t launcher[] = { + { MENU_LAUNCH_NOCHECKARGS, " Config Utility ", "CONFIG.ENH", "CONFIG.BASE", "" }, + { MENU_LAUNCH_NOCHECKARGS, " Font Manager ", "FONTMGR.ENH", "FONTMGR.BASE", "" }, + { MENU_LAUNCH_CHECKARGS, " Theme Chooser ", "BASIC.SYSTEM", "BASIC.SYSTEM", "THEMES.BAS" }, + { MENU_LAUNCH_NOCHECKARGS, " Format Utility ", "FORMAT.ENH", "FORMAT.BASE", "" }, + { MENU_LAUNCH_NOCHECKARGS, " Config Remover ", "RMCFG.ENH", "RMCFG.BASE", "" }, + { MENU_LAUNCH_NOCHECKARGS, " One-time VGA Tool ", "OTVGA.ENH", "OTVGA.BASE", "" }, + { MENU_SEPARATOR, NULL, NULL, NULL, NULL }, + { MENU_LAUNCH_NOCHECKARGS, " Applesoft Basic ", "BASIC.SYSTEM", "BASIC.SYSTEM", "" }, + { MENU_SEPARATOR, NULL, NULL, NULL, NULL }, + { MENU_EXIT, " Exit ", NULL, NULL, NULL }, + { MENU_TERMINATOR, NULL, NULL, NULL, NULL }, +}; + +int main_menu_action(int action) { + FILE *f; + switch(launcher[action].type) { + case MENU_LAUNCH_CHECKARGS: + // Type 1: Launch with Filename Argument + if(strlen(launcher[action].arguments)) { + f = fopen(launcher[action].arguments, "rb"); + if(f != NULL) { + fclose(f); + } else { + return 2; + } + } + + // Type 2: Launch without checking arguments + case MENU_LAUNCH_NOCHECKARGS: +#if defined(__APPLE2ENH__) + f = fopen(launcher[action].filename_enhanced, "rb"); + if(f != NULL) { + fclose(f); + exec(launcher[action].filename_enhanced, launcher[action].arguments); + } +#endif + f = fopen(launcher[action].filename_base, "rb"); + if(f != NULL) { + fclose(f); + exec(launcher[action].filename_base, launcher[action].arguments); + } + + default: + return 2; + + case MENU_EXIT: + return confirm_exit(); + } +} + +void main (void) { + int i, y; + int paint_menu = 2; + int selected_item = 0; + int launcher_rows = 0; + int last_item = 0; + int window_top; + int separator_allowed; + int go = 0; + FILE *f; + + backdrop(PROGNAME); + gotoy(12); gotox(14); + cputs("Loading Menu"); + + // Check for the presence of every menu item and it's arguments + separator_allowed = 0; + for(i = 0; launcher[i].type != MENU_TERMINATOR; i++) { + switch(launcher[i].type) { + case MENU_LAUNCH_CHECKARGS: + if(strlen(launcher[i].arguments)) { + f = fopen(launcher[i].arguments, "rb"); + if(f != NULL) { + fclose(f); + } else { + launcher[i].type = MENU_MISSING; + break; + } + } + case MENU_LAUNCH_NOCHECKARGS: +#if defined(__APPLE2ENH__) + f = fopen(launcher[i].filename_enhanced, "rb"); + if(f != NULL) { + fclose(f); + } else { +#endif + f = fopen(launcher[i].filename_base, "rb"); + if(f != NULL) { + fclose(f); + } else { + launcher[i].type = MENU_MISSING; + break; + } +#if defined(__APPLE2ENH__) + } + case MENU_EXIT: + launcher_rows+=2; + last_item = i; + separator_allowed = 1; + break; + case MENU_SEPARATOR: + if(separator_allowed) { + launcher_rows++; + separator_allowed = 0; + } + break; +#endif + } + } + + // Make sure a valid item is selected. + while((launcher[selected_item].type < MENU_LAUNCH_CHECKARGS) && (selected_item < last_item)) { + selected_item++; + } + + window_top = 13 - ((launcher_rows+1)/2); + + while(paint_menu >= 0) { + if(paint_menu == 2) { + backdrop(PROGNAME); + + window(" Applications ", 24, launcher_rows+1, 0); + + y = 0; + separator_allowed = 0; + for(i = 0; launcher[i].type != MENU_TERMINATOR; i++) { + switch(launcher[i].type) { + case MENU_MISSING: + break; + case MENU_LAUNCH_CHECKARGS: + case MENU_LAUNCH_NOCHECKARGS: + case MENU_EXIT: + y+=2; + separator_allowed = 1; + break; + case MENU_SEPARATOR: + if(separator_allowed) { + gotoy(window_top+y); gotox(8); + repeatchar(CHAR_BORDER_BOTTOM, 24); + y++; + separator_allowed = 0; + } + break; + } + } + } + if(paint_menu) { + y = 0; + separator_allowed = 0; + for(i = 0; launcher[i].type != MENU_TERMINATOR; i++) { + switch(launcher[i].type) { + case MENU_MISSING: + break; + case MENU_LAUNCH_CHECKARGS: + case MENU_LAUNCH_NOCHECKARGS: + case MENU_EXIT: + gotoy(window_top+y); gotox(9); + revers(selected_item == i); + cputs(launcher[i].entry); + revers(0); + y+=2; + separator_allowed = 1; + break; + case MENU_SEPARATOR: + if(separator_allowed) { + y++; + separator_allowed = 0; + } + break; + } + } + paint_menu = 0; + } + + switch(cgetc()) { + case 0x08: + case 0x0B: + if(selected_item > 0) { + selected_item--; + // Skip separators and inactive items + while((launcher[selected_item].type < MENU_LAUNCH_CHECKARGS) && (selected_item > 0)) { + selected_item--; + } + while((launcher[selected_item].type < MENU_LAUNCH_CHECKARGS) && (selected_item < last_item)) { + selected_item++; + } + paint_menu = 1; + } + break; + case 0x15: + case 0x0A: + if(selected_item < last_item) { + selected_item++; + // Skip separators and inactive items + while((launcher[selected_item].type < MENU_LAUNCH_CHECKARGS) && (selected_item < last_item)) { + selected_item++; + } + while((launcher[selected_item].type < MENU_LAUNCH_CHECKARGS) && (selected_item > 0)) { + selected_item--; + } + paint_menu = 1; + } + break; + + case 0x1B: + paint_menu = confirm_exit(); + break; + case 0x0D: + go = 1; + break; + } + + if(go) { + paint_menu = main_menu_action(selected_item); + go = 0; + } + } +} diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..09a9caa --- /dev/null +++ b/src/menu.h @@ -0,0 +1,369 @@ +#ifndef __MENU_H +#define __MENU_H + +#if defined(__APPLE2ENH__) + #define CHAR_CURSOR 0x7F + #define CHAR_BAR_MIDDLE 0xD3 + #define CHAR_BORDER_BOTTOM 0xCC + #define CHAR_TITLEBAR_ENCLOSED 0xDC + #define CHAR_BORDER_TOP '_' + #define CHAR_BORDER_RIGHT 0xDA + #define CHAR_BORDER_LEFT 0xDF + #define CHAR_BORDER_TOP_LEFT 0xDA + #define CHAR_BORDER_TOP_RIGHT 0xDF + #define CHAR_TITLEBAR_FOLDER 0xD4 + #define CHAR_BORDER_BOTTOM_LEFT ' ' + #define CHAR_BORDER_BOTTOM_RIGHT ' ' +#else + #define CHAR_CURSOR (' '|0x80) + #define CHAR_BAR_MIDDLE '-' + #define CHAR_BORDER_BOTTOM '-' + #define CHAR_TITLEBAR_ENCLOSED '-' + #define CHAR_BORDER_TOP '_' + #define CHAR_BORDER_RIGHT '!' + #define CHAR_BORDER_LEFT '!' + #define CHAR_BORDER_TOP_LEFT '.' + #define CHAR_BORDER_TOP_RIGHT '.' + #define CHAR_TITLEBAR_FOLDER '_' + #define CHAR_BORDER_BOTTOM_LEFT '\'' + #define CHAR_BORDER_BOTTOM_RIGHT '\'' +#endif + + +void repeatchar(char ch, int num) { + while(num--) { + cputc(ch); + } +} + +void hline() { + repeatchar(CHAR_BAR_MIDDLE, 40); +} + +void backdrop(char *str) { + int w, i; + + w = strlen(str); + if(w > 20) { + w = 20; + } + + clrscr(); + gotoy(0); gotox(1); + cputs("V2 Analog"); + + gotoy(0); gotox(39 - w); + + if((w >= 19) && str[19]) +#if defined(__APPLE2ENH__) + w = 19; +#else + w = 17; +#endif + + for(i = 0; i < w; i++) { + cputc(str[i]); + } + +#if defined(__APPLE2ENH__) + if((i == 19) && str[i]) + cputc(0xC9); // Elipsis +#else + if((i == 17) && str[i]) + cputs("..."); +#endif + + gotoy(1); gotox(0); + hline(); + + gotoy(22); gotox(0); + hline(); + + gotoy(23); gotox(4); + cputs("https://www.v2retrocomputing.com"); +} + +void printlimited(char *str, int maxwidth) { + int i; + + if(strlen(str) <= maxwidth) { + cputs(str); + } else { + for(i = 0; i < (maxwidth-3); i++) { + cputc(str[i]); + } + cputs("..."); + } +} + +void window(char *title, int width, int height, int type) { + int w, x, y, a, b, c; + + if(width > 38) { + width = 40; + } + + if(height > 22) { + height = 22; + } + + y = 12 - ((height+2)/2); + + if(strlen(title) > (width-2)) { + w = width-2; + } else { + w = strlen(title); + } + + if(width < 40) { + x = 20 - (width/2); + } else { + x = 0; + } + +#if defined(__APPLE2ENH__) + a = 0; +#else + a = (width < 38); +#endif + b = (width < 40); + x -= a+b; + +#if defined(__APPLE2ENH__) + if(y > 2) { + gotoy(y-1); gotox(x); + if(a) cputc(' '); + if(b) cputc(' '); + repeatchar(CHAR_BORDER_TOP, type ? width : w); + if(!type && (w < width)) repeatchar(' ', width - w); + if(b) cputc(' '); + if(a) cputc(' '); + } +#else + if(y > 2) { + gotoy(y-1); gotox(x); + repeatchar(' ', width+a+a+b+b); + } +#endif + if(y+height < 22) { + gotoy(y+height); gotox(x); + repeatchar(' ', width+a+a+b+b); + } + + gotoy(y); gotox(x); + if(a) cputc(' '); + if(b) cputc(CHAR_BORDER_TOP_LEFT); + if(type) { + c = (width - w) / 2; + repeatchar(CHAR_TITLEBAR_ENCLOSED, c); + } + revers(1); + printlimited(title, w); + revers(0); +#if defined(__APPLE2ENH__) + if(!type) cputc(CHAR_TITLEBAR_FOLDER); +#endif + if(type) { + repeatchar(CHAR_TITLEBAR_ENCLOSED, width - (w+c)); + if(b) cputc(CHAR_BORDER_TOP_RIGHT); + } else { +#if defined(__APPLE2ENH__) + repeatchar(CHAR_BORDER_TOP, width-(w+1)); + if(b) cputc(' '); +#else + repeatchar(CHAR_BORDER_TOP, width-w); + if(b) cputc(CHAR_BORDER_TOP_RIGHT); +#endif + } + if(a) cputc(' '); + + y++; + +#if defined(__APPLE2ENH__) + gotoy(y); gotox(x); + if(a) cputc(' '); + if(b) cputc(CHAR_BORDER_RIGHT); + repeatchar(CHAR_BORDER_BOTTOM, width); + if(b) cputc(CHAR_BORDER_LEFT); + if(a) cputc(' '); + + for(c = 1; c < height-1; c++) { +#else + for(c = 0; c < height; c++) { +#endif + gotoy(y+c); gotox(x); + if(a) cputc(' '); + if(b) cputc(CHAR_BORDER_RIGHT); + repeatchar(' ', width); + if(b) cputc(CHAR_BORDER_LEFT); + if(a) cputc(' '); + } +#if defined(__APPLE2ENH__) + gotoy(y+c); gotox(x); + if(a) cputc(' '); + if(b) cputc(CHAR_BORDER_RIGHT); + repeatchar(CHAR_BORDER_TOP, width); + if(b) cputc(CHAR_BORDER_LEFT); + if(a) cputc(' '); + c++; +#endif + + if((y+c) < 22) { + gotoy(y+c); gotox(x); + if(a) cputc(' '); + if(b) cputc(CHAR_BORDER_BOTTOM_LEFT); + repeatchar(CHAR_BORDER_BOTTOM, width); + if(b) cputc(CHAR_BORDER_BOTTOM_RIGHT); + if(a) cputc(' '); + } +} + +void message(char *title, char *str) { + int w, x, c; + + if(strlen(str) > 34) { + c = w = 34; + } else { + c = w = strlen(str); + } + + if(strlen(title) > 34) { + c = 34; + } else if(strlen(title) > w) { + c = strlen(title); + } + + window(title, c+4, 7, 1); + + x = 20 - (w / 2); + gotoy(11); gotox(x); + printlimited(str, w); +// for(c = 0; (c < w) && str[c]; c++) { +// cputc(str[c]); +// } + + x = 20 - 2; + gotoy(13); gotox(x); + revers(1); + cputs(" OK "); + revers(0); + + for(;;) { + switch(cgetc()) { + case 0x0A: + case 0x0D: + case 0x1B: + case 'O': + case 'o': + return; + } + } +} + +int confirm(char *title, char *str) { + int w, x, c, sel = 1; + + if(strlen(str) > 34) { + c = w = 34; + } else { + c = w = strlen(str); + } + + if(strlen(title) > 34) { + c = 34; + } else if(strlen(title) > w) { + c = strlen(title); + } + + window(title, c+4, 7, 1); + + x = 20 - (w / 2); + gotoy(11); gotox(x); + printlimited(str, w); + + for(;;) { + x = 20 - 5; + gotoy(13); gotox(x); + if(sel) { + revers(1); + cputs(" Yes "); + revers(0); + cputs(" [No]"); + } else { + cputs("[Yes] "); + revers(1); + cputs(" No "); + revers(0); + } + + switch(cgetc()) { + case 0x08: + case 0x0A: + case 0x0B: + case 0x15: + sel = !sel; + break; + case 0x0D: + return sel; + case 'Y': + case 'y': + return 1; + case 0x1B: + case 'N': + case 'n': + return 0; + } + } +} + +#ifdef __V2ANALOG_H +int prompt_slot(char *progname) { + int c; + int done=0; + + backdrop(progname); + + window(" Slot Number? ", 38, 7, 1); + gotoy(11); gotox(2); + cputs("Which slot is the card installed in?"); + + while(!done) { +#if defined(__APPLE2ENH__) + gotoy(12); gotox(19); + repeatchar(CHAR_BORDER_TOP, 3); +#endif + gotoy(13); gotox(19); + revers(1); + printf(" %i ", cardslot); + revers(0); + + c = cgetc(); + if((c >= '1') && (c <= '7')) { + cardslot = c - '0'; + return 1; + } else + switch(c) { + case 0x08: + case 0x0A: + case 0x2D: + if(cardslot > 0) + cardslot--; + break; + case 0x0B: + case 0x15: + case 0x2B: + if(cardslot < 7) + cardslot++; + break; + case 0x0D: + done = 1; + return 1; + case 0x1B: + return 0; + } + } + +} +#endif + +#endif /* __MENU_H */ diff --git a/src/v2analog.h b/src/v2analog.h new file mode 100644 index 0000000..79b436f --- /dev/null +++ b/src/v2analog.h @@ -0,0 +1,230 @@ +#ifndef __V2ANALOG_H +#define __V2ANALOG_H + +#define CARD_REGISTER(n) (*(volatile unsigned char *)(0xC080 | (n) | (cardslot << 4))) + +#define VGA_MONOMODE CARD_REGISTER(0x1) +#define VGA_TBCOLOR CARD_REGISTER(0x2) +#define VGA_BORDER CARD_REGISTER(0x3) + +#define CF_PTRL *((volatile unsigned char *)(0xC0ED | (cardslot << 8))) +#define CF_PTRH *((volatile unsigned char *)(0xC0EE | (cardslot << 8))) +#define CF_DATA *((volatile unsigned char *)(0xC0EF | (cardslot << 8))) + +#define CMD_BUFFER ((volatile unsigned char *)(0xC0F0 | (cardslot << 8))) +#define RPY_BUFFER ((volatile unsigned char *)(0xC0F8 | (cardslot << 8))) + +#define REPLY_OK 0x00 +#define REPLY_BUSY 0xBB +#define REPLY_EOF 0x01 +#define REPLY_NOFILE 0x02 +#define REPLY_EPARAM 0x03 +#define REPLY_ECMD 0x04 + +typedef enum { + MODE_REBOOT = 0, + MODE_DIAG, + MODE_FS, + MODE_VGACARD, + MODE_APPLICARD, + MODE_SERIAL, + MODE_PARALLEL, + MODE_MIDI, + MODE_SNESMAX, + MODE_ETHERNET +} v2mode_t; + +typedef enum { + SERIAL_LOOP = 0, + SERIAL_USB, + SERIAL_WIFI, + SERIAL_PRINTER, +} serialmux_t; + +typedef enum { + USB_HOST_CDC, + USB_GUEST_CDC, + USB_GUEST_MIDI, +} usbmux_t; + +typedef enum { + WIFI_CLIENT = 0, + WIFI_AP, +} wifimode_t; + +#define FS_COMMAND CARD_REGISTER(0x0) +#define FS_FILE CARD_REGISTER(0x1) +#define FS_FLAGS CARD_REGISTER(0x1) +#define FS_SIZELSB CARD_REGISTER(0x2) +#define FS_SIZEMSB CARD_REGISTER(0x3) +#define FS_OFFLSB CARD_REGISTER(0x2) +#define FS_OFFMSB CARD_REGISTER(0x3) +#define FS_WHENCE CARD_REGISTER(0x4) +#define FS_BUSY CARD_REGISTER(0xD) +#define FS_STATUS CARD_REGISTER(0xE) +#define FS_EXECUTE CARD_REGISTER(0xF) + +#define FS_O_RDONLY 0x0001 +#define FS_O_WRONLY 0x0002 +#define FS_O_RDWR 0x0003 +#define FS_O_CREAT 0x0100 +#define FS_O_EXCL 0x0200 +#define FS_O_TRUNC 0x0400 +#define FS_O_APPEND 0x0800 + +#define FS_SEEK_SET 0 +#define FS_SEEK_CUR 1 +#define FS_SEEK_END 2 + +typedef enum { + FS_OPEN = 0x10, + FS_CLOSE = 0x11, + FS_READ = 0x12, + FS_WRITE = 0x13, + FS_SEEK = 0x14, + FS_TELL = 0x15, +} fscommand_t; + +typedef enum { + FS_ERR_OK = 0, // No error + FS_ERR_IO = -1, // Error during device operation + FS_ERR_CORRUPT = -2, // Corrupted + FS_ERR_NOENT = -3, // No directory entry + FS_ERR_EXIST = -4, // Entry already exists + FS_ERR_NOTDIR = -5, // Entry is not a dir + FS_ERR_ISDIR = -5, // Entry is a dir + FS_ERR_NOTEMPTY = -7, // Dir is not empty + FS_ERR_BADF = -8, // Bad file number + FS_ERR_FBIG = -9, // File too large + FS_ERR_INVAL = -10, // Invalid parameter + FS_ERR_NOSPC = -11, // No space left on device + FS_ERR_NOMEM = -12, // No more memory available + FS_ERR_NOATTR = -13, // No data/attr available + FS_ERR_NAMETOOLONG = -14 // File name too long +} fserror_t; + +typedef enum { + MACHINE_AUTO = 0, + MACHINE_APPLE_II = 1, + MACHINE_APPLE_IIE = 2, + MACHINE_APPLE_IIGS = 3, + MACHINE_PRAVETZ = 4, + MACHINE_MAXVALUE = 5 +} compat_t; + +void hexprint(volatile uint8_t *buf, int size) { + while(size--) { + cprintf("%2X ", *buf++); + } +} + +int cfg_cmd3(char *cmd, uint16_t param0, uint16_t param1, uint16_t param2) { + uint16_t timeout = 0x1fff; + + gotoy(16); gotox(8); + cputc(cmd[0]); + cputc(cmd[1]); + cprintf(" $%04X $%04X $%04X", param0, param1, param2); + + RPY_BUFFER[7] = 0xFF; + CMD_BUFFER[7] = (param2 >> 8) & 0xFF; + RPY_BUFFER[6] = 0xFF; + CMD_BUFFER[6] = param2 & 0xFF; + RPY_BUFFER[5] = 0xFF; + CMD_BUFFER[5] = (param1 >> 8) & 0xFF; + RPY_BUFFER[4] = 0xFF; + CMD_BUFFER[4] = param1 & 0xFF; + RPY_BUFFER[3] = 0xFF; + CMD_BUFFER[3] = (param0 >> 8) & 0xFF; + RPY_BUFFER[2] = 0xFF; + CMD_BUFFER[2] = param0 & 0xFF; + RPY_BUFFER[1] = 0xFF; + CMD_BUFFER[1] = cmd[1]; + RPY_BUFFER[0] = 0xFF; + CMD_BUFFER[0] = cmd[0]; + + // Wait for the command to start processing + while(RPY_BUFFER[0] == 0xFF) { + if(timeout > 0) timeout--; + } + + // Wait while the command is processing + while(RPY_BUFFER[0] == REPLY_BUSY) { + if(timeout > 0) timeout--; + } + + gotoy(18); gotox(8); + hexprint(RPY_BUFFER, 8); + + return (timeout == 0) || (RPY_BUFFER[0] != REPLY_OK); +} + +int cfg_cmd2(char *cmd, uint16_t param0, uint16_t param1) { + return cfg_cmd3(cmd, param0, param1, 0); +} + +int cfg_cmd1(char *cmd, uint16_t param0) { + return cfg_cmd3(cmd, param0, 0, 0); +} + +int cfg_cmd0(char *cmd) { + return cfg_cmd3(cmd, 0, 0, 0); +} + + + + +#define NEWCONFIG_MAGIC 0x0001434E // "NC\x01\x00" + +#define CFGTOKEN_MODE_VGA 0x0000564D // "MV\x00\x00" VGA +#define CFGTOKEN_MODE_PCPI 0x00005A4D // "MZ\x00\x00" PCPI Applicard +#define CFGTOKEN_MODE_SER 0x0000534D // "MS\x00\x00" Serial +#define CFGTOKEN_MODE_PAR 0x0000504D // "MP\x00\x00" Parallel +#define CFGTOKEN_MODE_SNES 0x0000474D // "MG\x00\x00" SNESMAX +#define CFGTOKEN_MODE_MIDI 0x00004D4D // "MM\x00\x00" SNESMAX +#define CFGTOKEN_MODE_NET 0x0000454D // "ME\x00\x00" Ethernet +#define CFGTOKEN_MODE_FILE 0x0000464D // "MF\x00\x00" Filesystem + +#define CFGTOKEN_HOST_AUTO 0x00004148 // "HA\x00\x00" Autodetect +#define CFGTOKEN_HOST_II 0x00003248 // "H2\x00\x00" II/II+ +#define CFGTOKEN_HOST_IIE 0x00004548 // "HE\x00\x00" IIe +#define CFGTOKEN_HOST_IIGS 0x00004748 // "HG\x00\x00" IIgs +#define CFGTOKEN_HOST_PRAVETZ 0x00005048 // "HP\x00\x00" Pravetz + +#define CFGTOKEN_MUX_LOOP 0x00004C53 // "SL\x00\x00" Serial Loopback +#define CFGTOKEN_MUX_USB 0x00005553 // "SU\x00\x00" USB CDC +#define CFGTOKEN_MUX_WIFI 0x00005753 // "SW\x00\x00" WiFi Modem +#define CFGTOKEN_MUX_PRN 0x00005053 // "SP\x00\x00" WiFi Printer +#define CFGTOKEN_SER_BAUD 0x02004253 // "SB\x00\x00" Serial Baudrate + +#define CFGTOKEN_USB_HOST 0x00004855 // "UH\x00\x00" USB CDC Host +#define CFGTOKEN_USB_GUEST 0x00004755 // "UG\x00\x00" USB CDC Guest Device +#define CFGTOKEN_USB_MIDI 0x00004D55 // "UM\x00\x00" USB MIDI Guest Device + +#define CFGTOKEN_WIFI_AP 0x00004157 // "WA\x00\x00" WiFi AP +#define CFGTOKEN_WIFI_CL 0x00004357 // "WC\x00\x00" WiFi Client + +#define CFGTOKEN_WIFI_SSID 0x00005357 // "WS\x00\xSS" WiFi SSID +#define CFGTOKEN_WIFI_PSK 0x00005057 // "WS\x00\xSS" WiFi PSK + +#define CFGTOKEN_WIFI_IP 0x04504957 // "WIP\xSS" WiFi IP +#define CFGTOKEN_WIFI_NM 0x044D4E57 // "WNM\xSS" WiFi Netmask + +#define CFGTOKEN_JD_HOST 0x0000484A // "JH\x00\x01" JetDirect Hostname +#define CFGTOKEN_JD_PORT 0x0200444A // "JD\x00\x01" JetDirect Port + +#define CFGTOKEN_MONO_00 0x00005056 // "VP\x00\x00" Full Color Video +#define CFGTOKEN_MONO_80 0x00805056 // "VP\x80\x00" B&W Video +#define CFGTOKEN_MONO_90 0x00905056 // "VP\x90\x00" B&W Inverse +#define CFGTOKEN_MONO_A0 0x00A05056 // "VP\xA0\x00" Amber +#define CFGTOKEN_MONO_B0 0x00B05056 // "VP\xB0\x00" Amber Inverse +#define CFGTOKEN_MONO_C0 0x00C05056 // "VP\xC0\x00" Green +#define CFGTOKEN_MONO_D0 0x00D05056 // "VP\xD0\x00" Green Inverse +#define CFGTOKEN_MONO_E0 0x00E05056 // "VP\xE0\x00" C64 +#define CFGTOKEN_MONO_F0 0x00F05056 // "VP\xF0\x00" Custom + +#define CFGTOKEN_TBCOLOR 0x00005456 // "VT\xXX\x00" Custom default TBCOLOR +#define CFGTOKEN_BORDER 0x00004256 // "VB\xXX\x00" Custom default BORDER + + +#endif /* __V2ANALOG_H */ diff --git a/src/v2loader.h b/src/v2loader.h new file mode 100644 index 0000000..df6eabd --- /dev/null +++ b/src/v2loader.h @@ -0,0 +1,35 @@ +#include + +void do_jump(uint16_t addr) { + void_jump jump = (void_jump)addr; + jump(); +} + +void load_and_jump(char *filename, uint16_t execaddr) { + FILE *f; + size_t bytesread; + long fsz; + long total = 0; + char *ptr, *loadaddr; + f = fopen(filename, "rb"); + + if(f == NULL) { + return; + } + + fseek(f, 0, SEEK_END); + fsz = ftell(f); + fseek(f, 0, SEEK_SET); + ptr = loadaddr = (char *)execaddr; + + while(!feof(f) && (fsz > 0)) { + bytesread = fread(ptr, 1, longmin(512, fsz), f); + if(bytesread > 0) { + ptr += bytesread; + fsz -= bytesread; + } + }; + fclose(f); + + do_jump(execaddr); +} diff --git a/src/v2types.h b/src/v2types.h new file mode 100644 index 0000000..cb394cc --- /dev/null +++ b/src/v2types.h @@ -0,0 +1,25 @@ +#ifndef __V2TYPES_H +#define __V2TYPES_H + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed long int32_t; + +typedef void (*void_jump)(void); + +long longmin(long a, long b) { + if(a < b) return a; + return b; +} + +long longmax(long a, long b) { + if(a > b) return a; + return b; +} + +#endif /* __V2TYPES_H */ + diff --git a/tools/ac.jar b/tools/ac.jar new file mode 100644 index 0000000..f523583 Binary files /dev/null and b/tools/ac.jar differ diff --git a/tools/acx.jar b/tools/acx.jar new file mode 100644 index 0000000..8a89745 Binary files /dev/null and b/tools/acx.jar differ diff --git a/tools/rlefont.c b/tools/rlefont.c new file mode 100644 index 0000000..abbb001 --- /dev/null +++ b/tools/rlefont.c @@ -0,0 +1,59 @@ +#include +#include + +unsigned char buf[2048]; + +int getrunlength(unsigned char *buf, int index) { + int rl; + unsigned char ch = buf[index]; + + for(rl = 1; ((index+rl) < 2048) && (rl < 128); rl++) { + if(buf[index+rl] != ch) break; + } + + return rl - 1; +} + +int main(int argc, char **argv) { + int i; + FILE *in, *out; + + if(argc != 3) { + fprintf(stderr, "Usage:\r\n\t%s \r\n", argv[0]); + return -1; + } + + in = fopen(argv[1], "rb"); + if(!in) { + fprintf(stderr, "Unable to open file '%s' for input.\r\n", argv[1]); + return -1; + } + + out = fopen(argv[2], "wb"); + if(!out) { + fprintf(stderr, "Unable to open file '%s' for output.\r\n", argv[2]); + fclose(in); + return -1; + } + + fread(buf, 1, 16, in); + fwrite(buf, 1, 16, out); + fread(buf, 1, 2048, in); + + while(i < 2048) { + int rl = getrunlength(buf, i); + + fputc((buf[i] & 0x7F), out); + + if(rl != 0) { + fputc((rl | 0x80), out); + } + + i += 1 + rl; + } + + fclose(in); + fclose(out); + + return 0; +} diff --git a/tools/unrlefont.c b/tools/unrlefont.c new file mode 100644 index 0000000..4690513 --- /dev/null +++ b/tools/unrlefont.c @@ -0,0 +1,46 @@ +#include + +int main(int argc, char **argv) { + int i = 0; + FILE *in, *out; + unsigned char ch, last; + + if(argc != 3) { + fprintf(stderr, "Usage:\r\n\t%s \r\n", argv[0]); + return -1; + } + + in = fopen(argv[1], "rb"); + if(!in) { + fprintf(stderr, "Unable to open file '%s' for input.\r\n", argv[1]); + return -1; + } + + out = fopen(argv[2], "wb"); + if(!out) { + fprintf(stderr, "Unable to open file '%s' for output.\r\n", argv[2]); + fclose(in); + return -1; + } + + while(i < 2048) { + ch = fgetc(in); + + if(ch & 0x80) { + ch = (ch & 0x7f) ? (ch & 0x7f) : 128; + while(ch--) { + fputc(last, out); + i++; + } + } else { + fputc(ch, out); + last = ch; + i++; + } + } + + fclose(in); + fclose(out); + + return 0; +} diff --git a/tools/xorfont.c b/tools/xorfont.c new file mode 100644 index 0000000..cf78ab5 --- /dev/null +++ b/tools/xorfont.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + int i; + FILE *a, *b, *out; + unsigned char ca, cb; + char *pathname; + char *filename; + + if(argc != 5) { + fprintf(stderr, "Usage\r\n\t%s \r\n", argv[0]); + return -1; + } + + a = fopen(argv[2], "rb"); + if(!a) { + fprintf(stderr, "Unable to open file '%s' for input.\r\n", argv[2]); + return -1; + } + + b = fopen(argv[3], "rb"); + if(!b) { + fprintf(stderr, "Unable to open file '%s' for input.\r\n", argv[3]); + fclose(a); + return -1; + } + + out = fopen(argv[4], "wb"); + if(!out) { + fprintf(stderr, "Unable to open file '%s' for output.\r\n", argv[4]); + fclose(a); + fclose(b); + return -1; + } + + for(i=0; i < 16; i++) { + if(i < strlen(argv[1])) { + fputc(toupper(argv[1][i]), out); + } else { + fputc(0, out); + } + } + + for(i=0; i < 2048; i++) { + ca = fgetc(a); + cb = fgetc(b); + fputc((ca ^ cb), out); + } + + fclose(a); + fclose(b); + fclose(out); + + return 0; +}