home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / hardware / eprommer / source.lha / src / eprommer.c < prev    next >
C/C++ Source or Header  |  1993-11-14  |  41KB  |  1,825 lines

  1. /*
  2.  * An adaption of EPROMmer.bas
  3.  * By Udi Finkelstein (C) 1990
  4.  *
  5.  * Changes by Carsten Rose in November 1992 - June 1993:
  6.  *  - changed to compile with DICE 2.07.54R
  7.  *  - GUI now generated with GadToolsBox V2.0c
  8.  *  - WB 2.0 Look
  9.  *  - Use default Screen Font (done by GTB)
  10.  *  - Notice Font Size          (done by GTB)
  11.  *  - Ability to Load and Save Files in 'intelhex' Format 
  12.  *                   (Pseudo Standard Object Code Format)
  13.  *  - req.library no longer used (use ASL FileRequest and EasyRequest)
  14.  *     if you don't like it use any of the 'ASL to REQ' Patches
  15.  *  - Integer Gadgets changed to String Gadgets , to allow input of HEX-Numbers
  16.  *    - Settings will be saved temporaly in ENV:Eprommer.Prefs or in ENVARC:Eprommer.Prefs
  17.  *    - Test of VPP more 'Eprom friendly' ;-)
  18.  *  - some little hacks more
  19.  */
  20.  
  21. #include "defs.h"
  22. #include "eprommer.h"
  23. #include "gad_eprommer.h"
  24. #include "intelhex.h"
  25.  
  26. #include "eprommer_protos.h"
  27.  
  28. /*#define DEBUG_PROG*/
  29.  
  30. #define CIA_MINUSEC    5    /* Minimum CIA access time (in micro seconds) */
  31.  
  32. #define DELAY {volatile u_char c;int i;for(i=0;i<waitcnt;i++) c=*ParPort;}
  33.  
  34. char *vers = "\0$VER: Eprommer 3.2d (November,14,1993)";
  35.  
  36. #define OE  0x01
  37. #define PGM 0x02
  38.  
  39. #define VOLTS12 (223 - 128)
  40. #define VOLTS21 (223 - 64)
  41. #define VOLTS25 (223 - 192)
  42.  
  43. /* PA2 = SEL  */
  44. #define Clock0 0
  45. #define Clock1 4
  46.  
  47. #define MAXDATABUFFER 0x10000    /* 64kB */
  48.  
  49. struct    Window *window_locked=NULL;  /* If program stops, check fisrt if any Window is locked, release them */
  50. struct    IntuiText IT_counting;         /* IntuiText struct which shows counting */
  51. BOOL    pp_flag=FALSE;ppb_flag=FALSE;
  52.  
  53. u_char *PEmemBase;
  54. char *EmemTop,*RamBot;
  55.  
  56. extern __far struct CIA ciaa,ciab;
  57.  
  58. volatile u_char *ParPort  = &ciaa.ciaprb;  /*(volatile u_char *)0xbfe101;*/
  59. volatile u_char *ParDDR   = &ciaa.ciaddrb; /*(volatile u_char *)0xbfe301;*/
  60. volatile u_char *CtrlPort = &ciab.ciapra;  /*(volatile u_char *)0xbfd000;*/
  61. volatile u_char *CtrlDDR  = &ciab.ciaddra; /*(volatile u_char *)0xbfd200;*/
  62.  
  63. u_char volt_tbl[] = { VOLTS25, VOLTS25, VOLTS21, VOLTS21,
  64.     VOLTS12, VOLTS12, VOLTS12, VOLTS12, VOLTS12, VOLTS12 };
  65.  
  66. /* PA0 = /OE, PA1 = /PGM */
  67. u_char rp_tbl[] = { 0, 0, 0, PGM, PGM, PGM, 0, 0, 0, 0 ,0};
  68.  
  69. u_char wp_tbl[] = { OE+PGM, OE, OE, OE, OE, OE, OE, OE, OE, OE, OE };
  70.  
  71. u_char lp_tbl[] = { OE+PGM, OE+PGM, OE+PGM, OE+PGM, OE+PGM,
  72.                     OE+PGM, OE+PGM, OE+PGM, OE+PGM, OE+PGM, OE+PGM };
  73. u_char ip_tbl[] = { OE, OE+PGM, OE+PGM, OE+PGM, OE+PGM, OE+PGM,
  74.                     OE+PGM, OE+PGM, OE+PGM , OE+PGM, OE+PGM };
  75.  
  76.     /* 1==EProm, 0==Static RAM (used to check only EProm's if any bits in the eprom are already 0) */
  77. u_char e_flag[] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 };
  78.  
  79. u_short ad_tbl[] = { 0, 0, 0, 0, 0, 0, 0, 0,0, 0x2000, 0 };
  80.  
  81.     /* Table of default program Alorythm */
  82. short ag_tbl[] = {AG_50MS,AG_50MS,AG_50MS,AG_INTE,AG_INTE,AG_INTE,AG_INTE,AG_INTE,AG_NDEL,AG_NDEL,AG_NDEL};
  83.  
  84.     /* Table of 'Programing' Functions Adresses */
  85. short (*wa_tbl2[])(u_char) = { Wr50ms, WrIntel, WrEprommer, WrFast };
  86.  
  87. short (*WriteAlg)(u_char);
  88.  
  89.     /* Table of Eprom default sizes */
  90. long size_tbl[] = { 2048, 4096, 4096, 8192, 8192, 16384, 32768, 65536, 2048, 8192, 32768 };
  91.  
  92.     /* Global Variables to do Eprom Handling */
  93. u_char VoltVal, ReadParam, WriteParam, LeaveParam, InhibitParam;
  94.  
  95. u_char     Addr0, /* Prepare Clock for High Byte of Address */ 
  96.         Addr1, /* Clock for High Byte of Address */ 
  97.         Addr2, /* Prepare Clock for Low Byte of Address */  
  98.         Addr3; /* Clock for Low Byte of Address */
  99. u_char Write1, Write2, Write3, Write4, Write5;
  100. u_char Read0, Read1;
  101.  
  102. long LastAddr;        /* Contains always the latest switched address */
  103. u_short AdParam;    /* Eprommer Hardware Offset. All Eprom Addresses will */
  104.                     /*  be added with this value. */
  105.  
  106.     /* These are all Mirrors of the appropriate String Gadget */
  107. u_char RAMValInt=0;    /* RAM Buffer Value */
  108. LONG   RAMLowInt=0,    /* Logical RAM Buffer Start Address */
  109.        EPROMLowInt=0, /* logical Eprom Start Address */
  110.        LengthInt=0;    /* Eprom Length */
  111.  
  112. #ifdef _DCC
  113.  extern struct IntuitionBase *IntuitionBase;
  114.  extern struct GfxBase *GfxBase;
  115. #else
  116.  struct IntuitionBase *IntuitionBase;
  117.  struct GfxBase *GfxBase;
  118. #endif
  119.  
  120. struct Library *MiscBase=NULL;
  121. struct MsgPort *tp;
  122. struct timerequest *tr;
  123. long Size;
  124. ULONG waitcnt=20;        /* Delay Counter for CIA Access. Depends of your Amiga 500/600/... */
  125. short EPType = -1;        /* Eprom Type EP_xxxx  / See Eprommer.h */
  126.  
  127. char LDir[DSIZE + 1], LFile[FCHARS + 1], LFullPath[DSIZE+FCHARS+2];
  128. char SDir[DSIZE + 1], SFile[FCHARS + 1], SFullPath[DSIZE+FCHARS+2];
  129.  
  130. u_char testvpp=VOLTS12;
  131.  
  132. struct Config conf,newconf;            /* contains User settings */
  133. BOOL epromout = FALSE;                /* Eprom in Socket ? */
  134. BOOL newepromout = FALSE;            /* Eprom in Socket ? */
  135.  
  136. BOOL abort_flag=FALSE;                    /* set, if User abort Operation */
  137.  
  138. APTR aslreq;
  139. struct Requester *plockreq=NULL;
  140.  
  141. /* Static Data for Busy Pointer */
  142. __chip UWORD waitpointer[] = {
  143.         0x0000, 0x0000,
  144.         0x0400, 0x07C0,
  145.         0x0000, 0x07C0,
  146.         0x0100, 0x0380,
  147.         0x0000, 0x07E0,
  148.         0x07C0, 0x1FF8,
  149.         0x1FF0, 0x3FEC,
  150.         0x3FF8, 0x7FDE,
  151.         0x3FF8, 0x7FBE,
  152.         0x7FFC, 0xFF7F,
  153.         0x7EFC, 0xFFFF,
  154.         0x7FFC, 0xFFFF,
  155.         0x3FF8, 0x7FFE,
  156.         0x3FF8, 0x7FFE,
  157.         0x1FF0, 0x3FFC,
  158.         0x07C0, 0x1FF8,
  159.         0x0000, 0x07E0,
  160.         0x0000, 0x0000};             /* reserved, must be NULL */
  161.  
  162. static long speedtest(struct timerequest *tr,long cnt)
  163. {
  164.     int i;
  165.     u_char c;
  166.     long sec1,sec2,micro1,micro2;
  167.  
  168.  
  169.     tr->tr_node.io_Command = TR_GETSYSTIME;
  170.     DoIO((struct IORequest *)tr);
  171.     sec1=tr->tr_time.tv_secs;
  172.     micro1=tr->tr_time.tv_micro;
  173.     
  174.     for(i=0;i<cnt;i++)
  175.         c = *ParPort;
  176.     
  177.     DoIO((struct IORequest *)tr);
  178.     sec2=tr->tr_time.tv_secs;
  179.     micro2=tr->tr_time.tv_micro;
  180.  
  181.     micro1 = (sec2 - sec1)*1000000 + micro2-micro1;
  182.  
  183.     return(micro1);
  184. }
  185.  
  186. static void checkspeed(void)
  187. {
  188.  
  189.     long cnt=10000,tm=0;
  190.  
  191.     while(tm<100000)
  192.     {
  193.         cnt*=5;
  194.         tm=speedtest(tr,cnt);
  195.     }
  196.  
  197.     waitcnt=cnt/(tm/CIA_MINUSEC);
  198. }
  199.  
  200. static void lockwindow(struct Window *wnd,int flag)
  201. {
  202.     /* Locks a window for User input and changes MousePointer for this Window
  203.      * like the Workbench BusyPointer.
  204.      * If flag is
  205.      *  TRUE: Opens an unvisible Requester.
  206.      *  FALSE: Close this Requester.
  207.      */
  208.  
  209. #ifdef DEBUG_PROG
  210. puts("lockwindow");
  211. #endif
  212.     if(flag)
  213.     {
  214.         SetPointer(wnd,waitpointer,16,16,0,0);
  215.         window_locked = wnd;
  216.         if(!Request(plockreq,wnd))
  217.             DisplayBeep(NULL);     /* Just if request can't open/lock the Window*/
  218.     }
  219.     else
  220.     {
  221.         EndRequest(plockreq,wnd);
  222.         window_locked = NULL;
  223.         ClearPointer(wnd);
  224.     }
  225. }
  226.  
  227. static void simplerequest(char *ctl, ...)
  228. {
  229.     /* Call this routine like printf().
  230.      *  Simply open a requester with your message.
  231.      */
  232.  
  233.     va_list va;
  234.  
  235.     struct EasyStruct easy = {
  236.         sizeof (struct EasyStruct),
  237.         0,
  238.         "Message",
  239.         NULL,   /* ctl */
  240.         "OK"
  241.     };
  242.  
  243.     easy.es_TextFormat = ctl;
  244.  
  245.     va_start(va,ctl);
  246.     
  247.     EasyRequestArgs(EprommerWnd,&easy,NULL,va);
  248.     va_end(va);
  249. }
  250.  
  251. static int twogadrequest(char *buttons,char *ctl, ...)
  252. {
  253.     /* Call this routine like printf(), but a special string 'buttons'.
  254.      * This string must contain the text for the 2 Buttons (mostly "OK|CANCEL").
  255.      * The 2 Buttons must be seperated with '|'.
  256.      *  Simply open a requester with your message.
  257.      *
  258.      * RC: 1 if the left Button is pushed
  259.      *     0 if the right Button is pushed
  260.      */
  261.  
  262.     va_list va;
  263.     int rc;
  264.     struct EasyStruct easy = {
  265.         sizeof (struct EasyStruct),
  266.         0,
  267.         "Message",
  268.         NULL,   /*ctl,*/
  269.         NULL
  270.     };
  271.     
  272.  
  273.     easy.es_TextFormat = ctl;
  274.     easy.es_GadgetFormat = buttons;
  275.  
  276.     va_start(va,ctl);
  277.     rc = EasyRequestArgs(EprommerWnd,&easy,NULL,va);
  278.     va_end(va);
  279.     return(rc);
  280. }
  281.  
  282. static void updatevalgad(int gadnr,int value)
  283. {
  284.     /* Update (Display) 'value' in 'gadnr' String Gadget */
  285.  
  286.     char tmp[256];
  287.  
  288.     switch(conf.numericalbase)
  289.     {
  290.         case CY_DEC:    sprintf(tmp, "%d", value);
  291.                         break;
  292.         case CY_DECHEX:
  293.         case CY_HEX:    sprintf(tmp, "0x%x", value);
  294.                         break;
  295.         default:        simplerequest("Error numerical Base, Type:%d. File:%s Line:%d",conf.numericalbase,__FILE__,__LINE__);
  296.     }
  297.     GT_SetGadgetAttrs(EprommerGadgets[gadnr],EprommerWnd,NULL,GTST_String,tmp,TAG_DONE);
  298. }
  299.  
  300. static void updateallvalgad(void)
  301. {
  302.     /* Updae all String Gadgets */
  303.     updatevalgad(GD_RamAddress,RAMLowInt);
  304.     updatevalgad(GD_EpromAddress,EPROMLowInt);
  305.     updatevalgad(GD_Length,LengthInt);
  306.     updatevalgad(GD_RamVal,(int)RAMValInt);
  307. }
  308.  
  309. /*
  310.  * Timer initialization done here
  311.  */
  312. static int OpenTimer(void)
  313. {
  314.  
  315.     if ((tp = CreatePort(0, 0)) == 0) return 1;
  316.     if ((tr = (struct timerequest *)CreateExtIO(tp, sizeof(struct timerequest)))
  317.         == NULL) return 1;
  318.  
  319.     if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)tr, 0))
  320.         return 1;
  321.  
  322.     return(NULL);
  323. }
  324.  
  325. /*
  326.  * Timer freed done here
  327.  */
  328. static void CloseTimer(struct timerequest *tr)
  329. {
  330.  
  331.     if (tp)
  332.     {
  333.         DeletePort(tp);
  334.         tp = NULL;
  335.     }
  336.  
  337.     if (tr) 
  338.     {
  339.         CloseDevice((struct IORequest *)tr);
  340.         DeleteExtIO((struct IORequest *)tr);
  341.         tr = NULL;
  342.     }
  343. }
  344.  
  345. /*
  346.  * A MicroSeconds precision delay routine
  347.  */
  348. static void uDelay(ULONG delay)
  349. {
  350.  
  351.     tr->tr_node.io_Command = TR_ADDREQUEST;
  352.     tr->tr_time.tv_secs = 0;
  353.     tr->tr_time.tv_micro = delay;
  354.     DoIO((struct IORequest *)tr);
  355. }
  356.  
  357. static void SetAddr(long Address)
  358. {
  359.     LastAddr = Address;
  360.     *ParDDR = 255;      /* Parallel Port Direction Output */
  361.     *ParPort = 253;     /* Prepare selection of High Byte Address Latch */
  362.     DELAY
  363.  
  364.     *CtrlPort = Addr0;    /* Select High Byte Address Latch and inactivate Address Latch Clock */
  365.     DELAY
  366.  
  367.     *ParPort = Address >> 8;  /* Write High Byte Address */
  368.     DELAY
  369.  
  370.     *CtrlPort = Addr1;  /* Clock High Byte Address into Latch*/
  371.     DELAY
  372.  
  373.     *ParPort = 254;        /* Prepare selection of Low Byte Address Latch */
  374.     DELAY
  375.  
  376.     *CtrlPort = Addr2;  /* Select Low Byte Address Latch and inactivate Address Latch Clock */
  377.     DELAY
  378.  
  379.     *ParPort = Address & 0xff; /* Write Low Byte Address */
  380.     DELAY
  381.  
  382.     *CtrlPort = Addr3;  /* Clock Low Byte Address into Latch */ 
  383. }
  384.  
  385. static void InitPorts(void)
  386. {
  387.  
  388.       /* Prepare VPP DataBits and Lo/Hi Address Latch to take Data */
  389.     *CtrlDDR  = Clock1 + OE + PGM;    /* Set to OutPut: 0000 0111 */
  390.     *CtrlPort = Clock0 + OE + PGM;  /* Write        : 0000 0011 */     
  391.     DELAY
  392.  
  393.     testvppoff();
  394.     SetAddr(0);
  395. }
  396.  
  397. static void testvppon(u_char volt)
  398. {
  399.     *ParDDR = 255;
  400.     *ParPort = volt;
  401.  
  402.     *CtrlPort = Clock0;
  403.     DELAY
  404.     *CtrlPort = Clock1;
  405. }
  406.  
  407. static void testvppoff(void)
  408. {
  409.     
  410.     *CtrlPort = LeaveParam + Clock0;
  411.     DELAY
  412.     *ParDDR  = 255;
  413.     *ParPort = 255;
  414.     DELAY
  415.     *CtrlPort = LeaveParam + Clock1;
  416. }
  417.  
  418. static void ThatsIt(void)
  419. {
  420.     /* Set Eprom Adress to 0, Init CIA */
  421.     SetAddr(0);
  422.     testvppoff();
  423.     *CtrlDDR = 0;
  424.     *ParDDR = 0;
  425. }
  426.  
  427. static u_char ReadByte(void)
  428. {
  429. u_char DataIn;
  430.  
  431.  
  432. /* If A15 is used for /WR, make sure it's high now - used for 62256,6264 */
  433.     if( (EPType==EP_6216) || (EPType==EP_6264)|| (EPType==EP_62256) )
  434.       SetAddr(LastAddr | 0x8000);
  435.  
  436. /* port is now input */
  437.     *ParDDR = 0;
  438.     *CtrlPort = Read0;
  439.     DELAY
  440.     DataIn = *ParPort;
  441.  
  442.     *CtrlPort = Read1;
  443.  
  444.     return DataIn;
  445. }
  446.  
  447. static void WriteByte(u_char DataOut, u_long delay)
  448. {
  449.  
  450. /* If A15 is used for /WR, make sure it's low now - used for 62256,6264 */
  451.     if( (EPType==EP_6216) || (EPType==EP_6264) || (EPType==EP_62256) )
  452.       SetAddr(LastAddr & ~0x8000);
  453.  
  454.     *ParDDR = 255;
  455.     *ParPort = VoltVal;
  456.     DELAY
  457.  
  458.     *CtrlPort = Write1;
  459.     DELAY
  460.  
  461.     *ParPort = DataOut;
  462.     DELAY
  463.  
  464.     *CtrlPort = Write2;
  465.     uDelay(delay);
  466.  
  467.     *CtrlPort = Write3;
  468.     DELAY
  469.  
  470.     *ParPort = 255;
  471.     DELAY
  472.  
  473.     *CtrlPort = Write4;
  474.     DELAY
  475.  
  476.     *CtrlPort = Write5;
  477. }
  478.  
  479. static void SetCycleParams(void )
  480. {
  481.     Write1 = InhibitParam + Clock1;
  482.     Write2 = WriteParam + Clock1;
  483.     Write3 = InhibitParam + Clock0;
  484.     Write4 = InhibitParam + Clock1;
  485.     Write5 = LeaveParam + Clock0;
  486.     Read0 = ReadParam + Clock0;
  487.     Read1 = LeaveParam + Clock0;
  488.     Addr0 = LeaveParam + Clock1;
  489.     Addr1 = LeaveParam + Clock0;
  490.     Addr2 = LeaveParam + Clock1;
  491.     Addr3 = LeaveParam + Clock0;
  492. }
  493.  
  494. /*
  495.  * Write a single byte
  496.  */
  497. static short WriteCycle(u_char DataOut)
  498. {
  499. u_char c;
  500.  
  501. #ifdef DEBUG_PROG
  502.     puts("WriteCycle");
  503. #endif
  504.  
  505. /* Any bit set in DataOut which is already reset in the EPROM? */
  506.     c = ReadByte();
  507.  
  508.     if (e_flag[EPType] && (~c & DataOut)) /* e_flag==0 -> EProm is a static RAM, NO check */ 
  509.         return 1;
  510.  
  511. /* Is data already identical? */
  512.     if (DataOut == c) return 0;
  513.  
  514. #ifdef DEBUG_PROG
  515.     printf("call WriteAlg: %x\n",WriteAlg);
  516. #endif
  517.  
  518.     return (*WriteAlg)(DataOut);
  519. }
  520.  
  521. /*
  522.  * The Eprommer algorythm - a variation on the intel algorythm.
  523.  */
  524. static short WrEprommer(u_char  DataOut)
  525. {
  526. short n;
  527. u_long l;
  528.  
  529. #ifdef DEBUG_PROG
  530.     puts("WriteEprommer");
  531. #endif
  532. /* Programming loop */
  533.     n = 0;
  534.     while(++n < 20) {
  535.         WriteByte(DataOut, 1000);
  536.         if (ReadByte() == DataOut) {
  537. /* Overprogramming section */
  538.             l = n * 5000;
  539.             if (l > 20000) l = 20000;
  540.             WriteByte(DataOut, l);
  541.             return 0;
  542.         }
  543.     }
  544. /* Too many retries, must be EPROM failure */
  545.     return 2;
  546. }
  547.  
  548. /*
  549.  * The IntEligent programming algorythm algorythm.
  550.  */
  551. static short WrIntel(u_char DataOut)
  552. {
  553. short n;
  554.  
  555. #ifdef DEBUG_PROG
  556.     puts("WriteIntel");
  557. #endif
  558. /* Programming loop */
  559.     n = 0;
  560.     while(++n < 15) {
  561.         WriteByte(DataOut, 1000);
  562.         if (ReadByte() == DataOut) {
  563. /* Overprogramming section */
  564.             WriteByte(DataOut, n * 4000);
  565.             return 0;
  566.         }
  567.     }
  568. /* Too many retries, must be EPROM failure */
  569.     return 2;
  570. }
  571.  
  572. /*
  573.  * The fastest algorythm - use for RAMs only!
  574.  */
  575. static short WrFast(u_char DataOut)
  576. {
  577. /* No loop! */
  578. #ifdef DEBUG_PROG
  579.     puts("WriteFast");
  580. #endif
  581.     WriteByte(DataOut, 10);
  582.     if (ReadByte() == DataOut) return 0;
  583.  
  584. /* RAM failure */
  585.     return 2;
  586. }
  587.  
  588. /*
  589.  * The basic 50ms pulse algorythm.
  590.  * Use for 2716, 2732 and 2732A chips which requires it. not all
  591.  * brands of chips require this slow algorythm (Intel does, TI don't).
  592.  */
  593. static short Wr50ms(u_char DataOut)
  594. {
  595. /* No loop! */
  596. #ifdef DEBUG_PROG
  597.     puts("Wr50ms");
  598. #endif
  599.     WriteByte(DataOut, 50000);
  600.     if (ReadByte() == DataOut) return 0;
  601.  
  602. /* RAM failure */
  603.     return 2;
  604. }
  605.  
  606. static void LoadFile(void)
  607. {
  608.     /* Load the file 'LFullPath' in  buffer pointed by 'PEmemBase+RAMLowInt'.
  609.      * Notice the 'conf.dataformat' and 'conf.clearbuffer'.
  610.      */
  611.  
  612.     FILE *fin;
  613.     char *perror;    /* Pointer to Error Message */
  614.     int  loadmode;
  615.  
  616.     if ((fin = fopen(LFullPath, "r")) == NULL) {
  617.         simplerequest("Could not open input file '%s'!", LFullPath);
  618.         return;
  619.     }
  620.     
  621.     if(conf.clearbuffer)
  622.         setmem(PEmemBase,MAXDATABUFFER,0xFF);
  623.  
  624.     lockwindow(EprommerWnd,TRUE);
  625.     if(conf.dataformat==INTELHEX)
  626.     {
  627.         loadmode = conf.bufferfragmented?FRAGMENTED:CONTINOUS;
  628.         if(perror=readintelhex(fin,PEmemBase+RAMLowInt,MAXDATABUFFER-RAMLowInt,&LengthInt,loadmode,&EPROMLowInt))
  629.         {
  630.             simplerequest(perror);
  631.             LengthInt=0;
  632.         }
  633.     }
  634.     else
  635.     {
  636.         LengthInt=fread(PEmemBase+RAMLowInt,1,MAXDATABUFFER-RAMLowInt,fin);
  637.     }
  638.     fclose(fin);
  639.     
  640.     if( (LengthInt+EPROMLowInt) >size_tbl[EPType])
  641.     {
  642.         if(EPROMLowInt>size_tbl[EPType])
  643.         {
  644.             simplerequest("Start Address:%ls bigger than Eprom size:%ld",EPROMLowInt,size_tbl[EPType]);
  645.             LengthInt=0;
  646.             EPROMLowInt=0;            
  647.         }
  648.         else
  649.         {
  650.             simplerequest("That's too much data.\nRead %ld Bytes, Start's at: %ld\nEprom Size: %ld Bytes",LengthInt,EPROMLowInt,size_tbl[EPType]);
  651.             LengthInt=size_tbl[EPType]-EPROMLowInt;
  652.         }
  653.     }
  654.     else if(conf.inforeq)
  655.         simplerequest("Read %ld Bytes",LengthInt);
  656.  
  657.     updatevalgad(GD_Length,LengthInt);
  658.     updatevalgad(GD_EpromAddress,EPROMLowInt);
  659.     lockwindow(EprommerWnd,FALSE);
  660. }
  661.  
  662. static void SaveFile(void)
  663. {
  664.     FILE *fin;
  665.     LONG len;
  666.     char *perror;    /* Pointer to Error Message */
  667.  
  668.     /* check if File exists */
  669.     if (fin=fopen(SFullPath, "r"))
  670.     {
  671.         fclose(fin);
  672.         if(!twogadrequest("OK|CANCEL","Do you want overwrite\n '%s'",SFullPath))
  673.             return;
  674.     }
  675.  
  676.     if ((fin = fopen(SFullPath, "w")) == NULL) {
  677.         simplerequest("Could not open output file '%s'!",SFullPath);
  678.         return;
  679.     }
  680.  
  681.     lockwindow(EprommerWnd,TRUE);
  682.     if(conf.dataformat==INTELHEX)
  683.     {
  684.         if(perror=writeintelhex(fin,PEmemBase + RAMLowInt,RAMLowInt,LengthInt))
  685.         {
  686.             simplerequest(perror);
  687.             return;
  688.         }
  689.         len = LengthInt;
  690.     }
  691.     else
  692.         len = fwrite(PEmemBase + RAMLowInt, 1, LengthInt, fin);
  693.  
  694.     fclose(fin);
  695.     updatevalgad(GD_Length,LengthInt);
  696.     lockwindow(EprommerWnd,FALSE);
  697.  
  698.     if (len != LengthInt)
  699.         simplerequest("We wrote only %ld bytes Instead of %ld bytes",len,LengthInt);
  700.     else
  701.         if(conf.inforeq)
  702.             simplerequest("Write %ld Bytes",LengthInt);
  703. }
  704.  
  705. static char *stoh(u_short value,char *pbuf)
  706. {
  707.     /* Convert 'value' to  4-digit ASCII Hex Notation.
  708.      * 
  709.      * Write ASCII Hex Code (4 Chars) at '*pbuf'.
  710.      *
  711.      * RC: pbuf+4    (points to next free char  )
  712.      */  
  713.  
  714.     u_char nibble;    /*  4 Bits of 'value' */
  715.  
  716.     nibble = 0x000F & value;
  717.     pbuf[3]= (nibble<=9) ? nibble+'0' : (nibble-0x0A)+'A';
  718.  
  719.     value >>=4;
  720.     nibble = 0x000F & value;
  721.     pbuf[2]= (nibble<=9) ? nibble+'0' : (nibble-0x0A)+'A';
  722.  
  723.     value >>=4;
  724.     nibble = 0x000F & value;
  725.     pbuf[1]= (nibble<=9) ? nibble+'0' : (nibble-0x0A)+'A';
  726.  
  727.     value >>=4;
  728.     nibble = 0x000F & value;
  729.     pbuf[0]= (nibble<=9) ? nibble+'0' : (nibble-0x0A)+'A';
  730.  
  731.     return(&pbuf[4]);
  732. }
  733.  
  734. static void startamigaguide(UWORD code)
  735. {
  736.     if(code==95)  /* Key: Help */
  737.         system("run SYS:Utilities/AmigaGuide Eprommer.guide");
  738. }
  739.  
  740. int EprommerRawKey( void )
  741. {
  742.     /* routine for "IDCMP_RAWKEY". */
  743.     startamigaguide(EprommerMsg.Code);
  744.     return(TRUE);
  745. }
  746.  
  747. int OptionsRawKey( void )
  748. {
  749.     /* routine for "IDCMP_RAWKEY". */
  750.     startamigaguide(OptionsMsg.Code);
  751.     return(TRUE);
  752. }
  753.  
  754. int BusyRawKey( void )
  755. {
  756.     /* routine for "IDCMP_RAWKEY". */
  757.     startamigaguide(BusyMsg.Code);
  758.     return(TRUE);
  759. }
  760.  
  761. int TestRawKey( void )
  762. {
  763.     /* routine for "IDCMP_RAWKEY". */
  764.     startamigaguide(TestMsg.Code);
  765.     return(TRUE);
  766. }
  767.  
  768.  
  769.  
  770.  
  771. int abortClicked(void)
  772. {
  773.     abort_flag = TRUE;
  774.  
  775.     return(TRUE);
  776. }
  777.  
  778. static void showaddr_checkabort(long addr,BOOL flag)
  779. {
  780.     int rc;
  781.     struct IntuiMessage    *m;
  782.     int            (*func)(void);
  783.  
  784.     if(!BusyWnd)    /* Busy Window already opened ? */
  785.     {
  786. #ifdef DEBUG_PROG
  787.         puts("OpenBusyWindow");
  788. #endif
  789.         if(rc=OpenBusyWindow())
  790.             cleanup("Error Open Busy Window");
  791.     }
  792.  
  793.     if(conf.counting && (flag || !(addr&0xFF)))
  794.     {
  795.         stoh((u_short)addr,&IT_counting.IText[2]);
  796.         PrintIText( BusyWnd->RPort, &IT_counting, 0,0 );
  797.     }
  798.  
  799.         /* check if 'abort' is pushed (through IDCMP_Class GadgetUp*/
  800.     while( m = GT_GetIMsg( BusyWnd->UserPort )) 
  801.     {
  802.         CopyMem(( char * )m, ( char * )&BusyMsg, (long)sizeof( struct IntuiMessage ));
  803.  
  804.         GT_ReplyIMsg( m );
  805.  
  806.         switch ( BusyMsg.Class ) 
  807.         {
  808.  
  809.             case    IDCMP_REFRESHWINDOW:
  810.                 GT_BeginRefresh( BusyWnd );
  811.                 BusyRender();
  812.                 GT_EndRefresh( BusyWnd, TRUE );
  813.                 break;
  814.  
  815.             case    IDCMP_GADGETUP:
  816.                 func = (int (*)(void)) (( struct Gadget * )BusyMsg.IAddress )->UserData;
  817.                 func();
  818.                 break;
  819.         }
  820.     }
  821. }
  822.  
  823. /*
  824.  * Read the EPROM
  825.  */
  826. static void ReadEPROM(void)
  827. {
  828.     long addr,s_addr, len;
  829.     u_char *c;
  830.  
  831.     len    = LengthInt;
  832.     s_addr = EPROMLowInt;
  833.     addr   = EPROMLowInt + AdParam;
  834.     c      = PEmemBase+RAMLowInt;
  835.  
  836. #ifdef DEBUG_PROG
  837. printf("ReadEprom len:%x addr:%x c:%x 1000:%d\n",len,addr,c,1000);
  838. #endif
  839.  
  840.     while (len--) 
  841.     {
  842.         showaddr_checkabort(s_addr++,FALSE);
  843.         SetAddr(addr++);
  844.         *c++ = ReadByte();
  845.         if(abort_flag)
  846.         {
  847.             CloseBusyWindow();
  848.             abort_flag = FALSE;
  849.             return;
  850.         }
  851.     }
  852.     CloseBusyWindow();
  853.     if(conf.inforeq)
  854.         simplerequest("We read %ld bytes", LengthInt);
  855. }
  856.  
  857. /*
  858.  * Compare the EPROM with the RAM buffer
  859.  */
  860. static void CompareEPROM(void)
  861. {
  862.     long addr,s_addr, len;
  863.     u_char *c, ce, cr;
  864.     int        flag_failed=FALSE;
  865.  
  866.     len    = LengthInt;
  867.     s_addr = EPROMLowInt;
  868.     addr   = EPROMLowInt + AdParam;
  869.     c = PEmemBase+(RAMLowInt);
  870.     while (len--) {
  871.         showaddr_checkabort(s_addr++,FALSE);
  872.         SetAddr(addr++);
  873.         if ((cr = *c++) != (ce = ReadByte()))
  874.         {
  875.             flag_failed = TRUE;
  876.             if (!twogadrequest("CONTINUE|CANCEL","Offset %ld, EPROM:%02lx   RAM:%02lx",
  877.                 addr - EPROMLowInt - 1, ce, cr) ) 
  878.               abort_flag = TRUE;
  879.         }
  880.         if(abort_flag)
  881.         {
  882.             CloseBusyWindow();
  883.             abort_flag = FALSE;
  884.             return;
  885.         }
  886.     }
  887.     CloseBusyWindow();
  888.     if(flag_failed)
  889.         simplerequest("Compare failed");
  890.     else
  891.         simplerequest("Compare successfull");
  892. }
  893.  
  894. /*
  895.  * Make sure EPROM is empty
  896.  */
  897. static void CheckEPROM(void)
  898. {
  899.     long addr,s_addr,end;
  900.  
  901.     s_addr = EPROMLowInt;
  902.     addr   = EPROMLowInt + AdParam;
  903.     end    = addr + LengthInt;
  904.     
  905.     for (; addr < end;) {
  906.         showaddr_checkabort(s_addr++,FALSE);
  907.         SetAddr((u_short)(addr++));
  908.         if (ReadByte() != 0xff) 
  909.         {
  910.             simplerequest("EPROM contains data at %ld!", s_addr - 1);
  911.             abort_flag = TRUE;
  912.         }
  913.  
  914.         if(abort_flag)
  915.         {
  916.             CloseBusyWindow();
  917.             abort_flag = FALSE;
  918.             return;
  919.         }
  920.     }
  921.     CloseBusyWindow();
  922.     simplerequest("EPROM is empty");
  923. }
  924.  
  925. /*
  926.  * Program the EPROM
  927.  */
  928. static void ProgramEPROM(void)
  929. {
  930. long addr,s_addr, len;
  931. u_char *c;
  932.  
  933. #ifdef DEBUG_PROG
  934.     puts("ProgramEPROM");
  935. #endif
  936.  
  937.     len = LengthInt;
  938.     s_addr = EPROMLowInt;
  939.     addr = EPROMLowInt+AdParam;
  940.     
  941.     c = PEmemBase+RAMLowInt;
  942.  
  943.     abort_flag = FALSE;
  944.  
  945.     while (len-- && !abort_flag) 
  946.     {
  947.         showaddr_checkabort(s_addr++,FALSE);
  948.         SetAddr(addr++);
  949.  
  950.         switch (WriteCycle(*c++)) 
  951.         {
  952.             case 2:
  953.                 simplerequest("Verify error at EPROM address %ld", s_addr - 1);
  954.                 abort_flag = TRUE;
  955.                 break;
  956.  
  957.             case 1:
  958.                 simplerequest("EPROM already has data at address %ld", s_addr - 1);
  959.                 abort_flag = TRUE;
  960.                 break;
  961.         }
  962.     }
  963.  
  964.     CloseBusyWindow();
  965.     abort_flag = FALSE;
  966.  
  967.     if(conf.inforeq)
  968.         simplerequest("We programmed %ld bytes", LengthInt);
  969. }
  970.  
  971. static void getstringgads(void)
  972. {
  973.     char *dummy;
  974.     int base;
  975.  
  976. #ifdef DEBUG_PROG
  977. puts("getstringgads");
  978. #endif
  979.     switch(conf.numericalbase)
  980.     {
  981.         case CY_DEC:    base=10;
  982.                         break;
  983.         case CY_DECHEX:    base=0;
  984.                         break;
  985.         case CY_HEX:    base=16;
  986.                         break;
  987.         default:        simplerequest("Error numerical Base, Type:%d. File:%s Line:%d",conf.numericalbase,__FILE__,__LINE__);
  988.     }
  989.  
  990.     RAMValInt   = (u_char)strtol(((struct StringInfo *)EprommerGadgets[GD_RamVal]->SpecialInfo)->Buffer,&dummy,base);
  991.     RAMLowInt   = strtol(((struct StringInfo *)EprommerGadgets[GD_RamAddress]->SpecialInfo)->Buffer,&dummy,base);
  992.     EPROMLowInt = strtol(((struct StringInfo *)EprommerGadgets[GD_EpromAddress]->SpecialInfo)->Buffer,&dummy,base);
  993.     LengthInt   = strtol(((struct StringInfo *)EprommerGadgets[GD_Length]->SpecialInfo)->Buffer,&dummy,base);
  994. }
  995.  
  996. static void dividepath(char *path,char *dir,char *file)
  997. {
  998.     /* divide 'path' in Name of Directory and Name of File */
  999.     
  1000.     char *pfile;
  1001.  
  1002.     if(!(pfile=strrchr(path,'/')))
  1003.     {
  1004.         if(!(pfile=strrchr(path,':')))
  1005.         {
  1006.             strcpy(file,path);
  1007.             *dir='\0';
  1008.             return;
  1009.         }
  1010.     }
  1011.     strncpy(dir,path,pfile-path+1);
  1012.     dir[pfile-path+1]='\0';
  1013.     strcpy(file,pfile+1);
  1014. }
  1015.  
  1016. static void setepromtype(int eptype)
  1017. {
  1018.     /* set EPROM parameters */
  1019.     EPType       = eptype;
  1020.     Size         = size_tbl[EPType];
  1021.     VoltVal      = volt_tbl[EPType];
  1022.     ReadParam    = rp_tbl[EPType];
  1023.     WriteParam   = wp_tbl[EPType];
  1024.     InhibitParam = ip_tbl[EPType];
  1025.     AdParam      = ad_tbl[EPType];
  1026.     *CtrlPort    = LeaveParam = lp_tbl[EPType];
  1027.     SetCycleParams();
  1028.     WriteAlg     = wa_tbl2[ag_tbl[EPType]];
  1029.  
  1030.     /* set dafault Program Algorythm for this Eprom */
  1031.     GT_SetGadgetAttrs(EprommerGadgets[GD_ProgAlgo],EprommerWnd,NULL,GTMX_Active,ag_tbl[EPType],TAG_DONE);
  1032.  
  1033.         /* check if 'Eprom Default Size' is set */
  1034.     if(conf.defepsize)
  1035.     {
  1036.         /* yes, set default size */
  1037.         LengthInt = size_tbl[EPType];
  1038.         updatevalgad(GD_Length,LengthInt);
  1039.     }
  1040. }
  1041.  
  1042. static void optionsvalid(void)
  1043. {
  1044.     /* Copy new configuration to old one.
  1045.      * Update the String Gadgets.
  1046.      * Erase the Vpp if they set.
  1047.      */
  1048.  
  1049.     int change;
  1050.  
  1051.     /* numericale Base changed ? */
  1052.     change = (conf.numericalbase==newconf.numericalbase)?FALSE:TRUE;
  1053.  
  1054.     conf = newconf; /* copy complete structure */
  1055.  
  1056.         /* Take latest used Directories */
  1057.     strcpy(conf.loaddir,LDir);
  1058.     strcpy(conf.savedir,SDir);
  1059.  
  1060.     if(change)  /* perhaps the base has been changed (Decimal or Hexadecimal) */
  1061.         updateallvalgad();
  1062.  
  1063.     waitcnt = conf.waitcnt;
  1064. }
  1065.  
  1066. int DataFormatClicked( void )
  1067. {
  1068.     /* routine when gadget "Data Format" is clicked. */
  1069.     
  1070.     conf.dataformat = EprommerMsg.Code;
  1071.     return(TRUE);
  1072. }
  1073.  
  1074. int ProgAlgoClicked( void )
  1075. {
  1076.     /* routine when gadget "" is clicked. */
  1077.  
  1078.     WriteAlg = wa_tbl2[EprommerMsg.Code];
  1079.     return(TRUE);
  1080. }
  1081.  
  1082. int RamAddressClicked( void )
  1083. {
  1084.     /* routine when gadget "Buffer" is clicked. */
  1085.     getstringgads();
  1086.     updatevalgad(GD_RamAddress,RAMLowInt);
  1087.     return(TRUE);
  1088. }
  1089.  
  1090. int EpromAddressClicked( void )
  1091. {
  1092.     /* routine when gadget "Eprom" is clicked. */
  1093.     int max;
  1094.  
  1095.     getstringgads();
  1096.  
  1097.     EPROMLowInt=MIN(EPROMLowInt,size_tbl[EPType]);  /* Adjust Length */
  1098.     max=size_tbl[EPType]-EPROMLowInt;
  1099.     LengthInt=MIN(max,size_tbl[EPType]);  /* Adjust Length */
  1100.  
  1101.     updatevalgad(GD_EpromAddress,EPROMLowInt);
  1102.     updatevalgad(GD_Length,LengthInt);
  1103.     return(TRUE);
  1104. }
  1105.  
  1106. int LengthClicked( void )
  1107. {
  1108.     /* routine when gadget "Length" is clicked. */
  1109.     int max;
  1110.  
  1111.     getstringgads();
  1112.  
  1113.     max=size_tbl[EPType]-EPROMLowInt;
  1114.     LengthInt=MIN(max,size_tbl[EPType]);  /* Adjust Length */
  1115.  
  1116.     updatevalgad(GD_Length,LengthInt);
  1117.     return(TRUE);
  1118. }
  1119.  
  1120. int EpromTypeClicked( void )
  1121. {
  1122.     if(conf.inforeq)
  1123.         simplerequest("Check for correct Personality Module");
  1124.     setepromtype(EprommerMsg.Code);
  1125.     conf.epromtype = (int)EPType;
  1126.     return(TRUE);
  1127. }
  1128.  
  1129. int RamValClicked( void )
  1130. {
  1131.     /* routine when gadget "RAM Value" is clicked. */
  1132.  
  1133.     getstringgads();
  1134.     updatevalgad(GD_RamVal,(int)RAMValInt);
  1135.     return(TRUE);
  1136. }
  1137.  
  1138. int ReadByteClicked( void )
  1139. {
  1140.     /* routine when gadget "Read Byte" is clicked. */
  1141.     getstringgads();
  1142.     RAMValInt = (u_char)(*(PEmemBase+RAMLowInt));
  1143.     updatevalgad(GD_RamVal,(int)RAMValInt);
  1144.     return(TRUE);
  1145. }
  1146.  
  1147. int WriteByteClicked( void )
  1148. {
  1149.     /* routine when gadget "Write Byte" is clicked. */
  1150.     getstringgads();
  1151.     *(PEmemBase+RAMLowInt) = RAMValInt;
  1152.     updatevalgad(GD_RamVal,(int)RAMValInt);
  1153.     return(TRUE);
  1154. }
  1155.  
  1156. int ReadEpromClicked( void )
  1157. {
  1158.     /* routine when gadget "Read" is clicked. */
  1159. #ifdef DEBUG_PROG
  1160.     puts("ReadEpromClicked");
  1161. #endif
  1162.     lockwindow  (EprommerWnd,TRUE);
  1163.     getstringgads();
  1164.     ReadEPROM();
  1165.     lockwindow(EprommerWnd,FALSE);
  1166.     return(TRUE);
  1167. }
  1168.  
  1169. int BlankTestClicked( void )
  1170. {
  1171.     /* routine when gadget "Check" is clicked. */
  1172.     lockwindow(EprommerWnd,TRUE);
  1173.     getstringgads();
  1174.     CheckEPROM();
  1175.     lockwindow(EprommerWnd,FALSE);
  1176.     return(TRUE);
  1177. }
  1178.  
  1179. int CompareEpromClicked( void )
  1180. {
  1181.     /* routine when gadget "Compare" is clicked. */
  1182.     lockwindow(EprommerWnd,TRUE);
  1183.     getstringgads();
  1184.     CompareEPROM();
  1185.     lockwindow(EprommerWnd,FALSE);
  1186.     return(TRUE);
  1187. }
  1188.  
  1189. int ProgramEpromClicked( void )
  1190. {
  1191. #ifdef DEBUG_PROG
  1192.     puts("ProgramEpromClicked");
  1193. #endif
  1194.  
  1195.     /* routine when gadget "Program" is clicked. */
  1196.     lockwindow(EprommerWnd,TRUE);
  1197.     getstringgads();
  1198.     ProgramEPROM();
  1199.     lockwindow(EprommerWnd,FALSE);
  1200.     return(TRUE);
  1201. }
  1202.  
  1203. int LoadFileReqClicked( void )
  1204. {
  1205.     char *pos;
  1206.     struct StringInfo *pstrinfo;
  1207.     int len;
  1208.  
  1209.     if(!LFullPath[0] && SFullPath[0])
  1210.     {
  1211.         /* no entry -> fill with 'savepath' */
  1212.  
  1213.         strcpy(LFullPath,SFullPath);
  1214.         strcpy(LFile,SFile);
  1215.         strcpy(LDir,SDir);
  1216.     }
  1217.  
  1218.     pos= (conf.dataformat==INTELHEX)?"Load IntelHex":"Load Binary";
  1219.  
  1220.     if(AslRequestTags(aslreq,ASL_Hail, pos,ASL_Window,EprommerWnd,ASL_File,LFile,
  1221.                       ASL_Dir,LDir,ASL_Height,(ULONG)EprommerWnd->Height,TAG_DONE))
  1222.     {
  1223.         strcpy(LFile,((struct FileRequester *)aslreq)->rf_File);
  1224.         strcpy(LDir,((struct FileRequester *)aslreq)->rf_Dir);
  1225.         strcpy(LFullPath,LDir);
  1226.         if(len=strlen(LFullPath))
  1227.         {
  1228.             if((LFullPath[len-1]!=':')&&(LFullPath[len-1]!='/'))
  1229.                 strcat(LFullPath,"/");
  1230.         }
  1231.         strcat(LFullPath,LFile);
  1232.  
  1233.         /* fill LoadFile StringGadget */
  1234.         pstrinfo = (struct StringInfo *)(EprommerGadgets[GD_LoadFile]->SpecialInfo);
  1235.         pos = pstrinfo->Buffer;
  1236.         strcpy(pos,LFullPath);
  1237.         pstrinfo->NumChars = strlen(pos);
  1238.         pstrinfo->BufferPos = 0;
  1239.         RefreshGList(EprommerGadgets[GD_LoadFile], EprommerWnd, NULL, 1);
  1240.         getstringgads();
  1241.         LoadFile();
  1242.     }
  1243.     return(TRUE);
  1244. }
  1245.  
  1246. int LoadBtClicked( void )
  1247. {
  1248.     /* routine when gadget "LOAD" is clicked. */
  1249.     getstringgads();
  1250.     if(!LFullPath[0])
  1251.         LoadFileReqClicked();
  1252.     else
  1253.         LoadFile();
  1254.  
  1255.     return(TRUE);
  1256. }
  1257.  
  1258. int SaveBtClicked( void )
  1259. {
  1260.     /* routine when gadget "SAVE" is clicked. */
  1261.  
  1262.     getstringgads();
  1263.     if(!SFullPath[0])
  1264.         SaveFileReqClicked();
  1265.     else
  1266.         SaveFile();
  1267.  
  1268.     return(TRUE);
  1269. }
  1270.  
  1271. int SaveFileReqClicked( void )
  1272. {
  1273.     /* routine when gadget "" is clicked. */
  1274.     char *pos;
  1275.     struct StringInfo *pstrinfo;
  1276.     int len;
  1277.  
  1278.     if(!SFullPath[0] && LFullPath[0])
  1279.     {
  1280.         /* no entry -> fill with 'loadpath' */
  1281.  
  1282.         strcpy(SFullPath,LFullPath);
  1283.         strcpy(SFile,LFile);
  1284.         strcpy(SDir,LDir);
  1285.     }
  1286.  
  1287.     pos= (conf.dataformat==INTELHEX)?"Save IntelHex":"Save Binary";
  1288.  
  1289.     if(AslRequestTags(aslreq,ASL_Hail, pos,ASL_Window,EprommerWnd,ASL_File,SFile,
  1290.                       ASL_Dir,SDir,ASL_Height,(ULONG)EprommerWnd->Height,TAG_DONE))
  1291.     {
  1292.         strcpy(SFile,((struct FileRequester *)aslreq)->rf_File);
  1293.         strcpy(SDir,((struct FileRequester *)aslreq)->rf_Dir);
  1294.         strcpy(SFullPath,SDir);
  1295.         if(len=strlen(SFullPath))
  1296.         {
  1297.             if((SFullPath[len-1]!=':')&&(SFullPath[len-1]!='/'))
  1298.                 strcat(SFullPath,"/");
  1299.         }
  1300.         strcat(SFullPath,SFile);
  1301.     
  1302.         /* fill SaveFile StringGadget */
  1303.         pstrinfo = (struct StringInfo *)(EprommerGadgets[GD_SaveFile]->SpecialInfo);
  1304.         pos = pstrinfo->Buffer;
  1305.         strcpy(pos,SFullPath);
  1306.         pstrinfo->NumChars = strlen(pos);
  1307.         pstrinfo->BufferPos = 0;
  1308.         RefreshGList(EprommerGadgets[GD_SaveFile], EprommerWnd, NULL, 1);
  1309.         getstringgads();
  1310.         SaveFile();
  1311.     }
  1312.  
  1313.     return(TRUE);
  1314. }
  1315.  
  1316. int LoadFileClicked( void )
  1317. {
  1318.     /* routine when gadget "Load" is clicked. */
  1319.  
  1320.     struct StringInfo *pstrinfo;
  1321.     char *pos;
  1322.  
  1323.     pstrinfo = (struct StringInfo *)(EprommerGadgets[GD_LoadFile]->SpecialInfo);
  1324.     pos = pstrinfo->Buffer;
  1325.  
  1326.         /* check if StringGadget isn't empty */
  1327.     if(strlen(pos))
  1328.     {
  1329.         strcpy(LFullPath,pos);
  1330.         dividepath(LFullPath,LDir,LFile);
  1331.         getstringgads();
  1332.         LoadFile();
  1333.     }
  1334.     return(TRUE);
  1335. }
  1336.  
  1337. int SaveFileClicked( void )
  1338. {
  1339.     /* routine when gadget "Save" is clicked. */
  1340.     struct StringInfo *pstrinfo;
  1341.     char *pos;
  1342.  
  1343.     pstrinfo = (struct StringInfo *)(EprommerGadgets[GD_SaveFile]->SpecialInfo);
  1344.     pos = pstrinfo->Buffer;
  1345.     
  1346.         /* check if StringGadget isn't empty */
  1347.     if(strlen(pos))
  1348.     {
  1349.         strcpy(SFullPath,pos);
  1350.         dividepath(SFullPath,SDir,SFile);
  1351.         getstringgads();
  1352.         SaveFile();
  1353.     }
  1354.     return(TRUE);
  1355. }
  1356.  
  1357. int EprommerCloseWindow( void )
  1358. {
  1359.     /* routine for "IDCMP_CLOSEWINDOW". */
  1360.     simplerequest("Please remove the EPROM now");
  1361.     return(FALSE);
  1362. }
  1363.  
  1364. int DoOptionsClicked( void )
  1365. {
  1366.     /* routine when gadget "Options" is clicked. */
  1367.  
  1368.     /* - Lock 'EprommerWindow' 
  1369.      * - Mark/Unmark CheckBox Gadgets :
  1370.      *  - GD_NumericalBase
  1371.      *    - GD_SetClearBuffer
  1372.      *    - GD_SetBufferFrag
  1373.      */
  1374.  
  1375.  
  1376.     int rc;
  1377.     
  1378.     /* Lock the Eprommer Window */
  1379.  
  1380.     lockwindow(EprommerWnd,TRUE);
  1381.  
  1382.     if(rc=OpenOptionsWindow())
  1383.         cleanup("Error Open Options Window");
  1384.  
  1385.     newconf = conf;        /* copy complete structure */
  1386.  
  1387.     GT_SetGadgetAttrs(OptionsGadgets[GD_NumericalBase],OptionsWnd,NULL,GTCY_Active,conf.numericalbase,TAG_DONE);
  1388.     GT_SetGadgetAttrs(OptionsGadgets[GD_SetBufferFrag],OptionsWnd,NULL,GTCB_Checked,conf.bufferfragmented,TAG_DONE);
  1389.     GT_SetGadgetAttrs(OptionsGadgets[GD_SetClearBuffer],OptionsWnd,NULL,GTCB_Checked,conf.clearbuffer,TAG_DONE);
  1390.     GT_SetGadgetAttrs(OptionsGadgets[GD_SetInfoReq],OptionsWnd,NULL,GTCB_Checked,conf.inforeq,TAG_DONE);
  1391.     GT_SetGadgetAttrs(OptionsGadgets[GD_count],OptionsWnd,NULL,GTCB_Checked,conf.counting,TAG_DONE);
  1392.     GT_SetGadgetAttrs(OptionsGadgets[GD_setepsize],OptionsWnd,NULL,GTCB_Checked,conf.defepsize,TAG_DONE);
  1393.     GT_SetGadgetAttrs(OptionsGadgets[GD_CIADelay],OptionsWnd,NULL,GTIN_Number,conf.waitcnt,TAG_DONE);
  1394.  
  1395.     rc=TRUE;
  1396.     while( rc ) 
  1397.     {
  1398.         WaitPort( OptionsWnd->UserPort );
  1399.         rc=HandleOptionsIDCMP();
  1400.     }
  1401.  
  1402.     CloseOptionsWindow();
  1403.     lockwindow(EprommerWnd,FALSE);
  1404.  
  1405.     return(TRUE);
  1406. }
  1407.  
  1408. int NumericalBaseClicked( void )
  1409. {
  1410.     /* routine when gadget "Input String Gadget" is clicked. */
  1411.  
  1412.     newconf.numericalbase=OptionsMsg.Code;
  1413.     return(TRUE);
  1414. }
  1415.  
  1416. int SetClearBufferClicked( void )
  1417. {
  1418.     /* routine when gadget "Clear Buffer (0xFF)" is clicked. */
  1419.     newconf.clearbuffer=OptionsGadgets[GD_SetClearBuffer]->Flags&SELECTED;
  1420.     return(TRUE);
  1421. }
  1422.  
  1423.  
  1424. int SetBufferFragClicked( void )
  1425. {
  1426.     /* routine when gadget "Buffer fragmented" is clicked. */
  1427.     newconf.bufferfragmented=OptionsGadgets[GD_SetBufferFrag]->Flags&SELECTED;
  1428.     return(TRUE);
  1429. }
  1430.  
  1431. int SavePrefsClicked( void )
  1432. {
  1433.     /* routine when gadget "SAVE" is clicked. */
  1434.  
  1435.     FILE *fpconfig=NULL;
  1436.  
  1437.     optionsvalid();
  1438.  
  1439.     if( (!(fpconfig=fopen(CONFIG_ENVARC,"w"))) ||
  1440.         (fwrite(&conf,sizeof(struct Config),1,fpconfig) != 1))
  1441.         simplerequest("Error. Can't write Settings to '%s'",CONFIG_ENVARC);
  1442.  
  1443.     if(fpconfig)
  1444.         fclose(fpconfig);
  1445.  
  1446.     return(TRUE);
  1447. }
  1448.  
  1449. int SetInfoReqClicked( void )
  1450. {
  1451.     /* routine when gadget "Info Requester" is clicked. */
  1452.  
  1453.     newconf.inforeq = OptionsGadgets[GD_SetInfoReq]->Flags&SELECTED;
  1454.  
  1455.     return(TRUE);
  1456. }
  1457.  
  1458. int countClicked( void )
  1459. {
  1460.     /* routine when gadget "Counting" is clicked. */
  1461.  
  1462.     newconf.counting = OptionsGadgets[GD_count]->Flags&SELECTED;
  1463.  
  1464.     return(TRUE);
  1465. }
  1466.  
  1467. int setepsizeClicked( void )
  1468. {
  1469.     /* routine when gadget "EProm default size" is clicked. */
  1470.  
  1471.     newconf.defepsize = OptionsGadgets[GD_setepsize]->Flags&SELECTED;
  1472.     return(TRUE);
  1473.  
  1474. }
  1475.  
  1476. int CIADelayClicked( void )
  1477. {
  1478.     /* routine when gadget "CIA Delay" is clicked. */
  1479.  
  1480.     newconf.waitcnt = ((struct StringInfo *)(OptionsGadgets[GD_CIADelay]->SpecialInfo))->LongInt;
  1481.     return(TRUE);
  1482. }
  1483.  
  1484. int OptionsOkClicked( void )
  1485. {
  1486.     /* routine when gadget "OK" is clicked. */
  1487.     optionsvalid();
  1488.     return(FALSE);
  1489. }
  1490.  
  1491. int OptionsCancelClicked( void )
  1492. {
  1493.     /* routine when gadget "CANCEL" is clicked. */
  1494.  
  1495.     return(FALSE);    
  1496. }
  1497.  
  1498. int OptionsCloseWindow( void )
  1499. {
  1500.     /* routine for "IDCMP_CLOSEWINDOW". */
  1501.  
  1502.     return(OptionsCancelClicked());
  1503. }
  1504.  
  1505. /***************** Routines to check Hardware ************************/
  1506.  
  1507. int TestHardwareClicked( void )
  1508. {
  1509.     /* routine when gadget "Test" is clicked. */
  1510.     int rc;
  1511.     char title[64];
  1512.  
  1513.        lockwindow  (EprommerWnd,TRUE);
  1514.     epromout = FALSE;    /* Safer to think there is an Eprom plugged in */
  1515.  
  1516.     if(rc=OpenTestWindow())
  1517.         cleanup("Error Open Test Window");
  1518.  
  1519.     SetAddr((TestMsg.Code==0)?0x5555:0xAAAA);     /* Switch Eprom Address */
  1520.  
  1521.     sprintf(title,"%s",TestWnd->Title);
  1522.  
  1523.     SetWindowTitles(TestWnd,title,NULL);
  1524.  
  1525.     rc = TRUE;
  1526.     while( rc ) 
  1527.     {
  1528.         WaitPort( TestWnd->UserPort );
  1529.         rc=HandleTestIDCMP();
  1530.     }
  1531.  
  1532.     testvppoff();
  1533.     testvpp=VOLTS12;
  1534.     CloseTestWindow();
  1535.     lockwindow  (EprommerWnd,FALSE);
  1536.     epromout = FALSE;    /* Safer to think there is an Eprom plugged in */
  1537.  
  1538.     return(TRUE);
  1539. }
  1540.  
  1541. int NoEpromClicked( void )
  1542. {
  1543.     /* routine when gadget "Eprom removed" is clicked. */
  1544.     GT_SetGadgetAttrs(TestGadgets[GD_SetVpp],TestWnd,NULL,GA_Disabled,epromout,TAG_DONE);
  1545.     epromout=TestGadgets[GD_NoEprom]->Flags&SELECTED;
  1546.  
  1547.     testvppoff();
  1548.  
  1549.     if(epromout)
  1550.         testvppon(testvpp);
  1551.  
  1552.     return(TRUE);
  1553. }
  1554.  
  1555. int SetVppClicked( void )
  1556. {
  1557.     /* routine when gadget "" is clicked. */
  1558.     switch(TestMsg.Code)
  1559.     {
  1560.         case CY_VPP12:    testvppoff();
  1561.                         testvppon(VOLTS12);
  1562.                         testvpp=VOLTS12;
  1563.                         break;
  1564.         case CY_VPP21:    testvppoff();
  1565.                         testvppon(VOLTS21);
  1566.                         testvpp=VOLTS21;
  1567.                         break;
  1568.         case CY_VPP25:    testvppoff();
  1569.                         testvppon(VOLTS25);
  1570.                         testvpp=VOLTS25;
  1571.                         break;
  1572.         default:        simplerequest("Error  VPP Cycle Gadget. File:%s Line:%d",__FILE__,__LINE__);
  1573.     }
  1574.     return(TRUE);
  1575. }
  1576.  
  1577. int T_CyAddressClicked( void )
  1578. {
  1579.     /* routine when gadget "Address" is clicked. */
  1580.  
  1581.     SetAddr((TestMsg.Code==0)?0x5555:0xAAAA);     /* Switch Eprom Address */
  1582.     return(TRUE);
  1583. }
  1584.  
  1585. int T_CyDataClicked( void )
  1586. {
  1587.     /* routine when gadget "Data" is clicked. */
  1588.     *ParPort = (TestMsg.Code==0)?0x55:0xAA;
  1589.     return(TRUE);
  1590. }
  1591.  
  1592. int TestCloseWindow( void )
  1593. {
  1594.     /* routine for "IDCMP_CLOSEWINDOW". */
  1595.     return(FALSE);
  1596. }
  1597.  
  1598. /*
  1599.  * free every resource we might have allocated
  1600.  */
  1601. static void cleanup(char *s)
  1602. {
  1603.     ThatsIt();
  1604.     if (window_locked) lockwindow(window_locked,FALSE);
  1605.     if (s) puts(s);
  1606.     if (pp_flag) FreeMiscResource(MR_PARALLELPORT);
  1607.     if (ppb_flag) FreeMiscResource(MR_PARALLELBITS);
  1608.     if (tp) CloseTimer(tr);
  1609.     CloseEprommerWindow();
  1610.     CloseOptionsWindow();
  1611.     CloseBusyWindow();
  1612.     CloseTestWindow();
  1613.     CloseDownScreen();
  1614. #ifndef _DCC
  1615.     if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  1616.     if (GfxBase) CloseLibrary((struct Library *)GfxBase);
  1617. #endif
  1618.     if (aslreq)  FreeAslRequest(aslreq);
  1619.     if (PEmemBase) FreeMem(PEmemBase,MAXDATABUFFER);
  1620.     if (plockreq)  FreeMem(plockreq,sizeof(struct Requester));
  1621.  
  1622.     if(s)
  1623.         exit(RETURN_ERROR);
  1624.     else
  1625.         exit(RETURN_OK);
  1626. }
  1627.  
  1628. static void handlesigint(int sig)
  1629. {
  1630.     cleanup("Ctrl-C detected");
  1631.  
  1632.     return;
  1633. }
  1634.  
  1635. int wbmain(void)
  1636. {
  1637.     int rc;
  1638.  
  1639.     rc=main(0,NULL);
  1640.     return(rc);
  1641. }
  1642.  
  1643. int main(int argc, char **argv)
  1644. {
  1645.     int rc,def_flag;
  1646.     FILE *fpconfig=NULL;
  1647.     char *owner;
  1648.     char title[64],*pos;
  1649.  
  1650.     signal(SIGINT,handlesigint);
  1651. /*
  1652.  * Open all libraries, as well as the program's window
  1653.  */
  1654.  
  1655. #ifndef _DCC
  1656.     if (!(IntuitionBase = (struct IntuitionBase *)
  1657.         OpenLibrary("intuition.library", 33L)))
  1658.             cleanup("No intuition.library!\n");
  1659.  
  1660.     if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 33L)))
  1661.         cleanup("No graphics.library!\n");
  1662. #endif
  1663.  
  1664.     if(rc=SetupScreen())
  1665.         cleanup("Error Setting Screen");
  1666.  
  1667.     if(rc=OpenEprommerWindow())
  1668.         cleanup("Error Open Eprommer Window");
  1669.  
  1670.     strcpy(title,&vers[7]);
  1671.     strcat(title," © Bob,Udi,Carsten");
  1672.     SetWindowTitles(EprommerWnd,title,(char *)-1);
  1673.  
  1674.     if(!(PEmemBase = AllocMem(MAXDATABUFFER,MEMF_ANY+MEMF_CLEAR)))
  1675.         cleanup("No Memory!\n");
  1676.  
  1677. #ifdef DEBUG_PROG
  1678.     printf("RAM:%lx\n",PEmemBase);
  1679. #endif
  1680.  
  1681.     /* Initialization for FileRequester */
  1682.     if(!(aslreq=AllocAslRequestTags(ASL_FileRequest,ASL_Hail,"FileRequester",TAG_DONE)))
  1683.         cleanup("Allocate ASL Requester failed");
  1684.  
  1685.     /* Initialization for Lock Requester */
  1686.     if(!(plockreq=AllocMem(sizeof(struct Requester),MEMF_ANY+MEMF_CLEAR)))
  1687.     {
  1688.         cleanup("Can't alocate memory for 'Lock Requester'");
  1689.         return;
  1690.     }
  1691.     plockreq->LeftEdge=-1;
  1692.     plockreq->TopEdge=-1;
  1693.     plockreq->Width=0;
  1694.     plockreq->Height=0;
  1695.  
  1696.  
  1697.     /* Initialization for timer */
  1698.     if (OpenTimer()) 
  1699.         cleanup("No timer!");
  1700.  
  1701.     /* Clear Load,Save Paths */
  1702.     SFullPath[0] = LFullPath[0] = '\0';
  1703.  
  1704.     /* Load/Set default Configuration */
  1705.     def_flag = TRUE;
  1706.     if(fpconfig=fopen(CONFIG_ENV,"r"))
  1707.     {
  1708.         if(fread(&conf,sizeof(struct Config),1,fpconfig) != 1)
  1709.         {
  1710.             simplerequest("Error reading '%s'",CONFIG_ENV);
  1711.             perror(CONFIG_ENV);
  1712.         }
  1713.         else
  1714.         {
  1715.             /* Take latest used Directories */
  1716.             strcpy(LDir,conf.loaddir);
  1717.             pos = ((struct StringInfo *)(EprommerGadgets[GD_LoadFile]->SpecialInfo))->Buffer;
  1718.             strcpy(pos,LDir);
  1719.  
  1720.             strcpy(SDir,conf.savedir);
  1721.             pos = ((struct StringInfo *)(EprommerGadgets[GD_SaveFile]->SpecialInfo))->Buffer;
  1722.             strcpy(pos,SDir);
  1723.  
  1724.             RefreshGList(EprommerGadgets[GD_LoadFile], EprommerWnd, NULL, 1);
  1725.             RefreshGList(EprommerGadgets[GD_SaveFile], EprommerWnd, NULL, 1);
  1726.         
  1727.             waitcnt = conf.waitcnt;
  1728.  
  1729.             def_flag=FALSE;
  1730.         }
  1731.         fclose(fpconfig);
  1732.         fpconfig=NULL;
  1733.     }
  1734.  
  1735.         /* determine CIA delay. Is there any commandline Option ? */
  1736.     if(argc>=2)
  1737.         waitcnt=MAX(1,atoi(argv[1]));
  1738.     else
  1739.     {
  1740.         if(def_flag)
  1741.             checkspeed(); /* No, so calculate the CIA-delay */
  1742.     }
  1743.  
  1744.     /* Defaults, if reading Prefs-File failed */
  1745.     if(def_flag)
  1746.     {
  1747.         conf.epromtype = EP_2716;            /* 2716 */
  1748.         conf.dataformat = BINARY;            /* set DataFormat to BINARY */
  1749.         conf.bufferfragmented = FALSE;        /* Buffer Fragmentation allowed */
  1750.         conf.clearbuffer = FALSE;            /* clear buffer first before load */
  1751.         conf.numericalbase = CY_DECHEX;        /* Set Default Input to Decimal and Hexadecimal */    
  1752.         conf.inforeq = TRUE;                /* Requester appears for default */
  1753.         conf.counting = TRUE;                /* Show address counting for default */
  1754.         conf.defepsize = TRUE;                /* Set default Eprom Size */
  1755.         conf.loaddir[0] = '\0';                /* Delete Load directory */
  1756.         conf.savedir[0] = '\0';                /* Delete Save directory */
  1757.         conf.waitcnt    = waitcnt;            /* CIA Delay */
  1758.     }
  1759.  
  1760.     setepromtype(conf.epromtype);
  1761.  
  1762.       /* Initialize hardware */
  1763.     InitPorts();
  1764.  
  1765.     GT_SetGadgetAttrs(EprommerGadgets[GD_EpromType],EprommerWnd,NULL,GTMX_Active,EPType,TAG_DONE);
  1766.     GT_SetGadgetAttrs(EprommerGadgets[GD_DataFormat],EprommerWnd,NULL,GTCY_Active,conf.dataformat,TAG_DONE);
  1767.  
  1768.         /* Prepare Address counting (Busy/Abort Window) */
  1769.     IT_counting = BusyIText[1];  /* Copy original IntuiText structure */
  1770.         /* X,Y-Position depends on Font Size. */
  1771.         /* OffX,OffY,Font,FontX,FontY are calculated in gad_eprommer.c during SetupScreen() */
  1772.     IT_counting.ITextFont = Font;
  1773.     IT_counting.LeftEdge  = OffX + ((( FontX * IT_counting.LeftEdge ) + 4 ) / 8 ) - ( IntuiTextLength( &IT_counting ) >> 1 );
  1774.     IT_counting.TopEdge   = OffY + ((( FontY * IT_counting.TopEdge  ) + 4 ) / 8 ) - ( Font->ta_YSize >> 1 );
  1775.     
  1776.  
  1777.         /* At Program End: MiscBase don't have to be closed - there's no 'CloseResource()' */
  1778.     if (!(MiscBase = (struct Library *)OpenResource(MISCNAME)))
  1779.         cleanup("Can't open 'misc.resource' !\n");
  1780.  
  1781.     if(owner = AllocMiscResource(MR_PARALLELPORT,"Eprommer"))
  1782.     {    
  1783.         if(!(twogadrequest("OK|CANCEL","Parallel Port already allocated by:%s\nDo you want continue ?",owner)))
  1784.             cleanup("PAR: busy");
  1785.     }
  1786.     else
  1787.         pp_flag = TRUE;
  1788.  
  1789.     if(pp_flag)
  1790.     {    
  1791.         if(owner = AllocMiscResource(MR_PARALLELBITS,"Eprommer"))
  1792.         {        
  1793.             if(!(twogadrequest("OK|CANCEL","Parallel Port Bits already allocated by:%s\nDo you want continue ?",owner)))
  1794.                 cleanup("PAR: busy");
  1795.         }
  1796.         else
  1797.             ppb_flag = TRUE;
  1798.     }
  1799.     
  1800. /*
  1801.  * Event loop
  1802.  */
  1803.     rc = TRUE;
  1804.     while( rc ) 
  1805.     {
  1806.         WaitPort( EprommerWnd->UserPort );
  1807.         rc=HandleEprommerIDCMP();
  1808.     }
  1809.  
  1810.         /* Take latest used Directories */
  1811.     strcpy(conf.loaddir,LDir);
  1812.     strcpy(conf.savedir,SDir);
  1813.  
  1814.     if( (!(fpconfig=fopen("ENV:Eprommer.prefs","w"))) ||
  1815.         (fwrite(&conf,sizeof(struct Config),1,fpconfig) != 1))
  1816.         simplerequest("Error. Can't write Settings to 'ENV:Eprommer.prefs'");
  1817.     
  1818.     if(fpconfig)
  1819.         fclose(fpconfig);
  1820.  
  1821.     cleanup(NULL);
  1822.     
  1823.     return(0);
  1824. }
  1825.