You can subscribe to this list here.
| 2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(35) |
Dec
(2) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2004 |
Jan
(37) |
Feb
(10) |
Mar
|
Apr
(2) |
May
(17) |
Jun
(1) |
Jul
(14) |
Aug
(14) |
Sep
(4) |
Oct
|
Nov
(14) |
Dec
(4) |
| 2005 |
Jan
(6) |
Feb
|
Mar
|
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(92) |
Dec
(12) |
| 2006 |
Jan
(3) |
Feb
(4) |
Mar
|
Apr
(5) |
May
(3) |
Jun
(15) |
Jul
(3) |
Aug
(1) |
Sep
(29) |
Oct
(1) |
Nov
(6) |
Dec
(5) |
| 2007 |
Jan
(2) |
Feb
(2) |
Mar
|
Apr
(3) |
May
(14) |
Jun
(2) |
Jul
(16) |
Aug
(73) |
Sep
(12) |
Oct
(9) |
Nov
(27) |
Dec
(3) |
| 2008 |
Jan
(4) |
Feb
(4) |
Mar
(3) |
Apr
(8) |
May
(23) |
Jun
(4) |
Jul
(1) |
Aug
(3) |
Sep
(7) |
Oct
(5) |
Nov
(1) |
Dec
(1) |
| 2009 |
Jan
|
Feb
(10) |
Mar
|
Apr
(4) |
May
(4) |
Jun
(10) |
Jul
|
Aug
(1) |
Sep
|
Oct
(7) |
Nov
|
Dec
(1) |
| 2010 |
Jan
|
Feb
(1) |
Mar
|
Apr
(6) |
May
|
Jun
(3) |
Jul
(11) |
Aug
(1) |
Sep
|
Oct
(15) |
Nov
(1) |
Dec
(5) |
| 2011 |
Jan
(4) |
Feb
(1) |
Mar
(6) |
Apr
|
May
(22) |
Jun
|
Jul
(8) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
| 2012 |
Jan
|
Feb
(10) |
Mar
(1) |
Apr
(6) |
May
(27) |
Jun
(48) |
Jul
(30) |
Aug
(4) |
Sep
|
Oct
(3) |
Nov
(1) |
Dec
(11) |
| 2013 |
Jan
(4) |
Feb
(7) |
Mar
(6) |
Apr
(18) |
May
(28) |
Jun
(20) |
Jul
|
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
(2) |
Dec
(7) |
| 2014 |
Jan
(3) |
Feb
(2) |
Mar
(4) |
Apr
(9) |
May
(11) |
Jun
(10) |
Jul
|
Aug
(18) |
Sep
(12) |
Oct
(17) |
Nov
(10) |
Dec
(16) |
| 2015 |
Jan
(5) |
Feb
(1) |
Mar
(5) |
Apr
(4) |
May
(28) |
Jun
(2) |
Jul
|
Aug
|
Sep
(6) |
Oct
|
Nov
(2) |
Dec
(1) |
| 2016 |
Jan
(14) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
(3) |
Jul
(4) |
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
|
Dec
(1) |
| 2017 |
Jan
(11) |
Feb
|
Mar
(21) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2018 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(2) |
Sep
(4) |
Oct
(4) |
Nov
|
Dec
(1) |
| 2019 |
Jan
(1) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(13) |
Sep
(4) |
Oct
|
Nov
|
Dec
|
| 2020 |
Jan
(10) |
Feb
(9) |
Mar
(5) |
Apr
(4) |
May
(3) |
Jun
(18) |
Jul
(4) |
Aug
(2) |
Sep
(20) |
Oct
(2) |
Nov
|
Dec
|
| 2021 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(1) |
Jun
(2) |
Jul
(1) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
| 2022 |
Jan
(1) |
Feb
(2) |
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(5) |
Sep
|
Oct
(1) |
Nov
|
Dec
(1) |
| 2023 |
Jan
(10) |
Feb
(7) |
Mar
(29) |
Apr
(31) |
May
(29) |
Jun
(34) |
Jul
(3) |
Aug
(24) |
Sep
(22) |
Oct
(10) |
Nov
(38) |
Dec
(27) |
| 2024 |
Jan
(15) |
Feb
(8) |
Mar
(4) |
Apr
(20) |
May
(33) |
Jun
(18) |
Jul
(15) |
Aug
(23) |
Sep
(26) |
Oct
(32) |
Nov
(6) |
Dec
(4) |
| 2025 |
Jan
(7) |
Feb
(1) |
Mar
(1) |
Apr
(4) |
May
(46) |
Jun
(19) |
Jul
(26) |
Aug
(48) |
Sep
(30) |
Oct
(8) |
Nov
(10) |
Dec
(31) |
| 2026 |
Jan
(26) |
Feb
(22) |
Mar
(11) |
Apr
(13) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: kosmirror <kos...@us...> - 2026-04-25 05:45:57
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 45b72287db497d57ee22c969905325e9422d61d4 (commit)
from d02cfe32d94cdf4efa5b677c3c803d297ad8a1bb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 45b72287db497d57ee22c969905325e9422d61d4
Author: Paul Cercueil <pa...@cr...>
Date: Thu Apr 23 14:51:02 2026 +0200
fs: Add workaround for fs_stat() on mount points
The various VFS handlers may not implement a .stat backend function. For
instance, the socket VFS does not implement any. However, we still want
to be able to tell that /sock is a directory and not a file.
Add a workaround, so that if we're trying to fs_stat() a mount point,
and the corresponding VFS does not provide a .stat backend function, we
just return it as a 0777 directory.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
kernel/fs/fs.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c
index 986a6417..6aeaaafb 100644
--- a/kernel/fs/fs.c
+++ b/kernel/fs/fs.c
@@ -868,6 +868,13 @@ int fs_stat(const char *path, struct stat *buf, int flag) {
return vfs->stat(vfs, fullpath + strlen(vfs->nmmgr.pathname), buf,
flag);
}
+ else if(!strcmp(path, vfs->nmmgr.pathname)) {
+ /* no vfs->stat - handle stat() on the mount folder */
+ *buf = (struct stat){
+ .st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO,
+ };
+ return 0;
+ }
else {
errno = ENOSYS;
return -1;
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-22 21:51:29
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via d02cfe32d94cdf4efa5b677c3c803d297ad8a1bb (commit)
via ed46bf037c1eebad0c56d32faf2656229be4b688 (commit)
from eca279028de19fca51b967a8515a9fb32b96f75d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d02cfe32d94cdf4efa5b677c3c803d297ad8a1bb
Author: Paul Cercueil <pa...@cr...>
Date: Tue Apr 21 13:25:44 2026 +0200
nmmgr: Use a single-linked list
There's no real reason to justify a double-linked list here, so switch
to a single-linked list.
Note the slightly more complex nmmgr_handler_remove() as we first check
whether or not the element to remove is in the list before removing it
(just because we return a different value if it does). This is fine as
this function is not meant to be called again and again.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit ed46bf037c1eebad0c56d32faf2656229be4b688
Author: Paul Cercueil <pa...@cr...>
Date: Tue Apr 21 13:24:15 2026 +0200
nmmgr: Check return code of mutex_lock_irqsafe()
The return value of mutex_lock_irqsafe() should always be checked. If
the locking failed, we will get an imbalance when we get to the
mutex_unlock().
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
include/kos/nmmgr.h | 4 ++--
kernel/exports/exports.c | 4 ++--
kernel/exports/nmmgr.c | 27 +++++++++++++++------------
kernel/fs/fs.c | 2 +-
kernel/fs/fs_dev.c | 2 +-
5 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/include/kos/nmmgr.h b/include/kos/nmmgr.h
index f2213569..763246a0 100644
--- a/include/kos/nmmgr.h
+++ b/include/kos/nmmgr.h
@@ -39,7 +39,7 @@ struct nmmgr_handler;
Contrary to what doxygen may think, this is not a function.
*/
-typedef LIST_HEAD(nmmgr_list, nmmgr_handler) nmmgr_list_t;
+typedef SLIST_HEAD(nmmgr_list, nmmgr_handler) nmmgr_list_t;
/** \brief List entry initializer for static structs.
\ingroup system_namemgr
@@ -64,7 +64,7 @@ typedef struct nmmgr_handler {
uint32_t version; /* Version code */
uint32_t flags; /* Bitmask of flags */
uint32_t type; /* Type of handler */
- LIST_ENTRY(nmmgr_handler) list_ent; /* Linked list entry */
+ SLIST_ENTRY(nmmgr_handler) list_ent; /* Linked list entry */
} nmmgr_handler_t;
/** \brief Alias handler interface.
diff --git a/kernel/exports/exports.c b/kernel/exports/exports.c
index da93af1a..5b1854fc 100644
--- a/kernel/exports/exports.c
+++ b/kernel/exports/exports.c
@@ -73,7 +73,7 @@ export_sym_t *export_lookup(const char *name) {
nmmgrs = nmmgr_get_list();
/* Go through and look at each symtab entry */
- LIST_FOREACH(nmmgr, nmmgrs, list_ent) {
+ SLIST_FOREACH(nmmgr, nmmgrs, list_ent) {
/* Not a symtab -> ignore */
if(nmmgr->type != NMMGR_TYPE_SYMTAB)
continue;
@@ -127,7 +127,7 @@ export_sym_t *export_lookup_addr(uintptr_t addr) {
nmmgrs = nmmgr_get_list();
/* Go through and look at each symtab entry */
- LIST_FOREACH(nmmgr, nmmgrs, list_ent) {
+ SLIST_FOREACH(nmmgr, nmmgrs, list_ent) {
/* Not a symtab -> ignore */
if(nmmgr->type != NMMGR_TYPE_SYMTAB)
continue;
diff --git a/kernel/exports/nmmgr.c b/kernel/exports/nmmgr.c
index dd31a114..bc58ab3c 100644
--- a/kernel/exports/nmmgr.c
+++ b/kernel/exports/nmmgr.c
@@ -39,7 +39,7 @@ nmmgr_handler_t * nmmgr_lookup(const char *fn) {
size_t cur_len = 0, tmp_len;
/* Scan the handler table and look for the best path match */
- LIST_FOREACH(tmp, &nmmgr_handlers, list_ent) {
+ SLIST_FOREACH(tmp, &nmmgr_handlers, list_ent) {
tmp_len = strlen(tmp->pathname);
if(!strncasecmp(tmp->pathname, fn, tmp_len)) {
if(cur_len < tmp_len) {
@@ -70,7 +70,7 @@ nmmgr_list_t * nmmgr_get_list(void) {
int nmmgr_handler_add(nmmgr_handler_t *hnd) {
mutex_lock(&mutex);
- LIST_INSERT_HEAD(&nmmgr_handlers, hnd, list_ent);
+ SLIST_INSERT_HEAD(&nmmgr_handlers, hnd, list_ent);
mutex_unlock(&mutex);
@@ -79,18 +79,21 @@ int nmmgr_handler_add(nmmgr_handler_t *hnd) {
/* Remove a name handler */
int nmmgr_handler_remove(nmmgr_handler_t *hnd) {
- nmmgr_handler_t *c, *tmp;
+ nmmgr_handler_t *tmp;
int rv = -1;
- mutex_lock_irqsafe(&mutex);
+ if(mutex_lock_irqsafe(&mutex) < 0)
+ return -1;
/* Verify that it's actually in there */
- LIST_FOREACH_SAFE(c, &nmmgr_handlers, list_ent, tmp) {
- if(c == hnd) {
- LIST_REMOVE(hnd, list_ent);
- rv = 0;
+ SLIST_FOREACH(tmp, &nmmgr_handlers, list_ent) {
+ if(tmp == hnd)
break;
- }
+ }
+
+ if(tmp) {
+ SLIST_REMOVE(&nmmgr_handlers, hnd, nmmgr_handler, list_ent);
+ rv = 0;
}
mutex_unlock(&mutex);
@@ -103,7 +106,7 @@ KOS_INIT_FLAG_WEAK(export_init, false);
/* Initialize structures */
void nmmgr_init(void) {
/* Start with no handlers */
- LIST_INIT(&nmmgr_handlers);
+ SLIST_INIT(&nmmgr_handlers);
/* Initialize our internal exports */
KOS_INIT_FLAG_CALL(export_init);
@@ -112,10 +115,10 @@ void nmmgr_init(void) {
void nmmgr_shutdown(void) {
nmmgr_handler_t *c, *n;
- c = LIST_FIRST(&nmmgr_handlers);
+ c = SLIST_FIRST(&nmmgr_handlers);
while(c != NULL) {
- n = LIST_NEXT(c, list_ent);
+ n = SLIST_NEXT(c, list_ent);
if(c->flags & NMMGR_FLAGS_NEEDSFREE)
free(c);
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c
index fa1ebeae..986a6417 100644
--- a/kernel/fs/fs.c
+++ b/kernel/fs/fs.c
@@ -68,7 +68,7 @@ static dirent_t *fs_root_readdir(fs_hnd_t *handle) {
nmhead = nmmgr_get_list();
- LIST_FOREACH(nmhnd, nmhead, list_ent) {
+ SLIST_FOREACH(nmhnd, nmhead, list_ent) {
if((nmhnd->flags & NMMGR_FLAGS_INDEV))
continue;
diff --git a/kernel/fs/fs_dev.c b/kernel/fs/fs_dev.c
index 5301f755..f787a826 100644
--- a/kernel/fs/fs_dev.c
+++ b/kernel/fs/fs_dev.c
@@ -34,7 +34,7 @@ static dirent_t *dev_root_readdir(dev_hnd_t * handle) {
nmhead = nmmgr_get_list();
- LIST_FOREACH(nmhnd, nmhead, list_ent) {
+ SLIST_FOREACH(nmhnd, nmhead, list_ent) {
if(!(nmhnd->flags & NMMGR_FLAGS_INDEV))
continue;
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-21 19:07:36
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via eca279028de19fca51b967a8515a9fb32b96f75d (commit)
from a8a520104f93036a7826bf308566a15f85be90f8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit eca279028de19fca51b967a8515a9fb32b96f75d
Author: darc <da...@pr...>
Date: Mon Apr 20 12:45:32 2026 -0500
init_flags_default.c includes arch/arch.h, but only for its inclusion of
kos/init.h. Change to directly include kos/init.h instead.
-----------------------------------------------------------------------
Summary of changes:
kernel/init/init_flags_default.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/init/init_flags_default.c b/kernel/init/init_flags_default.c
index 2065c43f..2b27cef7 100644
--- a/kernel/init/init_flags_default.c
+++ b/kernel/init/init_flags_default.c
@@ -4,7 +4,7 @@
(c)2002 Megan Potter
*/
-#include <arch/arch.h>
+#include <kos/init.h>
/* Default values which will be used if the user doesn't declare anything */
__weak_symbol KOS_INIT_FLAGS(INIT_DEFAULT);
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-21 04:55:46
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via a8a520104f93036a7826bf308566a15f85be90f8 (commit)
from 66716f6f086dad24cc136576d9f82857a6a294dd (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a8a520104f93036a7826bf308566a15f85be90f8
Author: darc <da...@pr...>
Date: Mon Apr 20 14:27:55 2026 -0500
Don't link dcplib for cpp/filesystem example
-----------------------------------------------------------------------
Summary of changes:
examples/dreamcast/cpp/filesystem/Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/dreamcast/cpp/filesystem/Makefile b/examples/dreamcast/cpp/filesystem/Makefile
index 74bbd909..b650543d 100644
--- a/examples/dreamcast/cpp/filesystem/Makefile
+++ b/examples/dreamcast/cpp/filesystem/Makefile
@@ -21,7 +21,7 @@ rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS)
- kos-c++ -o $(TARGET) $(OBJS) -ldcplib
+ kos-c++ -o $(TARGET) $(OBJS)
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
@@ -33,4 +33,4 @@ dist: $(TARGET)
else
all $(TARGET) clean rm-elf run dist:
$(KOS_GCCVER_MIN_WARNING)
-endif
\ No newline at end of file
+endif
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-20 15:46:24
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 66716f6f086dad24cc136576d9f82857a6a294dd (commit)
from a56d6991dbcfac23cc65d45e66df998eefea588c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 66716f6f086dad24cc136576d9f82857a6a294dd
Author: QuzarDC <qu...@co...>
Date: Sat Apr 18 13:28:58 2026 -0400
maple: Correct shutdown device count.
This was working just plain wrong. It was treating
`maple_driver_detach` as if it was 0 for no device
which is backwards. Now it appropriately counts the
number of devices that were still attached on shutdown.
Additionally remove the unnecessary freeing of
`dev->status`. `maple_driver_detach` already does such
a check and frees it if needed.
-----------------------------------------------------------------------
Summary of changes:
kernel/arch/dreamcast/hardware/maple/maple_init_shutdown.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/kernel/arch/dreamcast/hardware/maple/maple_init_shutdown.c b/kernel/arch/dreamcast/hardware/maple/maple_init_shutdown.c
index 79498f25..51187c7f 100644
--- a/kernel/arch/dreamcast/hardware/maple/maple_init_shutdown.c
+++ b/kernel/arch/dreamcast/hardware/maple/maple_init_shutdown.c
@@ -151,7 +151,6 @@ static void maple_hw_init(void) {
void maple_hw_shutdown(void) {
int p, u, cnt;
uint32_t ptr;
- maple_device_t *dev;
/* Reset all devices to leave them as we found them */
maple_dev_reset_all();
@@ -184,12 +183,9 @@ void maple_hw_shutdown(void) {
/* Free any attached devices */
for(cnt = 0, p = 0; p < MAPLE_PORT_COUNT; p++) {
for(u = 0; u < MAPLE_UNIT_COUNT; u++) {
- cnt += !!maple_driver_detach(p, u);
+ cnt += !maple_driver_detach(p, u);
- dev = maple_state.ports[p].units[u];
- if(dev)
- free(dev->status);
- free(dev);
+ free(maple_state.ports[p].units[u]);
}
}
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-18 15:52:35
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via a56d6991dbcfac23cc65d45e66df998eefea588c (commit)
from 958bce8fc037666ef6476da679c1f73bf133d24a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a56d6991dbcfac23cc65d45e66df998eefea588c
Author: Paul Cercueil <pa...@cr...>
Date: Thu Apr 16 02:23:59 2026 +0200
pthread: Add pthread_cleanup_{push,pop}
Add the functions pthread_cleanup_push() and pthread_cleanup_pop().
These functions can be used to register (and respectively unregister)
cleanup callbacks, that will be called when pthread_exit() is called
(and *not* when the thread routine returns normally).
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
addons/libpthread/pthread_exit.c | 26 ++++++++++++++++++++++++++
include/pthread.h | 2 ++
2 files changed, 28 insertions(+)
diff --git a/addons/libpthread/pthread_exit.c b/addons/libpthread/pthread_exit.c
index 8f7af1a4..da2bb260 100644
--- a/addons/libpthread/pthread_exit.c
+++ b/addons/libpthread/pthread_exit.c
@@ -2,12 +2,38 @@
pthread_exit.c
Copyright (C) 2023 Lawrence Sebald
+ Copyright (C) 2026 Paul Cercueil
*/
#include "pthread-internal.h"
#include <pthread.h>
#include <kos/thread.h>
+struct pthread_cleanup_cb {
+ void (*cb)(void *d);
+ void *arg;
+};
+
+static _Thread_local struct pthread_cleanup_cb cleanups[16];
+static _Thread_local unsigned int nb_cleanups;
+
+void pthread_cleanup_push(void (*routine)(void *), void *arg) {
+ if(nb_cleanups < __array_size(cleanups))
+ cleanups[nb_cleanups++] = (struct pthread_cleanup_cb){ routine, arg };
+}
+
+void pthread_cleanup_pop(int execute) {
+ if(nb_cleanups > 0) {
+ nb_cleanups--;
+
+ if(execute)
+ cleanups[nb_cleanups].cb(cleanups[nb_cleanups].arg);
+ }
+}
+
void pthread_exit(void *value_ptr) {
+ while(nb_cleanups > 0)
+ pthread_cleanup_pop(1);
+
thd_exit(value_ptr);
}
diff --git a/include/pthread.h b/include/pthread.h
index e0e052e1..4380e4e5 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -241,6 +241,8 @@ int pthread_getconcurrency(void);
int pthread_setconcurrency(int new_level);
int pthread_atfork(void (*prepare)(void), void (*parent)(void),
void (*child)(void));
+void pthread_cleanup_push(void (*routine)(void *), void *arg);
+void pthread_cleanup_pop(int execute);
#if __GNU_VISIBLE || __BSD_VISIBLE
/* Technically, the BSD prototype for this is to return void, not int.
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-18 14:42:19
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 958bce8fc037666ef6476da679c1f73bf133d24a (commit)
via 6dddd58d0e14b352bcf1dcb2b355b7cde5161222 (commit)
from 9f9b5f584af8622f7a209959782e3256688ad41c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 958bce8fc037666ef6476da679c1f73bf133d24a
Author: Andress Barajas <and...@gm...>
Date: Fri Apr 17 14:35:52 2026 -0700
Clean up vmu_game VMU status handling by making new_vmu() easier to read.
commit 6dddd58d0e14b352bcf1dcb2b355b7cde5161222
Author: Andress Barajas <and...@gm...>
Date: Fri Apr 17 14:31:25 2026 -0700
Fix vmu_game resource cleanup
Close the /vmu/a1 handle after probing for a VMU so the example
does not leave a VMU filesystem handle open through shutdown otherwise you will be greeted with an ASSERTION FAILURE
Also check the game data allocation before reading and free the
buffer after vmufs_write().
-----------------------------------------------------------------------
Summary of changes:
examples/dreamcast/vmu/vmu_game/vmu_game.c | 67 +++++++++++++++++-------------
1 file changed, 37 insertions(+), 30 deletions(-)
diff --git a/examples/dreamcast/vmu/vmu_game/vmu_game.c b/examples/dreamcast/vmu/vmu_game/vmu_game.c
index 90e0eeb4..a7ab16b1 100644
--- a/examples/dreamcast/vmu/vmu_game/vmu_game.c
+++ b/examples/dreamcast/vmu/vmu_game/vmu_game.c
@@ -1,7 +1,7 @@
/* KallistiOS ##version##
vmu_game.c
- (c)2020 BBHoodsta
+ Copyright (C) 2020 Andy Barajas
*/
/* This simple example shows how to use the vmufs_write function to write
@@ -9,42 +9,45 @@
#include <kos.h>
-void draw_findings(void) {
- file_t d;
+static void draw_findings(void) {
+ file_t d;
d = fs_open("/vmu/a1", O_RDONLY | O_DIR);
-
if(!d) {
bfont_draw_str_vram_fmt(10, 88, false, "Can't read VMU");
+ return;
}
- else {
- bfont_draw_str_vram_fmt(10, 88, false, "VMU found. Press Start.");
- }
+
+ bfont_draw_str_vram_fmt(10, 88, false, "VMU found. Press Start.");
+ fs_close(d);
}
-int dev_checked = 0;
-void new_vmu(void) {
- maple_device_t * dev;
+static void clear_status_area(void) {
+ memset(vram_s + 88 * 640, 0, 640 * BFONT_HEIGHT * sizeof(*vram_s));
+}
+
+static bool dev_checked = false;
+static void new_vmu(void) {
+ maple_device_t *dev;
+ bool present;
dev = maple_enum_dev(0, 1);
+ present = (dev != NULL);
- if(dev == NULL) {
- if(dev_checked) {
- memset(vram_s + 88 * 640, 0, 640 * (480 - 64) * 2);
- bfont_draw_str_vram_fmt(10, 88, false, "No VMU");
- dev_checked = 0;
- }
- }
- else if(dev_checked) {
- }
- else {
- memset(vram_s + 88 * 640, 0, 640 * (480 - 88));
+ if(present == dev_checked)
+ return;
+
+ clear_status_area();
+
+ if(present)
draw_findings();
- dev_checked = 1;
- }
+ else
+ bfont_draw_str_vram_fmt(10, 88, false, "No VMU");
+
+ dev_checked = present;
}
-int wait_start(void) {
+static int wait_start(void) {
maple_device_t *cont;
cont_state_t *state;
@@ -66,28 +69,34 @@ int wait_start(void) {
}
/* Here's the actual meat of it */
-void write_game_entry(void) {
+static void write_game_entry(void) {
file_t f;
int data_size;
uint8_t *data;
maple_device_t *dev;
f = fs_open("/rd/TETRIS.VMS", O_RDONLY);
-
if(!f) {
printf("Error reading Tetris game from romdisk\n");
return;
}
data_size = fs_total(f);
- data = (uint8_t*) malloc(data_size + 1);
+ data = (uint8_t *)malloc(data_size + 1);
+ if(!data) {
+ printf("Error allocating memory for game data\n");
+ fs_close(f);
+ return;
+ }
+
fs_read(f, data, data_size);
fs_close(f);
dev = maple_enum_type(0, MAPLE_FUNC_MEMCARD);
-
if(dev)
vmufs_write(dev, "Tetris", data, data_size, VMUFS_VMUGAME);
+
+ free(data);
}
int main(int argc, char **argv) {
@@ -100,5 +109,3 @@ int main(int argc, char **argv) {
return 0;
}
-
-
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-18 14:35:08
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 9f9b5f584af8622f7a209959782e3256688ad41c (commit)
via 90451a5a942c2e153c7bcc526cd0b1eb51273359 (commit)
via 8fdba3f92690ff3e197d73ff9b93441200538add (commit)
via b9c650f8e966731bd41f66bf5b469d2b6c30d055 (commit)
via a6548a61b9189a40b8ec263c49fa2e2f215b3a48 (commit)
via 4b72fcfe9ce00f064ed12e7110d0241dd574b86c (commit)
via 7f01129155f2d52903db6b9e2fd7e6689989c437 (commit)
via 6f9ef4000ca707c4d97fc2c7a5264804126cc4bf (commit)
via 017be50b54e0fed1b678f5474faf45f2b881b16b (commit)
via 34b2fb53d78e9c4352c40f1d3ff1b30ffd692fea (commit)
via 54e1605621a916d20bf6b9ff6ac0b6575ce538aa (commit)
via 9929a56267824c2ed0a44703430c6442496795ae (commit)
via dc46968cafeeda244ece5f33330d4bfaa1376b9d (commit)
via d155927657fbe33a37612b25012e8a0ddfee0dea (commit)
via 6c0d1d118e64a976586457d1f4555aaef22f1c8b (commit)
via ff7f07d2bca9baa54417aeddf672527ab735a095 (commit)
via 1b2c9e2b762c9ebbeb5d7d767727b4fd8d52b1df (commit)
via f4c0b5369d40097bd4f6725cde825d4140875344 (commit)
via b51f232d42a7f689b5717da8fd8ecdb9f8a39c5d (commit)
via 5cbfe5fd094bdcbe1572682b0189712c2b699372 (commit)
via 53f3b41d714c7f6f1625abbcc4c51a2b12845f22 (commit)
via 67a4c6a8353d47d0afd298b7015ce100d6aae877 (commit)
via 0d33adcf4cd9d309be2e63b33429376e2ae216f1 (commit)
from 3a4642672e318a43f872c23b014364668faa2350 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 9f9b5f584af8622f7a209959782e3256688ad41c
Author: Paul Cercueil <pa...@cr...>
Date: Fri Mar 20 15:16:15 2026 +0100
bba: Don't silently ignore DMA transfer failure
When a DMA transfer is ongoing, and a second DMA transfer has already
been queued, new transfers were silently dropped.
Instead, return an error when this happens, so that the calling
functions at least know about it.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 90451a5a942c2e153c7bcc526cd0b1eb51273359
Author: Paul Cercueil <pa...@cr...>
Date: Thu Mar 19 22:41:54 2026 +0100
bba: Allow DMA transfers in interrupt context
The bba_copy_packet() function can actually run in interrupt context,
because the DMA code path does not wait for the DMA transfer to
complete.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 8fdba3f92690ff3e197d73ff9b93441200538add
Author: Paul Cercueil <pa...@cr...>
Date: Mon Dec 22 12:43:14 2025 +0100
bba: Drop g2_read_block_8_fast()
Three reasons:
- This code has no business being in the broadband adapter's driver, and
if it had to be somewhere, it would be in G2 bus code.
- It is a fallback code, only used for tiny payloads or when called
inside an interrupt context.
- It had some code to handle unaligned transfer lengths, but we now
ensure that the transfer length will always be aligned to 32 bytes.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit b9c650f8e966731bd41f66bf5b469d2b6c30d055
Author: Paul Cercueil <pa...@cr...>
Date: Thu Mar 19 22:09:14 2026 +0100
bba: Rework rxbuff mechanism
I can't exactly explain why, but the previous mechanism was broken. This
could be proven by disabling the DMA path to and force the PIO path
while using the same address alignment code as for the DMA path, which
would result in crashes. Doing this would show that the DMA path would
overwrite data in the shared rxbuff buffer.
Rework this mechanism by aligning all the packet buffers to 32 bytes,
and copying the packets starting from the first 32-byte-aligned address
before the packet (if the packet is not aligned itself), with a copy
size that is itself a multiple of 32 bytes.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit a6548a61b9189a40b8ec263c49fa2e2f215b3a48
Author: Paul Cercueil <pa...@cr...>
Date: Thu Mar 19 22:19:21 2026 +0100
bba: Drop no-wrapping code path
The no-wrapping code path has not really been tested since the beginning
of KallistiOS, and there's no reason to use it. We can just drop it to
simplify the driver.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 4b72fcfe9ce00f064ed12e7110d0241dd574b86c
Author: Paul Cercueil <pa...@cr...>
Date: Wed Mar 4 17:42:17 2026 +0100
bba: Don't check for TX buffer alignment
The TX buffers are guaranteed to be always aligned to 32 bytes.
To be sure, an assert() has been added.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 7f01129155f2d52903db6b9e2fd7e6689989c437
Author: Paul Cercueil <pa...@cr...>
Date: Wed Mar 4 17:41:10 2026 +0100
net: Align TX buffers to 32 bytes
Aligning the TX buffers to 32 bytes means that we won't have to check
for alignment in the network device drivers, or handle non-aligned
buffers in a different way.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 6f9ef4000ca707c4d97fc2c7a5264804126cc4bf
Author: Paul Cercueil <pa...@cr...>
Date: Wed Mar 4 17:39:52 2026 +0100
bba: Use sem_wait_irqsafe()
The code was basically inlining a sem_wait_irqsafe(), so we can call
this function instead.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 017be50b54e0fed1b678f5474faf45f2b881b16b
Author: Paul Cercueil <pa...@cr...>
Date: Wed Mar 4 17:40:35 2026 +0100
bba: Poll for "clear to transmit" with thd_poll()
Handle polling with thd_poll() instead of doing it manually.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 34b2fb53d78e9c4352c40f1d3ff1b30ffd692fea
Author: Paul Cercueil <pa...@cr...>
Date: Fri Feb 27 12:23:01 2026 +0100
bba: Poll RTL ready / link stable with thd_poll()
Handle polling with thd_poll() instead of doing it manually.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 54e1605621a916d20bf6b9ff6ac0b6575ce538aa
Author: Paul Cercueil <pa...@cr...>
Date: Fri Feb 27 12:15:42 2026 +0100
bba: Change link_stable type to bool
The link_stable variable is used as a boolean, therefore it makes sense
to have its type set to bool.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 9929a56267824c2ed0a44703430c6442496795ae
Author: Paul Cercueil <pa...@cr...>
Date: Mon Dec 22 13:10:23 2025 +0100
bba: Prevent racing between bba_copy_dma() and callback
The 'check dma_used' and 'set next_len' must be an atomic operation, or
it will race with the callback function.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit dc46968cafeeda244ece5f33330d4bfaa1376b9d
Author: Paul Cercueil <pa...@cr...>
Date: Sun Dec 21 17:14:18 2025 +0100
bba: Use worker thread for RX
Simplify the threaded RX mechanism by using a worker thread instead of
re-implementing its functionality.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit d155927657fbe33a37612b25012e8a0ddfee0dea
Author: Paul Cercueil <pa...@cr...>
Date: Fri Feb 27 11:23:23 2026 +0100
bba: Factorize code
Factorize the input packet processing code, which was duplicated.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 6c0d1d118e64a976586457d1f4555aaef22f1c8b
Author: Paul Cercueil <pa...@cr...>
Date: Fri Feb 27 11:13:03 2026 +0100
bba: Drop useless code
Drop bba_rx_sema2 semaphore, and bba_lock() / bba_unlock() functions,
which were useless.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit ff7f07d2bca9baa54417aeddf672527ab735a095
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:21:03 2026 +0000
net: Fix ephemeral port allocation
Ephemeral port allocation was not working properly, as it was comparing
port numbers in the wrong byte order.
commit 1b2c9e2b762c9ebbeb5d7d767727b4fd8d52b1df
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:20:40 2026 +0000
net: Fix IP fragmentation off-by-one
IP packets can be up to the MTU size, included; therefore IP packets
whose size match the MTU can be transmitted without being fragmented.
commit f4c0b5369d40097bd4f6725cde825d4140875344
Author: Bruceleeto <ast...@gm...>
Date: Wed Mar 18 07:38:55 2026 +0000
net: Duplicate OOO segments are now rejected
Fix an issue where receiving duplicated out-of-order TCP segments would
cause a deadlock in the network stack.
commit b51f232d42a7f689b5717da8fd8ecdb9f8a39c5d
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:18:23 2026 +0000
net: Reduce TCP timer interval from 50ms to 10ms
50ms is a lot of time, considering that our scheduler typically works at
100 Hz.
commit 5cbfe5fd094bdcbe1572682b0189712c2b699372
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:18:03 2026 +0000
net: Add out-of-order TCP segment reassembly
The network stack was sometimes re-assembling TCP segments incorrectly,
when those arrived out-of-order, causing the application to obtain
corrupted data.
commit 53f3b41d714c7f6f1625abbcc4c51a2b12845f22
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:16:41 2026 +0000
net: Fix TCP window-reopen deadlock
When the receive window was zero, the sender has entered TCP
persist mode. Send a window-update ACK so it knows the window
has reopened â without this the connection deadlocks.
commit 67a4c6a8353d47d0afd298b7015ce100d6aae877
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:16:25 2026 +0000
net: Fix MSS double-subtraction of TCP header size
MSS already represents max data octets (excludes TCP/IP headers per
RFC 879). Don't subtract sizeof(tcp_hdr_t) again.
commit 0d33adcf4cd9d309be2e63b33429376e2ae216f1
Author: Bruceleeto <ast...@gm...>
Date: Sun Mar 22 17:15:51 2026 +0000
net: Increase TCP receive window to 65535
The default TCP receive window of 8192 bytes is just too small and
causes a really low throughput.
-----------------------------------------------------------------------
Summary of changes:
.../dreamcast/hardware/network/broadband_adapter.c | 315 ++++++++-------------
kernel/net/net_arp.c | 5 +-
kernel/net/net_ipv4.c | 3 +-
kernel/net/net_ipv4_frag.c | 2 +-
kernel/net/net_ipv6.c | 3 +-
kernel/net/net_tcp.c | 229 ++++++++++++---
kernel/net/net_thd.c | 5 +-
7 files changed, 320 insertions(+), 242 deletions(-)
diff --git a/kernel/arch/dreamcast/hardware/network/broadband_adapter.c b/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
index e0be5ae0..dfd20791 100644
--- a/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
+++ b/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
@@ -9,6 +9,7 @@
*/
#include <stdalign.h>
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
@@ -24,17 +25,17 @@
#include <kos/net.h>
#include <kos/thread.h>
#include <kos/sem.h>
+#include <kos/worker_thread.h>
/* Configuration definitions */
#define RTL_MEM (0x1840000)
-#define RX_NOWRAP 1 /* Default to no wrapping */
#define RX_BUFFER_SHIFT 1 /* 0 : 8Kb, 1 : 16Kb, 2 : 32Kb, 3 : 64Kb */
#define RX_CONFIG_DEFAULT (RT_ERTH(0) | RT_RXC_RXFTH(0) | \
RT_RXC_RBLEN(RX_BUFFER_SHIFT) | RT_RXC_MXDMA(6) | \
- (RX_NOWRAP ? RT_RXC_WRAP : 0))
+ RT_RXC_WRAP)
#define RX_BUFFER_LEN (0x2000 << RX_BUFFER_SHIFT)
@@ -226,7 +227,7 @@ static uint32_t const txdesc[TX_NB_BUFFERS] = {
};
/* Is the link stabilized? */
-static volatile int link_stable;
+static bool link_stable;
/* Receive callback */
static eth_rx_callback_t eth_rx_callback;
@@ -244,19 +245,17 @@ void bba_set_rx_callback(eth_rx_callback_t cb) {
eth_rx_callback = cb;
}
-static int rtl_reset(void) {
- int i = 100;
+static int rtl_is_ready(void *d) {
+ (void)d;
+ return !(g2_read_8(NIC(RT_CHIPCMD)) & RT_CMD_RESET);
+}
+static int rtl_reset(void) {
/* Soft-reset the chip */
g2_write_8(NIC(RT_CHIPCMD), RT_CMD_RESET);
/* Wait for it to come back */
- while((g2_read_8(NIC(RT_CHIPCMD)) & RT_CMD_RESET) && i > 0) {
- i--;
- thd_sleep(10);
- }
-
- if(g2_read_8(NIC(RT_CHIPCMD)) & RT_CMD_RESET) {
+ if(!thd_poll(rtl_is_ready, NULL, 1000)) {
dbglog(DBG_ERROR, "bba: timed out on reset\n");
return -1;
}
@@ -271,7 +270,7 @@ static int rtl_reset(void) {
static int bba_hw_init(void) {
uint32_t tmp;
- link_stable = 0;
+ link_stable = false;
/* Initialize GAPS */
if(gaps_init() < 0)
@@ -426,45 +425,11 @@ static void bba_hw_shutdown(void) {
asic_evt_remove_handler(ASIC_EVT_EXP_PCI);
}
-static void g2_read_block_8_fast(uint8_t *dst, uint8_t *src, int len) {
- if(len <= 0)
- return;
-
- g2_lock_scoped();
-
- uint32_t *d = (uint32_t *) dst;
- uint32_t *s = (uint32_t *) src;
- len = (len + 3) >> 2;
-
- while(len & 7) {
- *d++ = *s++;
- --len;
- }
-
- if(len > 0) {
-
- len >>= 3;
-
- do {
- d[0] = *s++;
- d[1] = *s++;
- d[2] = *s++;
- d[3] = *s++;
- d[4] = *s++;
- d[5] = *s++;
- d[6] = *s++;
- d[7] = *s++;
- d += 8;
- }
- while(--len);
- }
-}
-
-
#define RXBSZ (64*1024) /* must be a power of two */
#define MAX_PKTS (RXBSZ / 32)
static struct pkt {
- int pkt_size;
+ uint16_t pkt_size;
+ uint16_t offt;
uint8_t *rxbuff;
} rx_pkt[MAX_PKTS];
@@ -476,11 +441,6 @@ static int dma_used;
static uint32_t rx_size;
-static kthread_t * bba_rx_thread;
-static semaphore_t bba_rx_sema;
-static int bba_rx_exit_thread;
-static semaphore_t bba_rx_sema2;
-
static void bba_rx(void);
static semaphore_t tx_sema;
@@ -489,6 +449,8 @@ static uint8_t *next_dst;
static uint8_t *next_src;
static int next_len;
+static kthread_worker_t *rx_worker;
+
static void rx_finish_enq(int room) {
/* Tell the chip where we are for overflow checking */
rtl.cur_rx = (rtl.cur_rx + rx_size + 4 + 3) & ~3;
@@ -496,7 +458,7 @@ static void rx_finish_enq(int room) {
if(room > 0 && (((rxin + 1) % MAX_PKTS) != rxout)) {
rxin = (rxin + 1) % MAX_PKTS;
- sem_signal(&bba_rx_sema);
+ thd_worker_wakeup(rx_worker);
thd_schedule(true);
}
}
@@ -520,29 +482,21 @@ static void bba_dma_cb(void *p) {
}
}
-static int bba_copy_dma(uint8_t *dst, uint32_t s, int len) {
+static int bba_copy_packet(uint8_t *dst, uint32_t s, int len) {
uint8_t *src = (uint8_t *) s;
- if(len <= 0)
- return 1;
-
- if(len > DMA_THRESHOLD && !irq_inside_int()) {
- uint32_t add;
-
- /*
- This way all will be nicely 32 bytes aligned (assuming that dst and src have
- same alignment initially and that we don't care about the beginning of dst
- buffer)
- */
- add = ((uint32_t) src) & 31;
- len += add;
- src -= add;
- dst -= add;
+ assert(__is_aligned((uintptr_t)dst, 32));
+ assert(__is_aligned(s, 32));
+ assert(__is_aligned(len, 32));
+ if(len > DMA_THRESHOLD) {
/* Invalidate the dcache over the range of the data. */
if(!__is_defined(USE_P2_AREA))
dcache_inval_range((uint32_t) dst, len);
+ /* Prevent racing against the callback */
+ irq_disable_scoped();
+
if(!dma_used) {
dma_used = 1;
g2_dma_transfer(dst, src, len, 0,
@@ -550,6 +504,10 @@ static int bba_copy_dma(uint8_t *dst, uint32_t s, int len) {
1, /* dir = 1, we're *reading* from the g2 bus */
0, G2_DMA_CHAN_BBA, 0);
}
+ else if(next_len) {
+ /* RX DMA is really busy - notify that we couldn't read the packet */
+ return -1;
+ }
else {
next_dst = dst;
next_src = src;
@@ -559,77 +517,85 @@ static int bba_copy_dma(uint8_t *dst, uint32_t s, int len) {
return 0;
}
else {
- g2_read_block_8_fast(dst, src, len);
+ g2_read_block_32((uint32_t *)dst, (uint32_t)src, len >> 2);
return !dma_used;
}
}
-/* Utility function to copy out a some data from the ring buffer into an SH-4
- buffer. This is done to make sure the buffers don't overflow. */
-/* XXX Could probably use a memcpy8 here, even */
-static int bba_copy_packet(uint8_t *dst, uint32_t src, int len) {
-
- if(__is_defined(RX_NOWRAP) || (src + len) < RX_BUFFER_LEN) {
- /* Straight copy is ok */
- return bba_copy_dma(dst, rtl_mem + src, len);
- }
- else {
- /* Have to copy around the ring end */
- bba_copy_dma(dst, rtl_mem + src, RX_BUFFER_LEN - src);
-
- return bba_copy_dma(dst + (RX_BUFFER_LEN - src),
- rtl_mem, len - (RX_BUFFER_LEN - src));
- }
+/* Compute the difference between the read head and the write head in a circular buffer */
+static inline unsigned int ptr_diff(const uint8_t *rd, const uint8_t *wr, size_t len) {
+ return (len + (uintptr_t)rd - (uintptr_t)wr) % len;
}
static int rx_enq(int ring_offset, size_t pkt_size) {
+ size_t aligned_size;
+ uint16_t offt;
+
/* If there's no one to receive it, don't bother. */
- if(eth_rx_callback) {
- if(rxin != rxout &&
- (((rx_pkt[rxout].rxbuff - (rxbuff + 32)) - rxbuff_pos) & (RXBSZ - 1)) < pkt_size + 2048) {
- return -1;
- }
+ if(!eth_rx_callback)
+ return -1;
+
+ offt = ring_offset & 0x1f;
+ aligned_size = __align_up(pkt_size + offt, 32);
+
+ /* Do we have space for it? */
+ if(rxin != rxout
+ && ptr_diff(rx_pkt[rxout].rxbuff, &rxbuff[rxbuff_pos], RXBSZ) < aligned_size) {
+ dbglog(DBG_WARNING, "No space in RX buffer\n");
+ return -1;
+ }
+
+ /* Get a pointer to the receive buffer where we will store the packet */
+ rx_pkt[rxin].rxbuff = &rxbuff[rxbuff_pos];
+ if(__is_defined(USE_P2_AREA))
+ rx_pkt[rxin].rxbuff = (void *)(((uintptr_t)rx_pkt[rxin].rxbuff) | MEM_AREA_P2_BASE);
- /* Receive buffer: temporary space to copy out received data */
+ rx_pkt[rxin].pkt_size = pkt_size;
+ rx_pkt[rxin].offt = offt;
- if(__is_defined(USE_P2_AREA))
- rx_pkt[rxin].rxbuff = rxbuff + 32 + (rxbuff_pos | MEM_AREA_P2_BASE) + (ring_offset & 31);
- else
- rx_pkt[rxin].rxbuff = rxbuff + 32 + rxbuff_pos + (ring_offset & 31);
+ rxbuff_pos += aligned_size;
+ if(rxbuff_pos >= RXBSZ)
+ rxbuff_pos = 0;
- rxbuff_pos = (rxbuff_pos + pkt_size + 63) & (RXBSZ - 32);
+ return bba_copy_packet(rx_pkt[rxin].rxbuff,
+ rtl_mem + (ring_offset & ~0x1f), aligned_size);
+}
+
+static int bba_link_is_stable(void *d) {
+ return *(int *)d;
+}
- rx_pkt[rxin].pkt_size = pkt_size;
- return bba_copy_packet(rx_pkt[rxin].rxbuff, ring_offset, pkt_size);
+static int bba_can_tx(void *d) {
+ (void)d;
+
+ if(!(g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) & RT_TX_HOST_OWNS)) {
+ if(g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) & RT_TX_ABORTED)
+ g2_write_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx),
+ g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) | 1);
+ return 0;
}
- else
- return 1;
+
+ return 1;
}
/* Transmit a single packet */
static int bba_rtx(const uint8_t *pkt, int len, int wait)
{
- if(!link_stable) {
- if(wait == BBA_TX_WAIT) {
- while(!link_stable)
- ;
- }
- else
- return BBA_TX_AGAIN;
+ if(wait == BBA_TX_WAIT) {
+ assert(!irq_inside_int());
+
+ if(!link_stable)
+ thd_poll(bba_link_is_stable, &link_stable, 0);
+ } else if(!link_stable) {
+ return BBA_TX_AGAIN;
}
/* Wait till it's clear to transmit */
if(wait == BBA_TX_WAIT) {
- while(!(g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) & RT_TX_HOST_OWNS)) {
- if(g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) & RT_TX_ABORTED)
- g2_write_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx),
- g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) | 1);
- }
+ thd_poll(bba_can_tx, NULL, 0);
}
- else {
- if(!(g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) & RT_TX_HOST_OWNS)) {
- return BBA_TX_AGAIN;
- }
+ else if(!(g2_read_32(NIC(RT_TXSTATUS0 + 4 * rtl.cur_tx)) & RT_TX_HOST_OWNS)) {
+ return BBA_TX_AGAIN;
}
/* Copy the packet out to RTL memory */
@@ -637,18 +603,8 @@ static int bba_rtx(const uint8_t *pkt, int len, int wait)
//g2_write_block_8(pkt, txdesc[rtl.cur_tx], len);
- /* Check alignment of the packet, if its 32-bit aligned, use
- g2_write_block_32, if its 16-bit aligned, use g2_write_block_16,
- otherwise, use g2_write_block_8. */
- if(!((uint32_t)pkt & 0x03)) {
- g2_write_block_32((uint32_t *) pkt, txdesc[rtl.cur_tx], (len + 3) >> 2);
- }
- else if(!((uint32_t)pkt & 0x01)) {
- g2_write_block_16((uint16_t *) pkt, txdesc[rtl.cur_tx], (len + 1) >> 1);
- }
- else {
- g2_write_block_8(pkt, txdesc[rtl.cur_tx], len);
- }
+ assert(__is_aligned((uintptr_t)pkt, 32));
+ g2_write_block_32((uint32_t *) pkt, txdesc[rtl.cur_tx], (len + 3) >> 2);
/* All packets must be at least 60 bytes, pad them with null bytes if
they are not already of an appropriate size. */
@@ -672,14 +628,10 @@ int bba_tx(const uint8_t *pkt, int len, int wait) {
if(!__is_defined(TX_SEMA))
return bba_rtx(pkt, len, wait);
- if(irq_inside_int()) {
- if(sem_trywait(&tx_sema)) {
- //printf("bba_tx called from an irq while a thread was running it !\n");
- return BBA_TX_OK; /* sorry guys ... */
- }
+ if(sem_wait_irqsafe(&tx_sema)) {
+ //printf("bba_tx called from an irq while a thread was running it !\n");
+ return BBA_TX_OK; /* sorry guys ... */
}
- else
- sem_wait(&tx_sema);
res = bba_rtx(pkt, len, wait);
sem_signal(&tx_sema);
@@ -687,43 +639,18 @@ int bba_tx(const uint8_t *pkt, int len, int wait) {
return res;
}
-void bba_lock(void) {
- //sem_wait(&bba_rx_sema2);
- //asic_evt_disable(ASIC_EVT_EXP_PCI, BBA_ASIC_IRQ);
-}
+static void bba_rx_process(void) {
+ /* Call the callback to process it */
+ eth_rx_callback(rx_pkt[rxout].rxbuff + rx_pkt[rxout].offt, rx_pkt[rxout].pkt_size);
-void bba_unlock(void) {
- //asic_evt_enable(ASIC_EVT_EXP_PCI, BBA_ASIC_IRQ);
- //sem_signal(&bba_rx_sema2);
+ rxout = (rxout + 1) % MAX_PKTS;
}
-static void *bba_rx_threadfunc(void *dummy) {
+static void bba_rx_worker(void *dummy) {
(void)dummy;
- while(!bba_rx_exit_thread) {
- //sem_wait_timed(&bba_rx_sema, 500);
- sem_wait(&bba_rx_sema);
-
- if(bba_rx_exit_thread)
- break;
-
- bba_lock();
-
- if(rxout != rxin) {
-
- /* Call the callback to process it */
- eth_rx_callback(rx_pkt[rxout].rxbuff, rx_pkt[rxout].pkt_size);
-
- rxout = (rxout + 1) % MAX_PKTS;
- }
-
- bba_unlock();
- }
-
- bba_rx_exit_thread = 0;
-
- printf("bba_rx_thread exiting ...\n");
- return NULL;
+ while(rxout != rxin)
+ bba_rx_process();
}
static void bba_rx(void) {
@@ -773,7 +700,7 @@ static void bba_link_change(void) {
dbglog(DBG_INFO, "bba: link stable\n");
// The link is back.
- link_stable = 1;
+ link_stable = true;
}
else {
dbglog(DBG_INFO, "bba: link lost\n");
@@ -785,7 +712,7 @@ static void bba_link_change(void) {
RT_MII_AN_START);
// The link is gone.
- link_stable = 0;
+ link_stable = false;
}
}
@@ -902,9 +829,12 @@ static int bba_if_shutdown(netif_t *self) {
return 0;
}
-static int bba_if_start(netif_t *self) {
- int i;
+static const kthread_attr_t bba_rx_worker_attr = {
+ .label = "bba-rx-worker",
+ .prio = 1,
+};
+static int bba_if_start(netif_t *self) {
(void)self;
if(!(bba_if.flags & NETIF_INITIALIZED))
@@ -914,25 +844,15 @@ static int bba_if_start(netif_t *self) {
return 0;
// Start the BBA RX thread.
- assert(bba_rx_thread == NULL);
- sem_init(&bba_rx_sema, 0);
- sem_init(&bba_rx_sema2, 1);
- bba_rx_thread = thd_create(0, bba_rx_threadfunc, 0);
- bba_rx_thread->prio = 1;
- thd_set_label(bba_rx_thread, "BBA-rx-thd");
+ assert(rx_worker == NULL);
+ rx_worker = thd_worker_create_ex(&bba_rx_worker_attr, bba_rx_worker, NULL);
/* We need something like this to get DHCP to work (since it doesn't
know anything about an activated and yet not-yet-receiving network
adapter =) */
- /* Spin until the link is stabilized */
- i = 1000;
- while(!link_stable && i > 0) {
- i--;
- thd_sleep(10);
- }
-
- if(!link_stable) {
+ /* Wait until the link is stabilized */
+ if(!thd_poll(bba_link_is_stable, &link_stable, 10000)) {
dbglog(DBG_ERROR, "bba: timed out waiting for link to stabilize\n");
return -1;
}
@@ -948,15 +868,10 @@ static int bba_if_stop(netif_t *self) {
return 0;
/* VP : Shutdown rx thread */
- assert(bba_rx_thread != NULL);
- bba_rx_exit_thread = 1;
- sem_signal(&bba_rx_sema);
- sem_signal(&bba_rx_sema2);
- thd_join(bba_rx_thread, NULL);
- sem_destroy(&bba_rx_sema);
- sem_destroy(&bba_rx_sema2);
+ assert(rx_worker != NULL);
+ thd_worker_destroy(rx_worker);
...<truncated>...
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-11 18:48:30
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 3a4642672e318a43f872c23b014364668faa2350 (commit)
via f0bbe37af79161d919ce9c6da603cb8f6ef7d90c (commit)
from b66fa29c0e80723235fb2ec4679d4742d60ce501 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 3a4642672e318a43f872c23b014364668faa2350
Author: Andress Barajas <and...@gm...>
Date: Wed Apr 8 08:22:28 2026 -0700
Remove legacy char-by-char read/write hooks
Drop the dbgio_read/dbgio_write interface from dbgio_handler_t and
remove the corresponding exports and backend stubs. Simplify PTY
console reads to use the buffer-based dbgio path consistently.
commit f0bbe37af79161d919ce9c6da603cb8f6ef7d90c
Author: Andress Barajas <and...@gm...>
Date: Tue Apr 7 19:08:50 2026 -0700
Route dcload console stdin through dbgio read_buffer
Register a buffered read callback for fs_dcload and use it for
unattached console PTY reads when fs_dcload is the active dbgio
backend.
This keeps the existing scalar PTY serial path for other dbgio
handlers while allowing stdio input like scanf() to work over
dcload.
-----------------------------------------------------------------------
Summary of changes:
include/kos/dbgio.h | 58 ++---------
kernel/arch/dreamcast/fs/fs_dcload.c | 6 +-
kernel/arch/dreamcast/fs/fs_dclsocket.c | 2 -
kernel/arch/dreamcast/hardware/scif.c | 2 -
kernel/arch/dreamcast/kernel/ser_console.c | 144 --------------------------
kernel/arch/dreamcast/util/fb_console.c | 7 --
kernel/arch/dreamcast/util/fb_console_naomi.c | 7 --
kernel/debug/dbgio.c | 33 +-----
kernel/exports.txt | 2 -
kernel/fs/fs_pty.c | 56 +---------
10 files changed, 24 insertions(+), 293 deletions(-)
delete mode 100644 kernel/arch/dreamcast/kernel/ser_console.c
diff --git a/include/kos/dbgio.h b/include/kos/dbgio.h
index d0acb79b..fdcb8d02 100644
--- a/include/kos/dbgio.h
+++ b/include/kos/dbgio.h
@@ -68,21 +68,6 @@ typedef struct dbgio_handler {
*/
int (*set_irq_usage)(int mode);
- /** \brief Read one character from the console.
- \retval 0 On success
- \retval -1 On failure (set errno as appropriate)
- */
- int (*read)(void);
-
- /** \brief Write one character to the console.
- \param c The character to write
- \retval 1 On success
- \retval -1 On error (set errno as appropriate)
- \note Interfaces may require a call to flush() before the
- output is actually flushed to the console.
- */
- int (*write)(int c);
-
/** \brief Flush any queued output.
\retval 0 On success
\retval -1 On error (set errno as appropriate)
@@ -148,7 +133,7 @@ int dbgio_remove_handler(dbgio_handler_t *handler);
\param name The dbgio interface to select
\retval 0 On success
-
+
\retval -1 On error
\par Error Conditions:
@@ -185,9 +170,9 @@ const char *dbgio_dev_get(void);
user programs.
\retval 0 On success
-
+
\retval -1 On error
-
+
\par Error Conditions:
\em ENODEV - No devices could be detected/initialized
*/
@@ -200,7 +185,7 @@ int dbgio_init(void);
mode at all.
\param mode The mode to use
-
+
\retval 0 On success
\retval -1 On error (errno should be set as appropriate)
*/
@@ -220,27 +205,6 @@ int dbgio_set_irq_usage(int mode);
*/
#define DBGIO_MODE_IRQ 1
-/** \brief Read one character from the console.
- \ingroup logging
-
- \retval 0 On success
- \retval -1 On error (errno should be set as appropriate)
-*/
-int dbgio_read(void);
-
-/** \brief Write one character to the console.
- \ingroup logging
-
- \note Interfaces may require a call to flush() before the
- output is actually flushed to the console.
-
- \param c The character to write
-
- \retval 1 On success (number of characters written)
- \retval -1 On error (errno should be set as appropriate)
-*/
-int dbgio_write(int c);
-
/** \brief Flush any queued output.
\ingroup logging
@@ -254,7 +218,7 @@ int dbgio_flush(void);
\param data The buffer to write
\param len The length of the buffer
-
+
\return Number of characters written on success, or -1 on
failure (errno should be set as appropriate)
*/
@@ -265,7 +229,7 @@ int dbgio_write_buffer(const uint8_t *data, int len);
\param data The buffer to read into
\param len The length of the buffer
-
+
\return Number of characters read on success, or -1 on
failure (errno should be set as appropriate)
*/
@@ -277,7 +241,7 @@ int dbgio_read_buffer(uint8_t *data, int len);
\param data The buffer to write
\param len The length of the buffer
-
+
\return Number of characters written on success, or -1 on
failure (errno should be set as appropriate)
*/
@@ -287,7 +251,7 @@ int dbgio_write_buffer_xlat(const uint8_t *data, int len);
\ingroup logging
\param str The string to write
-
+
\return Number of characters written on success, or -1 on
failure (errno should be set as appropriate)
*/
@@ -298,17 +262,17 @@ int dbgio_write_str(const char *str);
*/
void dbgio_disable(void);
-/** \brief Enable debug I/O globally.
+/** \brief Enable debug I/O globally.
\ingroup logging
*/
void dbgio_enable(void);
/** \brief Built-in debug I/O printf function.
\ingroup logging
-
+
\param fmt A printf() style format string
\param ... Format arguments
-
+
\return The number of bytes written, or <0 on error (errno
should be set as appropriate)
*/
diff --git a/kernel/arch/dreamcast/fs/fs_dcload.c b/kernel/arch/dreamcast/fs/fs_dcload.c
index 70353de6..a02c383e 100644
--- a/kernel/arch/dreamcast/fs/fs_dcload.c
+++ b/kernel/arch/dreamcast/fs/fs_dcload.c
@@ -51,8 +51,8 @@ int dcload_write_buffer(const uint8_t *data, int len, int xlat) {
return len;
}
-int dcload_read_cons(void) {
- return -1;
+int dcload_read_buffer(uint8_t *data, int len) {
+ return dcload_read(STDIN_FILENO, data, len);
}
static void *fs_dcload_open(vfs_handler_t *vfs, const char *fn, int mode) {
@@ -439,7 +439,7 @@ void fs_dcload_init_console(void) {
dbgio_dcload.name = dbgio_dcload_name;
dbgio_dcload.detected = syscall_dcload_detected;
dbgio_dcload.write_buffer = dcload_write_buffer;
- // dbgio_dcload.read = dcload_read_cons;
+ dbgio_dcload.read_buffer = dcload_read_buffer;
/* We actually need to detect here to make sure we're on
dcload-serial, or scif_init must not proceed. */
diff --git a/kernel/arch/dreamcast/fs/fs_dclsocket.c b/kernel/arch/dreamcast/fs/fs_dclsocket.c
index 2ef5246e..6f93fda6 100644
--- a/kernel/arch/dreamcast/fs/fs_dclsocket.c
+++ b/kernel/arch/dreamcast/fs/fs_dclsocket.c
@@ -677,8 +677,6 @@ void fs_dclsocket_init_console(void) {
}
dbgio_dcls.set_irq_usage = dbgio_null.set_irq_usage;
- dbgio_dcls.read = dbgio_null.read;
- dbgio_dcls.write = dbgio_null.write;
dbgio_dcls.flush = dbgio_null.flush;
dbgio_dcls.read_buffer = dbgio_null.read_buffer;
diff --git a/kernel/arch/dreamcast/hardware/scif.c b/kernel/arch/dreamcast/hardware/scif.c
index 39667873..19bdc366 100644
--- a/kernel/arch/dreamcast/hardware/scif.c
+++ b/kernel/arch/dreamcast/hardware/scif.c
@@ -412,8 +412,6 @@ dbgio_handler_t dbgio_scif = {
.init = scif_init_fake,
.shutdown = scif_shutdown,
.set_irq_usage = scif_set_irq_usage,
- .read = scif_read,
- .write = scif_write,
.flush = scif_flush,
.write_buffer = scif_write_buffer,
.read_buffer = scif_read_buffer
diff --git a/kernel/arch/dreamcast/kernel/ser_console.c b/kernel/arch/dreamcast/kernel/ser_console.c
deleted file mode 100644
index 2ec9bcc9..00000000
--- a/kernel/arch/dreamcast/kernel/ser_console.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* KallistiOS ##version##
-
- ser_console.c
- (c)2001 Megan Potter
-
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <arch/dbgio.h>
-#include <kos/irq.h>
-#include <kos/thread.h>
-#include <kos/sem.h>
-
-/* This is a little thing I ported over from KOS-MMU which turned out
- to be extremely useful during debugging. It basically sets up a
- simple serial console on the DC serial port which you can use
- to view process listings, etc. It has to be manually enabled,
- though, and it will interfere with dc-load-serial, so don't try
- to use both at once. */
-
-static char buffer[256];
-static semaphore_t *chr_ready;
-
-static vuint16 * const SCSCR2 = (vuint16*)0xffe80008;
-
-int thd_pslist();
-
-static void ser_irq(irq_t source, irq_context_t *context) {
- *SCSCR2 &= ~(1 << 6);
- *SCSCR2 |= (1 << 6);
-
- sem_signal(chr_ready);
-}
-
-static int dbgio_wait_ready(void *d) {
- int ret = dbgio_read();
-
- return ret == -1 ? 0 : (ret + 1);
-}
-
-static char *read_line(void) {
- int q = 0, ch;
-
- while(1) {
- ch = thd_poll((thd_cb_t)dbgio_wait_ready, NULL, 0) - 1;
-
- if(ch == '\r') {
- buffer[q] = 0;
- dbgio_write_str("\n");
- return buffer;
- }
-
- if(ch == '\x08') {
- q--;
- dbgio_write_str("\x08 \x08");
- continue;
- }
-
- buffer[q++] = ch;
- dbgio_write(ch);
- }
-}
-
-static char curdir[256];
-
-static void interact(void) {
- char tmp[16];
- char *buf;
- int cnt = 0;
-
- curdir[0] = '/';
- curdir[1] = 0;
-
- while(1) {
- sprintf(tmp, "%d", cnt);
- dbgio_write_str(tmp);
- dbgio_write(' ');
- dbgio_write_str(curdir);
- dbgio_write('>');
- /*write_str("%d %s> ", cnt, curdir); */
- buf = read_line();
-
- if(buf[0] == 0) {
- cnt++;
- continue;
- }
-
- if(!strcmp(buf, "quit") || !strcmp(buf, "exit")) {
- break;
- }
- else if(!strcmp(buf, "die")) {
- arch_exit();
- }
- else if(!strcmp(buf, "ps")) {
- thd_pslist();
- }
- else if(!strcmp(buf, "reboot")) {
- arch_reboot();
- }
- else if(!strcmp(buf, "menu")) {
- (*(void(**)())0x8c0000e0)(1);
- }
- else {
- dbgio_write_str("commands: die quit/exit reboot menu ps\n");
- }
-
- cnt++;
- }
-}
-
-static void real_start(void *param) {
- dbgio_printk_func old;
-
- /* Set debug output to the serial console again */
- old = dbgio_set_printk(dbgio_write_str);
-
- /* Make a semaphore */
- /* chr_ready = sem_create(0); */
-
- /* Hook the serial IRQ */
- /* irq_set_handler(EXC_SCIF_RXI, ser_irq);
- *SCSCR2 |= 1 << 6;
- irq_set_priority(IRQ_SRC_SCIF, 14); */
-
- /* Do the shell */
- interact();
- dbgio_write_str("shell exiting\n");
-
- /* Unhook serial IRQ */
- /* irq_set_priority(IRQ_SRC_SCIF, IRQ_PRIO_MASKED);
- *SCSCR2 &= ~(1 << 6);
- irq_set_handler(EXC_SCIF_RXI, NULL); */
-
- /* Destroy the semaphore */
- /* sem_destroy(chr_ready); */
-
- dbgio_set_printk(old);
-}
-
-void ser_console_init(void) {
- thd_create(real_start, NULL);
-}
-
diff --git a/kernel/arch/dreamcast/util/fb_console.c b/kernel/arch/dreamcast/util/fb_console.c
index e1b814e4..e7a7fcf4 100644
--- a/kernel/arch/dreamcast/util/fb_console.c
+++ b/kernel/arch/dreamcast/util/fb_console.c
@@ -50,11 +50,6 @@ static int fb_set_irq_usage(int mode) {
return 0;
}
-static int fb_read(void) {
- errno = EAGAIN;
- return -1;
-}
-
static int fb_write(int c) {
uint16_t *t = fb;
@@ -114,8 +109,6 @@ dbgio_handler_t dbgio_fb = {
.init = fb_init,
.shutdown = fb_shutdown,
.set_irq_usage = fb_set_irq_usage,
- .read = fb_read,
- .write = fb_write,
.flush = fb_flush,
.write_buffer = fb_write_buffer,
.read_buffer = fb_read_buffer
diff --git a/kernel/arch/dreamcast/util/fb_console_naomi.c b/kernel/arch/dreamcast/util/fb_console_naomi.c
index e1361340..ff45d97d 100644
--- a/kernel/arch/dreamcast/util/fb_console_naomi.c
+++ b/kernel/arch/dreamcast/util/fb_console_naomi.c
@@ -52,11 +52,6 @@ static int fb_set_irq_usage(int mode) {
return 0;
}
-static int fb_read(void) {
- errno = EAGAIN;
- return -1;
-}
-
static int fb_write(int c) {
uint16_t *t = fb;
@@ -116,8 +111,6 @@ dbgio_handler_t dbgio_fb = {
.init = fb_init,
.shutdown = fb_shutdown,
.set_irq_usage = fb_set_irq_usage,
- .read = fb_read,
- .write = fb_write,
.flush = fb_flush,
.write_buffer = fb_write_buffer,
.read_buffer = fb_read_buffer
diff --git a/kernel/debug/dbgio.c b/kernel/debug/dbgio.c
index 02917ee5..148ea301 100644
--- a/kernel/debug/dbgio.c
+++ b/kernel/debug/dbgio.c
@@ -123,24 +123,6 @@ int dbgio_set_irq_usage(int mode) {
return -1;
}
-int dbgio_read(void) {
- if(dbgio_enabled) {
- assert(dbgio);
- return dbgio->read();
- }
-
- return -1;
-}
-
-int dbgio_write(int c) {
- if(dbgio_enabled) {
- assert(dbgio);
- return dbgio->write(c);
- }
-
- return -1;
-}
-
int dbgio_flush(void) {
if(dbgio_enabled) {
assert(dbgio);
@@ -218,27 +200,24 @@ int dbgio_printf(const char *fmt, ...) {
static int null_detected(void) {
return 1;
}
+
static int null_init(void) {
return 0;
}
+
static int null_shutdown(void) {
return 0;
}
+
static int null_set_irq_usage(int mode) {
(void)mode;
return 0;
}
-static int null_read(void) {
- errno = EAGAIN;
- return -1;
-}
-static int null_write(int c) {
- (void)c;
- return 1;
-}
+
static int null_flush(void) {
return 0;
}
+
static int null_write_buffer(const uint8_t *data, int len, int xlat) {
(void)data;
(void)len;
@@ -258,8 +237,6 @@ dbgio_handler_t dbgio_null = {
.init = null_init,
.shutdown = null_shutdown,
.set_irq_usage = null_set_irq_usage,
- .read = null_read,
- .write = null_write,
.flush = null_flush,
.write_buffer = null_write_buffer,
.read_buffer = null_read_buffer
diff --git a/kernel/exports.txt b/kernel/exports.txt
index d5247c85..ab496ed6 100644
--- a/kernel/exports.txt
+++ b/kernel/exports.txt
@@ -189,12 +189,10 @@ dbgio_enable
dbgio_disable
dbgio_dev_select
dbgio_dev_get
-dbgio_write
dbgio_flush
dbgio_write_buffer
dbgio_write_buffer_xlat
dbgio_write_str
-dbgio_read
dbgio_read_buffer
dbgio_printf
diff --git a/kernel/fs/fs_pty.c b/kernel/fs/fs_pty.c
index 5e85ae6f..ee439b6d 100644
--- a/kernel/fs/fs_pty.c
+++ b/kernel/fs/fs_pty.c
@@ -450,53 +450,6 @@ static int pty_close(void *h) {
return 0;
}
-/* Read from a pty endpoint, kernel console special case */
-static ssize_t pty_read_serial(pipefd_t *fdobj, ptyhalf_t *ph, void *buf, size_t bytes) {
- int c, r = 0;
-
- (void)ph;
-
- while(bytes > 0) {
- again:
- /* Try to read a char */
- c = dbgio_read();
-
- /* Get anything? */
...<truncated>...
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-11 18:39:12
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via b66fa29c0e80723235fb2ec4679d4742d60ce501 (commit)
via ede5210298bebf78c28d2daf45fd247bb826001f (commit)
via 115664135908e7f771384f248d195ff65a935d15 (commit)
from 471ba7f806747f9f2656784ecf321395d4b72799 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b66fa29c0e80723235fb2ec4679d4742d60ce501
Author: Paul Cercueil <pa...@cr...>
Date: Fri Jan 9 15:21:25 2026 +0100
thd: Enable thread ageing support
Until now, a low-priority thread could be completely starved when the
scheduler always had higher-priority running threads to preempt.
Address this issue by implementing thread ageing. This mechanism
increases a thread priority at every given time interval (harcoded to
8 ticks here) since the last preemption, giving it a chance to
eventually run.
Note that this means we're now parsing the entire run queue to find the
thread that will eventually be preempted. This should be fine,
KallistiOS is not Linux and the number of running threads is generally
minimal.
Fixes #1295.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit ede5210298bebf78c28d2daf45fd247bb826001f
Author: Paul Cercueil <pa...@cr...>
Date: Wed Jan 14 12:55:55 2026 +0100
thd: Reduce cputime accuracy to milliseconds
Avoid reading the timer twice in different units when rescheduling, by
reading the thread's cputime in milliseconds.
This obviously drops the time precision, but it is questionnable whether
or not this precision was needed in the first place, especially since
the scheduler works in milliseconds.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 115664135908e7f771384f248d195ff65a935d15
Author: Paul Cercueil <pa...@cr...>
Date: Tue Jan 13 21:14:02 2026 +0100
Add new <kos/intmath.h> header
This header can be used for all the integer math functions that are
arch-independent.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
include/kos/intmath.h | 40 ++++++++++++++++++++++++++
include/kos/thread.h | 5 +++-
kernel/thread/thread.c | 78 +++++++++++++++++++++++++++++++++-----------------
3 files changed, 95 insertions(+), 28 deletions(-)
create mode 100644 include/kos/intmath.h
diff --git a/include/kos/intmath.h b/include/kos/intmath.h
new file mode 100644
index 00000000..f6746a4a
--- /dev/null
+++ b/include/kos/intmath.h
@@ -0,0 +1,40 @@
+/* KallistiOS ##version##
+
+ kos/intmath.h
+ Copyright (C) 2026 Paul Cercueil
+
+ Integer math helper functions
+*/
+
+/** \file kos/intmath.h
+ \brief Functions to help with integer math.
+ \ingroup intmath
+
+ \author Paul Cercueil
+*/
+
+#ifndef __KOS_INTMATH_H
+#define __KOS_INTMATH_H
+
+#include <kos/cdefs.h>
+__BEGIN_DECLS
+
+#include <stdbool.h>
+
+static inline bool is_power_of_two(unsigned int val)
+{
+ return (val & (val - 1)) == 0;
+}
+
+static inline unsigned int log2_rdown(unsigned int val)
+{
+ return 31 - __builtin_clz(val);
+}
+
+static inline unsigned int log2_rup(unsigned int val)
+{
+ return log2_rdown(val) + !is_power_of_two(val);
+}
+
+__END_DECLS
+#endif /* __KOS_INTMATH_H */
diff --git a/include/kos/thread.h b/include/kos/thread.h
index 67400a77..27e4dabc 100644
--- a/include/kos/thread.h
+++ b/include/kos/thread.h
@@ -89,6 +89,9 @@ __BEGIN_DECLS
This macro defines the maximum value for a thread's priority. Note that the
larger this number, the lower the priority of the thread.
+
+ Priority values above this threshold are still supported, with the caveat
+ that the scheduler might not give any CPU time to the thread.
*/
#define PRIO_MAX 4096
@@ -216,7 +219,7 @@ typedef struct __attribute__((aligned(32))) kthread {
*/
uint64_t wait_timeout;
- /** \brief Per-Thread CPU Time. */
+ /** \brief Per-Thread CPU Time, in milliseconds. */
struct {
uint64_t scheduled; /**< \brief time when the thread became active */
uint64_t total; /**< \brief total running CPU time for thread */
diff --git a/kernel/thread/thread.c b/kernel/thread/thread.c
index 0dc90e09..f622651f 100644
--- a/kernel/thread/thread.c
+++ b/kernel/thread/thread.c
@@ -9,6 +9,7 @@
#include <assert.h>
#include <string.h>
+#include <limits.h>
#include <malloc.h>
#include <stdint.h>
#include <stdio.h>
@@ -20,6 +21,7 @@
#include <kos/thread.h>
#include <kos/dbgio.h>
#include <kos/dbglog.h>
+#include <kos/intmath.h>
#include <kos/irq.h>
#include <kos/sem.h>
#include <kos/rwsem.h>
@@ -52,7 +54,15 @@ static alignas(THD_STACK_ALIGNMENT) uint8_t thd_idle_stack[512];
/* Thread scheduler data */
/* Scheduler timer interrupt frequency (Hertz) */
-static unsigned int thd_sched_ms = 1000 / THD_SCHED_HZ;
+static unsigned int thd_sched_ms;
+
+/* log2() of the time interval in milliseconds since a thread's last preemption,
+ * after which the thread's priority is doubled */
+static unsigned int thd_ageing_ms_log2;
+
+/* The number of ticks since its last preemption after which a thread's priority
+ * will be doubled. */
+#define THD_AGEING_THRESHOLD 8
/* Thread list. This includes all threads except dead ones. */
static struct ktlist thd_list;
@@ -121,7 +131,7 @@ int thd_each(int (*cb)(kthread_t *thd, void *user_data), void *data) {
}
int thd_pslist(int (*pf)(const char *fmt, ...)) {
- uint64_t cpu_time, ns_time, cpu_total = 0;
+ uint64_t cpu_time, ms_time, cpu_total = 0;
kthread_t *cur;
pf("All threads (may not be deterministic):\n");
@@ -129,7 +139,7 @@ int thd_pslist(int (*pf)(const char *fmt, ...)) {
irq_disable_scoped();
thd_get_cpu_time(thd_get_current());
- ns_time = timer_ns_gettime64();
+ ms_time = timer_ms_gettime64();
LIST_FOREACH(cur, &thd_list, t_list) {
pf("%08lx ", CONTEXT_PC(cur->context));
@@ -147,15 +157,15 @@ int thd_pslist(int (*pf)(const char *fmt, ...)) {
cpu_total += cpu_time;
pf("%12llu (%6.3lf%%) ",
- cpu_time, (double)cpu_time / (double)ns_time * 100.0);
+ cpu_time, (double)cpu_time / (double)ms_time * 100.0);
pf("%-10s ", thd_state_to_str(cur));
pf("%-10s\n", cur->label);
}
pf("-\t -\t -\t -\t -");
- pf("%12llu (%6.3lf%%) - [system]\n", (ns_time - cpu_total),
- (double)(ns_time - cpu_total) / (double)ns_time * 100.0);
+ pf("%12llu (%6.3lf%%) - [system]\n", (ms_time - cpu_total),
+ (double)(ms_time - cpu_total) / (double)ms_time * 100.0);
pf("--end of list--\n");
@@ -603,20 +613,18 @@ tid_t thd_get_id(const kthread_t *thd) {
/*****************************************************************************/
/* Scheduling routines */
-static void thd_update_cpu_time(kthread_t *thd) {
- const uint64_t ns = timer_ns_gettime64();
-
+static void thd_update_cpu_time(kthread_t *thd, uint64_t now) {
thd_current->cpu_time.total +=
- ns - thd_current->cpu_time.scheduled;
+ now - thd_current->cpu_time.scheduled;
- thd->cpu_time.scheduled = ns;
+ thd->cpu_time.scheduled = now;
}
/* Helper function that sets a thread being scheduled */
-static inline void thd_schedule_inner(kthread_t *thd) {
+static inline void thd_schedule_inner(kthread_t *thd, uint64_t now) {
thd_remove_from_runnable(thd);
- thd_update_cpu_time(thd);
+ thd_update_cpu_time(thd, now);
thd_current = thd;
_impure_ptr = &thd->thd_reent;
@@ -634,6 +642,15 @@ static inline void thd_schedule_inner(kthread_t *thd) {
irq_set_context(&thd_current->context);
}
+static inline prio_t thd_calc_prio(const kthread_t *thd, uint32_t now) {
+ prio_t prio = thd->prio;
+
+ if(__predict_true(prio < PRIO_MAX))
+ prio >>= (now - (uint32_t)thd->cpu_time.scheduled) >> thd_ageing_ms_log2;
+
+ return prio;
+}
+
/* Thread scheduler; this function will find a new thread to run when a
context switch is requested. No work is done in here except to change
out the thd_current variable contents. Assumed that we are in an
@@ -651,7 +668,8 @@ static inline void thd_schedule_inner(kthread_t *thd) {
don't want a full context switch inside the same priority group.
*/
void thd_schedule(bool front_of_line) {
- kthread_t *thd;
+ kthread_t *thd, *next_thd = NULL;
+ prio_t prio, max_prio = INT_MAX;
uint64_t now;
int ret;
@@ -696,8 +714,14 @@ void thd_schedule(bool front_of_line) {
}
/* Is it runnable? If not, keep going */
- if(thd->state == STATE_READY)
- break;
+ if(thd->state != STATE_READY)
+ continue;
+
+ prio = thd_calc_prio(thd, now);
+ if(prio < max_prio) {
+ next_thd = thd;
+ max_prio = prio;
+ }
}
/* If we didn't already re-enqueue the thread and we are supposed to do so,
@@ -708,22 +732,22 @@ void thd_schedule(bool front_of_line) {
/* Make sure we have a thread, just in case we couldn't find anything
above. */
- if(thd == NULL || thd == thd_idle_thd)
- thd = thd_current;
+ if(next_thd == NULL || next_thd == thd_idle_thd)
+ next_thd = thd_current;
}
else if(__predict_false(thd_current->state == STATE_POLLING)) {
thd_add_to_runnable(thd_current, front_of_line);
}
/* Didn't find one? Big problem here... */
- if(thd == NULL) {
+ if(next_thd == NULL) {
thd_pslist(printf);
arch_panic("couldn't find a runnable thread");
}
/* We should now have a runnable thread, so remove it from the
run queue and switch to it. */
- thd_schedule_inner(thd);
+ thd_schedule_inner(next_thd, now);
}
/* Temporary priority boosting function: call this from within an interrupt
@@ -752,7 +776,7 @@ void thd_schedule_next(kthread_t *thd) {
thd_add_to_runnable(thd_current, 0);
}
- thd_schedule_inner(thd);
+ thd_schedule_inner(thd, timer_ms_gettime64());
}
/* See kos/thread.h for description */
@@ -988,10 +1012,6 @@ struct _reent *thd_get_reent(kthread_t *thd) {
}
uint64_t thd_get_cpu_time(kthread_t *thd) {
- /* Check whether we should force an update immediately for accuracy. */
- if(thd == thd_get_current())
- thd_update_cpu_time(thd);
-
return thd->cpu_time.total;
}
@@ -1029,6 +1049,7 @@ int thd_set_hz(unsigned int hertz) {
return -1;
thd_sched_ms = 1000 / hertz;
+ thd_ageing_ms_log2 = log2_rup(thd_sched_ms * THD_AGEING_THRESHOLD);
return 0;
}
@@ -1055,7 +1076,7 @@ int thd_init(void) {
const kthread_attr_t idle_attr = {
.stack_size = sizeof(thd_idle_stack),
.stack_ptr = thd_idle_stack,
- .prio = PRIO_MAX,
+ .prio = PRIO_MAX + 1, /* disable ageing */
.label = "[idle]",
.disable_tls = true
};
@@ -1087,6 +1108,9 @@ int thd_init(void) {
/* Reinitialize thread counter */
thd_count = 0;
+ /* Set default HZ value */
+ thd_set_hz(THD_SCHED_HZ);
+
/* Setup a kernel task for the currently running "main" thread */
kern = thd_create_ex(&kern_attr, NULL, NULL);
if(!kern) {
@@ -1096,7 +1120,7 @@ int thd_init(void) {
/* Main thread -- the kern thread */
thd_current = kern;
- thd_schedule_inner(kern);
+ thd_schedule_inner(kern, timer_ms_gettime64());
/* Initialize tls */
arch_tls_init();
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-07 20:56:31
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 471ba7f806747f9f2656784ecf321395d4b72799 (commit)
from c792dbae1f45e393856b9751266765e90ec9a031 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 471ba7f806747f9f2656784ecf321395d4b72799
Author: Yev <ev...@gm...>
Date: Tue Apr 7 21:37:14 2026 +0200
Remove 'lstat' definition duplicate
-----------------------------------------------------------------------
Summary of changes:
kernel/libc/koslib/Makefile | 2 +-
kernel/libc/koslib/lstat.c | 11 -----------
2 files changed, 1 insertion(+), 12 deletions(-)
delete mode 100644 kernel/libc/koslib/lstat.c
diff --git a/kernel/libc/koslib/Makefile b/kernel/libc/koslib/Makefile
index 6ead1353..4247dace 100644
--- a/kernel/libc/koslib/Makefile
+++ b/kernel/libc/koslib/Makefile
@@ -14,7 +14,7 @@ OBJS = abort.o memset2.o memset4.o memcpy2.o memcpy4.o \
creat.o sleep.o rmdir.o rename.o inet_pton.o inet_ntop.o \
inet_ntoa.o inet_aton.o poll.o select.o symlink.o readlink.o \
gethostbyname.o getaddrinfo.o dirfd.o nanosleep.o basename.o dirname.o \
- sched_yield.o dup.o dup2.o pipe.o uname.o pathconf.o stat.o lstat.o \
+ sched_yield.o dup.o dup2.o pipe.o uname.o pathconf.o stat.o \
link.o unlink.o
include $(KOS_BASE)/Makefile.prefab
diff --git a/kernel/libc/koslib/lstat.c b/kernel/libc/koslib/lstat.c
deleted file mode 100644
index 9bd5bf19..00000000
--- a/kernel/libc/koslib/lstat.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/* KallistiOS ##version##
-
- lstat.c
- Copyright (C)2026 Yevhen Lohachov
-*/
-
-#include <kos/fs.h>
-
-int lstat(const char *restrict path, struct stat *restrict buf) {
- return fs_stat(path, buf, AT_SYMLINK_NOFOLLOW);
-}
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-06 17:24:47
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via c792dbae1f45e393856b9751266765e90ec9a031 (commit)
via 35d8e0275c3fadb9a6f78f3b20452a41e29a90fa (commit)
via 607d1a84610906c79c75f2bf08fb887913e0c826 (commit)
from 7192a89610a536ff87453be47788c1ccd280492c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c792dbae1f45e393856b9751266765e90ec9a031
Author: Paul Cercueil <pa...@cr...>
Date: Thu Apr 2 01:36:24 2026 +0200
fs: Start FD values at 3
The file descriptors with values 0, 1 and 2 are reserved respectively
for the standard input, the standard output, and the error output.
Having the filesystem code allocate FD values starting from 0 was pretty
dangerous; case in point, the PTY driver would open /pty/sl00 and get
the file descriptor 0, and doing so, mapping /pty/sl00 to the standard
input, even though the PTY code did not explicitly set that up.
The simpler fix is just to start the FD values at 3. To avoid changing
behaviour, the PTY driver will now also dup2() the opened PTY file to
the stdin FD.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 35d8e0275c3fadb9a6f78f3b20452a41e29a90fa
Author: Paul Cercueil <pa...@cr...>
Date: Thu Apr 2 01:30:30 2026 +0200
fs: Handle case where old FD == new FD in fs_dup2()
Previously, when the same FD was passed as both the new and old FD to
fs_dup2(), the algorithm would close the FD then try to get a reference
to a NULL pointer.
Address this issue by following the POSIX spec, and return the FD
directly, with its reference count incremented.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 607d1a84610906c79c75f2bf08fb887913e0c826
Author: Paul Cercueil <pa...@cr...>
Date: Thu Apr 2 01:28:53 2026 +0200
fs: Remove unneeded include
No dbgio functions are used anywhere in that file.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
kernel/fs/fs.c | 7 +++++--
kernel/fs/fs_pty.c | 3 ++-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c
index 48dd0184..fa1ebeae 100644
--- a/kernel/fs/fs.c
+++ b/kernel/fs/fs.c
@@ -39,7 +39,6 @@ something like this:
#include <kos/thread.h>
#include <kos/mutex.h>
#include <kos/nmmgr.h>
-#include <kos/dbgio.h>
#include <kos/dbglog.h>
/* File handle structure; this is an entirely internal structure so it does
@@ -195,7 +194,7 @@ static int fs_hnd_assign(fs_hnd_t *hnd) {
fs_hnd_ref(hnd);
- for(i = 0; i < FD_SETSIZE; i++) {
+ for(i = 3; i < FD_SETSIZE; i++) {
fs_hnd_t *old = NULL;
if(atomic_compare_exchange_strong(&fd_table[i], &old, hnd))
@@ -310,6 +309,9 @@ file_t fs_dup2(file_t oldfd, file_t newfd) {
return -1;
}
+ if(oldfd == newfd)
+ goto out_get_ref;
+
do {
prev = fd_table[newfd];
if(prev) {
@@ -320,6 +322,7 @@ file_t fs_dup2(file_t oldfd, file_t newfd) {
} while(!atomic_compare_exchange_strong(&fd_table[newfd],
&prev, fd_table[oldfd]));
+out_get_ref:
fs_hnd_ref(fd_table[newfd]);
return newfd;
diff --git a/kernel/fs/fs_pty.c b/kernel/fs/fs_pty.c
index 2fe030c4..5e85ae6f 100644
--- a/kernel/fs/fs_pty.c
+++ b/kernel/fs/fs_pty.c
@@ -180,7 +180,8 @@ int fs_pty_create(char *buffer, int maxbuflen, file_t *master_out, file_t *slave
if(boot) {
/* Get the slave channel setup first, and dup it across
- our stdout and stderr. */
+ our stdin, stdout and stderr. */
+ fs_dup2(*slave_out, STDIN_FILENO);
fs_dup2(*slave_out, STDOUT_FILENO);
fs_dup2(*slave_out, STDERR_FILENO);
}
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-04-04 22:00:22
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 7192a89610a536ff87453be47788c1ccd280492c (commit)
via 8a107af610bc230b92084414f5d07e333cf1af1c (commit)
via 3b64de11d3d615ebf6ba90cdb3662b4645ba3092 (commit)
via e0c66738b95b86f35512e0f1279976ee2846d100 (commit)
via aaf291e9aee8c7f5a63cc212907b050d687cfe20 (commit)
via 16ffa36c750e9762a00f52c2295d412304c0cbf8 (commit)
via f72896553d87ec600ef1cb3e6750615955db2b01 (commit)
via ffe0796655603443cb417d97654e8083b1f5e23f (commit)
via efe2beb697b4f637650fd17147333c894c29e132 (commit)
via 57e8faadcdf919a9b99456e5d4228287a28718b6 (commit)
from d351ea934285f1beb90f7eca1c0bc14e9c96b7eb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 7192a89610a536ff87453be47788c1ccd280492c
Author: Paul Cercueil <pa...@cr...>
Date: Sat Apr 4 23:20:33 2026 +0200
kos-chain: Also copy <sys/lock.h> to arch-independent Newlib dir
Our Newlib patch bypasses the "machine_dir" on ARM, which means that
Newlib will use the arch-independent <sys/lock.h>. When copying our
custom lock.h file, we therefore need to copy it to that location as
well. Note that we still need to copy it to the "machine_dir", as it is
the copy that will eventually be installed into the toolchain.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 8a107af610bc230b92084414f5d07e333cf1af1c
Author: Paul Cercueil <pa...@cr...>
Date: Mon Mar 30 16:07:52 2026 +0200
Change GCCVER < 9 warning to GCCVER < 8
This will permit to compile KallistiOS for the AICA, which cannot be
targetted by GCC 9 or newer.
Besides, KallistiOS compiles fine with the GCC 8.5.0 toolchain.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 3b64de11d3d615ebf6ba90cdb3662b4645ba3092
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 20:41:01 2026 +0100
kos-chain: Build Newlib 4.6.0 for ARM7DI
Newlib must be compiled targetting the ARM7DI and not just a random
ARMv4 CPU. This means that ARM-specific routines must be disabled
(as they wouldn't compile), and the C code must be compiled with the
-mcpu=arm7di flag.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit e0c66738b95b86f35512e0f1279976ee2846d100
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 20:37:50 2026 +0100
kos-chain: Update GCC-8.5.0 patch to support ARM7DI
Until now libgcc was built for a standard ARMv4, meaning that the ARM
CPU (which is an ARMv3 ARM7DI) would crash when calling libgcc
functions.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit aaf291e9aee8c7f5a63cc212907b050d687cfe20
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 23:33:41 2026 +0100
init: Don't export symbols by default
Until about a year ago, we had an init flag to enable dynamic loading as
INIT_LIBRARY, which was enabled by default, and an init flag to export
all the symbols listed in the export files, as INIT_EXPORT.
However, since commit 65286eb00 (part of PR #680 on github), those two
flags have the same value, which means that since then we've been
exporting all the symbols listed in the export files by default.
This really shouldn't be a default though; therefore, remove the
INIT_LIBRARY flag from the defaults.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 16ffa36c750e9762a00f52c2295d412304c0cbf8
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 23:00:52 2026 +0100
Move arch_exec functions to DC-specific exports
These are not part of an arch API and therefore are not guaranteed to be
present on any other platform.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit f72896553d87ec600ef1cb3e6750615955db2b01
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 22:34:31 2026 +0100
Move default init flags to arch-agnostic kernel
INIT_DEFAULT should always contain the defaults for the kernel + for the
current platform. Therefore the code setting the default init flags is
arch-agnostic and can be shared across platforms.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit ffe0796655603443cb417d97654e8083b1f5e23f
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 2 14:29:44 2025 +0100
treewide: Add and use g2_lock_scoped()
Add a scoped variant of g2_lock(), and use it where it makes sense.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit efe2beb697b4f637650fd17147333c894c29e132
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 22:03:38 2026 +0100
libc: Abort on exit with INIT_NO_SHUTDOWN
When the INIT_NO_SHUTDOWN flag has been set, the application should
never exit, and if it does, it's a bug.
In that error path, call arch_panic() instead of arch_menu(), because
the latter is very Dreamcast-specific, while the former is
arch-independent.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 57e8faadcdf919a9b99456e5d4228287a28718b6
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 8 21:55:11 2026 +0100
Don't link libromdiskbase with C library
libromdiskbase does not call any symbol and therefore does not need to
be linked to anything.
This works around a problem when using romdisks on older versions of
GCC, where the compiler would complain about duplicated symbols at
linking time.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
Makefile.rules | 2 +-
include/kos/cdefs.h | 2 +-
include/kos/init.h | 2 +-
kernel/Makefile | 2 +-
kernel/arch/dreamcast/exports.txt | 4 +
kernel/arch/dreamcast/hardware/g2bus.c | 74 ++++-----------
.../dreamcast/hardware/network/broadband_adapter.c | 6 +-
kernel/arch/dreamcast/hardware/spu.c | 4 +-
kernel/arch/dreamcast/include/dc/g2bus.h | 19 ++++
kernel/arch/dreamcast/kernel/Makefile | 1 -
kernel/arch/dreamcast/sound/snd_iface.c | 10 +-
kernel/arch/dreamcast/sound/snd_stream.c | 4 +-
kernel/exports.txt | 4 -
kernel/init/Makefile | 9 ++
.../dreamcast/kernel => init}/init_flags_default.c | 0
kernel/libc/newlib/newlib_exit.c | 7 +-
utils/kos-chain/patches/targets/gcc-8.5.0-kos.diff | 105 ++++++++++++---------
.../patches/targets/newlib-4.6.0.20260123-kos.diff | 14 ++-
utils/kos-chain/profiles/aica/stable.mk | 3 +
utils/kos-chain/scripts/patch.mk | 1 +
20 files changed, 138 insertions(+), 135 deletions(-)
create mode 100644 kernel/init/Makefile
rename kernel/{arch/dreamcast/kernel => init}/init_flags_default.c (100%)
diff --git a/Makefile.rules b/Makefile.rules
index 90862c21..bbc587aa 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -83,7 +83,7 @@ romdisk.img:
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2c/bin2c romdisk.img romdisk_tmp.c romdisk
kos-cc -o romdisk_tmp.o -c romdisk_tmp.c
- $(KOS_CC) -o romdisk.o -r romdisk_tmp.o $(KOS_LIB_PATHS) -Wl,--whole-archive -lromdiskbase
+ $(KOS_CC) -o romdisk.o -r romdisk_tmp.o $(KOS_LIB_PATHS) -Wl,--whole-archive -lromdiskbase -nostdlib
rm romdisk_tmp.c romdisk_tmp.o
endif
diff --git a/include/kos/cdefs.h b/include/kos/cdefs.h
index 055118e8..06ec265c 100644
--- a/include/kos/cdefs.h
+++ b/include/kos/cdefs.h
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
/* Check GCC version */
-#if __GNUC__ < 9
+#if __GNUC__ < 8
# warning Your GCC is too old. This will probably not work right.
#endif
diff --git a/include/kos/init.h b/include/kos/init.h
index 02f02d64..7c9012a0 100644
--- a/include/kos/init.h
+++ b/include/kos/init.h
@@ -139,7 +139,7 @@ extern const void * __kos_romdisk;
/** Default init flags (IRQs on, preemption enabled, romdisks). */
#define INIT_DEFAULT (INIT_IRQ | INIT_THD_PREEMPT | INIT_FS_ALL | \
- INIT_LIBRARY | INIT_DEFAULT_ARCH)
+ INIT_DEFAULT_ARCH)
/** Init flags to include all virtual filesystems within `/dev` */
#define INIT_FS_DEV (INIT_FS_NULL | INIT_FS_RND)
diff --git a/kernel/Makefile b/kernel/Makefile
index 0668b8c3..45e548e4 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -6,7 +6,7 @@
#
OBJS = banner.o version.o
-SUBDIRS = arch debug fs thread mm net libc exports romdisk
+SUBDIRS = arch debug fs thread mm net libc exports romdisk init
STUBS = stubs/kernel_export_stubs.o stubs/arch_export_stubs.o stubs/subarch_export_stubs.o
# Everything from here up should be plain old C.
diff --git a/kernel/arch/dreamcast/exports.txt b/kernel/arch/dreamcast/exports.txt
index ba1851a7..ba61c415 100644
--- a/kernel/arch/dreamcast/exports.txt
+++ b/kernel/arch/dreamcast/exports.txt
@@ -90,6 +90,10 @@ timer_enable_ints
timer_disable_ints
timer_ints_enabled
+# Kernel image replacement
+arch_exec_at
+arch_exec
+
# Misc
arch_reboot
arch_menu
diff --git a/kernel/arch/dreamcast/hardware/g2bus.c b/kernel/arch/dreamcast/hardware/g2bus.c
index 09dbfcec..7f6bd321 100644
--- a/kernel/arch/dreamcast/hardware/g2bus.c
+++ b/kernel/arch/dreamcast/hardware/g2bus.c
@@ -26,163 +26,121 @@
/* Read one byte from G2 */
uint8_t g2_read_8(uintptr_t address) {
- g2_ctx_t ctx;
- uint8_t out;
+ g2_lock_scoped();
- ctx = g2_lock();
- out = *((volatile uint8_t*)address);
- g2_unlock(ctx);
-
- return out;
+ return *((volatile uint8_t*)address);
}
/* Write one byte to G2 */
void g2_write_8(uintptr_t address, uint8_t value) {
- g2_ctx_t ctx;
+ g2_lock_scoped();
- ctx = g2_lock();
*((volatile uint8_t*)address) = value;
- g2_unlock(ctx);
}
/* Read one word from G2 */
uint16_t g2_read_16(uintptr_t address) {
- g2_ctx_t ctx;
- uint16_t out;
-
- ctx = g2_lock();
- out = *((volatile uint16_t*)address);
- g2_unlock(ctx);
+ g2_lock_scoped();
- return out;
+ return *((volatile uint16_t*)address);
}
/* Write one word to G2 */
void g2_write_16(uintptr_t address, uint16_t value) {
- g2_ctx_t ctx;
+ g2_lock_scoped();
- ctx = g2_lock();
*((volatile uint16_t*)address) = value;
- g2_unlock(ctx);
}
/* Read one dword from G2 */
uint32_t g2_read_32(uintptr_t address) {
- g2_ctx_t ctx;
- uint32_t out;
-
- ctx = g2_lock();
- out = *((volatile uint32_t*)address);
- g2_unlock(ctx);
+ g2_lock_scoped();
- return out;
+ return *((volatile uint32_t*)address);
}
/* Write one dword to G2 */
void g2_write_32(uintptr_t address, uint32_t value) {
- g2_ctx_t ctx;
+ g2_lock_scoped();
- ctx = g2_lock();
*((volatile uint32_t*)address) = value;
- g2_unlock(ctx);
}
/* Read a block of 8-bit values from G2 */
void g2_read_block_8(uint8_t * output, uintptr_t address, size_t amt) {
const volatile uint8_t * input = (const volatile uint8_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = *input++;
}
-
- g2_unlock(ctx);
}
/* Write a block 8-bit values to G2 */
void g2_write_block_8(const uint8_t * input, uintptr_t address, size_t amt) {
volatile uint8_t * output = (volatile uint8_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = *input++;
}
-
- g2_unlock(ctx);
}
/* Read a block of 16-bit values from G2 */
void g2_read_block_16(uint16_t * output, uintptr_t address, size_t amt) {
const volatile uint16_t * input = (const volatile uint16_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = *input++;
}
-
- g2_unlock(ctx);
}
/* Write a block of 16-bit values to G2 */
void g2_write_block_16(const uint16_t * input, uintptr_t address, size_t amt) {
volatile uint16_t * output = (volatile uint16_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = *input++;
}
-
- g2_unlock(ctx);
}
/* Read a block of 32-bit values from G2 */
void g2_read_block_32(uint32_t * output, uintptr_t address, size_t amt) {
const volatile uint32_t * input = (const volatile uint32_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = *input++;
}
-
- g2_unlock(ctx);
}
/* Write a block of 32-bit values to G2 */
void g2_write_block_32(const uint32_t * input, uintptr_t address, size_t amt) {
volatile uint32_t * output = (volatile uint32_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = *input++;
}
-
- g2_unlock(ctx);
}
/* A memset-like function for G2 */
void g2_memset_8(uintptr_t address, uint8_t c, size_t amt) {
volatile uint8_t * output = (volatile uint8_t *)address;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
while(amt--) {
*output++ = c;
}
-
- g2_unlock(ctx);
}
/* When writing to the SPU RAM, this is required at least every 8 32-bit
diff --git a/kernel/arch/dreamcast/hardware/network/broadband_adapter.c b/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
index 60481401..e0be5ae0 100644
--- a/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
+++ b/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
@@ -430,9 +430,7 @@ static void g2_read_block_8_fast(uint8_t *dst, uint8_t *src, int len) {
if(len <= 0)
return;
- g2_ctx_t ctx;
-
- ctx = g2_lock();
+ g2_lock_scoped();
uint32_t *d = (uint32_t *) dst;
uint32_t *s = (uint32_t *) src;
@@ -460,8 +458,6 @@ static void g2_read_block_8_fast(uint8_t *dst, uint8_t *src, int len) {
}
while(--len);
}
-
- g2_unlock(ctx);
}
diff --git a/kernel/arch/dreamcast/hardware/spu.c b/kernel/arch/dreamcast/hardware/spu.c
index a5537288..8cf172f0 100644
--- a/kernel/arch/dreamcast/hardware/spu.c
+++ b/kernel/arch/dreamcast/hardware/spu.c
@@ -250,9 +250,8 @@ void spu_memset_sq(uintptr_t dst, uint32_t what, size_t length) {
/* Reset the AICA channel registers */
void spu_reset_chans(void) {
int i;
- g2_ctx_t ctx;
- ctx = g2_lock();
+ g2_lock_scoped();
g2_fifo_wait();
g2_write_32_raw(SNDREGADDR(0x2800), 0);
@@ -266,7 +265,6 @@ void spu_reset_chans(void) {
g2_fifo_wait();
g2_write_32_raw(SNDREGADDR(0x2800), 0x000f);
- g2_unlock(ctx);
}
/* Enable/disable the SPU; note that disable implies reset of the
diff --git a/kernel/arch/dreamcast/include/dc/g2bus.h b/kernel/arch/dreamcast/include/dc/g2bus.h
index cb9c1c53..d22822b8 100644
--- a/kernel/arch/dreamcast/include/dc/g2bus.h
+++ b/kernel/arch/dreamcast/include/dc/g2bus.h
@@ -190,6 +190,25 @@ static inline void g2_unlock(g2_ctx_t ctx) {
irq_restore(ctx.irq_state);
}
+/** \cond */
+static inline void __g2_scoped_cleanup(g2_ctx_t *state) {
+ g2_unlock(*state);
+}
+
+#define ___g2_lock_scoped(l) \
+ g2_ctx_t __scoped_g2_lock_##l __attribute__((cleanup(__g2_scoped_cleanup))) = g2_lock()
+
+#define __g2_lock_scoped(l) ___g2_lock_scoped(l)
+/** \endcond */
+
+/** \brief Disable IRQs and G2 DMA with scope management
+
+ This function makes the following g2_read_*()/g2_write_*() functions atomic
+ by disabling IRQs and G2 DMA and storing their states. The state will
+ automatically be restored once the execution exits the functional block in
+ which the macro was called.
+*/
+#define g2_lock_scoped() __g2_lock_scoped(__LINE__)
#undef G2_DMA_SUSPEND_SPU
#undef G2_DMA_SUSPEND_BBA
diff --git a/kernel/arch/dreamcast/kernel/Makefile b/kernel/arch/dreamcast/kernel/Makefile
index 83e74a28..8e1ffacb 100644
--- a/kernel/arch/dreamcast/kernel/Makefile
+++ b/kernel/arch/dreamcast/kernel/Makefile
@@ -11,7 +11,6 @@
COPYOBJS = cache.o entry.o irq.o init.o panic.o
COPYOBJS += rtc.o timer.o perfctr.o perf_monitor.o
-COPYOBJS += init_flags_default.o
COPYOBJS += mmu.o itlb.o
COPYOBJS += exec.o execasm.o stack.o gdb_stub.o thdswitch.o tls_static.o arch_exports.o subarch_exports.o
OBJS = $(COPYOBJS) startup.o
diff --git a/kernel/arch/dreamcast/sound/snd_iface.c b/kernel/arch/dreamcast/sound/snd_iface.c
index 872833f4..97077fa7 100644
--- a/kernel/arch/dreamcast/sound/snd_iface.c
+++ b/kernel/arch/dreamcast/sound/snd_iface.c
@@ -75,10 +75,9 @@ void snd_shutdown(void) {
/* Submit a request to the SH4->AICA queue; size is in uint32's */
int snd_sh4_to_aica(void *packet, uint32_t size) {
uint32_t qa, bot, start, top, *pkt32, cnt;
- g2_ctx_t ctx;
assert_msg(size < AICA_CMD_MAX_SIZE, "SH4->AICA packets may not be >256 uint32's long");
- ctx = g2_lock();
+ g2_lock_scoped();
/* Set these up for reference */
qa = SPU_RAM_UNCACHED_BASE + AICA_MEM_CMD_QUEUE;
@@ -111,7 +110,6 @@ int snd_sh4_to_aica(void *packet, uint32_t size) {
g2_fifo_wait();
g2_write_32_raw(qa + offsetof(aica_queue_t, head), start - bot);
- g2_unlock(ctx);
/* We could wait until head == tail here for processing, but there's
not really much point; it'll just slow things down. */
@@ -136,7 +134,8 @@ void snd_sh4_to_aica_stop(void) {
might mean a permanent failure since the queue is probably out of sync. */
int snd_aica_to_sh4(void *packetout) {
uint32 bot, start, stop, top, size, cnt, *pkt32;
- g2_ctx_t ctx = g2_lock();
+
+ g2_lock_scoped();
/* Set these up for reference */
bot = SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE;
@@ -150,7 +149,6 @@ int snd_aica_to_sh4(void *packetout) {
/* Is there anything? */
if(start == stop) {
- g2_unlock(ctx);
return 0;
}
@@ -158,7 +156,6 @@ int snd_aica_to_sh4(void *packetout) {
size = g2_read_32_raw(start + offsetof(aica_cmd_t, size));
if(size >= AICA_CMD_MAX_SIZE) {
- g2_unlock(ctx);
dbglog(DBG_ERROR, "snd_aica_to_sh4(): packet larger than %d dwords\n", AICA_CMD_MAX_SIZE);
return -1;
}
@@ -189,7 +186,6 @@ int snd_aica_to_sh4(void *packetout) {
g2_fifo_wait();
g2_write_32_raw(bot + offsetof(aica_queue_t, tail), start - (SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE));
- g2_unlock(ctx);
return 1;
}
diff --git a/kernel/arch/dreamcast/sound/snd_stream.c b/kernel/arch/dreamcast/sound/snd_stream.c
index 8101bd62..8739d279 100644
--- a/kernel/arch/dreamcast/sound/snd_stream.c
+++ b/kernel/arch/dreamcast/sound/snd_stream.c
@@ -236,7 +236,6 @@ static void snd_pcm16_split_unaligned(void *buffer, void *left, void *right, siz
}
void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t size) {
- g2_ctx_t ctx;
uint32_t i;
uint16_t *s = (uint16_t *)data;
size_t remain = size;
@@ -253,7 +252,7 @@ void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t
sq_lock((void *)left);
dcache_pref_block(s);
- ctx = g2_lock();
+ g2_lock_scoped();
/* Make sure the FIFOs are empty */
g2_fifo_wait();
@@ -315,7 +314,6 @@ void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t
right += 2;
}
}
- g2_unlock(ctx);
}
/* Initialize stream system */
diff --git a/kernel/exports.txt b/kernel/exports.txt
index 3a5331e9..d5247c85 100644
--- a/kernel/exports.txt
+++ b/kernel/exports.txt
@@ -210,10 +210,6 @@ irq_get_global_handler
irq_set_context
irq_get_context
-# Kernel image replacement
-arch_exec_at
-arch_exec
-
# Misc other kernel control
arch_exit
arch_abort
diff --git a/kernel/init/Makefile b/kernel/init/Makefile
new file mode 100644
index 00000000..758134f5
--- /dev/null
+++ b/kernel/init/Makefile
@@ -0,0 +1,9 @@
+# KallistiOS ##version##
+#
+# init/Makefile
+# (c)2026 Paul Cercueil
+#
+
+OBJS = init_flags_default.o
+
+include $(KOS_BASE)/Makefile.prefab
diff --git a/kernel/arch/dreamcast/kernel/init_flags_default.c b/kernel/init/init_flags_default.c
similarity index 100%
rename from kernel/arch/dreamcast/kernel/init_flags_default.c
rename to kernel/init/init_flags_default.c
diff --git a/kernel/libc/newlib/newlib_exit.c b/kernel/libc/newlib/newlib_exit.c
index 00e5be2f..7276cfa6 100644
--- a/kernel/libc/newlib/newlib_exit.c
+++ b/kernel/libc/newlib/newlib_exit.c
@@ -6,7 +6,6 @@
*/
#include <arch/arch.h>
-#include <kos/dbglog.h>
#include <kos/init_base.h>
extern void arch_exit_handler(int ret_code) __noreturn;
@@ -26,9 +25,5 @@ __used void _exit(int code) {
KOS_INIT_FLAG_CALL(kos_shutdown);
- dbglog(DBG_WARNING,
- "arch: _exit(%d) called without SHUTDOWN flag enabled!\n",
- code);
-
- arch_menu();
+ arch_panic("exit() called with INIT_NO_SHUTDOWN flag");
}
diff --git a/utils/kos-chain/patches/targets/gcc-8.5.0-kos.diff b/utils/kos-chain/patches/targets/gcc-8.5.0-kos.diff
index 5fc471f3..85a98908 100644
--- a/utils/kos-chain/patches/targets/gcc-8.5.0-kos.diff
+++ b/utils/kos-chain/patches/targets/gcc-8.5.0-kos.diff
...<truncated>...
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-31 15:51:03
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via d351ea934285f1beb90f7eca1c0bc14e9c96b7eb (commit)
via 05d82b875995c8c84d5d968c7d3762044e06b709 (commit)
from ad7893a06d466594c2b65a0a86eca8261de4d646 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d351ea934285f1beb90f7eca1c0bc14e9c96b7eb
Author: Paul Cercueil <pa...@cr...>
Date: Wed Mar 25 00:26:50 2026 +0100
pthread: Fix mutex type fields aliasing each other
The pthread_mutex_t needs two fields to work, one being "mutex" as the
underlying mutex object, and the other being "type" which represent the
mutex type (e.g. error-checking, or recursive).
These two fields cannot alias each other, and therefore should be placed
into a "struct" inside the union.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 05d82b875995c8c84d5d968c7d3762044e06b709
Author: Paul Cercueil <pa...@cr...>
Date: Wed Mar 25 00:22:30 2026 +0100
pthread: Update initializers, part 2
The previous commit 5098110b5 ("pthread: Update initializers to fix
pthread's rwlock") made one mistake, in that they switched from
initializing the __data field of the unions, to initialize the
underlying types directly.
This works when compiling libpthread, but does not work when compiling
the toolchain, which relies on a different definition of the same
structures in <sys/_pthreadtypes.h>, where the unions don't contain the
underlying types, and only contain the __data field.
Address this issue by updating the types in <sys/_pthreadtypes> so that
they allow the GCC 9.5.0 based toolchain to compile.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
addons/libpthread/pthread-internal.h | 6 ++++--
include/sys/_pthreadtypes.h | 7 +++++++
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/addons/libpthread/pthread-internal.h b/addons/libpthread/pthread-internal.h
index 2ccf5bf5..0d32d783 100644
--- a/addons/libpthread/pthread-internal.h
+++ b/addons/libpthread/pthread-internal.h
@@ -46,8 +46,10 @@ typedef union pthread_attr_t {
} pthread_attr_t;
typedef union pthread_mutex_t {
- mutex_t mutex;
- unsigned int type;
+ struct {
+ mutex_t mutex;
+ unsigned int type;
+ };
unsigned char __data[__PTHREAD_MUTEX_SIZE];
long int __align;
} pthread_mutex_t;
diff --git a/include/sys/_pthreadtypes.h b/include/sys/_pthreadtypes.h
index 67d6166d..9afcbf95 100644
--- a/include/sys/_pthreadtypes.h
+++ b/include/sys/_pthreadtypes.h
@@ -11,6 +11,10 @@
#include <sys/cdefs.h>
__BEGIN_DECLS
+#include <kos/cond.h>
+#include <kos/mutex.h>
+#include <kos/rwsem.h>
+
typedef unsigned long int pthread_t;
typedef struct pthread_mutexattr_t {
@@ -60,6 +64,7 @@ typedef union pthread_attr_t {
#define __PTHREAD_MUTEX_SIZE 32
typedef union pthread_mutex_t {
+ mutex_t mutex;
unsigned char __data[__PTHREAD_MUTEX_SIZE];
long int __align;
} pthread_mutex_t;
@@ -72,6 +77,7 @@ typedef union pthread_mutex_t {
#define __PTHREAD_COND_SIZE 16
typedef union pthread_cond_t {
+ condvar_t cond;
unsigned char __data[__PTHREAD_COND_SIZE];
long int __align;
} pthread_cond_t;
@@ -84,6 +90,7 @@ typedef union pthread_cond_t {
#define __PTHREAD_RWLOCK_SIZE 32
typedef union pthread_rwlock_t {
+ rw_semaphore_t rwsem;
unsigned char __data[__PTHREAD_RWLOCK_SIZE];
long int __align;
} pthread_rwlock_t;
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-31 03:00:21
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via ad7893a06d466594c2b65a0a86eca8261de4d646 (commit)
from f6ed91ea9871f03aa37395ca6a8f1127b7628341 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ad7893a06d466594c2b65a0a86eca8261de4d646
Author: Falco Girgis <gyr...@gm...>
Date: Wed Feb 25 19:30:39 2026 -0600
Removed pvr_wait_ready() from most examples.
Someone correctly complained, upon hearing pvr_wait_ready() was no
longer required, that every example still uses it.... yeeeeeeeeeeah.
lol.
Anyway, removed it from all of them that wasn't setting border colors
around it, which were just the benchmarks + bubbles.
I ran about half a dozen of them, and everything works fine (as I
figured). Just some overdue cleanup to reflect cleanup of the PVR API.
-----------------------------------------------------------------------
Summary of changes:
examples/dreamcast/2ndmix/2ndmix.c | 1 -
examples/dreamcast/cpp/clock/clock.cc | 1 -
examples/dreamcast/cpp/dcplib/fnt_test.cc | 1 -
examples/dreamcast/libdream/ta/ta.c | 1 -
examples/dreamcast/mruby/dreampresent/dckos.c | 1 -
examples/dreamcast/parallax/bubbles/bubbles.c | 10 ----------
examples/dreamcast/parallax/delay_cube/delay_cube.c | 1 -
examples/dreamcast/parallax/font/font.c | 1 -
examples/dreamcast/parallax/raster_melt/raster_melt.c | 1 -
examples/dreamcast/parallax/rotocube/rotocube.c | 1 -
examples/dreamcast/parallax/serpent_dma/serpent.c | 1 -
examples/dreamcast/parallax/sinus/sinus.c | 1 -
examples/dreamcast/png/example.c | 1 -
examples/dreamcast/pvr/bumpmap/bump.c | 1 -
examples/dreamcast/pvr/cheap_shadow/shadow.c | 1 -
examples/dreamcast/pvr/modifier_volume/modifier.c | 1 -
examples/dreamcast/pvr/modifier_volume_tex/modifier.c | 1 -
examples/dreamcast/pvr/modifier_volume_zclip/example.c | 1 -
examples/dreamcast/pvr/palette/4bpp/4bpp.c | 1 -
examples/dreamcast/pvr/palette/8bpp/8bpp.c | 1 -
examples/dreamcast/pvr/palette/wormhole/wormhole.c | 1 -
examples/dreamcast/pvr/plasma/plasma.c | 2 --
examples/dreamcast/pvr/pvrline/pvrline.c | 1 -
examples/dreamcast/pvr/pvrmark/pvrmark.c | 4 ----
examples/dreamcast/pvr/pvrmark_strips/pvrmark_strips.c | 4 ----
.../pvr/pvrmark_strips_direct/pvrmark_strips_direct.c | 4 ----
examples/dreamcast/pvr/strided_texture/strided_texture.c | 1 -
examples/dreamcast/pvr/texture_render/texture_render.c | 5 +----
examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c | 2 --
examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c | 2 --
examples/dreamcast/rumble/rumble.c | 2 --
examples/dreamcast/sound/ghettoplay-vorbis/ghettoplay.c | 1 -
examples/dreamcast/tsunami/banner/banner.cpp | 2 --
examples/dreamcast/tsunami/font/font.cpp | 1 -
examples/dreamcast/vmu/vmu_beep/beep.c | 3 ---
35 files changed, 1 insertion(+), 63 deletions(-)
diff --git a/examples/dreamcast/2ndmix/2ndmix.c b/examples/dreamcast/2ndmix/2ndmix.c
index abb82f73..dc227d6c 100644
--- a/examples/dreamcast/2ndmix/2ndmix.c
+++ b/examples/dreamcast/2ndmix/2ndmix.c
@@ -794,7 +794,6 @@ void font_init(void) {
int framecnt = 0;
void draw_one_frame(void) {
/* Begin opaque polygons */
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/cpp/clock/clock.cc b/examples/dreamcast/cpp/clock/clock.cc
index f71783d8..837a006a 100644
--- a/examples/dreamcast/cpp/clock/clock.cc
+++ b/examples/dreamcast/cpp/clock/clock.cc
@@ -64,7 +64,6 @@ void drawFrame() {
timespec_get(&spec, TIME_UTC);
localtime_r(&spec.tv_sec, &tm);
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_TR_POLY);
diff --git a/examples/dreamcast/cpp/dcplib/fnt_test.cc b/examples/dreamcast/cpp/dcplib/fnt_test.cc
index b8790fd3..cc97152e 100644
--- a/examples/dreamcast/cpp/dcplib/fnt_test.cc
+++ b/examples/dreamcast/cpp/dcplib/fnt_test.cc
@@ -64,7 +64,6 @@ void switchFilterMode() {
void drawFrame() {
//ta_begin_render();
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_TR_POLY);
//pvr_dummy_poly (TA_OPAQUE);
diff --git a/examples/dreamcast/libdream/ta/ta.c b/examples/dreamcast/libdream/ta/ta.c
index faf6e33c..b669bc92 100644
--- a/examples/dreamcast/libdream/ta/ta.c
+++ b/examples/dreamcast/libdream/ta/ta.c
@@ -131,7 +131,6 @@ void draw_frame(void) {
}
/* Start opaque poly list */
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/mruby/dreampresent/dckos.c b/examples/dreamcast/mruby/dreampresent/dckos.c
index 593a8210..bf52695f 100644
--- a/examples/dreamcast/mruby/dreampresent/dckos.c
+++ b/examples/dreamcast/mruby/dreampresent/dckos.c
@@ -157,7 +157,6 @@ void _display_png_file(char *file_path, int x1, int y1, int x2, int y2) {
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/parallax/bubbles/bubbles.c b/examples/dreamcast/parallax/bubbles/bubbles.c
index ab9c06be..fe7abe22 100644
--- a/examples/dreamcast/parallax/bubbles/bubbles.c
+++ b/examples/dreamcast/parallax/bubbles/bubbles.c
@@ -96,10 +96,6 @@ static float r = 0;
static void sphere_frame_opaque(void) {
int i;
- vid_border_color(255, 0, 0);
- pvr_wait_ready();
- vid_border_color(0, 255, 0);
-
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
@@ -135,7 +131,6 @@ static void sphere_frame_opaque(void) {
plx_mat3d_pop();
- vid_border_color(0, 0, 255);
pvr_scene_finish();
r++;
@@ -145,10 +140,6 @@ static void sphere_frame_opaque(void) {
static void sphere_frame_trans(void) {
int i;
- vid_border_color(255, 0, 0);
- pvr_wait_ready();
- vid_border_color(0, 255, 0);
-
pvr_scene_begin();
pvr_list_begin(PVR_LIST_TR_POLY);
@@ -168,7 +159,6 @@ static void sphere_frame_trans(void) {
plx_mat3d_pop();
- vid_border_color(0, 0, 255);
pvr_scene_finish();
r++;
diff --git a/examples/dreamcast/parallax/delay_cube/delay_cube.c b/examples/dreamcast/parallax/delay_cube/delay_cube.c
index d0b2c58d..5aff5468 100644
--- a/examples/dreamcast/parallax/delay_cube/delay_cube.c
+++ b/examples/dreamcast/parallax/delay_cube/delay_cube.c
@@ -124,7 +124,6 @@ int main(int argc, char **argv) {
MAPLE_FOREACH_END()
// Setup the frame
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/parallax/font/font.c b/examples/dreamcast/parallax/font/font.c
index b142e2e1..a60c04cc 100644
--- a/examples/dreamcast/parallax/font/font.c
+++ b/examples/dreamcast/parallax/font/font.c
@@ -35,7 +35,6 @@ int main(int argc, char **argv) {
w.z = 10.0f;
while(!done) {
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_begin(PVR_LIST_TR_POLY);
diff --git a/examples/dreamcast/parallax/raster_melt/raster_melt.c b/examples/dreamcast/parallax/raster_melt/raster_melt.c
index 37e3a82f..20fbf7c1 100644
--- a/examples/dreamcast/parallax/raster_melt/raster_melt.c
+++ b/examples/dreamcast/parallax/raster_melt/raster_melt.c
@@ -57,7 +57,6 @@ int main(int argc, char **argv) {
MAPLE_FOREACH_END()
// Setup the frame
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/parallax/rotocube/rotocube.c b/examples/dreamcast/parallax/rotocube/rotocube.c
index 3b54afaa..a6cbb928 100644
--- a/examples/dreamcast/parallax/rotocube/rotocube.c
+++ b/examples/dreamcast/parallax/rotocube/rotocube.c
@@ -137,7 +137,6 @@ int main(int argc, char **argv) {
MAPLE_FOREACH_END()
// Setup the frame
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/parallax/serpent_dma/serpent.c b/examples/dreamcast/parallax/serpent_dma/serpent.c
index bf048cfc..6ea6a55c 100644
--- a/examples/dreamcast/parallax/serpent_dma/serpent.c
+++ b/examples/dreamcast/parallax/serpent_dma/serpent.c
@@ -163,7 +163,6 @@ static void sphere_frame(void) {
if(!small_sphere.data)
sphere(&small_sphere);
- pvr_wait_ready();
pvr_scene_begin();
//start = timer_ms_gettime64();
diff --git a/examples/dreamcast/parallax/sinus/sinus.c b/examples/dreamcast/parallax/sinus/sinus.c
index 189c41ba..70594225 100644
--- a/examples/dreamcast/parallax/sinus/sinus.c
+++ b/examples/dreamcast/parallax/sinus/sinus.c
@@ -76,7 +76,6 @@ int main(int argc, char **argv) {
MAPLE_FOREACH_END()
// Setup the frame
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/png/example.c b/examples/dreamcast/png/example.c
index 52d42bca..900efccd 100644
--- a/examples/dreamcast/png/example.c
+++ b/examples/dreamcast/png/example.c
@@ -184,7 +184,6 @@ int y = 0;
/* draw one frame */
void draw_frame(void) {
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/bumpmap/bump.c b/examples/dreamcast/pvr/bumpmap/bump.c
index b0e107d3..cb8b4814 100644
--- a/examples/dreamcast/pvr/bumpmap/bump.c
+++ b/examples/dreamcast/pvr/bumpmap/bump.c
@@ -185,7 +185,6 @@ static void do_frame(void) {
shdr[0].oargb = pvr_pack_bump(bumpiness, F_PI / 4.0f, 5.0f * F_PI / 6.0f);
shdr[0].argb = 0;
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/cheap_shadow/shadow.c b/examples/dreamcast/pvr/cheap_shadow/shadow.c
index 3477f099..d9319235 100644
--- a/examples/dreamcast/pvr/cheap_shadow/shadow.c
+++ b/examples/dreamcast/pvr/cheap_shadow/shadow.c
@@ -136,7 +136,6 @@ void do_frame(void) {
pvr_modifier_vol_t mod;
int i;
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(list);
diff --git a/examples/dreamcast/pvr/modifier_volume/modifier.c b/examples/dreamcast/pvr/modifier_volume/modifier.c
index e9279987..f6fe2e21 100644
--- a/examples/dreamcast/pvr/modifier_volume/modifier.c
+++ b/examples/dreamcast/pvr/modifier_volume/modifier.c
@@ -121,7 +121,6 @@ void do_frame(void) {
pvr_modifier_vol_t mod;
int i;
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(list);
diff --git a/examples/dreamcast/pvr/modifier_volume_tex/modifier.c b/examples/dreamcast/pvr/modifier_volume_tex/modifier.c
index 8c475287..97d6aef2 100644
--- a/examples/dreamcast/pvr/modifier_volume_tex/modifier.c
+++ b/examples/dreamcast/pvr/modifier_volume_tex/modifier.c
@@ -173,7 +173,6 @@ void do_frame(void) {
pvr_modifier_vol_t mod;
int i;
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(list);
diff --git a/examples/dreamcast/pvr/modifier_volume_zclip/example.c b/examples/dreamcast/pvr/modifier_volume_zclip/example.c
index 1c0bf25c..fe971ded 100644
--- a/examples/dreamcast/pvr/modifier_volume_zclip/example.c
+++ b/examples/dreamcast/pvr/modifier_volume_zclip/example.c
@@ -285,7 +285,6 @@ int main(int argc, char* argv[])
mat_lookat(&cam_pos, &cam_tar, &cam_up);
mat_store(&cam_pvm);
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/palette/4bpp/4bpp.c b/examples/dreamcast/pvr/palette/4bpp/4bpp.c
index 04cebaf0..4a409255 100644
--- a/examples/dreamcast/pvr/palette/4bpp/4bpp.c
+++ b/examples/dreamcast/pvr/palette/4bpp/4bpp.c
@@ -164,7 +164,6 @@ int main(int argc, char** argv) {
frame = (frame + 1) % 256;
animate_palette(frame);
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/palette/8bpp/8bpp.c b/examples/dreamcast/pvr/palette/8bpp/8bpp.c
index 4adb4489..aa5237fb 100644
--- a/examples/dreamcast/pvr/palette/8bpp/8bpp.c
+++ b/examples/dreamcast/pvr/palette/8bpp/8bpp.c
@@ -156,7 +156,6 @@ int main(int argc, char** argv) {
animate_palette(frame);
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/palette/wormhole/wormhole.c b/examples/dreamcast/pvr/palette/wormhole/wormhole.c
index e8be75f6..38326da0 100644
--- a/examples/dreamcast/pvr/palette/wormhole/wormhole.c
+++ b/examples/dreamcast/pvr/palette/wormhole/wormhole.c
@@ -181,7 +181,6 @@ int main(int argc, char** argv) {
animate_wormhole(frame);
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/plasma/plasma.c b/examples/dreamcast/pvr/plasma/plasma.c
index 7016377a..32618146 100644
--- a/examples/dreamcast/pvr/plasma/plasma.c
+++ b/examples/dreamcast/pvr/plasma/plasma.c
@@ -140,8 +140,6 @@ void do_frame(void) {
float r, g, b;
vid_border_color(255, 0, 0);
- pvr_wait_ready();
- vid_border_color(0, 255, 0);
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_prim(&hdr[txr_cur], sizeof(*hdr));
diff --git a/examples/dreamcast/pvr/pvrline/pvrline.c b/examples/dreamcast/pvr/pvrline/pvrline.c
index b766953b..f71c6038 100644
--- a/examples/dreamcast/pvr/pvrline/pvrline.c
+++ b/examples/dreamcast/pvr/pvrline/pvrline.c
@@ -104,7 +104,6 @@ int main(int argc, char **argv)
}
}
- pvr_wait_ready();
pvr_scene_begin();
/* set vertex buffers for pvr_list_prim use */
diff --git a/examples/dreamcast/pvr/pvrmark/pvrmark.c b/examples/dreamcast/pvr/pvrmark/pvrmark.c
index 200c6add..ff32b57f 100644
--- a/examples/dreamcast/pvr/pvrmark/pvrmark.c
+++ b/examples/dreamcast/pvr/pvrmark/pvrmark.c
@@ -80,9 +80,6 @@ void do_frame(void) {
#define nextnum() seed = seed * 1164525 + 1013904223;
#define getnum(mn) (seed & ((mn) - 1))
- vid_border_color(0, 0, 0);
- pvr_wait_ready();
- vid_border_color(255, 0, 0);
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_prim(&hdr, sizeof(hdr));
@@ -126,7 +123,6 @@ void do_frame(void) {
pvr_list_finish();
pvr_scene_finish();
- vid_border_color(0, 255, 0);
oldseed = seed;
}
diff --git a/examples/dreamcast/pvr/pvrmark_strips/pvrmark_strips.c b/examples/dreamcast/pvr/pvrmark_strips/pvrmark_strips.c
index 1a58436a..8005dc40 100644
--- a/examples/dreamcast/pvr/pvrmark_strips/pvrmark_strips.c
+++ b/examples/dreamcast/pvr/pvrmark_strips/pvrmark_strips.c
@@ -74,9 +74,6 @@ void do_frame(void) {
int x, y, z;
int i, col;
- vid_border_color(0, 0, 0);
- pvr_wait_ready();
- vid_border_color(255, 0, 0);
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_prim(&hdr, sizeof(hdr));
@@ -111,7 +108,6 @@ void do_frame(void) {
pvr_list_finish();
pvr_scene_finish();
- vid_border_color(0, 255, 0);
}
time_t begin;
diff --git a/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c b/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c
index 0304fe95..74356aa6 100644
--- a/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c
+++ b/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c
@@ -95,9 +95,6 @@ static void do_frame(void) {
static int oldseed = 0xdeadbeef;
int seed = oldseed;
- vid_border_color(0, 0, 0);
- pvr_wait_ready();
- vid_border_color(255, 0, 0);
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_prim(&hdr, sizeof(hdr));
@@ -137,7 +134,6 @@ static void do_frame(void) {
pvr_list_finish();
pvr_scene_finish();
- vid_border_color(0, 255, 0);
oldseed = seed;
}
diff --git a/examples/dreamcast/pvr/strided_texture/strided_texture.c b/examples/dreamcast/pvr/strided_texture/strided_texture.c
index 8115a2f4..d9e7b6d2 100644
--- a/examples/dreamcast/pvr/strided_texture/strided_texture.c
+++ b/examples/dreamcast/pvr/strided_texture/strided_texture.c
@@ -97,7 +97,6 @@ static pvr_vertex_t verts[4];
static pvr_ptr_t board_texture;
static void draw_frame(void) {
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/texture_render/texture_render.c b/examples/dreamcast/pvr/texture_render/texture_render.c
index 3ad28502..96d653da 100644
--- a/examples/dreamcast/pvr/texture_render/texture_render.c
+++ b/examples/dreamcast/pvr/texture_render/texture_render.c
@@ -124,14 +124,12 @@ void draw_frame(void) {
pvr_poly_cxt_col(&cxt, PVR_LIST_OP_POLY);
pvr_poly_compile(&poly, &cxt);
- /* Start opaque poly list */
- pvr_wait_ready();
-
if(!to_texture)
pvr_scene_begin();
else
pvr_scene_begin_txr(d_texture, &tx_x, &tx_y);
+ /* Start opaque poly list */
pvr_list_begin(PVR_LIST_OP_POLY);
/* Send polygon header to the TA using store queues */
@@ -164,7 +162,6 @@ void draw_textured(void) {
d_texture, PVR_FILTER_NONE);
pvr_poly_compile(&hdr, &cxt);
- pvr_wait_ready();
pvr_scene_begin();
/* Start opaque poly list */
diff --git a/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c b/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c
index aa02b1d7..27a825f5 100644
--- a/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c
+++ b/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c
@@ -235,8 +235,6 @@ static void convert_YUV420_to_YUV422_texture(void) {
}
static void show_image(void) {
-
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c b/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c
index 3e6354db..aabab40d 100644
--- a/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c
+++ b/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c
@@ -240,8 +240,6 @@ static void convert_YUV422_to_YUV422_texture(void) {
}
static void show_image(void) {
-
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/rumble/rumble.c b/examples/dreamcast/rumble/rumble.c
index f75a23d7..68eb6c1f 100644
--- a/examples/dreamcast/rumble/rumble.c
+++ b/examples/dreamcast/rumble/rumble.c
@@ -63,7 +63,6 @@ void wait_for_dev_attach(maple_device_t **dev_ptr, unsigned int func) {
return;
/* Draw up a screen */
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_begin(PVR_LIST_TR_POLY);
@@ -141,7 +140,6 @@ int main(int argc, char *argv[]) {
wait_for_dev_attach(&purudev, MAPLE_FUNC_PURUPURU);
/* Start drawing and draw the header */
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_begin(PVR_LIST_TR_POLY);
diff --git a/examples/dreamcast/sound/ghettoplay-vorbis/ghettoplay.c b/examples/dreamcast/sound/ghettoplay-vorbis/ghettoplay.c
index 370094f0..09b7ae7c 100644
--- a/examples/dreamcast/sound/ghettoplay-vorbis/ghettoplay.c
+++ b/examples/dreamcast/sound/ghettoplay-vorbis/ghettoplay.c
@@ -135,7 +135,6 @@ int main(int argc, char **argv) {
bkg_setup();
while(!check_start()) {
- pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
diff --git a/examples/dreamcast/tsunami/banner/banner.cpp b/examples/dreamcast/tsunami/banner/banner.cpp
index 509b6778..d98fe5c6 100644
--- a/examples/dreamcast/tsunami/banner/banner.cpp
+++ b/examples/dreamcast/tsunami/banner/banner.cpp
...<truncated>...
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-30 13:52:30
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via f6ed91ea9871f03aa37395ca6a8f1127b7628341 (commit)
via 3b60394ed9bc751fa4acacc109f6c5d929d3dd1e (commit)
from 572aa64d146c6a999e28fef81f21e08a440c6ee1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f6ed91ea9871f03aa37395ca6a8f1127b7628341
Author: Yev <ev...@gm...>
Date: Sat Mar 28 00:07:25 2026 +0100
Add std::filesystem example to kos
commit 3b60394ed9bc751fa4acacc109f6c5d929d3dd1e
Author: Yev <ev...@gm...>
Date: Sat Mar 28 00:07:06 2026 +0100
Add missing std::filesystem support by building newlib with proper dirent.h and adding missing fs functions
-----------------------------------------------------------------------
Summary of changes:
.../dreamcast/cpp/{clock => filesystem}/Makefile | 18 +-
examples/dreamcast/cpp/filesystem/filesystem.cpp | 187 +++++++++++++++++++++
.../dreamcast/cpp/filesystem/romdisk/data/file.txt | 1 +
.../dreamcast/cpp/filesystem/romdisk/file1.txt | 4 +
.../dreamcast/cpp/filesystem/romdisk/file2.txt | 3 +
kernel/libc/koslib/Makefile | 3 +-
kernel/libc/koslib/link.c | 11 ++
kernel/libc/koslib/lstat.c | 11 ++
kernel/libc/koslib/pathconf.c | 36 ++++
kernel/libc/koslib/stat.c | 11 ++
kernel/libc/koslib/unlink.c | 11 ++
utils/kos-chain/patches/gcc/fake-kos.c | 9 +
utils/kos-chain/scripts/newlib.mk | 1 +
13 files changed, 298 insertions(+), 8 deletions(-)
copy examples/dreamcast/cpp/{clock => filesystem}/Makefile (55%)
create mode 100644 examples/dreamcast/cpp/filesystem/filesystem.cpp
create mode 100644 examples/dreamcast/cpp/filesystem/romdisk/data/file.txt
create mode 100644 examples/dreamcast/cpp/filesystem/romdisk/file1.txt
create mode 100644 examples/dreamcast/cpp/filesystem/romdisk/file2.txt
create mode 100644 kernel/libc/koslib/link.c
create mode 100644 kernel/libc/koslib/lstat.c
create mode 100644 kernel/libc/koslib/pathconf.c
create mode 100644 kernel/libc/koslib/stat.c
create mode 100644 kernel/libc/koslib/unlink.c
diff --git a/examples/dreamcast/cpp/clock/Makefile b/examples/dreamcast/cpp/filesystem/Makefile
similarity index 55%
copy from examples/dreamcast/cpp/clock/Makefile
copy to examples/dreamcast/cpp/filesystem/Makefile
index e9839821..74bbd909 100644
--- a/examples/dreamcast/cpp/clock/Makefile
+++ b/examples/dreamcast/cpp/filesystem/Makefile
@@ -1,19 +1,19 @@
#
-# DC Clock App
-# Based on Peter Hatch's Font Test
-# (c)2002 Megan Potter
+# std::filesystem test program
#
-TARGET = clock.elf
-OBJS = clock.o romdisk.o
+TARGET = filesystem.elf
+OBJS = filesystem.o romdisk.o
+KOS_CPPFLAGS += -std=c++23
KOS_ROMDISK_DIR = romdisk
-
-KOS_CPPFLAGS += -std=gnu++17
+KOS_GCCVER_MIN = 14.0.0
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
+ifeq ($(call KOS_GCCVER_MIN_CHECK,$(KOS_GCCVER_MIN)),1)
+
clean: rm-elf
-rm -f $(OBJS)
@@ -30,3 +30,7 @@ dist: $(TARGET)
-rm -f $(OBJS) romdisk.img
$(KOS_STRIP) $(TARGET)
+else
+ all $(TARGET) clean rm-elf run dist:
+ $(KOS_GCCVER_MIN_WARNING)
+endif
\ No newline at end of file
diff --git a/examples/dreamcast/cpp/filesystem/filesystem.cpp b/examples/dreamcast/cpp/filesystem/filesystem.cpp
new file mode 100644
index 00000000..62d382cd
--- /dev/null
+++ b/examples/dreamcast/cpp/filesystem/filesystem.cpp
@@ -0,0 +1,187 @@
+/* KallistiOS ##version##
+
+ filesystem.cpp
+ Copyright (C) 2026 Yevhen Lohachov
+
+ This example serves two purposes: to demonstrate the basic usage
+ of the C++17 std::filesystem API, and to serve as a validation test for
+ the toolchain, to ensure that it's functioning properly.
+*/
+
+#include <filesystem>
+#include <print>
+#include <chrono>
+
+namespace fs = std::filesystem;
+
+namespace {
+
+void print_entry(const fs::directory_entry& entry) {
+ if (entry.is_directory()) {
+ std::print("[dir]\t{}\n", entry.path().string());
+ } else if (entry.is_regular_file()) {
+ std::print("[file]\t{} - {} bytes\n", entry.path().string(), entry.file_size());
+ } else if (entry.is_symlink()) {
+ std::print("[symlink]\t{}\n", entry.path().string());
+ } else {
+ std::print("[other]\t{}\n", entry.path().string());
+ }
+}
+
+void print_perm(fs::perms p)
+{
+ using fs::perms;
+ auto show = [=](char op, perms perm)
+ {
+ std::print("{}", (perms::none == (perm & p) ? '-' : op));
+ };
+ show('r', perms::owner_read);
+ show('w', perms::owner_write);
+ show('x', perms::owner_exec);
+ show('r', perms::group_read);
+ show('w', perms::group_write);
+ show('x', perms::group_exec);
+ show('r', perms::others_read);
+ show('w', perms::others_write);
+ show('x', perms::others_exec);
+ std::print("\n");
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ std::print("*** std::filesystem test ***\n");
+
+ const fs::path ro_dir = fs::path("/rd");
+ // const fs::path ro_dir = fs::path("/pc");
+ // const fs::path ro_dir = fs::path("/cd");
+
+ const fs::path rw_dir = fs::path("/ram");
+
+ if (!fs::exists(ro_dir)) {
+ std::print("[ERR] Path does not exist: {}\n", ro_dir.string());
+ return 1;
+ }
+ if (!fs::exists(rw_dir)) {
+ std::print("[ERR] Path does not exist: {}\n", rw_dir.string());
+ return 1;
+ }
+
+ if (!fs::is_directory(ro_dir)) {
+ std::print("[ERR] Path is not a directory: {}\n", ro_dir.string());
+ return 1;
+ }
+ if (!fs::is_directory(rw_dir)) {
+ std::print("[ERR] Path is not a directory: {}\n", rw_dir.string());
+ return 1;
+ }
+
+ std::error_code ec;
+
+ std::print("\n*** Setting current path ***\n");
+ fs::current_path(ro_dir, ec);
+ if (ec) {
+ std::print("[ERR] Failed to set current path: {}\n", ec.message());
+ }
+ std::print("Current path: {}\n", fs::current_path(ec).string());
+ if (ec) {
+ std::print("[ERR] Failed to get current path: {}\n", ec.message());
+ }
+
+ auto src_file = ro_dir / "data/file.txt";
+ auto dst_file = rw_dir / "copy.txt";
+ auto nonexistent_file = rw_dir / "nonexistent_file.txt";
+ auto hard_link_file = rw_dir / "hard_link.txt";
+ auto symlink_file = rw_dir / "symlink.txt";
+
+ std::print("\n*** Copying file test ***\n");
+ fs::copy_file(src_file, dst_file, fs::copy_options::update_existing, ec);
+ if (ec) {
+ std::print("[ERR] Failed to copy file: {}\n", ec.message());
+ } else {
+ std::print("Copied file from {} -> {}\n", src_file.string(), dst_file.string());
+ }
+
+ std::print("\n*** Testing file existence ***\n");
+ if (!fs::exists(dst_file)) {
+ std::print("[ERR] File does not exist: {}\n", dst_file.string());
+ } else {
+ std::print("File exists: {}\n", dst_file.string());
+ }
+
+ if (!fs::exists(nonexistent_file)) {
+ std::print("File does not exist: {}\n", nonexistent_file.string());
+ } else {
+ std::print("[ERR] File exists: {}\n", nonexistent_file.string());
+ }
+
+ std::print("\n*** Last write time ***\n");
+ auto ftime = fs::last_write_time(dst_file, ec);
+ if (ec) {
+ std::print("[ERR] Failed to get last write time: {}\n", ec.message());
+ } else {
+ std::print("Last write time: {}\n", ftime);
+ }
+
+ std::print("\n*** Removing file test ***\n");
+ fs::remove(dst_file, ec);
+ if (ec) {
+ std::print("[ERR] Failed to remove file: {}\n", ec.message());
+ } else {
+ std::print("Removed file: {}\n", dst_file.string());
+ }
+
+ std::print("\n*** Permissions test ***\n");
+ print_perm(fs::status(src_file).permissions());
+
+ std::print("\n*** Directory entries ***\n");
+ for (const auto& entry : fs::directory_iterator(ro_dir, fs::directory_options::skip_permission_denied)) {
+ print_entry(entry);
+ }
+
+ std::print("\n*** Recursive directory entries ***\n");
+ for (const auto& entry : fs::recursive_directory_iterator(ro_dir, fs::directory_options::skip_permission_denied)) {
+ print_entry(entry);
+ }
+
+ std::print("\n*** Creating directory test ***\n");
+ fs::create_directory(rw_dir, ec);
+ if (ec) {
+ std::print("[ERR] Failed to create directory: {}\n", ec.message());
+ } else {
+ std::print("Created directory: {}\n", rw_dir.string());
+ }
+
+ std::print("\n*** Hard link test ***\n");
+ fs::create_hard_link(src_file, hard_link_file, ec);
+ if (ec) {
+ std::print("[ERR] Failed to create hard link: {}\n", ec.message());
+ } else {
+ std::print("Created hard link: {} -> {}\n", src_file.string(), hard_link_file.string());
+ }
+
+ int hl_count = fs::hard_link_count(hard_link_file, ec);
+ if (ec) {
+ std::print("[ERR] Failed to get hard link count: {}\n", ec.message());
+ } else {
+ std::print("Hard link count: {}\n", hl_count);
+ }
+
+ std::print("\n*** Symlink test ***\n");
+ fs::create_symlink(src_file, symlink_file, ec);
+ if (ec) {
+ std::print("[ERR] Failed to create symlink: {}\n", ec.message());
+ } else {
+ std::print("Created symlink: {} -> {}\n", src_file.string(), symlink_file.string());
+ }
+
+ auto sym_target = fs::read_symlink(symlink_file, ec);
+ if (ec) {
+ std::print("[ERR] Failed to read symlink: {}\n", ec.message());
+ } else {
+ std::print("Symlink target: {}\n", sym_target.string());
+ }
+
+ std::print("\nDone.\n");
+ return 0;
+}
diff --git a/examples/dreamcast/cpp/filesystem/romdisk/data/file.txt b/examples/dreamcast/cpp/filesystem/romdisk/data/file.txt
new file mode 100644
index 00000000..51845765
--- /dev/null
+++ b/examples/dreamcast/cpp/filesystem/romdisk/data/file.txt
@@ -0,0 +1 @@
+the quick brown fox jumps over the lazy dog
\ No newline at end of file
diff --git a/examples/dreamcast/cpp/filesystem/romdisk/file1.txt b/examples/dreamcast/cpp/filesystem/romdisk/file1.txt
new file mode 100644
index 00000000..c2ac92a4
--- /dev/null
+++ b/examples/dreamcast/cpp/filesystem/romdisk/file1.txt
@@ -0,0 +1,4 @@
+ /\_/\
+( ^.^ )
+ (")(")
+
\ No newline at end of file
diff --git a/examples/dreamcast/cpp/filesystem/romdisk/file2.txt b/examples/dreamcast/cpp/filesystem/romdisk/file2.txt
new file mode 100644
index 00000000..b9a07c80
--- /dev/null
+++ b/examples/dreamcast/cpp/filesystem/romdisk/file2.txt
@@ -0,0 +1,3 @@
+ /\_/\
+( o.o )
+ > ^ <
diff --git a/kernel/libc/koslib/Makefile b/kernel/libc/koslib/Makefile
index 625beae2..6ead1353 100644
--- a/kernel/libc/koslib/Makefile
+++ b/kernel/libc/koslib/Makefile
@@ -14,6 +14,7 @@ OBJS = abort.o memset2.o memset4.o memcpy2.o memcpy4.o \
creat.o sleep.o rmdir.o rename.o inet_pton.o inet_ntop.o \
inet_ntoa.o inet_aton.o poll.o select.o symlink.o readlink.o \
gethostbyname.o getaddrinfo.o dirfd.o nanosleep.o basename.o dirname.o \
- sched_yield.o dup.o dup2.o pipe.o uname.o
+ sched_yield.o dup.o dup2.o pipe.o uname.o pathconf.o stat.o lstat.o \
+ link.o unlink.o
include $(KOS_BASE)/Makefile.prefab
diff --git a/kernel/libc/koslib/link.c b/kernel/libc/koslib/link.c
new file mode 100644
index 00000000..05377924
--- /dev/null
+++ b/kernel/libc/koslib/link.c
@@ -0,0 +1,11 @@
+/* KallistiOS ##version##
+
+ link.c
+ Copyright (C)2026 Yevhen Lohachov
+*/
+
+#include <kos/fs.h>
+
+int link(const char *oldpath, const char *newpath) {
+ return fs_link(oldpath, newpath);
+}
diff --git a/kernel/libc/koslib/lstat.c b/kernel/libc/koslib/lstat.c
new file mode 100644
index 00000000..9bd5bf19
--- /dev/null
+++ b/kernel/libc/koslib/lstat.c
@@ -0,0 +1,11 @@
+/* KallistiOS ##version##
+
+ lstat.c
+ Copyright (C)2026 Yevhen Lohachov
+*/
+
+#include <kos/fs.h>
+
+int lstat(const char *restrict path, struct stat *restrict buf) {
+ return fs_stat(path, buf, AT_SYMLINK_NOFOLLOW);
+}
diff --git a/kernel/libc/koslib/pathconf.c b/kernel/libc/koslib/pathconf.c
new file mode 100644
index 00000000..c2826359
--- /dev/null
+++ b/kernel/libc/koslib/pathconf.c
@@ -0,0 +1,36 @@
+/* KallistiOS ##version##
+
+ pathconf.c
+ Copyright (C)2026 Yevhen Lohachov
+*/
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <kos/fs.h>
+#include <kos/limits.h>
+
+long pathconf(const char *path, int name) {
+ (void)path;
+ switch (name)
+ {
+ case _PC_LINK_MAX:
+ return SYMLOOP_MAX;
+ break;
+ case _PC_NAME_MAX:
+ return NAME_MAX;
+ break;
+ case _PC_PATH_MAX:
+ return PATH_MAX;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return 1;
+ break;
+ case _PC_NO_TRUNC:
+ return 1;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
diff --git a/kernel/libc/koslib/stat.c b/kernel/libc/koslib/stat.c
new file mode 100644
index 00000000..e7a16597
--- /dev/null
+++ b/kernel/libc/koslib/stat.c
@@ -0,0 +1,11 @@
+/* KallistiOS ##version##
+
+ stat.c
+ Copyright (C)2026 Yevhen Lohachov
+*/
+
+#include <kos/fs.h>
+
+int stat(const char *restrict path, struct stat *restrict buf) {
+ return fs_stat(path, buf, 0);
+}
diff --git a/kernel/libc/koslib/unlink.c b/kernel/libc/koslib/unlink.c
new file mode 100644
index 00000000..ef1e28e4
--- /dev/null
+++ b/kernel/libc/koslib/unlink.c
@@ -0,0 +1,11 @@
+/* KallistiOS ##version##
+
+ unlink.c
+ Copyright (C)2026 Yevhen Lohachov
+*/
+
+#include <kos/fs.h>
+
+int unlink(const char *path) {
+ return fs_unlink(path);
+}
diff --git a/utils/kos-chain/patches/gcc/fake-kos.c b/utils/kos-chain/patches/gcc/fake-kos.c
index 10e4faa8..db8915dc 100644
--- a/utils/kos-chain/patches/gcc/fake-kos.c
+++ b/utils/kos-chain/patches/gcc/fake-kos.c
@@ -62,3 +62,12 @@ alias(_fstat_r);
alias(_isatty_r);
alias(_exit);
alias(__setup_argv_and_call_main);
+alias(chdir);
+alias(getcwd);
+alias(mkdir);
+alias(rename);
+alias(stat);
+alias(lstat);
+alias(symlink);
+alias(link);
+alias(unlink);
diff --git a/utils/kos-chain/scripts/newlib.mk b/utils/kos-chain/scripts/newlib.mk
index da64bab6..12855da6 100644
--- a/utils/kos-chain/scripts/newlib.mk
+++ b/utils/kos-chain/scripts/newlib.mk
@@ -43,6 +43,7 @@ fixup-newlib-apply: fixup-newlib-init
cp $(kos_base)/include/pthread.h $(newlib_inc)
cp $(kos_base)/include/sys/_pthreadtypes.h $(newlib_inc)/sys
cp $(kos_base)/include/sys/_pthread.h $(newlib_inc)/sys
+ cp $(kos_base)/include/sys/dirent.h $(newlib_inc)/sys
ifndef MINGW32
ln -nsf $(kos_base)/include/kos $(newlib_inc)
ln -nsf $(kos_base)/kernel/arch/$(platform)/include/arch $(newlib_inc)
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-30 13:45:42
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 572aa64d146c6a999e28fef81f21e08a440c6ee1 (commit)
from 9ba0350f12a0ce2d33974103fb302e5637438074 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 572aa64d146c6a999e28fef81f21e08a440c6ee1
Author: Siana Gearz <sia...@gm...>
Date: Mon Mar 16 16:18:14 2026 +0100
utils/pvrtex: fix file corruption on Windows
Use 'rb'/'wb' in fopen calls to prevent CRLF substitution in binary files
on Windows.
Fix approvaltest makefile to actually run the test by default. Looks
like it was always intended to, but then just didn't.
before change: approvaltest on Windows fails;
after change: approvaltest succeeds.
Fixes https://github.com/KallistiOS/KallistiOS/issues/1339
-----------------------------------------------------------------------
Summary of changes:
utils/pvrtex/approvaltest/Makefile | 4 ++--
utils/pvrtex/file_common.c | 4 ++--
utils/pvrtex/file_dctex.c | 4 ++--
utils/pvrtex/file_pvr.c | 2 +-
utils/pvrtex/file_tex.c | 4 ++--
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/utils/pvrtex/approvaltest/Makefile b/utils/pvrtex/approvaltest/Makefile
index c0e78900..dfcf5e76 100644
--- a/utils/pvrtex/approvaltest/Makefile
+++ b/utils/pvrtex/approvaltest/Makefile
@@ -7,7 +7,7 @@ RUN_DIR = $(TEST_DIR)/run
PVRTEX = ../pvrtex
# Default target
-all: test
+all: compare
# Define the array of commands
TESTS = \
@@ -59,4 +59,4 @@ approve:
clean:
@rm -rf $(RECEIVED_DIR)
-.PHONY: all test approve clean
\ No newline at end of file
+.PHONY: all compare approve clean
\ No newline at end of file
diff --git a/utils/pvrtex/file_common.c b/utils/pvrtex/file_common.c
index 8049bce3..dd0bf17b 100644
--- a/utils/pvrtex/file_common.c
+++ b/utils/pvrtex/file_common.c
@@ -63,7 +63,7 @@ void WritePvrTexEncoder(const PvrTexEncoder *pte, FILE *f, ptewSmallVQType svq,
int FileSize(const char *fname) {
assert(fname);
- FILE *f = fopen(fname, "r");
+ FILE *f = fopen(fname, "rb");
if (f == NULL)
return -1;
fseek(f, 0, SEEK_END);
@@ -75,7 +75,7 @@ int FileSize(const char *fname) {
size_t Slurp(const char *fname, void **data) {
assert(fname);
- FILE *f = fopen(fname, "r");
+ FILE *f = fopen(fname, "rb");
if (f == NULL)
return 0;
diff --git a/utils/pvrtex/file_dctex.c b/utils/pvrtex/file_dctex.c
index af66def2..33b2a48a 100644
--- a/utils/pvrtex/file_dctex.c
+++ b/utils/pvrtex/file_dctex.c
@@ -28,7 +28,7 @@ static int convert_size(int size) {
void fDtWrite(const PvrTexEncoder *pte, const char *outfname) {
assert(pte);
- FILE *f = fopen(outfname, "w");
+ FILE *f = fopen(outfname, "wb");
assert(f);
unsigned textype = 0;
@@ -74,7 +74,7 @@ void fDtWrite(const PvrTexEncoder *pte, const char *outfname) {
unsigned resultsize = FileSize(outfname);
ErrorExitOn(resultsize != size, "Size of file written for \"%s\" was incorrect. Expected file to be %u bytes, but result was %u bytes.\n", outfname, size, resultsize);
- f = fopen(outfname, "r");
+ f = fopen(outfname, "rb");
void *readbuff = malloc(size);
if (fread(readbuff, size, 1, f) == 1) {
if (!fDtValidateHeader(readbuff)) {
diff --git a/utils/pvrtex/file_pvr.c b/utils/pvrtex/file_pvr.c
index 0fdbae0b..2c9714b0 100644
--- a/utils/pvrtex/file_pvr.c
+++ b/utils/pvrtex/file_pvr.c
@@ -21,7 +21,7 @@ void fPvrWrite(const PvrTexEncoder *pte, const char *outfname) {
assert(pte->pvr_tex);
assert(outfname);
- FILE *f = fopen(outfname, "w");
+ FILE *f = fopen(outfname, "wb");
assert(f);
//Write header
diff --git a/utils/pvrtex/file_tex.c b/utils/pvrtex/file_tex.c
index 03e5f0f1..a856be45 100644
--- a/utils/pvrtex/file_tex.c
+++ b/utils/pvrtex/file_tex.c
@@ -8,7 +8,7 @@
void fTexWrite(const PvrTexEncoder *pte, const char *outfname) {
assert(pte);
- FILE *f = fopen(outfname, "w");
+ FILE *f = fopen(outfname, "wb");
assert(f);
unsigned textype = 0;
@@ -61,7 +61,7 @@ void fTexWritePalette(const PvrTexEncoder *pte, const char *outfname) {
pteLog(LOG_COMPLETION, "Writing .PAL to \"%s\"...\n", outfname);
- FILE *f = fopen(outfname, "w");
+ FILE *f = fopen(outfname, "wb");
assert(f);
WriteFourCC("DPAL", f);
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-26 01:54:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 9ba0350f12a0ce2d33974103fb302e5637438074 (commit)
from 7f7baedeccdb309d48296bcc5dfddf39a16ea861 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 9ba0350f12a0ce2d33974103fb302e5637438074
Author: Paul Cercueil <pa...@cr...>
Date: Mon Mar 23 13:48:24 2026 +0100
fs: Normalize path in fs_stat() and fs_readlink()
Use fs_normalize_path() instead of manually trying to recreate the
absolute path of the argument.
This has an added benefit, which is that the VFS backends won't have to
handle '.' and '..' in the respective .stat and .readlink callbacks.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
kernel/fs/fs.c | 22 ++++------------------
1 file changed, 4 insertions(+), 18 deletions(-)
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c
index 7e51c892..48dd0184 100644
--- a/kernel/fs/fs.c
+++ b/kernel/fs/fs.c
@@ -815,15 +815,8 @@ int fs_readlink(const char *path, char *buf, size_t bufsize) {
vfs_handler_t *vfs;
char fullpath[PATH_MAX];
- /* Prepend the current working directory if we have to. */
- if(path[0] == '/') {
- strcpy(fullpath, path);
- }
- else {
- strcpy(fullpath, fs_getwd());
- strcat(fullpath, "/");
- strcat(fullpath, path);
- }
+ if(!fs_normalize_path(path, fullpath))
+ return -1;
/* Look for the handler */
vfs = fs_verify_handler(fullpath);
@@ -857,15 +850,8 @@ int fs_stat(const char *path, struct stat *buf, int flag) {
return -1;
}
- /* Prepend the current working directory if we have to. */
- if(path[0] == '/') {
- strcpy(fullpath, path);
- }
- else {
- strcpy(fullpath, fs_getwd());
- strcat(fullpath, "/");
- strcat(fullpath, path);
- }
+ if(!fs_normalize_path(path, fullpath))
+ return -1;
/* Look for the handler */
vfs = fs_verify_handler(fullpath);
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-19 18:34:12
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 7f7baedeccdb309d48296bcc5dfddf39a16ea861 (commit)
from 5098110b5b0310f297a6a9a1f6b64e025eb30d75 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 7f7baedeccdb309d48296bcc5dfddf39a16ea861
Author: Paul Cercueil <pa...@cr...>
Date: Thu Mar 5 00:10:58 2026 +0100
bba: Fix config defines
The __is_defined() macro only resolves to 1 if the macro it's used with
is defined to 1; any other value will cause __is_defined() to resolve to
0.
Fix the RX_NOWRAP / TX_SEMA macros that were set, but not properly set
to 1.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
kernel/arch/dreamcast/hardware/network/broadband_adapter.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/kernel/arch/dreamcast/hardware/network/broadband_adapter.c b/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
index 77a560fc..60481401 100644
--- a/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
+++ b/kernel/arch/dreamcast/hardware/network/broadband_adapter.c
@@ -29,11 +29,12 @@
#define RTL_MEM (0x1840000)
-#define RX_NOWRAP RT_RXC_WRAP /* Default to no wrapping */
+#define RX_NOWRAP 1 /* Default to no wrapping */
#define RX_BUFFER_SHIFT 1 /* 0 : 8Kb, 1 : 16Kb, 2 : 32Kb, 3 : 64Kb */
#define RX_CONFIG_DEFAULT (RT_ERTH(0) | RT_RXC_RXFTH(0) | \
- RT_RXC_RBLEN(RX_BUFFER_SHIFT) | RT_RXC_MXDMA(6) | RX_NOWRAP)
+ RT_RXC_RBLEN(RX_BUFFER_SHIFT) | RT_RXC_MXDMA(6) | \
+ (RX_NOWRAP ? RT_RXC_WRAP : 0))
#define RX_BUFFER_LEN (0x2000 << RX_BUFFER_SHIFT)
@@ -54,7 +55,7 @@
it might be a good idea to protect bba_tx with a semaphore from inside.
I'm not sure lwip needs that, but dcplaya does when using both lwip and its
own dcload syscalls emulation.*/
-#define TX_SEMA
+#define TX_SEMA 1
/* If this is defined, the dma buffer will be located in P2 area, and no call to
dcache_inval_range need to be done before receiving data.
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-18 01:49:25
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 5098110b5b0310f297a6a9a1f6b64e025eb30d75 (commit)
from 8f7497cfc424851897fc78a6e523fdceef2324e7 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5098110b5b0310f297a6a9a1f6b64e025eb30d75
Author: Paul Cercueil <pa...@cr...>
Date: Tue Mar 17 18:03:56 2026 +0100
pthread: Update initializers to fix pthread's rwlock
Use the proper initializers for the mutex, cond and rwsem types.
This fixes the rwlock initialization, as the fields are no longer all
zeroes.
Fixes #1338.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
include/pthread.h | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/include/pthread.h b/include/pthread.h
index 4d67758c..e0e052e1 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -39,6 +39,10 @@
#include <sched.h>
#include <time.h>
+#include <kos/cond.h>
+#include <kos/mutex.h>
+#include <kos/rwsem.h>
+
__BEGIN_DECLS
/* Process shared/private flag. Since we don't support multiple processes, these
@@ -128,7 +132,7 @@ int pthread_cond_init(pthread_cond_t *__RESTRICT cond,
const pthread_condattr_t *__RESTRICT attr);
int pthread_cond_destroy(pthread_cond_t *cond);
-#define PTHREAD_COND_INITIALIZER { .__data = { 0 } }
+#define PTHREAD_COND_INITIALIZER { .cond = COND_INITIALIZER }
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
@@ -158,7 +162,7 @@ int pthread_mutex_init(pthread_mutex_t *__RESTRICT mutex,
const pthread_mutexattr_t *__RESTRICT attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
-#define PTHREAD_MUTEX_INITIALIZER { .__data = { 0 } }
+#define PTHREAD_MUTEX_INITIALIZER { .mutex = MUTEX_INITIALIZER }
#define PTHREAD_MUTEX_NORMAL 0
#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
#define PTHREAD_MUTEX_ERRORCHECK 2
@@ -196,7 +200,7 @@ int pthread_rwlock_init(pthread_rwlock_t *__RESTRICT rwlock,
const pthread_rwlockattr_t *__RESTRICT attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
-#define PTHREAD_RWLOCK_INITIALIZER { .__data = { 0 } }
+#define PTHREAD_RWLOCK_INITIALIZER { .rwsem = RWSEM_INITIALIZER }
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *__RESTRICT rwlock,
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-12 22:29:29
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 8f7497cfc424851897fc78a6e523fdceef2324e7 (commit)
from d950bd63ea3f70d0fe826ea3563937e582c6a2e2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8f7497cfc424851897fc78a6e523fdceef2324e7
Author: Paul Cercueil <pa...@cr...>
Date: Mon Mar 2 14:30:00 2026 +0100
rwsem: Use semaphore instead of mutex for read lock
The problem with using a mutex for the read lock, is that the thread
which locks the mutex must be the one to unlock it.
This does not work well with R/W semaphores, because the reader thread
that will release the lock may not be the one that obtained it. This
happens for instance in the TCP stack.
Address this issue by using a regular semaphore as our read lock instead
of a mutex.
A consequence of this is that a writer that waits on the read lock now
won't try to boost the thread holding it. That should be fine, because
once again, the thread that first got the lock may have released it long
ago, and other readers are holding the R/W semaphore.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
include/kos/rwsem.h | 5 +++--
kernel/thread/rwsem.c | 27 ++++++++++++++-------------
2 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/include/kos/rwsem.h b/include/kos/rwsem.h
index fb0d77bc..5b5c7886 100644
--- a/include/kos/rwsem.h
+++ b/include/kos/rwsem.h
@@ -45,6 +45,7 @@ __BEGIN_DECLS
#include <stddef.h>
#include <kos/mutex.h>
+#include <kos/sem.h>
/** \brief Reader/writer semaphore structure.
@@ -58,11 +59,11 @@ typedef struct rw_semaphore {
int read_count;
mutex_t write_lock;
- mutex_t read_lock;
+ semaphore_t read_sem;
} rw_semaphore_t;
/** \brief Initializer for a transient reader/writer semaphore */
-#define RWSEM_INITIALIZER { 0, MUTEX_INITIALIZER, MUTEX_INITIALIZER }
+#define RWSEM_INITIALIZER { 0, MUTEX_INITIALIZER, SEM_INITIALIZER(1) }
/** \brief Initialize a reader/writer semaphore.
diff --git a/kernel/thread/rwsem.c b/kernel/thread/rwsem.c
index 8c4b0fe5..37d17914 100644
--- a/kernel/thread/rwsem.c
+++ b/kernel/thread/rwsem.c
@@ -23,14 +23,14 @@ typedef enum rwsem_update_type {
int rwsem_init(rw_semaphore_t *s) {
s->read_count = 0;
s->write_lock = (mutex_t)MUTEX_INITIALIZER;
- s->read_lock = (mutex_t)MUTEX_INITIALIZER;
+ s->read_sem = (semaphore_t)SEM_INITIALIZER(1);
return 0;
}
/* Destroy a reader/writer semaphore */
int rwsem_destroy(rw_semaphore_t *s) {
- if(mutex_is_locked(&s->write_lock) || mutex_is_locked(&s->read_lock)) {
+ if(mutex_is_locked(&s->write_lock) || sem_count(&s->read_sem) == 0) {
errno = EBUSY;
return -1;
}
@@ -64,18 +64,19 @@ static int rwsem_update_timed(rw_semaphore_t *s, unsigned int timeout,
if(type == UPDATE_TYPE_UPGRADE)
rwsem_read_unlock(s);
- if(mutex_lock_timed(&s->read_lock, timeout)) {
+ if(sem_wait_timed(&s->read_sem, timeout)) {
if(type == UPDATE_TYPE_READ) {
atomic_fetch_sub(&s->read_count, 1);
} else if(type == UPDATE_TYPE_UPGRADE
&& atomic_fetch_add(&s->read_count, 1) == 0) {
- /* mutex_locked_timed() timed out, but the read count we just
+ /* sem_wait_timed() timed out, but the read count we just
* updated was zero, which means that whatever was holding up
- * the mutex may have unlocked it since then, or will unlock it
- * the next time it runs without delay. This is guaranteed
- * because we hold up the write mutex, so no other reader or
- * writer can lock up the read mutex before we do. */
- mutex_lock(&s->read_lock);
+ * the semaphore may have unlocked it since then, or will
+ * unlock it the next time it runs without delay. This is
+ * guaranteed because we hold up the write mutex, so no other
+ * reader or writer can lock up the read semaphore before we
+ * do. */
+ sem_wait(&s->read_sem);
}
mutex_unlock(&s->write_lock);
@@ -117,14 +118,14 @@ int rwsem_write_lock_irqsafe(rw_semaphore_t *s) {
/* Unlock a reader/writer semaphore from a read lock. */
int rwsem_read_unlock(rw_semaphore_t *s) {
if(atomic_fetch_sub(&s->read_count, 1) == 1)
- mutex_unlock(&s->read_lock);
+ sem_signal(&s->read_sem);
return 0;
}
/* Unlock a reader/writer semaphore from a write lock. */
int rwsem_write_unlock(rw_semaphore_t *s) {
- mutex_unlock(&s->read_lock);
+ sem_signal(&s->read_sem);
mutex_unlock(&s->write_lock);
return 0;
@@ -147,7 +148,7 @@ int rwsem_read_trylock(rw_semaphore_t *s) {
}
if(atomic_fetch_add(&s->read_count, 1) == 0
- && mutex_trylock(&s->read_lock)) {
+ && sem_trywait(&s->read_sem)) {
atomic_fetch_sub(&s->read_count, 1);
mutex_unlock(&s->write_lock);
errno = EWOULDBLOCK;
@@ -166,7 +167,7 @@ int rwsem_write_trylock(rw_semaphore_t *s) {
return -1;
}
- if(mutex_trylock(&s->read_lock)) {
+ if(sem_trywait(&s->read_sem)) {
mutex_unlock(&s->write_lock);
errno = EWOULDBLOCK;
return -1;
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-12 21:20:37
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via d950bd63ea3f70d0fe826ea3563937e582c6a2e2 (commit)
from 85f84859679319cbb0df217b93b9dc6a830c93f0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d950bd63ea3f70d0fe826ea3563937e582c6a2e2
Author: Falco Girgis <gyr...@gm...>
Date: Thu Mar 12 07:42:46 2026 -0500
Bumping KOS version on master branch to 2.3.0.
- We introduced an API-breaking change to genwait(), which makes it now
take one less argument on master.
- The problem is that master is versioned at 2.2.2, which has the
genwait() change, but SO IS the v2.2.x branch, which does NOT have the
genwait change.
- We need to introduce a minor version bump into master to be able to
version properly within our codebase (Ocarina of Time) like so:
static void WaitForVBlank(void) {
/* +3 = 20 FPS (matching N64 original), +2 = 30, +1 = 60, +0 = uncapped */
while (sVblCounter < sLastVbl + 3)
genwait_wait((void*)&sVblCounter, NULL, 0, NULL);
genwait_wait((void*)&sVblCounter, NULL, 0);
sLastVbl = sVblCounter;
}
** This version bump just means the next tagged release will be v2.3.0,
but we are not actually tagging that release yet, just bumping the
version here. **
-----------------------------------------------------------------------
Summary of changes:
include/kos/version.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/kos/version.h b/include/kos/version.h
index 11372be6..65fa1156 100644
--- a/include/kos/version.h
+++ b/include/kos/version.h
@@ -98,8 +98,8 @@
*/
#define KOS_VERSION_MAJOR 2 /**< KOS's current major revision number. */
-#define KOS_VERSION_MINOR 2 /**< KOS's current minor revision number. */
-#define KOS_VERSION_PATCH 2 /**< KOS's current patch revision number. */
+#define KOS_VERSION_MINOR 3 /**< KOS's current minor revision number. */
+#define KOS_VERSION_PATCH 0 /**< KOS's current patch revision number. */
/** KOS's current version as an integer ID. */
#define KOS_VERSION \
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-12 03:51:05
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 85f84859679319cbb0df217b93b9dc6a830c93f0 (commit)
via 9d513f63b7808ac910457a417313713a82e06ec3 (commit)
via 3897415785912f7edaa5a1a3d86aab8569be223d (commit)
via 871fd59b46d36e3a8751be3cff416f2ac54696de (commit)
via 5f13d959fade31c82e04ada08b409d6303a93a19 (commit)
via 30fbeb8f3e1ef080384411f9ee76533f1ec65856 (commit)
via 96b01ea7b5f221974b0da5a53c2c1962ad1c7d1b (commit)
via c08dacd6e03ee045060cd7f9209a0f386e770221 (commit)
via 1f814015289c0eed7e1d425e1df992e0707395ac (commit)
from 8b8df3d67a642dd9fc716b80864226f3bf20da50 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 85f84859679319cbb0df217b93b9dc6a830c93f0
Author: SilverNexus <haw...@pr...>
Date: Sat Feb 28 03:01:20 2026 -0500
Per change request, add exit condition to the example.
A, B, X, Y, and Start pressed together terminates the example.
commit 9d513f63b7808ac910457a417313713a82e06ec3
Author: SilverNexus <haw...@pr...>
Date: Thu Oct 23 19:08:06 2025 -0400
Per pull request suggestion, add duration to sprite blits.
Since the screen seems to be automatically cleared every frame, we have to add some from infrastructure to draw stuff for multiple frames.
commit 3897415785912f7edaa5a1a3d86aab8569be223d
Author: SilverNexus <haw...@pr...>
Date: Mon Oct 20 15:36:02 2025 -0400
Add an oddball-sized image to better show that the texture-handling works for all image sizes.
commit 871fd59b46d36e3a8751be3cff416f2ac54696de
Author: SilverNexus <haw...@pr...>
Date: Mon Oct 20 12:59:09 2025 -0400
Per pull request suggestion, ignore . and .. directory walk entries.
commit 5f13d959fade31c82e04ada08b409d6303a93a19
Author: SilverNexus <haw...@pr...>
Date: Mon Oct 20 12:53:21 2025 -0400
Per pull request suggestion, make sprites draw within the bounds of the screen.
Previous behavior had them sometimes draw off the bottom and right edges. By changing the modulo to account for texture size, they now draw inside the bounds of the screen.
commit 30fbeb8f3e1ef080384411f9ee76533f1ec65856
Author: SilverNexus <haw...@pr...>
Date: Tue Sep 23 02:30:02 2025 -0400
Add an 8x8 texture.
Extra motive of troubleshooting my main project, but the fact that it displays here just fine tells me it's something in the other project.
commit 96b01ea7b5f221974b0da5a53c2c1962ad1c7d1b
Author: SilverNexus <haw...@pr...>
Date: Mon Sep 22 00:49:13 2025 -0400
Use better memory stewardship.
commit c08dacd6e03ee045060cd7f9209a0f386e770221
Author: SilverNexus <haw...@pr...>
Date: Mon Sep 22 00:36:48 2025 -0400
Fix an off-by-one error in array iterations.
Was previously stopping at 1, since it would decrement to zero and immediately check, thus exiting before index 0 was handled.
commit 1f814015289c0eed7e1d425e1df992e0707395ac
Author: SilverNexus <haw...@pr...>
Date: Sun Sep 21 15:11:14 2025 -0400
Create example for handling raylib Image and Texture2D structures.
Code comments note a couple caveats that may not be obvious to a newbie.
-----------------------------------------------------------------------
Summary of changes:
examples/dreamcast/raylib/texture2d/Makefile | 26 +++
examples/dreamcast/raylib/texture2d/NOTE | 22 +++
.../raylib/texture2d/images/bear.rtro.x31.png | Bin 0 -> 444 bytes
.../dreamcast/raylib/texture2d/images/bearhead.png | Bin 0 -> 284 bytes
.../dreamcast/raylib/texture2d/images/box_tl.png | Bin 0 -> 147 bytes
.../raylib/texture2d/images/brazier.rtro.113.png | Bin 0 -> 207 bytes
.../raylib/texture2d/images/chair_small.png | Bin 0 -> 300 bytes
.../texture2d/images/close_dresser.rtro.111.png | Bin 0 -> 230 bytes
.../texture2d/images/cookingpot.toobig.111.png | Bin 0 -> 308 bytes
.../texture2d/images/drag_steak.base.111.png | Bin 0 -> 323 bytes
.../texture2d/images/dragon_wing.base.111.png | Bin 0 -> 374 bytes
.../images/grand_piano_black.rtro.x11.png | Bin 0 -> 400 bytes
.../texture2d/images/handmirror.base.112.png | Bin 0 -> 339 bytes
.../texture2d/images/kobold_gen.base.111.png | Bin 0 -> 312 bytes
.../texture2d/images/messageboard32.rtro.111.png | Bin 0 -> 309 bytes
.../texture2d/images/pl_dragon_r.rtro.151.png | Bin 0 -> 384 bytes
.../raylib/texture2d/images/stew_veg.base.111.png | Bin 0 -> 276 bytes
.../raylib/texture2d/images/topaz.base.112.png | Bin 0 -> 412 bytes
.../texture2d/images/university.rtro.x11.png | Bin 0 -> 1222 bytes
examples/dreamcast/raylib/texture2d/main.c | 217 +++++++++++++++++++++
20 files changed, 265 insertions(+)
create mode 100644 examples/dreamcast/raylib/texture2d/Makefile
create mode 100644 examples/dreamcast/raylib/texture2d/NOTE
create mode 100644 examples/dreamcast/raylib/texture2d/images/bear.rtro.x31.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/bearhead.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/box_tl.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/brazier.rtro.113.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/chair_small.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/close_dresser.rtro.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/cookingpot.toobig.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/drag_steak.base.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/dragon_wing.base.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/grand_piano_black.rtro.x11.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/handmirror.base.112.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/kobold_gen.base.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/messageboard32.rtro.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/pl_dragon_r.rtro.151.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/stew_veg.base.111.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/topaz.base.112.png
create mode 100644 examples/dreamcast/raylib/texture2d/images/university.rtro.x11.png
create mode 100644 examples/dreamcast/raylib/texture2d/main.c
diff --git a/examples/dreamcast/raylib/texture2d/Makefile b/examples/dreamcast/raylib/texture2d/Makefile
new file mode 100644
index 00000000..30c374d6
--- /dev/null
+++ b/examples/dreamcast/raylib/texture2d/Makefile
@@ -0,0 +1,26 @@
+#
+# Raylib 2D Image Example
+# Author: Neila Hawkins
+#
+
+CC=kos-cc
+
+TARGET=rayimages.elf
+SRC=main.c
+
+LIBS=-lraylib -lGL
+CFLAGS=-std=c11 -g
+
+KOS_ROMDISK_DIR = images
+
+KOS_BUILD_SUBARCHS = pristine
+
+all: $(TARGET)
+
+include $(KOS_BASE)/Makefile.rules
+
+$(TARGET): $(SRC) Makefile romdisk.o
+ $(CC) -o $(TARGET) $(SRC) romdisk.o $(CFLAGS) $(LIBS)
+
+clean:
+ rm $(TARGET) romdisk.img romdisk.o
diff --git a/examples/dreamcast/raylib/texture2d/NOTE b/examples/dreamcast/raylib/texture2d/NOTE
new file mode 100644
index 00000000..1fe99df1
--- /dev/null
+++ b/examples/dreamcast/raylib/texture2d/NOTE
@@ -0,0 +1,22 @@
+The images provided in this example are all created by Neila Hawkins,
+and most contributed to Crossfire RPG Game under various Creative Commons licences.
+
+The specific licensing and photo references of each is as follows:
+bear.rtro.x31.png: CC-BY-2.0. Drawn from reference photo at https://www.flickr.com/photos/42409752@N07/6266114045/ by Amareta Kelly
+bearhead.png: CC-BY-2.0. Drawn from reference photo at https://www.flickr.com/photos/42409752@N07/6266114045/ by Amareta Kelly
+brazier.rtro.113.png: CC-0. Redrawn version (new viewing angle) of other art from within Crossfire RPG Game
+close_dresser.rtro.111.png: CC-0
+cookingpot.toobig.111.png: CC-0
+dragon_wing.base.111.png: CC-BY-SA 2.0. Drawn from reference photo at https://www.flickr.com/photos/34176693@N06/40813744885 by Hari K Patibanda
+drag_steak.base.111.png: CC-BY-SA-2.0. Drawn from reference photo at https://www.flickr.com/photos/stuart_spivack/277659093/ by stu_spivack
+grand_piano_black.rtro.x11.png: CC-SA-2.0. Drawn from reference photo at https://www.flickr.com/photos/51764518@N02/49286256543 by Joe Haupt
+handmirror.base.112.png: CC-BY-4.0. Drawn from reference photo at https://creativecommons.org/licenses/by/4.0/ by Thomas Quine
+kobold_gen.base.111.png: CC-0. Redrawn version (new viewing angle) of other art from withing Crossfire RPG Game
+messageboard32.rtro.111.png: CC-0. Redrawn version (new viewing angle) of other art from within Crossfire RPG Game
+pl_dragon_r.rtro.151.png: CC-0
+stew_veg.base.111.png: CC-0
+topaz.base.112.png: CC-BY-2.0. Drawn from reference photo at https://www.flickr.com/photos/47445767@N05/32298163220 by James St. John
+university.rtro.x11.png: CC-0. Redrawn version (new viewing angle) of other art from within Crossfire RPG Game
+
+box_tl.png: CC-0. Rather than a Crossfire RPG Game asset, this was made in an attempt to build a client for said game using raylib. It is the top-left corner of a text box, size 8x8.
+chair_small.png: CC-0. Borne of a discussion of designing tail-accessible chairs.
diff --git a/examples/dreamcast/raylib/texture2d/images/bear.rtro.x31.png b/examples/dreamcast/raylib/texture2d/images/bear.rtro.x31.png
new file mode 100644
index 00000000..a57a074b
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/bear.rtro.x31.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/bearhead.png b/examples/dreamcast/raylib/texture2d/images/bearhead.png
new file mode 100644
index 00000000..63b3781d
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/bearhead.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/box_tl.png b/examples/dreamcast/raylib/texture2d/images/box_tl.png
new file mode 100644
index 00000000..a3cdf31b
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/box_tl.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/brazier.rtro.113.png b/examples/dreamcast/raylib/texture2d/images/brazier.rtro.113.png
new file mode 100644
index 00000000..d8570a62
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/brazier.rtro.113.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/chair_small.png b/examples/dreamcast/raylib/texture2d/images/chair_small.png
new file mode 100644
index 00000000..81543d1d
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/chair_small.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/close_dresser.rtro.111.png b/examples/dreamcast/raylib/texture2d/images/close_dresser.rtro.111.png
new file mode 100644
index 00000000..b76efd97
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/close_dresser.rtro.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/cookingpot.toobig.111.png b/examples/dreamcast/raylib/texture2d/images/cookingpot.toobig.111.png
new file mode 100644
index 00000000..b7778275
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/cookingpot.toobig.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/drag_steak.base.111.png b/examples/dreamcast/raylib/texture2d/images/drag_steak.base.111.png
new file mode 100644
index 00000000..4fd205c1
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/drag_steak.base.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/dragon_wing.base.111.png b/examples/dreamcast/raylib/texture2d/images/dragon_wing.base.111.png
new file mode 100644
index 00000000..dc4af716
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/dragon_wing.base.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/grand_piano_black.rtro.x11.png b/examples/dreamcast/raylib/texture2d/images/grand_piano_black.rtro.x11.png
new file mode 100644
index 00000000..9db46893
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/grand_piano_black.rtro.x11.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/handmirror.base.112.png b/examples/dreamcast/raylib/texture2d/images/handmirror.base.112.png
new file mode 100644
index 00000000..0009b8ad
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/handmirror.base.112.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/kobold_gen.base.111.png b/examples/dreamcast/raylib/texture2d/images/kobold_gen.base.111.png
new file mode 100644
index 00000000..a1b88386
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/kobold_gen.base.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/messageboard32.rtro.111.png b/examples/dreamcast/raylib/texture2d/images/messageboard32.rtro.111.png
new file mode 100644
index 00000000..224961bf
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/messageboard32.rtro.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/pl_dragon_r.rtro.151.png b/examples/dreamcast/raylib/texture2d/images/pl_dragon_r.rtro.151.png
new file mode 100644
index 00000000..ccab5521
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/pl_dragon_r.rtro.151.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/stew_veg.base.111.png b/examples/dreamcast/raylib/texture2d/images/stew_veg.base.111.png
new file mode 100644
index 00000000..485c3379
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/stew_veg.base.111.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/topaz.base.112.png b/examples/dreamcast/raylib/texture2d/images/topaz.base.112.png
new file mode 100644
index 00000000..fcfd31b1
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/topaz.base.112.png differ
diff --git a/examples/dreamcast/raylib/texture2d/images/university.rtro.x11.png b/examples/dreamcast/raylib/texture2d/images/university.rtro.x11.png
new file mode 100644
index 00000000..acb213e8
Binary files /dev/null and b/examples/dreamcast/raylib/texture2d/images/university.rtro.x11.png differ
diff --git a/examples/dreamcast/raylib/texture2d/main.c b/examples/dreamcast/raylib/texture2d/main.c
new file mode 100644
index 00000000..5c532cd7
--- /dev/null
+++ b/examples/dreamcast/raylib/texture2d/main.c
@@ -0,0 +1,217 @@
+#include <raylib/raylib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ASSETS "/rd"
+//#define ASSETS "images"
+
+/**
+ * Functions for handling a custom vector of images.
+ */
+typedef struct ImageCollection {
+ Image *image_arr;
+ int capacity;
+ int used;
+} ImageCollection;
+
+void image_collection_init(ImageCollection *collection, int initialsize) {
+ collection->image_arr = malloc(sizeof(Image) * initialsize);
+ if (!collection->image_arr)
+ return;
+ collection->capacity = initialsize;
+ collection->used = 0;
+}
+
+void image_collection_add(ImageCollection *collection, Image *img) {
+ if (collection->capacity == collection->used) {
+ collection->capacity <<= 1;
+ collection->image_arr = realloc(collection->image_arr, sizeof(Image) * collection->capacity);
+ if (!collection->image_arr)
+ return;
+ }
+ memcpy(&collection->image_arr[collection->used], img, sizeof(Image));
+ ++collection->used;
+}
+
+void image_collection_cleanup(ImageCollection *collection) {
+ for (int i = collection->used; i--;) {
+ UnloadImage(collection->image_arr[i]);
+ }
+ free(collection->image_arr);
+}
+/**
+ * End custom vector
+ */
+
+/**
+ * Structure for creating a circular buffer of textures.
+ */
+typedef struct {
+ Texture *elem;
+ int x;
+ int y;
+} ScreenElement;
+
+typedef struct {
+ ScreenElement *scr;
+ int at;
+ int len;
+} ElementBuffer;
+
+void buffer_add_element(ElementBuffer *buf, Texture *elem, int x, int y) {
+ buf->scr[buf->at].elem = elem;
+ buf->scr[buf->at].x = x;
+ buf->scr[buf->at].y = y;
+ buf->at = (buf->at + 1) % buf->len;
+}
+
+ElementBuffer *buffer_init(int len) {
+ ElementBuffer *buf = malloc(sizeof(ElementBuffer));
+ buf->scr = calloc(sizeof(ScreenElement), len);
+ buf->at = 0;
+ buf->len = len;
+ return buf;
+}
+
+void buffer_cleanup(ElementBuffer *buf) {
+ free(buf->scr);
+ free(buf);
+}
+/**
+ * End circular buffer
+ */
+
+uint32_t power_of_two(int dim) {
+ // int is 32-bit.
+ dim--;
+ dim |= dim >> 1;
+ dim |= dim >> 2;
+ dim |= dim >> 4;
+ dim |= dim >> 8;
+ dim |= dim >> 16;
+ dim++;
+ return (uint32_t)dim;
+}
+
+int main() {
+ InitWindow(640, 480, "Raylib Image Test");
+ if (!IsWindowReady())
+ return 1;
+ SetTargetFPS(60);
+
+ ImageCollection collection;
+ image_collection_init(&collection, 10);
+
+ // We're gonna load each file and blit it to the screen.
+ DIR *dir = opendir(ASSETS);
+ if (!dir) {
+ printf("Directory load failure!");
+ return 1;
+ }
+
+ struct dirent *at_dir;
+
+ while ((at_dir = readdir(dir))) {
+ // Skip over . and .. filesystem directory structure.
+ if (strcmp(at_dir->d_name, ".") == 0 || strcmp(at_dir->d_name, "..") == 0)
+ continue;
+ char buf[NAME_MAX+5];
+ strcpy(buf, ASSETS"/");
+ strcat(buf, at_dir->d_name);
+ Image img = LoadImage(buf);
+ if (IsImageValid(img)) {
+ // Resize the image to a power of 2 to convert it to a texture.
+
+ // For the Dreamcast, Textures (in VRAM) must have dimensions
+ // of a power of 2 to correctly draw.
+ // So we resize the image canvas here to load the texture
+ // specifically in dimensions of a power of 2.
+ uint32_t width = power_of_two(img.width);
+ uint32_t height = power_of_two(img.height);
+
+ ImageResizeCanvas(&img, width, height, 0, 0, BLANK);
+
+ image_collection_add(&collection, &img);
+ }
+ }
+
+ closedir(dir);
+
+ if (collection.used == 0)
+ return -1; // Don't draw if empty selection.
+
+ // Load the textures before the loop. Loading textures after BeginDrawing does not work.
+ Texture2D *textures = malloc(sizeof(Texture2D) * collection.used);
+ for (int i = collection.used; i--;) {
+ textures[i] = LoadTextureFromImage(collection.image_arr[i]);
+ // Once textures are loaded, you can free Images.
+ // In our case, we have them in a data structure, so we wait until after the loop.
+ }
+
+ // Since we clean up the images, don't reference data that probably isn't right.
+ int texture_len = collection.used;
+
+ image_collection_cleanup(&collection);
+
+ // 400 is arbitrary. Should be enough for images to stay for a decent amount of time.
+ ElementBuffer *buf = buffer_init(400);
+
+ // Now we blit all the sprites to the screen repeatedly in random locations.
+ while (!WindowShouldClose()) {
+ for (int i = texture_len; i--;) {
+ if (IsTextureValid(textures[i])) {
+ /* By subtracting the dimensions of the texture from the modulo,
+ * we can ensure that the sprites appear on the screen.
+ * Due to canvas resizing, this will make some sprites not draw
+ * all the way in the corner, but this is better behavior
+ * than drawing mostly off the screen.
+ */
+ int x = rand() % (640 - textures[i].width),
+ y = rand() % (480 - textures[i].height);
+ // Add to the circular buffer
+ buffer_add_element(buf, &textures[i], x, y);
+ }
+ }
+ BeginDrawing();
+ // We loop like this so it draws from oldest entry to newest entry.
+ for (int i = buf->at, first = 1; first == 1 || i != buf->at; first = 0, i = (i + 1) % buf->len) {
+ if (buf->scr[i].elem != NULL) {
+ DrawTexture(*buf->scr[i].elem, buf->scr[i].x, buf->scr[i].y, WHITE);
+ }
+ }
+ EndDrawing();
+
+ // Check the inputs for an exit combination of ABXYStart on every controller port
+ // A more complicated program would likely want to decouple input checks from framerate,
+ // which this example accomplishes by putting the input check in the same loop as drawing.
+ for (int i = 0; i < 4; ++i) {
+ // Assuming gamepad 0 is the primary controller
+ if(IsGamepadAvailable(i)){
+ int a_pressed = IsGamepadButtonDown(i, GAMEPAD_BUTTON_RIGHT_FACE_DOWN);
+ int b_pressed = IsGamepadButtonDown(i, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT);
+ int x_pressed = IsGamepadButtonDown(i, GAMEPAD_BUTTON_RIGHT_FACE_LEFT);
+ int y_pressed = IsGamepadButtonDown(i, GAMEPAD_BUTTON_RIGHT_FACE_UP);
+ int start_pressed = IsGamepadButtonDown(i, GAMEPAD_BUTTON_MIDDLE_RIGHT);
+
+ // Now we do the check. We don't really care what controller presses the combo,
+ // only that some controller presses the combo.
+ if (a_pressed && b_pressed && x_pressed && y_pressed && start_pressed) {
+ // I think this directly closes the window, which should escape the loop
+ CloseWindow();
+ }
+ }
+ }
+ }
+
+ // Cleanup. Even thought we shouldn't reach here under normal circumstances.
+ buffer_cleanup(buf);
+ for (int i = texture_len; i--;) {
+ UnloadTexture(textures[i]);
+ }
+ CloseWindow();
+
+ return 0;
+}
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-03-04 02:21:50
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 8b8df3d67a642dd9fc716b80864226f3bf20da50 (commit)
from 73f25c951ebf75b20e93c0e08bc62287cc93ac93 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8b8df3d67a642dd9fc716b80864226f3bf20da50
Author: Paul Cercueil <pa...@cr...>
Date: Sun Mar 1 00:31:53 2026 +0100
net: Fix checksum, part 3
The code was breaking aliasing rules when called from
net_ipv4_checksum_pseudo(), as the struct address was indirectly casted
to a uint16_t pointer, causing GCC to not bother emit the proper code
for the undefined behaviour.
Address this issue by using a locally defined uint16_t type that is
allowed to alias.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
kernel/net/net_ipv4.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/kernel/net/net_ipv4.c b/kernel/net/net_ipv4.c
index cf3f3530..6b803236 100644
--- a/kernel/net/net_ipv4.c
+++ b/kernel/net/net_ipv4.c
@@ -35,6 +35,8 @@ static inline uint16_t checksum_one(uint16_t val, uint16_t sum) {
/* Perform an IP-style checksum on a block of data */
uint16_t __pure net_ipv4_checksum(const uint8_t *data, size_t bytes, uint16_t sum) {
+ typedef uint16_t __attribute__((may_alias)) alias_u16_t;
+
/* Make sure we don't do any unaligned memory accesses */
if((uintptr_t)data & 1) {
sum = checksum_one(*data, sum);
@@ -44,7 +46,7 @@ uint16_t __pure net_ipv4_checksum(const uint8_t *data, size_t bytes, uint16_t su
/* Compute checksum two bytes at a time */
for(; bytes > 1; bytes -= 2, data += 2)
- sum = checksum_one(*(const uint16_t *)data, sum);
+ sum = checksum_one(*(const alias_u16_t *)data, sum);
/* Handle the last byte, if we have an odd byte count */
if(bytes)
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|
|
From: kosmirror <kos...@us...> - 2026-02-27 15:02:49
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via 73f25c951ebf75b20e93c0e08bc62287cc93ac93 (commit)
from ac2e539a5b41f7bac4ebffa9bf70d31be0dbe96c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 73f25c951ebf75b20e93c0e08bc62287cc93ac93
Author: Falco Girgis <gyr...@gm...>
Date: Fri Feb 27 08:43:18 2026 -0600
Optimized pvr_pack_bump() redundant trigonometry.
Our boy, PH3NOM, correctly pointed out that pvr_pack_bump(), by virtue
of using our inline ASM routines from fmath.h, SEPARATELY for sin +
cosine values, was doing TWO FSCA calls and throwing away a result of
each.
- Changed pvr_pack_bump() to retrieve both sine + cosine simultaneously
from a single fsincos() call.
- Tested with the PVR bump map example which uses it... and... she's
still bumpy!
-----------------------------------------------------------------------
Summary of changes:
kernel/arch/dreamcast/math/fmath.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/kernel/arch/dreamcast/math/fmath.c b/kernel/arch/dreamcast/math/fmath.c
index 471e99e2..b7f00f33 100644
--- a/kernel/arch/dreamcast/math/fmath.c
+++ b/kernel/arch/dreamcast/math/fmath.c
@@ -67,11 +67,15 @@ void fsincosr(float f, float *s, float *c) {
}
uint32_t __pure pvr_pack_bump(float h, float t, float q) {
+ float s, c;
+
+ fsincos(t, &s, &c);
+
uint8_t hp = (uint8_t)(h * 255.0f);
uint8_t k1 = ~hp;
- uint8_t k2 = (uint8_t)(hp * __fsin(t));
- uint8_t k3 = (uint8_t)(hp * __fcos(t));
- uint8_t qp = (uint8_t)((q / (2 * F_PI)) * 255.0f);
+ uint8_t k2 = (uint8_t)(hp * s);
+ uint8_t k3 = (uint8_t)(hp * c);
+ uint8_t qp = (uint8_t)((q / (2.0f * F_PI)) * 255.0f);
return (k1 << 24) | (k2 << 16) | (k3 << 8) | qp;
}
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|