Compare commits

...

23 Commits

Author SHA1 Message Date
Bananymous 3aa20a3a32 Kernel: Fix ACPI _GPE calling
This adds patch adds support for extended GPEs and the second GPE
register block.
2025-08-07 19:35:13 +03:00
Bananymous de7c3d3d29 Kernel: Don't try to create . in USTAR
Our build system adds . entry to the tar archive and it should be
handled as an no-op
2025-08-07 19:35:13 +03:00
Bananymous 3f89df338e IDT: Remove stack OOB check
This makes debugging easier when you can see the actual register values
and what is mapped and where
2025-08-07 19:35:13 +03:00
Bananymous c7f89c9b77 ports: Update SDL2 2.30.11 -> 2.32.8 2025-08-07 16:43:05 +03:00
Bananymous a107e463e8 ports/SDL2: Add audio support 2025-08-07 16:43:05 +03:00
Bananymous 7a5cfe1728 LibAudio/AudioServer: Add support for playing real time audio 2025-08-07 16:43:05 +03:00
Bananymous 7ad3f967db Kernel: Don't stop audio processing after each entry in AC97 2025-08-07 16:43:05 +03:00
Bananymous d1c814cf9d Kernel: Optimize consecutive absolute mouse move events
This is a hack to make window server usable without kvm :D
2025-08-07 16:43:05 +03:00
Bananymous 72f85dce2b Kernel: Make userspace stack on-demand allocated
Also bump the hardlimit of stack size from 512 KiB->32 MiB. This still
feels quite low but is much better than before :D
2025-08-07 16:43:05 +03:00
Bananymous f5bbcc017c Kernel: Only send one smp message when reserving a range
This was causing some kernel panic because processors ran out of smp
message storage when reserving large areas.

Also most of the time there is no need to actually send the SMP message.
If process is mapping something to just its own address space, there is
no need for a TLB shootdown. Maybe this should be only limited to kernel
memory and threads across the same process. I'm not sure what the best
approach here and it is better to send too many invalidations that too
few!
2025-08-07 16:43:05 +03:00
Bananymous 2980173c8e ports: Fix config.sub downloading 2025-08-07 16:28:09 +03:00
Bananymous a84c348045 LibC: Add shm_{open,unlink} stubs
These are needed for our llvm port
2025-08-07 16:28:09 +03:00
Bananymous d845ecc811 LibC: Add wcstok, wcstol and swprintf stubs
These are needed for our python3 port
2025-08-07 16:28:09 +03:00
Bananymous 064d9009a2 LibC: Add clock_getres stub
This is needed for our python3 port
2025-08-07 02:50:24 +03:00
Bananymous b6aa5bdfab LibC: Implement if_indextoname and if_nametoindex
These are needed for our cmake port
2025-08-07 02:50:24 +03:00
Bananymous a3bdf0456e LibC: Add getpriority stub
This is needed for our cmake port
2025-08-07 02:50:24 +03:00
Bananymous e3ecf05866 LibC: Add stubs for {get,free}ifaddrs
These are needed for our libuv port
2025-08-07 02:50:24 +03:00
Bananymous 6240374dd1 LibC: Add semaphore stubs
These are needed for our bochs port
2025-08-07 02:50:24 +03:00
Bananymous e17ee831a7 LibC: Add times stub
This is needed for our openssl port
2025-08-07 02:50:24 +03:00
Bananymous aef9bd6357 LibC: Add mk{nod,fifo}{,at} stubs
These are needed for our tcl port
2025-08-07 02:50:24 +03:00
Bananymous 8857227a35 LibC: Add getservbyname stub
This is needed by our tcl port
2025-08-07 02:50:24 +03:00
Bananymous 937250c681 userspace: Add dummy libdl
This allows ports to link against without needing to patch it out
2025-08-07 02:50:24 +03:00
Bananymous 66d3a1d025 ls: Output in columns 2025-08-07 02:50:24 +03:00
36 changed files with 977 additions and 229 deletions

View File

@ -497,13 +497,13 @@ namespace Kernel
return true;
}
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
{
SpinLockGuard _(m_lock);
ASSERT(vaddr % PAGE_SIZE == 0);
if (only_free && !is_page_free(vaddr))
return false;
map_page_at(0, vaddr, Flags::Reserved);
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
return true;
}
@ -517,7 +517,14 @@ namespace Kernel
if (only_free && !is_range_free(vaddr, bytes))
return false;
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
reserve_page(vaddr + offset);
reserve_page(vaddr + offset, true, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = bytes / PAGE_SIZE,
}
});
return true;
}

View File

@ -814,13 +814,13 @@ namespace Kernel
return page_data & s_page_addr_mask;
}
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
{
SpinLockGuard _(m_lock);
ASSERT(vaddr % PAGE_SIZE == 0);
if (only_free && !is_page_free(vaddr))
return false;
map_page_at(0, vaddr, Flags::Reserved);
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
return true;
}
@ -834,7 +834,14 @@ namespace Kernel
if (only_free && !is_range_free(vaddr, bytes))
return false;
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
reserve_page(vaddr + offset);
reserve_page(vaddr + offset, true, false);
Processor::broadcast_smp_message({
.type = Processor::SMPMessage::Type::FlushTLB,
.flush_tlb = {
.vaddr = vaddr,
.page_count = bytes / PAGE_SIZE,
}
});
return true;
}

View File

@ -28,7 +28,7 @@ namespace Kernel
BAN::ErrorOr<void> initialize_bld();
BAN::ErrorOr<void> initialize_interrupts();
void queue_samples_to_bld();
bool queue_samples_to_bld();
private:
static constexpr size_t m_bdl_entries = 32;

View File

@ -112,7 +112,7 @@ namespace Kernel
bool is_page_free(vaddr_t) const;
bool is_range_free(vaddr_t, size_t bytes) const;
bool reserve_page(vaddr_t, bool only_free = true);
bool reserve_page(vaddr_t, bool only_free = true, bool send_smp_message = true);
bool reserve_range(vaddr_t, size_t bytes, bool only_free = true);
vaddr_t reserve_free_page(vaddr_t first_address, vaddr_t last_address = UINTPTR_MAX);

View File

@ -35,7 +35,9 @@ namespace Kernel
// FIXME: kernel stack does NOT have to be this big, but my recursive AML interpreter
// stack overflows on some machines with 8 page stack
static constexpr size_t kernel_stack_size { PAGE_SIZE * 16 };
static constexpr size_t userspace_stack_size { PAGE_SIZE * 128 };
// TODO: userspace stack is hard limited to 32 MiB, maybe make this dynamic?
static constexpr size_t userspace_stack_size { 32 << 20 };
public:
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*);

View File

@ -927,42 +927,79 @@ acpi_release_global_lock:
return 0;
};
#define FIND_GPE(idx) \
BAN::Optional<GAS> gpe##idx; \
{ \
const uint8_t null[sizeof(GAS)] {}; \
if (fadt().length > offsetof(FADT, x_gpe##idx##_blk) \
&& memcmp(fadt().x_gpe##idx##_blk, null, sizeof(GAS)) == 0) { \
auto gas = *reinterpret_cast<GAS*>(fadt().x_gpe##idx##_blk); \
if (!gas.read().is_error()) \
gpe0 = gas; \
} \
\
if (!gpe##idx.has_value() && fadt().gpe##idx##_blk) { \
gpe##idx = GAS { \
.address_space_id = GAS::AddressSpaceID::SystemIO, \
.register_bit_width = 8, \
.register_bit_offset = 0, \
.access_size = 1, \
.address = fadt().gpe##idx##_blk, \
}; \
} \
}
FIND_GPE(0);
FIND_GPE(1);
while (true)
{
uint16_t sts_port;
uint16_t pending;
sts_port = fadt().pm1a_evt_blk;
if (pending = get_fixed_event(sts_port); pending)
goto handle_event;
sts_port = fadt().pm1b_evt_blk;
if (pending = get_fixed_event(sts_port); pending)
goto handle_event;
const auto read_gpe = [this](GAS gpe, uint8_t gpe_blk_len, uint32_t base) -> bool {
for (uint8_t i = 0; i < gpe_blk_len / 2; i++)
{
bool handled_event = false;
uint8_t gpe0_bytes = fadt().gpe0_blk_len / 2;
for (uint8_t i = 0; i < gpe0_bytes; i++)
{
uint8_t sts = IO::inb(fadt().gpe0_blk + i);
uint8_t en = IO::inb(fadt().gpe0_blk + gpe0_bytes + i);
pending = sts & en;
auto status = ({ auto tmp = gpe; tmp.address += i; tmp; });
auto enabled = ({ auto tmp = gpe; tmp.address += (gpe_blk_len / 2) + i; tmp; });
const uint8_t pending = MUST(status.read()) & MUST(enabled.read());
if (pending == 0)
continue;
auto index = i * 8 + (pending & ~(pending - 1));
if (m_gpe_methods[index])
if (auto ret = AML::method_call(m_gpe_scope, m_gpe_methods[index]->node, BAN::Array<AML::Reference*, 7>{}); ret.is_error())
dwarnln("Failed to evaluate _GPE {}: ", index, ret.error());
handled_event = true;
IO::outb(fadt().gpe0_blk + i, 1 << index);
}
if (handled_event)
for (size_t bit = 0; bit < 8; bit++)
{
if (!(pending & (1 << bit)))
continue;
const auto index = base + i * 8 + bit;
if (auto* method = m_gpe_methods[index]; method == nullptr)
dwarnln("No handler for _GPE {}", index);
else if (auto ret = AML::method_call(m_gpe_scope, method->node, BAN::Array<AML::Reference*, 7>{}); ret.is_error())
dwarnln("Failed to evaluate _GPE {}: ", index, ret.error());
else
dprintln("handled _GPE {}", index);
}
MUST(status.write(pending));
return true;
}
return false;
};
sts_port = fadt().pm1a_evt_blk;
if ((pending = get_fixed_event(sts_port)))
goto handle_event;
sts_port = fadt().pm1b_evt_blk;
if ((pending = get_fixed_event(sts_port)))
goto handle_event;
if (gpe0.has_value() && read_gpe(gpe0.value(), fadt().gpe0_blk_len, 0))
continue;
if (gpe1.has_value() && read_gpe(gpe1.value(), fadt().gpe1_blk_len, fadt().gpe1_base))
continue;
// FIXME: this can cause missing of event if it happens between
// reading the status and blocking

View File

@ -185,14 +185,10 @@ namespace Kernel
void AC97AudioController::handle_new_data()
{
ASSERT(m_spinlock.current_processor_has_lock());
if (m_bdl_head != m_bdl_tail)
return;
queue_samples_to_bld();
}
void AC97AudioController::queue_samples_to_bld()
bool AC97AudioController::queue_samples_to_bld()
{
ASSERT(m_spinlock.current_processor_has_lock());
@ -228,7 +224,7 @@ namespace Kernel
// if head was not updated, no data was queued
if (lvi == m_bdl_head)
return;
return false;
m_sample_data_blocker.unblock();
@ -238,6 +234,8 @@ namespace Kernel
const uint8_t control = m_bus_master->read8(BusMasterRegister::PO_CR);
if (!(control & RDBM))
m_bus_master->write8(BusMasterRegister::PO_CR, control | RDBM);
return true;
}
void AC97AudioController::handle_irq()
@ -249,17 +247,18 @@ namespace Kernel
SpinLockGuard _(m_spinlock);
if (status & LVBCI)
bool did_enqueue = false;
if (status & BCIS)
{
m_bdl_tail = (m_bdl_tail + 1) % m_bdl_entries;
did_enqueue = queue_samples_to_bld();
}
if ((status & LVBCI) && !did_enqueue)
{
const uint8_t control = m_bus_master->read8(BusMasterRegister::PO_CR);
m_bus_master->write8(BusMasterRegister::PO_CR, control & ~RDBM);
}
if (status & BCIS)
{
m_bdl_tail = (m_bdl_tail + 1) % m_bdl_entries;
queue_samples_to_bld();
}
}
}

View File

@ -109,7 +109,9 @@ namespace Kernel
if (file_type == DIRTYPE)
{
if (auto ret = parent_inode->create_directory(file_name_sv, file_mode, file_uid, file_gid); ret.is_error())
if (file_name_sv == "."_sv)
; // NOTE: don't create "." (root)
else if (auto ret = parent_inode->create_directory(file_name_sv, file_mode, file_uid, file_gid); ret.is_error())
dwarnln("failed to create directory '{}': {}", file_name_sv, ret.error());
}
else if (file_type == LNKTYPE)

View File

@ -207,26 +207,6 @@ namespace Kernel
goto done;
}
}
// Check if stack is OOB
if (ARCH(i686) && !GDT::is_user_segment(interrupt_stack->cs))
; // 32 bit does not push stack pointer when no CPL change happens
else if (thread.userspace_stack_bottom() < interrupt_stack->sp && interrupt_stack->sp <= thread.userspace_stack_top())
; // using userspace stack
else if (thread.kernel_stack_bottom() < interrupt_stack->sp && interrupt_stack->sp <= thread.kernel_stack_top())
; // using kernel stack
else
{
derrorln("Stack pointer out of bounds!");
derrorln("rip {H}", interrupt_stack->ip);
derrorln("rsp {H}, userspace stack {H}->{H}, kernel stack {H}->{H}",
interrupt_stack->sp,
thread.userspace_stack_bottom(), thread.userspace_stack_top(),
thread.kernel_stack_bottom(), thread.kernel_stack_top()
);
Thread::current().handle_signal(SIGKILL);
goto done;
}
}
}

View File

@ -102,6 +102,12 @@ namespace Kernel
last_event.move_event.rel_y += curr_event.move_event.rel_y;
return;
}
if (last_event.type == LibInput::MouseEventType::MouseMoveAbsEvent && curr_event.type == LibInput::MouseEventType::MouseMoveAbsEvent)
{
last_event.move_abs_event.abs_x = curr_event.move_abs_event.abs_x;
last_event.move_abs_event.abs_y = curr_event.move_abs_event.abs_y;
return;
}
if (last_event.type == LibInput::MouseEventType::MouseScrollEvent && curr_event.type == LibInput::MouseEventType::MouseScrollEvent)
{
last_event.scroll_event.scroll += curr_event.scroll_event.scroll;

View File

@ -143,7 +143,7 @@ namespace Kernel
BAN::ErrorOr<bool> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
{
ASSERT(contains(vaddr));
ASSERT(&PageTable::current() == &m_page_table);
vaddr &= PAGE_ADDR_MASK;
if (m_preallocated)
return false;
@ -158,8 +158,11 @@ namespace Kernel
if (m_paddrs[index] == 0)
return BAN::Error::from_errno(ENOMEM);
PageTable::with_fast_page(m_paddrs[index], []{
memset(PageTable::fast_page_as_ptr(), 0x00, PAGE_SIZE);
});
m_page_table.map_page_at(m_paddrs[index], vaddr, m_flags);
memset(reinterpret_cast<void*>(vaddr), 0, PAGE_SIZE);
return true;
}

View File

@ -138,7 +138,7 @@ namespace Kernel
stack_addr_start, USERSPACE_END,
userspace_stack_size,
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, true
false, true
));
thread_deleter.disable();
@ -217,6 +217,7 @@ namespace Kernel
save_sse();
memcpy(thread->m_sse_storage, m_sse_storage, sizeof(m_sse_storage));
TRY(thread->userspace_stack().allocate_page_for_demand_paging(thread->userspace_stack_top() - PAGE_SIZE));
PageTable::with_fast_page(thread->userspace_stack().paddr_of(thread->userspace_stack_top() - PAGE_SIZE), [=] {
PageTable::fast_page_as<void*>(PAGE_SIZE - sizeof(uintptr_t)) = arg;
});
@ -299,6 +300,10 @@ namespace Kernel
vaddr_t vaddr = userspace_stack_top() - needed_size;
const size_t page_count = BAN::Math::div_round_up(needed_size, PAGE_SIZE);
for (size_t i = 0; i < page_count; i++)
TRY(m_userspace_stack->allocate_page_for_demand_paging(vaddr + i * PAGE_SIZE));
const auto stack_copy_buf =
[this](BAN::ConstByteSpan buffer, vaddr_t vaddr) -> void
{

View File

@ -1,25 +1,22 @@
#!/bin/bash ../install.sh
NAME='SDL2'
VERSION='2.30.11'
DOWNLOAD_URL="https://github.com/libsdl-org/SDL/archive/refs/tags/release-$VERSION.tar.gz#cc6136dd964854e8846c679703322f3e2a341d27a06a53f8b3f642c26f1b0cfd"
TAR_CONTENT="SDL-release-$VERSION"
VERSION='2.32.8'
DOWNLOAD_URL="https://github.com/libsdl-org/SDL/releases/download/release-$VERSION/SDL2-$VERSION.tar.gz#0ca83e9c9b31e18288c7ec811108e58bac1f1bb5ec6577ad386830eac51c787e"
DEPENDENCIES=('mesa')
configure() {
$BANAN_CMAKE \
$BANAN_CMAKE --fresh -S . -B build -G Ninja \
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
--fresh -GNinja -S . -B build \
-DCMAKE_INSTALL_PREFIX='/usr' \
-DCMAKE_BUILD_TYPE=Release \
-DBANAN_OS=true \
-DUNIX=true \
-DSDL_LIBSAMPLERATE=OFF \
-DSDL_PTHREADS_SEM=OFF
-DSDL_PTHREADS_SEM=OFF \
|| exit 1
}
build() {
$BANAN_CMAKE --build build --config Release || exit 1
$BANAN_CMAKE --build build || exit 1
}
install() {

View File

@ -1,7 +1,28 @@
diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.txt
--- SDL-release-2.30.11/CMakeLists.txt 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.30.11-banan_os/CMakeLists.txt 2025-08-03 14:04:09.894244781 +0300
@@ -1452,7 +1452,7 @@
diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake
--- SDL2-2.32.8/cmake/sdlplatform.cmake 2024-08-14 13:35:43.000000000 +0300
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2025-08-06 02:07:18.347821313 +0300
@@ -28,6 +28,8 @@
set(SDL_CMAKE_PLATFORM AIX)
elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
set(SDL_CMAKE_PLATFORM MINIX)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "banan-os")
+ set(SDL_CMAKE_PLATFORM BANAN_OS)
elseif(CMAKE_SYSTEM_NAME MATCHES "QNX")
set(SDL_CMAKE_PLATFORM QNX)
endif()
diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
--- SDL2-2.32.8/CMakeLists.txt 2025-06-03 02:00:39.000000000 +0300
+++ SDL2-2.32.8-banan_os/CMakeLists.txt 2025-08-06 02:19:44.864415796 +0300
@@ -14,7 +14,7 @@
set(SDL2_SUBPROJECT ON)
endif()
-if (HAIKU)
+if (HAIKU OR BANAN_OS)
enable_language(CXX)
set(LINKER_LANGUAGE CXX)
endif()
@@ -1462,7 +1462,7 @@
CheckPTHREAD()
CheckLibUnwind()
@ -10,7 +31,7 @@ diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.tx
if(SDL_AUDIO)
if(SYSV5 OR SOLARIS OR HPUX)
set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
@@ -2422,6 +2422,49 @@
@@ -2459,6 +2459,57 @@
CheckPTHREAD()
list(APPEND EXTRA_LIBS root be media game device textencoding)
@ -21,8 +42,16 @@ diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.tx
+ set(HAVE_SDL_MISC TRUE)
+ endif()
+
+ if(SDL_AUDIO)
+ set(SDL_AUDIO_DRIVER_BANANOS 1)
+ file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/banan_os/*.cpp)
+ list(APPEND SOURCE_FILES ${AUDIO_SOURCES})
+ set(HAVE_SDL_AUDIO TRUE)
+ list(APPEND EXTRA_LIBS audio)
+ endif()
+
+ if(SDL_VIDEO)
+ set(SDL_VIDEO_DRIVER_BANAN_OS 1)
+ set(SDL_VIDEO_DRIVER_BANANOS 1)
+ file(GLOB VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/banan_os/*.cpp)
+ list(APPEND SOURCE_FILES ${VIDEO_SOURCES})
+ set(HAVE_SDL_VIDEO TRUE)
@ -30,7 +59,7 @@ diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.tx
+
+ if(SDL_OPENGL)
+ set(SDL_VIDEO_OPENGL 1)
+ set(SDL_VIDEO_OPENGL_BANAN_OS 1)
+ set(SDL_VIDEO_OPENGL_BANANOS 1)
+ set(SDL_VIDEO_RENDER_OGL 1)
+ list(APPEND EXTRA_LIBS OSMesa)
+ set(HAVE_OPENGL TRUE)
@ -60,20 +89,28 @@ diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.tx
elseif(RISCOS)
if(SDL_MISC)
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL2-2.30.11-banan_os/include/SDL_config.h.cmake
--- SDL-release-2.30.11/include/SDL_config.h.cmake 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.30.11-banan_os/include/SDL_config.h.cmake 2025-08-03 14:04:09.894803585 +0300
@@ -406,6 +406,7 @@
diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SDL_config.h.cmake
--- SDL2-2.32.8/include/SDL_config.h.cmake 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2025-08-06 02:01:21.085539504 +0300
@@ -307,6 +307,7 @@
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_HAIKU @SDL_AUDIO_DRIVER_HAIKU@
+#cmakedefine SDL_AUDIO_DRIVER_BANANOS @SDL_AUDIO_DRIVER_BANANOS@
#cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@
#cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@
@@ -406,6 +407,7 @@
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
+#cmakedefine SDL_VIDEO_DRIVER_BANAN_OS @SDL_VIDEO_DRIVER_BANAN_OS@
+#cmakedefine SDL_VIDEO_DRIVER_BANANOS @SDL_VIDEO_DRIVER_BANANOS@
#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
#cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL2-2.30.11-banan_os/include/SDL_platform.h
--- SDL-release-2.30.11/include/SDL_platform.h 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.30.11-banan_os/include/SDL_platform.h 2025-08-03 14:04:09.895022748 +0300
diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_platform.h
--- SDL2-2.32.8/include/SDL_platform.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2025-08-06 02:01:21.085701327 +0300
@@ -36,6 +36,10 @@
#undef __HAIKU__
#define __HAIKU__ 1
@ -85,9 +122,225 @@ diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL2-2.30.11-banan_os/inclu
#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
#undef __BSDI__
#define __BSDI__ 1
diff -ruN SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp
--- SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-08-03 14:04:09.895198889 +0300
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2025-08-06 02:01:21.085876490 +0300
@@ -0,0 +1,150 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_AUDIO_DRIVER_BANANOS
+
+extern "C" {
+#include "SDL_audio.h"
+#include "../SDL_audio_c.h"
+#include "../SDL_sysaudio.h"
+}
+
+#include "SDL_banan_os_audio.h"
+
+#include <unistd.h>
+
+#define DUMP_FUNCTIONS 0
+
+#if DUMP_FUNCTIONS
+# define DUMP_FUNCTION() dprintln(__FUNCTION__)
+#else
+# define DUMP_FUNCTION()
+#endif
+
+static void BANANOS_CloseDevice(_THIS)
+{
+ DUMP_FUNCTION();
+
+ if (!_this->hidden)
+ return;
+
+ if (_this->hidden->mixbuf)
+ SDL_free(_this->hidden->mixbuf);
+
+ delete _this->hidden;
+}
+
+static int BANANOS_OpenDevice(_THIS, char const*)
+{
+ DUMP_FUNCTION();
+
+ // TODO: try to accept already existing spec
+ _this->spec.freq = 44100;
+ _this->spec.format = AUDIO_S16LSB;
+ _this->spec.channels = 2;
+ _this->spec.samples = 2048;
+ SDL_CalculateAudioSpec(&_this->spec);
+
+ auto audio_or_error = LibAudio::Audio::create(_this->spec.channels, _this->spec.freq, 0x1000);
+ if (audio_or_error.is_error())
+ return SDL_SetError("failed to create audio device: %s", audio_or_error.error().get_message());
+
+ void* mixbuf = SDL_malloc(_this->spec.size);
+ if (mixbuf == nullptr)
+ return SDL_OutOfMemory();
+
+ _this->hidden = new SDL_PrivateAudioData(audio_or_error.release_value(), mixbuf);
+ if (!_this->hidden)
+ return SDL_OutOfMemory();
+ MUST(_this->hidden->audio.start());
+
+ return 0;
+}
+
+static void BANANOS_PlayDevice(_THIS)
+{
+ DUMP_FUNCTION();
+
+ const bool should_play = SDL_AtomicGet(&_this->enabled) && !SDL_AtomicGet(&_this->paused);
+ _this->hidden->audio.set_paused(!should_play);
+ if (!should_play)
+ {
+ usleep(100);
+ return;
+ }
+
+ static_assert(BAN::is_same_v<LibAudio::AudioBuffer::sample_t, double>);
+
+ const auto convert_sample = [](int16_t input) {
+ return (static_cast<double>(input) - BAN::numeric_limits<int16_t>::min()) / BAN::numeric_limits<int16_t>::max() * 2.0 - 1.0;
+ };
+
+ const size_t input_samples = _this->spec.size / sizeof(int16_t);
+ size_t samples_queued = 0;
+
+ const int16_t* mixbuf = static_cast<const int16_t*>(_this->hidden->mixbuf);
+ while (samples_queued < input_samples)
+ {
+ const size_t to_convert = BAN::Math::min(_this->hidden->conversion.size(), input_samples - samples_queued);
+ for (size_t i = 0; i < to_convert; i++)
+ _this->hidden->conversion[i] = convert_sample(mixbuf[samples_queued + i]);
+
+ auto sample_span = _this->hidden->conversion.span();
+ while (!sample_span.empty())
+ {
+ const size_t queued = _this->hidden->audio.queue_samples(sample_span);
+ if (queued == 0)
+ usleep(100);
+ sample_span = sample_span.slice(queued);
+ }
+
+ samples_queued += to_convert;
+ }
+}
+
+static Uint8* BANANOS_GetDeviceBuf(_THIS)
+{
+ DUMP_FUNCTION();
+
+ return static_cast<Uint8*>(_this->hidden->mixbuf);
+}
+
+static SDL_bool BANANOS_Init(SDL_AudioDriverImpl* impl)
+{
+ impl->OpenDevice = BANANOS_OpenDevice;
+ impl->CloseDevice = BANANOS_CloseDevice;
+ impl->PlayDevice = BANANOS_PlayDevice;
+ impl->GetDeviceBuf = BANANOS_GetDeviceBuf;
+
+ impl->ProvidesOwnCallbackThread = SDL_FALSE;
+ impl->HasCaptureSupport = SDL_FALSE;
+ impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
+ impl->SupportsNonPow2Samples = SDL_TRUE;
+
+ return SDL_TRUE;
+}
+
+AudioBootStrap BANANOSAUDIO_bootstrap = {
+ "banan-os", "banan-os AudioServer", BANANOS_Init, SDL_FALSE
+};
+
+#endif
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2025-08-06 02:01:21.085937043 +0300
@@ -0,0 +1,34 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#pragma once
+
+#include <LibAudio/Audio.h>
+#include <BAN/Array.h>
+
+#define _THIS SDL_AudioDevice* _this
+
+struct SDL_PrivateAudioData {
+ LibAudio::Audio audio;
+ void* mixbuf { nullptr };
+ BAN::Array<LibAudio::AudioBuffer::sample_t, 4096> conversion;
+};
diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_audio.c
--- SDL2-2.32.8/src/audio/SDL_audio.c 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2025-08-06 02:01:21.086082872 +0300
@@ -87,6 +87,9 @@
#ifdef SDL_AUDIO_DRIVER_HAIKU
&HAIKUAUDIO_bootstrap,
#endif
+#ifdef SDL_AUDIO_DRIVER_BANANOS
+ &BANANOSAUDIO_bootstrap,
+#endif
#ifdef SDL_AUDIO_DRIVER_COREAUDIO
&COREAUDIO_bootstrap,
#endif
diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h
--- SDL2-2.32.8/src/audio/SDL_sysaudio.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2025-08-06 02:01:21.086309718 +0300
@@ -196,6 +196,7 @@
extern AudioBootStrap WINMM_bootstrap;
extern AudioBootStrap PAUDIO_bootstrap;
extern AudioBootStrap HAIKUAUDIO_bootstrap;
+extern AudioBootStrap BANANOSAUDIO_bootstrap;
extern AudioBootStrap COREAUDIO_bootstrap;
extern AudioBootStrap DISKAUDIO_bootstrap;
extern AudioBootStrap DUMMYAUDIO_bootstrap;
diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp
--- SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-08-06 02:01:21.086457363 +0300
@@ -0,0 +1,30 @@
+/*
+ Simple DirectMedia Layer
@ -119,9 +372,9 @@ diff -ruN SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.30.11-bana
+
+/* vi: set ts=4 sw=4 expandtab: */
+
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-03 14:04:09.895299391 +0300
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-06 02:01:21.086557935 +0300
@@ -0,0 +1,60 @@
+/*
+ Simple DirectMedia Layer
@ -147,7 +400,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SD
+
+#include "../../SDL_internal.h"
+
+#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+#ifdef SDL_VIDEO_DRIVER_BANANOS
+
+#include "SDL_messagebox.h"
+
@ -156,7 +409,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SD
+#include <BAN/Debug.h>
+#include <LibGUI/MessageBox.h>
+
+int BANAN_OS_ShowMessageBox(const SDL_MessageBoxData* messageboxdata, int* buttonid)
+int BANANOS_ShowMessageBox(const SDL_MessageBoxData* messageboxdata, int* buttonid)
+{
+ BAN::Vector<BAN::StringView> buttons;
+ for (int i = 0; i < messageboxdata->numbuttons; i++) {
@ -180,12 +433,12 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SD
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
+#endif /* SDL_VIDEO_DRIVER_BANANOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-03 14:04:09.895347931 +0300
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-06 02:01:21.086603053 +0300
@@ -0,0 +1,45 @@
+/*
+ Simple DirectMedia Layer
@ -209,33 +462,33 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h SDL2
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_BANAN_OS_MESSAGEBOX_H
+#define SDL_BANAN_OS_MESSAGEBOX_H
+#ifndef SDL_BANANOS_MESSAGEBOX_H
+#define SDL_BANANOS_MESSAGEBOX_H
+
+#include "../../SDL_internal.h"
+
+#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+#ifdef SDL_VIDEO_DRIVER_BANANOS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int
+BANAN_OS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+BANANOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SDL_BANAN_OS_MESSAGEBOX_H */
+#endif /* SDL_BANANOS_MESSAGEBOX_H */
+
+#endif
+
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-08-04 14:57:50.844360579 +0300
@@ -0,0 +1,719 @@
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-08-06 02:01:21.086666679 +0300
@@ -0,0 +1,718 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
@ -256,10 +509,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+#ifdef SDL_VIDEO_DRIVER_BANANOS
+
+extern "C" {
+#include "../SDL_sysvideo.h"
@ -422,7 +674,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+};
+static Keymap s_keymap;
+
+static int BANAN_OS_mouse_button_to_sdl(LibInput::MouseButton button)
+static int BANANOS_mouse_button_to_sdl(LibInput::MouseButton button)
+{
+ switch (button) {
+#define BUTTON_CASE(my, sdl) case LibInput::MouseButton::my: return SDL_BUTTON_##sdl
@ -438,7 +690,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+
+static SDL_VideoDevice* s_video_device = nullptr;
+
+static SDL_Cursor* BANAN_OS_CreateSystemCursor(SDL_SystemCursor id)
+static SDL_Cursor* BANANOS_CreateSystemCursor(SDL_SystemCursor id)
+{
+ DUMP_FUNCTION();
+
@ -453,7 +705,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return cursor;
+}
+
+static void BANAN_OS_FreeCursor(SDL_Cursor* cursor)
+static void BANANOS_FreeCursor(SDL_Cursor* cursor)
+{
+ DUMP_FUNCTION();
+
@ -461,7 +713,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ SDL_free(cursor);
+}
+
+static int BANAN_OS_ShowCursor(SDL_Cursor* cursor)
+static int BANANOS_ShowCursor(SDL_Cursor* cursor)
+{
+ DUMP_FUNCTION();
+
@ -475,7 +727,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static int BANAN_OS_SetRelativeMouseMode(SDL_bool enabled)
+static int BANANOS_SetRelativeMouseMode(SDL_bool enabled)
+{
+ DUMP_FUNCTION();
+
@ -490,24 +742,24 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static void BANAN_OS_InitMouse(_THIS)
+static void BANANOS_InitMouse(_THIS)
+{
+ DUMP_FUNCTION();
+
+ auto* mouse = SDL_GetMouse();
+ mouse->ShowCursor = BANAN_OS_ShowCursor;
+ mouse->SetRelativeMouseMode = BANAN_OS_SetRelativeMouseMode;
+ mouse->CreateSystemCursor = BANAN_OS_CreateSystemCursor;
+ mouse->FreeCursor = BANAN_OS_FreeCursor;
+ mouse->ShowCursor = BANANOS_ShowCursor;
+ mouse->SetRelativeMouseMode = BANANOS_SetRelativeMouseMode;
+ mouse->CreateSystemCursor = BANANOS_CreateSystemCursor;
+ mouse->FreeCursor = BANANOS_FreeCursor;
+
+ SDL_SetDefaultCursor(BANAN_OS_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
+ SDL_SetDefaultCursor(BANANOS_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
+}
+
+static int BANAN_OS_VideoInit(_THIS)
+static int BANANOS_VideoInit(_THIS)
+{
+ DUMP_FUNCTION();
+
+ BANAN_OS_InitMouse(_this);
+ BANANOS_InitMouse(_this);
+
+ int fb_fd = open("/dev/fb0", O_RDONLY);
+ if (fb_fd == -1) {
@ -543,7 +795,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static void BANAN_OS_VideoQuit(_THIS)
+static void BANANOS_VideoQuit(_THIS)
+{
+ DUMP_FUNCTION();
+
@ -551,14 +803,14 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ s_video_device = nullptr;
+}
+
+static void BANAN_OS_free(_THIS)
+static void BANANOS_free(_THIS)
+{
+ DUMP_FUNCTION();
+ delete static_cast<banan_os_video_device_data*>(_this->driverdata);
+ SDL_free(_this);
+}
+
+static int BANAN_OS_CreateSDLWindow(_THIS, SDL_Window* window)
+static int BANANOS_CreateSDLWindow(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -600,7 +852,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ [window, ban_window](LibGUI::EventPacket::MouseButtonEvent::event_t event) {
+ const int state = event.pressed ? SDL_PRESSED : SDL_RELEASED;
+ SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y);
+ SDL_SendMouseButton(window, 0, state, BANAN_OS_mouse_button_to_sdl(event.button));
+ SDL_SendMouseButton(window, 0, state, BANANOS_mouse_button_to_sdl(event.button));
+ }
+ );
+
@ -651,7 +903,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static void BANAN_OS_DestroyWindow(_THIS, SDL_Window* window)
+static void BANANOS_DestroyWindow(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -667,7 +919,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ window->driverdata = nullptr;
+}
+
+static void BANAN_OS_ShowWindow(_THIS, SDL_Window* window)
+static void BANANOS_ShowWindow(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -681,7 +933,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_attributes(attributes);
+}
+
+static void BANAN_OS_HideWindow(_THIS, SDL_Window* window)
+static void BANANOS_HideWindow(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -695,7 +947,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_attributes(attributes);
+}
+
+static void BANAN_OS_SetWindowTitle(_THIS, SDL_Window* window)
+static void BANANOS_SetWindowTitle(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -703,7 +955,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_title(window->title);
+}
+
+static void BANAN_OS_SetWindowPosition(_THIS, SDL_Window* window)
+static void BANANOS_SetWindowPosition(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -711,7 +963,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_position(window->x, window->y);
+}
+
+static void BANAN_OS_SetWindowSize(_THIS, SDL_Window* window)
+static void BANANOS_SetWindowSize(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -719,7 +971,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->request_resize(window->w, window->h);
+}
+
+static void BANAN_OS_SetWindowMinimumSize(_THIS, SDL_Window* window)
+static void BANANOS_SetWindowMinimumSize(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -727,7 +979,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_min_size(window->min_w, window->min_h);
+}
+
+static void BANAN_OS_SetWindowMaximumSize(_THIS, SDL_Window* window)
+static void BANANOS_SetWindowMaximumSize(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -735,12 +987,12 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_max_size(window->min_w, window->min_h);
+}
+
+static void BANAN_OS_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
+static void BANANOS_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
+{
+ DUMP_FUNCTION();
+}
+
+static void BANAN_OS_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+static void BANANOS_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+ DUMP_FUNCTION();
+
@ -751,7 +1003,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ }
+}
+
+static void BANAN_OS_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+static void BANANOS_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+{
+ DUMP_FUNCTION();
+
@ -759,7 +1011,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ ban_window.window->set_fullscreen(fullscreen);
+}
+
+static int BANAN_OS_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format, void** pixels, int* pitch)
+static int BANANOS_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format, void** pixels, int* pitch)
+{
+ DUMP_FUNCTION();
+
@ -783,7 +1035,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static int BANAN_OS_UpdateWindowFramebuffer(_THIS, SDL_Window* window, const SDL_Rect* rects, int numrects)
+static int BANANOS_UpdateWindowFramebuffer(_THIS, SDL_Window* window, const SDL_Rect* rects, int numrects)
+{
+ DUMP_FUNCTION();
+
@ -795,12 +1047,12 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static void BANAN_OS_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
+static void BANANOS_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+}
+
+static void BANAN_OS_PumpEvents(_THIS)
+static void BANANOS_PumpEvents(_THIS)
+{
+ DUMP_FUNCTION();
+
@ -809,7 +1061,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ window->window->poll_events();
+}
+
+static int BANAN_OS_GL_LoadLibrary(_THIS, const char* path)
+static int BANANOS_GL_LoadLibrary(_THIS, const char* path)
+{
+ DUMP_FUNCTION();
+
@ -822,14 +1074,14 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static void* BANAN_OS_GL_GetProcAddress(_THIS, const char* proc)
+static void* BANANOS_GL_GetProcAddress(_THIS, const char* proc)
+{
+ DUMP_FUNCTION();
+
+ return reinterpret_cast<void*>(OSMesaGetProcAddress(proc));
+}
+
+static SDL_GLContext BANAN_OS_GL_CreateContext(_THIS, SDL_Window* window)
+static SDL_GLContext BANANOS_GL_CreateContext(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -853,7 +1105,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return gl_context;
+}
+
+static void BANAN_OS_GL_DeleteContext(_THIS, SDL_GLContext context)
+static void BANANOS_GL_DeleteContext(_THIS, SDL_GLContext context)
+{
+ DUMP_FUNCTION();
+
@ -861,7 +1113,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ OSMesaDestroyContext(gl_context);
+}
+
+static int BANAN_OS_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context)
+static int BANANOS_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context)
+{
+ DUMP_FUNCTION();
+
@ -880,7 +1132,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static int BANAN_OS_GL_SwapWindow(_THIS, SDL_Window* window)
+static int BANANOS_GL_SwapWindow(_THIS, SDL_Window* window)
+{
+ DUMP_FUNCTION();
+
@ -895,7 +1147,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return 0;
+}
+
+static SDL_VideoDevice* BANAN_OS_CreateDevice(void)
+static SDL_VideoDevice* BANANOS_CreateDevice(void)
+{
+ DUMP_FUNCTION();
+
@ -911,70 +1163,70 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
+ return nullptr;
+ }
+
+ device->VideoInit = BANAN_OS_VideoInit;
+ device->VideoQuit = BANAN_OS_VideoQuit;
+ device->VideoInit = BANANOS_VideoInit;
+ device->VideoQuit = BANANOS_VideoQuit;
+
+ device->CreateSDLWindow = BANAN_OS_CreateSDLWindow;
+ device->DestroyWindow = BANAN_OS_DestroyWindow;
+ device->ShowWindow = BANAN_OS_ShowWindow;
+ device->HideWindow = BANAN_OS_HideWindow;
+ device->CreateSDLWindow = BANANOS_CreateSDLWindow;
+ device->DestroyWindow = BANANOS_DestroyWindow;
+ device->ShowWindow = BANANOS_ShowWindow;
+ device->HideWindow = BANANOS_HideWindow;
+
+ device->SetWindowTitle = BANAN_OS_SetWindowTitle;
+ device->SetWindowPosition = BANAN_OS_SetWindowPosition;
+ device->SetWindowSize = BANAN_OS_SetWindowSize;
+ device->SetWindowMinimumSize = BANAN_OS_SetWindowMinimumSize;
+ device->SetWindowMaximumSize = BANAN_OS_SetWindowMaximumSize;
+ device->SetWindowBordered = BANAN_OS_SetWindowBordered;
+ device->SetWindowResizable = BANAN_OS_SetWindowResizable;
+ device->SetWindowFullscreen = BANAN_OS_SetWindowFullscreen;
+ device->SetWindowTitle = BANANOS_SetWindowTitle;
+ device->SetWindowPosition = BANANOS_SetWindowPosition;
+ device->SetWindowSize = BANANOS_SetWindowSize;
+ device->SetWindowMinimumSize = BANANOS_SetWindowMinimumSize;
+ device->SetWindowMaximumSize = BANANOS_SetWindowMaximumSize;
+ device->SetWindowBordered = BANANOS_SetWindowBordered;
+ device->SetWindowResizable = BANANOS_SetWindowResizable;
+ device->SetWindowFullscreen = BANANOS_SetWindowFullscreen;
+
+ device->CreateWindowFramebuffer = BANAN_OS_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = BANAN_OS_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = BANAN_OS_DestroyWindowFramebuffer;
+ device->CreateWindowFramebuffer = BANANOS_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = BANANOS_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = BANANOS_DestroyWindowFramebuffer;
+
+ device->PumpEvents = BANAN_OS_PumpEvents;
+ device->PumpEvents = BANANOS_PumpEvents;
+
+ device->GL_LoadLibrary = BANAN_OS_GL_LoadLibrary;
+ device->GL_GetProcAddress = BANAN_OS_GL_GetProcAddress;
+ device->GL_CreateContext = BANAN_OS_GL_CreateContext;
+ device->GL_DeleteContext = BANAN_OS_GL_DeleteContext;
+ device->GL_MakeCurrent = BANAN_OS_GL_MakeCurrent;
+ device->GL_SwapWindow = BANAN_OS_GL_SwapWindow;
+ device->GL_LoadLibrary = BANANOS_GL_LoadLibrary;
+ device->GL_GetProcAddress = BANANOS_GL_GetProcAddress;
+ device->GL_CreateContext = BANANOS_GL_CreateContext;
+ device->GL_DeleteContext = BANANOS_GL_DeleteContext;
+ device->GL_MakeCurrent = BANANOS_GL_MakeCurrent;
+ device->GL_SwapWindow = BANANOS_GL_SwapWindow;
+
+ device->free = BANAN_OS_free;
+ device->free = BANANOS_free;
+
+ return device;
+}
+
+VideoBootStrap BANAN_OS_bootstrap = {
+VideoBootStrap BANANOS_bootstrap = {
+ "banan-os", "banan-os graphics",
+ BANAN_OS_CreateDevice,
+ BANAN_OS_ShowMessageBox
+ BANANOS_CreateDevice,
+ BANANOS_ShowMessageBox
+};
+
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
+#endif /* SDL_VIDEO_DRIVER_BANANOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h
--- SDL-release-2.30.11/src/video/SDL_sysvideo.h 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h 2025-08-03 14:04:09.895655165 +0300
diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h
--- SDL2-2.32.8/src/video/SDL_sysvideo.h 2025-05-20 00:24:41.000000000 +0300
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2025-08-06 02:01:21.086873550 +0300
@@ -462,6 +462,7 @@
extern VideoBootStrap WINDOWS_bootstrap;
extern VideoBootStrap WINRT_bootstrap;
extern VideoBootStrap HAIKU_bootstrap;
+extern VideoBootStrap BANAN_OS_bootstrap;
+extern VideoBootStrap BANANOS_bootstrap;
extern VideoBootStrap PND_bootstrap;
extern VideoBootStrap UIKIT_bootstrap;
extern VideoBootStrap Android_bootstrap;
diff -ruN SDL-release-2.30.11/src/video/SDL_video.c SDL2-2.30.11-banan_os/src/video/SDL_video.c
--- SDL-release-2.30.11/src/video/SDL_video.c 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.30.11-banan_os/src/video/SDL_video.c 2025-08-03 14:04:09.896007237 +0300
@@ -94,6 +94,9 @@
diff -ruN SDL2-2.32.8/src/video/SDL_video.c SDL2-2.32.8-banan_os/src/video/SDL_video.c
--- SDL2-2.32.8/src/video/SDL_video.c 2025-05-20 00:24:41.000000000 +0300
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2025-08-06 02:01:21.087224294 +0300
@@ -96,6 +96,9 @@
#ifdef SDL_VIDEO_DRIVER_HAIKU
&HAIKU_bootstrap,
#endif
+#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+ &BANAN_OS_bootstrap,
+#ifdef SDL_VIDEO_DRIVER_BANANOS
+ &BANANOS_bootstrap,
+#endif
#ifdef SDL_VIDEO_DRIVER_PANDORA
&PND_bootstrap,

View File

@ -59,7 +59,7 @@ config_sub_update() {
config_sub_path="$BANAN_PORT_DIR/config.sub"
if [ $(find $config_sub_path -mtime +1) ]; then
if [ ! -f "$config_sub_path" ] || [ $(find "$config_sub_path" -mtime +1) ]; then
wget -O "$config_sub_path" 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
fi

View File

@ -1,6 +1,7 @@
set(USERSPACE_LIBRARIES
LibAudio
LibC
LibDL
LibELF
LibFont
LibGUI

View File

@ -12,6 +12,17 @@
namespace LibAudio
{
BAN::ErrorOr<Audio> Audio::create(uint32_t channels, uint32_t sample_rate, uint32_t sample_frames)
{
Audio result;
TRY(result.initialize((sample_frames + 10) * channels));
result.m_audio_buffer->sample_rate = sample_rate;
result.m_audio_buffer->channels = channels;
return result;
}
BAN::ErrorOr<Audio> Audio::load(BAN::StringView path)
{
Audio result(TRY(AudioLoader::load(path)));
@ -69,18 +80,6 @@ namespace LibAudio
return *this;
}
BAN::ErrorOr<void> Audio::start()
{
ASSERT(m_server_fd != -1);
const ssize_t nsend = send(m_server_fd, &m_smo_key, sizeof(m_smo_key), 0);
if (nsend == -1)
return BAN::Error::from_errno(errno);
ASSERT(nsend == sizeof(m_smo_key));
return {};
}
BAN::ErrorOr<void> Audio::initialize(uint32_t total_samples)
{
m_smo_size = sizeof(AudioBuffer) + total_samples * sizeof(AudioBuffer::sample_t);
@ -118,11 +117,58 @@ namespace LibAudio
return {};
}
BAN::ErrorOr<void> Audio::start()
{
ASSERT(m_server_fd != -1);
const ssize_t nsend = send(m_server_fd, &m_smo_key, sizeof(m_smo_key), 0);
if (nsend == -1)
return BAN::Error::from_errno(errno);
ASSERT(nsend == sizeof(m_smo_key));
return {};
}
void Audio::set_paused(bool paused)
{
ASSERT(m_server_fd != -1);
if (m_audio_buffer->paused == paused)
return;
m_audio_buffer->paused = paused;
long dummy = 0;
send(m_server_fd, &dummy, sizeof(dummy), 0);
}
size_t Audio::queue_samples(BAN::Span<const AudioBuffer::sample_t> samples)
{
size_t samples_queued = 0;
uint32_t head = m_audio_buffer->head;
while (samples_queued < samples.size())
{
const uint32_t next_head = (head + 1) % m_audio_buffer->capacity;
if (next_head == m_audio_buffer->tail)
break;
m_audio_buffer->samples[head] = samples[samples_queued++];
head = next_head;
if (samples_queued % 128 == 0)
m_audio_buffer->head = head;
}
if (samples_queued % 128 != 0)
m_audio_buffer->head = head;
return samples_queued;
}
void Audio::update()
{
if (!m_audio_loader)
return;
if (!m_audio_loader->samples_remaining() && !is_playing())
return set_paused(true);
while (m_audio_loader->samples_remaining())
{
const uint32_t next_head = (m_audio_buffer->head + 1) % m_audio_buffer->capacity;

View File

@ -18,6 +18,8 @@ namespace LibAudio
uint32_t sample_rate;
uint32_t channels;
BAN::Atomic<bool> paused { false };
uint32_t capacity;
BAN::Atomic<uint32_t> tail { 0 };
BAN::Atomic<uint32_t> head { 0 };
@ -29,6 +31,7 @@ namespace LibAudio
BAN_NON_COPYABLE(Audio);
public:
static BAN::ErrorOr<Audio> create(uint32_t channels, uint32_t sample_rate, uint32_t sample_frames);
static BAN::ErrorOr<Audio> load(BAN::StringView path);
static BAN::ErrorOr<Audio> random(uint32_t samples);
~Audio() { clear(); }
@ -37,9 +40,13 @@ namespace LibAudio
Audio& operator=(Audio&& other);
BAN::ErrorOr<void> start();
void update();
void set_paused(bool paused);
bool is_playing() const { return m_audio_buffer->tail != m_audio_buffer->head; }
void update();
size_t queue_samples(BAN::Span<const AudioBuffer::sample_t> samples);
private:
Audio() = default;

View File

@ -12,6 +12,7 @@ set(LIBC_SOURCES
fenv.cpp
ftw.cpp
grp.cpp
ifaddrs.cpp
inttypes.cpp
langinfo.cpp
libgen.cpp
@ -19,6 +20,7 @@ set(LIBC_SOURCES
locale.cpp
malloc.cpp
math.cpp
net/if.cpp
netdb.cpp
netinet/in.cpp
poll.cpp
@ -27,6 +29,7 @@ set(LIBC_SOURCES
pwd.cpp
scanf_impl.cpp
sched.cpp
semaphore.cpp
setjmp.cpp
signal.cpp
stdio.cpp
@ -45,6 +48,7 @@ set(LIBC_SOURCES
sys/stat.cpp
sys/statvfs.cpp
sys/time.cpp
sys/times.cpp
sys/uio.cpp
sys/utsname.cpp
sys/wait.cpp

View File

@ -0,0 +1,15 @@
#include <ifaddrs.h>
#include <BAN/Assert.h>
int getifaddrs(struct ifaddrs** ifap)
{
(void)ifap;
ASSERT_NOT_REACHED();
}
void freeifaddrs(struct ifaddrs* ifa)
{
(void)ifa;
ASSERT_NOT_REACHED();
}

View File

@ -0,0 +1,32 @@
#ifndef _IFADDRS_H
#define _IFADDRS_H 1
// https://man7.org/linux/man-pages/man3/getifaddrs.3.html
#include <sys/cdefs.h>
__BEGIN_DECLS
struct ifaddrs
{
struct ifaddrs* ifa_next; /* Next item in list */
char* ifa_name; /* Name of interface */
unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */
struct sockaddr* ifa_addr; /* Address of interface */
struct sockaddr* ifa_netmask; /* Netmask of interface */
union {
struct sockaddr* ifu_broadaddr; /* Broadcast address of interface */
struct sockaddr* ifu_dstaddr; /* Point-to-point destination address */
} ifa_ifu;
void* ifa_data; /* Address-specific data */
};
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
int getifaddrs(struct ifaddrs **ifap);
void freeifaddrs(struct ifaddrs *ifa);
__END_DECLS
#endif

View File

@ -0,0 +1,71 @@
#include <dirent.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
static int selector(const dirent* dirent)
{
if (strcmp(dirent->d_name, "lo") == 0)
return 1;
if (strncmp(dirent->d_name, "eth", 3) == 0)
return 1;
return 0;
}
static int comparator(const dirent** d1, const dirent** d2)
{
if (strcmp((*d1)->d_name, "lo"))
return -1;
if (strcmp((*d2)->d_name, "lo"))
return +1;
return alphasort(d1, d2);
}
char* if_indextoname(unsigned ifindex, char* ifname)
{
if (ifindex == 0)
return nullptr;
dirent** namelist;
const int count = scandir("/dev", &namelist, selector, comparator);
if (count == -1)
return nullptr;
char* result = nullptr;
if (ifindex - 1 < static_cast<unsigned>(count))
{
strcpy(ifname, namelist[ifindex - 1]->d_name);
result = ifname;
}
for (int i = 0; i < count; i++)
free(namelist[i]);
free(namelist);
return result;
}
unsigned if_nametoindex(const char* ifname)
{
dirent** namelist;
const int count = scandir("/dev", &namelist, selector, comparator);
if (count == -1)
return 0;
unsigned result = 0;
for (int i = 0; i < count; i++)
{
if (strcmp(ifname, namelist[i]->d_name) != 0)
continue;
result = i + 1;
break;
}
for (int i = 0; i < count; i++)
free(namelist[i]);
free(namelist);
return result;
}

View File

@ -311,3 +311,11 @@ error_close_socket:
close(socket);
return nullptr;
}
#include <BAN/Debug.h>
struct servent* getservbyname(const char* name, const char* proto)
{
dwarnln("TODO: getservbyname(\"{}\", \"{}\")", name, proto);
return nullptr;
}

View File

@ -0,0 +1,47 @@
#include <BAN/Debug.h>
#include <errno.h>
#include <semaphore.h>
int sem_destroy(sem_t* sem)
{
(void)sem;
dwarnln("TODO: sem_destroy");
errno = ENOTSUP;
return -1;
}
int sem_init(sem_t* sem, int pshared, unsigned value)
{
(void)sem;
(void)pshared;
(void)value;
dwarnln("TODO: sem_init");
errno = ENOTSUP;
return -1;
}
int sem_post(sem_t* sem)
{
(void)sem;
dwarnln("TODO: sem_post");
errno = ENOTSUP;
return -1;
}
int sem_trywait(sem_t* sem)
{
(void)sem;
dwarnln("TODO: sem_trywait");
errno = ENOTSUP;
return -1;
}
int sem_wait(sem_t* sem)
{
(void)sem;
dwarnln("TODO: sem_wait");
errno = ENOTSUP;
return -1;
}

View File

@ -45,8 +45,28 @@ int posix_madvise(void* addr, size_t len, int advice)
}
#include <BAN/Assert.h>
#include <BAN/Debug.h>
#include <errno.h>
int mlock(const void*, size_t)
{
ASSERT_NOT_REACHED();
}
int shm_open(const char* name, int oflag, mode_t mode)
{
(void)name;
(void)oflag;
(void)mode;
dwarnln("TODO: shm_open");
errno = ENOTSUP;
return -1;
}
int shm_unlink(const char* name)
{
(void)name;
dwarnln("TODO: shm_unlink");
errno = ENOTSUP;
return -1;
}

View File

@ -69,6 +69,13 @@ int setrlimit(int resource, const struct rlimit* rlp)
return -1;
}
int getpriority(int which, id_t who)
{
dwarnln("TODO: getpriority({}, {}, {})", which, who);
errno = ENOTSUP;
return -1;
}
int setpriority(int which, id_t who, int value)
{
dwarnln("TODO: setpriority({}, {}, {})", which, who, value);

View File

@ -1,4 +1,5 @@
#include <BAN/Assert.h>
#include <BAN/Debug.h>
#include <fcntl.h>
#include <sys/stat.h>
@ -54,6 +55,34 @@ int mkdir(const char* path, mode_t mode)
return syscall(SYS_CREATE_DIR, path, __UMASKED_MODE(mode));
}
int mkfifo(const char* path, mode_t mode)
{
(void)path; (void)mode;
dwarnln("TODO: mkfifo");
return -1;
}
int mkfifoat(int fd, const char* path, mode_t mode)
{
(void)fd; (void)path; (void)mode;
dwarnln("TODO: mkfifoat");
return -1;
}
int mknod(const char* path, mode_t mode, dev_t dev)
{
(void)path; (void)mode; (void)dev;
dwarnln("TODO: mknod");
return -1;
}
int mknodat(int fd, const char* path, mode_t mode, dev_t dev)
{
(void)fd; (void)path; (void)mode; (void)dev;
dwarnln("TODO: mknodat");
return -1;
}
int futimens(int fd, const struct timespec times[2])
{
return utimensat(fd, nullptr, times, 0);

View File

@ -0,0 +1,9 @@
#include <sys/times.h>
#include <BAN/Assert.h>
clock_t times(struct tms* buffer)
{
(void)buffer;
ASSERT_NOT_REACHED();
}

View File

@ -19,6 +19,15 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
return syscall(SYS_CLOCK_GETTIME, clock_id, tp);
}
int clock_getres(clockid_t clock_id, struct timespec* res)
{
(void)clock_id;
res->tv_sec = 0;
res->tv_nsec = 10;
dprintln("TODO: clock_getres");
return 0;
}
int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
{
pthread_testcancel();

View File

@ -24,6 +24,10 @@ int wcwidth(wchar_t wc)
return wc != '\0';
}
wchar_t* wcstok(wchar_t* __restrict, const wchar_t* __restrict, wchar_t** __restrict) { ASSERT_NOT_REACHED(); }
long wcstol(const wchar_t* __restrict, wchar_t** __restrict, int) { ASSERT_NOT_REACHED(); }
int swprintf(wchar_t* __restrict, size_t, const wchar_t* __restrict, ...) { ASSERT_NOT_REACHED(); }
size_t wcrtomb(char* __restrict s, wchar_t ws, mbstate_t* __restrict ps)
{
(void)ps;

View File

@ -0,0 +1,18 @@
set(SOURCES
dummy.cpp
)
add_library(libdl-static STATIC ${SOURCES})
add_library(libdl-shared SHARED ${SOURCES})
target_link_options(libdl-static PRIVATE -nolibc)
target_link_options(libdl-shared PRIVATE -nolibc)
banan_link_library(libdl-static libc)
banan_link_library(libdl-shared libc)
set_target_properties(libdl-static PROPERTIES OUTPUT_NAME libdl)
set_target_properties(libdl-shared PROPERTIES OUTPUT_NAME libdl)
install(TARGETS libdl-static OPTIONAL)
install(TARGETS libdl-shared OPTIONAL)

View File

View File

@ -40,6 +40,13 @@ bool AudioServer::on_client_packet(int fd, long smo_key)
{
auto& audio_buffer = m_audio_buffers[fd];
if (smo_key == 0)
{
if (audio_buffer.buffer)
reset_kernel_buffer();
return true;
}
audio_buffer.buffer = static_cast<LibAudio::AudioBuffer*>(smo_map(smo_key));
audio_buffer.sample_frames_queued = 0;
if (audio_buffer.buffer == nullptr)
@ -53,8 +60,11 @@ bool AudioServer::on_client_packet(int fd, long smo_key)
return true;
}
void AudioServer::update()
uint64_t AudioServer::update()
{
// FIXME: get this from the kernel
static constexpr uint64_t kernel_buffer_ms = 50;
uint32_t kernel_buffer_size;
if (ioctl(m_audio_device_fd, SND_GET_BUFFERSZ, &kernel_buffer_size) == -1)
ASSERT_NOT_REACHED();
@ -72,14 +82,17 @@ void AudioServer::update()
const size_t max_sample_frames = (m_samples.capacity() - m_samples.size()) / m_channels;
const size_t queued_samples_end = m_samples.size();
if (max_sample_frames == 0)
return;
return kernel_buffer_ms;
size_t max_sample_frames_to_queue = max_sample_frames;
bool anyone_playing = false;
for (auto& [_, buffer] : m_audio_buffers)
{
if (buffer.buffer == nullptr)
continue;
const double sample_ratio = buffer.buffer->sample_rate / static_cast<double>(m_sample_rate);
const sample_t sample_ratio = buffer.buffer->sample_rate / static_cast<sample_t>(m_sample_rate);
if (buffer.sample_frames_queued)
{
@ -91,13 +104,38 @@ void AudioServer::update()
buffer.sample_frames_queued -= buffer_sample_frames_played;
}
if (buffer.buffer->paused)
continue;
anyone_playing = true;
const uint32_t buffer_total_sample_frames = ((buffer.buffer->capacity + buffer.buffer->head - buffer.buffer->tail) % buffer.buffer->capacity) / buffer.buffer->channels;
const uint32_t buffer_sample_frames_available = (buffer_total_sample_frames - buffer.sample_frames_queued) / sample_ratio;
max_sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames_to_queue, buffer_sample_frames_available);
}
if (!anyone_playing)
return 60'000;
// FIXME: this works but if any client stops producing audio samples
// the whole audio server halts
const uint32_t samples_per_10ms = m_sample_rate / 100;
if (max_sample_frames_to_queue < samples_per_10ms)
return 1;
for (auto& [_, buffer] : m_audio_buffers)
{
if (buffer.buffer == nullptr || buffer.buffer->paused)
continue;
const sample_t sample_ratio = buffer.buffer->sample_rate / static_cast<sample_t>(m_sample_rate);
const uint32_t buffer_total_sample_frames = ((buffer.buffer->capacity + buffer.buffer->head - buffer.buffer->tail) % buffer.buffer->capacity) / buffer.buffer->channels;
const uint32_t buffer_sample_frames_available = (buffer_total_sample_frames - buffer.sample_frames_queued) / sample_ratio;
if (buffer_sample_frames_available == 0)
continue;
const size_t sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames, buffer_sample_frames_available);
if (sample_frames_to_queue == 0)
const size_t sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames_to_queue, buffer_sample_frames_available);
if (sample_frames_to_queue < samples_per_10ms)
continue;
while (m_samples.size() < queued_samples_end + sample_frames_to_queue * m_channels)
@ -113,10 +151,17 @@ void AudioServer::update()
m_samples[queued_samples_end + i * m_channels + j] += buffer.buffer->samples[(buffer_tail + buffer_frame * buffer.buffer->channels + j) % buffer.buffer->capacity];
}
buffer.sample_frames_queued += sample_frames_to_queue * sample_ratio;
buffer.sample_frames_queued += BAN::Math::min<uint32_t>(
buffer_total_sample_frames,
BAN::Math::ceil(sample_frames_to_queue * sample_ratio)
);
}
send_samples();
const double play_ms = 1000.0 * m_samples_sent / m_channels / m_sample_rate;
const uint64_t wake_ms = BAN::Math::max<uint64_t>(play_ms, kernel_buffer_ms) - kernel_buffer_ms;
return wake_ms;
}
void AudioServer::reset_kernel_buffer()

View File

@ -19,7 +19,7 @@ public:
void on_client_disconnect(int fd);
bool on_client_packet(int fd, long smo_key);
void update();
uint64_t update();
private:
struct ClientInfo
@ -28,6 +28,8 @@ private:
size_t sample_frames_queued { 0 };
};
using sample_t = LibAudio::AudioBuffer::sample_t;
private:
enum class AddOrRemove { Add, Remove };
@ -42,7 +44,7 @@ private:
size_t m_samples_sent { 0 };
BAN::Array<uint8_t, 1024> m_send_buffer;
BAN::CircularQueue<double, 64 * 1024> m_samples;
BAN::CircularQueue<sample_t, 64 * 1024> m_samples;
BAN::HashMap<int, ClientInfo> m_audio_buffers;
};

View File

@ -96,8 +96,7 @@ int main()
dprintln("AudioServer started");
constexpr uint64_t update_interval_ms = 100;
uint64_t next_update_ms = get_current_ms() + update_interval_ms;
uint64_t next_update_ms = get_current_ms();
for (;;)
{
@ -113,11 +112,7 @@ int main()
}
const uint64_t current_ms = get_current_ms();
if (current_ms >= next_update_ms)
{
audio_server->update();
next_update_ms = current_ms + update_interval_ms;
}
next_update_ms = current_ms + audio_server->update();
const uint64_t timeout_ms = next_update_ms - current_ms;

View File

@ -8,6 +8,7 @@
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
struct config_t
@ -37,6 +38,9 @@ struct full_entry_t
BAN::String full_name;
};
bool g_stdout_terminal { false };
winsize g_terminal_size {};
const char* entry_color(mode_t mode)
{
// TODO: handle suid, sgid, sticky
@ -116,6 +120,37 @@ BAN::String build_time_string(BAN::Time time)
return MUST(BAN::String::formatted("{2}:{2}", time.hour, time.minute));
}
BAN::Vector<size_t> resolve_column_widths(const BAN::Vector<simple_entry_t>& entries, size_t columns)
{
BAN::Vector<size_t> widths;
MUST(widths.resize(columns));
const size_t rows = BAN::Math::div_round_up(entries.size(), columns);
for (size_t i = 0; i < entries.size(); i++)
widths[i / rows] = BAN::Math::max(widths[i / rows], entries[i].name.size());
size_t full_width = (columns - 1);
for (auto width : widths)
{
if (width == 0)
return {};
full_width += width;
}
if (full_width <= g_terminal_size.ws_col)
return widths;
return {};
}
BAN::Vector<size_t> resolve_layout(const BAN::Vector<simple_entry_t>& entries)
{
for (size_t columns = entries.size(); columns > 1; columns--)
if (auto widths = resolve_column_widths(entries, columns); !widths.empty())
return widths;
return {};
}
int list_directory(const BAN::String& path, config_t config)
{
static char link_buffer[PATH_MAX];
@ -198,14 +233,59 @@ int list_directory(const BAN::String& path, config_t config)
if (!config.list)
{
for (size_t i = 0; i < entries.size(); i++)
if (!g_stdout_terminal)
{
if (i > 0)
for (const auto& entry : entries)
printf("%s\n", entry.name.data());
return ret;
}
bool should_quote = false;
for (size_t i = 0; i < entries.size() && !should_quote; i++)
should_quote = entries[i].name.sv().contains(' ');
if (!should_quote)
for (auto& entry : entries)
MUST(entry.name.push_back(' '));
else
{
for (auto& entry : entries)
{
const char ch = entry.name.sv().contains(' ') ? '\'' : ' ';
MUST(entry.name.insert(ch, 0));
MUST(entry.name.push_back(ch));
}
}
auto layout = resolve_layout(entries);
if (layout.empty())
for (const auto& entry : entries)
printf("%s%s\e[m\n", entry_color(entry.st.st_mode), entry.name.data());
else
{
const size_t cols = layout.size();
const size_t rows = BAN::Math::div_round_up(entries.size(), cols);
for (size_t row = 0; row < rows; row++)
{
for (size_t col = 0; col < cols; col++)
{
const size_t i = col * rows + row;
if (i >= entries.size())
break;
char format[32];
sprintf(format, "%%s%%-%zus\e[m", layout[col]);
if (col != 0)
printf(" ");
const char* format = entries[i].name.sv().contains(' ') ? "'%s%s\e[m'" : "%s%s\e[m";
printf(format, entry_color(entries[i].st.st_mode), entries[i].name.data());
}
printf("\n");
}
}
return ret;
}
@ -326,6 +406,8 @@ int main(int argc, const char* argv[])
else for (; i < argc; i++)
MUST(files.emplace_back(BAN::StringView(argv[i])));
g_stdout_terminal = isatty(STDOUT_FILENO) && ioctl(STDOUT_FILENO, TIOCGWINSZ, &g_terminal_size) == 0;
int ret = 0;
for (size_t i = 0; i < files.size(); i++)
{