Compare commits

..

No commits in common. "3aa20a3a3263e025fbaef93e8e5ba28f49fe4841" and "647fedfa1981cd6e4f10225fbaa49354d4a7a75e" have entirely different histories.

36 changed files with 230 additions and 978 deletions

View File

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

View File

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

View File

@ -28,7 +28,7 @@ namespace Kernel
BAN::ErrorOr<void> initialize_bld(); BAN::ErrorOr<void> initialize_bld();
BAN::ErrorOr<void> initialize_interrupts(); BAN::ErrorOr<void> initialize_interrupts();
bool queue_samples_to_bld(); void queue_samples_to_bld();
private: private:
static constexpr size_t m_bdl_entries = 32; 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_page_free(vaddr_t) const;
bool is_range_free(vaddr_t, size_t bytes) const; bool is_range_free(vaddr_t, size_t bytes) const;
bool reserve_page(vaddr_t, bool only_free = true, bool send_smp_message = true); bool reserve_page(vaddr_t, bool only_free = true);
bool reserve_range(vaddr_t, size_t bytes, bool only_free = 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); vaddr_t reserve_free_page(vaddr_t first_address, vaddr_t last_address = UINTPTR_MAX);

View File

@ -35,9 +35,7 @@ namespace Kernel
// FIXME: kernel stack does NOT have to be this big, but my recursive AML interpreter // FIXME: kernel stack does NOT have to be this big, but my recursive AML interpreter
// stack overflows on some machines with 8 page stack // stack overflows on some machines with 8 page stack
static constexpr size_t kernel_stack_size { PAGE_SIZE * 16 }; 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: public:
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*); static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*);

View File

@ -927,79 +927,42 @@ acpi_release_global_lock:
return 0; 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) while (true)
{ {
uint16_t sts_port; uint16_t sts_port;
uint16_t pending; uint16_t pending;
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++)
{
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;
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; sts_port = fadt().pm1a_evt_blk;
if ((pending = get_fixed_event(sts_port))) if (pending = get_fixed_event(sts_port); pending)
goto handle_event; goto handle_event;
sts_port = fadt().pm1b_evt_blk; sts_port = fadt().pm1b_evt_blk;
if ((pending = get_fixed_event(sts_port))) if (pending = get_fixed_event(sts_port); pending)
goto handle_event; goto handle_event;
if (gpe0.has_value() && read_gpe(gpe0.value(), fadt().gpe0_blk_len, 0)) {
continue; 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;
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)
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 // FIXME: this can cause missing of event if it happens between
// reading the status and blocking // reading the status and blocking

View File

@ -185,10 +185,14 @@ namespace Kernel
void AC97AudioController::handle_new_data() void AC97AudioController::handle_new_data()
{ {
ASSERT(m_spinlock.current_processor_has_lock()); ASSERT(m_spinlock.current_processor_has_lock());
if (m_bdl_head != m_bdl_tail)
return;
queue_samples_to_bld(); queue_samples_to_bld();
} }
bool AC97AudioController::queue_samples_to_bld() void AC97AudioController::queue_samples_to_bld()
{ {
ASSERT(m_spinlock.current_processor_has_lock()); ASSERT(m_spinlock.current_processor_has_lock());
@ -224,7 +228,7 @@ namespace Kernel
// if head was not updated, no data was queued // if head was not updated, no data was queued
if (lvi == m_bdl_head) if (lvi == m_bdl_head)
return false; return;
m_sample_data_blocker.unblock(); m_sample_data_blocker.unblock();
@ -234,8 +238,6 @@ namespace Kernel
const uint8_t control = m_bus_master->read8(BusMasterRegister::PO_CR); const uint8_t control = m_bus_master->read8(BusMasterRegister::PO_CR);
if (!(control & RDBM)) if (!(control & RDBM))
m_bus_master->write8(BusMasterRegister::PO_CR, control | RDBM); m_bus_master->write8(BusMasterRegister::PO_CR, control | RDBM);
return true;
} }
void AC97AudioController::handle_irq() void AC97AudioController::handle_irq()
@ -247,18 +249,17 @@ namespace Kernel
SpinLockGuard _(m_spinlock); SpinLockGuard _(m_spinlock);
bool did_enqueue = false; if (status & LVBCI)
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); const uint8_t control = m_bus_master->read8(BusMasterRegister::PO_CR);
m_bus_master->write8(BusMasterRegister::PO_CR, control & ~RDBM); 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,9 +109,7 @@ namespace Kernel
if (file_type == DIRTYPE) if (file_type == DIRTYPE)
{ {
if (file_name_sv == "."_sv) if (auto ret = parent_inode->create_directory(file_name_sv, file_mode, file_uid, file_gid); ret.is_error())
; // 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()); dwarnln("failed to create directory '{}': {}", file_name_sv, ret.error());
} }
else if (file_type == LNKTYPE) else if (file_type == LNKTYPE)

View File

@ -207,6 +207,26 @@ namespace Kernel
goto done; 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,12 +102,6 @@ namespace Kernel
last_event.move_event.rel_y += curr_event.move_event.rel_y; last_event.move_event.rel_y += curr_event.move_event.rel_y;
return; 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) if (last_event.type == LibInput::MouseEventType::MouseScrollEvent && curr_event.type == LibInput::MouseEventType::MouseScrollEvent)
{ {
last_event.scroll_event.scroll += curr_event.scroll_event.scroll; 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) BAN::ErrorOr<bool> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
{ {
ASSERT(contains(vaddr)); ASSERT(contains(vaddr));
vaddr &= PAGE_ADDR_MASK; ASSERT(&PageTable::current() == &m_page_table);
if (m_preallocated) if (m_preallocated)
return false; return false;
@ -158,11 +158,8 @@ namespace Kernel
if (m_paddrs[index] == 0) if (m_paddrs[index] == 0)
return BAN::Error::from_errno(ENOMEM); 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); m_page_table.map_page_at(m_paddrs[index], vaddr, m_flags);
memset(reinterpret_cast<void*>(vaddr), 0, PAGE_SIZE);
return true; return true;
} }

View File

@ -138,7 +138,7 @@ namespace Kernel
stack_addr_start, USERSPACE_END, stack_addr_start, USERSPACE_END,
userspace_stack_size, userspace_stack_size,
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
false, true true, true
)); ));
thread_deleter.disable(); thread_deleter.disable();
@ -217,7 +217,6 @@ namespace Kernel
save_sse(); save_sse();
memcpy(thread->m_sse_storage, m_sse_storage, sizeof(m_sse_storage)); 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::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; PageTable::fast_page_as<void*>(PAGE_SIZE - sizeof(uintptr_t)) = arg;
}); });
@ -300,10 +299,6 @@ namespace Kernel
vaddr_t vaddr = userspace_stack_top() - needed_size; 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 = const auto stack_copy_buf =
[this](BAN::ConstByteSpan buffer, vaddr_t vaddr) -> void [this](BAN::ConstByteSpan buffer, vaddr_t vaddr) -> void
{ {

View File

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

View File

@ -1,28 +1,7 @@
diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.txt
--- SDL2-2.32.8/cmake/sdlplatform.cmake 2024-08-14 13:35:43.000000000 +0300 --- SDL-release-2.30.11/CMakeLists.txt 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2025-08-06 02:07:18.347821313 +0300 +++ SDL2-2.30.11-banan_os/CMakeLists.txt 2025-08-03 14:04:09.894244781 +0300
@@ -28,6 +28,8 @@ @@ -1452,7 +1452,7 @@
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() CheckPTHREAD()
CheckLibUnwind() CheckLibUnwind()
@ -31,7 +10,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
if(SDL_AUDIO) if(SDL_AUDIO)
if(SYSV5 OR SOLARIS OR HPUX) if(SYSV5 OR SOLARIS OR HPUX)
set(SDL_AUDIO_DRIVER_SUNAUDIO 1) set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
@@ -2459,6 +2459,57 @@ @@ -2422,6 +2422,49 @@
CheckPTHREAD() CheckPTHREAD()
list(APPEND EXTRA_LIBS root be media game device textencoding) list(APPEND EXTRA_LIBS root be media game device textencoding)
@ -42,16 +21,8 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
+ set(HAVE_SDL_MISC TRUE) + set(HAVE_SDL_MISC TRUE)
+ endif() + 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) + if(SDL_VIDEO)
+ set(SDL_VIDEO_DRIVER_BANANOS 1) + set(SDL_VIDEO_DRIVER_BANAN_OS 1)
+ file(GLOB VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/banan_os/*.cpp) + file(GLOB VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/banan_os/*.cpp)
+ list(APPEND SOURCE_FILES ${VIDEO_SOURCES}) + list(APPEND SOURCE_FILES ${VIDEO_SOURCES})
+ set(HAVE_SDL_VIDEO TRUE) + set(HAVE_SDL_VIDEO TRUE)
@ -59,7 +30,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
+ +
+ if(SDL_OPENGL) + if(SDL_OPENGL)
+ set(SDL_VIDEO_OPENGL 1) + set(SDL_VIDEO_OPENGL 1)
+ set(SDL_VIDEO_OPENGL_BANANOS 1) + set(SDL_VIDEO_OPENGL_BANAN_OS 1)
+ set(SDL_VIDEO_RENDER_OGL 1) + set(SDL_VIDEO_RENDER_OGL 1)
+ list(APPEND EXTRA_LIBS OSMesa) + list(APPEND EXTRA_LIBS OSMesa)
+ set(HAVE_OPENGL TRUE) + set(HAVE_OPENGL TRUE)
@ -89,28 +60,20 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
elseif(RISCOS) elseif(RISCOS)
if(SDL_MISC) if(SDL_MISC)
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c) file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SDL_config.h.cmake diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL2-2.30.11-banan_os/include/SDL_config.h.cmake
--- SDL2-2.32.8/include/SDL_config.h.cmake 2025-01-01 17:47:53.000000000 +0200 --- SDL-release-2.30.11/include/SDL_config.h.cmake 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2025-08-06 02:01:21.085539504 +0300 +++ SDL2-2.30.11-banan_os/include/SDL_config.h.cmake 2025-08-03 14:04:09.894803585 +0300
@@ -307,6 +307,7 @@ @@ -406,6 +406,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_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@ #cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@ #cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
+#cmakedefine SDL_VIDEO_DRIVER_BANANOS @SDL_VIDEO_DRIVER_BANANOS@ +#cmakedefine SDL_VIDEO_DRIVER_BANAN_OS @SDL_VIDEO_DRIVER_BANAN_OS@
#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@ #cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
#cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@ #cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@ #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_platform.h diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL2-2.30.11-banan_os/include/SDL_platform.h
--- SDL2-2.32.8/include/SDL_platform.h 2025-01-01 17:47:53.000000000 +0200 --- SDL-release-2.30.11/include/SDL_platform.h 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2025-08-06 02:01:21.085701327 +0300 +++ SDL2-2.30.11-banan_os/include/SDL_platform.h 2025-08-03 14:04:09.895022748 +0300
@@ -36,6 +36,10 @@ @@ -36,6 +36,10 @@
#undef __HAIKU__ #undef __HAIKU__
#define __HAIKU__ 1 #define __HAIKU__ 1
@ -122,225 +85,9 @@ diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_pl
#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__) #if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
#undef __BSDI__ #undef __BSDI__
#define __BSDI__ 1 #define __BSDI__ 1
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 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
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.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 +++ SDL2-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-08-03 14:04:09.895198889 +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 @@ @@ -0,0 +1,30 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -372,9 +119,9 @@ diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/
+ +
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
+ +
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 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
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200 --- 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.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-06 02:01:21.086557935 +0300 +++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-03 14:04:09.895299391 +0300
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -400,7 +147,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.
+ +
+#include "../../SDL_internal.h" +#include "../../SDL_internal.h"
+ +
+#ifdef SDL_VIDEO_DRIVER_BANANOS +#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+ +
+#include "SDL_messagebox.h" +#include "SDL_messagebox.h"
+ +
@ -409,7 +156,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.
+#include <BAN/Debug.h> +#include <BAN/Debug.h>
+#include <LibGUI/MessageBox.h> +#include <LibGUI/MessageBox.h>
+ +
+int BANANOS_ShowMessageBox(const SDL_MessageBoxData* messageboxdata, int* buttonid) +int BANAN_OS_ShowMessageBox(const SDL_MessageBoxData* messageboxdata, int* buttonid)
+{ +{
+ BAN::Vector<BAN::StringView> buttons; + BAN::Vector<BAN::StringView> buttons;
+ for (int i = 0; i < messageboxdata->numbuttons; i++) { + for (int i = 0; i < messageboxdata->numbuttons; i++) {
@ -433,12 +180,12 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.
+ return 0; + return 0;
+} +}
+ +
+#endif /* SDL_VIDEO_DRIVER_BANANOS */ +#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
+ +
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
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 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
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200 --- 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.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-06 02:01:21.086603053 +0300 +++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-03 14:04:09.895347931 +0300
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -462,33 +209,33 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-
+ 3. This notice may not be removed or altered from any source distribution. + 3. This notice may not be removed or altered from any source distribution.
+*/ +*/
+ +
+#ifndef SDL_BANANOS_MESSAGEBOX_H +#ifndef SDL_BANAN_OS_MESSAGEBOX_H
+#define SDL_BANANOS_MESSAGEBOX_H +#define SDL_BANAN_OS_MESSAGEBOX_H
+ +
+#include "../../SDL_internal.h" +#include "../../SDL_internal.h"
+ +
+#ifdef SDL_VIDEO_DRIVER_BANANOS +#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+ +
+#ifdef __cplusplus +#ifdef __cplusplus
+extern "C" { +extern "C" {
+#endif +#endif
+ +
+extern int +extern int
+BANANOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); +BANAN_OS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+ +
+#ifdef __cplusplus +#ifdef __cplusplus
+} +}
+#endif +#endif
+ +
+#endif /* SDL_BANANOS_MESSAGEBOX_H */ +#endif /* SDL_BANAN_OS_MESSAGEBOX_H */
+ +
+#endif +#endif
+ +
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
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 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
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL-release-2.30.11/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 +++ 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,718 @@ @@ -0,0 +1,719 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
@ -509,9 +256,10 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ misrepresented as being the original software. + misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution. + 3. This notice may not be removed or altered from any source distribution.
+*/ +*/
+
+#include "../../SDL_internal.h" +#include "../../SDL_internal.h"
+ +
+#ifdef SDL_VIDEO_DRIVER_BANANOS +#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+ +
+extern "C" { +extern "C" {
+#include "../SDL_sysvideo.h" +#include "../SDL_sysvideo.h"
@ -674,7 +422,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+}; +};
+static Keymap s_keymap; +static Keymap s_keymap;
+ +
+static int BANANOS_mouse_button_to_sdl(LibInput::MouseButton button) +static int BANAN_OS_mouse_button_to_sdl(LibInput::MouseButton button)
+{ +{
+ switch (button) { + switch (button) {
+#define BUTTON_CASE(my, sdl) case LibInput::MouseButton::my: return SDL_BUTTON_##sdl +#define BUTTON_CASE(my, sdl) case LibInput::MouseButton::my: return SDL_BUTTON_##sdl
@ -690,7 +438,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ +
+static SDL_VideoDevice* s_video_device = nullptr; +static SDL_VideoDevice* s_video_device = nullptr;
+ +
+static SDL_Cursor* BANANOS_CreateSystemCursor(SDL_SystemCursor id) +static SDL_Cursor* BANAN_OS_CreateSystemCursor(SDL_SystemCursor id)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -705,7 +453,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return cursor; + return cursor;
+} +}
+ +
+static void BANANOS_FreeCursor(SDL_Cursor* cursor) +static void BANAN_OS_FreeCursor(SDL_Cursor* cursor)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -713,7 +461,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ SDL_free(cursor); + SDL_free(cursor);
+} +}
+ +
+static int BANANOS_ShowCursor(SDL_Cursor* cursor) +static int BANAN_OS_ShowCursor(SDL_Cursor* cursor)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -727,7 +475,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static int BANANOS_SetRelativeMouseMode(SDL_bool enabled) +static int BANAN_OS_SetRelativeMouseMode(SDL_bool enabled)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -742,24 +490,24 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static void BANANOS_InitMouse(_THIS) +static void BANAN_OS_InitMouse(_THIS)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
+ auto* mouse = SDL_GetMouse(); + auto* mouse = SDL_GetMouse();
+ mouse->ShowCursor = BANANOS_ShowCursor; + mouse->ShowCursor = BANAN_OS_ShowCursor;
+ mouse->SetRelativeMouseMode = BANANOS_SetRelativeMouseMode; + mouse->SetRelativeMouseMode = BANAN_OS_SetRelativeMouseMode;
+ mouse->CreateSystemCursor = BANANOS_CreateSystemCursor; + mouse->CreateSystemCursor = BANAN_OS_CreateSystemCursor;
+ mouse->FreeCursor = BANANOS_FreeCursor; + mouse->FreeCursor = BANAN_OS_FreeCursor;
+ +
+ SDL_SetDefaultCursor(BANANOS_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW)); + SDL_SetDefaultCursor(BANAN_OS_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
+} +}
+ +
+static int BANANOS_VideoInit(_THIS) +static int BANAN_OS_VideoInit(_THIS)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
+ BANANOS_InitMouse(_this); + BANAN_OS_InitMouse(_this);
+ +
+ int fb_fd = open("/dev/fb0", O_RDONLY); + int fb_fd = open("/dev/fb0", O_RDONLY);
+ if (fb_fd == -1) { + if (fb_fd == -1) {
@ -795,7 +543,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static void BANANOS_VideoQuit(_THIS) +static void BANAN_OS_VideoQuit(_THIS)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -803,14 +551,14 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ s_video_device = nullptr; + s_video_device = nullptr;
+} +}
+ +
+static void BANANOS_free(_THIS) +static void BANAN_OS_free(_THIS)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ delete static_cast<banan_os_video_device_data*>(_this->driverdata); + delete static_cast<banan_os_video_device_data*>(_this->driverdata);
+ SDL_free(_this); + SDL_free(_this);
+} +}
+ +
+static int BANANOS_CreateSDLWindow(_THIS, SDL_Window* window) +static int BANAN_OS_CreateSDLWindow(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -852,7 +600,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ [window, ban_window](LibGUI::EventPacket::MouseButtonEvent::event_t event) { + [window, ban_window](LibGUI::EventPacket::MouseButtonEvent::event_t event) {
+ const int state = event.pressed ? SDL_PRESSED : SDL_RELEASED; + const int state = event.pressed ? SDL_PRESSED : SDL_RELEASED;
+ SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y); + SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y);
+ SDL_SendMouseButton(window, 0, state, BANANOS_mouse_button_to_sdl(event.button)); + SDL_SendMouseButton(window, 0, state, BANAN_OS_mouse_button_to_sdl(event.button));
+ } + }
+ ); + );
+ +
@ -903,7 +651,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static void BANANOS_DestroyWindow(_THIS, SDL_Window* window) +static void BANAN_OS_DestroyWindow(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -919,7 +667,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ window->driverdata = nullptr; + window->driverdata = nullptr;
+} +}
+ +
+static void BANANOS_ShowWindow(_THIS, SDL_Window* window) +static void BANAN_OS_ShowWindow(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -933,7 +681,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_attributes(attributes); + ban_window.window->set_attributes(attributes);
+} +}
+ +
+static void BANANOS_HideWindow(_THIS, SDL_Window* window) +static void BANAN_OS_HideWindow(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -947,7 +695,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_attributes(attributes); + ban_window.window->set_attributes(attributes);
+} +}
+ +
+static void BANANOS_SetWindowTitle(_THIS, SDL_Window* window) +static void BANAN_OS_SetWindowTitle(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -955,7 +703,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_title(window->title); + ban_window.window->set_title(window->title);
+} +}
+ +
+static void BANANOS_SetWindowPosition(_THIS, SDL_Window* window) +static void BANAN_OS_SetWindowPosition(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -963,7 +711,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_position(window->x, window->y); + ban_window.window->set_position(window->x, window->y);
+} +}
+ +
+static void BANANOS_SetWindowSize(_THIS, SDL_Window* window) +static void BANAN_OS_SetWindowSize(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -971,7 +719,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->request_resize(window->w, window->h); + ban_window.window->request_resize(window->w, window->h);
+} +}
+ +
+static void BANANOS_SetWindowMinimumSize(_THIS, SDL_Window* window) +static void BANAN_OS_SetWindowMinimumSize(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -979,7 +727,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_min_size(window->min_w, window->min_h); + ban_window.window->set_min_size(window->min_w, window->min_h);
+} +}
+ +
+static void BANANOS_SetWindowMaximumSize(_THIS, SDL_Window* window) +static void BANAN_OS_SetWindowMaximumSize(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -987,12 +735,12 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_max_size(window->min_w, window->min_h); + ban_window.window->set_max_size(window->min_w, window->min_h);
+} +}
+ +
+static void BANANOS_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered) +static void BANAN_OS_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+} +}
+ +
+static void BANANOS_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable) +static void BANAN_OS_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1003,7 +751,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ } + }
+} +}
+ +
+static void BANANOS_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) +static void BANAN_OS_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1011,7 +759,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ ban_window.window->set_fullscreen(fullscreen); + ban_window.window->set_fullscreen(fullscreen);
+} +}
+ +
+static int BANANOS_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format, void** pixels, int* pitch) +static int BANAN_OS_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format, void** pixels, int* pitch)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1035,7 +783,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static int BANANOS_UpdateWindowFramebuffer(_THIS, SDL_Window* window, const SDL_Rect* rects, int numrects) +static int BANAN_OS_UpdateWindowFramebuffer(_THIS, SDL_Window* window, const SDL_Rect* rects, int numrects)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1047,12 +795,12 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static void BANANOS_DestroyWindowFramebuffer(_THIS, SDL_Window* window) +static void BANAN_OS_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+} +}
+ +
+static void BANANOS_PumpEvents(_THIS) +static void BANAN_OS_PumpEvents(_THIS)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1061,7 +809,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ window->window->poll_events(); + window->window->poll_events();
+} +}
+ +
+static int BANANOS_GL_LoadLibrary(_THIS, const char* path) +static int BANAN_OS_GL_LoadLibrary(_THIS, const char* path)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1074,14 +822,14 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static void* BANANOS_GL_GetProcAddress(_THIS, const char* proc) +static void* BANAN_OS_GL_GetProcAddress(_THIS, const char* proc)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
+ return reinterpret_cast<void*>(OSMesaGetProcAddress(proc)); + return reinterpret_cast<void*>(OSMesaGetProcAddress(proc));
+} +}
+ +
+static SDL_GLContext BANANOS_GL_CreateContext(_THIS, SDL_Window* window) +static SDL_GLContext BANAN_OS_GL_CreateContext(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1105,7 +853,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return gl_context; + return gl_context;
+} +}
+ +
+static void BANANOS_GL_DeleteContext(_THIS, SDL_GLContext context) +static void BANAN_OS_GL_DeleteContext(_THIS, SDL_GLContext context)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1113,7 +861,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ OSMesaDestroyContext(gl_context); + OSMesaDestroyContext(gl_context);
+} +}
+ +
+static int BANANOS_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context) +static int BANAN_OS_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1132,7 +880,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static int BANANOS_GL_SwapWindow(_THIS, SDL_Window* window) +static int BANAN_OS_GL_SwapWindow(_THIS, SDL_Window* window)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1147,7 +895,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return 0; + return 0;
+} +}
+ +
+static SDL_VideoDevice* BANANOS_CreateDevice(void) +static SDL_VideoDevice* BANAN_OS_CreateDevice(void)
+{ +{
+ DUMP_FUNCTION(); + DUMP_FUNCTION();
+ +
@ -1163,70 +911,70 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+ return nullptr; + return nullptr;
+ } + }
+ +
+ device->VideoInit = BANANOS_VideoInit; + device->VideoInit = BANAN_OS_VideoInit;
+ device->VideoQuit = BANANOS_VideoQuit; + device->VideoQuit = BANAN_OS_VideoQuit;
+ +
+ device->CreateSDLWindow = BANANOS_CreateSDLWindow; + device->CreateSDLWindow = BANAN_OS_CreateSDLWindow;
+ device->DestroyWindow = BANANOS_DestroyWindow; + device->DestroyWindow = BANAN_OS_DestroyWindow;
+ device->ShowWindow = BANANOS_ShowWindow; + device->ShowWindow = BANAN_OS_ShowWindow;
+ device->HideWindow = BANANOS_HideWindow; + device->HideWindow = BANAN_OS_HideWindow;
+ +
+ device->SetWindowTitle = BANANOS_SetWindowTitle; + device->SetWindowTitle = BANAN_OS_SetWindowTitle;
+ device->SetWindowPosition = BANANOS_SetWindowPosition; + device->SetWindowPosition = BANAN_OS_SetWindowPosition;
+ device->SetWindowSize = BANANOS_SetWindowSize; + device->SetWindowSize = BANAN_OS_SetWindowSize;
+ device->SetWindowMinimumSize = BANANOS_SetWindowMinimumSize; + device->SetWindowMinimumSize = BANAN_OS_SetWindowMinimumSize;
+ device->SetWindowMaximumSize = BANANOS_SetWindowMaximumSize; + device->SetWindowMaximumSize = BANAN_OS_SetWindowMaximumSize;
+ device->SetWindowBordered = BANANOS_SetWindowBordered; + device->SetWindowBordered = BANAN_OS_SetWindowBordered;
+ device->SetWindowResizable = BANANOS_SetWindowResizable; + device->SetWindowResizable = BANAN_OS_SetWindowResizable;
+ device->SetWindowFullscreen = BANANOS_SetWindowFullscreen; + device->SetWindowFullscreen = BANAN_OS_SetWindowFullscreen;
+ +
+ device->CreateWindowFramebuffer = BANANOS_CreateWindowFramebuffer; + device->CreateWindowFramebuffer = BANAN_OS_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = BANANOS_UpdateWindowFramebuffer; + device->UpdateWindowFramebuffer = BANAN_OS_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = BANANOS_DestroyWindowFramebuffer; + device->DestroyWindowFramebuffer = BANAN_OS_DestroyWindowFramebuffer;
+ +
+ device->PumpEvents = BANANOS_PumpEvents; + device->PumpEvents = BANAN_OS_PumpEvents;
+ +
+ device->GL_LoadLibrary = BANANOS_GL_LoadLibrary; + device->GL_LoadLibrary = BANAN_OS_GL_LoadLibrary;
+ device->GL_GetProcAddress = BANANOS_GL_GetProcAddress; + device->GL_GetProcAddress = BANAN_OS_GL_GetProcAddress;
+ device->GL_CreateContext = BANANOS_GL_CreateContext; + device->GL_CreateContext = BANAN_OS_GL_CreateContext;
+ device->GL_DeleteContext = BANANOS_GL_DeleteContext; + device->GL_DeleteContext = BANAN_OS_GL_DeleteContext;
+ device->GL_MakeCurrent = BANANOS_GL_MakeCurrent; + device->GL_MakeCurrent = BANAN_OS_GL_MakeCurrent;
+ device->GL_SwapWindow = BANANOS_GL_SwapWindow; + device->GL_SwapWindow = BANAN_OS_GL_SwapWindow;
+ +
+ device->free = BANANOS_free; + device->free = BANAN_OS_free;
+ +
+ return device; + return device;
+} +}
+ +
+VideoBootStrap BANANOS_bootstrap = { +VideoBootStrap BANAN_OS_bootstrap = {
+ "banan-os", "banan-os graphics", + "banan-os", "banan-os graphics",
+ BANANOS_CreateDevice, + BANAN_OS_CreateDevice,
+ BANANOS_ShowMessageBox + BANAN_OS_ShowMessageBox
+}; +};
+ +
+#endif /* SDL_VIDEO_DRIVER_BANANOS */ +#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
+ +
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h
--- SDL2-2.32.8/src/video/SDL_sysvideo.h 2025-05-20 00:24:41.000000000 +0300 --- SDL-release-2.30.11/src/video/SDL_sysvideo.h 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2025-08-06 02:01:21.086873550 +0300 +++ SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h 2025-08-03 14:04:09.895655165 +0300
@@ -462,6 +462,7 @@ @@ -462,6 +462,7 @@
extern VideoBootStrap WINDOWS_bootstrap; extern VideoBootStrap WINDOWS_bootstrap;
extern VideoBootStrap WINRT_bootstrap; extern VideoBootStrap WINRT_bootstrap;
extern VideoBootStrap HAIKU_bootstrap; extern VideoBootStrap HAIKU_bootstrap;
+extern VideoBootStrap BANANOS_bootstrap; +extern VideoBootStrap BANAN_OS_bootstrap;
extern VideoBootStrap PND_bootstrap; extern VideoBootStrap PND_bootstrap;
extern VideoBootStrap UIKIT_bootstrap; extern VideoBootStrap UIKIT_bootstrap;
extern VideoBootStrap Android_bootstrap; extern VideoBootStrap Android_bootstrap;
diff -ruN SDL2-2.32.8/src/video/SDL_video.c SDL2-2.32.8-banan_os/src/video/SDL_video.c diff -ruN SDL-release-2.30.11/src/video/SDL_video.c SDL2-2.30.11-banan_os/src/video/SDL_video.c
--- SDL2-2.32.8/src/video/SDL_video.c 2025-05-20 00:24:41.000000000 +0300 --- SDL-release-2.30.11/src/video/SDL_video.c 2025-01-01 19:09:38.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2025-08-06 02:01:21.087224294 +0300 +++ SDL2-2.30.11-banan_os/src/video/SDL_video.c 2025-08-03 14:04:09.896007237 +0300
@@ -96,6 +96,9 @@ @@ -94,6 +94,9 @@
#ifdef SDL_VIDEO_DRIVER_HAIKU #ifdef SDL_VIDEO_DRIVER_HAIKU
&HAIKU_bootstrap, &HAIKU_bootstrap,
#endif #endif
+#ifdef SDL_VIDEO_DRIVER_BANANOS +#ifdef SDL_VIDEO_DRIVER_BANAN_OS
+ &BANANOS_bootstrap, + &BANAN_OS_bootstrap,
+#endif +#endif
#ifdef SDL_VIDEO_DRIVER_PANDORA #ifdef SDL_VIDEO_DRIVER_PANDORA
&PND_bootstrap, &PND_bootstrap,

View File

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

View File

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

View File

@ -12,17 +12,6 @@
namespace LibAudio 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) BAN::ErrorOr<Audio> Audio::load(BAN::StringView path)
{ {
Audio result(TRY(AudioLoader::load(path))); Audio result(TRY(AudioLoader::load(path)));
@ -80,6 +69,18 @@ namespace LibAudio
return *this; 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) BAN::ErrorOr<void> Audio::initialize(uint32_t total_samples)
{ {
m_smo_size = sizeof(AudioBuffer) + total_samples * sizeof(AudioBuffer::sample_t); m_smo_size = sizeof(AudioBuffer) + total_samples * sizeof(AudioBuffer::sample_t);
@ -117,58 +118,11 @@ namespace LibAudio
return {}; 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() void Audio::update()
{ {
if (!m_audio_loader) if (!m_audio_loader)
return; return;
if (!m_audio_loader->samples_remaining() && !is_playing())
return set_paused(true);
while (m_audio_loader->samples_remaining()) while (m_audio_loader->samples_remaining())
{ {
const uint32_t next_head = (m_audio_buffer->head + 1) % m_audio_buffer->capacity; const uint32_t next_head = (m_audio_buffer->head + 1) % m_audio_buffer->capacity;

View File

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

View File

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

View File

@ -1,15 +0,0 @@
#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

@ -1,32 +0,0 @@
#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

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

View File

@ -1,47 +0,0 @@
#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,28 +45,8 @@ int posix_madvise(void* addr, size_t len, int advice)
} }
#include <BAN/Assert.h> #include <BAN/Assert.h>
#include <BAN/Debug.h>
#include <errno.h>
int mlock(const void*, size_t) int mlock(const void*, size_t)
{ {
ASSERT_NOT_REACHED(); 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,13 +69,6 @@ int setrlimit(int resource, const struct rlimit* rlp)
return -1; 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) int setpriority(int which, id_t who, int value)
{ {
dwarnln("TODO: setpriority({}, {}, {})", which, who, value); dwarnln("TODO: setpriority({}, {}, {})", which, who, value);

View File

@ -1,5 +1,4 @@
#include <BAN/Assert.h> #include <BAN/Assert.h>
#include <BAN/Debug.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -55,34 +54,6 @@ int mkdir(const char* path, mode_t mode)
return syscall(SYS_CREATE_DIR, path, __UMASKED_MODE(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]) int futimens(int fd, const struct timespec times[2])
{ {
return utimensat(fd, nullptr, times, 0); return utimensat(fd, nullptr, times, 0);

View File

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

View File

@ -19,15 +19,6 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
return syscall(SYS_CLOCK_GETTIME, clock_id, 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) int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
{ {
pthread_testcancel(); pthread_testcancel();

View File

@ -24,10 +24,6 @@ int wcwidth(wchar_t wc)
return wc != '\0'; 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) size_t wcrtomb(char* __restrict s, wchar_t ws, mbstate_t* __restrict ps)
{ {
(void)ps; (void)ps;

View File

@ -1,18 +0,0 @@
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

@ -40,13 +40,6 @@ bool AudioServer::on_client_packet(int fd, long smo_key)
{ {
auto& audio_buffer = m_audio_buffers[fd]; 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.buffer = static_cast<LibAudio::AudioBuffer*>(smo_map(smo_key));
audio_buffer.sample_frames_queued = 0; audio_buffer.sample_frames_queued = 0;
if (audio_buffer.buffer == nullptr) if (audio_buffer.buffer == nullptr)
@ -60,11 +53,8 @@ bool AudioServer::on_client_packet(int fd, long smo_key)
return true; return true;
} }
uint64_t AudioServer::update() void AudioServer::update()
{ {
// FIXME: get this from the kernel
static constexpr uint64_t kernel_buffer_ms = 50;
uint32_t kernel_buffer_size; uint32_t kernel_buffer_size;
if (ioctl(m_audio_device_fd, SND_GET_BUFFERSZ, &kernel_buffer_size) == -1) if (ioctl(m_audio_device_fd, SND_GET_BUFFERSZ, &kernel_buffer_size) == -1)
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@ -82,17 +72,14 @@ uint64_t AudioServer::update()
const size_t max_sample_frames = (m_samples.capacity() - m_samples.size()) / m_channels; const size_t max_sample_frames = (m_samples.capacity() - m_samples.size()) / m_channels;
const size_t queued_samples_end = m_samples.size(); const size_t queued_samples_end = m_samples.size();
if (max_sample_frames == 0) if (max_sample_frames == 0)
return kernel_buffer_ms; return;
size_t max_sample_frames_to_queue = max_sample_frames;
bool anyone_playing = false;
for (auto& [_, buffer] : m_audio_buffers) for (auto& [_, buffer] : m_audio_buffers)
{ {
if (buffer.buffer == nullptr) if (buffer.buffer == nullptr)
continue; continue;
const sample_t sample_ratio = buffer.buffer->sample_rate / static_cast<sample_t>(m_sample_rate); const double sample_ratio = buffer.buffer->sample_rate / static_cast<double>(m_sample_rate);
if (buffer.sample_frames_queued) if (buffer.sample_frames_queued)
{ {
@ -104,38 +91,13 @@ uint64_t AudioServer::update()
buffer.sample_frames_queued -= buffer_sample_frames_played; 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_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; const uint32_t buffer_sample_frames_available = (buffer_total_sample_frames - buffer.sample_frames_queued) / sample_ratio;
if (buffer_sample_frames_available == 0) if (buffer_sample_frames_available == 0)
continue; continue;
const size_t sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames_to_queue, buffer_sample_frames_available); const size_t sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames, buffer_sample_frames_available);
if (sample_frames_to_queue < samples_per_10ms) if (sample_frames_to_queue == 0)
continue; continue;
while (m_samples.size() < queued_samples_end + sample_frames_to_queue * m_channels) while (m_samples.size() < queued_samples_end + sample_frames_to_queue * m_channels)
@ -151,17 +113,10 @@ uint64_t 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]; 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 += BAN::Math::min<uint32_t>( buffer.sample_frames_queued += sample_frames_to_queue * sample_ratio;
buffer_total_sample_frames,
BAN::Math::ceil(sample_frames_to_queue * sample_ratio)
);
} }
send_samples(); 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() void AudioServer::reset_kernel_buffer()

View File

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

View File

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

View File

@ -8,7 +8,6 @@
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
struct config_t struct config_t
@ -38,9 +37,6 @@ struct full_entry_t
BAN::String full_name; BAN::String full_name;
}; };
bool g_stdout_terminal { false };
winsize g_terminal_size {};
const char* entry_color(mode_t mode) const char* entry_color(mode_t mode)
{ {
// TODO: handle suid, sgid, sticky // TODO: handle suid, sgid, sticky
@ -120,37 +116,6 @@ BAN::String build_time_string(BAN::Time time)
return MUST(BAN::String::formatted("{2}:{2}", time.hour, time.minute)); 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) int list_directory(const BAN::String& path, config_t config)
{ {
static char link_buffer[PATH_MAX]; static char link_buffer[PATH_MAX];
@ -233,59 +198,14 @@ int list_directory(const BAN::String& path, config_t config)
if (!config.list) if (!config.list)
{ {
if (!g_stdout_terminal) for (size_t i = 0; i < entries.size(); i++)
{ {
for (const auto& entry : entries) if (i > 0)
printf("%s\n", entry.name.data()); printf(" ");
return ret; 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");
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(" ");
printf(format, entry_color(entries[i].st.st_mode), entries[i].name.data());
}
printf("\n");
}
}
return ret; return ret;
} }
@ -406,8 +326,6 @@ int main(int argc, const char* argv[])
else for (; i < argc; i++) else for (; i < argc; i++)
MUST(files.emplace_back(BAN::StringView(argv[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; int ret = 0;
for (size_t i = 0; i < files.size(); i++) for (size_t i = 0; i < files.size(); i++)
{ {