#include "std.h"
#include "emul.h"
#include "vars.h"
#include "memory.h"
#include "dbglabls.h"
#include "z80asm.h"
#include "util.h"
char asmbuf[0x40];
#define _iw 9
#define _ib 10
#define _shrt 27
#define _ld 0x89
#define _zr16 0x8A
#define _zr8 0x8B
#define _cb 0x8C
#define _zjr 0x8D
#define _hl 0x8E
#define _zr81 0x8F
#define _zop 0x90
#define _zf 0x91
#define _zr16a 0x92
#define _zr8_ 0x9D
#define _zr81_ 0x9E
static unsigned char asm_tab_z80[] =
{
#if 0
2,0xED,0xFF,0xFF,0xFF, // call unreal api
'u','a','p','i',0,
#endif
// fix bug out (c),a => out (0C),a
2, 0xED, 0x70, 0xFF, 0xFF, // in (c)
'i','n',' ','(','c',')',0,
2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0
'o','u','t',' ','(','c',')',',','0',0,
2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c)
'i','n',' ',_zr8,',','(','c',')',0,
2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8
'o','u','t',' ','(','c',')',',',_zr8,0,
1,0xCB,0xFF, // all cb-opcodes
_cb,0,
1, 0x00, 0xFF, // nop
'n','o','p',0,
1, 0x08, 0xFF, // ex af,af'
'e','x',' ','a','f',',','a','f','\'',0,
1,0x02, 0xFF, // ld (bc),a
_ld, '(','b','c',')',',','a',0,
1,0x12, 0xFF, // ld (de),a
_ld, '(','d','e',')',',','a',0,
1,0x0A, 0xFF, // ld a,(bc)
_ld, 'a',',','(','b','c',')',0,
1,0x1A, 0xFF, // ld a,(de)
_ld, 'a',',','(','d','e',')',0,
1,0x03,0xCF, // inc r16
'i','n','c',' ',_zr16,0,
1,0x0B,0xCF, // dec r16
'd','e','c',' ',_zr16,0,
1,0x04,0xC7, // inc r8
'i','n','c',' ', _zr8,0,
1, 0x05, 0xC7, // dec r8
'd','e','c',' ', _zr8,0,
1, 0x07, 0xFF, // rlca
'r','l','c','a',0,
1, 0x17, 0xFF, // rla
'r','l','a',0,
1, 0x27, 0xFF, // daa
'd','a','a',0,
1, 0x37, 0xFF, // scf
's','c','f',0,
1, 0x0F, 0xFF, // rrca
'r','r','c','a',0,
1, 0x1F, 0xFF, // rra
'r','r','a',0,
1, 0x2F, 0xFF, // cpl
'c','p','l',0,
1, 0x3F, 0xFF, // ccf
'c','c','f',0,
1, 0x00, 0xC7, // relative jumps
_zjr, _shrt, 0,
1, 0x09, 0xCF, // add hl, r16
'a','d','d',' ',_hl,',',_zr16,0,
1, 0x32, 0xFF, // ld (nnnn),a
_ld,'(',_iw,')',',','a',0,
1, 0x3A, 0xFF, // ld a,(nnnn)
_ld,'a',',','(',_iw,')',0,
1, 0x22, 0xFF, // ld (nnnn),hl
_ld,'(',_iw,')',',',_hl,0,
1, 0x2A, 0xFF, // ld hl,(nnnn)
_ld,_hl,',','(',_iw,')',0,
1, 0x76, 0xFF, // halt
'h','a','l','t',0,
1, 0x40, 0xC0, // ld r8,r8
_ld, _zr8_, ',', _zr81_, 0,
1, 0x80, 0xC0, // op r8
_zop/*, ' '*/, _zr81, 0,
1, 0xC0, 0xC7, // ret cc
'r','e','t',' ',_zf,0,
1, 0xC2, 0xC7, // jp cc, nnnn
'j','p',' ',_zf,',',_iw,0,
1, 0xC4, 0xC7, // call cc, nnnn
'c','a','l','l',' ',_zf,',',_iw,0,
1, 0xC6, 0xC7, // op immb
_zop/*, ' '*/, _ib, 0,
1, 0xC1, 0xCF, // pop r16a
'p','o','p',' ',_zr16a,0,
1, 0xC5, 0xCF, // push r16a
'p','u','s','h',' ',_zr16a,0,
1, 0xC3, 0xFF, // jp nnnn
'j','p', ' ', _iw,0,
1, 0xD3, 0xFF, // out (nn),a
'o','u','t',' ','(',_ib,')',',','a',0,
1, 0xE3, 0xFF, // ex (sp),hl
'e','x',' ','(','s','p',')',',',_hl,0,
1, 0xF3, 0xFF, // di
'd','i',0,
1, 0xC9, 0xFF, // ret
'r','e','t',0,
1, 0xD9, 0xFF, // exx
'e','x','x',0,
1, 0xE9, 0xFF, // jp (hl)
'j','p',' ','(',_hl,')',0,
1, 0xF9, 0xFF, // ld sp, hl
_ld, 's','p',',',_hl,0,
1, 0xDB, 0xFF, // in a,(nn)
'i','n',' ','a',',','(',_ib,')',0,
1, 0xEB, 0xFF, // ex de,hl - no 'ex de,ix' !
'e','x',' ','d','e',',','h','l',0,
1, 0xFB, 0xFF, // ei
'e','i',0,
1, 0xCD, 0xFF, // call nnnn
'c','a','l','l',' ',_iw,0,
1, 0xC7, 0xFF, // rst 0
'r','s','t',' ','0',0,
1, 0xCF, 0xFF, // rst 8
'r','s','t',' ','8',0,
1, 0xD7, 0xFF, // rst 10
'r','s','t',' ','1','0',0,
1, 0xDF, 0xFF, // rst 18
'r','s','t',' ','1','8',0,
1, 0xE7, 0xFF, // rst 20
'r','s','t',' ','2','0',0,
1, 0xEF, 0xFF, // rst 28
'r','s','t',' ','2','8',0,
1, 0xF7, 0xFF, // rst 30
'r','s','t',' ','3','0',0,
1, 0xFF, 0xFF, // rst 38
'r','s','t',' ','3','8',0,
// ED opcodes
#if 0 // moved above
2, 0xED, 0x70, 0xFF, 0xFF, // in (c)
'i','n',' ','(','c',')',0,
2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0
'o','u','t',' ','(','c',')',',','0',0,
2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c)
'i','n',' ',_zr8,',','(','c',')',0,
2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8
'o','u','t',' ','(','c',')',',',_zr8,0,
#endif
2, 0xED, 0x42, 0xFF, 0xCF, // sbc hl,r16
's','b','c',' ','h','l',',',_zr16,0,
2, 0xED, 0x4A, 0xFF, 0xCF, // adc hl,r16
'a','d','c',' ','h','l',',',_zr16,0,
2, 0xED, 0x43, 0xFF, 0xCF, // ld (nnnn), r16
_ld, '(',_iw,')',',',_zr16, 0,
2, 0xED, 0x4B, 0xFF, 0xCF, // ld r16, (nnnn)
_ld, _zr16, ',', '(',_iw,')', 0,
2, 0xED, 0x44, 0xFF, 0xC7, // neg
'n','e','g',0,
2, 0xED, 0x45, 0xFF, 0xCF, // retn
'r','e','t','n',0,
2, 0xED, 0x4D, 0xFF, 0xCF, // reti
'r','e','t','i',0,
2, 0xED, 0x46, 0xFF, 0xDF, // im 0
'i','m',' ','0',0,
2, 0xED, 0x56, 0xFF, 0xDF, // im 1
'i','m',' ','1',0,
2, 0xED, 0x5E, 0xFF, 0xDF, // im 2
'i','m',' ','2',0,
2, 0xED, 0x4E, 0xFF, 0xDF, // im 0/1
'i','m',' ','0','/','1',0,
2, 0xED, 0x47, 0xFF, 0xFF, // ld i,a
_ld, 'i',',','a',0,
2, 0xED, 0x57, 0xFF, 0xFF, // ld a,i
_ld, 'a',',','i',0,
2, 0xED, 0x67, 0xFF, 0xFF, // rrd
'r','r','d',0,
2, 0xED, 0x4F, 0xFF, 0xFF, // ld r,a
_ld, 'r',',','a',0,
2, 0xED, 0x5F, 0xFF, 0xFF, // ld a,r
_ld, 'a',',','r',0,
2, 0xED, 0x6F, 0xFF, 0xFF, // rld
'r','l','d',0,
2, 0xED, 0xA0, 0xFF, 0xFF, // ldi
'l','d','i',0,
2, 0xED, 0xA1, 0xFF, 0xFF, // cpi
'c','p','i',0,
2, 0xED, 0xA2, 0xFF, 0xFF, // ini
'i','n','i',0,
2, 0xED, 0xA3, 0xFF, 0xFF, // outi
'o','u','t','i',0,
2, 0xED, 0xA8, 0xFF, 0xFF, // ldd
'l','d','d',0,
2, 0xED, 0xA9, 0xFF, 0xFF, // cpd
'c','p','d',0,
2, 0xED, 0xAA, 0xFF, 0xFF, // ind
'i','n','d',0,
2, 0xED, 0xAB, 0xFF, 0xFF, // outd
'o','u','t','d',0,
2, 0xED, 0xB0, 0xFF, 0xFF, // ldir
'l','d','i','r',0,
2, 0xED, 0xB1, 0xFF, 0xFF, // cpir
'c','p','i','r',0,
2, 0xED, 0xB2, 0xFF, 0xFF, // inir
'i','n','i','r',0,
2, 0xED, 0xB3, 0xFF, 0xFF, // otir
'o','t','i','r',0,
2, 0xED, 0xB8, 0xFF, 0xFF, // lddr
'l','d','d','r',0,
2, 0xED, 0xB9, 0xFF, 0xFF, // cpdr
'c','p','d','r',0,
2, 0xED, 0xBA, 0xFF, 0xFF, // indr
'i','n','d','r',0,
2, 0xED, 0xBB, 0xFF, 0xFF, // otdr
'o','t','d','r',0,
2, 0xED, 0x00, 0xFF, 0x00, // all others 'ED'
'n','o','p','*',0,
// place immediates after all - 'ld a,b' is not 'ld a,0B'
1, 0x01, 0xCF, // ld r16,imm16
_ld, _zr16, ',', _iw, 0,
1, 0x06, 0xC7, // ld r8, imm8
_ld, _zr8, ',', _ib, 0,
0 // end
};
#define abs(x) ((x)>0? (x):(-(x)))
// =======================================================================
static char z80r16_1[] = "bc\0de\0hl\0sp";
static char z80r16_2[] = "bc\0de\0ix\0sp";
static char z80r16_3[] = "bc\0de\0iy\0sp";
static 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";
static 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";
static 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";
static 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"
"bit 0,\0bit 1,\0bit 2,\0bit 3,\0bit 4,\0bit 5,\0bit 6,\0bit 7,\0"
"res 0,\0res 1,\0res 2,\0res 3,\0res 4,\0res 5,\0res 6,\0res 7,\0"
"set 0,\0set 1,\0set 2,\0set 3,\0set 4,\0set 5,\0set 6,\0set 7,\0";
static char zjr[] = "xxxxxx\0xxxxxx\0djnz \0\0jr \0\0\0\0jr nz,\0jr z,\0\0jr nc,\0jr c,\0";
//char zop[] = "add\0adc\0sub\0sbc\0and\0xor\0or\0\0cp"; lvd
static 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";
static char zf[] = "nz\0z\0\0nc\0c\0\0po\0pe\0p\0\0m";
// =======================================================================
static void disasm_address(char *line, unsigned addr, char labels)
{
char *label = nullptr;
if (labels&&addr) label = mon_labels.find(am_r(addr));
if (label) {
//strcpy(line, label);
int i;
for (i=0;(i<20)&&label[i];i++)line[i]=label[i];
line[i]=label[i];
} //Alone Coder 0.36.6
else sprintf(line, "%04X", addr & 0xFFFF);
}
const unsigned char *disasm(const unsigned char *cmd, unsigned current, char labels)
{
const unsigned char *st = cmd;
unsigned char z80p;
char *z80r16, *z80r8;
z80r16 = z80r16_1;
z80r8 = z80r8_1;
z80p = 0;
for(;;)
{ // z80 prefixes
if(*cmd == 0xDD)
{
z80r16 = z80r16_2;
z80r8 = z80r8_2;
z80p = 0xDD;
}
else if(*cmd == 0xFD)
{
z80r16 = z80r16_3;
z80r8 = z80r8_3; z80p = 0xFD;
}
else break;
cmd++;
}
for(unsigned char *ptr = asm_tab_z80; *ptr; )
{
// cmd - start of command, c1 - mod/rm, cm - current pointer
const unsigned char *rcmd = cmd;
if(*cmd == 0xED)
{
rcmd++;
z80r16 = z80r16_1;
z80r8 = z80r8_1;
z80p = 0;
}
const unsigned char *cm = rcmd + 1;
for(int j = 0; j < *ptr; j++) // match mask
if((cmd[j] & ptr[j + *ptr + 1]) != ptr[j + 1]) goto nextcmd;
*asmbuf = 0;
unsigned char *pt;
for(pt = ptr + (2 * *ptr) + 1; *pt; pt++)
{ // scan all commands
char ln[/*32*/64];
const char *l1 = ln;
ln[0] = 0; //Alone Coder 0.36.6
switch(*pt)
{
case _zr16: // in rcmd & 0x30
l1 = z80r16 + 3 * ((*rcmd >> 4) & 3);
break;
case _zr16a: // in rcmd & 0x30
if(((*rcmd >> 4) & 3) == 3) l1 = "af";
else l1 = z80r16 + 3 * ((*rcmd >> 4) & 3);
break;
case _hl: // hl/ix/iy
l1 = z80r16 + 3 * 2;
break;
case _zjr: // relative jumps
l1 = zjr + 7 * ((*rcmd >> 3) & 7);
break;
case _zop: // z80 operations at rcmd & 0x38
//l1 = zop+4*((*rcmd>>3)&7); lvd
l1 = zop + 8 * ((*rcmd >> 3) & 7);
break;
case _zf: // z80 flags at rcmd & 0x38
l1 = zf + 3 * ((*rcmd >> 3) & 7);
break;
case _cb: // all CB-opcodes
{
if(!z80p)
{
sprintf(ln, "%s%s", cbtab + (*cm >> 3) * 7, z80r8_1 + (*cm & 7) * 5);
cm++;
}
else
{
if((cm[1] & 7) != 6 && ((cm[1] & 0xC0) != 0x40)) // operand is reg,(ix+nn)
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));
else // only (ix+nn)
sprintf(ln, "%s(i%c%c%02X)", cbtab + (cm[1] >> 3) * 7, z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
cm += 2;
}
break;
}
case _zr8: // in rcmd & 0x38
if(z80p && ((*rcmd & 0x38) == 0x30))
{
sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
cm++;
}
else l1 = z80r8 + 5 * ((*rcmd >> 3) & 7);
break;
case _zr8_: // in rcmd & 0x38, in ld r8,r8
if(!z80p || (*rcmd & 7) == 6) { l1 = z80r8_1 + 5 * ((*rcmd >> 3) & 7); break; }
if((*rcmd & 0x38) == 0x30)
{
sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
cm++;
}
else l1 = z80r8 + 5 * ((*rcmd >> 3) & 7);
break;
case _zr81: // in rcmd & 7
if(z80p && (*rcmd & 7) == 6)
{
sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
cm++;
}
else l1 = z80r8 + 5 * (*rcmd & 7);
break;
case _zr81_: // in rcmd & 7, in ld r8,r8
if(!z80p || ((*rcmd & 0x38) == 0x30)) { l1 = z80r8_1 + 5 * (*rcmd & 7); break; }
if((*rcmd & 7) == 6)
{
sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
cm++;
}
else l1 = z80r8 + 5 * (*rcmd & 7);
break;
case _ld:
l1 = "ld "; break;
case _shrt: // short jump
disasm_address(ln, unsigned(current + cm - st + *(signed char*)cm + 1), labels);
cm++;
break;
case _ib: // immediate byte at cm
sprintf(ln, "%02X", *cm++);
break;
case _iw: // immediate word at cm
disasm_address(ln, *(unsigned short*)cm, labels); cm += 2;
break;
default:
*(short*)ln = *pt;
}
strcat(asmbuf, l1);
}
// make tabulation between instruction and operands
{
// if( !cpu.logena ) //LVD
{
char b1[0x40], *p = asmbuf, *q = b1;
while(*p != ' ' && *p) *q++ = *p++;
*q++ = *p;
if(*p)
{
while(q < b1 + 5) *q++ = ' '; // +5 - tab size=5, was 4
while(*++p) *q++ = *p;
}
*q = 0;
strcpy(asmbuf, b1);
}
return max(cm, cmd + *ptr);
}
nextcmd:
ptr += (2 * *ptr) + 1; while(*ptr++); // skip mask,code and instruction
}
strcpy(asmbuf, "???"); return cmd + 1;
}
static int getindex(unsigned char **ptr, char *table, unsigned width, int size) {
unsigned max = 0, imax; // find max match - fdiv and fdivr must be found as fdivr
for (unsigned i = 0; i < unsigned(size); i++)
{
size_t ln = strlen(table + i * width);
if(!strncmp((char*)*ptr, table + i * width, ln))
{
if(ln > max)
{
max = unsigned(ln);
imax = i;
}
}
}
if (max) {
(*ptr) += strlen(table + imax*width);
return int(imax);
}
return -1;
}
static int scanhex(unsigned char **ptr) {
int r = 0, s = 1;
if(**ptr == '-')
{
(*ptr)++;
s = -1;
}
if (**ptr == '+') (*ptr)++;
while(isdigit(**ptr) || (**ptr >= 'a' && **ptr <= 'f'))
{
r = 16 * r + hexdigit(**ptr);
(*ptr)++;
}
return r*s;
}
static unsigned char cmdb[16];
unsigned char asmresult[24];
static unsigned char z80p;
static unsigned char a_command[0x40];
static int z80scanr8(unsigned char **ptr, unsigned char **cm) {
int in = getindex(ptr, z80r8_1, 5, 8);
if (in >= 0) return in;
char *r8 = z80r8_1;
if (z80p == 0xDD) r8 = z80r8_2;
if (z80p == 0xFD) r8 = z80r8_3;
in = getindex(ptr, r8, 5, 8);
if (!z80p) return in;
if (*(unsigned short*)(*ptr) != WORD2('(','i')) return in;
(*ptr) += 3;
char c = char(*(*ptr - 1));
if ((z80p == 0xDD && c != 'x') || (z80p == 0xFD && c != 'y')) return -1;
int ofs = (**ptr == ')') ? 0 : scanhex(ptr);
if (ofs > 127 || ofs < -128) return -1;
if (*((*ptr)++) != ')') return -1;
*(signed char*)(*cm)++ = (signed char)ofs;
return 6;
}
static unsigned assemble(unsigned addr)
{
char *z80r16 = z80r16_1;
if (z80p == 0xDD) z80r16 = z80r16_2;
if (z80p == 0xFD) z80r16 = z80r16_3;
for (unsigned char *p1 = asm_tab_z80; *p1; ) {
memset(cmdb, 0, sizeof(cmdb));
unsigned char *cc = a_command; memcpy(cmdb, p1+1, *p1);
unsigned char *cmd = cmdb;
unsigned char *rcmd = cmd;
unsigned char *cm;
if (*cmd == 0xED) { rcmd++; if (z80p) goto nextcmd; }
cm = rcmd+1;
int in;
unsigned char *ptr; //Alone Coder
for (/*unsigned char * */ptr = p1+2 * *p1+1; *ptr; ptr++) {
switch (*ptr) {
case _zr16: // in rcmd & 0x30
if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
*rcmd |= (in << 4);
break;
case _zr16a: // in rcmd & 0x30
if (*(unsigned short*)cc == WORD2('a','f')) {
cc += 2;
in = 3;
} else {
if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
}
*rcmd |= (in << 4);
break;
case _zjr: // relative jumps
if ((in = getindex(&cc, zjr, 7, 8)) < 0) goto nextcmd;
*rcmd |= (in << 3);
break;
case _zop: // z80 ops
if ((in = getindex(&cc, zop, 8, 8)) < 0) goto nextcmd;
*rcmd |= (in << 3);
break;
case _zf: // z80 flags
if ((in = getindex(&cc, zf, 3, 8)) < 0) goto nextcmd;
*rcmd |= (in << 3);
break;
case _hl: // hl/ix/iy
if ((in = getindex(&cc, z80r16, 3, 4)) != 2) goto nextcmd;
break;
case _cb: // all CB-opcodes
{
if ((in = getindex(&cc, cbtab, 7, 32)) < 0) goto nextcmd;
int in1 = getindex(&cc, z80r8_1, 5, 8);
if (!z80p) {
if (in1 < 0) goto nextcmd;
} else {
if (in1 < 0) {
in1 = z80scanr8(&cc, &cm);
if (in1 < 0) goto nextcmd;
} else {
if (*cc++ != ',' || z80scanr8(&cc, &cm) != 6) goto nextcmd;
}
}
*cm++ = u8(in*8+in1);
break;
}
case _zr8: // r8 in *rcmd & 0x38
case _zr8_: // r8 in *rcmd & 0x38, in ld r8,r8
if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
*rcmd |= in<<3;
break;
case _zr81: // r8 in *rcmd & 7
case _zr81_: // r8 in *rcmd & 7, in ld r8,r8
if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
*rcmd |= in;
break;
case _ld:
if ((*(unsigned*)cc & 0xFFFFFF) != WORD4('l','d',' ',0)) goto nextcmd;
cc += 3; break;
case _shrt: // short jump
{
if (!ishex(char(*cc))) goto nextcmd;
in = scanhex(&cc);
int x = i16(in-(int)addr+cmdb-cm-1);
if (x > 0x7F || x < -0x80) goto nextcmd;
*(char*)cm = char(x); cm++;
break;
}
case _ib: // immediate byte at cm
if (*cc == '\'' && cc[2] == '\'') { in = cc[1]; cc+=3; goto imm; }
if (!ishex(char(*cc))) goto nextcmd;
in = scanhex(&cc);
if ((unsigned)in > 0xFF) goto nextcmd;
imm:
*(char*)cm++ = (char)in;
break;
case _iw: // immediate word at cm
if (!ishex(char(*cc))) goto nextcmd;
in = scanhex(&cc);
if ((unsigned)in > 0xFFFF) goto nextcmd;
*(unsigned short*)cm = (unsigned short)in; cm += 2;
break;
default:
if (*ptr != *cc++) goto nextcmd;
}
}
if (!*cc) return max(unsigned(cm-cmdb), unsigned(*p1));
nextcmd:
p1 += (2 * *p1) + 1; while (*p1++);
}
return 0;
}
unsigned assemble_cmd(unsigned char *cmd, unsigned addr)
{
unsigned char *res = a_command;
unsigned char bf[0x40]; strcpy((char*)bf, (char*)cmd);
for (res = bf; *res; res++) { // don't allow to kill space befor (# - place 0x01
if (*(short*)res == WORD2(' ','(')) *(short*)res = WORD2(1,'(');
if (*(short*)res == WORD2(' ','#')) *(short*)res = WORD2(1,'#');
}
res = a_command; cmd = bf;
while (*cmd == ' ') cmd++;
while (*cmd && *cmd != ' ') *res++ = u8(tolower(*cmd++));
while (*cmd) {
while (*cmd == ' ' && (!isalnum(cmd[1]) || !isalnum(res[-1]))) cmd++;
*res++ = (cmd[-1] == '\'') ? *cmd : u8(tolower(*cmd));
cmd++;
}
if (res[-1] == ' ') res[-1] = 0;
*res = 0;
// replace 0x01 to space again
for (res = a_command; *res; res++) if (!(*res-1)) *res = ' ';
unsigned r;
z80p = 0; if ((r = assemble(addr))) goto inspref1;
z80p = 0xDD; if ((r = assemble(addr))) goto inspref1;
z80p = 0xFD; if ((r = assemble(addr))) goto inspref1;
return 0;
inspref1:
unsigned char *p = asmresult;
if (z80p) *p++ = z80p;
for (unsigned i=0; i < r; i++) *p++ = cmdb[i];
return r + (z80p ? 1 : 0);
}