Subversion Repositories pentevo

Rev

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

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "memory.h"
  6. #include "dbglabls.h"
  7.  
  8. #include "util.h"
  9.  
  10. char asmbuf[0x40];
  11.  
  12. #define _iw  9
  13. #define _ib  10
  14. #define _shrt 27
  15. #define _ld 0x89
  16. #define _zr16 0x8A
  17. #define _zr8 0x8B
  18. #define _cb 0x8C
  19. #define _zjr 0x8D
  20. #define _hl 0x8E
  21. #define _zr81 0x8F
  22. #define _zop 0x90
  23. #define _zf 0x91
  24. #define _zr16a 0x92
  25. #define _zr8_ 0x9D
  26. #define _zr81_ 0x9E
  27.  
  28. unsigned char asm_tab_z80[] =
  29. {
  30. #if 0
  31.    2,0xED,0xFF,0xFF,0xFF, // call unreal api
  32.    'u','a','p','i',0,
  33. #endif
  34.  
  35.    // fix bug out (c),a => out (0C),a
  36.    2, 0xED, 0x70, 0xFF, 0xFF, // in (c)
  37.    'i','n',' ','(','c',')',0,
  38.    2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0
  39.    'o','u','t',' ','(','c',')',',','0',0,
  40.    2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c)
  41.    'i','n',' ',_zr8,',','(','c',')',0,
  42.    2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8
  43.    'o','u','t',' ','(','c',')',',',_zr8,0,
  44.  
  45.  
  46.    1,0xCB,0xFF, // all cb-opcodes
  47.    _cb,0,
  48.    1, 0x00, 0xFF, // nop
  49.    'n','o','p',0,
  50.    1, 0x08, 0xFF, // ex af,af'
  51.    'e','x',' ','a','f',',','a','f','\'',0,
  52.    1,0x02, 0xFF, // ld (bc),a
  53.    _ld, '(','b','c',')',',','a',0,
  54.    1,0x12, 0xFF, // ld (de),a
  55.    _ld, '(','d','e',')',',','a',0,
  56.    1,0x0A, 0xFF, // ld a,(bc)
  57.    _ld, 'a',',','(','b','c',')',0,
  58.    1,0x1A, 0xFF, // ld a,(de)
  59.    _ld, 'a',',','(','d','e',')',0,
  60.    1,0x03,0xCF, // inc r16
  61.    'i','n','c',' ',_zr16,0,
  62.    1,0x0B,0xCF, // dec r16
  63.    'd','e','c',' ',_zr16,0,
  64.    1,0x04,0xC7, // inc r8
  65.    'i','n','c',' ', _zr8,0,
  66.    1, 0x05, 0xC7, // dec r8
  67.    'd','e','c',' ', _zr8,0,
  68.    1, 0x07, 0xFF, // rlca
  69.    'r','l','c','a',0,
  70.    1, 0x17, 0xFF, // rla
  71.    'r','l','a',0,
  72.    1, 0x27, 0xFF, // daa
  73.    'd','a','a',0,
  74.    1, 0x37, 0xFF, // scf
  75.    's','c','f',0,
  76.    1, 0x0F, 0xFF, // rrca
  77.    'r','r','c','a',0,
  78.    1, 0x1F, 0xFF, // rra
  79.    'r','r','a',0,
  80.    1, 0x2F, 0xFF, // cpl
  81.    'c','p','l',0,
  82.    1, 0x3F, 0xFF, // ccf
  83.    'c','c','f',0,
  84.    1, 0x00, 0xC7, // relative jumps
  85.    _zjr, _shrt, 0,
  86.    1, 0x09, 0xCF, // add hl, r16
  87.    'a','d','d',' ',_hl,',',_zr16,0,
  88.    1, 0x32, 0xFF, // ld (nnnn),a
  89.    _ld,'(',_iw,')',',','a',0,
  90.    1, 0x3A, 0xFF, // ld a,(nnnn)
  91.    _ld,'a',',','(',_iw,')',0,
  92.    1, 0x22, 0xFF, // ld (nnnn),hl
  93.    _ld,'(',_iw,')',',',_hl,0,
  94.    1, 0x2A, 0xFF, // ld hl,(nnnn)
  95.    _ld,_hl,',','(',_iw,')',0,
  96.    1, 0x76, 0xFF, // halt
  97.    'h','a','l','t',0,
  98.    1, 0x40, 0xC0, // ld r8,r8
  99.    _ld, _zr8_, ',', _zr81_, 0,
  100.    1, 0x80, 0xC0, // op r8
  101.    _zop/*, ' '*/, _zr81, 0,
  102.    1, 0xC0, 0xC7, // ret cc
  103.    'r','e','t',' ',_zf,0,
  104.    1, 0xC2, 0xC7, // jp cc, nnnn
  105.    'j','p',' ',_zf,',',_iw,0,
  106.    1, 0xC4, 0xC7, // call cc, nnnn
  107.    'c','a','l','l',' ',_zf,',',_iw,0,
  108.    1, 0xC6, 0xC7, // op immb
  109.    _zop/*, ' '*/, _ib, 0,
  110.    1, 0xC1, 0xCF, // pop r16a
  111.    'p','o','p',' ',_zr16a,0,
  112.    1, 0xC5, 0xCF, // push r16a
  113.    'p','u','s','h',' ',_zr16a,0,
  114.    1, 0xC3, 0xFF, // jp nnnn
  115.    'j','p', ' ', _iw,0,
  116.    1, 0xD3, 0xFF, // out (nn),a
  117.    'o','u','t',' ','(',_ib,')',',','a',0,
  118.    1, 0xE3, 0xFF, // ex (sp),hl
  119.    'e','x',' ','(','s','p',')',',',_hl,0,
  120.    1, 0xF3, 0xFF, // di
  121.    'd','i',0,
  122.    1, 0xC9, 0xFF, // ret
  123.    'r','e','t',0,
  124.    1, 0xD9, 0xFF, // exx
  125.    'e','x','x',0,
  126.    1, 0xE9, 0xFF, // jp (hl)
  127.    'j','p',' ','(',_hl,')',0,
  128.    1, 0xF9, 0xFF, // ld sp, hl
  129.    _ld, 's','p',',',_hl,0,
  130.    1, 0xDB, 0xFF, // in a,(nn)
  131.    'i','n',' ','a',',','(',_ib,')',0,
  132.    1, 0xEB, 0xFF,  // ex de,hl  - no 'ex de,ix' !
  133.    'e','x',' ','d','e',',','h','l',0,
  134.    1, 0xFB, 0xFF, // ei
  135.    'e','i',0,
  136.    1, 0xCD, 0xFF, // call nnnn
  137.    'c','a','l','l',' ',_iw,0,
  138.    1, 0xC7, 0xFF, // rst 0
  139.    'r','s','t',' ','0',0,
  140.    1, 0xCF, 0xFF, // rst 8
  141.    'r','s','t',' ','8',0,
  142.    1, 0xD7, 0xFF, // rst 10
  143.    'r','s','t',' ','1','0',0,
  144.    1, 0xDF, 0xFF, // rst 18
  145.    'r','s','t',' ','1','8',0,
  146.    1, 0xE7, 0xFF, // rst 20
  147.    'r','s','t',' ','2','0',0,
  148.    1, 0xEF, 0xFF, // rst 28
  149.    'r','s','t',' ','2','8',0,
  150.    1, 0xF7, 0xFF, // rst 30
  151.    'r','s','t',' ','3','0',0,
  152.    1, 0xFF, 0xFF, // rst 38
  153.    'r','s','t',' ','3','8',0,
  154.  
  155.  
  156.    // ED opcodes
  157. #if 0 // moved above
  158.    2, 0xED, 0x70, 0xFF, 0xFF, // in (c)
  159.    'i','n',' ','(','c',')',0,
  160.    2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0
  161.    'o','u','t',' ','(','c',')',',','0',0,
  162.    2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c)
  163.    'i','n',' ',_zr8,',','(','c',')',0,
  164.    2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8
  165.    'o','u','t',' ','(','c',')',',',_zr8,0,
  166. #endif
  167.    2, 0xED, 0x42, 0xFF, 0xCF, // sbc hl,r16
  168.    's','b','c',' ','h','l',',',_zr16,0,
  169.    2, 0xED, 0x4A, 0xFF, 0xCF, // adc hl,r16
  170.    'a','d','c',' ','h','l',',',_zr16,0,
  171.    2, 0xED, 0x43, 0xFF, 0xCF, // ld (nnnn), r16
  172.    _ld, '(',_iw,')',',',_zr16, 0,
  173.    2, 0xED, 0x4B, 0xFF, 0xCF, // ld r16, (nnnn)
  174.    _ld, _zr16, ',', '(',_iw,')', 0,
  175.    2, 0xED, 0x44, 0xFF, 0xC7, // neg
  176.    'n','e','g',0,
  177.    2, 0xED, 0x45, 0xFF, 0xCF, // retn
  178.    'r','e','t','n',0,
  179.    2, 0xED, 0x4D, 0xFF, 0xCF, // reti
  180.    'r','e','t','i',0,
  181.    2, 0xED, 0x46, 0xFF, 0xDF, // im 0
  182.    'i','m',' ','0',0,
  183.    2, 0xED, 0x56, 0xFF, 0xDF, // im 1
  184.    'i','m',' ','1',0,
  185.    2, 0xED, 0x5E, 0xFF, 0xDF, // im 2
  186.    'i','m',' ','2',0,
  187.    2, 0xED, 0x4E, 0xFF, 0xDF, // im 0/1
  188.    'i','m',' ','0','/','1',0,
  189.    2, 0xED, 0x47, 0xFF, 0xFF, // ld i,a
  190.    _ld, 'i',',','a',0,
  191.    2, 0xED, 0x57, 0xFF, 0xFF, // ld a,i
  192.    _ld, 'a',',','i',0,
  193.    2, 0xED, 0x67, 0xFF, 0xFF, // rrd
  194.    'r','r','d',0,
  195.    2, 0xED, 0x4F, 0xFF, 0xFF, // ld r,a
  196.    _ld, 'r',',','a',0,
  197.    2, 0xED, 0x5F, 0xFF, 0xFF, // ld a,r
  198.    _ld, 'a',',','r',0,
  199.    2, 0xED, 0x6F, 0xFF, 0xFF, // rld
  200.    'r','l','d',0,
  201.  
  202.    2, 0xED, 0xA0, 0xFF, 0xFF, // ldi
  203.    'l','d','i',0,
  204.    2, 0xED, 0xA1, 0xFF, 0xFF, // cpi
  205.    'c','p','i',0,
  206.    2, 0xED, 0xA2, 0xFF, 0xFF, // ini
  207.    'i','n','i',0,
  208.    2, 0xED, 0xA3, 0xFF, 0xFF, // outi
  209.    'o','u','t','i',0,
  210.    2, 0xED, 0xA8, 0xFF, 0xFF, // ldd
  211.    'l','d','d',0,
  212.    2, 0xED, 0xA9, 0xFF, 0xFF, // cpd
  213.    'c','p','d',0,
  214.    2, 0xED, 0xAA, 0xFF, 0xFF, // ind
  215.    'i','n','d',0,
  216.    2, 0xED, 0xAB, 0xFF, 0xFF, // outd
  217.    'o','u','t','d',0,
  218.  
  219.    2, 0xED, 0xB0, 0xFF, 0xFF, // ldir
  220.    'l','d','i','r',0,
  221.    2, 0xED, 0xB1, 0xFF, 0xFF, // cpir
  222.    'c','p','i','r',0,
  223.    2, 0xED, 0xB2, 0xFF, 0xFF, // inir
  224.    'i','n','i','r',0,
  225.    2, 0xED, 0xB3, 0xFF, 0xFF, // otir
  226.    'o','t','i','r',0,
  227.    2, 0xED, 0xB8, 0xFF, 0xFF, // lddr
  228.    'l','d','d','r',0,
  229.    2, 0xED, 0xB9, 0xFF, 0xFF, // cpdr
  230.    'c','p','d','r',0,
  231.    2, 0xED, 0xBA, 0xFF, 0xFF, // indr
  232.    'i','n','d','r',0,
  233.    2, 0xED, 0xBB, 0xFF, 0xFF, // otdr
  234.    'o','t','d','r',0,
  235.  
  236.    2, 0xED, 0x00, 0xFF, 0x00, // all others 'ED'
  237.    'n','o','p','*',0,
  238.  
  239.    // place immediates after all - 'ld a,b' is not 'ld a,0B'
  240.    1, 0x01, 0xCF, // ld r16,imm16
  241.    _ld, _zr16, ',', _iw, 0,
  242.    1, 0x06, 0xC7, // ld r8, imm8
  243.    _ld, _zr8, ',', _ib, 0,
  244.  
  245.    0 // end
  246. };
  247.  
  248.  
  249. #define abs(x) ((x)>0? (x):(-(x)))
  250.  
  251. // =======================================================================
  252. char z80r16_1[] = "bc\0de\0hl\0sp";
  253. char z80r16_2[] = "bc\0de\0ix\0sp";
  254. char z80r16_3[] = "bc\0de\0iy\0sp";
  255. char z80r8_1[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0h\0\0\0\0l\0\0\0\0(hl)\0a";
  256. char z80r8_2[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0xh\0\0\0xl\0\0\0(1x)\0a";
  257. char z80r8_3[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0yh\0\0\0yl\0\0\0(1y)\0a";
  258. char cbtab[] = "rlc \0\0\0rrc \0\0\0rl \0\0\0\0rr \0\0\0\0sla \0\0\0sra \0\0\0sli \0\0\0srl \0\0\0"
  259.                "bit 0,\0bit 1,\0bit 2,\0bit 3,\0bit 4,\0bit 5,\0bit 6,\0bit 7,\0"
  260.                "res 0,\0res 1,\0res 2,\0res 3,\0res 4,\0res 5,\0res 6,\0res 7,\0"
  261.                "set 0,\0set 1,\0set 2,\0set 3,\0set 4,\0set 5,\0set 6,\0set 7,\0";
  262. char zjr[] = "xxxxxx\0xxxxxx\0djnz \0\0jr \0\0\0\0jr nz,\0jr z,\0\0jr nc,\0jr c,\0";
  263. //char zop[] = "add\0adc\0sub\0sbc\0and\0xor\0or\0\0cp"; lvd
  264. char zop[] = "add a,\0\0adc a,\0\0sub \0\0\0\0sbc a,\0\0and \0\0\0\0xor \0\0\0\0or \0\0\0\0\0cp \0\0\0\0\0";
  265. char zf[] = "nz\0z\0\0nc\0c\0\0po\0pe\0p\0\0m";
  266. // =======================================================================
  267.  
  268. void disasm_address(char *line, unsigned addr, char labels)
  269. {
  270.    char *label = 0;
  271.    if (labels&&addr) label = mon_labels.find(am_r(addr));
  272.    if (label) {
  273.            //strcpy(line, label);
  274.                 int i;
  275.                 for (i=0;(i<20)&&label[i];i++)line[i]=label[i];
  276.                 line[i]=label[i];
  277.    } //Alone Coder 0.36.6
  278.    else sprintf(line, "%04X", addr & 0xFFFF);
  279. }
  280.  
  281. unsigned char *disasm(unsigned char *cmd, unsigned current, char labels)
  282. {
  283.    unsigned char *st = cmd, z80p;
  284.    char *z80r16, *z80r8;
  285.  
  286.    z80r16 = z80r16_1, z80r8 = z80r8_1, z80p = 0;
  287.    for (;;) { // z80 prefixes
  288.       if (*cmd == 0xDD) z80r16 = z80r16_2, z80r8 = z80r8_2, z80p = 0xDD;
  289.       else if (*cmd == 0xFD) z80r16 = z80r16_3, z80r8 = z80r8_3, z80p = 0xFD;
  290.       else break;
  291.       cmd++;
  292.    }
  293.  
  294.    for (unsigned char *ptr = asm_tab_z80; *ptr; ) {
  295.       // cmd - start of command, c1 - mod/rm, cm - current pointer
  296.       unsigned char *rcmd = cmd;
  297.       if (*cmd == 0xED) rcmd++, z80r16 = z80r16_1, z80r8 = z80r8_1, z80p = 0;
  298.       unsigned char *cm = rcmd+1;
  299.  
  300.       for (int j = 0; j < *ptr; j++) // match mask
  301.          if ((cmd[j] & ptr[j+*ptr+1]) != ptr[j+1]) goto nextcmd;
  302.       *asmbuf = 0;
  303.       unsigned char *pt;
  304.       for (pt = ptr + (2 * *ptr) + 1; *pt; pt++) { // scan all commands
  305.          char ln[/*32*/64];
  306.          const char *l1 = ln;
  307.          ln[0] = 0; //Alone Coder 0.36.6
  308.          switch (*pt) {
  309.             case _zr16: // in rcmd & 0x30
  310.                l1 = z80r16+3*((*rcmd>>4) & 3);
  311.                break;
  312.             case _zr16a: // in rcmd & 0x30
  313.                if (((*rcmd>>4)&3) == 3) l1 = "af";
  314.                else l1 = z80r16+3*((*rcmd>>4) & 3);
  315.                break;
  316.             case _hl: // hl/ix/iy
  317.                l1 = z80r16+3*2;
  318.                break;
  319.             case _zjr: // relative jumps
  320.                l1 = zjr+7*((*rcmd>>3)&7);
  321.                break;
  322.             case _zop: // z80 operations at rcmd & 0x38
  323.                //l1 = zop+4*((*rcmd>>3)&7); lvd
  324.                l1 = zop+8*((*rcmd>>3)&7);
  325.                break;
  326.             case _zf: // z80 flags at rcmd & 0x38
  327.                l1 = zf+3*((*rcmd>>3)&7);
  328.                break;
  329.             case _cb: // all CB-opcodes
  330.             {
  331.                if (!z80p) {
  332.                   sprintf(ln, "%s%s", cbtab+(*cm>>3)*7, z80r8_1+(*cm&7)*5);
  333.                   cm++;
  334.                } else {
  335.                   if ((cm[1] & 7) != 6 && ((cm[1] & 0xC0) != 0x40)) // operand is reg,(ix+nn)
  336.                      sprintf(ln, "%s%s,(i%c%c%02X)", cbtab+(cm[1]>>3)*7, z80r8_1+(cm[1]&7)*5, z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm));
  337.                   else // only (ix+nn)
  338.                      sprintf(ln, "%s(i%c%c%02X)", cbtab+(cm[1]>>3)*7, z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm));
  339.                   cm += 2;
  340.                }
  341.                break;
  342.             }
  343.             case _zr8: // in rcmd & 0x38
  344.                if (z80p && ((*rcmd & 0x38) == 0x30)) {
  345.                   sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm));
  346.                   cm++;
  347.                } else l1 = z80r8+5*((*rcmd>>3) & 7);
  348.                break;
  349.             case _zr8_: // in rcmd & 0x38, in ld r8,r8
  350.                if (!z80p || (*rcmd & 7)==6) { l1 = z80r8_1+5*((*rcmd>>3) & 7); break; }
  351.                if ((*rcmd & 0x38) == 0x30) {
  352.                   sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm));
  353.                   cm++;
  354.                } else l1 = z80r8+5*((*rcmd>>3) & 7);
  355.                break;
  356.             case _zr81: // in rcmd & 7
  357.                if (z80p && (*rcmd & 7)==6) {
  358.                   sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm));
  359.                   cm++;
  360.                } else l1 = z80r8+5*(*rcmd & 7);
  361.                break;
  362.             case _zr81_: // in rcmd & 7, in ld r8,r8
  363.                if (!z80p || ((*rcmd & 0x38) == 0x30)) { l1 = z80r8_1+5*(*rcmd & 7); break; }
  364.                if ((*rcmd & 7)==6) {
  365.                   sprintf(ln, "(i%c%c%02X)", z80p==0xDD ? 'x':'y', *(char*)cm>=0?'+':'-',abs(*(char*)cm));
  366.                   cm++;
  367.                } else l1 = z80r8+5*(*rcmd & 7);
  368.                break;
  369.             case _ld:
  370.                l1 = "ld "; break;
  371.             case _shrt: // short jump
  372.                disasm_address(ln, current+cm-st + *(signed char*)cm + 1, labels);
  373.                cm++;
  374.                break;
  375.             case _ib: // immediate byte at cm
  376.                sprintf(ln, "%02X", *cm++);
  377.                break;
  378.             case _iw: // immediate word at cm
  379.                disasm_address(ln, *(unsigned short*)cm, labels); cm += 2;
  380.                break;
  381.             default:
  382.                *(short*)ln = *pt;
  383.          }
  384.          strcat(asmbuf, l1);
  385.       }
  386.       // make tabulation between instruction and operands
  387.           {
  388. //                        if( !cpu.logena ) //LVD
  389.                         {
  390.                                 char b1[0x40], *p = asmbuf, *q = b1;
  391.                                 while (*p != ' ' && *p) *q++ = *p++;
  392.                                 *q++ = *p;
  393.                                 if (*p) {
  394.                                         while (q < b1+5) *q++ = ' '; // +5 - tab size=5, was 4
  395.                                         while (*++p) *q++ = *p;
  396.                                 }
  397.                                 *q = 0;
  398.                                 strcpy(asmbuf, b1);
  399.                         }
  400.          return max(cm, cmd+*ptr);
  401.       }
  402. nextcmd:
  403.       ptr += (2 * *ptr) + 1; while (*ptr++); // skip mask,code and instruction
  404.    }
  405.    strcpy(asmbuf, "???"); return cmd+1;
  406. }
  407.  
  408. int getindex(unsigned char **ptr, char *table, unsigned width, int size) {
  409.    int max = 0, imax; // find max match - fdiv and fdivr must be found as fdivr
  410.    for (int i = 0; i < size; i++) {
  411.       int ln = strlen(table + i*width);
  412.       if (!strncmp((char*)*ptr, table + i*width, ln))
  413.          if (ln > max) max = ln, imax = i;
  414.    }
  415.    if (max) {
  416.       (*ptr) += strlen(table + imax*width);
  417.       return imax;
  418.    }
  419.    return -1;
  420. }
  421. int scanhex(unsigned char **ptr) {
  422.    int r = 0, s = 1;
  423.    if (**ptr == '-') (*ptr)++, s = -1;
  424.    if (**ptr == '+') (*ptr)++;
  425.    while (isdigit(**ptr) || (**ptr >= 'a' && **ptr <= 'f'))
  426.       r = 16*r + hexdigit(**ptr), (*ptr)++;
  427.    return r*s;
  428. }
  429. unsigned char cmdb[16];
  430. unsigned char asmresult[24];
  431. unsigned char z80p;
  432. unsigned char a_command[0x40];
  433.  
  434. int z80scanr8(unsigned char **ptr, unsigned char **cm) {
  435.    int in = getindex(ptr, z80r8_1, 5, 8);
  436.    if (in >= 0) return in;
  437.    char *r8 = z80r8_1;
  438.    if (z80p == 0xDD) r8 = z80r8_2;
  439.    if (z80p == 0xFD) r8 = z80r8_3;
  440.    in = getindex(ptr, r8, 5, 8);
  441.    if (!z80p) return in;
  442.    if (*(unsigned short*)(*ptr) != WORD2('(','i')) return in;
  443.    (*ptr) += 3;
  444.    char c = *(*ptr - 1);
  445.    if ((z80p == 0xDD && c != 'x') || (z80p == 0xFD && c != 'y')) return -1;
  446.    int ofs = (**ptr == ')') ? 0 : scanhex(ptr);
  447.    if (ofs > 127 || ofs < -128) return -1;
  448.    if (*((*ptr)++) != ')') return -1;
  449.    *(signed char*)(*cm)++ = (signed char)ofs;
  450.    return 6;
  451. }
  452.  
  453. int assemble(unsigned addr)
  454. {
  455.    char *z80r16 = z80r16_1;
  456.    if (z80p == 0xDD) z80r16 = z80r16_2;
  457.    if (z80p == 0xFD) z80r16 = z80r16_3;
  458.  
  459.    for (unsigned char *p1 = asm_tab_z80; *p1; ) {
  460.       memset(cmdb, 0, sizeof(cmdb));
  461.       unsigned char *cc = a_command; memcpy(cmdb, p1+1, *p1);
  462.       unsigned char *cmd = cmdb;
  463.       unsigned char *rcmd = cmd;
  464.       unsigned char *cm;
  465.       if (*cmd == 0xED) { rcmd++; if (z80p) goto nextcmd; }
  466.       cm = rcmd+1;
  467.  
  468.       int in;
  469.           unsigned char *ptr; //Alone Coder
  470.       for (/*unsigned char * */ptr = p1+2 * *p1+1; *ptr; ptr++) {
  471.          switch (*ptr) {
  472.             case _zr16: // in rcmd & 0x30
  473.                if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
  474.                *rcmd |= (in << 4);
  475.                break;
  476.             case _zr16a: // in rcmd & 0x30
  477.                if (*(unsigned short*)cc == WORD2('a','f')) {
  478.                   cc += 2;
  479.                   in = 3;
  480.                } else {
  481.                   if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
  482.                }
  483.                *rcmd |= (in << 4);
  484.                break;
  485.             case _zjr: // relative jumps
  486.                if ((in = getindex(&cc, zjr, 7, 8)) < 0) goto nextcmd;
  487.                *rcmd |= (in << 3);
  488.                break;
  489.             case _zop: // z80 ops
  490.                if ((in = getindex(&cc, zop, 8, 8)) < 0) goto nextcmd;
  491.                *rcmd |= (in << 3);
  492.                break;
  493.             case _zf: // z80 flags
  494.                if ((in = getindex(&cc, zf, 3, 8)) < 0) goto nextcmd;
  495.                *rcmd |= (in << 3);
  496.                break;
  497.             case _hl: // hl/ix/iy
  498.                if ((in = getindex(&cc, z80r16, 3, 4)) != 2) goto nextcmd;
  499.                break;
  500.             case _cb: // all CB-opcodes
  501.             {
  502.                if ((in = getindex(&cc, cbtab, 7, 32)) < 0) goto nextcmd;
  503.                int in1 = getindex(&cc, z80r8_1, 5, 8);
  504.                if (!z80p) {
  505.                   if (in1 < 0) goto nextcmd;
  506.                } else {
  507.                   if (in1 < 0) {
  508.                      in1 = z80scanr8(&cc, &cm);
  509.                      if (in1 < 0) goto nextcmd;
  510.                   } else {
  511.                      if (*cc++ != ',' || z80scanr8(&cc, &cm) != 6) goto nextcmd;
  512.                   }
  513.                }
  514.                *cm++ = in*8+in1;
  515.                break;
  516.             }
  517.             case _zr8: // r8 in *rcmd & 0x38
  518.             case _zr8_: // r8 in *rcmd & 0x38, in ld r8,r8
  519.                if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
  520.                *rcmd |= in<<3;
  521.                break;
  522.             case _zr81: // r8 in *rcmd & 7
  523.             case _zr81_: // r8 in *rcmd & 7, in ld r8,r8
  524.                if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
  525.                *rcmd |= in;
  526.                break;
  527.             case _ld:
  528.                if ((*(unsigned*)cc & 0xFFFFFF) != WORD4('l','d',' ',0)) goto nextcmd;
  529.                cc += 3; break;
  530.             case _shrt: // short jump
  531.             {
  532.                if (!ishex(*cc)) goto nextcmd;
  533.                in = scanhex(&cc);
  534.                int x = i16(in-(int)addr+cmdb-cm-1);
  535.                if (x > 0x7F || x < -0x80) goto nextcmd;
  536.                *(char*)cm = x; cm++;
  537.                break;
  538.             }
  539.             case _ib: // immediate byte at cm
  540.                if (*cc == '\'' && cc[2] == '\'') { in = cc[1]; cc+=3; goto imm; }
  541.                if (!ishex(*cc)) goto nextcmd;
  542.                in = scanhex(&cc);
  543.                if ((unsigned)in > 0xFF) goto nextcmd;
  544. imm:
  545.                *(char*)cm++ = (char)in;
  546.                break;
  547.             case _iw: // immediate word at cm
  548.                if (!ishex(*cc)) goto nextcmd;
  549.                in = scanhex(&cc);
  550.                if ((unsigned)in > 0xFFFF) goto nextcmd;
  551.                *(unsigned short*)cm = (unsigned short)in; cm += 2;
  552.                break;
  553.             default:
  554.                if (*ptr != *cc++) goto nextcmd;
  555.          }
  556.       }
  557.       if (!*cc) return max(unsigned(cm-cmdb), unsigned(*p1));
  558. nextcmd:
  559.       p1 += (2 * *p1) + 1; while (*p1++);
  560.    }
  561.    return 0;
  562. }
  563.  
  564. int assemble_cmd(unsigned char *cmd, unsigned addr)
  565. {
  566.    unsigned char *res = a_command;
  567.    unsigned char bf[0x40]; strcpy((char*)bf, (char*)cmd);
  568.    for (res = bf; *res; res++) { // don't allow to kill space befor (# - place 0x01
  569.       if (*(short*)res == WORD2(' ','(')) *(short*)res = WORD2(1,'(');
  570.       if (*(short*)res == WORD2(' ','#')) *(short*)res = WORD2(1,'#');
  571.    }
  572.    res = a_command; cmd = bf;
  573.    while (*cmd == ' ') cmd++;
  574.    while (*cmd && *cmd != ' ') *res++ = tolower(*cmd++);
  575.    while (*cmd) {
  576.       while (*cmd == ' ' && (!isalnum(cmd[1]) || !isalnum(res[-1]))) cmd++;
  577.       *res++ = (cmd[-1] == '\'') ? *cmd : tolower(*cmd);
  578.       cmd++;
  579.    }
  580.    if (res[-1] == ' ') res[-1] = 0;
  581.    *res = 0;
  582.    // replace 0x01 to space again
  583.    for (res = a_command; *res; res++) if (!(*res-1)) *res = ' ';
  584.  
  585.    unsigned r;
  586.    z80p = 0;    if ((r = assemble(addr))) goto inspref1;
  587.    z80p = 0xDD; if ((r = assemble(addr))) goto inspref1;
  588.    z80p = 0xFD; if ((r = assemble(addr))) goto inspref1;
  589.    return 0;
  590. inspref1:
  591.    unsigned char *p = asmresult;
  592.    if (z80p) *p++ = z80p;
  593.    for (unsigned i=0; i < r; i++) *p++ = cmdb[i];
  594.    return r + (z80p ? 1 : 0);
  595. }
  596.