Compare commits
17 Commits
3aa20a3a32
...
06015d006d
Author | SHA1 | Date |
---|---|---|
|
06015d006d | |
|
0dbfd8ac66 | |
|
58c1fd36b9 | |
|
2f725848f4 | |
|
6250710bbd | |
|
028024b0da | |
|
4f61230506 | |
|
309ec660b6 | |
|
695262624d | |
|
c96c264801 | |
|
af0bca74e4 | |
|
f41e254e35 | |
|
7e472a9c1d | |
|
ee3f10313a | |
|
5b587d199e | |
|
009b073892 | |
|
92e962430b |
|
@ -35,10 +35,8 @@ namespace Kernel
|
|||
|
||||
bool has_egid(gid_t) const;
|
||||
|
||||
BAN::ErrorOr<void> initialize_supplementary_groups();
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<BAN::String> find_username() const;
|
||||
BAN::Span<const gid_t> groups() const { return m_supplementary.span(); }
|
||||
BAN::ErrorOr<void> set_groups(BAN::Span<const gid_t> groups);
|
||||
|
||||
private:
|
||||
uid_t m_ruid, m_euid, m_suid;
|
||||
|
|
|
@ -20,6 +20,6 @@ namespace Kernel::ELF
|
|||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode>, const Credentials&, PageTable&);
|
||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials&, PageTable&);
|
||||
|
||||
}
|
||||
|
|
|
@ -71,13 +71,13 @@ namespace Kernel
|
|||
|
||||
File root_file()
|
||||
{
|
||||
return File(root_inode(), "/"_sv);
|
||||
return File { root_inode(), "/"_sv };
|
||||
}
|
||||
|
||||
BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int);
|
||||
BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags)
|
||||
BAN::ErrorOr<File> file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials&, BAN::StringView, int);
|
||||
BAN::ErrorOr<File> file_from_absolute_path(BAN::RefPtr<Inode> root_inode, const Credentials& credentials, BAN::StringView path, int flags)
|
||||
{
|
||||
return file_from_relative_path(root_file(), credentials, path, flags);
|
||||
return file_from_relative_path(root_inode, File { root_inode, "/"_sv }, credentials, path, flags);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/HashMap.h>
|
||||
#include <BAN/Endianness.h>
|
||||
#include <BAN/Queue.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
|
@ -63,6 +64,8 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
virtual bool can_read_impl() const override;
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <BAN/WeakPtr.h>
|
||||
#include <kernel/FS/Socket.h>
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
|
||||
namespace Kernel
|
||||
|
@ -39,8 +40,8 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan);
|
||||
|
||||
bool is_bound() const { return !m_bound_path.empty(); }
|
||||
bool is_bound_to_unused() const { return m_bound_path == "X"_sv; }
|
||||
bool is_bound() const { return !m_bound_file.canonical_path.empty(); }
|
||||
bool is_bound_to_unused() const { return !m_bound_file.inode; }
|
||||
|
||||
bool is_streaming() const;
|
||||
|
||||
|
@ -63,7 +64,7 @@ namespace Kernel
|
|||
|
||||
private:
|
||||
const Socket::Type m_socket_type;
|
||||
BAN::String m_bound_path;
|
||||
VirtualFileSystem::File m_bound_file;
|
||||
|
||||
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size);
|
||||
BAN::ErrorOr<long> sys_chdir(const char* path);
|
||||
BAN::ErrorOr<long> sys_fchdir(int fildes);
|
||||
BAN::ErrorOr<long> sys_chroot(const char* path);
|
||||
|
||||
BAN::ErrorOr<long> sys_setuid(uid_t);
|
||||
BAN::ErrorOr<long> sys_setgid(gid_t);
|
||||
|
@ -95,6 +96,9 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_getppid() const { return m_parent; }
|
||||
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
|
||||
|
||||
BAN::ErrorOr<long> sys_getgroups(gid_t groups[], size_t count);
|
||||
BAN::ErrorOr<long> sys_setgroups(const gid_t groups[], size_t count);
|
||||
|
||||
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags);
|
||||
|
||||
BAN::ErrorOr<void> create_file_or_dir(int fd, const char* path, mode_t mode) const;
|
||||
|
@ -231,6 +235,7 @@ namespace Kernel
|
|||
static void update_alarm_queue();
|
||||
|
||||
const VirtualFileSystem::File& working_directory() const { return m_working_directory; }
|
||||
const VirtualFileSystem::File& root_file() const { return m_root_file; }
|
||||
|
||||
private:
|
||||
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
||||
|
@ -310,6 +315,7 @@ namespace Kernel
|
|||
mutable Mutex m_process_lock;
|
||||
|
||||
VirtualFileSystem::File m_working_directory;
|
||||
VirtualFileSystem::File m_root_file;
|
||||
|
||||
BAN::Vector<Thread*> m_threads;
|
||||
|
||||
|
@ -334,6 +340,8 @@ namespace Kernel
|
|||
BAN::Vector<ChildExitStatus> m_child_exit_statuses;
|
||||
ThreadBlocker m_child_exit_blocker;
|
||||
|
||||
BAN::Atomic<bool> m_is_exiting { false };
|
||||
|
||||
bool m_has_called_exec { false };
|
||||
|
||||
BAN::UniqPtr<PageTable> m_page_table;
|
||||
|
|
|
@ -243,14 +243,27 @@ namespace Kernel::ACPI::AML
|
|||
|
||||
BAN::ErrorOr<void> Namespace::initialize_op_regions()
|
||||
{
|
||||
struct FullNode
|
||||
{
|
||||
Scope scope;
|
||||
Reference* reference;
|
||||
};
|
||||
|
||||
BAN::Vector<FullNode> op_regions;
|
||||
|
||||
for (const auto& [obj_path, obj_ref] : m_named_objects)
|
||||
{
|
||||
if (obj_ref->node.type != Node::Type::OpRegion)
|
||||
continue;
|
||||
// FIXME: if _REG adds stuff to namespace, iterators are invalidated
|
||||
(void)opregion_call_reg(obj_path, obj_ref->node);
|
||||
TRY(op_regions.emplace_back(
|
||||
TRY(obj_path.copy()),
|
||||
obj_ref
|
||||
));
|
||||
}
|
||||
|
||||
for (const auto& [obj_path, obj_ref] : op_regions)
|
||||
(void)opregion_call_reg(obj_path, obj_ref->node);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,157 +1,9 @@
|
|||
#include <kernel/Credentials.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
static id_t parse_id(BAN::StringView line)
|
||||
{
|
||||
id_t id = 0;
|
||||
for (char c : line)
|
||||
{
|
||||
if (!isdigit(c))
|
||||
return -1;
|
||||
id = (id * 10) + (c - '0');
|
||||
}
|
||||
return id;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<BAN::String> Credentials::find_username() const
|
||||
{
|
||||
auto inode = TRY(VirtualFileSystem::get().file_from_absolute_path(*this, "/etc/passwd"_sv, O_RDONLY)).inode;
|
||||
|
||||
BAN::String line;
|
||||
off_t offset = 0;
|
||||
uint8_t buffer[128];
|
||||
while (offset < inode->size())
|
||||
{
|
||||
size_t nread = TRY(inode->read(offset, { buffer, sizeof(buffer) }));
|
||||
|
||||
bool line_done = false;
|
||||
for (size_t i = 0; i < nread; i++)
|
||||
{
|
||||
if (buffer[i] == '\n')
|
||||
{
|
||||
TRY(line.append({ (const char*)buffer, i }));
|
||||
line_done = true;
|
||||
offset += i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!line_done)
|
||||
{
|
||||
offset += nread;
|
||||
TRY(line.append({ (const char*)buffer, nread }));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto parts = TRY(line.sv().split(':', true));
|
||||
if (parts.size() == 7 && m_euid == parse_id(parts[2]))
|
||||
{
|
||||
BAN::String result;
|
||||
TRY(result.append(parts[0]));
|
||||
return result;
|
||||
}
|
||||
|
||||
line.clear();
|
||||
}
|
||||
|
||||
auto parts = TRY(line.sv().split(':', true));
|
||||
if (parts.size() == 7 && m_euid == parse_id(parts[2]))
|
||||
{
|
||||
BAN::String result;
|
||||
TRY(result.append(parts[0]));
|
||||
return result;
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Credentials::initialize_supplementary_groups()
|
||||
{
|
||||
m_supplementary.clear();
|
||||
|
||||
auto username = TRY(find_username());
|
||||
|
||||
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path(*this, "/etc/group", O_RDONLY);
|
||||
if (file_or_error.is_error())
|
||||
{
|
||||
if (file_or_error.error().get_error_code() == ENOENT)
|
||||
return {};
|
||||
return file_or_error.error();
|
||||
}
|
||||
|
||||
auto inode = file_or_error.value().inode;
|
||||
|
||||
BAN::String line;
|
||||
off_t offset = 0;
|
||||
uint8_t buffer[128];
|
||||
while (offset < inode->size())
|
||||
{
|
||||
size_t nread = TRY(inode->read(offset, { buffer, sizeof(buffer) }));
|
||||
|
||||
bool line_done = false;
|
||||
for (size_t i = 0; i < nread; i++)
|
||||
{
|
||||
if (buffer[i] == '\n')
|
||||
{
|
||||
TRY(line.append({ (const char*)buffer, i }));
|
||||
line_done = true;
|
||||
offset += i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!line_done)
|
||||
{
|
||||
offset += nread;
|
||||
TRY(line.append({ (const char*)buffer, nread }));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto parts = TRY(line.sv().split(':', true));
|
||||
if (parts.size() != 4)
|
||||
{
|
||||
line.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto users = TRY(parts[3].split(','));
|
||||
for (auto user : users)
|
||||
{
|
||||
if (user != username)
|
||||
continue;
|
||||
if (gid_t gid = parse_id(parts[2]); gid != -1)
|
||||
{
|
||||
TRY(m_supplementary.push_back(gid));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line.clear();
|
||||
}
|
||||
|
||||
auto parts = TRY(line.sv().split(':', true));
|
||||
if (parts.size() == 4)
|
||||
{
|
||||
auto users = TRY(parts[3].split(','));
|
||||
for (auto user : users)
|
||||
{
|
||||
if (user != username)
|
||||
continue;
|
||||
if (gid_t gid = parse_id(parts[2]); gid != -1)
|
||||
{
|
||||
TRY(m_supplementary.push_back(gid));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool Credentials::has_egid(gid_t gid) const
|
||||
{
|
||||
if (m_egid == gid)
|
||||
|
@ -162,4 +14,13 @@ namespace Kernel
|
|||
return false;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Credentials::set_groups(BAN::Span<const gid_t> groups)
|
||||
{
|
||||
m_supplementary.clear();
|
||||
TRY(m_supplementary.resize(groups.size()));
|
||||
for (size_t i = 0; i < groups.size(); i++)
|
||||
m_supplementary[i] = groups[i];
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace Kernel::ELF
|
|||
return BAN::move(program_headers);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> inode, const Credentials& credentials, PageTable& page_table)
|
||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials& credentials, PageTable& page_table)
|
||||
{
|
||||
auto file_header = TRY(read_and_validate_file_header(inode));
|
||||
auto program_headers = TRY(read_program_headers(inode, file_header));
|
||||
|
@ -143,7 +143,7 @@ namespace Kernel::ELF
|
|||
|
||||
if (!interpreter.empty())
|
||||
{
|
||||
auto interpreter_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, interpreter, O_EXEC)).inode;
|
||||
auto interpreter_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(root, credentials, interpreter, O_EXEC)).inode;
|
||||
auto interpreter_file_header = TRY(read_and_validate_file_header(interpreter_inode));
|
||||
auto interpreter_program_headers = TRY(read_program_headers(interpreter_inode, interpreter_file_header));
|
||||
|
||||
|
|
|
@ -186,7 +186,8 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView block_device_path, BAN::StringView target)
|
||||
{
|
||||
auto block_device_file = TRY(file_from_absolute_path(credentials, block_device_path, true));
|
||||
// TODO: allow custom root
|
||||
auto block_device_file = TRY(file_from_absolute_path(root_inode(), credentials, block_device_path, true));
|
||||
if (!block_device_file.inode->is_device())
|
||||
return BAN::Error::from_errno(ENOTBLK);
|
||||
|
||||
|
@ -200,7 +201,8 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::RefPtr<FileSystem> file_system, BAN::StringView path)
|
||||
{
|
||||
auto file = TRY(file_from_absolute_path(credentials, path, true));
|
||||
// TODO: allow custom root
|
||||
auto file = TRY(file_from_absolute_path(root_inode(), credentials, path, true));
|
||||
if (!file.inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
|
||||
|
@ -227,7 +229,7 @@ namespace Kernel
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
|
||||
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
|
@ -269,6 +271,8 @@ namespace Kernel
|
|||
auto orig = inode;
|
||||
|
||||
// resolve file name
|
||||
{
|
||||
if (!(inode == root_inode && path_part == ".."_sv))
|
||||
{
|
||||
auto parent_inode = inode;
|
||||
if (path_part == ".."_sv)
|
||||
|
@ -277,6 +281,7 @@ namespace Kernel
|
|||
if (!parent_inode->can_access(credentials, O_SEARCH))
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
inode = TRY(parent_inode->find_inode(path_part));
|
||||
}
|
||||
|
||||
if (path_part == ".."_sv)
|
||||
{
|
||||
|
@ -310,7 +315,7 @@ namespace Kernel
|
|||
|
||||
if (link_target.front() == '/')
|
||||
{
|
||||
inode = root_inode();
|
||||
inode = root_inode;
|
||||
canonical_path.clear();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
@ -255,6 +256,18 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case FIONREAD:
|
||||
*static_cast<int*>(argument) = m_recv_window.data_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return NetworkSocket::ioctl_impl(request, argument);
|
||||
}
|
||||
|
||||
bool TCPSocket::can_read_impl() const
|
||||
{
|
||||
if (m_has_connected && !m_has_sent_zero && m_state != State::Established && m_state != State::Listen)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <kernel/Thread.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
@ -138,4 +139,22 @@ namespace Kernel
|
|||
return TRY(m_network_layer.sendto(*this, message, address, address_len));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case FIONREAD:
|
||||
{
|
||||
SpinLockGuard guard(m_packet_lock);
|
||||
if (m_packets.empty())
|
||||
*static_cast<int*>(argument) = 0;
|
||||
else
|
||||
*static_cast<int*>(argument) = m_packets.front().packet_size;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NetworkSocket::ioctl_impl(request, argument);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,15 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
static BAN::HashMap<BAN::String, BAN::WeakPtr<UnixDomainSocket>> s_bound_sockets;
|
||||
struct UnixSocketHash
|
||||
{
|
||||
BAN::hash_t operator()(const BAN::RefPtr<Inode>& socket)
|
||||
{
|
||||
return BAN::hash<const Inode*>{}(socket.ptr());
|
||||
}
|
||||
};
|
||||
|
||||
static BAN::HashMap<BAN::RefPtr<Inode>, BAN::WeakPtr<UnixDomainSocket>, UnixSocketHash> s_bound_sockets;
|
||||
static SpinLock s_bound_socket_lock;
|
||||
|
||||
static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE;
|
||||
|
@ -57,9 +65,7 @@ namespace Kernel
|
|||
if (is_bound() && !is_bound_to_unused())
|
||||
{
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
auto it = s_bound_sockets.find(m_bound_path);
|
||||
if (it != s_bound_sockets.end())
|
||||
s_bound_sockets.remove(it);
|
||||
s_bound_sockets.remove(m_bound_file.inode);
|
||||
}
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
|
@ -117,17 +123,22 @@ namespace Kernel
|
|||
return_inode = reinterpret_cast<UnixDomainSocket*>(return_inode_tmp.ptr());
|
||||
}
|
||||
|
||||
TRY(return_inode->m_bound_path.push_back('X'));
|
||||
TRY(return_inode->m_bound_file.canonical_path.push_back('X'));
|
||||
return_inode->m_info.get<ConnectionInfo>().connection = TRY(pending->get_weak_ptr());
|
||||
pending->m_info.get<ConnectionInfo>().connection = TRY(return_inode->get_weak_ptr());
|
||||
pending->m_info.get<ConnectionInfo>().connection_done = true;
|
||||
|
||||
if (address && address_len && !is_bound_to_unused())
|
||||
{
|
||||
size_t copy_len = BAN::Math::min<size_t>(*address_len, sizeof(sockaddr) + m_bound_path.size() + 1);
|
||||
auto& sockaddr_un = *reinterpret_cast<struct sockaddr_un*>(address);
|
||||
sockaddr_un.sun_family = AF_UNIX;
|
||||
strncpy(sockaddr_un.sun_path, pending->m_bound_path.data(), copy_len);
|
||||
sockaddr_un sa_un {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path {},
|
||||
};
|
||||
strcpy(sa_un.sun_path, pending->m_bound_file.canonical_path.data());
|
||||
|
||||
const size_t to_copy = BAN::Math::min<size_t>(*address_len, sizeof(sockaddr_un));
|
||||
memcpy(address, &sa_un, to_copy);
|
||||
*address_len = to_copy;
|
||||
}
|
||||
|
||||
return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<unix socket>"_sv), O_RDWR | flags));
|
||||
|
@ -141,10 +152,11 @@ namespace Kernel
|
|||
if (sockaddr_un.sun_family != AF_UNIX)
|
||||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||
if (!is_bound())
|
||||
TRY(m_bound_path.push_back('X'));
|
||||
TRY(m_bound_file.canonical_path.push_back('X'));
|
||||
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
|
||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||
Process::current().root_file().inode,
|
||||
Process::current().credentials(),
|
||||
absolute_path,
|
||||
O_RDWR
|
||||
|
@ -154,7 +166,7 @@ namespace Kernel
|
|||
|
||||
{
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
auto it = s_bound_sockets.find(file.canonical_path);
|
||||
auto it = s_bound_sockets.find(file.inode);
|
||||
if (it == s_bound_sockets.end())
|
||||
return BAN::Error::from_errno(ECONNREFUSED);
|
||||
target = it->value.lock();
|
||||
|
@ -236,7 +248,7 @@ namespace Kernel
|
|||
|
||||
// FIXME: This feels sketchy
|
||||
auto parent_file = bind_path.front() == '/'
|
||||
? VirtualFileSystem::get().root_file()
|
||||
? TRY(Process::current().root_file().clone())
|
||||
: TRY(Process::current().working_directory().clone());
|
||||
if (auto ret = Process::current().create_file_or_dir(AT_FDCWD, bind_path.data(), 0755 | S_IFSOCK); ret.is_error())
|
||||
{
|
||||
|
@ -245,6 +257,7 @@ namespace Kernel
|
|||
return ret.release_error();
|
||||
}
|
||||
auto file = TRY(VirtualFileSystem::get().file_from_relative_path(
|
||||
Process::current().root_file().inode,
|
||||
parent_file,
|
||||
Process::current().credentials(),
|
||||
bind_path,
|
||||
|
@ -252,10 +265,10 @@ namespace Kernel
|
|||
));
|
||||
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
if (s_bound_sockets.contains(file.canonical_path))
|
||||
if (s_bound_sockets.contains(file.inode))
|
||||
return BAN::Error::from_errno(EADDRINUSE);
|
||||
TRY(s_bound_sockets.emplace(file.canonical_path, TRY(get_weak_ptr())));
|
||||
m_bound_path = BAN::move(file.canonical_path);
|
||||
TRY(s_bound_sockets.emplace(file.inode, TRY(get_weak_ptr())));
|
||||
m_bound_file = BAN::move(file);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -354,14 +367,21 @@ namespace Kernel
|
|||
}
|
||||
else
|
||||
{
|
||||
BAN::String canonical_path;
|
||||
BAN::RefPtr<Inode> target_inode;
|
||||
|
||||
if (!address)
|
||||
{
|
||||
auto& connectionless_info = m_info.get<ConnectionlessInfo>();
|
||||
if (connectionless_info.peer_address.empty())
|
||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||
TRY(canonical_path.append(connectionless_info.peer_address));
|
||||
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(connectionless_info.peer_address));
|
||||
target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||
Process::current().root_file().inode,
|
||||
Process::current().credentials(),
|
||||
absolute_path,
|
||||
O_RDWR
|
||||
)).inode;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -372,17 +392,16 @@ namespace Kernel
|
|||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||
|
||||
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
|
||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||
target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||
Process::current().root_file().inode,
|
||||
Process::current().credentials(),
|
||||
absolute_path,
|
||||
O_WRONLY
|
||||
));
|
||||
|
||||
canonical_path = BAN::move(file.canonical_path);
|
||||
)).inode;
|
||||
}
|
||||
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
auto it = s_bound_sockets.find(canonical_path);
|
||||
auto it = s_bound_sockets.find(target_inode);
|
||||
if (it == s_bound_sockets.end())
|
||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||
auto target = it->value.lock();
|
||||
|
@ -449,20 +468,11 @@ namespace Kernel
|
|||
if (!connection)
|
||||
return BAN::Error::from_errno(ENOTCONN);
|
||||
|
||||
sockaddr_un sa_un;
|
||||
sa_un.sun_family = AF_UNIX;
|
||||
sa_un.sun_path[0] = 0;
|
||||
|
||||
{
|
||||
SpinLockGuard _(s_bound_socket_lock);
|
||||
for (auto& [path, socket] : s_bound_sockets)
|
||||
{
|
||||
if (socket.lock() != connection)
|
||||
continue;
|
||||
strcpy(sa_un.sun_path, path.data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
sockaddr_un sa_un {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = {},
|
||||
};
|
||||
strcpy(sa_un.sun_path, connection->m_bound_file.canonical_path.data());
|
||||
|
||||
const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len);
|
||||
memcpy(address, &sa_un, to_copy);
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags)
|
||||
{
|
||||
return open(TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags)), flags);
|
||||
return open(TRY(VirtualFileSystem::get().file_from_absolute_path(Process::current().root_file().inode, m_credentials, absolute_path, flags)), flags);
|
||||
}
|
||||
|
||||
struct SocketInfo
|
||||
|
|
|
@ -101,9 +101,10 @@ namespace Kernel
|
|||
BAN::ErrorOr<Process*> Process::create_userspace(const Credentials& credentials, BAN::StringView path, BAN::Span<BAN::StringView> arguments)
|
||||
{
|
||||
auto* process = create_process(credentials, 0);
|
||||
TRY(process->m_credentials.initialize_supplementary_groups());
|
||||
|
||||
process->m_working_directory = VirtualFileSystem::get().root_file();
|
||||
process->m_root_file = VirtualFileSystem::get().root_file();
|
||||
|
||||
process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace()));
|
||||
|
||||
TRY(process->m_cmdline.emplace_back());
|
||||
|
@ -119,7 +120,7 @@ namespace Kernel
|
|||
auto executable_file = TRY(process->find_file(AT_FDCWD, path.data(), O_EXEC));
|
||||
auto executable_inode = executable_file.inode;
|
||||
|
||||
auto executable = TRY(ELF::load_from_inode(executable_inode, process->m_credentials, process->page_table()));
|
||||
auto executable = TRY(ELF::load_from_inode(process->m_root_file.inode, executable_inode, process->m_credentials, process->page_table()));
|
||||
process->m_mapped_regions = BAN::move(executable.regions);
|
||||
|
||||
if (executable_inode->mode().mode & +Inode::Mode::ISUID)
|
||||
|
@ -257,6 +258,16 @@ namespace Kernel
|
|||
|
||||
void Process::exit(int status, int signal)
|
||||
{
|
||||
bool expected = false;
|
||||
if (!m_is_exiting.compare_exchange(expected, true))
|
||||
{
|
||||
Thread::current().on_exit();
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
const auto state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||
|
||||
if (m_parent)
|
||||
{
|
||||
Process* parent_process = nullptr;
|
||||
|
@ -294,13 +305,18 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_threads.size(); i++)
|
||||
{
|
||||
if (m_threads[i] == &Thread::current())
|
||||
continue;
|
||||
m_threads[i]->add_signal(SIGKILL);
|
||||
LockGuard _(m_process_lock);
|
||||
for (auto* thread : m_threads)
|
||||
if (thread != &Thread::current())
|
||||
ASSERT(thread->add_signal(SIGKILL));
|
||||
}
|
||||
|
||||
while (m_threads.size() > 1)
|
||||
Processor::yield();
|
||||
|
||||
Processor::set_interrupt_state(state);
|
||||
|
||||
Thread::current().on_exit();
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
|
@ -442,7 +458,7 @@ namespace Kernel
|
|||
|
||||
auto parent_file = TRY(find_relative_parent(fd, path));
|
||||
auto file = path
|
||||
? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags))
|
||||
? TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent_file, m_credentials, path, flags))
|
||||
: BAN::move(parent_file);
|
||||
|
||||
return file;
|
||||
|
@ -466,7 +482,7 @@ namespace Kernel
|
|||
|
||||
if (auto index = path_sv.rfind('/'); index.has_value())
|
||||
{
|
||||
parent = TRY(VirtualFileSystem::get().file_from_relative_path(relative_parent, m_credentials, path_sv.substring(0, index.value()), flags));
|
||||
parent = TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, relative_parent, m_credentials, path_sv.substring(0, index.value()), flags));
|
||||
file_name = path_sv.substring(index.value() + 1);
|
||||
}
|
||||
else
|
||||
|
@ -496,7 +512,7 @@ namespace Kernel
|
|||
ASSERT(m_process_lock.is_locked());
|
||||
|
||||
if (path && path[0] == '/')
|
||||
return VirtualFileSystem::get().root_file();
|
||||
return TRY(m_root_file.clone());
|
||||
|
||||
if (fd == AT_FDCWD)
|
||||
return TRY(m_working_directory.clone());
|
||||
|
@ -507,7 +523,6 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> Process::sys_exit(int status)
|
||||
{
|
||||
ASSERT(this == &Process::current());
|
||||
LockGuard _(m_process_lock);
|
||||
exit(status, 0);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
@ -569,6 +584,7 @@ namespace Kernel
|
|||
}
|
||||
|
||||
auto working_directory = TRY(m_working_directory.clone());
|
||||
auto root_file = TRY(m_root_file.clone());
|
||||
|
||||
BAN::Vector<BAN::String> cmdline;
|
||||
TRY(cmdline.resize(m_cmdline.size()));
|
||||
|
@ -591,6 +607,7 @@ namespace Kernel
|
|||
Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp);
|
||||
forked->m_controlling_terminal = m_controlling_terminal;
|
||||
forked->m_working_directory = BAN::move(working_directory);
|
||||
forked->m_root_file = BAN::move(root_file);
|
||||
forked->m_cmdline = BAN::move(cmdline);
|
||||
forked->m_environ = BAN::move(environ);
|
||||
forked->m_page_table = BAN::move(page_table);
|
||||
|
@ -643,7 +660,7 @@ namespace Kernel
|
|||
auto executable_file = TRY(find_file(AT_FDCWD, path, O_EXEC));
|
||||
auto executable_inode = executable_file.inode;
|
||||
|
||||
auto executable = TRY(ELF::load_from_inode(executable_inode, m_credentials, *new_page_table));
|
||||
auto executable = TRY(ELF::load_from_inode(m_root_file.inode, executable_inode, m_credentials, *new_page_table));
|
||||
auto new_mapped_regions = BAN::move(executable.regions);
|
||||
|
||||
BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector;
|
||||
|
@ -1031,7 +1048,7 @@ namespace Kernel
|
|||
TRY(validate_string_access(path));
|
||||
|
||||
auto [parent, file_name] = TRY(find_parent_file(fd, path, O_RDONLY));
|
||||
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, file_name, flags);
|
||||
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent, m_credentials, file_name, flags);
|
||||
|
||||
VirtualFileSystem::File file;
|
||||
if (file_or_error.is_error())
|
||||
|
@ -1041,7 +1058,7 @@ namespace Kernel
|
|||
|
||||
// FIXME: There is a race condition between next two lines
|
||||
TRY(parent.inode->create_file(file_name, (mode & 0777) | Inode::Mode::IFREG, m_credentials.euid(), m_credentials.egid()));
|
||||
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, file_name, flags & ~O_RDWR));
|
||||
file = TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent, m_credentials, file_name, flags & ~O_RDWR));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1122,7 +1139,7 @@ namespace Kernel
|
|||
credentials.set_egid(credentials.rgid());
|
||||
|
||||
auto relative_parent = TRY(find_relative_parent(AT_FDCWD, path));
|
||||
TRY(VirtualFileSystem::get().file_from_relative_path(relative_parent, credentials, path, flags));
|
||||
TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, relative_parent, credentials, path, flags));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1245,6 +1262,7 @@ namespace Kernel
|
|||
flag = O_NOFOLLOW;
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_string_access(path));
|
||||
|
||||
auto inode = TRY(find_file(fd, path, flag)).inode;
|
||||
|
||||
|
@ -1267,6 +1285,7 @@ namespace Kernel
|
|||
flag = O_NOFOLLOW;
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_string_access(path));
|
||||
|
||||
auto inode = TRY(find_file(fd, path, flag)).inode;
|
||||
|
||||
|
@ -2082,22 +2101,25 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> Process::sys_chdir(const char* path)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
TRY(validate_string_access(path));
|
||||
|
||||
auto file = TRY(find_file(AT_FDCWD, path, O_SEARCH));
|
||||
m_working_directory = BAN::move(file);
|
||||
|
||||
m_working_directory = TRY(find_file(AT_FDCWD, path, O_SEARCH));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_fchdir(int fildes)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
m_working_directory = TRY(m_open_file_descriptors.file_of(fildes));
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto file = TRY(m_open_file_descriptors.file_of(fildes));
|
||||
m_working_directory = BAN::move(file);
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_chroot(const char* path)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_string_access(path));
|
||||
if (!m_credentials.is_superuser())
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
m_root_file = TRY(find_file(AT_FDCWD, path, O_SEARCH));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2905,7 +2927,6 @@ namespace Kernel
|
|||
m_credentials.set_euid(uid);
|
||||
m_credentials.set_ruid(uid);
|
||||
m_credentials.set_suid(uid);
|
||||
TRY(m_credentials.initialize_supplementary_groups());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2914,7 +2935,6 @@ namespace Kernel
|
|||
if (uid == m_credentials.ruid() || uid == m_credentials.suid())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
TRY(m_credentials.initialize_supplementary_groups());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2975,7 +2995,6 @@ namespace Kernel
|
|||
if (uid == m_credentials.ruid() || uid == m_credentials.suid() || m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
TRY(m_credentials.initialize_supplementary_groups());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3042,8 +3061,6 @@ namespace Kernel
|
|||
if (euid != -1)
|
||||
m_credentials.set_euid(euid);
|
||||
|
||||
TRY(m_credentials.initialize_supplementary_groups());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3191,6 +3208,28 @@ namespace Kernel
|
|||
return BAN::Error::from_errno(error);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_getgroups(gid_t groups[], size_t count)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(groups, count * sizeof(gid_t), true));
|
||||
auto current = m_credentials.groups();
|
||||
if (current.size() > count)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
for (size_t i = 0; i < current.size(); i++)
|
||||
groups[i] = current[i];
|
||||
return current.size();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_setgroups(const gid_t groups[], size_t count)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(groups, count * sizeof(gid_t), true));
|
||||
if (!m_credentials.is_superuser())
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
TRY(m_credentials.set_groups({ groups, count }));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> Process::absolute_path_of(BAN::StringView path) const
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
|
|
@ -121,8 +121,8 @@ namespace Kernel
|
|||
void TTY::keyboard_task(void*)
|
||||
{
|
||||
BAN::RefPtr<Inode> keyboard_inode;
|
||||
if (auto ret = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard"_sv, O_RDONLY); !ret.is_error())
|
||||
keyboard_inode = ret.value().inode;
|
||||
if (auto ret = DevFileSystem::get().root_inode()->find_inode("keyboard"_sv); !ret.is_error())
|
||||
keyboard_inode = ret.release_value();
|
||||
else
|
||||
{
|
||||
dprintln("could not open keyboard device: {}", ret.error());
|
||||
|
|
|
@ -40,10 +40,9 @@ namespace Kernel
|
|||
switch (m_speed_class)
|
||||
{
|
||||
case USB::SpeedClass::LowSpeed:
|
||||
case USB::SpeedClass::FullSpeed:
|
||||
m_endpoints[0].max_packet_size = 8;
|
||||
is_ls_or_fs_device_on_hs_hub = m_info.parent_hub && (m_info.parent_hub->speed_class() == USB::SpeedClass::HighSpeed);
|
||||
break;
|
||||
case USB::SpeedClass::FullSpeed:
|
||||
case USB::SpeedClass::HighSpeed:
|
||||
m_endpoints[0].max_packet_size = 64;
|
||||
break;
|
||||
|
@ -53,6 +52,16 @@ namespace Kernel
|
|||
default: ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
switch (m_speed_class)
|
||||
{
|
||||
case USB::SpeedClass::LowSpeed:
|
||||
case USB::SpeedClass::FullSpeed:
|
||||
is_ls_or_fs_device_on_hs_hub = m_info.parent_hub && (m_info.parent_hub->speed_class() == USB::SpeedClass::HighSpeed);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_input_context = TRY(DMARegion::create(33 * context_size));
|
||||
memset(reinterpret_cast<void*>(m_input_context->vaddr()), 0, m_input_context->size());
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='SDL2_mixer'
|
||||
VERSION='2.8.1'
|
||||
DOWNLOAD_URL="https://github.com/libsdl-org/SDL_mixer/releases/download/release-$VERSION/SDL2_mixer-$VERSION.tar.gz#cb760211b056bfe44f4a1e180cc7cb201137e4d1572f2002cc1be728efd22660"
|
||||
DEPENDENCIES=('SDL2')
|
||||
|
||||
configure() {
|
||||
$BANAN_CMAKE --fresh -S . -B build -G Ninja \
|
||||
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||
-DCMAKE_INSTALL_PREFIX='/usr' \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DSDL2MIXER_WAVPACK=OFF \
|
||||
-DSDL2MIXER_MIDI=OFF \
|
||||
-DSDL2MIXER_OPUS=OFF \
|
||||
-DSDL2MIXER_MOD=OFF \
|
||||
|| exit 1
|
||||
}
|
||||
|
||||
build() {
|
||||
$BANAN_CMAKE --build build || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
$BANAN_CMAKE --install build || exit 1
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
NAME='binutils'
|
||||
VERSION='2.44'
|
||||
DOWNLOAD_URL="https://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.gz#0cdd76777a0dfd3dd3a63f215f030208ddb91c2361d2bcc02acec0f1c16b6a2e"
|
||||
DEPENDENCIES=('zlib')
|
||||
DEPENDENCIES=('zlib' 'zstd')
|
||||
MAKE_INSTALL_TARGETS=('install-strip')
|
||||
CONFIGURE_OPTIONS=(
|
||||
"--target=$BANAN_TOOLCHAIN_TRIPLE"
|
||||
|
@ -16,6 +16,13 @@ CONFIGURE_OPTIONS=(
|
|||
'--disable-werror'
|
||||
)
|
||||
|
||||
pre_configure() {
|
||||
unset PKG_CONFIG_DIR
|
||||
unset PKG_CONFIG_SYSROOT_DIR
|
||||
unset PKG_CONFIG_LIBDIR
|
||||
unset PKG_CONFIG_PATH
|
||||
}
|
||||
|
||||
post_install() {
|
||||
# remove libtool files
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libbfd.la
|
||||
|
|
|
@ -2,20 +2,22 @@
|
|||
|
||||
NAME='doom'
|
||||
VERSION='git'
|
||||
DOWNLOAD_URL="https://github.com/ozkl/doomgeneric.git#613f870b6fa83ede448a247de5a2571092fa729d"
|
||||
DOWNLOAD_URL="https://github.com/ozkl/doomgeneric.git#5041246e859052e2e258ca6edb4e1e9bbd98fcf5"
|
||||
DEPENDENCIES=('SDL2' 'SDL2_mixer' 'timidity')
|
||||
|
||||
configure() {
|
||||
make --directory doomgeneric clean
|
||||
rm -rf doomgeneric/build
|
||||
}
|
||||
|
||||
build() {
|
||||
if [ ! -f ../doom1.wad ]; then
|
||||
wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad -O ../doom1.wad || exit 1
|
||||
fi
|
||||
make --directory doomgeneric --file Makefile.banan_os -j$(nproc) || exit 1
|
||||
|
||||
CFLAGS='-std=c11' make --directory doomgeneric --file Makefile.sdl CC="$CC" SDL_PATH="$BANAN_SYSROOT/usr/bin/" || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
cp doomgeneric/build/doom "${BANAN_SYSROOT}/bin/" || exit 1
|
||||
cp doomgeneric/doomgeneric "${BANAN_SYSROOT}/bin/doom" || exit 1
|
||||
cp ../doom1.wad "$BANAN_SYSROOT/home/user/" || exit 1
|
||||
}
|
||||
|
|
|
@ -1,224 +0,0 @@
|
|||
From 0f37d9f2df042eb8ba021dd91b898c1f07d86b58 Mon Sep 17 00:00:00 2001
|
||||
From: Bananymous <bananymousosq@gmail.com>
|
||||
Date: Fri, 18 Oct 2024 03:44:10 +0300
|
||||
Subject: [PATCH] Add support for banan-os
|
||||
|
||||
---
|
||||
doomgeneric/Makefile.banan_os | 57 +++++++++++
|
||||
doomgeneric/doomgeneric_banan_os.cpp | 138 +++++++++++++++++++++++++++
|
||||
2 files changed, 200 insertions(+)
|
||||
create mode 100644 doomgeneric/Makefile.banan_os
|
||||
create mode 100644 doomgeneric/doomgeneric_banan_os.cpp
|
||||
|
||||
diff --git a/doomgeneric/Makefile.banan_os b/doomgeneric/Makefile.banan_os
|
||||
new file mode 100644
|
||||
index 0000000..0878148
|
||||
--- /dev/null
|
||||
+++ b/doomgeneric/Makefile.banan_os
|
||||
@@ -0,0 +1,57 @@
|
||||
+################################################################
|
||||
+#
|
||||
+# $Id:$
|
||||
+#
|
||||
+# $Log:$
|
||||
+#
|
||||
+
|
||||
+ifeq ($(V),1)
|
||||
+ VB=''
|
||||
+else
|
||||
+ VB=@
|
||||
+endif
|
||||
+
|
||||
+CC=$(BANAN_ARCH)-pc-banan_os-gcc
|
||||
+CXX=$(BANAN_ARCH)-pc-banan_os-g++
|
||||
+CFLAGS+=-O3 -std=c11 -Wall -DNORMALUNIX -DLINUX -DSNDSERV -D_DEFAULT_SOURCE
|
||||
+CXXFLAGS+=$(CFLAGS) --std=c++20
|
||||
+LDFLAGS+=
|
||||
+LIBS+=-lgui -linput -lstdc++
|
||||
+
|
||||
+# subdirectory for objects
|
||||
+OBJDIR=build
|
||||
+OUTPUT=$(OBJDIR)/doom
|
||||
+
|
||||
+SRC_DOOM = dummy.o am_map.o doomdef.o doomstat.o dstrings.o d_event.o d_items.o d_iwad.o d_loop.o d_main.o d_mode.o d_net.o f_finale.o f_wipe.o g_game.o hu_lib.o hu_stuff.o info.o i_cdmus.o i_endoom.o i_joystick.o i_scale.o i_sound.o i_system.o i_timer.o memio.o m_argv.o m_bbox.o m_cheat.o m_config.o m_controls.o m_fixed.o m_menu.o m_misc.o m_random.o p_ceilng.o p_doors.o p_enemy.o p_floor.o p_inter.o p_lights.o p_map.o p_maputl.o p_mobj.o p_plats.o p_pspr.o p_saveg.o p_setup.o p_sight.o p_spec.o p_switch.o p_telept.o p_tick.o p_user.o r_bsp.o r_data.o r_draw.o r_main.o r_plane.o r_segs.o r_sky.o r_things.o sha1.o sounds.o statdump.o st_lib.o st_stuff.o s_sound.o tables.o v_video.o wi_stuff.o w_checksum.o w_file.o w_main.o w_wad.o z_zone.o w_file_stdc.o i_input.o i_video.o doomgeneric.o doomgeneric_banan_os.o
|
||||
+OBJS += $(addprefix $(OBJDIR)/, $(SRC_DOOM))
|
||||
+
|
||||
+all: $(OUTPUT)
|
||||
+
|
||||
+clean:
|
||||
+ rm -rf $(OBJDIR)
|
||||
+ rm -f $(OUTPUT)
|
||||
+ rm -f $(OUTPUT).gdb
|
||||
+ rm -f $(OUTPUT).map
|
||||
+
|
||||
+$(OUTPUT): $(OBJS)
|
||||
+ @echo [Linking $@]
|
||||
+ $(VB)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) \
|
||||
+ -o $(OUTPUT) $(LIBS) -Wl,-Map,$(OUTPUT).map
|
||||
+ @echo [Size]
|
||||
+ -$(CROSS_COMPILE)size $(OUTPUT)
|
||||
+
|
||||
+$(OBJS): | $(OBJDIR)
|
||||
+
|
||||
+$(OBJDIR):
|
||||
+ mkdir -p $(OBJDIR)
|
||||
+
|
||||
+$(OBJDIR)/%.o: %.c
|
||||
+ @echo [Compiling $<]
|
||||
+ $(VB)$(CC) $(CFLAGS) -c $< -o $@
|
||||
+
|
||||
+$(OBJDIR)/%.o: %.cpp
|
||||
+ @echo [Compiling $<]
|
||||
+ $(VB)$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
+
|
||||
+print:
|
||||
+ @echo OBJS: $(OBJS)
|
||||
\ No newline at end of file
|
||||
diff --git a/doomgeneric/doomgeneric_banan_os.cpp b/doomgeneric/doomgeneric_banan_os.cpp
|
||||
new file mode 100644
|
||||
index 0000000..9161771
|
||||
--- /dev/null
|
||||
+++ b/doomgeneric/doomgeneric_banan_os.cpp
|
||||
@@ -0,0 +1,139 @@
|
||||
+extern "C"
|
||||
+{
|
||||
+#include "doomgeneric.h"
|
||||
+#include "doomkeys.h"
|
||||
+}
|
||||
+
|
||||
+#include <assert.h>
|
||||
+#include <ctype.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/banan-os.h>
|
||||
+#include <sys/framebuffer.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <time.h>
|
||||
+
|
||||
+#include <LibGUI/Window.h>
|
||||
+
|
||||
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
+
|
||||
+static BAN::UniqPtr<LibGUI::Window> s_window;
|
||||
+
|
||||
+static constexpr size_t s_key_queue_size = 16;
|
||||
+static unsigned short s_key_queue[s_key_queue_size];
|
||||
+static size_t s_key_read_index = 0;
|
||||
+static size_t s_key_write_index = 0;
|
||||
+
|
||||
+extern "C"
|
||||
+{
|
||||
+
|
||||
+void DG_Init()
|
||||
+{
|
||||
+ s_window = MUST(LibGUI::Window::create(DOOMGENERIC_RESX, DOOMGENERIC_RESY, "DOOM"_sv));
|
||||
+ s_window->set_key_event_callback(
|
||||
+ [](LibGUI::EventPacket::KeyEvent::event_t event)
|
||||
+ {
|
||||
+ unsigned short doom_key = 0;
|
||||
+ switch (event.key)
|
||||
+ {
|
||||
+ case LibInput::Key::Enter:
|
||||
+ doom_key = KEY_ENTER;
|
||||
+ break;
|
||||
+ case LibInput::Key::Escape:
|
||||
+ doom_key = KEY_ESCAPE;
|
||||
+ break;
|
||||
+ case LibInput::Key::ArrowLeft:
|
||||
+ doom_key = KEY_LEFTARROW;
|
||||
+ break;
|
||||
+ case LibInput::Key::ArrowUp:
|
||||
+ doom_key = KEY_UPARROW;
|
||||
+ break;
|
||||
+ case LibInput::Key::ArrowRight:
|
||||
+ doom_key = KEY_RIGHTARROW;
|
||||
+ break;
|
||||
+ case LibInput::Key::ArrowDown:
|
||||
+ doom_key = KEY_DOWNARROW;
|
||||
+ break;
|
||||
+ case LibInput::Key::LeftCtrl:
|
||||
+ case LibInput::Key::RightCtrl:
|
||||
+ doom_key = KEY_FIRE;
|
||||
+ break;
|
||||
+ case LibInput::Key::Space:
|
||||
+ doom_key = KEY_USE;
|
||||
+ break;
|
||||
+ case LibInput::Key::RightShift:
|
||||
+ doom_key = KEY_RSHIFT;
|
||||
+ break;
|
||||
+ default:
|
||||
+ {
|
||||
+ const char* utf8 = LibInput::key_to_utf8(event.key, event.modifier);
|
||||
+ if (utf8 && strlen(utf8) == 1 && isalpha(*utf8))
|
||||
+ doom_key = tolower(*utf8);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (doom_key == 0)
|
||||
+ return;
|
||||
+
|
||||
+ s_key_queue[s_key_write_index] = doom_key | (int)event.pressed() << 8;
|
||||
+ s_key_write_index = (s_key_write_index + 1) % s_key_queue_size;
|
||||
+ }
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void DG_DrawFrame()
|
||||
+{
|
||||
+ auto& texture = s_window->texture();
|
||||
+ for (size_t y = 0; y < DOOMGENERIC_RESY; y++)
|
||||
+ for (size_t x = 0; x < DOOMGENERIC_RESX; x++)
|
||||
+ texture.set_pixel(x, y, 0xFF000000 | DG_ScreenBuffer[y * DOOMGENERIC_RESX + x]);
|
||||
+ s_window->invalidate();
|
||||
+ s_window->poll_events();
|
||||
+}
|
||||
+
|
||||
+void DG_SleepMs(uint32_t ms)
|
||||
+{
|
||||
+ struct timespec ts;
|
||||
+ ts.tv_sec = ms / 1000;
|
||||
+ ts.tv_nsec = (ms % 1000) * 1000000;
|
||||
+ nanosleep(&ts, NULL);
|
||||
+}
|
||||
+
|
||||
+uint32_t DG_GetTicksMs()
|
||||
+{
|
||||
+ struct timespec ts;
|
||||
+ clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
+ return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
|
||||
+}
|
||||
+
|
||||
+int DG_GetKey(int* pressed, unsigned char* doomKey)
|
||||
+{
|
||||
+ if (s_key_read_index == s_key_write_index)
|
||||
+ return 0;
|
||||
+
|
||||
+ unsigned short key_data = s_key_queue[s_key_read_index];
|
||||
+ s_key_read_index = (s_key_read_index + 1) % s_key_queue_size;
|
||||
+
|
||||
+ *pressed = key_data >> 8;
|
||||
+ *doomKey = key_data & 0xFF;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+void DG_SetWindowTitle(const char* title)
|
||||
+{
|
||||
+ (void)title;
|
||||
+}
|
||||
+
|
||||
+int main(int argc, char** argv)
|
||||
+{
|
||||
+ doomgeneric_Create(argc, argv);
|
||||
+
|
||||
+ for (;;)
|
||||
+ doomgeneric_Tick();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+}
|
||||
--
|
||||
2.45.2
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
From a4e6b807885a7cb4a507b4e114743aa0004376ad Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Sun, 10 Aug 2025 01:57:38 +0300
|
||||
Subject: [PATCH] add support for custom SDL path
|
||||
|
||||
---
|
||||
doomgeneric/Makefile.sdl | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doomgeneric/Makefile.sdl b/doomgeneric/Makefile.sdl
|
||||
index 38402da..8c2f84e 100644
|
||||
--- a/doomgeneric/Makefile.sdl
|
||||
+++ b/doomgeneric/Makefile.sdl
|
||||
@@ -12,8 +12,8 @@ else
|
||||
endif
|
||||
|
||||
|
||||
-SDL_CFLAGS = `sdl2-config --cflags`
|
||||
-SDL_LIBS = `sdl2-config --cflags --libs` -lSDL2_mixer
|
||||
+SDL_CFLAGS = `$(SDL_PATH)sdl2-config --cflags`
|
||||
+SDL_LIBS = `$(SDL_PATH)sdl2-config --cflags --libs` -lSDL2_mixer
|
||||
|
||||
|
||||
CC=clang # gcc or g++
|
||||
--
|
||||
2.50.1
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From c28fd460c15a3d4cc5aac35d1ea5744f1722cab4 Mon Sep 17 00:00:00 2001
|
||||
From: Bananymous <bananymousosq@gmail.com>
|
||||
Date: Wed, 3 Apr 2024 21:39:22 +0300
|
||||
Subject: [PATCH] Call exit() on I_Quit() and I_Error()
|
||||
|
||||
---
|
||||
doomgeneric/i_system.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/doomgeneric/i_system.c b/doomgeneric/i_system.c
|
||||
index 5d00091..bfb204f 100644
|
||||
--- a/doomgeneric/i_system.c
|
||||
+++ b/doomgeneric/i_system.c
|
||||
@@ -257,6 +257,8 @@ void I_Quit (void)
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
+ exit(0);
|
||||
+
|
||||
#if ORIGCODE
|
||||
SDL_Quit();
|
||||
|
||||
@@ -403,6 +405,8 @@ void I_Error (char *error, ...)
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
+ exit(1);
|
||||
+
|
||||
exit_gui_popup = !M_ParmExists("-nogui");
|
||||
|
||||
// Pop up a GUI dialog box to show the error message, if the
|
||||
--
|
||||
2.47.1
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
From fd5308b45021ca18e7703d810e2e2ba86c174669 Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Sun, 10 Aug 2025 01:56:26 +0300
|
||||
Subject: [PATCH] set timidity config path
|
||||
|
||||
---
|
||||
doomgeneric/i_sdlmusic.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doomgeneric/i_sdlmusic.c b/doomgeneric/i_sdlmusic.c
|
||||
index f56392f..80b9021 100644
|
||||
--- a/doomgeneric/i_sdlmusic.c
|
||||
+++ b/doomgeneric/i_sdlmusic.c
|
||||
@@ -110,7 +110,7 @@ static boolean sdl_was_initialized = false;
|
||||
static boolean musicpaused = false;
|
||||
static int current_music_volume;
|
||||
|
||||
-char *timidity_cfg_path = "";
|
||||
+char *timidity_cfg_path = "/etc/timidity.cfg";
|
||||
|
||||
static char *temp_timidity_cfg = NULL;
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From 70c235938f0b64c4f08a478d3107e5254ad904c6 Mon Sep 17 00:00:00 2001
|
||||
From: Bananymous <bananymousosq@gmail.com>
|
||||
Date: Wed, 27 Nov 2024 13:28:42 +0200
|
||||
Subject: [PATCH] Remove unnecessary copy from framebuffer
|
||||
|
||||
---
|
||||
doomgeneric/doomgeneric.c | 2 --
|
||||
doomgeneric/doomgeneric_banan_os.cpp | 6 +++---
|
||||
2 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/doomgeneric/doomgeneric.c b/doomgeneric/doomgeneric.c
|
||||
index 782a7e7..f4eb63e 100644
|
||||
--- a/doomgeneric/doomgeneric.c
|
||||
+++ b/doomgeneric/doomgeneric.c
|
||||
@@ -18,8 +18,6 @@ void doomgeneric_Create(int argc, char **argv)
|
||||
|
||||
M_FindResponseFile();
|
||||
|
||||
- DG_ScreenBuffer = malloc(DOOMGENERIC_RESX * DOOMGENERIC_RESY * 4);
|
||||
-
|
||||
DG_Init();
|
||||
|
||||
D_DoomMain ();
|
||||
diff --git a/doomgeneric/doomgeneric_banan_os.cpp b/doomgeneric/doomgeneric_banan_os.cpp
|
||||
index d00c30d..9d13b43 100644
|
||||
--- a/doomgeneric/doomgeneric_banan_os.cpp
|
||||
+++ b/doomgeneric/doomgeneric_banan_os.cpp
|
||||
@@ -80,14 +80,13 @@ void DG_Init()
|
||||
s_key_write_index = (s_key_write_index + 1) % s_key_queue_size;
|
||||
}
|
||||
);
|
||||
+
|
||||
+ ASSERT(DG_ScreenBuffer == nullptr);
|
||||
+ DG_ScreenBuffer = s_window->texture().pixels().data();
|
||||
}
|
||||
|
||||
void DG_DrawFrame()
|
||||
{
|
||||
- auto& texture = s_window->texture();
|
||||
- for (size_t y = 0; y < DOOMGENERIC_RESY; y++)
|
||||
- for (size_t x = 0; x < DOOMGENERIC_RESX; x++)
|
||||
- texture.set_pixel(x, y, 0xFF000000 | DG_ScreenBuffer[y * DOOMGENERIC_RESX + x]);
|
||||
s_window->invalidate();
|
||||
s_window->poll_events();
|
||||
}
|
||||
--
|
||||
2.47.1
|
||||
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
NAME='quake2'
|
||||
VERSION='git'
|
||||
DOWNLOAD_URL="https://github.com/ozkl/quake2generic.git#a967e4f567a98941326fc7fe76eee5e52a04a633"
|
||||
DOWNLOAD_URL="https://github.com/ozkl/quake2generic.git#50190797664fd42fc1b0266150c54f76f92bfa15"
|
||||
DEPENDENCIES=('SDL2' 'SDL2_mixer')
|
||||
|
||||
configure() {
|
||||
:
|
||||
make clean
|
||||
}
|
||||
|
||||
build() {
|
||||
|
@ -24,11 +25,13 @@ build() {
|
|||
echo "File hash does not match" >&2
|
||||
exit 1
|
||||
fi
|
||||
make -j$(nproc) || exit 1
|
||||
|
||||
cflags='-Dstricmp=strcasecmp -Wno-incompatible-pointer-types'
|
||||
make CC="$CC" BASE_CFLAGS="$cflags" SDL_PATH="$BANAN_SYSROOT/usr/bin/" -j$(nproc) || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
cp build/quake2 "${BANAN_SYSROOT}/bin/" || exit 1
|
||||
cp -v build/quake2-soft "${BANAN_SYSROOT}/bin/quake2" || exit 1
|
||||
|
||||
baseq2_tar=$(realpath ../baseq2.tar.gz || exit 1)
|
||||
cd "$BANAN_SYSROOT/home/user/"
|
||||
|
|
|
@ -1,482 +0,0 @@
|
|||
From f900c2967edc684334b663e522aeec79e8fee10d Mon Sep 17 00:00:00 2001
|
||||
From: Bananymous <bananymousosq@gmail.com>
|
||||
Date: Thu, 14 Nov 2024 12:33:39 +0200
|
||||
Subject: [PATCH] Add support for banan-os
|
||||
|
||||
---
|
||||
Makefile | 106 +++-------------
|
||||
port_soft_banan_os.cpp | 277 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 295 insertions(+), 88 deletions(-)
|
||||
create mode 100644 port_soft_banan_os.cpp
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 46142df..4437418 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,7 +1,3 @@
|
||||
-
|
||||
-SDL_CFLAGS = `sdl2-config --cflags`
|
||||
-SDL_LIBS = `sdl2-config --cflags --libs` -lSDL2_mixer
|
||||
-
|
||||
MOUNT_DIR=.
|
||||
|
||||
BUILDDIR=build
|
||||
@@ -18,21 +14,19 @@ GAME_DIR=$(MOUNT_DIR)/game
|
||||
CTF_DIR=$(MOUNT_DIR)/ctf
|
||||
XATRIX_DIR=$(MOUNT_DIR)/xatrix
|
||||
|
||||
-CC=clang #emcc
|
||||
+CC=$(BANAN_ARCH)-banan_os-gcc
|
||||
BASE_CFLAGS=-Dstricmp=strcasecmp
|
||||
|
||||
+CXX=$(BANAN_ARCH)-banan_os-g++
|
||||
+CXXFLAGS=--std=c++20
|
||||
|
||||
RELEASE_CFLAGS=$(BASE_CFLAGS) -O6 -ffast-math -funroll-loops \
|
||||
-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
|
||||
-malign-jumps=2 -malign-functions=2
|
||||
|
||||
DEBUG_CFLAGS=$(BASE_CFLAGS) -g
|
||||
-LDFLAGS=-ldl -lm
|
||||
-XCFLAGS=-I/opt/X11/include
|
||||
-
|
||||
-GLLDFLAGS=-L/usr/X11/lib -L/usr/local/lib \
|
||||
- $(SDL_LIBS) -lGL
|
||||
-GLCFLAGS=$(SDL_CFLAGS)
|
||||
+LDFLAGS=-lgui -linput
|
||||
+XCFLAGS=
|
||||
|
||||
SHLIBEXT=so
|
||||
|
||||
@@ -43,6 +37,10 @@ DO_CC=$(CC) $(CFLAGS) -o $@ -c $<
|
||||
DO_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
|
||||
DO_GL_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) $(GLCFLAGS) $(XCFLAGS) -o $@ -c $<
|
||||
|
||||
+DO_CXX=$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
|
||||
+DO_SHLIB_CXX=$(CXX) $(CFLAGS) $(CXXFLAGS) $(SHLIBCFLAGS) -o $@ -c $<
|
||||
+DO_GL_SHLIB_CXX=$(CXX) $(CFLAGS) $(CXXFLAGS) $(SHLIBCFLAGS) $(GLCFLAGS) $(XCFLAGS) -o $@ -c $<
|
||||
+
|
||||
#############################################################################
|
||||
# SETUP AND BUILD
|
||||
#############################################################################
|
||||
@@ -61,14 +59,12 @@ createdirs:
|
||||
@-mkdir -p $(BUILDDIR) \
|
||||
$(BUILDDIR)/client \
|
||||
$(BUILDDIR)/ref_soft \
|
||||
- $(BUILDDIR)/ref_softsdl \
|
||||
- $(BUILDDIR)/ref_gl \
|
||||
$(BUILDDIR)/net \
|
||||
$(BUILDDIR)/sound \
|
||||
$(BUILDDIR)/game
|
||||
|
||||
|
||||
-TARGETS: $(BUILDDIR)/quake2-soft $(BUILDDIR)/quake2-gl
|
||||
+TARGETS: $(BUILDDIR)/quake2
|
||||
|
||||
#############################################################################
|
||||
# CLIENT/SERVER
|
||||
@@ -122,7 +118,7 @@ QUAKE2_OBJS = \
|
||||
\
|
||||
$(BUILDDIR)/client/pmove.o \
|
||||
\
|
||||
- $(BUILDDIR)/net/net_unix.o \
|
||||
+ $(BUILDDIR)/net/net_loopback.o \
|
||||
\
|
||||
$(BUILDDIR)/sound/snddma_null.o \
|
||||
\
|
||||
@@ -200,38 +196,11 @@ REF_SOFT_OBJS = \
|
||||
$(BUILDDIR)/ref_soft/r_rast.o \
|
||||
$(BUILDDIR)/ref_soft/r_scan.o \
|
||||
$(BUILDDIR)/ref_soft/r_sprite.o \
|
||||
- $(BUILDDIR)/ref_soft/r_surf.o
|
||||
-
|
||||
-
|
||||
-REF_SOFT_SDL_OBJS = \
|
||||
- $(BUILDDIR)/ref_soft/port_soft_sdl.o
|
||||
-
|
||||
-
|
||||
-#############################################################################
|
||||
-# REF_GL
|
||||
-#############################################################################
|
||||
-
|
||||
-REF_GL_OBJS = \
|
||||
- $(BUILDDIR)/ref_gl/gl_draw.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_image.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_light.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_mesh.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_model.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_rmain.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_rmisc.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_rsurf.o \
|
||||
- $(BUILDDIR)/ref_gl/gl_warp.o \
|
||||
- \
|
||||
- $(BUILDDIR)/ref_gl/qgl_system.o \
|
||||
- $(BUILDDIR)/ref_gl/port_gl_sdl.o
|
||||
-
|
||||
-
|
||||
-$(BUILDDIR)/quake2-soft : $(QUAKE2_OBJS) $(GAME_OBJS) $(REF_SOFT_OBJS) $(REF_SOFT_SDL_OBJS)
|
||||
- $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(GAME_OBJS) $(REF_SOFT_OBJS) $(REF_SOFT_SDL_OBJS) $(LDFLAGS) $(GLLDFLAGS)
|
||||
-
|
||||
-$(BUILDDIR)/quake2-gl : $(QUAKE2_OBJS) $(GAME_OBJS) $(REF_GL_OBJS)
|
||||
- $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(GAME_OBJS) $(REF_GL_OBJS) $(LDFLAGS) $(GLLDFLAGS)
|
||||
+ $(BUILDDIR)/ref_soft/r_surf.o \
|
||||
+ $(BUILDDIR)/ref_soft/port_soft_banan_os.o
|
||||
|
||||
+$(BUILDDIR)/quake2 : $(QUAKE2_OBJS) $(GAME_OBJS) $(REF_SOFT_OBJS)
|
||||
+ $(CC) $(CFLAGS) -o $@ $(QUAKE2_OBJS) $(GAME_OBJS) $(REF_SOFT_OBJS) $(LDFLAGS)
|
||||
|
||||
$(BUILDDIR)/client/cl_cin.o : $(CLIENT_DIR)/cl_cin.c
|
||||
$(DO_CC)
|
||||
@@ -362,7 +331,7 @@ $(BUILDDIR)/client/q_system.o : $(OTHER_DIR)/q_system.c
|
||||
$(BUILDDIR)/client/glob.o : $(OTHER_DIR)/glob.c
|
||||
$(DO_CC)
|
||||
|
||||
-$(BUILDDIR)/net/net_unix.o : $(NET_DIR)/net_unix.c
|
||||
+$(BUILDDIR)/net/net_loopback.o : $(NET_DIR)/net_loopback.c
|
||||
$(DO_CC)
|
||||
|
||||
$(BUILDDIR)/port_platform_unix.o : $(MOUNT_DIR)/port_platform_unix.c
|
||||
@@ -689,45 +658,8 @@ $(BUILDDIR)/ref_soft/r_sprite.o : $(REF_SOFT_DIR)/r_sprite.c
|
||||
$(BUILDDIR)/ref_soft/r_surf.o : $(REF_SOFT_DIR)/r_surf.c
|
||||
$(DO_GL_SHLIB_CC)
|
||||
|
||||
-$(BUILDDIR)/ref_soft/port_soft_sdl.o : $(MOUNT_DIR)/port_soft_sdl.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-#############################################################################
|
||||
-# REF_GL
|
||||
-#############################################################################
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_draw.o : $(REF_GL_DIR)/gl_draw.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_image.o : $(REF_GL_DIR)/gl_image.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_light.o : $(REF_GL_DIR)/gl_light.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_mesh.o : $(REF_GL_DIR)/gl_mesh.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_model.o : $(REF_GL_DIR)/gl_model.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_rmain.o : $(REF_GL_DIR)/gl_rmain.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_rmisc.o : $(REF_GL_DIR)/gl_rmisc.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_rsurf.o : $(REF_GL_DIR)/gl_rsurf.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/gl_warp.o : $(REF_GL_DIR)/gl_warp.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/qgl_system.o : $(REF_GL_DIR)/qgl_system.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
-
|
||||
-$(BUILDDIR)/ref_gl/port_gl_sdl.o : $(MOUNT_DIR)/port_gl_sdl.c
|
||||
- $(DO_GL_SHLIB_CC)
|
||||
+$(BUILDDIR)/ref_soft/port_soft_banan_os.o : $(MOUNT_DIR)/port_soft_banan_os.cpp
|
||||
+ $(DO_GL_SHLIB_CXX)
|
||||
|
||||
|
||||
#############################################################################
|
||||
@@ -738,8 +670,6 @@ clean:
|
||||
-rm -rf \
|
||||
$(BUILDDIR)/client \
|
||||
$(BUILDDIR)/ref_soft \
|
||||
- $(BUILDDIR)/ref_softsdl \
|
||||
- $(BUILDDIR)/ref_gl \
|
||||
$(BUILDDIR)/game \
|
||||
$(BUILDDIR)/net \
|
||||
$(BUILDDIR)/sound \
|
||||
diff --git a/port_soft_banan_os.cpp b/port_soft_banan_os.cpp
|
||||
new file mode 100644
|
||||
index 0000000..c7d7e16
|
||||
--- /dev/null
|
||||
+++ b/port_soft_banan_os.cpp
|
||||
@@ -0,0 +1,278 @@
|
||||
+#include <LibGUI/Window.h>
|
||||
+#include <LibInput/KeyEvent.h>
|
||||
+#include <LibInput/MouseEvent.h>
|
||||
+#include <LibImage/Image.h>
|
||||
+
|
||||
+#include <BAN/Debug.h>
|
||||
+
|
||||
+extern "C" {
|
||||
+
|
||||
+#include "ref_soft/r_local.h"
|
||||
+#include "client/keys.h"
|
||||
+
|
||||
+#include "quake2.h"
|
||||
+
|
||||
+static LibImage::Image::Color s_palette[256];
|
||||
+
|
||||
+static int s_mouse_dx { 0 };
|
||||
+static int s_mouse_dy { 0 };
|
||||
+static bool s_relative_mouse { false };
|
||||
+
|
||||
+static BAN::Vector<uint8_t> s_buffer;
|
||||
+static BAN::UniqPtr<LibGUI::Window> s_window;
|
||||
+static bool s_is_fullscreen { false };
|
||||
+
|
||||
+static int key_to_quake_key(LibInput::Key key)
|
||||
+{
|
||||
+ using namespace LibInput;
|
||||
+
|
||||
+ switch (key)
|
||||
+ {
|
||||
+ case Key::PageUp: return K_PGUP;
|
||||
+ case Key::PageDown: return K_PGDN;
|
||||
+ case Key::Home: return K_HOME;
|
||||
+ case Key::End: return K_END;
|
||||
+ case Key::ArrowLeft: return K_LEFTARROW;
|
||||
+ case Key::ArrowRight: return K_RIGHTARROW;
|
||||
+ case Key::ArrowDown: return K_DOWNARROW;
|
||||
+ case Key::ArrowUp: return K_UPARROW;
|
||||
+ case Key::Escape: return K_ESCAPE;
|
||||
+ case Key::Enter: return K_ENTER;
|
||||
+ case Key::Tab: return K_TAB;
|
||||
+ case Key::F1: return K_F1;
|
||||
+ case Key::F2: return K_F2;
|
||||
+ case Key::F3: return K_F3;
|
||||
+ case Key::F4: return K_F4;
|
||||
+ case Key::F5: return K_F5;
|
||||
+ case Key::F6: return K_F6;
|
||||
+ case Key::F7: return K_F7;
|
||||
+ case Key::F8: return K_F8;
|
||||
+ case Key::F9: return K_F9;
|
||||
+ case Key::F10: return K_F10;
|
||||
+ case Key::F11: return K_F11;
|
||||
+ case Key::F12: return K_F12;
|
||||
+ case Key::Backspace: return K_BACKSPACE;
|
||||
+ case Key::Delete: return K_DEL;
|
||||
+ case Key::LeftShift:
|
||||
+ case Key::RightShift: return K_SHIFT;
|
||||
+ case Key::LeftCtrl:
|
||||
+ case Key::RightCtrl: return K_CTRL;
|
||||
+ case Key::LeftAlt:
|
||||
+ case Key::RightAlt: return K_ALT;
|
||||
+ case Key::Insert: return K_INS;
|
||||
+ default:
|
||||
+ if (const char* ascii = key_to_utf8(key, 0); ascii && strlen(ascii) == 1)
|
||||
+ return *ascii;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int button_to_quake_button(LibInput::MouseButton button)
|
||||
+{
|
||||
+ using namespace LibInput;
|
||||
+
|
||||
+ switch (button)
|
||||
+ {
|
||||
+ case LibInput::MouseButton::Left: return K_MOUSE1;
|
||||
+ case LibInput::MouseButton::Right: return K_MOUSE2;
|
||||
+ case LibInput::MouseButton::Middle: return K_MOUSE3;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void create_window(uint32_t width, uint32_t height)
|
||||
+{
|
||||
+ ASSERT(!s_window);
|
||||
+ s_window = MUST(LibGUI::Window::create(width, height, "Quake2"_sv));
|
||||
+
|
||||
+ s_window->set_mouse_move_event_callback(
|
||||
+ [](auto event)
|
||||
+ {
|
||||
+ if (!s_relative_mouse)
|
||||
+ return;
|
||||
+ s_mouse_dx += event.x;
|
||||
+ s_mouse_dy += event.y;
|
||||
+ }
|
||||
+ );
|
||||
+
|
||||
+ s_window->set_mouse_button_event_callback(
|
||||
+ [](auto event)
|
||||
+ {
|
||||
+ if (int button = button_to_quake_button(event.button))
|
||||
+ Quake2_SendKey(button, event.pressed);
|
||||
+ }
|
||||
+ );
|
||||
+
|
||||
+ s_window->set_key_event_callback(
|
||||
+ [](auto event)
|
||||
+ {
|
||||
+ if (int key = key_to_quake_key(event.key))
|
||||
+ Quake2_SendKey(key, event.pressed());
|
||||
+ }
|
||||
+ );
|
||||
+
|
||||
+ s_window->set_close_window_event_callback(
|
||||
+ []()
|
||||
+ {
|
||||
+ char command[] = "quit";
|
||||
+ ri.Cmd_ExecuteText(EXEC_NOW, command);
|
||||
+ }
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+rserr_t SWimp_SetMode(int* pwidth, int* pheight, int mode, qboolean fullscreen)
|
||||
+{
|
||||
+ int width, height;
|
||||
+
|
||||
+ if (!ri.Vid_GetModeInfo(&width, &height, mode))
|
||||
+ return rserr_invalid_mode;
|
||||
+
|
||||
+ if (!s_window)
|
||||
+ create_window(width, height);
|
||||
+ else if (s_window->width() != width || s_window->height() != height)
|
||||
+ {
|
||||
+ s_window->request_resize(width, height);
|
||||
+
|
||||
+ bool resized { false };
|
||||
+ s_window->set_resize_window_event_callback([&]() { resized = true; });
|
||||
+ while (!resized)
|
||||
+ s_window->poll_events();
|
||||
+ s_window->set_resize_window_event_callback({});
|
||||
+
|
||||
+ ASSERT(s_window->width() == width && s_window->height() == height);
|
||||
+ }
|
||||
+
|
||||
+ if (s_is_fullscreen != fullscreen)
|
||||
+ {
|
||||
+ s_is_fullscreen = fullscreen;
|
||||
+ s_window->set_fullscreen(fullscreen);
|
||||
+ }
|
||||
+
|
||||
+ MUST(s_buffer.resize(s_window->width() * s_window->height()));
|
||||
+ vid.rowbytes = s_window->width();
|
||||
+ vid.buffer = s_buffer.data();
|
||||
+
|
||||
+ *pwidth = s_window->width();
|
||||
+ *pheight = s_window->height();
|
||||
+
|
||||
+ ri.Vid_NewWindow(s_window->width(), s_window->height());
|
||||
+
|
||||
+ return rserr_ok;
|
||||
+}
|
||||
+
|
||||
+void SWimp_Shutdown(void)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+int SWimp_Init(void* hInstance, void* wndProc)
|
||||
+{
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static qboolean SWimp_InitGraphics(qboolean fullscreen)
|
||||
+{
|
||||
+ return rserr_ok;
|
||||
+}
|
||||
+
|
||||
+void SWimp_SetPalette(const unsigned char* palette)
|
||||
+{
|
||||
+ for (int i = 0; i < 256; i++)
|
||||
+ {
|
||||
+ s_palette[i].r = *palette++;
|
||||
+ s_palette[i].g = *palette++;
|
||||
+ s_palette[i].b = *palette++;
|
||||
+ s_palette[i].a = *palette++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void SWimp_BeginFrame(float camera_seperation)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+void SWimp_EndFrame(void)
|
||||
+{
|
||||
+ auto& texture = s_window->texture();
|
||||
+ const uint32_t width = s_window->width();
|
||||
+ const uint32_t height = s_window->height();
|
||||
+ for (int y = 0; y < height; y++)
|
||||
+ for (int x = 0; x < width; x++)
|
||||
+ texture.set_pixel(x, y, s_palette[s_buffer[y * width + x]].as_argb());
|
||||
+ s_window->invalidate();
|
||||
+}
|
||||
+
|
||||
+void SWimp_AppActivate(qboolean active)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+int QG_Milliseconds(void)
|
||||
+{
|
||||
+ struct timespec ts;
|
||||
+ clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
+ return (ts.tv_sec * 1'000) + (ts.tv_nsec / 1'000'000);
|
||||
+}
|
||||
+
|
||||
+void QG_GetMouseDiff(int* dx, int* dy)
|
||||
+{
|
||||
+ *dx = s_mouse_dx;
|
||||
+ s_mouse_dx = 0;
|
||||
+
|
||||
+ *dy = s_mouse_dy;
|
||||
+ s_mouse_dy = 0;
|
||||
+}
|
||||
+
|
||||
+void QG_CaptureMouse(void)
|
||||
+{
|
||||
+ s_relative_mouse = true;
|
||||
+ s_window->set_mouse_capture(true);
|
||||
+}
|
||||
+
|
||||
+void QG_ReleaseMouse(void)
|
||||
+{
|
||||
+ s_relative_mouse = false;
|
||||
+ s_window->set_mouse_capture(false);
|
||||
+}
|
||||
+
|
||||
+static uint64_t get_current_ns()
|
||||
+{
|
||||
+ timespec last_ts;
|
||||
+ clock_gettime(CLOCK_MONOTONIC, &last_ts);
|
||||
+ return (uint64_t)last_ts.tv_sec * 1'000'000'000 + last_ts.tv_nsec;
|
||||
+}
|
||||
+
|
||||
+int main(int argc, char** argv)
|
||||
+{
|
||||
+ Quake2_Init(argc, argv);
|
||||
+
|
||||
+ uint64_t last_ns = get_current_ns();
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ s_window->poll_events();
|
||||
+
|
||||
+ const uint64_t current_ns = get_current_ns();
|
||||
+ uint64_t duration_ns = current_ns - last_ns;
|
||||
+
|
||||
+ if (duration_ns < 1'000'000)
|
||||
+ {
|
||||
+ timespec sleep_ts {
|
||||
+ .tv_sec = 0,
|
||||
+ .tv_nsec = (long)(1'000'000 - duration_ns)
|
||||
+ };
|
||||
+ while (nanosleep(&sleep_ts, &sleep_ts))
|
||||
+ continue;
|
||||
+ duration_ns = get_current_ns() - last_ns;
|
||||
+ }
|
||||
+
|
||||
+ Quake2_Frame(duration_ns / 1'000'000);
|
||||
+
|
||||
+ last_ns = current_ns;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+}
|
||||
--
|
||||
2.47.0
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
From fd08d90bb7ee8388a9e005bae23edcccbfc73dbb Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Sun, 10 Aug 2025 19:52:20 +0300
|
||||
Subject: [PATCH] add support for custom SDL path and add sound support
|
||||
|
||||
---
|
||||
Makefile | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 8edbffa..de2f605 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
-SDL_CFLAGS = `sdl2-config --cflags`
|
||||
-SDL_LIBS = `sdl2-config --cflags --libs` -lSDL2_mixer
|
||||
+SDL_CFLAGS = `$(SDL_PATH)sdl2-config --cflags`
|
||||
+SDL_LIBS = `$(SDL_PATH)sdl2-config --cflags --libs` -lSDL2_mixer
|
||||
|
||||
MOUNT_DIR=.
|
||||
|
||||
@@ -124,7 +124,7 @@ QUAKE2_OBJS = \
|
||||
\
|
||||
$(BUILDDIR)/net/net_unix.o \
|
||||
\
|
||||
- $(BUILDDIR)/sound/snddma_null.o \
|
||||
+ $(BUILDDIR)/sound/snd_sdl.o \
|
||||
\
|
||||
$(BUILDDIR)/port_platform_unix.o
|
||||
|
||||
@@ -353,7 +353,7 @@ $(BUILDDIR)/client/vid_menu.o : $(OTHER_DIR)/vid_menu.c
|
||||
$(BUILDDIR)/client/vid_lib.o : $(OTHER_DIR)/vid_lib.c
|
||||
$(DO_CC)
|
||||
|
||||
-$(BUILDDIR)/client/snddma_null.o : $(NULL_DIR)/snddma_null.c
|
||||
+$(BUILDDIR)/client/snd_sdl.o : $(NULL_DIR)/snd_sdl.c
|
||||
$(DO_CC)
|
||||
|
||||
$(BUILDDIR)/client/q_system.o : $(OTHER_DIR)/q_system.c
|
||||
@@ -368,7 +368,7 @@ $(BUILDDIR)/net/net_unix.o : $(NET_DIR)/net_unix.c
|
||||
$(BUILDDIR)/port_platform_unix.o : $(MOUNT_DIR)/port_platform_unix.c
|
||||
$(DO_CC)
|
||||
|
||||
-$(BUILDDIR)/sound/snddma_null.o : $(SOUND_DIR)/snddma_null.c
|
||||
+$(BUILDDIR)/sound/snd_sdl.o : $(SOUND_DIR)/snd_sdl.c
|
||||
$(DO_GL_SHLIB_CC)
|
||||
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From fbdf3e7c40c1de83a2361bb904d8dbd3464ccebd Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Sun, 10 Aug 2025 19:54:38 +0300
|
||||
Subject: [PATCH 2/2] fix socket creation
|
||||
|
||||
---
|
||||
net/net_unix.c | 10 +---------
|
||||
1 file changed, 1 insertion(+), 9 deletions(-)
|
||||
|
||||
diff --git a/net/net_unix.c b/net/net_unix.c
|
||||
index a92e57c..f297dff 100644
|
||||
--- a/net/net_unix.c
|
||||
+++ b/net/net_unix.c
|
||||
@@ -451,24 +451,16 @@ int NET_Socket (char *net_interface, int port)
|
||||
qboolean _true = true;
|
||||
int i = 1;
|
||||
|
||||
- if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
+ if ((newsocket = socket (PF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
Com_Printf ("ERROR: UDP_OpenSocket: socket:", NET_ErrorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
- // make it non-blocking
|
||||
- if (ioctl (newsocket, FIONBIO, &_true) == -1)
|
||||
- {
|
||||
- Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString());
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
// make it broadcast capable
|
||||
if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
|
||||
{
|
||||
Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString());
|
||||
- return 0;
|
||||
}
|
||||
|
||||
if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
|
||||
--
|
||||
2.50.1
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='timidity'
|
||||
VERSION='2.15.0'
|
||||
DOWNLOAD_URL="https://sourceforge.net/projects/timidity/files/TiMidity++/TiMidity++-$VERSION/TiMidity++-$VERSION.tar.gz#0b6109a3c64604c8851cd9bb4cbafc014a4e13b0025f597e586d9742388f6fb7"
|
||||
TAR_CONTENT="TiMidity++-$VERSION"
|
||||
CONFIG_SUB=('autoconf/config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'--without-x'
|
||||
'lib_cv_va_copy=y'
|
||||
'lib_cv___va_copy=n'
|
||||
'lib_cv_va_val_copy=n'
|
||||
'CFLAGS=-std=c11'
|
||||
)
|
||||
|
||||
pre_configure() {
|
||||
unset CC CXX LD
|
||||
}
|
||||
|
||||
post_install() {
|
||||
if [ ! -f ../eawpats.zip ]; then
|
||||
wget https://www.quaddicted.com/files/idgames/sounds/eawpats.zip -O ../eawpats.zip || exit 1
|
||||
fi
|
||||
|
||||
eawpats_dir="/usr/share/eawpats"
|
||||
mkdir -p "$BANAN_SYSROOT/$eawpats_dir"
|
||||
unzip -qod "$BANAN_SYSROOT/$eawpats_dir" ../eawpats.zip
|
||||
|
||||
cp "$BANAN_SYSROOT/$eawpats_dir/timidity.cfg" "$BANAN_SYSROOT/etc/"
|
||||
sed -i "s|^dir .*$|dir $eawpats_dir|g" "$BANAN_SYSROOT/etc/timidity.cfg"
|
||||
}
|
|
@ -3,13 +3,15 @@
|
|||
NAME='tinygb'
|
||||
VERSION='git'
|
||||
DOWNLOAD_URL="https://github.com/jewelcodes/tinygb.git#57fdaff675a6b5b963b2b6624868d9698eabe375"
|
||||
DEPENDENCIES=('SDL2')
|
||||
|
||||
configure() {
|
||||
make -f Makefile.banan_os clean
|
||||
sed -i "s|shell sdl2-config|shell $BANAN_SYSROOT/usr/bin/sdl2-config|g" Makefile
|
||||
make clean
|
||||
}
|
||||
|
||||
build() {
|
||||
make -f Makefile.banan_os -j$(nproc) || exit 1
|
||||
make CC="$CC" LD="$CC" || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
|
|
|
@ -1,420 +0,0 @@
|
|||
From 7f7c6402e384591bca63021aa97d60a8107de88d Mon Sep 17 00:00:00 2001
|
||||
From: Bananymous <bananymousosq@gmail.com>
|
||||
Date: Mon, 5 May 2025 00:59:03 +0300
|
||||
Subject: [PATCH] Add support for banan-os
|
||||
|
||||
---
|
||||
Makefile.banan_os | 28 +++
|
||||
src/platform/banan-os/main.cpp | 362 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 390 insertions(+)
|
||||
create mode 100644 Makefile.banan_os
|
||||
create mode 100644 src/platform/banan-os/main.cpp
|
||||
|
||||
diff --git a/Makefile.banan_os b/Makefile.banan_os
|
||||
new file mode 100644
|
||||
index 0000000..22e191e
|
||||
--- /dev/null
|
||||
+++ b/Makefile.banan_os
|
||||
@@ -0,0 +1,28 @@
|
||||
+CC = $(BANAN_ARCH)-banan_os-gcc
|
||||
+CXX = $(BANAN_ARCH)-banan_os-g++
|
||||
+LD = $(BANAN_ARCH)-banan_os-gcc
|
||||
+
|
||||
+CFLAGS = -c -O2 -Isrc/include -Wall
|
||||
+CXXFLAGS = --std=c++20
|
||||
+LDFLAGS = -O2 -lgui -linput
|
||||
+
|
||||
+SRC := $(shell find src -name "*.c" -not -path 'src/platform/*') $(shell find src/platform/banan-os -name "*.c" -or -name "*.cpp")
|
||||
+OBJ := $(addsuffix .o,$(SRC))
|
||||
+
|
||||
+all: tinygb
|
||||
+
|
||||
+clean:
|
||||
+ @rm -f $(OBJ)
|
||||
+ @rm -f tinygb
|
||||
+
|
||||
+%.c.o: %.c
|
||||
+ @echo -e "\x1B[0;1;35m [ CC ]\x1B[0m $@"
|
||||
+ $(CC) -o $@ $(CFLAGS) $<
|
||||
+
|
||||
+%.cpp.o: %.cpp
|
||||
+ @echo -e "\x1B[0;1;35m [ CC ]\x1B[0m $@"
|
||||
+ $(CXX) -o $@ $(CFLAGS) $(CXXFLAGS) $<
|
||||
+
|
||||
+tinygb: $(OBJ)
|
||||
+ @echo -e "\x1B[0;1;36m [ LD ]\x1B[0m tinygb"
|
||||
+ $(LD) $(OBJ) -o tinygb $(LDFLAGS)
|
||||
diff --git a/src/platform/banan-os/main.cpp b/src/platform/banan-os/main.cpp
|
||||
new file mode 100644
|
||||
index 0000000..94f249e
|
||||
--- /dev/null
|
||||
+++ b/src/platform/banan-os/main.cpp
|
||||
@@ -0,0 +1,364 @@
|
||||
+
|
||||
+/* tinygb - a tiny gameboy emulator
|
||||
+ (c) 2022 by jewel */
|
||||
+
|
||||
+extern "C" {
|
||||
+#include <tinygb.h>
|
||||
+}
|
||||
+
|
||||
+#include <LibGUI/Window.h>
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <time.h>
|
||||
+
|
||||
+long rom_size;
|
||||
+int scaling = 4;
|
||||
+int frameskip = 0; // no skip
|
||||
+
|
||||
+timing_t timing;
|
||||
+char *rom_filename;
|
||||
+
|
||||
+BAN::UniqPtr<LibGUI::Window> s_window;
|
||||
+
|
||||
+// Key Config
|
||||
+LibInput::Key key_a;
|
||||
+LibInput::Key key_b;
|
||||
+LibInput::Key key_start;
|
||||
+LibInput::Key key_select;
|
||||
+LibInput::Key key_up;
|
||||
+LibInput::Key key_down;
|
||||
+LibInput::Key key_left;
|
||||
+LibInput::Key key_right;
|
||||
+LibInput::Key key_throttle;
|
||||
+
|
||||
+LibInput::Key get_key(const char* keyname)
|
||||
+{
|
||||
+ if (keyname == nullptr);
|
||||
+ else if (!strcmp("a", keyname)) return LibInput::Key::A;
|
||||
+ else if (!strcmp("b", keyname)) return LibInput::Key::B;
|
||||
+ else if (!strcmp("c", keyname)) return LibInput::Key::C;
|
||||
+ else if (!strcmp("d", keyname)) return LibInput::Key::D;
|
||||
+ else if (!strcmp("e", keyname)) return LibInput::Key::E;
|
||||
+ else if (!strcmp("f", keyname)) return LibInput::Key::F;
|
||||
+ else if (!strcmp("g", keyname)) return LibInput::Key::G;
|
||||
+ else if (!strcmp("h", keyname)) return LibInput::Key::H;
|
||||
+ else if (!strcmp("i", keyname)) return LibInput::Key::I;
|
||||
+ else if (!strcmp("j", keyname)) return LibInput::Key::J;
|
||||
+ else if (!strcmp("k", keyname)) return LibInput::Key::K;
|
||||
+ else if (!strcmp("l", keyname)) return LibInput::Key::L;
|
||||
+ else if (!strcmp("m", keyname)) return LibInput::Key::M;
|
||||
+ else if (!strcmp("n", keyname)) return LibInput::Key::N;
|
||||
+ else if (!strcmp("o", keyname)) return LibInput::Key::O;
|
||||
+ else if (!strcmp("p", keyname)) return LibInput::Key::P;
|
||||
+ else if (!strcmp("q", keyname)) return LibInput::Key::Q;
|
||||
+ else if (!strcmp("r", keyname)) return LibInput::Key::R;
|
||||
+ else if (!strcmp("s", keyname)) return LibInput::Key::S;
|
||||
+ else if (!strcmp("t", keyname)) return LibInput::Key::T;
|
||||
+ else if (!strcmp("u", keyname)) return LibInput::Key::U;
|
||||
+ else if (!strcmp("v", keyname)) return LibInput::Key::V;
|
||||
+ else if (!strcmp("w", keyname)) return LibInput::Key::W;
|
||||
+ else if (!strcmp("x", keyname)) return LibInput::Key::X;
|
||||
+ else if (!strcmp("y", keyname)) return LibInput::Key::Y;
|
||||
+ else if (!strcmp("z", keyname)) return LibInput::Key::Z;
|
||||
+ else if (!strcmp("0", keyname)) return LibInput::Key::_0;
|
||||
+ else if (!strcmp("1", keyname)) return LibInput::Key::_1;
|
||||
+ else if (!strcmp("2", keyname)) return LibInput::Key::_2;
|
||||
+ else if (!strcmp("3", keyname)) return LibInput::Key::_3;
|
||||
+ else if (!strcmp("4", keyname)) return LibInput::Key::_4;
|
||||
+ else if (!strcmp("5", keyname)) return LibInput::Key::_5;
|
||||
+ else if (!strcmp("6", keyname)) return LibInput::Key::_6;
|
||||
+ else if (!strcmp("7", keyname)) return LibInput::Key::_7;
|
||||
+ else if (!strcmp("8", keyname)) return LibInput::Key::_8;
|
||||
+ else if (!strcmp("9", keyname)) return LibInput::Key::_9;
|
||||
+ else if (!strcmp("up", keyname)) return LibInput::Key::ArrowUp;
|
||||
+ else if (!strcmp("down", keyname)) return LibInput::Key::ArrowDown;
|
||||
+ else if (!strcmp("left", keyname)) return LibInput::Key::ArrowLeft;
|
||||
+ else if (!strcmp("right", keyname)) return LibInput::Key::ArrowRight;
|
||||
+ else if (!strcmp("space", keyname)) return LibInput::Key::Space;
|
||||
+ else if (!strcmp("rshift", keyname)) return LibInput::Key::RightShift;
|
||||
+ else if (!strcmp("lshift", keyname)) return LibInput::Key::LeftShift;
|
||||
+ else if (!strcmp("backspace", keyname)) return LibInput::Key::Backspace;
|
||||
+ else if (!strcmp("delete", keyname)) return LibInput::Key::Delete;
|
||||
+ else if (!strcmp("tab", keyname)) return LibInput::Key::Tab;
|
||||
+ else if (!strcmp("escape", keyname)) return LibInput::Key::Escape;
|
||||
+ else if (!strcmp("exclamation", keyname)) return LibInput::Key::ExclamationMark;
|
||||
+ else if (!strcmp("at", keyname)) return LibInput::Key::AtSign;
|
||||
+ else if (!strcmp("hash", keyname)) return LibInput::Key::Hashtag;
|
||||
+ else if (!strcmp("dollar", keyname)) return LibInput::Key::Dollar;
|
||||
+ else if (!strcmp("percent", keyname)) return LibInput::Key::Percent;
|
||||
+ else if (!strcmp("caret", keyname)) return LibInput::Key::Caret;
|
||||
+ else if (!strcmp("ampersand", keyname)) return LibInput::Key::Ampersand;
|
||||
+ else if (!strcmp("asterisk", keyname)) return LibInput::Key::Asterix;
|
||||
+ else if (!strcmp("leftparenthesis", keyname)) return LibInput::Key::OpenParenthesis;
|
||||
+ else if (!strcmp("rightparenthesis", keyname)) return LibInput::Key::CloseParenthesis;
|
||||
+
|
||||
+ return LibInput::Key::None;
|
||||
+}
|
||||
+
|
||||
+static void load_keys()
|
||||
+{
|
||||
+ key_a = get_key(config_file.a);
|
||||
+ if (key_a == LibInput::Key::None)
|
||||
+ key_a = LibInput::Key::Z;
|
||||
+
|
||||
+ key_b = get_key(config_file.b);
|
||||
+ if (key_b == LibInput::Key::None)
|
||||
+ key_b = LibInput::Key::X;
|
||||
+
|
||||
+ key_start = get_key(config_file.start);
|
||||
+ if (key_start == LibInput::Key::None)
|
||||
+ key_start = LibInput::Key::Enter;
|
||||
+
|
||||
+ key_select = get_key(config_file.select);
|
||||
+ if (key_select == LibInput::Key::None)
|
||||
+ key_select = LibInput::Key::RightShift;
|
||||
+
|
||||
+ key_up = get_key(config_file.up);
|
||||
+ if (key_up == LibInput::Key::None)
|
||||
+ key_up = LibInput::Key::ArrowUp;
|
||||
+
|
||||
+ key_down = get_key(config_file.down);
|
||||
+ if (key_down == LibInput::Key::None)
|
||||
+ key_down = LibInput::Key::ArrowDown;
|
||||
+
|
||||
+ key_left = get_key(config_file.left);
|
||||
+ if (key_left == LibInput::Key::None)
|
||||
+ key_left = LibInput::Key::ArrowLeft;
|
||||
+
|
||||
+ key_right = get_key(config_file.right);
|
||||
+ if (key_right == LibInput::Key::None)
|
||||
+ key_right = LibInput::Key::ArrowRight;
|
||||
+
|
||||
+ key_throttle = get_key(config_file.throttle);
|
||||
+ if (key_throttle == LibInput::Key::None)
|
||||
+ key_throttle = LibInput::Key::Space;
|
||||
+}
|
||||
+
|
||||
+void delay(int ms)
|
||||
+{
|
||||
+ const timespec ts {
|
||||
+ .tv_sec = static_cast<time_t>(ms / 1000),
|
||||
+ .tv_nsec = (ms % 1000) * 1000000
|
||||
+ };
|
||||
+ nanosleep(&ts, nullptr);
|
||||
+}
|
||||
+
|
||||
+void destroy_window()
|
||||
+{
|
||||
+ s_window.clear();
|
||||
+}
|
||||
+
|
||||
+void update_window(uint32_t *framebuffer)
|
||||
+{
|
||||
+ auto pixels = s_window->texture().pixels();
|
||||
+ for (int i = 0; i < scaled_h; i++)
|
||||
+ {
|
||||
+ uint32_t* src = &framebuffer[i * scaled_w];
|
||||
+ uint32_t* dst = using_sgb_border
|
||||
+ ? &pixels[(i + gb_y) * s_window->width() + gb_x]
|
||||
+ : &pixels[i * s_window->width()];
|
||||
+ memcpy(dst, src, scaled_w * 4);
|
||||
+ }
|
||||
+
|
||||
+ if (framecount > frameskip)
|
||||
+ {
|
||||
+ s_window->invalidate();
|
||||
+ framecount = 0;
|
||||
+ drawn_frames++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void update_border(uint32_t *framebuffer)
|
||||
+{
|
||||
+ auto pixels = s_window->texture().pixels();
|
||||
+ for (int i = 0; i < sgb_scaled_h; i++)
|
||||
+ {
|
||||
+ uint32_t* src = &framebuffer[i * sgb_scaled_w];
|
||||
+ uint32_t* dst = &pixels[i * s_window->width()];
|
||||
+ memcpy(dst, src, sgb_scaled_w*4);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void resize_sgb_window()
|
||||
+{
|
||||
+ s_window->request_resize(SGB_WIDTH * scaling, SGB_HEIGHT * scaling);
|
||||
+
|
||||
+ bool resized { false };
|
||||
+ s_window->set_resize_window_event_callback([&]() { resized = true; });
|
||||
+ while (!resized)
|
||||
+ s_window->poll_events();
|
||||
+ s_window->set_resize_window_event_callback({});
|
||||
+
|
||||
+ ASSERT(s_window->width() == static_cast<uint32_t>(SGB_WIDTH * scaling));
|
||||
+ ASSERT(s_window->height() == static_cast<uint32_t>(SGB_HEIGHT * scaling));
|
||||
+}
|
||||
+
|
||||
+int main(int argc, char **argv) {
|
||||
+ if(argc != 2) {
|
||||
+ fprintf(stdout, "usage: %s rom_name\n", argv[0]);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ rom_filename = argv[1];
|
||||
+
|
||||
+ open_log();
|
||||
+ open_config();
|
||||
+ load_keys();
|
||||
+
|
||||
+ // open the rom
|
||||
+ FILE *rom_file = fopen(rom_filename, "r");
|
||||
+ if(!rom_file) {
|
||||
+ write_log("unable to open %s for reading: %s\n", rom_filename, strerror(errno));
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ fseek(rom_file, 0L, SEEK_END);
|
||||
+ rom_size = ftell(rom_file);
|
||||
+ fseek(rom_file, 0L, SEEK_SET);
|
||||
+
|
||||
+ write_log("loading rom from file %s, %d KiB\n", rom_filename, rom_size / 1024);
|
||||
+
|
||||
+ rom = malloc(rom_size);
|
||||
+ if(!rom) {
|
||||
+ write_log("unable to allocate memory\n");
|
||||
+ fclose(rom_file);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (fread(rom, 1, rom_size, rom_file) <= 0)
|
||||
+ {
|
||||
+ write_log("an error occured while reading from rom file: %s\n", strerror(errno));
|
||||
+ fclose(rom_file);
|
||||
+ free(rom);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ fclose(rom_file);
|
||||
+
|
||||
+ if (auto ret = LibGUI::Window::create(GB_WIDTH * scaling, GB_HEIGHT * scaling, "tinygb"_sv); !ret.is_error())
|
||||
+ s_window = ret.release_value();
|
||||
+ else
|
||||
+ {
|
||||
+ write_log("couldn't create SDL window: %s\n", ret.error().get_message());
|
||||
+ free(rom);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ s_window->set_key_event_callback([](LibGUI::EventPacket::KeyEvent::event_t event) {
|
||||
+ int key = 0;
|
||||
+ if (event.key == key_left)
|
||||
+ key = JOYPAD_LEFT;
|
||||
+ else if (event.key == key_right)
|
||||
+ key = JOYPAD_RIGHT;
|
||||
+ else if (event.key == key_up)
|
||||
+ key = JOYPAD_UP;
|
||||
+ else if (event.key == key_down)
|
||||
+ key = JOYPAD_DOWN;
|
||||
+ else if (event.key == key_a)
|
||||
+ key = JOYPAD_A;
|
||||
+ else if (event.key == key_b)
|
||||
+ key = JOYPAD_B;
|
||||
+ else if (event.key == key_start)
|
||||
+ key = JOYPAD_START;
|
||||
+ else if (event.key == key_select)
|
||||
+ key = JOYPAD_SELECT;
|
||||
+ else if (event.key == key_throttle)
|
||||
+ throttle_enabled = event.released();
|
||||
+ else if (event.pressed() && (event.key == LibInput::Key::Plus || event.key == LibInput::Key::Equals))
|
||||
+ next_palette();
|
||||
+ else if (event.pressed() && (event.key == LibInput::Key::Hyphen))
|
||||
+ prev_palette();
|
||||
+
|
||||
+ if (key)
|
||||
+ joypad_handle(event.pressed(), key);
|
||||
+ });
|
||||
+
|
||||
+ // start emulation
|
||||
+ memory_start();
|
||||
+ cpu_start();
|
||||
+ display_start();
|
||||
+ timer_start();
|
||||
+ sound_start();
|
||||
+
|
||||
+ time_t rawtime;
|
||||
+ struct tm *timeinfo;
|
||||
+ int sec = 500; // any invalid number
|
||||
+ char new_title[256];
|
||||
+ int percentage;
|
||||
+ int throttle_underflow = 0;
|
||||
+ int throttle_target = throttle_lo + SPEED_ALLOWANCE;
|
||||
+
|
||||
+ while(1) {
|
||||
+ s_window->poll_events();
|
||||
+
|
||||
+ for(timing.current_cycles = 0; timing.current_cycles < timing.main_cycles; ) {
|
||||
+ cpu_cycle();
|
||||
+ display_cycle();
|
||||
+ timer_cycle();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ time(&rawtime);
|
||||
+ timeinfo = localtime(&rawtime);
|
||||
+
|
||||
+ if(sec != timeinfo->tm_sec) {
|
||||
+ sec = timeinfo->tm_sec;
|
||||
+ percentage = (drawn_frames * 1000) / 597;
|
||||
+ sprintf(new_title, "tinygb (%d fps - %d%%)", drawn_frames, percentage);
|
||||
+ s_window->set_title(new_title);
|
||||
+
|
||||
+ // adjust cpu throttle according to acceptable fps (98%-102%)
|
||||
+ if(throttle_enabled) {
|
||||
+ if(percentage < throttle_lo) {
|
||||
+ // emulation is too slow
|
||||
+ if(!throttle_time) {
|
||||
+ // throttle_time--;
|
||||
+
|
||||
+ if(!throttle_underflow) {
|
||||
+ throttle_underflow = 1;
|
||||
+ write_log("WARNING: CPU throttle interval has underflown, emulation may be too slow\n");
|
||||
+ }
|
||||
+ } else {
|
||||
+ //write_log("too slow; decreasing throttle time: %d\n", throttle_time);
|
||||
+
|
||||
+ // this will speed up the speed adjustments for a more natural feel
|
||||
+ if(percentage < (throttle_target/3)) throttle_time /= 3;
|
||||
+ else if(percentage < (throttle_target/2)) throttle_time /= 2;
|
||||
+ else throttle_time--;
|
||||
+ }
|
||||
+
|
||||
+ // prevent this from going too low
|
||||
+ if(throttle_time <= (THROTTLE_THRESHOLD/3)) {
|
||||
+ cycles_per_throttle += (cycles_per_throttle/5); // delay 20% less often
|
||||
+ throttle_time = (THROTTLE_THRESHOLD/3);
|
||||
+ }
|
||||
+ } else if(percentage > throttle_hi) {
|
||||
+ // emulation is too fast
|
||||
+ //write_log("too fast; increasing throttle time: %d\n", throttle_time);
|
||||
+
|
||||
+ if(throttle_time) {
|
||||
+ // to make sure we're not multiplying zero
|
||||
+ if(percentage > (throttle_target*3)) throttle_time *= 3;
|
||||
+ else if(percentage > (throttle_target*2)) throttle_time *= 2;
|
||||
+ else throttle_time++;
|
||||
+ }
|
||||
+ else {
|
||||
+ throttle_time++;
|
||||
+ }
|
||||
+
|
||||
+ // prevent unnecessary lag
|
||||
+ if(throttle_time > THROTTLE_THRESHOLD) {
|
||||
+ cycles_per_throttle -= (cycles_per_throttle/5); // delay 20% more often
|
||||
+ throttle_time = THROTTLE_THRESHOLD;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ drawn_frames = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ die(0, "");
|
||||
+ return 0;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.49.0
|
||||
|
|
@ -39,8 +39,8 @@ SOUND_ARGS='-device ac97'
|
|||
qemu-system-$QEMU_ARCH \
|
||||
-m 1G -smp 4 \
|
||||
$BIOS_ARGS \
|
||||
$DISK_ARGS \
|
||||
$USB_ARGS \
|
||||
$DISK_ARGS \
|
||||
$NET_ARGS \
|
||||
$SOUND_ARGS \
|
||||
$@ \
|
||||
|
|
|
@ -10,6 +10,7 @@ set(LIBC_SOURCES
|
|||
errno.cpp
|
||||
fcntl.cpp
|
||||
fenv.cpp
|
||||
fnmatch.cpp
|
||||
ftw.cpp
|
||||
grp.cpp
|
||||
ifaddrs.cpp
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#include <fnmatch.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static int fnmatch_impl(const char* pattern, const char* string, int flags, bool leading)
|
||||
{
|
||||
while (*pattern)
|
||||
{
|
||||
if ((flags & FNM_PERIOD) && leading && *string == '.' && *pattern != '.')
|
||||
return FNM_NOMATCH;
|
||||
leading = false;
|
||||
|
||||
switch (*pattern)
|
||||
{
|
||||
case '*':
|
||||
{
|
||||
const char* ptr = strchrnul(string, (flags & FNM_PATHNAME) ? '/' : '0');
|
||||
while (ptr >= string)
|
||||
if (fnmatch_impl(pattern + 1, ptr--, flags, false) == 0)
|
||||
return 0;
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
case '[':
|
||||
{
|
||||
if (strchr(pattern, ']') == nullptr)
|
||||
break;
|
||||
pattern++;
|
||||
|
||||
const bool negate = (*pattern == '!');
|
||||
if (negate)
|
||||
pattern++;
|
||||
|
||||
uint8_t ch;
|
||||
uint32_t bitmap[0x100 / 8] {};
|
||||
while ((ch = *pattern++) != ']')
|
||||
bitmap[ch / 32] |= 1 << (ch % 32);
|
||||
|
||||
ch = *string++;
|
||||
if (!!(bitmap[ch / 32] & (1 << (ch % 32))) == negate)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
continue;
|
||||
}
|
||||
case '?':
|
||||
{
|
||||
if (*string == '\0')
|
||||
return FNM_NOMATCH;
|
||||
if ((flags & FNM_PATHNAME) && *string == '/')
|
||||
return FNM_NOMATCH;
|
||||
pattern++;
|
||||
string++;
|
||||
continue;
|
||||
}
|
||||
case '\\':
|
||||
{
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
pattern++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*pattern == '\0')
|
||||
break;
|
||||
|
||||
if (*pattern != *string)
|
||||
return FNM_NOMATCH;
|
||||
if ((flags & FNM_PATHNAME) && *string == '/')
|
||||
leading = true;
|
||||
pattern++;
|
||||
string++;
|
||||
}
|
||||
|
||||
return *string ? FNM_NOMATCH : 0;
|
||||
}
|
||||
|
||||
int fnmatch(const char* pattern, const char* string, int flags)
|
||||
{
|
||||
return fnmatch_impl(pattern, string, flags, true);
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
static FILE* s_grent_fp = nullptr;
|
||||
static group s_grent_struct;
|
||||
|
@ -211,3 +212,106 @@ int getgrnam_r(const char* name, struct group* grp, char* buffer, size_t bufsize
|
|||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gid_t* get_user_groups(const char* user)
|
||||
{
|
||||
FILE* fp = fopen("/etc/group", "r");
|
||||
if (fp == nullptr)
|
||||
return nullptr;
|
||||
|
||||
const long initial_len = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||
|
||||
size_t buffer_len = (initial_len == -1) ? 512 : initial_len;
|
||||
char* buffer = static_cast<char*>(malloc(buffer_len));
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t group_count = 0;
|
||||
gid_t* groups = static_cast<gid_t*>(malloc(sizeof(gid_t)));
|
||||
if (groups == nullptr)
|
||||
{
|
||||
free(buffer);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
struct group result;
|
||||
struct group* resultp;
|
||||
|
||||
int error = getgrent_impl(fp, &result, buffer, buffer_len, &resultp);
|
||||
if (error == ERANGE)
|
||||
{
|
||||
const size_t new_buffer_len = buffer_len * 2;
|
||||
char* new_buffer = static_cast<char*>(realloc(buffer, new_buffer_len));
|
||||
if (new_buffer == nullptr)
|
||||
{
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
buffer = new_buffer;
|
||||
buffer_len = new_buffer_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
free(buffer);
|
||||
free(groups);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (resultp == nullptr)
|
||||
break;
|
||||
|
||||
bool contains = false;
|
||||
for (size_t i = 0; result.gr_mem[i] && !contains; i++)
|
||||
contains = (strcmp(result.gr_mem[i], user) == 0);
|
||||
if (!contains)
|
||||
continue;
|
||||
|
||||
gid_t* new_groups = static_cast<gid_t*>(realloc(groups, group_count * sizeof(gid_t)));
|
||||
if (new_groups == nullptr)
|
||||
{
|
||||
free(buffer);
|
||||
free(groups);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
groups = new_groups;
|
||||
groups[group_count++] = result.gr_gid;
|
||||
}
|
||||
|
||||
groups[group_count] = -1;
|
||||
|
||||
free(buffer);
|
||||
fclose(fp);
|
||||
return groups;
|
||||
}
|
||||
|
||||
int initgroups(const char* user, gid_t group)
|
||||
{
|
||||
gid_t* groups = get_user_groups(user);
|
||||
if (groups == nullptr)
|
||||
return -1;
|
||||
|
||||
size_t group_count = 0;
|
||||
while (groups[group_count] != -1)
|
||||
group_count++;
|
||||
groups[group_count] = group;
|
||||
|
||||
int result = setgroups(group_count + 1, groups);
|
||||
free(groups);
|
||||
return result;
|
||||
}
|
||||
|
||||
int setgroups(size_t size, const gid_t list[])
|
||||
{
|
||||
return syscall(SYS_SETGROUPS, list, size);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ struct group* getgrnam(const char* name);
|
|||
int getgrnam_r(const char* name, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
||||
void setgrent(void);
|
||||
|
||||
int initgroups(const char* user, gid_t group);
|
||||
int setgroups(size_t size, const gid_t list[]);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,6 +59,8 @@ enum
|
|||
#define IPV6_V6ONLY IPV6_V6ONLY
|
||||
};
|
||||
|
||||
#define IN_MULTICAST(a) (((in_addr_t)(a) & 0xF0000000) == 0xE0000000)
|
||||
|
||||
#define INADDR_ANY 0
|
||||
#define INADDR_NONE 0xFFFFFFFF
|
||||
#define INADDR_BROADCAST 0xFFFFFFFF
|
||||
|
@ -67,31 +69,63 @@ enum
|
|||
#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
|
||||
#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
|
||||
|
||||
#if 0
|
||||
#define IN6_IS_ADDR_UNSPECIFIED(addr)
|
||||
#define IN6_IS_ADDR_LOOPBACK(addr)
|
||||
#define IN6_IS_ADDR_MULTICAST(addr)
|
||||
#define IN6_IS_ADDR_LINKLOCAL(addr)
|
||||
#define IN6_IS_ADDR_SITELOCAL(addr)
|
||||
#define IN6_IS_ADDR_V4MAPPED(addr)
|
||||
#define IN6_IS_ADDR_V4COMPAT(addr)
|
||||
#define IN6_IS_ADDR_MC_NODELOCAL(addr)
|
||||
#define IN6_IS_ADDR_MC_LINKLOCAL(addr)
|
||||
#define IN6_IS_ADDR_MC_SITELOCAL(addr)
|
||||
#define IN6_IS_ADDR_MC_ORGLOCAL(addr)
|
||||
#define IN6_IS_ADDR_MC_GLOBAL(addr)
|
||||
#endif
|
||||
#define IN6_IS_ADDR_UNSPECIFIED(a) \
|
||||
((a)->s6_addr32[0] == 0 && \
|
||||
(a)->s6_addr32[1] == 0 && \
|
||||
(a)->s6_addr32[2] == 0 && \
|
||||
(a)->s6_addr32[3] == 0)
|
||||
#define IN6_IS_ADDR_LOOPBACK(a) \
|
||||
((a)->s6_addr32[0] == 0 && \
|
||||
(a)->s6_addr32[1] == 0 && \
|
||||
(a)->s6_addr32[2] == 0 && \
|
||||
(a)->s6_addr32[3] == htonl(1))
|
||||
#define IN6_IS_ADDR_MULTICAST(a) \
|
||||
((a)->s6_addr[0] == 0xFF)
|
||||
#define IN6_IS_ADDR_LINKLOCAL(a) \
|
||||
((a)->s6_addr[0] == 0xFE && \
|
||||
((a)->s6_addr[1] & 0xC0) == 0x80)
|
||||
#define IN6_IS_ADDR_SITELOCAL(a) \
|
||||
((a)->s6_addr[0] == 0xFE && \
|
||||
((a)->s6_addr[1] & 0xC0) == 0xC0)
|
||||
#define IN6_IS_ADDR_V4MAPPED(a) \
|
||||
((a)->s6_addr32[0] == 0 && \
|
||||
(a)->s6_addr32[1] == 0 && \
|
||||
(a)->s6_addr32[2] == htonl(0x0000FFFF))
|
||||
#define IN6_IS_ADDR_V4COMPAT(a) \
|
||||
((a)->s6_addr32[0] == 0 && \
|
||||
(a)->s6_addr32[1] == 0 && \
|
||||
(a)->s6_addr32[2] == 0 && \
|
||||
ntohl((a)->s6_addr32[3]) > 1)
|
||||
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
((a)->s6_addr[1] & 0x0F) == 0x01)
|
||||
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
((a)->s6_addr[1] & 0x0F) == 0x02)
|
||||
#define IN6_IS_ADDR_MC_SITELOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
((a)->s6_addr[1] & 0x0F) == 0x05)
|
||||
#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
((a)->s6_addr[1] & 0x0F) == 0x08)
|
||||
#define IN6_IS_ADDR_MC_GLOBAL(a) \
|
||||
(IN6_IS_ADDR_MULTICAST(a) && \
|
||||
((a)->s6_addr[1] & 0x0F) == 0x0E)
|
||||
|
||||
struct sockaddr_in
|
||||
{
|
||||
sa_family_t sin_family; /* AF_INET. */
|
||||
in_port_t sin_port; /* Port number. */
|
||||
struct in_addr sin_addr; /* IP address. */
|
||||
unsigned char sin_zero[8];
|
||||
};
|
||||
|
||||
struct in6_addr
|
||||
{
|
||||
union {
|
||||
uint8_t s6_addr[16];
|
||||
uint32_t s6_addr32[4];
|
||||
};
|
||||
};
|
||||
|
||||
struct sockaddr_in6
|
||||
|
|
|
@ -37,6 +37,8 @@ __BEGIN_DECLS
|
|||
|
||||
#define KDLOADFONT 30
|
||||
|
||||
#define FIONREAD 40 /* get number of input bytes available */
|
||||
|
||||
struct winsize
|
||||
{
|
||||
unsigned short ws_row;
|
||||
|
|
|
@ -25,7 +25,7 @@ __BEGIN_DECLS
|
|||
struct sockaddr
|
||||
{
|
||||
sa_family_t sa_family; /* Address family. */
|
||||
char sa_data[0]; /* Socket address (variable-length data). */
|
||||
char sa_data[14]; /* Socket address (variable-length data). */
|
||||
};
|
||||
|
||||
struct sockaddr_storage
|
||||
|
|
|
@ -111,6 +111,9 @@ __BEGIN_DECLS
|
|||
O(SYS_FLOCK, flock) \
|
||||
O(SYS_GET_NPROCESSOR, get_nprocessor) \
|
||||
O(SYS_FUTEX, futex) \
|
||||
O(SYS_GETGROUPS, getgroups) \
|
||||
O(SYS_SETGROUPS, setgroups) \
|
||||
O(SYS_CHROOT, chroot) \
|
||||
|
||||
enum Syscall
|
||||
{
|
||||
|
|
|
@ -596,6 +596,7 @@ int unlinkat(int fd, const char* path, int flag);
|
|||
int usleep(useconds_t usec);
|
||||
ssize_t write(int fildes, const void* buf, size_t nbyte);
|
||||
|
||||
int chroot(const char* path);
|
||||
int getpagesize(void);
|
||||
char* getpass(const char* prompt);
|
||||
|
||||
|
|
|
@ -626,6 +626,10 @@ int getopt(int argc, char* const argv[], const char* optstring)
|
|||
return '?';
|
||||
}
|
||||
|
||||
int chroot(const char* path)
|
||||
return syscall(SYS_CHROOT, path);
|
||||
}
|
||||
|
||||
int getpagesize(void)
|
||||
{
|
||||
return PAGE_SIZE;
|
||||
|
@ -673,8 +677,7 @@ error:
|
|||
|
||||
int getgroups(int gidsetsize, gid_t grouplist[])
|
||||
{
|
||||
dwarnln("FIXME: getgroups({}, {})", gidsetsize, grouplist);
|
||||
return 0;
|
||||
return syscall(SYS_GETGROUPS, grouplist, gidsetsize);
|
||||
}
|
||||
|
||||
pid_t getppid(void)
|
||||
|
|
|
@ -31,7 +31,8 @@ namespace LibFont
|
|||
|
||||
#if __is_kernel
|
||||
{
|
||||
auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, O_RDONLY)).inode;
|
||||
// FIXME: This does not account for chroot
|
||||
auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path(Kernel::VirtualFileSystem::get().root_inode(), { 0, 0, 0, 0 }, path, O_RDONLY)).inode;
|
||||
TRY(file_data.resize(inode->size()));
|
||||
TRY(inode->read(0, BAN::ByteSpan(file_data.span())));
|
||||
}
|
||||
|
|
|
@ -128,7 +128,8 @@ namespace LibInput
|
|||
|
||||
#if __is_kernel
|
||||
{
|
||||
auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, 0));
|
||||
// FIXME: This does not account for chroot
|
||||
auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path(Kernel::VirtualFileSystem::get().root_inode(), { 0, 0, 0, 0 }, path, 0));
|
||||
TRY(file_data.resize(file.inode->size()));
|
||||
TRY(file.inode->read(0, BAN::ByteSpan { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() }));
|
||||
canonical_path = file.canonical_path;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <BAN/Vector.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -41,6 +42,12 @@ int main(int argc, char** argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (fork() == 0)
|
||||
{
|
||||
execl("/bin/AudioServer", "AudioServer", NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
|
||||
termios termios;
|
||||
|
@ -94,6 +101,8 @@ int main(int argc, char** argv)
|
|||
|
||||
printf("Welcome back %s!\n", pwd->pw_name);
|
||||
|
||||
if (initgroups(name_buffer, pwd->pw_gid) == -1)
|
||||
perror("initgroups");
|
||||
if (setgid(pwd->pw_gid) == -1)
|
||||
perror("setgid");
|
||||
if (setuid(pwd->pw_uid) == -1)
|
||||
|
|
|
@ -442,6 +442,7 @@ int main(int, char**)
|
|||
.sin_family = AF_INET,
|
||||
.sin_port = 0,
|
||||
.sin_addr = { .s_addr = resolved->raw },
|
||||
.sin_zero = {},
|
||||
};
|
||||
|
||||
if (send(client.socket, &addr, sizeof(addr), 0) == -1)
|
||||
|
@ -489,6 +490,7 @@ int main(int, char**)
|
|||
.sin_family = AF_INET,
|
||||
.sin_port = 0,
|
||||
.sin_addr = { .s_addr = result->raw },
|
||||
.sin_zero = {},
|
||||
};
|
||||
|
||||
if (send(client.socket, &addr, sizeof(addr), 0) == -1)
|
||||
|
|
Loading…
Reference in New Issue