Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion software/io/c64/c64.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,10 @@ class C64 : public GenericHost, ConfigurableObject
static void hard_stop(void);
void resume(void);
void freeze(void);
virtual void get_all_memory(uint8_t *) { /* NOT YET IMPLEMENTED */ };

virtual void get_all_memory(uint8_t *) { /* NOT YET IMPLEMENTED EXCEPT FOR U64*/ };
virtual uint8_t peek(uint32_t) { /* NOT YET IMPLEMENTED EXCEPT FOR U64*/ };
virtual void poke(uint32_t, uint8_t) { /* NOT YET IMPLEMENTED EXCEPT FOR U64*/ };

static uint8_t get_exrom_game(void) {
return (C64_CLOCK_DETECT & 0x0C) >> 2;
Expand Down
14 changes: 14 additions & 0 deletions software/system/dump_hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define DUMP_BYTES 16
#endif

static const char hex_chars[] = "0123456789ABCDEF";

void dump_hex_actual(void *pp, int len, int relative)
{
int w,t;
Expand Down Expand Up @@ -124,3 +126,15 @@ void dump_hex_verify(void *pp1, void *pp2, int len)
}
}
}

void dump_hex_byte(char *buf, int offset, uint8_t byte)
{
buf[offset] = hex_chars[(byte >> 4) & 0x0F];
buf[offset + 1] = hex_chars[byte & 0x0F];
}

void dump_hex_word(char *buf, int offset, uint16_t word)
{
dump_hex_byte(buf, offset, (word >> 8) & 0xFF);
dump_hex_byte(buf, offset + 2, word & 0xFF);
}
2 changes: 2 additions & 0 deletions software/system/dump_hex.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ void dump_hex_relative(void *pp, int len);
void dump_hex_actual(void *pp, int len, int relative);
void dump_hex_dirty(void *p, int len, uint8_t ptrn);
void dump_hex_verify(void *pp1, void *pp2, int len);
void dump_hex_byte(char *buf, int offset, uint8_t byte);
void dump_hex_word(char *buf, int offset, uint16_t word);

#ifdef __cplusplus
}
Expand Down
82 changes: 64 additions & 18 deletions software/u64/u64_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,12 @@ static SemaphoreHandle_t resetSemaphore;
#define CFG_BADLINES_EN 0x53
#define CFG_SUPERCPU_DET 0x54

#define CFG_MONITOR 0x60

#define CFG_SCAN_MODE_TEST 0xA8
#define CFG_VIC_TEST 0xA9


uint8_t C64_EMUSID1_BASE_BAK;
uint8_t C64_EMUSID2_BASE_BAK;
uint8_t C64_SID1_BASE_BAK;
Expand Down Expand Up @@ -1050,21 +1053,31 @@ int U64Config :: setSidEmuParams(ConfigItem *it)
#define MENU_U64_WIFI_ENABLE 4
#define MENU_U64_WIFI_BOOT 5
#define MENU_U64_DETECT_SIDS 6
#define MENU_U64_POKE 7
#define MENU_U64_PEEK 7
#define MENU_U64_POKE 8
#define MENU_U64_MONITOR 9

void U64Config :: create_task_items(void)
{
TaskCategory *dev = TasksCollection :: getCategory("Developer", SORT_ORDER_DEVELOPER);
myActions.peek = new Action("Peek", SUBSYSID_U64, MENU_U64_PEEK);
myActions.poke = new Action("Poke", SUBSYSID_U64, MENU_U64_POKE);
myActions.monitor = new Action("Monitor", SUBSYSID_U64, MENU_U64_MONITOR);
myActions.saveedid = new Action("Save EDID to file", SUBSYSID_U64, MENU_U64_SAVEEDID);
myActions.siddetect = new Action("Detect SIDs", SUBSYSID_U64, MENU_U64_DETECT_SIDS);
myActions.wifioff = new Action("Disable WiFi", SUBSYSID_U64, MENU_U64_WIFI_DISABLE);
myActions.wifion = new Action("Enable WiFi", SUBSYSID_U64, MENU_U64_WIFI_ENABLE);
myActions.wifiboot = new Action("Enable WiFi Boot", SUBSYSID_U64, MENU_U64_WIFI_BOOT);

dev->append(myActions.saveedid );
dev->append(myActions.saveedid);

#if U64
dev->append(myActions.peek);
dev->append(myActions.poke);
dev->append(myActions.monitor);
#endif

#if DEVELOPER > 0
dev->append(myActions.poke );
dev->append(myActions.siddetect);
dev->append(myActions.wifioff );
dev->append(myActions.wifion );
Expand All @@ -1077,6 +1090,24 @@ void U64Config :: update_task_items(bool writablePath, Path *p)
myActions.saveedid->setDisabled(!writablePath);
}

bool U64Config :: stop_c64() {
portENTER_CRITICAL();
bool running = !(C64_STOP & C64_HAS_STOPPED);
if (running) {
C64 *machine = C64 :: getMachine();
machine->stop(false);
}
return running;
}

void U64Config :: resume_c64(bool stopped) {
if (stopped) {
C64 *machine = C64 :: getMachine();
machine->start();
}
portEXIT_CRITICAL();
}

int U64Config :: executeCommand(SubsysCommand *cmd)
{
File *f = 0;
Expand All @@ -1091,7 +1122,9 @@ int U64Config :: executeCommand(SubsysCommand *cmd)
C64 *machine;
I2C_Driver i2c;
static char poke_buffer[16];
uint32_t addr, value;
static char peek_buffer[16];
static char peek_range_buffer[16];
uint32_t addr, end_addr, value;

switch(cmd->functionID) {
case MENU_U64_SAVEEDID:
Expand Down Expand Up @@ -1153,27 +1186,41 @@ int U64Config :: executeCommand(SubsysCommand *cmd)
U64_WIFI_CONTROL = 7;
break;

case MENU_U64_PEEK:
if (cmd->user_interface->string_box("Peek AAAA", peek_buffer, 16)) {
sscanf(peek_buffer, "%x", &addr);

value = C64 :: getMachine()->peek(addr);

char msg[20];
sprintf(msg, "Peek(%4x)=%2x", addr, value);
cmd->user_interface->popup(msg, BUTTON_OK);
}
break;

case MENU_U64_POKE:
if (cmd->user_interface->string_box("Poke AAAA,DD", poke_buffer, 16)) {

sscanf(poke_buffer, "%x,%x", &addr, &value);

C64 *machine = C64 :: getMachine();
portENTER_CRITICAL();

if (!(C64_STOP & C64_HAS_STOPPED)) {
machine->stop(false);
C64 :: getMachine()->poke(addr, (uint8_t) value);
uint8_t verified_value = C64 :: getMachine()->peek(addr);

C64_POKE(addr, value);

machine->resume();
} else {
C64_POKE(addr, value);
}
portEXIT_CRITICAL();
char msg[20];
sprintf(msg, "Poke(%4x,%2x)=%2x", addr, value, verified_value);
cmd->user_interface->popup(msg, BUTTON_OK);
}
break;

case MENU_U64_MONITOR:
int ram_size = 64 * 1024;
uint8_t *pb = new uint8_t[ram_size];

C64 :: getMachine()->get_all_memory(pb);

cmd->user_interface->run_hex_editor((const char *) pb, ram_size);
delete[] pb;
break;

case MENU_U64_DETECT_SIDS:
machine = C64 :: getMachine();
machine->stop(false);
Expand All @@ -1194,7 +1241,6 @@ int U64Config :: executeCommand(SubsysCommand *cmd)
return 0;
}


uint8_t U64Config :: GetSidType(int slot)
{
uint8_t val;
Expand Down
4 changes: 4 additions & 0 deletions software/u64/u64_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ extern U64Config u64_configurator;
class U64Config : public ConfigurableObject, ObjectWithMenu, SubSystem
{
struct {
Action *peek;
Action *poke;
Action *monitor;
Action *saveedid;
Action *siddetect;
Action *wifioff;
Expand Down Expand Up @@ -103,6 +105,8 @@ class U64Config : public ConfigurableObject, ObjectWithMenu, SubSystem
void create_task_items(void);
void update_task_items(bool writablePath, Path *p);
int executeCommand(SubsysCommand *cmd);
bool stop_c64();
void resume_c64(bool stopped);
void effectuate_settings();

static int setPllOffset(ConfigItem *it);
Expand Down
50 changes: 43 additions & 7 deletions software/u64/u64_machine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,60 @@
#include "FreeRTOS.h"
#include <string.h>

void U64Machine :: get_all_memory(uint8_t *pb)
{
bool U64Machine :: before_memory_access() {
bool freezerMenu = isFrozen;

if (!freezerMenu) {
stop(false);
}
portENTER_CRITICAL();
C64_DMA_MEMONLY = 1;
memcpy(pb, (uint8_t *)C64_MEMORY_BASE, 65536);
return freezerMenu;
}

void U64Machine :: after_memory_access(uint8_t *pb, bool freezerMenu) {
C64_DMA_MEMONLY = 0;
portEXIT_CRITICAL();

if (!freezerMenu) {
resume();
} else { // if we were in freezer menu, the backup of the 1K-4K RAM should be used
// restore memory
} else {
// if we were in freezer menu, the backup of the 1K-4K RAM should be used to restore memory
memcpy(pb + 1024, screen_backup, 1024);
memcpy(pb + 2048, ram_backup, 2048);
}
}

void U64Machine :: get_all_memory(uint8_t *pb)
{
bool freezerMenu = before_memory_access();
memcpy(pb, (uint8_t *)C64_MEMORY_BASE, 65536);
after_memory_access(pb, freezerMenu);
}

uint8_t U64Machine :: peek(uint32_t address)
{
bool freezerMenu = before_memory_access();
uint8_t *pb = new uint8_t[64 * 1024];
get_all_memory(pb);

uint8_t byte = *(pb + address);
printf("peek(%d + %d)=%d", pb, address, byte);

after_memory_access(pb, freezerMenu);
delete[] pb;
return byte;
}

void U64Machine :: poke(uint32_t address, uint8_t byte)
{
bool freezerMenu = before_memory_access();
uint8_t *pb = new uint8_t[64 * 1024];
get_all_memory(pb);

// TODO Ensure this works on freeze mode, not just in HDMI overlay mode
memset((void *) C64_MEMORY_BASE + address, byte, 1);
printf("poke(%d + %d)=%d", C64_MEMORY_BASE, address, byte);

after_memory_access(pb, freezerMenu);
delete[] pb;
}

8 changes: 7 additions & 1 deletion software/u64/u64_machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ class U64Machine : public C64
{
U64Machine() { }
~U64Machine() { }

bool before_memory_access();
void after_memory_access(uint8_t *, bool);

void get_all_memory(uint8_t *pb);
public:
uint8_t peek(uint32_t address);
void poke(uint32_t address, uint8_t byte);

public:
friend class C64;
};

Expand Down
58 changes: 58 additions & 0 deletions software/userinterface/ass_editor.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "editor.h"
#include <string.h>
#include <stdio.h>

static const char hex_chars[] = "0123456789ABCDEF";

// Assembly editor; currently only supports disassembly.
AssEditor :: AssEditor(UserInterface *ui, const char *text_buffer, int max_len) : Editor(ui, text_buffer, max_len)
{
}

void AssEditor :: line_breakdown(const char *text_buffer, int buffer_size)
{
Line current;
int pos = 0;
linecount = 0;

text->clear_list();
while (pos < buffer_size) {
current.buffer = text_buffer + pos;
current.length = (buffer_size - pos > BYTES_PER_HEX_ROW) ? BYTES_PER_HEX_ROW : buffer_size - pos;;
text->append(current);
pos += current.length;
linecount++;
}
}

inline void add_hex_byte(char *buf, int offset, uint8_t byte)
{
buf[offset] = hex_chars[(byte >> 4) & 0x0F];
buf[offset + 1] = hex_chars[byte & 0x0F];
}

inline void add_hex_word(char *buf, int offset, uint16_t word)
{
add_hex_byte(buf, offset, (word >> 8) & 0xFF);
add_hex_byte(buf, offset + 2, word & 0xFF);
}

void HexEditor :: draw(int line_idx, Line *line)
{
#define HEX_COL_START 5
#define TXT_COL_START (HEX_COL_START + (3 * BYTES_PER_HEX_ROW))

char hex_buf[CHARS_PER_HEX_ROW];
memset(hex_buf, ' ', CHARS_PER_HEX_ROW);
add_hex_word(hex_buf, 0, line_idx * BYTES_PER_HEX_ROW);

for (int i = 0; i < line->length; i++) {
uint8_t c = (uint8_t) line->buffer[i];
add_hex_byte(hex_buf, HEX_COL_START + (3 * i), c);
// represent all non-printable characters as '.' based on the character set used by firmware version 3.10j
hex_buf[TXT_COL_START + i] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c);
}

window->output_length(hex_buf, CHARS_PER_HEX_ROW);
window->repeat(' ', window->get_size_x() - CHARS_PER_HEX_ROW);
}
Loading