mirror of
https://github.com/zeldaret/oot.git
synced 2024-12-28 15:56:51 +00:00
493bdbc3c6
subrepo: subdir: "tools/ZAPD" merged: "4751db5c9" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "4751db5c9" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
863 lines
14 KiB
C
863 lines
14 KiB
C
#include <inttypes.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#ifdef _WIN32
|
|
# include <io.h>
|
|
# define read _read
|
|
# define write _write
|
|
#else
|
|
# include <unistd.h>
|
|
#endif
|
|
#include "gbi.h"
|
|
#include "gfxd.h"
|
|
#include "priv.h"
|
|
|
|
static TLOCAL struct gfxd_state state;
|
|
|
|
static int buffer_input_fn(void *buf, int count)
|
|
{
|
|
if (count > config.input_buf_size)
|
|
count = config.input_buf_size;
|
|
memcpy(buf, config.input_buf, count);
|
|
config.input_buf += count;
|
|
config.input_buf_size -= count;
|
|
return count;
|
|
}
|
|
|
|
static int buffer_output_fn(const char *buf, int count)
|
|
{
|
|
if (count > config.output_buf_size)
|
|
count = config.output_buf_size;
|
|
memcpy(config.output_buf, buf, count);
|
|
config.output_buf += count;
|
|
config.output_buf_size -= count;
|
|
return count;
|
|
}
|
|
|
|
static int fd_input_fn(void *buf, int count)
|
|
{
|
|
return read(config.input_fd, buf, count);
|
|
}
|
|
|
|
static int fd_output_fn(const char *buf, int count)
|
|
{
|
|
return write(config.output_fd, buf, count);
|
|
}
|
|
|
|
static void swap_words(Gfx *gfx)
|
|
{
|
|
uint8_t b[8];
|
|
uint8_t *pw = (void *) gfx;
|
|
uint8_t *pb = b;
|
|
|
|
int endian = config.endian;
|
|
int wordsize = config.wordsize;
|
|
|
|
for (int i = 0; i < 8 / wordsize; i++)
|
|
{
|
|
if (endian == gfxd_endian_host)
|
|
{
|
|
switch (wordsize)
|
|
{
|
|
case 1:
|
|
{
|
|
uint8_t w = *(uint8_t *) pw;
|
|
*pb++ = w >> 0;
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
uint16_t w = *(uint16_t *) pw;
|
|
*pb++ = w >> 8;
|
|
*pb++ = w >> 0;
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
uint32_t w = *(uint32_t *) pw;
|
|
*pb++ = w >> 24;
|
|
*pb++ = w >> 16;
|
|
*pb++ = w >> 8;
|
|
*pb++ = w >> 0;
|
|
break;
|
|
}
|
|
case 8:
|
|
{
|
|
uint64_t w = *(uint64_t *) pw;
|
|
*pb++ = w >> 56;
|
|
*pb++ = w >> 48;
|
|
*pb++ = w >> 40;
|
|
*pb++ = w >> 32;
|
|
*pb++ = w >> 24;
|
|
*pb++ = w >> 16;
|
|
*pb++ = w >> 8;
|
|
*pb++ = w >> 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int j = 0; j < wordsize; j++)
|
|
{
|
|
if (endian == gfxd_endian_little)
|
|
*pb++ = pw[wordsize - 1 - j];
|
|
else
|
|
*pb++ = pw[j];
|
|
}
|
|
}
|
|
pw += wordsize;
|
|
}
|
|
|
|
gfx->hi = ((uint32_t) b[0] << 24)
|
|
| ((uint32_t) b[1] << 16)
|
|
| ((uint32_t) b[2] << 8)
|
|
| ((uint32_t) b[3] << 0);
|
|
gfx->lo = ((uint32_t) b[4] << 24)
|
|
| ((uint32_t) b[5] << 16)
|
|
| ((uint32_t) b[6] << 8)
|
|
| ((uint32_t) b[7] << 0);
|
|
}
|
|
|
|
static void get_more_input(void)
|
|
{
|
|
if (state.end_input != 0)
|
|
return;
|
|
|
|
char *recv_buf = (void *) &state.gfx[0];
|
|
|
|
while (state.n_gfx < sizeof(state.gfx) / sizeof(state.gfx[0]))
|
|
{
|
|
int n_read = sizeof(state.gfx) - state.n_byte;
|
|
n_read = config.input_fn(&recv_buf[state.n_byte], n_read);
|
|
if (n_read == 0)
|
|
return;
|
|
state.n_byte += n_read;
|
|
|
|
while (state.n_gfx < state.n_byte / sizeof(Gfx))
|
|
{
|
|
Gfx gfx = state.gfx[state.n_gfx];
|
|
gfxd_macro_t *m = &state.macro[state.n_gfx];
|
|
|
|
swap_words(&gfx);
|
|
|
|
int ret = config.ucode->disas_fn(m, gfx.hi, gfx.lo);
|
|
if (ret != 0 && config.stop_on_invalid != 0)
|
|
{
|
|
state.end_input = 1;
|
|
state.ret = ret;
|
|
return;
|
|
}
|
|
|
|
state.n_gfx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int32_t typed_arg_i(int type, int idx)
|
|
{
|
|
const gfxd_value_t *v = gfxd_value_by_type(type, idx);
|
|
if (v != NULL)
|
|
return v->i;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static uint32_t typed_arg_u(int type, int idx)
|
|
{
|
|
const gfxd_value_t *v = gfxd_value_by_type(type, idx);
|
|
if (v != NULL)
|
|
return v->u;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
TLOCAL struct gfxd_config config =
|
|
{
|
|
.ucode = NULL,
|
|
.endian = gfxd_endian_big,
|
|
.wordsize = 4,
|
|
.arg = NULL,
|
|
|
|
.stop_on_invalid = 1,
|
|
.stop_on_end = 1,
|
|
.emit_dec_color = 0,
|
|
.emit_q_macro = 0,
|
|
.emit_ext_macro = 0,
|
|
|
|
.input_buf = NULL,
|
|
.input_buf_size = 0,
|
|
.input_fn = &buffer_input_fn,
|
|
|
|
.output_buf = NULL,
|
|
.output_buf_size = 0,
|
|
.output_fn = &buffer_output_fn,
|
|
|
|
.macro_fn = &gfxd_macro_dflt,
|
|
.arg_fn = &gfxd_arg_dflt,
|
|
|
|
.tlut_fn = NULL,
|
|
.timg_fn = NULL,
|
|
.cimg_fn = NULL,
|
|
.zimg_fn = NULL,
|
|
.dl_fn = NULL,
|
|
.mtx_fn = NULL,
|
|
.lookat_fn = NULL,
|
|
.light_fn = NULL,
|
|
.seg_fn = NULL,
|
|
.vtx_fn = NULL,
|
|
.vp_fn = NULL,
|
|
.uctext_fn = NULL,
|
|
.ucdata_fn = NULL,
|
|
.dram_fn = NULL,
|
|
};
|
|
|
|
void gfxd_input_buffer(const void *buf, int size)
|
|
{
|
|
config.input_buf = buf;
|
|
config.input_buf_size = size;
|
|
config.input_fn = &buffer_input_fn;
|
|
}
|
|
|
|
void gfxd_output_buffer(char *buf, int size)
|
|
{
|
|
config.output_buf = buf;
|
|
config.output_buf_size = size;
|
|
config.output_fn = &buffer_output_fn;
|
|
}
|
|
|
|
void gfxd_input_fd(int fd)
|
|
{
|
|
config.input_fd = fd;
|
|
config.input_fn = &fd_input_fn;
|
|
}
|
|
|
|
void gfxd_output_fd(int fd)
|
|
{
|
|
config.output_fd = fd;
|
|
config.output_fn = &fd_output_fn;
|
|
}
|
|
|
|
void gfxd_input_callback(gfxd_input_fn_t *fn)
|
|
{
|
|
if (fn != NULL)
|
|
config.input_fn = fn;
|
|
else
|
|
gfxd_input_buffer(NULL, 0);
|
|
}
|
|
|
|
void gfxd_output_callback(gfxd_output_fn_t *fn)
|
|
{
|
|
if (fn != NULL)
|
|
config.output_fn = fn;
|
|
else
|
|
gfxd_output_buffer(NULL, 0);
|
|
}
|
|
|
|
void gfxd_macro_fn(gfxd_macro_fn_t *fn)
|
|
{
|
|
if (fn != NULL)
|
|
config.macro_fn = fn;
|
|
else
|
|
config.macro_fn = gfxd_macro_dflt;
|
|
}
|
|
|
|
void gfxd_arg_fn(gfxd_arg_fn_t *fn)
|
|
{
|
|
if (fn != NULL)
|
|
config.arg_fn = fn;
|
|
else
|
|
config.arg_fn = gfxd_arg_dflt;
|
|
}
|
|
|
|
int gfxd_write(const void *buf, int count)
|
|
{
|
|
return config.output_fn(buf, count);
|
|
}
|
|
|
|
int gfxd_puts(const char *str)
|
|
{
|
|
return gfxd_write(str, strlen(str));
|
|
}
|
|
|
|
int gfxd_printf(const char *fmt, ...)
|
|
{
|
|
char s[256];
|
|
|
|
va_list arg;
|
|
va_start(arg, fmt);
|
|
int n = vsnprintf(s, sizeof(s), fmt, arg);
|
|
va_end(arg);
|
|
|
|
if (n > sizeof(s) - 1)
|
|
n = sizeof(s) - 1;
|
|
|
|
return gfxd_write(s, n);
|
|
}
|
|
|
|
int gfxd_print_value(int type, const gfxd_value_t *value)
|
|
{
|
|
return config.ucode->arg_tbl[type].fn(value);
|
|
}
|
|
|
|
int gfxd_macro_dflt(void)
|
|
{
|
|
gfxd_macro_t *m = &state.macro[0];
|
|
const gfxd_macro_type_t *t = &config.ucode->macro_tbl[m->id];
|
|
|
|
const char *name = gfxd_macro_name();
|
|
if (name == NULL)
|
|
{
|
|
if (config.arg != NULL)
|
|
{
|
|
gfxd_puts(config.arg);
|
|
gfxd_puts(" = ");
|
|
}
|
|
|
|
gfxd_puts("(Gfx){");
|
|
}
|
|
else
|
|
{
|
|
gfxd_puts(name);
|
|
gfxd_puts("(");
|
|
|
|
if (config.arg != NULL)
|
|
{
|
|
gfxd_puts(config.arg);
|
|
if (t->n_arg != 0)
|
|
gfxd_puts(", ");
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < t->n_arg; i++)
|
|
{
|
|
if (i != 0)
|
|
gfxd_puts(", ");
|
|
|
|
config.arg_fn(i);
|
|
}
|
|
|
|
if (name == NULL)
|
|
gfxd_puts("}");
|
|
else
|
|
gfxd_puts(")");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int gfxd_arg_callbacks(int arg_num)
|
|
{
|
|
int id = gfxd_macro_id();
|
|
|
|
switch (gfxd_arg_type(arg_num))
|
|
{
|
|
case gfxd_Tlut:
|
|
{
|
|
if (config.tlut_fn != NULL)
|
|
{
|
|
int32_t num;
|
|
if (id == gfxd_DPLoadTLUT_pal16)
|
|
num = 16;
|
|
else if (id == gfxd_DPLoadTLUT_pal256)
|
|
num = 256;
|
|
else
|
|
num = typed_arg_i(gfxd_Num, 0);
|
|
return config.tlut_fn(
|
|
typed_arg_u(gfxd_Tlut, 0),
|
|
typed_arg_i(gfxd_Pal, 0),
|
|
num);
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Timg:
|
|
{
|
|
if (config.timg_fn != NULL)
|
|
{
|
|
int32_t siz = typed_arg_i(gfxd_Siz, 0);
|
|
if (siz == -1)
|
|
siz = G_IM_SIZ_4b;
|
|
return config.timg_fn(
|
|
typed_arg_u(gfxd_Timg, 0),
|
|
typed_arg_i(gfxd_Fmt, 0),
|
|
siz,
|
|
typed_arg_i(gfxd_Dim, 0),
|
|
typed_arg_i(gfxd_Dim, 1),
|
|
typed_arg_i(gfxd_Pal, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Cimg:
|
|
{
|
|
if (config.cimg_fn != NULL)
|
|
{
|
|
return config.cimg_fn(
|
|
typed_arg_u(gfxd_Cimg, 0),
|
|
typed_arg_i(gfxd_Fmt, 0),
|
|
typed_arg_i(gfxd_Siz, 0),
|
|
typed_arg_i(gfxd_Dim, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Zimg:
|
|
{
|
|
if (config.zimg_fn != NULL)
|
|
{
|
|
return config.zimg_fn(
|
|
typed_arg_u(gfxd_Zimg, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Dl:
|
|
{
|
|
if (config.dl_fn != NULL)
|
|
{
|
|
return config.dl_fn(
|
|
typed_arg_u(gfxd_Dl, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Mtxptr:
|
|
{
|
|
if (config.mtx_fn != NULL)
|
|
{
|
|
return config.mtx_fn(
|
|
typed_arg_u(gfxd_Mtxptr, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Lookatptr:
|
|
{
|
|
if (config.lookat_fn != NULL)
|
|
{
|
|
int32_t num;
|
|
if (id == gfxd_SPLookAt)
|
|
num = 2;
|
|
else
|
|
num = 1;
|
|
return config.lookat_fn(
|
|
typed_arg_u(gfxd_Lookatptr, 0),
|
|
num);
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Lightptr:
|
|
{
|
|
if (config.light_fn != NULL)
|
|
{
|
|
int32_t num;
|
|
if (id == gfxd_SPSetLights1)
|
|
num = 1;
|
|
else if (id == gfxd_SPSetLights2)
|
|
num = 2;
|
|
else if (id == gfxd_SPSetLights3)
|
|
num = 3;
|
|
else if (id == gfxd_SPSetLights4)
|
|
num = 4;
|
|
else if (id == gfxd_SPSetLights5)
|
|
num = 5;
|
|
else if (id == gfxd_SPSetLights6)
|
|
num = 6;
|
|
else if (id == gfxd_SPSetLights7)
|
|
num = 7;
|
|
else
|
|
num = 1;
|
|
return config.light_fn(
|
|
typed_arg_u(gfxd_Lightptr, 0),
|
|
num);
|
|
}
|
|
break;
|
|
|
|
}
|
|
case gfxd_Segptr:
|
|
{
|
|
if (config.seg_fn != NULL)
|
|
{
|
|
return config.seg_fn(
|
|
typed_arg_u(gfxd_Segptr, 0),
|
|
typed_arg_i(gfxd_Seg, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Vtxptr:
|
|
{
|
|
if (config.vtx_fn != NULL)
|
|
{
|
|
return config.vtx_fn(
|
|
typed_arg_u(gfxd_Vtxptr, 0),
|
|
typed_arg_i(gfxd_Num, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Vpptr:
|
|
{
|
|
if (config.vp_fn != NULL)
|
|
{
|
|
return config.vp_fn(
|
|
typed_arg_u(gfxd_Vpptr, 0));
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Uctext:
|
|
{
|
|
if (config.uctext_fn != NULL)
|
|
{
|
|
return config.uctext_fn(
|
|
typed_arg_u(gfxd_Uctext, 0),
|
|
0x1000);
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Ucdata:
|
|
{
|
|
if (config.ucdata_fn != NULL)
|
|
{
|
|
uint32_t size;
|
|
if (id == gfxd_SPLoadUcodeEx)
|
|
size = typed_arg_u(gfxd_Size, 0);
|
|
else
|
|
size = 0x800;
|
|
return config.ucdata_fn(
|
|
typed_arg_u(gfxd_Ucdata, 0),
|
|
size);
|
|
}
|
|
break;
|
|
}
|
|
case gfxd_Dram:
|
|
{
|
|
if (config.dram_fn != NULL)
|
|
{
|
|
return config.dram_fn(
|
|
typed_arg_u(gfxd_Dram, 0),
|
|
typed_arg_u(gfxd_Size, 0));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gfxd_arg_dflt(int arg_num)
|
|
{
|
|
if (gfxd_arg_callbacks(arg_num) == 0)
|
|
{
|
|
gfxd_arg_t *a = &state.macro[0].arg[arg_num];
|
|
|
|
gfxd_print_value(a->type, &a->value);
|
|
}
|
|
}
|
|
|
|
void gfxd_tlut_callback(gfxd_tlut_fn_t *fn)
|
|
{
|
|
config.tlut_fn = fn;
|
|
}
|
|
|
|
void gfxd_timg_callback(gfxd_timg_fn_t *fn)
|
|
{
|
|
config.timg_fn = fn;
|
|
}
|
|
|
|
void gfxd_cimg_callback(gfxd_cimg_fn_t *fn)
|
|
{
|
|
config.cimg_fn = fn;
|
|
}
|
|
|
|
void gfxd_zimg_callback(gfxd_zimg_fn_t *fn)
|
|
{
|
|
config.zimg_fn = fn;
|
|
}
|
|
|
|
void gfxd_dl_callback(gfxd_dl_fn_t *fn)
|
|
{
|
|
config.dl_fn = fn;
|
|
}
|
|
|
|
void gfxd_mtx_callback(gfxd_mtx_fn_t *fn)
|
|
{
|
|
config.mtx_fn = fn;
|
|
}
|
|
|
|
void gfxd_lookat_callback(gfxd_lookat_fn_t *fn)
|
|
{
|
|
config.lookat_fn = fn;
|
|
}
|
|
|
|
void gfxd_light_callback(gfxd_light_fn_t *fn)
|
|
{
|
|
config.light_fn = fn;
|
|
}
|
|
|
|
void gfxd_seg_callback(gfxd_seg_fn_t *fn)
|
|
{
|
|
config.seg_fn = fn;
|
|
}
|
|
|
|
void gfxd_vtx_callback(gfxd_vtx_fn_t *fn)
|
|
{
|
|
config.vtx_fn = fn;
|
|
}
|
|
|
|
void gfxd_vp_callback(gfxd_vp_fn_t *fn)
|
|
{
|
|
config.vp_fn = fn;
|
|
}
|
|
|
|
void gfxd_uctext_callback(gfxd_uctext_fn_t *fn)
|
|
{
|
|
config.uctext_fn = fn;
|
|
}
|
|
|
|
void gfxd_ucdata_callback(gfxd_ucdata_fn_t *fn)
|
|
{
|
|
config.ucdata_fn = fn;
|
|
}
|
|
|
|
void gfxd_dram_callback(gfxd_dram_fn_t *fn)
|
|
{
|
|
config.dram_fn = fn;
|
|
}
|
|
|
|
void gfxd_target(gfxd_ucode_t ucode)
|
|
{
|
|
config.ucode = ucode;
|
|
}
|
|
|
|
void gfxd_endian(int endian, int wordsize)
|
|
{
|
|
config.endian = endian;
|
|
config.wordsize = wordsize;
|
|
}
|
|
|
|
void gfxd_dynamic(const char *arg)
|
|
{
|
|
config.arg = arg;
|
|
}
|
|
|
|
void gfxd_enable(int cap)
|
|
{
|
|
switch (cap)
|
|
{
|
|
case gfxd_stop_on_invalid:
|
|
config.stop_on_invalid = 1;
|
|
break;
|
|
|
|
case gfxd_stop_on_end:
|
|
config.stop_on_end = 1;
|
|
break;
|
|
|
|
case gfxd_emit_dec_color:
|
|
config.emit_dec_color = 1;
|
|
break;
|
|
|
|
case gfxd_emit_q_macro:
|
|
config.emit_q_macro = 1;
|
|
break;
|
|
|
|
case gfxd_emit_ext_macro:
|
|
config.emit_ext_macro = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void gfxd_disable(int cap)
|
|
{
|
|
switch (cap)
|
|
{
|
|
case gfxd_stop_on_invalid:
|
|
config.stop_on_invalid = 0;
|
|
return;
|
|
|
|
case gfxd_stop_on_end:
|
|
config.stop_on_end = 0;
|
|
return;
|
|
|
|
case gfxd_emit_dec_color:
|
|
config.emit_dec_color = 0;
|
|
break;
|
|
|
|
case gfxd_emit_q_macro:
|
|
config.emit_q_macro = 0;
|
|
break;
|
|
|
|
case gfxd_emit_ext_macro:
|
|
config.emit_ext_macro = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void gfxd_udata_set(void *ptr)
|
|
{
|
|
config.udata = ptr;
|
|
}
|
|
|
|
void *gfxd_udata_get(void)
|
|
{
|
|
return config.udata;
|
|
}
|
|
|
|
int gfxd_execute(void)
|
|
{
|
|
state.macro_offset = 0;
|
|
state.n_byte = 0;
|
|
state.n_gfx = 0;
|
|
state.end_input = 0;
|
|
state.ret = 0;
|
|
|
|
for (;;)
|
|
{
|
|
get_more_input();
|
|
if (state.n_gfx == 0)
|
|
break;
|
|
|
|
gfxd_macro_t *m = &state.macro[0];
|
|
config.ucode->combine_fn(m, state.n_gfx);
|
|
|
|
const gfxd_macro_type_t *t = &config.ucode->macro_tbl[m->id];
|
|
if (t->ext != 0 && config.emit_ext_macro == 0)
|
|
{
|
|
Gfx gfx = state.gfx[0];
|
|
swap_words(&gfx);
|
|
|
|
t = &config.ucode->macro_tbl[gfxd_Invalid];
|
|
t->disas_fn(m, gfx.hi, gfx.lo);
|
|
}
|
|
|
|
int ret = config.macro_fn();
|
|
if (ret != 0)
|
|
{
|
|
state.ret = ret;
|
|
break;
|
|
}
|
|
|
|
if (config.stop_on_end != 0
|
|
&& (m->id == gfxd_SPBranchList
|
|
|| m->id == gfxd_SPEndDisplayList))
|
|
{
|
|
break;
|
|
}
|
|
|
|
int n_pop = config.ucode->macro_tbl[m->id].n_gfx;
|
|
int n_rem = state.n_gfx - n_pop;
|
|
{
|
|
int n_byte = n_rem * sizeof(gfxd_macro_t);
|
|
memmove(&state.macro[0], &state.macro[n_pop], n_byte);
|
|
state.n_gfx = n_rem;
|
|
}
|
|
{
|
|
int n_byte = n_rem * sizeof(Gfx);
|
|
memmove(&state.gfx[0], &state.gfx[n_pop], n_byte);
|
|
state.n_byte = n_byte;
|
|
}
|
|
state.macro_offset += n_pop * sizeof(Gfx);
|
|
}
|
|
|
|
return state.ret;
|
|
}
|
|
|
|
int gfxd_macro_offset(void)
|
|
{
|
|
return state.macro_offset;
|
|
}
|
|
|
|
int gfxd_macro_packets(void)
|
|
{
|
|
return config.ucode->macro_tbl[state.macro[0].id].n_gfx;
|
|
}
|
|
|
|
const void *gfxd_macro_data(void)
|
|
{
|
|
return state.gfx;
|
|
}
|
|
|
|
int gfxd_macro_id(void)
|
|
{
|
|
return state.macro[0].id;
|
|
}
|
|
|
|
const char *gfxd_macro_name(void)
|
|
{
|
|
int id = state.macro[0].id;
|
|
const gfxd_macro_type_t *t = &config.ucode->macro_tbl[id];
|
|
|
|
if (t->prefix == NULL && t->suffix == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
static TLOCAL char buf[32];
|
|
|
|
char *p = buf;
|
|
if (t->prefix != NULL)
|
|
{
|
|
const char *s = t->prefix;
|
|
while (*s != '\0')
|
|
*p++ = *s++;
|
|
}
|
|
*p++ = 'g';
|
|
if (config.arg == NULL)
|
|
*p++ = 's';
|
|
if (t->suffix != NULL)
|
|
{
|
|
const char *s = t->suffix;
|
|
while (*s != '\0')
|
|
*p++ = *s++;
|
|
}
|
|
*p++ = '\0';
|
|
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
int gfxd_arg_count(void)
|
|
{
|
|
return config.ucode->macro_tbl[state.macro[0].id].n_arg;
|
|
}
|
|
|
|
int gfxd_arg_type(int arg_num)
|
|
{
|
|
return state.macro[0].arg[arg_num].type;
|
|
}
|
|
|
|
const char *gfxd_arg_name(int arg_num)
|
|
{
|
|
return state.macro[0].arg[arg_num].name;
|
|
}
|
|
|
|
int gfxd_arg_fmt(int arg_num)
|
|
{
|
|
return config.ucode->arg_tbl[state.macro[0].arg[arg_num].type].fmt;
|
|
}
|
|
|
|
const gfxd_value_t *gfxd_arg_value(int arg_num)
|
|
{
|
|
return &state.macro[0].arg[arg_num].value;
|
|
}
|
|
|
|
const gfxd_value_t *gfxd_value_by_type(int type, int idx)
|
|
{
|
|
gfxd_macro_t *m = &state.macro[0];
|
|
const gfxd_macro_type_t *t = &config.ucode->macro_tbl[m->id];
|
|
|
|
for (int i = 0; i < t->n_arg; i++)
|
|
{
|
|
gfxd_arg_t *a = &m->arg[i];
|
|
if (a->type == type)
|
|
{
|
|
if (idx == 0)
|
|
return &a->value;
|
|
else
|
|
idx--;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int gfxd_arg_valid(int arg_num)
|
|
{
|
|
return state.macro[0].arg[arg_num].bad == 0;
|
|
}
|