Files
goldeneye_src/src/rmon.c
T
2025-04-25 10:11:31 -04:00

351 lines
7.5 KiB
C

/*
* THIS FILE IS AN OS FILE (PR\libultra\rmon\rmonMain.c)
*/
#include <stdarg.h>
#include <ultra64.h>
#include <PR/os.h>
#include "libultra/libc/xstdio.h"
#include "crash.h"
#include "rmon.h" /*<PR/rmon.h>*/
#ifdef ENABLE_USB
#include <os_internal.h>
#include "libultra/os/osint.h"
#include "usb.h"
#define RMON_MESSAGE_QUEUE_SIZE 10
#define RMON_MESSAGE_PRINTF_BUFFER_LENGTH 56
enum RMON_MESG_TYPE {
RMON_MESG_TEST = 1,
RMON_MESG_PRINTF
};
struct RmonMesgBase {
int type;
};
struct RmonMesgPrintf {
int type;
int length;
char buffer[RMON_MESSAGE_PRINTF_BUFFER_LENGTH];
};
int rmonCurrentMesgStack;
struct RmonMesgBase rmonMesgStack[2];
int rmonCurrentMesgPrintfStack;
struct RmonMesgPrintf rmonMesgPrintfStack[2];
OSMesg rmonMesg[RMON_MESSAGE_QUEUE_SIZE];
OSMesgQueue rmonMessageQueue;
OSTimer rmonSleeptimer;
OSMesgQueue rmonSleepMq;
OSMesg rmonSleepMesg;
void rmonHandleTestMsg(struct RmonMesgBase *msg);
void rmonHandlePrintfMsg(struct RmonMesgPrintf *msg);
// sprintf internal function to unwrap paramaters
extern char *proutSprintf(char *dst, const char *src, size_t count);
void rmonInit(void) {
rmonCurrentMesgStack = 0;
rmonCurrentMesgPrintfStack = 0;
osCreateMesgQueue(&rmonMessageQueue, &rmonMesg, RMON_MESSAGE_QUEUE_SIZE);
osCreateMesgQueue(&rmonSleepMq, &rmonSleepMesg, 1);
}
#endif
/************************************************************************
Function: rmonMain
Args: none
Type: void
Purpose: This is the main loop of the rmon debugger. It is mostly a protocol
parser/dispatcher.
************************************************************************/
void rmonMain(void) {
#ifdef ENABLE_USB
rmonInit();
while (1)
{
OSMesg work;
struct RmonMesgBase *msg;
while (0 == osRecvMesg(&rmonMessageQueue, &work, OS_MESG_NOBLOCK))
{
msg = work;
switch (msg->type)
{
case RMON_MESG_TEST:
rmonHandleTestMsg((struct RmonMesgBase *)msg);
break;
case RMON_MESG_PRINTF:
rmonHandlePrintfMsg((struct RmonMesgPrintf *)msg);
break;
default:
break;
}
}
osSetTimer(&rmonSleeptimer, OS_USEC_TO_CYCLES(1000000), 0, &rmonSleepMq, rmonSleepMesg);
osRecvMesg(&rmonSleepMq, &rmonSleepMesg, OS_MESG_BLOCK);
}
# endif
}
/**
* rmonGetToken
* returns true if this if rmon is disabled
*/
s32 rmonGetToken(void) {
#if defined(DEBUG)
//flesh out sending a token from pc app
return FALSE;
#else
return TRUE;
#endif
}
/**
* REMOVED
* rmonStatus
* returns the status of rmon
*/
s32 rmonStatus(void) {
#ifdef DEBUG
//removed
#else
return -1;
#endif
}
/**
* Removed
* reimpliment osWriteHost
* target rmon and usb
*/
void osWriteHost(void * buffer, u32 size)
{
if (buffer);
if (size);
#ifdef ENABLE_USB
//flesh out a proper ge parser on pc app
usb_write(DATATYPE_RMONBINARY , buffer, size);
#endif
}
/**
* Removed
* reimpliment osReadHost
* target rmon and usb
*/
void osReadHost(void * buffer, u32 size)
{
#ifdef ENABLE_USB
char incoming_type = 0;
int incoming_size = 0;
#endif
if (buffer);
if (size);
#ifdef ENABLE_USB
//flesh out a proper pc side tool still
osSyncPrintf("USB: Waiting for data\n");
while(1)
{
// Check if there's data in USB
// Needs to be a while loop because we can't write to USB if there's data that needs to be read first
while (usb_poll() != 0)
{
int header = usb_poll();
// Store the size and type from the header
incoming_type = USBHEADER_GETTYPE(header);
incoming_size = USBHEADER_GETSIZE(header);
osSyncPrintf("USB: Received header %d\n", incoming_type);
osSyncPrintf("USB: Received size %d\n", incoming_size);
// Ensure we're receiving a text command
if (incoming_type != DATATYPE_RMONBINARY)
{
//errortype = 1;
usb_purge();
osSyncPrintf("USB: Received invalid type %d\n", incoming_type);
return;
}
osSyncPrintf("USB: Read data\n");
usb_read(buffer, size);
return;
}
}
#endif
}
/**
* Removed
* rmon7000CEC8
* unknown function
*/
void rmon7000CEC8(void) {
#ifdef DEBUG
//removed
#endif
}
/**
* Removed
* rmon7000CED0
* unknown function
*/
void rmon7000CED0(void) {
#ifdef DEBUG
//removed
#endif
}
/**
* Removed
* rmon7000CED8
* unknown function
*/
void rmon7000CED8(void) {
#ifdef DEBUG
//removed
#endif
}
/**
* Removed
* rmonPrintf
*/
void rmonPrintf(void)
{
}
/*
* -----------------------------------------------------------------
* This is a new file (PR/libultra/libc/syncprintf.c)
*/
/**
* Send text to Remote Debugger, GE redirects to screen (crashAppendChar)
*/
#ifndef ENABLE_USB
void *proutSyncPrintf(void *str, const char *buf, size_t n)
{
u32 sent = 0;
#ifndef _FINALROM
while (sent < n)
{
# ifdef USERDB
sent += __osRdbSend((u8 *)&buf[sent], n - sent, RDB_TYPE_GtoH_PRINT);
# endif
crashAppendChar(buf[sent++]);
}
#endif
return ((void *)1); /* return a fake pointer so that it's not NULL */
}
#endif
/**
* Print formatted string to Debugger
*/
void osSyncPrintf(const char *fmt, ...)
{
#ifdef ENABLE_USB
u8 buffer[100];
#endif
int ans;
va_list args;
va_start(args, fmt);
#ifdef ENABLE_USB
ans = _Printf(&proutSprintf, buffer, fmt, args);
#else
ans = _Printf(&proutSyncPrintf, NULL, fmt, args);
#endif
va_end(args);
#ifdef ENABLE_USB
if (ans >= 0) {
if (ans > 99)
{
ans = 99;
}
buffer[ans] = 0;
}
usb_write_text(buffer, ans);
#endif
}
#ifdef ENABLE_USB
/**
* Print formatted string to Debugger.
* This is a non blocking call. The printf message will be copied
* to the rmon printf queue. It is possible for the queue to overflow (wrap around).
* The printf message is copied to a local byte array, truncating the message if necessary.
*/
void osAsyncPrintf(const char *format, ...)
{
s32 written;
va_list args;
struct RmonMesgPrintf *dest = &rmonMesgPrintfStack[rmonCurrentMesgPrintfStack];
rmonCurrentMesgPrintfStack++;
if (rmonCurrentMesgPrintfStack > 1) {
rmonCurrentMesgPrintfStack = 0;
}
dest->type = RMON_MESG_PRINTF;
va_start(args, format);
written = _Printf(proutSprintf, dest->buffer, format, args);
va_end(args);
if (written >= 0) {
if (written > RMON_MESSAGE_PRINTF_BUFFER_LENGTH - 1)
{
written = RMON_MESSAGE_PRINTF_BUFFER_LENGTH - 1;
}
dest->buffer[written] = 0;
}
dest->length = written;
osSendMesg(&rmonMessageQueue, (OSMesg)dest, OS_MESG_NOBLOCK);
}
void osQueueTest(void)
{
struct RmonMesgBase *dest = &rmonMesgStack[rmonCurrentMesgStack];
rmonCurrentMesgStack++;
if (rmonCurrentMesgStack > 1) {
rmonCurrentMesgStack = 0;
}
dest->type = RMON_MESG_TEST;
osSendMesg(&rmonMessageQueue, (OSMesg)dest, OS_MESG_NOBLOCK);
}
void rmonHandleTestMsg(struct RmonMesgBase *msg)
{
usb_write_text("????\n", 6);
}
void rmonHandlePrintfMsg(struct RmonMesgPrintf *msg)
{
// pending read data will abort write, so clobber any incoming data.
//usb_purge();
usb_write_text(msg->buffer, msg->length);
}
#endif