Subversion Repositories pentevo

Rev

Rev 723 | Blame | Last modification | View Log | Download | RSS feed

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "tape.h"
  6. #include "memory.h"
  7.  
  8. #include "util.h"
  9. #include "png/zlib.h"
  10.  
  11. #define Z80FQ 3500000
  12.  
  13. unsigned tape_pulse[0x100]; // └ыЇртшЄ шч шьяєы№ёют Ёрчэющ фышэ√ (ўшёыю ёшьтюыют рыЇртшЄр эх сюыхх 256, ёё√ыъш юфэюсрщЄют√х)
  14. unsigned max_pulses = 0;
  15. unsigned tape_err = 0;
  16.  
  17. unsigned char *tape_image = 0; // ╠рёёшт ёё√ыюъ эр рыЇртшЄ (ёё√ыъш юфэюсрщЄют√х)
  18. unsigned tape_imagesize = 0;
  19.  
  20. TAPEINFO *tapeinfo;
  21. unsigned tape_infosize;
  22.  
  23. unsigned appendable;
  24.  
  25. typedef int (__cdecl *inflateInit__ptr)(z_streamp strm, const char *version, int stream_size);
  26. typedef int (__cdecl *inflate_ptr)(z_streamp strm, int flush);
  27. typedef int (__cdecl *inflateEnd_ptr)(z_streamp strm);
  28.  
  29. static inflateInit__ptr inflateInit__p = 0;
  30. static inflate_ptr inflate_p = 0;
  31. static inflateEnd_ptr inflateEnd_p = 0;
  32.  
  33. static HMODULE ZlibDll = 0;
  34.  
  35. bool ZlibInit()
  36. {
  37.     ZlibDll = LoadLibrary("zlib1.dll");
  38.     if(!ZlibDll)
  39.         return false;
  40.     inflateInit__p = (inflateInit__ptr)GetProcAddress(ZlibDll, "inflateInit_");
  41.     if(!inflateInit__p)
  42.         return false;
  43.     inflate_p = (inflate_ptr)GetProcAddress(ZlibDll,"inflate");
  44.     if(!inflate_p)
  45.         return false;
  46.     inflateEnd_p = (inflateEnd_ptr)GetProcAddress(ZlibDll,"inflateEnd");
  47.     if(!inflateEnd_p)
  48.         return false;
  49.     return true;
  50. }
  51.  
  52. void ZlibDone()
  53. {
  54.     if(ZlibDll)
  55.         FreeLibrary(ZlibDll);
  56. }
  57.  
  58. // ╚∙хЄ фышэє шьяєы№ёр т рыЇртшЄх ш тючтЁр∙рхЄ шэфхъё эрщфхээюую ¤ыхьхэЄр
  59. // ┼ёыш шьяєы№ё ё Єръющ °шЁшэющ эх эрщфхэ, юэ фюсрты хЄё  т ъюэхЎ ш тючтЁр∙рхЄё  хую шэфхъё
  60. // tape image contains indexes in tape_pulse[]
  61. unsigned find_pulse(unsigned t)
  62. {
  63.    if (max_pulses < _countof(tape_pulse))
  64.    {
  65.       double e = 0.10 * t; // ЁрчсЁюё 10%
  66.       for (unsigned i = 0; i < max_pulses; i++)
  67.       {
  68.          if ((t - e) < tape_pulse[i] && tape_pulse[i] <= (t + e))
  69.          {
  70.              return i;
  71.          }
  72.       }
  73.       tape_pulse[max_pulses] = t;
  74.       return max_pulses++;
  75.    }
  76.    if (!tape_err)
  77.    {
  78.        errmsg("pulse table full");
  79.        tape_err = 1;
  80.    }
  81.    unsigned nearest = 0; int delta = 0x7FFFFFFF;
  82.    for (unsigned i = 0; i < _countof(tape_pulse); i++)
  83.    {
  84.       if (delta > abs((int)t - (int)tape_pulse[i]))
  85.       {
  86.          nearest = i;
  87.          delta = abs((int)t - (int)tape_pulse[i]);
  88.       }
  89.    }
  90.    return nearest;
  91. }
  92.  
  93. void find_tape_index()
  94. {
  95.    for (unsigned i = 0; i < tape_infosize; i++)
  96.       if (comp.tape.play_pointer >= tape_image + tapeinfo[i].pos)
  97.          comp.tape.index = i;
  98.    temp.led.tape_started = -600*3500000;
  99. }
  100.  
  101. void find_tape_sizes()
  102. {
  103.    for (unsigned i = 0; i < tape_infosize; i++) {
  104.       unsigned end = (i == tape_infosize-1) ? tape_imagesize : tapeinfo[i+1].pos;
  105.  
  106.       unsigned sz = 0;
  107.       for (unsigned j = tapeinfo[i].pos; j < end; j++)
  108.          sz += tape_pulse[tape_image[j]];
  109.       tapeinfo[i].t_size = sz;
  110.    }
  111. }
  112.  
  113. void stop_tape()
  114. {
  115.    find_tape_index();
  116.    const char *msg = "tape stopped";
  117.    if (comp.tape.play_pointer == comp.tape.end_of_tape)
  118.       comp.tape.index = 0, msg = "end of tape";
  119.    comp.tape.play_pointer = 0;
  120.    strcpy(statusline, msg); statcnt = 40;
  121.    comp.tape.edge_change = 0x7FFFFFFFFFFFFFFFULL;
  122.    comp.tape.tape_bit = -1;
  123. }
  124.  
  125. void reset_tape()
  126. {
  127.    comp.tape.index = 0;
  128.    comp.tape.play_pointer = 0;
  129.    comp.tape.edge_change = 0x7FFFFFFFFFFFFFFFULL;
  130.    comp.tape.tape_bit = -1;
  131. }
  132.  
  133. void start_tape()
  134. {
  135.    if (!tape_image) return;
  136.    strcpy(statusline, "tape started"); statcnt = 40;
  137.    comp.tape.play_pointer = tape_image + tapeinfo[comp.tape.index].pos;
  138.    comp.tape.end_of_tape = tape_image + tape_imagesize;
  139.    comp.tape.edge_change = comp.t_states + cpu.t;
  140.    temp.led.tape_started = -600*3500000;
  141.    comp.tape.tape_bit = -1;
  142. }
  143.  
  144. void closetape()
  145. {
  146.    if (tape_image) free(tape_image), tape_image = 0;
  147.    if (tapeinfo) free(tapeinfo), tapeinfo = 0;
  148.    comp.tape.play_pointer = 0; // stop tape
  149.    comp.tape.index = 0; // rewind tape
  150.    tape_err = max_pulses = tape_imagesize = tape_infosize = 0;
  151.    comp.tape.edge_change = 0x7FFFFFFFFFFFFFFFULL;
  152.    comp.tape.tape_bit = -1;
  153. }
  154.  
  155. void reserve(unsigned datasize)
  156. {
  157.    const int blocksize = 16384;
  158.    unsigned newsize = align_by(datasize+tape_imagesize+1, blocksize);
  159.    if (!tape_image) tape_image = (unsigned char*)malloc(newsize);
  160.    if (align_by(tape_imagesize, blocksize) < newsize) tape_image = (unsigned char*)realloc(tape_image, newsize);
  161. }
  162.  
  163. void makeblock(const unsigned char *data, unsigned size, unsigned pilot_t,
  164.       unsigned s1_t, unsigned s2_t, unsigned zero_t, unsigned one_t,
  165.       unsigned pilot_len, unsigned pause, unsigned char last = 8)
  166. {
  167.    reserve(size*16 + pilot_len + 3);
  168.    if (pilot_len != -1) {
  169.       unsigned t = find_pulse(pilot_t);
  170.       for (unsigned i = 0; i < pilot_len; i++)
  171.          tape_image[tape_imagesize++] = t;
  172.       tape_image[tape_imagesize++] = find_pulse(s1_t);
  173.       tape_image[tape_imagesize++] = find_pulse(s2_t);
  174.    }
  175.    unsigned t0 = find_pulse(zero_t), t1 = find_pulse(one_t);
  176.    for (; size>1; size--, data++)
  177.       for (unsigned char j = 0x80; j; j >>= 1)
  178.          tape_image[tape_imagesize++] = (*data & j) ? t1 : t0,
  179.          tape_image[tape_imagesize++] = (*data & j) ? t1 : t0;
  180.    for (unsigned char j = 0x80; j != (unsigned char)(0x80 >> last); j >>= 1) // last byte
  181.       tape_image[tape_imagesize++] = (*data & j) ? t1 : t0,
  182.       tape_image[tape_imagesize++] = (*data & j) ? t1 : t0;
  183.    if (pause) tape_image[tape_imagesize++] = find_pulse(pause*3500);
  184. }
  185.  
  186. void desc(const unsigned char *data, unsigned size, char *dst)
  187. {
  188.    unsigned char crc = 0; char prg[10];
  189.    unsigned i; //Alone Coder 0.36.7
  190.    for (/*unsigned*/ i = 0; i < size; i++) crc ^= data[i];
  191.    if (!*data && size == 19 && (data[1] == 0 || data[1] == 3)) {
  192.       for (i = 0; i < 10; i++) prg[i] = (data[i+2] < ' ' || data[i+2] >= 0x80) ? '?' : data[i+2];
  193.       for (i = 9; i && prg[i] == ' '; prg[i--] = 0);
  194.       sprintf(dst, "%s: \"%s\" %d,%d", data[1] ? "Bytes":"Program", prg,
  195.          *(unsigned short*)(data+14), *(unsigned short*)(data+12));
  196.    } else if (*data == 0xFF) sprintf(dst, "data block, %d bytes", size-2);
  197.    else sprintf(dst, "#%02X block, %d bytes", *data, size-2);
  198.    sprintf(dst + strlen(dst), ", crc %s", crc ? "bad":"ok");
  199. }
  200.  
  201. static bool alloc_infocell()
  202. {
  203.    TAPEINFO *tmp = (TAPEINFO*)realloc(tapeinfo, (tape_infosize+1)*sizeof(TAPEINFO));
  204.    if(!tmp)
  205.    {
  206.        return false;
  207.    }
  208.    tapeinfo = tmp;
  209.    tapeinfo[tape_infosize].pos = tape_imagesize;
  210.    appendable = 0;
  211.    return true;
  212. }
  213.  
  214. bool named_cell(const void *nm, unsigned sz = 0)
  215. {
  216.    if(!alloc_infocell())
  217.        return false;
  218.  
  219.    const size_t n = _countof(tapeinfo[tape_infosize].desc)-1;
  220.    size_t len = min(n, sz ? sz : strlen((const char*)nm));
  221.    strncpy(tapeinfo[tape_infosize].desc, (const char*)nm, len);
  222.    tapeinfo[tape_infosize].desc[len] = 0;
  223.    tape_infosize++;
  224.    return true;
  225. }
  226.  
  227. int readTAP()
  228. {
  229.    unsigned char *ptr = snbuf; closetape();
  230.    while (ptr < snbuf+snapsize) {
  231.       unsigned size = *(unsigned short*)ptr; ptr += 2;
  232.       if (!size) break;
  233.       alloc_infocell();
  234.       desc(ptr, size, tapeinfo[tape_infosize].desc);
  235.       tape_infosize++;
  236.       makeblock(ptr, size, 2168, 667, 735, 855, 1710, (*ptr < 4) ? 8064 : 3220, 1000);
  237.       ptr += size;
  238.    }
  239.    find_tape_sizes();
  240.    return (ptr == snbuf+snapsize);
  241. }
  242.  
  243. #pragma pack(push, 1)
  244. struct TCswHdr
  245. {
  246.     char Signature[22];
  247.     u8 Term;
  248.     u8 VerMajor;
  249.     u8 VerMinor;
  250.     union
  251.     {
  252.         struct
  253.         {
  254.             u16 SampleRate;
  255.             u8 CompressionType;
  256.             u8 Flags;
  257.             u8 Reserved[3];
  258.             u8 Data[1];
  259.         } Ver1;
  260.  
  261.         struct
  262.         {
  263.             u32 SampleRate;
  264.             u32 PulsesAfterDecompression;
  265.             u8 CompressionType;
  266.             u8 Flags;
  267.             u8 HeaderExtLen;
  268.             char EncAppDesc[16];
  269.             u8 ExtHdr[1];
  270.         } Ver2;
  271.     };
  272. };
  273. #pragma pack(pop)
  274.  
  275. int readCSW()
  276. {
  277.    closetape();
  278.    named_cell("CSW tape image");
  279.  
  280.    const TCswHdr *CswHdr = (TCswHdr *)snbuf;
  281.    u8 CompType;
  282.    u32 SampleRate;
  283.    u8 Flags;
  284.    u32 DataOffset;
  285.    u32 PulsesCount;
  286.    switch(CswHdr->VerMajor)
  287.    {
  288.    case 1:
  289.        CompType = CswHdr->Ver1.CompressionType;
  290.        SampleRate = CswHdr->Ver1.SampleRate;
  291.        Flags = CswHdr->Ver1.Flags;
  292.        DataOffset = offsetof(TCswHdr, Ver1.Data);
  293.        PulsesCount = snapsize - 0x18; // ═хяюэ Єэр  ъюэёЄрэЄр
  294.    break;
  295.  
  296.    case 2:
  297.        CompType = CswHdr->Ver2.CompressionType;
  298.        SampleRate = CswHdr->Ver2.SampleRate;
  299.        Flags = CswHdr->Ver2.Flags;
  300.        DataOffset = offsetof(TCswHdr, Ver2.ExtHdr) + CswHdr->Ver2.HeaderExtLen;
  301.        PulsesCount = CswHdr->Ver2.PulsesAfterDecompression;
  302.    break;
  303.  
  304.    default: // unknown csw version
  305.        return 0;
  306.    }
  307.  
  308.    u32 UncompressedSize = snapsize;
  309.    switch(CompType)
  310.    {
  311.    case 2: // Z-RLE
  312.        {
  313.            if(!temp.ZlibSupport)
  314.                return 0;
  315.            static const size_t out_sz = sizeof(snbuf);
  316.            void *out = malloc(out_sz);
  317.            if(!out)
  318.                return 0;
  319.  
  320.            z_stream strm;
  321.            strm.zalloc = Z_NULL;
  322.            strm.zfree = Z_NULL;
  323.            strm.opaque = Z_NULL;
  324.            strm.avail_in = snapsize - DataOffset;
  325.            strm.next_in = snbuf + DataOffset;
  326.            int ret = inflateInit__p(&strm, ZLIB_VERSION, sizeof(strm));
  327.            if(ret != Z_OK)
  328.            {
  329.                free(out);
  330.                return 0;
  331.            }
  332.  
  333.            strm.avail_out = out_sz;
  334.            strm.next_out = (Byte *)out;
  335.            ret = inflate_p(&strm, Z_FINISH);
  336.            if(ret < 0)
  337.            {
  338.                free(out);
  339.                inflateEnd_p(&strm);
  340.                return 0;
  341.            }
  342.            UncompressedSize = out_sz - strm.avail_out;
  343.            memcpy(snbuf + DataOffset, out, UncompressedSize);
  344.            UncompressedSize += DataOffset;
  345.            free(out);
  346.            inflateEnd_p(&strm);
  347.        }
  348.    case 1: // RLE
  349.    break;
  350.  
  351.    default:
  352.        return 0; // unknown compression type
  353.    }
  354.  
  355.    unsigned rate = Z80FQ / SampleRate; // usually 3.5mhz / 44khz
  356.    if (!rate)
  357.        return 0;
  358.  
  359.    reserve(PulsesCount);
  360.  
  361.    if (!(Flags & 1))
  362.        tape_image[tape_imagesize++] = find_pulse(1);
  363.  
  364.    unsigned i = 0;
  365.    for (unsigned char *ptr = snbuf + DataOffset; ptr < snbuf + UncompressedSize; i++)
  366.    {
  367.       unsigned len = *ptr++ * rate;
  368.       if (!len)
  369.       {
  370.           len = *(unsigned*)ptr * rate;
  371.           ptr += 4;
  372.       }
  373.       tape_image[tape_imagesize++] = find_pulse(len);
  374.    }
  375.  
  376.    tape_image[tape_imagesize++] = find_pulse(Z80FQ/10);
  377.    find_tape_sizes();
  378.    return 1;
  379. }
  380.  
  381. void create_appendable_block()
  382. {
  383.    if (!tape_infosize || appendable) return;
  384.    named_cell("set of pulses"); appendable = 1;
  385. }
  386.  
  387. void parse_hardware(const unsigned char *ptr)
  388. {
  389.    unsigned n = *ptr++;
  390.    if (!n) return;
  391.    named_cell("- HARDWARE TYPE ");
  392.    static char ids[] =
  393.      "computer\0"
  394.         "ZX Spectrum 16k\0"
  395.         "ZX Spectrum 48k, Plus\0"
  396.         "ZX Spectrum 48k ISSUE 1\0"
  397.         "ZX Spectrum 128k (Sinclair)\0"
  398.         "ZX Spectrum 128k +2 (Grey case)\0"
  399.         "ZX Spectrum 128k +2A, +3\0"
  400.         "Timex Sinclair TC-2048\0"
  401.         "Timex Sinclair TS-2068\0"
  402.         "Pentagon 128\0"
  403.         "Sam Coupe\0"
  404.         "Didaktik M\0"
  405.         "Didaktik Gama\0"
  406.         "ZX-81 or TS-1000 with  1k RAM\0"
  407.         "ZX-81 or TS-1000 with 16k RAM or more\0"
  408.         "ZX Spectrum 128k, Spanish version\0"
  409.         "ZX Spectrum, Arabic version\0"
  410.         "TK 90-X\0"
  411.         "TK 95\0"
  412.         "Byte\0"
  413.         "Elwro\0"
  414.         "ZS Scorpion\0"
  415.         "Amstrad CPC 464\0"
  416.         "Amstrad CPC 664\0"
  417.         "Amstrad CPC 6128\0"
  418.         "Amstrad CPC 464+\0"
  419.         "Amstrad CPC 6128+\0"
  420.         "Jupiter ACE\0"
  421.         "Enterprise\0"
  422.         "Commodore 64\0"
  423.         "Commodore 128\0"
  424.         "\0"
  425.      "ext. storage\0"
  426.         "Microdrive\0"
  427.         "Opus Discovery\0"
  428.         "Disciple\0"
  429.         "Plus-D\0"
  430.         "Rotronics Wafadrive\0"
  431.         "TR-DOS (BetaDisk)\0"
  432.         "Byte Drive\0"
  433.         "Watsford\0"
  434.         "FIZ\0"
  435.         "Radofin\0"
  436.         "Didaktik disk drives\0"
  437.         "BS-DOS (MB-02)\0"
  438.         "ZX Spectrum +3 disk drive\0"
  439.         "JLO (Oliger) disk interface\0"
  440.         "FDD3000\0"
  441.         "Zebra disk drive\0"
  442.         "Ramex Millenia\0"
  443.         "Larken\0"
  444.         "\0"
  445.      "ROM/RAM type add-on\0"
  446.         "Sam Ram\0"
  447.         "Multiface\0"
  448.         "Multiface 128k\0"
  449.         "Multiface +3\0"
  450.         "MultiPrint\0"
  451.         "MB-02 ROM/RAM expansion\0"
  452.         "\0"
  453.      "sound device\0"
  454.         "Classic AY hardware\0"
  455.         "Fuller Box AY sound hardware\0"
  456.         "Currah microSpeech\0"
  457.         "SpecDrum\0"
  458.         "AY ACB stereo; Melodik\0"
  459.         "AY ABC stereo\0"
  460.         "\0"
  461.      "joystick\0"
  462.         "Kempston\0"
  463.         "Cursor, Protek, AGF\0"
  464.         "Sinclair 2\0"
  465.         "Sinclair 1\0"
  466.         "Fuller\0"
  467.         "\0"
  468.      "mice\0"
  469.         "AMX mouse\0"
  470.         "Kempston mouse\0"
  471.         "\0"
  472.      "other controller\0"
  473.         "Trickstick\0"
  474.         "ZX Light Gun\0"
  475.         "Zebra Graphics Tablet\0"
  476.         "\0"
  477.      "serial port\0"
  478.         "ZX Interface 1\0"
  479.         "ZX Spectrum 128k\0"
  480.         "\0"
  481.      "parallel port\0"
  482.         "Kempston S\0"
  483.         "Kempston E\0"
  484.         "ZX Spectrum 128k +2A, +3\0"
  485.         "Tasman\0"
  486.         "DK'Tronics\0"
  487.         "Hilderbay\0"
  488.         "INES Printerface\0"
  489.         "ZX LPrint Interface 3\0"
  490.         "MultiPrint\0"
  491.         "Opus Discovery\0"
  492.         "Standard 8255 chip with ports 31,63,95\0"
  493.         "\0"
  494.      "printer\0"
  495.         "ZX Printer, Alphacom 32 & compatibles\0"
  496.         "Generic Printer\0"
  497.         "EPSON Compatible\0"
  498.         "\0"
  499.      "modem\0"
  500.         "VTX 5000\0"
  501.         "T/S 2050 or Westridge 2050\0"
  502.         "\0"
  503.      "digitaiser\0"
  504.         "RD Digital Tracer\0"
  505.         "DK'Tronics Light Pen\0"
  506.         "British MicroGraph Pad\0"
  507.         "\0"
  508.      "network adapter\0"
  509.         "ZX Interface 1\0"
  510.         "\0"
  511.      "keyboard / keypad\0"
  512.         "Keypad for ZX Spectrum 128k\0"
  513.         "\0"
  514.      "AD/DA converter\0"
  515.         "Harley Systems ADC 8.2\0"
  516.         "Blackboard Electronics\0"
  517.         "\0"
  518.      "EPROM Programmer\0"
  519.         "Orme Electronics\0"
  520.         "\0"
  521.      "\0";
  522.    for (unsigned i = 0; i < n; i++) {
  523.       unsigned char type_n = *ptr++;
  524.       unsigned char id_n = *ptr++;
  525.       unsigned char value_n = *ptr++;
  526.       const char *type = ids, *id, *value;
  527.       unsigned j; //Alone Coder 0.36.7
  528.       for (/*unsigned*/ j = 0; j < type_n; j++) {
  529.          if (!*type) break;
  530.          while (*(short*)type) type++;
  531.          type += 2;
  532.       }
  533.       if (!*type) type = id = "??"; else {
  534.          id = type + strlen(type) + 1;
  535.          for (j = 0; j < id_n; j++) {
  536.             if (!*id) { id = "??"; break; }
  537.             id += strlen(id)+1;
  538.          }
  539.       }
  540.       switch (value_n) {
  541.          case 0: value = "compatible with"; break;
  542.          case 1: value = "uses"; break;
  543.          case 2: value = "compatible, but doesn't use"; break;
  544.          case 3: value = "incompatible with"; break;
  545.          default: value = "??";
  546.       }
  547.       char bf[512]; sprintf(bf, "%s %s: %s", value, type, id);
  548.       named_cell(bf);
  549.    }
  550.    named_cell("-");
  551. }
  552.  
  553. int readTZX()
  554. {
  555.    const unsigned char *ptr = snbuf;
  556.    closetape();
  557.    unsigned size, pause, i, j, n, t, t0;
  558.    unsigned char pl, last;
  559.    const unsigned char *end;
  560.    char *p;
  561.    unsigned loop_n = 0, loop_p;
  562.    unsigned TzxVer = (ptr[8] << 8) | ptr[9];
  563.    char nm[512];
  564.  
  565.    ptr += 10; // ╧Ёюяєёъ чруюыютър
  566.  
  567.    while (ptr < snbuf+snapsize)
  568.    {
  569.       switch (*ptr++) {
  570.          case 0x10: // normal block
  571.             alloc_infocell();
  572.             size = *(unsigned short*)(ptr+2);
  573.             pause = *(unsigned short*)ptr;
  574.             ptr += 4;
  575.             desc(ptr, size, tapeinfo[tape_infosize].desc);
  576.             tape_infosize++;
  577.             makeblock(ptr, size, 2168, 667, 735, 855, 1710,
  578.                 (*ptr < 4) ? 8064 : 3220, pause);
  579.             ptr += size;
  580.             break;
  581.          case 0x11: // turbo block
  582.             alloc_infocell();
  583.             size = 0xFFFFFF & *(unsigned*)(ptr+0x0F);
  584.             desc(ptr + 0x12, size, tapeinfo[tape_infosize].desc);
  585.             tape_infosize++;
  586.             makeblock(ptr + 0x12, size,
  587.                *(unsigned short*)ptr, *(unsigned short*)(ptr+2),
  588.                *(unsigned short*)(ptr+4), *(unsigned short*)(ptr+6),
  589.                *(unsigned short*)(ptr+8), *(unsigned short*)(ptr+10),
  590.                *(unsigned short*)(ptr+13), ptr[12]);
  591.             // todo: test used bits - ptr+12
  592.             ptr += size + 0x12;
  593.             break;
  594.          case 0x12: // pure tone
  595.             create_appendable_block();
  596.             pl = find_pulse(*(unsigned short*)ptr);
  597.             n = *(unsigned short*)(ptr+2);
  598.             reserve(n);
  599.             for (i = 0; i < n; i++) tape_image[tape_imagesize++] = pl;
  600.             ptr += 4;
  601.             break;
  602.          case 0x13: // sequence of pulses of different lengths
  603.             create_appendable_block();
  604.             n = *ptr++;
  605.             reserve(n);
  606.             for (i = 0; i < n; i++, ptr += 2)
  607.                tape_image[tape_imagesize++] = find_pulse(*(unsigned short*)ptr);
  608.             break;
  609.          case 0x14: // pure data block
  610.             create_appendable_block();
  611.             size = 0xFFFFFF & *(unsigned*)(ptr+7);
  612.             makeblock(ptr + 0x0A, size, 0, 0, 0, *(unsigned short*)ptr,
  613.                       *(unsigned short*)(ptr+2), -1, *(unsigned short*)(ptr+5), ptr[4]);
  614.             ptr += size + 0x0A;
  615.             break;
  616.          case 0x15: // direct recording
  617.             size = 0xFFFFFF & *(unsigned*)(ptr+5);
  618.             t0 = *(unsigned short*)ptr;
  619.             pause = *(unsigned short*)(ptr+2);
  620.             last = ptr[4];
  621.             named_cell("direct recording");
  622.             ptr += 8;
  623.             pl = 0; n = 0;
  624.             for (i = 0; i < size; i++) // count number of pulses
  625.                for (j = 0x80; j; j >>= 1)
  626.                   if ((ptr[i] ^ pl) & j) n++, pl ^= -1;
  627.             t = 0; pl = 0;
  628.             reserve(n+2);
  629.             for (i = 1; i < size; i++, ptr++) // find pulses
  630.                for (j = 0x80; j; j >>= 1) {
  631.                   t += t0;
  632.                   if ((*ptr ^ pl) & j) {
  633.                      tape_image[tape_imagesize++] = find_pulse(t);
  634.                      pl ^= -1; t = 0;
  635.                   }
  636.                }
  637.             // find pulses - last byte
  638.             for (j = 0x80; j != (unsigned char)(0x80 >> last); j >>= 1) {
  639.                t += t0;
  640.                if ((*ptr ^ pl) & j) {
  641.                   tape_image[tape_imagesize++] = find_pulse(t);
  642.                   pl ^= -1; t = 0;
  643.                }
  644.             }
  645.             ptr++;
  646.             tape_image[tape_imagesize++] = find_pulse(t); // last pulse ???
  647.             if (pause) tape_image[tape_imagesize++] = find_pulse(pause*3500);
  648.             break;
  649.          case 0x20: // pause (silence) or 'stop the tape' command
  650.             pause = *(unsigned short*)ptr;
  651.             sprintf(nm, pause? "pause %d ms" : "stop the tape", pause);
  652.             named_cell(nm);
  653.             reserve(2); ptr += 2;
  654.             if (!pause) { // at least 1ms pulse as specified in TZX 1.13
  655.                tape_image[tape_imagesize++] = find_pulse(3500);
  656.                pause = -1;
  657.             } else pause *= 3500;
  658.             tape_image[tape_imagesize++] = find_pulse(pause);
  659.             break;
  660.          case 0x21: // group start
  661.             n = *ptr++;
  662.             named_cell(ptr, n); ptr += n;
  663.             appendable = 1;
  664.             break;
  665.          case 0x22: // group end
  666.             break;
  667.          case 0x23: // jump to block
  668.             named_cell("* jump"); ptr += 2;
  669.             break;
  670.          case 0x24: // loop start
  671.             loop_n = *(unsigned short*)ptr; loop_p = tape_imagesize; ptr += 2;
  672.             break;
  673.          case 0x25: // loop end
  674.             if (!loop_n) break;
  675.             size = tape_imagesize - loop_p;
  676.             reserve((loop_n-1) * size);
  677.             for (i = 1; i < loop_n; i++)
  678.                memcpy(tape_image + loop_p + i*size, tape_image + loop_p, size);
  679.             tape_imagesize += (loop_n-1) * size;
  680.             loop_n = 0;
  681.             break;
  682.          case 0x26: // call
  683.             named_cell("* call"); ptr += 2 + 2 * *(unsigned short*)ptr;
  684.             break;
  685.          case 0x27: // ret
  686.             named_cell("* return");
  687.             break;
  688.          case 0x28: // select block
  689.             {
  690.                 int l = _countof(nm);
  691.                 l -= sprintf(nm, "* choice: ");
  692.                 n = ptr[2];
  693.                 p = (char*)ptr+3;
  694.  
  695.                 for (i = 0; i < n; i++)
  696.                 {
  697.                    size = *(unsigned char*)(p+2);
  698.                    l -= size;
  699.                    if(i)
  700.                        l -= 4;
  701.  
  702.                    if(l >= 0)
  703.                    {
  704.                        if (i)
  705.                            strcat(nm, " / ");
  706.  
  707.                        char *q = nm + strlen(nm);
  708.                        memcpy(q, p+3, size);
  709.                        q[size] = 0;
  710.                    }
  711.  
  712.                    p += size+3;
  713.                 }
  714.                 named_cell(nm);
  715.                 ptr += 2 + *(unsigned short*)ptr;
  716.             }
  717.             break;
  718.          case 0x2A: // stop if 48k
  719.             named_cell("* stop if 48K");
  720.             ptr += 4 + *(unsigned*)ptr;
  721.             break;
  722.          case 0x30: // text description
  723.             n = *ptr++;
  724.             named_cell(ptr, n); ptr += n;
  725.             appendable = 1;
  726.             break;
  727.          case 0x31: // message block
  728.             named_cell("- MESSAGE BLOCK ");
  729.             end = ptr + 2 + ptr[1]; pl = *end; *(char *)end = 0;
  730.             for (p = (char*)ptr+2; p < (char*)end; p++)
  731.                if (*p == 0x0D) *p = 0;
  732.             for (p = (char*)ptr+2; p < (char*)end; p += strlen(p)+1)
  733.                named_cell(p);
  734.             *(char *)end = pl; ptr = end;
  735.             named_cell("-");
  736.             break;
  737.          case 0x32: // archive info
  738.             named_cell("- ARCHIVE INFO ");
  739.             p = (char*)ptr + 3;
  740.             for (i = 0; i < ptr[2]; i++) {
  741.                const char *info;
  742.                switch (*p++) {
  743.                   case 0: info = "Title"; break;
  744.                   case 1: info = "Publisher"; break;
  745.                   case 2: info = "Author"; break;
  746.                   case 3: info = "Year"; break;
  747.                   case 4: info = "Language"; break;
  748.                   case 5: info = "Type"; break;
  749.                   case 6: info = "Price"; break;
  750.                   case 7: info = "Protection"; break;
  751.                   case 8: info = "Origin"; break;
  752.                   case -1:info = "Comment"; break;
  753.                   default:info = "info"; break;
  754.                }
  755.                unsigned size = *(BYTE*)p+1;
  756.                char tmp = p[size]; p[size] = 0;
  757.                sprintf(nm, "%s: %s", info, p+1);
  758.                p[size] = tmp; p += size;
  759.                named_cell(nm);
  760.             }
  761.             named_cell("-");
  762.             ptr += 2 + *(unsigned short*)ptr;
  763.             break;
  764.          case 0x33: // hardware type
  765.             parse_hardware(ptr);
  766.             ptr += 1 + 3 * *ptr;
  767.             break;
  768.          case 0x34: // emulation info
  769.             named_cell("* emulation info"); ptr += 8;
  770.             break;
  771.          case 0x35: // custom info
  772.             if (!memcmp(ptr, "POKEs           ", 16)) {
  773.                named_cell("- POKEs block ");
  774.                named_cell(ptr+0x15, ptr[0x14]);
  775.                p = (char*)ptr + 0x15 + ptr[0x14];
  776.                n = *(unsigned char*)p++;
  777.                for (i = 0; i < n; i++) {
  778.                   named_cell(p+1, *(unsigned char*)p);
  779.                   p += *p+1;
  780.                   t = *(unsigned char*)p++;
  781.                   strcpy(nm, "POKE ");
  782.                   for (j = 0; j < t; j++) {
  783.                      sprintf(nm+strlen(nm), "%d,", *(unsigned short*)(p+1));
  784.                      sprintf(nm+strlen(nm), *p & 0x10 ? "nn" : "%d", *(unsigned char*)(p+3));
  785.                      if (!(*p & 0x08)) sprintf(nm+strlen(nm), "(page %d)", *p & 7);
  786.                      strcat(nm, "; "); p += 5;
  787.                   }
  788.                   named_cell(nm);
  789.                }
  790.                *(unsigned*)nm = '-';
  791.             } else sprintf(nm, "* custom info: %s", ptr), nm[15+16] = 0;
  792.             named_cell(nm);
  793.             ptr += 0x14 + *(unsigned*)(ptr+0x10);
  794.             break;
  795.          case 0x40: // snapshot
  796.             named_cell("* snapshot"); ptr += 4 + (0xFFFFFF & *(unsigned*)(ptr + 1));
  797.             break;
  798.          default:
  799.             if(TzxVer >= 0x10A)
  800.             {
  801.                 // ┬ эрўрых ърцфюую эхёЄрэфрЁЄэюую сыюър шфхЄ хую фышэр
  802.                 sprintf(nm, "* unknown id: 0x%X", ptr[-1]);
  803.                 named_cell(nm);
  804.                 u32 Skip = *(u32 *)ptr;
  805.                 ptr += Skip + sizeof(u32);
  806.             }
  807.             else
  808.             {
  809.                 ptr += snapsize;
  810.             }
  811.       }
  812.    }
  813.    for (i = 0; i < tape_infosize; i++) {
  814.       if (*(short*)tapeinfo[i].desc == WORD2('*', ' '))
  815.       {
  816.          if(strlen(tapeinfo[i].desc) < _countof(tapeinfo[i].desc) - sizeof(" [UNSUPPORTED]"))
  817.              strcat(tapeinfo[i].desc, " [UNSUPPORTED]");
  818.          else
  819.          {
  820.              strcpy(tapeinfo[i].desc + _countof(tapeinfo[i].desc) - sizeof(" [UNSUPPORTED]"), " [UNSUPPORTED]");
  821.          }
  822.       }
  823.       if (*tapeinfo[i].desc == '-')
  824.          while (strlen(tapeinfo[i].desc) < sizeof(tapeinfo[i].desc)-1)
  825.             strcat(tapeinfo[i].desc, "-");
  826.    }
  827.    if (tape_imagesize && tape_pulse[tape_image[tape_imagesize-1]] < 350000)
  828.       reserve(1), tape_image[tape_imagesize++] = find_pulse(350000); // small pause [rqd for 3ddeathchase]
  829.    find_tape_sizes();
  830.    return (ptr == snbuf+snapsize);
  831. }
  832.  
  833. unsigned char tape_bit() // used in io.cpp & sound.cpp
  834. {
  835.    __int64 cur = comp.t_states + cpu.t;
  836.    if (cur < comp.tape.edge_change)
  837.        return (unsigned char)comp.tape.tape_bit;
  838.    while (comp.tape.edge_change < cur)
  839.    {
  840.       if (!temp.sndblock)
  841.       {
  842.          unsigned t = (unsigned)(comp.tape.edge_change - comp.t_states - temp.cpu_t_at_frame_start);
  843.          if ((int)t >= 0)
  844.          {
  845.             unsigned tape_in = conf.sound.micin_vol & comp.tape.tape_bit;
  846. //            comp.tape.sound.update(t, tape_in, tape_in); //Alone Coder
  847.             comp.tape_sound.update(t, tape_in, tape_in); //Alone Coder
  848.          }
  849.       }
  850.       unsigned pulse; comp.tape.tape_bit ^= -1;
  851.       if (comp.tape.play_pointer == comp.tape.end_of_tape ||
  852.           (pulse = tape_pulse[*comp.tape.play_pointer++]) == -1)
  853.               stop_tape();
  854.       else
  855.           comp.tape.edge_change += pulse;
  856.    }
  857.    return (unsigned char)comp.tape.tape_bit;
  858. }
  859.  
  860. void fast_tape()
  861. {
  862.    unsigned char *ptr = am_r(cpu.pc);
  863.    unsigned p = *(unsigned*)ptr;
  864.    if (p == WORD4(0x3D,0x20,0xFD,0xA7))
  865.    { // dec a:jr nz,$-1
  866.       cpu.t += ((unsigned char)(cpu.a-1))*16; cpu.a = 1;
  867.       return;
  868.    }
  869.    if ((unsigned short)p == WORD2(0x10,0xFE))
  870.    { // djnz $
  871.       cpu.t += ((unsigned char)(cpu.b-1))*13; cpu.b = 1;
  872.       return;
  873.    }
  874.    if ((unsigned short)p == WORD2(0x3D,0xC2) && (cpu.pc & 0xFFFF)==(p>>16))
  875.    { // dec a:jp nz,$-1
  876.       cpu.t += ((unsigned char)(cpu.a-1))*14; cpu.a = 1;
  877.       return;
  878.    }
  879.    if ((p | WORD4(0,0,0,0xFF)) == WORD4(0x04,0xC8,0x3E,0xFF))
  880.    {
  881.       if (*(unsigned*)(ptr+4) == WORD4(0xDB,0xFE,0x1F,0xD0) &&
  882.           *(unsigned*)(ptr+8) == WORD4(0xA9,0xE6,0x20,0x28) && ptr[12] == 0xF3)
  883.       { // find edge (rom routine)
  884.          for (;;)
  885.          {
  886.             if (cpu.b == 0xFF)
  887.                 return;
  888.             if ((tape_bit() ? 0x20 : 0) ^ (cpu.c & 0x20))
  889.                 return;
  890.             cpu.b++; cpu.t += 59;
  891.          }
  892.       }
  893.       if (*(unsigned*)(ptr+4) == WORD4(0xDB,0xFE,0xCB,0x1F) &&
  894.           *(unsigned*)(ptr+8) == WORD4(0xA9,0xE6,0x20,0x28) && ptr[12] == 0xF3)
  895.       { // rra,ret nc => rr a (popeye2)
  896.          for (;;)
  897.          {
  898.             if (cpu.b == 0xFF) return;
  899.             if ((tape_bit() ^ cpu.c) & 0x20) return;
  900.             cpu.b++; cpu.t += 58;
  901.          }
  902.       }
  903.       if (*(unsigned*)(ptr+4) == WORD4(0xDB,0xFE,0x1F,0x00) &&
  904.           *(unsigned*)(ptr+8) == WORD4(0xA9,0xE6,0x20,0x28) && ptr[12] == 0xF3)
  905.       { // ret nc nopped (some bleep loaders)
  906.          for (;;)
  907.          {
  908.             if (cpu.b == 0xFF) return;
  909.             if ((tape_bit() ^ cpu.c) & 0x20) return;
  910.             cpu.b++; cpu.t += 58;
  911.          }
  912.       }
  913.       if (*(unsigned*)(ptr+4) == WORD4(0xDB,0xFE,0xA9,0xE6) &&
  914.           *(unsigned*)(ptr+8) == WORD4(0x40,0xD8,0x00,0x28) && ptr[12] == 0xF3)
  915.       { // no rra, no break check (rana rama)
  916.          for (;;)
  917.          {
  918.             if (cpu.b == 0xFF) return;
  919.             if ((tape_bit() ^ cpu.c) & 0x40) return;
  920.             cpu.b++; cpu.t += 59;
  921.          }
  922.       }
  923.       if (*(unsigned*)(ptr+4) == WORD4(0xDB,0xFE,0x1F,0xA9) &&
  924.           *(unsigned*)(ptr+8) == WORD4(0xE6,0x20,0x28,0xF4))
  925.       { // ret nc skipped: routine without BREAK checking (ZeroMusic & JSW)
  926.          for (;;)
  927.          {
  928.             if (cpu.b == 0xFF) return;
  929.             if ((tape_bit() ^ cpu.c) & 0x20) return;
  930.             cpu.b++; cpu.t += 54;
  931.          }
  932.       }
  933.    }
  934.    if ((p | WORD4(0,0,0,0xFF)) == WORD4(0x04,0x20,0x03,0xFF) &&
  935.         ptr[6] == 0xDB && *(unsigned*)(ptr+8) == WORD4(0x1F,0xC8,0xA9,0xE6) &&
  936.         (*(unsigned*)(ptr+0x0C) | WORD4(0,0,0,0xFF)) == WORD4(0x20,0x28,0xF1,0xFF))
  937.    { // find edge from Donkey Kong
  938.       for (;;) {
  939.          if (cpu.b == 0xFF) return;
  940.          if ((tape_bit() ^ cpu.c) & 0x20) return;
  941.          cpu.b++; cpu.t += 59;
  942.       }
  943.    }
  944.    if ((p | WORD4(0,0xFF,0,0)) == WORD4(0x3E,0xFF,0xDB,0xFE) &&
  945.        *(unsigned*)(ptr+4) == WORD4(0xA9,0xE6,0x40,0x20) &&
  946.        (*(unsigned*)(ptr+8) | WORD4(0xFF,0,0,0)) == WORD4(0xFF,0x05,0x20,0xF4))
  947.    { // lode runner
  948.       for (;;)
  949.       {
  950.          if (cpu.b == 1) return;
  951.          if ((tape_bit() ^ cpu.c) & 0x40) return;
  952.          cpu.t += 52; cpu.b--;
  953.       }
  954.    }
  955. }
  956.  
  957. void tape_traps()
  958. {
  959.    unsigned pulse;
  960.    do
  961.    {
  962.        if(comp.tape.play_pointer>=comp.tape.end_of_tape ||
  963.           (pulse=tape_pulse[*comp.tape.play_pointer++])==-1)
  964.        {
  965.            stop_tape();
  966.            return;
  967.        }
  968.    }while(pulse > 770);
  969.    comp.tape.play_pointer++;
  970.  
  971.    // loading header
  972.    cpu.l=0;
  973.    cpu.h = 0;
  974.    for(unsigned bit=0x80;bit;bit>>=1)
  975.    {
  976.        if(comp.tape.play_pointer>=comp.tape.end_of_tape||
  977.          (pulse=tape_pulse[*comp.tape.play_pointer++])==-1)
  978.        {
  979.          stop_tape();
  980.          cpu.pc = 0x05DF;
  981.          return;
  982.        }
  983.        cpu.l |= (pulse>1240) ? bit : 0;
  984.        comp.tape.play_pointer++;
  985.    }
  986.    cpu.h ^= cpu.l;
  987.  
  988.    // loading data
  989.    do
  990.    {
  991.      cpu.l = 0;
  992.      for(unsigned bit=0x80; bit; bit >>= 1)
  993.      {
  994.        if(comp.tape.play_pointer >= comp.tape.end_of_tape ||
  995.           (pulse = tape_pulse[*comp.tape.play_pointer++])==-1)
  996.        {
  997.          stop_tape();
  998.          cpu.pc = 0x05DF;
  999.          return;
  1000.        }
  1001.        cpu.l |= (pulse > 1240) ? bit : 0;
  1002.        comp.tape.play_pointer++;
  1003.      }
  1004.      cpu.h ^= cpu.l;
  1005.      cpu.DbgMemIf->wm(cpu.ix++, cpu.l);
  1006.      cpu.de--;
  1007.    }while(cpu.de & 0xFFFF);
  1008.  
  1009.    // loading CRC
  1010.    cpu.l = 0;
  1011.    for(unsigned bit = 0x80; bit; bit >>= 1)
  1012.    {
  1013.      if(comp.tape.play_pointer>=comp.tape.end_of_tape||
  1014.        (pulse=tape_pulse[*comp.tape.play_pointer++])==-1)
  1015.      {
  1016.        stop_tape();
  1017.        cpu.pc = 0x05DF;
  1018.        return;
  1019.      }
  1020.      cpu.l |= (pulse > 1240) ? bit : 0;
  1021.      comp.tape.play_pointer++;
  1022.    }
  1023.    cpu.h ^= cpu.l;
  1024.    cpu.pc = 0x05DF; // ld a,h / cp 01 / ret
  1025.    cpu.bc = 0xB001;
  1026.  
  1027.    comp.tape.play_pointer++;
  1028.    stop_tape();
  1029.  
  1030.      /*cpu.pc=0x0604; // the old one
  1031.      unsigned pulse;
  1032.      pulse = tape_pulse[*comp.tape.play_pointer++];
  1033.      if(pulse == -1) stop_tape();
  1034.      else{
  1035.        comp.t_states+=pulse;
  1036.        comp.tape.edge_change = comp.t_states + cpu.t + 520;
  1037.  
  1038.        cpu.b+=(pulse-520)/56;
  1039.        cpu.f|=CF;
  1040.      }*/
  1041. }
  1042.