home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 September / CHIP_CD_1997_09_PL.iso / software / news / wspecem / sources / sna_load.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-25  |  34.1 KB  |  1,394 lines

  1.  
  2. /* Sna_Load.c : Snapshot and data transfer disk logic -- loading part.
  3.  *
  4.  * Copyright 1996 Rui Fernando Ferreira Ribeiro.
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * History:
  23.  *      4th April 96:
  24.  *              . modified R register handling
  25.  *              . corrected runaway condition in getbyte() with
  26.  *              corrupted snapshots (would kill emulator)
  27.  *              . Added .SIT and .BLK handling logic
  28.  *
  29.  *      18th April 96:
  30.  *               . ED/FD load lever trap implemented
  31.  */
  32.  
  33. #include <windows.h>
  34. #include <commdlg.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <dir.h>
  39. #include "env.h"
  40. #include "snap.h"
  41.  
  42. // as defined in WSpecem.c
  43. // A handle that identifies the main window
  44. extern HWND      hwndApp;
  45.  
  46. /* local functions prototypes */
  47. static sna_load(HFILE hfp);
  48. static snx_load(HFILE hfp);
  49. static sp_load(HFILE  hfp);
  50. static z80_load(HFILE hfp);
  51. static slt_load(HFILE hfp);
  52. static sit_load(HFILE hfp);
  53. static raw_load(HFILE hfp);
  54. static zx_load(HFILE hfp);
  55. static prg_load(HFILE hfp);
  56. static ach_load(HFILE hfp);
  57. static rom_load(HFILE hfp);
  58. static dat_load(HFILE hfp);
  59. static tap_load(HFILE hfp);
  60. static scr_load(HFILE hfp);
  61. static load_slt_level(HFILE hfp);
  62. static load_options(HFILE hfp);
  63.  
  64. /* name of file currently in use */
  65. static char snapname[260];
  66.  
  67. // Name of tape file on use
  68. static char TapName[260];
  69. // Current file position of tapefile. We'll seek to this position when we
  70. // open it
  71. static long TapFilePos = 0;
  72.  
  73. // signal EOF
  74. static is_eof = 0;
  75.  
  76. /* address of SLT_info block:
  77.     if true, we're dealing with a SLT file.
  78.  */
  79. long SLT_info_block_ad = 0L;
  80. // It will be active when we are inside the level loader trap. The level
  81. // loader trap is also used to load tape blocks.
  82. static BOOLEAN inside_level_trap = 0;
  83.  
  84.  
  85. /* logic for local software-cache */
  86. #define BUFFER_SIZE 2048
  87.  
  88. // Current position of read buffer
  89. static short BufferPos = BUFFER_SIZE;
  90. // Bytes still to be read
  91. static short BytesRead = BUFFER_SIZE;
  92. // pointer to the actual buffer
  93. static PBYTE pbBuf = NULL;
  94.  
  95. // real file position, minus the bytes still in the buffer
  96. long file_pos = 0L;
  97.  
  98. // check for end-of-file
  99. static feof_file(void)
  100. {
  101.    return is_eof;
  102. }
  103.  
  104. // get another byte from buffer
  105. static UCHAR getbyte(HFILE hfp)
  106. {
  107.    UCHAR c;
  108.  
  109.    // if file is not still at end
  110.    if(!feof_file())
  111.    {
  112.       // are there any bytes on the buffer?
  113.       if(BufferPos == BytesRead)
  114.       {
  115.      // If not
  116.    
  117.      if(pbBuf == NULL) // buffer is allocated?
  118.      {
  119.             // if not, allocate
  120.         pbBuf = (PBYTE) LocalAlloc(LMEM_FIXED, BUFFER_SIZE);
  121.             // and lock it
  122.         LocalLock((HLOCAL)pbBuf);
  123.      }
  124.  
  125.          // read a block of BUFFER_SIZE bytes form actual file
  126.      if((BytesRead = _lread(hfp, pbBuf, BUFFER_SIZE))<1)
  127.      {
  128.             // if there's not a single byte, we reached EOF
  129.         is_eof = 1;
  130.      }
  131.      else
  132.      {
  133.             // else signal not EOF and BufferPos == 0
  134.         is_eof = 0;
  135.         BufferPos = 0;
  136.             // return 1 byte and increment Buffer positon
  137.         c = (UCHAR) (*(pbBuf+BufferPos++));
  138.         // and file position
  139.         file_pos++;
  140.      }
  141.       }
  142.       else
  143.       {
  144.      is_eof = 0;
  145.      c = (UCHAR) (*(pbBuf+BufferPos++));
  146.      file_pos++;
  147.       }
  148.       /* test for eof condition and signal it if present */
  149.       if(BufferPos == BytesRead)
  150.       {
  151.      if((BytesRead = _lread(hfp, pbBuf, BUFFER_SIZE))<1)
  152.      {
  153.         is_eof = 1;
  154.      }
  155.      else
  156.      {
  157.         is_eof = 0;
  158.         BufferPos = 0;
  159.      }
  160.       }
  161.    }
  162.    else
  163.       c = 0;
  164.    return c;
  165. }
  166.  
  167. // seek in the file, using buffer
  168. static void z_seek(HFILE hfp, long disp)
  169. {
  170.    while(disp--)
  171.       (void)getbyte(hfp);
  172. }
  173.  
  174. // close file
  175. static void z_close(HFILE hfp)
  176. {
  177.    if(pbBuf != NULL)
  178.    {
  179.       LocalUnlock((HLOCAL)pbBuf);
  180.       LocalFree((HLOCAL)pbBuf);
  181.       pbBuf = NULL;
  182.    }
  183.    /* BytesRead can't <= zero, or we'll never open a file again
  184.     */
  185.    BufferPos = BytesRead = 1;
  186.    /* is is_eof == 1, we'll never read a file again
  187.     */
  188.    is_eof = 0;
  189.    file_pos = 0L;
  190.    _lclose(hfp);
  191. }
  192.  
  193.  
  194. /* type of files */
  195. static snap_type(char * file_name)
  196. {
  197.   char ext[MAXEXT];
  198.    int flags;
  199.    int val = 255;
  200.    struct map
  201.    {
  202.       char * snap_extension;
  203.       short snap_val;
  204.    } map_ext[] =
  205.    {
  206.     { ".SNA", SNA_FMT },
  207.     { ".SNX", SNX_FMT },
  208.     { ".Z80", Z80_FMT },
  209.     { ".SIT", SIT_FMT },
  210.     { ".SP",  SP_FMT  },
  211.     { ".RAW", RAW_FMT },
  212.     { ".ZX",  ZX_FMT  },
  213.     { ".PRG", PRG_FMT },
  214.     { ".ACH", ACH_FMT },
  215.     { ".TAP", TAP_FMT },
  216.     { ".BLK", TAP_FMT },
  217.     { ".ROM", ROM_FMT },
  218.     { ".DAT", DAT_FMT },
  219.     { ".SCR", SCR_FMT },
  220.     { ".SLT", SLT_FMT },
  221.     { ".INI", INI_FMT }
  222.    };
  223.  
  224.    flags = fnsplit(file_name, NULL, NULL, NULL, ext);
  225.    if(flags & EXTENSION)
  226.    {
  227.       short i;
  228.  
  229.       for(i = 0 ; i < sizeof(map_ext)/sizeof(struct map) ; i++)
  230.     if(!strcmpi(ext,map_ext[i].snap_extension))
  231.     {
  232.        val = map_ext[i].snap_val;
  233.        break;
  234.      }
  235.    }
  236.    return val;
  237. }
  238.  
  239.  
  240. /* open file for reading */
  241. int open_sna(LPSTR file_name)
  242. {
  243.    HFILE stream;
  244.    int status = 0;
  245.    char snapcopy[260];
  246.    char *p = snapcopy;
  247.  
  248.    while(*p++ = *file_name++);
  249.  
  250.    if(!inside_level_trap)
  251.    {
  252.       char Caption_name[260];
  253.       short i;
  254.  
  255.       strcpy(Caption_name, "WSpecEm - ");
  256.                             
  257.       i = strlen(snapcopy);
  258.       while(snapcopy[i] != '\\')
  259.      i--;
  260.       strcat(Caption_name, snapcopy + i+1);
  261.       //  put snapshot name to lower case -- but only for
  262.       // display
  263.       strlwr(&Caption_name[0]+9);
  264.       SetWindowText(hwndApp, Caption_name);
  265.       SLT_info_block_ad = 0;
  266.    }
  267.    build_F();
  268.    R = (R & 0x7F) | BIT_7;
  269.  
  270.    if(stream = _lopen(snapcopy, READ))
  271.    {
  272.       switch(snap_type(snapcopy))
  273.       {
  274.      case SNA_FMT:
  275.         status = sna_load(stream);
  276.         break;
  277.  
  278.      case SNX_FMT:
  279.         status = snx_load(stream);
  280.         break;
  281.  
  282.      case Z80_FMT:
  283.         status = z80_load(stream);
  284.         break;
  285.  
  286.      case SLT_FMT:
  287.         if(inside_level_trap)
  288.            status = load_slt_level(stream);
  289.         else
  290.             {
  291.            status = slt_load(stream);
  292.             }
  293.         break;
  294.  
  295.      case SIT_FMT:
  296.         status = sit_load(stream);
  297.         break;
  298.  
  299.      case SP_FMT:
  300.         status = sp_load(stream);
  301.         break;
  302.  
  303.      case RAW_FMT:
  304.         status = raw_load(stream);
  305.         break;
  306.  
  307.      case ZX_FMT:
  308.         status = zx_load(stream);
  309.         break;
  310.  
  311.      case PRG_FMT:
  312.         status = prg_load(stream);
  313.         break;
  314.  
  315.      case ACH_FMT:
  316.         status = ach_load(stream);
  317.         break;
  318.  
  319.      case ROM_FMT:
  320.         status = rom_load(stream);
  321.         do_reset();
  322.         break;
  323.  
  324.      case SCR_FMT:
  325.         status = scr_load(stream);
  326.         break;
  327.  
  328.      case DAT_FMT:
  329.         status = dat_load(stream);
  330.         break;
  331.  
  332.      case TAP_FMT:
  333.         if (!inside_level_trap)
  334.         {
  335.            strcpy(TapName, snapcopy);
  336.            TapFilePos = 0;
  337.         }
  338.         else
  339.         {
  340.            status = tap_load(stream);
  341.         }
  342.         break;
  343.      case INI_FMT:
  344.         status = load_options(stream);
  345.         break;
  346.  
  347.      default:
  348.         status = 2;
  349.             break;
  350.       }
  351.  
  352.       read_F();
  353.       R_BIT7 = (R & BIT_7);
  354.  
  355.       if(!inside_level_trap)
  356.      strcpy(snapname, snapcopy); 
  357.  
  358.       z_close(stream);
  359.       /* if status is false a corrective action must be taken
  360.        */
  361.       if(!inside_level_trap)
  362.       {
  363.          if(status == 2)
  364.         Warning("Can't recognize this extension.");
  365.      else
  366.         if(status == 1)
  367.             {
  368.            Panic("Corrupted data.");         
  369.         }
  370.       }
  371.    }
  372.    return status;
  373. }
  374.  
  375. /* get a word from file in Intel format */
  376. static unsigned short get2(HFILE hfp)
  377. {
  378.    unsigned char l=getbyte(hfp);
  379.    unsigned char h=getbyte(hfp);
  380.  
  381.    return (h<<8)|l;
  382. }
  383.  
  384. /* get a word from file in big-endian format */
  385. static unsigned short getword(HFILE hfp)
  386. {
  387.    unsigned char h=getbyte(hfp);
  388.    unsigned char l=getbyte(hfp);
  389.  
  390.    return (h<<8)|l;
  391. }
  392.  
  393. static load_raw(HFILE hfp, USHORT inic, USHORT end)
  394. {
  395.    USHORT i;
  396.  
  397.    for(i=inic ; i < end ; )
  398.       writebyte(i++, getbyte(hfp));
  399.    writebyte(i, getbyte(hfp));
  400.    return 0;
  401. }
  402.  
  403. /* loads .sna type */
  404. static sna_load(HFILE hfp)
  405. {
  406.    I=getbyte(hfp);                /* 00 */
  407.    HL2=get2(hfp);                 /* 01 */
  408.    DE2=get2(hfp);                 /* 03 */
  409.    BC2=get2(hfp);                 /* 05 */
  410.    AF2=get2(hfp);                 /* 07 */
  411.    HL=get2(hfp);                  /* 09 */
  412.    DE=get2(hfp);                  /* 0B */
  413.    BC=get2(hfp);                  /* 0D */
  414.    IY=get2(hfp);                  /* 0F */
  415.    IX=get2(hfp);                  /* 11 */
  416.    IFF1=IFF2=(getbyte(hfp)>>2)&1; /* 13 */
  417.    R=getbyte(hfp);                /* 14 */
  418.    F=getbyte(hfp);                /* 15 */
  419.    A=getbyte(hfp);                /* 16 */
  420.    SP=get2(hfp);                  /* 17 */
  421.    _IM=getbyte(hfp);              /* 19 */
  422.  
  423.    /* get around a problem with some snaps --- perhaps a bug in a old version
  424.      of xzx...or a bad snap?
  425.     */
  426.    if(_IM == 3)
  427.    {
  428.       _IM = 2;
  429.    }
  430.    writeport(254,(getbyte(hfp)&7)|8); /* 1A */
  431.    load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  432.  
  433.    /* all .SNA files must have 49149 bytes of lenght and SP must point to RAM
  434.     */
  435.    if(/*(ftell(hfp) != 49179L) || */(SP < 0x4000))
  436.    {
  437.       return 1;
  438.    }
  439.  
  440.    /* retn(); */
  441.    PutPC(pop());
  442.  
  443.    /* added for compability with JPP -- now any file that works in JPP
  444.       works here (well-fargo, bounder, batman and enduro racer
  445.       saved at certain places)
  446.       - just putting 0 at word in [SP-2] helps...
  447.       I don't know why, but it works!
  448.     */
  449.    writeword(SP-2,0);
  450.  
  451.    return 0;
  452. }
  453.  
  454. static sit_load(HFILE hfp)
  455. {
  456.    USHORT i;
  457.  
  458.    BC=get2(hfp);
  459.    DE=get2(hfp);
  460.    HL=get2(hfp);
  461.    AF=get2(hfp);
  462.    IX=get2(hfp);
  463.    IY=get2(hfp);
  464.    SP=get2(hfp);
  465.    PC=get2(hfp);
  466.    R=getbyte(hfp);
  467.    I=getbyte(hfp);
  468.    BC2=get2(hfp);
  469.    DE2=get2(hfp);
  470.    HL2=get2(hfp);
  471.    AF2=get2(hfp);
  472.    _IM=getbyte(hfp);
  473.    writeport(254,getbyte(hfp));
  474.    rom_load(hfp);
  475.    load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  476.    return 0;
  477. }
  478.  
  479. static snx_load(HFILE hfp)
  480. {
  481.    USHORT len;
  482.    USHORT addr;
  483.    UCHAR val, compressed;
  484.  
  485.    // 0..3    "XSNA"                  Identification for emulator
  486.    if(get2(hfp)!= 'XS')
  487.       return 0;
  488.    if(get2(hfp)!= 'NA')
  489.       return 0;
  490.    // 4,5     Header lenght           #Bytes in following header
  491.    len = get2(hfp);
  492.    I=getbyte(hfp);                /* 06 */
  493.    HL2=get2(hfp);                 /* 07 */
  494.    DE2=get2(hfp);                 /* 09 */
  495.    BC2=get2(hfp);                 /* 0B */
  496.    AF2=get2(hfp);                 /* 0D */
  497.    HL=get2(hfp);                  /* 0F */
  498.    DE=get2(hfp);                  /* 11 */
  499.    BC=get2(hfp);                  /* 13 */
  500.    IY=get2(hfp);                  /* 15 */
  501.    IX=get2(hfp);                  /* 17 */
  502.    IFF1=IFF2=(getbyte(hfp)>>2)&1; /* 19 */
  503.    R=getbyte(hfp);                /* 1A */
  504.    F=getbyte(hfp);                /* 1B */
  505.    A=getbyte(hfp);                /* 1C */
  506.    SP=get2(hfp);                  /* 1D */
  507.    _IM=getbyte(hfp);              /* 1F */
  508.  
  509.    writeport(254,(getbyte(hfp)&7)|8); /* 20 */
  510.  
  511.    //  if1sw      1       switch Interface 1: 0=not emulated, 1=emulated
  512.    //  flashsw    1       switch FLASH:       0=not emulated, 1=emulated
  513.    //  attrsw     1       switch Attributes:  0=no attributes,1=attributes
  514.    //  zy_sw      1       switch keys Z-Y:    Bit 7=0 QWERTY, 1=QWERZ
  515.    //                           +joystick emulation Bit 0,1 00=Kempston
  516.    //                                                       01=IF1/1
  517.    //                                                       10=IF2/2
  518.    //                                                       11=Cursor
  519.    //                           Bit 6 contains ULA-emulation from Version 2.07 on.
  520.    //                                                      (0=off, 1=on).
  521.    //       r_sw       1       switch R-register:0=R not emulated, 1=R emulated
  522.    //                               Bit 7 is used as value for the EAR-bit.
  523.    //       int_sw     1       switch interrupt frequency: 0=50Hz, 1=100Hz
  524.    //       rs232sw    1       switch RS232 redirection:  Bit 0=RS232, Bit 1=CENTR.
  525.    //       sndsw      1       switch sound emulation:
  526.    //                             Lower nibble:  0=OFF,1=direct,2=Interrupt
  527.    //                             Higher nibble: frequency 0..4 for mode 2
  528.    //       bordsw     1       switch border emulation: 0=OFF,1=direkt,2=Interrupt
  529.    //       im2hw      1       switch IM2 hardware vector 0..255
  530.  
  531.    z_seek(hfp, (long)10);  // 21
  532.  
  533.    // headlen == ?
  534.  
  535.    //              2 Bytes count            Number of bytes in block ***)
  536.    //              1 Byte  Flag             Mark if "compressed" block
  537.    //  either (Flag = $ff):
  538.    //              1 Byte  Fill value       Byte to be repeated count times
  539.    // or     (Flag = 0):
  540.    //              Count bytes data         without compression
  541.    //
  542.    // ***) Optimisation, if number of bytes in block <= 16 !!!
  543.    //       The first byte of count contains a value >= $E0, that is to interpret
  544.    //       in the following way:  the lower nibble contains the byte count - 1,
  545.    //       the upper nibble is $E for an uncompressed
  546.    //       block, $F for a compressed block.
  547.    //       The second count byte and the flag byte are not present in this case !
  548.    //
  549.    // The blocks from byte 43 on are repeated for the whole ram dump.
  550.    addr = 0x4000u;
  551.    while(addr)
  552.    {
  553.       len = getbyte(hfp);
  554.       if(len >= (UCHAR)0xE0)
  555.       {
  556.      compressed = (len >= (UCHAR)0xF0);
  557.      len = (len & 0xF)+1;
  558.       }
  559.       else
  560.       {
  561.      len = (len << 8) | getbyte(hfp);
  562.      compressed = (getbyte(hfp) == (UCHAR)0xFF);
  563.       }
  564.       if(compressed)
  565.       {
  566.      val = getbyte(hfp);
  567.      while(len--)
  568.         writebyte(addr++, val);
  569.       }
  570.       else
  571.      while(len--)
  572.         writebyte(addr++, getbyte(hfp) );
  573.    }
  574.    /* retn(); */
  575.    PutPC(pop());
  576.  
  577.    /* As usual, write 0 on corrupted elements [due to snapshot format]
  578.     */
  579.    writeword(SP-2,0);
  580.  
  581.    return 0;
  582. }
  583.  
  584. /* loads .sp type */
  585. static sp_load(HFILE hfp)
  586. {
  587.    UCHAR byte;
  588.    USHORT start, len;
  589.  
  590.    if((BC=get2(hfp)) != 'SP') /* 'SP' */   /* 00 */
  591.    {
  592.       start = 0x4000;
  593.       len = 0xC000;
  594.    }
  595.    else
  596.    {
  597.       len=get2(hfp);               /* 02 */
  598.       start=get2(hfp);             /* 04 */
  599.       BC=get2(hfp);                /* 06 */
  600.    }
  601.    DE=get2(hfp);                   /* 08 */
  602.    HL=get2(hfp);                   /* 0A */
  603.    AF=get2(hfp);                   /* 0C */
  604.    IX=get2(hfp);                   /* 0E */
  605.    IY=get2(hfp);                   /* 10 */
  606.    BC2=get2(hfp);                  /* 12 */
  607.    DE2=get2(hfp);                  /* 14 */
  608.    HL2=get2(hfp);                  /* 16 */
  609.    AF2=get2(hfp);                  /* 18 */
  610.    R=getbyte(hfp);                 /* 1A */
  611.    I=getbyte(hfp);                 /* 1B */
  612.    SP=get2(hfp);                   /* 1C */
  613.    PutPC(get2(hfp));               /* 1E */
  614.  
  615.    /* 2 reserved bytes */
  616.    (void)getbyte(hfp);
  617.    (void)getbyte(hfp);
  618.  
  619.    writeport(254, getbyte(hfp));   /* 22 */
  620.  
  621.    /* reserved byte */
  622.    (void)getbyte(hfp);
  623.    byte=getbyte(hfp);              /* 24 */
  624.    IFF1=IFF2=byte&1;
  625.    _IM=(byte&2)?2:1;
  626.    (void)getbyte(hfp);             /* 25 */
  627.    load_raw(hfp, (USHORT)start, (USHORT)((USHORT)(start-1)+(USHORT)len));
  628.    return 0;
  629. }
  630.  
  631. static z80_decompress(USHORT address, USHORT len, HFILE hfp)
  632. {
  633.    UCHAR byte;
  634.    USHORT i;
  635.  
  636.    while(len--)
  637.    {
  638.       byte=getbyte(hfp);
  639.  
  640.       if((byte==0xed) && len)
  641.       {
  642.      byte=getbyte(hfp);
  643.      len--;
  644.      if(byte==0xed)
  645.      {
  646.         /* if len==0 file is trashed */
  647.         i=getbyte(hfp);
  648.         len--;
  649.         /* if len==0 file is trashed */
  650.         byte=getbyte(hfp);
  651.         len--;
  652.         while(i--)
  653.            writebyte(address++, byte);
  654.      }
  655.      else
  656.      {
  657.         writebyte(address++, 0xed);
  658.         writebyte(address++, byte);
  659.      }
  660.       }
  661.       else
  662.      writebyte(address++, byte);
  663.    }
  664.    return 0;
  665. }
  666.  
  667. static z80_load(HFILE hfp)
  668. {
  669.    USHORT i;
  670.    UCHAR byte;
  671.    USHORT address;
  672.    UCHAR compressed = 0;
  673.    UCHAR page_skipped = 0;
  674.  
  675.    A=getbyte(hfp);                 /* 00 */
  676.    F=getbyte(hfp);                 /* 01 */
  677.    BC=get2(hfp);                   /* 02 */
  678.    HL=get2(hfp);                   /* 04 */
  679.    PutPC(get2(hfp));               /* 06 */
  680.    SP=get2(hfp);                   /* 08 */
  681.    I=getbyte(hfp);                 /* 0A */
  682.    R=getbyte(hfp) & 0x7F;/* 0B */
  683.    byte=getbyte(hfp);              /* 0C */
  684.    if(byte == 255) byte = 1;
  685.    if(byte & 1)
  686.       R |= (UCHAR)0x80;
  687.    writeport(254, (byte >> 1) & 7);
  688.    if(byte & 0x20) compressed++;
  689.    DE=get2(hfp);                   /* 0D */
  690.    BC2=get2(hfp);                  /* 0F */
  691.    DE2=get2(hfp);                  /* 11 */
  692.    HL2=get2(hfp);                  /* 13 */
  693.    A2=getbyte(hfp);                /* 15 */
  694.    F2=getbyte(hfp);                /* 16 */
  695.    IY=get2(hfp);                   /* 17 */
  696.    IX=get2(hfp);                   /* 19 */
  697.    IFF1=(getbyte(hfp) != 0);       /* 1B */
  698.    IFF2=(getbyte(hfp) != 0);       /* 1C */
  699.    byte=getbyte(hfp);              /* 1D */
  700.    _IM=byte & 3;
  701.    /* bit 2 == 1 --- issue 2 emulation */
  702.    /* bit 6,7 0-Cursor/Protek/AGF joystick
  703.           1-Sinclair 1 joystick
  704.           2-Sinclair 2 joystick
  705.     */
  706.    if((USHORT)PC == 0)     /* we have a extended header if PC=0 */
  707.    {
  708.       USHORT len;
  709.  
  710.       len=get2(hfp);               /* 1E */
  711.       PutPC(get2(hfp));            /* 20 */
  712.       byte=getbyte(hfp); /* hardware mode */
  713.       if(len)
  714.      z_seek(hfp, (long)(len-3));
  715.       /*-----------------------------------------*/
  716.       /* time to read pages */
  717.       while(!feof_file())
  718.       {
  719.      len=get2(hfp);  /* page len */
  720.      if(feof_file() || (len == 0))
  721.         break;
  722.      /* get 16k-page number */
  723.      byte=getbyte(hfp);
  724.      switch(byte)
  725.      {
  726.         case 4: address = (USHORT)0x8000;
  727.         break;
  728.         case 5: address = (USHORT)0xC000;
  729.         break;
  730.         case 8: address = (USHORT)0x4000;
  731.         break;
  732.         default:
  733.         /* hardware not implemented ... skiping page....
  734.          if it's a program wich only uses the 128k chip sound,
  735.          it'll work... and then, maybe not ; but it's worth a
  736.          try
  737.          */
  738.         page_skipped = 1;
  739.         z_seek(hfp, (long)len);
  740.         continue;
  741.      }
  742.      z80_decompress(address, len, hfp);
  743.       }
  744.    }
  745.    else
  746.    {
  747.       if(compressed)
  748.       {
  749.      address = 0x4000; 
  750.  
  751.          while(address)
  752.          {
  753.             byte=getbyte(hfp);
  754.  
  755.             if((byte==0xed) && (address != 0xFFFF))
  756.             {
  757.            byte=getbyte(hfp);
  758.            if(byte==0xed)
  759.            {
  760.           i=getbyte(hfp);
  761.               /* if i==0 file is trashed */
  762.               byte=getbyte(hfp);
  763.               while(i--)
  764.               writebyte(address++, byte);
  765.            }
  766.            else
  767.            {
  768.               writebyte(address++, 0xed);
  769.               writebyte(address++, byte);
  770.            }
  771.             }
  772.             else
  773.            writebyte(address++, byte);
  774.          }
  775.       }
  776.       else
  777.      load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  778.    }
  779.    if(page_skipped)
  780.       Warning("This snapshot is requesting non emulated hardware.\n\
  781. If it crashes, reset the emulator.");
  782.    return 0;
  783. }
  784.  
  785. /* loads .slt type */
  786. static slt_load(HFILE hfp)
  787. {
  788.    UCHAR byte;
  789.    UCHAR state = 'S';
  790.    UCHAR i;
  791.  
  792.    z80_load(hfp);
  793.    /* Will have to test if new .SLT extensions here.
  794.     */
  795.  
  796.    i = 10; /* allow for 10 bytes for searching for .SLT */
  797.    while(i--)
  798.    {
  799.       // implement here a finite-state machine to find SLT keyword
  800.       byte = getbyte(hfp);
  801.       if(state == byte)
  802.       {
  803.      switch(byte)
  804.      {
  805.         case 'S':
  806.            state = 'L';
  807.            break;
  808.         case 'L':
  809.            state = 'T';
  810.            break;
  811.  
  812.         case 'T':
  813.            state = 0;
  814.            break;
  815.      }
  816.       }
  817.       else
  818.      state = 'S';
  819.       if(!state)
  820.       {
  821.      SLT_info_block_ad = file_pos;
  822.      break;
  823.       }
  824.    }
  825.    if(state)
  826.    {
  827.       Warning("This snapshot is a .Z80, not a .SLT.");
  828.    }
  829.    return 0;
  830. }
  831.  
  832. /* loads .raw type */
  833. static raw_load(HFILE hfp)
  834. {
  835.    /* if error in header, could give the message 'should be saved with
  836.     "SAVE *\"b\' CODE 16384, 49152 '
  837.     */
  838.    if(getbyte(hfp)!=3)     /* CODE */      /* 00 */
  839.       return 0;
  840.    if(get2(hfp)!=0xC000)                   /* 01 */
  841.       return 0;
  842.    if(get2(hfp)!=0x4000)                   /* 03 */
  843.       return 0;
  844.    (void)get2(hfp);                        /* 05 */
  845.    (void)get2(hfp);                        /* 07 */
  846.  
  847.    load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  848.    PutPC(0x1BF4);  /* entry of next statement */
  849.    AF = 0x5F99;
  850.    BC = 0x1FF0;
  851.    DE = 0x5D0C;
  852.    HL = 0x5d0E;
  853.    AF2 = 0x0044;
  854.    BC2 = 0x1820;
  855.    DE2 = 0x0007;
  856.    HL2 = 0x5CF1;
  857.    IX = 0x03D4;
  858.    IY = 0x5C3A;
  859.    I = 0x3F;
  860.    R = 0;
  861.    _IM = 1;
  862.    IFF1 = IFF2 = 1;
  863.    /* set SP by RAMTOP */
  864.    SP = readword(0x5CB2);
  865.    /* Reset ERR NR to no error */
  866.    writebyte(0x5C3A, 0xFF);
  867.    /* Set border by means of BORDCR */
  868.    writeport(254, (readbyte(0x5C48)&0x38)>>3);
  869.    /* put return adress to MAIN_4 on stack */
  870.    push(0x1303);
  871.    return 0;
  872. }
  873.  
  874. static zx_load(HFILE hfp)
  875. {
  876.    UCHAR byte;
  877.  
  878.    z_seek(hfp, 132L);
  879.    load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  880.    z_seek(hfp, 0x8EL);
  881.    IFF1 = IFF2 = ((getbyte(hfp)&1)!=0);
  882.    z_seek(hfp, 7L);
  883.    BC  = getword(hfp);
  884.    BC2 = getword(hfp);
  885.    DE  = getword(hfp);
  886.    DE2 = getword(hfp);
  887.    HL  = getword(hfp);
  888.    HL2 = getword(hfp);
  889.    IX  = getword(hfp);
  890.    IY  = getword(hfp);
  891.    I   = getbyte(hfp);
  892.    R   = getbyte(hfp);
  893.    (void)getword(hfp); getbyte(hfp);
  894.    A2  = getbyte(hfp);
  895.    (void)getbyte(hfp);
  896.    A   = getbyte(hfp);
  897.    (void)getbyte(hfp);
  898.    F2  = getbyte(hfp);
  899.    (void)getbyte(hfp);
  900.    F   = getbyte(hfp);
  901.    (void)getword(hfp);
  902.    PutPC(getword(hfp));
  903.    (void)getword(hfp);
  904.    SP  = getword(hfp);
  905.    z_seek(hfp, 5L);
  906.    byte = getbyte(hfp);
  907.    if(byte == (UCHAR)0xFFu)
  908.       _IM = 2;
  909.    else
  910.        _IM = (byte == 1)?2:1;
  911.    return 0;
  912. }
  913.  
  914. static prg_load(HFILE hfp)
  915. {
  916.    z_seek(hfp, 0xDCL);
  917.    IY   = get2(hfp);                       /* DC */
  918.    IX   = get2(hfp);                       /* DE */
  919.    DE2  = get2(hfp);                       /* E0 */
  920.    BC2  = get2(hfp);                       /* E2 */
  921.    HL2  = get2(hfp);                       /* E4 */
  922.    AF2  = get2(hfp);                       /* E6 */
  923.    DE   = get2(hfp);                       /* E8 */
  924.    BC   = get2(hfp);                       /* EA */
  925.    HL   = get2(hfp);                       /* EC */
  926.    IFF1 = IFF2 = (getbyte(hfp)& BIT_7);    /* EE */
  927.    I    = getbyte(hfp);                    /* EF */
  928.    _IM   = (I == 0x3F)?1:2;                /* F0 */
  929.    SP   = get2(hfp);                       /* F1 */
  930.    z_seek(hfp, 0x0EL);
  931.    load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  932.    /* Set border by means of BORDCR */
  933.    writeport(254,(readbyte(0x5C48)& 0x38) >> 3 );
  934.    R    = readbyte(SP + 1);
  935.    AF   = readword(SP + 2);
  936.    PutPC(readword(SP + 4));
  937.    /*writebyte(SP+1, 0);
  938.    writeword(SP+2, 0);
  939.    writeword(SP+4, 0);*/
  940.    SP += 6;
  941.    return 0;
  942. }
  943.  
  944. static ach_load(HFILE hfp)
  945.    A = getbyte(hfp);               /* 00 */
  946.    (void)getword(hfp); (void)getbyte(hfp);
  947.    F = getbyte(hfp);               /* 04 */
  948.    (void)getword(hfp); (void)getbyte(hfp);
  949.    B = getbyte(hfp);               /* 08 */
  950.    (void)getword(hfp); (void)getbyte(hfp);
  951.    C = getbyte(hfp);               /* 0C */
  952.    (void)getword(hfp); (void)getbyte(hfp);
  953.    D = getbyte(hfp);               /* 10 */
  954.    (void)getword(hfp); (void)getbyte(hfp);
  955.    E = getbyte(hfp);               /* 14 */
  956.    (void)getword(hfp); (void)getbyte(hfp);
  957.    H = getbyte(hfp);               /* 18 */
  958.    (void)getword(hfp); (void)getbyte(hfp);
  959.    L = getbyte(hfp);               /* 1C */
  960.    (void)getword(hfp); (void)getbyte(hfp);
  961.    PutPC(get2(hfp));               /* 20 */
  962.    z_seek(hfp, 6L);
  963.    SP = get2(hfp);                 /* 28 */
  964.    z_seek(hfp, 0x94L-0x2AL);
  965.    R = getbyte(hfp);               /* 94 */
  966.    z_seek(hfp, 0x9CL-0x95L);
  967.    writeport(254, getbyte(hfp));   /* 9C */
  968.    z_seek(hfp, 0xA4L-0x9DL);
  969.    _IM = getbyte(hfp) & 3; /* A4 */
  970.    if(_IM == 3)
  971.       _IM = 0;
  972.    z_seek(hfp, 0xBEL - 0xA5L);
  973.    I = getbyte(hfp);               /* BE */
  974.    IFF1 = IFF2 = (getbyte(hfp)!=0);/* BF */
  975.    z_seek(hfp, 0xECL-0xC0L);
  976.    AF2 = getword(hfp);     /* EC */
  977.    (void)getword(hfp);
  978.    BC2 = getword(hfp);     /* F0 */
  979.    (void)getword(hfp);
  980.    DE2 = getword(hfp);     /* F4 */
  981.    HL2 = getword(hfp);     /* F6 */
  982.    IX  = get2(hfp);        /* F8 */
  983.    (void)getword(hfp);
  984.    IY  = get2(hfp);        /* FC */
  985.    (void)getword(hfp);
  986.                /* FE */
  987.    rom_load(hfp);
  988.    load_raw(hfp, (USHORT)0x4000u, (USHORT)0xFFFFu);
  989.    return 0;
  990. }
  991.  
  992. // patch it for LOAD/SAVE routines for .TAP files
  993. // do_it == 1 patch it, do_it = 0 unpatch
  994. void patch_rom(BOOLEAN do_it)
  995. {
  996.    USHORT crc = 0, i;
  997.    // vars to save ROM bytes patched
  998.    static v056c, v056d, v056e, v059e, v05c8, v05c9;
  999.  
  1000.    if(do_it)
  1001.    {
  1002.       /* check if it is Spectrum ROM first!
  1003.         If it is a different ROM, we can't patch it
  1004.     [Shadow of Unicorn]
  1005.        */
  1006.  
  1007.       /* patch Spectrum ROM -- patchs for LOAD/SAVE */
  1008.       /* verify SA-BYTES */
  1009.       for(i = 0x04C2 ; i < 0x053C ; i++)
  1010.          crc += readbyte(i);
  1011.  
  1012.       /* verify LD-BYTES */
  1013.       for(i = 0x0556 ; i < 0x0605 ; i++)
  1014.          crc += readbyte(i);
  1015.  
  1016.       /* verify SA-ALL --- shorter CRC cycle to work with
  1017.          Spanish and Brazilian translations of ROMs
  1018.        */
  1019.       for(i = 0x075A ; i < 0x078A ; i++)
  1020.          crc += readbyte(i);
  1021.  
  1022.       v056c = readbyte(0x056C);
  1023.       v056d = readbyte(0x056D);
  1024.       v056e = readbyte(0x056E);
  1025.       v059e = readbyte(0x059E);
  1026.       v05c8 = readbyte(0x05C8);
  1027.       v05c9 = readbyte(0x05C9);
  1028.  
  1029.       if(crc == 38151)
  1030.       {
  1031.          /* jumps to relevant routine */
  1032.  
  1033.          /* patches for LD-BYTES */
  1034.          *(mem+0x056C) = 0xC3;   /* jp */
  1035.          *(mem+0x056D) = 0x9f;
  1036.          *(mem+0x056E) = 0x05;
  1037.  
  1038.      *(mem+0x059E) = 0x00;  /* nop */
  1039.  
  1040.          *(mem+0x05c8) = 0xED;  /* install handler */
  1041.          *(mem+0x05c9) = 0xFB;
  1042.       }
  1043.    }
  1044.    else
  1045.    {
  1046.       // unpatch ROM
  1047.       *(mem+0x056C) = v056c;
  1048.       *(mem+0x056D) = v056d;
  1049.       *(mem+0x056E) = v056e;
  1050.  
  1051.       *(mem+0x059E) = v059e;
  1052.  
  1053.       *(mem+0x05C8) = v05c8;
  1054.       *(mem+0x05C9) = v05c9;
  1055.    }
  1056. }
  1057.  
  1058. // load Spectrum ROM
  1059. static rom_load(HFILE hfp)
  1060. {
  1061.    USHORT i = 0;
  1062.  
  1063.    for(i = 0 ; i  < 0x4000 ; i++)
  1064.    {
  1065.       if(feof_file())
  1066.          break;
  1067.       *(mem+i) = getbyte(hfp);
  1068.    }
  1069.    patch_rom(1);
  1070.    return ((i == 0x4000)?0:3);
  1071. }
  1072.  
  1073. static scr_load(HFILE hfp)
  1074. {
  1075.    load_raw(hfp, (USHORT)0x4000, (USHORT)(0x4000+6912-1) );
  1076.    return 0;
  1077. }
  1078.  
  1079. static dat_load(HFILE hfp)
  1080. {
  1081.    USHORT i = HL;
  1082.  
  1083.    while(!feof_file())
  1084.    {
  1085.       writebyte(i++, getbyte(hfp));
  1086.    }
  1087.    return 0;
  1088. }
  1089.  
  1090. /* This will load / verify the next block of a .TAP file
  1091.   to do:
  1092.   --- TAPE rewind implemented... 
  1093.   when we arrive at the end of the virtual tape, we'll rewind back
  1094.   to start automaticaly
  1095.  */
  1096. static tap_load(HFILE hfp)
  1097. {
  1098.    USHORT len;
  1099.    BOOLEAN verify_error = 0;
  1100.    BOOLEAN load_block = 1;
  1101.  
  1102.    /* this i
  1103.    only works with a hack at
  1104.        0x05C8    (TWO-BYTE OPCODE EDFB)
  1105.     */
  1106.    z_seek(hfp, TapFilePos);
  1107.    len = get2(hfp);
  1108.    if(/*F'Z = 0*/ !(AF2 & BIT_6) )
  1109.    { 
  1110.       len--;  /* we are already subtracting the space used by the flag
  1111.            */
  1112.       H = getbyte(hfp);
  1113.       load_block = (AF2>>8) == H;
  1114.    }
  1115.  
  1116.    if (load_block)
  1117.    {
  1118.       while(DE && len)
  1119.       {
  1120.          L = getbyte(hfp);
  1121.      len--;
  1122.          H ^= L;
  1123.      if (/*F'C != 0 */ AF2 & BIT_0)    // if not verify
  1124.         writebyte(IX, L);
  1125.      else
  1126.         if(readbyte(IX) != L)
  1127.         {
  1128.            verify_error = 1;
  1129.            break;
  1130.             }
  1131.      IX++;
  1132.      DE--;
  1133.       }
  1134.       if (len && !verify_error)
  1135.       {
  1136.          H ^= getbyte(hfp);
  1137.      len--;
  1138.       }
  1139.    }
  1140.  
  1141.    if (len)
  1142.       z_seek(hfp, len);
  1143.  
  1144.    if(!DE)
  1145.       {
  1146.          B = 0xB0;
  1147.       }
  1148.  
  1149.    if(!verify_error)
  1150.    {
  1151.       AF2 &= (AF2 | BIT_6); /* Z' = 1 */
  1152.       A = H;
  1153.  
  1154.       /* if A is not 0, we'll have here a tape loading error...
  1155.        but we must not interfere with it. Can be a proteccion
  1156.         method and not a error, it depends on the caller.
  1157.        */
  1158.       PC = 0x05E0;
  1159.    }
  1160.    else        
  1161.    {
  1162.       flags._Z = 0;
  1163.       ret();
  1164.    }
  1165.  
  1166.    build_F();
  1167.  
  1168.    TapFilePos = file_pos;
  1169.  
  1170.    while(getbyte(hfp) == (UCHAR)0)
  1171.       if(feof_file())
  1172.       {
  1173.      TapFilePos = 0;
  1174.      break;
  1175.       } 
  1176.    /*   if(!get2(hfp))
  1177.       TapFilePos = 0;
  1178.       */
  1179.    /* force a redraw --- tell it's interrupt time */
  1180.    Force_interrupt();
  1181.    return 0;
  1182. }
  1183.  
  1184.  
  1185. void reload_snap(void)
  1186. {
  1187.    if(snapname[0])
  1188.       (void)open_sna(snapname);
  1189. }
  1190.  
  1191. void save_snap(void)
  1192. {
  1193.    save_sna(snapname);
  1194. }
  1195.  
  1196. /* load emulator options */
  1197. static load_options(HFILE hfp)
  1198. {
  1199.    Scale        = getbyte(hfp);
  1200.    bSoundOn     = getbyte(hfp);
  1201.    bFlashOn     = getbyte(hfp);
  1202.    bModel3      = getbyte(hfp);
  1203.    ScreenUpdate = getbyte(hfp);
  1204.    DelayEmVal   = get2(hfp);
  1205.    if(Scale == 0)
  1206.    {
  1207.       Scale    = 1;
  1208.       bSoundOn = 1;
  1209.       bFlashOn = 1;
  1210.       bModel3  = 1;
  1211.    }
  1212.    /* Not an error, routine done to be compatible with .INI files of
  1213.      previous versions
  1214.     */
  1215.    if(ScreenUpdate == 0)
  1216.    {
  1217.        ScreenUpdate = 3;
  1218.        DelayEmVal = 0;
  1219.    }
  1220.    return 0;
  1221. }
  1222.  
  1223. // --------------------------------------------------------
  1224. void level_loader_trap(void)
  1225. {
  1226.    char s_copy[260];
  1227.    short pos;
  1228.  
  1229.    inside_level_trap = 1;
  1230.    if(PC == (0x05C8+2))
  1231.    {
  1232.       (void)open_sna(TapName);
  1233.    }
  1234.    else
  1235.    {
  1236.       strcpy(s_copy, snapname);
  1237.  
  1238.       // If it is a .SLT file, we don't need to find the .DAT files
  1239.       if(!SLT_info_block_ad)
  1240.       {
  1241.      // Steps to find the .DAT files
  1242.      // Cut extension of snap name and dot
  1243.      pos = strlen(s_copy);
  1244.      while(--pos)
  1245.         if(!pos || (s_copy[pos] == '.')|| (s_copy[pos] == '/')||
  1246.         (s_copy[pos] == '\\'))
  1247.            break;
  1248.      if(s_copy[pos] == '.')
  1249.         s_copy[pos] = '\0';
  1250.      // append itoa(A)and append ".DAT"
  1251.      sprintf(s_copy+strlen(s_copy), "%u.DAT", A);
  1252.       }
  1253.       (void)open_sna(s_copy);
  1254.    }
  1255.    inside_level_trap = 0;
  1256. }
  1257.  
  1258. /* LOAD data levels of .SLT files
  1259.  */
  1260. static load_slt_level(HFILE hfp)
  1261. {
  1262.    /* Offset of the level on file */
  1263.    long Off_level = 0;
  1264.    USHORT data_type;  /* 0 for end of table, 1 for level data */
  1265.    long length;       /* length of block being read           */
  1266.    USHORT len,        /* length of sougth block               */
  1267.       level;      /* level sougth                         */
  1268.    BOOLEAN found = 0; /* level found?                         */
  1269.  
  1270.    z_seek(hfp, SLT_info_block_ad);
  1271.    while(data_type = get2(hfp))
  1272.    {
  1273.       /* avoid a possible infinite loop here
  1274.        */
  1275.       if(feof_file())
  1276.      break;
  1277.  
  1278.       level  = get2(hfp);
  1279.       length = get2(hfp) | (((long)get2(hfp)) << 16);
  1280.  
  1281.       if((data_type == 1) && (level == A))
  1282.       {
  1283.      found = 1;
  1284.      len = length;
  1285.       }
  1286.       if(!found)
  1287.      Off_level += length;
  1288.    }
  1289.  
  1290.    if(found)
  1291.    {
  1292.       (void)getword(hfp);
  1293.       (void)getword(hfp);
  1294.       (void)getword(hfp);
  1295.       z_seek(hfp, Off_level);
  1296.       z80_decompress(HL, len, hfp);
  1297.    }
  1298.    return 0;
  1299. }
  1300.  
  1301. void open_menu(HWND hWnd)
  1302. {
  1303.   static char szName[256];
  1304.   OPENFILENAME ofnTemp;
  1305.   DWORD Errval; // Error value
  1306.   char buf[5];  // Error buffer
  1307.   char Errstr[50]="GetOpenFileName returned Error #";
  1308.   UINT i;
  1309.   /* This string is so long is has to be kept here instead of in the
  1310.      resource (at least with Turbo C++)
  1311.    */
  1312.   static char szTemp[] =
  1313.         "All spectrum files|*.ach;*.blk;*.prg;*.scr;*.sit;"
  1314.         "*.slt;*.sp;*.sna;*.snx;*.raw;*.tap;*.z80;*.zx;*.rom|"
  1315.         "ACH - !Speccy|*.ach|"
  1316.         "BLK - Sinclair|*.blk|"
  1317.         "PRG - SpecEm|*.prg|"
  1318.         "SCR - Spectrum screen|*.scr|"
  1319.         "SIT - Sinclair|*.sit|"
  1320.         "SLT - z80,x128|*.slt|"
  1321.         "SP  - Spectrum,VgaSpec|*.sp|"
  1322.         "SNA - JPP, xzx|*.sna|"
  1323.         "SNX - Specci|*.snx|"
  1324.         "RAW - raw files|*.raw|"
  1325.         "TAP - cassete files|*.tap|"
  1326.         "Z80 - Z80, Waravejo,x128|*.z80|"
  1327.         "ZX  - KGB|*.zx|"
  1328.         "ROM - change ROM|*.rom|";
  1329.  
  1330.  
  1331.    char chReplace = '|';
  1332.  
  1333.    for (i = 0; szTemp[i] != '\0'; i++) {
  1334.      if (szTemp[i] == chReplace)
  1335.          szTemp[i] = '\0';
  1336.    }
  1337.  
  1338.   ofnTemp.lStructSize = sizeof( OPENFILENAME );
  1339.   ofnTemp.hwndOwner = hWnd; // An invalid hWnd causes non-modality
  1340.   ofnTemp.hInstance = 0;
  1341.   ofnTemp.lpstrFilter = (LPSTR)szTemp;  // See previous note concerning string
  1342.   ofnTemp.lpstrCustomFilter = NULL;
  1343.   ofnTemp.nMaxCustFilter = 0;
  1344.   ofnTemp.nFilterIndex = 1;
  1345.   ofnTemp.lpstrFile = (LPSTR)szName;  // Stores the result in this variable
  1346.   ofnTemp.nMaxFile = sizeof( szName );
  1347.   ofnTemp.lpstrFileTitle = NULL;
  1348.   ofnTemp.nMaxFileTitle = 0;
  1349.   ofnTemp.lpstrInitialDir = NULL;
  1350.   ofnTemp.lpstrTitle = "Open Snapshot";  // Title for dialog
  1351.   ofnTemp.Flags = /*OFN_SHOWHELP*/ OFN_HIDEREADONLY |
  1352.            OFN_OVERWRITEPROMPT | OFN_LONGNAMES;
  1353.   ofnTemp.nFileOffset = 0;
  1354.   ofnTemp.nFileExtension = 0;
  1355.   ofnTemp.lpstrDefExt = "*";
  1356.   ofnTemp.lCustData = 0L;
  1357.   ofnTemp.lpfnHook = NULL;
  1358.   ofnTemp.lpTemplateName = NULL;
  1359.   /*
  1360.    If the call to GetOpenFileName() fails you can call CommDlgExtendedError()
  1361.    to retrieve the type of error that occured.
  1362.    */
  1363.   if(GetOpenFileName( &ofnTemp ) != TRUE)
  1364.   {
  1365.     Errval=CommDlgExtendedError();
  1366.     if(Errval!=0) // 0 value means user selected Cancel
  1367.     {
  1368.       sprintf(buf,"%ld",Errval);
  1369.       strcat(Errstr,buf);
  1370.       MessageBox(hWnd,Errstr,"WARNING",MB_OK|MB_ICONSTOP);
  1371.     }
  1372.   }
  1373.   else
  1374.   {
  1375.      (void)open_sna(ofnTemp.lpstrFile);
  1376.   }
  1377. }
  1378.  
  1379. /*   UINT  i, cbString;
  1380.    char  chReplace;
  1381.    char  szFilter[256];
  1382.  
  1383.  
  1384.    szFile[0] = '\0';
  1385.    if ((cbString = LoadString(hinst, IDS_FILTERSTRING,
  1386.    szFilter, sizeof(szFilter))) == 0) {
  1387.     ErrorHandler();
  1388.    return 0L;
  1389.    }
  1390.    chReplace = szFilter[cbString - 1];*/
  1391.  
  1392. /* EOF : Sna_Load.c */
  1393.