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