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
77 changes: 48 additions & 29 deletions pi/is_viewer.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
#include "common.h"
#include "is_viewer.h"

#define READ_HEAD 0x04
#define WRITE_HEAD 0x14
#define BUFFER 0x20

// Minus text buffer base offset, plus NULL terminator
#define IS_BUFFER_SIZE IS_VIEWER_ADDRESS_LEN - 0x20 + 1
#define IS_BUFFER_SIZE IS_VIEWER_ADDRESS_LEN - BUFFER + 1

int is_viewer_init(struct is_viewer *is, int is_viewer_output) {
memset(is, 0, sizeof(*is));
Expand Down Expand Up @@ -47,37 +51,52 @@ int write_is_viewer(struct is_viewer *is, uint32_t address, uint32_t word, uint3
assert(offset + 4 <= is->len);

if (offset == 0x14) {
if (word > 0) {
assert(is->output_buffer_pos + word + 0x20 < is->len);
memcpy(is->output_buffer + is->output_buffer_pos, is->buffer + 0x20, word);
is->output_buffer_pos += word;
is->output_buffer[is->output_buffer_pos] = '\0';

// once a full line is present, convert the output from EUC to UTF-8
if (memchr(is->output_buffer, '\n', is->output_buffer_pos)) {
char *inptr = (char *)is->output_buffer;
size_t len = strlen(inptr);
size_t outlen = 3 * len;
char *outptr = (char *)is->output_buffer_conv;
memset(is->output_buffer_conv, 0, IS_BUFFER_SIZE * 3);
iconv(is->cd, &inptr, &len, &outptr, &outlen);

if (is->show_output)
printf("%s", is->output_buffer_conv);
else if (!is->output_warning) {
printf("ISViewer debugging output detected and suppressed.\nRun cen64 with option -is-viewer to display it\n");
is->output_warning = 1;
}

memset(is->output_buffer, 0, is->output_buffer_pos);
is->output_buffer_pos = 0;
uint32_t read_head;
memcpy(&read_head, is->buffer + READ_HEAD, sizeof(read_head));
read_head = byteswap_32(read_head);

uint32_t write_head;
memcpy(&write_head, is->buffer + WRITE_HEAD, sizeof(write_head));
write_head = byteswap_32(write_head);

uint32_t count;
if (word < read_head) {
// Ring buffer has wrapped
uint32_t first_half = (IS_VIEWER_ADDRESS_LEN - BUFFER) - read_head;
memcpy(is->output_buffer, is->buffer + BUFFER + read_head, first_half);
memcpy(is->output_buffer + first_half, is->buffer + BUFFER, word);
count = first_half + word;
} else {
// Fast path: string is in sequential memory
count = word - read_head;
memcpy(is->output_buffer, is->buffer + BUFFER + read_head, count);
}
is->output_buffer[count] = '\0';

// once a full line is present, convert the output from EUC to UTF-8
if (memchr(is->output_buffer, '\n', count)) {
char *inptr = (char *)is->output_buffer;
size_t len = count;
size_t outlen = 3 * len;
char *outptr = (char *)is->output_buffer_conv;
memset(is->output_buffer_conv, 0, IS_BUFFER_SIZE * 3 + 1);
iconv(is->cd, &inptr, &len, &outptr, &outlen);

if (is->show_output)
printf("%s", is->output_buffer_conv);
else if (!is->output_warning) {
printf("ISViewer debugging output detected and suppressed.\nRun cen64 with option -is-viewer to display it\n");
is->output_warning = 1;
}

// Update read head
read_head = byteswap_32(word);
memcpy(is->buffer + READ_HEAD, &read_head, sizeof(read_head));
}
memset(is->buffer + 0x20, 0, word);
} else {
word = byteswap_32(word);
memcpy(is->buffer + offset, &word, sizeof(word));
}

word = byteswap_32(word);
memcpy(is->buffer + offset, &word, sizeof(word));

return 0;
}
3 changes: 1 addition & 2 deletions pi/is_viewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@

// IS Viewer
#define IS_VIEWER_BASE_ADDRESS 0x13FF0000
#define IS_VIEWER_ADDRESS_LEN 0x00001000
#define IS_VIEWER_ADDRESS_LEN 0x00010000

struct is_viewer {
uint32_t base_address;
uint32_t len;

uint8_t *buffer;
uint8_t *output_buffer;
size_t output_buffer_pos;
uint8_t *output_buffer_conv;
int show_output;
int output_warning;
Expand Down