Gintracer: v0.2.0 - Update disasembler menu
@add * Improve performance on the disasm menu * fix centering error on the disasm menu
This commit is contained in:
parent
01c9805e00
commit
d69e0de92f
BIN
gintrace.g3a
BIN
gintrace.g3a
Binary file not shown.
|
@ -12,8 +12,8 @@
|
|||
|
||||
/* define font information */
|
||||
#ifdef FXCG50
|
||||
#define FWIDTH 8
|
||||
#define FHEIGHT 9
|
||||
#define FWIDTH 9
|
||||
#define FHEIGHT 10
|
||||
#endif
|
||||
#ifdef FX9860G
|
||||
#define FWIDTH 5
|
||||
|
@ -24,6 +24,13 @@
|
|||
#define DISASM_NB_COLUMN (DWIDTH / (FWIDTH + 1))
|
||||
#define DISASM_NB_ROW (DHEIGHT / (FHEIGHT + 1))
|
||||
|
||||
|
||||
/* buffcursor: buffer cursor (line + note) */
|
||||
struct buffcursor {
|
||||
int line_idx;
|
||||
int note_idx;
|
||||
};
|
||||
|
||||
/* tracer: internal information used to display disassembly view */
|
||||
struct tracer {
|
||||
/* circular buffer information.
|
||||
|
@ -38,8 +45,11 @@ struct tracer {
|
|||
size_t width;
|
||||
size_t height;
|
||||
} size;
|
||||
off_t cursor;
|
||||
uint16_t *anchor;
|
||||
struct {
|
||||
off_t line_idx;
|
||||
uint16_t *addr;
|
||||
} anchor;
|
||||
struct buffcursor cursor;
|
||||
} buffer;
|
||||
|
||||
/* display offset */
|
||||
|
|
|
@ -35,7 +35,8 @@ int main(void)
|
|||
/* intialize UBC information */
|
||||
ubc_install();
|
||||
ubc_set_handler(&gintrace_handler);
|
||||
ubc_set_breakpoint(0, (void*)0x80358a6c, NULL);
|
||||
//ubc_set_breakpoint(0, (void*)0x80358a6c, NULL);
|
||||
ubc_set_breakpoint(0, (void*)0x80358a7e, NULL);
|
||||
|
||||
/* try to trace the function */
|
||||
gint_switch((void *)0x80358a6c);
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
#include <gint/keyboard.h>
|
||||
|
||||
/* define the menu information */
|
||||
/* TODO: find way to have local information */
|
||||
/* TODO: find a way to have local information (session) */
|
||||
struct tracer tracer;
|
||||
|
||||
//---
|
||||
// Internal disassembler processing
|
||||
//---
|
||||
/* dhreverse(): Reverse horizotal area (TODO: move me !!) */
|
||||
/* dhreverse(): Reverse pixels color on a horizontal area (TODO: move me !!) */
|
||||
static void dhreverse(int ypos, size_t size)
|
||||
{
|
||||
#ifdef FXCG50
|
||||
|
@ -34,39 +34,56 @@ static void dhreverse(int ypos, size_t size)
|
|||
}
|
||||
|
||||
|
||||
/* disasm_update_index(): Little helper to update the circular index */
|
||||
static int disasm_update_index(int index, int direction)
|
||||
/* disasm_util_line_update(): Little helper to update the line index
|
||||
* @nte:
|
||||
* This function will update the given line circular index based on the given
|
||||
* direction. This is a dirty way to avoid use of modulo.
|
||||
*
|
||||
* @arg
|
||||
* - line_idx The line index
|
||||
* - direction The direction: upward (negative) and downward (positive)
|
||||
*
|
||||
* @return
|
||||
* - the new line index */
|
||||
static int disasm_util_line_update(int line_idx, int direction)
|
||||
{
|
||||
/* update the counter */
|
||||
if (direction > 0)
|
||||
index = index - 1;
|
||||
if (direction < 0)
|
||||
index = index + 1;
|
||||
|
||||
/* check border */
|
||||
if (index < 0)
|
||||
index = (int)tracer.buffer.size.height - 1;
|
||||
if (index >= (int)tracer.buffer.size.height)
|
||||
index = 0;
|
||||
line_idx = line_idx + direction;
|
||||
while (1) {
|
||||
if (line_idx < 0) {
|
||||
line_idx += (int)tracer.buffer.size.height;
|
||||
continue;
|
||||
}
|
||||
if (line_idx >= (int)tracer.buffer.size.height) {
|
||||
line_idx -= (int)tracer.buffer.size.height;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* return the index */
|
||||
return (index);
|
||||
return (line_idx);
|
||||
}
|
||||
|
||||
/* disasm_check_special_addr(): Check if the address is special
|
||||
*
|
||||
/* disasm_check_special_addr(): Check if the address is special.
|
||||
* @note:
|
||||
* mode & 1 -> check hardware module register
|
||||
* mode & 2 -> check syscall address */
|
||||
static void disasm_check_special_addr(char *buffer, void *address, int mode)
|
||||
* This function will check if the given address is special (like a syscall or
|
||||
* a register) and generate a string which content all information.
|
||||
*
|
||||
* @arg:
|
||||
* - buffer Buffer to store the string information
|
||||
* - address Address to check
|
||||
* - type Type of check:
|
||||
* type & 1 -> check hardware module register
|
||||
* type & 2 -> check syscall address */
|
||||
static void disasm_check_special_addr(char *buffer, void *address, int type)
|
||||
{
|
||||
extern struct tracer tracer;
|
||||
const char *addrname;
|
||||
|
||||
addrname = NULL;
|
||||
if ((mode & 1) != 0)
|
||||
if ((type & 1) != 0)
|
||||
addrname = disasm_dictionary_check_peripheral(address);
|
||||
if (addrname == NULL && (mode & 2) != 0)
|
||||
if (addrname == NULL && (type & 2) != 0)
|
||||
addrname = disasm_dictionary_check_syscalls(address);
|
||||
if (addrname == NULL)
|
||||
return;
|
||||
|
@ -77,16 +94,23 @@ static void disasm_check_special_addr(char *buffer, void *address, int mode)
|
|||
/* disasm_get_mnemonic_info(): Get mnemonic information
|
||||
*
|
||||
* @note:
|
||||
* line[0] -> "address opcode opcode_name"
|
||||
* line[1] -> opcode address note
|
||||
* line[2] -> first note (arg0)
|
||||
* line[3] -> first note (arg1)
|
||||
* line[4] -> first note (arg2) */
|
||||
* This function will analyze the given instruction's address. All of its
|
||||
* information will be stored in a buffer "line". A line is constituted of:
|
||||
* - line[0] -> "address opcode opcode_name"
|
||||
* - line[1] -> address note (syscall, register, ...)
|
||||
* - line[2] -> note (arg0)
|
||||
* - line[3] -> note (arg1)
|
||||
* - line[4] -> note (arg2)
|
||||
*
|
||||
* @arg:
|
||||
* - line Line index, used to find the buffer line to store information
|
||||
* - pc Current Program Counter which store the instruction address */
|
||||
static void disasm_get_mnemonic_info(int line, uint16_t *pc)
|
||||
{
|
||||
const struct opcode *opcode_info;
|
||||
uint16_t opcode;
|
||||
uintptr_t arg[3];
|
||||
int note;
|
||||
|
||||
/* Wipe note */
|
||||
tracer.buffer.raw[line][0][0] = '\0';
|
||||
|
@ -96,9 +120,12 @@ static void disasm_get_mnemonic_info(int line, uint16_t *pc)
|
|||
tracer.buffer.raw[line][4][0] = '\0';
|
||||
|
||||
/* check special address (register, syscall, ...) */
|
||||
disasm_check_special_addr(tracer.buffer.raw[line][1], pc, 2);
|
||||
note = 1;
|
||||
disasm_check_special_addr(tracer.buffer.raw[line][note], pc, 2);
|
||||
if (tracer.buffer.raw[line][note][0] != '\0')
|
||||
note += 1;
|
||||
|
||||
/* generate the "default" information (only the address and word) */
|
||||
/* generate the "default" string info (only the address and word) */
|
||||
snprintf(&tracer.buffer.raw[line][0][0],
|
||||
tracer.buffer.size.width, "%.8lx %.4x ",
|
||||
(uintptr_t)pc, (unsigned int)pc[0]);
|
||||
|
@ -119,62 +146,147 @@ static void disasm_get_mnemonic_info(int line, uint16_t *pc)
|
|||
opcode, i, pc);
|
||||
if (arg[i] == 0x00000000)
|
||||
continue;
|
||||
disasm_check_special_addr(
|
||||
tracer.buffer.raw[line][2 + i],
|
||||
(void*)arg[i], 3
|
||||
);
|
||||
disasm_check_special_addr(tracer.buffer.raw[line][note++],
|
||||
(void*)arg[i], 3);
|
||||
}
|
||||
|
||||
/* generate the complet mnemonic information */
|
||||
/* generate the complete mnemonic information */
|
||||
snprintf(&tracer.buffer.raw[line][0][14],
|
||||
tracer.buffer.size.width - 14,
|
||||
opcode_info->name, arg[0], arg[1], arg[2]);
|
||||
}
|
||||
|
||||
/* disasm_buffer_update(): Update the internal display buffer information */
|
||||
static void disasm_buffer_update(void)
|
||||
/* disasm_util_note_counter(): Retrun the index max of a line
|
||||
* @note
|
||||
* This function will return the maximum index for a given line. That line
|
||||
* contains one instruction information and four possible notes. So, the index
|
||||
* that will be returned can be set in this range [0;4].
|
||||
*
|
||||
* @arg
|
||||
* - line_idx Line index
|
||||
*
|
||||
* @return
|
||||
* The note index max of the line_idx */
|
||||
static int disasm_util_note_counter(int line_idx)
|
||||
{
|
||||
int direction;
|
||||
size_t gap;
|
||||
int line;
|
||||
int pc;
|
||||
int note_idx;
|
||||
|
||||
/* first, we need to calculate the gaps between the current buffer's
|
||||
* based anchor and the new memory information, then determine the
|
||||
* direction */
|
||||
direction = (intptr_t)(tracer.buffer.anchor - tracer.memory);
|
||||
gap = (direction < 0) ? 0 - direction : direction;
|
||||
if (gap > tracer.buffer.size.height) {
|
||||
gap = tracer.buffer.size.height;
|
||||
direction = -tracer.buffer.size.height;
|
||||
note_idx = 0;
|
||||
while (++note_idx < 5) {
|
||||
if (tracer.buffer.raw[line_idx][note_idx][0] == '\0')
|
||||
break;
|
||||
}
|
||||
if (gap == 0)
|
||||
return;
|
||||
|
||||
/* update the virtual PC, used with the internal memory information.
|
||||
* Note that we reach */
|
||||
pc = gap - 1;
|
||||
if (direction < 0)
|
||||
pc = tracer.buffer.size.height - gap;
|
||||
|
||||
/* get the start line index */
|
||||
line = tracer.buffer.cursor;
|
||||
if (direction > 0)
|
||||
line = disasm_update_index(tracer.buffer.cursor, direction);
|
||||
|
||||
/* update the internal buffer */
|
||||
tracer.buffer.anchor = tracer.memory;
|
||||
while ((signed)--gap >= 0) {
|
||||
disasm_get_mnemonic_info(line, &tracer.buffer.anchor[pc]);
|
||||
if (direction > 0)
|
||||
tracer.buffer.cursor = line;
|
||||
line = disasm_update_index(line, direction);
|
||||
pc = (direction < 0) ? pc + 1 : pc - 1;
|
||||
}
|
||||
if (direction < 0)
|
||||
tracer.buffer.cursor = line;
|
||||
return (note_idx - 1);
|
||||
}
|
||||
|
||||
/* disasm_util_row_update(): Update the row counter and return true if OOB
|
||||
* @note:
|
||||
* This function will update the row counter, used to display one line of
|
||||
* information. If the row counter exits the screen, true is returned
|
||||
*
|
||||
* @arg:
|
||||
* - row The row counter
|
||||
* - direction The direction: upward (-1), downward (1)
|
||||
*
|
||||
* @return
|
||||
* 0 The row is always visible
|
||||
* 1 The row is out of screen */
|
||||
static int disasm_util_row_update(int *row, int direction)
|
||||
{
|
||||
*row = *row + direction;
|
||||
return(*row < 0 || *row >= DISASM_NB_ROW);
|
||||
}
|
||||
|
||||
/* disasm_util_line_fetch(): Generate all information for the given line.
|
||||
*
|
||||
* @arg:
|
||||
* - line_idx Line index
|
||||
* - pc Memory address
|
||||
* - direction Direction to push the limit */
|
||||
static void disasm_util_line_fetch(int line_idx, uint16_t *pc, int direction)
|
||||
{
|
||||
if (tracer.buffer.raw[line_idx][0][0] == '\0') {
|
||||
disasm_get_mnemonic_info(line_idx, pc);
|
||||
line_idx = disasm_util_line_update(line_idx, direction);
|
||||
tracer.buffer.raw[line_idx][0][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* disasm_display_addr_info(): Display entiere line information
|
||||
* @note
|
||||
* This function is a bit complex. It will display, if available, one entire
|
||||
* line's information like address, opcode name and notes. If the line is not
|
||||
* available, it will be generated and cached into a circular buffer.
|
||||
*
|
||||
* The process to get one instruction information (opcode + notes) cost a lot
|
||||
* of time because of the amount of data to check. This is why a part of the
|
||||
* display is cached into an internal circular buffer to avoid display lags
|
||||
* during the displacement.
|
||||
*
|
||||
* @args:
|
||||
* - row current row id (used to display information)
|
||||
* - line_idx buffer line index
|
||||
* - context context information
|
||||
* - direction display upward (negative) or downward (positive)
|
||||
*
|
||||
* @return
|
||||
* - 0 Row is still on the screen
|
||||
* - 1 Row is out-of-screen */
|
||||
int disasm_display_addr_info(int *row, struct buffcursor *cursor,
|
||||
struct ucontext *context, int direction, int pc)
|
||||
{
|
||||
int note_max_idx;
|
||||
void *ptr;
|
||||
|
||||
/* generate the line if missing and move the limit */
|
||||
disasm_util_line_fetch(cursor->line_idx,
|
||||
&tracer.buffer.anchor.addr[pc], direction);
|
||||
|
||||
/* get the last note index if downward */
|
||||
note_max_idx = 5;
|
||||
if (direction == 1)
|
||||
note_max_idx = disasm_util_note_counter(cursor->line_idx);
|
||||
|
||||
/* walk trough the notes */
|
||||
while (cursor->note_idx <= note_max_idx && cursor->note_idx >= 0) {
|
||||
/* check loop condition */
|
||||
ptr = tracer.buffer.raw[cursor->line_idx][cursor->note_idx];
|
||||
if (((char*)ptr)[0] == '\0')
|
||||
break;
|
||||
|
||||
/* check note */
|
||||
if (cursor->note_idx != 0) {
|
||||
drect(0, (*row) * (FHEIGHT + 1) - 1, DWIDTH,
|
||||
((*row) * (FHEIGHT + 1) - 1) + (FHEIGHT + 2),
|
||||
0x556655);
|
||||
dtext(tracer.disp.hoffset * (FWIDTH + 1),
|
||||
(*row) * (FHEIGHT + 1), C_WHITE, ptr);
|
||||
} else {
|
||||
/* check instruction */
|
||||
dtext(tracer.disp.hoffset * (FWIDTH + 1),
|
||||
(*row) * (FHEIGHT + 1), C_BLACK, ptr);
|
||||
|
||||
/* highlight SPC if possible */
|
||||
ptr = &tracer.buffer.anchor.addr[pc];
|
||||
if ((uintptr_t)ptr == context->spc)
|
||||
dhreverse((*row) * (FHEIGHT + 1) - 1,
|
||||
FHEIGHT + 2);
|
||||
/* draw next break / instruction */
|
||||
if (tracer.next_break != context->spc
|
||||
&& ptr == (void*)tracer.next_break) {
|
||||
dhline((*row) * (FHEIGHT + 1) - 1, C_BLACK);
|
||||
dhline( ((*row) + 1) * (FHEIGHT + 1) - 1,
|
||||
C_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
/* update internal information */
|
||||
if (disasm_util_row_update(row, direction) == 1)
|
||||
return (1);
|
||||
cursor->note_idx -= direction;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -186,7 +298,7 @@ static void disasm_ctor(void)
|
|||
{
|
||||
memset(&tracer, 0x00, sizeof(struct tracer));
|
||||
tracer.buffer.size.width = DISASM_NB_COLUMN * 2;
|
||||
tracer.buffer.size.height = DISASM_NB_ROW * 2;
|
||||
tracer.buffer.size.height = DISASM_NB_ROW * 2 + 2;
|
||||
tracer.buffer.raw = calloc(sizeof(void*), tracer.buffer.size.height);
|
||||
for (size_t i = 0; i < tracer.buffer.size.height; ++i) {
|
||||
tracer.buffer.raw[i] = calloc(sizeof(char*), 5);
|
||||
|
@ -196,7 +308,8 @@ static void disasm_ctor(void)
|
|||
tracer.buffer.raw[i][3] = calloc(tracer.buffer.size.width, 1);
|
||||
tracer.buffer.raw[i][4] = calloc(tracer.buffer.size.width, 1);
|
||||
}
|
||||
tracer.buffer.cursor = 0;
|
||||
tracer.buffer.cursor.line_idx = 0;
|
||||
tracer.buffer.cursor.note_idx = 0;
|
||||
tracer.disp.hoffset = 0;
|
||||
tracer.disp.voffset = 0;
|
||||
}
|
||||
|
@ -220,65 +333,79 @@ static void disasm_dtor(void)
|
|||
memset(&tracer, 0x00, sizeof(struct tracer));
|
||||
}
|
||||
|
||||
/* disasm_init(): Called each breakpoint, update the internal buffer */
|
||||
/* disasm_init(): Called at each breakpoint, update the internal buffer */
|
||||
static void disasm_init(struct ucontext *context)
|
||||
{
|
||||
tracer.memory = (void*)(uintptr_t)((context->spc + 3) & ~3);
|
||||
int a;
|
||||
|
||||
tracer.buffer.anchor.addr = (void*)(uintptr_t)((context->spc + 1) & ~1);
|
||||
tracer.next_break = context->spc;
|
||||
tracer.next_instruction = context->spc;
|
||||
tracer.spc = context->spc;
|
||||
disasm_buffer_update();
|
||||
|
||||
tracer.buffer.cursor.note_idx = 0;
|
||||
tracer.buffer.cursor.line_idx = 0;
|
||||
a = disasm_util_line_update(tracer.buffer.cursor.line_idx, -1);
|
||||
tracer.buffer.raw[a][0][0] = '\0';
|
||||
tracer.buffer.raw[tracer.buffer.cursor.line_idx][0][0] = '\0';
|
||||
disasm_util_line_fetch(tracer.buffer.cursor.line_idx,
|
||||
&tracer.buffer.anchor.addr[0], 1);
|
||||
}
|
||||
|
||||
/* disasm_display(); Display trace information */
|
||||
static void disasm_display(struct ucontext *context)
|
||||
{
|
||||
int line;
|
||||
struct buffcursor cursor;
|
||||
int row;
|
||||
int pc;
|
||||
|
||||
/* display the first part (current middle line and before, upward) */
|
||||
pc = 0;
|
||||
line = tracer.buffer.cursor;
|
||||
for (int row = 0; row < DISASM_NB_ROW; ++row) {
|
||||
/* display notes and opcode information */
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (tracer.buffer.raw[line][i + 1][0] == '\0')
|
||||
continue;
|
||||
drect(0, row * (FHEIGHT + 1) - 1, DWIDTH,
|
||||
(row * (FHEIGHT + 1) - 1) + (FHEIGHT + 2),
|
||||
0x556655);
|
||||
dtext(tracer.disp.hoffset * (FWIDTH + 1),
|
||||
row * (FHEIGHT + 1), C_WHITE,
|
||||
tracer.buffer.raw[line][i + 1]);
|
||||
row = row + 1;
|
||||
if (row >= DISASM_NB_ROW)
|
||||
return;
|
||||
}
|
||||
dtext(tracer.disp.hoffset * (FWIDTH + 1),
|
||||
row * (FHEIGHT + 1), C_BLACK,
|
||||
tracer.buffer.raw[line][0]);
|
||||
row = DISASM_NB_ROW / 2;
|
||||
cursor.line_idx = tracer.buffer.cursor.line_idx;
|
||||
cursor.note_idx = tracer.buffer.cursor.note_idx;
|
||||
disasm_display_addr_info(&row, &cursor, context, -1, pc);
|
||||
while (row >= 0) {
|
||||
disasm_display_addr_info(&row, &cursor, context, -1, pc);
|
||||
cursor.line_idx = disasm_util_line_update(cursor.line_idx, -1);
|
||||
cursor.note_idx = 0;
|
||||
pc = pc - 1;
|
||||
}
|
||||
|
||||
/* highlight SPC if possible */
|
||||
if ((uintptr_t)&tracer.buffer.anchor[pc] == context->spc)
|
||||
dhreverse(row * (FHEIGHT + 1) - 1, FHEIGHT + 2);
|
||||
|
||||
/* draw next break / instruction */
|
||||
if (tracer.next_break != context->spc
|
||||
&& (uintptr_t)&tracer.buffer.anchor[pc] == tracer.next_break) {
|
||||
dhline(row * (FHEIGHT + 1) - 1, C_BLACK);
|
||||
dhline((row + 1) * (FHEIGHT + 1) - 1, C_BLACK);
|
||||
}
|
||||
|
||||
/* update line position (circular buffer) */
|
||||
line = line + 1;
|
||||
if (line >= (int)tracer.buffer.size.height)
|
||||
line = 0;
|
||||
/* display the second part (after the current middle line, downward)
|
||||
* @note:
|
||||
* I use a huge dirty workaround to skip the current middle line
|
||||
* because all the instruction is generated at the display_addr()
|
||||
* function. So, if the line is not generated, its notes will not be
|
||||
* displayed and skipped. So, we need to update the line, fetch
|
||||
* information, get the note index max then start displaying lines. */
|
||||
pc = 0;
|
||||
row = (DISASM_NB_ROW / 2) + 1;
|
||||
cursor.line_idx = tracer.buffer.cursor.line_idx;
|
||||
cursor.note_idx = tracer.buffer.cursor.note_idx - 1;
|
||||
if (cursor.note_idx < 0) {
|
||||
pc = 1;
|
||||
cursor.line_idx = disasm_util_line_update(cursor.line_idx, 1);
|
||||
disasm_util_line_fetch(cursor.line_idx,
|
||||
&tracer.buffer.anchor.addr[pc], 1);
|
||||
cursor.note_idx = disasm_util_note_counter(cursor.line_idx);
|
||||
}
|
||||
while (row <= DISASM_NB_ROW) {
|
||||
disasm_display_addr_info(&row, &cursor, context, 1, pc);
|
||||
pc = pc + 1;
|
||||
cursor.line_idx = disasm_util_line_update(cursor.line_idx, 1);
|
||||
disasm_util_line_fetch(cursor.line_idx,
|
||||
&tracer.buffer.anchor.addr[pc], 1);
|
||||
cursor.note_idx = disasm_util_note_counter(cursor.line_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/* disasm_keyboard(): Handle one key event */
|
||||
static int disasm_keyboard(struct ucontext *context, int key)
|
||||
{
|
||||
int note_idx;
|
||||
int line_idx;
|
||||
|
||||
/* horizontal update */
|
||||
if (key == KEY_LEFT)
|
||||
tracer.disp.hoffset += 1;
|
||||
|
@ -287,12 +414,31 @@ static int disasm_keyboard(struct ucontext *context, int key)
|
|||
|
||||
/* vertical update */
|
||||
if (key == KEY_UP) {
|
||||
tracer.memory = &tracer.memory[-1];
|
||||
disasm_buffer_update();
|
||||
tracer.buffer.cursor.note_idx += 1;
|
||||
note_idx = tracer.buffer.cursor.note_idx;
|
||||
line_idx = tracer.buffer.cursor.line_idx;
|
||||
if (note_idx >= 5
|
||||
|| tracer.buffer.raw[line_idx][note_idx][0] == '\0') {
|
||||
tracer.buffer.anchor.addr =
|
||||
&tracer.buffer.anchor.addr[-1];
|
||||
line_idx = disasm_util_line_update(line_idx, -1);
|
||||
tracer.buffer.cursor.line_idx = line_idx;
|
||||
tracer.buffer.cursor.note_idx = 0;
|
||||
}
|
||||
}
|
||||
if (key == KEY_DOWN) {
|
||||
tracer.memory = &tracer.memory[1];
|
||||
disasm_buffer_update();
|
||||
tracer.buffer.cursor.note_idx -= 1;
|
||||
note_idx = tracer.buffer.cursor.note_idx;
|
||||
line_idx = tracer.buffer.cursor.line_idx;
|
||||
if (note_idx < 0) {
|
||||
tracer.buffer.anchor.addr =
|
||||
&tracer.buffer.anchor.addr[1];
|
||||
line_idx = disasm_util_line_update(line_idx, 1);
|
||||
disasm_util_line_fetch(line_idx, tracer.memory, 1);
|
||||
note_idx = disasm_util_note_counter(line_idx);
|
||||
tracer.buffer.cursor.line_idx = line_idx;
|
||||
tracer.buffer.cursor.note_idx = note_idx;
|
||||
}
|
||||
}
|
||||
|
||||
/* move break point */
|
||||
|
|
Loading…
Reference in New Issue