diff --git a/rabbitizer/module.c b/rabbitizer/module.c new file mode 100644 index 0000000..613f8d3 --- /dev/null +++ b/rabbitizer/module.c @@ -0,0 +1,213 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "structmember.h" + +#include "instructions/RabbitizerInstr.h" + +typedef struct PyRabbitizerInstr { + PyObject_HEAD + //PyObject *first; /* first name */ + //PyObject *last; /* last name */ + //int number; + RabbitizerInstr instr; +} PyRabbitizerInstr; + +static void +Instr_dealloc(PyRabbitizerInstr *self) +{ + RabbitizerInstr_Destroy(&self->instr); + Py_TYPE(self)->tp_free((PyObject *) self); +} + +#if 0 +static PyObject * +Instr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyRabbitizerInstr *self; + self = (PyRabbitizerInstr *) type->tp_alloc(type, 0); + if (self != NULL) { + self->first = PyUnicode_FromString(""); + if (self->first == NULL) { + Py_DECREF(self); + return NULL; + } + self->last = PyUnicode_FromString(""); + if (self->last == NULL) { + Py_DECREF(self); + return NULL; + } + self->number = 0; + } + return (PyObject *) self; +} +#endif + +static int +Instr_init(PyRabbitizerInstr *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"word", NULL}; + uint32_t word; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &word)) + return -1; + + RabbitizerInstr_Init(&self->instr, word); + RabbitizerInstr_ProcessUniqueId(&self->instr); + + return 0; +} + +static PyMemberDef Instr_members[] = { + {"extraLjustWidthOpcode", T_INT, offsetof(PyRabbitizerInstr, instr.extraLjustWidthOpcode), 0, + "extraLjustWidthOpcode description"}, + {"vram", T_UINT, offsetof(PyRabbitizerInstr, instr.vram), 0, + "vram description"}, + {NULL} /* Sentinel */ +}; + +#if 0 +static PyObject * +Instr_getfirst(PyRabbitizerInstr *self, void *closure) +{ + Py_INCREF(self->first); + return self->first; +} + +static int +Instr_setfirst(PyRabbitizerInstr *self, PyObject *value, void *closure) +{ + PyObject *tmp; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); + return -1; + } + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "The first attribute value must be a string"); + return -1; + } + tmp = self->first; + Py_INCREF(value); + self->first = value; + Py_DECREF(tmp); + return 0; +} + +static PyObject * +Instr_getlast(PyRabbitizerInstr *self, void *closure) +{ + Py_INCREF(self->last); + return self->last; +} + +static int +Instr_setlast(PyRabbitizerInstr *self, PyObject *value, void *closure) +{ + PyObject *tmp; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); + return -1; + } + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "The last attribute value must be a string"); + return -1; + } + tmp = self->last; + Py_INCREF(value); + self->last = value; + Py_DECREF(tmp); + return 0; +} +#endif + +static PyGetSetDef Instr_getsetters[] = { +#if 0 + {"first", (getter) Instr_getfirst, (setter) Instr_setfirst, + "first name", NULL}, + {"last", (getter) Instr_getlast, (setter) Instr_setlast, + "last name", NULL}, +#endif + {NULL} /* Sentinel */ +}; + +#if 0 +static PyObject * +Instr_name(PyRabbitizerInstr *self, PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromFormat("%S %S", self->first, self->last); +} +#endif + + +static PyObject * +Instr_Disassemble(PyRabbitizerInstr *self, PyObject *Py_UNUSED(ignored)) +{ + size_t bufferSize; + char *buffer; + PyObject *ret; + + bufferSize = RabbitizerInstr_GetSizeForBuffer(&self->instr, 0); + + buffer = malloc(bufferSize+1); + RabbitizerInstr_Disassemble(&self->instr, buffer, NULL, 0); + + ret = PyUnicode_FromString(buffer); + + free(buffer); + + return ret; +} + +static PyMethodDef Instr_methods[] = { +#if 0 + {"name", (PyCFunction) Instr_name, METH_NOARGS, + "Return the name, combining the first and last name" + }, +#endif + {"disassemble", (PyCFunction) Instr_Disassemble, METH_NOARGS, "description"}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject InstrType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "rabbitizer.Instr", + .tp_doc = PyDoc_STR("Instruction"), + .tp_basicsize = sizeof(PyRabbitizerInstr), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_new = PyType_GenericNew, + .tp_init = (initproc) Instr_init, + .tp_dealloc = (destructor) Instr_dealloc, + .tp_members = Instr_members, + .tp_methods = Instr_methods, + .tp_getset = Instr_getsetters, +}; + +static PyModuleDef rabbitizer_module = { + PyModuleDef_HEAD_INIT, + .m_name = "rabbitizer", + .m_doc = "", + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit_rabbitizer(void) +{ + PyObject *m; + if (PyType_Ready(&InstrType) < 0) + return NULL; + + m = PyModule_Create(&rabbitizer_module); + if (m == NULL) + return NULL; + + Py_INCREF(&InstrType); + if (PyModule_AddObject(m, "Instr", (PyObject *) &InstrType) < 0) { + Py_DECREF(&InstrType); + Py_DECREF(m); + return NULL; + } + + return m; +} diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..fd75c48 --- /dev/null +++ b/setup.py @@ -0,0 +1,20 @@ +from setuptools import setup, find_packages, Extension + + +setup( + name='rabbitizer', + version='0.1.0', + packages=find_packages(), + ext_modules=[ + Extension( + # the qualified name of the extension module to build + 'rabbitizer', + # the files to compile into our module relative to ``setup.py`` + ['rabbitizer/module.c', + "src/instructions/RabbitizerInstr_Disassemble.c", "src/instructions/RabbitizerInstr_ProcessUniqueId.c", "src/instructions/RabbitizerInstr.c", + "src/instructions/RabbitizerInstrDescriptor.c", "src/instructions/RabbitizerInstrId.c", "src/instructions/RabbitizerRegister.c", + "src/common/Utils.c"], + include_dirs=['include'] + ), + ], +) diff --git a/src/instructions/RabbitizerInstr_Disassemble.c b/src/instructions/RabbitizerInstr_Disassemble.c index ae7ae15..2620a1a 100644 --- a/src/instructions/RabbitizerInstr_Disassemble.c +++ b/src/instructions/RabbitizerInstr_Disassemble.c @@ -422,6 +422,8 @@ size_t RabbitizerInstr_GetSizeForBuffer(const RabbitizerInstr *self, size_t immO size_t RabbitizerInstr_Disassemble(const RabbitizerInstr *self, char *dst, const char *immOverride, size_t immOverrideLength) { + assert(dst != NULL); + if (!RabbitizerInstr_IsImplemented(self) || RabbitizerInstr_MustDisasmAsData(self)) { size_t totalSize = 0; size_t tempSize;