// info  nam="SAMPLE06A"  tit="ディスアセンブル"  dsc="バイトコードのディスアセンブル"  pro=2

enum {
  E_STK = 20,
         E_SEG, E_OPC, E_DIV, E_NUL, E_ORD, E_EXE, E_BCD, E_VER, E_PRO, // 20- 29
};

typedef struct {
  I4B   ofs;
  U2B   asz;
  U2B   bsz;
} CFNI;
typedef CFNI *pCFNI;
typedef const CFNI *rCFNI;

typedef struct {
  pCFNI fn;
  I4B   ni;
} CFNS;
typedef CFNS *pCFNS;
typedef const CFNS *rCFNS;

#define  NSX_BFN  0x20000000
#define  NSX_CFN  0x30000000

#define  TPX_DAT  0x02000000
#define  TPX_BSS  0x03000000

enum {
  end_v,   rsv01,   rsv02,   ent_w,   drp_i,   drp_d,   swp_i,   swp_d,   // 00-07
  swp_d_i, swp_i_d, swp_b,   swp_w,   dup_i,   dup_d,   psh_i_0, psh_d_0, // 08-0F
  psh_c,   psh_b,   psh_s,   psh_w,   psh_i,   psh_l,   psh_f,   psh_d,   // 10-17
  bfn_b,   bfn_w,   psh_bs,  psh_bi,  psh_dw,  psh_du,  psh_ew,  psh_eu,  // 18-1F
  fch_c,   fch_b,   fch_s,   fch_w,   fch_i,   fch_l,   fch_f,   fch_d,   // 20-27
  cfn_b,   cfn_w,   fch_bs,  fch_bi,  fch_dw,  fch_du,  fch_ew,  fch_eu,  // 28-2F
  sto_c,   sto_s,   sto_i,   sto_l,   sto_f,   sto_d,   rsv36,   rsv37,   // 30-37
  sto_c_v, sto_s_v, sto_i_v, sto_l_v, sto_f_v, sto_d_v, rsv3E,   rsv3F,   // 38-3F
  add_i,   add_i_b, add_i_w, add_i_i, add_l,   add_d,   add_p_i, add_i_p, // 40-47
  mul_i,   mul_i_b, mul_i_w, mul_i_i, mul_l,   mul_d,   jeq_i_0, jne_i_0, // 48-4F
  sub_i,   sub_i_b, sub_i_w, sub_i_i, sub_l,   sub_d,   sub_p_i, sub_p,   // 50-57
  div_i,   div_i_b, div_i_w, div_i_i, div_l,   div_d,   jan_i,   jor_i,   // 58-5F
  shr_i,   shr_i_b, shr_u,   shr_u_b, shr_l,   shr_q,   not_i,   not_l,   // 60-67
  shl_i,   shl_i_b, shl_l,   mod_i,   mod_i_b, mod_l,   nop_v,   jmp_v,   // 68-6F
  and_i,   and_i_b, and_i_w, and_i_i, and_l,   neg_i,   neg_l,   neg_d,   // 70-77
  or_i,    or_i_b,  or_i_w,  or_i_i,  or_l,    xor_i,   xor_i_i, xor_l,   // 78-7F
  cnv_i_c, cnv_i_b, cnv_i_s, cnv_i_w, cnv_i_l, cnv_i_d, cnv_u_l, cnv_u_d, // 80-87
  cnv_l_c, cnv_l_b, cnv_l_s, cnv_l_w, cnv_l_i, cnv_l_u, cnv_l_d, cnv_q_d, // 88-8F
  cnv_d_c, cnv_d_b, cnv_d_s, cnv_d_w, cnv_d_i, cnv_d_u, cnv_d_l, cnv_d_q, // 90-97
  hib_i,   hiw_i,   mkw_i,   mku_i,   chk_b,   chk_w,   chk_c,   chk_s,   // 98-9F
  lt_i,    lt_u,    lt_l,    lt_q,    lt_d,    lt_i_0,  lt_l_0,  lt_d_0,  // A0-A7
  le_i,    le_u,    le_l,    le_q,    le_d,    le_i_0,  le_l_0,  le_d_0,  // A8-AF
  gt_i,    gt_u,    gt_l,    gt_q,    gt_d,    gt_i_0,  gt_l_0,  gt_d_0,  // B0-B7
  ge_i,    ge_u,    ge_l,    ge_q,    ge_d,    ge_i_0,  ge_l_0,  ge_d_0,  // B8-BF
  eq_i,    eq_l,    eq_d,    eq_i_0,  eq_d_0,  fnc_v,   fnc_i,   fnc_d,   // C0-C7
  ne_i,    ne_l,    ne_d,    ne_i_0,  ne_d_0,  ret_v,   ret_i,   ret_d,   // C8-CF
  inc_c,   inc_s,   inc_i,   inc_l,   inc_f,   inc_d,   inc_p,   inc_i_i, // D0-D7
  inc_c_v, inc_s_v, inc_i_v, inc_l_v, inc_f_v, inc_d_v, inc_p_v, inc_p_p, // D8-DF
  dec_c,   dec_s,   dec_i,   dec_l,   dec_f,   dec_d,   dec_p,   dec_i_i, // E0-E7
  dec_c_v, dec_s_v, dec_i_v, dec_l_v, dec_f_v, dec_d_v, dec_p_v, dec_p_p, // E8-EF
};

static U1B  OSZ[256] = {
  0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1, 1, 2, 2, 4, 8, 4, 8, 1, 2, 2, 4, 2, 4, 2, 4,
  0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 2, 4,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 1, 2, 4, 0, 0, 2, 2, 0, 1, 2, 4, 0, 0, 2, 2,
  0, 1, 2, 4, 0, 0, 2, 2, 0, 1, 2, 4, 0, 0, 2, 2,
  0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 2,
  0, 1, 2, 4, 0, 0, 0, 0, 0, 1, 2, 4, 0, 0, 4, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2,
  0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2,
};

I4B  cmdsiz(I4B oc)
{ // 命令長
  return 1 + OSZ[(U1B)oc];
}

typedef struct {
  pBIN  pb;
  I4B   sz;
} SEGS;
typedef SEGS *pSEGS;
typedef const SEGS *rSEGS;

I4B  maxord(rSEGS pc)
{ // 序数の最大値
  I4B mx = 0;
  rBIN cp, ce;

  for (cp = pc->pb, ce = cp + pc->sz; cp < ce; cp += cmdsiz(*cp)) {
    if (*cp == ent_w) {
      if (*(rU2B)(cp+1) > mx) { mx = *(rU2B)(cp+1);}
    }
  }
  return mx;
}

void SetCFNS(pCFNS cf, rSEGS pc)
{ // 関数テーブル項目の設定
  rBIN cp, ce;
  pCFNI fn;

  for (cp = pc->pb, ce = cp + pc->sz; cp < ce; cp += cmdsiz(*cp)) {
    if (*cp == ent_w) {
      fn = &cf->fn[*(rU2B)(cp+1)];
      fn->ofs = cp - pc->pb + cmdsiz(ent_w);
      fn->asz = *(rU2B)(cp+3);
      fn->bsz = *(rU2B)(cp+5);
    }
  }
}

typedef struct {
  I4B   app;
  I4B   pro;
  I4B   ent;
  I4B   ssz;
  uANY  xe;
  SEGS  cs;
  SEGS  ds;
  I4B   esz;
  IDXS  rs;
  CFNS  fs;
} HBCD_;
typedef HBCD_ BCDE, *HBCD;

#define  DEFSSZ  131072

typedef struct {
  I4B   app;
  I4B   pro;
  I4B   ent;
  U4B   rsv;
  I1B   tit[32];
  I1B   dsc[64];
} BCDH;
typedef BCDH *pBCDH;

HBCD CreateBCD(I4B app, I4B pro, I4B ent, I4B ssz, rSEGS pc, rSEGS pd, I4B esz, rIDXS pr)
{ // バイトコード作成
  HBCD hb;

  hb = halloc(sizeof(BCDE), TRUE); if (!hb) { return ierr(E_MEM);}
  hb->app = app;
  hb->pro = pro;
  hb->ent = ent;
  hb->ssz = ssz? ssz: DEFSSZ;
  if (pc && pc->sz > 0) {
    hb->cs.sz = pc->sz;
    hb->cs.pb = halloc(pc->sz, FALSE); if (!hb->cs.pb) { ierr(E_MEM); goto _30;}
    memcpy(hb->cs.pb, pc->pb, pc->sz);
  }
  if (pd && pd->sz > 0) {
    hb->ds.sz = pd->sz;
    hb->ds.pb = halloc(pd->sz, FALSE); if (!hb->ds.pb) { ierr(E_MEM); goto _20;}
    memcpy(hb->ds.pb, pd->pb, pd->sz);
  }
  hb->esz = esz;
  if (pr && pr->ni > 0) {
    hb->rs.ni = pr->ni;
    hb->rs.pi = halloc(pr->ni * sizeof(I4B), FALSE); if (!hb->rs.pi) { ierr(E_MEM); goto _10;}
    memcpy(hb->rs.pi, pr->pi, pr->ni * sizeof(I4B));
  }
  return hb;

 _10: hfree(hb->ds.pb);
 _20: hfree(hb->cs.pb);
 _30: hfree(hb);
  return NULL;
}

void DeleteBCD(HBCD hb)
{ // バイトコードの削除
  if (!hb) return;
//  DeleteExecEnv(hb->xe);
  hfree(hb->fs.fn);
  hfree(hb->rs.pi);
  hfree(hb->ds.pb);
  hfree(hb->cs.pb);
  hfree(hb);
}

BOOL AttachBCD(HBCD hb)
{ // バイトコードを実行可能にする
  hb->fs.ni = maxord(&hb->cs) + 1;
  hb->fs.fn = halloc(hb->fs.ni * sizeof(CFNI), TRUE); if (!hb->fs.fn) { return (BOOL)ierr(E_MEM);}
  SetCFNS(&hb->fs, &hb->cs);
//  hb->xe = CreateExecEnv(hb->ssz, hb->ds.sz, hb->esz, &fsCOM, &hb->fs);
//  if (!hb->xe) { hfree(hb->fs.fn); return FALSE;}
//  SetExecCS(hb->xe, &hb->cs);
//  if (hb->ds.pb) { SetExecDS(hb->xe, &hb->ds, &hb->rs);}
  return TRUE;
}

#define  SEG_COD  1
#define  SEG_DAT  2
#define  SEG_BSS  3
#define  SEG_REL  4

  // バイトコードセグメントヘッダ
typedef struct {
  I4B   seg;
  I4B   len;
} SEGH;

HBCD LoadBCD(rSTR nam, I4B app, I4B pro, I4B ssz)
{ // バイトコードファイル読込
  I4B re;
  HFIL hf;
  HBCD hb;
  BCDH bhd;
  SEGH shd;

  hb = CreateBCD(0, 0, 0, ssz, NULL, NULL, 0, NULL); if (!hb) return NULL;
  hf = open_file(nam, OP_RDO); if (!hf) { ferr(E_FIR, nam); goto _50;}
  re = read_file(hf, &bhd, sizeof(BCDH)); if (!re) { ferr(E_FIR, nam); goto _40;}
  if (app != 0 && LOU2B(bhd.app) != LOU2B(app)) { ierr(E_BCD); goto _40;}
  if (app != 0 && HIU2B(bhd.app) != HIU2B(app)) { ierr(E_VER); goto _40;}
  if (pro != 0 && bhd.pro != pro) { ierr(E_PRO); goto _40;}
  hb->app = bhd.app;
  hb->pro = bhd.pro;
  hb->ent = bhd.ent;
  re = read_file(hf, &shd, sizeof(SEGH)); if (!re) { ferr(E_FIR, nam); goto _40;}
  if (shd.seg != SEG_COD) { ierr(E_BCD); goto _40;}
  if (shd.len > 0) {
    hb->cs.sz = shd.len;
    hb->cs.pb = halloc(shd.len, FALSE); if (!hb->cs.pb) { ierr(E_MEM); goto _40;}
    re = read_file(hf, hb->cs.pb, shd.len); if (!re) { ferr(E_FIR, nam); goto _30;}
  } else { ierr(E_BCD); goto _40;}
  re = read_file(hf, &shd, sizeof(SEGH)); if (!re) { ferr(E_FIR, nam); goto _30;}
  if (shd.seg != SEG_DAT) { ierr(E_BCD); goto _30;}
  if (shd.len > 0) {
    hb->ds.sz = shd.len;
    hb->ds.pb = halloc(shd.len, FALSE); if (!hb->ds.pb) { ierr(E_MEM); goto _30;}
    re = read_file(hf, hb->ds.pb, shd.len); if (!re) { ferr(E_FIR, nam); goto _20;}
  }
  re = read_file(hf, &shd, sizeof(SEGH)); if (!re) { ferr(E_FIR, nam); goto _20;}
  if (shd.seg != SEG_BSS) { ierr(E_BCD); goto _20;}
  hb->esz = shd.len;
  re = read_file(hf, &shd, sizeof(SEGH)); if (!re) { ferr(E_FIR, nam); goto _20;}
  if (shd.seg != SEG_REL) { ierr(E_BCD); goto _20;}
  if (shd.len > 0) {
    hb->rs.ni = shd.len;
    hb->rs.pi = halloc(shd.len * sizeof(I4B), FALSE); if (!hb->rs.pi) { ierr(E_MEM); goto _20;}
    re = read_file(hf, hb->rs.pi, shd.len * sizeof(I4B)); if (!re) { ferr(E_FIR, nam); goto _10;}
  }
  re = AttachBCD(hb); if (!re) goto _10;
  close_file(hf);
  return hb;

 _10: hfree(hb->rs.pi);
 _20: hfree(hb->ds.pb);
 _30: hfree(hb->cs.pb);
 _40: close_file(hf);
 _50: hfree(hb);
  return NULL;
}

 // ニモニック
static rSTR MNE[256] = {
  "end_v",  "?",      "?",      "ent_w",  "drp_i",  "drp_d",  "swp_i",  "swp_d",
  "swp_d_i","swp_i_d","swp_b",  "swp_w",  "dup_i",  "dup_d",  "psh_i_0","psh_d_0",
  "psh_c",  "psh_b",  "psh_s",  "psh_w",  "psh_i",  "psh_l",  "psh_f",  "psh_d",
  "bfn_b",  "bfn_w",  "psh_bs", "psh_bi", "psh_dw", "psh_du", "psh_ew", "psh_eu",
  "fch_c",  "fch_b",  "fch_s",  "fch_w",  "fch_i",  "fch_l",  "fch_f",  "fch_d",
  "cfn_b",  "cfn_w",  "fch_bs", "fch_bi", "fch_dw", "fch_du", "fch_ew", "fch_eu",
  "sto_c",  "sto_s",  "sto_i",  "sto_l",  "sto_f",  "sto_d",  "?",      "?",
  "sto_c_v","sto_s_v","sto_i_v","sto_l_v","sto_f_v","sto_d_v","?",      "?",
  "add_i",  "add_i_b","add_i_w","add_i_i","add_l",  "add_d",  "add_p_i","add_i_p",
  "mul_i",  "mul_i_b","mul_i_w","mul_i_i","mul_l",  "mul_d",  "jeq_i_0","jne_i_0",
  "sub_i",  "sub_i_b","sub_i_w","sub_i_i","sub_l",  "sub_d",  "sub_p_i","sub_p",
  "div_i",  "div_i_b","div_i_w","div_i_i","div_l",  "div_d",  "jan_i",  "jor_i",
  "shr_i",  "shr_i_b","shr_u",  "shr_u_b","shr_l",  "shr_q",  "not_i",  "not_l",
  "shl_i",  "shl_i_b","shl_l",  "mod_i",  "mod_i_b","mod_l",  "nop_v",  "jmp_v",
  "and_i",  "and_i_b","and_i_w","and_i_i","and_l",  "neg_i",  "neg_l",  "neg_d",
  "or_i",   "or_i_b", "or_i_w", "or_i_i", "or_l",   "xor_i",  "xor_i_i","xor_l",
  "cnv_i_c","cnv_i_b","cnv_i_s","cnv_i_w","cnv_i_l","cnv_i_d","cnv_u_l","cnv_u_d",
  "cnv_l_c","cnv_l_b","cnv_l_s","cnv_l_w","cnv_l_i","cnv_l_u","cnv_l_d","cnv_q_d",
  "cnv_d_c","cnv_d_b","cnv_d_s","cnv_d_w","cnv_d_i","cnv_d_u","cnv_d_l","cnv_d_q",
  "hib_i",  "hiw_i",  "mkw_i",  "mku_i",  "chk_b",  "chk_w",  "chk_c",  "chk_s",
  "lt_i",   "lt_u",   "lt_l",   "lt_q",   "lt_d",   "lt_i_0", "lt_l_0", "lt_d_0",
  "le_i",   "le_u",   "le_l",   "le_q",   "le_d",   "le_i_0", "le_l_0", "le_d_0",
  "gt_i",   "gt_u",   "gt_l",   "gt_q",   "gt_d",   "gt_i_0", "gt_l_0", "gt_d_0",
  "ge_i",   "ge_u",   "ge_l",   "ge_q",   "ge_d",   "ge_i_0", "ge_l_0", "ge_d_0",
  "eq_i",   "eq_l",   "eq_d",   "eq_i_0", "eq_d_0", "fnc_v",  "fnc_i",  "fnc_d",
  "ne_i",   "ne_l",   "ne_d",   "ne_i_0", "ne_d_0", "ret_v",  "ret_i",  "ret_d",
  "inc_c",  "inc_s",  "inc_i",  "inc_l",  "inc_f",  "inc_d",  "inc_p",  "inc_i_i",
  "inc_c_v","inc_s_v","inc_i_v","inc_l_v","inc_f_v","inc_d_v","inc_p_v","inc_p_p",
  "dec_c",  "dec_s",  "dec_i",  "dec_l",  "dec_f",  "dec_d",  "dec_p",  "dec_i_i",
  "dec_c_v","dec_s_v","dec_i_v","dec_l_v","dec_f_v","dec_d_v","dec_p_v","dec_p_p",
  "?",      "?",      "?",      "?",      "?",      "?",      "?",      "?",
  "?",      "?",      "?",      "?",      "?",      "?",      "?",      "?",
};

rSTR oprcod(pSTR bf, rBIN cs, rBIN cp)
{ // バイトコード
  I4B ofs = cp - cs;
  pSTR pt = bf;

  pt += sprintfs(pt, "%06d: %s", ofs, MNE[*cp]);
  switch (*cp++) {
  case ent_w:
    sprintfs(pt, "  %d, %d, %d", *(rU2B)cp, *(rU2B)(cp+2), *(rU2B)(cp+4)); break;
  case psh_c:
    sprintfs(pt, "  %d", *(rI1B)cp); break;
  case psh_b:   case bfn_b:   case cfn_b:   case add_i_b: case sub_i_b: case mul_i_b: case div_i_b:
  case shr_i_b: case shr_u_b: case shl_i_b: case mod_i_b: case and_i_b: case or_i_b:
    sprintfs(pt, "  %d", *(rU1B)cp); break;
  case psh_s:   case psh_bs:  case fch_bs:
    sprintfs(pt, "  %d", *(rI2B)cp); break;
  case psh_w:   case bfn_w:   case cfn_w:   case psh_dw:  case psh_ew:  case fch_dw:  case fch_ew:
  case add_i_w: case sub_i_w: case add_p_i: case add_i_p: case sub_p_i: case sub_p:
  case mul_i_w: case div_i_w: case and_i_w: case or_i_w:  case fnc_v:   case fnc_i:   case fnc_d:
  case inc_p:   case inc_p_v: case inc_p_p: case dec_p:   case dec_p_v: case dec_p_p:
    sprintfs(pt, "  %d", *(rU2B)cp); break;
  case psh_i:   case psh_bi:  case fch_bi:  case add_i_i: case sub_i_i: case mul_i_i: case div_i_i:
  case and_i_i: case or_i_i:  case xor_i_i:
    sprintfs(pt, "  0x%08x", *(rI4B)cp); break;
  case jeq_i_0: case jne_i_0: case jan_i:   case jor_i:   case jmp_v:
    sprintfs(pt, "  %06d", ofs + 3 + *(rI2B)cp); break;
  case psh_du:  case psh_eu:  case fch_du:  case fch_eu:
    sprintfs(pt, "  %u", *(rU4B)cp); break;
  case psh_l:
    sprintfs(pt, "  %lldLL", *(rI8B)cp); break;
  case psh_f:
    sprintfs(pt, "  %.6G", (F8B)*(rF4B)cp); break;
  case psh_d:
    sprintfs(pt, "  %.15G", *(rF8B)cp); break;
  }
  return bf;
}

void dumpcod(HFIL hf, rSEGS pc)
{ // バイトコード書出
  rBIN cp, ce;
  I1B bf[LBUF];

  write_line(hf, format("COD: %06d", pc->sz)); if (pc->sz <= 0) return;
  for (cp = pc->pb, ce = cp + pc->sz; cp < ce; cp += cmdsiz(*cp)) {
    write_line(hf, oprcod(bf, pc->pb, cp));
  }
}

void dumpdat(HFIL hf, rSEGS pd)
{ // 初期値データ書出
  I4B i, n;
  I1B bf[LBUF], *pt;

  write_line(hf, format("DAT: %06d", pd->sz));
  for (n = 0; n < pd->sz; n += 32) {
    pt = bf;
    pt += sprintfs(pt, "%06d: ", n);
    for (i = 0; i < 32 && n + i < pd->sz; i++) {
      pt += sprintfs(pt, (i > 0 && i % 4 == 0)? "  %02x": "%02x", pd->pb[n + i]);
    }
    write_line(hf, bf);
  }
}

void dumpbss(HFIL hf, I4B esz)
{ // 初期値なしデータサイズ書出
  write_line(hf, format("BSS: %06d", esz));
}

void dumprel(HFIL hf, rIDXS pr)
{ // 再配置情報書出
  I4B i, n;
  I1B bf[LBUF], *pt;

  write_line(hf, format("REL: %04d", pr->ni));
  for (n = 0; n < pr->ni; n += 10) {
    pt = bf;
    pt += sprintfs(pt, "%04d: ", n);
    for (i = 0; i < 10 && n + i < pr->ni; i++) {
      pt += sprintfs(pt, "  %06d", pr->pi[n + i]);
    }
    write_line(hf, bf);
  }
}

void dumpcfn(HFIL hf, rCFNS cf)
{ // ユーザー定義関数情報書出
  I4B i;
  pCFNI fn;

  write_line(hf, format("CFN: %04d", cf->ni));
  for (i = 0; i < cf->ni; i++) {
    fn = &cf->fn[i];
    write_line(hf, format("%04d:   %06d  %d  %d", i, fn->ofs, fn->asz, fn->bsz));
  }
}

U4B  OCTREV(U4B u)
{ // 逆順
  U4B v;

  ((pBIN)&v)[0] = ((rBIN)&u)[3];
  ((pBIN)&v)[1] = ((rBIN)&u)[2];
  ((pBIN)&v)[2] = ((rBIN)&u)[1];
  ((pBIN)&v)[3] = ((rBIN)&u)[0];
  return v;
}

BOOL DisassembleBCD(rSTR nam, HBCD hb)
{ // ディスアセンブル
  HFIL hf;

  hf = open_file(nam, OP_WRI); if (!hf) { return (BOOL)ferr(E_FIW, nam);}
  write_line(hf, format("HDR: %08x  %d  %d", OCTREV(hb->app), hb->pro, hb->ent));
  dumpcod(hf, &hb->cs);
  dumpdat(hf, &hb->ds);
  dumpbss(hf, hb->esz);
  dumprel(hf, &hb->rs);
  dumpcfn(hf, &hb->fs);
  close_file(hf);
  return TRUE;
}

typedef struct {
  char  inam[512];
  char  onam[512];
} INPDAT;

void CommandMain(HWND hwnd)
{ // ディスアセンブル
  int re;
  HBUF rb;
  HBCD hb;
  static INPDAT dat;
  static COLI ci[2] = {
   { STR(512), 48, "inam", "入力ファイル名", },
   { STR(512), 48, "onam", "出力ファイル名", },
  };
  static COLS cs = { ci, NELEM(ci) };
  static TBLI ti = { &cs, };

  rb = CreateRowBufX(&dat, &ti);
  re = EditRowDlgBox(hwnd, rb, "ディスアセンブル");
  DeleteRowBuf(rb);
  if (!re || !dat.inam[0] || !dat.onam[0]) return;
  hb = LoadBCD(dat.inam, 0, 0, 0); if (!hb) return;
  DisassembleBCD(dat.onam, hb);
  DeleteBCD(hb);
  OkBox(hwnd, format("'%s'を作成しました。", dat.onam), NULL);
}
