2024-01-11 16:02:53 -05:00
|
|
|
//
|
|
|
|
// Created by william on 10/01/24.
|
|
|
|
//
|
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
#include <stdlib.h>
|
2024-01-16 15:46:22 -05:00
|
|
|
#include <assert.h>
|
2024-01-11 16:02:53 -05:00
|
|
|
#include "program_view.h"
|
|
|
|
#include "../cpu/op.h"
|
2024-01-16 15:46:22 -05:00
|
|
|
#include "memory_view.h"
|
|
|
|
|
|
|
|
void decode_operands(ProgramView *view) {
|
|
|
|
int pc = PROGRAM_VIEW_BASE_ADDR;
|
|
|
|
while (pc < 0xfffa) {
|
|
|
|
DebugOperand *operand = malloc(sizeof(DebugOperand));
|
|
|
|
if (operand == NULL) {
|
|
|
|
perror("Failed to allocate memory for debug operand");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2024-01-11 16:02:53 -05:00
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
byte op_code = view->ram[pc];
|
|
|
|
operand->addr = pc;
|
|
|
|
operand->op_code = op_code;
|
|
|
|
operand->addr_mode = get_op_addr_mode(op_code);
|
2024-01-14 21:59:13 -05:00
|
|
|
|
|
|
|
pc += 1;
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
if (operand->addr_mode == ADDR_MODE_ACCUMULATOR || operand->addr_mode == ADDR_MODE_IMPLICIT) {
|
|
|
|
operand->value = 0;
|
|
|
|
} else if (operand->addr_mode == ADDR_MODE_RELATIVE || operand->addr_mode == ADDR_MODE_IMMEDIATE ||
|
|
|
|
operand->addr_mode == ADDR_MODE_ZERO_PAGE || operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X ||
|
|
|
|
operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) {
|
|
|
|
operand->value = view->ram[pc];
|
2024-01-14 21:59:13 -05:00
|
|
|
pc += 1;
|
|
|
|
} else {
|
2024-01-16 15:46:22 -05:00
|
|
|
operand->value = view->ram[pc];
|
|
|
|
operand->value += view->ram[pc + 1] << 8;
|
2024-01-14 21:59:13 -05:00
|
|
|
pc += 2;
|
|
|
|
}
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
linked_list_add(&view->operands, operand);
|
2024-01-11 16:02:53 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
char *get_addr_mode_format_str(AddressingMode addr_mode) {
|
|
|
|
switch (addr_mode) {
|
|
|
|
case ADDR_MODE_ABSOLUTE:
|
|
|
|
return "$%04x";
|
|
|
|
case ADDR_MODE_ABSOLUTE_INDEXED_X:
|
|
|
|
return "$%04x,x";
|
|
|
|
case ADDR_MODE_ABSOLUTE_INDEXED_Y:
|
|
|
|
return "$%04x,y";
|
|
|
|
case ADDR_MODE_ACCUMULATOR:
|
|
|
|
return "A";
|
|
|
|
case ADDR_MODE_IMMEDIATE:
|
|
|
|
return "#$%02x";
|
|
|
|
case ADDR_MODE_IMPLICIT:
|
|
|
|
return "";
|
|
|
|
case ADDR_MODE_INDIRECT_X:
|
|
|
|
return "($%04x,x)";
|
|
|
|
case ADDR_MODE_INDIRECT_JUMP:
|
|
|
|
return "($%04x)";
|
|
|
|
case ADDR_MODE_INDIRECT_Y:
|
|
|
|
return "($%04x),y";
|
|
|
|
case ADDR_MODE_RELATIVE:
|
|
|
|
return "$%04x";
|
|
|
|
case ADDR_MODE_ZERO_PAGE:
|
|
|
|
return "$%02x,y";
|
|
|
|
case ADDR_MODE_ZERO_PAGE_INDEXED_X:
|
|
|
|
return "$%02x,x";
|
|
|
|
case ADDR_MODE_ZERO_PAGE_INDEXED_Y:
|
|
|
|
return "$%02x,y";
|
|
|
|
}
|
2024-01-11 16:02:53 -05:00
|
|
|
}
|
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
void program_view_write_line(ProgramView *view, int line, DebugOperand *operand) {
|
|
|
|
char *op_name = get_op_code_name(operand->op_code);
|
|
|
|
|
|
|
|
window_inter_print(view->window, 0, line, "%04x:", operand->addr);
|
2024-01-16 15:46:22 -05:00
|
|
|
window_inter_print(view->window, 6, line, "(%02x) %s", operand->op_code, op_name);
|
2024-01-14 21:59:13 -05:00
|
|
|
|
|
|
|
char *format = get_addr_mode_format_str(operand->addr_mode);
|
2024-01-16 15:46:22 -05:00
|
|
|
window_inter_print(view->window, 16, line, format, operand->value);
|
2024-01-14 21:59:13 -05:00
|
|
|
}
|
2024-01-11 16:02:53 -05:00
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
void program_view_print(ProgramView *view) {
|
|
|
|
LinkedListNode *current_node = view->current_operand_node;
|
|
|
|
int line = 0;
|
|
|
|
while (line <= 0xf && current_node != NULL) {
|
|
|
|
program_view_write_line(view, line, (DebugOperand *) current_node->data);
|
|
|
|
current_node = current_node->next;
|
|
|
|
line++;
|
2024-01-11 16:02:53 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
void program_view_cursor_init(ProgramView *view) {
|
2024-01-16 15:46:22 -05:00
|
|
|
window_inter_cursor_init(view->window, 0, 0xf);
|
2024-01-14 21:59:13 -05:00
|
|
|
view->window->cursor.width = PROGRAM_VIEW_WIDTH - 2;
|
|
|
|
}
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
void pv_scroll(ProgramView *view, int direction) {
|
|
|
|
assert(direction == CURSOR_OFFSET_DOWN || direction == CURSOR_OFFSET_UP);
|
|
|
|
|
|
|
|
if (direction == CURSOR_OFFSET_UP) {
|
|
|
|
view->current_operand_node = view->current_operand_node->previous;
|
|
|
|
} else {
|
|
|
|
view->current_operand_node = view->current_operand_node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
program_view_print(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pv_handle_cursor_move(InteractWindow *window, int horizontal, int vertical) {
|
|
|
|
ProgramView *view = (ProgramView *) window->view;
|
|
|
|
|
|
|
|
if (vertical == CURSOR_OFFSET_DOWN && view->window->cursor.pos_y == 0xf ||
|
|
|
|
vertical == CURSOR_OFFSET_UP && view->window->cursor.pos_y == 0) {
|
|
|
|
// Scroll the view
|
|
|
|
pv_scroll(view, vertical);
|
|
|
|
}
|
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
cursor_move(&window->cursor, horizontal, vertical);
|
|
|
|
}
|
2024-01-11 16:02:53 -05:00
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
void program_view_handle_key_down(InteractWindow *window, int keycode) {
|
2024-01-11 16:02:53 -05:00
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
}
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
void pv_deinit(InteractWindow *window) {
|
|
|
|
ProgramView *view = (ProgramView *) window->view;
|
|
|
|
linked_list_uninit(&view->operands);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool pv_predicate_operand_by_addr(void *data, void *userdata) {
|
|
|
|
DebugOperand *operand = (DebugOperand *) data;
|
|
|
|
address *addr = (address *) userdata;
|
|
|
|
return operand->addr == *addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void program_view_init(InteractWindow *interact, System *system, int x, int y) {
|
2024-01-14 21:59:13 -05:00
|
|
|
ProgramView *view = malloc(sizeof(ProgramView));
|
|
|
|
view->window = interact;
|
2024-01-16 15:46:22 -05:00
|
|
|
view->ram = system->ram;
|
|
|
|
view->pc = &system->cpu.program_counter;
|
|
|
|
view->operands = linked_list_init();
|
2024-01-11 16:02:53 -05:00
|
|
|
|
2024-01-14 21:59:13 -05:00
|
|
|
interact->view = view;
|
2024-01-16 15:46:22 -05:00
|
|
|
interact->handle_cursor_move = &pv_handle_cursor_move;
|
2024-01-14 21:59:13 -05:00
|
|
|
interact->handle_key_down = &program_view_handle_key_down;
|
2024-01-16 15:46:22 -05:00
|
|
|
interact->deinit = &pv_deinit;
|
2024-01-14 21:59:13 -05:00
|
|
|
window_inter_init(interact, x, y, PROGRAM_VIEW_WIDTH, PROGRAM_VIEW_HEIGHT, "PROGRAM VIEW");
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
decode_operands(view);
|
|
|
|
view->current_operand_node = linked_list_get_if(&view->operands, &pv_predicate_operand_by_addr, view->pc);
|
2024-01-14 21:59:13 -05:00
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
program_view_print(view);
|
2024-01-14 21:59:13 -05:00
|
|
|
program_view_cursor_init(view);
|
2024-01-11 16:02:53 -05:00
|
|
|
}
|