Skip to content

Commit

Permalink
v31.4 Bugfixes and additions
Browse files Browse the repository at this point in the history
  • Loading branch information
SweMonkey committed Jan 2, 2025
1 parent 5648d4d commit 8c13f23
Show file tree
Hide file tree
Showing 49 changed files with 1,688 additions and 1,113 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 smds
Copyright (c) 2025 smds

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
39 changes: 39 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
v0.31.4
IRC: Added NICK and PART to the internal command parser that parses messages received from the server. (Sending NICK/PART from client to server is already supported)
IRC: Reverted the upload icon colour back to default, changing it from red to orange serves no purpose anymore.
Drivers: Added timeout to pinging in xport driver, apparently there wasn't one already...
Telnet/Term: Added IAC DM (Data Mark).
Telnet/Term: Prototype scrollable regions (Scroll part of the screen vertically). It can scroll content upwards only! scrolling down requires more work.
Telnet/Term: Rewrote the OSC parser so it is not hardcoded to just reading title changes.
Telnet/Term: Fake RGB24 attribute colour support (Truncates RGB888 to RGB111, yes 1 bit per channel).
Telnet/Term: Rewrote attribute code parser slightly, hopefully I haven't borked colour attribute changes in some way...
Telnet/Term: Cursor is now using s16 instead of s32 (Haven't dared to change this before in case of hidden edge cases).
Telnet/Term: Many little changes and fixes here and there.
Telnet: Added F1-F12, Page Up/Down, End, Home, Insert and Delete function keys.
Buffer system now uses boolean return values instead of cryptic magic numbers as return values on PUSH/POP.
Cleaned up Buffer_PeekLast() and various other functions.
For no real reason: 2 new theme colours: Aqua and hot pink. Don't ask why.
Removed old debug streaming.
Changed Backspace default back from ^H to DEL now that I've found out why it bugged out at times (smdt manually moved cursor and inserted blankspace, it shouldn't do that).
Some UTF-8 code point fixes and additions in U+2500 and a few arrows in U+2190.
Added 68k exception pages (Inspired by Vladikcompers recent exception handler added to SGDK). Still fairly basic but its better than what SMDT had before: no exception handlers at all.
Uname command can now show SMDT build date and time.

Bugs?
Spurious keyboard input when SMDT is overwhelmed by large incoming data transfers? May be emulator/xport emulator error on my end but I have not noticed this problem in previous versions of SMDT...

Bugfixes:
IRC: Receiving NAMES list should no longer show a channel as having new messages.
IRC: Nicklist now shows the last nick in the nicklist. Beware that showing >300 nicks may cause issues still.
IRC: Normal mIRC colours should now work as expected when using 4x8 fonts, albeit in mono (2 colours).
IRC: Now using \4 and \5 to set/unset custom text colouring in IRC (instead of \1 and \2), in hindsight this change was not actually necessary but it doesn't matter anyway.
Telnet/Term: Fixed G1 charset bug that caused the terminal to use the wrong character set in certain applications.
Telnet/Term: Fixed ESC PARAM not resetting all parameters between different escape sequences.
Telnet/Term: Finally fixed wraparound "bug" that appears when the terminal receives \n at column 80 (causing 2 newlines), as opposed to receiving a printable character at column 80 (which should wrap and print to the next line).
Drivers: Maybe fixed PS/2 timing issues on model 2 / NTSC genesis systems?

Known bugs:
TimeToStr_Full() in IRC client does not take your timezone into account? (Command 333 @ IRC.c).
4x8 colouring in IRC can only colour even number of characters, uneven number will result in the final character being uncoloured.


v0.31.3 Minor bugfix
IRC mono colour antialiasing colour is now updated to reflect the new amber text colour.
Interrupts were disabled to early on StateExit() which made the XPN drivers unable to actually communicate during Disconnect(). This caused excessive delays when trying to disconnect from servers.
Expand Down
4 changes: 2 additions & 2 deletions doc/VRAM.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ $10 - $15 Cursor tiles (Block/Line/Bar 8x8/4x8)
$16 Blank/invisible cursor tile
$17 Mouse pointer cursor
$18 - $1F Icons
$20 - $2F Screensaver sprite tiles (16 tiles) - Used by boot logo on startup
$30 - $3F Free (16 tiles) - Used by boot logo on startup
$20 - $2F Screensaver sprite tiles (16 tiles)
$30 - $3F Free (16 tiles)
$40 - $23F Terminal ASCII font
$240 - $43F Terminal ASCII font duplicate used for 80 column colour support otherwise free (480 tiles)
$440 - $4FF UI font and window tiles
Expand Down
147 changes: 45 additions & 102 deletions src/Buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@

/// @brief Check if buffer is full
/// @param b Pointer to buffer
/// @return 0xFF if full, otherwise 0
u8 Buffer_IsFull(Buffer *b)
/// @return TRUE if full, otherwise FALSE
bool Buffer_IsFull(Buffer *b)
{
if ((b->head + 1) == b->tail) // if the head + 1 == tail, circular buffer is full
return 0xFF;

return 0; // return false
return ((b->head + 1 == BUFFER_LEN ? 0 : b->head + 1) == b->tail);
}

/// @brief Check if buffer is empty
/// @param b Pointer to buffer
/// @return 0xFF if empty, otherwise 0
u8 Buffer_IsEmpty(Buffer *b)
/// @return TRUE if empty, otherwise FALSE
bool Buffer_IsEmpty(Buffer *b)
{
if (b->head == b->tail) // if the head == tail, circular buffer is empty
return 0xFF;

return 0; // return false
return b->head == b->tail;
}

/// @brief Get the number of bytes in buffer
Expand All @@ -45,86 +39,56 @@ u16 Buffer_GetNum(Buffer *b)
/// @brief Push byte into buffer at head
/// @param b Pointer to buffer
/// @param data Byte data to push into buffer
/// @return 0xFF is returned if the buffer is full (data is dropped). 0 on successful push
u8 Buffer_Push(Buffer *b, u8 data)
/// @return FALSE is returned if the buffer is full (data is dropped). TRUE on successful push
bool Buffer_Push(Buffer *b, u8 data)
{
u16 next;

next = b->head + 1; // next is where head will point to after this write.
if (next >= BUFFER_LEN)
if (next == BUFFER_LEN)
next = 0;

if (next == b->tail) // if the head + 1 == tail, circular buffer is full
return 0xFF;
return FALSE;

b->data[b->head] = data; // Load data and then move
b->head = next; // head to next data offset.

return 0; // return success to indicate successful push.
return TRUE; // return success to indicate successful push.
}

/// @brief Pop buffer data at tail into return byte
/// @param b Pointer to buffer
/// @param data Return byte to pop data into
/// @return 0xFF is returned if the buffer is empty. 0 on successful pop.
u8 Buffer_Pop(Buffer *b, u8 *data)
/// @return FALSE is returned if the buffer is empty. TRUE on successful pop.
bool Buffer_Pop(Buffer *b, u8 *data)
{
u16 next;

if (b->head == b->tail) // if the head == tail, we don't have any data
return 0xFF;
return FALSE;

next = b->tail + 1; // next is where tail will point to after this read.
if (next >= BUFFER_LEN) next = 0;
if (next == BUFFER_LEN) next = 0;

*data = b->data[b->tail]; // Read data and then move
b->tail = next; // tail to next offset.

return 0; // return success to indicate successful pop.
}

/// @brief Push byte into buffer at specific position - Do not use! Not implemented!
/// @param b Pointer to buffer
/// @param pos Position where the byte should be pushed into
/// @param data Byte data to push into buffer
/// @return FALSE is returned if the buffer is full (data is dropped). TRUE on successful push
bool Buffer_PushAt(Buffer *b, u16 pos, u8 data)
{
//u16 next;

if (Buffer_IsFull(b)) return FALSE;

// Quick path
if (Buffer_IsEmpty(b))
{
b->data[pos] = data;
return TRUE;
}

if (b->tail < b->head)
{
// ...
}
else if (b->tail > b->head)
{
// ...
}

return TRUE; // return success to indicate successful push.
return TRUE; // return success to indicate successful pop.
}

/// @brief Pop the byte at the head of buffer
/// @param b Pointer to buffer
/// @return 0xFF if the buffer is empty. 0 on successful pop.
u8 Buffer_ReversePop(Buffer *b)
/// @return FALSE if the buffer is empty. TRUE on successful pop.
bool Buffer_ReversePop(Buffer *b)
{
if (b->head == b->tail) // if the head == tail, we don't have any data
return 0xFF;
return FALSE;

if (b->head == 0) b->head = BUFFER_LEN-1;
else b->head--;

return 0;
return TRUE;
}

/// @brief Clear the buffer
Expand All @@ -145,60 +109,39 @@ void Buffer_Flush0(Buffer *b)
for (u8 i = 0; i < 32; i++) b->data[i] = 0;
}

/// @brief Get the last <num> of bytes up to head
/// @param b Pointer to buffer
/// @param num Number of bytes to return
/// @param r Array of bytes to return the popped data in
void Buffer_PeekLast(Buffer *b, u16 num, u8 r[])
/// @brief Get the last <num> bytes from the buffer.
/// @param b Pointer to the buffer.
/// @param num Number of bytes to return.
/// @param r Array to store the extracted bytes.
void Buffer_PeekLast(Buffer *b, u16 num, u8 r[])
{
u16 tmpTail = b->tail;
u16 c = 0;
u16 next;
// Calculate the size of valid data in the buffer
u16 size = (b->head >= b->tail)
? (b->head - b->tail)
: (BUFFER_LEN - b->tail + b->head);

// Get the size difference between the head and tail to determine amount of bytes we can pull from it
if (b->tail < b->head)
{
tmpTail = (b->head - num) > 0 ? b->head - num : 0; // Tail smaller than head. We must check if we actually have 'num' bytes available
}
else if (b->tail > b->head)
{
tmpTail = ((b->head-1-((num-1)-c))+BUFFER_LEN) % BUFFER_LEN; // Tail larger than head. Wrap around and get 'num' bytes available
}

tmpTail = (tmpTail < b->tail ? b->tail : tmpTail); // Make sure the temporary tail is not behind the real tail

if (tmpTail == b->head)
// Determine the actual number of bytes to copy
u16 bytesToCopy = (num > size) ? size : num;

// Ensure the result array is fully zero-filled if no valid data is available
if (bytesToCopy == 0)
{
// Tail == head. No bytes available, clear 'r' and return
while (c < num)
{
r[c] = 0;
c++;
}
for (u16 i = 0; i < num; i++) r[i] = 0;
return;
}

// Fill the array 'r' with all the bytes from head back to the tail in reverse order
while (c < num)
{
if (b->head == tmpTail) // if the head == tail, we don't have any data
break;

next = tmpTail + 1; // next is where tail will point to after this read.
if(next >= BUFFER_LEN)
next = 0;

r[c] = b->data[tmpTail]; // Read data and then move
tmpTail = next; // tail to next offset.
c++;
}
// Calculate the starting index for reading
u16 start = (b->head >= bytesToCopy)
? (b->head - bytesToCopy)
: (BUFFER_LEN + b->head - bytesToCopy);

// If the array 'r' is not full then fill the rest of the array with NULL
while (c < num)
// Copy the valid bytes into the result array
for (u16 i = 0; i < bytesToCopy; i++)
{
r[c] = 0;
c++;
u16 index = (start + i) % BUFFER_LEN;
r[i] = b->data[index];
}

return;
// Null-terminate/zero-fill the remainder of the array
for (u16 i = bytesToCopy; i < num; i++) r[i] = 0;
}
10 changes: 5 additions & 5 deletions src/Buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ typedef struct s_buffer
u16 tail;
} Buffer;

u8 Buffer_IsFull(Buffer *b);
u8 Buffer_IsEmpty(Buffer *b);
bool Buffer_IsFull(Buffer *b);
bool Buffer_IsEmpty(Buffer *b);
u16 Buffer_GetNum(Buffer *b);
u8 Buffer_Push(Buffer *b, u8 data);
u8 Buffer_Pop(Buffer *b, u8 *data);
u8 Buffer_ReversePop(Buffer *b);
bool Buffer_Push(Buffer *b, u8 data);
bool Buffer_Pop(Buffer *b, u8 *data);
bool Buffer_ReversePop(Buffer *b);

void Buffer_Flush(Buffer *b);
void Buffer_Flush0(Buffer *b);
Expand Down
30 changes: 14 additions & 16 deletions src/DevMgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,21 +131,16 @@ void DetectDevices()

// -- PS/2 Keyboard setup --------------------------
bool ps2_r = FALSE;

// Try to find the keyboard twice... because apparently that is needed in some cases
for (u8 i = 0; i < 2; i++)
{
if ( DevId0 == DEVICE_UNKNOWN) {ps2_r = KB_PS2_Init(DP_Port1);}
if ((DevId1 == DEVICE_UNKNOWN) && !ps2_r) {ps2_r = KB_PS2_Init(DP_Port2);}
if ((DevId2 == DEVICE_UNKNOWN) && !ps2_r) {ps2_r = KB_PS2_Init(DP_Port3);}

if (ps2_r)
{
DevList[DevSeq++] = &DRV_KBPS2;
TRM_SetStatusIcon(ICO_KB_OK, ICO_POS_0);
bNoKeyboard = FALSE;
break;
}
if ( DevId0 == DEVICE_UNKNOWN) {ps2_r = KB_PS2_Init(DP_Port1);}
if ((DevId1 == DEVICE_UNKNOWN) && !ps2_r) {ps2_r = KB_PS2_Init(DP_Port2);}
if ((DevId2 == DEVICE_UNKNOWN) && !ps2_r) {ps2_r = KB_PS2_Init(DP_Port3);}

if (ps2_r)
{
DevList[DevSeq++] = &DRV_KBPS2;
TRM_SetStatusIcon(ICO_KB_OK, ICO_POS_0);
bNoKeyboard = FALSE;
}

// -- Saturn Keyboard setup ------------------------
Expand Down Expand Up @@ -198,11 +193,11 @@ void DetectDevices()
char SEGASTR[5] = {0, 0, 0, 0, 0};
memcpyU32((u32*)SEGASTR, (u32*)0x400100, 1);
//stdout_printf("SEGASTR= \"%s\" -- SCDver= %u\n%c %c %c %c\n", SEGASTR, SCDver, *((vu8*) 0x400100), *((vu8*) 0x400101), *((vu8*) 0x400102), *((vu8*) 0x400103));
//printf("SEGASTR= \"%s\" -- SCDver= %u\n%c %c %c %c\n", SEGASTR, SCDver, *((vu8*) 0x400100), *((vu8*) 0x400101), *((vu8*) 0x400102), *((vu8*) 0x400103));
if ((SCDver) || (strcmp(SEGASTR, "SEGA") == 0))
{
stdout_printf("%s CD found.\n", bPALSystem ? "SEGA" : "MEGA");
printf("%s CD found.\n", bPALSystem ? "SEGA" : "MEGA");
bMegaCD = TRUE;
}*/

Expand Down Expand Up @@ -269,6 +264,9 @@ void DetectDevices()

Stdout_Push("├No network adapters found\n");
Stdout_Push("└Listening on built in UART\n");

TRM_SetStatusIcon(ICO_NET_ERROR, ICO_POS_1);
TRM_SetStatusIcon(ICO_NET_ERROR, ICO_POS_2);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/DevMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ typedef struct s_device

#define DEV_PORT ((s >> 1)+1)
#define DEV_SLOT(device) (device.Id.Bitshift >> 1)
#define DEV_FULL(device) DEV_PORT, DEV_SLOT(device)

#define DEV_MASK_SHIFT(d) (d.Id.Bitmask << d.Id.Bitshift) // Helper macro to get the shifted mask
#define DEV_MASK_AND_SHIFT(d, b) ((b & d.Id.Bitmask) << d.Id.Bitshift) // Helper macro to apply the mask and shift to a value 'b'
Expand Down
2 changes: 1 addition & 1 deletion src/FavView.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static const char *tab_text[3] =

static char *list_telnet[] =
{
"alt.org:23", "telehack.com:23", "bbs.bottomlessabyss.net:2023", "bbs.kd3.us:23"
"alt.org:23", "telehack.com:23", "bbs.bottomlessabyss.net:2023"
};

static char *list_irc[] =
Expand Down
6 changes: 3 additions & 3 deletions src/HexView.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void HexView_Open(const char *filename)
{
strcpy(WinTitle, "HexView - Stdout");

bufptr = (char*)stdout.data;
bufptr = (char*)StdoutBuffer.data;
bufsize = BUFFER_LEN;
bIOFILE = TRUE;
}
Expand All @@ -170,7 +170,7 @@ void HexView_Open(const char *filename)
SM_File *f = F_Open(fn_buf, FM_RDONLY);
if (f == NULL)
{
stdout_printf("Failed to open file \"%s\"\n", filename);
printf("Failed to open file \"%s\"\n", filename);
return;
}

Expand All @@ -180,7 +180,7 @@ void HexView_Open(const char *filename)
bufptr = (char*)malloc(bufsize+1);
if (bufptr == NULL)
{
stdout_printf("Failed to allocate buffer\n");
printf("Failed to allocate buffer\n");
F_Close(f);
return;
}
Expand Down
Loading

0 comments on commit 8c13f23

Please sign in to comment.